feat(grid): improve data copy format controls

This commit is contained in:
t8y2 committed 2026-07-30 23:08:15 +08:00
1 parent 0234470466
commit 38e1c66f26
18 files changed
+235 -35

No files matched your search

@@ -433,6 +433,37 @@ describe("useDataGridExport prepared row statements", () => {
expect(state.canCopyWithExtractor("sql-inserts")).toBe(true);
});
it("supports a one-off INSERT primary-key override without changing saved options", async () => {
const autoIncrementTable: DataGridTableMeta = {
tableName: "users",
primaryKeys: ["id"],
columns: [{ name: "id", data_type: "int", is_nullable: false, is_primary_key: true, extra: "auto_increment" }],
};
const matrix: CellSelectionMatrix = { rowIndexes: [0], columnIndexes: [0], columns: ["id"], rows: [[7]] };
const savedOptions = {
...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS,
sql: { ...DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS.sql, excludePrimaryKeysFromInsert: true },
};
const includePrimaryKeys = {
...savedOptions,
sql: { ...savedOptions.sql, excludePrimaryKeysFromInsert: false },
};
vi.mocked(extractDataGridSelection).mockResolvedValueOnce({
text: "INSERT INTO `users` (`id`) VALUES (7);",
mimeType: "text/sql",
fileExtension: "sql",
rowCount: 1,
columnCount: 1,
});
const state = createExportState(autoIncrementTable, ["id"], matrix, [7], undefined, undefined, [], savedOptions);
expect(state.canCopyWithExtractor("sql-inserts")).toBe(false);
expect(state.canCopyWithExtractor("sql-inserts", includePrimaryKeys)).toBe(true);
await expect(state.copyWithExtractor("sql-inserts", includePrimaryKeys)).resolves.toBe(true);
expect(extractDataGridSelection).toHaveBeenCalledWith(expect.objectContaining({ options: expect.objectContaining({ sql: expect.objectContaining({ excludePrimaryKeysFromInsert: false }) }) }));
expect(savedOptions.sql.excludePrimaryKeysFromInsert).toBe(true);
});
it("sends only selected values for non-SQL extraction and marks column selections", async () => {
const matrix: CellSelectionMatrix = { rowIndexes: [0], columnIndexes: [1], columns: ["name"], rows: [["Ada"]] };
vi.mocked(extractDataGridSelection).mockResolvedValueOnce({
@@ -173,12 +173,12 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
});
}
function canCopyWithExtractor(extractor: DataGridCopyExtractorId): boolean {
function canCopyWithExtractor(extractor: DataGridCopyExtractorId, extractorOptions: DataGridExtractorOptions = options.extractorOptions?.value ?? DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS): boolean {
if (hasUnsupportedDiscreteSelection.value) return false;
if (!options.hasRowSelection.value && !options.hasCellSelection.value && !options.contextCell.value) return false;
if (extractorUnavailableForDatabase(extractor, options.databaseType.value)) return false;
if (extractor === "sql-inserts") {
const request = buildRequest(extractor);
const request = buildRequest(extractor, extractorOptions);
return request !== null && options.canCopySqlInsert(request);
}
if (extractor === "sql-updates") {
@@ -198,13 +198,13 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
return { text, mimeType: "application/javascript", fileExtension: "js", rowCount: rowLimit ?? request.rows.length, columnCount: request.selectedColumnIndexes.length, warnings: undefined, omittedColumns: undefined };
}
async function copyWithExtractor(extractor: DataGridCopyExtractorId): Promise<boolean> {
async function copyWithExtractor(extractor: DataGridCopyExtractorId, extractorOptions: DataGridExtractorOptions = options.extractorOptions?.value ?? DEFAULT_DATA_GRID_EXTRACTOR_OPTIONS): Promise<boolean> {
if (hasUnsupportedDiscreteSelection.value) {
toast(t("grid.copyExtractorUnsupportedSelection"), 5000);
return false;
}
if (!canCopyWithExtractor(extractor)) return false;
const request = buildRequest(extractor);
if (!canCopyWithExtractor(extractor, extractorOptions)) return false;
const request = buildRequest(extractor, extractorOptions);
if (!request) return false;
try {
const mongoResult = await resolveMongoExtractorResult(extractor, request);