mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	basic refactoring of relation map code
This commit is contained in:
		| @@ -10,27 +10,6 @@ let mapData; | ||||
| let instance; | ||||
| let initDone = false; | ||||
|  | ||||
| async function show() { | ||||
|     $noteDetailRelationMap.show(); | ||||
|  | ||||
|     await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP); | ||||
|  | ||||
|     const currentNote = noteDetailService.getCurrentNote(); | ||||
|     mapData = { | ||||
|         notes: [], | ||||
|         relations: [] | ||||
|     }; | ||||
|  | ||||
|     if (currentNote.content) { | ||||
|         try { | ||||
|             mapData = JSON.parse(currentNote.content); | ||||
|         } | ||||
|         catch (e) { | ||||
|             console.log("Could not parse content: ", e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     jsPlumb.ready(async function () { | ||||
| const uniDirectionalOverlays = [ | ||||
|     [ "Arrow", { | ||||
|         location: 1, | ||||
| @@ -58,6 +37,122 @@ async function show() { | ||||
|     } ] | ||||
| ]; | ||||
|  | ||||
| function loadMapData() { | ||||
|     const currentNote = noteDetailService.getCurrentNote(); | ||||
|     mapData = { | ||||
|         notes: [], | ||||
|         relations: [] | ||||
|     }; | ||||
|  | ||||
|     if (currentNote.content) { | ||||
|         try { | ||||
|             mapData = JSON.parse(currentNote.content); | ||||
|         } catch (e) { | ||||
|             console.log("Could not parse content: ", e); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| async function show() { | ||||
|     $noteDetailRelationMap.show(); | ||||
|  | ||||
|     await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP); | ||||
|  | ||||
|     loadMapData(); | ||||
|  | ||||
|     jsPlumb.ready(initJsPlumb); | ||||
| } | ||||
|  | ||||
| async function loadNotesAndRelations() { | ||||
|     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; | ||||
|             } | ||||
|  | ||||
|             const connection = instance.connect({ | ||||
|                 id: `${relation.sourceNoteId}${relation.targetNoteId}`, | ||||
|                 source: relation.sourceNoteId, | ||||
|                 target: relation.targetNoteId, | ||||
|                 type: relation.type | ||||
|             }); | ||||
|  | ||||
|             relation.connectionId = connection.id; | ||||
|  | ||||
|             connection.getOverlay("label").setLabel(relation.name); | ||||
|             connection.canvas.setAttribute("data-connection-id", connection.id); | ||||
|         } | ||||
|  | ||||
|         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", | ||||
| @@ -100,7 +195,63 @@ async function show() { | ||||
|             {title: "Remove note", cmd: "remove", uiIcon: "ui-icon-trash"}, | ||||
|             {title: "Edit title", cmd: "edit-title", uiIcon: "ui-icon-pencil"}, | ||||
|         ], | ||||
|             select: function(event, ui) { | ||||
|         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"); | ||||
|  | ||||
| @@ -131,138 +282,6 @@ async function show() { | ||||
|         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; | ||||
|                 } | ||||
|  | ||||
|                 const connection = instance.connect({ id: `${relation.sourceNoteId}${relation.targetNoteId}`, source: relation.sourceNoteId, target: relation.targetNoteId, type: relation.type }); | ||||
|  | ||||
|                 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); | ||||
|         } | ||||
|  | ||||
|         $relationMapCanvas[0].addEventListener('zoom', function(e) { | ||||
|             mapData.transform = pz.getTransform(); | ||||
|             saveData(); | ||||
|         }); | ||||
|  | ||||
|         $relationMapCanvas[0].addEventListener('panend', function(e) { | ||||
|             mapData.transform = pz.getTransform(); | ||||
|             saveData(); | ||||
|         }, true); | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function saveData() { | ||||
|     noteDetailService.noteChanged(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user