mirror of
https://github.com/olehomelchenko/astrolabe-nvc.git
synced 2025-12-21 21:22:23 +00:00
feat: implement Alpine.js settings panel for user preferences and configuration management
This commit is contained in:
203
src/js/app.js
203
src/js/app.js
@@ -184,61 +184,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
|
||||
// Settings Modal
|
||||
const settingsLink = document.getElementById('settings-link');
|
||||
const settingsApplyBtn = document.getElementById('settings-apply-btn');
|
||||
const settingsResetBtn = document.getElementById('settings-reset-btn');
|
||||
const settingsCancelBtn = document.getElementById('settings-cancel-btn');
|
||||
|
||||
if (settingsLink) {
|
||||
settingsLink.addEventListener('click', openSettingsModal);
|
||||
}
|
||||
|
||||
if (settingsCancelBtn) {
|
||||
settingsCancelBtn.addEventListener('click', closeSettingsModal);
|
||||
}
|
||||
|
||||
if (settingsApplyBtn) {
|
||||
settingsApplyBtn.addEventListener('click', applySettings);
|
||||
}
|
||||
|
||||
if (settingsResetBtn) {
|
||||
settingsResetBtn.addEventListener('click', function() {
|
||||
if (confirm('Reset all settings to defaults? This cannot be undone.')) {
|
||||
resetSettings();
|
||||
loadSettingsIntoUI();
|
||||
Toast.show('Settings reset to defaults', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Settings UI interactions
|
||||
const fontSizeSlider = document.getElementById('setting-font-size');
|
||||
const fontSizeValue = document.getElementById('setting-font-size-value');
|
||||
if (fontSizeSlider && fontSizeValue) {
|
||||
fontSizeSlider.addEventListener('input', function() {
|
||||
fontSizeValue.textContent = this.value + 'px';
|
||||
});
|
||||
}
|
||||
|
||||
const renderDebounceSlider = document.getElementById('setting-render-debounce');
|
||||
const renderDebounceValue = document.getElementById('setting-render-debounce-value');
|
||||
if (renderDebounceSlider && renderDebounceValue) {
|
||||
renderDebounceSlider.addEventListener('input', function() {
|
||||
renderDebounceValue.textContent = this.value + 'ms';
|
||||
});
|
||||
}
|
||||
|
||||
const dateFormatSelect = document.getElementById('setting-date-format');
|
||||
const customDateFormatItem = document.getElementById('custom-date-format-item');
|
||||
if (dateFormatSelect && customDateFormatItem) {
|
||||
dateFormatSelect.addEventListener('change', function() {
|
||||
if (this.value === 'custom') {
|
||||
customDateFormatItem.style.display = 'block';
|
||||
} else {
|
||||
customDateFormatItem.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
// Settings buttons and UI interactions now handled by Alpine.js in settingsPanel() component
|
||||
|
||||
// Dataset Manager
|
||||
const datasetsLink = document.getElementById('datasets-link');
|
||||
@@ -567,160 +518,12 @@ function registerMonacoKeyboardShortcuts() {
|
||||
KeyboardActions.publishDraft);
|
||||
}
|
||||
|
||||
// Settings modal functions (special handling for loading settings into UI)
|
||||
// Settings modal functions (simplified - most logic now in Alpine settingsPanel() component)
|
||||
function openSettingsModal() {
|
||||
loadSettingsIntoUI();
|
||||
ModalManager.open('settings-modal');
|
||||
// Settings will be loaded via Alpine's init() method
|
||||
}
|
||||
|
||||
function closeSettingsModal() {
|
||||
ModalManager.close('settings-modal');
|
||||
}
|
||||
|
||||
function loadSettingsIntoUI() {
|
||||
const settings = getSettings();
|
||||
|
||||
// Appearance settings
|
||||
const uiThemeSelect = document.getElementById('setting-ui-theme');
|
||||
if (uiThemeSelect) {
|
||||
uiThemeSelect.value = settings.ui.theme;
|
||||
}
|
||||
|
||||
// Editor settings
|
||||
const fontSizeSlider = document.getElementById('setting-font-size');
|
||||
const fontSizeValue = document.getElementById('setting-font-size-value');
|
||||
if (fontSizeSlider && fontSizeValue) {
|
||||
fontSizeSlider.value = settings.editor.fontSize;
|
||||
fontSizeValue.textContent = settings.editor.fontSize + 'px';
|
||||
}
|
||||
|
||||
const editorThemeSelect = document.getElementById('setting-editor-theme');
|
||||
if (editorThemeSelect) {
|
||||
editorThemeSelect.value = settings.editor.theme;
|
||||
}
|
||||
|
||||
const tabSizeSelect = document.getElementById('setting-tab-size');
|
||||
if (tabSizeSelect) {
|
||||
tabSizeSelect.value = settings.editor.tabSize;
|
||||
}
|
||||
|
||||
const minimapCheckbox = document.getElementById('setting-minimap');
|
||||
if (minimapCheckbox) {
|
||||
minimapCheckbox.checked = settings.editor.minimap;
|
||||
}
|
||||
|
||||
const wordWrapCheckbox = document.getElementById('setting-word-wrap');
|
||||
if (wordWrapCheckbox) {
|
||||
wordWrapCheckbox.checked = settings.editor.wordWrap === 'on';
|
||||
}
|
||||
|
||||
const lineNumbersCheckbox = document.getElementById('setting-line-numbers');
|
||||
if (lineNumbersCheckbox) {
|
||||
lineNumbersCheckbox.checked = settings.editor.lineNumbers === 'on';
|
||||
}
|
||||
|
||||
// Performance settings
|
||||
const renderDebounceSlider = document.getElementById('setting-render-debounce');
|
||||
const renderDebounceValue = document.getElementById('setting-render-debounce-value');
|
||||
if (renderDebounceSlider && renderDebounceValue) {
|
||||
renderDebounceSlider.value = settings.performance.renderDebounce;
|
||||
renderDebounceValue.textContent = settings.performance.renderDebounce + 'ms';
|
||||
}
|
||||
|
||||
// Formatting settings
|
||||
const dateFormatSelect = document.getElementById('setting-date-format');
|
||||
const customDateFormatItem = document.getElementById('custom-date-format-item');
|
||||
if (dateFormatSelect) {
|
||||
dateFormatSelect.value = settings.formatting.dateFormat;
|
||||
if (customDateFormatItem) {
|
||||
customDateFormatItem.style.display = settings.formatting.dateFormat === 'custom' ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
const customDateFormatInput = document.getElementById('setting-custom-date-format');
|
||||
if (customDateFormatInput) {
|
||||
customDateFormatInput.value = settings.formatting.customDateFormat;
|
||||
}
|
||||
}
|
||||
|
||||
function applySettings() {
|
||||
// Collect values from UI
|
||||
const newSettings = {
|
||||
'ui.theme': document.getElementById('setting-ui-theme').value,
|
||||
'editor.fontSize': parseInt(document.getElementById('setting-font-size').value),
|
||||
'editor.theme': document.getElementById('setting-editor-theme').value,
|
||||
'editor.tabSize': parseInt(document.getElementById('setting-tab-size').value),
|
||||
'editor.minimap': document.getElementById('setting-minimap').checked,
|
||||
'editor.wordWrap': document.getElementById('setting-word-wrap').checked ? 'on' : 'off',
|
||||
'editor.lineNumbers': document.getElementById('setting-line-numbers').checked ? 'on' : 'off',
|
||||
'performance.renderDebounce': parseInt(document.getElementById('setting-render-debounce').value),
|
||||
'formatting.dateFormat': document.getElementById('setting-date-format').value,
|
||||
'formatting.customDateFormat': document.getElementById('setting-custom-date-format').value
|
||||
};
|
||||
|
||||
// Validate settings
|
||||
let hasErrors = false;
|
||||
for (const [path, value] of Object.entries(newSettings)) {
|
||||
const errors = validateSetting(path, value);
|
||||
if (errors.length > 0) {
|
||||
Toast.show(errors.join(', '), 'error');
|
||||
hasErrors = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasErrors) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save settings
|
||||
if (updateSettings(newSettings)) {
|
||||
// Apply theme to document
|
||||
const uiTheme = newSettings['ui.theme'];
|
||||
document.documentElement.setAttribute('data-theme', uiTheme);
|
||||
|
||||
// Sync editor theme with UI theme
|
||||
const editorTheme = uiTheme === 'experimental' ? 'vs-dark' : 'vs-light';
|
||||
newSettings['editor.theme'] = editorTheme;
|
||||
|
||||
// Apply editor settings immediately
|
||||
if (editor) {
|
||||
editor.updateOptions({
|
||||
fontSize: newSettings['editor.fontSize'],
|
||||
theme: editorTheme,
|
||||
tabSize: newSettings['editor.tabSize'],
|
||||
minimap: { enabled: newSettings['editor.minimap'] },
|
||||
wordWrap: newSettings['editor.wordWrap'],
|
||||
lineNumbers: newSettings['editor.lineNumbers']
|
||||
});
|
||||
}
|
||||
|
||||
// Update the editor theme in settings
|
||||
updateSetting('editor.theme', editorTheme);
|
||||
|
||||
// Update debounced render function
|
||||
if (typeof updateRenderDebounce === 'function') {
|
||||
updateRenderDebounce(newSettings['performance.renderDebounce']);
|
||||
}
|
||||
|
||||
// Re-render snippet list to reflect date format changes
|
||||
renderSnippetList();
|
||||
|
||||
// Update metadata display if a snippet is selected
|
||||
if (window.currentSnippetId) {
|
||||
const snippet = SnippetStorage.getSnippet(window.currentSnippetId);
|
||||
if (snippet) {
|
||||
document.getElementById('snippet-created').textContent = formatDate(snippet.created, true);
|
||||
document.getElementById('snippet-modified').textContent = formatDate(snippet.modified, true);
|
||||
}
|
||||
}
|
||||
|
||||
Toast.show('Settings applied successfully', 'success');
|
||||
closeSettingsModal();
|
||||
|
||||
// Track event
|
||||
Analytics.track('settings-apply', 'Applied settings');
|
||||
} else {
|
||||
Toast.show('Failed to save settings', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user