[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant-backoffice] branch master updated: fix validation messag
From: |
gnunet |
Subject: |
[taler-merchant-backoffice] branch master updated: fix validation messages |
Date: |
Fri, 25 Jun 2021 16:28:54 +0200 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository merchant-backoffice.
The following commit(s) were added to refs/heads/master by this push:
new 1ce7ccc fix validation messages
1ce7ccc is described below
commit 1ce7ccc04487406250cee603638950b80d6a779a
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Jun 25 11:28:13 2021 -0300
fix validation messages
---
.../frontend/src/components/form/InputArray.tsx | 11 +++-
.../frontend/src/components/form/InputDuration.tsx | 8 +--
.../instance/DefaultInstanceFormFields.tsx | 2 +-
.../src/components/picker/DurationPicker.tsx | 4 +-
.../frontend/src/paths/admin/create/CreatePage.tsx | 67 ++++++++++++++++++----
.../src/paths/instance/update/UpdatePage.tsx | 56 +++++++++++++++---
6 files changed, 118 insertions(+), 30 deletions(-)
diff --git a/packages/frontend/src/components/form/InputArray.tsx
b/packages/frontend/src/components/form/InputArray.tsx
index 211d995..9f16cbf 100644
--- a/packages/frontend/src/components/form/InputArray.tsx
+++ b/packages/frontend/src/components/form/InputArray.tsx
@@ -34,10 +34,12 @@ const defaultToString = (f?: any): string => f || ''
const defaultFromString = (v: string): any => v as any
export function InputArray<T>({ name, readonly, placeholder, tooltip, label,
help, addonBefore, isValid = () => true, fromStr = defaultFromString, toStr =
defaultToString }: Props<keyof T>): VNode {
- const { error: formError, value, onChange } = useField<T>(name);
+ const { error: formError, value, onChange, required } = useField<T>(name);
const [localError, setLocalError] = useState<string | null>(null)
- const error = formError || localError
+ const error = localError || formError
+
+ console.log(formError, localError)
const array: any[] = (value ? value! : []) as any;
const [currentValue, setCurrentValue] = useState('');
@@ -58,11 +60,14 @@ export function InputArray<T>({ name, readonly,
placeholder, tooltip, label, hel
{addonBefore && <div class="control">
<a class="button is-static">{addonBefore}</a>
</div>}
- <p class="control is-expanded">
+ <p class="control is-expanded has-icons-right">
<input class={error ? "input is-danger" : "input"} type="text"
placeholder={placeholder} readonly={readonly} disabled={readonly}
name={String(name)} value={currentValue}
onChange={(e): void => setCurrentValue(e.currentTarget.value)} />
+ {required && <span class="icon has-text-danger is-right">
+ <i class="mdi mdi-alert" />
+ </span>}
</p>
<p class="control">
<button class="button is-info has-tooltip-left"
disabled={!currentValue} onClick={(): void => {
diff --git a/packages/frontend/src/components/form/InputDuration.tsx
b/packages/frontend/src/components/form/InputDuration.tsx
index 258858b..e5849b4 100644
--- a/packages/frontend/src/components/form/InputDuration.tsx
+++ b/packages/frontend/src/components/form/InputDuration.tsx
@@ -99,11 +99,11 @@ export function InputDuration<T>({ name, expand,
placeholder, tooltip, label, he
</div>
{error && <p class="help is-danger">{error}</p>}
</div>
- {!readonly && <span data-tooltip={i18n`change value to empty`}>
- <button class="button is-info mr-3" onClick={() => onChange(undefined
as any)} ><Translate>clear</Translate></button>
- </span>}
{withForever && <span data-tooltip={i18n`change value to never`}>
- <button class="button is-info" onClick={() => onChange({ d_ms:
'forever' } as any)}><Translate>forever</Translate></button>
+ <button class="button is-info mr-3" onClick={() => onChange({ d_ms:
'forever' } as any)}><Translate>forever</Translate></button>
+ </span>}
+ {!readonly && <span data-tooltip={i18n`change value to empty`}>
+ <button class="button is-info " onClick={() => onChange(undefined as
any)} ><Translate>clear</Translate></button>
</span>}
</div>
{opened && <SimpleModal onCancel={() => setOpened(false)}>
diff --git
a/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
b/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
index 2d7f93f..4187d77 100644
--- a/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
+++ b/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
@@ -75,11 +75,11 @@ export function DefaultInstanceFormFields({ readonlyId,
showId }: { readonlyId?:
<InputDuration<Entity> name="default_pay_delay"
label={i18n`Default payment delay`}
+ withForever
tooltip={i18n`Time customers have to pay an order before the offer
expires by default.`} />
<InputDuration<Entity> name="default_wire_transfer_delay"
label={i18n`Default wire transfer delay`}
- withForever
tooltip={i18n`Maximum time an exchange is allowed to delay wiring funds
to the merchant, enabling it to aggregate smaller payments into larger wire
transfers and reducing wire fees.`} />
</Fragment>;
diff --git a/packages/frontend/src/components/picker/DurationPicker.tsx
b/packages/frontend/src/components/picker/DurationPicker.tsx
index b452561..235a63e 100644
--- a/packages/frontend/src/components/picker/DurationPicker.tsx
+++ b/packages/frontend/src/components/picker/DurationPicker.tsx
@@ -107,7 +107,7 @@ function DurationColumn({ unit, min = 0, max, value,
onIncrease, onDecrease, onC
<div class="rdp-column" style={{ top: 0 }}>
- <div class="rdp-cell" key={value - 1}>
+ <div class="rdp-cell" key={value - 2}>
{onDecrease && <button style={{ width: '100%', textAlign:
'center', margin: 5 }}
onClick={onDecrease}>
<span class="icon">
@@ -130,7 +130,7 @@ function DurationColumn({ unit, min = 0, max, value,
onIncrease, onDecrease, onC
{value < max ? toTwoDigitString(value + 1) : ''}
</div>
- <div class="rdp-cell" key={value - 1}>
+ <div class="rdp-cell" key={value + 2}>
{onIncrease && <button style={{ width: '100%', textAlign:
'center', margin: 5 }}
onClick={onIncrease}>
<span class="icon">
diff --git a/packages/frontend/src/paths/admin/create/CreatePage.tsx
b/packages/frontend/src/paths/admin/create/CreatePage.tsx
index c9276d7..ff7e6d6 100644
--- a/packages/frontend/src/paths/admin/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/admin/create/CreatePage.tsx
@@ -27,8 +27,9 @@ import { FormErrors, FormProvider } from
"../../../components/form/FormProvider"
import { SetTokenNewInstanceModal } from "../../../components/modal";
import { MerchantBackend } from "../../../declaration";
import { Translate, useTranslator } from "../../../i18n";
-import { InstanceCreateSchema as schema } from '../../../schemas';
import { DefaultInstanceFormFields } from
"../../../components/instance/DefaultInstanceFormFields";
+import { PAYTO_REGEX } from "../../../utils/constants";
+import { Amounts } from "@gnu-taler/taler-util";
export type Entity = MerchantBackend.Instances.InstanceConfigurationMessage &
{ auth_token?: string }
@@ -46,18 +47,64 @@ function with_defaults(id?: string): Partial<Entity> {
default_wire_transfer_delay: { d_ms: 1000 * 2 * 60 * 60 * 24 }, // one day
};
}
+
+function undefinedIfEmpty<T>(obj: T): T | undefined {
+ return Object.keys(obj).some(k => (obj as any)[k] !== undefined) ? obj :
undefined
+}
+
export function CreatePage({ onCreate, onBack, forceId }: Props): VNode {
const [value, valueHandler] = useState(with_defaults(forceId))
const [isTokenSet, updateIsTokenSet] = useState<boolean>(false);
const [isTokenDialogActive, updateIsTokenDialogActive] =
useState<boolean>(false);
- let errors: FormErrors<Entity> = {}
- try {
- schema.validateSync(value, { abortEarly: false })
- } catch (err) {
- const yupErrors = err.inner as yup.ValidationError[]
- errors = yupErrors.reduce((prev, cur) => !cur.path ? prev : ({ ...prev,
[cur.path]: cur.message }), {})
- }
+ const i18n = useTranslator()
+
+ const errors: FormErrors<Entity> = {
+ id: !value.id ? i18n`required` : undefined,
+ name: !value.name ? i18n`required` : undefined,
+ auth: {
+ method: value.auth?.method === 'token' && !value.auth?.token ?
i18n`token can't be empty` : (
+ value.auth?.method !== 'external' ? i18n`access token is not defined`
: undefined
+ )
+ },
+ payto_uris:
+ !value.payto_uris || !value.payto_uris.length ? i18n`required` : (
+ undefinedIfEmpty(value.payto_uris.map(p => {
+ return !PAYTO_REGEX.test(p) ? i18n`is not valid` : undefined
+ }))
+ ),
+ default_max_deposit_fee:
+ !value.default_max_deposit_fee ? i18n`required` : (
+ !Amounts.parse(value.default_max_deposit_fee) ? i18n`invalid format` :
+ undefined
+ ),
+ default_max_wire_fee:
+ !value.default_max_wire_fee ? i18n`required` : (
+ !Amounts.parse(value.default_max_wire_fee) ? i18n`invalid format` :
+ undefined
+ ),
+ default_wire_fee_amortization:
+ value.default_wire_fee_amortization === undefined ? i18n`required` : (
+ isNaN(value.default_wire_fee_amortization) ? i18n`is not a number` : (
+ value.default_wire_fee_amortization < 1 ? i18n`must be 1 or greater`
:
+ undefined
+ )
+ ),
+ default_pay_delay:
+ !value.default_pay_delay ? i18n`required` : undefined,
+ default_wire_transfer_delay:
+ !value.default_wire_transfer_delay ? i18n`required` : undefined,
+ address: undefinedIfEmpty({
+ address_lines:
+ value.address?.address_lines && value.address?.address_lines.length >
7 ? i18n`max 7 lines` :
+ undefined
+ }),
+ jurisdiction: undefinedIfEmpty({
+ address_lines: value.address?.address_lines &&
value.address?.address_lines.length > 7 ? i18n`max 7 lines` :
+ undefined
+ }),
+ };
+
const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !==
undefined)
const submit = (): Promise<void> => {
@@ -67,15 +114,13 @@ export function CreatePage({ onCreate, onBack, forceId }:
Props): VNode {
value.auth = newToken === null || newToken === undefined ? { method:
"external" } : { method: "token", token: `secret-token:${newToken}` };
// remove above use conversion
// schema.validateSync(value, { abortEarly: false })
- return onCreate(schema.cast(value) as Entity);
+ return onCreate(value as Entity);
}
function updateToken(token: string | null) {
valueHandler(old => ({ ...old, auth_token: token === null ? undefined :
token }))
}
- const i18n = useTranslator()
-
return <div>
<div class="columns">
<div class="column" />
diff --git a/packages/frontend/src/paths/instance/update/UpdatePage.tsx
b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
index c900192..6e7b9eb 100644
--- a/packages/frontend/src/paths/instance/update/UpdatePage.tsx
+++ b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
@@ -30,6 +30,8 @@ import { MerchantBackend } from "../../../declaration";
import { Translate, useTranslator } from "../../../i18n";
import { InstanceUpdateSchema as schema } from '../../../schemas';
import { DefaultInstanceFormFields } from
"../../../components/instance/DefaultInstanceFormFields";
+import { PAYTO_REGEX } from "../../../utils/constants";
+import { Amounts } from "@gnu-taler/taler-util";
type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage & {
auth_token?: string }
@@ -60,7 +62,9 @@ function getTokenValuePart(t?: string): string | undefined {
return match[1]
}
-
+function undefinedIfEmpty<T>(obj: T): T | undefined {
+ return Object.keys(obj).some(k => (obj as any)[k] !== undefined) ? obj :
undefined
+}
export function UpdatePage({ onUpdate, onChangeAuth, selected, onBack }:
Props): VNode {
const { id, token } = useInstanceContext()
@@ -79,13 +83,48 @@ export function UpdatePage({ onUpdate, onChangeAuth,
selected, onBack }: Props):
const [value, valueHandler] = useState<Partial<Entity>>(convert(selected))
- let errors: FormErrors<Entity> = {}
- try {
- schema.validateSync(value, { abortEarly: false })
- } catch (err) {
- const yupErrors = err.inner as yup.ValidationError[]
- errors = yupErrors.reduce((prev, cur) => !cur.path ? prev : ({ ...prev,
[cur.path]: cur.message }), {})
- }
+ const i18n = useTranslator()
+
+ const errors: FormErrors<Entity> = {
+ name: !value.name ? i18n`required` : undefined,
+ payto_uris:
+ !value.payto_uris || !value.payto_uris.length ? i18n`required` : (
+ undefinedIfEmpty(value.payto_uris.map(p => {
+ return !PAYTO_REGEX.test(p) ? i18n`is not valid` : undefined
+ }))
+ ),
+ default_max_deposit_fee:
+ !value.default_max_deposit_fee ? i18n`required` : (
+ !Amounts.parse(value.default_max_deposit_fee) ? i18n`invalid format` :
+ undefined
+ ),
+ default_max_wire_fee:
+ !value.default_max_wire_fee ? i18n`required` : (
+ !Amounts.parse(value.default_max_wire_fee) ? i18n`invalid format` :
+ undefined
+ ),
+ default_wire_fee_amortization:
+ value.default_wire_fee_amortization === undefined ? i18n`required` : (
+ isNaN(value.default_wire_fee_amortization) ? i18n`is not a number` : (
+ value.default_wire_fee_amortization < 1 ? i18n`must be 1 or greater`
:
+ undefined
+ )
+ ),
+ default_pay_delay:
+ !value.default_pay_delay ? i18n`required` : undefined,
+ default_wire_transfer_delay:
+ !value.default_wire_transfer_delay ? i18n`required` : undefined,
+ address: undefinedIfEmpty({
+ address_lines:
+ value.address?.address_lines && value.address?.address_lines.length >
7 ? i18n`max 7 lines` :
+ undefined
+ }),
+ jurisdiction: undefinedIfEmpty({
+ address_lines: value.address?.address_lines &&
value.address?.address_lines.length > 7 ? i18n`max 7 lines` :
+ undefined
+ }),
+ };
+
const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !==
undefined)
const submit = async (): Promise<void> => {
await onUpdate(schema.cast(value));
@@ -93,7 +132,6 @@ export function UpdatePage({ onUpdate, onChangeAuth,
selected, onBack }: Props):
return Promise.resolve()
}
const [active, setActive] = useState(false);
- const i18n = useTranslator()
return <div>
<section class="section">
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-merchant-backoffice] branch master updated: fix validation messages,
gnunet <=