Merge remote-tracking branch 'origin/stable'

# Conflicts:
#	src/public/app/widgets/collapsible_widgets/note_info.js
This commit is contained in:
zadam 2020-06-04 22:37:04 +02:00
commit 4ae965c5cb
7 changed files with 41 additions and 25 deletions

View File

@ -170,6 +170,16 @@ class NoteShort {
* @returns {Attribute[]} all note's attributes, including inherited ones * @returns {Attribute[]} all note's attributes, including inherited ones
*/ */
getAttributes(type, name) { getAttributes(type, name) {
return this.__filterAttrs(this.__getCachedAttributes([]), type, name);
}
__getCachedAttributes(path) {
// notes/clones cannot form tree cycles, it is possible to create attribute inheritance cycle via templates
// when template instance is a parent of template itself
if (path.includes(this.noteId)) {
return [];
}
if (!(this.noteId in noteAttributeCache)) { if (!(this.noteId in noteAttributeCache)) {
const ownedAttributes = this.getOwnedAttributes(); const ownedAttributes = this.getOwnedAttributes();
@ -177,11 +187,13 @@ class NoteShort {
ownedAttributes ownedAttributes
]; ];
const newPath = [...path, this.noteId];
for (const templateAttr of ownedAttributes.filter(oa => oa.type === 'relation' && oa.name === 'template')) { for (const templateAttr of ownedAttributes.filter(oa => oa.type === 'relation' && oa.name === 'template')) {
const templateNote = this.treeCache.notes[templateAttr.value]; const templateNote = this.treeCache.notes[templateAttr.value];
if (templateNote) { if (templateNote && templateNote.noteId !== this.noteId) {
attrArrs.push(templateNote.getAttributes()); attrArrs.push(templateNote.__getCachedAttributes(newPath));
} }
} }
@ -189,7 +201,7 @@ class NoteShort {
for (const parentNote of this.getParentNotes()) { for (const parentNote of this.getParentNotes()) {
// these virtual parent-child relationships are also loaded into frontend tree cache // these virtual parent-child relationships are also loaded into frontend tree cache
if (parentNote.type !== 'search') { if (parentNote.type !== 'search') {
attrArrs.push(parentNote.getInheritableAttributes()); attrArrs.push(parentNote.__getInheritableAttributes(newPath));
} }
} }
} }
@ -197,7 +209,7 @@ class NoteShort {
noteAttributeCache.attributes[this.noteId] = attrArrs.flat(); noteAttributeCache.attributes[this.noteId] = attrArrs.flat();
} }
return this.__filterAttrs(noteAttributeCache.attributes[this.noteId], type, name); return noteAttributeCache.attributes[this.noteId];
} }
__filterAttrs(attributes, type, name) { __filterAttrs(attributes, type, name) {
@ -212,8 +224,8 @@ class NoteShort {
} }
} }
getInheritableAttributes() { __getInheritableAttributes(path) {
const attrs = this.getAttributes(); const attrs = this.__getCachedAttributes(path);
return attrs.filter(attr => attr.isInheritable); return attrs.filter(attr => attr.isInheritable);
} }

View File

@ -34,7 +34,7 @@ export default class MainTreeExecutors extends Component {
return; return;
} }
const {note} = await noteCreateService.createNote(activeNote.noteId, { await noteCreateService.createNote(activeNote.noteId, {
isProtected: activeNote.isProtected, isProtected: activeNote.isProtected,
saveSelection: false saveSelection: false
}); });

View File

