commit ca11dd20231ad9f1c8e06b0e257061ccccc324d5
parent 4098fb972e566cd2f718056279a547136f69d10f
Author: Sebastian <sebasjm@gmail.com>
Date: Fri, 14 Nov 2025 11:08:04 -0300
fix horrible rendering on error
Diffstat:
5 files changed, 89 insertions(+), 68 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/components/SolveMFA.tsx b/packages/merchant-backoffice-ui/src/components/SolveMFA.tsx
@@ -175,11 +175,11 @@ function SolveChallenge({
borderTop: 0,
}}
>
- <button class="button" onClick={onCancel}>
+ <button class="button" type="button" onClick={onCancel}>
<i18n.Translate>Back</i18n.Translate>
</button>
<ButtonBetterBulma
- type="is-info"
+ type="submit"
onClick={verify}
>
<i18n.Translate>Verify</i18n.Translate>
diff --git a/packages/merchant-backoffice-ui/src/components/form/JumpToElementById.tsx b/packages/merchant-backoffice-ui/src/components/form/JumpToElementById.tsx
@@ -15,9 +15,8 @@
*/
import { AccessToken, TranslatedString } from "@gnu-taler/taler-util";
import {
- ButtonBetter,
ButtonBetterBulma,
- LocalNotificationBanner,
+ Notification,
useLocalNotificationBetter,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
@@ -25,6 +24,21 @@ import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useSessionContext } from "../../context/session.js";
+function NotificationFieldFoot({
+ notification,
+}: {
+ notification?: Notification;
+}): VNode | null {
+ if (!notification) return null;
+ if (notification.message.type === "error")
+ return (
+ <p class="help is-danger" style={{ fontSize: 16 }}>
+ {notification.message.description}
+ </p>
+ );
+ return null;
+}
+
export function JumpToElementById({
onSelect,
placeholder,
@@ -51,29 +65,37 @@ export function JumpToElementById({
return (
<Fragment>
- <LocalNotificationBanner notification={notification} />
-
<div class="level">
<div class="level-left">
<div class="level-item">
- <div class="field has-addons">
- <div class="control">
- <input
- class={"input"}
- type="text"
- value={id ?? ""}
- onChange={(e) => setId(e.currentTarget.value)}
- placeholder={placeholder}
- />
+ <form>
+ <div class="field has-addons">
+ <div class="control">
+ <input
+ class={"input"}
+ type="text"
+ value={id ?? ""}
+ onChange={(e) => {
+ setId(e.currentTarget.value)
+ if (notification) notification.acknowledge()
+ }}
+ placeholder={placeholder}
+ />
+ <NotificationFieldFoot notification={notification} />
+ </div>
+ <span class="has-tooltip-bottom" data-tooltip={description}>
+ <ButtonBetterBulma
+ class="button"
+ type="submit"
+ onClick={checkExist}
+ >
+ <span class="icon">
+ <i class="mdi mdi-arrow-right" />
+ </span>
+ </ButtonBetterBulma>
+ </span>
</div>
- <span class="has-tooltip-bottom" data-tooltip={description}>
- <ButtonBetterBulma class="button" onClick={checkExist}>
- <span class="icon">
- <i class="mdi mdi-arrow-right" />
- </span>
- </ButtonBetterBulma>
- </span>
- </div>
+ </form>
</div>
</div>
</div>
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx
@@ -58,6 +58,8 @@ export type Entity = TalerMerchantApi.InstanceConfigurationMessage & {
auth_token?: string;
// default_pay_delay: Duration;
// default_wire_transfer_delay: Duration;
+ password: string;
+ repeat: string;
};
export interface Props {
@@ -78,13 +80,12 @@ function with_defaults(id?: string): Partial<Entity> {
};
}
-type TokenForm = { password: string; repeat: string };
+// type TokenForm = { };
export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
const [pref, updatePref] = usePreference();
const { i18n } = useTranslationContext();
const [value, valueHandler] = useState(with_defaults(forceId));
- const [tokenForm, setTokenForm] = useState<Partial<TokenForm>>({});
const errors = undefinedIfEmpty<FormErrors<Entity>>({
id: !value.id
@@ -128,20 +129,15 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
? i18n.str`Max 7 lines`
: undefined,
}),
- });
-
- const hasErrors = errors !== undefined;
-
- const tokenFormErrors = undefinedIfEmpty<FormErrors<TokenForm>>({
- password: !tokenForm.password ? i18n.str`Required` : undefined,
- repeat: !tokenForm.repeat
+ password: !value.password ? i18n.str`Required` : undefined,
+ repeat: !value.repeat
? i18n.str`Required`
- : tokenForm.repeat !== tokenForm.password
+ : value.repeat !== value.password
? i18n.str`Doesn't match`
: undefined,
});
- const hasTokenErrors = tokenFormErrors !== undefined;
+ const hasErrors = errors !== undefined;
const [notification, safeFunctionHandler] = useLocalNotificationBetter();
const { state: session, lib, logIn } = useSessionContext();
const mfa = useChallengeHandler();
@@ -150,7 +146,7 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
...(value as TalerMerchantApi.InstanceConfigurationMessage),
auth: {
method: MerchantAuthMethod.TOKEN,
- password: tokenForm.password!,
+ password: value.password!,
},
};
const create = safeFunctionHandler(
@@ -166,7 +162,11 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
});
if (instanceResp.type === "fail") return instanceResp;
if (data.auth.password) {
- const tokenResp = await lib.subInstanceApi(data.id).instance.createAccessToken(
+ const api =
+ data.id === "admin"
+ ? lib.instance
+ : lib.subInstanceApi(data.id).instance;
+ const tokenResp = await api.createAccessToken(
data.id,
data.auth.password,
FOREVER_REFRESHABLE_TOKEN(i18n.str`Instance created`),
@@ -176,9 +176,7 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
}
return opEmptySuccess();
},
- !session.token || hasErrors || hasTokenErrors
- ? undefined
- : [session.token, data, []],
+ !session.token || hasErrors ? undefined : [session.token, data, []],
);
create.onSuccess = (success, oldtoken, data) => {
if (success) {
@@ -260,42 +258,37 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
showId={!forceId}
showLessFields={!pref.advanceInstanceMode}
/>
- </FormProvider>
- <FormProvider
- errors={tokenFormErrors}
- object={tokenForm}
- valueHandler={setTokenForm}
- >
- <Input<TokenForm>
+ <Input<Entity>
name="password"
label={i18n.str`New password`}
tooltip={i18n.str`Next password to be used`}
inputType="password"
/>
- <Input<TokenForm>
+ <Input<Entity>
name="repeat"
label={i18n.str`Repeat password`}
tooltip={i18n.str`Confirm the same password`}
inputType="password"
/>
+ <div class="buttons is-right mt-5">
+ {onBack && (
+ <button class="button" type="button" onClick={onBack}>
+ <i18n.Translate>Cancel</i18n.Translate>
+ </button>
+ )}
+ <ButtonBetterBulma
+ onClick={create}
+ type="submit"
+ data-tooltip={
+ hasErrors
+ ? i18n.str`Please complete the marked fields and choose authorization method`
+ : i18n.str`Confirm operation`
+ }
+ >
+ <i18n.Translate>Confirm</i18n.Translate>
+ </ButtonBetterBulma>
+ </div>
</FormProvider>
- <div class="buttons is-right mt-5">
- {onBack && (
- <button class="button" onClick={onBack}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- )}
- <ButtonBetterBulma
- onClick={create}
- data-tooltip={
- hasErrors
- ? i18n.str`Please complete the marked fields and choose authorization method`
- : i18n.str`Confirm operation`
- }
- >
- <i18n.Translate>Confirm</i18n.Translate>
- </ButtonBetterBulma>
- </div>
</div>
<div class="column" />
</div>
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/update/UpdatePage.tsx
@@ -74,7 +74,12 @@ function convert(from: TalerMerchantApi.QueryInstancesResponse): Entity {
return { ...defaults, ...rest } as Entity;
}
-export function UpdatePage({ doUpdate, onConfirm, selected, onBack }: Props): VNode {
+export function UpdatePage({
+ doUpdate,
+ onConfirm,
+ selected,
+ onBack,
+}: Props): VNode {
const { state } = useSessionContext();
const [value, valueHandler] = useState<Partial<Entity>>(convert(selected));
@@ -127,7 +132,7 @@ export function UpdatePage({ doUpdate, onConfirm, selected, onBack }: Props): VN
d: TalerMerchantApi.InstanceReconfigurationMessage,
challengeIds: string[],
) => doUpdate(token, d, { challengeIds }),
- hasErrors || !state.token? undefined : [state.token, result, []]
+ hasErrors || !state.token ? undefined : [state.token, result, []],
);
update.onSuccess = onConfirm;
update.onFail = (fail) => {
@@ -199,6 +204,7 @@ export function UpdatePage({ doUpdate, onConfirm, selected, onBack }: Props): VN
</button>
<ButtonBetterBulma
+ type="submit"
onClick={update}
data-tooltip={
hasErrors
diff --git a/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx
@@ -245,10 +245,10 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
borderTop: 0,
}}
>
- <button class="button" onClick={onCancel}>
+ <button class="button" type="button" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</button>
- <ButtonBetterBulma type="is-info" onClick={create}>
+ <ButtonBetterBulma onClick={create} type="submit">
<i18n.Translate>Create</i18n.Translate>
</ButtonBetterBulma>
</footer>