Browse Source

refactor(nc-gui): simplify relation creation

pull/4066/head
braks 2 years ago
parent
commit
cfee983e40
  1. 11
      packages/nc-gui/components/erd/RelationEdge.vue
  2. 90
      packages/nc-gui/components/erd/utils.ts

11
packages/nc-gui/components/erd/RelationEdge.vue

@ -2,7 +2,6 @@
import type { EdgeProps, Position } from '@vue-flow/core' import type { EdgeProps, Position } from '@vue-flow/core'
import { EdgeText, getBezierPath } from '@vue-flow/core' import { EdgeText, getBezierPath } from '@vue-flow/core'
import type { CSSProperties } from '@vue/runtime-dom' import type { CSSProperties } from '@vue/runtime-dom'
import type { ColumnType } from 'nocodb-sdk'
import { computed, toRef } from '#imports' import { computed, toRef } from '#imports'
interface RelationEdgeProps extends EdgeProps { interface RelationEdgeProps extends EdgeProps {
@ -14,11 +13,7 @@ interface RelationEdgeProps extends EdgeProps {
sourcePosition: Position sourcePosition: Position
targetPosition: Position targetPosition: Position
data: { data: {
column: ColumnType & { isManyToMany: boolean
colOptions?: {
type: string
}
}
isSelfRelation: boolean isSelfRelation: boolean
label: string label: string
} }
@ -31,8 +26,6 @@ const props = defineProps<RelationEdgeProps>()
const data = toRef(props, 'data') const data = toRef(props, 'data')
const isManyToMany = computed(() => data.value.column?.colOptions?.type === 'mm')
const edgePath = computed(() => { const edgePath = computed(() => {
if (data.value.isSelfRelation) { if (data.value.isSelfRelation) {
const { sourceX, sourceY, targetX, targetY } = props const { sourceX, sourceY, targetX, targetY } = props
@ -105,7 +98,7 @@ export default {
/> />
<rect <rect
v-if="isManyToMany" v-if="data.isManyToMany"
class="nc-erd-edge-rect" class="nc-erd-edge-rect"
:x="targetX" :x="targetX"
:y="targetY - 4" :y="targetY - 4"

90
packages/nc-gui/components/erd/utils.ts

@ -14,6 +14,15 @@ export interface ErdFlowConfig {
showJunctionTableNames: boolean showJunctionTableNames: boolean
} }
interface Relation {
source: string
target: string
childColId?: string
parentColId?: string
modelId?: string
type: 'mm' | 'hm'
}
export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ErdFlowConfig>) { export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ErdFlowConfig>) {
const elements = ref<Elements>([]) const elements = ref<Elements>([])
@ -26,42 +35,61 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<Er
const erdTables = computed(() => unref(tables)) const erdTables = computed(() => unref(tables))
const config = $computed(() => unref(props)) const config = $computed(() => unref(props))
const ltarColumns = computed(() => const relations = computed(() =>
erdTables.value.reduce((acc, table) => { erdTables.value.reduce((acc, table) => {
const meta = metasWithIdAsKey.value[table.id!] const meta = metasWithIdAsKey.value[table.id!]
const columns = meta.columns?.filter( const columns =
(column: ColumnType) => column.uidt === UITypes.LinkToAnotherRecord && column.system !== 1, meta.columns?.filter((column: ColumnType) => column.uidt === UITypes.LinkToAnotherRecord && column.system !== 1) || []
)
columns?.forEach((column: ColumnType) => { columns.forEach((column: ColumnType) => {
const colOptions = column.colOptions as LinkToAnotherRecordType const colOptions = column.colOptions as LinkToAnotherRecordType
const source = column.fk_model_id
const target = colOptions.fk_related_model_id
const sourceExists = erdTables.value.find((t) => t.id === source)
const targetExists = erdTables.value.find((t) => t.id === target)
if (source && target && sourceExists && targetExists) {
const relation: Relation = {
source,
target,
childColId: colOptions.fk_child_column_id,
parentColId: colOptions.fk_parent_column_id,
modelId: colOptions.fk_mm_model_id,
type: 'hm',
}
if (colOptions.type === 'hm') { if (colOptions.type === 'hm') {
return acc.push(column) relation.type = 'hm'
return acc.push(relation)
} }
if (colOptions.type === 'mm') { if (colOptions.type === 'mm') {
// Avoid duplicate mm connections // Avoid duplicate mm connections
const correspondingColumn = acc.find((c) => { const correspondingColumn = acc.find(
const correspondingColOptions = c.colOptions as LinkToAnotherRecordType (relation) =>
relation.type === 'mm' &&
return ( relation.parentColId === colOptions.fk_child_column_id &&
correspondingColOptions.type === 'mm' && relation.childColId === colOptions.fk_parent_column_id,
correspondingColOptions.fk_parent_column_id === colOptions.fk_child_column_id &&
correspondingColOptions.fk_child_column_id === colOptions.fk_parent_column_id
) )
})
if (!correspondingColumn) { if (!correspondingColumn) {
return acc.push(column) relation.type = 'mm'
return acc.push(relation)
}
} }
} }
}) })
return acc return acc
}, [] as ColumnType[]), }, [] as Relation[]),
) )
const edgeMMTableLabel = (modelId: string) => { const edgeMMTableLabel = (modelId?: string) => {
if (!modelId) return ''
const mmModel = metasWithIdAsKey.value[modelId] const mmModel = metasWithIdAsKey.value[modelId]
if (mmModel.title !== mmModel.table_name) { if (mmModel.title !== mmModel.table_name) {
@ -97,29 +125,19 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<Er
} }
function createEdges() { function createEdges() {
return ltarColumns.value.reduce<Edge[]>((acc, column) => { return relations.value.reduce<Edge[]>((acc, { source, target, childColId, parentColId, type, modelId }) => {
const source = column.fk_model_id!
const target = (column.colOptions as LinkToAnotherRecordType).fk_related_model_id!
const hasSource = erdTables.value.find((table) => table.id === source)
const hasTarget = erdTables.value.find((table) => table.id === target)
if (!hasSource || !hasTarget) return acc
let sourceColumnId, targetColumnId let sourceColumnId, targetColumnId
let edgeLabel = '' let edgeLabel = ''
if ((column.colOptions as LinkToAnotherRecordType).type === 'hm') { if (type === 'hm') {
sourceColumnId = (column.colOptions as LinkToAnotherRecordType).fk_child_column_id sourceColumnId = childColId
targetColumnId = (column.colOptions as LinkToAnotherRecordType).fk_child_column_id targetColumnId = childColId
} }
if ((column.colOptions as LinkToAnotherRecordType).type === 'mm') { if (type === 'mm') {
sourceColumnId = (column.colOptions as LinkToAnotherRecordType).fk_parent_column_id sourceColumnId = parentColId
targetColumnId = (column.colOptions as LinkToAnotherRecordType).fk_child_column_id targetColumnId = childColId
edgeLabel = config.showJunctionTableNames edgeLabel = config.showJunctionTableNames ? edgeMMTableLabel(modelId) : ''
? edgeMMTableLabel((column.colOptions as LinkToAnotherRecordType).fk_mm_model_id!)
: ''
} }
if (source !== target) dagreGraph.setEdge(source, target) if (source !== target) dagreGraph.setEdge(source, target)
@ -132,7 +150,7 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<Er
targetHandle: `d-${targetColumnId}-${target}`, targetHandle: `d-${targetColumnId}-${target}`,
type: 'custom', type: 'custom',
data: { data: {
column, isManyToMany: type === 'mm',
isSelfRelation: source === target && sourceColumnId === targetColumnId, isSelfRelation: source === target && sourceColumnId === targetColumnId,
label: edgeLabel, label: edgeLabel,
}, },

Loading…
Cancel
Save