diff --git a/src/public/javascripts/dialogs/link_map.js b/src/public/javascripts/dialogs/link_map.js
index 24dc25013..59b44e61e 100644
--- a/src/public/javascripts/dialogs/link_map.js
+++ b/src/public/javascripts/dialogs/link_map.js
@@ -1,6 +1,7 @@
import server from '../services/server.js';
import noteDetailService from "../services/note_detail.js";
import libraryLoader from "../services/library_loader.js";
+import treeCache from "../services/tree_cache.js";
const $linkMapContainer = $("#link-map-container");
@@ -84,9 +85,12 @@ async function loadNotesAndRelations() {
const noteIds = new Set(links.map(l => l.noteId).concat(links.map(l => l.targetNoteId)));
+ // preload all notes
+ const notes = await treeCache.getNotes(Array.from(noteIds));
+
const graph = new Springy.Graph();
graph.addNodes(...noteIds);
- graph.addEdges(links.map(l => [l.noteId, l.targetNoteId]));
+ graph.addEdges(...links.map(l => [l.noteId, l.targetNoteId]));
const layout = new Springy.Layout.ForceDirected(
graph,
@@ -95,10 +99,38 @@ async function loadNotesAndRelations() {
0.5 // Damping
);
+ const renderer = new Springy.Renderer(
+ layout,
+ () => {},
+ () => {},
+ () => {},
+ () => {
+ layout.eachNode((node, point) => {
+ console.log(node, point.p);
- for (const link of links) {
+ const note = notes.find(n => n.noteId === node.id);
- }
+ const $noteBox = $("
")
+ .addClass("note-box")
+ .prop("id", noteIdToId(node.id))
+ .append($("").addClass("title").append(note.title))
+ .css("left", (300 + point.p.x * 100) + "px")
+ .css("top", (300 + point.p.y * 100) + "px");
+
+ jsPlumbInstance.getContainer().appendChild($noteBox[0]);
+ });
+
+ for (const link of links) {
+ const connection = jsPlumbInstance.connect({
+ source: noteIdToId(link.noteId),
+ target: noteIdToId(link.targetNoteId),
+ type: link.type
+ });
+ }
+ }
+ );
+
+ renderer.start();
}
function initJsPlumbInstance() {
@@ -113,23 +145,27 @@ function initJsPlumbInstance() {
return;
}
- this.jsPlumbInstance = jsPlumb.getInstance({
+ jsPlumbInstance = jsPlumb.getInstance({
Endpoint: ["Dot", {radius: 2}],
Connector: "StateMachine",
ConnectionOverlays: uniDirectionalOverlays,
HoverPaintStyle: { stroke: "#777", strokeWidth: 1 },
- Container: this.$relationMapContainer.attr("id")
+ Container: $linkMapContainer.attr("id")
});
- this.jsPlumbInstance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays });
+ jsPlumbInstance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays });
- this.jsPlumbInstance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays });
+ jsPlumbInstance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays });
- this.jsPlumbInstance.registerConnectionType("inverse", { anchor:"Continuous", connector:"StateMachine", overlays: inverseRelationsOverlays });
+ jsPlumbInstance.registerConnectionType("inverse", { anchor:"Continuous", connector:"StateMachine", overlays: inverseRelationsOverlays });
- this.jsPlumbInstance.registerConnectionType("link", { anchor:"Continuous", connector:"StateMachine", overlays: linkOverlays });
+ jsPlumbInstance.registerConnectionType("link", { anchor:"Continuous", connector:"StateMachine", overlays: linkOverlays });
- this.jsPlumbInstance.bind("connection", (info, originalEvent) => this.connectionCreatedHandler(info, originalEvent));
+ jsPlumbInstance.bind("connection", (info, originalEvent) => connectionCreatedHandler(info, originalEvent));
+}
+
+function noteIdToId(noteId) {
+ return "link-map-note-" + noteId;
}
export default {
diff --git a/src/public/stylesheets/desktop.css b/src/public/stylesheets/desktop.css
index 30beb328d..e6b1ee608 100644
--- a/src/public/stylesheets/desktop.css
+++ b/src/public/stylesheets/desktop.css
@@ -335,4 +335,10 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
.note-tab-row.note-tab-row-is-sorting .note-tab:not(.note-tab-is-dragging),
.note-tab-row:not(.note-tab-row-is-sorting) .note-tab.note-tab-was-just-dragged {
transition: transform 120ms ease-in-out;
+}
+
+#link-map-container {
+ position: relative;
+ height: 700px;
+ outline: none; /* remove dotted outline on click */
}
\ No newline at end of file
diff --git a/src/routes/api/link_map.js b/src/routes/api/link_map.js
index 66568c2da..e34bae139 100644
--- a/src/routes/api/link_map.js
+++ b/src/routes/api/link_map.js
@@ -14,7 +14,7 @@ async function getLinks(noteIds) {
WHERE (noteId IN (???) OR value IN (???))
AND type = 'relation'
AND isDeleted = 0
- `, noteIds);
+ `, Array.from(noteIds));
}
async function getLinkMap(req) {
@@ -27,7 +27,7 @@ async function getLinkMap(req) {
const newLinks = await getLinks(noteIds);
const newNoteIds = new Set(newLinks.map(l => l.noteId).concat(newLinks.map(l => l.targetNoteId)));
- if (newNoteIds.length === noteIds.length) {
+ if (newNoteIds.size === noteIds.size) {
// no new note discovered, no need to search any further
break;
}