diff --git a/package-lock.json b/package-lock.json index f4bba7e9..cedc673f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@uiw/codemirror-theme-github": "^4.21.25", "@uiw/codemirror-theme-vscode": "^4.21.25", "@uiw/react-codemirror": "^4.21.25", - "@vercel/analytics": "^1.2.2", "axios": "^1.7.4", "classnames": "^2.5.1", "dexie": "^3.2.4", @@ -2253,26 +2252,6 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/@vercel/analytics": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.2.2.tgz", - "integrity": "sha512-X0rctVWkQV1e5Y300ehVNqpOfSOufo7ieA5PIdna8yX/U7Vjz0GFsGf4qvAhxV02uQ2CVt7GYcrFfddXXK2Y4A==", - "dependencies": { - "server-only": "^0.0.1" - }, - "peerDependencies": { - "next": ">= 13", - "react": "^18 || ^19" - }, - "peerDependenciesMeta": { - "next": { - "optional": true - }, - "react": { - "optional": true - } - } - }, "node_modules/@vitejs/plugin-react": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", @@ -5816,11 +5795,6 @@ "semver": "bin/semver.js" } }, - "node_modules/server-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", - "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==" - }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", diff --git a/package.json b/package.json index 30a1b279..e61fa25d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "@uiw/codemirror-theme-github": "^4.21.25", "@uiw/codemirror-theme-vscode": "^4.21.25", "@uiw/react-codemirror": "^4.21.25", - "@vercel/analytics": "^1.2.2", "axios": "^1.7.4", "classnames": "^2.5.1", "dexie": "^3.2.4", diff --git a/src/components/EditorCanvas/Canvas.jsx b/src/components/EditorCanvas/Canvas.jsx index 2a675167..50f15003 100644 --- a/src/components/EditorCanvas/Canvas.jsx +++ b/src/components/EditorCanvas/Canvas.jsx @@ -3,6 +3,7 @@ import { Action, Cardinality, Constraint, + SubtypeRestriction, ObjectType, } from "../../data/constants"; import { Toast } from "@douyinfe/semi-ui"; @@ -435,6 +436,8 @@ export default function Canvas() { tables[linkingLine.startTableId].fields[linkingLine.startFieldId].name }_fk`, id: relationships.length, + subtype: false, + subtype_restriction: "", }; delete newRelationship.startX; delete newRelationship.startY; diff --git a/src/components/EditorCanvas/Relationship.jsx b/src/components/EditorCanvas/Relationship.jsx index 9f512a9a..e6d70a3d 100644 --- a/src/components/EditorCanvas/Relationship.jsx +++ b/src/components/EditorCanvas/Relationship.jsx @@ -1,10 +1,12 @@ import { useRef } from "react"; -import { Cardinality, ObjectType, Tab } from "../../data/constants"; +import { Cardinality, ObjectType, Tab, SubtypeRestriction } from "../../data/constants"; import { calcPath } from "../../utils/calcPath"; import { useDiagram, useSettings, useLayout, useSelect } from "../../hooks"; import { useTranslation } from "react-i18next"; import { SideSheet } from "@douyinfe/semi-ui"; import RelationshipInfo from "../EditorSidePanel/RelationshipsTab/RelationshipInfo"; +import { CrowOM, CrowOO, CrowZM, IDEFZM, DefaultNotation, subDP, subDT, subOP, subOT } from "./RelationshipFormat"; + export default function Relationship({ data }) { const { settings } = useSettings(); @@ -13,31 +15,83 @@ export default function Relationship({ data }) { const { selectedElement, setSelectedElement } = useSelect(); const { t } = useTranslation(); const pathRef = useRef(); + const type = settings.notation === 'default' ? 0 : 10; + const relationshipType=(0,0); + let direction = 1; let cardinalityStart = "1"; let cardinalityEnd = "1"; + let cardinalityvar; + let subtypevar; switch (data.cardinality) { // the translated values are to ensure backwards compatibility - case t(Cardinality.MANY_TO_ONE): - case Cardinality.MANY_TO_ONE: - cardinalityStart = "n"; - cardinalityEnd = "1"; + case t(Cardinality.ZERO_TO_MANY): + case Cardinality.ZERO_TO_MANY: + if (settings.notation === 'default') { + cardinalityStart = "n"; + cardinalityEnd = "1"; + } else { + cardinalityStart = "(1,*)"; + cardinalityEnd = "(1,1)"; + cardinalityvar="1"; + } break; case t(Cardinality.ONE_TO_MANY): case Cardinality.ONE_TO_MANY: - cardinalityStart = "1"; - cardinalityEnd = "n"; + if (settings.notation === 'default') { + cardinalityStart = "1"; + cardinalityEnd = "n"; + } else { + cardinalityStart = "(1,1)"; + cardinalityEnd = "(1,*)"; + cardinalityvar="2"; + } break; case t(Cardinality.ONE_TO_ONE): case Cardinality.ONE_TO_ONE: - cardinalityStart = "1"; - cardinalityEnd = "1"; + if (settings.notation === 'default') { + cardinalityStart = "1"; + cardinalityEnd = "1"; + } else { + cardinalityStart = "(1,1)"; + cardinalityEnd = "(1,1)"; + cardinalityvar="3"; + } break; default: break; } + switch (data.subtype_restriction){ + case t(SubtypeRestriction.DISJOINT_TOTAL): + case SubtypeRestriction.DISJOINT_TOTAL: + subtypevar="1"; + console.log(subtypevar) + break; + + case t(SubtypeRestriction.DISJOINT_PARTIAL): + case SubtypeRestriction.DISJOINT_PARTIAL: + subtypevar="2"; + console.log(subtypevar) + break; + + case t(SubtypeRestriction.OVERLAPPING_TOTAL): + case SubtypeRestriction.OVERLAPPING_TOTAL: + subtypevar="3"; + console.log(subtypevar) + break; + + case t(SubtypeRestriction.OVERLAPPING_PARTIAL): + case SubtypeRestriction.OVERLAPPING_PARTIAL: + subtypevar="4"; + console.log(subtypevar) + break; + default: + break; + + } + let cardinalityStartX = 0; let cardinalityEndX = 0; let cardinalityStartY = 0; @@ -45,13 +99,18 @@ export default function Relationship({ data }) { const cardinalityOffset = 28; + if (pathRef.current) { - const pathLength = pathRef.current.getTotalLength(); + const pathLength = settings.notation === 'default' ? + pathRef.current.getTotalLength() - cardinalityOffset: + pathRef.current.getTotalLength(); + const point1 = pathRef.current.getPointAtLength(cardinalityOffset); cardinalityStartX = point1.x; cardinalityStartY = point1.y; + const point2 = pathRef.current.getPointAtLength( - pathLength - cardinalityOffset, + pathLength, ); cardinalityEndX = point2.x; cardinalityEndY = point2.y; @@ -80,6 +139,10 @@ export default function Relationship({ data }) { } }; + if ((settings.notation === 'crows_foot' || settings.notation === 'idef1x') && cardinalityEndX < cardinalityStartX){ + direction = -1; + } + return ( <> @@ -102,48 +165,22 @@ export default function Relationship({ data }) { stroke="gray" className="group-hover:stroke-sky-700" fill="none" + strokeDasharray={relationshipType} strokeWidth={2} cursor="pointer" /> - {pathRef.current && settings.showCardinality && ( - <> - - - {cardinalityStart} - - - - {cardinalityEnd} - - - )} + + {CrowOM(pathRef.current,settings.notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {CrowOO(pathRef.current,settings.notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {CrowZM(pathRef.current,settings.notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {DefaultNotation(pathRef.current,settings.notation, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, cardinalityStart, cardinalityEnd)} + {IDEFZM(pathRef.current,settings.notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {subDP(pathRef.current,settings.notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {subDT(pathRef.current,settings.notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {subOT(pathRef.current,settings.notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + {subOP(pathRef.current,settings.notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd)} + + + + + + {cardinalityStart} + + + {cardinalityEnd} + + + + + ) + ) +} + +export function CrowOO(pathRef, notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalitySart, cardinalityEnd){ + return( + pathRef && notation === 'crows_foot' && cardinalityvar==3 &&( + <> + + + + + + + + {cardinalitySart} + + + {cardinalityEnd} + + + ) + ) +} + + +export function CrowZM(pathRef, notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'crows_foot' && (cardinalityvar==1) &&( + <> + + + + + {cardinalityStart} + + + {cardinalityEnd} + + + + + ) + ) +} + +export function DefaultNotation(pathRef, notation, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'default' && ( + <> + + + {cardinalityStart} + + + + {cardinalityEnd} + + + ) + ) +} + +export function IDEFZM(pathRef, notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'idef1x' && (cardinalityvar==1) &&( + <> + + + {cardinalityStart} + + + {cardinalityEnd} + + + ) + ) +} + +export function subDP(pathRef, notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'idef1x' && (cardinalityvar=="2") &&( + <> + + + D + + + + {cardinalityStart} + + + {cardinalityEnd} + + + ) + ) +} + +export function subDT(pathRef, notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'idef1x' && (subtypevar=="1") &&( + <> + + + D + + + + + {cardinalityStart} + + + {cardinalityEnd} + + + ) + ) +} + +export function subOP(pathRef, notation, cardinalityvar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'idef1x' && (cardinalityvar=="4") &&( + <> + + + O + + + + {cardinalityStart} + + + {cardinalityEnd} + + + ) + ) +} + +export function subOT(pathRef, notation, subtypevar, cardinalityEndX, cardinalityEndY, cardinalityStartX, cardinalityStartY, direction, cardinalityStart, cardinalityEnd){ + return( + pathRef && notation === 'idef1x' && (subtypevar=="3") &&( + <> + + + O + + + + + {cardinalityStart} + + + {cardinalityEnd} + + + ) + ) +} + diff --git a/src/components/EditorHeader/ControlPanel.jsx b/src/components/EditorHeader/ControlPanel.jsx index 593e69d6..a7b9aa08 100644 --- a/src/components/EditorHeader/ControlPanel.jsx +++ b/src/components/EditorHeader/ControlPanel.jsx @@ -1220,17 +1220,40 @@ export default function ControlPanel({ function: viewGrid, shortcut: "Ctrl+Shift+G", }, - show_cardinality: { - state: settings.showCardinality ? ( - - ) : ( - - ), - function: () => - setSettings((prev) => ({ - ...prev, - showCardinality: !prev.showCardinality, - })), + // show_cardinality: { + // state: settings.showCardinality ? ( + // + // ) : ( + // + // ), + // function: () => + // setSettings((prev) => ({ + // ...prev, + // showCardinality: !prev.showCardinality, + // })), + // }, + notation: { + children: [ + { + default_notation: () => { + console.log(settings.notation); + setSettings((prev) => ({ ...prev, notation: "default" })); + }, + }, + { + crows_foot_notation: () => { + console.log(settings.notation); + setSettings((prev) => ({ ...prev, notation: "crows_foot" })); + }, + }, + { + idef1x_notation: () => { + console.log(settings.notation); + setSettings((prev) => ({ ...prev, notation: "idef1x" })); + }, + }, + ], + function: () => {}, }, show_debug_coordinates: { state: settings.showDebugCoordinates ? ( diff --git a/src/components/EditorSidePanel/RelationshipsTab/RelationshipInfo.jsx b/src/components/EditorSidePanel/RelationshipsTab/RelationshipInfo.jsx index bc184f10..4bd028d4 100644 --- a/src/components/EditorSidePanel/RelationshipsTab/RelationshipInfo.jsx +++ b/src/components/EditorSidePanel/RelationshipsTab/RelationshipInfo.jsx @@ -1,4 +1,4 @@ -import { Row, Col, Select, Button, Popover, Table } from "@douyinfe/semi-ui"; +import { Row, Col, Select, Button, Popover, Table, Checkbox } from "@douyinfe/semi-ui"; import { IconDeleteStroked, IconLoopTextStroked, @@ -6,6 +6,7 @@ import { } from "@douyinfe/semi-icons"; import { Cardinality, + SubtypeRestriction, Constraint, Action, ObjectType, @@ -97,6 +98,53 @@ export default function RelationshipInfo({ data }) { ); }; + const changeSubtypeRestriction = (value) => { + setUndoStack((prev) => [ + ...prev, + { + action: Action.EDIT, + element: ObjectType.RELATIONSHIP, + rid: data.id, + undo: { subtype_restriction: data.subtype_restriction }, + redo: { subtype_restriction: value }, + message: t("edit_relationship", { + refName: data.name, + extra: "[subtype_restriction]", + }), + }, + ]); + setRedoStack([]); + setRelationships((prev) => + prev.map((e, idx) => + idx === data.id ? { ...e, subtype_restriction: value } : e, + ), + ); + }; + + const toggleSubtype = () => { + const prevVal = data.subtype; + setUndoStack((prev) => [ + ...prev, + { + action: Action.EDIT, + element: ObjectType.RELATIONSHIP, + rid: data.id, + undo: { subtype: data.subtype }, + redo: { subtype: !data.subtype }, + message: t("edit_relationship", { + refName: data.name, + extra: "[subtype]", + }), + }, + ]); + setRedoStack([]); + setRelationships((prev) => + prev.map((e, idx) => + idx === data.id ? { ...e, subtype: !prevVal } : e, + ), + ); + }; + const changeConstraint = (key, value) => { const undoKey = `${key}Constraint`; setUndoStack((prev) => [ @@ -180,6 +228,32 @@ export default function RelationshipInfo({ data }) { className="w-full" onChange={changeCardinality} /> + + +
{t("subtype")}: +
+ + + + +
+ {data.subtype && + +
{t("subtype_restriction")}:
+