chore(react/type_widgets): finalize porting relation map

This commit is contained in:
Elian Doran 2025-10-04 10:32:23 +03:00
parent 67d9154795
commit 9cceff4f02
No known key found for this signature in database
2 changed files with 18 additions and 125 deletions

View File

@ -11,7 +11,7 @@ import dialog from "../../../services/dialog";
import server from "../../../services/server";
import toast from "../../../services/toast";
import { CreateChildrenResponse, RelationMapPostResponse, RelationMapRelation } from "@triliumnext/commons";
import RelationMapApi, { ClientRelation, MapData, MapDataNoteEntry } from "./api";
import RelationMapApi, { ClientRelation, MapData, MapDataNoteEntry, RelationType } from "./api";
import setupOverlays, { uniDirectionalOverlays } from "./overlays";
import { JsPlumb } from "./jsplumb";
import { getMousePosition, getZoom, idToNoteId, noteIdToId } from "./utils";
@ -26,6 +26,23 @@ interface Clipboard {
title: string;
}
declare module "jsplumb" {
interface Connection {
canvas: HTMLCanvasElement;
getType(): string;
bind(event: string, callback: (obj: unknown, event: MouseEvent) => void): void;
}
interface Overlay {
setLabel(label: string): void;
}
interface ConnectParams {
type: RelationType;
}
}
export default function RelationMap({ note, ntxId }: TypeWidgetProps) {
const [ data, setData ] = useState<MapData>();
const containerRef = useRef<HTMLDivElement>(null);

View File

@ -1,124 +0,0 @@
import server from "../../services/server.js";
import linkService from "../../services/link.js";
import contextMenu from "../../menus/context_menu.js";
import toastService from "../../services/toast.js";
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
import TypeWidget from "./type_widget.js";
import appContext, { type EventData } from "../../components/app_context.js";
import utils from "../../services/utils.js";
import froca from "../../services/froca.js";
import dialogService from "../../services/dialog.js";
import { t } from "../../services/i18n.js";
import type FNote from "../../entities/fnote.js";
import type { ConnectionMadeEventInfo, jsPlumbInstance, OverlaySpec } from "jsplumb";
declare module "jsplumb" {
interface Connection {
canvas: HTMLCanvasElement;
getType(): string;
bind(event: string, callback: (obj: unknown, event: MouseEvent) => void): void;
}
interface Overlay {
setLabel(label: string): void;
}
interface ConnectParams {
type: RelationType;
}
}
let containerCounter = 1;
type MenuCommands = "openInNewTab" | "remove" | "editTitle";
export default class RelationMapTypeWidget extends TypeWidget {
private clipboard?: Clipboard | null;
private jsPlumbInstance?: import("jsplumb").jsPlumbInstance | null;
private pzInstance?: PanZoom | null;
private mapData?: MapData | null;
private relations?: Relation[] | null;
private $relationMapContainer!: JQuery<HTMLElement>;
private $relationMapWrapper!: JQuery<HTMLElement>;
static getType() {
return "relationMap";
}
doRender() {
this.$widget = $(TPL);
this.$relationMapContainer = this.$widget.find(".relation-map-container");
this.mapData = null;
this.jsPlumbInstance = null;
// outside of mapData because they are not persisted in the note content
this.relations = null;
this.pzInstance = null;
this.$relationMapWrapper = this.$widget.find(".relation-map-wrapper");
this.$relationMapWrapper.on("click", (event) => {
return true;
});
this.$relationMapContainer.attr("id", "relation-map-container-" + containerCounter++);
this.clipboard = null;
this.$widget.on("drop", (ev) => this.dropNoteOntoRelationMapHandler(ev));
this.initialized = new Promise(async (res) => {
// Weird typecast is needed probably due to bad typings in the module itself.
const jsPlumb = (await import("jsplumb")).default.jsPlumb as unknown as jsPlumbInstance;
jsPlumb.ready(res);
});
super.doRender();
}
async doRefresh(note: FNote) {
await this.initJsPlumbInstance();
this.loadNotesAndRelations();
}
clearMap() {
// delete all endpoints and connections
// this is done at this point (after async operations) to reduce flicker to the minimum
this.jsPlumbInstance?.deleteEveryEndpoint();
// without this, we still end up with note boxes remaining in the canvas
this.$relationMapContainer.empty();
}
cleanup() {
if (this.jsPlumbInstance) {
this.clearMap();
}
if (this.pzInstance) {
this.pzInstance.dispose();
this.pzInstance = null;
}
}
async initJsPlumbInstance() {
if (this.jsPlumbInstance) {
this.cleanup();
return;
}
if (!this.jsPlumbInstance) {
return;
}
}
saveData() {
this.spacedUpdate.scheduleUpdate();
}
}