@ -73,7 +73,7 @@ class TabContext extends Component {
protectedSessionHolder.touchProtectedSessionIfNecessary(this.note); protectedSessionHolder.touchProtectedSessionIfNecessary(this.note);
if (triggerSwitchEvent) { if (triggerSwitchEvent) {
this.triggerEvent('tabNoteSwitched', { await this.triggerEvent('tabNoteSwitched', {
tabContext: this, tabContext: this,
notePath: this.notePath notePath: this.notePath
}); });

View File

@ -203,7 +203,7 @@ export default class TabManager extends Component {
if (activate) { if (activate) {
this.activateTab(tabContext.tabId, false); this.activateTab(tabContext.tabId, false);
this.triggerEvent('tabNoteSwitchedAndActivated', { await this.triggerEvent('tabNoteSwitchedAndActivated', {
tabContext, tabContext,
notePath: tabContext.notePath // resolved note path notePath: tabContext.notePath // resolved note path
}); });

View File

@ -34,9 +34,8 @@ const TPL = `
<tr> <tr>
<th>Type:</th> <th>Type:</th>
<td> <td>
<span class="note-info-type"></span>, <span class="note-info-type"></span>
MIME:
<span class="note-info-mime"></span> <span class="note-info-mime"></span>
</td> </td>
</tr> </tr>
@ -70,9 +69,12 @@ export default class NoteInfoWidget extends CollapsibleWidget {
this.$type.text(note.type); this.$type.text(note.type);
this.$mime if (note.mime) {
.text(note.mime) this.$mime.text('(' + note.mime + ')');
.attr("title", note.mime); }
else {
this.$mime.empty();
}
} }
entitiesReloadedEvent({loadResults}) { entitiesReloadedEvent({loadResults}) {

View File

@ -858,8 +858,11 @@ export default class NoteTreeWidget extends TabAwareWidget {
this.toggleInt(this.isEnabled()); this.toggleInt(this.isEnabled());
const oldActiveNode = this.getActiveNode(); const oldActiveNode = this.getActiveNode();
let oldActiveNodeFocused = false;
if (oldActiveNode) { if (oldActiveNode) {
oldActiveNodeFocused = oldActiveNode.hasFocus();
oldActiveNode.setActive(false); oldActiveNode.setActive(false);
oldActiveNode.setFocus(false); oldActiveNode.setFocus(false);
} }
@ -872,8 +875,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
await this.expandToNote(this.tabContext.notePath); await this.expandToNote(this.tabContext.notePath);
} }
newActiveNode.setActive(true, {noEvents: true}); newActiveNode.setActive(true, {noEvents: true, noFocus: !oldActiveNodeFocused});
newActiveNode.makeVisible({scrollIntoView: true}); newActiveNode.makeVisible({scrollIntoView: true});
} }
} }
@ -902,7 +904,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
async entitiesReloadedEvent({loadResults}) { async entitiesReloadedEvent({loadResults}) {
const activeNode = this.getActiveNode(); const activeNode = this.getActiveNode();
const activeNodeFocused = activeNode ? activeNode.hasFocus() : false; const activeNodeFocused = activeNode && activeNode.hasFocus();
const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null; const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null;
const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null; const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null;
const nextNotePath = nextNode ? treeService.getNotePath(nextNode) : null; const nextNotePath = nextNode ? treeService.getNotePath(nextNode) : null;
@ -1025,7 +1027,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
} }
if (node) { if (node) {
node.setActive(true, {noEvents: true}); node.setActive(true, {noEvents: true, noFocus: true});
} }
else { else {
// this is used when original note has been deleted and we want to move the focus to the note above/below // this is used when original note has been deleted and we want to move the focus to the note above/below
@ -1040,7 +1042,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
// return focus if the previously active node was also focused // return focus if the previously active node was also focused
if (newActiveNode && activeNodeFocused) { if (newActiveNode && activeNodeFocused) {
newActiveNode.setFocus(true); await newActiveNode.setFocus(true);
} }
} }
} }
@ -1068,7 +1070,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
if (activeNotePath) { if (activeNotePath) {
const node = await this.getNodeFromPath(activeNotePath, true); const node = await this.getNodeFromPath(activeNotePath, true);
await node.setActive(true, {noEvents: true}); await node.setActive(true, {noEvents: true, noFocus: true});
} }
} }

View File

@ -96,9 +96,9 @@ async function anonymize() {
await db.run("UPDATE api_tokens SET token = 'API token value'"); await db.run("UPDATE api_tokens SET token = 'API token value'");
await db.run("UPDATE notes SET title = 'title'"); await db.run("UPDATE notes SET title = 'title'");
await db.run("UPDATE note_contents SET content = 'text'"); await db.run("UPDATE note_contents SET content = 'text' WHERE content IS NOT NULL");
await db.run("UPDATE note_revisions SET title = 'title'"); await db.run("UPDATE note_revisions SET title = 'title'");
await db.run("UPDATE note_revision_contents SET content = 'title'"); await db.run("UPDATE note_revision_contents SET content = 'title' WHERE content IS NOT NULL");
await db.run("UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'"); await db.run("UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'");
await db.run("UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name != 'template'"); await db.run("UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name != 'template'");
await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL"); await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");