Extract Modal base class and fix target editor defaults
Add core/modal.js with reusable Modal class that handles open/close, body locking, backdrop close, dirty checking, error display, and a static stack for ESC key management. Migrate all 13 modals across 8 feature files to use the base class, eliminating ~200 lines of duplicated boilerplate. Replace manual ESC handler list in app.js with Modal.closeTopmost(), fixing 3 modals that were previously unreachable via ESC. Remove 5 unused initialValues variables from state.js. Fix target editor to auto-select first device/source and auto-generate name like the KC editor does. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,10 @@
|
||||
import { _profilesCache, set_profilesCache } from '../core/state.js';
|
||||
import { API_BASE, getHeaders, escapeHtml, handle401Error } from '../core/api.js';
|
||||
import { t, updateAllText } from '../core/i18n.js';
|
||||
import { lockBody, unlockBody, showToast, showConfirm } from '../core/ui.js';
|
||||
import { showToast, showConfirm } from '../core/ui.js';
|
||||
import { Modal } from '../core/modal.js';
|
||||
|
||||
const profileModal = new Modal('profile-editor-modal');
|
||||
|
||||
export async function loadProfiles() {
|
||||
const container = document.getElementById('profiles-content');
|
||||
@@ -137,14 +140,12 @@ export async function openProfileEditor(profileId) {
|
||||
logicSelect.value = 'or';
|
||||
}
|
||||
|
||||
modal.style.display = 'flex';
|
||||
lockBody();
|
||||
profileModal.open();
|
||||
updateAllText();
|
||||
}
|
||||
|
||||
export function closeProfileEditorModal() {
|
||||
document.getElementById('profile-editor-modal').style.display = 'none';
|
||||
unlockBody();
|
||||
profileModal.forceClose();
|
||||
}
|
||||
|
||||
async function loadProfileTargetChecklist(selectedIds) {
|
||||
@@ -304,12 +305,10 @@ export async function saveProfileEditor() {
|
||||
const nameInput = document.getElementById('profile-editor-name');
|
||||
const enabledInput = document.getElementById('profile-editor-enabled');
|
||||
const logicSelect = document.getElementById('profile-editor-logic');
|
||||
const errorEl = document.getElementById('profile-editor-error');
|
||||
|
||||
const name = nameInput.value.trim();
|
||||
if (!name) {
|
||||
errorEl.textContent = 'Name is required';
|
||||
errorEl.style.display = 'block';
|
||||
profileModal.showError('Name is required');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -336,12 +335,11 @@ export async function saveProfileEditor() {
|
||||
throw new Error(err.detail || 'Failed to save profile');
|
||||
}
|
||||
|
||||
closeProfileEditorModal();
|
||||
profileModal.forceClose();
|
||||
showToast(isEdit ? 'Profile updated' : 'Profile created', 'success');
|
||||
loadProfiles();
|
||||
} catch (e) {
|
||||
errorEl.textContent = e.message;
|
||||
errorEl.style.display = 'block';
|
||||
profileModal.showError(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user