configuration of displayed link types + max number of links

This commit is contained in:
zadam 2019-06-10 14:33:59 +02:00
parent ccbb2e2e12
commit 8ab081a3fd
7 changed files with 82 additions and 19 deletions

View File

@ -506,7 +506,7 @@
Springy.requestAnimationFrame(function step() { Springy.requestAnimationFrame(function step() {
t.tick(0.03); t.tick(0.03);
if (render !== undefined) { if (!t._stop && render !== undefined) {
render(); render();
} }

View File

@ -16,14 +16,22 @@ const linkOverlays = [
} ] } ]
]; ];
const LINK_TYPES = [ "hyper", "image", "relation", "relation-map" ];
const $dialog = $("#link-map-dialog"); const $dialog = $("#link-map-dialog");
const $maxNotesInput = $("#link-map-max-notes");
let jsPlumbInstance = null; let jsPlumbInstance = null;
let pzInstance = null; let pzInstance = null;
let renderer = null;
async function showDialog() { async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
// set default settings
$maxNotesInput.val(50);
LINK_TYPES.forEach(lt => $("#link-map-" + lt).attr("checked", "checked"));
await libraryLoader.requireLibrary(libraryLoader.LINK_MAP); await libraryLoader.requireLibrary(libraryLoader.LINK_MAP);
jsPlumb.ready(() => { jsPlumb.ready(() => {
@ -38,12 +46,26 @@ async function showDialog() {
} }
async function loadNotesAndRelations() { async function loadNotesAndRelations() {
cleanup();
const linkTypes = LINK_TYPES.filter(lt => $(`#link-map-${lt}:checked`).length > 0);
const maxNotes = parseInt($maxNotesInput.val());
console.log(linkTypes);
const activeNoteId = noteDetailService.getActiveNoteId(); const activeNoteId = noteDetailService.getActiveNoteId();
const links = await server.get(`notes/${activeNoteId}/link-map`); const links = await server.post(`notes/${activeNoteId}/link-map`, {
linkTypes,
maxNotes
});
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)));
if (noteIds.size === 0) {
noteIds.add(activeNoteId);
}
// preload all notes // preload all notes
const notes = await treeCache.getNotes(Array.from(noteIds)); const notes = await treeCache.getNotes(Array.from(noteIds));
@ -94,7 +116,7 @@ async function loadNotesAndRelations() {
return $noteBox; return $noteBox;
} }
const renderer = new Springy.Renderer( renderer = new Springy.Renderer(
layout, layout,
() => {}, () => {},
(edge, p1, p2) => { (edge, p1, p2) => {
@ -150,6 +172,10 @@ function initPanZoom() {
} }
function cleanup() { function cleanup() {
if (renderer) {
renderer.stop();
}
// delete all endpoints and connections // delete all endpoints and connections
// this is done at this point (after async operations) to reduce flicker to the minimum // this is done at this point (after async operations) to reduce flicker to the minimum
jsPlumbInstance.deleteEveryEndpoint(); jsPlumbInstance.deleteEveryEndpoint();
@ -183,6 +209,10 @@ function noteIdToId(noteId) {
return "link-map-note-" + noteId; return "link-map-note-" + noteId;
} }
$(".link-map-settings").change(loadNotesAndRelations);
$maxNotesInput.on("input", loadNotesAndRelations);
export default { export default {
showDialog showDialog
}; };

View File

@ -336,9 +336,3 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
.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

@ -1,5 +1,7 @@
.link-map-active-note { #link-map-container {
background-color: var(--more-accented-background-color) !important; position: relative;
height: calc(95vh - 130px);
outline: none; /* remove dotted outline on click */
} }
#link-map-container .note-box { #link-map-container .note-box {
@ -34,3 +36,7 @@
position: absolute !important; position: absolute !important;
z-index: 100; z-index: 100;
} }
.link-map-active-note {
background-color: var(--more-accented-background-color) !important;
}

View File

@ -2,8 +2,8 @@
const sql = require('../../services/sql'); const sql = require('../../services/sql');
async function getLinks(noteIds) { async function getLinks(noteIds, linkTypes) {
return await sql.getManyRows(` return (await sql.getManyRows(`
SELECT noteId, targetNoteId, type SELECT noteId, targetNoteId, type
FROM links FROM links
WHERE (noteId IN (???) OR targetNoteId IN (???)) WHERE (noteId IN (???) OR targetNoteId IN (???))
@ -14,17 +14,18 @@ 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
`, Array.from(noteIds)); `, Array.from(noteIds))).filter(l => linkTypes.includes(l.type));
} }
async function getLinkMap(req) { async function getLinkMap(req) {
const {noteId} = req.params; const {noteId} = req.params;
const {linkTypes, maxNotes} = req.body;
let noteIds = new Set([noteId]); let noteIds = new Set([noteId]);
let links = []; let links = [];
while (true) { while (true) {
const newLinks = await getLinks(noteIds); const newLinks = await getLinks(noteIds, linkTypes);
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.size === noteIds.size) { if (newNoteIds.size === noteIds.size) {
@ -32,7 +33,7 @@ async function getLinkMap(req) {
break; break;
} }
if (newNoteIds.length > 50) { if (newNoteIds.size > maxNotes) {
// to many notes to display // to many notes to display
break; break;
} }

View File

@ -155,7 +155,7 @@ function register(app) {
apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames); apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames);
apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute); apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute);
apiRoute(GET, '/api/notes/:noteId/link-map', linkMapRoute.getLinkMap); apiRoute(POST, '/api/notes/:noteId/link-map', linkMapRoute.getLinkMap);
apiRoute(GET, '/api/date-notes/date/:date', dateNotesRoute.getDateNote); apiRoute(GET, '/api/date-notes/date/:date', dateNotesRoute.getDateNote);
apiRoute(GET, '/api/date-notes/month/:month', dateNotesRoute.getMonthNote); apiRoute(GET, '/api/date-notes/month/:month', dateNotesRoute.getMonthNote);

View File

@ -1,8 +1,40 @@
<div id="link-map-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog"> <div id="link-map-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl" role="document"> <div class="modal-dialog modal-xl" style="max-width: 90%;" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">Link map</h5> <h5 class="modal-title" style="width: auto;">Link map</h5>
<div style="vertical-align: middle;">
<div class="form-check form-check-inline">
<input class="form-check-input link-map-settings" type="checkbox" id="link-map-hyper">
<label class="form-check-label" for="link-map-hyper">text links</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input link-map-settings" type="checkbox" id="link-map-image">
<label class="form-check-label" for="link-map-image">image links</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input link-map-settings" type="checkbox" id="link-map-relation">
<label class="form-check-label" for="link-map-relation">relations</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input link-map-settings" type="checkbox" id="link-map-relation-map">
<label class="form-check-label" for="link-map-relation-map">relation map links</label>
</div>
<div style="display: inline-block; position: relative; top: -3px;">
<label for="link-map-max-notes" title="Max number of displayed notes">
<strong>max notes:</strong>
</label>
<input id="link-map-max-notes" type="number" value="50" min="5" max="1000" step="10"
class="form-control form-control-sm"
style="width: 80px; display: inline-block; text-align: right;"/>
</div>
</div>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0;"> <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0;">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>