mirror of
https://github.com/zadam/trilium.git
synced 2025-11-13 00:35:50 +01:00
improvements to notemap in relation to search
This commit is contained in:
@@ -83,12 +83,13 @@ function getNeighbors(note, depth) {
|
||||
|
||||
function getLinkMap(req) {
|
||||
const mapRootNote = becca.getNote(req.params.noteId);
|
||||
// if the map root itself has ignore (journal typically) then there wouldn't be anything to display so
|
||||
// if the map root itself has exclude attribute (journal typically) then there wouldn't be anything to display, so
|
||||
// we'll just ignore it
|
||||
const ignoreExcludeFromNoteMap = mapRootNote.hasLabel('excludeFromNoteMap');
|
||||
const subtree = mapRootNote.getSubtree({includeArchived: false, resolveSearch: true});
|
||||
|
||||
const noteIds = new Set(
|
||||
mapRootNote.getSubtreeNotes(false)
|
||||
subtree.notes
|
||||
.filter(note => ignoreExcludeFromNoteMap || !note.hasLabel('excludeFromNoteMap'))
|
||||
.map(note => note.noteId)
|
||||
);
|
||||
@@ -142,8 +143,9 @@ function getTreeMap(req) {
|
||||
// if the map root itself has ignore (journal typically) then there wouldn't be anything to display so
|
||||
// we'll just ignore it
|
||||
const ignoreExcludeFromNoteMap = mapRootNote.hasLabel('excludeFromNoteMap');
|
||||
const subtree = mapRootNote.getSubtree({includeArchived: false, resolveSearch: true});
|
||||
|
||||
const notes = mapRootNote.getSubtreeNotes(false)
|
||||
const notes = subtree.notes
|
||||
.filter(note => ignoreExcludeFromNoteMap || !note.hasLabel('excludeFromNoteMap'))
|
||||
.filter(note => {
|
||||
if (note.type !== 'image' || note.getChildNotes().length > 0) {
|
||||
@@ -170,25 +172,40 @@ function getTreeMap(req) {
|
||||
|
||||
const links = [];
|
||||
|
||||
for (const branch of Object.values(becca.branches)) {
|
||||
if (!noteIds.has(branch.parentNoteId) || !noteIds.has(branch.noteId)) {
|
||||
for (const {parentNoteId, childNoteId} of subtree.relationships) {
|
||||
if (!noteIds.has(parentNoteId) || !noteIds.has(childNoteId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
links.push({
|
||||
id: branch.branchId,
|
||||
sourceNoteId: branch.parentNoteId,
|
||||
targetNoteId: branch.noteId
|
||||
sourceNoteId: parentNoteId,
|
||||
targetNoteId: childNoteId
|
||||
});
|
||||
}
|
||||
|
||||
const noteIdToDescendantCountMap = buildDescendantCountMap();
|
||||
|
||||
updateDescendantCountMapForSearch(noteIdToDescendantCountMap, subtree.relationships);
|
||||
|
||||
return {
|
||||
notes: notes,
|
||||
noteIdToDescendantCountMap: buildDescendantCountMap(),
|
||||
noteIdToDescendantCountMap: noteIdToDescendantCountMap,
|
||||
links: links
|
||||
};
|
||||
}
|
||||
|
||||
function updateDescendantCountMapForSearch(noteIdToDescendantCountMap, relationships) {
|
||||
for (const {parentNoteId, childNoteId} of relationships) {
|
||||
const parentNote = becca.notes[parentNoteId];
|
||||
if (!parentNote || parentNote.type !== 'search') {
|
||||
continue;
|
||||
}
|
||||
|
||||
noteIdToDescendantCountMap[parentNote.noteId] = noteIdToDescendantCountMap[parentNoteId] || 0;
|
||||
noteIdToDescendantCountMap[parentNote.noteId] += noteIdToDescendantCountMap[childNoteId] || 1;
|
||||
}
|
||||
}
|
||||
|
||||
function removeImages(document) {
|
||||
const images = document.getElementsByTagName('img');
|
||||
while (images.length > 0) {
|
||||
|
||||
@@ -2,49 +2,11 @@
|
||||
|
||||
const becca = require('../../becca/becca');
|
||||
const SearchContext = require('../../services/search/search_context');
|
||||
const log = require('../../services/log');
|
||||
const scriptService = require('../../services/script');
|
||||
const searchService = require('../../services/search/services/search');
|
||||
const bulkActionService = require("../../services/bulk_actions");
|
||||
const cls = require("../../services/cls");
|
||||
const {formatAttrForSearch} = require("../../services/attribute_formatter");
|
||||
|
||||
function searchFromNoteInt(note) {
|
||||
let searchResultNoteIds, highlightedTokens;
|
||||
|
||||
const searchScript = note.getRelationValue('searchScript');
|
||||
const searchString = note.getLabelValue('searchString');
|
||||
|
||||
if (searchScript) {
|
||||
searchResultNoteIds = searchFromRelation(note, 'searchScript');
|
||||
highlightedTokens = [];
|
||||
} else {
|
||||
const searchContext = new SearchContext({
|
||||
fastSearch: note.hasLabel('fastSearch'),
|
||||
ancestorNoteId: note.getRelationValue('ancestor'),
|
||||
ancestorDepth: note.getLabelValue('ancestorDepth'),
|
||||
includeArchivedNotes: note.hasLabel('includeArchivedNotes'),
|
||||
orderBy: note.getLabelValue('orderBy'),
|
||||
orderDirection: note.getLabelValue('orderDirection'),
|
||||
limit: note.getLabelValue('limit'),
|
||||
debug: note.hasLabel('debug'),
|
||||
fuzzyAttributeSearch: false
|
||||
});
|
||||
|
||||
searchResultNoteIds = searchService.findResultsWithQuery(searchString, searchContext)
|
||||
.map(sr => sr.noteId);
|
||||
|
||||
highlightedTokens = searchContext.highlightedTokens;
|
||||
}
|
||||
|
||||
// we won't return search note's own noteId
|
||||
// also don't allow root since that would force infinite cycle
|
||||
return {
|
||||
searchResultNoteIds: searchResultNoteIds.filter(resultNoteId => !['root', note.noteId].includes(resultNoteId)),
|
||||
highlightedTokens
|
||||
};
|
||||
}
|
||||
|
||||
function searchFromNote(req) {
|
||||
const note = becca.getNote(req.params.noteId);
|
||||
|
||||
@@ -61,7 +23,7 @@ function searchFromNote(req) {
|
||||
return [400, `Note ${req.params.noteId} is not a search note.`]
|
||||
}
|
||||
|
||||
return searchFromNoteInt(note);
|
||||
return searchService.searchFromNote(note);
|
||||
}
|
||||
|
||||
function searchAndExecute(req) {
|
||||
@@ -80,48 +42,11 @@ function searchAndExecute(req) {
|
||||
return [400, `Note ${req.params.noteId} is not a search note.`]
|
||||
}
|
||||
|
||||
const {searchResultNoteIds} = searchFromNoteInt(note);
|
||||
const {searchResultNoteIds} = searchService.searchFromNote(note);
|
||||
|
||||
bulkActionService.executeActions(note, searchResultNoteIds);
|
||||
}
|
||||
|
||||
function searchFromRelation(note, relationName) {
|
||||
const scriptNote = note.getRelationTarget(relationName);
|
||||
|
||||
if (!scriptNote) {
|
||||
log.info(`Search note's relation ${relationName} has not been found.`);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!scriptNote.isJavaScript() || scriptNote.getScriptEnv() !== 'backend') {
|
||||
log.info(`Note ${scriptNote.noteId} is not executable.`);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!note.isContentAvailable()) {
|
||||
log.info(`Note ${scriptNote.noteId} is not available outside of protected session.`);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
const result = scriptService.executeNote(scriptNote, { originEntity: note });
|
||||
|
||||
if (!Array.isArray(result)) {
|
||||
log.info(`Result from ${scriptNote.noteId} is not an array.`);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
if (result.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// we expect either array of noteIds (strings) or notes, in that case we extract noteIds ourselves
|
||||
return typeof result[0] === 'string' ? result : result.map(item => item.noteId);
|
||||
}
|
||||
|
||||
function quickSearch(req) {
|
||||
const {searchString} = req.params;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ function getSubtreeSize(req) {
|
||||
return [404, `Note ${noteId} was not found.`];
|
||||
}
|
||||
|
||||
const subTreeNoteIds = note.getSubtreeNotes().map(note => note.noteId);
|
||||
const subTreeNoteIds = note.getSubtreeNoteIds();
|
||||
|
||||
sql.fillParamList(subTreeNoteIds);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user