mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	relation map WIP
This commit is contained in:
		
							
								
								
									
										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({
 | 
			
		||||
            Endpoint: ["Dot", {radius: 2}],
 | 
			
		||||
            Connector: "StateMachine",
 | 
			
		||||
            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"
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        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) {
 | 
			
		||||
        //     const connection = info.connection;
 | 
			
		||||
@@ -153,6 +174,9 @@ async function show() {
 | 
			
		||||
            $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 () {
 | 
			
		||||
            const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0);
 | 
			
		||||
            let curX = 100;
 | 
			
		||||
@@ -179,12 +203,18 @@ async function show() {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            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;
 | 
			
		||||
 | 
			
		||||
                connection.getOverlay("label").setLabel(relation.name);
 | 
			
		||||
                connection.canvas.setAttribute("data-connection-id", connection.id);
 | 
			
		||||
 | 
			
		||||
                //instance.recalculateOffsets(connection);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            initDone = true;
 | 
			
		||||
@@ -200,8 +230,6 @@ async function show() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function saveData() {
 | 
			
		||||
    const currentNote = noteDetailService.getCurrentNote();
 | 
			
		||||
 | 
			
		||||
    noteDetailService.saveNote();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -296,9 +324,13 @@ $addChildNotesButton.click(async () => {
 | 
			
		||||
    let curY = maxY + 200;
 | 
			
		||||
 | 
			
		||||
    for (const child of children) {
 | 
			
		||||
        if (mapData.notes.some(note => note.id === child.noteId)) {
 | 
			
		||||
            // note already exists
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const note = {
 | 
			
		||||
            id: child.noteId,
 | 
			
		||||
            title: child.title,
 | 
			
		||||
            width: "auto",
 | 
			
		||||
            height: "auto"
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,11 @@
 | 
			
		||||
#relation-map-canvas {
 | 
			
		||||
#note-detail-relation-map {
 | 
			
		||||
    height: 500px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#relation-map-canvas {
 | 
			
		||||
    position: absolute; /* needs to be absolute otherwise connections will be misplaced */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.note-box {
 | 
			
		||||
    padding: 16px;
 | 
			
		||||
    position: absolute !important;
 | 
			
		||||
 
 | 
			
		||||
@@ -92,6 +92,35 @@ async function setNoteTypeMime(req) {
 | 
			
		||||
    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 = {
 | 
			
		||||
    getNote,
 | 
			
		||||
    updateNote,
 | 
			
		||||
@@ -99,5 +128,6 @@ module.exports = {
 | 
			
		||||
    sortNotes,
 | 
			
		||||
    protectSubtree,
 | 
			
		||||
    setNoteTypeMime,
 | 
			
		||||
    getChildren
 | 
			
		||||
    getChildren,
 | 
			
		||||
    getRelationMap
 | 
			
		||||
};
 | 
			
		||||
@@ -121,6 +121,7 @@ function register(app) {
 | 
			
		||||
    apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectSubtree);
 | 
			
		||||
    apiRoute(PUT, /\/api\/notes\/(.*)\/type\/(.*)\/mime\/(.*)/, notesApiRoute.setNoteTypeMime);
 | 
			
		||||
    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-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user