mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
converting sidebar widgets to normal widgets
This commit is contained in:
parent
23701219e1
commit
c9770573b2
@ -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
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 = $("<span>").append($("<strong>").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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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') {
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 = $('<li>').append($("<a>", {
|
||||
'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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 = `
|
||||
<div class="card widget">
|
||||
@ -20,25 +21,7 @@ const WIDGET_TPL = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
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() {}
|
||||
}
|
||||
|
||||
|
@ -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 ...");
|
||||
|
@ -138,7 +138,12 @@
|
||||
|
||||
<div id="center-pane"></div>
|
||||
|
||||
<% include sidebar.ejs %>
|
||||
<button id="hide-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-right hide-in-zen-mode" title="Hide sidebar"></button>
|
||||
<button id="show-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-left hide-in-zen-mode" title="Show sidebar"></button>
|
||||
|
||||
<div id="right-pane" class="hide-in-zen-mode">
|
||||
<div id="sidebar-container"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-sm" id="context-menu-container"></div>
|
||||
|
@ -1,6 +0,0 @@
|
||||
<button id="hide-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-right hide-in-zen-mode" title="Hide sidebar"></button>
|
||||
<button id="show-sidebar-button" class="btn btn-sm icon-button bx bx-chevrons-left hide-in-zen-mode" title="Show sidebar"></button>
|
||||
|
||||
<div id="right-pane" class="hide-in-zen-mode">
|
||||
<div id="sidebar-container"></div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user