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

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

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

Loading…
Cancel
Save