mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 21:11:30 +08:00 
			
		
		
		
	fixes and tweaks for relation map
This commit is contained in:
		
							parent
							
								
									2a129809b3
								
							
						
					
					
						commit
						a19af8a61d
					
				| @ -2,7 +2,7 @@ import messagingService from "./messaging.js"; | |||||||
| import utils from "./utils.js"; | import utils from "./utils.js"; | ||||||
| 
 | 
 | ||||||
| function showMessage(message) { | function showMessage(message) { | ||||||
|     console.log(utils.now(), "message: ", message); |     console.debug(utils.now(), "message: ", message); | ||||||
| 
 | 
 | ||||||
|     $.notify({ |     $.notify({ | ||||||
|         // options
 |         // options
 | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| import server from "./server.js"; | import server from "./server.js"; | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
|  | import linkService from "./link.js"; | ||||||
| import libraryLoader from "./library_loader.js"; | import libraryLoader from "./library_loader.js"; | ||||||
| 
 | 
 | ||||||
| const $noteDetailRelationMap = $("#note-detail-relation-map"); | const $noteDetailRelationMap = $("#note-detail-relation-map"); | ||||||
| @ -18,7 +19,7 @@ const uniDirectionalOverlays = [ | |||||||
|         length: 14, |         length: 14, | ||||||
|         foldback: 0.8 |         foldback: 0.8 | ||||||
|     } ], |     } ], | ||||||
|     [ "Label", { label: "", id: "label", cssClass: "aLabel" }] |     [ "Label", { label: "", id: "label", cssClass: "connection-label" }] | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| const biDirectionalOverlays = [ | const biDirectionalOverlays = [ | ||||||
| @ -28,7 +29,7 @@ const biDirectionalOverlays = [ | |||||||
|         length: 14, |         length: 14, | ||||||
|         foldback: 0.8 |         foldback: 0.8 | ||||||
|     } ], |     } ], | ||||||
|     [ "Label", { label: "", id: "label", cssClass: "aLabel" }], |     [ "Label", { label: "", id: "label", cssClass: "connection-label" }], | ||||||
|     [ "Arrow", { |     [ "Arrow", { | ||||||
|         location: 0, |         location: 0, | ||||||
|         id: "arrow2", |         id: "arrow2", | ||||||
| @ -86,7 +87,7 @@ async function loadNotesAndRelations() { | |||||||
| 
 | 
 | ||||||
|     mapData.notes = mapData.notes.filter(note => note.id in data.noteTitles); |     mapData.notes = mapData.notes.filter(note => note.id in data.noteTitles); | ||||||
| 
 | 
 | ||||||
|     instance.batch(function () { |     instance.batch(async function () { | ||||||
|         const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0); |         const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0); | ||||||
|         let curX = 100; |         let curX = 100; | ||||||
|         let curY = maxY + 200; |         let curY = maxY + 200; | ||||||
| @ -95,9 +96,9 @@ async function loadNotesAndRelations() { | |||||||
|             const title = data.noteTitles[note.id]; |             const title = data.noteTitles[note.id]; | ||||||
| 
 | 
 | ||||||
|             if (note.x && note.y) { |             if (note.x && note.y) { | ||||||
|                 newNode(note.id, title, note.x, note.y); |                 await newNode(note.id, title, note.x, note.y); | ||||||
|             } else { |             } else { | ||||||
|                 newNode(note.id, title, curX, curY); |                 await newNode(note.id, title, curX, curY); | ||||||
| 
 | 
 | ||||||
|                 if (curX > 1000) { |                 if (curX > 1000) { | ||||||
|                     curX = 100; |                     curX = 100; | ||||||
| @ -159,46 +160,11 @@ async function initJsPlumb () { | |||||||
|         Container: "relation-map-canvas" |         Container: "relation-map-canvas" | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays }); |     instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays }); | ||||||
| 
 | 
 | ||||||
|     instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays }); |     instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays }); | ||||||
| 
 | 
 | ||||||
|     instance.bind("connection", async function (info, originalEvent) { |     instance.bind("connection", connectionCreatedHandler); | ||||||
|         // if there's no event, then this has been triggered programatically
 |  | ||||||
|         if (!originalEvent) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const name = prompt("Specify new relation name:"); |  | ||||||
| 
 |  | ||||||
|         if (!name || !name.trim()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const connection = info.connection; |  | ||||||
| 
 |  | ||||||
|         const targetNoteId = connection.target.id; |  | ||||||
|         const sourceNoteId = connection.source.id; |  | ||||||
| 
 |  | ||||||
|         const existing = relations.some(rel => |  | ||||||
|             rel.targetNoteId === targetNoteId |  | ||||||
|             && rel.sourceNoteId === sourceNoteId |  | ||||||
|             && rel.name === name); |  | ||||||
| 
 |  | ||||||
|         if (existing) { |  | ||||||
|             alert("Connection '" + name + "' between these notes already exists."); |  | ||||||
| 
 |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         await server.put(`notes/${sourceNoteId}/relations/${name}/to/${targetNoteId}`); |  | ||||||
| 
 |  | ||||||
|         relations.push({ targetNoteId, sourceNoteId, name }); |  | ||||||
| 
 |  | ||||||
|         connection.setType("uniDirectional"); |  | ||||||
|         connection.getOverlay("label").setLabel(name); |  | ||||||
|     }); |  | ||||||
| 
 | 
 | ||||||
|     $relationMapCanvas.contextmenu({ |     $relationMapCanvas.contextmenu({ | ||||||
|         delegate: ".note-box", |         delegate: ".note-box", | ||||||
| @ -212,7 +178,7 @@ async function initJsPlumb () { | |||||||
|     $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {}); |     $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {}); | ||||||
| 
 | 
 | ||||||
|     $relationMapCanvas.contextmenuRelation({ |     $relationMapCanvas.contextmenuRelation({ | ||||||
|         delegate: ".aLabel,.jtk-connector", |         delegate: ".connection-label,.jtk-connector", | ||||||
|         autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call
 |         autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call
 | ||||||
|         menu: [ |         menu: [ | ||||||
|             {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"}, |             {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"}, | ||||||
| @ -230,13 +196,53 @@ async function initJsPlumb () { | |||||||
|     await loadNotesAndRelations(); |     await loadNotesAndRelations(); | ||||||
| 
 | 
 | ||||||
|     // so that canvas is not panned when clicking/dragging note box
 |     // so that canvas is not panned when clicking/dragging note box
 | ||||||
|     $relationMapCanvas.on('mousedown touchstart', '.note-box, .aLabel', e => e.stopPropagation()); |     $relationMapCanvas.on('mousedown touchstart', '.note-box, .connection-label', e => e.stopPropagation()); | ||||||
| 
 | 
 | ||||||
|     jsPlumb.fire("jsPlumbDemoLoaded", instance); |     jsPlumb.fire("jsPlumbDemoLoaded", instance); | ||||||
| 
 | 
 | ||||||
|     initPanZoom(); |     initPanZoom(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | async function connectionCreatedHandler(info, originalEvent) { | ||||||
|  |     // if there's no event, then this has been triggered programatically
 | ||||||
|  |     if (!originalEvent) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const name = prompt("Specify new relation name:"); | ||||||
|  | 
 | ||||||
|  |     if (!name || !name.trim()) { | ||||||
|  |         instance.deleteConnection(connection); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const connection = info.connection; | ||||||
|  | 
 | ||||||
|  |     const targetNoteId = connection.target.id; | ||||||
|  |     const sourceNoteId = connection.source.id; | ||||||
|  | 
 | ||||||
|  |     const existing = relations.some(rel => | ||||||
|  |         rel.targetNoteId === targetNoteId | ||||||
|  |         && rel.sourceNoteId === sourceNoteId | ||||||
|  |         && rel.name === name); | ||||||
|  | 
 | ||||||
|  |     if (existing) { | ||||||
|  |         alert("Connection '" + name + "' between these notes already exists."); | ||||||
|  | 
 | ||||||
|  |         instance.deleteConnection(connection); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await server.put(`notes/${sourceNoteId}/relations/${name}/to/${targetNoteId}`); | ||||||
|  | 
 | ||||||
|  |     relations.push({ targetNoteId, sourceNoteId, name }); | ||||||
|  | 
 | ||||||
|  |     connection.setType("uniDirectional"); | ||||||
|  |     connection.getOverlay("label").setLabel(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| function relationContextMenuHandler(event, ui) { | function relationContextMenuHandler(event, ui) { | ||||||
|     const {connection} = ui.extraData; |     const {connection} = ui.extraData; | ||||||
| 
 | 
 | ||||||
| @ -347,12 +353,12 @@ function initNode(el) { | |||||||
|     instance.fire("jsPlumbDemoNodeAdded", el); |     instance.fire("jsPlumbDemoNodeAdded", el); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function newNode(id, title, x, y) { | async function newNode(id, title, x, y) { | ||||||
|     const $noteBox = $("<div>") |     const $noteBox = $("<div>") | ||||||
|         .addClass("note-box") |         .addClass("note-box") | ||||||
|         .prop("id", id) |         .prop("id", id) | ||||||
|         .append($("<div>").addClass("handle")) |         .append($("<div>").addClass("handle")) | ||||||
|         .append($("<span>").addClass("title").text(title)) |         .append($("<span>").addClass("title").html(await linkService.createNoteLink(id, title))) | ||||||
|         .append($("<div>").addClass("endpoint")) |         .append($("<div>").addClass("endpoint")) | ||||||
|         .css("left", x + "px") |         .css("left", x + "px") | ||||||
|         .css("top", y + "px"); |         .css("top", y + "px"); | ||||||
| @ -379,7 +385,7 @@ $addChildNotesButton.click(async () => { | |||||||
| 
 | 
 | ||||||
|         mapData.notes.push(note); |         mapData.notes.push(note); | ||||||
| 
 | 
 | ||||||
|         newNode(note.id, note.title, curX, curY); |         await newNode(note.id, note.title, curX, curY); | ||||||
| 
 | 
 | ||||||
|         if (curX > 1000) { |         if (curX > 1000) { | ||||||
|             curX = 100; |             curX = 100; | ||||||
|  | |||||||
| @ -3,6 +3,11 @@ | |||||||
|     overflow: hidden; |     overflow: hidden; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* this is removing dotted border around focused/active relation map */ | ||||||
|  | #note-detail-relation-map, #note-detail-relation-map:active, #note-detail-relation-map:focus { | ||||||
|  |     outline: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #relation-map-canvas { | #relation-map-canvas { | ||||||
|     position: absolute; /* needs to be absolute otherwise connections will be misplaced */ |     position: absolute; /* needs to be absolute otherwise connections will be misplaced */ | ||||||
| } | } | ||||||
| @ -31,16 +36,21 @@ | |||||||
|     color: white; |     color: white; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .aLabel { | .note-box .title { | ||||||
|  |     font-size: larger; | ||||||
|  |     font-weight: 600; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .connection-label { | ||||||
|     transition: background-color 0.25s ease-in; |     transition: background-color 0.25s ease-in; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .aLabel.jtk-hover, .jtk-source-hover, .jtk-target-hover { | .connection-label.jtk-hover, .jtk-source-hover, .jtk-target-hover { | ||||||
|     background-color: #1e8151; |     background-color: #1e8151; | ||||||
|     color: white; |     color: white; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .aLabel { | .connection-label { | ||||||
|     background-color: white; |     background-color: white; | ||||||
|     opacity: 0.8; |     opacity: 0.8; | ||||||
|     padding: 0.3em; |     padding: 0.3em; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 azivner
						azivner