import noteAutocompleteService from "../services/note_autocomplete.js"; import SpacedUpdate from "../services/spaced_update.js"; import server from "../services/server.js"; import TabAwareWidget from "./tab_aware_widget.js"; import treeCache from "../services/tree_cache.js"; import ws from "../services/ws.js"; const TPL = `
Search string:
Add search option:
Descendant of:
Fast search
Include archived notes
Order by
Delete matched note
Rename attribute name:
From:
To:
`; export default class SearchDefinitionWidget extends TabAwareWidget { static getType() { return "search"; } renderTitle(note) { return { show: note.type === 'search', activate: true, $title: 'Search' }; } doRender() { this.$widget = $(TPL); this.$component = this.$widget.find('.search-definition-widget'); this.contentSized(); this.overflowing(); this.$searchString = this.$widget.find(".search-string"); this.$searchString.on('input', () => this.searchStringSU.scheduleUpdate()); this.searchStringSU = new SpacedUpdate(async () => { const searchString = this.$searchString.val(); await this.setAttribute('label', 'searchString', searchString); if (this.note.title.startsWith('Search: ')) { await server.put(`notes/${this.noteId}/change-title`, { title: 'Search: ' + (searchString.length < 30 ? searchString : `${searchString.substr(0, 30)}…`) }); } }, 1000); this.$descendantOf = this.$widget.find('.descendant-of'); noteAutocompleteService.initNoteAutocomplete(this.$descendantOf); this.$descendantOf.on('autocomplete:closed', async () => { const descendantOfNoteId = this.$descendantOf.getSelectedNoteId(); await this.setAttribute('relation', 'descendantOf', descendantOfNoteId); }); this.$widget.on('click', '[data-search-option-add]', async event => { const searchOption = $(event.target).attr('data-search-option-add'); if (searchOption === 'fastSearch') { await this.setAttribute('label', 'fastSearch'); } else if (searchOption === 'orderBy') { await this.setAttribute('label', 'orderBy', 'relevancy'); await this.setAttribute('label', 'orderDirection', 'asc'); } else if (searchOption === 'includeArchivedNotes') { await this.setAttribute('label', 'includeArchivedNotes'); } else if (searchOption === 'descendantOf') { await this.setAttribute('relation', 'descendantOf', 'root'); } this.refresh(); }); this.$widget.on('click', '[data-search-option-del]', async event => { async function deleteAttr(note, attrName) { for (const attr of note.getOwnedAttributes()) { if (attr.name === attrName) { await server.remove(`notes/${note.noteId}/attributes/${attr.attributeId}`); } } } const searchOption = $(event.target).attr('data-search-option-del'); await deleteAttr(this.note, searchOption); if (searchOption === 'orderBy') { await deleteAttr(this.note, 'orderDirection'); } await ws.waitForMaxKnownEntityChangeId(); this.refresh(); }); this.$orderBy = this.$widget.find('select[name=orderBy]'); this.$orderBy.on('change', async () => { const orderBy = this.$orderBy.val(); await this.setAttribute('label', 'orderBy', orderBy); }); this.$orderDirection = this.$widget.find('select[name=orderDirection]'); this.$orderDirection.on('change', async () => { const orderDirection = this.$orderDirection.val(); await this.setAttribute('label', 'orderDirection', orderDirection); }); } async setAttribute(type, name, value = '') { await server.put(`notes/${this.noteId}/set-attribute`, { type, name, value }); await ws.waitForMaxKnownEntityChangeId(); } async refreshResults() { await treeCache.reloadNotes([this.noteId]); } async refreshWithNote(note) { this.$component.show(); this.$searchString.val(this.note.getLabelValue('searchString')); for (const attrName of ['includeArchivedNotes', 'descendantOf', 'fastSearch', 'orderBy']) { const has = note.hasLabel(attrName) || note.hasRelation(attrName); this.$widget.find(`[data-search-option-add='${attrName}'`).toggle(!has); this.$widget.find(`[data-search-option-conf='${attrName}'`).toggle(has); } const descendantOfNoteId = this.note.getRelationValue('descendantOf'); const descendantOfNote = descendantOfNoteId ? await treeCache.getNote(descendantOfNoteId, true) : null; this.$descendantOf .val(descendantOfNote ? descendantOfNote.title : "") .setSelectedNotePath(descendantOfNoteId); if (note.hasLabel('orderBy')) { this.$orderBy.val(note.getLabelValue('orderBy')); this.$orderDirection.val(note.getLabelValue('orderDirection') || 'asc'); } this.refreshResults(); // important specifically when this search note was not yet refreshed } focusOnSearchDefinitionEvent() { this.$searchString.focus(); } getContent() { return ''; } }