mirror of
https://github.com/baptisteArno/typebot.io.git
synced 2026-06-05 21:04:43 +08:00
🐛 Fix missing result columns in CSV export (#2513)
- Append missing result headers to saved column orders so newly added response blocks stay visible. - Reuse the normalized column order for selected-results CSV export instead of a local missing-header fallback. - Add regression coverage for default, saved, and legacy column orders.
This commit is contained in:
parent
b4a7aab16d
commit
08cb6ea10f
@ -76,32 +76,18 @@ export const SelectionToolbar = ({
|
||||
const headerIds = parseColumnsOrder(
|
||||
typebot?.resultsTablePreferences?.columnsOrder,
|
||||
resultHeader,
|
||||
)
|
||||
.reduce<string[]>((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<string[]>((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 } = {};
|
||||
|
||||
46
packages/results/src/parseColumnsOrder.test.ts
Normal file
46
packages/results/src/parseColumnsOrder.test.ts
Normal file
@ -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"]);
|
||||
});
|
||||
});
|
||||
@ -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"];
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user