mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 13:39:01 +01:00 
			
		
		
		
	basic refactoring of relation map code
This commit is contained in:
		
							parent
							
								
									67d47c389a
								
							
						
					
					
						commit
						07cbc385e5
					
				@ -10,11 +10,34 @@ let mapData;
 | 
			
		||||
let instance;
 | 
			
		||||
let initDone = false;
 | 
			
		||||
 | 
			
		||||
async function show() {
 | 
			
		||||
    $noteDetailRelationMap.show();
 | 
			
		||||
const uniDirectionalOverlays = [
 | 
			
		||||
    [ "Arrow", {
 | 
			
		||||
        location: 1,
 | 
			
		||||
        id: "arrow",
 | 
			
		||||
        length: 14,
 | 
			
		||||
        foldback: 0.8
 | 
			
		||||
    } ],
 | 
			
		||||
    [ "Label", { label: "", id: "label", cssClass: "aLabel" }]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
    await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP);
 | 
			
		||||
const biDirectionalOverlays = [
 | 
			
		||||
    [ "Arrow", {
 | 
			
		||||
        location: 1,
 | 
			
		||||
        id: "arrow",
 | 
			
		||||
        length: 14,
 | 
			
		||||
        foldback: 0.8
 | 
			
		||||
    } ],
 | 
			
		||||
    [ "Label", { label: "", id: "label", cssClass: "aLabel" }],
 | 
			
		||||
    [ "Arrow", {
 | 
			
		||||
        location: 0,
 | 
			
		||||
        id: "arrow2",
 | 
			
		||||
        length: 14,
 | 
			
		||||
        direction: -1,
 | 
			
		||||
        foldback: 0.8
 | 
			
		||||
    } ]
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function loadMapData() {
 | 
			
		||||
    const currentNote = noteDetailService.getCurrentNote();
 | 
			
		||||
    mapData = {
 | 
			
		||||
        notes: [],
 | 
			
		||||
@ -24,246 +47,242 @@ async function show() {
 | 
			
		||||
    if (currentNote.content) {
 | 
			
		||||
        try {
 | 
			
		||||
            mapData = JSON.parse(currentNote.content);
 | 
			
		||||
        }
 | 
			
		||||
        catch (e) {
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            console.log("Could not parse content: ", e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    jsPlumb.ready(async function () {
 | 
			
		||||
        const uniDirectionalOverlays = [
 | 
			
		||||
            [ "Arrow", {
 | 
			
		||||
                location: 1,
 | 
			
		||||
                id: "arrow",
 | 
			
		||||
                length: 14,
 | 
			
		||||
                foldback: 0.8
 | 
			
		||||
            } ],
 | 
			
		||||
            [ "Label", { label: "", id: "label", cssClass: "aLabel" }]
 | 
			
		||||
        ];
 | 
			
		||||
async function show() {
 | 
			
		||||
    $noteDetailRelationMap.show();
 | 
			
		||||
 | 
			
		||||
        const biDirectionalOverlays = [
 | 
			
		||||
            [ "Arrow", {
 | 
			
		||||
                location: 1,
 | 
			
		||||
                id: "arrow",
 | 
			
		||||
                length: 14,
 | 
			
		||||
                foldback: 0.8
 | 
			
		||||
            } ],
 | 
			
		||||
            [ "Label", { label: "", id: "label", cssClass: "aLabel" }],
 | 
			
		||||
            [ "Arrow", {
 | 
			
		||||
                location: 0,
 | 
			
		||||
                id: "arrow2",
 | 
			
		||||
                length: 14,
 | 
			
		||||
                direction: -1,
 | 
			
		||||
                foldback: 0.8
 | 
			
		||||
            } ]
 | 
			
		||||
        ];
 | 
			
		||||
    await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP);
 | 
			
		||||
 | 
			
		||||
        instance = jsPlumb.getInstance({
 | 
			
		||||
            Endpoint: ["Dot", {radius: 2}],
 | 
			
		||||
            Connector: "StateMachine",
 | 
			
		||||
            HoverPaintStyle: {stroke: "#1e8151", strokeWidth: 2 },
 | 
			
		||||
            Container: "relation-map-canvas"
 | 
			
		||||
        });
 | 
			
		||||
    loadMapData();
 | 
			
		||||
 | 
			
		||||
    jsPlumb.ready(initJsPlumb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays });
 | 
			
		||||
async function loadNotesAndRelations() {
 | 
			
		||||
    const noteIds = mapData.notes.map(note => note.id);
 | 
			
		||||
    const data = await server.post("notes/relation-map", {noteIds});
 | 
			
		||||
 | 
			
		||||
        instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays });
 | 
			
		||||
    const relations = [];
 | 
			
		||||
 | 
			
		||||
        // instance.bind("connection", function (info) {
 | 
			
		||||
        //     const connection = info.connection;
 | 
			
		||||
        //     let name = "none";
 | 
			
		||||
        //
 | 
			
		||||
        //     if (initDone) {
 | 
			
		||||
        //         name = prompt("Specify new connection label:");
 | 
			
		||||
        //
 | 
			
		||||
        //         mapData.relations.push({
 | 
			
		||||
        //             connectionId: connection.id,
 | 
			
		||||
        //             source: connection.sourceId,
 | 
			
		||||
        //             target: connection.targetId,
 | 
			
		||||
        //             name: name
 | 
			
		||||
        //         });
 | 
			
		||||
        //
 | 
			
		||||
        //         saveData();
 | 
			
		||||
        //     }
 | 
			
		||||
        //
 | 
			
		||||
        //     connection.getOverlay("label").setLabel(name);
 | 
			
		||||
        // });
 | 
			
		||||
    for (const relation of data.relations) {
 | 
			
		||||
        const match = relations.find(rel =>
 | 
			
		||||
            rel.name === relation.name
 | 
			
		||||
            && ((rel.sourceNoteId === relation.sourceNoteId && rel.targetNoteId === relation.targetNoteId)
 | 
			
		||||
            || (rel.sourceNoteId === relation.targetNoteId && rel.targetNoteId === relation.sourceNoteId)));
 | 
			
		||||
 | 
			
		||||
        jsPlumb.on($relationMapCanvas[0], "dblclick", function(e) {
 | 
			
		||||
            newNode(jsPlumbUtil.uuid(),"new", e.offsetX, e.offsetY);
 | 
			
		||||
        });
 | 
			
		||||
        if (match) {
 | 
			
		||||
            match.type = 'biDirectional';
 | 
			
		||||
        } else {
 | 
			
		||||
            relation.type = 'uniDirectional';
 | 
			
		||||
            relations.push(relation);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        $relationMapCanvas.contextmenu({
 | 
			
		||||
            delegate: ".note-box",
 | 
			
		||||
            menu: [
 | 
			
		||||
                {title: "Remove note", cmd: "remove", uiIcon: "ui-icon-trash"},
 | 
			
		||||
                {title: "Edit title", cmd: "edit-title", uiIcon: "ui-icon-pencil"},
 | 
			
		||||
            ],
 | 
			
		||||
            select: function(event, ui) {
 | 
			
		||||
                const $noteBox = ui.target.closest(".note-box");
 | 
			
		||||
                const noteId = $noteBox.prop("id");
 | 
			
		||||
    mapData.notes = mapData.notes.filter(note => note.id in data.noteTitles);
 | 
			
		||||
 | 
			
		||||
                if (ui.cmd === "remove") {
 | 
			
		||||
                    if (!confirm("Are you sure you want to remove the note?")) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
    instance.batch(function () {
 | 
			
		||||
        const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0);
 | 
			
		||||
        let curX = 100;
 | 
			
		||||
        let curY = maxY + 200;
 | 
			
		||||
 | 
			
		||||
                    instance.remove(noteId);
 | 
			
		||||
        for (const note of mapData.notes) {
 | 
			
		||||
            const title = data.noteTitles[note.id];
 | 
			
		||||
 | 
			
		||||
                    mapData.notes = mapData.notes.filter(note => note.id !== noteId);
 | 
			
		||||
                    mapData.relations = mapData.relations.filter(relation => relation.source !== noteId && relation.target !== noteId);
 | 
			
		||||
            if (note.x && note.y) {
 | 
			
		||||
                newNode(note.id, title, note.x, note.y);
 | 
			
		||||
            } else {
 | 
			
		||||
                newNode(note.id, title, curX, curY);
 | 
			
		||||
 | 
			
		||||
                    saveData();
 | 
			
		||||
                if (curX > 1000) {
 | 
			
		||||
                    curX = 100;
 | 
			
		||||
                    curY += 200;
 | 
			
		||||
                } else {
 | 
			
		||||
                    curX += 200;
 | 
			
		||||
                }
 | 
			
		||||
                else if (ui.cmd === "edit-title") {
 | 
			
		||||
                    const title = prompt("Enter new note title:");
 | 
			
		||||
 | 
			
		||||
                    if (!title) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    const note = mapData.notes.find(note => note.id === noteId);
 | 
			
		||||
                    note.title = title;
 | 
			
		||||
 | 
			
		||||
                    $noteBox.find(".title").text(note.title);
 | 
			
		||||
 | 
			
		||||
                    saveData();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {});
 | 
			
		||||
 | 
			
		||||
        $relationMapCanvas.contextmenuRelation({
 | 
			
		||||
            delegate: ".aLabel,.jtk-connector",
 | 
			
		||||
            autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call
 | 
			
		||||
            menu: [
 | 
			
		||||
                {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"},
 | 
			
		||||
                {title: "Edit relation name", cmd: "edit-name", uiIcon: "ui-icon-pencil"},
 | 
			
		||||
            ],
 | 
			
		||||
            select: function(event, ui) {
 | 
			
		||||
                const {connection} = ui.extraData;
 | 
			
		||||
 | 
			
		||||
                if (ui.cmd === 'remove') {
 | 
			
		||||
                    if (!confirm("Are you sure you want to remove the relation?")) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    instance.deleteConnection(connection);
 | 
			
		||||
 | 
			
		||||
                    mapData.relations = mapData.relations.filter(relation => relation.connectionId !== connection.id);
 | 
			
		||||
                    saveData();
 | 
			
		||||
                }
 | 
			
		||||
                else if (ui.cmd === 'edit-name') {
 | 
			
		||||
                    const relationName = prompt("Specify new relation name:");
 | 
			
		||||
 | 
			
		||||
                    connection.getOverlay("label").setLabel(relationName);
 | 
			
		||||
 | 
			
		||||
                    const relation = mapData.relations.find(relation => relation.connectionId === connection.id);
 | 
			
		||||
                    relation.name = relationName;
 | 
			
		||||
 | 
			
		||||
                    saveData();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        instance.bind("contextmenu", function (c, e) {
 | 
			
		||||
            e.preventDefault();
 | 
			
		||||
 | 
			
		||||
            $relationMapCanvas.contextmenuRelation("open", e, { connection: c });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        const noteIds = mapData.notes.map(note => note.id);
 | 
			
		||||
        const data = await server.post("notes/relation-map", { noteIds });
 | 
			
		||||
 | 
			
		||||
        const relations = [];
 | 
			
		||||
 | 
			
		||||
        for (const relation of data.relations) {
 | 
			
		||||
            const match = relations.find(rel =>
 | 
			
		||||
                rel.name === relation.name
 | 
			
		||||
                && ((rel.sourceNoteId === relation.sourceNoteId && rel.targetNoteId === relation.targetNoteId)
 | 
			
		||||
                    || (rel.sourceNoteId === relation.targetNoteId && rel.targetNoteId === relation.sourceNoteId)));
 | 
			
		||||
 | 
			
		||||
            if (match) {
 | 
			
		||||
                match.type = 'biDirectional';
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                relation.type = 'uniDirectional';
 | 
			
		||||
                relations.push(relation);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        mapData.notes = mapData.notes.filter(note => note.id in data.noteTitles);
 | 
			
		||||
 | 
			
		||||
        instance.batch(function () {
 | 
			
		||||
            const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0);
 | 
			
		||||
            let curX = 100;
 | 
			
		||||
            let curY = maxY + 200;
 | 
			
		||||
 | 
			
		||||
            for (const note of mapData.notes) {
 | 
			
		||||
                const title = data.noteTitles[note.id];
 | 
			
		||||
 | 
			
		||||
                if (note.x && note.y) {
 | 
			
		||||
                    newNode(note.id, title, note.x, note.y);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    newNode(note.id, title, curX, curY);
 | 
			
		||||
 | 
			
		||||
                    if (curX > 1000) {
 | 
			
		||||
                        curX = 100;
 | 
			
		||||
                        curY += 200;
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        curX += 200;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
        for (const relation of relations) {
 | 
			
		||||
            if (relation.name === 'isChildOf') {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (const relation of relations) {
 | 
			
		||||
                if (relation.name === 'isChildOf') {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
            const connection = instance.connect({
 | 
			
		||||
                id: `${relation.sourceNoteId}${relation.targetNoteId}`,
 | 
			
		||||
                source: relation.sourceNoteId,
 | 
			
		||||
                target: relation.targetNoteId,
 | 
			
		||||
                type: relation.type
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
                const connection = instance.connect({ id: `${relation.sourceNoteId}${relation.targetNoteId}`, source: relation.sourceNoteId, target: relation.targetNoteId, type: relation.type });
 | 
			
		||||
            relation.connectionId = connection.id;
 | 
			
		||||
 | 
			
		||||
                relation.connectionId = connection.id;
 | 
			
		||||
 | 
			
		||||
                connection.getOverlay("label").setLabel(relation.name);
 | 
			
		||||
                connection.canvas.setAttribute("data-connection-id", connection.id);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            initDone = true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // so that canvas is not panned when clicking/dragging note box
 | 
			
		||||
        $relationMapCanvas.on('mousedown touchstart', '.note-box, .aLabel', e => e.stopPropagation());
 | 
			
		||||
 | 
			
		||||
        jsPlumb.fire("jsPlumbDemoLoaded", instance);
 | 
			
		||||
 | 
			
		||||
        const pz = panzoom($relationMapCanvas[0], {
 | 
			
		||||
            maxZoom: 2,
 | 
			
		||||
            minZoom: 0.1,
 | 
			
		||||
            smoothScroll: false
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (mapData.transform) {
 | 
			
		||||
            pz.moveTo(mapData.transform.x, mapData.transform.y);
 | 
			
		||||
            pz.zoomTo(0, 0, mapData.transform.scale);
 | 
			
		||||
            connection.getOverlay("label").setLabel(relation.name);
 | 
			
		||||
            connection.canvas.setAttribute("data-connection-id", connection.id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $relationMapCanvas[0].addEventListener('zoom', function(e) {
 | 
			
		||||
            mapData.transform = pz.getTransform();
 | 
			
		||||
            saveData();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        $relationMapCanvas[0].addEventListener('panend', function(e) {
 | 
			
		||||
            mapData.transform = pz.getTransform();
 | 
			
		||||
            saveData();
 | 
			
		||||
        }, true);
 | 
			
		||||
        initDone = true;
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function initPanZoom() {
 | 
			
		||||
    const pz = panzoom($relationMapCanvas[0], {
 | 
			
		||||
        maxZoom: 2,
 | 
			
		||||
        minZoom: 0.1,
 | 
			
		||||
        smoothScroll: false
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (mapData.transform) {
 | 
			
		||||
        pz.moveTo(mapData.transform.x, mapData.transform.y);
 | 
			
		||||
        pz.zoomTo(0, 0, mapData.transform.scale);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $relationMapCanvas[0].addEventListener('zoom', function (e) {
 | 
			
		||||
        mapData.transform = pz.getTransform();
 | 
			
		||||
        saveData();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $relationMapCanvas[0].addEventListener('panend', function (e) {
 | 
			
		||||
        mapData.transform = pz.getTransform();
 | 
			
		||||
        saveData();
 | 
			
		||||
    }, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function initJsPlumb () {
 | 
			
		||||
    instance = jsPlumb.getInstance({
 | 
			
		||||
        Endpoint: ["Dot", {radius: 2}],
 | 
			
		||||
        Connector: "StateMachine",
 | 
			
		||||
        HoverPaintStyle: {stroke: "#1e8151", strokeWidth: 2 },
 | 
			
		||||
        Container: "relation-map-canvas"
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays });
 | 
			
		||||
 | 
			
		||||
    instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays });
 | 
			
		||||
 | 
			
		||||
    // instance.bind("connection", function (info) {
 | 
			
		||||
    //     const connection = info.connection;
 | 
			
		||||
    //     let name = "none";
 | 
			
		||||
    //
 | 
			
		||||
    //     if (initDone) {
 | 
			
		||||
    //         name = prompt("Specify new connection label:");
 | 
			
		||||
    //
 | 
			
		||||
    //         mapData.relations.push({
 | 
			
		||||
    //             connectionId: connection.id,
 | 
			
		||||
    //             source: connection.sourceId,
 | 
			
		||||
    //             target: connection.targetId,
 | 
			
		||||
    //             name: name
 | 
			
		||||
    //         });
 | 
			
		||||
    //
 | 
			
		||||
    //         saveData();
 | 
			
		||||
    //     }
 | 
			
		||||
    //
 | 
			
		||||
    //     connection.getOverlay("label").setLabel(name);
 | 
			
		||||
    // });
 | 
			
		||||
 | 
			
		||||
    jsPlumb.on($relationMapCanvas[0], "dblclick", function(e) {
 | 
			
		||||
        newNode(jsPlumbUtil.uuid(),"new", e.offsetX, e.offsetY);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $relationMapCanvas.contextmenu({
 | 
			
		||||
        delegate: ".note-box",
 | 
			
		||||
        menu: [
 | 
			
		||||
            {title: "Remove note", cmd: "remove", uiIcon: "ui-icon-trash"},
 | 
			
		||||
            {title: "Edit title", cmd: "edit-title", uiIcon: "ui-icon-pencil"},
 | 
			
		||||
        ],
 | 
			
		||||
        select: noteContextMenuHandler
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {});
 | 
			
		||||
 | 
			
		||||
    $relationMapCanvas.contextmenuRelation({
 | 
			
		||||
        delegate: ".aLabel,.jtk-connector",
 | 
			
		||||
        autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call
 | 
			
		||||
        menu: [
 | 
			
		||||
            {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"},
 | 
			
		||||
            {title: "Edit relation name", cmd: "edit-name", uiIcon: "ui-icon-pencil"},
 | 
			
		||||
        ],
 | 
			
		||||
        select: relationContextMenuHandler
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    instance.bind("contextmenu", function (c, e) {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
 | 
			
		||||
        $relationMapCanvas.contextmenuRelation("open", e, { connection: c });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    await loadNotesAndRelations();
 | 
			
		||||
 | 
			
		||||
    // so that canvas is not panned when clicking/dragging note box
 | 
			
		||||
    $relationMapCanvas.on('mousedown touchstart', '.note-box, .aLabel', e => e.stopPropagation());
 | 
			
		||||
 | 
			
		||||
    jsPlumb.fire("jsPlumbDemoLoaded", instance);
 | 
			
		||||
 | 
			
		||||
    initPanZoom();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function relationContextMenuHandler(event, ui) {
 | 
			
		||||
    const {connection} = ui.extraData;
 | 
			
		||||
 | 
			
		||||
    if (ui.cmd === 'remove') {
 | 
			
		||||
        if (!confirm("Are you sure you want to remove the relation?")) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        instance.deleteConnection(connection);
 | 
			
		||||
 | 
			
		||||
        mapData.relations = mapData.relations.filter(relation => relation.connectionId !== connection.id);
 | 
			
		||||
        saveData();
 | 
			
		||||
    }
 | 
			
		||||
    else if (ui.cmd === 'edit-name') {
 | 
			
		||||
        const relationName = prompt("Specify new relation name:");
 | 
			
		||||
 | 
			
		||||
        connection.getOverlay("label").setLabel(relationName);
 | 
			
		||||
 | 
			
		||||
        const relation = mapData.relations.find(relation => relation.connectionId === connection.id);
 | 
			
		||||
        relation.name = relationName;
 | 
			
		||||
 | 
			
		||||
        saveData();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function noteContextMenuHandler(event, ui) {
 | 
			
		||||
    const $noteBox = ui.target.closest(".note-box");
 | 
			
		||||
    const noteId = $noteBox.prop("id");
 | 
			
		||||
 | 
			
		||||
    if (ui.cmd === "remove") {
 | 
			
		||||
        if (!confirm("Are you sure you want to remove the note?")) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        instance.remove(noteId);
 | 
			
		||||
 | 
			
		||||
        mapData.notes = mapData.notes.filter(note => note.id !== noteId);
 | 
			
		||||
        mapData.relations = mapData.relations.filter(relation => relation.source !== noteId && relation.target !== noteId);
 | 
			
		||||
 | 
			
		||||
        saveData();
 | 
			
		||||
    }
 | 
			
		||||
    else if (ui.cmd === "edit-title") {
 | 
			
		||||
        const title = prompt("Enter new note title:");
 | 
			
		||||
 | 
			
		||||
        if (!title) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const note = mapData.notes.find(note => note.id === noteId);
 | 
			
		||||
        note.title = title;
 | 
			
		||||
 | 
			
		||||
        $noteBox.find(".title").text(note.title);
 | 
			
		||||
 | 
			
		||||
        saveData();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function saveData() {
 | 
			
		||||
    noteDetailService.noteChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user