mirror of
https://github.com/zadam/trilium.git
synced 2025-11-10 23:35:50 +01:00
chore(type_widgets): start porting relation map
This commit is contained in:
@@ -35,7 +35,8 @@ const TYPE_MAPPINGS: Record<ExtendedNoteType, () => Promise<{ default: TypeWidge
|
|||||||
"readOnlyText": () => import("./type_widgets/text/ReadOnlyText"),
|
"readOnlyText": () => import("./type_widgets/text/ReadOnlyText"),
|
||||||
"editableText": () => import("./type_widgets/text/EditableText"),
|
"editableText": () => import("./type_widgets/text/EditableText"),
|
||||||
"render": () => import("./type_widgets/Render"),
|
"render": () => import("./type_widgets/Render"),
|
||||||
"canvas": () => import("./type_widgets/Canvas")
|
"canvas": () => import("./type_widgets/Canvas"),
|
||||||
|
"relationMap": () => import("./type_widgets/RelationMap")
|
||||||
// TODO: finalize the record.
|
// TODO: finalize the record.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
106
apps/client/src/widgets/type_widgets/RelationMap.tsx
Normal file
106
apps/client/src/widgets/type_widgets/RelationMap.tsx
Normal file
@@ -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 (
|
||||||
|
<div className="note-detail-relation-map note-detail-printable">
|
||||||
|
<div className="relation-map-wrapper">
|
||||||
|
<JsPlumb
|
||||||
|
className="relation-map-container"
|
||||||
|
props={{
|
||||||
|
Endpoint: ["Dot", { radius: 2 }],
|
||||||
|
Connector: "StateMachine",
|
||||||
|
ConnectionOverlays: uniDirectionalOverlays,
|
||||||
|
HoverPaintStyle: { stroke: "#777", strokeWidth: 1 },
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Defaults, "container">;
|
||||||
|
}) {
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!containerRef.current) return;
|
||||||
|
|
||||||
|
const jsPlumbInstance = jsPlumb.getInstance({
|
||||||
|
Container: containerRef.current,
|
||||||
|
...props
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => jsPlumbInstance.cleanupListeners();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={containerRef} className={className}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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 = [
|
const biDirectionalOverlays = [
|
||||||
[
|
[
|
||||||
"Arrow",
|
"Arrow",
|
||||||
@@ -102,13 +89,6 @@ const linkOverlays = [
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
const TPL = /*html*/`
|
|
||||||
<div class="note-detail-relation-map note-detail-printable">
|
|
||||||
<div class="relation-map-wrapper">
|
|
||||||
<div class="relation-map-container"></div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
let containerCounter = 1;
|
let containerCounter = 1;
|
||||||
|
|
||||||
interface Clipboard {
|
interface Clipboard {
|
||||||
@@ -116,19 +96,6 @@ interface Clipboard {
|
|||||||
title: string;
|
title: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MapData {
|
|
||||||
notes: {
|
|
||||||
noteId: string;
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}[];
|
|
||||||
transform: {
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
scale: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RelationType = "uniDirectional" | "biDirectional" | "inverse";
|
export type RelationType = "uniDirectional" | "biDirectional" | "inverse";
|
||||||
|
|
||||||
interface Relation {
|
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) {
|
noteIdToId(noteId: string) {
|
||||||
return `rel-map-note-${noteId}`;
|
return `rel-map-note-${noteId}`;
|
||||||
}
|
}
|
||||||
@@ -476,15 +418,6 @@ export default class RelationMapTypeWidget extends TypeWidget {
|
|||||||
return;
|
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) {
|
if (!this.jsPlumbInstance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user