mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	better detection of changes in attributes and how they affect notes
This commit is contained in:
		@@ -23,8 +23,8 @@ class Attribute {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /** @returns {NoteShort} */
 | 
					    /** @returns {NoteShort} */
 | 
				
			||||||
    async getNote() {
 | 
					    getNote() {
 | 
				
			||||||
        return await this.treeCache.getNote(this.noteId);
 | 
					        return this.treeCache.notes[this.noteId];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    get jsonValue() {
 | 
					    get jsonValue() {
 | 
				
			||||||
@@ -39,6 +39,34 @@ class Attribute {
 | 
				
			|||||||
    get toString() {
 | 
					    get toString() {
 | 
				
			||||||
        return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name}, value=${this.value})`;
 | 
					        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;
 | 
				
			||||||
@@ -437,6 +437,35 @@ class NoteShort {
 | 
				
			|||||||
        return targets;
 | 
					        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.
 | 
					     * Clear note's attributes cache to force fresh reload for next attribute request.
 | 
				
			||||||
     * Cache is note instance scoped.
 | 
					     * Cache is note instance scoped.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,10 @@ class TreeCache {
 | 
				
			|||||||
            if (attr.type === 'relation' && attr.name === 'template' && !(attr.value in existingNotes) && !noteIds.has(attr.value)) {
 | 
					            if (attr.type === 'relation' && attr.name === 'template' && !(attr.value in existingNotes) && !noteIds.has(attr.value)) {
 | 
				
			||||||
                missingNoteIds.push(attr.value);
 | 
					                missingNoteIds.push(attr.value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!(attr.noteId in existingNotes) && !noteIds.has(attr.noteId)) {
 | 
				
			||||||
 | 
					                missingNoteIds.push(attr.noteId);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (missingNoteIds.length > 0) {
 | 
					        if (missingNoteIds.length > 0) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -270,13 +270,30 @@ export default class NoteDetailWidget extends TabAwareWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async entitiesReloadedEvent({loadResults}) {
 | 
					    async entitiesReloadedEvent({loadResults}) {
 | 
				
			||||||
        // FIXME: we should test what happens when the loaded note is deleted
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (loadResults.isNoteContentReloaded(this.noteId, this.componentId)
 | 
					        if (loadResults.isNoteContentReloaded(this.noteId, this.componentId)
 | 
				
			||||||
            || (loadResults.isNoteReloaded(this.noteId, this.componentId) && (this.type !== await this.getWidgetType() || this.mime !== this.note.mime))) {
 | 
					            || (loadResults.isNoteReloaded(this.noteId, this.componentId) && (this.type !== await this.getWidgetType() || this.mime !== this.note.mime))) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.handleEvent('noteTypeMimeChanged', {noteId: this.noteId});
 | 
					            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() {
 | 
					    beforeUnloadEvent() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -268,13 +268,8 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
 | 
				
			|||||||
        $attr.prop("attribute-id", result.attributeId);
 | 
					        $attr.prop("attribute-id", result.attributeId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    entitiesReloadedEvent({loadResults}) {console.log("loadResults", loadResults);
 | 
					    entitiesReloadedEvent({loadResults}) {
 | 
				
			||||||
        // relation/label definitions are very often inherited by tree or template,
 | 
					        if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) {
 | 
				
			||||||
        // 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))) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.refresh();
 | 
					            this.refresh();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user