feat(diagram): open table data from graph cards

This commit is contained in:
t8y2 2026-07-07 14:26:52 +08:00
parent c60b23ffe7
commit 586faf28c8
4 changed files with 45 additions and 4 deletions

View File

@ -252,7 +252,7 @@ function requestActiveEditorExecute() {
const dialogs = useDialogSources();
const { getDatabaseOptions } = useDatabaseOptions();
const { openLineageTarget, openDatabaseSearchTarget, onStructureEditorSaved, openTableTarget } = useNavigationTargets(dialogs);
const { openLineageTarget, openDatabaseSearchTarget, openDiagramTarget, onStructureEditorSaved, openTableTarget } = useNavigationTargets(dialogs);
const { onExecuteSql, onReloadData, onPaginate, onSort } = useDataGridActions(activeTab);
const { setupTauriListeners, cleanupTauriListeners } = useTauriEvents({
openTableTarget,
@ -1974,6 +1974,7 @@ onUnmounted(() => {
"
@open-lineage-target="openLineageTarget"
@open-database-search-target="openDatabaseSearchTarget"
@open-diagram-target="openDiagramTarget"
/>
<UpdateDialog
v-if="showUpdateDialog"

View File

@ -32,6 +32,18 @@ const props = defineProps<{
focusTableName?: string;
}>();
const emit = defineEmits<{
"open-target": [
value: {
connectionId: string;
database: string;
schema?: string;
tableName: string;
tableType?: string;
},
];
}>();
const CARD_WIDTH = 270;
const COLUMN_ROW_HEIGHT = 24;
const CARD_HEADER_HEIGHT = 44;
@ -183,6 +195,17 @@ function relationshipTitle(relationship: DiagramRelationship): string {
return `${relationship.sourceTable}.${relationship.sourceColumn} (${relationship.sourceCardinality}:${relationship.targetCardinality}) -> ${relationship.targetTable}.${relationship.targetColumn}`;
}
function openTableData(tableName: string) {
if (!connectionId.value || !database.value || !tableName) return;
emit("open-target", {
connectionId: connectionId.value,
database: database.value,
schema: isSchemaAware.value ? schema.value || undefined : undefined,
tableName,
tableType: "TABLE",
});
}
function relationshipStorageKey(): string {
if (!connectionId.value || !database.value) return "";
return ["dbx", "diagram", "relationships", "v1", connectionId.value, database.value, schema.value || ""].join(":");
@ -1015,6 +1038,7 @@ onUnmounted(stopDrag);
width: `${CARD_WIDTH}px`,
transform: `translate(${positions[table.name]?.x ?? 0}px, ${positions[table.name]?.y ?? 0}px)`,
}"
@dblclick.stop="openTableData(table.name)"
>
<div class="flex h-11 cursor-grab items-center gap-2 border-b bg-muted/40 px-3 active:cursor-grabbing" @mousedown="startDrag(table.name, $event)">
<Table2 class="h-4 w-4 shrink-0 text-muted-foreground" />
@ -1103,13 +1127,14 @@ onUnmounted(stopDrag);
<div
v-for="entity in engineeringDiagram.entities"
:key="entity.id"
class="absolute flex items-center justify-center border border-blue-500/70 bg-blue-100/80 px-3 text-center text-sm font-semibold text-blue-950 shadow-sm dark:bg-blue-950/35 dark:text-blue-100"
class="absolute flex cursor-pointer items-center justify-center border border-blue-500/70 bg-blue-100/80 px-3 text-center text-sm font-semibold text-blue-950 shadow-sm dark:bg-blue-950/35 dark:text-blue-100"
:class="entity.name === focusTableName ? 'ring-2 ring-primary/40' : ''"
:style="{
width: `${entity.width}px`,
height: `${entity.height}px`,
transform: `translate(${entity.x}px, ${entity.y}px)`,
}"
@dblclick.stop="openTableData(entity.name)"
>
<span class="truncate">{{ entity.name }}</span>
</div>

View File

@ -66,6 +66,15 @@ const emit = defineEmits<{
whereInput?: string;
},
];
openDiagramTarget: [
target: {
connectionId: string;
database: string;
schema?: string;
tableName: string;
tableType?: string;
},
];
}>();
const { t } = useI18n();
@ -143,6 +152,7 @@ watch(
:prefill-database="dialogs.diagramPrefillDatabase.value"
:prefill-schema="dialogs.diagramPrefillSchema.value"
:focus-table-name="dialogs.diagramFocusTableName.value"
@open-target="emit('openDiagramTarget', $event)"
/>
<TableImportDialog
v-if="dialogs.showTableImportDialog.value"

View File

@ -152,7 +152,7 @@ async function openTableTarget(target: NavigationTarget, options: { tableInfoTab
}
}
export function useNavigationTargets(dialogs: { showFieldLineageDialog: { value: boolean }; showDatabaseSearchDialog: { value: boolean } }) {
export function useNavigationTargets(dialogs: { showFieldLineageDialog: { value: boolean }; showDatabaseSearchDialog: { value: boolean }; showDiagramDialog: { value: boolean } }) {
const connectionStore = useConnectionStore();
const queryStore = useQueryStore();
@ -166,6 +166,11 @@ export function useNavigationTargets(dialogs: { showFieldLineageDialog: { value:
await openTableTarget(target);
}
async function openDiagramTarget(target: NavigationTarget) {
dialogs.showDiagramDialog.value = false;
await openTableTarget(target);
}
async function onStructureEditorSaved(reloadData: () => Promise<void>, toast: (msg: string, duration?: number) => void, context: { connectionId: string; database: string; schema?: string; tableName: string }, commentChanged?: boolean) {
if (!context.tableName) {
try {
@ -198,5 +203,5 @@ export function useNavigationTargets(dialogs: { showFieldLineageDialog: { value:
}
}
return { openLineageTarget, openDatabaseSearchTarget, onStructureEditorSaved, openTableTarget };
return { openLineageTarget, openDatabaseSearchTarget, openDiagramTarget, onStructureEditorSaved, openTableTarget };
}