From 2c028f7c454a77dfebf565959840064442bdc0ee Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 31 Oct 2020 22:47:15 +0100 Subject: [PATCH] new CollapsibleSectionContainer WIP --- package-lock.json | 6 +- package.json | 2 +- .../layouts/desktop_extra_window_layout.js | 4 +- .../app/layouts/desktop_main_window_layout.js | 6 +- src/public/app/widgets/abstract_container.js | 30 -- src/public/app/widgets/attribute_editor.js | 2 +- src/public/app/widgets/attribute_list.js | 273 ------------------ .../widgets/collapsible_section_container.js | 71 ++++- src/public/app/widgets/flex_container.js | 27 +- .../app/widgets/inherited_attribute_list.js | 66 +++++ .../app/widgets/owned_attribute_list.js | 63 ++++ 11 files changed, 233 insertions(+), 317 deletions(-) delete mode 100644 src/public/app/widgets/abstract_container.js delete mode 100644 src/public/app/widgets/attribute_list.js create mode 100644 src/public/app/widgets/inherited_attribute_list.js create mode 100644 src/public/app/widgets/owned_attribute_list.js diff --git a/package-lock.json b/package-lock.json index 773f891c8..1c3ad3f51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4549,9 +4549,9 @@ } }, "jasmine": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.2.tgz", - "integrity": "sha512-Uc0o2MRnC8TS1MjDrB8jE1umKEo2mflzGvdg0Ncs+yuLtOJ+uz/Wz8VmGsNGtuASr8+E0LDgPkOpvdoC76m5WQ==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.3.tgz", + "integrity": "sha512-Th91zHsbsALWjDUIiU5d/W5zaYQsZFMPTdeNmi8GivZPmAaUAK8MblSG3yQI4VMGC/abF2us7ex60NH1AAIMTA==", "dev": true, "requires": { "glob": "^7.1.6", diff --git a/package.json b/package.json index 68661cff5..c348cce70 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "electron-packager": "15.1.0", "electron-rebuild": "2.3.2", "esm": "3.2.25", - "jasmine": "3.6.2", + "jasmine": "3.6.3", "jsdoc": "3.6.6", "lorem-ipsum": "2.0.3", "rcedit": "2.2.0", diff --git a/src/public/app/layouts/desktop_extra_window_layout.js b/src/public/app/layouts/desktop_extra_window_layout.js index b362de5d1..b14cd7d1e 100644 --- a/src/public/app/layouts/desktop_extra_window_layout.js +++ b/src/public/app/layouts/desktop_extra_window_layout.js @@ -9,7 +9,7 @@ import RunScriptButtonsWidget from "../widgets/run_script_buttons.js"; import NoteTypeWidget from "../widgets/note_type.js"; import NoteActionsWidget from "../widgets/note_actions.js"; import NoteDetailWidget from "../widgets/note_detail.js"; -import AttributeListWidget from "../widgets/attribute_list.js"; +import OwnedAttributeListWidget from "../widgets/owned_attribute_list.js"; export default class DesktopExtraWindowLayout { constructor(customWidgets) { @@ -39,7 +39,7 @@ export default class DesktopExtraWindowLayout { .child(new NoteTypeWidget().hideInZenMode()) .child(new NoteActionsWidget().hideInZenMode()) ) - .child(new TabCachingWidget(() => new AttributeListWidget())) + .child(new TabCachingWidget(() => new OwnedAttributeListWidget())) .child(new TabCachingWidget(() => new NoteDetailWidget())) .child(...this.customWidgets.get('center-pane')) ) diff --git a/src/public/app/layouts/desktop_main_window_layout.js b/src/public/app/layouts/desktop_main_window_layout.js index a5e8e7c46..f7381ea96 100644 --- a/src/public/app/layouts/desktop_main_window_layout.js +++ b/src/public/app/layouts/desktop_main_window_layout.js @@ -11,7 +11,7 @@ import NoteTreeWidget from "../widgets/note_tree.js"; import TabCachingWidget from "../widgets/tab_caching_widget.js"; import NotePathsWidget from "../widgets/note_paths.js"; import NoteTitleWidget from "../widgets/note_title.js"; -import AttributeListWidget from "../widgets/attribute_list.js"; +import OwnedAttributeListWidget from "../widgets/owned_attribute_list.js"; import RunScriptButtonsWidget from "../widgets/run_script_buttons.js"; import NoteTypeWidget from "../widgets/note_type.js"; import NoteActionsWidget from "../widgets/note_actions.js"; @@ -26,6 +26,7 @@ import SidePaneToggles from "../widgets/side_pane_toggles.js"; import EditedNotesWidget from "../widgets/collapsible_widgets/edited_notes.js"; import CollapsibleSectionContainer from "../widgets/collapsible_section_container.js"; import PromotedAttributesWidget from "../widgets/promoted_attributes.js"; +import InheritedAttributesWidget from "../widgets/inherited_attribute_list.js"; const RIGHT_PANE_CSS = ` - -
-
- -
Promoted attributes
- -
-
- -
- - -
-
- -
- -
-
- -
-
- -
- -
-
- -
- -
-
- -
-
-
- -`; - -export default class AttributeListWidget extends TabAwareWidget { - constructor() { - super(); - - this.attributeDetailWidget = new AttributeDetailWidget().setParent(this); - this.attributeEditorWidget = new AttributeEditorWidget(this.attributeDetailWidget).setParent(this); - - this.child(this.attributeEditorWidget, this.attributeDetailWidget); - } - - renderTitle() { - this.$title = $('
').text('Attribute list'); - return this.$title; - } - - doRender() { - this.$widget = $(TPL); - this.overflowing(); - - this.$promotedExpander = this.$widget.find('.attr-promoted-expander'); - this.$allAttrWrapper = this.$widget.find('.all-attr-wrapper'); - - this.$promotedExpander.on('click', async () => { - const collapse = this.$allAttrWrapper.is(":visible"); - - await options.save('promotedAttributesExpanded', !collapse); - - this.triggerEvent(`promotedAttributesCollapsedStateChanged`, {collapse}); - }); - - this.$ownedAndInheritedWrapper = this.$widget.find('.owned-and-inherited-wrapper'); - - this.$ownedExpander = this.$widget.find('.attr-owned-and-inherited-expander'); - this.$ownedExpander.on('click', async () => { - const collapse = this.$ownedAndInheritedWrapper.is(":visible"); - - await options.save('attributeListExpanded', !collapse); - - this.triggerEvent(`attributeListCollapsedStateChanged`, {collapse}); - }); - - this.$ownedExpanderText = this.$ownedExpander.find('.area-expander-text'); - - this.$inheritedAttributesWrapper = this.$widget.find('.inherited-attributes-wrapper'); - - this.$inheritedExpander = this.$widget.find('.attr-inherited-expander'); - this.$inheritedExpander.on('click', () => { - if (this.$inheritedAttributesWrapper.is(":visible")) { - this.$inheritedAttributesWrapper.slideUp(200); - } - else { - this.$inheritedAttributesWrapper.slideDown(200); - } - }); - - this.$inheritedExpanderText = this.$inheritedExpander.find('.area-expander-text'); - - this.$inheritedEmptyExpander = this.$widget.find('.attr-inherited-empty-expander'); - - this.$widget.find('.attr-editor-placeholder').replaceWith(this.attributeEditorWidget.render()); - this.$widget.append(this.attributeDetailWidget.render()); - } - - async refreshWithNote(note, updateOnly = false) { - if (!updateOnly) { - // const hasPromotedAttrs = this.promotedAttributesWidget.getPromotedDefinitionAttributes().length > 0; - // - // if (hasPromotedAttrs) { - // this.$promotedExpander.show(); - // this.$allAttrWrapper.toggle(options.is('promotedAttributesExpanded')); - // this.$ownedAndInheritedWrapper.hide(); - // this.$inheritedAttributesWrapper.hide(); - // } else { - // this.$promotedExpander.hide(); - // this.$allAttrWrapper.show(); - // this.$ownedAndInheritedWrapper.toggle(options.is('attributeListExpanded')); - // } - } - - const ownedAttributes = note.getOwnedAttributes().filter(attr => !attr.isAutoLink); - - this.$ownedExpanderText.text(ownedAttributes.length + ' owned ' + this.attrPlural(ownedAttributes.length)); - - const inheritedAttributes = note.getAttributes().filter(attr => attr.noteId !== this.noteId); - - if (inheritedAttributes.length === 0) { - this.$inheritedExpander.hide(); - this.$inheritedEmptyExpander.show(); - } - else { - this.$inheritedExpander.show(); - this.$inheritedEmptyExpander.hide(); - } - - this.$inheritedExpanderText.text(inheritedAttributes.length + ' inherited ' + this.attrPlural(inheritedAttributes.length)); - - this.$inheritedAttributesWrapper.empty(); - - await this.renderInheritedAttributes(inheritedAttributes, this.$inheritedAttributesWrapper); - } - - attrPlural(number) { - return 'attribute' + (number === 1 ? '' : 's'); - } - - async renderInheritedAttributes(attributes, $container) { - for (const attribute of attributes) { - const $attr = (await attributeRenderer.renderAttribute(attribute, false)) - .on('click', e => this.attributeDetailWidget.showAttributeDetail({ - attribute: { - noteId: attribute.noteId, - type: attribute.type, - name: attribute.name, - value: attribute.value - }, - isOwned: false, - x: e.pageX, - y: e.pageY - })); - - $container - .append($attr) - .append(" "); - } - } - - async saveAttributesCommand() { - await this.attributeEditorWidget.save(); - } - - async reloadAttributesCommand() { - await this.attributeEditorWidget.refresh(); - } - - async updateAttributeListCommand({attributes}) { - await this.attributeEditorWidget.updateAttributeList(attributes); - } - - /** - * This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered - * separately but should behave uniformly for the user. - */ - attributeListCollapsedStateChangedEvent({collapse}) { - if (collapse) { - this.$ownedAndInheritedWrapper.slideUp(200); - } else { - this.$ownedAndInheritedWrapper.slideDown(200); - } - } - - /** - * This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered - * separately but should behave uniformly for the user. - */ - promotedAttributesCollapsedStateChangedEvent({collapse}) { - if (collapse) { - this.$allAttrWrapper.slideUp(200); - } else { - this.$allAttrWrapper.slideDown(200); - } - } - - entitiesReloadedEvent({loadResults}) { - if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { - this.refreshWithNote(this.note, true); - } - } -} diff --git a/src/public/app/widgets/collapsible_section_container.js b/src/public/app/widgets/collapsible_section_container.js index fc380b81e..1b5799180 100644 --- a/src/public/app/widgets/collapsible_section_container.js +++ b/src/public/app/widgets/collapsible_section_container.js @@ -1,8 +1,12 @@ -import AbstractContainer from "./abstract_container.js"; +import TabAwareWidget from "./tab_aware_widget.js"; const TPL = `
`; -export default class CollapsibleSectionContainer extends AbstractContainer { +export default class CollapsibleSectionContainer extends TabAwareWidget { + constructor() { + super(); + + this.children = []; + + this.positionCounter = 10; + } + + child(...components) { + if (!components) { + return this; + } + + super.child(...components); + + for (const component of components) { + if (!component.position) { + component.position = this.positionCounter; + this.positionCounter += 10; + } + } + + this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1); + + return this; + } + doRender() { this.$widget = $(TPL); this.contentSized(); @@ -47,7 +92,8 @@ export default class CollapsibleSectionContainer extends AbstractContainer { for (const widget of this.children) { this.$titleContainer.append( - $('
') + $('
') + .attr('data-section-component-id', widget.componentId) .append(widget.renderTitle()) ); @@ -55,8 +101,27 @@ export default class CollapsibleSectionContainer extends AbstractContainer { this.$bodyContainer.append( $('
') + .attr('data-section-component-id', widget.componentId) .append(widget.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) { + this.$titleContainer.find(`.section-title-real[data-section-component-id="${$sectionTitle.attr('data-section-component-id')}"]`).addClass("active"); + this.$bodyContainer.find(`.section-body[data-section-component-id="${$sectionTitle.attr('data-section-component-id')}"]`).addClass("active"); + } + }); + } + + async refreshWithNote(note) { + this.$titleContainer.find('.section-title-real:first').trigger('click'); } } diff --git a/src/public/app/widgets/flex_container.js b/src/public/app/widgets/flex_container.js index cff7f176a..d2e90842d 100644 --- a/src/public/app/widgets/flex_container.js +++ b/src/public/app/widgets/flex_container.js @@ -1,6 +1,6 @@ -import AbstractContainer from "./abstract_container.js"; +import BasicWidget from "./basic_widget.js"; -export default class FlexContainer extends AbstractContainer { +export default class FlexContainer extends BasicWidget { constructor(direction) { super(); @@ -9,6 +9,29 @@ export default class FlexContainer extends AbstractContainer { } this.attrs.style = `display: flex; flex-direction: ${direction};`; + + this.children = []; + + this.positionCounter = 10; + } + + child(...components) { + if (!components) { + return this; + } + + super.child(...components); + + for (const component of components) { + if (!component.position) { + component.position = this.positionCounter; + this.positionCounter += 10; + } + } + + this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1); + + return this; } doRender() { diff --git a/src/public/app/widgets/inherited_attribute_list.js b/src/public/app/widgets/inherited_attribute_list.js new file mode 100644 index 000000000..63360c119 --- /dev/null +++ b/src/public/app/widgets/inherited_attribute_list.js @@ -0,0 +1,66 @@ +import TabAwareWidget from "./tab_aware_widget.js"; +import AttributeDetailWidget from "./attribute_detail.js"; +import attributeRenderer from "../services/attribute_renderer.js"; + +const TPL = ` +
+ + +
+
` + +export default class InheritedAttributesWidget extends TabAwareWidget { + constructor() { + super(); + + this.attributeDetailWidget = new AttributeDetailWidget().setParent(this); + this.child(this.attributeDetailWidget); + } + + renderTitle() { + this.$title = $('
').text('Inherited attributes'); + return this.$title; + } + + doRender() { + this.$widget = $(TPL); + this.contentSized(); + + this.$container = this.$widget.find('.inherited-attributes-container'); + this.$widget.append(this.attributeDetailWidget.render()); + } + + async refreshWithNote(note) { + this.$container.empty(); + + const inheritedAttributes = note.getAttributes().filter(attr => attr.noteId !== this.noteId); + + for (const attribute of inheritedAttributes) { + const $attr = (await attributeRenderer.renderAttribute(attribute, false)) + .on('click', e => this.attributeDetailWidget.showAttributeDetail({ + attribute: { + noteId: attribute.noteId, + type: attribute.type, + name: attribute.name, + value: attribute.value + }, + isOwned: false, + x: e.pageX, + y: e.pageY + })); + + this.$container + .append($attr) + .append(" "); + } + } +} diff --git a/src/public/app/widgets/owned_attribute_list.js b/src/public/app/widgets/owned_attribute_list.js new file mode 100644 index 000000000..11b5d38c1 --- /dev/null +++ b/src/public/app/widgets/owned_attribute_list.js @@ -0,0 +1,63 @@ +import TabAwareWidget from "./tab_aware_widget.js"; +import AttributeDetailWidget from "./attribute_detail.js"; +import AttributeEditorWidget from "./attribute_editor.js"; + +const TPL = ` +
+ + +
+
+`; + +export default class OwnedAttributeListWidget extends TabAwareWidget { + constructor() { + super(); + + this.attributeDetailWidget = new AttributeDetailWidget().setParent(this); + this.attributeEditorWidget = new AttributeEditorWidget(this.attributeDetailWidget).setParent(this); + + this.child(this.attributeEditorWidget, this.attributeDetailWidget); + } + + renderTitle() { + this.$title = $('
').text('Owned attributes'); + return this.$title; + } + + doRender() { + this.$widget = $(TPL); + this.overflowing(); + + this.$widget.find('.attr-editor-placeholder').replaceWith(this.attributeEditorWidget.render()); + this.$widget.append(this.attributeDetailWidget.render()); + } + + async saveAttributesCommand() { + await this.attributeEditorWidget.save(); + } + + async reloadAttributesCommand() { + await this.attributeEditorWidget.refresh(); + } + + async updateAttributeListCommand({attributes}) { + await this.attributeEditorWidget.updateAttributeList(attributes); + } + + entitiesReloadedEvent({loadResults}) { + if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { + this.refreshWithNote(this.note, true); + } + } +}