mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 07:38:53 +02:00
feat(react): port sort child notes
This commit is contained in:
parent
164feaa3ec
commit
bca397e3e4
@ -305,7 +305,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "根据不同语言或地区的字符排序和排序规则排序。",
|
||||
"natural_sort_language": "自然排序语言",
|
||||
"the_language_code_for_natural_sort": "自然排序的语言代码,例如中文的 \"zh-CN\"。",
|
||||
"sort": "排序 <kbd>Enter</kbd>"
|
||||
"sort": "排序"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "上传附件到笔记",
|
||||
|
@ -303,7 +303,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "Sortierung im Hinblick auf unterschiedliche Sortier- und Sortierregeln für Zeichen in verschiedenen Sprachen oder Regionen.",
|
||||
"natural_sort_language": "Natürliche Sortiersprache",
|
||||
"the_language_code_for_natural_sort": "Der Sprachcode für die natürliche Sortierung, z. B. \"de-DE\" für Deutsch.",
|
||||
"sort": "Sortieren <kbd>Eingabetaste</kbd>"
|
||||
"sort": "Sortieren"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Lade Anhänge zur Notiz hoch",
|
||||
|
@ -309,7 +309,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "sort with respect to different character sorting and collation rules in different languages or regions.",
|
||||
"natural_sort_language": "Natural sort language",
|
||||
"the_language_code_for_natural_sort": "The language code for natural sort, e.g. \"zh-CN\" for Chinese.",
|
||||
"sort": "Sort <kbd>enter</kbd>"
|
||||
"sort": "Sort"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Upload attachments to note",
|
||||
|
@ -308,7 +308,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "ordenar con respecto a diferentes reglas de ordenamiento y clasificación de caracteres en diferentes idiomas o regiones.",
|
||||
"natural_sort_language": "Idioma de clasificación natural",
|
||||
"the_language_code_for_natural_sort": "El código del idioma para el ordenamiento natural, ej. \"zh-CN\" para Chino.",
|
||||
"sort": "Ordenar <kbd>Enter</kbd>"
|
||||
"sort": "Ordenar"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Cargar archivos adjuntos a nota",
|
||||
|
@ -303,7 +303,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "trier en fonction de différentes règles de tri et de classement des caractères dans différentes langues ou régions.",
|
||||
"natural_sort_language": "Langage de tri naturel",
|
||||
"the_language_code_for_natural_sort": "Le code de langue pour le tri naturel, par ex. \"zh-CN\" pour le chinois.",
|
||||
"sort": "Trier <kbd>Entrée</kbd>"
|
||||
"sort": "Trier"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Téléverser des pièces jointes à la note",
|
||||
|
@ -1193,7 +1193,7 @@
|
||||
"folders": "Dosare",
|
||||
"natural_sort": "Ordonare naturală",
|
||||
"natural_sort_language": "Limba pentru ordonare naturală",
|
||||
"sort": "Ordonare <kbd>Enter</kbd>",
|
||||
"sort": "Ordonare",
|
||||
"sort_children_by": "Ordonează subnotițele după...",
|
||||
"sort_folders_at_top": "ordonează dosarele primele",
|
||||
"sort_with_respect_to_different_character_sorting": "ordonează respectând regulile de sortare și clasificare diferite în funcție de limbă și regiune.",
|
||||
|
@ -309,7 +309,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "sortiranje sa poštovanjem različitih pravila sortiranja karaktera i kolacija u različitim jezicima ili regionima.",
|
||||
"natural_sort_language": "Jezik za prirodno sortiranje",
|
||||
"the_language_code_for_natural_sort": "Kod jezika za prirodno sortiranje, npr. \"zh-CN\" za Kineski.",
|
||||
"sort": "Sortiraj <kbd>enter</kbd>"
|
||||
"sort": "Sortiraj"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "Otpremite priloge uz belešku",
|
||||
|
@ -278,7 +278,7 @@
|
||||
"sort_with_respect_to_different_character_sorting": "根據不同語言或地區的字符排序和排序規則排序。",
|
||||
"natural_sort_language": "自然排序語言",
|
||||
"the_language_code_for_natural_sort": "自然排序的語言程式碼,例如繁體中文的 \"zh-TW\"。",
|
||||
"sort": "排序 <kbd>Enter</kbd>"
|
||||
"sort": "排序"
|
||||
},
|
||||
"upload_attachments": {
|
||||
"upload_attachments_to_note": "上傳附件到筆記",
|
||||
|
@ -1,113 +0,0 @@
|
||||
import type { EventData } from "../../components/app_context.js";
|
||||
import { closeActiveDialog, openDialog } from "../../services/dialog.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import server from "../../services/server.js";
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
|
||||
const TPL = /*html*/`<div class="sort-child-notes-dialog modal mx-auto" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" style="max-width: 500px" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${t("sort_child_notes.sort_children_by")}</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("sort_child_notes.close")}"></button>
|
||||
</div>
|
||||
<form class="sort-child-notes-form">
|
||||
<div class="modal-body">
|
||||
<h5>${t("sort_child_notes.sorting_criteria")}</h5>
|
||||
<div class="form-check">
|
||||
<label for="sort-by-title" class="form-check-label tn-radio">
|
||||
<input id="sort-by-title" class="form-check-input" type="radio" name="sort-by" value="title" checked>
|
||||
${t("sort_child_notes.title")}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label for="sort-by-dateCreated" class="form-check-label tn-radio">
|
||||
<input id="sort-by-dateCreated" class="form-check-input" type="radio" name="sort-by" value="dateCreated">
|
||||
${t("sort_child_notes.date_created")}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label for="sort-by-dateModified" class="form-check-label tn-radio">
|
||||
<input id="sort-by-dateModified" class="form-check-input" type="radio" name="sort-by" value="dateModified">
|
||||
${t("sort_child_notes.date_modified")}
|
||||
</label>
|
||||
</div>
|
||||
<br/>
|
||||
<h5>${t("sort_child_notes.sorting_direction")}</h5>
|
||||
<div class="form-check">
|
||||
<label for="sort-direction-asc" class="form-check-label tn-radio">
|
||||
<input id="sort-direction-asc" class="form-check-input" type="radio" name="sort-direction" value="asc" checked>
|
||||
${t("sort_child_notes.ascending")}
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label for="sort-direction-desc" class="form-check-label tn-radio">
|
||||
<input id="sort-direction-desc" class="form-check-input" type="radio" name="sort-direction" value="desc">
|
||||
${t("sort_child_notes.descending")}
|
||||
</label>
|
||||
</div>
|
||||
<br />
|
||||
<h5>${t("sort_child_notes.folders")}</h5>
|
||||
<div class="form-check">
|
||||
<label for="sort-folders-first" class="form-check-label tn-checkbox">
|
||||
<input id="sort-folders-first" class="form-check-input" type="checkbox" name="sort-folders-first" value="1">
|
||||
${t("sort_child_notes.sort_folders_at_top")}
|
||||
</label>
|
||||
</div>
|
||||
<br />
|
||||
<h5>${t("sort_child_notes.natural_sort")}</h5>
|
||||
<div class="form-check">
|
||||
<label for="sort-natural" class="form-check-label tn-checkbox">
|
||||
<input id="sort-natural" class="form-check-input" type="checkbox" name="sort-natural" value="1">
|
||||
${t("sort_child_notes.sort_with_respect_to_different_character_sorting")}
|
||||
</label>
|
||||
</div>
|
||||
<br />
|
||||
<div class="form-check">
|
||||
<label>
|
||||
${t("sort_child_notes.natural_sort_language")}
|
||||
<input class="form-control" name="sort-locale">
|
||||
${t("sort_child_notes.the_language_code_for_natural_sort")}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">${t("sort_child_notes.sort")}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
export default class SortChildNotesDialog extends BasicWidget {
|
||||
|
||||
private parentNoteId?: string;
|
||||
private $form!: JQuery<HTMLElement>;
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$form = this.$widget.find(".sort-child-notes-form");
|
||||
|
||||
this.$form.on("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const sortBy = this.$form.find("input[name='sort-by']:checked").val();
|
||||
const sortDirection = this.$form.find("input[name='sort-direction']:checked").val();
|
||||
const foldersFirst = this.$form.find("input[name='sort-folders-first']").is(":checked");
|
||||
const sortNatural = this.$form.find("input[name='sort-natural']").is(":checked");
|
||||
const sortLocale = this.$form.find("input[name='sort-locale']").val();
|
||||
|
||||
await server.put(`notes/${this.parentNoteId}/sort-children`, { sortBy, sortDirection, foldersFirst, sortNatural, sortLocale });
|
||||
|
||||
closeActiveDialog();
|
||||
});
|
||||
}
|
||||
|
||||
async sortChildNotesEvent({ node }: EventData<"sortChildNotes">) {
|
||||
this.parentNoteId = node.data.noteId;
|
||||
|
||||
openDialog(this.$widget);
|
||||
|
||||
this.$form.find("input:first").focus();
|
||||
}
|
||||
}
|
104
apps/client/src/widgets/dialogs/sort_child_notes.tsx
Normal file
104
apps/client/src/widgets/dialogs/sort_child_notes.tsx
Normal file
@ -0,0 +1,104 @@
|
||||
import { useState } from "preact/hooks";
|
||||
import { EventData } from "../../components/app_context";
|
||||
import { closeActiveDialog, openDialog } from "../../services/dialog";
|
||||
import { t } from "../../services/i18n";
|
||||
import Button from "../react/Button";
|
||||
import FormCheckbox from "../react/FormCheckbox";
|
||||
import FormRadioGroup from "../react/FormRadioGroup";
|
||||
import FormTextBox from "../react/FormTextBox";
|
||||
import Modal from "../react/Modal";
|
||||
import ReactBasicWidget from "../react/ReactBasicWidget";
|
||||
import server from "../../services/server";
|
||||
|
||||
function SortChildNotesDialogComponent({ parentNoteId }: { parentNoteId?: string }) {
|
||||
const [ sortBy, setSortBy ] = useState("title");
|
||||
const [ sortDirection, setSortDirection ] = useState("asc");
|
||||
const [ foldersFirst, setFoldersFirst ] = useState(false);
|
||||
const [ sortNatural, setSortNatural ] = useState(false);
|
||||
const [ sortLocale, setSortLocale ] = useState("");
|
||||
|
||||
async function onSubmit() {
|
||||
await server.put(`notes/${parentNoteId}/sort-children`, {
|
||||
sortBy,
|
||||
sortDirection,
|
||||
foldersFirst,
|
||||
sortNatural,
|
||||
sortLocale
|
||||
});
|
||||
|
||||
// Close the dialog after submission
|
||||
closeActiveDialog();
|
||||
}
|
||||
|
||||
return (parentNoteId &&
|
||||
<Modal
|
||||
className="sort-child-notes-dialog"
|
||||
title={t("sort_child_notes.sort_children_by")}
|
||||
size="lg"
|
||||
onSubmit={onSubmit}
|
||||
footer={<Button text={t("sort_child_notes.sort")} keyboardShortcut="Enter" />}
|
||||
>
|
||||
<h5>{t("sort_child_notes.sorting_criteria")}</h5>
|
||||
<FormRadioGroup
|
||||
name="sort-by"
|
||||
values={[
|
||||
{ value: "title", label: t("sort_child_notes.title") },
|
||||
{ value: "dateCreated", label: t("sort_child_notes.date_created") },
|
||||
{ value: "dateModified", label: t("sort_child_notes.date_modified") }
|
||||
]}
|
||||
currentValue={sortBy} onChange={setSortBy}
|
||||
/>
|
||||
<br/>
|
||||
|
||||
<h5>{t("sort_child_notes.sorting_direction")}</h5>
|
||||
<FormRadioGroup
|
||||
name="sort-direction"
|
||||
values={[
|
||||
{ value: "asc", label: t("sort_child_notes.ascending") },
|
||||
{ value: "desc", label: t("sort_child_notes.descending") }
|
||||
]}
|
||||
currentValue={sortDirection} onChange={setSortDirection}
|
||||
/>
|
||||
<br/>
|
||||
|
||||
<h5>{t("sort_child_notes.folders")}</h5>
|
||||
<FormCheckbox
|
||||
label={t("sort_child_notes.sort_folders_at_top")}
|
||||
name="sort-folders-first"
|
||||
currentValue={foldersFirst} onChange={setFoldersFirst}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<h5>{t("sort_child_notes.natural_sort")}</h5>
|
||||
<FormCheckbox
|
||||
name="sort-natural"
|
||||
label={t("sort_child_notes.sort_with_respect_to_different_character_sorting")}
|
||||
currentValue={sortNatural} onChange={setSortNatural}
|
||||
/>
|
||||
<FormTextBox
|
||||
className="form-check"
|
||||
name="sort-locale"
|
||||
label={t("sort_child_notes.natural_sort_language")}
|
||||
description={t("sort_child_notes.the_language_code_for_natural_sort")}
|
||||
currentValue={sortLocale} onChange={setSortLocale}
|
||||
/>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default class SortChildNotesDialog extends ReactBasicWidget {
|
||||
|
||||
private parentNoteId?: string;
|
||||
|
||||
get component() {
|
||||
return <SortChildNotesDialogComponent parentNoteId={this.parentNoteId} />;
|
||||
}
|
||||
|
||||
async sortChildNotesEvent({ node }: EventData<"sortChildNotes">) {
|
||||
this.parentNoteId = node.data.noteId;
|
||||
this.doRender();
|
||||
openDialog(this.$widget);
|
||||
}
|
||||
|
||||
|
||||
}
|
23
apps/client/src/widgets/react/FormCheckbox.tsx
Normal file
23
apps/client/src/widgets/react/FormCheckbox.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
interface FormCheckboxProps {
|
||||
name: string;
|
||||
label: string;
|
||||
currentValue?: boolean;
|
||||
onChange(newValue: boolean): void;
|
||||
}
|
||||
|
||||
export default function FormCheckbox({ name, label, currentValue, onChange }: FormCheckboxProps) {
|
||||
return (
|
||||
<div className="form-check">
|
||||
<label className="form-check-label tn-checkbox">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
name={name}
|
||||
checked={currentValue || false}
|
||||
value="1"
|
||||
onChange={e => onChange((e.target as HTMLInputElement).checked)} />
|
||||
{label}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
30
apps/client/src/widgets/react/FormRadioGroup.tsx
Normal file
30
apps/client/src/widgets/react/FormRadioGroup.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
interface FormRadioProps {
|
||||
name: string;
|
||||
currentValue?: string;
|
||||
values: {
|
||||
value: string;
|
||||
label: string;
|
||||
}[];
|
||||
onChange(newValue: string): void;
|
||||
}
|
||||
|
||||
export default function FormRadioGroup({ name, values, currentValue, onChange }: FormRadioProps) {
|
||||
return (
|
||||
<>
|
||||
{(values || []).map(({ value, label }) => (
|
||||
<div className="form-check">
|
||||
<label className="form-check-label tn-radio">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="radio"
|
||||
name={name}
|
||||
value={value}
|
||||
checked={value === currentValue}
|
||||
onChange={e => onChange((e.target as HTMLInputElement).value)} />
|
||||
{label}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
25
apps/client/src/widgets/react/FormTextBox.tsx
Normal file
25
apps/client/src/widgets/react/FormTextBox.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
interface FormTextBoxProps {
|
||||
name: string;
|
||||
label: string;
|
||||
currentValue?: string;
|
||||
className?: string;
|
||||
description?: string;
|
||||
onChange?(newValue: string): void;
|
||||
}
|
||||
|
||||
export default function FormTextBox({ name, label, description, className, currentValue, onChange }: FormTextBoxProps) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<label>
|
||||
{label}
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
name={name}
|
||||
value={currentValue}
|
||||
onInput={e => onChange?.(e.currentTarget.value)} />
|
||||
{description && <small className="form-text text-muted">{description}</small>}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user