Control 설정 모달 확장
This commit is contained in:
@@ -38,6 +38,12 @@
|
||||
customServiceList: $('#customServiceList'),
|
||||
noticeBaseline: $('#noticeBaseline'),
|
||||
rebootBtn: $('#rebootBtn'),
|
||||
settingsBtn: $('#settingsBtn'),
|
||||
settingsDialog: $('#settingsDialog'),
|
||||
settingsBody: $('#settingsBody'),
|
||||
settingsClose: $('#settingsClose'),
|
||||
settingsSave: $('#settingsSave'),
|
||||
settingsReset: $('#settingsReset'),
|
||||
translateBtn: $('#translateBtn'),
|
||||
themeBtn: $('#themeBtn'),
|
||||
customDialog: $('#customDialog'),
|
||||
@@ -78,6 +84,8 @@
|
||||
theme: 'dark',
|
||||
batteryTooltipOpen: false,
|
||||
batteryTooltipText: '',
|
||||
settingsPayload: null,
|
||||
settingsOpen: false,
|
||||
};
|
||||
|
||||
const storageKeys = {
|
||||
@@ -165,6 +173,13 @@
|
||||
hide: 'Hide',
|
||||
translateButton: 'Translate',
|
||||
themeButton: 'Theme',
|
||||
settingsButton: 'Settings',
|
||||
settingsTitle: 'Settings',
|
||||
settingsSaved: 'Settings saved',
|
||||
settingsResetDone: 'Settings reset',
|
||||
settingsSaveFailed: 'settings save failed',
|
||||
settingsResetConfirm: 'Reset all Control settings to defaults?',
|
||||
settingsDefault: 'default',
|
||||
rebootButton: 'Reboot',
|
||||
dialogAlert: 'Alert',
|
||||
dialogConfirm: 'Confirm',
|
||||
@@ -299,6 +314,13 @@
|
||||
hide: '숨기기',
|
||||
translateButton: '번역',
|
||||
themeButton: '테마',
|
||||
settingsButton: '설정',
|
||||
settingsTitle: '설정',
|
||||
settingsSaved: '설정을 저장했습니다.',
|
||||
settingsResetDone: '설정을 기본값으로 되돌렸습니다.',
|
||||
settingsSaveFailed: '설정 저장 실패',
|
||||
settingsResetConfirm: 'Control 설정을 모두 기본값으로 되돌릴까요?',
|
||||
settingsDefault: '기본값',
|
||||
rebootButton: '재부팅',
|
||||
dialogAlert: '알림',
|
||||
dialogConfirm: '확인',
|
||||
@@ -386,6 +408,7 @@
|
||||
});
|
||||
els.translateBtn && (els.translateBtn.textContent = t('translateButton'));
|
||||
els.themeBtn && (els.themeBtn.textContent = t('themeButton'));
|
||||
els.settingsBtn && (els.settingsBtn.textContent = t('settingsButton'));
|
||||
els.rebootBtn && (els.rebootBtn.textContent = t('rebootButton'));
|
||||
if (els.dmesgToggle) {
|
||||
els.dmesgToggle.textContent = state.dmesgOpen ? t('hide') : t('show');
|
||||
@@ -583,6 +606,102 @@
|
||||
return json.data;
|
||||
}
|
||||
|
||||
function renderSettings(payload = state.settingsPayload) {
|
||||
if (!els.settingsBody || !payload) return;
|
||||
state.settingsPayload = payload;
|
||||
const groups = payload.groups || {};
|
||||
const byGroup = {};
|
||||
(payload.items || []).forEach(item => {
|
||||
const group = item.group || 'etc';
|
||||
if (!byGroup[group]) byGroup[group] = [];
|
||||
byGroup[group].push(item);
|
||||
});
|
||||
|
||||
els.settingsBody.innerHTML = Object.entries(byGroup).map(([group, items]) => `
|
||||
<section class="settings-group">
|
||||
<h4>${escapeHtml(groups[group] || group)}</h4>
|
||||
<div class="settings-grid">
|
||||
${items.map(item => `
|
||||
<label class="settings-field">
|
||||
<span class="settings-label">
|
||||
<span>${escapeHtml(item.label || item.key)}</span>
|
||||
<span>${escapeHtml(item.unit || '')}</span>
|
||||
</span>
|
||||
<span class="settings-control">
|
||||
<input
|
||||
data-setting-key="${escapeHtml(item.key)}"
|
||||
type="number"
|
||||
min="${escapeHtml(item.min ?? '')}"
|
||||
max="${escapeHtml(item.max ?? '')}"
|
||||
step="${escapeHtml(item.step ?? '1')}"
|
||||
value="${escapeHtml(item.value ?? item.default ?? '')}">
|
||||
<span class="settings-default">${t('settingsDefault')} ${escapeHtml(item.default ?? '')}</span>
|
||||
</span>
|
||||
</label>
|
||||
`).join('')}
|
||||
</div>
|
||||
</section>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
async function openSettings() {
|
||||
if (!els.settingsDialog) return;
|
||||
try {
|
||||
renderSettings(await api('settings'));
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
notice(e.message || t('refreshFailed'), 'error');
|
||||
return;
|
||||
}
|
||||
state.settingsOpen = true;
|
||||
els.settingsDialog.dataset.open = '1';
|
||||
els.settingsDialog.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
|
||||
function closeSettings() {
|
||||
if (!els.settingsDialog) return;
|
||||
state.settingsOpen = false;
|
||||
delete els.settingsDialog.dataset.open;
|
||||
els.settingsDialog.setAttribute('aria-hidden', 'true');
|
||||
}
|
||||
|
||||
function currentSettingsFormValues() {
|
||||
const values = {};
|
||||
els.settingsBody?.querySelectorAll('[data-setting-key]').forEach(input => {
|
||||
values[input.dataset.settingKey] = input.value;
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
try {
|
||||
const data = await api('settings_save', {
|
||||
settings: JSON.stringify(currentSettingsFormValues()),
|
||||
});
|
||||
render(data);
|
||||
renderSettings(data.settings);
|
||||
notice(t('settingsSaved'), 'success');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
notice(e.message || t('settingsSaveFailed'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function resetSettings() {
|
||||
if (!await window.customConfirm(t('settingsResetConfirm'), { title: t('settingsTitle') })) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = await api('settings_reset', {});
|
||||
render(data);
|
||||
renderSettings(data.settings);
|
||||
notice(t('settingsResetDone'), 'success');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
notice(e.message || t('settingsSaveFailed'), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function websocketUrl() {
|
||||
const scheme = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
return `${scheme}//${location.host}/ws`;
|
||||
@@ -1622,6 +1741,12 @@
|
||||
}
|
||||
|
||||
function render(data) {
|
||||
if (data.settings) {
|
||||
state.settingsPayload = data.settings;
|
||||
if (state.settingsOpen) {
|
||||
renderSettings(data.settings);
|
||||
}
|
||||
}
|
||||
renderTop(data);
|
||||
renderSystemStatus(data);
|
||||
renderWifi(data);
|
||||
@@ -1866,6 +1991,15 @@
|
||||
els.rebootBtn?.addEventListener('click', () => {
|
||||
requestReboot();
|
||||
});
|
||||
els.settingsBtn?.addEventListener('click', openSettings);
|
||||
els.settingsClose?.addEventListener('click', closeSettings);
|
||||
els.settingsSave?.addEventListener('click', saveSettings);
|
||||
els.settingsReset?.addEventListener('click', resetSettings);
|
||||
els.settingsDialog?.addEventListener('click', event => {
|
||||
if (event.target === els.settingsDialog) {
|
||||
closeSettings();
|
||||
}
|
||||
});
|
||||
els.translateBtn?.addEventListener('click', () => {
|
||||
applyLang(state.lang === 'ko' ? 'en' : 'ko');
|
||||
refreshStatus();
|
||||
@@ -1884,6 +2018,11 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
document.addEventListener('keydown', event => {
|
||||
if (event.key === 'Escape' && state.settingsOpen) {
|
||||
closeSettings();
|
||||
}
|
||||
});
|
||||
|
||||
initPreferences();
|
||||
connectControlSocket();
|
||||
|
||||
Reference in New Issue
Block a user