diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 3fbf1b3b88..1d343bd61d 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -2541,6 +2541,7 @@ const { } = useDataGridColumnLayoutState({ columns: computed(() => props.result.columns), sourceColumns: computed(() => props.sourceColumns), + columnComments: () => props.resultColumnComments, commentByColumn: columnCommentMap, displayableColumnIndexes, allNullColumnIndexes: allNullColumnIndexesForResult, @@ -2557,6 +2558,7 @@ const goToColumnItems = computed(() => buildDataGridColumnLookupItems({ columns: props.result.columns, sourceColumns: props.sourceColumns, + columnComments: props.resultColumnComments, displayableIndexes: displayableColumnIndexes.value, commentByColumn: columnCommentMap.value, }), diff --git a/apps/desktop/src/components/grid/__tests__/DataGridColumnComments.spec.ts b/apps/desktop/src/components/grid/__tests__/DataGridColumnComments.spec.ts index 1bf5302d0b..00b86e1895 100644 --- a/apps/desktop/src/components/grid/__tests__/DataGridColumnComments.spec.ts +++ b/apps/desktop/src/components/grid/__tests__/DataGridColumnComments.spec.ts @@ -12,4 +12,9 @@ describe("DataGrid column comments", () => { expect(dataGridSource).toContain(':tooltip-column-comment="resolvedColumnComment(col.name, col.actualColIdx)"'); expect(dataGridSource).toContain("(column, index) => headerColumnComment(column, index)"); }); + + it("routes per-ordinal comments to field filtering and go-to-column lookup", () => { + expect(dataGridSource).toMatch(/useDataGridColumnLayoutState\(\{[\s\S]*?columnComments: \(\) => props\.resultColumnComments,[\s\S]*?\}\);/); + expect(dataGridSource).toMatch(/const goToColumnItems = computed\(\(\) =>[\s\S]*?buildDataGridColumnLookupItems\(\{[\s\S]*?columnComments: props\.resultColumnComments,[\s\S]*?\}\),[\s\S]*?\);/); + }); }); diff --git a/apps/desktop/src/composables/__tests__/useDataGridColumnLayout.spec.ts b/apps/desktop/src/composables/__tests__/useDataGridColumnLayout.spec.ts index cc43519e7e..1364da353c 100644 --- a/apps/desktop/src/composables/__tests__/useDataGridColumnLayout.spec.ts +++ b/apps/desktop/src/composables/__tests__/useDataGridColumnLayout.spec.ts @@ -255,6 +255,28 @@ describe("useDataGridColumnLayout", () => { scope.stop(); }); + it("uses grouped result comments in field filtering without name-map fallback", () => { + const scope = effectScope(); + const state = scope.run(() => + useDataGridColumnLayoutState({ + columns: ref(["asin_url", "total"]), + sourceColumns: ref(undefined), + columnComments: ref(["asin亚马逊前台地址", undefined]), + commentByColumn: ref(new Map([["total", "Wrong aggregate comment"]])), + displayableColumnIndexes: ref([0, 1]), + allNullColumnIndexes: ref([]), + columnOrderKeys: ref(["asin_url\0\0", "total\0\0"]), + layoutScopeKey: ref("grouped-result-comments"), + tableScopeKey: ref(""), + }), + )!; + + expect(state.orderedColumnLayoutOptions.value.map((option) => option.comment)).toEqual(["asin亚马逊前台地址", undefined]); + expect(state.filteredColumnLayoutOptions("亚马逊").map((option) => option.column)).toEqual(["asin_url"]); + expect(state.filteredColumnLayoutOptions("wrong")).toEqual([]); + scope.stop(); + }); + it("keeps a new resize active when the previous resize completion frame is pending", () => { const frames = new Map(); let nextFrame = 1; diff --git a/apps/desktop/src/composables/useDataGridColumnLayout.ts b/apps/desktop/src/composables/useDataGridColumnLayout.ts index 363a350fc0..0c5dd3a9f7 100644 --- a/apps/desktop/src/composables/useDataGridColumnLayout.ts +++ b/apps/desktop/src/composables/useDataGridColumnLayout.ts @@ -83,6 +83,7 @@ export function dataGridHorizontalColumnWindow(options: { widths: readonly numbe export function useDataGridColumnLayoutState(options: { columns: MaybeRefOrGetter; sourceColumns?: MaybeRefOrGetter; + columnComments?: MaybeRefOrGetter; commentByColumn?: MaybeRefOrGetter>; displayableColumnIndexes: MaybeRefOrGetter; allNullColumnIndexes: MaybeRefOrGetter; @@ -116,6 +117,7 @@ export function useDataGridColumnLayoutState(options: { buildDataGridColumnLookupItems({ columns: toValue(options.columns), sourceColumns: toValue(options.sourceColumns), + columnComments: toValue(options.columnComments), displayableIndexes: toValue(options.displayableColumnIndexes), commentByColumn: toValue(options.commentByColumn), }), diff --git a/apps/desktop/src/lib/__tests__/dataGridColumnLookup.spec.ts b/apps/desktop/src/lib/__tests__/dataGridColumnLookup.spec.ts index 3df3ca1145..62b5dea0e3 100644 --- a/apps/desktop/src/lib/__tests__/dataGridColumnLookup.spec.ts +++ b/apps/desktop/src/lib/__tests__/dataGridColumnLookup.spec.ts @@ -37,4 +37,41 @@ describe("data grid column lookup search", () => { it("returns all columns for an empty query", () => { expect(filterDataGridColumnLookupItems(items, " ")).toEqual(items); }); + + it("keeps grouped comments aligned by result ordinal and searches them", () => { + const groupedItems = buildDataGridColumnLookupItems({ + columns: ["label", "label", "total"], + columnComments: ["Primary label", "Joined label", undefined], + commentByColumn: new Map([ + ["label", "Wrong name-based label"], + ["total", "Wrong aggregate label"], + ]), + }); + + expect(groupedItems.map((item) => item.comment)).toEqual(["Primary label", "Joined label", undefined]); + expect(filterDataGridColumnLookupItems(groupedItems, "joined").map((item) => item.index)).toEqual([1]); + expect(filterDataGridColumnLookupItems(groupedItems, "wrong")).toEqual([]); + }); + + it("falls back to source metadata only when ordinal comments are absent", () => { + const comments = new Map([ + ["department", "Department name"], + ["total", "Unsafe aggregate fallback"], + ]); + + expect( + buildDataGridColumnLookupItems({ + columns: ["dept"], + sourceColumns: ["department"], + commentByColumn: comments, + }), + ).toMatchObject([{ comment: "Department name" }]); + expect( + buildDataGridColumnLookupItems({ + columns: ["total"], + columnComments: [undefined], + commentByColumn: comments, + }), + ).toEqual([{ index: 0, name: "total" }]); + }); }); diff --git a/apps/desktop/src/lib/dataGrid/dataGridColumnLookup.ts b/apps/desktop/src/lib/dataGrid/dataGridColumnLookup.ts index 44e95b3591..8c03874a4b 100644 --- a/apps/desktop/src/lib/dataGrid/dataGridColumnLookup.ts +++ b/apps/desktop/src/lib/dataGrid/dataGridColumnLookup.ts @@ -10,6 +10,7 @@ export interface DataGridColumnLookupItem { export interface DataGridColumnLookupOptions { columns: readonly string[]; sourceColumns?: readonly (string | undefined)[]; + columnComments?: readonly (string | undefined)[]; displayableIndexes?: readonly number[]; commentByColumn?: ReadonlyMap; } @@ -38,7 +39,9 @@ export function buildDataGridColumnLookupItems(options: DataGridColumnLookupOpti return indexes.map((index) => { const name = options.columns[index] ?? `#${index + 1}`; const sourceName = options.sourceColumns?.[index]; - const comment = dataGridColumnCommentFor(options.commentByColumn, name, sourceName); + // A present ordinal array owns unresolved entries too; falling back by + // name there could leak another source's comment onto an aggregate/alias. + const comment = options.columnComments === undefined ? dataGridColumnCommentFor(options.commentByColumn, name, sourceName) : nonEmptyComment(options.columnComments[index]); return { index, name,