mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
quick search impl finished
This commit is contained in:
parent
d406df48a8
commit
3a94b04ef4
2
db/migrations/0180__rename_quickSearch_shortcut.sql
Normal file
2
db/migrations/0180__rename_quickSearch_shortcut.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
UPDATE options SET name = 'keyboardShortcutsQuickSearch' WHERE name = 'keyboardShortcutsSearchNotes';
|
||||||
|
UPDATE entity_changes SET entityId = 'keyboardShortcutsQuickSearch' WHERE entityId = 'keyboardShortcutsSearchNotes' AND entityName = 'options';
|
@ -48,7 +48,7 @@ async function createSearchNote(opts = {}) {
|
|||||||
|
|
||||||
const attrsToUpdate = [
|
const attrsToUpdate = [
|
||||||
opts.ancestorNoteId ? { type: 'relation', name: 'ancestor', value: opts.ancestorNoteId } : undefined,
|
opts.ancestorNoteId ? { type: 'relation', name: 'ancestor', value: opts.ancestorNoteId } : undefined,
|
||||||
{ type: 'label', name: 'searchString', value: opts.searchStringe }
|
{ type: 'label', name: 'searchString', value: opts.searchString }
|
||||||
].filter(attr => !!attr);
|
].filter(attr => !!attr);
|
||||||
|
|
||||||
if (attrsToUpdate.length > 0) {
|
if (attrsToUpdate.length > 0) {
|
||||||
|
@ -89,7 +89,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
|||||||
this.addButtonToToolbar = opts => {
|
this.addButtonToToolbar = opts => {
|
||||||
const buttonId = "toolbar-button-" + opts.title.replace(/\s/g, "-");
|
const buttonId = "toolbar-button-" + opts.title.replace(/\s/g, "-");
|
||||||
|
|
||||||
const button = $('<button>')
|
const button = $('<button class="noborder">')
|
||||||
.addClass("btn btn-sm")
|
.addClass("btn btn-sm")
|
||||||
.on('click', opts.action);
|
.on('click', opts.action);
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import BasicWidget from "./basic_widget.js";
|
import BasicWidget from "./basic_widget.js";
|
||||||
import server from "../services/server.js";
|
import server from "../services/server.js";
|
||||||
import linkService from "../services/link.js";
|
import linkService from "../services/link.js";
|
||||||
|
import dateNotesService from "../services/date_notes.js";
|
||||||
import treeCache from "../services/tree_cache.js";
|
import treeCache from "../services/tree_cache.js";
|
||||||
import utils from "../services/utils.js";
|
import utils from "../services/utils.js";
|
||||||
|
import appContext from "../services/app_context.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="quick-search input-group input-group-sm" style="width: 250px;">
|
<div class="quick-search input-group input-group-sm" style="width: 250px;">
|
||||||
@ -18,7 +20,7 @@ const TPL = `
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
box-shadow: 10px 10px 93px -25px black;
|
box-shadow: -30px 50px 93px -50px black;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -27,18 +29,12 @@ const TPL = `
|
|||||||
<button class="btn btn-outline-secondary search-button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<button class="btn btn-outline-secondary search-button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<span class="bx bx-search"></span>
|
<span class="bx bx-search"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right"></div>
|
||||||
<a class="dropdown-item" href="#">Action</a>
|
|
||||||
<a class="dropdown-item" href="#">Another action</a>
|
|
||||||
<a class="dropdown-item" href="#">Something else here</a>
|
|
||||||
<div role="separator" class="dropdown-divider"></div>
|
|
||||||
<a class="dropdown-item" href="#">Separated link</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const MAX_DISPLAYED_NOTES = 20;
|
const MAX_DISPLAYED_NOTES = 15;
|
||||||
|
|
||||||
export default class QuickSearchWidget extends BasicWidget {
|
export default class QuickSearchWidget extends BasicWidget {
|
||||||
doRender() {
|
doRender() {
|
||||||
@ -48,8 +44,9 @@ export default class QuickSearchWidget extends BasicWidget {
|
|||||||
this.$searchString = this.$widget.find('.search-string');
|
this.$searchString = this.$widget.find('.search-string');
|
||||||
this.$dropdownMenu = this.$widget.find('.dropdown-menu');
|
this.$dropdownMenu = this.$widget.find('.dropdown-menu');
|
||||||
this.$dropdownToggle = this.$widget.find('.search-button');
|
this.$dropdownToggle = this.$widget.find('.search-button');
|
||||||
|
this.$dropdownToggle.dropdown();
|
||||||
|
|
||||||
this.$widget.find('.input-group-append').on('show.bs.dropdown', () => this.search());
|
this.$widget.find('.input-group-append').on('shown.bs.dropdown', () => this.search());
|
||||||
|
|
||||||
utils.bindElShortcut(this.$searchString, 'return', () => {
|
utils.bindElShortcut(this.$searchString, 'return', () => {
|
||||||
this.$dropdownToggle.dropdown('show');
|
this.$dropdownToggle.dropdown('show');
|
||||||
@ -57,21 +54,30 @@ export default class QuickSearchWidget extends BasicWidget {
|
|||||||
this.$searchString.focus();
|
this.$searchString.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
utils.bindElShortcut(this.$searchString, 'down', () => {
|
||||||
|
this.$dropdownMenu.find('.dropdown-item:first').focus();
|
||||||
|
});
|
||||||
|
|
||||||
return this.$widget;
|
return this.$widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
async search() {
|
async search() {
|
||||||
|
const searchString = this.$searchString.val().trim();
|
||||||
|
|
||||||
|
if (!searchString) {
|
||||||
|
this.$dropdownToggle.dropdown("hide");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.$dropdownMenu.empty();
|
this.$dropdownMenu.empty();
|
||||||
this.$dropdownMenu.append('<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span> Searching ...</span>');
|
this.$dropdownMenu.append('<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span> Searching ...</span>');
|
||||||
|
|
||||||
const resultNoteIds = await server.get('quick-search/' + encodeURIComponent(this.$searchString.val()));
|
const resultNoteIds = await server.get('quick-search/' + encodeURIComponent(searchString));
|
||||||
|
|
||||||
const displayedNoteIds = resultNoteIds.slice(0, Math.min(MAX_DISPLAYED_NOTES, resultNoteIds.length));
|
const displayedNoteIds = resultNoteIds.slice(0, Math.min(MAX_DISPLAYED_NOTES, resultNoteIds.length));
|
||||||
|
|
||||||
this.$dropdownMenu.empty();
|
this.$dropdownMenu.empty();
|
||||||
|
|
||||||
this.$dropdownMenu.append('<div class="dropdown-item"><button class="btn btn-sm">Show in full search</button></div>');
|
|
||||||
|
|
||||||
if (displayedNoteIds.length === 0) {
|
if (displayedNoteIds.length === 0) {
|
||||||
this.$dropdownMenu.append('<span class="dropdown-item disabled">No results found</span>');
|
this.$dropdownMenu.append('<span class="dropdown-item disabled">No results found</span>');
|
||||||
}
|
}
|
||||||
@ -79,6 +85,14 @@ export default class QuickSearchWidget extends BasicWidget {
|
|||||||
for (const note of await treeCache.getNotes(displayedNoteIds)) {
|
for (const note of await treeCache.getNotes(displayedNoteIds)) {
|
||||||
const $link = await linkService.createNoteLink(note.noteId, {showNotePath: true});
|
const $link = await linkService.createNoteLink(note.noteId, {showNotePath: true});
|
||||||
$link.addClass('dropdown-item');
|
$link.addClass('dropdown-item');
|
||||||
|
$link.attr("tabIndex", "0");
|
||||||
|
$link.on('click', () => this.$dropdownToggle.dropdown("hide"));
|
||||||
|
utils.bindElShortcut($link, 'return', () => {
|
||||||
|
$link.find('a').trigger({
|
||||||
|
type: 'click',
|
||||||
|
which: 1 // left click
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
this.$dropdownMenu.append($link);
|
this.$dropdownMenu.append($link);
|
||||||
}
|
}
|
||||||
@ -87,6 +101,23 @@ export default class QuickSearchWidget extends BasicWidget {
|
|||||||
this.$dropdownMenu.append(`<span class="dropdown-item disabled">... and ${resultNoteIds.length - MAX_DISPLAYED_NOTES} more results.</span>`);
|
this.$dropdownMenu.append(`<span class="dropdown-item disabled">... and ${resultNoteIds.length - MAX_DISPLAYED_NOTES} more results.</span>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const $showInFullButton = $('<a class="dropdown-item" tabindex="0">')
|
||||||
|
.append($('<button class="btn btn-sm">Show in full search</button>'));
|
||||||
|
|
||||||
|
this.$dropdownMenu.append($showInFullButton);
|
||||||
|
|
||||||
|
utils.bindElShortcut($showInFullButton, 'return', async () => {
|
||||||
|
const searchNote = await dateNotesService.createSearchNote({searchString: this.$searchString.val()});
|
||||||
|
|
||||||
|
await appContext.tabManager.getActiveTabContext().setNote(searchNote.noteId);
|
||||||
|
});
|
||||||
|
|
||||||
|
utils.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
|
||||||
|
|
||||||
this.$dropdownToggle.dropdown('update');
|
this.$dropdownToggle.dropdown('update');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quickSearchEvent() {
|
||||||
|
this.$searchString.focus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ const TPL = `
|
|||||||
height: 35px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.standard-top-widget button:not(.search-button) {
|
.standard-top-widget button.noborder {
|
||||||
padding: 1px 5px 1px 5px;
|
padding: 1px 5px 1px 5px;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
@ -35,35 +35,35 @@ const TPL = `
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div style="flex-grow: 100; display: flex;">
|
<div style="flex-grow: 100; display: flex;">
|
||||||
<button class="btn btn-sm" data-trigger-command="createNoteIntoInbox">
|
<button class="btn btn-sm noborder" data-trigger-command="createNoteIntoInbox">
|
||||||
<span class="bx bx-file-blank"></span>
|
<span class="bx bx-file-blank"></span>
|
||||||
New note
|
New note
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm" data-trigger-command="searchNotes">
|
<button class="btn btn-sm noborder" data-trigger-command="searchNotes">
|
||||||
<span class="bx bx-search"></span>
|
<span class="bx bx-search"></span>
|
||||||
Search
|
Search
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm" data-trigger-command="jumpToNote">
|
<button class="btn btn-sm noborder" data-trigger-command="jumpToNote">
|
||||||
<span class="bx bx-send"></span>
|
<span class="bx bx-send"></span>
|
||||||
Jump to note
|
Jump to note
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm" data-trigger-command="showRecentChanges">
|
<button class="btn btn-sm noborder" data-trigger-command="showRecentChanges">
|
||||||
<span class="bx bx-history"></span>
|
<span class="bx bx-history"></span>
|
||||||
|
|
||||||
Recent changes
|
Recent changes
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm enter-protected-session-button"
|
<button class="btn btn-sm enter-protected-session-button noborder"
|
||||||
title="Enter protected session to be able to find and view protected notes">
|
title="Enter protected session to be able to find and view protected notes">
|
||||||
<span class="bx bx-log-in"></span>
|
<span class="bx bx-log-in"></span>
|
||||||
|
|
||||||
Enter protected session
|
Enter protected session
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn btn-sm leave-protected-session-button"
|
<button class="btn btn-sm leave-protected-session-button noborder"
|
||||||
title="Leave protected session so that protected notes are not accessible any more."
|
title="Leave protected session so that protected notes are not accessible any more."
|
||||||
style="display: none;">
|
style="display: none;">
|
||||||
<span class="bx bx-log-out"></span>
|
<span class="bx bx-log-out"></span>
|
||||||
|
@ -4,7 +4,7 @@ const build = require('./build');
|
|||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||||
|
|
||||||
const APP_DB_VERSION = 179;
|
const APP_DB_VERSION = 180;
|
||||||
const SYNC_VERSION = 19;
|
const SYNC_VERSION = 19;
|
||||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ const DEFAULT_KEYBOARD_ACTIONS = [
|
|||||||
scope: "window"
|
scope: "window"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
actionName: "searchNotes",
|
actionName: "quickSearch",
|
||||||
defaultShortcuts: ["CommandOrControl+S"],
|
defaultShortcuts: ["CommandOrControl+S"],
|
||||||
scope: "window"
|
scope: "window"
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user