Files
astrolabe-nvc/index.html

191 lines
7.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Astrolabe - Vega-Lite Snippet Manager</title>
<link rel="stylesheet" href="src/styles.css">
<!-- Monaco Editor -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.47.0/min/vs/loader.js"></script>
</head>
<body>
<!-- Header -->
<div class="header">
<div class="header-left">
<span class="header-icon">🔭</span>
<span class="header-title">Astrolabe</span>
</div>
<div class="header-links">
<span class="header-link">New</span>
<span class="header-link">Import</span>
<span class="header-link">Export</span>
<span class="header-link">Help</span>
</div>
</div>
<div class="app-container">
<!-- Toggle Button Strip -->
<div class="toggle-strip">
<button class="toggle-btn active" id="toggle-snippets" title="Toggle Snippets Panel">
📄
</button>
<button class="toggle-btn active" id="toggle-editor" title="Toggle Editor Panel">
✏️
</button>
<button class="toggle-btn active" id="toggle-preview" title="Toggle Preview Panel">
👁️
</button>
</div>
<div class="main-panels">
<!-- Snippet Library Panel -->
<div class="panel snippet-panel" id="snippet-panel">
<div class="panel-header">
Snippets
</div>
<div class="panel-content">
<ul class="snippet-list">
<li class="snippet-item">
<div class="snippet-name">2025-10-13_14-23-45</div>
<div class="snippet-date">Oct 13, 2:23 PM</div>
</li>
<li class="snippet-item">
<div class="snippet-name">2025-10-12_09-15-30</div>
<div class="snippet-date">Oct 12, 9:15 AM</div>
</li>
<li class="snippet-item">
<div class="snippet-name">2025-10-11_16-42-18</div>
<div class="snippet-date">Oct 11, 4:42 PM</div>
</li>
</ul>
<div class="placeholder">
Click to select a snippet
</div>
</div>
</div>
<!-- Resize Handle 1 -->
<div class="resize-handle" id="resize-handle-1"></div>
<!-- Editor Panel -->
<div class="panel editor-panel" id="editor-panel">
<div class="panel-header">
Editor
</div>
<div class="panel-content">
<div id="monaco-editor" style="height: 100%; width: 100%;"></div>
</div>
</div>
<!-- Resize Handle 2 -->
<div class="resize-handle" id="resize-handle-2"></div>
<!-- Preview Panel -->
<div class="panel preview-panel" id="preview-panel">
<div class="panel-header">
Preview
</div>
<div class="panel-content">
<div id="vega-preview" style="height: 100%; width: 100%; overflow: auto;"></div>
</div>
</div>
</div>
</div>
<script src="src/js/config.js"></script>
<script src="src/js/panel-manager.js"></script>
<script src="src/js/editor.js"></script>
<script src="src/js/app.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// 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 actual Vega-Lite schema JSON for better 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 actual schema
if (vegaLiteSchema) {
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
validate: true,
schemas: [{
uri: "https://vega.github.io/schema/vega-lite/v5.json",
fileMatch: ["*"], // Associate with all files
schema: vegaLiteSchema
}]
});
}
// Load Vega libraries before creating editor
await loadVegaLibraries();
// Create the editor with improved configuration
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();
});
// Initial render
renderVisualization();
});
// Enhanced toggle functionality with memory and expansion
const toggleButtons = document.querySelectorAll('.toggle-btn');
toggleButtons.forEach(button => {
button.addEventListener('click', function () {
const panelId = this.id.replace('toggle-', ''); // Remove 'toggle-' prefix
togglePanel(panelId);
});
});
// Basic snippet selection
const snippetItems = document.querySelectorAll('.snippet-item');
snippetItems.forEach(item => {
item.addEventListener('click', function () {
snippetItems.forEach(i => i.classList.remove('selected'));
this.classList.add('selected');
});
});
// Header link handlers (placeholder)
const headerLinks = document.querySelectorAll('.header-link');
headerLinks.forEach(link => {
link.addEventListener('click', function () {
// TODO: Implement actual functionality in future phases
});
});
});
</script>
</body>
</html>