mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 13:39:01 +01:00 
			
		
		
		
	add "top" label to keep notes on top, allow sorting by label, #2343
This commit is contained in:
		
							parent
							
								
									df4cf80be4
								
							
						
					
					
						commit
						211ff90ee8
					
				@ -189,6 +189,7 @@ const ATTR_HELP = {
 | 
				
			|||||||
        "runAtHour": "On which hour should this run. Should be used together with <code>#run=hourly</code>. Can be defined multiple times for more runs during the day.",
 | 
					        "runAtHour": "On which hour should this run. Should be used together with <code>#run=hourly</code>. Can be defined multiple times for more runs during the day.",
 | 
				
			||||||
        "disableInclusion": "scripts with this label won't be included into parent script execution.",
 | 
					        "disableInclusion": "scripts with this label won't be included into parent script execution.",
 | 
				
			||||||
        "sorted": "keeps child notes sorted by title alphabetically",
 | 
					        "sorted": "keeps child notes sorted by title alphabetically",
 | 
				
			||||||
 | 
					        "top": "keep given note on top in its parent (applies only on sorted parents)",
 | 
				
			||||||
        "hidePromotedAttributes": "Hide promoted attributes on this note",
 | 
					        "hidePromotedAttributes": "Hide promoted attributes on this note",
 | 
				
			||||||
        "readOnly": "editor is in read only mode. Works only for text and code notes.",
 | 
					        "readOnly": "editor is in read only mode. Works only for text and code notes.",
 | 
				
			||||||
        "autoReadOnlyDisabled": "text/code notes can be set automatically into read mode when they are too large. You can disable this behavior on per-note basis by adding this label to the note",
 | 
					        "autoReadOnlyDisabled": "text/code notes can be set automatically into read mode when they are too large. You can disable this behavior on per-note basis by adding this label to the note",
 | 
				
			||||||
@ -208,6 +209,8 @@ const ATTR_HELP = {
 | 
				
			|||||||
        "inbox": "default inbox location for new notes",
 | 
					        "inbox": "default inbox location for new notes",
 | 
				
			||||||
        "hoistedInbox": "default inbox location for new notes when hoisted to some ancestor of this note",
 | 
					        "hoistedInbox": "default inbox location for new notes when hoisted to some ancestor of this note",
 | 
				
			||||||
        "sqlConsoleHome": "default location of SQL console notes",
 | 
					        "sqlConsoleHome": "default location of SQL console notes",
 | 
				
			||||||
 | 
					        "bookmarked": "note with this label will appear in bookmarks",
 | 
				
			||||||
 | 
					        "bookmarkFolder": "note with this label will appear in bookmarks as folder (allowing access to its children)"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "relation": {
 | 
					    "relation": {
 | 
				
			||||||
        "runOnNoteCreation": "executes when note is created on backend",
 | 
					        "runOnNoteCreation": "executes when note is created on backend",
 | 
				
			||||||
 | 
				
			|||||||
@ -49,6 +49,8 @@ const BUILTIN_ATTRIBUTES = [
 | 
				
			|||||||
    { type: 'label', name: 'mapRootNoteId' },
 | 
					    { type: 'label', name: 'mapRootNoteId' },
 | 
				
			||||||
    { type: 'label', name: 'bookmarked' },
 | 
					    { type: 'label', name: 'bookmarked' },
 | 
				
			||||||
    { type: 'label', name: 'bookmarkFolder' },
 | 
					    { type: 'label', name: 'bookmarkFolder' },
 | 
				
			||||||
 | 
					    { type: 'label', name: 'sorted' },
 | 
				
			||||||
 | 
					    { type: 'label', name: 'top' },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // relation names
 | 
					    // relation names
 | 
				
			||||||
    { type: 'relation', name: 'runOnNoteCreation', isDangerous: true },
 | 
					    { type: 'relation', name: 'runOnNoteCreation', isDangerous: true },
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,10 @@ eventService.subscribe(eventService.NOTE_TITLE_CHANGED, note => {
 | 
				
			|||||||
eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED ], ({ entityName, entity }) => {
 | 
					eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED ], ({ entityName, entity }) => {
 | 
				
			||||||
    if (entityName === 'attributes') {
 | 
					    if (entityName === 'attributes') {
 | 
				
			||||||
        runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity);
 | 
					        runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (entity.type === 'label' && entity.name === 'sorted') {
 | 
				
			||||||
 | 
					            handleSortedAttribute(entity);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (entityName === 'notes') {
 | 
					    else if (entityName === 'notes') {
 | 
				
			||||||
        runAttachedRelations(entity, 'runOnNoteChange', entity);
 | 
					        runAttachedRelations(entity, 'runOnNoteChange', entity);
 | 
				
			||||||
@ -83,17 +87,7 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) =>
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (entity.type === 'label' && entity.name === 'sorted') {
 | 
					        else if (entity.type === 'label' && entity.name === 'sorted') {
 | 
				
			||||||
            treeService.sortNotesIfNeeded(entity.noteId);
 | 
					            handleSortedAttribute(entity);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (entity.isInheritable) {
 | 
					 | 
				
			||||||
                const note = becca.notes[entity.noteId];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (note) {
 | 
					 | 
				
			||||||
                    for (const noteId of note.getSubtreeNoteIds()) {
 | 
					 | 
				
			||||||
                        treeService.sortNotesIfNeeded(noteId);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else if (entityName === 'notes') {
 | 
					    else if (entityName === 'notes') {
 | 
				
			||||||
@ -122,6 +116,20 @@ function processInverseRelations(entityName, entity, handler) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function handleSortedAttribute(entity) {
 | 
				
			||||||
 | 
					    treeService.sortNotesIfNeeded(entity.noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (entity.isInheritable) {
 | 
				
			||||||
 | 
					        const note = becca.notes[entity.noteId];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (note) {
 | 
				
			||||||
 | 
					            for (const noteId of note.getSubtreeNoteIds()) {
 | 
				
			||||||
 | 
					                treeService.sortNotesIfNeeded(noteId);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => {
 | 
					eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => {
 | 
				
			||||||
    processInverseRelations(entityName, entity, (definition, note, targetNote) => {
 | 
					    processInverseRelations(entityName, entity, (definition, note, targetNote) => {
 | 
				
			||||||
        // we need to make sure that also target's inverse attribute exists and if not, then create it
 | 
					        // we need to make sure that also target's inverse attribute exists and if not, then create it
 | 
				
			||||||
 | 
				
			|||||||
@ -108,9 +108,9 @@ function loadSubtreeNoteIds(parentNoteId, subtreeNoteIds) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function sortNotes(parentNoteId, sortBy = 'title', reverse = false, foldersFirst = false) {
 | 
					function sortNotes(parentNoteId, customSortBy = 'title', reverse = false, foldersFirst = false) {
 | 
				
			||||||
    if (!sortBy) {
 | 
					    if (!customSortBy) {
 | 
				
			||||||
        sortBy = 'title';
 | 
					        customSortBy = 'title';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sql.transactional(() => {
 | 
					    sql.transactional(() => {
 | 
				
			||||||
@ -129,10 +129,41 @@ function sortNotes(parentNoteId, sortBy = 'title', reverse = false, foldersFirst
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let aEl = normalize(a[sortBy]);
 | 
					            function fetchValue(note, key) {
 | 
				
			||||||
            let bEl = normalize(b[sortBy]);
 | 
					                const rawValue = ['title', 'dateCreated', 'dateModified'].includes(key)
 | 
				
			||||||
 | 
					                    ? note[key]
 | 
				
			||||||
 | 
					                    : note.getLabelValue(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return aEl < bEl ? -1 : 1;
 | 
					                return normalize(rawValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            function compare(a, b) {
 | 
				
			||||||
 | 
					                return b === null || b === undefined || a < b ? -1 : 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const topAEl = fetchValue(a, 'top');
 | 
				
			||||||
 | 
					            const topBEl = fetchValue(b, 'top');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            console.log(a.title, topAEl);
 | 
				
			||||||
 | 
					            console.log(b.title, topBEl);
 | 
				
			||||||
 | 
					            console.log("comp", compare(topAEl, topBEl) && !reverse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (topAEl !== topBEl) {
 | 
				
			||||||
 | 
					                // since "top" should not be reversible, we'll reverse it once more to nullify this effect
 | 
				
			||||||
 | 
					                return compare(topAEl, topBEl) * (reverse ? -1 : 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const customAEl = fetchValue(a, customSortBy);
 | 
				
			||||||
 | 
					            const customBEl = fetchValue(b, customSortBy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (customAEl !== customBEl) {
 | 
				
			||||||
 | 
					                return compare(customAEl, customBEl);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const titleAEl = fetchValue(a, 'title');
 | 
				
			||||||
 | 
					            const titleBEl = fetchValue(b, 'title');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return compare(titleAEl, titleBEl);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (reverse) {
 | 
					        if (reverse) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user