refactoring of "collapsible section container" into "ribbon container"

This commit is contained in:
zadam 2021-06-03 12:47:13 +02:00
parent 9216e430db
commit f1344e3b95
17 changed files with 294 additions and 292 deletions

2
package-lock.json generated
View file

@ -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": {

View file

@ -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")

View file

@ -1,262 +0,0 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js";
const TPL = `
<div class="section-container">
<style>
.section-container {
margin-bottom: 5px;
}
.section-top-row {
display: flex;
}
.section-title-container {
display: flex;
flex-direction: row;
justify-content: center;
margin-left: 10px;
flex-grow: 1;
flex-flow: row wrap;
}
.section-title {
color: var(--muted-text-color);
border-bottom: 1px solid var(--main-border-color);
}
.section-title .bx {
font-size: 150%;
position: relative;
top: 3px;
}
.section-title.active {
color: var(--main-text-color);
border-bottom: 1px solid var(--main-text-color);
flex-shrink: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.section-title:hover {
cursor: pointer;
}
.section-title:hover {
color: var(--main-text-color);
}
.section-title:first-of-type {
padding-left: 10px;
}
.section-title-empty {
flex-basis: 35px;
flex-shrink: 1;
}
.section-title-empty:last-of-type {
flex-shrink: 1;
flex-grow: 1;
}
.section-button-container {
display: flex;
border-bottom: 1px solid var(--main-border-color);
margin-right: 5px;
}
.section-button-container .icon-action {
padding: 5px;
position: relative;
top: -3px;
margin-left: 10px;
}
.section-body {
display: none;
border-bottom: 1px solid var(--main-border-color);
margin-left: 10px;
margin-right: 10px;
}
.section-body.active {
display: block;
}
.section-title-label {
display: none;
}
.section-title.active .section-title-label {
display: inline;
}
</style>
<div class="section-top-row">
<div class="section-title-container"></div>
<div class="section-button-container"></div>
</div>
<div class="section-body-container"></div>
</div>`;
export default class CollapsibleSectionContainer extends NoteContextAwareWidget {
constructor() {
super();
this.sectionWidgets = [];
this.buttonWidgets = [];
}
section(widget) {
super.child(widget);
this.sectionWidgets.push(widget);
return this;
}
button(widget) {
super.child(widget);
this.buttonWidgets.push(widget);
return this;
}
doRender() {
this.$widget = $(TPL);
this.overflowing();
this.$titleContainer = this.$widget.find('.section-title-container');
this.$buttonContainer = this.$widget.find('.section-button-container');
this.$bodyContainer = this.$widget.find('.section-body-container');
for (const sectionWidget of this.sectionWidgets) {
this.$bodyContainer.append(
$('<div class="section-body">')
.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 = $('<div class="section-title section-title-real">')
.attr('data-section-component-id', sectionWidget.componentId)
.append($('<span class="section-title-icon">')
.addClass(ret.icon)
.attr("title", ret.title))
.append(" ")
.append($('<span class="section-title-label">').text(ret.title));
this.$titleContainer.append($sectionTitle);
this.$titleContainer.append('<div class="section-title section-title-empty">');
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)
}
}

View file

@ -0,0 +1,263 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js";
const TPL = `
<div class="ribbon-container">
<style>
.ribbon-container {
margin-bottom: 5px;
}
.ribbon-top-row {
display: flex;
}
.ribbon-tab-container {
display: flex;
flex-direction: row;
justify-content: center;
margin-left: 10px;
flex-grow: 1;
flex-flow: row wrap;
}
.ribbon-tab-title {
color: var(--muted-text-color);
border-bottom: 1px solid var(--main-border-color);
}
.ribbon-tab-title .bx {
font-size: 150%;
position: relative;
top: 3px;
}
.ribbon-tab-title.active {
color: var(--main-text-color);
border-bottom: 1px solid var(--main-text-color);
flex-shrink: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ribbon-tab-title:hover {
cursor: pointer;
}
.ribbon-tab-title:hover {
color: var(--main-text-color);
}
.ribbon-tab-title:first-of-type {
padding-left: 10px;
}
.ribbon-tab-spacer {
flex-basis: 35px;
flex-shrink: 1;
border-bottom: 1px solid var(--main-border-color);
}
.ribbon-tab-spacer:last-of-type {
flex-shrink: 1;
flex-grow: 1;
}
.ribbon-button-container {
display: flex;
border-bottom: 1px solid var(--main-border-color);
margin-right: 5px;
}
.ribbon-button-container .icon-action {
padding: 5px;
position: relative;
top: -3px;
margin-left: 10px;
}
.ribbon-body {
display: none;
border-bottom: 1px solid var(--main-border-color);
margin-left: 10px;
margin-right: 10px;
}
.ribbon-body.active {
display: block;
}
.ribbon-tab-title-label {
display: none;
}
.ribbon-tab-title.active .ribbon-tab-title-label {
display: inline;
}
</style>
<div class="ribbon-top-row">
<div class="ribbon-tab-container"></div>
<div class="ribbon-button-container"></div>
</div>
<div class="ribbon-body-container"></div>
</div>`;
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(
$('<div class="ribbon-body">')
.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 = $('<div class="ribbon-tab-title">')
.attr('data-ribbon-component-id', ribbonWidget.componentId)
.append($('<span class="ribbon-tab-title-icon">')
.addClass(ret.icon)
.attr("title", ret.title))
.append(" ")
.append($('<span class="ribbon-tab-title-label">').text(ret.title));
this.$tabContainer.append($ribbonTitle);
this.$tabContainer.append('<div class="ribbon-tab-spacer">');
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)
}
}

View file

@ -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)) {

View file

@ -290,7 +290,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
this.refresh();
this.getTitle(this.note);
this.triggerCommand('refreshSectionContainer');
this.triggerCommand('refreshRibbonContainer');
}
}
}