Interaktives Abhängigkeiten-Panel (Vorgänger/Nachfolger, andockbar)
Rechtsklick auf eine Zelle → "🕸 Abhängigkeiten anzeigen" öffnet ein an der rechten Seite angedocktes Panel (wie das Einstellungen-Panel links) mit den direkten Vorgängern (was die Zelle liest) und Nachfolgern (was sie liest), auch über Tabellen-/Blattgrenzen hinweg. Ein Klick auf einen Eintrag navigiert wirklich dorthin: wählt die echte Zelle im Dokument aus, wechselt bei Bedarf das Blatt-Tab, und das Panel zentriert sich neu — Blatt-Tabs, Canvas, Formel- und Statusleiste bleiben dabei die ganze Zeit sichtbar und bedienbar (kein Vollbild-Dialog). Jeder Eintrag zeigt immer den Blattnamen, nie nur implizit. Zirkelbezüge werden rot markiert. Neu in der Engine: Workbook.graphPrecedents/graphDependents, dünne öffentliche Wrapper um den bereits vorhandenen DependencyGraph. Im Store: cellGraphSelf/cellGraphNeighbors (Anreicherung für die Anzeige) sowie openDependencyGraph/closeDependencyGraph (dokumentweiter UI-State, ruft intern das bestehende selectCell auf). 424 Tests (Engine-/Store-Ebene vollständig abgedeckt), vue-tsc/eslint/build sauber. Das Panel selbst nur live per Playwright verifiziert (kein Komponenten-Test-Setup vorhanden, in README dokumentiert). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+78
-1
@@ -35,6 +35,7 @@ import {
|
||||
blockAlwaysReturns,
|
||||
parseDateTimeLiteral,
|
||||
BUILTIN_SIGNATURES,
|
||||
type CellRef,
|
||||
type CellValue,
|
||||
type TableModel,
|
||||
type Token,
|
||||
@@ -51,6 +52,7 @@ import {
|
||||
import type {
|
||||
CellCoord,
|
||||
CellFormat,
|
||||
CellGraphNode,
|
||||
ChartObject,
|
||||
CustomFunction,
|
||||
DocumentState,
|
||||
@@ -423,7 +425,14 @@ function createStore() {
|
||||
const bump = () => (recalcTick.value += 1);
|
||||
|
||||
/** View-only state: not part of the document, not persisted. */
|
||||
const ui = reactive({ settingsOpen: false });
|
||||
const ui = reactive({
|
||||
settingsOpen: false,
|
||||
/** The dependency-graph drawer's centered cell, or `null` when closed
|
||||
* -- a single document-wide panel (like `settingsOpen`), not owned by
|
||||
* any one `TableGrid` instance, so navigating across tables/sheets
|
||||
* inside it doesn't depend on which grid happened to open it. */
|
||||
depGraph: null as { tableId: string; col: number; row: number } | null,
|
||||
});
|
||||
/** Copy/cut buffer -- not part of the persisted document. */
|
||||
const clipboard = ref<ClipboardData | null>(null);
|
||||
/** Whichever formula editor is currently open (in-cell editor or formula
|
||||
@@ -1244,6 +1253,70 @@ function createStore() {
|
||||
const cellIsError = (t: string, c: number, r: number) => isError(cellValue(t, c, r));
|
||||
const cellIsFormula = (t: string, c: number, r: number) => cellInput(t, c, r).startsWith('=');
|
||||
|
||||
// ---- dependency-graph view (precedents/dependents of a cell) ---------
|
||||
const isCellCircular = (v: CellValue): boolean => isError(v) && v.code === '#CIRC';
|
||||
function describeCellRef(ref: CellRef): CellGraphNode | null {
|
||||
const table = tableById(ref.tableId);
|
||||
if (!table) return null; // dangling (table deleted mid-navigation) -- drop it
|
||||
const sheetId = sheetIdOfObject(ref.tableId);
|
||||
const sheetName = (sheetId && sheetById(sheetId)?.name) || '';
|
||||
const value = wb.cellValue(ref.tableId, ref.col, ref.row);
|
||||
return {
|
||||
tableId: ref.tableId,
|
||||
tableName: table.name,
|
||||
sheetName,
|
||||
col: ref.col,
|
||||
row: ref.row,
|
||||
label: toA1(ref.col, ref.row),
|
||||
raw: cellInput(ref.tableId, ref.col, ref.row),
|
||||
value,
|
||||
isCircular: isCellCircular(value),
|
||||
};
|
||||
}
|
||||
/** Stable render order -- a `Set`'s iteration order is otherwise
|
||||
* insertion-order-dependent and would make the graph view jump around
|
||||
* on every re-render for no reason. */
|
||||
const graphNodeSort = (a: CellGraphNode, b: CellGraphNode): number =>
|
||||
a.tableName.localeCompare(b.tableName) || a.row - b.row || a.col - b.col;
|
||||
|
||||
/** The centered cell itself, described the same way as a precedent/
|
||||
* dependent node -- null if its table no longer exists. */
|
||||
function cellGraphSelf(tableId: string, col: number, row: number): CellGraphNode | null {
|
||||
void recalcTick.value;
|
||||
return describeCellRef({ tableId, col, row });
|
||||
}
|
||||
/** Direct precedents/dependents of a cell (see engine/graph.ts), enriched
|
||||
* for display -- the data source for the interactive dependency-graph
|
||||
* view (`DependencyGraphView.vue`). */
|
||||
function cellGraphNeighbors(
|
||||
tableId: string,
|
||||
col: number,
|
||||
row: number,
|
||||
): { precedents: CellGraphNode[]; dependents: CellGraphNode[] } {
|
||||
void recalcTick.value;
|
||||
const toNodes = (refs: CellRef[]) =>
|
||||
refs.map(describeCellRef).filter((n): n is CellGraphNode => n !== null).sort(graphNodeSort);
|
||||
return {
|
||||
precedents: toNodes(wb.graphPrecedents(tableId, col, row)),
|
||||
dependents: toNodes(wb.graphDependents(tableId, col, row)),
|
||||
};
|
||||
}
|
||||
/** Opens the dependency-graph drawer centered on this cell -- also *really*
|
||||
* selects it (via the existing `selectCell`, which already switches the
|
||||
* active sheet/object as a side effect), so the sheet tabs, canvas,
|
||||
* formula bar and status bar all reflect where you are, not just the
|
||||
* drawer itself. Reused as-is for navigating *inside* the already-open
|
||||
* drawer (clicking a precedent/dependent node calls this again) -- a
|
||||
* jump across sheets/tables inside the graph is then indistinguishable
|
||||
* from clicking that cell directly. */
|
||||
function openDependencyGraph(tableId: string, col: number, row: number) {
|
||||
selectCell(tableId, col, row);
|
||||
ui.depGraph = { tableId, col, row };
|
||||
}
|
||||
function closeDependencyGraph() {
|
||||
ui.depGraph = null;
|
||||
}
|
||||
|
||||
// ---- cell writes --------------------------------------
|
||||
function setCellInput(tableId: string, col: number, row: number, raw: string) {
|
||||
const table = tableById(tableId);
|
||||
@@ -2157,6 +2230,10 @@ function createStore() {
|
||||
cellIsNumeric,
|
||||
cellIsError,
|
||||
cellIsFormula,
|
||||
cellGraphSelf,
|
||||
cellGraphNeighbors,
|
||||
openDependencyGraph,
|
||||
closeDependencyGraph,
|
||||
setCellInput,
|
||||
clearRange,
|
||||
addRows,
|
||||
|
||||
Reference in New Issue
Block a user