gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant-backoffice] branch master updated: more i18n


From: gnunet
Subject: [taler-merchant-backoffice] branch master updated: more i18n
Date: Thu, 11 Feb 2021 22:11:51 +0100

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 8a0fbe7  more i18n
8a0fbe7 is described below

commit 8a0fbe79ef3c16cd256c4ebc35f4e8b0bc38dba3
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Feb 11 18:11:39 2021 -0300

    more i18n
---
 README.md                                          |   2 +
 .../modal/index.tsx}                               |   7 +-
 src/components/yup/YupInput.tsx                    |  32 +++++++
 src/i18n/index.ts                                  | 101 +++++++++++++++++++++
 src/routes/instances/CardTable.tsx                 |   3 +-
 src/routes/instances/CreateModal.stories.tsx       |  16 ++++
 src/routes/instances/CreateModal.tsx               |  27 +-----
 src/routes/instances/DeleteModal.tsx               |   4 +-
 src/routes/instances/EmptyTable.tsx                |   3 +-
 src/routes/instances/Table.tsx                     |   9 +-
 src/routes/instances/UpdateModal.stories.tsx       |   6 +-
 src/routes/instances/UpdateModal.tsx               |  22 ++---
 src/routes/instances/View.stories.tsx              |  34 +++++--
 src/routes/instances/View.tsx                      |   7 +-
 14 files changed, 214 insertions(+), 59 deletions(-)

diff --git a/README.md b/README.md
index c756821..24987d7 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,8 @@ Use the browser to navigate into `http://localhost:8080`
 
 *   preact-router: URL component router for Preact
 
+*   preact-i18n: Simple localization for Preact
+
 *   SWR: React Hooks library for data fetching. (stale-while-revalidate)
 
 *   Yup: schema builder for value parsing and validation
diff --git a/src/routes/instances/ConfirmModal.tsx 
b/src/components/modal/index.tsx
similarity index 76%
rename from src/routes/instances/ConfirmModal.tsx
rename to src/components/modal/index.tsx
index a074a60..b95eea7 100644
--- a/src/routes/instances/ConfirmModal.tsx
+++ b/src/components/modal/index.tsx
@@ -1,4 +1,5 @@
 import { h, VNode } from "preact";
