taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 6c9df8fed4d015a5e0c075149f67f97f2dc41cd1
parent 2efb0d71f3507bade1fbcb609251d6ebf18d9c81
Author: Sebastian <sebasjm@taler-systems.com>
Date:   Fri, 30 Jan 2026 11:32:53 -0300

fix #10743

Diffstat:
Mpackages/merchant-backoffice-ui/src/components/form/FormProvider.tsx | 4++--
Mpackages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx | 4++--
Mpackages/merchant-backoffice-ui/src/components/menu/SideBar.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/hooks/preference.ts | 7++++++-
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/settings/index.tsx | 30+++++++++++++++++++++++-------
Mpackages/taler-util/src/types-taler-merchant.ts | 2+-
8 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/packages/merchant-backoffice-ui/src/components/form/FormProvider.tsx b/packages/merchant-backoffice-ui/src/components/form/FormProvider.tsx @@ -61,12 +61,12 @@ export function FormProvider<T>({ }), [errors, object, valueHandler], ); - const [{ persona }] = usePreference(); + const [{ developer }] = usePreference(); return ( <FormContext.Provider value={value}> <form>{children}</form> - {persona !== "developer" ? undefined : <pre>{JSON.stringify(value.object, undefined, 2)}</pre>} + {developer ? <pre>{JSON.stringify(value.object, undefined, 2)}</pre> : undefined} </FormContext.Provider> ); } diff --git a/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx b/packages/merchant-backoffice-ui/src/components/menu/LangSelector.tsx @@ -35,7 +35,7 @@ const LANG_NAMES_PROD: LangsNames = { de: "Deutsch [de]", en: "English [en]", }; -const LANG_NAMES_DEV: LangsNames = { +const LANG_NAMES_ALL: LangsNames = { fr: "Français [fr]", de: "Deutsch [de]", en: "English [en]", @@ -56,7 +56,7 @@ export function LangSelector(): VNode { const { lang, changeLanguage } = useTranslationContext(); const [{ persona }] = usePreference(); const names = - persona === "developer" ? LANG_NAMES_DEV : LANG_NAMES_PROD; + persona === "tester" ? LANG_NAMES_ALL : LANG_NAMES_PROD; return ( <div class="dropdown is-active "> diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx @@ -455,7 +455,7 @@ const ALL_ELEMENTS = Object.values(UIElement).reduce((prev, ui) => { export function getAvailableForPersona(p: MerchantPersona): ElementMap { switch (p) { - case "developer": + case "tester": return ALL_ELEMENTS; case "expert": return { diff --git a/packages/merchant-backoffice-ui/src/hooks/preference.ts b/packages/merchant-backoffice-ui/src/hooks/preference.ts @@ -20,6 +20,7 @@ import { MerchantPersona, buildCodecForObject, codecForAbsoluteTime, + codecForBoolean, codecForConstString, codecForEither, codecOptional, @@ -64,6 +65,7 @@ export interface Preferences { hideMissingAccountUntil: AbsoluteTime; dateFormat: "ymd" | "dmy" | "mdy"; persona: MerchantPersona; + developer: boolean; } const defaultSettings: Preferences = { @@ -71,11 +73,14 @@ const defaultSettings: Preferences = { hideMissingAccountUntil: AbsoluteTime.never(), dateFormat: "ymd", persona: "expert", + developer: false, }; + export const codecForPreferences = (): Codec<Preferences> => buildCodecForObject<Preferences>() .property("hideKycUntil", codecForAbsoluteTime) + .property("developer", codecOptionalDefault(codecForBoolean(), false)) .property("hideMissingAccountUntil", codecForAbsoluteTime) .property( "dateFormat", @@ -89,7 +94,7 @@ export const codecForPreferences = (): Codec<Preferences> => "persona", codecOptionalDefault( codecForEither( - codecForConstString("developer"), + codecForConstString("tester"), codecForConstString("expert"), codecForConstString("offline-vending-machine"), codecForConstString("point-of-sale"), diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx @@ -73,7 +73,7 @@ export function CreatePage({ onCreated, onBack }: Props): VNode { const [{ persona }] = usePreference(); const accountAuthType = - persona === "developer" ? ["none", "basic", "bearer"] : ["none", "basic"]; + persona === "tester" ? ["none", "basic", "bearer"] : ["none", "basic"]; const [state, setState] = useState<Partial<Entity>>({ credit_facade_credentials: { diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx @@ -76,7 +76,7 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode { const [{ persona }] = usePreference(); const accountAuthType = - persona === "developer" + persona === "tester" ? ["unedit", "none", "basic", "bearer"] : ["unedit", "none", "basic"]; diff --git a/packages/merchant-backoffice-ui/src/paths/settings/index.tsx b/packages/merchant-backoffice-ui/src/paths/settings/index.tsx @@ -35,6 +35,7 @@ import { Preferences, usePreference, } from "../../hooks/preference.js"; +import { InputBoolean } from "../../components/form/InputBoolean.js"; const TALER_SCREEN_ID = 83; @@ -59,9 +60,10 @@ export function Settings({ onClose }: { onClose?: () => void }): VNode { hideKycUntil: next.hideKycUntil ?? AbsoluteTime.never(), dateFormat: next.dateFormat ?? "ymd", persona: next.persona ?? config.default_persona, + developer: next.developer ?? false }; - const isDeveloper = next.persona === "developer"; + const isDeveloper = next.developer === true; if (isDeveloper !== showDebugInfo) { updateCommonPref("showDebugInfo", isDeveloper); } @@ -139,15 +141,15 @@ export function Settings({ onClose }: { onClose?: () => void }): VNode { "offline-vending-machine", "point-of-sale", "expert", - "developer", + "tester", ] as MerchantPersona[] } toStr={(e: MerchantPersona) => { switch (e) { + case "tester": + return i18n.str`Beta tester`; case "expert": return i18n.str`Expert user`; - case "developer": - return i18n.str`Taler developer`; case "offline-vending-machine": return i18n.str`Unattended in-person offline vending`; case "point-of-sale": @@ -159,17 +161,31 @@ export function Settings({ onClose }: { onClose?: () => void }): VNode { } }} /> + <InputBoolean + label={i18n.str`Developer tools`} + tooltip={i18n.str`Enable UI tools for troubleshooting.`} + name="developer" + /> </FormProvider> </div> - {value.persona === "developer" ? ( + {value.persona === "tester" ? ( <NotificationCard notification={{ - message: i18n.str`Developer mode`, - description: i18n.str`Only use developer mode if you know how the application works. Some features enabled in this mode are still under testing.`, + message: i18n.str`Testing features`, + description: i18n.str`Only use beta-tester mode if you know how the application works. Features enabled in this mode requires more work.`, type: "WARN", }} /> ) : undefined} + {value.developer ? ( + <NotificationCard + notification={{ + message: i18n.str`Developer mode`, + description: i18n.str`Only use developer mode if you know what you are doing. Tools enabled in this mode are intended to fix problems or get more information about the runtime. YOU MAY LOSE DATA.`, + type: "ERROR", + }} + /> + ) : undefined} </div> <div class="column" /> </div> diff --git a/packages/taler-util/src/types-taler-merchant.ts b/packages/taler-util/src/types-taler-merchant.ts @@ -1191,7 +1191,7 @@ export const codecForMerchantContractDiscountTokenDetails = .build("TalerMerchantApi.ContractDiscountTokenDetails"); export type MerchantPersona = - | "developer" + | "tester" | "expert" | "offline-vending-machine" | "point-of-sale"