link map WIP

This commit is contained in:
zadam 2019-06-04 22:57:10 +02:00
parent 87b16f3325
commit 4b96ada781
3 changed files with 54 additions and 12 deletions

View File

@ -1,6 +1,7 @@
import server from '../services/server.js'; import server from '../services/server.js';
import noteDetailService from "../services/note_detail.js"; import noteDetailService from "../services/note_detail.js";
import libraryLoader from "../services/library_loader.js"; import libraryLoader from "../services/library_loader.js";
import treeCache from "../services/tree_cache.js";
const $linkMapContainer = $("#link-map-container"); 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))); 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(); const graph = new Springy.Graph();
graph.addNodes(...noteIds); 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( const layout = new Springy.Layout.ForceDirected(
graph, graph,
@ -95,10 +99,38 @@ async function loadNotesAndRelations() {
0.5 // Damping 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 = $("<div>")
.addClass("note-box")
.prop("id", noteIdToId(node.id))
.append($("<span>").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() { function initJsPlumbInstance() {
@ -113,23 +145,27 @@ function initJsPlumbInstance() {
return; return;
} }
this.jsPlumbInstance = jsPlumb.getInstance({ jsPlumbInstance = jsPlumb.getInstance({
Endpoint: ["Dot", {radius: 2}], Endpoint: ["Dot", {radius: 2}],
Connector: "StateMachine", Connector: "StateMachine",
ConnectionOverlays: uniDirectionalOverlays, ConnectionOverlays: uniDirectionalOverlays,
HoverPaintStyle: { stroke: "#777", strokeWidth: 1 }, 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 { export default {

View File

@ -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.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 { .note-tab-row:not(.note-tab-row-is-sorting) .note-tab.note-tab-was-just-dragged {
transition: transform 120ms ease-in-out; transition: transform 120ms ease-in-out;
}
#link-map-container {
position: relative;
height: 700px;
outline: none; /* remove dotted outline on click */
} }

View File

@ -14,7 +14,7 @@ async function getLinks(noteIds) {
WHERE (noteId IN (???) OR value IN (???)) WHERE (noteId IN (???) OR value IN (???))
AND type = 'relation' AND type = 'relation'
AND isDeleted = 0 AND isDeleted = 0
`, noteIds); `, Array.from(noteIds));
} }
async function getLinkMap(req) { async function getLinkMap(req) {
@ -27,7 +27,7 @@ async function getLinkMap(req) {
const newLinks = await getLinks(noteIds); const newLinks = await getLinks(noteIds);
const newNoteIds = new Set(newLinks.map(l => l.noteId).concat(newLinks.map(l => l.targetNoteId))); 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 // no new note discovered, no need to search any further
break; break;
} }