diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index 9378be28e..557960f5b 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -35,7 +35,8 @@ const TYPE_MAPPINGS: Record Promise<{ default: TypeWidge "readOnlyText": () => import("./type_widgets/text/ReadOnlyText"), "editableText": () => import("./type_widgets/text/EditableText"), "render": () => import("./type_widgets/Render"), - "canvas": () => import("./type_widgets/Canvas") + "canvas": () => import("./type_widgets/Canvas"), + "relationMap": () => import("./type_widgets/RelationMap") // TODO: finalize the record. }; diff --git a/apps/client/src/widgets/type_widgets/RelationMap.tsx b/apps/client/src/widgets/type_widgets/RelationMap.tsx new file mode 100644 index 000000000..c77ad6461 --- /dev/null +++ b/apps/client/src/widgets/type_widgets/RelationMap.tsx @@ -0,0 +1,106 @@ +import { useEffect, useRef, useState } from "preact/hooks"; +import { TypeWidgetProps } from "./type_widget"; +import { Defaults, jsPlumb, OverlaySpec } from "jsplumb"; +import { useNoteBlob } from "../react/hooks"; +import FNote from "../../entities/fnote"; + +interface MapData { + notes: { + noteId: string; + x: number; + y: number; + }[]; + transform: { + x: number, + y: number, + scale: number + } +} + +const uniDirectionalOverlays: OverlaySpec[] = [ + [ + "Arrow", + { + location: 1, + id: "arrow", + length: 14, + foldback: 0.8 + } + ], + ["Label", { label: "", id: "label", cssClass: "connection-label" }] +]; + +export default function RelationMap({ note }: TypeWidgetProps) { + const data = useData(note); + console.log("Got data", data); + + return ( +
+
+ +
+
+ ) +} + +function useData(note: FNote) { + const blob = useNoteBlob(note); + let content: MapData | null = null; + + if (blob?.content) { + try { + content = JSON.parse(blob.content); + } catch (e) { + console.log("Could not parse content: ", e); + } + } + + if (!content) { + content = { + notes: [], + // it is important to have this exact value here so that initial transform is the same as this + // which will guarantee note won't be saved on first conversion to the relation map note type + // this keeps the principle that note type change doesn't destroy note content unless user + // does some actual change + transform: { + x: 0, + y: 0, + scale: 1 + } + }; + } + + return content; +} + +function JsPlumb({ className, props }: { + className?: string; + props: Omit; +}) { + const containerRef = useRef(null); + + useEffect(() => { + if (!containerRef.current) return; + + const jsPlumbInstance = jsPlumb.getInstance({ + Container: containerRef.current, + ...props + }); + + return () => jsPlumbInstance.cleanupListeners(); + }, []); + + return ( +
+ +
+ ) +} diff --git a/apps/client/src/widgets/type_widgets_old/relation_map.ts b/apps/client/src/widgets/type_widgets_old/relation_map.ts index b69c7a94e..9b37f2773 100644 --- a/apps/client/src/widgets/type_widgets_old/relation_map.ts +++ b/apps/client/src/widgets/type_widgets_old/relation_map.ts @@ -30,19 +30,6 @@ declare module "jsplumb" { } } -const uniDirectionalOverlays: OverlaySpec[] = [ - [ - "Arrow", - { - location: 1, - id: "arrow", - length: 14, - foldback: 0.8 - } - ], - ["Label", { label: "", id: "label", cssClass: "connection-label" }] -]; - const biDirectionalOverlays = [ [ "Arrow", @@ -102,13 +89,6 @@ const linkOverlays = [ ] ]; -const TPL = /*html*/` -
-
-
-
-
`; - let containerCounter = 1; interface Clipboard { @@ -116,19 +96,6 @@ interface Clipboard { title: string; } -interface MapData { - notes: { - noteId: string; - x: number; - y: number; - }[]; - transform: { - x: number, - y: number, - scale: number - } -} - export type RelationType = "uniDirectional" | "biDirectional" | "inverse"; interface Relation { @@ -280,31 +247,6 @@ export default class RelationMapTypeWidget extends TypeWidget { } } - async loadMapData() { - this.mapData = { - notes: [], - // it is important to have this exact value here so that initial transform is the same as this - // which will guarantee note won't be saved on first conversion to the relation map note type - // this keeps the principle that note type change doesn't destroy note content unless user - // does some actual change - transform: { - x: 0, - y: 0, - scale: 1 - } - }; - - const blob = await this.note?.getBlob(); - - if (blob?.content) { - try { - this.mapData = JSON.parse(blob.content); - } catch (e) { - console.log("Could not parse content: ", e); - } - } - } - noteIdToId(noteId: string) { return `rel-map-note-${noteId}`; } @@ -476,15 +418,6 @@ export default class RelationMapTypeWidget extends TypeWidget { return; } - const jsPlumb = (await import("jsplumb")).default.jsPlumb; - this.jsPlumbInstance = jsPlumb.getInstance({ - Endpoint: ["Dot", { radius: 2 }], - Connector: "StateMachine", - ConnectionOverlays: uniDirectionalOverlays, - HoverPaintStyle: { stroke: "#777", strokeWidth: 1 }, - Container: this.$relationMapContainer.attr("id") - }); - if (!this.jsPlumbInstance) { return; }