diff --git a/src/public/javascripts/services/app_context.js b/src/public/javascripts/services/app_context.js index 05323bdf7..b00ea20f2 100644 --- a/src/public/javascripts/services/app_context.js +++ b/src/public/javascripts/services/app_context.js @@ -12,6 +12,12 @@ import NoteTitleWidget from "../widgets/note_title.js"; import PromotedAttributesWidget from "../widgets/promoted_attributes.js"; import NoteDetailWidget from "../widgets/note_detail.js"; import TabCachingWidget from "../widgets/tab_caching_widget.js"; +import NoteInfoWidget from "../widgets/note_info.js"; +import NoteRevisionsWidget from "../widgets/note_revisions.js"; +import LinkMapWidget from "../widgets/link_map.js"; +import SimilarNotesWidget from "../widgets/similar_notes.js"; +import WhatLinksHereWidget from "../widgets/what_links_here.js"; +import AttributesWidget from "../widgets/attributes.js"; class AppContext { constructor() { @@ -56,10 +62,26 @@ class AppContext { widget.renderTo($centerPane); } + const $rightPane = $("#right-pane"); + + const rightPaneWidgets = [ + new NoteInfoWidget(this), + new TabCachingWidget(this, () => new AttributesWidget(this)), + new TabCachingWidget(this, () => new LinkMapWidget(this)), + new TabCachingWidget(this, () => new NoteRevisionsWidget(this)), + new TabCachingWidget(this, () => new SimilarNotesWidget(this)), + new TabCachingWidget(this, () => new WhatLinksHereWidget(this)), + ]; + + for (const widget of rightPaneWidgets) { + widget.renderTo($rightPane); + } + this.widgets = [ this.tabRow, ...leftPaneWidgets, - ...centerPaneWidgets + ...centerPaneWidgets, + ...rightPaneWidgets ]; } diff --git a/src/public/javascripts/services/tab_context.js b/src/public/javascripts/services/tab_context.js index 808ed4194..d67a83160 100644 --- a/src/public/javascripts/services/tab_context.js +++ b/src/public/javascripts/services/tab_context.js @@ -5,7 +5,6 @@ import bundleService from "./bundle.js"; import Attributes from "./attributes.js"; import utils from "./utils.js"; import optionsService from "./options.js"; -import Sidebar from "./sidebar.js"; import appContext from "./app_context.js"; let showSidebarInNewTab = true; @@ -39,14 +38,6 @@ class TabContext { this.noteChangeDisabled = false; this.isNoteChanged = false; this.attributes = new Attributes(this); - - if (utils.isDesktop()) { - const sidebarState = this.state.sidebar || { - visible: showSidebarInNewTab - }; - - this.sidebar = new Sidebar(this, sidebarState); - } } async setNote(note, notePath) { @@ -70,10 +61,6 @@ class TabContext { this.setCurrentNotePathToHash(); - if (this.sidebar) { - this.sidebar.noteLoaded(); // load async - } - this.noteChangeDisabled = true; try { @@ -118,10 +105,6 @@ class TabContext { } } - if (this.sidebar) { - this.sidebar.show(); - } - this.setCurrentNotePathToHash(); this.setTitleBar(); } @@ -254,10 +237,6 @@ class TabContext { await this.saveNoteIfChanged(); this.$tabContent.remove(); } - - if (this.sidebar) { - this.sidebar.remove(); - } } cleanup() { @@ -274,10 +253,6 @@ class TabContext { } this.attributes.eventReceived(name, data); - - if (this.sidebar) { - this.sidebar.eventReceived(name, data); - } } getTabState() { @@ -288,8 +263,7 @@ class TabContext { return { tabId: this.tabId, notePath: this.notePath, - active: this.tabRow.activeTabEl === this.$tab[0], - sidebar: this.sidebar && this.sidebar.getSidebarState() + active: this.tabRow.activeTabEl === this.$tab[0] } } diff --git a/src/public/javascripts/widgets/attributes.js b/src/public/javascripts/widgets/attributes.js index f8fe3c9b0..5074bbac0 100644 --- a/src/public/javascripts/widgets/attributes.js +++ b/src/public/javascripts/widgets/attributes.js @@ -23,9 +23,9 @@ class AttributesWidget extends StandardWidget { return [$showFullButton]; } - async doRenderBody() { - const attributes = await this.ctx.attributes.getAttributes(); - const ownedAttributes = attributes.filter(attr => attr.noteId === this.ctx.note.noteId); + async activeTabChanged() { + const attributes = await this.tabContext.attributes.getAttributes(); + const ownedAttributes = attributes.filter(attr => attr.noteId === this.tabContext.note.noteId); if (attributes.length === 0) { this.$body.text("No attributes yet..."); @@ -36,7 +36,7 @@ class AttributesWidget extends StandardWidget { await this.renderAttributes(ownedAttributes, $attributesContainer); - const inheritedAttributes = attributes.filter(attr => attr.noteId !== this.ctx.note.noteId); + const inheritedAttributes = attributes.filter(attr => attr.noteId !== this.tabContext.note.noteId); if (inheritedAttributes.length > 0) { const $inheritedAttrs = $("").append($("").text("Inherited: ")); @@ -88,13 +88,11 @@ class AttributesWidget extends StandardWidget { } } - eventReceived(name, data) { - if (name === 'syncData') { - if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.ctx.note.noteId)) { - // no need to invalidate attributes since the Attribute class listens to this as well - // (and is guaranteed to run first) - this.doRenderBody(); - } + syncDataListener({data}) { + if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.tabContext.note.noteId)) { + // no need to invalidate attributes since the Attribute class listens to this as well + // (and is guaranteed to run first) + this.doRenderBody(); } } } diff --git a/src/public/javascripts/widgets/basic_widget.js b/src/public/javascripts/widgets/basic_widget.js index 256f416ed..fd94d9cf2 100644 --- a/src/public/javascripts/widgets/basic_widget.js +++ b/src/public/javascripts/widgets/basic_widget.js @@ -26,6 +26,8 @@ class BasicWidget { doRender() {} eventReceived(name, data) { + console.log("received", name, "to", this.widgetId); + const fun = this[name + 'Listener']; if (typeof fun === 'function') { diff --git a/src/public/javascripts/widgets/calendar.js b/src/public/javascripts/widgets/calendar.js index 4e3fe63e2..c62621b62 100644 --- a/src/public/javascripts/widgets/calendar.js +++ b/src/public/javascripts/widgets/calendar.js @@ -29,15 +29,17 @@ class CalendarWidget extends StandardWidget { async isEnabled() { return await super.isEnabled() - && await this.ctx.note.hasLabel("dateNote"); + && await this.tabContext.note.hasLabel("dateNote"); } async doRenderBody() { await libraryLoader.requireLibrary(libraryLoader.CALENDAR_WIDGET); this.$body.html(TPL); + } - this.init(this.$body, await this.ctx.note.getLabelValue("dateNote")); + async activeTabChanged() { + this.init(this.$body, await this.tabContext.note.getLabelValue("dateNote")); } init($el, activeDate) { diff --git a/src/public/javascripts/widgets/edited_notes.js b/src/public/javascripts/widgets/edited_notes.js index 01ebf07b1..9995d5407 100644 --- a/src/public/javascripts/widgets/edited_notes.js +++ b/src/public/javascripts/widgets/edited_notes.js @@ -16,23 +16,23 @@ class EditedNotesWidget extends StandardWidget { async isEnabled() { return await super.isEnabled() - && await this.ctx.note.hasLabel("dateNote"); + && await this.tabContext.note.hasLabel("dateNote"); } async doRenderBody() { + const note = this.tabContext.note; // remember which title was when we found the similar notes - this.title = this.ctx.note.title; + this.title = note.title; + let editedNotes = await server.get('edited-notes/' + await note.getLabelValue("dateNote")); - let editedNotes = await server.get('edited-notes/' + await this.ctx.note.getLabelValue("dateNote")); - - editedNotes = editedNotes.filter(note => note.noteId !== this.ctx.note.noteId); + editedNotes = editedNotes.filter(n => n.noteId !== note.noteId); if (editedNotes.length === 0) { this.$body.text("No edited notes on this day yet ..."); return; } - const noteIds = editedNotes.flatMap(note => note.noteId); + const noteIds = editedNotes.flatMap(n => n.noteId); await treeCache.getNotes(noteIds, true); // preload all at once diff --git a/src/public/javascripts/widgets/link_map.js b/src/public/javascripts/widgets/link_map.js index b5c8e49ee..ba36d3ca3 100644 --- a/src/public/javascripts/widgets/link_map.js +++ b/src/public/javascripts/widgets/link_map.js @@ -28,7 +28,7 @@ class LinkMapWidget extends StandardWidget { return [$showFullButton]; } - async doRenderBody() { + async activeTabChanged() { this.$body.css('opacity', 0); this.$body.html(TPL); @@ -38,7 +38,7 @@ class LinkMapWidget extends StandardWidget { const LinkMapServiceClass = (await import('../services/link_map.js')).default; - this.linkMapService = new LinkMapServiceClass(this.ctx.note, $linkMapContainer, { + this.linkMapService = new LinkMapServiceClass(this.tabContext.note, $linkMapContainer, { maxDepth: 1, zoom: 0.6 }); @@ -54,14 +54,12 @@ class LinkMapWidget extends StandardWidget { } } - eventReceived(name, data) { - if (name === 'syncData') { - if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.ctx.note.noteId)) { - // no need to invalidate attributes since the Attribute class listens to this as well - // (and is guaranteed to run first) - if (this.linkMapService) { - this.linkMapService.loadNotesAndRelations(); - } + syncDataListener({data}) { + if (data.find(sd => sd.entityName === 'attributes' && sd.noteId === this.tabContext.note.noteId)) { + // no need to invalidate attributes since the Attribute class listens to this as well + // (and is guaranteed to run first) + if (this.linkMapService) { + this.linkMapService.loadNotesAndRelations(); } } } diff --git a/src/public/javascripts/widgets/note_info.js b/src/public/javascripts/widgets/note_info.js index db4a30f8c..b199c4e7d 100644 --- a/src/public/javascripts/widgets/note_info.js +++ b/src/public/javascripts/widgets/note_info.js @@ -27,16 +27,18 @@ const TPL = ` class NoteInfoWidget extends StandardWidget { getWidgetTitle() { return "Note info"; } - async doRenderBody() { + doRenderBody() { this.$body.html(TPL); + } + activeTabChanged() { const $noteId = this.$body.find(".note-info-note-id"); const $dateCreated = this.$body.find(".note-info-date-created"); const $dateModified = this.$body.find(".note-info-date-modified"); const $type = this.$body.find(".note-info-type"); const $mime = this.$body.find(".note-info-mime"); - const note = this.ctx.note; + const note = this.tabContext.note; $noteId.text(note.noteId); $dateCreated @@ -54,11 +56,9 @@ class NoteInfoWidget extends StandardWidget { .attr("title", note.mime); } - eventReceived(name, data) { - if (name === 'syncData') { - if (data.find(sd => sd.entityName === 'notes' && sd.entityId === this.ctx.note.noteId)) { - this.doRenderBody(); - } + syncDataListener({data}) { + if (data.find(sd => sd.entityName === 'notes' && sd.entityId === this.tabContext.note.noteId)) { + this.activeTabChanged(); } } } diff --git a/src/public/javascripts/widgets/note_revisions.js b/src/public/javascripts/widgets/note_revisions.js index 477aed16c..278db80b3 100644 --- a/src/public/javascripts/widgets/note_revisions.js +++ b/src/public/javascripts/widgets/note_revisions.js @@ -26,8 +26,9 @@ class NoteRevisionsWidget extends StandardWidget { return [$showFullButton]; } - async doRenderBody() { - const revisionItems = await server.get(`notes/${this.ctx.note.noteId}/revisions`); + async activeTabChanged() { + const note = this.tabContext.note; + const revisionItems = await server.get(`notes/${note.noteId}/revisions`); if (revisionItems.length === 0) { this.$body.text("No revisions yet..."); @@ -41,7 +42,7 @@ class NoteRevisionsWidget extends StandardWidget { for (const item of revisionItems) { const $listItem = $('
  • ').append($("", { 'data-action': 'note-revision', - 'data-note-path': this.ctx.note.noteId, + 'data-note-path': note.noteId, 'data-note-revision-id': item.noteRevisionId, href: 'javascript:' }).text(item.dateLastEdited.substr(0, 16))); @@ -54,11 +55,9 @@ class NoteRevisionsWidget extends StandardWidget { } } - eventReceived(name, data) { - if (name === 'syncData') { - if (data.find(sd => sd.entityName === 'note_revisions' && sd.noteId === this.ctx.note.noteId)) { - this.doRenderBody(); - } + syncDataListener({data}) { + if (data.find(sd => sd.entityName === 'note_revisions' && sd.noteId === this.tabContext.note.noteId)) { + this.activeTabChanged(); } } } diff --git a/src/public/javascripts/widgets/similar_notes.js b/src/public/javascripts/widgets/similar_notes.js index 21e6d2b41..6ecb1533c 100644 --- a/src/public/javascripts/widgets/similar_notes.js +++ b/src/public/javascripts/widgets/similar_notes.js @@ -14,11 +14,11 @@ class SimilarNotesWidget extends StandardWidget { getMaxHeight() { return "200px"; } - async doRenderBody() { + async activeTabChanged() { // remember which title was when we found the similar notes - this.title = this.ctx.note.title; + this.title = this.tabContext.note.title; - const similarNotes = await server.get('similar-notes/' + this.ctx.note.noteId); + const similarNotes = await server.get('similar-notes/' + this.tabContext.note.noteId); if (similarNotes.length === 0) { this.$body.text("No similar notes found ..."); @@ -47,13 +47,11 @@ class SimilarNotesWidget extends StandardWidget { this.$body.empty().append($list); } - eventReceived(name, data) { - if (name === 'noteSaved') { - if (this.title !== this.ctx.note.title) { - this.rendered = false; + noteSavedListener({data}) { + if (this.title !== this.tabContext.note.title) { + this.rendered = false; - this.renderBody(); - } + this.renderBody(); } } } diff --git a/src/public/javascripts/widgets/standard_widget.js b/src/public/javascripts/widgets/standard_widget.js index c85718cc3..7c456fe9d 100644 --- a/src/public/javascripts/widgets/standard_widget.js +++ b/src/public/javascripts/widgets/standard_widget.js @@ -1,4 +1,5 @@ -import optionsService from "../services/options.js"; +import utils from "../services/utils.js"; +import TabAwareWidget from "./tab_aware_widget.js"; const WIDGET_TPL = `
    @@ -20,25 +21,7 @@ const WIDGET_TPL = `
    `; -class StandardWidget { - /** - * @param {TabContext} ctx - * @param {Options} options - * @param {object} sidebarState - */ - constructor(ctx, options, sidebarState) { - this.ctx = ctx; - // construct in camelCase - this.widgetName = this.constructor.name.substr(0, 1).toLowerCase() + this.constructor.name.substr(1); - this.widgetOptions = options.getJson(this.widgetName) || { - expanded: true - }; - - this.state = sidebarState.widgets.find(s => s.name === this.widgetName) || { - expanded: this.widgetOptions.expanded - }; - } - +class StandardWidget extends TabAwareWidget { getWidgetTitle() { return "Untitled widget"; } getHeaderActions() { return []; } @@ -47,20 +30,20 @@ class StandardWidget { getMaxHeight() { return null; } - getPosition() { return this.widgetOptions.position; } + //getPosition() { return this.widgetOptions.position; } render() { - const widgetId = `tab-${this.ctx.tabId}-widget-${this.widgetName}`; + const widgetInstanceId = this.widgetId + "-" + utils.randomString(10); this.$widget = $(WIDGET_TPL); - this.$widget.find('[data-target]').attr('data-target', "#" + widgetId); + this.$widget.find('[data-target]').attr('data-target', "#" + widgetInstanceId); this.$bodyWrapper = this.$widget.find('.body-wrapper'); - this.$bodyWrapper.attr('id', widgetId); + this.$bodyWrapper.attr('id', widgetInstanceId); - if (this.state.expanded) { +// if (this.state.expanded) { this.$bodyWrapper.collapse("show"); - } +// } this.$body = this.$bodyWrapper.find('.card-body'); @@ -71,9 +54,9 @@ class StandardWidget { this.$body.css("overflow", "auto"); } - this.$widget.on('shown.bs.collapse', () => this.renderBody()); - this.$widget.on('shown.bs.collapse', () => this.ctx.stateChanged()); - this.$widget.on('hidden.bs.collapse', () => this.ctx.stateChanged()); + // this.$widget.on('shown.bs.collapse', () => this.renderBody()); + // this.$widget.on('shown.bs.collapse', () => this.ctx.stateChanged()); + // this.$widget.on('hidden.bs.collapse', () => this.ctx.stateChanged()); this.$title = this.$widget.find('.widget-title'); this.$title.text(this.getWidgetTitle()); @@ -103,11 +86,11 @@ class StandardWidget { } async renderBody() { - if (!this.isExpanded() || this.rendered) { - return; - } - - this.rendered = true; + // if (!this.isExpanded() || this.rendered) { + // return; + // } + // + // this.rendered = true; await this.doRenderBody(); } @@ -139,8 +122,6 @@ class StandardWidget { }; } - eventReceived(name, data) {} - cleanup() {} } diff --git a/src/public/javascripts/widgets/what_links_here.js b/src/public/javascripts/widgets/what_links_here.js index e06193643..c0b049d13 100644 --- a/src/public/javascripts/widgets/what_links_here.js +++ b/src/public/javascripts/widgets/what_links_here.js @@ -22,8 +22,8 @@ class WhatLinksHereWidget extends StandardWidget { return [$showFullButton]; } - async doRenderBody() { - const targetRelations = await this.ctx.note.getTargetRelations(); + async activeTabChanged() { + const targetRelations = await this.tabContext.note.getTargetRelations(); if (targetRelations.length === 0) { this.$body.text("Nothing links here yet ..."); diff --git a/src/views/desktop.ejs b/src/views/desktop.ejs index e5f87be58..4b885a109 100644 --- a/src/views/desktop.ejs +++ b/src/views/desktop.ejs @@ -138,7 +138,12 @@
    - <% include sidebar.ejs %> + + + +
    + +
    diff --git a/src/views/sidebar.ejs b/src/views/sidebar.ejs deleted file mode 100644 index 82f4f9ecf..000000000 --- a/src/views/sidebar.ejs +++ /dev/null @@ -1,6 +0,0 @@ - - - -
    - -
    \ No newline at end of file