+import { Text } from "preact-i18n";
 
 interface Props {
   active?: boolean;
@@ -14,15 +15,15 @@ export default function ConfirmModal({ active, description, 
onCancel, onConfirm,
     <div class="modal-background jb-modal-close" onClick={onCancel} />
     <div class="modal-card">
       <header class="modal-card-head">
-        <p class="modal-card-title">Confirm action: {description}</p>
+        <p class="modal-card-title"> <Text id="confirm_modal.title" /> { 
!description ? null : <Text id={`confirm_modal.${description}`} /> }</p>
         <button class="delete jb-modal-close" aria-label="close" 
onClick={onCancel} />
       </header>
       <section class="modal-card-body">
         {children}
       </section>
       <footer class="modal-card-foot">
-        <button class="button jb-modal-close" onClick={onCancel} 
>Cancel</button>
-        <button class={danger ? "button is-danger jb-modal-close" : "button 
is-info jb-modal-close"} onClick={onConfirm} >Confirm</button>
+        <button class="button jb-modal-close" onClick={onCancel} ><Text 
id="cancel" /></button>
+        <button class={danger ? "button is-danger jb-modal-close" : "button 
is-info jb-modal-close"} onClick={onConfirm} ><Text id="confirm" /></button>
       </footer>
     </div>
     <button class="modal-close is-large jb-modal-close" aria-label="close" 
onClick={onCancel} />
diff --git a/src/components/yup/YupInput.tsx b/src/components/yup/YupInput.tsx
new file mode 100644
index 0000000..b10ff22
--- /dev/null
+++ b/src/components/yup/YupInput.tsx
@@ -0,0 +1,32 @@
+import { h, VNode } from "preact";
+import { Text, useText } from "preact-i18n";
+
+interface Props {
+  name: string;
+  value: any;
+  info: any;
+  errors: any;
+  valueHandler: any;
+}
+
+export default function YupInput({ name, info, value, errors, valueHandler }: 
Props): VNode {
+  const dict = useText({placeholder: `fields.instance.${name}.placeholder`})
+
+  return <div class="field is-horizontal">
+  <div class="field-label is-normal">
+    <label class="label"><Text id={`fields.instance.${name}.label`} /></label>
+  </div>
+  <div class="field-body">
+    <div class="field">
+      <p class="control is-expanded has-icons-left">
+        <input class="input" type="text" 
+            placeholder={dict['placeholder']} readonly={info?.meta?.readonly} 
+            name={name} value={value[name]} 
+            onChange={(e): void => valueHandler((prev: any) => ({ ...prev, 
[name]: e.currentTarget.value }))} />
+        <Text id={`fields.instance.${name}.help`} />
+      </p>
+      {errors[name] ? <p class="help is-danger"><Text 
id={`validation.${errors[name].type}`} 
fields={errors[name].params}>{errors[name].message}</Text></p> : null}
+    </div>
+  </div>
+</div>
+}
diff --git a/src/i18n/index.ts b/src/i18n/index.ts
index 0a47692..73467ca 100644
--- a/src/i18n/index.ts
+++ b/src/i18n/index.ts
@@ -1,18 +1,119 @@
 export default {
   es: {
+    confirm_modal: {
+      title: 'confirmar accion',
+      create_instance: 'crear instancia',
+      delete_instance: 'borrar instancia',
+      update_instance: 'actualizar instancia',
+    },
     notification: {
       unauthorized: {
         title: 'acceso no autorizado',
         description: 'el servidor a denegado el acceso'
       },
     },
+    cancel: 'cancelar',
+    confirm: 'confirmar',
+    fields: {
+      instance: {
+        id: {
+          label: 'Id',
+        },
+        merchant_pub: {
+          label: 'Clave pública'
+        },
+        payment_targets: {
+          label: 'Dirección de pago',
+        },
+        name: {
+          label: 'Nombre',
+        },
+        payto_uris: {
+          label: 'PaytTO URI',
+          placeholder: 'comma separated values',
+          help: 'payto://x-taler-bank/bank.taler:5882/blogger',
+        },
+        default_max_deposit_fee: {
+          label: 'Máximo pago por depósito',
+        },
+        default_max_wire_fee: {
+          label: 'Máximo pago por transferencia bancaria',
+        },
+        default_wire_fee_amortization: {
+          label: 'Amortización de pago',
+        },
+      },
+    },
+    validation: {
+      required: '{{label}} es obligatorio',
+      typeError: '{{label}} '
+    },
+    text: {
+      instances: 'Instancias',
+      merchant: 'Merchant',
+      list_of_configured_instances: 'Lista de instancias configuradas',
+      instance: {
+        empty_list: 'No instance configured yet, setup one pressing the + 
button',
+      }
+    }
   },
   en: {
+    confirm_modal: {
+      title: 'confirm action',
+      create_instance: 'create instance',
+      delete_instance: 'delete instance',
+      update_instance: 'update instance',
+    },
     notification: {
       unauthorized: {
         title: 'unauthorized access',
         description: 'backend has denied access'
       },
     },
+    cancel: 'cancel',
+    confirm: 'confirm',
+    fields: {
+      instance: {
+        id: {
+          label: 'Id',
+        },
+        merchant_pub: {
+          label: 'Public Key'
+        },
+        payment_targets: {
+          label: 'Payment targets',
+        },
+        name: {
+          label: 'Name',
+        },
+        payto_uris: {
+          label: 'PaytTO URI',
+          placeholder: 'comma separated values',
+          help: 'payto://x-taler-bank/bank.taler:5882/blogger',
+        },
+        default_max_deposit_fee: {
+          label: 'Max deposit fee',
+        },
+        default_max_wire_fee: {
+          label: 'Max wire fee',
+        },
+        default_wire_fee_amortization: {
+          label: 'Max fee amortization',
+        },
+      }
+    },
+    validation: {
+      required: '{{label}} is required',
+      typeError: '{{label}} '
+    },
+    text: {
+      instances: 'Instances',
+      merchant: 'Merchant',
+      list_of_configured_instances: 'List of configured instances',
+      
+      instance: {
+        empty_list: 'No instance configured yet, setup one pressing the + 
button',
+      }
+    },
   },
 }
\ No newline at end of file
diff --git a/src/routes/instances/CardTable.tsx 
b/src/routes/instances/CardTable.tsx
index 551a543..44c0402 100644
--- a/src/routes/instances/CardTable.tsx
+++ b/src/routes/instances/CardTable.tsx
@@ -1,4 +1,5 @@
 import { h, VNode } from "preact";
+import { Text } from "preact-i18n";
 import { useEffect, useState } from "preact/hooks";
 import { MerchantBackend, WidthId as WithId } from "../../declaration";
 import EmptyTable from "./EmptyTable";
@@ -47,7 +48,7 @@ export default function CardTable({ instances, onCreate, 
onSelect, selected }: P
 
   return <div class="card has-table">
     <header class="card-header">
-      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-account-multiple" /></span>Instances</p>
+      <p class="card-header-title"><span class="icon"><i class="mdi 
mdi-account-multiple" /></span><Text id="text.instances" /></p>
       
       <button class={rowSelection.length > 0 ? "card-header-icon" : 
"card-header-icon is-hidden"} 
         type="button" onClick={(): void => 
actionQueueHandler(buildActions(instances, rowSelection, 'DELETE'))} >
diff --git a/src/routes/instances/CreateModal.stories.tsx 
b/src/routes/instances/CreateModal.stories.tsx
new file mode 100644
index 0000000..1906f0c
--- /dev/null
+++ b/src/routes/instances/CreateModal.stories.tsx
@@ -0,0 +1,16 @@
+/* eslint-disable @typescript-eslint/camelcase */
+import { h, VNode } from 'preact';
+import CreateModal from './CreateModal'
+
+
+export default {
+  title: 'Instances/CreateModal',
+  component: CreateModal,
+  argTypes: {
+    element: { control: 'object' },
+    onCancel: { action: 'onCancel' },
+    onConfirm: { action: 'onConfirm' },
+  }
+};
+
+export const Example = (a: any): VNode => <CreateModal {...a} />;
diff --git a/src/routes/instances/CreateModal.tsx 
b/src/routes/instances/CreateModal.tsx
index 2c99b60..b66b483 100644
--- a/src/routes/instances/CreateModal.tsx
+++ b/src/routes/instances/CreateModal.tsx
@@ -2,7 +2,8 @@ import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { Duration, MerchantBackend } from "../../declaration";
 import * as yup from 'yup';
-import ConfirmModal from "./ConfirmModal";
+import ConfirmModal from "../../components/modal";
+import YupInput from "../../components/yup/YupInput"
 
 function stringToArray(this: yup.AnySchema, current: any, original: string): 
string[] {
   if (this.isType(current)) return current;
@@ -25,7 +26,6 @@ const schema = yup.object().shape({
   name: yup.string().required().label("Name"),
   payto_uris: yup.array().of(yup.string())
     .min(1).label("Payment Method")
-    .meta({ placeholder: 'comma separated values', help: 
'payto://x-taler-bank/bank.taler:5882/blogger' })
     .transform(stringToArray),
   default_max_deposit_fee: yup.string().required().label("Max Deposit Fee"),
   default_max_wire_fee: yup.string().required().label("Max Wire"),
@@ -53,32 +53,15 @@ export default function CreateModal({ onCancel, onConfirm 
}: Props): VNode {
       onConfirm({ ...schema.cast(value), address: {}, jurisdiction: {}, 
default_wire_transfer_delay: { d_ms: 6000 }, default_pay_delay: { d_ms: 3000 } 
} as MerchantBackend.Instances.InstanceConfigurationMessage);
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
       setErrors(pathMessages)
     }
   }
 
-  return <ConfirmModal description="create instance" active onConfirm={submit} 
onCancel={onCancel}>
+  return <ConfirmModal description="create_instance" active onConfirm={submit} 
onCancel={onCancel}>
     {Object.keys(schema.fields).map(f => {
-
       const info = schema.fields[f].describe()
-
-      // Just text field for now
-      return <div class="field is-horizontal">
-        <div class="field-label is-normal">
-          <label class="label">{info.label}</label>
-        </div>
-        <div class="field-body">
-          <div class="field">
-            <p class="control is-expanded has-icons-left">
-              <input class="input" type="text" 
placeholder={info?.meta?.placeholder} readonly={info?.meta?.readonly} name={f} 
value={value[f]} onChange={(e): void => valueHandler((prev: any) => ({ ...prev, 
[f]: e.currentTarget.value }))} />
-              {info?.meta?.help}
-            </p>
-            {errors[f] ? <p class="help is-danger">{errors[f]}</p> : null}
-          </div>
-        </div>
-      </div>
-
+      return <YupInput name={f} info={info} errors={errors} value={value} 
valueHandler={valueHandler} />
     })}
 
   </ConfirmModal>
diff --git a/src/routes/instances/DeleteModal.tsx 
b/src/routes/instances/DeleteModal.tsx
index 276dab4..d7788d1 100644
--- a/src/routes/instances/DeleteModal.tsx
+++ b/src/routes/instances/DeleteModal.tsx
@@ -1,6 +1,6 @@
 import { h, VNode } from "preact";
 import { MerchantBackend, WidthId } from "../../declaration";
-import ConfirmModal from "./ConfirmModal";
+import ConfirmModal from "../../components/modal";
 
 interface Props {
   element: MerchantBackend.Instances.QueryInstancesResponse & WidthId;
@@ -9,7 +9,7 @@ interface Props {
 }
 
 export default function DeleteModal({ element, onCancel, onConfirm }: Props): 
VNode {
-  return <ConfirmModal description="delete instance" danger active 
onCancel={onCancel} onConfirm={() => onConfirm(element)}>
+  return <ConfirmModal description="delete_instance" danger active 
onCancel={onCancel} onConfirm={() => onConfirm(element)}>
     <p>This will permanently delete instance "{element.name}" with id 
<b>{element.id}</b></p>
     <p>Please confirm this action</p>
   </ConfirmModal>
diff --git a/src/routes/instances/EmptyTable.tsx 
b/src/routes/instances/EmptyTable.tsx
index 5aff8ef..f7faf92 100644
--- a/src/routes/instances/EmptyTable.tsx
+++ b/src/routes/instances/EmptyTable.tsx
@@ -1,10 +1,11 @@
 import { h, VNode } from "preact";
+import { Text } from "preact-i18n";
 
 export default function EmptyTable(): VNode {
   return <div class="content has-text-grey has-text-centered">
     <p>
       <span class="icon is-large"><i class="mdi mdi-emoticon-sad mdi-48px" 
/></span>
     </p>
-    <p>No instance configured yet, setup one pressing the + button </p>
+    <p><Text id="text.intance.empty_list" /></p>
   </div>
 }
diff --git a/src/routes/instances/Table.tsx b/src/routes/instances/Table.tsx
index 761b068..67ce90d 100644
--- a/src/routes/instances/Table.tsx
+++ b/src/routes/instances/Table.tsx
@@ -1,4 +1,5 @@
 import { h, VNode } from "preact"
+import { Text } from "preact-i18n"
 import { StateUpdater } from "preact/hooks"
 import { MerchantBackend } from "../../declaration"
 
@@ -24,10 +25,10 @@ export default function Table({ rowSelection, 
rowSelectionHandler, instances, on
               <span class="check" />
             </label>
           </th>
-          <th>id</th>
-          <th>name</th>
-          <th>public key</th>
-          <th>payments</th>
+          <th><Text id="fields.instance.id.label" /></th>
+          <th><Text id="fields.instance.name.label" /></th>
+          <th><Text id="fields.instance.merchant_pub.label" /></th>
+          <th><Text id="fields.instance.payment_targets.label" /></th>
           <th />
         </tr>
       </thead>
diff --git a/src/routes/instances/UpdateModal.stories.tsx 
b/src/routes/instances/UpdateModal.stories.tsx
index 1ae5bca..4d8cb0f 100644
--- a/src/routes/instances/UpdateModal.stories.tsx
+++ b/src/routes/instances/UpdateModal.stories.tsx
@@ -1,5 +1,5 @@
 /* eslint-disable @typescript-eslint/camelcase */
-import { h } from 'preact';
+import { h, VNode } from 'preact';
 import UpdateModal from './UpdateModal'
 
 
@@ -13,11 +13,11 @@ export default {
   }
 };
 
-export const WithDefaultInstance = (a: any) => <UpdateModal {...a} />;
+export const WithDefaultInstance = (a: any): VNode => <UpdateModal {...a} />;
 WithDefaultInstance.args = {
   element: {
     id: 'default',
-    name: 'the default instance',
+    name: 'update',
     merchant_pub: 'abcdef',
     payment_targets: ['qwe','asd']
   }
diff --git a/src/routes/instances/UpdateModal.tsx 
b/src/routes/instances/UpdateModal.tsx
index d729729..9906b0f 100644
--- a/src/routes/instances/UpdateModal.tsx
+++ b/src/routes/instances/UpdateModal.tsx
@@ -2,7 +2,8 @@ import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { MerchantBackend } from "../../declaration";
 import * as yup from 'yup';
-import ConfirmModal from "./ConfirmModal";
+import ConfirmModal from '../../components/modal'
+import { Text } from "preact-i18n";
 
 function stringToArray(this: yup.AnySchema, current: any, original: string): 
string[] {
   if (this.isType(current)) return current;
@@ -10,14 +11,11 @@ function stringToArray(this: yup.AnySchema, current: any, 
original: string): str
 }
 
 const schema = yup.object().shape({
-  name: yup.string().required().label("Name"),
-  payto_uris: yup.array().of(yup.string())
-    .min(1).label("Payment Method")
-    .meta({ placeholder: 'comma separated values', help: 
'payto://x-taler-bank/bank.taler:5882/blogger' })
-    .transform(stringToArray),
-  default_max_deposit_fee: yup.string().required().label("Max Deposit Fee"),
-  default_max_wire_fee: yup.string().required().label("Max Wire"),
-  default_wire_fee_amortization: yup.number().required().label("WireFee 
Amortization"),
+  name: yup.string().required(),
+  payto_uris: yup.array().of(yup.string()).min(1).transform(stringToArray),
+  default_max_deposit_fee: yup.string().required(),
+  default_max_wire_fee: yup.string().required(),
+  default_wire_fee_amortization: yup.number().required(),
   // default_pay_delay: yup.number().required().label("Pay 
delay").transform(numberToDuration),
   // default_wire_transfer_delay: yup.number().required().label("Wire transfer 
Delay").transform(numberToDuration),
 });
@@ -45,12 +43,12 @@ export default function UpdateModal({ element, onCancel, 
onConfirm }: Props): VN
       onConfirm({...schema.cast(value), address: {}, jurisdiction: {}, 
default_wire_transfer_delay: { d_ms: 6000 }, default_pay_delay: { d_ms: 3000 }} 
as MerchantBackend.Instances.InstanceReconfigurationMessage);
     } catch (err) {
       const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
+      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: { type: cur.type, params: cur.params, message: cur.message 
} }), {})
       setErrors(pathMessages)
     }
   }
 
-  return <ConfirmModal description="update instance" active={element != null} 
onConfirm={submit} onCancel={onCancel}>
+  return <ConfirmModal description="update_instance" active={element != null} 
onConfirm={submit} onCancel={onCancel}>
     {Object.keys(schema.fields).map(f => {
 
       const info = schema.fields[f].describe()
@@ -58,7 +56,7 @@ export default function UpdateModal({ element, onCancel, 
onConfirm }: Props): VN
       // Just text field for now
       return <div class="field is-horizontal">
         <div class="field-label is-normal">
-          <label class="label">{info.label}</label>
+          <label class="label"><Text id={`fields.instance.${f}.label`} 
/></label>
         </div>
         <div class="field-body">
           <div class="field">
diff --git a/src/routes/instances/View.stories.tsx 
b/src/routes/instances/View.stories.tsx
index 5804152..292c073 100644
--- a/src/routes/instances/View.stories.tsx
+++ b/src/routes/instances/View.stories.tsx
@@ -7,9 +7,7 @@ export default {
   title: 'Instances/View',
   component: View,
   argTypes: {
-    onLogin: { action: 'onLogin' },
-    onLogout: { action: 'onLogout' },
-    onCreateAccount: { action: 'onCreateAccount' },
+    onSelect: { action: 'onSelect' },
   },
 };
 
@@ -28,17 +26,37 @@ WithDefaultInstance.args = {
   }]
 }
 
-export const WithTwoInstance = (a: any) => <View {...a} />;
-WithTwoInstance.args = {
+export const WithFiveInstance = (a: any) => <View {...a} />;
+WithFiveInstance.args = {
   instances: [{
     id: 'first',
     name: 'the first instance',
     merchant_pub: 'abcdefgh',
-    payment_targets: []
+    payment_targets: ['asd']
   },{
     id: 'second',
-    name: 'other instance',
+    name: 'the second instance',
+    merchant_pub: 'zxczxcz',
+    payment_targets: ['asd']
+  },{
+    id: 'third',
+    name: 'the third instance',
+    merchant_pub: 'QWEQWEWQE',
+    payment_targets: ['asd']
+  },{
+    id: 'other',
+    name: 'the other instance',
+    merchant_pub: 'FHJHGJGHJ',
+    payment_targets: ['asd']
+  },{
+    id: 'another',
+    name: 'the another instance',
+    merchant_pub: 'abcd3423423efgh',
+    payment_targets: ['asd']
+  },{
+    id: 'last',
+    name: 'last instance',
     merchant_pub: 'zxcvvbnm',
-    payment_targets: ['pay-to']
+    payment_targets: ['pay-to','asd']
   }]
 }
diff --git a/src/routes/instances/View.tsx b/src/routes/instances/View.tsx
index 4305564..61435cd 100644
--- a/src/routes/instances/View.tsx
+++ b/src/routes/instances/View.tsx
@@ -5,6 +5,7 @@ import Table from './CardTable';
 import DeleteModal from './DeleteModal'
 import UpdateModal from './UpdateModal'
 import CreateModal from './CreateModal'
+import { Text } from "preact-i18n";
 
 interface Props {
   instances: MerchantBackend.Instances.Instance[];
@@ -32,8 +33,8 @@ export default function View({ instances, isLoading, 
onCreate, onDelete, onSelec
         <div class="level-left">
           <div class="level-item">
             <ul>
-              <li>Merchant</li>
-              <li>Instances</li>
+              <li><Text id="text.merchant" /></li>
+              <li><Text id="text.instances" /></li>
             </ul>
           </div>
         </div>
@@ -45,7 +46,7 @@ export default function View({ instances, isLoading, 
onCreate, onDelete, onSelec
         <div class="level">
           <div class="level-left">
             <div class="level-item">
-              <h1 class="title">List of configured instances</h1>
+              <h1 class="title"><Text id="text.list_of_configured_instances" 
/></h1>
             </div>
           </div>
           <div class="level-right" style="display: none;">

-- 
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]