Start with an empty document; offer Datei › Neu and Datei › Muster
A first start (nothing in localStorage) now opens a blank document -- one sheet "Blatt 1" with an empty "Tabelle 1" -- instead of the pre-filled sample. The file menu gets "Neu" (blank document) and "Muster · Umsatzanalyse" (the former seed), both behind a confirm and both starting a fresh undo history. The toolbar's "Zurücksetzen" button is gone; its job is now Datei › Muster. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -196,10 +196,17 @@ async function doImport(action: 'replace' | 'append' | 'confirm') {
|
||||
}
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
if (confirm('Vorbefülltes Dokument wiederherstellen? Alle Änderungen gehen verloren.')) {
|
||||
function onNew() {
|
||||
if (confirm('Neues, leeres Dokument anlegen? Alle Änderungen gehen verloren.')) {
|
||||
store.newDocument();
|
||||
toasts.info('Neues Dokument angelegt.');
|
||||
}
|
||||
}
|
||||
|
||||
function onSample() {
|
||||
if (confirm('Musterdokument laden? Alle Änderungen gehen verloren.')) {
|
||||
store.resetToSeed();
|
||||
toasts.info('Dokument zurückgesetzt.');
|
||||
toasts.info('Musterdokument geladen.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -291,6 +298,9 @@ function onReset() {
|
||||
<div class="menu-wrap">
|
||||
<button class="btn" @click="fileMenuOpen = !fileMenuOpen">Datei ▾</button>
|
||||
<ul v-if="fileMenuOpen" class="menu" @click="fileMenuOpen = false">
|
||||
<li><button @click="onNew">Neu</button></li>
|
||||
<li><button @click="onSample">Muster · Umsatzanalyse</button></li>
|
||||
<li class="sep" />
|
||||
<li><button @click="pickFile">Importieren … (.json .csv .xlsx)</button></li>
|
||||
<li class="sep" />
|
||||
<li><button @click="runJsonExport">Export · Dokument (.json)</button></li>
|
||||
@@ -310,7 +320,6 @@ function onReset() {
|
||||
>
|
||||
<ToolbarIcon :name="themeIcon" />
|
||||
</button>
|
||||
<button class="btn" @click="onReset">Zurücksetzen</button>
|
||||
|
||||
<input ref="fileInput" type="file" accept=".json,.csv,.xlsx" hidden @change="onFileChosen" />
|
||||
<span v-if="busy" class="busy">Verarbeite …</span>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/**
|
||||
* Document templates: `createBlankDocument()` (Datei › Neu, and what a first
|
||||
* start opens) and `createSeedDocument()` (Datei › Muster).
|
||||
*
|
||||
* The pre-filled document ("roter Faden" of the study), in the v2 canvas model:
|
||||
* one sheet ("Analyse") carrying three table objects and a chart object, plus a
|
||||
* second empty sheet to try things out.
|
||||
@@ -144,3 +147,21 @@ export function createSeedDocument(): DocumentState {
|
||||
macros: [],
|
||||
};
|
||||
}
|
||||
|
||||
/** An empty document: one sheet with one empty table, ready to type into. */
|
||||
export function createBlankDocument(): DocumentState {
|
||||
const table = makeTable('Tabelle 1', 40, 40, 12, 6, []);
|
||||
const sheet = { id: nextId('sheet'), name: 'Blatt 1', objects: [table] };
|
||||
return {
|
||||
version: 2,
|
||||
sheets: [sheet],
|
||||
activeSheetId: sheet.id,
|
||||
activeObjectId: table.id,
|
||||
selection: { tableId: table.id, anchor: { col: 0, row: 0 }, focus: { col: 0, row: 0 } },
|
||||
locale: 'de-DE',
|
||||
csvDelimiter: ',',
|
||||
customFunctions: [],
|
||||
namedRanges: [],
|
||||
macros: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -120,6 +120,19 @@ describe('seed document acceptance (canvas model)', () => {
|
||||
expect(val(s, 'Übersicht', 'B2')).toBe(5970);
|
||||
});
|
||||
|
||||
it('newDocument replaces everything with one empty sheet + table and a fresh history', () => {
|
||||
const s = fresh();
|
||||
setCell(s, 'Umsatz', 'B2', '99999');
|
||||
s.newDocument();
|
||||
expect(s.doc.sheets).toHaveLength(1);
|
||||
expect(s.doc.sheets[0].name).toBe('Blatt 1');
|
||||
const [table] = s.doc.sheets[0].objects;
|
||||
expect(table.kind === 'table' && table.name).toBe('Tabelle 1');
|
||||
expect(table.kind === 'table' && Object.keys(table.cells)).toEqual([]);
|
||||
expect(s.doc.namedRanges).toEqual([]);
|
||||
expect(s.canUndo.value).toBe(false);
|
||||
});
|
||||
|
||||
it('inserting a new table and referencing it across sheets works', () => {
|
||||
const s = fresh();
|
||||
const sheet2 = s.doc.sheets[1].id;
|
||||
|
||||
@@ -77,7 +77,7 @@ import type {
|
||||
TextObject,
|
||||
} from './types';
|
||||
import { defaultTableView, DEFAULT_ROW_H, MIN_GRID_SIZE, MAX_GRID_SIZE } from './types';
|
||||
import { createSeedDocument } from '../data/seed';
|
||||
import { createBlankDocument, createSeedDocument } from '../data/seed';
|
||||
import { validateDocument } from '../io/json';
|
||||
|
||||
const STORAGE_KEY = 'numolus:doc:v2';
|
||||
@@ -535,7 +535,7 @@ function loadInitial(): DocumentState {
|
||||
} catch {
|
||||
/* missing / corrupt / stale-schema -> clean fallback */
|
||||
}
|
||||
return createSeedDocument();
|
||||
return createBlankDocument();
|
||||
}
|
||||
|
||||
// ---- store singleton --------------------------------------------------
|
||||
@@ -2848,6 +2848,11 @@ function createStore() {
|
||||
applyDocumentState(next);
|
||||
resetHistory();
|
||||
}
|
||||
/** Datei › Neu: an empty document. */
|
||||
function newDocument() {
|
||||
replaceDocument(createBlankDocument());
|
||||
}
|
||||
/** Datei › Muster: the pre-filled sample document. */
|
||||
function resetToSeed() {
|
||||
replaceDocument(createSeedDocument());
|
||||
}
|
||||
@@ -3040,6 +3045,7 @@ function createStore() {
|
||||
pointDrag,
|
||||
// document
|
||||
replaceDocument,
|
||||
newDocument,
|
||||
resetToSeed,
|
||||
appendSheets,
|
||||
addTableFromCells,
|
||||
|
||||
Reference in New Issue
Block a user