diff --git a/frontend/src/viewers/SchemaLinkingViewer.test.tsx b/frontend/src/viewers/SchemaLinkingViewer.test.tsx
index 681e9034..7651d2a9 100644
--- a/frontend/src/viewers/SchemaLinkingViewer.test.tsx
+++ b/frontend/src/viewers/SchemaLinkingViewer.test.tsx
@@ -55,3 +55,30 @@ test("(c) oversized linking (>45) shows cap notice", () => {
screen.getByText(/troppi elementi per il grafico/i)
).toBeInTheDocument();
});
+
+test("(d) ~10 promoted + ~50 excluded does NOT cap; graph is available", async () => {
+ const mixedLinking = {
+ question: "caso misto",
+ candidates: [
+ ...Array.from({ length: 10 }, (_, i) => ({
+ kind: "table" as const,
+ name: `kept_${i}`,
+ decision: "promoted" as const,
+ })),
+ ...Array.from({ length: 50 }, (_, i) => ({
+ kind: "table" as const,
+ name: `dropped_${i}`,
+ decision: "excluded" as const,
+ })),
+ ],
+ joins: [],
+ excluded: [],
+ open_questions: [],
+ };
+ render();
+ expect(
+ screen.queryByText(/troppi elementi per il grafico/i)
+ ).not.toBeInTheDocument();
+ // Grafico (mermaid) view is the default and renders the mocked svg.
+ await waitFor(() => expect(screen.getByTestId("mm")).toBeInTheDocument());
+});
diff --git a/frontend/src/viewers/SchemaLinkingViewer.tsx b/frontend/src/viewers/SchemaLinkingViewer.tsx
index d1c02bb2..c0b9ea24 100644
--- a/frontend/src/viewers/SchemaLinkingViewer.tsx
+++ b/frontend/src/viewers/SchemaLinkingViewer.tsx
@@ -25,19 +25,23 @@ export interface SchemaLinking {
open_questions: string[];
}
-function buildFlowchart(candidates: Candidate[], joins: Join[]): string {
- const promoted = candidates.filter((c) => c.decision === "promoted");
+/** The inline "perché" comment for a candidate: evidence first, then signal keys. */
+function reasonFor(c: Candidate): string {
+ if (c.evidence?.length) return c.evidence[0];
+ if (c.signals && Object.keys(c.signals).length)
+ return Object.keys(c.signals).join(", ");
+ return "";
+}
+
+function buildFlowchart(promoted: Candidate[], joins: Join[]): string {
const nodeId = (name: string) => name.replace(/[^a-zA-Z0-9]/g, "_");
const lines: string[] = ["flowchart TB"];
for (const c of promoted) {
const id = nodeId(c.name);
- const tooltip = c.evidence?.length
- ? ` %% ${c.evidence[0]}`
- : c.signals && Object.keys(c.signals).length
- ? ` %% ${Object.keys(c.signals).join(", ")}`
- : "";
+ const reason = reasonFor(c);
+ const tooltip = reason ? ` %% ${reason}` : "";
const shape = c.kind === "table" ? `[${c.name}]` : `(${c.name})`;
lines.push(` ${id}${shape}${tooltip}`);
}
@@ -52,8 +56,7 @@ function buildFlowchart(candidates: Candidate[], joins: Join[]): string {
return lines.join("\n");
}
-function buildHierarchicalRows(candidates: Candidate[]) {
- const promoted = candidates.filter((c) => c.decision === "promoted");
+function buildHierarchicalRows(promoted: Candidate[]) {
const tables = promoted.filter((c) => c.kind === "table");
const columns = promoted.filter((c) => c.kind === "column");
@@ -75,7 +78,9 @@ function buildHierarchicalRows(candidates: Candidate[]) {
}
export function SchemaLinkingViewer({ linking }: { linking: SchemaLinking }) {
- const oversized = linking.candidates.length > CAP;
+ const promoted = linking.candidates.filter((c) => c.decision === "promoted");
+ // The graph only contains promoted candidates, so cap on that count.
+ const oversized = promoted.length > CAP;
const [view, setView] = useState<"chart" | "table">(
oversized ? "table" : "chart"
);
@@ -84,16 +89,17 @@ export function SchemaLinkingViewer({ linking }: { linking: SchemaLinking }) {
useEffect(() => {
if (view !== "chart" || oversized) return;
let cancelled = false;
- const def = buildFlowchart(linking.candidates, linking.joins);
+ const def = buildFlowchart(promoted, linking.joins);
renderMermaid(def).then((s) => {
if (!cancelled) setSvg(s);
});
return () => {
cancelled = true;
};
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [view, linking, oversized]);
- const { grouped, orphans } = buildHierarchicalRows(linking.candidates);
+ const { grouped, orphans } = buildHierarchicalRows(promoted);
return (
@@ -143,7 +149,7 @@ export function SchemaLinkingViewer({ linking }: { linking: SchemaLinking }) {
{table.name} |
tabella |
- {table.evidence?.[0] ?? ""}
+ {reasonFor(table)}
|
{cols.map((col) => (
@@ -153,7 +159,7 @@ export function SchemaLinkingViewer({ linking }: { linking: SchemaLinking }) {
colonna |
- {col.evidence?.[0] ?? ""}
+ {reasonFor(col)}
|
))}
@@ -166,7 +172,7 @@ export function SchemaLinkingViewer({ linking }: { linking: SchemaLinking }) {
colonna |
- {col.evidence?.[0] ?? ""}
+ {reasonFor(col)}
|
))}