Skip to content

Commit 550c878

Browse files
authored
ENG-1102 Create reified relation via canvas (#593)
1 parent 1ea2811 commit 550c878

File tree

1 file changed

+88
-51
lines changed

1 file changed

+88
-51
lines changed

apps/roam/src/components/canvas/DiscourseRelationShape/DiscourseRelationUtil.tsx

Lines changed: 88 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import {
1010
TLShapeUtilFlag,
1111
Geometry2d,
1212
Edge2d,
13+
Editor,
1314
Vec,
1415
Group2d,
1516
TLHandle,
16-
useDefaultColorTheme,
1717
SVGContainer,
1818
TextLabel,
1919
TEXT_PROPS,
@@ -63,6 +63,8 @@ import {
6363
shapeAtTranslationStart,
6464
updateArrowTerminal,
6565
} from "./helpers";
66+
import { getSetting } from "~/utils/extensionSettings";
67+
import { createReifiedRelation } from "~/utils/createReifiedBlock";
6668
import { discourseContext, isPageUid } from "~/components/canvas/Tldraw";
6769
import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle";
6870
import { InputTextNode } from "roamjs-components/types";
@@ -78,6 +80,7 @@ import getCurrentPageUid from "roamjs-components/dom/getCurrentPageUid";
7880
import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid";
7981
import { AddReferencedNodeType } from "./DiscourseRelationTool";
8082
import { dispatchToastEvent } from "~/components/canvas/ToastListener";
83+
import sendErrorEmail from "~/utils/sendErrorEmail";
8184

8285
const COLOR_ARRAY = Array.from(textShapeProps.color.values)
8386
.filter((c) => !["red", "green", "grey"].includes(c))
@@ -492,6 +495,16 @@ export const createAllReferencedNodeUtils = (
492495
});
493496
};
494497

498+
const asDiscourseNodeShape = (
499+
shape: TLShape,
500+
editor: Editor,
501+
): DiscourseNodeShape | null => {
502+
const shapeUtil = editor.getShapeUtil(shape.type);
503+
return shapeUtil instanceof BaseDiscourseNodeUtil
504+
? (shape as DiscourseNodeShape)
505+
: null;
506+
};
507+
495508
export const createAllRelationShapeUtils = (
496509
allRelationIds: string[],
497510
): TLShapeUtilConstructor<DiscourseRelationShape>[] => {
@@ -540,58 +553,82 @@ export const createAllRelationShapeUtils = (
540553
if (arrow.type !== target.type) {
541554
editor.updateShapes([{ id: arrow.id, type: target.type }]);
542555
}
543-
const { triples, label: relationLabel } = relation;
544-
const isOriginal = arrow.props.text === relationLabel;
545-
const newTriples = triples
546-
.map((t) => {
547-
if (/is a/i.test(t[1])) {
548-
const targetNode =
549-
(t[2] === "source" && isOriginal) ||
550-
(t[2] === "destination" && !isOriginal)
551-
? source
552-
: target;
553-
const { title, uid } =
554-
targetNode.props as DiscourseNodeShape["props"];
555-
return [
556-
t[0],
557-
isPageUid(uid) ? "has title" : "with uid",
558-
isPageUid(uid) ? title : uid,
559-
];
560-
}
561-
return t.slice(0);
562-
})
563-
.map(([source, relation, target]) => ({ source, relation, target }));
564-
const parentUid = getCurrentPageUid();
565-
const title = getPageTitleByPageUid(parentUid);
566-
await triplesToBlocks({
567-
defaultPageTitle: `Auto generated from [[${title}]]`,
568-
toPage: async (title: string, blocks: InputTextNode[]) => {
569-
const parentUid =
570-
getPageUidByPageTitle(title) ||
571-
(await createPage({ title: title }));
572-
573-
await Promise.all(
574-
blocks.map((node, order) =>
575-
createBlock({ node, order, parentUid }).catch(() =>
576-
console.error(
577-
`Failed to create block: ${JSON.stringify(
578-
{ node, order, parentUid },
579-
null,
580-
4,
581-
)}`,
556+
if (getSetting("use-reified-relations")) {
557+
const sourceAsDNS = asDiscourseNodeShape(source, editor);
558+
const targetAsDNS = asDiscourseNodeShape(target, editor);
559+
560+
if (sourceAsDNS && targetAsDNS)
561+
await createReifiedRelation({
562+
sourceUid: sourceAsDNS.props.uid,
563+
destinationUid: targetAsDNS.props.uid,
564+
relationBlockUid: relation.id,
565+
});
566+
else {
567+
void sendErrorEmail({
568+
error: new Error(
569+
"attempt to create a relation between non discourse nodes",
570+
),
571+
type: "canvas-create-relation-non-dgn",
572+
}).catch(() => undefined);
573+
}
574+
} else {
575+
const { triples, label: relationLabel } = relation;
576+
const isOriginal = arrow.props.text === relationLabel;
577+
const newTriples = triples
578+
.map((t) => {
579+
if (/is a/i.test(t[1])) {
580+
const targetNode =
581+
(t[2] === "source" && isOriginal) ||
582+
(t[2] === "destination" && !isOriginal)
583+
? source
584+
: target;
585+
const { title, uid } =
586+
targetNode.props as DiscourseNodeShape["props"];
587+
return [
588+
t[0],
589+
isPageUid(uid) ? "has title" : "with uid",
590+
isPageUid(uid) ? title : uid,
591+
];
592+
}
593+
return t.slice(0);
594+
})
595+
.map(([source, relation, target]) => ({
596+
source,
597+
relation,
598+
target,
599+
}));
600+
const parentUid = getCurrentPageUid();
601+
const title = getPageTitleByPageUid(parentUid);
602+
await triplesToBlocks({
603+
defaultPageTitle: `Auto generated from [[${title}]]`,
604+
toPage: async (title: string, blocks: InputTextNode[]) => {
605+
const parentUid =
606+
getPageUidByPageTitle(title) ||
607+
(await createPage({ title: title }));
608+
609+
await Promise.all(
610+
blocks.map((node, order) =>
611+
createBlock({ node, order, parentUid }).catch(() =>
612+
console.error(
613+
`Failed to create block: ${JSON.stringify(
614+
{ node, order, parentUid },
615+
null,
616+
4,
617+
)}`,
618+
),
582619
),
583620
),
584-
),
585-
);
586-
await openBlockInSidebar(parentUid);
587-
},
588-
nodeSpecificationsByLabel: Object.fromEntries(
589-
Object.values(discourseContext.nodes).map((n) => [
590-
n.text,
591-
n.specification,
592-
]),
593-
),
594-
})(newTriples)();
621+
);
622+
await openBlockInSidebar(parentUid);
623+
},
624+
nodeSpecificationsByLabel: Object.fromEntries(
625+
Object.values(discourseContext.nodes).map((n) => [
626+
n.text,
627+
n.specification,
628+
]),
629+
),
630+
})(newTriples)();
631+
}
595632
};
596633

597634
override getDefaultProps(): DiscourseRelationShape["props"] {

0 commit comments

Comments
 (0)