diff --git a/apps/client/src/widgets/ribbon/SearchDefinitionTab.tsx b/apps/client/src/widgets/ribbon/SearchDefinitionTab.tsx index ac7bf8d14..bf285caef 100644 --- a/apps/client/src/widgets/ribbon/SearchDefinitionTab.tsx +++ b/apps/client/src/widgets/ribbon/SearchDefinitionTab.tsx @@ -1,207 +1,209 @@ -import { t } from "../../services/i18n"; -import Button from "../react/Button"; -import { TabContext } from "./ribbon-interface"; -import { SaveSearchNoteResponse } from "@triliumnext/commons"; -import attributes from "../../services/attributes"; -import FNote from "../../entities/fnote"; -import toast from "../../services/toast"; -import froca from "../../services/froca"; -import { useContext, useEffect, useState } from "preact/hooks"; -import { ParentComponent } from "../react/react_utils"; -import { useTriliumEvent } from "../react/hooks"; -import appContext from "../../components/app_context"; -import server from "../../services/server"; -import ws from "../../services/ws"; -import tree from "../../services/tree"; -import { SEARCH_OPTIONS, SearchOption } from "./SearchDefinitionOptions"; -import Dropdown from "../react/Dropdown"; -import Icon from "../react/Icon"; -import bulk_action, { ACTION_GROUPS } from "../../services/bulk_action"; -import { FormListHeader, FormListItem } from "../react/FormList"; -import RenameNoteBulkAction from "../bulk_actions/note/rename_note"; -import { getErrorMessage } from "../../services/utils"; import "./SearchDefinitionTab.css"; +import { SaveSearchNoteResponse } from "@triliumnext/commons"; +import { useContext, useEffect, useState } from "preact/hooks"; + +import appContext from "../../components/app_context"; +import FNote from "../../entities/fnote"; +import attributes from "../../services/attributes"; +import bulk_action, { ACTION_GROUPS } from "../../services/bulk_action"; +import froca from "../../services/froca"; +import { t } from "../../services/i18n"; +import server from "../../services/server"; +import toast from "../../services/toast"; +import tree from "../../services/tree"; +import { getErrorMessage } from "../../services/utils"; +import ws from "../../services/ws"; +import RenameNoteBulkAction from "../bulk_actions/note/rename_note"; +import Button from "../react/Button"; +import Dropdown from "../react/Dropdown"; +import { FormListHeader, FormListItem } from "../react/FormList"; +import { useTriliumEvent } from "../react/hooks"; +import Icon from "../react/Icon"; +import { ParentComponent } from "../react/react_utils"; +import { TabContext } from "./ribbon-interface"; +import { SEARCH_OPTIONS, SearchOption } from "./SearchDefinitionOptions"; + export default function SearchDefinitionTab({ note, ntxId, hidden }: TabContext) { - const parentComponent = useContext(ParentComponent); - const [ searchOptions, setSearchOptions ] = useState<{ availableOptions: SearchOption[], activeOptions: SearchOption[] }>(); - const [ error, setError ] = useState<{ message: string }>(); + const parentComponent = useContext(ParentComponent); + const [ searchOptions, setSearchOptions ] = useState<{ availableOptions: SearchOption[], activeOptions: SearchOption[] }>(); + const [ error, setError ] = useState<{ message: string }>(); - function refreshOptions() { - if (!note) return; + function refreshOptions() { + if (!note) return; - const availableOptions: SearchOption[] = []; - const activeOptions: SearchOption[] = []; + const availableOptions: SearchOption[] = []; + const activeOptions: SearchOption[] = []; - for (const searchOption of SEARCH_OPTIONS) { - const attr = note.getAttribute(searchOption.attributeType, searchOption.attributeName); - if (attr) { - activeOptions.push(searchOption); - } else { - availableOptions.push(searchOption); - } - } - - setSearchOptions({ availableOptions, activeOptions }); - } - - async function refreshResults() { - const noteId = note?.noteId; - if (!noteId) { - return; - } - - try { - const result = await froca.loadSearchNote(noteId); - if (result?.error) { - setError({ message: result?.error}) - } else { - setError(undefined); + for (const searchOption of SEARCH_OPTIONS) { + const attr = note.getAttribute(searchOption.attributeType, searchOption.attributeName); + if (attr) { + activeOptions.push(searchOption); + } else { + availableOptions.push(searchOption); + } } - } catch (e: unknown) { - toast.showError(getErrorMessage(e)); + + setSearchOptions({ availableOptions, activeOptions }); } - parentComponent?.triggerEvent("searchRefreshed", { ntxId }); - } + async function refreshResults() { + const noteId = note?.noteId; + if (!noteId) { + return; + } - // Refresh the list of available and active options. - useEffect(refreshOptions, [ note ]); - useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if (loadResults.getAttributeRows().find((attrRow) => attributes.isAffecting(attrRow, note))) { - refreshOptions(); + try { + const result = await froca.loadSearchNote(noteId); + if (result?.error) { + setError({ message: result?.error}); + } else { + setError(undefined); + } + } catch (e: unknown) { + toast.showError(getErrorMessage(e)); + } + + parentComponent?.triggerEvent("searchRefreshed", { ntxId }); } - }); - return ( -
-
- {note && !hidden && + // Refresh the list of available and active options. + useEffect(refreshOptions, [ note ]); + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (loadResults.getAttributeRows().find((attrRow) => attributes.isAffecting(attrRow, note))) { + refreshOptions(); + } + }); + + return ( +
+
+ {note && !hidden && - - - - + + + - - - - {searchOptions?.activeOptions.map(({ attributeType, attributeName, component, additionalAttributesToDelete, defaultValue }) => { - const Component = component; - return ; - })} - - - - - + + + + {searchOptions?.activeOptions.map(({ attributeType, attributeName, component, additionalAttributesToDelete, defaultValue }) => { + const Component = component; + return ; + })} + + + + + - - + // Note the {{- notePathTitle}} in json file is not typo, it's unescaping + // See https://www.i18next.com/translation-function/interpolation#unescape + toast.showMessage(t("search_definition.search_note_saved", { notePathTitle: await tree.getNotePathTitle(notePath) })); + }} + />} + + + +
{t("search_definition.add_search_option")} - {searchOptions?.availableOptions.map(({ icon, label, tooltip, attributeName, attributeType, defaultValue }) => ( -
{t("search_definition.add_search_option")} + {searchOptions?.availableOptions.map(({ icon, label, tooltip, attributeName, attributeType, defaultValue }) => ( +
-
-
+
+
-
- } -
-
- ) + } +
+
+ ); } function BulkActionsList({ note }: { note: FNote }) { - const [ bulkActions, setBulkActions ] = useState(); + const [ bulkActions, setBulkActions ] = useState(); - function refreshBulkActions() { - if (note) { - setBulkActions(bulk_action.parseActions(note)); + function refreshBulkActions() { + if (note) { + setBulkActions(bulk_action.parseActions(note)); + } } - } - // React to changes. - useEffect(refreshBulkActions, [ note ]); - useTriliumEvent("entitiesReloaded", ({loadResults}) => { - if (loadResults.getAttributeRows().find(attr => attr.type === "label" && attr.name === "action" && attributes.isAffecting(attr, note))) { - refreshBulkActions(); - } - }); + // React to changes. + useEffect(refreshBulkActions, [ note ]); + useTriliumEvent("entitiesReloaded", ({loadResults}) => { + if (loadResults.getAttributeRows().find(attr => attr.type === "label" && attr.name === "action" && attributes.isAffecting(attr, note))) { + refreshBulkActions(); + } + }); - return ( - - {bulkActions?.map(bulkAction => ( - bulkAction.doRender() - ))} - - ) + return ( + + {bulkActions?.map(bulkAction => ( + bulkAction.doRender() + ))} + + ); } function AddBulkActionButton({ note }: { note: FNote }) { - return ( - {" "}{t("search_definition.action")}} - noSelectButtonStyle - > - {ACTION_GROUPS.map(({ actions, title }) => ( - <> - + return ( + {" "}{t("search_definition.action")}} + noSelectButtonStyle + > + {ACTION_GROUPS.map(({ actions, title }) => ( + <> + - {actions.map(({ actionName, actionTitle }) => ( - bulk_action.addAction(note.noteId, actionName)}>{actionTitle} + {actions.map(({ actionName, actionTitle }) => ( + bulk_action.addAction(note.noteId, actionName)}>{actionTitle} + ))} + ))} - - ))} - - ) + + ); }