fix(grid): show structured copy errors

Closes #5401
This commit is contained in:
t8y2
2026-08-12 01:04:13 +00:00
parent 8788bed921
commit 02a56e4f64
2 changed files with 18 additions and 5 deletions
@@ -644,6 +644,22 @@ describe("useDataGridExport prepared row statements", () => {
expect(toast).not.toHaveBeenCalledWith("grid.copyExtractorWarningOmittedColumns", 5000);
});
it.each([
["output limit", { code: "output-too-large", message: "Extracted clipboard output exceeds 32 MiB; export the data to a file instead." }, "Extracted clipboard output exceeds 32 MiB; export the data to a file instead."],
["input limit", { code: "input-too-large", message: "Selected data is too large for clipboard extraction; export the data to a file instead." }, "Selected data is too large for clipboard extraction; export the data to a file instead."],
["Error", new Error("extractor failed"), "extractor failed"],
["string", "extractor failed", "extractor failed"],
["null", null, "Unknown error occurred"],
])("formats %s extractor failures", async (_label, rejection, expectedMessage) => {
const matrix: CellSelectionMatrix = { rowIndexes: [0], columnIndexes: [0], columns: ["id"], rows: [[1]] };
vi.mocked(extractDataGridSelection).mockRejectedValueOnce(rejection);
const state = createExportState(editableTable, ["id"], matrix, [1]);
await expect(state.copyWithExtractor("csv")).resolves.toBe(false);
expect(toast).toHaveBeenCalledWith(`grid.copyFailed: ${expectedMessage}`, 5000);
});
it("rejects irregular discrete cell selections before building an extractor request", async () => {
const state = createExportState(editableTable, ["id", "name"], undefined, undefined, {
columns: ["id", "name"],
@@ -19,6 +19,7 @@ import {
type DataGridExtractWarningCode,
} from "@/lib/dataGrid/dataGridCopyExtractor";
import type { DataGridTableMeta } from "@/lib/dataGrid/dataGridSql";
import { formatError } from "@/lib/backend/errorUtils";
import type { DatabaseType } from "@/types/database";
interface ExtractorRowItem {
@@ -245,7 +246,7 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
showWarnings(result.warnings, result.omittedColumns);
return true;
} catch (error: unknown) {
toast(t("grid.copyFailed", { message: errorMessage(error) }), 5000);
toast(t("grid.copyFailed", { message: formatError(error) }), 5000);
return false;
}
}
@@ -295,10 +296,6 @@ function compactTableMeta(tableMeta: DataGridTableMeta | undefined, requiredColu
return { ...tableMeta, columns: tableMeta.columns.filter((column) => requiredNames.has(normalizeName(column.name))) };
}
function errorMessage(error: unknown): string {
return error instanceof Error ? error.message : String(error);
}
function normalizeName(name: string): string {
const trimmed = name.trim();
const first = trimmed[0];