Browse Source

Merge pull request #8428 from nocodb/nc-fix/2834-one-to-one-erd

fix: add one to one relation in ERD diagram
pull/8433/head
Pranav C 6 months ago committed by GitHub
parent
commit
2455c47088
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 12
      packages/nc-gui/components/erd/RelationEdge.vue
  2. 45
      packages/nc-gui/components/erd/utils.ts

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

@ -116,7 +116,19 @@ export default {
</EdgeLabelRenderer>
<template v-if="!showSkeleton">
<circle
v-if="data.isOneToOne"
class="nc-erd-edge-circle"
:cx="sourceX"
:cy="sourceY"
fill="#fff"
:r="5"
stroke="#898E99"
:stroke-width="2"
/>
<rect
v-else
class="nc-erd-edge-rect"
:x="sourceX"
:y="sourceY - 4"

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

@ -1,9 +1,9 @@
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { UITypes, isLinksOrLTAR } from 'nocodb-sdk'
import { RelationTypes, UITypes, isLinksOrLTAR } from 'nocodb-sdk'
import dagre from 'dagre'
import type { Edge, EdgeMarker, Elements, Node } from '@vue-flow/core'
import type { MaybeRef } from '@vueuse/core'
import { MarkerType, Position, isEdge, isNode } from '@vue-flow/core'
import type { MaybeRef } from '@vueuse/core'
import { scaleLinear as d3ScaleLinear } from 'd3-scale'
import tinycolor from 'tinycolor2'
@ -29,6 +29,7 @@ export interface NodeData {
export interface EdgeData {
isManyToMany: boolean
isOneToOne: boolean
isSelfRelation: boolean
label?: string
simpleLabel?: string
@ -41,7 +42,7 @@ interface Relation {
childColId?: string
parentColId?: string
modelId?: string
type: 'mm' | 'hm'
type: RelationTypes
}
/**
@ -89,27 +90,36 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ER
childColId: colOptions.fk_child_column_id,
parentColId: colOptions.fk_parent_column_id,
modelId: colOptions.fk_mm_model_id,
type: 'hm',
type: RelationTypes.HAS_MANY,
}
if (colOptions.type === RelationTypes.HAS_MANY) {
relation.type = RelationTypes.HAS_MANY
acc.push(relation)
continue
}
if (colOptions.type === RelationTypes.ONE_TO_ONE) {
relation.type = RelationTypes.ONE_TO_ONE
if (colOptions.type === 'hm') {
relation.type = 'hm'
// skip adding relation link from both side
if (column.meta?.bt) continue
acc.push(relation)
continue
}
if (colOptions.type === 'mm') {
if (colOptions.type === RelationTypes.MANY_TO_MANY) {
// Avoid duplicate mm connections
const correspondingColumn = acc.find(
(relation) =>
relation.type === 'mm' &&
relation.type === RelationTypes.MANY_TO_MANY &&
relation.parentColId === colOptions.fk_child_column_id &&
relation.childColId === colOptions.fk_parent_column_id,
)
if (!correspondingColumn) {
relation.type = 'mm'
relation.type = RelationTypes.MANY_TO_MANY
acc.push(relation)
continue
@ -123,7 +133,11 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ER
)
function edgeLabel({ type, source, target, modelId, childColId, parentColId }: Relation) {
const typeLabel = type === 'mm' ? 'many to many' : 'has many'
let typeLabel: string
if (type === RelationTypes.HAS_MANY) typeLabel = 'has many'
else if (type === RelationTypes.MANY_TO_MANY) typeLabel = 'many to many'
else if (type === 'oo') typeLabel = 'one to one'
const parentCol = metasWithIdAsKey.value[source].columns?.find((col) => {
const colOptions = col.colOptions as LinkToAnotherRecordType
@ -140,12 +154,12 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ER
const colOptions = col.colOptions as LinkToAnotherRecordType
if (!colOptions) return false
return colOptions.fk_parent_column_id === (type === 'mm' ? childColId : parentColId)
return colOptions.fk_parent_column_id === (type === RelationTypes.MANY_TO_MANY ? childColId : parentColId)
})
if (!parentCol || !childCol) return ''
if (type === 'mm') {
if (type === RelationTypes.MANY_TO_MANY) {
if (config.value.showJunctionTableNames) {
if (!modelId) return ''
@ -208,12 +222,12 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ER
return relations.value.reduce<Edge<EdgeData>[]>((acc, { source, target, childColId, parentColId, type, modelId }) => {
let sourceColumnId, targetColumnId
if (type === 'hm') {
if (type === RelationTypes.HAS_MANY || type === 'oo') {
sourceColumnId = childColId
targetColumnId = childColId
}
if (type === 'mm') {
if (type === RelationTypes.MANY_TO_MANY) {
sourceColumnId = parentColId
targetColumnId = childColId
}
@ -239,7 +253,8 @@ export function useErdElements(tables: MaybeRef<TableType[]>, props: MaybeRef<ER
type: MarkerType.ArrowClosed,
},
data: {
isManyToMany: type === 'mm',
isManyToMany: type === RelationTypes.MANY_TO_MANY,
isOneToOne: type === 'oo',
isSelfRelation: source === target && sourceColumnId === targetColumnId,
label,
simpleLabel,

Loading…
Cancel
Save