@@ -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" ;
6668import { discourseContext , isPageUid } from "~/components/canvas/Tldraw" ;
6769import getPageUidByPageTitle from "roamjs-components/queries/getPageUidByPageTitle" ;
6870import { InputTextNode } from "roamjs-components/types" ;
@@ -78,6 +80,7 @@ import getCurrentPageUid from "roamjs-components/dom/getCurrentPageUid";
7880import getPageTitleByPageUid from "roamjs-components/queries/getPageTitleByPageUid" ;
7981import { AddReferencedNodeType } from "./DiscourseRelationTool" ;
8082import { dispatchToastEvent } from "~/components/canvas/ToastListener" ;
83+ import sendErrorEmail from "~/utils/sendErrorEmail" ;
8184
8285const 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+
495508export 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 ( / i s 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 ( / i s 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