mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
note cache refactoring WIP
This commit is contained in:
parent
78ea0b4ba9
commit
e3071e630a
@ -75,7 +75,7 @@ function updateTitleFormGroupVisibility() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$form.on('submit', () => {
|
$form.on('submit', () => {
|
||||||
const notePath = $autoComplete.getSelectedPath();
|
const notePath = $autoComplete.getSelectedNotePath();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
$dialog.modal('hide');
|
$dialog.modal('hide');
|
||||||
|
@ -269,7 +269,7 @@ function initKoPlugins() {
|
|||||||
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
|
||||||
noteAutocompleteService.initNoteAutocomplete($(element));
|
noteAutocompleteService.initNoteAutocomplete($(element));
|
||||||
|
|
||||||
$(element).setSelectedPath(bindingContext.$data.selectedPath);
|
$(element).setSelectedNotePath(bindingContext.$data.selectedPath);
|
||||||
|
|
||||||
$(element).on('autocomplete:selected', function (event, suggestion, dataset) {
|
$(element).on('autocomplete:selected', function (event, suggestion, dataset) {
|
||||||
bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
|
bindingContext.$data.selectedPath = $(element).val().trim() ? suggestion.path : '';
|
||||||
|
@ -52,7 +52,7 @@ async function cloneNotesTo(notePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$form.on('submit', () => {
|
$form.on('submit', () => {
|
||||||
const notePath = $noteAutoComplete.getSelectedPath();
|
const notePath = $noteAutoComplete.getSelectedNotePath();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
$dialog.modal('hide');
|
$dialog.modal('hide');
|
||||||
|
@ -38,7 +38,7 @@ async function includeNote(notePath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$form.on('submit', () => {
|
$form.on('submit', () => {
|
||||||
const notePath = $autoComplete.getSelectedPath();
|
const notePath = $autoComplete.getSelectedNotePath();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
$dialog.modal('hide');
|
$dialog.modal('hide');
|
||||||
|
@ -41,7 +41,7 @@ async function moveNotesTo(parentNoteId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$form.on('submit', () => {
|
$form.on('submit', () => {
|
||||||
const notePath = $noteAutoComplete.getSelectedPath();
|
const notePath = $noteAutoComplete.getSelectedNotePath();
|
||||||
|
|
||||||
if (notePath) {
|
if (notePath) {
|
||||||
$dialog.modal('hide');
|
$dialog.modal('hide');
|
||||||
|
@ -3,7 +3,7 @@ import appContext from "./app_context.js";
|
|||||||
import utils from './utils.js';
|
import utils from './utils.js';
|
||||||
|
|
||||||
// this key needs to have this value so it's hit by the tooltip
|
// this key needs to have this value so it's hit by the tooltip
|
||||||
const SELECTED_PATH_KEY = "data-note-path";
|
const SELECTED_NOTE_PATH_KEY = "data-note-path";
|
||||||
|
|
||||||
async function autocompleteSource(term, cb) {
|
async function autocompleteSource(term, cb) {
|
||||||
const result = await server.get('autocomplete'
|
const result = await server.get('autocomplete'
|
||||||
@ -12,8 +12,8 @@ async function autocompleteSource(term, cb) {
|
|||||||
|
|
||||||
if (result.length === 0) {
|
if (result.length === 0) {
|
||||||
result.push({
|
result.push({
|
||||||
pathTitle: "No results",
|
notePathTitle: "No results",
|
||||||
path: ""
|
notePath: ""
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ function clearText($el) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$el.setSelectedPath("");
|
$el.setSelectedNotePath("");
|
||||||
$el.autocomplete("val", "").trigger('change');
|
$el.autocomplete("val", "").trigger('change');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ function showRecentNotes($el) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$el.setSelectedPath("");
|
$el.setSelectedNotePath("");
|
||||||
$el.autocomplete("val", "");
|
$el.autocomplete("val", "");
|
||||||
$el.trigger('focus');
|
$el.trigger('focus');
|
||||||
}
|
}
|
||||||
@ -91,10 +91,10 @@ function initNoteAutocomplete($el, options) {
|
|||||||
}, [
|
}, [
|
||||||
{
|
{
|
||||||
source: autocompleteSource,
|
source: autocompleteSource,
|
||||||
displayKey: 'pathTitle',
|
displayKey: 'notePathTitle',
|
||||||
templates: {
|
templates: {
|
||||||
suggestion: function(suggestion) {
|
suggestion: function(suggestion) {
|
||||||
return suggestion.highlightedTitle;
|
return suggestion.highlightedNotePathTitle;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// we can't cache identical searches because notes can be created / renamed, new recent notes can be added
|
// we can't cache identical searches because notes can be created / renamed, new recent notes can be added
|
||||||
@ -102,7 +102,7 @@ function initNoteAutocomplete($el, options) {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$el.on('autocomplete:selected', (event, suggestion) => $el.setSelectedPath(suggestion.path));
|
$el.on('autocomplete:selected', (event, suggestion) => $el.setSelectedNotePath(suggestion.notePath));
|
||||||
$el.on('autocomplete:closed', () => {
|
$el.on('autocomplete:closed', () => {
|
||||||
if (!$el.val().trim()) {
|
if (!$el.val().trim()) {
|
||||||
clearText($el);
|
clearText($el);
|
||||||
@ -113,24 +113,24 @@ function initNoteAutocomplete($el, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$.fn.getSelectedPath = function () {
|
$.fn.getSelectedNotePath = function () {
|
||||||
if (!$(this).val().trim()) {
|
if (!$(this).val().trim()) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return $(this).attr(SELECTED_PATH_KEY);
|
return $(this).attr(SELECTED_NOTE_PATH_KEY);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.setSelectedPath = function (path) {
|
$.fn.setSelectedNotePath = function (notePath) {
|
||||||
path = path || "";
|
notePath = notePath || "";
|
||||||
|
|
||||||
$(this).attr(SELECTED_PATH_KEY, path);
|
$(this).attr(SELECTED_NOTE_PATH_KEY, notePath);
|
||||||
|
|
||||||
$(this)
|
$(this)
|
||||||
.closest(".input-group")
|
.closest(".input-group")
|
||||||
.find(".go-to-selected-note-button")
|
.find(".go-to-selected-note-button")
|
||||||
.toggleClass("disabled", !path.trim())
|
.toggleClass("disabled", !notePath.trim())
|
||||||
.attr(SELECTED_PATH_KEY, path); // we also set attr here so tooltip can be displayed
|
.attr(SELECTED_NOTE_PATH_KEY, notePath); // we also set attr here so tooltip can be displayed
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
|||||||
this.promotedAttributeChanged(event);
|
this.promotedAttributeChanged(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.setSelectedPath(valueAttr.value);
|
$input.setSelectedNotePath(valueAttr.value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ws.logError("Unknown attribute type=" + valueAttr.type);
|
ws.logError("Unknown attribute type=" + valueAttr.type);
|
||||||
@ -250,7 +250,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
|||||||
value = $attr.is(':checked') ? "true" : "false";
|
value = $attr.is(':checked') ? "true" : "false";
|
||||||
}
|
}
|
||||||
else if ($attr.prop("attribute-type") === "relation") {
|
else if ($attr.prop("attribute-type") === "relation") {
|
||||||
const selectedPath = $attr.getSelectedPath();
|
const selectedPath = $attr.getSelectedNotePath();
|
||||||
|
|
||||||
value = selectedPath ? treeService.getNoteIdFromNotePath(selectedPath) : "";
|
value = selectedPath ? treeService.getNoteIdFromNotePath(selectedPath) : "";
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ async function getAutocomplete(req) {
|
|||||||
results = await getRecentNotes(activeNoteId);
|
results = await getRecentNotes(activeNoteId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
results = await noteCacheService.findNotesWithFulltext(query);
|
results = await noteCacheService.findNotesForAutocomplete(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
const msTaken = Date.now() - timestampStarted;
|
const msTaken = Date.now() - timestampStarted;
|
||||||
@ -57,10 +57,9 @@ async function getRecentNotes(activeNoteId) {
|
|||||||
const title = noteCacheService.getNoteTitleForPath(rn.notePath.split('/'));
|
const title = noteCacheService.getNoteTitleForPath(rn.notePath.split('/'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
path: rn.notePath,
|
notePath: rn.notePath,
|
||||||
pathTitle: title,
|
notePathTitle: title,
|
||||||
highlightedTitle: title,
|
highlightedNotePathTitle: utils.escapeHtml(title)
|
||||||
noteTitle: noteCacheService.getNoteTitleFromPath(rn.notePath)
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -371,6 +371,8 @@ async function load() {
|
|||||||
branches = await getMappedRows(`SELECT branchId, noteId, parentNoteId, prefix FROM branches WHERE isDeleted = 0`,
|
branches = await getMappedRows(`SELECT branchId, noteId, parentNoteId, prefix FROM branches WHERE isDeleted = 0`,
|
||||||
row => new Branch(row));
|
row => new Branch(row));
|
||||||
|
|
||||||
|
attributeIndex = [];
|
||||||
|
|
||||||
attributes = await getMappedRows(`SELECT attributeId, noteId, type, name, value, isInheritable FROM attributes WHERE isDeleted = 0`,
|
attributes = await getMappedRows(`SELECT attributeId, noteId, type, name, value, isInheritable FROM attributes WHERE isDeleted = 0`,
|
||||||
row => new Attribute(row));
|
row => new Attribute(row));
|
||||||
|
|
||||||
@ -378,17 +380,7 @@ async function load() {
|
|||||||
loadedPromiseResolve();
|
loadedPromiseResolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const expression = {
|
class AndExp {
|
||||||
operator: 'and',
|
|
||||||
operands: [
|
|
||||||
{
|
|
||||||
operator: 'exists',
|
|
||||||
fieldName: 'hokus'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
class AndOp {
|
|
||||||
constructor(subExpressions) {
|
constructor(subExpressions) {
|
||||||
this.subExpressions = subExpressions;
|
this.subExpressions = subExpressions;
|
||||||
}
|
}
|
||||||
@ -402,7 +394,7 @@ class AndOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OrOp {
|
class OrExp {
|
||||||
constructor(subExpressions) {
|
constructor(subExpressions) {
|
||||||
this.subExpressions = subExpressions;
|
this.subExpressions = subExpressions;
|
||||||
}
|
}
|
||||||
@ -441,7 +433,7 @@ class NoteSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExistsOp {
|
class ExistsExp {
|
||||||
constructor(attributeType, attributeName) {
|
constructor(attributeType, attributeName) {
|
||||||
this.attributeType = attributeType;
|
this.attributeType = attributeType;
|
||||||
this.attributeName = attributeName;
|
this.attributeName = attributeName;
|
||||||
@ -469,7 +461,7 @@ class ExistsOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EqualsOp {
|
class EqualsExp {
|
||||||
constructor(attributeType, attributeName, attributeValue) {
|
constructor(attributeType, attributeName, attributeValue) {
|
||||||
this.attributeType = attributeType;
|
this.attributeType = attributeType;
|
||||||
this.attributeName = attributeName;
|
this.attributeName = attributeName;
|
||||||
@ -498,7 +490,7 @@ class EqualsOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoteContentFulltextOp {
|
class NoteContentFulltextExp {
|
||||||
constructor(tokens) {
|
constructor(tokens) {
|
||||||
this.tokens = tokens;
|
this.tokens = tokens;
|
||||||
}
|
}
|
||||||
@ -525,7 +517,7 @@ class NoteContentFulltextOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoteCacheFulltextOp {
|
class NoteCacheFulltextExp {
|
||||||
constructor(tokens) {
|
constructor(tokens) {
|
||||||
this.tokens = tokens;
|
this.tokens = tokens;
|
||||||
}
|
}
|
||||||
@ -569,7 +561,7 @@ class NoteCacheFulltextOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundTokens.length > 0) {
|
if (foundTokens.length > 0) {
|
||||||
const remainingTokens = tokens.filter(token => !foundTokens.includes(token));
|
const remainingTokens = this.tokens.filter(token => !foundTokens.includes(token));
|
||||||
|
|
||||||
this.searchDownThePath(parentNote, remainingTokens, [note.noteId], resultNoteSet, searchContext);
|
this.searchDownThePath(parentNote, remainingTokens, [note.noteId], resultNoteSet, searchContext);
|
||||||
}
|
}
|
||||||
@ -651,6 +643,21 @@ class NoteCacheFulltextOp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SearchResult {
|
||||||
|
constructor(notePathArray) {
|
||||||
|
this.notePathArray = notePathArray;
|
||||||
|
this.notePathTitle = getNoteTitleForPath(notePathArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
get notePath() {
|
||||||
|
return this.notePathArray.join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
get noteId() {
|
||||||
|
return this.notePathArray[this.notePathArray.length - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function findNotesWithExpression(expression) {
|
async function findNotesWithExpression(expression) {
|
||||||
|
|
||||||
const hoistedNote = notes[hoistedNoteService.getHoistedNoteId()];
|
const hoistedNote = notes[hoistedNoteService.getHoistedNoteId()];
|
||||||
@ -664,10 +671,27 @@ async function findNotesWithExpression(expression) {
|
|||||||
noteIdToNotePath: {}
|
noteIdToNotePath: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
expression.execute(allNoteSet, searchContext);
|
const noteSet = await expression.execute(allNoteSet, searchContext);
|
||||||
|
|
||||||
|
let searchResults = noteSet.notes
|
||||||
|
.map(note => searchContext.noteIdToNotePath[note.noteId] || getSomePath(note))
|
||||||
|
.filter(notePathArray => notePathArray.includes(hoistedNoteService.getHoistedNoteId()))
|
||||||
|
.map(notePathArray => new SearchResult(notePathArray));
|
||||||
|
|
||||||
|
// sort results by depth of the note. This is based on the assumption that more important results
|
||||||
|
// are closer to the note root.
|
||||||
|
searchResults.sort((a, b) => {
|
||||||
|
if (a.notePathArray.length === b.notePathArray.length) {
|
||||||
|
return a.notePathTitle < b.notePathTitle ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findNotesWithFulltext(query, searchInContent) {
|
return a.notePathArray.length < b.notePathArray.length ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return searchResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findNotesForAutocomplete(query) {
|
||||||
if (!query.trim().length) {
|
if (!query.trim().length) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -678,74 +702,54 @@ async function findNotesWithFulltext(query, searchInContent) {
|
|||||||
.split(/[ -]/)
|
.split(/[ -]/)
|
||||||
.filter(token => token !== '/'); // '/' is used as separator
|
.filter(token => token !== '/'); // '/' is used as separator
|
||||||
|
|
||||||
const cacheResults = findInNoteCache(tokens);
|
const expression = new NoteCacheFulltextExp(tokens);
|
||||||
|
|
||||||
const contentResults = searchInContent ? await findInNoteContent(tokens) : [];
|
let searchResults = await findNotesWithExpression(expression);
|
||||||
|
|
||||||
let results = cacheResults.concat(contentResults);
|
searchResults = searchResults.slice(0, 200);
|
||||||
|
|
||||||
if (hoistedNoteService.getHoistedNoteId() !== 'root') {
|
highlightSearchResults(searchResults, tokens);
|
||||||
results = results.filter(res => res.pathArray.includes(hoistedNoteService.getHoistedNoteId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort results by depth of the note. This is based on the assumption that more important results
|
|
||||||
// are closer to the note root.
|
|
||||||
results.sort((a, b) => {
|
|
||||||
if (a.pathArray.length === b.pathArray.length) {
|
|
||||||
return a.title < b.title ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.pathArray.length < b.pathArray.length ? -1 : 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
const apiResults = results.slice(0, 200).map(res => {
|
|
||||||
const notePath = res.pathArray.join('/');
|
|
||||||
|
|
||||||
|
return searchResults.map(result => {
|
||||||
return {
|
return {
|
||||||
noteId: res.noteId,
|
notePath: result.notePath,
|
||||||
branchId: res.branchId,
|
notePathTitle: result.notePathTitle,
|
||||||
path: notePath,
|
highlightedNotePathTitle: result.highlightedNotePathTitle
|
||||||
pathTitle: res.titleArray.join(' / '),
|
}
|
||||||
noteTitle: getNoteTitleFromPath(notePath)
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
highlightResults(apiResults, tokens);
|
|
||||||
|
|
||||||
return apiResults;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function highlightResults(results, allTokens) {
|
function highlightSearchResults(searchResults, tokens) {
|
||||||
// we remove < signs because they can cause trouble in matching and overwriting existing highlighted chunks
|
// we remove < signs because they can cause trouble in matching and overwriting existing highlighted chunks
|
||||||
// which would make the resulting HTML string invalid.
|
// which would make the resulting HTML string invalid.
|
||||||
// { and } are used for marking <b> and </b> tag (to avoid matches on single 'b' character)
|
// { and } are used for marking <b> and </b> tag (to avoid matches on single 'b' character)
|
||||||
allTokens = allTokens.map(token => token.replace('/[<\{\}]/g', ''));
|
tokens = tokens.map(token => token.replace('/[<\{\}]/g', ''));
|
||||||
|
|
||||||
// sort by the longest so we first highlight longest matches
|
// sort by the longest so we first highlight longest matches
|
||||||
allTokens.sort((a, b) => a.length > b.length ? -1 : 1);
|
tokens.sort((a, b) => a.length > b.length ? -1 : 1);
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of searchResults) {
|
||||||
const note = notes[result.noteId];
|
const note = notes[result.noteId];
|
||||||
|
|
||||||
|
result.highlightedNotePathTitle = result.notePathTitle;
|
||||||
|
|
||||||
for (const attr of note.attributes) {
|
for (const attr of note.attributes) {
|
||||||
if (allTokens.find(token => attr.name.includes(token) || attr.value.includes(token))) {
|
if (tokens.find(token => attr.name.includes(token) || attr.value.includes(token))) {
|
||||||
result.pathTitle += ` <small>${formatAttribute(attr)}</small>`;
|
result.highlightedNotePathTitle += ` <small>${formatAttribute(attr)}</small>`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.highlightedTitle = result.pathTitle;
|
for (const token of tokens) {
|
||||||
}
|
|
||||||
|
|
||||||
for (const token of allTokens) {
|
|
||||||
const tokenRegex = new RegExp("(" + utils.escapeRegExp(token) + ")", "gi");
|
const tokenRegex = new RegExp("(" + utils.escapeRegExp(token) + ")", "gi");
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of searchResults) {
|
||||||
result.highlightedTitle = result.highlightedTitle.replace(tokenRegex, "{$1}");
|
result.highlightedNotePathTitle = result.highlightedNotePathTitle.replace(tokenRegex, "{$1}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of searchResults) {
|
||||||
result.highlightedTitle = result.highlightedTitle
|
result.highlightedNotePathTitle = result.highlightedNotePathTitle
|
||||||
.replace(/{/g, "<b>")
|
.replace(/{/g, "<b>")
|
||||||
.replace(/}/g, "</b>");
|
.replace(/}/g, "</b>");
|
||||||
}
|
}
|
||||||
@ -839,17 +843,6 @@ function isInAncestor(noteId, ancestorNoteId) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteTitleFromPath(notePath) {
|
|
||||||
const pathArr = notePath.split("/");
|
|
||||||
|
|
||||||
if (pathArr.length === 1) {
|
|
||||||
return getNoteTitle(pathArr[0], 'root');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return getNoteTitle(pathArr[pathArr.length - 1], pathArr[pathArr.length - 2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNoteTitle(childNoteId, parentNoteId) {
|
function getNoteTitle(childNoteId, parentNoteId) {
|
||||||
const childNote = notes[childNoteId];
|
const childNote = notes[childNoteId];
|
||||||
const parentNote = notes[parentNoteId];
|
const parentNote = notes[parentNoteId];
|
||||||
@ -868,17 +861,17 @@ function getNoteTitle(childNoteId, parentNoteId) {
|
|||||||
return ((branch && branch.prefix) ? `${branch.prefix} - ` : '') + title;
|
return ((branch && branch.prefix) ? `${branch.prefix} - ` : '') + title;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteTitleArrayForPath(path) {
|
function getNoteTitleArrayForPath(notePathArray) {
|
||||||
const titles = [];
|
const titles = [];
|
||||||
|
|
||||||
if (path[0] === hoistedNoteService.getHoistedNoteId() && path.length === 1) {
|
if (notePathArray[0] === hoistedNoteService.getHoistedNoteId() && notePathArray.length === 1) {
|
||||||
return [ getNoteTitle(hoistedNoteService.getHoistedNoteId()) ];
|
return [ getNoteTitle(hoistedNoteService.getHoistedNoteId()) ];
|
||||||
}
|
}
|
||||||
|
|
||||||
let parentNoteId = 'root';
|
let parentNoteId = 'root';
|
||||||
let hoistedNotePassed = false;
|
let hoistedNotePassed = false;
|
||||||
|
|
||||||
for (const noteId of path) {
|
for (const noteId of notePathArray) {
|
||||||
// start collecting path segment titles only after hoisted note
|
// start collecting path segment titles only after hoisted note
|
||||||
if (hoistedNotePassed) {
|
if (hoistedNotePassed) {
|
||||||
const title = getNoteTitle(noteId, parentNoteId);
|
const title = getNoteTitle(noteId, parentNoteId);
|
||||||
@ -896,8 +889,8 @@ function getNoteTitleArrayForPath(path) {
|
|||||||
return titles;
|
return titles;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoteTitleForPath(path) {
|
function getNoteTitleForPath(notePathArray) {
|
||||||
const titles = getNoteTitleArrayForPath(path);
|
const titles = getNoteTitleArrayForPath(notePathArray);
|
||||||
|
|
||||||
return titles.join(' / ');
|
return titles.join(' / ');
|
||||||
}
|
}
|
||||||
@ -1153,10 +1146,9 @@ sqlInit.dbReady.then(() => utils.stopWatch("Note cache load", load));
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
loadedPromise,
|
loadedPromise,
|
||||||
findNotesWithFulltext,
|
findNotesForAutocomplete,
|
||||||
getNotePath,
|
getNotePath,
|
||||||
getNoteTitleForPath,
|
getNoteTitleForPath,
|
||||||
getNoteTitleFromPath,
|
|
||||||
isAvailable,
|
isAvailable,
|
||||||
isArchived,
|
isArchived,
|
||||||
isInAncestor,
|
isInAncestor,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user