From 5006e1095ab1b34c0c3ad15dd33a2fd4b5a60438 Mon Sep 17 00:00:00 2001 From: Peter Stuifzand Date: Wed, 28 Oct 2020 20:01:25 +0100 Subject: [PATCH] Add search queries inside the tree --- editor/src/editor.js | 53 +++++++++++++++++++++++++++++++---------- editor/src/search.js | 56 +++++++++++++++++++++++++------------------- file.go | 8 +++++++ list-editor/index.js | 27 +++++++++++++++++---- list-editor/store.js | 30 +++++++++++++++++++++++- 5 files changed, 132 insertions(+), 42 deletions(-) diff --git a/editor/src/editor.js b/editor/src/editor.js index 371b7b4..569b215 100644 --- a/editor/src/editor.js +++ b/editor/src/editor.js @@ -27,7 +27,6 @@ import formulaFunctions from './formula' moment.locale('nl') const math = create(all) - math.import(formulaFunctions) function isMultiline(input) { @@ -109,8 +108,8 @@ function showSearchResultsExtended(element, template, searchTool, query, input, $lc.offset(pos) } - var templateText = he.decode(document.getElementById(template).innerHTML); - var rendered = Mustache.render(templateText, { + let templateText = he.decode(document.getElementById(template).innerHTML); + let rendered = Mustache.render(templateText, { page: value.trim().replace(/\s+/g, '_'), results: results }, {}, ['[[', ']]']); @@ -467,7 +466,7 @@ function Editor(holder, input) { if (insideSearch) { let query = value.substring(start + 1, end); showSearchResults(commandSearch, query, input, value, 'command').then(results => { - if (query.length > 0 && result.length === 0) { + if (query.length > 0 && results.length === 0) { searchEnabled = false } }) @@ -481,27 +480,58 @@ function Editor(holder, input) { } }) }) - editor.on('stop-editing', function (input) { - $(input).parents('.list-item').removeClass('active'); + + editor.on('stop-editing', function (input, id) { + let $input = $(input); + $input.parents('.list-item').removeClass('active'); $('#link-complete').off() PrismJS.highlightAll() mermaid.init() renderGraphs(); - }) + if ($input.val()) { + let query = $input.val(); + let res = query.match(/{{query: ([^}]+)}}/) + if (res) { + search.startQuery(res[1]) + .then(hits => { + let results = _.flatMap(hits, hit => { + return [ + { + text: "[[" + hit.title + "]]", + indented: 0, + fold: 'open', + hidden: false, + fleeting: true + }, + { + text: hit.line, + indented: 1, + fold: 'open', + hidden: false, + fleeting: true + } + ] + }) + editor.replaceChildren(id, results) + }).then(function () { + editor.render() + }) + } + } + }); return editor }) } let searchInput = document.getElementById('search-input'); -search(searchInput).then(searcher => { + +_.tap(search.search(searchInput), searcher => { let showSearch = _.debounce(function (searcher) { let query = $(searchInput).val() if (query === '') { - let autocomplete = document.getElementById('autocomplete'); - $(autocomplete).hide() + $('#autocomplete').hide() return false } - showSearchResultsExtended('#autocomplete', 'result-template', query => searcher.search(query), query, searchInput, query, 'search-result') return true; }, 200) @@ -513,5 +543,4 @@ search(searchInput).then(searcher => { }) }) - export default Editor; diff --git a/editor/src/search.js b/editor/src/search.js index f05755a..8114831 100644 --- a/editor/src/search.js +++ b/editor/src/search.js @@ -2,29 +2,37 @@ import $ from 'jquery' import qs from 'querystring'; function search(element) { - return new Promise(function (resolve, reject) { - resolve({ - element: element, - search(query) { - element.classList.add('is-loading') - return fetch('/search/?' + qs.encode({q:query})) - .then(res => res.json()) - .then(data => { - let actualResult = []; - $.each(data.hits, (key, value) => { - actualResult.push({ - ref: value.fields.page, - title: value.fields.title, - text: value.fragments.text[0] - }) - }) - element.classList.remove('is-loading') - console.log(actualResult) - return actualResult - }) - } - }) - }) + return { + element: element, + search(query) { + element.classList.add('is-loading') + return startQuery(query) + .then(res => { + element.classList.remove('is-loading') + return res + }) + } + } } -export default search; +function startQuery(query) { + return fetch('/search/?' + qs.encode({q: query})) + .then(res => res.json()) + .then(data => { + let actualResult = []; + $.each(data.hits, (key, value) => { + actualResult.push({ + ref: value.fields.page, + title: value.fields.title, + line: value.fields.text, + text: value.fragments.text[0] + }) + }) + return actualResult + }) +} + +export default { + search, + startQuery +}; diff --git a/file.go b/file.go index 7bdc2a0..b0ef526 100644 --- a/file.go +++ b/file.go @@ -85,6 +85,7 @@ func (v2 ListItemV2) ListItem() ListItem { v2.ID.StrID, v2.Indented, v2.Text, + false, } } @@ -93,6 +94,7 @@ type ListItem struct { ID string Indented int Text string + Fleeting bool `json:"fleeting,omitempty"` } type ActualListItem struct { @@ -101,6 +103,7 @@ type ActualListItem struct { Text string `json:"text"` Fold string `json:"fold"` Hidden bool `json:"hidden"` + Fleeting bool `json:"fleeting,omitempty"` } type FilePages struct { @@ -313,6 +316,7 @@ func saveBlocksFromPage(dirname string, page Page) error { var listItems []ListItem err := json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItems) if err != nil { + log.Println("decoding default failed: %w", err) var listItemsV2 []ListItemV2 err = json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItemsV2) listItems, err = saveWithNewIDs(dirname, listItemsV2, page.Name) @@ -353,6 +357,10 @@ func saveBlocksFromPage(dirname string, page Page) error { var prev = &parent for i, item := range listItems { + if item.Fleeting { + continue + } + prevList[item.ID] = item if item.Indented > prev.Indented { parent = *prev diff --git a/list-editor/index.js b/list-editor/index.js index f822712..dea12f6 100644 --- a/list-editor/index.js +++ b/list-editor/index.js @@ -13,6 +13,7 @@ function editor(root, inputData, options) { let cursor = createCursor() let selection = createSelection() let store = createStore(inputData); + let drake = null; function createStore(inputData) { let data = [ @@ -93,6 +94,19 @@ function editor(root, inputData, options) { startEditing(root, store, cursor) } + function replaceChildren(id, children) + { + store.replaceChildren(id, children) + } + + + function renderUpdate() + { + disableDragging(drake) + render(root, store); + drake = enableDragging(root) + } + let EDITOR = { on, save, @@ -101,7 +115,9 @@ function editor(root, inputData, options) { update, start, zoomin, - treeForId + treeForId, + replaceChildren, + render: renderUpdate }; root.classList.add('root') @@ -115,7 +131,6 @@ function editor(root, inputData, options) { options = _.merge(defaults, options) - let drake = null; let events = { change: [], @@ -293,7 +308,8 @@ function editor(root, inputData, options) { } let text = element.val() - $(element).closest('.list-item').removeClass('editor'); + element.closest('.list-item').removeClass('editor'); + let id = element.data('id') store.update(element.data('id'), (value) => { return _.merge(value, { text: text @@ -306,9 +322,9 @@ function editor(root, inputData, options) { } let $span = $('
'); - options.transform(text, $span, element.attr('data-id'), EDITOR) + options.transform(text, $span, id, EDITOR) element.replaceWith($span); - trigger('stop-editing', currentEditor[0]) + trigger('stop-editing', currentEditor[0], id) editing = false currentEditor = null @@ -460,6 +476,7 @@ function editor(root, inputData, options) { stopEditing(root, store, currentEditor); } } + if (event.key === 'Enter') { startEditing(root, store, cursor); return false diff --git a/list-editor/store.js b/list-editor/store.js index dd9ac6e..0bb1e87 100644 --- a/list-editor/store.js +++ b/list-editor/store.js @@ -399,8 +399,35 @@ function Store(inputData) { return changed; } + function replaceChildren(id, newChildren) { + let first = index(id) + let firstVal = value(id) + if (firstVal.fleeting) { + return + } + let last = lastHigherIndented(first) + first++ + let ids = [] + _.each(newChildren, item => { + item.indented += 1 + firstVal.indented + if (!item.id) { + item.id = ID() + } + ids.push(item.id) + values[item.id] = item + }) + idList.splice(first, last - first, ...ids) + } + + let removeLevel = 9999999999; _.each(inputData, (d) => { - append(d) + if (d.text.startsWith("{{query:")) { + removeLevel = d.indented; + append(d) + } else if (d.indented <= removeLevel) { + removeLevel = 9999999999; + append(d) + } }) return { @@ -424,6 +451,7 @@ function Store(inputData) { debug, tree, flat, + replaceChildren, hasChanged, clearChanged, };