mirror of
https://github.com/zadam/trilium.git
synced 2025-02-22 14:03:36 +08:00
added "save search to note" button
This commit is contained in:
parent
e48609aa68
commit
c886583396
10 changed files with 93 additions and 40 deletions
3
TODO
3
TODO
|
@ -2,3 +2,6 @@
|
|||
- all ribbon tabs should have assignable shortcut
|
||||
- new icon
|
||||
- green theme
|
||||
- polish becca entities API
|
||||
- separate private and public APIs in becca entities
|
||||
- handle FIXMEs
|
||||
|
|
|
@ -1008,6 +1008,24 @@ class Note extends AbstractEntity {
|
|||
*/
|
||||
removeRelation(name, value) { return this.removeAttribute(RELATION, name, value); }
|
||||
|
||||
searchNotesInSubtree(searchString) {
|
||||
const searchService = require("../../services/search/services/search");
|
||||
|
||||
return searchService.searchNotes(searchString);
|
||||
}
|
||||
|
||||
searchNoteInSubtree(searchString) {
|
||||
return this.searchNotesInSubtree(searchString)[0];
|
||||
}
|
||||
|
||||
cloneTo(parentNoteId) {
|
||||
const cloningService = require("../../services/cloning");
|
||||
|
||||
const branch = this.becca.getNote(parentNoteId).getParentBranches()[0];
|
||||
|
||||
return cloningService.cloneNoteToParent(this.noteId, branch.branchId);
|
||||
}
|
||||
|
||||
decrypt() {
|
||||
if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
|
||||
try {
|
||||
|
|
|
@ -3,6 +3,7 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
|||
import froca from "../../services/froca.js";
|
||||
import ws from "../../services/ws.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
|
||||
import DeleteNoteSearchAction from "../search_actions/delete_note.js";
|
||||
import DeleteLabelSearchAction from "../search_actions/delete_label.js";
|
||||
|
@ -21,6 +22,8 @@ import SearchScript from "../search_options/search_script.js";
|
|||
import Limit from "../search_options/limit.js";
|
||||
import DeleteNoteRevisionsSearchAction from "../search_actions/delete_note_revisions.js";
|
||||
import Debug from "../search_options/debug.js";
|
||||
import appContext from "../../services/app_context.js";
|
||||
import toast from "../../services/toast.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="search-definition-widget">
|
||||
|
@ -164,6 +167,11 @@ const TPL = `
|
|||
<span class="bx bxs-zap"></span>
|
||||
Search & Execute actions
|
||||
</button>
|
||||
|
||||
<button type="button" class="btn btn-sm save-to-note-button">
|
||||
<span class="bx bx-save"></span>
|
||||
Save to note
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -258,6 +266,19 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
|
|||
|
||||
this.$searchAndExecuteButton = this.$widget.find('.search-and-execute-button');
|
||||
this.$searchAndExecuteButton.on('click', () => this.searchAndExecute());
|
||||
|
||||
this.$saveToNoteButton = this.$widget.find('.save-to-note-button');
|
||||
this.$saveToNoteButton.on('click', async () => {
|
||||
const {notePath} = await server.post("save-search-note", {searchNoteId: this.noteId});
|
||||
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
await appContext.tabManager.getActiveContext().setNote(notePath);
|
||||
|
||||
console.log("notePath", notePath);
|
||||
|
||||
toastService.showMessage("Search note has been saved into " + await treeService.getNotePathTitle(notePath));
|
||||
});
|
||||
}
|
||||
|
||||
async refreshResultsCommand() {
|
||||
|
@ -278,6 +299,8 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
|
|||
async refreshWithNote(note) {
|
||||
this.$component.show();
|
||||
|
||||
this.$saveToNoteButton.toggle(!note.getAllNotePaths().find(notePathArr => !notePathArr.includes("hidden")));
|
||||
|
||||
this.$searchOptions.empty();
|
||||
|
||||
for (const OptionClass of OPTION_CLASSES) {
|
||||
|
|
|
@ -12,9 +12,16 @@ const utils = require('../../services/utils');
|
|||
const path = require('path');
|
||||
const Attribute = require('../../becca/entities/attribute.js');
|
||||
const htmlSanitizer = require('../../services/html_sanitizer');
|
||||
const {formatAttrForSearch} = require("../../services/attribute_formatter.js");
|
||||
|
||||
function findClippingNote(todayNote, pageUrl) {
|
||||
const notes = todayNote.getDescendantNotesWithLabel('pageUrl', pageUrl);
|
||||
const notes = todayNote.searchNoteInSubtree(
|
||||
formatAttrForSearch({
|
||||
type: 'label',
|
||||
name: "pageUrl",
|
||||
value: pageUrl
|
||||
}, true)
|
||||
);
|
||||
|
||||
for (const note of notes) {
|
||||
if (note.getOwnedLabelValue('clipType') === 'clippings') {
|
||||
|
|
|
@ -13,11 +13,11 @@ function getInboxNote(req) {
|
|||
|
||||
let inbox;
|
||||
|
||||
if (hoistedNote) {
|
||||
([inbox] = hoistedNote.getDescendantNotesWithLabel('hoistedInbox'));
|
||||
if (!hoistedNote.isRoot()) {
|
||||
inbox = hoistedNote.searchNoteInSubtree('#hoistedInbox');
|
||||
|
||||
if (!inbox) {
|
||||
([inbox] = hoistedNote.getDescendantNotesWithLabel('inbox'));
|
||||
inbox = hoistedNote.searchNoteInSubtree('#inbox');
|
||||
}
|
||||
|
||||
if (!inbox) {
|
||||
|
@ -114,39 +114,35 @@ function getSearchRoot() {
|
|||
return searchRoot;
|
||||
}
|
||||
|
||||
function saveSearchNote(req) {
|
||||
const searchNote = becca.getNote(req.body.searchNoteId);
|
||||
|
||||
const hoistedNote = getHoistedNote();
|
||||
let searchHome;
|
||||
|
||||
if (!hoistedNote.isRoot()) {
|
||||
searchHome = hoistedNote.searchNoteInSubtree('#hoistedSearchHome')
|
||||
|| hoistedNote.searchNoteInSubtree('#searchHome')
|
||||
|| hoistedNote;
|
||||
}
|
||||
else {
|
||||
const today = dateUtils.localNowDate();
|
||||
|
||||
searchHome = hoistedNote.searchNoteInSubtree('#searchHome')
|
||||
|| dateNoteService.getDateNote(today);
|
||||
}
|
||||
|
||||
return searchNote.cloneTo(searchHome.noteId);
|
||||
}
|
||||
|
||||
function createSearchNote(req) {
|
||||
const params = req.body;
|
||||
const searchString = params.searchString || "";
|
||||
let ancestorNoteId = params.ancestorNoteId;
|
||||
|
||||
const hoistedNote = getHoistedNote();
|
||||
|
||||
let searchHome = getSearchRoot();
|
||||
|
||||
// if (hoistedNote) {
|
||||
// ([searchHome] = hoistedNote.getDescendantNotesWithLabel('hoistedSearchHome'));
|
||||
//
|
||||
// if (!searchHome) {
|
||||
// ([searchHome] = hoistedNote.getDescendantNotesWithLabel('searchHome'));
|
||||
// }
|
||||
//
|
||||
// if (!searchHome) {
|
||||
// searchHome = hoistedNote;
|
||||
// }
|
||||
//
|
||||
// if (!ancestorNoteId) {
|
||||
// ancestorNoteId = hoistedNote.noteId;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// const today = dateUtils.localNowDate();
|
||||
//
|
||||
// searchHome = attributeService.getNoteWithLabel('searchHome')
|
||||
// || dateNoteService.getDateNote(today);
|
||||
// }
|
||||
const ancestorNoteId = params.ancestorNoteId || hoistedNote.noteId;
|
||||
|
||||
const {note} = noteService.createNewNote({
|
||||
parentNoteId: searchHome.noteId,
|
||||
parentNoteId: getSearchRoot().noteId,
|
||||
title: 'Search: ' + searchString,
|
||||
content: "",
|
||||
type: 'search',
|
||||
|
@ -163,9 +159,7 @@ function createSearchNote(req) {
|
|||
}
|
||||
|
||||
function getHoistedNote() {
|
||||
return cls.getHoistedNoteId() && cls.getHoistedNoteId() !== 'root'
|
||||
? becca.getNote(cls.getHoistedNoteId())
|
||||
: null;
|
||||
return becca.getNote(cls.getHoistedNoteId());
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@ -175,5 +169,6 @@ module.exports = {
|
|||
getYearNote,
|
||||
getDateNotesForMonth,
|
||||
createSqlConsole,
|
||||
createSearchNote
|
||||
createSearchNote,
|
||||
saveSearchNote
|
||||
};
|
||||
|
|
|
@ -92,7 +92,7 @@ function update(name, value) {
|
|||
}
|
||||
|
||||
function getUserThemes() {
|
||||
const notes = searchService.findNotes("#appTheme");
|
||||
const notes = searchService.searchNotes("#appTheme");
|
||||
const ret = [];
|
||||
|
||||
for (const note of notes) {
|
||||
|
|
|
@ -212,6 +212,7 @@ function register(app) {
|
|||
apiRoute(GET, '/api/date-notes/notes-for-month/:month', dateNotesRoute.getDateNotesForMonth);
|
||||
apiRoute(POST, '/api/sql-console', dateNotesRoute.createSqlConsole);
|
||||
apiRoute(POST, '/api/search-note', dateNotesRoute.createSearchNote);
|
||||
apiRoute(POST, '/api/save-search-note', dateNotesRoute.saveSearchNote);
|
||||
|
||||
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
||||
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
|
||||
|
|
|
@ -60,7 +60,7 @@ const BUILTIN_ATTRIBUTES = [
|
|||
];
|
||||
|
||||
function getNotesWithLabel(name, value) {
|
||||
return searchService.findNotes(formatAttrForSearch({type: 'label', name, value}, true));
|
||||
return searchService.searchNotes(formatAttrForSearch({type: 'label', name, value}, true));
|
||||
}
|
||||
|
||||
function getNoteIdsWithLabels(names) {
|
||||
|
@ -75,6 +75,7 @@ function getNoteIdsWithLabels(names) {
|
|||
return Array.from(noteIds);
|
||||
}
|
||||
|
||||
// TODO: should be in search service
|
||||
function getNoteWithLabel(name, value) {
|
||||
const notes = getNotesWithLabel(name, value);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ const Branch = require('../becca/entities/branch.js');
|
|||
const TaskContext = require("./task_context.js");
|
||||
const utils = require('./utils');
|
||||
const becca = require("../becca/becca.js");
|
||||
const beccaService = require("../becca/becca_service");
|
||||
|
||||
function cloneNoteToParent(noteId, parentBranchId, prefix) {
|
||||
const parentBranch = becca.getBranch(parentBranchId);
|
||||
|
@ -32,7 +33,11 @@ function cloneNoteToParent(noteId, parentBranchId, prefix) {
|
|||
parentBranch.isExpanded = true; // the new target should be expanded so it immediately shows up to the user
|
||||
parentBranch.save();
|
||||
|
||||
return { success: true, branchId: branch.branchId };
|
||||
return {
|
||||
success: true,
|
||||
branchId: branch.branchId,
|
||||
notePath: beccaService.getNotePath(parentBranch.noteId).path + "/" + noteId
|
||||
};
|
||||
}
|
||||
|
||||
function ensureNoteIsPresentInParent(noteId, parentNoteId, prefix) {
|
||||
|
|
|
@ -136,7 +136,7 @@ function parseQueryToExpression(query, searchContext) {
|
|||
* @param {string} query
|
||||
* @return {Note[]}
|
||||
*/
|
||||
function findNotes(query) {
|
||||
function searchNotes(query) {
|
||||
const searchResults = findResultsWithQuery(query, new SearchContext());
|
||||
|
||||
return searchResults.map(sr => becca.notes[sr.noteId]);
|
||||
|
@ -263,5 +263,5 @@ module.exports = {
|
|||
searchTrimmedNotes,
|
||||
searchNotesForAutocomplete,
|
||||
findResultsWithQuery,
|
||||
findNotes
|
||||
searchNotes
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue