diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue index 7cc820fa0a..5ec0715a32 100644 --- a/apps/desktop/src/components/grid/DataGrid.vue +++ b/apps/desktop/src/components/grid/DataGrid.vue @@ -78,13 +78,13 @@ import DataGridQueryControls from "@/components/grid/DataGridQueryControls.vue"; import DataGridFilterBuilder from "@/components/grid/DataGridFilterBuilder.vue"; import DataGridFilterWorkbench from "@/components/grid/DataGridFilterWorkbench.vue"; import DataGridTextFilterWorkbench from "@/components/grid/DataGridTextFilterWorkbench.vue"; +import DataGridTableInfoPanels from "@/components/grid/DataGridTableInfoPanels.vue"; import TemporalCellEditor from "@/components/grid/TemporalCellEditor.vue"; import EnumCellEditor from "@/components/grid/EnumCellEditor.vue"; import DataGridReadonlyTextSelection from "@/components/grid/DataGridReadonlyTextSelection.vue"; import GridSnapshotDialog from "@/components/grid/GridSnapshotDialog.vue"; import type { QueryResult, ColumnInfo, ConstraintInfo, DatabaseType, ForeignKeyInfo, IndexInfo, TriggerInfo, TableInfoTab, QueryResultSourceColumnRef, QueryPageJumpProgress } from "@/types/database"; import { isQueryExecutionErrorResult } from "@/lib/query/queryResultError"; -import { tableColumnDefaultDisplayValue } from "@/lib/table/tableColumnDefaultPresentation"; import { shouldNavigateFromTableInfoColumnClick } from "@/lib/table/tableInfoColumnNavigation"; import { tableInfoTabForDrawerToggle } from "@/lib/table/tableInfoTabPreference"; import * as api from "@/lib/backend/api"; @@ -13697,181 +13697,31 @@ function openGridSnapshot() { -
| # | -- {{ t("grid.columnName") }} - | -- {{ t("grid.columnType") }} - | -- {{ t("grid.tableInfoNullable") }} - | -- {{ t("structureEditor.defaultValue") }} - | -
|---|---|---|---|---|
| - {{ index + 1 }} - | -
-
-
- {{ column.comment }}
-
- |
- - {{ gaussdbMColumnType(column.data_type) }} - | -- {{ column.is_nullable ? "YES" : "NO" }} - | -- {{ tableColumnDefaultDisplayValue(column.column_default) }} - | -
+import { KeyRound, Loader2, Trash2 } from "@lucide/vue";
+import { useI18n } from "vue-i18n";
+import { Button } from "@/components/ui/button";
+import { tableColumnDefaultDisplayValue } from "@/lib/table/tableColumnDefaultPresentation";
+import type { ColumnInfo, ConstraintInfo, ForeignKeyInfo, IndexInfo, TableInfoTab, TriggerInfo } from "@/types/database";
+
+interface DataGridTableInfoPanelsProps {
+ activeTab: TableInfoTab;
+ searchQuery: string;
+ columns: ColumnInfo[];
+ columnsLoading: boolean;
+ indexes: IndexInfo[];
+ indexesLoading: boolean;
+ indexesError: string;
+ canManageMongoIndexes: boolean;
+ foreignKeys: ForeignKeyInfo[];
+ foreignKeysLoading: boolean;
+ foreignKeysError: string;
+ triggers: TriggerInfo[];
+ triggersLoading: boolean;
+ triggersError: string;
+ constraints: ConstraintInfo[];
+ constraintsLoading: boolean;
+ constraintsError: string;
+ isProtectedMongoIndex: (index: IndexInfo) => boolean;
+ formatColumnType: (dataType: string) => string;
+}
+
+const props = defineProps();
+
+const emit = defineEmits<{
+ tableInfoColumnClick: [columnName: string];
+ scrollToTableInfoColumn: [columnName: string];
+ requestDropMongoIndex: [index: IndexInfo];
+}>();
+
+const { t } = useI18n();
+
+
+
+
+
+
+
+
+ {{ t("grid.tableInfoNoResults") }}
+
+
+
+
+ #
+
+ {{ t("grid.columnName") }}
+
+
+ {{ t("grid.columnType") }}
+
+
+ {{ t("grid.tableInfoNullable") }}
+
+
+ {{ t("structureEditor.defaultValue") }}
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ {{ column.name }}
+
+
+ {{ column.comment }}
+
+
+
+ {{ props.formatColumnType(column.data_type) }}
+
+
+ {{ column.is_nullable ? "YES" : "NO" }}
+
+
+ {{ tableColumnDefaultDisplayValue(column.column_default) }}
+
+
+
+
+
+
+
+
+
+
+
+ {{ props.indexesError }}
+
+
+ {{ t("grid.tableInfoNoResults") }}
+
+
+ {{ t("grid.tableInfoEmpty") }}
+
+
+
+
+
+ {{ index.name }}
+
+ PK
+ UNIQUE
+ {{ index.index_type }}
+
+
+ {{ index.columns.join(", ") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ props.foreignKeysError }}
+
+
+ {{ t("grid.tableInfoNoResults") }}
+
+
+ {{ t("grid.tableInfoEmpty") }}
+
+
+
+ {{ foreignKey.name }}
+ {{ foreignKey.column }} -> {{ foreignKey.ref_table }}.{{ foreignKey.ref_column }}
+
+
+
+
+
+
+
+
+
+ {{ props.triggersError }}
+
+
+ {{ t("grid.tableInfoNoResults") }}
+
+
+ {{ t("grid.tableInfoEmpty") }}
+
+
+
+ {{ trigger.name }}
+ {{ trigger.timing }} {{ trigger.event }}
+
+
+
+
+
+
+
+
+
+ {{ props.constraintsError }}
+
+
+ {{ t("grid.tableInfoNoResults") }}
+
+
+ {{ t("grid.tableInfoEmpty") }}
+
+
+
+
+ {{ constraint.name }}
+ {{ constraint.constraint_type }}
+ {{ t("grid.tableInfoConstraintDisabled") }}
+ {{ t("grid.tableInfoConstraintNotValidated") }}
+
+ {{ constraint.columns.join(", ") }}
+ -> {{ constraint.ref_schema ? `${constraint.ref_schema}.` : "" }}{{ constraint.ref_table }}{{ constraint.ref_columns.length ? `(${constraint.ref_columns.join(", ")})` : "" }}
+ {{ constraint.definition }}
+
+
+
+
diff --git a/apps/desktop/src/components/grid/__tests__/DataGridDdlSearch.spec.ts b/apps/desktop/src/components/grid/__tests__/DataGridDdlSearch.spec.ts
index babf397c16..de3faad81e 100644
--- a/apps/desktop/src/components/grid/__tests__/DataGridDdlSearch.spec.ts
+++ b/apps/desktop/src/components/grid/__tests__/DataGridDdlSearch.spec.ts
@@ -2,6 +2,7 @@ import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const dataGridSource = readFileSync(new URL("../DataGrid.vue", import.meta.url), "utf8");
+const metadataLoaderSource = readFileSync(new URL("../../../composables/useDataGridTableMetadataLoaders.ts", import.meta.url), "utf8");
describe("DataGrid DDL search navigation", () => {
it("resets navigation when the raw search query changes", () => {
@@ -9,12 +10,13 @@ describe("DataGrid DDL search navigation", () => {
});
it("uses the shared DDL cache policy and exposes refresh controls", () => {
- expect(dataGridSource).toContain('from "@/lib/metadata/objectDdlCache"');
- expect(dataGridSource).toContain("async function fetchDdl(force = settingsStore.editorSettings.refreshDdlOnOpen)");
- expect(dataGridSource).toMatch(/loadObjectDdl\([\s\S]*?objectType: tableObjectSourceKind\(props\.tableMeta\.tableType\),[\s\S]*?\{ force \},/);
+ expect(metadataLoaderSource).toContain('from "@/lib/metadata/objectDdlCache"');
+ expect(metadataLoaderSource).toContain("async function fetchDdl(force = options.settingsStore.editorSettings.refreshDdlOnOpen)");
+ expect(metadataLoaderSource).toMatch(/objectType: tableObjectSourceKind\(props\.tableMeta\.tableType\)/);
+ expect(metadataLoaderSource).toContain("loadObjectDdl(request, { force })");
expect(dataGridSource).toMatch(/async function refreshActiveTableInfo\(\)[\s\S]*?fetchDdl\(true\)[\s\S]*?fetchTableInfoColumns\(true\)[\s\S]*?fetchIndexes\(\)[\s\S]*?fetchForeignKeys\(\)[\s\S]*?fetchConstraints\(\)[\s\S]*?fetchTriggers\(\)/);
expect(dataGridSource).toContain('@click="refreshActiveTableInfo"');
- expect(dataGridSource).toMatch(/loadObjectMetadataFacet\(request, "columns"/);
+ expect(metadataLoaderSource).toMatch(/loadObjectMetadataFacet\(request, "columns"/);
expect(dataGridSource).toMatch(/activeTableInfoTab\.value === "constraints"\) return constraintsLoading\.value/);
expect(dataGridSource).not.toContain("setTableInfoRefreshDdlOnOpen");
});