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"
},