added "save search to note" button

This commit is contained in:
zadam 2021-06-06 11:01:10 +02:00
parent e48609aa68
commit c886583396
10 changed files with 93 additions and 40 deletions

3
TODO
View file

@ -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

View file

@ -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 {

View file

@ -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) {

View file

@ -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') {

View file

@ -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
};

View file

@ -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) {

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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
};