Skip to content

Commit

Permalink
feat: relationship svg
Browse files Browse the repository at this point in the history
  • Loading branch information
dineug committed Nov 12, 2023
1 parent 542f2a1 commit 0bb8409
Show file tree
Hide file tree
Showing 17 changed files with 1,063 additions and 93 deletions.
4 changes: 4 additions & 0 deletions packages/erd-editor/src/components/erd/canvas/Canvas.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { cache, FC, html, Ref, ref, repeat } from '@dineug/r-html';

import { useAppContext } from '@/components/appContext';
import CanvasSvg from '@/components/erd/canvas/canvas-svg/CanvasSvg';
import DrawRelationship from '@/components/erd/canvas/draw-relationship/DrawRelationship';
import HighLevelTable from '@/components/erd/canvas/high-level-table/HighLevelTable';
import Memo from '@/components/erd/canvas/memo/Memo';
import Table from '@/components/erd/canvas/table/Table';
import { Show } from '@/constants/schema';
import { bHas } from '@/utils/bit';
import { query } from '@/utils/collection/query';

import * as styles from './Canvas.styles';
Expand Down Expand Up @@ -64,6 +67,7 @@ const Canvas: FC<CanvasProps> = (props, ctx) => {
memo => memo.id,
memo => html`<${Memo} memo=${memo} />`
)}
${bHas(show, Show.relationship) ? html`<${CanvasSvg} />` : null}
${drawRelationship?.start
? html`<${DrawRelationship}
root=${props.root}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { css } from '@dineug/r-html';

export const root = css`
position: absolute;
top: 0;
left: 0;
overflow: visible;
.relationship {
stroke: var(--key-fk);
}
.relationship.identification {
stroke: var(--key-pfk);
}
.relationship:hover {
stroke: var(--relationship-hover);
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { FC, repeat, svg } from '@dineug/r-html';

import { useAppContext } from '@/components/appContext';
import Relationship from '@/components/erd/canvas/canvas-svg/relationship/Relationship';
import { query } from '@/utils/collection/query';

import * as styles from './CanvasSvg.styles';

export type CanvasSvgProps = {
strokeWidth?: number;
class?: any;
};

const CanvasSvg: FC<CanvasSvgProps> = (props, ctx) => {
const app = useAppContext(ctx);

return () => {
const { store } = app.value;
const {
settings: { width, height },
doc: { relationshipIds },
collections,
} = store.state;

const relationships = query(collections)
.collection('relationshipEntities')
.selectByIds(relationshipIds);

return svg`
<svg
class=${[styles.root, props.class]}
style=${{
width: `${width}px`,
height: `${height}px`,
'min-width': `${width}px`,
'min-height': `${height}px`,
}}
>
${repeat(
relationships,
relationship => relationship.id,
relationship => svg`
<g class=${[
'relationship',
{ identification: relationship.identification },
]}>
<${Relationship}
relationship=${relationship}
strokeWidth=${props.strokeWidth ?? 3}
/>
</g>
`
)}
</svg>
`;
};
};

export default CanvasSvg;
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import { DOMTemplateLiterals, svg } from '@dineug/r-html';

import { RelationshipType } from '@/constants/schema';
import { RelationshipPath } from '@/utils/draw-relationship';

const relationshipZeroOneN = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<circle
cx=${line.circle.cx} cy=${line.circle.cy} r="8"
fill-opacity="0.0"
stroke-width="3"
></circle>
<line
x1=${line.line.end.base.x1} y1=${line.line.end.base.y1}
x2=${line.line.end.base.x2} y2=${line.line.end.base.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.left.x1} y1=${line.line.end.left.y1}
x2=${line.line.end.left.x2} y2=${line.line.end.left.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center.x1} y1=${line.line.end.center.y1}
x2=${line.line.end.center.x2} y2=${line.line.end.center.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.right.x1} y1=${line.line.end.right.y1}
x2=${line.line.end.right.x2} y2=${line.line.end.right.y2}
stroke-width="3"
></line>
`;

const relationshipZeroOne = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<circle
cx=${line.circle.cx} cy=${line.circle.cy} r="8"
fill-opacity="0.0"
stroke-width="3"
></circle>
<line
x1=${line.line.end.base.x1} y1=${line.line.end.base.y1}
x2=${line.line.end.base.x2} y2=${line.line.end.base.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center.x1} y1=${line.line.end.center.y1}
x2=${line.line.end.center.x2} y2=${line.line.end.center.y2}
stroke-width="3"
></line>
`;

const relationshipZeroN = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<circle
cx=${line.circle.cx} cy=${line.circle.cy} r="8"
fill-opacity="0.0"
stroke-width="3"
></circle>
<line
x1=${line.line.end.left.x1} y1=${line.line.end.left.y1}
x2=${line.line.end.left.x2} y2=${line.line.end.left.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center.x1} y1=${line.line.end.center.y1}
x2=${line.line.end.center.x2} y2=${line.line.end.center.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.right.x1} y1=${line.line.end.right.y1}
x2=${line.line.end.right.x2} y2=${line.line.end.right.y2}
stroke-width="3"
></line>
`;

const relationshipOneOnly = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.base.x1} y1=${line.line.end.base.y1}
x2=${line.line.end.base.x2} y2=${line.line.end.base.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.base2.x1} y1=${line.line.end.base2.y1}
x2=${line.line.end.base2.x2} y2=${line.line.end.base2.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center2.x1} y1=${line.line.end.center2.y1}
x2=${line.line.end.center2.x2} y2=${line.line.end.center2.y2}
stroke-width="3"
></line>
`;

const relationshipOneN = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.base.x1} y1=${line.line.end.base.y1}
x2=${line.line.end.base.x2} y2=${line.line.end.base.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.left.x1} y1=${line.line.end.left.y1}
x2=${line.line.end.left.x2} y2=${line.line.end.left.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center2.x1} y1=${line.line.end.center2.y1}
x2=${line.line.end.center2.x2} y2=${line.line.end.center2.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.right.x1} y1=${line.line.end.right.y1}
x2=${line.line.end.right.x2} y2=${line.line.end.right.y2}
stroke-width="3"
></line>
`;

const relationshipOne = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.base.x1} y1=${line.line.end.base.y1}
x2=${line.line.end.base.x2} y2=${line.line.end.base.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center2.x1} y1=${line.line.end.center2.y1}
x2=${line.line.end.center2.x2} y2=${line.line.end.center2.y2}
stroke-width="3"
></line>
`;

const relationshipN = ({ path, line }: RelationshipPath) =>
svg`
<line
x1=${path.line.end.x1} y1=${path.line.end.y1}
x2=${path.line.end.x2} y2=${path.line.end.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.left.x1} y1=${line.line.end.left.y1}
x2=${line.line.end.left.x2} y2=${line.line.end.left.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.center2.x1} y1=${line.line.end.center2.y1}
x2=${line.line.end.center2.x2} y2=${line.line.end.center2.y2}
stroke-width="3"
></line>
<line
x1=${line.line.end.right.x1} y1=${line.line.end.right.y1}
x2=${line.line.end.right.x2} y2=${line.line.end.right.y2}
stroke-width="3"
></line>
`;

export const relationshipShapeMap: Record<
number,
(value: RelationshipPath) => DOMTemplateLiterals
> = {
[0b0000000000000000000000000000001]: relationshipZeroOneN,
[RelationshipType.ZeroOne]: relationshipZeroOne,
[RelationshipType.ZeroN]: relationshipZeroN,
[RelationshipType.OneOnly]: relationshipOneOnly,
[RelationshipType.OneN]: relationshipOneN,
[0b0000000000000000000000000100000]: relationshipOne,
[0b0000000000000000000000001000000]: relationshipN,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { FC, svg } from '@dineug/r-html';

import { StartRelationshipType } from '@/constants/schema';
import { Relationship as RelationshipType } from '@/internal-types';
import { getRelationshipPath } from '@/utils/draw-relationship/pathFinding';

import { relationshipShapeMap } from './Relationship.template';

export type RelationshipProps = {
relationship: RelationshipType;
strokeWidth: number;
};

const Relationship: FC<RelationshipProps> = (props, ctx) => {
return () => {
const { relationship, strokeWidth } = props;
const relationshipPath = getRelationshipPath(relationship);
const { path, line } = relationshipPath;
const relationshipShapeTpl =
relationshipShapeMap[relationship.relationshipType];
const shape = relationshipShapeTpl
? relationshipShapeTpl(relationshipPath)
: null;

const d = path.path.d();

return svg`
<path
d=${d}
stroke-dasharray=${relationship.identification ? 0 : 10}
stroke-width=${strokeWidth}
fill="transparent"
></path>
<line
x1=${path.line.start.x1} y1=${path.line.start.y1}
x2=${path.line.start.x2} y2=${path.line.start.y2}
stroke-width="3"
></line>
<line
x1=${line.line.start.base.x1} y1=${line.line.start.base.y1}
x2=${line.line.start.base.x2} y2=${line.line.start.base.y2}
stroke-width="3"
></line>
${
relationship.startRelationshipType === StartRelationshipType.ring
? svg`
<circle
cx=${line.startCircle.cx} cy=${line.startCircle.cy} r="8"
fill-opacity="0.0"
stroke-width="3"
></circle>
<line
x1=${line.line.start.center.x1} y1=${line.line.start.center.y1}
x2=${line.line.start.center.x2} y2=${line.line.start.center.y2}
stroke-width="3"
></line>
`
: svg`
<line
x1=${line.line.start.base2.x1} y1=${line.line.start.base2.y1}
x2=${line.line.start.base2.x2} y2=${line.line.start.base2.y2}
stroke-width="3"
></line>
<line
x1=${line.line.start.center2.x1} y1=${line.line.start.center2.y1}
x2=${line.line.start.center2.x2} y2=${line.line.start.center2.y2}
stroke-width="3"
></line>
`
}
${shape}
`;
};
};

export default Relationship;
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useAppContext } from '@/components/appContext';
import { drawRelationshipAction } from '@/engine/modules/editor/atom.actions';
import { DrawRelationship as DrawRelationshipType } from '@/engine/modules/editor/state';
import { useUnmounted } from '@/hooks/useUnmounted';
import { getDraw } from '@/utils/draw-relationship/drawRelationship';
import { getDraw } from '@/utils/draw-relationship/draw';

import * as styles from './DrawRelationship.styles';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ export const border = css`
box-shadow: 0 1px 6px var(--minimap-shadow);
background-color: transparent;
`;

export const canvasSvg = css`
pointer-events: none;
`;
Loading

0 comments on commit 0bb8409

Please sign in to comment.