mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
relation map WIP
This commit is contained in:
parent
b17f442d1f
commit
4a5a63d7b4
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||||
|
</project>
|
@ -30,24 +30,45 @@ async function show() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jsPlumb.ready(function () {
|
jsPlumb.ready(async function () {
|
||||||
|
const uniDirectionalConnection = [
|
||||||
|
[ "Arrow", {
|
||||||
|
location: 1,
|
||||||
|
id: "arrow",
|
||||||
|
length: 14,
|
||||||
|
foldback: 0.8
|
||||||
|
} ],
|
||||||
|
[ "Label", { label: "", id: "label", cssClass: "aLabel" }]
|
||||||
|
];
|
||||||
|
|
||||||
|
const biDirectionalConnection = [
|
||||||
|
[ "Arrow", {
|
||||||
|
location: 1,
|
||||||
|
id: "arrow",
|
||||||
|
length: 14,
|
||||||
|
foldback: 0.8
|
||||||
|
} ],
|
||||||
|
[ "Label", { label: "", id: "label", cssClass: "aLabel" }],
|
||||||
|
[ "Arrow", {
|
||||||
|
location: 0,
|
||||||
|
id: "arrow2",
|
||||||
|
length: 14,
|
||||||
|
direction: -1,
|
||||||
|
foldback: 0.8
|
||||||
|
} ]
|
||||||
|
];
|
||||||
|
|
||||||
instance = jsPlumb.getInstance({
|
instance = jsPlumb.getInstance({
|
||||||
Endpoint: ["Dot", {radius: 2}],
|
Endpoint: ["Dot", {radius: 2}],
|
||||||
Connector: "StateMachine",
|
Connector: "StateMachine",
|
||||||
HoverPaintStyle: {stroke: "#1e8151", strokeWidth: 2 },
|
HoverPaintStyle: {stroke: "#1e8151", strokeWidth: 2 },
|
||||||
ConnectionOverlays: [
|
|
||||||
[ "Arrow", {
|
|
||||||
location: 1,
|
|
||||||
id: "arrow",
|
|
||||||
length: 14,
|
|
||||||
foldback: 0.8
|
|
||||||
} ],
|
|
||||||
[ "Label", { label: "", id: "label", cssClass: "aLabel" }]
|
|
||||||
],
|
|
||||||
Container: "relation-map-canvas"
|
Container: "relation-map-canvas"
|
||||||
});
|
});
|
||||||
|
|
||||||
instance.registerConnectionType("basic", { anchor:"Continuous", connector:"StateMachine" });
|
|
||||||
|
instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalConnection });
|
||||||
|
|
||||||
|
instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalConnection });
|
||||||
|
|
||||||
// instance.bind("connection", function (info) {
|
// instance.bind("connection", function (info) {
|
||||||
// const connection = info.connection;
|
// const connection = info.connection;
|
||||||
@ -153,6 +174,9 @@ async function show() {
|
|||||||
$relationMapCanvas.contextmenuRelation("open", e, { connection: c });
|
$relationMapCanvas.contextmenuRelation("open", e, { connection: c });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const noteIds = mapData.notes.map(note => note.noteId);
|
||||||
|
const data = await server.post("notes/relation-map", { noteIds });
|
||||||
|
|
||||||
instance.batch(function () {
|
instance.batch(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;
|
||||||
@ -179,12 +203,18 @@ async function show() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const relation of mapData.relations) {
|
for (const relation of mapData.relations) {
|
||||||
const connection = instance.connect({ id: relation.id, source: relation.source, target: relation.target, type: "basic" });
|
if (relation.name === 'isChildOf') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = instance.connect({ id: relation.id, source: relation.source, target: relation.target, type: "uniDirectional" });
|
||||||
|
|
||||||
relation.connectionId = connection.id;
|
relation.connectionId = connection.id;
|
||||||
|
|
||||||
connection.getOverlay("label").setLabel(relation.name);
|
connection.getOverlay("label").setLabel(relation.name);
|
||||||
connection.canvas.setAttribute("data-connection-id", connection.id);
|
connection.canvas.setAttribute("data-connection-id", connection.id);
|
||||||
|
|
||||||
|
//instance.recalculateOffsets(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
initDone = true;
|
initDone = true;
|
||||||
@ -200,8 +230,6 @@ async function show() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function saveData() {
|
function saveData() {
|
||||||
const currentNote = noteDetailService.getCurrentNote();
|
|
||||||
|
|
||||||
noteDetailService.saveNote();
|
noteDetailService.saveNote();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,9 +324,13 @@ $addChildNotesButton.click(async () => {
|
|||||||
let curY = maxY + 200;
|
let curY = maxY + 200;
|
||||||
|
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
|
if (mapData.notes.some(note => note.id === child.noteId)) {
|
||||||
|
// note already exists
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const note = {
|
const note = {
|
||||||
id: child.noteId,
|
id: child.noteId,
|
||||||
title: child.title,
|
|
||||||
width: "auto",
|
width: "auto",
|
||||||
height: "auto"
|
height: "auto"
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#relation-map-canvas {
|
#note-detail-relation-map {
|
||||||
height: 500px;
|
height: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#relation-map-canvas {
|
||||||
|
position: absolute; /* needs to be absolute otherwise connections will be misplaced */
|
||||||
|
}
|
||||||
|
|
||||||
.note-box {
|
.note-box {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
|
@ -92,6 +92,35 @@ async function setNoteTypeMime(req) {
|
|||||||
await note.save();
|
await note.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRelationMap(req) {
|
||||||
|
const noteIds = req.body.noteIds;
|
||||||
|
const resp = {
|
||||||
|
noteTitles: {},
|
||||||
|
relations: []
|
||||||
|
};
|
||||||
|
|
||||||
|
if (noteIds.length === 0) {
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const questionMarks = noteIds.map(noteId => '?').join(',');
|
||||||
|
|
||||||
|
(await repository.getEntities(`SELECT * FROM notes WHERE noteId IN (${questionMarks})`, noteIds))
|
||||||
|
.forEach(note => resp.noteTitles[note.noteId] = note.title);
|
||||||
|
|
||||||
|
// FIXME: this actually doesn't take into account inherited relations! But maybe it is better this way?
|
||||||
|
resp.relations = (await repository.getEntities(`SELECT * FROM attributes WHERE type = 'relation' AND noteId IN (${questionMarks})`, noteIds))
|
||||||
|
.map(relation => { return {
|
||||||
|
sourceNoteId: relation.noteId,
|
||||||
|
targetNoteId: relation.value,
|
||||||
|
name: relation.name
|
||||||
|
}; })
|
||||||
|
// both sourceNoteId and targetNoteId has to be in the included notes, but source was already checked in the SQL query
|
||||||
|
.filter(relation => noteIds.includes(relation.targetNoteId));
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getNote,
|
getNote,
|
||||||
updateNote,
|
updateNote,
|
||||||
@ -99,5 +128,6 @@ module.exports = {
|
|||||||
sortNotes,
|
sortNotes,
|
||||||
protectSubtree,
|
protectSubtree,
|
||||||
setNoteTypeMime,
|
setNoteTypeMime,
|
||||||
getChildren
|
getChildren,
|
||||||
|
getRelationMap
|
||||||
};
|
};
|
@ -121,6 +121,7 @@ function register(app) {
|
|||||||
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
|
apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
|
||||||
apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime);
|
apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime);
|
||||||
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
|
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
|
||||||
|
apiRoute(POST, '/api/notes/relation-map', notesApiRoute.getRelationMap);
|
||||||
|
|
||||||
apiRoute(PUT, '/api/notes/:noteId/clone-to/:parentNoteId', cloningApiRoute.cloneNoteToParent);
|
apiRoute(PUT, '/api/notes/:noteId/clone-to/:parentNoteId', cloningApiRoute.cloneNoteToParent);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
|
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user