feat(elasticsearch): add custom checks and tabular REST results
This commit is contained in:
1 parent
e2b35944ce
commit
a49137ae8b
44 files changed
+917
-74
No files matched your search
@@ -122,7 +122,7 @@ function createExportState(
|
||||
context: computed(() => "table-data"),
|
||||
sourceColumns: computed(() => columns),
|
||||
visibleColumnIndexes: computed(() => visibleColumnIndexes ?? columns.map((_, index) => index)),
|
||||
columnTypes: computed(() => columns.map(() => "varchar")),
|
||||
columnTypes: computed(() => columns.map((column) => tableMeta.columns?.find((item) => item.name === column)?.data_type ?? "varchar")),
|
||||
extractorOptions: computed(() => extractorOptions),
|
||||
whereInput: computed(() => undefined),
|
||||
orderBy: computed(() => undefined),
|
||||
@@ -547,6 +547,37 @@ describe("useDataGridExport prepared row statements", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps JSON cells structured in JSON and SQL extractor requests", async () => {
|
||||
const tableMeta: DataGridTableMeta = {
|
||||
tableName: "events",
|
||||
primaryKeys: ["id"],
|
||||
columns: [
|
||||
{ name: "id", data_type: "int", is_nullable: false, is_primary_key: true },
|
||||
{ name: "payload", data_type: "json", is_nullable: true },
|
||||
],
|
||||
};
|
||||
const matrix: CellSelectionMatrix = {
|
||||
rowIndexes: [0],
|
||||
columnIndexes: [0, 1],
|
||||
columns: ["id", "payload"],
|
||||
rows: [[7, '{"name":"Ada","tags":["admin"]}']],
|
||||
};
|
||||
vi.mocked(extractDataGridSelection).mockResolvedValue({
|
||||
text: "copied",
|
||||
mimeType: "application/json",
|
||||
fileExtension: "json",
|
||||
rowCount: 1,
|
||||
columnCount: 2,
|
||||
});
|
||||
const state = createExportState(tableMeta, ["id", "payload"], matrix, [7, '{"name":"Ada","tags":["admin"]}']);
|
||||
|
||||
await expect(state.copyWithExtractor("json")).resolves.toBe(true);
|
||||
await expect(state.copyWithExtractor("sql-inserts")).resolves.toBe(true);
|
||||
|
||||
expect(extractDataGridSelection).toHaveBeenNthCalledWith(1, expect.objectContaining({ rows: [[7, { name: "Ada", tags: ["admin"] }]] }));
|
||||
expect(extractDataGridSelection).toHaveBeenNthCalledWith(2, expect.objectContaining({ rows: [[7, { name: "Ada", tags: ["admin"] }]] }));
|
||||
});
|
||||
|
||||
it("rejects SQL UPDATE instead of silently skipping a row with a null primary key", async () => {
|
||||
const matrix: CellSelectionMatrix = {
|
||||
rowIndexes: [0],
|
||||
|
||||
@@ -348,7 +348,14 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
|
||||
}
|
||||
const obj: Record<string, unknown> = {};
|
||||
columns.value.forEach((col, i) => {
|
||||
obj[col] = item.data[i];
|
||||
const value = item.data[i];
|
||||
if (typeof value === "string" && columnTypes.value?.[i]?.trim().toLowerCase() === "json") {
|
||||
try {
|
||||
obj[col] = JSON.parse(value);
|
||||
return;
|
||||
} catch {}
|
||||
}
|
||||
obj[col] = value;
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
@@ -443,6 +450,7 @@ export function useDataGridExport(options: UseDataGridExportOptions) {
|
||||
allDisplayItems,
|
||||
allSourceColumns,
|
||||
visibleColumnIndexes,
|
||||
columnTypes,
|
||||
extractorOptions: extractorOptionsOption,
|
||||
databaseType,
|
||||
tableMeta,
|
||||
|
||||
@@ -32,6 +32,7 @@ interface UseDataGridExtractorOptions {
|
||||
allDisplayItems: ComputedRef<ExtractorRowItem[]>;
|
||||
allSourceColumns: ComputedRef<Array<string | undefined> | undefined>;
|
||||
visibleColumnIndexes: ComputedRef<number[]>;
|
||||
columnTypes: ComputedRef<Array<string | undefined> | undefined>;
|
||||
extractorOptions?: ComputedRef<DataGridExtractorOptions>;
|
||||
databaseType: ComputedRef<DatabaseType | undefined>;
|
||||
tableMeta: ComputedRef<DataGridTableMeta | undefined>;
|
||||
@@ -54,6 +55,15 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
|
||||
const { toast } = useToast();
|
||||
const hasUnsupportedDiscreteSelection = computed(() => options.hasCellSelection.value && options.selectedCellMatrix.value === null);
|
||||
|
||||
function normalizeCellValue(value: unknown, columnType: string | undefined): unknown {
|
||||
if (typeof value !== "string" || columnType?.trim().toLowerCase() !== "json") return value;
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function selectionData(): SelectionData | null {
|
||||
if (options.hasRowSelection.value && options.selectedRowIds.value.size > 0) {
|
||||
const rows = options.displayItems.value.filter((item) => options.selectedRowIds.value.has(item.id) && !item.isDraft).map((item) => item.data);
|
||||
@@ -116,13 +126,14 @@ export function useDataGridExtractor(options: UseDataGridExtractorOptions) {
|
||||
}
|
||||
}
|
||||
const compactIndexBySource = new Map(requiredSourceIndexes.map((sourceIndex, compactIndex) => [sourceIndex, compactIndex]));
|
||||
const columnTypesBySource = new Map(visibleIndexes.map((sourceIndex, visibleIndex) => [sourceIndex, options.columnTypes.value?.[visibleIndex]]));
|
||||
const columns = requiredSourceIndexes.map((sourceIndex, compactIndex) => ({
|
||||
displayName: fullColumns[sourceIndex],
|
||||
sourceName: sourceNames?.[sourceIndex],
|
||||
sourceIndex: compactIndex,
|
||||
}));
|
||||
const selectedColumnIndexes = selectedSourceIndexes.map((sourceIndex) => compactIndexBySource.get(sourceIndex)).filter((index): index is number => index !== undefined);
|
||||
const rows = sourceRows.map((row) => requiredSourceIndexes.map((sourceIndex) => row[sourceIndex]));
|
||||
const rows = sourceRows.map((row) => requiredSourceIndexes.map((sourceIndex) => normalizeCellValue(row[sourceIndex], columnTypesBySource.get(sourceIndex))));
|
||||
const descriptor = DATA_GRID_COPY_EXTRACTOR_DESCRIPTORS[extractor];
|
||||
const tableMeta =
|
||||
descriptor.category === "sql"
|
||||
|
||||
Reference in new issue
Block a user