Makros: UI (Button-Objekt, Verwaltungspanel, Symbolleiste)
Zweiter von zwei Commits (Fundament in e670f13). Neues, frei platzierbares
Button-Objekt auf der Fläche, das per Klick ein zugewiesenes Makro
ausführt (Zuweisung im Inspektor oder per Rechtsklick direkt am Button).
Neues "▶ Makros"-Panel (Liste + Formular, dritter "▶ Ausführen"-Button pro
Zeile) für Anlegen/Bearbeiten/Löschen/Testlauf ohne Canvas-Button.
Beim Live-Testen gefunden und behoben: ADDTABLE/ADDSHEET navigieren als
Nebeneffekt zur eingefügten Tabelle/zum eingefügten Blatt (richtig für
einen Symbolleisten-Klick, überraschend für einen Makro-Lauf im
Hintergrund) — runMacro() sichert und stellt jetzt aktives Blatt/Objekt/
Auswahl nach dem Lauf wieder her. Nebenbei zwei bestehende
"impliziter-Else"-Fehler behoben, die mit einer vierten Objektart zu
echten Fehlerquellen geworden wären (io/json.ts normaliseObject,
CanvasObject.vue Render-Dispatch).
Vollständig live per Playwright End-zu-Ende verifiziert: Makro über das
echte Formular angelegt, per Listen-Button und per Button-Objekt
ausgeführt, Rechtsklick-Zuweisung geprüft, ein absichtlich fehlerhaftes
Makro zeigt einen Fehler-Toast statt abzustürzen — keine Konsolenfehler.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+55
-15
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
import type {
|
||||
ButtonObject,
|
||||
CellCoord,
|
||||
CellFormat,
|
||||
ChartObject,
|
||||
@@ -277,6 +278,24 @@ function isTextObject(x: unknown): x is TextObject {
|
||||
);
|
||||
}
|
||||
|
||||
function isButtonObject(x: unknown): x is ButtonObject {
|
||||
const o = x as ButtonObject;
|
||||
return (
|
||||
!!o &&
|
||||
o.kind === 'button' &&
|
||||
typeof o.id === 'string' &&
|
||||
typeof o.name === 'string' &&
|
||||
Number.isFinite(o.x) &&
|
||||
Number.isFinite(o.y) &&
|
||||
Number.isFinite(o.width) &&
|
||||
Number.isFinite(o.height) &&
|
||||
typeof o.label === 'string'
|
||||
// macroId is intentionally NOT checked against a real macro here --
|
||||
// same lenient "dangling id renders as unassigned" convention as a
|
||||
// chart's sourceTableId, see ButtonObject's doc comment.
|
||||
);
|
||||
}
|
||||
|
||||
function normaliseTableView(v: Partial<TableView> | undefined, rows: number, cols: number): TableView {
|
||||
const d = defaultTableView();
|
||||
const mode = v?.mode === 'fixed' ? 'fixed' : 'auto';
|
||||
@@ -333,20 +352,41 @@ function normaliseObject(o: SheetObject): SheetObject {
|
||||
bg: colorOrUndef(o.bg),
|
||||
};
|
||||
}
|
||||
return {
|
||||
kind: 'chart',
|
||||
id: o.id,
|
||||
name: o.name,
|
||||
x: Math.max(0, Math.round(o.x)),
|
||||
y: Math.max(0, Math.round(o.y)),
|
||||
width: Math.max(200, Math.round(o.width)),
|
||||
height: Math.max(140, Math.round(o.height)),
|
||||
view: o.view,
|
||||
sourceTableId: o.sourceTableId ?? null,
|
||||
locale: localeOrUndef(o.locale),
|
||||
bg: colorOrUndef(o.bg),
|
||||
fg: colorOrUndef(o.fg),
|
||||
};
|
||||
if (o.kind === 'button') {
|
||||
return {
|
||||
kind: 'button',
|
||||
id: o.id,
|
||||
name: o.name,
|
||||
x: Math.max(0, Math.round(o.x)),
|
||||
y: Math.max(0, Math.round(o.y)),
|
||||
width: Math.max(60, Math.round(o.width)),
|
||||
height: Math.max(28, Math.round(o.height)),
|
||||
label: String(o.label ?? ''),
|
||||
macroId: typeof o.macroId === 'string' ? o.macroId : null,
|
||||
bg: colorOrUndef(o.bg),
|
||||
fg: colorOrUndef(o.fg),
|
||||
};
|
||||
}
|
||||
if (o.kind === 'chart') {
|
||||
return {
|
||||
kind: 'chart',
|
||||
id: o.id,
|
||||
name: o.name,
|
||||
x: Math.max(0, Math.round(o.x)),
|
||||
y: Math.max(0, Math.round(o.y)),
|
||||
width: Math.max(200, Math.round(o.width)),
|
||||
height: Math.max(140, Math.round(o.height)),
|
||||
view: o.view,
|
||||
sourceTableId: o.sourceTableId ?? null,
|
||||
locale: localeOrUndef(o.locale),
|
||||
bg: colorOrUndef(o.bg),
|
||||
fg: colorOrUndef(o.fg),
|
||||
};
|
||||
}
|
||||
// Every SheetObject kind is handled above -- reachable only if a new kind
|
||||
// is added to the union without a branch here (a compile-time error at
|
||||
// the call site would already catch that; this is the runtime backstop).
|
||||
throw new JsonImportError('Unbekannte Objektart.');
|
||||
}
|
||||
|
||||
export function validateDocument(x: unknown): DocumentState {
|
||||
@@ -369,7 +409,7 @@ export function validateDocument(x: unknown): DocumentState {
|
||||
if (sheetIds.has(s.id)) throw new JsonImportError('Doppelte Blatt-ID.');
|
||||
sheetIds.add(s.id);
|
||||
for (const o of s.objects) {
|
||||
if (!isTableObject(o) && !isChartObject(o) && !isTextObject(o))
|
||||
if (!isTableObject(o) && !isChartObject(o) && !isTextObject(o) && !isButtonObject(o))
|
||||
throw new JsonImportError('Mindestens ein Objekt ist fehlerhaft.');
|
||||
if (objectIds.has(o.id)) throw new JsonImportError('Doppelte Objekt-ID.');
|
||||
objectIds.add(o.id);
|
||||
|
||||
Reference in New Issue
Block a user