mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	cleaned up link map
This commit is contained in:
		@@ -1,36 +0,0 @@
 | 
			
		||||
import utils from "../services/utils.js";
 | 
			
		||||
import LinkMapService from "../services/link_map.js";
 | 
			
		||||
import appContext from "../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const $linkMapContainer = $("#link-map-container");
 | 
			
		||||
 | 
			
		||||
const $dialog = $("#link-map-dialog");
 | 
			
		||||
const $maxNotesInput = $("#link-map-max-notes");
 | 
			
		||||
 | 
			
		||||
let linkMapService;
 | 
			
		||||
 | 
			
		||||
function getOptions() {
 | 
			
		||||
    return {
 | 
			
		||||
        maxNotes: $maxNotesInput.val()
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function showDialog() {
 | 
			
		||||
    // set default settings
 | 
			
		||||
    $maxNotesInput.val(20);
 | 
			
		||||
 | 
			
		||||
    $linkMapContainer.css("height", $("body").height() - 150);
 | 
			
		||||
 | 
			
		||||
    $linkMapContainer.empty();
 | 
			
		||||
 | 
			
		||||
    utils.openDialog($dialog);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$dialog.on('shown.bs.modal', () => {
 | 
			
		||||
    const note = appContext.tabManager.getActiveContextNote();
 | 
			
		||||
 | 
			
		||||
    linkMapService = new LinkMapService(note, $linkMapContainer, getOptions());
 | 
			
		||||
    linkMapService.render();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
$maxNotesInput.on("input", () => linkMapService.loadNotesAndRelations(getOptions()));
 | 
			
		||||
@@ -35,7 +35,6 @@ import ClosePaneButton from "../widgets/buttons/close_pane_button.js";
 | 
			
		||||
import BasicPropertiesWidget from "../widgets/section_widgets/basic_properties.js";
 | 
			
		||||
import NoteInfoWidget from "../widgets/section_widgets/note_info_widget.js";
 | 
			
		||||
import BookPropertiesWidget from "../widgets/section_widgets/book_properties.js";
 | 
			
		||||
import ShowNoteSourceButton from "../widgets/buttons/show_note_source.js";
 | 
			
		||||
import LinkMapWidget from "../widgets/section_widgets/link_map.js";
 | 
			
		||||
import NotePathsWidget from "../widgets/section_widgets/note_paths.js";
 | 
			
		||||
import SimilarNotesWidget from "../widgets/section_widgets/similar_notes.js";
 | 
			
		||||
 
 | 
			
		||||
@@ -33,17 +33,6 @@ const RELATION_MAP = {
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const LINK_MAP = {
 | 
			
		||||
    js: [
 | 
			
		||||
        "libraries/jsplumb.js",
 | 
			
		||||
        "libraries/panzoom.js",
 | 
			
		||||
        "libraries/springy.js"
 | 
			
		||||
    ],
 | 
			
		||||
    css: [
 | 
			
		||||
        "stylesheets/link_map.css"
 | 
			
		||||
    ]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const PRINT_THIS = {js: ["libraries/printThis.js"]};
 | 
			
		||||
 | 
			
		||||
const CALENDAR_WIDGET = {css: ["stylesheets/calendar.css"]};
 | 
			
		||||
@@ -106,7 +95,6 @@ export default {
 | 
			
		||||
    ESLINT,
 | 
			
		||||
    COMMONMARK,
 | 
			
		||||
    RELATION_MAP,
 | 
			
		||||
    LINK_MAP,
 | 
			
		||||
    PRINT_THIS,
 | 
			
		||||
    CALENDAR_WIDGET,
 | 
			
		||||
    KATEX,
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,6 @@ export default class RootCommandExecutor extends Component {
 | 
			
		||||
        import("../dialogs/note_source.js").then(d => d.showDialog());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showLinkMapCommand() {
 | 
			
		||||
        import("../dialogs/link_map.js").then(d => d.showDialog());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pasteMarkdownIntoTextCommand() {
 | 
			
		||||
        import("../dialogs/markdown_import.js").then(d => d.importMarkdownInline());
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,115 +0,0 @@
 | 
			
		||||
import CollapsibleWidget from "../collapsible_widget.js";
 | 
			
		||||
import froca from "../../services/froca.js";
 | 
			
		||||
 | 
			
		||||
let linkMapContainerIdCtr = 1;
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="link-map-widget">
 | 
			
		||||
    <div class="link-map-container" style="height: 300px;"></div>
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export default class LinkMapWidget extends CollapsibleWidget {
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return super.isEnabled() && !this.note.hasLabel('linkMapWidgetDisabled');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get widgetTitle() { return "Link map"; }
 | 
			
		||||
 | 
			
		||||
    get help() {
 | 
			
		||||
        return {
 | 
			
		||||
            title: "Link map shows incoming and outgoing links from/to the current note.",
 | 
			
		||||
            url: "https://github.com/zadam/trilium/wiki/Link-map"
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get headerActions() {
 | 
			
		||||
        const $showFullButton = $("<a>")
 | 
			
		||||
            .addClass("bx bx-network-chart")
 | 
			
		||||
            .addClass('widget-header-action')
 | 
			
		||||
            .attr('title', 'Show full link map');
 | 
			
		||||
 | 
			
		||||
        $showFullButton.on('click', async () => {
 | 
			
		||||
            const linkMapDialog = await import("../../dialogs/link_map.js");
 | 
			
		||||
            linkMapDialog.showDialog();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return [$showFullButton];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    decorateWidget() {
 | 
			
		||||
        this.$body.css("max-height", "400px");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async refreshWithNote(note) {
 | 
			
		||||
        const noteId = this.noteId;
 | 
			
		||||
 | 
			
		||||
        let shown = false;
 | 
			
		||||
 | 
			
		||||
        // avoid executing this expensive operation multiple times when just going through notes (with keyboard especially)
 | 
			
		||||
        // until the users settles on a note
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
            if (this.noteId === noteId) {
 | 
			
		||||
                // there's a problem with centering the rendered link map before it is actually shown on the screen
 | 
			
		||||
                // that's why we make the whole process lazy and with the help of IntersectionObserver wait until the
 | 
			
		||||
                // tab is really shown and only then render
 | 
			
		||||
                const observer = new IntersectionObserver(entries => {
 | 
			
		||||
                    if (!shown && entries[0].isIntersecting) {
 | 
			
		||||
                        shown = true;
 | 
			
		||||
                        this.displayLinkMap(note);
 | 
			
		||||
                    }
 | 
			
		||||
                }, {
 | 
			
		||||
                    rootMargin: '0px',
 | 
			
		||||
                    threshold: 0.1
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                observer.observe(this.$body[0]);
 | 
			
		||||
            }
 | 
			
		||||
        }, 1000);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async displayLinkMap(note) {
 | 
			
		||||
        this.$body.css('opacity', 0);
 | 
			
		||||
        this.$body.html(TPL);
 | 
			
		||||
 | 
			
		||||
        const $linkMapContainer = this.$body.find('.link-map-container');
 | 
			
		||||
        $linkMapContainer.attr("id", "link-map-container-" + linkMapContainerIdCtr++);
 | 
			
		||||
 | 
			
		||||
        const LinkMapServiceClass = (await import('../../services/link_map.js')).default;
 | 
			
		||||
 | 
			
		||||
        this.linkMapService = new LinkMapServiceClass(note, $linkMapContainer, {
 | 
			
		||||
            maxDepth: 1,
 | 
			
		||||
            zoom: 0.6
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await this.linkMapService.render();
 | 
			
		||||
 | 
			
		||||
        this.$body.animate({opacity: 1}, 300);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cleanup() {
 | 
			
		||||
        if (this.linkMapService) {
 | 
			
		||||
            this.linkMapService.cleanup();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    entitiesReloadedEvent({loadResults}) {
 | 
			
		||||
        if (loadResults.getAttributes().find(attr => attr.type === 'relation' && (attr.noteId === this.noteId || attr.value === this.noteId))) {
 | 
			
		||||
            this.noteSwitched();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const changedNoteIds = loadResults.getNoteIds();
 | 
			
		||||
 | 
			
		||||
        if (changedNoteIds.length > 0) {
 | 
			
		||||
            const $linkMapContainer = this.$body.find('.link-map-container');
 | 
			
		||||
 | 
			
		||||
            for (const noteId of changedNoteIds) {
 | 
			
		||||
                const note = froca.notes[noteId];
 | 
			
		||||
 | 
			
		||||
                if (note) {
 | 
			
		||||
                    $linkMapContainer.find(`a[data-note-path="${noteId}"]`).text(note.title);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,66 +0,0 @@
 | 
			
		||||
.link-map-container {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    outline: none; /* remove dotted outline on click */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-container .note-box {
 | 
			
		||||
    padding: 0px 8px 8px 8px;
 | 
			
		||||
    position: absolute !important;
 | 
			
		||||
    background-color: var(--main-background-color);
 | 
			
		||||
    color: var(--main-text-color);
 | 
			
		||||
    z-index: 4;
 | 
			
		||||
    border: 1px solid #666;
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    opacity: 0.8;
 | 
			
		||||
    font-size: 11px;
 | 
			
		||||
    width: auto;
 | 
			
		||||
    min-width: 120px;
 | 
			
		||||
    max-width: 250px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-container .note-box:hover {
 | 
			
		||||
    background-color: var(--more-accented-background-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-container .note-box .title {
 | 
			
		||||
    font-size: larger;
 | 
			
		||||
    font-weight: 600;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-active-note {
 | 
			
		||||
    background-color: var(--accented-background-color) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-container .jsplumb-connection-hover path {
 | 
			
		||||
    stroke-width: 2 !important;
 | 
			
		||||
    stroke: var(--main-text-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-widget {
 | 
			
		||||
    outline: none;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-widget .note-box .title {
 | 
			
		||||
    font-size: 19px !important;
 | 
			
		||||
    font-weight: 600
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#link-map-dialog .note-box .bx {
 | 
			
		||||
    font-size: 24px !important;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 6px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.link-map-widget .note-box .bx {
 | 
			
		||||
    font-size: 30px !important;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 6px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
@@ -33,7 +33,6 @@
 | 
			
		||||
<%- include('dialogs/prompt.ejs') %>
 | 
			
		||||
<%- include('dialogs/confirm.ejs') %>
 | 
			
		||||
<%- include('dialogs/help.ejs') %>
 | 
			
		||||
<%- include('dialogs/link_map.ejs') %>
 | 
			
		||||
<%- include('dialogs/clone_to.ejs') %>
 | 
			
		||||
<%- include('dialogs/move_to.ejs') %>
 | 
			
		||||
<%- include('dialogs/backend_log.ejs') %>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
<div id="link-map-dialog" class="modal fade mx-auto" tabindex="-1" role="dialog">
 | 
			
		||||
    <div class="modal-dialog modal-xl" style="max-width: 90%;" role="document">
 | 
			
		||||
        <div class="modal-content">
 | 
			
		||||
            <div class="modal-header">
 | 
			
		||||
                <h5 class="modal-title" style="width: auto;">Link map</h5>
 | 
			
		||||
 | 
			
		||||
                <div style="vertical-align: middle;">
 | 
			
		||||
                    <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="20" min="5" max="1000" step="5"
 | 
			
		||||
                               class="form-control form-control-sm"
 | 
			
		||||
                               style="width: 80px; display: inline-block; text-align: right;"/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div style="display: inline-block;">
 | 
			
		||||
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0;">
 | 
			
		||||
                        <span aria-hidden="true">×</span>
 | 
			
		||||
                    </button>
 | 
			
		||||
 | 
			
		||||
                    <button class="help-button" type="button" data-help-page="Link-map" title="Help on Link map">?</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="modal-body" style="outline: none; overflow: hidden; height: 85vh;">
 | 
			
		||||
                <div id="link-map-container" class="link-map-container"></div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
		Reference in New Issue
	
	Block a user