diff --git a/src/public/javascripts/services/sidebar.js b/src/public/javascripts/services/sidebar.js index 8da56c745..7e57d44b8 100644 --- a/src/public/javascripts/services/sidebar.js +++ b/src/public/javascripts/services/sidebar.js @@ -3,22 +3,6 @@ import LinkMapWidget from "../widgets/link_map.js"; import NoteRevisionsWidget from "../widgets/note_revisions.js"; import AttributesWidget from "../widgets/attributes.js"; -const WIDGET_TPL = ` -
-
- - -
-
- -
-
-
-
-`; - let widgetIdCtr = 1; class Sidebar { @@ -28,8 +12,9 @@ class Sidebar { constructor(ctx) { this.ctx = ctx; this.widgets = []; + this.rendered = false; this.$sidebar = ctx.$tabContent.find(".note-detail-sidebar"); - this.$widgets = this.$sidebar.find(".note-detail-widgets"); + this.$widgetContainer = this.$sidebar.find(".note-detail-widget-container"); this.$showSideBarButton = this.ctx.$tabContent.find(".show-sidebar-button"); this.$showSideBarButton.hide(); @@ -61,32 +46,21 @@ class Sidebar { async noteLoaded() { this.widgets = []; - this.$widgets.empty(); + this.$widgetContainer.empty(); - const widgetClasses = [AttributesWidget, LinkMapWidget, NoteRevisionsWidget, NoteInfoWidget]; + //const widgetClasses = [AttributesWidget, LinkMapWidget, NoteRevisionsWidget, NoteInfoWidget]; + const widgetClasses = [AttributesWidget]; for (const widgetClass of widgetClasses) { - const $widget = this.createWidgetElement(); + const widget = new widgetClass(this.ctx); + this.widgets.push(widget); - const attributesWidget = new widgetClass(this.ctx, $widget); - this.widgets.push(attributesWidget); + widget.renderBody(); // let it run in parallel - attributesWidget.renderBody(); // let it run in parallel - - this.$widgets.append($widget); + this.$widgetContainer.append(widget.getWidgetElement()); } } - createWidgetElement() { - const widgetId = 'widget-' + widgetIdCtr++; - - const $widget = $(WIDGET_TPL); - $widget.find('[data-target]').attr('data-target', "#" + widgetId); - $widget.find('.body-wrapper').attr('id', widgetId); - - return $widget; - } - syncDataReceived(syncData) { for (const widget of this.widgets) { if (widget.syncDataReceived) { diff --git a/src/public/javascripts/widgets/attributes.js b/src/public/javascripts/widgets/attributes.js index febfc2ca1..90b122d8b 100644 --- a/src/public/javascripts/widgets/attributes.js +++ b/src/public/javascripts/widgets/attributes.js @@ -2,22 +2,13 @@ import attributesDialog from "../dialogs/attributes.js"; import utils from "../services/utils.js"; import linkService from "../services/link.js"; import messagingService from "../services/messaging.js"; +import StandardWidget from "./standard_widget.js"; + +class AttributesWidget extends StandardWidget { + constructor(ctx, state) { + super(ctx, state, 'attributes'); -class AttributesWidget { - /** - * @param {TabContext} ctx - * @param {jQuery} $widget - */ - constructor(ctx, $widget) { - this.ctx = ctx; - this.$widget = $widget; - this.$widget.on('show.bs.collapse', () => this.renderBody()); - this.$widget.on('show.bs.collapse', () => this.ctx.stateChanged()); - this.$widget.on('hide.bs.collapse', () => this.ctx.stateChanged()); - this.$title = this.$widget.find('.widget-title'); this.$title.text("Attributes"); - this.$headerActions = this.$widget.find('.widget-header-actions'); - this.$bodyWrapper = this.$widget.find('.body-wrapper'); const $showFullButton = $("").append("show dialog").addClass('widget-header-action'); $showFullButton.click(() => { @@ -27,18 +18,12 @@ class AttributesWidget { this.$headerActions.append($showFullButton); } - async renderBody() { - if (!this.isVisible()) { - return; - } - - const $body = this.$widget.find('.card-body'); - + async doRenderBody() { const attributes = await this.ctx.attributes.getAttributes(); const ownedAttributes = attributes.filter(attr => attr.noteId === this.ctx.note.noteId); if (attributes.length === 0) { - $body.text("No attributes yet..."); + this.$body.text("No attributes yet..."); return; } @@ -75,7 +60,7 @@ class AttributesWidget { $inheritedAttrs.hide(); } - $body.empty().append($attributesContainer); + this.$body.empty().append($attributesContainer); } async renderAttributes(attributes, $container) { @@ -102,20 +87,9 @@ class AttributesWidget { if (syncData.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.renderBody(); + this.doRenderBody(); } } - - getWidgetState() { - return { - id: 'attributes', - visible: this.isVisible() - }; - } - - isVisible() { - return this.$bodyWrapper.is(":visible"); - } } export default AttributesWidget; \ No newline at end of file diff --git a/src/public/javascripts/widgets/standard_widget.js b/src/public/javascripts/widgets/standard_widget.js new file mode 100644 index 000000000..09d21110d --- /dev/null +++ b/src/public/javascripts/widgets/standard_widget.js @@ -0,0 +1,77 @@ +const WIDGET_TPL = ` +
+
+ + +
+
+ +
+
+
+
+`; + +class StandardWidget { + /** + * @param {TabContext} ctx + * @param {object} state + * @param {string} widgetId + */ + constructor(ctx, state, widgetId) { + this.ctx = ctx; + this.widgetId = widgetId; + + this.$widget = $(WIDGET_TPL); + this.$widget.find('[data-target]').attr('data-target', "#widget-" + widgetId); + + this.$bodyWrapper = this.$widget.find('.body-wrapper'); + this.$bodyWrapper.attr('id', "widget-" + widgetId); + + if (state && state.visible) { + this.$bodyWrapper.addClass("show"); + } + + this.$body = this.$bodyWrapper.find('.card-body'); + + 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.$headerActions = this.$widget.find('.widget-header-actions'); + } + + async renderBody() { + if (!this.isVisible() || this.rendered) { + return; + } + + this.rendered = true; + + await this.doRenderBody(); + } + + /** for overriding */ + async doRenderBody() {} + + isVisible() { + return this.$bodyWrapper.is(":visible"); + } + + getWidgetState() { + return { + id: this.widgetId, + visible: this.isVisible() + }; + } + + getWidgetElement() { + return this.$widget; + } + + syncDataReceived(syncData) {} +} + +export default StandardWidget; \ No newline at end of file diff --git a/src/views/sidebar.ejs b/src/views/sidebar.ejs index 69cded6dd..8e904d608 100644 --- a/src/views/sidebar.ejs +++ b/src/views/sidebar.ejs @@ -3,5 +3,5 @@ -
+
\ No newline at end of file