This commit is contained in:
@@ -197,6 +197,7 @@
|
||||
<div class="toolbar">
|
||||
<h2>Devices</h2>
|
||||
<button class="btn btn-primary" id="btn-discover" onclick="discoverDevices()">⟳ Scan</button>
|
||||
<button class="btn btn-secondary btn-sm" id="btn-manual-add" onclick="openManualModal()" title="Add device manually" style="width:auto;padding:9px 12px;">+</button>
|
||||
</div>
|
||||
<div id="page-header-devices" class="page-header">
|
||||
<span class="ws-dot" id="ws-dot-d"></span>
|
||||
@@ -436,6 +437,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Manual Add Modal ── -->
|
||||
<div class="modal-backdrop" id="modal-manual" onclick="closeManualModal(event)">
|
||||
<div class="modal" onclick="event.stopPropagation()">
|
||||
<div class="modal-header">
|
||||
<span class="modal-title">Add Device Manually</span>
|
||||
<button class="modal-close" onclick="closeManualModal()">✕</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">IP Address</label>
|
||||
<input class="form-input" id="f-manual-host" type="text" placeholder="192.168.1.100" autofocus />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Port</label>
|
||||
<input class="form-input" id="f-manual-port" type="number" placeholder="49153" value="49153" />
|
||||
</div>
|
||||
<div id="modal-manual-error" style="display:none;color:var(--danger);font-size:13px;margin-bottom:10px;"></div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-ghost" onclick="closeManualModal()">Cancel</button>
|
||||
<button class="btn btn-primary" id="btn-add-manual" onclick="addManualDevice()">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Delete Confirm ── -->
|
||||
<div class="confirm-backdrop" id="confirm-delete">
|
||||
<div class="confirm-box">
|
||||
@@ -603,6 +627,67 @@ async function toggleDevice(i, e) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Manual Add ─────────────────────────────────────────────────────────────
|
||||
function openManualModal() {
|
||||
document.getElementById('f-manual-host').value = '';
|
||||
document.getElementById('f-manual-port').value = '49153';
|
||||
document.getElementById('modal-manual-error').style.display = 'none';
|
||||
document.getElementById('modal-manual').classList.add('open');
|
||||
setTimeout(() => document.getElementById('f-manual-host').focus(), 100);
|
||||
}
|
||||
|
||||
function closeManualModal(e) {
|
||||
if (e && e.target !== document.getElementById('modal-manual')) return;
|
||||
document.getElementById('modal-manual').classList.remove('open');
|
||||
}
|
||||
|
||||
async function addManualDevice() {
|
||||
const errEl = document.getElementById('modal-manual-error');
|
||||
errEl.style.display = 'none';
|
||||
|
||||
const host = document.getElementById('f-manual-host').value.trim();
|
||||
const port = parseInt(document.getElementById('f-manual-port').value, 10) || 49153;
|
||||
|
||||
if (!host) {
|
||||
errEl.textContent = '⚠ Enter an IP address';
|
||||
errEl.style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = document.getElementById('btn-add-manual');
|
||||
btn.disabled = true; btn.textContent = 'Adding…';
|
||||
|
||||
try {
|
||||
const result = await api('POST', '/api/devices/discover', {
|
||||
manualEntries: [{ host, port }]
|
||||
});
|
||||
|
||||
if (!result || result.length === 0) {
|
||||
errEl.textContent = '⚠ No device found at that address';
|
||||
errEl.style.display = 'block';
|
||||
btn.disabled = false; btn.textContent = 'Add';
|
||||
return;
|
||||
}
|
||||
|
||||
const device = result.find((d) => d.host === host);
|
||||
if (device) {
|
||||
const friendlyName = device.friendlyName || device.name || host;
|
||||
toast(`Added ${friendlyName}`, 'success');
|
||||
devices = result;
|
||||
renderDevices();
|
||||
closeManualModal();
|
||||
} else {
|
||||
errEl.textContent = '⚠ Device added but not found in results';
|
||||
errEl.style.display = 'block';
|
||||
}
|
||||
} catch (err) {
|
||||
errEl.textContent = `⚠ ${err.message}`;
|
||||
errEl.style.display = 'block';
|
||||
} finally {
|
||||
btn.disabled = false; btn.textContent = 'Add';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Rules list ─────────────────────────────────────────────────────────────
|
||||
async function loadRules() {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user