feat(structure): add view data entry to the DDL structure tab
This commit is contained in:
15 files changed
+41
-4
No files matched your search
@@ -11034,7 +11034,7 @@ function copyDdl() {
|
||||
|
||||
function openTableStructureEditor() {
|
||||
if (!props.connectionId || !props.database || !props.tableMeta?.tableName || !canOpenTableStructureEditor.value) return;
|
||||
queryStore.openTableStructure(props.connectionId, props.database, props.tableMeta.schema, props.tableMeta.tableName, activeTableInfoTab.value, undefined, props.tableMeta.catalog);
|
||||
queryStore.openTableStructure(props.connectionId, props.database, props.tableMeta.schema, props.tableMeta.tableName, activeTableInfoTab.value, undefined, props.tableMeta.catalog, (props.tableMeta.tableType || "").toUpperCase() === "VIEW" ? "view" : "table");
|
||||
}
|
||||
|
||||
function toggleDdlWrap() {
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ describe("DataGrid edit-table-structure shortcut", () => {
|
||||
expect(event.defaultPrevented).toBe(true);
|
||||
expect(bubbled).not.toHaveBeenCalled();
|
||||
expect(openTableStructure).toHaveBeenCalledOnce();
|
||||
expect(openTableStructure).toHaveBeenCalledWith("connection-1", "app", "public", "users", "ddl", undefined, "warehouse");
|
||||
expect(openTableStructure).toHaveBeenCalledWith("connection-1", "app", "public", "users", "ddl", undefined, "warehouse", "table");
|
||||
});
|
||||
|
||||
it("uses a configured shortcut and leaves the default key untouched", async () => {
|
||||
|
||||
@@ -964,6 +964,24 @@ function onHandleViewTableData(target: SqlObjectNavigationTarget) {
|
||||
emit("viewTableData", props.activeTab.id, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* The structure/DDL editor only owns the object identity, so build the
|
||||
* navigation target from the active tab and reuse the same "view data" path as
|
||||
* the SQL editor context menu (issue #6724).
|
||||
*/
|
||||
function onHandleStructureViewData() {
|
||||
const tab = props.activeTab;
|
||||
const meta = tab.tableMeta;
|
||||
const tableName = tab.structureTableName || meta?.tableName;
|
||||
if (!tableName) return;
|
||||
emit("viewTableData", tab.id, {
|
||||
name: tableName,
|
||||
database: meta?.database || tab.database,
|
||||
schema: meta?.schema || tab.schema,
|
||||
type: tab.structureTableType === "view" ? "view" : "table",
|
||||
});
|
||||
}
|
||||
|
||||
function onHandleViewTableDdl(target: SqlObjectNavigationTarget) {
|
||||
emit("viewTableDdl", props.activeTab.id, target);
|
||||
}
|
||||
@@ -2804,6 +2822,7 @@ defineExpose({
|
||||
@saved="(commentChanged) => emit('structureEditorSaved', activeTab.id, commentChanged)"
|
||||
@close="emit('structureEditorClose', activeTab.id)"
|
||||
@open-settings="(initialTab, initialSection) => emit('openSettings', initialTab, initialSection)"
|
||||
@view-data="onHandleStructureViewData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
+1
@@ -49,6 +49,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Pencil: Icon,
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
@@ -55,6 +55,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Maximize2: Icon,
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||||
import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ClipboardList, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue";
|
||||
import { AlertTriangle, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, ClipboardList, Copy, Database, Info, KeyRound, ListChevronsUpDown, Loader2, Maximize2, Pencil, Plus, RefreshCw, RotateCcw, Rows3, Save, Search, Settings, SlidersHorizontal, Trash2, UserRound, X } from "@lucide/vue";
|
||||
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||
@@ -173,6 +173,8 @@ const emit = defineEmits<{
|
||||
saved: [commentChanged: boolean];
|
||||
close: [];
|
||||
openSettings: [initialTab?: string, initialSection?: string];
|
||||
/** Jump from the DDL view to the table's data tab (issue #6724). */
|
||||
viewData: [];
|
||||
}>();
|
||||
|
||||
const activeTab = ref<TableInfoTab>("columns");
|
||||
@@ -4412,6 +4414,10 @@ watch(
|
||||
<TabsTrigger v-if="tableMetadataCapabilities.triggers" value="triggers">{{ t("structureEditor.triggers") }}</TabsTrigger>
|
||||
</TabsList>
|
||||
<div class="flex shrink-0 items-center gap-1.5">
|
||||
<Button v-if="!isCreateMode" size="sm" variant="outline" :class="structureToolbarButtonClass" data-structure-view-data @click="emit('viewData')">
|
||||
<Rows3 :class="structureIconClass" />
|
||||
{{ t("contextMenu.viewData") }}
|
||||
</Button>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<SlidersHorizontal :class="[structureIconClass, 'text-muted-foreground']" />
|
||||
<div ref="structureDensityMenuRef" class="relative">
|
||||
|
||||
Vendored
+1
@@ -48,6 +48,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Maximize2: Icon,
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
+1
@@ -66,6 +66,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
RotateCcw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
Vendored
+1
@@ -50,6 +50,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
RotateCcw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
+1
@@ -56,6 +56,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
RotateCcw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
Vendored
+1
@@ -59,6 +59,7 @@ vi.mock("@lucide/vue", async () => {
|
||||
Plus: Icon,
|
||||
RefreshCw: Icon,
|
||||
RotateCcw: Icon,
|
||||
Rows3: Icon,
|
||||
Save: Icon,
|
||||
Search: Icon,
|
||||
Settings: Icon,
|
||||
|
||||
@@ -2433,6 +2433,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
resultAutoSave: t.resultAutoSave,
|
||||
uiState: t.uiState,
|
||||
structureTableName: t.structureTableName,
|
||||
structureTableType: t.structureTableType,
|
||||
structureDraft: t.structureDraft,
|
||||
objectBrowser: t.objectBrowser,
|
||||
objectSource: t.objectSource,
|
||||
@@ -3680,7 +3681,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
tab.structureInitialTabRequestId = (tab.structureInitialTabRequestId ?? 0) + 1;
|
||||
}
|
||||
|
||||
function openTableStructure(connectionId: string, database: string, schema?: string, tableName?: string, initialTab?: TableInfoTab, initialTarget?: TableStructureEditorTarget, catalog?: string) {
|
||||
function openTableStructure(connectionId: string, database: string, schema?: string, tableName?: string, initialTab?: TableInfoTab, initialTarget?: TableStructureEditorTarget, catalog?: string, tableType?: "table" | "view") {
|
||||
const resolvedTableName = tableName || "";
|
||||
if (resolvedTableName) {
|
||||
const existing = tabs.value.find((tab) => tab.mode === "structure" && tab.connectionId === connectionId && tab.database === database && (tab.catalog || "") === (catalog || "") && (tab.schema || "") === (schema || "") && (tab.structureTableName || "") === resolvedTableName);
|
||||
@@ -3706,6 +3707,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
isExplaining: false,
|
||||
mode: "structure",
|
||||
structureTableName: resolvedTableName,
|
||||
structureTableType: tableType,
|
||||
structureInitialTab: initialTab,
|
||||
structureInitialTabRequestId: initialTab || initialTarget?.name ? 1 : undefined,
|
||||
structureInitialTarget: initialTarget?.name ? initialTarget : undefined,
|
||||
@@ -4362,6 +4364,7 @@ export const useQueryStore = defineStore("query", () => {
|
||||
nacosNamespace: original.nacosNamespace,
|
||||
nacosNamespaceName: original.nacosNamespaceName,
|
||||
structureTableName: original.structureTableName,
|
||||
structureTableType: original.structureTableType,
|
||||
structureDraft: original.structureDraft ? cloneTabDraft(original.structureDraft) : undefined,
|
||||
objectBrowser: original.objectBrowser ? { ...original.objectBrowser } : undefined,
|
||||
objectSource: original.objectSource ? { ...original.objectSource } : undefined,
|
||||
|
||||
@@ -1780,6 +1780,8 @@ export interface QueryTab {
|
||||
nacosTargetRequestId?: number;
|
||||
nacosConfigEditorViewport?: NacosConfigEditorViewport;
|
||||
structureTableName?: string;
|
||||
/** Navigation type of the opened structure object; views matter for "view data" routing. */
|
||||
structureTableType?: "table" | "view";
|
||||
structureInitialTab?: TableInfoTab;
|
||||
structureInitialTabRequestId?: number;
|
||||
structureInitialTarget?: TableStructureEditorTarget;
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
Reference in new issue
Block a user