diff --git a/TODO b/TODO index 004148c8b..e18aa830c 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,4 @@ - all ribbon tabs should have assignable shortcut - new icon -- green theme - polish becca entities API - separate private and public APIs in becca entities -- handle FIXMEs -- fix Steel Blue example diff --git a/db/TODO.txt b/db/TODO.txt index 838c525b1..1e2fc2b3f 100644 --- a/db/TODO.txt +++ b/db/TODO.txt @@ -3,3 +3,8 @@ - isDeleted = 0 by default - rename openTabs to openNoteContexts - migrate black theme to dark theme +- unify readOnly handling to a single attribute: + * readOnly - like now + * readOnly=auto - like without readOnly (used to override inherited readOnly) + * readOnly=never - like autoReadOnlyDisabled +- remove focusOnAttributesKeyboardShortcut diff --git a/src/public/app/widgets/containers/ribbon_container.js b/src/public/app/widgets/containers/ribbon_container.js index 0b6ba9e8d..7e8d889c9 100644 --- a/src/public/app/widgets/containers/ribbon_container.js +++ b/src/public/app/widgets/containers/ribbon_container.js @@ -161,31 +161,34 @@ export default class RibbonContainer extends NoteContextAwareWidget { 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; - } + this.toggleRibbonTab($ribbonTitle); }); } + toggleRibbonTab($ribbonTitle) { + 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; @@ -202,6 +205,7 @@ export default class RibbonContainer extends NoteContextAwareWidget { const $ribbonTitle = $('
') .attr('data-ribbon-component-id', ribbonWidget.componentId) + .attr('data-ribbon-component-name', ribbonWidget.name) .append($('') .addClass(ret.icon) .attr("title", ret.title)) @@ -234,10 +238,56 @@ export default class RibbonContainer extends NoteContextAwareWidget { } } + isRibbonTabActive(name) { + const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`); + + return $ribbonComponent.hasClass("active"); + } + refreshRibbonContainerCommand() { this.refreshWithNote(this.note, true); } + ensureOwnedAttributesAreOpen(ntxId) { + if (this.isNoteContext(ntxId) && !this.isRibbonTabActive('ownedAttributes')) { + this.toggleRibbonTabWithName('ownedAttributes', ntxId); + } + } + + addNewLabelEvent({ntxId}) { + this.ensureOwnedAttributesAreOpen(ntxId); + } + + addNewRelationEvent({ntxId}) { + this.ensureOwnedAttributesAreOpen(ntxId); + } + + toggleRibbonTabWithName(name, ntxId) { + if (!this.isNoteContext(ntxId)) { + return false; + } + + const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`); + + if ($ribbonComponent) { + this.toggleRibbonTab($ribbonComponent); + } + } + + handleEvent(name, data) { + const PREFIX = "toggleRibbonTab"; + + if (name.startsWith(PREFIX)) { + let componentName = name.substr(PREFIX.length); + componentName = componentName[0].toLowerCase() + componentName.substr(1); + + this.toggleRibbonTabWithName(componentName, data.ntxId); + } + else { + return super.handleEvent(name, data); + } + } + async handleEventInChildren(name, data) { if (['activeContextChanged', 'setNoteContext'].includes(name)) { // won't trigger .refresh(); diff --git a/src/public/app/widgets/ribbon_widgets/basic_properties.js b/src/public/app/widgets/ribbon_widgets/basic_properties.js index dd63b5493..d79458c0a 100644 --- a/src/public/app/widgets/ribbon_widgets/basic_properties.js +++ b/src/public/app/widgets/ribbon_widgets/basic_properties.js @@ -46,6 +46,10 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget { this.child(this.noteTypeWidget, this.protectedNoteSwitchWidget, this.editabilitySelectWidget); } + get name() { + return "basicProperties"; + } + isEnabled() { return this.note && (this.note.type === 'text' || this.note.type === 'code'); } diff --git a/src/public/app/widgets/ribbon_widgets/book_properties.js b/src/public/app/widgets/ribbon_widgets/book_properties.js index 0446d39b4..a4eaf996f 100644 --- a/src/public/app/widgets/ribbon_widgets/book_properties.js +++ b/src/public/app/widgets/ribbon_widgets/book_properties.js @@ -42,6 +42,10 @@ const TPL = `
`; export default class BookPropertiesWidget extends NoteContextAwareWidget { + get name() { + return "bookProperties"; + } + isEnabled() { return this.note && this.note.type === 'book'; } diff --git a/src/public/app/widgets/ribbon_widgets/file_properties.js b/src/public/app/widgets/ribbon_widgets/file_properties.js index e7b8c49e7..d40360521 100644 --- a/src/public/app/widgets/ribbon_widgets/file_properties.js +++ b/src/public/app/widgets/ribbon_widgets/file_properties.js @@ -55,6 +55,10 @@ const TPL = ` `; export default class FilePropertiesWidget extends NoteContextAwareWidget { + get name() { + return "fileProperties"; + } + isEnabled() { return this.note && this.note.type === 'file'; } diff --git a/src/public/app/widgets/ribbon_widgets/image_properties.js b/src/public/app/widgets/ribbon_widgets/image_properties.js index a53b3f1a7..447a31e33 100644 --- a/src/public/app/widgets/ribbon_widgets/image_properties.js +++ b/src/public/app/widgets/ribbon_widgets/image_properties.js @@ -37,6 +37,10 @@ const TPL = ` `; export default class ImagePropertiesWidget extends NoteContextAwareWidget { + get name() { + return "imageProperties"; + } + isEnabled() { return this.note && this.note.type === 'image'; } diff --git a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js index 9ca7899e2..3f32bfa00 100644 --- a/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js +++ b/src/public/app/widgets/ribbon_widgets/inherited_attribute_list.js @@ -21,6 +21,10 @@ const TPL = ` `; export default class InheritedAttributesWidget extends NoteContextAwareWidget { + get name() { + return "inheritedAttributes"; + } + constructor() { super(); diff --git a/src/public/app/widgets/ribbon_widgets/link_map.js b/src/public/app/widgets/ribbon_widgets/link_map.js index 6e7f1638c..2418a77ec 100644 --- a/src/public/app/widgets/ribbon_widgets/link_map.js +++ b/src/public/app/widgets/ribbon_widgets/link_map.js @@ -38,6 +38,10 @@ const TPL = ` `; export default class LinkMapWidget extends NoteContextAwareWidget { + get name() { + return "linkMap"; + } + isEnabled() { return this.note; } diff --git a/src/public/app/widgets/ribbon_widgets/note_info_widget.js b/src/public/app/widgets/ribbon_widgets/note_info_widget.js index 5f506d98b..659711a57 100644 --- a/src/public/app/widgets/ribbon_widgets/note_info_widget.js +++ b/src/public/app/widgets/ribbon_widgets/note_info_widget.js @@ -62,6 +62,10 @@ const TPL = ` `; export default class NoteInfoWidget extends NoteContextAwareWidget { + get name() { + return "noteInfo"; + } + isEnabled() { return this.note; } diff --git a/src/public/app/widgets/ribbon_widgets/note_paths.js b/src/public/app/widgets/ribbon_widgets/note_paths.js index 30809a937..eb622c74c 100644 --- a/src/public/app/widgets/ribbon_widgets/note_paths.js +++ b/src/public/app/widgets/ribbon_widgets/note_paths.js @@ -36,6 +36,10 @@ const TPL = ` `; export default class NotePathsWidget extends NoteContextAwareWidget { + get name() { + return "notePaths"; + } + isEnabled() { return this.note; } diff --git a/src/public/app/widgets/ribbon_widgets/note_properties.js b/src/public/app/widgets/ribbon_widgets/note_properties.js index b151a0d1c..b51cd0ce4 100644 --- a/src/public/app/widgets/ribbon_widgets/note_properties.js +++ b/src/public/app/widgets/ribbon_widgets/note_properties.js @@ -14,6 +14,9 @@ const TPL = ` `; +/** + * TODO: figure out better name or conceptualize better. + */ export default class NotePropertiesWidget extends NoteContextAwareWidget { isEnabled() { return this.note && !!this.note.getLabelValue('pageUrl'); diff --git a/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js b/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js index 5cdd31325..89fd36050 100644 --- a/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js +++ b/src/public/app/widgets/ribbon_widgets/owned_attribute_list.js @@ -22,6 +22,10 @@ const TPL = ` `; export default class OwnedAttributeListWidget extends NoteContextAwareWidget { + get name() { + return "ownedAttributes"; + } + constructor() { super(); diff --git a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js index b4be7aefe..9626b498f 100644 --- a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js +++ b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js @@ -35,6 +35,10 @@ const TPL = ` `; export default class PromotedAttributesWidget extends NoteContextAwareWidget { + get name() { + return "promotedAttributes"; + } + doRender() { this.$widget = $(TPL); this.contentSized(); diff --git a/src/public/app/widgets/ribbon_widgets/search_definition.js b/src/public/app/widgets/ribbon_widgets/search_definition.js index d8809f5f8..ad9288cd9 100644 --- a/src/public/app/widgets/ribbon_widgets/search_definition.js +++ b/src/public/app/widgets/ribbon_widgets/search_definition.js @@ -23,7 +23,6 @@ import Limit from "../search_options/limit.js"; import DeleteNoteRevisionsSearchAction from "../search_actions/delete_note_revisions.js"; import Debug from "../search_options/debug.js"; import appContext from "../../services/app_context.js"; -import toast from "../../services/toast.js"; const TPL = `
diff --git a/src/public/app/widgets/ribbon_widgets/similar_notes.js b/src/public/app/widgets/ribbon_widgets/similar_notes.js index 8f6e029d2..7a65d35bc 100644 --- a/src/public/app/widgets/ribbon_widgets/similar_notes.js +++ b/src/public/app/widgets/ribbon_widgets/similar_notes.js @@ -31,6 +31,10 @@ const TPL = ` `; export default class SimilarNotesWidget extends NoteContextAwareWidget { + get name() { + return "similarNotes"; + } + isEnabled() { return super.isEnabled() && this.note.type !== 'search' diff --git a/src/services/keyboard_actions.js b/src/services/keyboard_actions.js index 47c43acba..c72d588ac 100644 --- a/src/services/keyboard_actions.js +++ b/src/services/keyboard_actions.js @@ -236,12 +236,6 @@ const DEFAULT_KEYBOARD_ACTIONS = [ description: "Shows Note Source dialog", scope: "window" }, - { - actionName: "showLinkMap", - defaultShortcuts: [], - description: "Shows Link Map dialog", - scope: "window" - }, { actionName: "showOptions", defaultShortcuts: [], @@ -324,12 +318,6 @@ const DEFAULT_KEYBOARD_ACTIONS = [ separator: "Attributes (labels & relations)" }, - { - actionName: "focusOnAttributes", - defaultShortcuts: ["Alt+A"], - description: "Put focus into attribute editor", - scope: "window" - }, { actionName: "addNewLabel", defaultShortcuts: ["Alt+L"], @@ -343,6 +331,77 @@ const DEFAULT_KEYBOARD_ACTIONS = [ scope: "window" }, + { + separator: "Ribbon tabs" + }, + + { + actionName: "toggleRibbonTabBasicProperties", + defaultShortcuts: [], + description: "Toggle Basic Properties", + scope: "window" + }, + { + actionName: "toggleRibbonTabBookProperties", + defaultShortcuts: [], + description: "Toggle Book Properties", + scope: "window" + }, + { + actionName: "toggleRibbonTabFileProperties", + defaultShortcuts: [], + description: "Toggle File Properties", + scope: "window" + }, + { + actionName: "toggleRibbonTabImageProperties", + defaultShortcuts: [], + description: "Toggle Image Properties", + scope: "window" + }, + { + actionName: "toggleRibbonTabOwnedAttributes", + defaultShortcuts: ["Alt+A"], + description: "Toggle Owned Attributes", + scope: "window" + }, + { + actionName: "toggleRibbonTabInheritedAttributes", + defaultShortcuts: [], + description: "Toggle Inherited Attributes", + scope: "window" + }, + { + actionName: "toggleRibbonTabPromotedAttributes", + defaultShortcuts: [], + description: "Toggle Promoted Attributes", + scope: "window" + }, + { + actionName: "toggleRibbonTabLinkMap", + defaultShortcuts: [], + description: "Toggle Link Map", + scope: "window" + }, + { + actionName: "toggleRibbonTabNoteInfo", + defaultShortcuts: [], + description: "Toggle Note Info", + scope: "window" + }, + { + actionName: "toggleRibbonTabNotePaths", + defaultShortcuts: [], + description: "Toggle Note Paths", + scope: "window" + }, + { + actionName: "toggleRibbonTabSimilarNotes", + defaultShortcuts: [], + description: "Toggle Similar Notes", + scope: "window" + }, + { separator: "Other" },