gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]