diff --git a/index.html b/index.html index c12d6b8..52838af 100644 --- a/index.html +++ b/index.html @@ -28,13 +28,13 @@
- - -
@@ -130,107 +130,6 @@ - - \ No newline at end of file diff --git a/src/js/app.js b/src/js/app.js index e69de29..460e997 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -0,0 +1,89 @@ +// Application initialization and event handlers + +document.addEventListener('DOMContentLoaded', function () { + // Initialize snippet storage and render list + initializeSnippetsStorage(); + + // Initialize sort controls + initializeSortControls(); + + // Initialize search controls + initializeSearchControls(); + + renderSnippetList(); + + // Load saved layout + loadLayoutFromStorage(); + + // Initialize resize functionality + initializeResize(); + + // Initialize Monaco Editor + require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.47.0/min/vs' } }); + require(['vs/editor/editor.main'], async function () { + // Fetch Vega-Lite schema for validation + let vegaLiteSchema; + try { + const response = await fetch('https://vega.github.io/schema/vega-lite/v5.json'); + vegaLiteSchema = await response.json(); + } catch (error) { + vegaLiteSchema = null; + } + + // Configure JSON language with schema + if (vegaLiteSchema) { + monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ + validate: true, + schemas: [{ + uri: "https://vega.github.io/schema/vega-lite/v5.json", + fileMatch: ["*"], + schema: vegaLiteSchema + }] + }); + } + + // Load Vega libraries before creating editor + await loadVegaLibraries(); + + // Create the editor + editor = monaco.editor.create(document.getElementById('monaco-editor'), { + value: JSON.stringify(sampleSpec, null, 2), + language: 'json', + theme: 'vs-light', + fontSize: 12, + minimap: { enabled: false }, + scrollBeyondLastLine: false, + automaticLayout: true, + wordWrap: 'on', + formatOnPaste: true, + formatOnType: true + }); + + // Add debounced auto-render on editor change + editor.onDidChangeModelContent(() => { + debouncedRender(); + debouncedAutoSave(); + }); + + // Initial render + renderVisualization(); + + // Initialize auto-save functionality + initializeAutoSave(); + }); + + // Toggle panel buttons + document.querySelectorAll('.toggle-btn').forEach(button => { + button.addEventListener('click', function () { + const panelId = this.id.replace('toggle-', ''); + togglePanel(panelId); + }); + }); + + // Header links - show placeholder + document.querySelectorAll('.header-link').forEach(link => { + link.addEventListener('click', function () { + alert('Coming soon in a future phase!'); + }); + }); +}); diff --git a/src/js/editor.js b/src/js/editor.js index 866349a..2ea6129 100644 --- a/src/js/editor.js +++ b/src/js/editor.js @@ -28,14 +28,14 @@ async function renderVisualization() { // Debounced render function function debouncedRender() { - clearTimeout(renderTimeout); - - // If we're updating the editor programmatically, render immediately + // Don't debounce if we're programmatically updating - render immediately if (window.isUpdatingEditor) { renderVisualization(); - } else { - renderTimeout = setTimeout(renderVisualization, 1500); // 1.5s delay for user edits + return; } + + clearTimeout(renderTimeout); + renderTimeout = setTimeout(renderVisualization, 1500); } // Load Vega libraries dynamically with UMD builds diff --git a/src/js/panel-manager.js b/src/js/panel-manager.js index 289f19f..ea3cef4 100644 --- a/src/js/panel-manager.js +++ b/src/js/panel-manager.js @@ -18,22 +18,10 @@ function updatePanelMemory() { function togglePanel(panelId) { + const panel = document.getElementById(panelId); + const button = document.getElementById(`toggle-${panelId}`); - // Fix ID mapping - buttons use plural, panels use singular - const panelIdMap = { - 'snippets': 'snippet-panel', - 'editor': 'editor-panel', - 'preview': 'preview-panel' - }; - - const actualPanelId = panelIdMap[panelId]; - const panel = document.getElementById(actualPanelId); - const button = document.getElementById('toggle-' + panelId); - - - if (!panel || !button) { - return; - } + if (!panel || !button) return; if (panel.style.display === 'none') { // Show panel @@ -126,9 +114,9 @@ function loadLayoutFromStorage() { previewPanel.style.display = layout.previewVisible !== false ? 'flex' : 'none'; // Update toggle button states - document.getElementById('toggle-snippets').classList.toggle('active', layout.snippetVisible !== false); - document.getElementById('toggle-editor').classList.toggle('active', layout.editorVisible !== false); - document.getElementById('toggle-preview').classList.toggle('active', layout.previewVisible !== false); + document.getElementById('toggle-snippet-panel').classList.toggle('active', layout.snippetVisible !== false); + document.getElementById('toggle-editor-panel').classList.toggle('active', layout.editorVisible !== false); + document.getElementById('toggle-preview-panel').classList.toggle('active', layout.previewVisible !== false); // Restore widths and redistribute snippetPanel.style.width = layout.snippetWidth; diff --git a/src/js/snippet-manager.js b/src/js/snippet-manager.js index ae7b927..f2f363b 100644 --- a/src/js/snippet-manager.js +++ b/src/js/snippet-manager.js @@ -8,14 +8,9 @@ function generateSnippetId() { // Generate auto-populated name with current datetime function generateSnippetName() { const now = new Date(); - const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - const day = String(now.getDate()).padStart(2, '0'); - const hours = String(now.getHours()).padStart(2, '0'); - const minutes = String(now.getMinutes()).padStart(2, '0'); - const seconds = String(now.getSeconds()).padStart(2, '0'); + const pad = (n) => String(n).padStart(2, '0'); - return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`; + return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}-${pad(now.getMinutes())}-${pad(now.getSeconds())}`; } // Create a new snippet using Phase 0 schema @@ -174,19 +169,12 @@ function initializeSnippetsStorage() { // Format date for display in snippet list function formatSnippetDate(isoString) { const date = new Date(isoString); - const now = new Date(); - const diffMs = now - date; - const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24)); + const diffDays = Math.floor((new Date() - date) / (1000 * 60 * 60 * 24)); - if (diffDays === 0) { - return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); - } else if (diffDays === 1) { - return 'Yesterday'; - } else if (diffDays < 7) { - return `${diffDays} days ago`; - } else { - return date.toLocaleDateString(); - } + if (diffDays === 0) return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + if (diffDays === 1) return 'Yesterday'; + if (diffDays < 7) return `${diffDays} days ago`; + return date.toLocaleDateString(); } // Format full date/time for display in meta info @@ -409,9 +397,7 @@ function clearSelection() { if (editor) { window.isUpdatingEditor = true; editor.setValue('{}'); - setTimeout(() => { - window.isUpdatingEditor = false; - }, 50); + window.isUpdatingEditor = false; } // Hide meta panel and show placeholder @@ -459,9 +445,7 @@ function selectSnippet(snippetId) { if (editor) { window.isUpdatingEditor = true; editor.setValue(JSON.stringify(snippet.draftSpec, null, 2)); - setTimeout(() => { - window.isUpdatingEditor = false; - }, 50); // Small delay to ensure setValue completes + window.isUpdatingEditor = false; } // Show and populate meta fields @@ -524,12 +508,6 @@ function debouncedAutoSave() { // Initialize auto-save on editor changes function initializeAutoSave() { - if (editor) { - editor.onDidChangeModelContent(() => { - debouncedAutoSave(); - }); - } - // Initialize meta fields auto-save const nameField = document.getElementById('snippet-name'); const commentField = document.getElementById('snippet-comment'); @@ -651,19 +629,7 @@ function deleteSnippet(snippetId) { // If we deleted the currently selected snippet, clear selection if (window.currentSnippetId === snippetId) { - window.currentSnippetId = null; - if (editor) { - window.isUpdatingEditor = true; - editor.setValue('{}'); - setTimeout(() => { - window.isUpdatingEditor = false; - }, 50); - } - // Hide comment field and show placeholder - const metaSection = document.getElementById('snippet-meta'); - const placeholder = document.querySelector('.placeholder'); - if (metaSection) metaSection.style.display = 'none'; - if (placeholder) placeholder.style.display = 'block'; + clearSelection(); } // Refresh the list