mirror of
https://github.com/zadam/trilium.git
synced 2025-10-21 15:49:00 +02:00
feat(react/settings): port content languages
This commit is contained in:
parent
c039f06c2b
commit
c368ec3c38
@ -40,7 +40,8 @@ function FormRadio({ name, value, label, currentValue, onChange, labelClassName
|
||||
name={useUniqueName(name)}
|
||||
value={value}
|
||||
checked={value === currentValue}
|
||||
onChange={e => onChange((e.target as HTMLInputElement).value)} />
|
||||
onChange={e => onChange((e.target as HTMLInputElement).value)}
|
||||
/>
|
||||
{label}
|
||||
</label>
|
||||
)
|
||||
|
@ -142,6 +142,14 @@ export function useTriliumOptionInt(name: OptionNames): [number, (newValue: numb
|
||||
]
|
||||
}
|
||||
|
||||
export function useTriliumOptionJson<T>(name: OptionNames): [ T, (newValue: T) => Promise<void> ] {
|
||||
const [ value, setValue ] = useTriliumOption(name);
|
||||
return [
|
||||
(JSON.parse(value) as T),
|
||||
(newValue => setValue(JSON.stringify(newValue)))
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique name via a random alphanumeric string of a fixed length.
|
||||
*
|
||||
|
@ -24,7 +24,6 @@ import HtmlImportTagsOptions from "./options/other/html_import_tags.js";
|
||||
import BackendLogWidget from "./content/backend_log.js";
|
||||
import AttachmentErasureTimeoutOptions from "./options/other/attachment_erasure_timeout.js";
|
||||
import MultiFactorAuthenticationOptions from './options/multi_factor_authentication.js';
|
||||
import LocalizationOptions from "./options/i18n/i18n.js";
|
||||
import CodeBlockOptions from "./options/text_notes/code_block.js";
|
||||
import EditorOptions from "./options/text_notes/editor.js";
|
||||
import ShareSettingsOptions from "./options/other/share_settings.js";
|
||||
@ -32,7 +31,6 @@ import AiSettingsOptions from "./options/ai_settings.js";
|
||||
import type FNote from "../../entities/fnote.js";
|
||||
import type NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import { t } from "../../services/i18n.js";
|
||||
import LanguageOptions from "./options/i18n/language.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import CodeTheme from "./options/code_notes/code_theme.js";
|
||||
import EditorFeaturesOptions from "./options/text_notes/features.js";
|
||||
|
@ -0,0 +1,40 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
interface CheckboxListProps<T> {
|
||||
values: T[];
|
||||
keyProperty: keyof T;
|
||||
titleProperty?: keyof T;
|
||||
currentValue: string[];
|
||||
onChange: (newValues: string[]) => void;
|
||||
}
|
||||
|
||||
export default function CheckboxList<T>({ values, keyProperty, titleProperty, currentValue, onChange }: CheckboxListProps<T>) {
|
||||
function toggleValue(value: string) {
|
||||
if (currentValue.includes(value)) {
|
||||
// Already there, needs removing.
|
||||
onChange(currentValue.filter(v => v !== value));
|
||||
} else {
|
||||
// Not there, needs adding.
|
||||
onChange([ ...currentValue, value ]);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ul style={{ listStyleType: "none", marginBottom: 0, columnWidth: "400px" }}>
|
||||
{values.map(value => (
|
||||
<li>
|
||||
<label className="tn-checkbox">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
value={String(value[keyProperty])}
|
||||
checked={currentValue.includes(String(value[keyProperty]))}
|
||||
onChange={e => toggleValue((e.target as HTMLInputElement).value)}
|
||||
/>
|
||||
{String(value[titleProperty ?? keyProperty] ?? value[keyProperty])}
|
||||
</label>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
@ -3,7 +3,7 @@ import { getAvailableLocales, t } from "../../../services/i18n";
|
||||
import FormSelect from "../../react/FormSelect";
|
||||
import OptionsRow from "./components/OptionsRow";
|
||||
import OptionsSection from "./components/OptionsSection";
|
||||
import { useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
|
||||
import { useTriliumOption, useTriliumOptionInt, useTriliumOptionJson } from "../../react/hooks";
|
||||
import type { Locale } from "@triliumnext/commons";
|
||||
import { isElectron, restartDesktopApp } from "../../../services/utils";
|
||||
import FormRadioGroup, { FormInlineRadioGroup } from "../../react/FormRadioGroup";
|
||||
@ -11,11 +11,13 @@ import FormText from "../../react/FormText";
|
||||
import RawHtml from "../../react/RawHtml";
|
||||
import Admonition from "../../react/Admonition";
|
||||
import Button from "../../react/Button";
|
||||
import CheckboxList from "./components/CheckboxList";
|
||||
|
||||
export default function InternationalizationOptions() {
|
||||
return (
|
||||
<>
|
||||
<LocalizationOptions />
|
||||
<ContentLanguages />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -116,3 +118,20 @@ function DateSettings() {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function ContentLanguages() {
|
||||
const locales = useMemo(() => getAvailableLocales(), []);
|
||||
const [ languages, setLanguages ] = useTriliumOptionJson<string[]>("languages");
|
||||
|
||||
return (
|
||||
<OptionsSection title={t("content_language.title")}>
|
||||
<FormText>{t("content_language.description")}</FormText>
|
||||
|
||||
<CheckboxList
|
||||
values={locales}
|
||||
keyProperty="id" titleProperty="name"
|
||||
currentValue={languages} onChange={setLanguages}
|
||||
/>
|
||||
</OptionsSection>
|
||||
);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
import OptionsWidget from "../options_widget.js";
|
||||
import type { OptionMap } from "@triliumnext/commons";
|
||||
import { getAvailableLocales } from "../../../../services/i18n.js";
|
||||
import { t } from "../../../../services/i18n.js";
|
||||
|
||||
const TPL = /*html*/`
|
||||
<div class="options-section">
|
||||
<h4>${t("content_language.title")}</h4>
|
||||
<p class="form-text">${t("content_language.description")}</p>
|
||||
|
||||
<ul class="options-languages">
|
||||
</ul>
|
||||
|
||||
<style>
|
||||
ul.options-languages {
|
||||
list-style-type: none;
|
||||
margin-bottom: 0;
|
||||
column-width: 400px;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default class LanguageOptions extends OptionsWidget {
|
||||
|
||||
private $languagesContainer!: JQuery<HTMLElement>;
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$languagesContainer = this.$widget.find(".options-languages");
|
||||
}
|
||||
|
||||
async save() {
|
||||
const enabledLanguages: string[] = [];
|
||||
|
||||
this.$languagesContainer.find("input:checked").each((i, el) => {
|
||||
const languageId = $(el).attr("data-language-id");
|
||||
if (languageId) {
|
||||
enabledLanguages.push(languageId);
|
||||
}
|
||||
});
|
||||
|
||||
await this.updateOption("languages", JSON.stringify(enabledLanguages));
|
||||
}
|
||||
|
||||
async optionsLoaded(options: OptionMap) {
|
||||
const availableLocales = getAvailableLocales();
|
||||
const enabledLanguages = (JSON.parse(options.languages) as string[]);
|
||||
|
||||
this.$languagesContainer.empty();
|
||||
for (const locale of availableLocales) {
|
||||
const checkbox = $('<input type="checkbox" class="form-check-input">')
|
||||
.attr("data-language-id", locale.id)
|
||||
.prop("checked", enabledLanguages.includes(locale.id));
|
||||
const wrapper = $(`<label class="tn-checkbox">`)
|
||||
.append(checkbox)
|
||||
.on("change", () => this.save())
|
||||
.append(locale.name);
|
||||
this.$languagesContainer.append($("<li>").append(wrapper));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user