Integrate probe endpoint into frontend
- Add ProbeAPI client (js/api/probe.js) - Add reusable modal component (js/ui/modal.js) with overlay, animations - Call GET /api/v1/probe after Check Address click - Auto-fill Camera Model with vendor from ARP/OUI lookup - Show modal on unreachable device with Change IP / Continue Anyway buttons - Add modal CSS styles matching existing dark theme
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Simple modal dialog component.
|
||||
* Shows a centered card with title, message, and configurable buttons.
|
||||
* Returns a Promise that resolves with the clicked button's id.
|
||||
*
|
||||
* Usage:
|
||||
* const result = await showModal({
|
||||
* title: 'Device Unreachable',
|
||||
* message: 'This IP is not responding.',
|
||||
* buttons: [
|
||||
* { id: 'change', label: 'Change IP', style: 'primary' },
|
||||
* { id: 'continue', label: 'Continue Anyway', style: 'outline' }
|
||||
* ]
|
||||
* });
|
||||
*/
|
||||
|
||||
let currentResolve = null;
|
||||
|
||||
export function showModal({ title, message, buttons }) {
|
||||
return new Promise((resolve) => {
|
||||
currentResolve = resolve;
|
||||
|
||||
const overlay = document.getElementById('modal-overlay');
|
||||
|
||||
// Clear previous content safely
|
||||
overlay.replaceChildren();
|
||||
|
||||
// Build modal DOM using safe DOM methods
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'modal';
|
||||
|
||||
const titleEl = document.createElement('div');
|
||||
titleEl.className = 'modal-title';
|
||||
titleEl.textContent = title;
|
||||
modal.appendChild(titleEl);
|
||||
|
||||
const messageEl = document.createElement('div');
|
||||
messageEl.className = 'modal-message';
|
||||
messageEl.textContent = message;
|
||||
modal.appendChild(messageEl);
|
||||
|
||||
const actionsEl = document.createElement('div');
|
||||
actionsEl.className = 'modal-actions';
|
||||
|
||||
buttons.forEach(btnConfig => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = `btn btn-${btnConfig.style || 'outline'}`;
|
||||
btn.textContent = btnConfig.label;
|
||||
btn.addEventListener('click', () => {
|
||||
hideModal();
|
||||
resolve(btnConfig.id);
|
||||
});
|
||||
actionsEl.appendChild(btn);
|
||||
});
|
||||
|
||||
modal.appendChild(actionsEl);
|
||||
overlay.appendChild(modal);
|
||||
|
||||
// Close on overlay click (outside modal)
|
||||
overlay.addEventListener('click', (e) => {
|
||||
if (e.target === overlay) {
|
||||
hideModal();
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
|
||||
// Show with animation
|
||||
overlay.classList.remove('hidden');
|
||||
requestAnimationFrame(() => {
|
||||
overlay.classList.add('show');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function hideModal() {
|
||||
const overlay = document.getElementById('modal-overlay');
|
||||
overlay.classList.remove('show');
|
||||
setTimeout(() => {
|
||||
overlay.classList.add('hidden');
|
||||
overlay.replaceChildren();
|
||||
}, 200);
|
||||
currentResolve = null;
|
||||
}
|
||||
Reference in New Issue
Block a user