New desktop
This commit is contained in:
162
temp/nexus-module-import/modules/pi_control/assets/commands.js
Normal file
162
temp/nexus-module-import/modules/pi_control/assets/commands.js
Normal file
@@ -0,0 +1,162 @@
|
||||
(() => {
|
||||
const form = document.querySelector('[data-command-form]');
|
||||
const list = document.querySelector('[data-command-list]');
|
||||
if (!form) return;
|
||||
|
||||
const idInput = form.querySelector('input[name="id"]');
|
||||
const labelInput = form.querySelector('input[name="label"]');
|
||||
const commandInput = form.querySelector('textarea[name="command"]');
|
||||
const timeoutInput = form.querySelector('input[name="timeout_sec"]');
|
||||
const adminInput = form.querySelector('input[name="admin_only"]');
|
||||
const submitBtn = form.querySelector('[data-command-submit]');
|
||||
const cancelBtn = form.querySelector('[data-command-cancel]');
|
||||
const modal = document.querySelector('[data-command-modal]');
|
||||
const modalTitle = document.querySelector('[data-command-modal-title]');
|
||||
const closeBtn = document.querySelector('[data-command-close]');
|
||||
const newBtn = document.querySelector('[data-command-new]');
|
||||
const unsavedBar = document.querySelector('[data-command-unsaved]');
|
||||
const discardBtn = document.querySelector('[data-command-discard]');
|
||||
|
||||
let initialSnapshot = '';
|
||||
|
||||
const resetForm = () => {
|
||||
if (idInput) idInput.value = '';
|
||||
if (labelInput) labelInput.value = '';
|
||||
if (commandInput) commandInput.value = '';
|
||||
if (timeoutInput) timeoutInput.value = '';
|
||||
if (adminInput) adminInput.checked = false;
|
||||
if (submitBtn) submitBtn.textContent = 'Speichern';
|
||||
if (unsavedBar) unsavedBar.style.display = 'none';
|
||||
};
|
||||
|
||||
const snapshot = () => {
|
||||
return JSON.stringify({
|
||||
id: idInput ? idInput.value : '',
|
||||
label: labelInput ? labelInput.value : '',
|
||||
command: commandInput ? commandInput.value : '',
|
||||
timeout: timeoutInput ? timeoutInput.value : '',
|
||||
admin: adminInput ? adminInput.checked : false,
|
||||
});
|
||||
};
|
||||
|
||||
const isDirty = () => snapshot() !== initialSnapshot;
|
||||
|
||||
const openModal = () => {
|
||||
if (!modal) return;
|
||||
modal.classList.add('is-open');
|
||||
modal.setAttribute('aria-hidden', 'false');
|
||||
initialSnapshot = snapshot();
|
||||
};
|
||||
|
||||
const closeModal = (force = false) => {
|
||||
if (!modal) return;
|
||||
if (!force && isDirty()) {
|
||||
if (unsavedBar) unsavedBar.style.display = 'flex';
|
||||
return;
|
||||
}
|
||||
modal.classList.remove('is-open');
|
||||
modal.setAttribute('aria-hidden', 'true');
|
||||
if (unsavedBar) unsavedBar.style.display = 'none';
|
||||
};
|
||||
|
||||
document.querySelectorAll('[data-command-edit]').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const item = btn.closest('.command-item');
|
||||
if (!item) return;
|
||||
if (idInput) idInput.value = item.dataset.commandId || '';
|
||||
if (labelInput) labelInput.value = item.dataset.label || '';
|
||||
if (commandInput) commandInput.value = item.dataset.command || '';
|
||||
if (timeoutInput) timeoutInput.value = item.dataset.timeout || '';
|
||||
if (adminInput) adminInput.checked = item.dataset.admin === '1';
|
||||
if (submitBtn) submitBtn.textContent = 'Aktualisieren';
|
||||
if (modalTitle) modalTitle.textContent = 'Befehl bearbeiten';
|
||||
const details = btn.closest('details');
|
||||
if (details) details.removeAttribute('open');
|
||||
openModal();
|
||||
});
|
||||
});
|
||||
|
||||
if (cancelBtn) {
|
||||
cancelBtn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
resetForm();
|
||||
});
|
||||
}
|
||||
|
||||
if (newBtn) {
|
||||
newBtn.addEventListener('click', () => {
|
||||
resetForm();
|
||||
if (modalTitle) modalTitle.textContent = 'Neuer Befehl';
|
||||
openModal();
|
||||
});
|
||||
}
|
||||
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', () => closeModal(false));
|
||||
}
|
||||
|
||||
if (discardBtn) {
|
||||
discardBtn.addEventListener('click', () => {
|
||||
resetForm();
|
||||
closeModal(true);
|
||||
});
|
||||
}
|
||||
|
||||
form.addEventListener('input', () => {
|
||||
if (unsavedBar && isDirty()) {
|
||||
unsavedBar.style.display = 'flex';
|
||||
}
|
||||
});
|
||||
|
||||
if (!list) return;
|
||||
|
||||
let dragging = null;
|
||||
|
||||
list.querySelectorAll('.command-item').forEach((item) => {
|
||||
item.addEventListener('dragstart', () => {
|
||||
dragging = item;
|
||||
item.classList.add('is-dragging');
|
||||
});
|
||||
item.addEventListener('dragend', () => {
|
||||
item.classList.remove('is-dragging');
|
||||
dragging = null;
|
||||
saveOrder();
|
||||
});
|
||||
});
|
||||
|
||||
list.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
if (!dragging) return;
|
||||
const after = getDragAfterElement(list, e.clientY);
|
||||
if (after == null) {
|
||||
list.appendChild(dragging);
|
||||
} else if (after !== dragging) {
|
||||
list.insertBefore(dragging, after);
|
||||
}
|
||||
});
|
||||
|
||||
const getDragAfterElement = (container, y) => {
|
||||
const elements = [...container.querySelectorAll('.command-item:not(.is-dragging)')];
|
||||
return elements.reduce(
|
||||
(closest, child) => {
|
||||
const box = child.getBoundingClientRect();
|
||||
const offset = y - box.top - box.height / 2;
|
||||
if (offset < 0 && offset > closest.offset) {
|
||||
return { offset, element: child };
|
||||
}
|
||||
return closest;
|
||||
},
|
||||
{ offset: Number.NEGATIVE_INFINITY, element: null }
|
||||
).element;
|
||||
};
|
||||
|
||||
const saveOrder = () => {
|
||||
const order = [...list.querySelectorAll('.command-item')].map((el) => el.dataset.commandId);
|
||||
fetch(window.location.pathname + '?reorder_json=1', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ order }),
|
||||
cache: 'no-store',
|
||||
}).catch(() => {});
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user