diff --git a/apps/builder/src/features/results/components/table/SelectionToolbar.tsx b/apps/builder/src/features/results/components/table/SelectionToolbar.tsx index 49d985bfb..67b9b4589 100644 --- a/apps/builder/src/features/results/components/table/SelectionToolbar.tsx +++ b/apps/builder/src/features/results/components/table/SelectionToolbar.tsx @@ -76,32 +76,18 @@ export const SelectionToolbar = ({ const headerIds = parseColumnsOrder( typebot?.resultsTablePreferences?.columnsOrder, resultHeader, - ) - .reduce((currentHeaderIds, columnId) => { - if ( - typebot?.resultsTablePreferences?.columnsVisibility[columnId] === - false - ) - return currentHeaderIds; - const columnLabel = resultHeader.find( - (headerCell) => headerCell.id === columnId, - )?.id; - if (!columnLabel) return currentHeaderIds; - currentHeaderIds.push(columnLabel); + ).reduce((currentHeaderIds, columnId) => { + if ( + typebot?.resultsTablePreferences?.columnsVisibility[columnId] === false + ) return currentHeaderIds; - }, []) - .concat( - typebot?.resultsTablePreferences?.columnsOrder - ? resultHeader - .filter( - (headerCell) => - !typebot?.resultsTablePreferences?.columnsOrder.includes( - headerCell.id, - ), - ) - .map((headerCell) => headerCell.id) - : [], - ); + const columnLabel = resultHeader.find( + (headerCell) => headerCell.id === columnId, + )?.id; + if (!columnLabel) return currentHeaderIds; + currentHeaderIds.push(columnLabel); + return currentHeaderIds; + }, []); const data = dataToUnparse.map<{ [key: string]: string }>((data) => { const newObject: { [key: string]: string } = {}; diff --git a/packages/results/src/parseColumnsOrder.test.ts b/packages/results/src/parseColumnsOrder.test.ts new file mode 100644 index 000000000..01476037a --- /dev/null +++ b/packages/results/src/parseColumnsOrder.test.ts @@ -0,0 +1,46 @@ +import { describe, expect, it } from "bun:test"; +import { parseColumnsOrder } from "./parseColumnsOrder"; +import type { ResultHeaderCell } from "./schemas/results"; + +const resultHeader = [ + { + id: "createdAt", + label: "Created at", + }, + { + id: "email", + label: "Email", + }, + { + id: "name", + label: "Name", + }, +] satisfies ResultHeaderCell[]; + +describe("parseColumnsOrder", () => { + it("returns the default order when no order is saved", () => { + expect(parseColumnsOrder(undefined, resultHeader)).toEqual([ + "select", + "createdAt", + "email", + "name", + "logs", + ]); + }); + + it("keeps the saved order and appends missing result headers", () => { + expect(parseColumnsOrder(["email", "createdAt"], resultHeader)).toEqual([ + "select", + "email", + "createdAt", + "name", + "logs", + ]); + }); + + it("resets orders saved with the old control column format", () => { + expect( + parseColumnsOrder(["select", "email", "logs"], resultHeader), + ).toEqual(["select", "createdAt", "email", "name", "logs"]); + }); +}); diff --git a/packages/results/src/parseColumnsOrder.ts b/packages/results/src/parseColumnsOrder.ts index 183762bf1..f939f245c 100644 --- a/packages/results/src/parseColumnsOrder.ts +++ b/packages/results/src/parseColumnsOrder.ts @@ -4,8 +4,16 @@ export const parseColumnsOrder = ( existingOrder: string[] | undefined, resultHeader: ResultHeaderCell[], ) => { - return existingOrder?.at(0) === "select" - ? // Old format potentially broken, reset to default - ["select", ...resultHeader.map((h) => h.id), "logs"] - : ["select", ...(existingOrder ?? resultHeader.map((h) => h.id)), "logs"]; + const resultHeaderIds = resultHeader.map((header) => header.id); + + if (existingOrder?.at(0) === "select") + // Old format potentially broken, reset to default + return ["select", ...resultHeaderIds, "logs"]; + + const orderedHeaderIds = existingOrder ?? resultHeaderIds; + const missingHeaderIds = resultHeaderIds.filter( + (headerId) => !orderedHeaderIds.includes(headerId), + ); + + return ["select", ...orderedHeaderIds, ...missingHeaderIds, "logs"]; };