mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 09:58:32 +02:00
UI fixes to search definition + backend support
This commit is contained in:
parent
3fa2535862
commit
d7e46263be
6
package-lock.json
generated
6
package-lock.json
generated
@ -4122,9 +4122,9 @@
|
|||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||||
},
|
},
|
||||||
"helmet": {
|
"helmet": {
|
||||||
"version": "4.3.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.4.1.tgz",
|
||||||
"integrity": "sha512-WsafDyKsIexB0+pUNkq3rL1rB5GVAghR68TP8ssM9DPEMzfBiluEQlVzJ/FEj6Vq2Ag3CNuxf7aYMjXrN0X49Q=="
|
"integrity": "sha512-G8tp0wUMI7i8wkMk2xLcEvESg5PiCitFMYgGRc/PwULB0RVhTP5GFdxOwvJwp9XVha8CuS8mnhmE8I/8dx/pbw=="
|
||||||
},
|
},
|
||||||
"hosted-git-info": {
|
"hosted-git-info": {
|
||||||
"version": "2.8.5",
|
"version": "2.8.5",
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
"express": "4.17.1",
|
"express": "4.17.1",
|
||||||
"express-session": "1.17.1",
|
"express-session": "1.17.1",
|
||||||
"fs-extra": "9.0.1",
|
"fs-extra": "9.0.1",
|
||||||
"helmet": "4.3.1",
|
"helmet": "4.4.1",
|
||||||
"html": "1.0.0",
|
"html": "1.0.0",
|
||||||
"html2plaintext": "2.1.2",
|
"html2plaintext": "2.1.2",
|
||||||
"http-proxy-agent": "4.0.1",
|
"http-proxy-agent": "4.0.1",
|
||||||
|
@ -47,7 +47,7 @@ async function createSearchNote(opts = {}) {
|
|||||||
const note = await server.post('search-note');
|
const note = await server.post('search-note');
|
||||||
|
|
||||||
const attrsToUpdate = [
|
const attrsToUpdate = [
|
||||||
opts.subTreeNoteId ? { type: 'label', name: 'subTreeNoteId', value: opts.subTreeNoteId } : undefined,
|
opts.ancestor ? { type: 'relation', name: 'ancestor', value: opts.ancestorNoteId } : undefined,
|
||||||
opts.searchString ? { type: 'label', name: 'searchString', value: opts.searchString } : undefined
|
opts.searchString ? { type: 'label', name: 'searchString', value: opts.searchString } : undefined
|
||||||
].filter(attr => !!attr);
|
].filter(attr => !!attr);
|
||||||
|
|
||||||
|
@ -67,8 +67,8 @@ export default class DialogCommandExecutor extends Component {
|
|||||||
appContext.triggerCommand('focusOnDetail', {tabId: tabContext.tabId});
|
appContext.triggerCommand('focusOnDetail', {tabId: tabContext.tabId});
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchNotesCommand({searchString, subTreeNoteId}) {
|
async searchNotesCommand({searchString, ancestorNoteId}) {
|
||||||
const searchNote = await dateNoteService.createSearchNote({searchString, subTreeNoteId});
|
const searchNote = await dateNoteService.createSearchNote({searchString, ancestorNoteId});
|
||||||
|
|
||||||
const tabContext = await appContext.tabManager.openTabWithNote(searchNote.noteId, true);
|
const tabContext = await appContext.tabManager.openTabWithNote(searchNote.noteId, true);
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ export default class DialogCommandExecutor extends Component {
|
|||||||
async searchInSubtreeCommand({notePath}) {
|
async searchInSubtreeCommand({notePath}) {
|
||||||
const noteId = treeService.getNoteIdFromNotePath(notePath);
|
const noteId = treeService.getNoteIdFromNotePath(notePath);
|
||||||
|
|
||||||
this.searchNotesCommand({subTreeNoteId: noteId});
|
this.searchNotesCommand({ancestorNoteId: noteId});
|
||||||
}
|
}
|
||||||
|
|
||||||
showBackendLogCommand() {
|
showBackendLogCommand() {
|
||||||
|
@ -23,6 +23,8 @@ async function autocompleteSourceForCKEditor(queryText) {
|
|||||||
highlightedNotePathTitle: row.highlightedNotePathTitle
|
highlightedNotePathTitle: row.highlightedNotePathTitle
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
}, {
|
||||||
|
allowCreatingNotes: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -34,7 +36,7 @@ async function autocompleteSource(term, cb, options = {}) {
|
|||||||
+ '?query=' + encodeURIComponent(term)
|
+ '?query=' + encodeURIComponent(term)
|
||||||
+ '&activeNoteId=' + activeNoteId);
|
+ '&activeNoteId=' + activeNoteId);
|
||||||
|
|
||||||
if (term.trim().length >= 1) {
|
if (term.trim().length >= 1 && options.allowCreatingNotes) {
|
||||||
results = [
|
results = [
|
||||||
{
|
{
|
||||||
action: 'create-note',
|
action: 'create-note',
|
||||||
|
@ -48,6 +48,10 @@ export default class NoteListWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkRenderStatus() {
|
checkRenderStatus() {
|
||||||
|
// console.log("this.isIntersecting", this.isIntersecting);
|
||||||
|
// console.log(`${this.noteIdRefreshed} === ${this.noteId}`, this.noteIdRefreshed === this.noteId);
|
||||||
|
// console.log("this.shownNoteId !== this.noteId", this.shownNoteId !== this.noteId);
|
||||||
|
|
||||||
if (this.isIntersecting
|
if (this.isIntersecting
|
||||||
&& this.noteIdRefreshed === this.noteId
|
&& this.noteIdRefreshed === this.noteId
|
||||||
&& this.shownNoteId !== this.noteId) {
|
&& this.shownNoteId !== this.noteId) {
|
||||||
@ -62,6 +66,11 @@ export default class NoteListWidget extends TabAwareWidget {
|
|||||||
await noteListRenderer.renderList();
|
await noteListRenderer.renderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We have this event so that we evaluate intersection only after note detail is loaded.
|
||||||
|
* If it's evaluated before note detail then it's clearly intersected (visible) although after note detail load
|
||||||
|
* it is not intersected (visible) anymore.
|
||||||
|
*/
|
||||||
noteDetailRefreshedEvent({tabId}) {
|
noteDetailRefreshedEvent({tabId}) {
|
||||||
if (!this.isTab(tabId)) {
|
if (!this.isTab(tabId)) {
|
||||||
return;
|
return;
|
||||||
@ -72,6 +81,17 @@ export default class NoteListWidget extends TabAwareWidget {
|
|||||||
setTimeout(() => this.checkRenderStatus(), 100);
|
setTimeout(() => this.checkRenderStatus(), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchRefreshedEvent({tabId}) {
|
||||||
|
if (!this.isTab(tabId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.noteIdRefreshed = this.noteId;
|
||||||
|
this.shownNoteId = null;
|
||||||
|
|
||||||
|
this.checkRenderStatus();
|
||||||
|
}
|
||||||
|
|
||||||
autoBookDisabledEvent({tabContext}) {
|
autoBookDisabledEvent({tabContext}) {
|
||||||
if (this.isTab(tabContext.tabId)) {
|
if (this.isTab(tabContext.tabId)) {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
@ -4,6 +4,7 @@ import server from "../services/server.js";
|
|||||||
import TabAwareWidget from "./tab_aware_widget.js";
|
import TabAwareWidget from "./tab_aware_widget.js";
|
||||||
import treeCache from "../services/tree_cache.js";
|
import treeCache from "../services/tree_cache.js";
|
||||||
import ws from "../services/ws.js";
|
import ws from "../services/ws.js";
|
||||||
|
import utils from "../services/utils.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="search-definition-widget">
|
<div class="search-definition-widget">
|
||||||
@ -64,9 +65,9 @@ const TPL = `
|
|||||||
<tr>
|
<tr>
|
||||||
<td>Add search option:</td>
|
<td>Add search option:</td>
|
||||||
<td colspan="2" class="add-search-option">
|
<td colspan="2" class="add-search-option">
|
||||||
<button type="button" class="btn btn-sm" data-search-option-add="descendantOf">
|
<button type="button" class="btn btn-sm" data-search-option-add="ancestor">
|
||||||
<span class="bx bx-filter-alt"></span>
|
<span class="bx bx-filter-alt"></span>
|
||||||
descendant of
|
ancestor
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm" data-search-option-add="fastSearch"
|
<button type="button" class="btn btn-sm" data-search-option-add="fastSearch"
|
||||||
@ -109,16 +110,16 @@ const TPL = `
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tbody class="search-options">
|
<tbody class="search-options">
|
||||||
<tr data-search-option-conf="descendantOf">
|
<tr data-search-option-conf="ancestor">
|
||||||
<td title="Matched notes must be within subtree of given note.">
|
<td title="Matched notes must be within subtree of given note.">
|
||||||
Descendant of: </td>
|
Ancestor: </td>
|
||||||
<td>
|
<td>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input class="descendant-of form-control" placeholder="search for note by its name">
|
<input class="ancestor form-control" placeholder="search for note by its name">
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="bx bx-x icon-action" data-search-option-del="descendantOf"></span>
|
<span class="bx bx-x icon-action" data-search-option-del="ancestor"></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr data-search-option-conf="fastSearch">
|
<tr data-search-option-conf="fastSearch">
|
||||||
@ -185,17 +186,19 @@ const TPL = `
|
|||||||
<span class="bx bx-x icon-action"></span>
|
<span class="bx bx-x icon-action"></span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<div style="display: flex; justify-content: space-evenly">
|
<div style="display: flex; justify-content: space-evenly">
|
||||||
<button type="button" class="btn btn-sm">
|
<button type="button" class="btn btn-sm search-button">
|
||||||
<span class="bx bx-search"></span>
|
<span class="bx bx-search"></span>
|
||||||
Search
|
Search
|
||||||
|
|
||||||
<kbd>enter</kbd>
|
<kbd>enter</kbd>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-sm">
|
<button type="button" class="btn btn-sm search-and-execute-button">
|
||||||
<span class="bx bxs-zap"></span>
|
<span class="bx bxs-zap"></span>
|
||||||
Search & Execute actions
|
Search & Execute actions
|
||||||
</button>
|
</button>
|
||||||
@ -257,6 +260,11 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
this.$searchString = this.$widget.find(".search-string");
|
this.$searchString = this.$widget.find(".search-string");
|
||||||
this.$searchString.on('input', () => this.searchStringSU.scheduleUpdate());
|
this.$searchString.on('input', () => this.searchStringSU.scheduleUpdate());
|
||||||
|
utils.bindElShortcut(this.$searchString, 'return', async () => {
|
||||||
|
await this.searchStringSU.updateNowIfNecessary();
|
||||||
|
|
||||||
|
this.refreshResults();
|
||||||
|
});
|
||||||
|
|
||||||
this.searchStringSU = new SpacedUpdate(async () => {
|
this.searchStringSU = new SpacedUpdate(async () => {
|
||||||
const searchString = this.$searchString.val();
|
const searchString = this.$searchString.val();
|
||||||
@ -270,13 +278,13 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
this.$descendantOf = this.$widget.find('.descendant-of');
|
this.$ancestor = this.$widget.find('.ancestor');
|
||||||
noteAutocompleteService.initNoteAutocomplete(this.$descendantOf);
|
noteAutocompleteService.initNoteAutocomplete(this.$ancestor);
|
||||||
|
|
||||||
this.$descendantOf.on('autocomplete:closed', async () => {
|
this.$ancestor.on('autocomplete:closed', async () => {
|
||||||
const descendantOfNoteId = this.$descendantOf.getSelectedNoteId();
|
const ancestorOfNoteId = this.$ancestor.getSelectedNoteId();
|
||||||
|
|
||||||
await this.setAttribute('relation', 'descendantOf', descendantOfNoteId);
|
await this.setAttribute('relation', 'ancestor', ancestorOfNoteId);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$widget.on('click', '[data-search-option-add]', async event => {
|
this.$widget.on('click', '[data-search-option-add]', async event => {
|
||||||
@ -292,8 +300,8 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
else if (searchOption === 'includeArchivedNotes') {
|
else if (searchOption === 'includeArchivedNotes') {
|
||||||
await this.setAttribute('label', 'includeArchivedNotes');
|
await this.setAttribute('label', 'includeArchivedNotes');
|
||||||
}
|
}
|
||||||
else if (searchOption === 'descendantOf') {
|
else if (searchOption === 'ancestor') {
|
||||||
await this.setAttribute('relation', 'descendantOf', 'root');
|
await this.setAttribute('relation', 'ancestor', 'root');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
@ -364,6 +372,11 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.$searchButton = this.$widget.find('.search-button');
|
||||||
|
this.$searchButton.on('click', () => this.refreshResults());
|
||||||
|
|
||||||
|
this.$searchAndExecuteButton = this.$widget.find('.search-and-execute-button');
|
||||||
}
|
}
|
||||||
|
|
||||||
async setAttribute(type, name, value = '') {
|
async setAttribute(type, name, value = '') {
|
||||||
@ -374,25 +387,27 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
async refreshResults() {
|
async refreshResults() {
|
||||||
await treeCache.reloadNotes([this.noteId]);
|
await treeCache.reloadNotes([this.noteId]);
|
||||||
|
|
||||||
|
this.triggerEvent('searchRefreshed', {tabId: this.tabContext.tabId});
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshWithNote(note) {
|
async refreshWithNote(note) {
|
||||||
this.$component.show();
|
this.$component.show();
|
||||||
this.$searchString.val(this.note.getLabelValue('searchString'));
|
this.$searchString.val(this.note.getLabelValue('searchString'));
|
||||||
|
|
||||||
for (const attrName of ['includeArchivedNotes', 'descendantOf', 'fastSearch', 'orderBy']) {
|
for (const attrName of ['includeArchivedNotes', 'ancestor', 'fastSearch', 'orderBy']) {
|
||||||
const has = note.hasLabel(attrName) || note.hasRelation(attrName);
|
const has = note.hasLabel(attrName) || note.hasRelation(attrName);
|
||||||
|
|
||||||
this.$widget.find(`[data-search-option-add='${attrName}'`).toggle(!has);
|
this.$widget.find(`[data-search-option-add='${attrName}'`).toggle(!has);
|
||||||
this.$widget.find(`[data-search-option-conf='${attrName}'`).toggle(has);
|
this.$widget.find(`[data-search-option-conf='${attrName}'`).toggle(has);
|
||||||
}
|
}
|
||||||
|
|
||||||
const descendantOfNoteId = this.note.getRelationValue('descendantOf');
|
const ancestorNoteId = this.note.getRelationValue('ancestor');
|
||||||
const descendantOfNote = descendantOfNoteId ? await treeCache.getNote(descendantOfNoteId, true) : null;
|
const ancestorNote = ancestorNoteId ? await treeCache.getNote(ancestorNoteId, true) : null;
|
||||||
|
|
||||||
this.$descendantOf
|
this.$ancestor
|
||||||
.val(descendantOfNote ? descendantOfNote.title : "")
|
.val(ancestorNote ? ancestorNote.title : "")
|
||||||
.setSelectedNotePath(descendantOfNoteId);
|
.setSelectedNotePath(ancestorNoteId);
|
||||||
|
|
||||||
if (note.hasLabel('orderBy')) {
|
if (note.hasLabel('orderBy')) {
|
||||||
this.$orderBy.val(note.getLabelValue('orderBy'));
|
this.$orderBy.val(note.getLabelValue('orderBy'));
|
||||||
@ -401,7 +416,9 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
|
|
||||||
this.$actionOptions.empty();
|
this.$actionOptions.empty();
|
||||||
|
|
||||||
for (const actionAttr of this.note.getLabels('action')) {
|
const actionLabels = this.note.getLabels('action');
|
||||||
|
|
||||||
|
for (const actionAttr of actionLabels) {
|
||||||
let actionDef;
|
let actionDef;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -418,7 +435,9 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
|
|||||||
this.$actionOptions.append($actionConf);
|
this.$actionOptions.append($actionConf);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refreshResults(); // important specifically when this search note was not yet refreshed
|
this.$searchAndExecuteButton.css('visibility', actionLabels.length > 0 ? 'visible' : 'hidden');
|
||||||
|
|
||||||
|
//this.refreshResults(); // important specifically when this search note was not yet refreshed
|
||||||
}
|
}
|
||||||
|
|
||||||
focusOnSearchDefinitionEvent() {
|
focusOnSearchDefinitionEvent() {
|
||||||
|
@ -34,9 +34,11 @@ async function searchFromNote(req) {
|
|||||||
}
|
}
|
||||||
else if (searchString) {
|
else if (searchString) {
|
||||||
const searchContext = new SearchContext({
|
const searchContext = new SearchContext({
|
||||||
includeNoteContent: note.getLabelValue('includeNoteContent') === 'true',
|
fastSearch: note.hasLabel('fastSearch'),
|
||||||
subTreeNoteId: note.getLabelValue('subTreeNoteId'),
|
ancestorNoteId: note.getRelationValue('ancestor'),
|
||||||
excludeArchived: true,
|
includeArchivedNotes: note.hasLabel('includeArchivedNotes'),
|
||||||
|
orderBy: note.getLabelValue('orderBy'),
|
||||||
|
orderDirection: note.getLabelValue('orderDirection'),
|
||||||
fuzzyAttributeSearch: false
|
fuzzyAttributeSearch: false
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,8 +109,8 @@ function getRelatedNotes(req) {
|
|||||||
const attr = req.body;
|
const attr = req.body;
|
||||||
|
|
||||||
const searchSettings = {
|
const searchSettings = {
|
||||||
includeNoteContent: false,
|
fastSearch: true,
|
||||||
excludeArchived: true,
|
includeArchivedNotes: false,
|
||||||
fuzzyAttributeSearch: false
|
fuzzyAttributeSearch: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
28
src/services/search/expressions/ancestor.js
Normal file
28
src/services/search/expressions/ancestor.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Expression = require('./expression');
|
||||||
|
const NoteSet = require('../note_set');
|
||||||
|
const log = require('../../log');
|
||||||
|
const noteCache = require('../../note_cache/note_cache');
|
||||||
|
|
||||||
|
class AncestorExp extends Expression {
|
||||||
|
constructor(ancestorNoteId) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.ancestorNoteId = ancestorNoteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(inputNoteSet, executionContext) {
|
||||||
|
const ancestorNote = noteCache.notes[this.ancestorNoteId];
|
||||||
|
|
||||||
|
if (!ancestorNote) {
|
||||||
|
log.error(`Subtree note '${this.ancestorNoteId}' was not not found.`);
|
||||||
|
|
||||||
|
return new NoteSet([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NoteSet(ancestorNote.subtreeNotes).intersection(inputNoteSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AncestorExp;
|
@ -44,7 +44,7 @@ class OrderByAndLimitExp extends Expression {
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.limit >= 0) {
|
if (this.limit > 0) {
|
||||||
notes = notes.slice(0, this.limit);
|
notes = notes.slice(0, this.limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const Expression = require('./expression');
|
|
||||||
const NoteSet = require('../note_set');
|
|
||||||
const log = require('../../log');
|
|
||||||
const noteCache = require('../../note_cache/note_cache');
|
|
||||||
|
|
||||||
class SubTreeExp extends Expression {
|
|
||||||
constructor(subTreeNoteId) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.subTreeNoteId = subTreeNoteId;
|
|
||||||
}
|
|
||||||
|
|
||||||
execute(inputNoteSet, executionContext) {
|
|
||||||
const subTreeNote = noteCache.notes[this.subTreeNoteId];
|
|
||||||
|
|
||||||
if (!subTreeNote) {
|
|
||||||
log.error(`Subtree note '${this.subTreeNoteId}' was not not found.`);
|
|
||||||
|
|
||||||
return new NoteSet([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new NoteSet(subTreeNote.subtreeNotes).intersection(inputNoteSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SubTreeExp;
|
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
class SearchContext {
|
class SearchContext {
|
||||||
constructor(params = {}) {
|
constructor(params = {}) {
|
||||||
this.includeNoteContent = !!params.includeNoteContent;
|
this.fastSearch = !!params.fastSearch;
|
||||||
this.subTreeNoteId = params.subTreeNoteId;
|
this.ancestorNoteId = params.ancestorNoteId;
|
||||||
this.excludeArchived = !!params.excludeArchived;
|
this.includeArchivedNotes = !!params.includeArchivedNotes;
|
||||||
|
this.orderBy = params.orderBy;
|
||||||
|
this.orderDirection = params.orderDirection;
|
||||||
this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch;
|
this.fuzzyAttributeSearch = !!params.fuzzyAttributeSearch;
|
||||||
this.highlightedTokens = [];
|
this.highlightedTokens = [];
|
||||||
this.originalQuery = "";
|
this.originalQuery = "";
|
||||||
|
@ -15,7 +15,7 @@ const NoteCacheFlatTextExp = require('../expressions/note_cache_flat_text.js');
|
|||||||
const NoteContentProtectedFulltextExp = require('../expressions/note_content_protected_fulltext.js');
|
const NoteContentProtectedFulltextExp = require('../expressions/note_content_protected_fulltext.js');
|
||||||
const NoteContentUnprotectedFulltextExp = require('../expressions/note_content_unprotected_fulltext.js');
|
const NoteContentUnprotectedFulltextExp = require('../expressions/note_content_unprotected_fulltext.js');
|
||||||
const OrderByAndLimitExp = require('../expressions/order_by_and_limit.js');
|
const OrderByAndLimitExp = require('../expressions/order_by_and_limit.js');
|
||||||
const SubTreeExp = require("../expressions/sub_tree.js");
|
const AncestorExp = require("../expressions/ancestor.js");
|
||||||
const buildComparator = require('./build_comparator.js');
|
const buildComparator = require('./build_comparator.js');
|
||||||
const ValueExtractor = require('../value_extractor.js');
|
const ValueExtractor = require('../value_extractor.js');
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ function getFulltext(tokens, searchContext) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchContext.includeNoteContent) {
|
if (!searchContext.fastSearch) {
|
||||||
return new OrExp([
|
return new OrExp([
|
||||||
new NoteCacheFlatTextExp(tokens),
|
new NoteCacheFlatTextExp(tokens),
|
||||||
new NoteContentProtectedFulltextExp('*=*', tokens),
|
new NoteContentProtectedFulltextExp('*=*', tokens),
|
||||||
@ -408,12 +408,25 @@ function getExpression(tokens, searchContext, level = 0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parse({fulltextTokens, expressionTokens, searchContext}) {
|
function parse({fulltextTokens, expressionTokens, searchContext}) {
|
||||||
return AndExp.of([
|
let exp = AndExp.of([
|
||||||
searchContext.excludeArchived ? new PropertyComparisonExp("isarchived", buildComparator("=", "false")) : null,
|
searchContext.includeArchivedNotes ? null : new PropertyComparisonExp("isarchived", buildComparator("=", "false")),
|
||||||
searchContext.subTreeNoteId ? new SubTreeExp(searchContext.subTreeNoteId) : null,
|
searchContext.ancestorNoteId ? new AncestorExp(searchContext.ancestorNoteId) : null,
|
||||||
getFulltext(fulltextTokens, searchContext),
|
getFulltext(fulltextTokens, searchContext),
|
||||||
getExpression(expressionTokens, searchContext)
|
getExpression(expressionTokens, searchContext)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (searchContext.orderBy && searchContext.orderBy !== 'relevancy') {
|
||||||
|
const filterExp = exp;
|
||||||
|
|
||||||
|
exp = new OrderByAndLimitExp([{
|
||||||
|
valueExtractor: new ValueExtractor(['note', searchContext.orderBy]),
|
||||||
|
direction: searchContext.orderDirection
|
||||||
|
}], 0);
|
||||||
|
|
||||||
|
exp.subExpression = filterExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = parse;
|
module.exports = parse;
|
||||||
|
@ -111,8 +111,8 @@ function searchTrimmedNotes(query, searchContext) {
|
|||||||
|
|
||||||
function searchNotesForAutocomplete(query) {
|
function searchNotesForAutocomplete(query) {
|
||||||
const searchContext = new SearchContext({
|
const searchContext = new SearchContext({
|
||||||
includeNoteContent: false,
|
fastSearch: true,
|
||||||
excludeArchived: true,
|
includeArchivedNotes: false,
|
||||||
fuzzyAttributeSearch: true
|
fuzzyAttributeSearch: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user