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