Add search queries inside the tree
This commit is contained in:
parent
5e1422f684
commit
5006e1095a
|
@ -27,7 +27,6 @@ import formulaFunctions from './formula'
|
||||||
moment.locale('nl')
|
moment.locale('nl')
|
||||||
|
|
||||||
const math = create(all)
|
const math = create(all)
|
||||||
|
|
||||||
math.import(formulaFunctions)
|
math.import(formulaFunctions)
|
||||||
|
|
||||||
function isMultiline(input) {
|
function isMultiline(input) {
|
||||||
|
@ -109,8 +108,8 @@ function showSearchResultsExtended(element, template, searchTool, query, input,
|
||||||
$lc.offset(pos)
|
$lc.offset(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
var templateText = he.decode(document.getElementById(template).innerHTML);
|
let templateText = he.decode(document.getElementById(template).innerHTML);
|
||||||
var rendered = Mustache.render(templateText, {
|
let rendered = Mustache.render(templateText, {
|
||||||
page: value.trim().replace(/\s+/g, '_'),
|
page: value.trim().replace(/\s+/g, '_'),
|
||||||
results: results
|
results: results
|
||||||
}, {}, ['[[', ']]']);
|
}, {}, ['[[', ']]']);
|
||||||
|
@ -467,7 +466,7 @@ function Editor(holder, input) {
|
||||||
if (insideSearch) {
|
if (insideSearch) {
|
||||||
let query = value.substring(start + 1, end);
|
let query = value.substring(start + 1, end);
|
||||||
showSearchResults(commandSearch, query, input, value, 'command').then(results => {
|
showSearchResults(commandSearch, query, input, value, 'command').then(results => {
|
||||||
if (query.length > 0 && result.length === 0) {
|
if (query.length > 0 && results.length === 0) {
|
||||||
searchEnabled = false
|
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()
|
$('#link-complete').off()
|
||||||
PrismJS.highlightAll()
|
PrismJS.highlightAll()
|
||||||
mermaid.init()
|
mermaid.init()
|
||||||
renderGraphs();
|
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
|
return editor
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let searchInput = document.getElementById('search-input');
|
let searchInput = document.getElementById('search-input');
|
||||||
search(searchInput).then(searcher => {
|
|
||||||
|
_.tap(search.search(searchInput), searcher => {
|
||||||
let showSearch = _.debounce(function (searcher) {
|
let showSearch = _.debounce(function (searcher) {
|
||||||
let query = $(searchInput).val()
|
let query = $(searchInput).val()
|
||||||
if (query === '') {
|
if (query === '') {
|
||||||
let autocomplete = document.getElementById('autocomplete');
|
$('#autocomplete').hide()
|
||||||
$(autocomplete).hide()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
showSearchResultsExtended('#autocomplete', 'result-template', query => searcher.search(query), query, searchInput, query, 'search-result')
|
showSearchResultsExtended('#autocomplete', 'result-template', query => searcher.search(query), query, searchInput, query, 'search-result')
|
||||||
return true;
|
return true;
|
||||||
}, 200)
|
}, 200)
|
||||||
|
@ -513,5 +543,4 @@ search(searchInput).then(searcher => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export default Editor;
|
export default Editor;
|
||||||
|
|
|
@ -2,29 +2,37 @@ import $ from 'jquery'
|
||||||
import qs from 'querystring';
|
import qs from 'querystring';
|
||||||
|
|
||||||
function search(element) {
|
function search(element) {
|
||||||
return new Promise(function (resolve, reject) {
|
return {
|
||||||
resolve({
|
element: element,
|
||||||
element: element,
|
search(query) {
|
||||||
search(query) {
|
element.classList.add('is-loading')
|
||||||
element.classList.add('is-loading')
|
return startQuery(query)
|
||||||
return fetch('/search/?' + qs.encode({q:query}))
|
.then(res => {
|
||||||
.then(res => res.json())
|
element.classList.remove('is-loading')
|
||||||
.then(data => {
|
return res
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
};
|
||||||
|
|
8
file.go
8
file.go
|
@ -85,6 +85,7 @@ func (v2 ListItemV2) ListItem() ListItem {
|
||||||
v2.ID.StrID,
|
v2.ID.StrID,
|
||||||
v2.Indented,
|
v2.Indented,
|
||||||
v2.Text,
|
v2.Text,
|
||||||
|
false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@ type ListItem struct {
|
||||||
ID string
|
ID string
|
||||||
Indented int
|
Indented int
|
||||||
Text string
|
Text string
|
||||||
|
Fleeting bool `json:"fleeting,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActualListItem struct {
|
type ActualListItem struct {
|
||||||
|
@ -101,6 +103,7 @@ type ActualListItem struct {
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
Fold string `json:"fold"`
|
Fold string `json:"fold"`
|
||||||
Hidden bool `json:"hidden"`
|
Hidden bool `json:"hidden"`
|
||||||
|
Fleeting bool `json:"fleeting,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FilePages struct {
|
type FilePages struct {
|
||||||
|
@ -313,6 +316,7 @@ func saveBlocksFromPage(dirname string, page Page) error {
|
||||||
var listItems []ListItem
|
var listItems []ListItem
|
||||||
err := json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItems)
|
err := json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItems)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Println("decoding default failed: %w", err)
|
||||||
var listItemsV2 []ListItemV2
|
var listItemsV2 []ListItemV2
|
||||||
err = json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItemsV2)
|
err = json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItemsV2)
|
||||||
listItems, err = saveWithNewIDs(dirname, listItemsV2, page.Name)
|
listItems, err = saveWithNewIDs(dirname, listItemsV2, page.Name)
|
||||||
|
@ -353,6 +357,10 @@ func saveBlocksFromPage(dirname string, page Page) error {
|
||||||
var prev = &parent
|
var prev = &parent
|
||||||
|
|
||||||
for i, item := range listItems {
|
for i, item := range listItems {
|
||||||
|
if item.Fleeting {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
prevList[item.ID] = item
|
prevList[item.ID] = item
|
||||||
if item.Indented > prev.Indented {
|
if item.Indented > prev.Indented {
|
||||||
parent = *prev
|
parent = *prev
|
||||||
|
|
|
@ -13,6 +13,7 @@ function editor(root, inputData, options) {
|
||||||
let cursor = createCursor()
|
let cursor = createCursor()
|
||||||
let selection = createSelection()
|
let selection = createSelection()
|
||||||
let store = createStore(inputData);
|
let store = createStore(inputData);
|
||||||
|
let drake = null;
|
||||||
|
|
||||||
function createStore(inputData) {
|
function createStore(inputData) {
|
||||||
let data = [
|
let data = [
|
||||||
|
@ -93,6 +94,19 @@ function editor(root, inputData, options) {
|
||||||
startEditing(root, store, cursor)
|
startEditing(root, store, cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replaceChildren(id, children)
|
||||||
|
{
|
||||||
|
store.replaceChildren(id, children)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function renderUpdate()
|
||||||
|
{
|
||||||
|
disableDragging(drake)
|
||||||
|
render(root, store);
|
||||||
|
drake = enableDragging(root)
|
||||||
|
}
|
||||||
|
|
||||||
let EDITOR = {
|
let EDITOR = {
|
||||||
on,
|
on,
|
||||||
save,
|
save,
|
||||||
|
@ -101,7 +115,9 @@ function editor(root, inputData, options) {
|
||||||
update,
|
update,
|
||||||
start,
|
start,
|
||||||
zoomin,
|
zoomin,
|
||||||
treeForId
|
treeForId,
|
||||||
|
replaceChildren,
|
||||||
|
render: renderUpdate
|
||||||
};
|
};
|
||||||
|
|
||||||
root.classList.add('root')
|
root.classList.add('root')
|
||||||
|
@ -115,7 +131,6 @@ function editor(root, inputData, options) {
|
||||||
|
|
||||||
options = _.merge(defaults, options)
|
options = _.merge(defaults, options)
|
||||||
|
|
||||||
let drake = null;
|
|
||||||
|
|
||||||
let events = {
|
let events = {
|
||||||
change: [],
|
change: [],
|
||||||
|
@ -293,7 +308,8 @@ function editor(root, inputData, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let text = element.val()
|
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) => {
|
store.update(element.data('id'), (value) => {
|
||||||
return _.merge(value, {
|
return _.merge(value, {
|
||||||
text: text
|
text: text
|
||||||
|
@ -306,9 +322,9 @@ function editor(root, inputData, options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let $span = $('<div class="content">');
|
let $span = $('<div class="content">');
|
||||||
options.transform(text, $span, element.attr('data-id'), EDITOR)
|
options.transform(text, $span, id, EDITOR)
|
||||||
element.replaceWith($span);
|
element.replaceWith($span);
|
||||||
trigger('stop-editing', currentEditor[0])
|
trigger('stop-editing', currentEditor[0], id)
|
||||||
editing = false
|
editing = false
|
||||||
currentEditor = null
|
currentEditor = null
|
||||||
|
|
||||||
|
@ -460,6 +476,7 @@ function editor(root, inputData, options) {
|
||||||
stopEditing(root, store, currentEditor);
|
stopEditing(root, store, currentEditor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.key === 'Enter') {
|
if (event.key === 'Enter') {
|
||||||
startEditing(root, store, cursor);
|
startEditing(root, store, cursor);
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -399,8 +399,35 @@ function Store(inputData) {
|
||||||
return changed;
|
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) => {
|
_.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 {
|
return {
|
||||||
|
@ -424,6 +451,7 @@ function Store(inputData) {
|
||||||
debug,
|
debug,
|
||||||
tree,
|
tree,
|
||||||
flat,
|
flat,
|
||||||
|
replaceChildren,
|
||||||
hasChanged,
|
hasChanged,
|
||||||
clearChanged,
|
clearChanged,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user