better detection of changes in attributes and how they affect notes

This commit is contained in:
zadam 2020-06-09 22:59:22 +02:00
parent 1db892d22f
commit 212b719ee9
5 changed files with 86 additions and 13 deletions

View File

@ -23,8 +23,8 @@ class Attribute {
}
/** @returns {NoteShort} */
async getNote() {
return await this.treeCache.getNote(this.noteId);
getNote() {
return this.treeCache.notes[this.noteId];
}
get jsonValue() {
@ -39,6 +39,34 @@ class Attribute {
get toString() {
return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name}, value=${this.value})`;
}
/**
* @return {boolean} - returns true if this attribute has the potential to influence the note in the argument.
* That can happen in multiple ways:
* 1. attribute is owned by the note
* 2. attribute is owned by the template of the note
* 3. attribute is owned by some note's ancestor and is inheritable
*/
isAffecting(affectedNote) {
const attrNote = this.getNote();
const owningNotes = [affectedNote, ...affectedNote.getTemplateNotes()];
for (const owningNote of owningNotes) {
if (owningNote.noteId === attrNote.noteId) {
return true;
}
}
if (this.isInheritable) {
for (const owningNote of owningNotes) {
if (owningNote.hasAncestor(attrNote)) {
return true;
}
}
}
return false;
}
}
export default Attribute;
export default Attribute;

View File

@ -437,6 +437,35 @@ class NoteShort {
return targets;
}
/**
* @returns {NoteShort[]}
*/
getTemplateNotes() {
const relations = this.getRelations('template');
return relations.map(rel => this.treeCache.notes[rel.value]);
}
hasAncestor(ancestorNote) {
if (this.noteId === ancestorNote.noteId) {
return true;
}
for (const templateNote of this.getTemplateNotes()) {
if (templateNote.hasAncestor(ancestorNote)) {
return true;
}
}
for (const parentNote of this.getParentNotes()) {
if (parentNote.hasAncestor(ancestorNote)) {console.log(parentNote);
return true;
}
}
return false;
}
/**
* Clear note's attributes cache to force fresh reload for next attribute request.
* Cache is note instance scoped.

View File

@ -54,6 +54,10 @@ class TreeCache {
if (attr.type === 'relation' && attr.name === 'template' && !(attr.value in existingNotes) && !noteIds.has(attr.value)) {
missingNoteIds.push(attr.value);
}
if (!(attr.noteId in existingNotes) && !noteIds.has(attr.noteId)) {
missingNoteIds.push(attr.noteId);
}
}
if (missingNoteIds.length > 0) {
@ -283,4 +287,4 @@ class TreeCache {
const treeCache = new TreeCache();
export default treeCache;
export default treeCache;

View File

@ -270,13 +270,30 @@ export default class NoteDetailWidget extends TabAwareWidget {
}
async entitiesReloadedEvent({loadResults}) {
// FIXME: we should test what happens when the loaded note is deleted
if (loadResults.isNoteContentReloaded(this.noteId, this.componentId)
|| (loadResults.isNoteReloaded(this.noteId, this.componentId) && (this.type !== await this.getWidgetType() || this.mime !== this.note.mime))) {
this.handleEvent('noteTypeMimeChanged', {noteId: this.noteId});
}
else {
const attrs = loadResults.getAttributes();
const label = attrs.find(attr =>
attr.type === 'label'
&& ['readOnly', 'autoReadOnlyDisabled', 'cssClass', 'bookZoomLevel'].includes(attr.name)
&& attr.isAffecting(this.note));
const relation = attrs.find(attr =>
attr.type === 'relation'
&& ['template', 'runOnNoteView', 'renderNote'].includes(attr.name)
&& attr.isAffecting(this.note));
if (label || relation) {
// probably incorrect event
// calling this.refresh() is not enough since the event needs to be propagated to children as well
this.handleEvent('noteTypeMimeChanged', {noteId: this.noteId});
}
}
}
beforeUnloadEvent() {

View File

@ -268,13 +268,8 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
$attr.prop("attribute-id", result.attributeId);
}
entitiesReloadedEvent({loadResults}) {console.log("loadResults", loadResults);
// relation/label definitions are very often inherited by tree or template,
// it's difficult to detect inheritance so we will
if (loadResults.getAttributes(this.componentId).find(attr =>
attr.noteId === this.noteId
|| ['label-definition', 'relation-definition'].includes(attr.type))) {
entitiesReloadedEvent({loadResults}) {
if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) {
this.refresh();
}
}