feat: add export and import functionality for snippets with UI controls

This commit is contained in:
2025-01-19 15:12:05 +02:00
parent f14f76e2f0
commit a8b2fa4be8
4 changed files with 72 additions and 0 deletions

View File

@@ -25,6 +25,11 @@
<img src="src/astrolabe.svg" alt="Astrolabe logo"> <img src="src/astrolabe.svg" alt="Astrolabe logo">
<h1>Astrolabe</h1> <h1>Astrolabe</h1>
</a> </a>
<div class="header-controls">
<button class="button mini" id="export-snippets">Export</button>
<button class="button mini" id="import-snippets">Import</button>
<input type="file" id="import-file" accept=".json" style="display: none">
</div>
</header> </header>
<div class="panel"> <div class="panel">
<div class="panel-header"> <div class="panel-header">

View File

@@ -13,4 +13,31 @@ export class StorageManager {
saveSnippets(snippets) { saveSnippets(snippets) {
localStorage.setItem(this.SNIPPETS_KEY, JSON.stringify(snippets)); localStorage.setItem(this.SNIPPETS_KEY, JSON.stringify(snippets));
} }
exportSnippets() {
const snippets = this.loadSnippets();
const blob = new Blob([JSON.stringify(snippets, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'astrolabe-snippets.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
async importSnippets(file) {
try {
const text = await file.text();
const snippets = JSON.parse(text);
if (!Array.isArray(snippets)) {
throw new Error('Invalid snippets format');
}
this.saveSnippets(snippets);
return snippets;
} catch (err) {
throw new Error('Failed to import snippets: ' + err.message);
}
}
} }

View File

@@ -21,4 +21,28 @@ require(['vs/editor/editor.main'], async function () {
window.editor = editor; window.editor = editor;
snippetManager.setEditor(editor); snippetManager.setEditor(editor);
document.getElementById('export-snippets').addEventListener('click', () => {
snippetManager.storageManager.exportSnippets();
});
document.getElementById('import-snippets').addEventListener('click', () => {
document.getElementById('import-file').click();
});
document.getElementById('import-file').addEventListener('change', async (e) => {
if (e.target.files.length > 0) {
try {
const snippets = await snippetManager.storageManager.importSnippets(e.target.files[0]);
snippetManager.snippets = snippets;
snippetManager.uiManager.renderSnippetList(snippets, snippetManager.currentSnippetId);
if (snippets.length > 0) {
snippetManager.loadSnippet(snippets[0].id);
}
e.target.value = ''; // Reset file input
} catch (err) {
alert(err.message);
}
}
});
}); });

View File

@@ -9,6 +9,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.75rem; gap: 0.75rem;
justify-content: space-between;
} }
.app-header a { .app-header a {
@@ -37,6 +38,21 @@
margin: 0; margin: 0;
} }
.header-controls {
display: flex;
gap: 0.5rem;
}
.button.mini {
padding: 0.25rem 0.75rem;
font-size: 0.875rem;
background: #607D8B;
}
.button.mini:hover {
background: #546E7A;
}
#vis { #vis {
width: 100%; width: 100%;
height: 100%; height: 100%;