diff --git a/package-lock.json b/package-lock.json
index bcf5694db..f935830df 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -885,7 +885,7 @@
},
"@webassemblyjs/helper-wasm-section": {
"version": "1.11.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.0.tgz",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-ribbon-1.11.0.tgz",
"integrity": "sha512-3Eb88hcbfY/FCukrg6i3EH8H2UsD7x8Vy47iVJrP967A9JGqgBVL9aH71SETPx1JrGsOUVLo0c7vMCN22ytJew==",
"dev": true,
"requires": {
diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js
index 0b4e6fe6f..8624651b0 100644
--- a/src/public/app/layouts/desktop_layout.js
+++ b/src/public/app/layouts/desktop_layout.js
@@ -5,19 +5,19 @@ import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
import TreeSidebarContainer from "../widgets/containers/tree_sidebar_container.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import NoteTitleWidget from "../widgets/note_title.js";
-import OwnedAttributeListWidget from "../widgets/section_widgets/owned_attribute_list.js";
+import OwnedAttributeListWidget from "../widgets/ribbon_widgets/owned_attribute_list.js";
import NoteActionsWidget from "../widgets/buttons/note_actions.js";
import NoteDetailWidget from "../widgets/note_detail.js";
-import CollapsibleSectionContainer from "../widgets/containers/collapsible_section_container.js";
-import PromotedAttributesWidget from "../widgets/section_widgets/promoted_attributes.js";
-import InheritedAttributesWidget from "../widgets/section_widgets/inherited_attribute_list.js";
+import RibbonContainer from "../widgets/containers/ribbon_container.js";
+import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
+import InheritedAttributesWidget from "../widgets/ribbon_widgets/inherited_attribute_list.js";
import NoteListWidget from "../widgets/note_list.js";
-import SearchDefinitionWidget from "../widgets/section_widgets/search_definition.js";
+import SearchDefinitionWidget from "../widgets/ribbon_widgets/search_definition.js";
import SqlResultWidget from "../widgets/sql_result.js";
import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
-import FilePropertiesWidget from "../widgets/section_widgets/file_properties.js";
-import ImagePropertiesWidget from "../widgets/section_widgets/image_properties.js";
-import NotePropertiesWidget from "../widgets/section_widgets/note_properties.js";
+import FilePropertiesWidget from "../widgets/ribbon_widgets/file_properties.js";
+import ImagePropertiesWidget from "../widgets/ribbon_widgets/image_properties.js";
+import NotePropertiesWidget from "../widgets/ribbon_widgets/note_properties.js";
import NoteIconWidget from "../widgets/note_icon.js";
import SearchResultWidget from "../widgets/search_result.js";
import SyncStatusWidget from "../widgets/sync_status.js";
@@ -32,12 +32,12 @@ import PaneContainer from "../widgets/containers/pane_container.js";
import SidebarToggleWidget from "../widgets/buttons/sidebar_toggle.js";
import CreatePaneButton from "../widgets/buttons/create_pane_button.js";
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 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";
+import BasicPropertiesWidget from "../widgets/ribbon_widgets/basic_properties.js";
+import NoteInfoWidget from "../widgets/ribbon_widgets/note_info_widget.js";
+import BookPropertiesWidget from "../widgets/ribbon_widgets/book_properties.js";
+import LinkMapWidget from "../widgets/ribbon_widgets/link_map.js";
+import NotePathsWidget from "../widgets/ribbon_widgets/note_paths.js";
+import SimilarNotesWidget from "../widgets/ribbon_widgets/similar_notes.js";
export default class DesktopLayout {
constructor(customWidgets) {
@@ -103,20 +103,20 @@ export default class DesktopLayout {
.child(new CreatePaneButton())
)
.child(
- new CollapsibleSectionContainer()
- .section(new SearchDefinitionWidget())
- .section(new BasicPropertiesWidget())
- .section(new BookPropertiesWidget())
- .section(new NotePropertiesWidget())
- .section(new FilePropertiesWidget())
- .section(new ImagePropertiesWidget())
- .section(new PromotedAttributesWidget())
- .section(new OwnedAttributeListWidget())
- .section(new InheritedAttributesWidget())
- .section(new NotePathsWidget())
- .section(new LinkMapWidget())
- .section(new SimilarNotesWidget())
- .section(new NoteInfoWidget())
+ new RibbonContainer()
+ .ribbon(new SearchDefinitionWidget())
+ .ribbon(new BasicPropertiesWidget())
+ .ribbon(new BookPropertiesWidget())
+ .ribbon(new NotePropertiesWidget())
+ .ribbon(new FilePropertiesWidget())
+ .ribbon(new ImagePropertiesWidget())
+ .ribbon(new PromotedAttributesWidget())
+ .ribbon(new OwnedAttributeListWidget())
+ .ribbon(new InheritedAttributesWidget())
+ .ribbon(new NotePathsWidget())
+ .ribbon(new LinkMapWidget())
+ .ribbon(new SimilarNotesWidget())
+ .ribbon(new NoteInfoWidget())
.button(new ButtonWidget()
.icon('bx bx-history')
.title("Note Revisions")
diff --git a/src/public/app/widgets/containers/collapsible_section_container.js b/src/public/app/widgets/containers/collapsible_section_container.js
deleted file mode 100644
index 346fbaf04..000000000
--- a/src/public/app/widgets/containers/collapsible_section_container.js
+++ /dev/null
@@ -1,262 +0,0 @@
-import NoteContextAwareWidget from "../note_context_aware_widget.js";
-
-const TPL = `
-
')
- .attr('data-section-component-id', sectionWidget.componentId)
- .append(sectionWidget.render())
- );
- }
-
- for (const buttonWidget of this.buttonWidgets) {
- this.$buttonContainer.append(buttonWidget.render());
- }
-
- this.$titleContainer.on('click', '.section-title-real', e => {
- const $sectionTitle = $(e.target).closest('.section-title-real');
-
- const activate = !$sectionTitle.hasClass("active");
-
- this.$titleContainer.find('.section-title-real').removeClass("active");
- this.$bodyContainer.find('.section-body').removeClass("active");
-
- if (activate) {
- const sectionComponentId = $sectionTitle.attr('data-section-component-id');
-
- this.lastActiveComponentId = sectionComponentId;
-
- this.$titleContainer.find(`.section-title-real[data-section-component-id="${sectionComponentId}"]`).addClass("active");
- this.$bodyContainer.find(`.section-body[data-section-component-id="${sectionComponentId}"]`).addClass("active");
-
- const activeChild = this.getActiveSectionWidget();
-
- if (activeChild) {
- activeChild.handleEvent('noteSwitched', {noteContext: this.noteContext, notePath: this.notePath});
- }
- }
- else {
- this.lastActiveComponentId = null;
- }
- });
- }
-
- async refreshWithNote(note, noExplicitActivation = false) {
- this.lastNoteType = note.type;
-
- let $sectionToActivate, $lastActiveSection;
-
- this.$titleContainer.empty();
-
- for (const sectionWidget of this.sectionWidgets) {
- const ret = sectionWidget.getTitle(note);
-
- if (!ret.show) {
- continue;
- }
-
- const $sectionTitle = $('
')
- .attr('data-section-component-id', sectionWidget.componentId)
- .append($('
')
- .addClass(ret.icon)
- .attr("title", ret.title))
- .append(" ")
- .append($('').text(ret.title));
-
- this.$titleContainer.append($sectionTitle);
- this.$titleContainer.append('');
-
- if (ret.activate && !this.lastActiveComponentId && !$sectionToActivate && !noExplicitActivation) {
- $sectionToActivate = $sectionTitle;
- }
-
- if (this.lastActiveComponentId === sectionWidget.componentId) {
- $lastActiveSection = $sectionTitle;
- }
- }
-
- this.$titleContainer.find('.section-title-icon').tooltip();
-
- if (!$sectionToActivate) {
- $sectionToActivate = $lastActiveSection;
- }
-
- if ($sectionToActivate) {
- $sectionToActivate.trigger('click');
- }
- else {
- this.$bodyContainer.find('.section-body').removeClass("active");
- }
- }
-
- refreshSectionContainerCommand() {
- this.refreshWithNote(this.note, true);
- }
-
- async handleEventInChildren(name, data) {
- if (['activeContextChanged', 'setNoteContext'].includes(name)) {
- // won't trigger .refresh();
- await super.handleEventInChildren('setNoteContext', data);
- }
- else {
- const activeSectionWidget = this.getActiveSectionWidget();
-
- // forward events only to active section, inactive ones don't need to be updated
- if (activeSectionWidget) {
- await activeSectionWidget.handleEvent(name, data);
- }
-
- for (const buttonWidget of this.buttonWidgets) {
- await buttonWidget.handleEvent(name, data);
- }
- }
- }
-
- entitiesReloadedEvent({loadResults}) {
- if (loadResults.isNoteReloaded(this.noteId) && this.lastNoteType !== this.note.type) {
- // note type influences the list of available sections the most
- // check for type is so that we don't update on each title rename
- this.lastNoteType = this.note.type;
-
- this.refresh();
- }
- }
-
- getActiveSectionWidget() {
- return this.sectionWidgets.find(ch => ch.componentId === this.lastActiveComponentId)
- }
-}
diff --git a/src/public/app/widgets/containers/ribbon_container.js b/src/public/app/widgets/containers/ribbon_container.js
new file mode 100644
index 000000000..1d26a3c9f
--- /dev/null
+++ b/src/public/app/widgets/containers/ribbon_container.js
@@ -0,0 +1,263 @@
+import NoteContextAwareWidget from "../note_context_aware_widget.js";
+
+const TPL = `
+
`;
+
+export default class RibbonContainer extends NoteContextAwareWidget {
+ constructor() {
+ super();
+
+ this.ribbonWidgets = [];
+ this.buttonWidgets = [];
+ }
+
+ ribbon(widget) {
+ super.child(widget);
+
+ this.ribbonWidgets.push(widget);
+
+ return this;
+ }
+
+ button(widget) {
+ super.child(widget);
+
+ this.buttonWidgets.push(widget);
+
+ return this;
+ }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.overflowing();
+
+ this.$tabContainer = this.$widget.find('.ribbon-tab-container');
+ this.$buttonContainer = this.$widget.find('.ribbon-button-container');
+ this.$bodyContainer = this.$widget.find('.ribbon-body-container');
+
+ for (const ribbonWidget of this.ribbonWidgets) {
+ this.$bodyContainer.append(
+ $('
')
+ .attr('data-ribbon-component-id', ribbonWidget.componentId)
+ .append(ribbonWidget.render())
+ );
+ }
+
+ for (const buttonWidget of this.buttonWidgets) {
+ this.$buttonContainer.append(buttonWidget.render());
+ }
+
+ this.$tabContainer.on('click', '.ribbon-tab-title', e => {
+ const $ribbonTitle = $(e.target).closest('.ribbon-tab-title');
+
+ const activate = !$ribbonTitle.hasClass("active");
+
+ this.$tabContainer.find('.ribbon-tab-title').removeClass("active");
+ this.$bodyContainer.find('.ribbon-body').removeClass("active");
+
+ if (activate) {
+ const ribbonComponendId = $ribbonTitle.attr('data-ribbon-component-id');
+
+ this.lastActiveComponentId = ribbonComponendId;
+
+ this.$tabContainer.find(`.ribbon-tab-title[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
+ this.$bodyContainer.find(`.ribbon-body[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
+
+ const activeChild = this.getActiveRibbonWidget();
+
+ if (activeChild) {
+ activeChild.handleEvent('noteSwitched', {noteContext: this.noteContext, notePath: this.notePath});
+ }
+ }
+ else {
+ this.lastActiveComponentId = null;
+ }
+ });
+ }
+
+ async refreshWithNote(note, noExplicitActivation = false) {
+ this.lastNoteType = note.type;
+
+ let $ribbonTabToActivate, $lastActiveRibbon;
+
+ this.$tabContainer.empty();
+
+ for (const ribbonWidget of this.ribbonWidgets) {
+ const ret = ribbonWidget.getTitle(note);
+
+ if (!ret.show) {
+ continue;
+ }
+
+ const $ribbonTitle = $('
')
+ .attr('data-ribbon-component-id', ribbonWidget.componentId)
+ .append($('
')
+ .addClass(ret.icon)
+ .attr("title", ret.title))
+ .append(" ")
+ .append($('').text(ret.title));
+
+ this.$tabContainer.append($ribbonTitle);
+ this.$tabContainer.append('');
+
+ if (ret.activate && !this.lastActiveComponentId && !$ribbonTabToActivate && !noExplicitActivation) {
+ $ribbonTabToActivate = $ribbonTitle;
+ }
+
+ if (this.lastActiveComponentId === ribbonWidget.componentId) {
+ $lastActiveRibbon = $ribbonTitle;
+ }
+ }
+
+ this.$tabContainer.find('.ribbon-tab-title-icon').tooltip();
+
+ if (!$ribbonTabToActivate) {
+ $ribbonTabToActivate = $lastActiveRibbon;
+ }
+
+ if ($ribbonTabToActivate) {
+ $ribbonTabToActivate.trigger('click');
+ }
+ else {
+ this.$bodyContainer.find('.ribbon-body').removeClass("active");
+ }
+ }
+
+ refreshRibbonContainerCommand() {
+ this.refreshWithNote(this.note, true);
+ }
+
+ async handleEventInChildren(name, data) {
+ if (['activeContextChanged', 'setNoteContext'].includes(name)) {
+ // won't trigger .refresh();
+ await super.handleEventInChildren('setNoteContext', data);
+ }
+ else {
+ const activeRibbonWidget = this.getActiveRibbonWidget();
+
+ // forward events only to active ribbon tab, inactive ones don't need to be updated
+ if (activeRibbonWidget) {
+ await activeRibbonWidget.handleEvent(name, data);
+ }
+
+ for (const buttonWidget of this.buttonWidgets) {
+ await buttonWidget.handleEvent(name, data);
+ }
+ }
+ }
+
+ entitiesReloadedEvent({loadResults}) {
+ if (loadResults.isNoteReloaded(this.noteId) && this.lastNoteType !== this.note.type) {
+ // note type influences the list of available ribbon tabs the most
+ // check for type is so that we don't update on each title rename
+ this.lastNoteType = this.note.type;
+
+ this.refresh();
+ }
+ }
+
+ getActiveRibbonWidget() {
+ return this.ribbonWidgets.find(ch => ch.componentId === this.lastActiveComponentId)
+ }
+}
diff --git a/src/public/app/widgets/section_widgets/basic_properties.js b/src/public/app/widgets/ribbon_widgets/basic_properties.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/basic_properties.js
rename to src/public/app/widgets/ribbon_widgets/basic_properties.js
diff --git a/src/public/app/widgets/section_widgets/book_properties.js b/src/public/app/widgets/ribbon_widgets/book_properties.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/book_properties.js
rename to src/public/app/widgets/ribbon_widgets/book_properties.js
diff --git a/src/public/app/widgets/section_widgets/file_properties.js b/src/public/app/widgets/ribbon_widgets/file_properties.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/file_properties.js
rename to src/public/app/widgets/ribbon_widgets/file_properties.js
diff --git a/src/public/app/widgets/section_widgets/image_properties.js b/src/public/app/widgets/ribbon_widgets/image_properties.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/image_properties.js
rename to src/public/app/widgets/ribbon_widgets/image_properties.js
diff --git a/src/public/app/widgets/section_widgets/inherited_attribute_list.js b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/inherited_attribute_list.js
rename to src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js
diff --git a/src/public/app/widgets/section_widgets/link_map.js b/src/public/app/widgets/ribbon_widgets/link_map.js
similarity index 99%
rename from src/public/app/widgets/section_widgets/link_map.js
rename to src/public/app/widgets/ribbon_widgets/link_map.js
index 6427301e1..fb90fe114 100644
--- a/src/public/app/widgets/section_widgets/link_map.js
+++ b/src/public/app/widgets/ribbon_widgets/link_map.js
@@ -211,6 +211,7 @@ export default class LinkMapWidget extends NoteContextAwareWidget {
const notes = await froca.getNotes(Object.keys(this.noteIdToLinkCountMap), true);
const noteIdToLinkIdMap = {};
+ noteIdToLinkIdMap[this.noteId] = new Set(); // for case there are no relations
const linksGroupedBySourceTarget = {};
for (const link of Object.values(this.linkIdToLinkMap)) {
diff --git a/src/public/app/widgets/section_widgets/note_info_widget.js b/src/public/app/widgets/ribbon_widgets/note_info_widget.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/note_info_widget.js
rename to src/public/app/widgets/ribbon_widgets/note_info_widget.js
diff --git a/src/public/app/widgets/section_widgets/note_paths.js b/src/public/app/widgets/ribbon_widgets/note_paths.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/note_paths.js
rename to src/public/app/widgets/ribbon_widgets/note_paths.js
diff --git a/src/public/app/widgets/section_widgets/note_properties.js b/src/public/app/widgets/ribbon_widgets/note_properties.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/note_properties.js
rename to src/public/app/widgets/ribbon_widgets/note_properties.js
diff --git a/src/public/app/widgets/section_widgets/owned_attribute_list.js b/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/owned_attribute_list.js
rename to src/public/app/widgets/ribbon_widgets/owned_attribute_list.js
diff --git a/src/public/app/widgets/section_widgets/promoted_attributes.js b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js
similarity index 99%
rename from src/public/app/widgets/section_widgets/promoted_attributes.js
rename to src/public/app/widgets/ribbon_widgets/promoted_attributes.js
index c8ee17e78..5b8e6441e 100644
--- a/src/public/app/widgets/section_widgets/promoted_attributes.js
+++ b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js
@@ -290,7 +290,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
this.refresh();
this.getTitle(this.note);
- this.triggerCommand('refreshSectionContainer');
+ this.triggerCommand('refreshRibbonContainer');
}
}
}
diff --git a/src/public/app/widgets/section_widgets/search_definition.js b/src/public/app/widgets/ribbon_widgets/search_definition.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/search_definition.js
rename to src/public/app/widgets/ribbon_widgets/search_definition.js
diff --git a/src/public/app/widgets/section_widgets/similar_notes.js b/src/public/app/widgets/ribbon_widgets/similar_notes.js
similarity index 100%
rename from src/public/app/widgets/section_widgets/similar_notes.js
rename to src/public/app/widgets/ribbon_widgets/similar_notes.js