From 85eb50ed0f6a35e8f07a913953a5c407f78965a3 Mon Sep 17 00:00:00 2001 From: azivner Date: Thu, 19 Apr 2018 20:59:44 -0400 Subject: [PATCH] autocomplete with prefixes --- .../javascripts/dialogs/branch_prefix.js | 2 +- src/public/javascripts/dialogs/event_log.js | 2 +- .../javascripts/dialogs/recent_changes.js | 2 +- src/public/javascripts/services/link.js | 6 +- src/public/javascripts/services/tree.js | 2 +- src/services/autocomplete.js | 115 ++++++++++++------ 6 files changed, 84 insertions(+), 45 deletions(-) diff --git a/src/public/javascripts/dialogs/branch_prefix.js b/src/public/javascripts/dialogs/branch_prefix.js index 6efd87b9a..292877c8e 100644 --- a/src/public/javascripts/dialogs/branch_prefix.js +++ b/src/public/javascripts/dialogs/branch_prefix.js @@ -25,7 +25,7 @@ async function showDialog() { $treePrefixInput.val(branch.prefix).focus(); - const noteTitle = treeUtils.getNoteTitle(currentNode.data.noteId); + const noteTitle = await treeUtils.getNoteTitle(currentNode.data.noteId); $noteTitle.html(noteTitle); } diff --git a/src/public/javascripts/dialogs/event_log.js b/src/public/javascripts/dialogs/event_log.js index 45be1241f..fada33f19 100644 --- a/src/public/javascripts/dialogs/event_log.js +++ b/src/public/javascripts/dialogs/event_log.js @@ -22,7 +22,7 @@ async function showDialog() { const dateTime = utils.formatDateTime(utils.parseDate(event.dateAdded)); if (event.noteId) { - const noteLink = linkService.createNoteLink(event.noteId).prop('outerHTML'); + const noteLink = await linkService.createNoteLink(event.noteId).prop('outerHTML'); event.comment = event.comment.replace('', noteLink); } diff --git a/src/public/javascripts/dialogs/recent_changes.js b/src/public/javascripts/dialogs/recent_changes.js index 4ed22eb46..38507e1ac 100644 --- a/src/public/javascripts/dialogs/recent_changes.js +++ b/src/public/javascripts/dialogs/recent_changes.js @@ -40,7 +40,7 @@ async function showDialog() { noteLink = change.current_title; } else { - noteLink = linkService.createNoteLink(change.noteId, change.title); + noteLink = await linkService.createNoteLink(change.noteId, change.title); } changesListEl.append($('
  • ') diff --git a/src/public/javascripts/services/link.js b/src/public/javascripts/services/link.js index 89d37bdc4..9a648f34d 100644 --- a/src/public/javascripts/services/link.js +++ b/src/public/javascripts/services/link.js @@ -23,11 +23,11 @@ function getNodePathFromLabel(label) { return null; } -function createNoteLink(notePath, noteTitle) { +async function createNoteLink(notePath, noteTitle) { if (!noteTitle) { const noteId = treeUtils.getNoteIdFromNotePath(notePath); - noteTitle = treeUtils.getNoteTitle(noteId); + noteTitle = await treeUtils.getNoteTitle(noteId); } const noteLink = $("", { @@ -75,7 +75,7 @@ function goToLink(e) { } function addLinkToEditor(linkTitle, linkHref) { - const editor = noteDetailText.getEditor();Rum + const editor = noteDetailText.getEditor(); editor.model.change( writer => { const insertPosition = editor.model.document.selection.getFirstPosition(); diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 0ead17615..f48b70532 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -203,7 +203,7 @@ async function showParentList(noteId, node) { item = $("").attr("title", "Current note").append(title); } else { - item = linkService.createNoteLink(notePath, title); + item = await linkService.createNoteLink(notePath, title); } $parentListList.append($("
  • ").append(item)); diff --git a/src/services/autocomplete.js b/src/services/autocomplete.js index 39f7cda82..0ff728c02 100644 --- a/src/services/autocomplete.js +++ b/src/services/autocomplete.js @@ -8,10 +8,15 @@ let noteIds; const childToParent = {}; const hideInAutocomplete = {}; +// key is 'childNoteId-parentNoteId' as a replacement for branchId which we don't use here +let prefixes = {}; + async function load() { noteTitles = await sql.getMap(`SELECT noteId, LOWER(title) FROM notes WHERE isDeleted = 0 AND isProtected = 0`); noteIds = Object.keys(noteTitles); + prefixes = await sql.getMap(`SELECT noteId || '-' || parentNoteId, prefix FROM branches WHERE prefix IS NOT NULL AND prefix != ''`); + const relations = await sql.getRows(`SELECT noteId, parentNoteId FROM branches WHERE isDeleted = 0`); for (const rel of relations) { @@ -39,19 +44,27 @@ function getResults(query) { continue; } - const title = noteTitles[noteId]; - const foundTokens = []; - - for (const token of tokens) { - if (title.includes(token)) { - foundTokens.push(token); - } + const parents = childToParent[noteId]; + if (!parents) { + continue; } - if (foundTokens.length > 0) { - const remainingTokens = tokens.filter(token => !foundTokens.includes(token)); + for (const parentNoteId of parents) { + const prefix = prefixes[noteId + '-' + parentNoteId]; + const title = (prefix || '') + ' ' + noteTitles[noteId]; + const foundTokens = []; - search(childToParent[noteId], remainingTokens, [noteId], results); + for (const token of tokens) { + if (title.includes(token)) { + foundTokens.push(token); + } + } + + if (foundTokens.length > 0) { + const remainingTokens = tokens.filter(token => !foundTokens.includes(token)); + + search(parentNoteId, remainingTokens, [noteId], results); + } } } @@ -60,13 +73,9 @@ function getResults(query) { return results; } -function search(noteIds, tokens, path, results) { - if (!noteIds || noteIds.length === 0) { - return; - } - +function search(noteId, tokens, path, results) { if (tokens.length === 0) { - const retPath = getSomePath(noteIds, path); + const retPath = getSomePath(noteId, path); if (retPath) { const noteTitle = getNoteTitle(retPath); @@ -80,16 +89,22 @@ function search(noteIds, tokens, path, results) { return; } - for (const noteId of noteIds) { + const parents = childToParent[noteId]; + if (!parents) { + return; + } + + for (const parentNoteId of parents) { if (results.length >= 200) { return; } - if (noteId === 'root' || hideInAutocomplete[noteId]) { + if (parentNoteId === 'root' || hideInAutocomplete[parentNoteId]) { continue; } - const title = noteTitles[noteId]; + const prefix = prefixes[noteId + '-' + parentNoteId]; + const title = (prefix || '') + ' ' + noteTitles[noteId]; const foundTokens = []; for (const token of tokens) { @@ -101,39 +116,44 @@ function search(noteIds, tokens, path, results) { if (foundTokens.length > 0) { const remainingTokens = tokens.filter(token => !foundTokens.includes(token)); - search(childToParent[noteId], remainingTokens, path.concat([noteId]), results); + search(parentNoteId, remainingTokens, path.concat([noteId]), results); } else { - search(childToParent[noteId], tokens, path.concat([noteId]), results); + search(parentNoteId, tokens, path.concat([noteId]), results); } } } function getNoteTitle(path) { - const titles = path.map(noteId => noteTitles[noteId]); + const titles = []; + + let parentNoteId = 'root'; + + for (const noteId of path) { + const prefix = prefixes[noteId + '-' + parentNoteId]; + const title = (prefix ? (prefix + ' - ') : '') + noteTitles[noteId]; + + titles.push(title); + parentNoteId = noteId; + } return titles.join(' / '); } -function getSomePath(noteIds, path) { - for (const noteId of noteIds) { - if (noteId === 'root') { - path.reverse(); +function getSomePath(noteId, path) { + if (noteId === 'root') { + path.reverse(); - return path; - } + return path; + } - if (hideInAutocomplete[noteId]) { - continue; - } + const parents = childToParent[noteId]; + if (!parents || parents.length === 0) { + return false; + } - const parents = childToParent[noteId]; - - if (!parents || parents.length === 0) { - continue; - } - - const retPath = getSomePath(parents, path.concat([noteId])); + for (const parentNoteId of parents) { + const retPath = getSomePath(parentNoteId, path.concat([noteId])); if (retPath) { return retPath; @@ -155,6 +175,25 @@ syncTableService.addListener(async (entityName, entityId) => { noteTitles[note.noteId] = note.title; } } + else if (entityName === 'branches') { + const branch = await repository.getBranch(entityId); + + if (childToParent[branch.noteId]) { + childToParent[branch.noteId] = childToParent[branch.noteId].filter(noteId => noteId !== branch.parentNoteId) + } + + if (branch.isDeleted) { + delete prefixes[branch.noteId + '-' + branch.parentNoteId]; + } + else { + if (branch.prefix) { + prefixes[branch.noteId + '-' + branch.parentNoteId] = branch.prefix; + } + + childToParent[branch.noteId] = childToParent[branch.noteId] || []; + childToParent[branch.noteId].push(branch.parentNoteId); + } + } else if (entityName === 'labels') { const label = await repository.getLabel(entityId);