mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 15:49:00 +02:00
chore(react/ribbon): port search string
This commit is contained in:
parent
0c8bfc39ef
commit
c1b30db3d1
@ -2,6 +2,7 @@ import server from "./server.js";
|
|||||||
import froca from "./froca.js";
|
import froca from "./froca.js";
|
||||||
import type FNote from "../entities/fnote.js";
|
import type FNote from "../entities/fnote.js";
|
||||||
import type { AttributeRow } from "./load_results.js";
|
import type { AttributeRow } from "./load_results.js";
|
||||||
|
import { AttributeType } from "@triliumnext/commons";
|
||||||
|
|
||||||
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
|
||||||
await server.put(`notes/${noteId}/attribute`, {
|
await server.put(`notes/${noteId}/attribute`, {
|
||||||
@ -25,6 +26,14 @@ async function removeAttributeById(noteId: string, attributeId: string) {
|
|||||||
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
|
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function removeOwnedAttributesByNameOrType(note: FNote, type: AttributeType, name: string) {
|
||||||
|
for (const attr of note.getOwnedAttributes()) {
|
||||||
|
if (attr.type === type && attr.name === name) {
|
||||||
|
await server.remove(`notes/${note.noteId}/attributes/${attr.attributeId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a label identified by its name from the given note, if it exists. Note that the label must be owned, i.e.
|
* Removes a label identified by its name from the given note, if it exists. Note that the label must be owned, i.e.
|
||||||
* it will not remove inherited attributes.
|
* it will not remove inherited attributes.
|
||||||
|
@ -3,16 +3,20 @@ interface FormTextAreaProps {
|
|||||||
currentValue: string;
|
currentValue: string;
|
||||||
onBlur?(newValue: string): void;
|
onBlur?(newValue: string): void;
|
||||||
rows: number;
|
rows: number;
|
||||||
|
className?: string;
|
||||||
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
export default function FormTextArea({ id, onBlur, rows, currentValue }: FormTextAreaProps) {
|
export default function FormTextArea({ id, onBlur, rows, currentValue, className, placeholder }: FormTextAreaProps) {
|
||||||
return (
|
return (
|
||||||
<textarea
|
<textarea
|
||||||
id={id}
|
id={id}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
|
className={`form-control ${className ?? ""}`}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
onBlur?.(e.currentTarget.value);
|
onBlur?.(e.currentTarget.value);
|
||||||
}}
|
}}
|
||||||
style={{ width: "100%" }}
|
style={{ width: "100%" }}
|
||||||
|
placeholder={placeholder}
|
||||||
>{currentValue}</textarea>
|
>{currentValue}</textarea>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
|
import { ComponentChildren } from "preact";
|
||||||
import { t } from "../../services/i18n";
|
import { t } from "../../services/i18n";
|
||||||
import Button from "../react/Button";
|
import Button from "../react/Button";
|
||||||
import { TabContext } from "./ribbon-interface";
|
import { TabContext } from "./ribbon-interface";
|
||||||
|
import Dropdown from "../react/Dropdown";
|
||||||
|
import ActionButton from "../react/ActionButton";
|
||||||
|
import FormTextArea from "../react/FormTextArea";
|
||||||
|
import { AttributeType, OptionNames } from "@triliumnext/commons";
|
||||||
|
import { removeOwnedAttributesByNameOrType } from "../../services/attributes";
|
||||||
|
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
|
||||||
|
import FNote from "../../entities/fnote";
|
||||||
|
|
||||||
interface SearchOption {
|
interface SearchOption {
|
||||||
searchOption: string;
|
searchOption: string;
|
||||||
@ -73,8 +81,58 @@ export default function SearchDefinitionTab({ note }: TabContext) {
|
|||||||
))}
|
))}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tbody className="search-options">
|
||||||
|
<SearchStringOption />
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SearchOption({ note, title, children, help, attributeName, attributeType }: {
|
||||||
|
note: FNote;
|
||||||
|
title: string,
|
||||||
|
children: ComponentChildren,
|
||||||
|
help: ComponentChildren,
|
||||||
|
attributeName: string,
|
||||||
|
attributeType: AttributeType
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<tr>
|
||||||
|
<td className="title-column">{title}</td>
|
||||||
|
<td>{children}</td>
|
||||||
|
<td className="button-column">
|
||||||
|
{help && <Dropdown buttonClassName="bx bx-help-circle icon-action" hideToggleArrow>{help}</Dropdown>}
|
||||||
|
<ActionButton
|
||||||
|
icon="bx bx-x"
|
||||||
|
className="search-option-del"
|
||||||
|
onClick={() => removeOwnedAttributesByNameOrType(note, attributeType, attributeName)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SearchStringOption() {
|
||||||
|
return <SearchOption
|
||||||
|
title={t("search_string.title_column")}
|
||||||
|
help={<>
|
||||||
|
<strong>{t("search_string.search_syntax")}</strong> - {t("search_string.also_see")} <a href="#" data-help-page="search.html">{t("search_string.complete_help")}</a>
|
||||||
|
<ul style="marigin-bottom: 0;">
|
||||||
|
<li>{t("search_string.full_text_search")}</li>
|
||||||
|
<li><code>#abc</code> - {t("search_string.label_abc")}</li>
|
||||||
|
<li><code>#year = 2019</code> - {t("search_string.label_year")}</li>
|
||||||
|
<li><code>#rock #pop</code> - {t("search_string.label_rock_pop")}</li>
|
||||||
|
<li><code>#rock or #pop</code> - {t("search_string.label_rock_or_pop")}</li>
|
||||||
|
<li><code>#year <= 2000</code> - {t("search_string.label_year_comparison")}</li>
|
||||||
|
<li><code>note.dateCreated >= MONTH-1</code> - {t("search_string.label_date_created")}</li>
|
||||||
|
</ul>
|
||||||
|
</>}
|
||||||
|
>
|
||||||
|
<FormTextArea
|
||||||
|
className="search-string"
|
||||||
|
placeholder={t("search_string.placeholder")}
|
||||||
|
/>
|
||||||
|
</SearchOption>
|
||||||
}
|
}
|
@ -163,10 +163,6 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
|
|||||||
this.triggerEvent("searchRefreshed", { ntxId: this.noteContext?.ntxId });
|
this.triggerEvent("searchRefreshed", { ntxId: this.noteContext?.ntxId });
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshSearchDefinitionCommand() {
|
|
||||||
await this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
async refreshWithNote(note: FNote) {
|
async refreshWithNote(note: FNote) {
|
||||||
if (!this.note) {
|
if (!this.note) {
|
||||||
return;
|
return;
|
||||||
|
@ -49,21 +49,4 @@ export default abstract class AbstractSearchOption extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract doRender(): JQuery<HTMLElement>;
|
abstract doRender(): JQuery<HTMLElement>;
|
||||||
|
|
||||||
async deleteOption() {
|
|
||||||
// TODO: Find a better pattern.
|
|
||||||
await this.deleteAttribute((this.constructor as any).attributeType, (this.constructor as any).optionName);
|
|
||||||
|
|
||||||
await ws.waitForMaxKnownEntityChangeId();
|
|
||||||
|
|
||||||
await this.triggerCommand("refreshSearchDefinition");
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteAttribute(type: AttributeType, name: string) {
|
|
||||||
for (const attr of this.note.getOwnedAttributes()) {
|
|
||||||
if (attr.type === type && attr.name === name) {
|
|
||||||
await server.remove(`notes/${this.note.noteId}/attributes/${attr.attributeId}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,34 +6,6 @@ import appContext, { type EventData } from "../../components/app_context.js";
|
|||||||
import { t } from "../../services/i18n.js";
|
import { t } from "../../services/i18n.js";
|
||||||
import { Tooltip } from "bootstrap";
|
import { Tooltip } from "bootstrap";
|
||||||
|
|
||||||
const TPL = /*html*/`
|
|
||||||
<tr>
|
|
||||||
<td class="title-column">${t("search_string.title_column")}</td>
|
|
||||||
<td>
|
|
||||||
<textarea class="form-control search-string" placeholder="${t("search_string.placeholder")}" autofocus></textarea>
|
|
||||||
</td>
|
|
||||||
<td class="button-column">
|
|
||||||
<div class="dropdown help-dropdown">
|
|
||||||
<span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right p-4">
|
|
||||||
<strong>${t("search_string.search_syntax")}</strong> - ${t("search_string.also_see")} <a href="#" data-help-page="search.html">${t("search_string.complete_help")}</a>
|
|
||||||
|
|
||||||
<ul style="marigin-bottom: 0;">
|
|
||||||
<li>${t("search_string.full_text_search")}</li>
|
|
||||||
<li><code>#abc</code> - ${t("search_string.label_abc")}</li>
|
|
||||||
<li><code>#year = 2019</code> - ${t("search_string.label_year")}</li>
|
|
||||||
<li><code>#rock #pop</code> - ${t("search_string.label_rock_pop")}</li>
|
|
||||||
<li><code>#rock or #pop</code> - ${t("search_string.label_rock_or_pop")}</li>
|
|
||||||
<li><code>#year <= 2000</code> - ${t("search_string.label_year_comparison")}</li>
|
|
||||||
<li><code>note.dateCreated >= MONTH-1</code> - ${t("search_string.label_date_created")}</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span class="bx bx-x icon-action search-option-del"></span>
|
|
||||||
</td>
|
|
||||||
</tr>`;
|
|
||||||
|
|
||||||
export default class SearchString extends AbstractSearchOption {
|
export default class SearchString extends AbstractSearchOption {
|
||||||
|
|
||||||
private $searchString!: JQuery<HTMLElement>;
|
private $searchString!: JQuery<HTMLElement>;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user