gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-backoffice] branch master updated: add tooltips to the b


From: gnunet
Subject: [taler-merchant-backoffice] branch master updated: add tooltips to the buttons
Date: Tue, 15 Jun 2021 15:29:29 +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 d4bce84  add tooltips to the buttons
d4bce84 is described below

commit d4bce8447350148c24a6ac0717d4d979d6fc0cfe
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Tue Jun 15 10:28:46 2021 -0300

    add tooltips to the buttons
---
 packages/frontend/.storybook/preview.js            |  6 +-
 .../src/components/exception/AsyncButton.tsx       |  1 +
 .../frontend/src/components/form/InputArray.tsx    |  4 +-
 .../frontend/src/components/form/InputSecured.tsx  |  7 +-
 .../frontend/src/components/form/InputStock.tsx    | 12 +++-
 .../frontend/src/components/form/InputTaxes.tsx    | 30 ++++----
 .../instance/DefaultInstanceFormFields.tsx         | 79 +++++++++++-----------
 .../frontend/src/components/menu/LangSelector.tsx  |  6 +-
 packages/frontend/src/components/modal/index.tsx   | 46 ++++++++-----
 .../src/components/product/ProductList.tsx         | 19 ++++--
 packages/frontend/src/context/backend.ts           |  8 +--
 packages/frontend/src/context/translation.ts       | 10 ++-
 packages/frontend/src/hooks/index.ts               |  4 +-
 .../frontend/src/paths/admin/create/CreatePage.tsx |  8 ++-
 .../instance/orders/create/Create.stories.tsx      |  2 +
 .../paths/instance/orders/create/CreatePage.tsx    |  8 ++-
 .../paths/instance/products/create/CreatePage.tsx  |  8 ++-
 .../paths/instance/products/update/UpdatePage.tsx  |  8 ++-
 .../paths/instance/reserves/create/CreatePage.tsx  | 10 ++-
 .../src/paths/instance/reserves/list/Table.tsx     | 22 ++++--
 .../paths/instance/transfers/create/CreatePage.tsx |  4 +-
 .../src/paths/instance/transfers/list/Table.tsx    | 10 ++-
 .../src/paths/instance/update/UpdatePage.tsx       | 10 ++-
 23 files changed, 200 insertions(+), 122 deletions(-)

diff --git a/packages/frontend/.storybook/preview.js 
b/packages/frontend/.storybook/preview.js
index ab24c75..d13103a 100644
--- a/packages/frontend/.storybook/preview.js
+++ b/packages/frontend/.storybook/preview.js
@@ -33,7 +33,7 @@ const mockInstance = {
 }
 
 const mockBackend = {
-  url: 'http://merchant.url/',
+  url: 'http://merchant.url',
   token: 'default-token',
   triedToLog: false,
 }
@@ -59,7 +59,7 @@ export const globalTypes = {
 };
 
 export const decorators = [
-  (Story, { globals }) => <TranslationProvider initial={globals.locale}>
+  (Story, { globals }) => <TranslationProvider initial='en' 
forceLang={globals.locale}>
     <Story />
   </TranslationProvider>,
   (Story) => <ConfigContextProvider value={mockConfig}>
@@ -68,7 +68,7 @@ export const decorators = [
   (Story) => <InstanceContextProvider value={mockInstance}>
     <Story />
   </InstanceContextProvider>,
-  (Story) => <BackendContextProvider value={mockBackend}>
+  (Story) => <BackendContextProvider defaultUrl={mockBackend.url}>
     <Story />
   </BackendContextProvider>,
 ];
diff --git a/packages/frontend/src/components/exception/AsyncButton.tsx 
b/packages/frontend/src/components/exception/AsyncButton.tsx
index 3dad3e0..92bab4b 100644
--- a/packages/frontend/src/components/exception/AsyncButton.tsx
+++ b/packages/frontend/src/components/exception/AsyncButton.tsx
@@ -28,6 +28,7 @@ type Props = {
   children: ComponentChildren,
   disabled: boolean;
   onClick?: () => Promise<void>;
+  [rest:string]: any,
 };
 
 export function AsyncButton({ onClick, disabled, children, ...rest }: Props) {
diff --git a/packages/frontend/src/components/form/InputArray.tsx 
b/packages/frontend/src/components/form/InputArray.tsx
index 5314eba..13800c7 100644
--- a/packages/frontend/src/components/form/InputArray.tsx
+++ b/packages/frontend/src/components/form/InputArray.tsx
@@ -65,7 +65,7 @@ export function InputArray<T>({ name, readonly, placeholder, 
tooltip, label, hel
               onChange={(e): void => setCurrentValue(e.currentTarget.value)} />
           </p>
           <p class="control">
-            <button class="button is-info" disabled={!currentValue} 
onClick={(): void => {
+            <button class="button is-info has-tooltip-left" 
disabled={!currentValue} onClick={(): void => {
               const v = fromStr(currentValue)
               if (!isValid(v)) {
                 setLocalError(i18n`The value ${v} is invalid for a payment 
url`)
@@ -74,7 +74,7 @@ export function InputArray<T>({ name, readonly, placeholder, 
tooltip, label, hel
               setLocalError(null)
               onChange([v, ...array] as any);
               setCurrentValue('');
-            }}><Translate>add</Translate></button>
+            }} data-tooltip={i18n`add element to the 
list`}><Translate>add</Translate></button>
           </p>
         </div>
         {help}
diff --git a/packages/frontend/src/components/form/InputSecured.tsx 
b/packages/frontend/src/components/form/InputSecured.tsx
index 7d8d655..7f871c7 100644
--- a/packages/frontend/src/components/form/InputSecured.tsx
+++ b/packages/frontend/src/components/form/InputSecured.tsx
@@ -20,7 +20,7 @@
 */
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
-import { Translate } from "../../i18n";
+import { Translate, useTranslator } from "../../i18n";
 import { InputProps, useField } from "./useField";
 
 export type Props<T> = InputProps<T>;
@@ -41,6 +41,8 @@ export function InputSecured<T>({ name, readonly, 
placeholder, tooltip, label, h
   const [active, setActive] = useState(false);
   const [newValue, setNuewValue] = useState("")
 
+  const i18n = useTranslator()
+
   return <Fragment>
     <div class="field is-horizontal">
       <div class="field-label is-normal">
@@ -55,7 +57,8 @@ export function InputSecured<T>({ name, readonly, 
placeholder, tooltip, label, h
         {!active ?
           <Fragment>
             <div class="field has-addons">
-              <button class="button" onClick={(): void => { 
setActive(!active); }} >
+              <button class="button" 
+                onClick={(): void => { setActive(!active); }} >
                 <div class="icon is-left"><i class="mdi mdi-lock-reset" 
/></div>
                 <span><Translate>Manage access token</Translate></span>
               </button>
diff --git a/packages/frontend/src/components/form/InputStock.tsx 
b/packages/frontend/src/components/form/InputStock.tsx
index b323012..a9200cd 100644
--- a/packages/frontend/src/components/form/InputStock.tsx
+++ b/packages/frontend/src/components/form/InputStock.tsx
@@ -87,9 +87,13 @@ export function InputStock<T>({ name, readonly, placeholder, 
tooltip, label, hel
         <div class="field-body is-flex-grow-3">
           <div class="field has-addons">
             {!alreadyExist ?
-              <button class="button" onClick={(): void => { valueHandler({ 
current: 0, lost: 0, sold: 0 } as Stock as any); }} >
+              <button class="button" 
+                data-tooltip={i18n`click here to configure the stock of the 
product, leave it as is and the backend will not control stock`}
+                onClick={(): void => { valueHandler({ current: 0, lost: 0, 
sold: 0 } as Stock as any); }} >
                 <span><Translate>Manage stock</Translate></span>
-              </button> : <button class="button" disabled >
+              </button> : <button class="button" 
+                data-tooltip={i18n`this product has been configured without 
stock control`}
+                disabled >
                 <span><Translate>Infinite</Translate></span>
               </button>
             }
@@ -144,7 +148,9 @@ export function InputStock<T>({ name, readonly, 
placeholder, tooltip, label, hel
           </Fragment> : <InputNumber<Entity> name="current"
             label={i18n`Current`}
             side={
-              <button class="button is-danger" onClick={(): void => { 
valueHandler(undefined as any) }} >
+              <button class="button is-danger" 
+                data-tooltip={i18n`remove stock control for this product`}
+                onClick={(): void => { valueHandler(undefined as any) }} >
                 <span><Translate>without stock</Translate></span>
               </button>
             }
diff --git a/packages/frontend/src/components/form/InputTaxes.tsx 
b/packages/frontend/src/components/form/InputTaxes.tsx
index af1dddd..91bbf85 100644
--- a/packages/frontend/src/components/form/InputTaxes.tsx
+++ b/packages/frontend/src/components/form/InputTaxes.tsx
@@ -38,18 +38,21 @@ export function InputTaxes<T>({ name, readonly, label }: 
Props<keyof T>): VNode
   const { value: taxes, onChange, } = useField<T>(name);
 
   const [value, valueHandler] = useState<Partial<Entity>>({})
-  const [errors, setErrors] = useState<FormErrors<Entity>>({})
+  // const [errors, setErrors] = useState<FormErrors<Entity>>({})
+
+  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 hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== 
undefined)
 
   const submit = useCallback((): void => {
-    try {
-      schema.validateSync(value, { abortEarly: false })
-      onChange([value as any, ...taxes] as any)
-      valueHandler({})
-    } catch (err) {
-      const errors = err.inner as yup.ValidationError[]
-      const pathMessages = errors.reduce((prev, cur) => !cur.path ? prev : ({ 
...prev, [cur.path]: cur.message }), {})
-      setErrors(pathMessages)
-    }
+    onChange([value as any, ...taxes] as any)
+    valueHandler({})
   }, [value])
 
   const i18n = useTranslator()
@@ -78,10 +81,13 @@ export function InputTaxes<T>({ name, readonly, label }: 
Props<keyof T>): VNode
           <Translate>currency and value separated with colon</Translate> 
<b>USD:2.3</b>
         </Input>
 
-        <Input<Entity> name="name" label={i18n`Name`} />
+        <Input<Entity> name="name" label={i18n`Description`} />
 
         <div class="buttons is-right mt-5">
-          <button class="button is-info" 
onClick={submit}><Translate>Add</Translate></button>
+          <button class="button is-info" 
+            data-tooltip={i18n`add tax to the tax list`}
+            disabled={hasErrors} 
+            onClick={submit}><Translate>Add</Translate></button>
         </div>
       </FormProvider>
     </InputGroup>
diff --git 
a/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx 
b/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
index 2b98383..2bfbeda 100644
--- a/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
+++ b/packages/frontend/src/components/instance/DefaultInstanceFormFields.tsx
@@ -35,54 +35,51 @@ export function DefaultInstanceFormFields({ readonlyId, 
showId }: { readonlyId?:
   const i18n = useTranslator();
   const backend = useBackendContext();
   return <Fragment>
-    { showId && <InputWithAddon<Entity> name="id" label={i18n`ID`} 
addonBefore={`${backend.url}/private/instances/`} readonly={readonlyId} 
tooltip={i18n`display name identification`} /> }
-
-    <Input<Entity> name="name" label={i18n`Name`} tooltip={i18n`descriptive 
name`} />
-
-    <InputPayto<Entity> name="payto_uris" label={i18n`Account address`} 
help="x-taler-bank/bank.taler:5882/blogger" tooltip={i18n`where the money will 
be sent`} />
-
-    <InputCurrency<Entity> name="default_max_deposit_fee" label={i18n`Default 
max deposit fee`} tooltip={i18n`max deposit fee when an order has not 
overridden it`} />
-
-    <InputCurrency<Entity> name="default_max_wire_fee" label={i18n`Default max 
wire fee`} tooltip={i18n`max wire fee when the order has not overridden it`} />
-
-    <Input<Entity> name="default_wire_fee_amortization" label={i18n`Default 
wire fee amortization`} tooltip={i18n`max wire fee amortization when the order 
has not overridden it`} />
-
-    <InputGroup name="address" label={i18n`Address`} tooltip={i18n`physical 
location of merchant`}>
+    {showId && <InputWithAddon<Entity> name="id"
+      addonBefore={`${backend.url}/private/instances/`} readonly={readonlyId}
+      label={i18n`Identifier`} 
+      tooltip={i18n`Name of the instance in URLs. The 'default' instance is 
special in that it is used to administer other instances.`} />
+    }
+
+    <Input<Entity> name="name"
+      label={i18n`Business name`}
+      tooltip={i18n`Legal name of the business represented by this instance.`} 
/>
+
+    <InputPayto<Entity> name="payto_uris"
+      label={i18n`Bank account URI`} 
help="x-taler-bank/bank.taler:5882/blogger" 
+      tooltip={i18n`URI specifying bank account for crediting revenue.`} />
+
+    <InputCurrency<Entity> name="default_max_deposit_fee"
+      label={i18n`Default max deposit fee`}
+      tooltip={i18n`Maximum deposit fees this merchant is willing to pay per 
order by default.`} />
+
+    <InputCurrency<Entity> name="default_max_wire_fee"
+      label={i18n`Default max wire fee`}
+      tooltip={i18n`Maximum wire fees this merchant is willing to pay per wire 
transfer by default.`} />
+
+    <Input<Entity> name="default_wire_fee_amortization"
+      label={i18n`Default wire fee amortization`}
+      tooltip={i18n`Number of orders excess wire transfer fees will be divided 
by to compute per order surcharge.`} />
+
+    <InputGroup name="address"
+      label={i18n`Address`}
+      tooltip={i18n`Physical location of the merchant.`}>
       <InputLocation name="address" />
     </InputGroup>
 
-    <InputGroup name="jurisdiction" label={i18n`Jurisdiction`} 
tooltip={i18n`legal location of merchant`}>
+    <InputGroup name="jurisdiction"
+      label={i18n`Jurisdiction`}
+      tooltip={i18n`Jurisdiction for legal disputes with the merchant.`}>
       <InputLocation name="jurisdiction" />
     </InputGroup>
 
-    <InputDuration<Entity> name="default_pay_delay" label={i18n`Default 
payment delay`} tooltip={i18n`max time to pay if the order does not override 
it`} />
+    <InputDuration<Entity> name="default_pay_delay"
+      label={i18n`Default payment delay`}
+      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`} tooltip={i18n`min time to wait the 
transfer if the merchant does not override it`} />
+    <InputDuration<Entity> name="default_wire_transfer_delay"
+      label={i18n`Default wire transfer delay`}
+      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>;
 }
-/*
-            <InputWithAddon<Entity> name="id" label={i18n`Identifier`} 
addonBefore={`${backend.url}/private/instances/`} readonly={!!forceId} 
tooltip={i18n`Name of the instance in URLs. The 'default' instance is special 
in that it is used to administer other instances.`} />
-
-            <Input<Entity> name="name" label={i18n`Business name`} 
tooltip={i18n`Legal name of the business represented by this instance.`} />
-
-            <InputPayto<Entity> name="payto_uris" label={i18n`Bank account 
URI`} help="x-taler-bank/bank.taler:5882/blogger" tooltip={i18n`URI specifying 
bank account for crediting revenue.`} />
-
-            <InputCurrency<Entity> name="default_max_deposit_fee" 
label={i18n`Default max deposit fee`} tooltip={i18n`Maximum deposit fees this 
merchant is willing to pay per order by default.`} />
-
-            <InputCurrency<Entity> name="default_max_wire_fee" 
label={i18n`Default max wire fee`} tooltip={i18n`Maximum wire fees this 
merchant is willing to pay per wire transfer by default.`} />
-
-            <Input<Entity> name="default_wire_fee_amortization" 
label={i18n`Default wire fee amortization`} tooltip={i18n`Number of orders 
excess wire transfer fees will be divided by to compute per order surcharge.`} 
/>
-
-            <InputGroup name="address" label={i18n`Address`} 
tooltip={i18n`Physical location of the merchant.`}>
-              <InputLocation name="address" />
-            </InputGroup>
-
-            <InputGroup name="jurisdiction" label={i18n`Jurisdiction`} 
tooltip={i18n`Jurisdiction for legal disputes with the merchant.`}>
-              <InputLocation name="jurisdiction" />
-            </InputGroup>
-
-            <InputDuration<Entity> name="default_pay_delay" 
label={i18n`Default payment delay`} 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`} 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.`} 
/>
-*/
\ No newline at end of file
diff --git a/packages/frontend/src/components/menu/LangSelector.tsx 
b/packages/frontend/src/components/menu/LangSelector.tsx
index bf61bd2..41d08a5 100644
--- a/packages/frontend/src/components/menu/LangSelector.tsx
+++ b/packages/frontend/src/components/menu/LangSelector.tsx
@@ -46,9 +46,13 @@ function getLangName(s: keyof LangsNames | string) {
 export function LangSelector(): VNode {
   const [updatingLang, setUpdatingLang] = useState(false)
   const { lang, changeLanguage } = useTranslationContext()
+
   return <div class="dropdown is-active ">
     <div class="dropdown-trigger">
-      <button class="button" aria-haspopup="true" 
aria-controls="dropdown-menu" onClick={() => setUpdatingLang(!updatingLang)}>
+      <button class="button has-tooltip-left" 
+        data-tooltip="change language selection"
+        aria-haspopup="true" 
+        aria-controls="dropdown-menu" onClick={() => 
setUpdatingLang(!updatingLang)}>
         <div class="icon is-small is-left">
           <img src={langIcon} />
         </div>
diff --git a/packages/frontend/src/components/modal/index.tsx 
b/packages/frontend/src/components/modal/index.tsx
index 9874a19..963dc05 100644
--- a/packages/frontend/src/components/modal/index.tsx
+++ b/packages/frontend/src/components/modal/index.tsx
@@ -180,25 +180,37 @@ export function SetTokenNewInstanceModal({ onCancel, 
onClear, onConfirm }: Updat
 
   const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== 
undefined)
 
-  const text = i18n`You are setting the access token for the new instance`
 
-  return <ClearConfirmModal description={text}
-    onCancel={onCancel}
-    onConfirm={!hasErrors ? () => onConfirm(form.new_token!) : undefined}
-    onClear={onClear}
-  >
-    <div class="columns">
-      <div class="column" />
-      <div class="column is-four-fifths" >
-        <FormProvider errors={errors} object={form} valueHandler={setValue}>
-          <Input<State> name="new_token" label={i18n`New access token`} 
tooltip={i18n`next access token to be used`} inputType="password" />
-          <Input<State> name="repeat_token" label={i18n`Repeat access token`} 
tooltip={i18n`confirm the same access token`} inputType="password" />
-        </FormProvider>
-        <p><Translate>Clearing the access token will mean public access to the 
instance</Translate></p>
-      </div>
-      <div class="column" />
+  return <div class="modal is-active">
+    <div class="modal-background " onClick={onCancel} />
+    <div class="modal-card">
+      <header class="modal-card-head">
+        <p class="modal-card-title">{i18n`You are setting the access token for 
the new instance`}</p>
+        <button class="delete " aria-label="close" onClick={onCancel} />
+      </header>
+      <section class="modal-card-body is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths" >
+            <FormProvider errors={errors} object={form} 
valueHandler={setValue}>
+              <Input<State> name="new_token" label={i18n`New access token`} 
tooltip={i18n`next access token to be used`} inputType="password" />
+              <Input<State> name="repeat_token" label={i18n`Repeat access 
token`} tooltip={i18n`confirm the same access token`} inputType="password" />
+            </FormProvider>
+            <p><Translate>With external authorization method no check will be 
done by the merchant backend</Translate></p>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+      <footer class="modal-card-foot">
+        {onClear && <button class="button is-danger" onClick={onClear} 
disabled={onClear === undefined} ><Translate>Set external 
authorization</Translate></button>}
+        <div class="buttons is-right" style={{ width: '100%' }}>
+          <button class="button " onClick={onCancel} 
><Translate>Cancel</Translate></button>
+          <button class="button is-info" onClick={() => 
onConfirm(form.new_token!)} disabled={hasErrors} ><Translate>Set access 
token</Translate></button>
+        </div>
+      </footer>
     </div>
-  </ClearConfirmModal>
+    <button class="modal-close is-large " aria-label="close" 
onClick={onCancel} />
+  </div>
 }
 
 export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
diff --git a/packages/frontend/src/components/product/ProductList.tsx 
b/packages/frontend/src/components/product/ProductList.tsx
index 104d8e2..b1486d6 100644
--- a/packages/frontend/src/components/product/ProductList.tsx
+++ b/packages/frontend/src/components/product/ProductList.tsx
@@ -17,24 +17,27 @@ import { h, VNode } from "preact"
 import { MerchantBackend } from "../../declaration"
 import { multiplyPrice } from "../../utils/amount"
 import emptyImage from "../../assets/empty.png";
+import { Translate, useTranslator } from "../../i18n";
 
 interface Props {
   list: MerchantBackend.Product[],
   actions?: {
     name: string;
+    tooltip: string;
     handler: (d: MerchantBackend.Product, index: number) => void;
   }[]
 }
 export function ProductList({ list, actions = [] }: Props): VNode {
+  const i18n = useTranslator()
   return <div class="table-container">
     <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
       <thead>
         <tr>
-          <th>image</th>
-          <th>description</th>
-          <th>quantity</th>
-          <th>unit price</th>
-          <th>total price</th>
+          <th><Translate>image</Translate></th>
+          <th><Translate>description</Translate></th>
+          <th><Translate>quantity</Translate></th>
+          <th><Translate>unit price</Translate></th>
+          <th><Translate>total price</Translate></th>
           <th />
         </tr>
       </thead>
@@ -51,9 +54,11 @@ export function ProductList({ list, actions = [] }: Props): 
VNode {
             <td >{entry.price}</td>
             <td >{multiplyPrice(entry.price, entry.quantity)}</td>
             <td class="is-actions-cell right-sticky">
-              {actions.map((a,i) => {
+              {actions.map((a, i) => {
                 return <div key={i} class="buttons is-right">
-                  <button class="button is-small is-danger jb-modal" 
type="button" onClick={() => a.handler(entry, index)}>
+                  <button class="button is-small is-danger has-tooltip-left"
+                    data-tooltip={a.tooltip}
+                    type="button" onClick={() => a.handler(entry, index)}>
                     {a.name}
                   </button>
                 </div>
diff --git a/packages/frontend/src/context/backend.ts 
b/packages/frontend/src/context/backend.ts
index 9355859..1a7cd72 100644
--- a/packages/frontend/src/context/backend.ts
+++ b/packages/frontend/src/context/backend.ts
@@ -45,8 +45,8 @@ const BackendContext = createContext<BackendContextType>({
   updateToken: () => null,
 })
 
-export function useBackendContextState(): BackendContextType {
-  const [url, triedToLog, changeBackend, resetBackend] = useBackendURL();
+export function useBackendContextState(defaultUrl?:string): BackendContextType 
{
+  const [url, triedToLog, changeBackend, resetBackend] = 
useBackendURL(defaultUrl);
   const [token, _updateToken] = useBackendDefaultToken();
   const updateToken = (t?:string) => {
     _updateToken(t)
@@ -69,8 +69,8 @@ export function useBackendContextState(): BackendContextType {
   return { url, token, triedToLog, changeBackend, updateToken, resetBackend, 
clearAllTokens, addTokenCleaner: addTokenCleanerMemo }
 }
 
-export const BackendContextProvider = ({children}:{children:any}):VNode => {
-  const value = useBackendContextState()
+export const BackendContextProvider = ({children, defaultUrl}:{children:any, 
defaultUrl?:string}):VNode => {
+  const value = useBackendContextState(defaultUrl)
   
   return h(BackendContext.Provider, {value, children});
 }
diff --git a/packages/frontend/src/context/translation.ts 
b/packages/frontend/src/context/translation.ts
index 02ccb70..952a1e3 100644
--- a/packages/frontend/src/context/translation.ts
+++ b/packages/frontend/src/context/translation.ts
@@ -20,7 +20,7 @@
 */
 
 import { createContext, h, VNode } from 'preact'
-import { useContext } from 'preact/hooks'
+import { useContext, useEffect } from 'preact/hooks'
 import { useLang } from '../hooks'
 import * as jedLib from "jed";
 import { strings } from "../i18n/strings";
@@ -42,10 +42,16 @@ const Context = createContext<Type>(initial)
 interface Props {
   initial?: string,
   children: any,
+  forceLang?: string
 }
 
-export const TranslationProvider = ({ initial, children }: Props): VNode => {
+export const TranslationProvider = ({ initial, children, forceLang }: Props): 
VNode => {
   const [lang, changeLanguage] = useLang(initial)
+  useEffect(() => {
+    if (forceLang) {
+      changeLanguage(forceLang)
+    }
+  })
   const handler = new jedLib.Jed(strings[lang]);
   return h(Context.Provider, { value: { lang, handler, changeLanguage }, 
children });
 }
diff --git a/packages/frontend/src/hooks/index.ts 
b/packages/frontend/src/hooks/index.ts
index aa8f3a4..3a16de7 100644
--- a/packages/frontend/src/hooks/index.ts
+++ b/packages/frontend/src/hooks/index.ts
@@ -28,8 +28,8 @@ const calculateRootPath = () => {
   return rootPath
 }
 
-export function useBackendURL(): [string, boolean, StateUpdater<string>, () => 
void] {
-  const [value, setter] = useNotNullLocalStorage('backend-url', 
calculateRootPath())
+export function useBackendURL(url?: string): [string, boolean, 
StateUpdater<string>, () => void] {
+  const [value, setter] = useNotNullLocalStorage('backend-url', url || 
calculateRootPath())
   const [triedToLog, setTriedToLog] = useLocalStorage('tried-login')
 
   const checkedSetter = (v: ValueOrFunction<string>) => {
diff --git a/packages/frontend/src/paths/admin/create/CreatePage.tsx 
b/packages/frontend/src/paths/admin/create/CreatePage.tsx
index 82286de..196284e 100644
--- a/packages/frontend/src/paths/admin/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/admin/create/CreatePage.tsx
@@ -104,7 +104,9 @@ export function CreatePage({ onCreate, onBack, forceId }: 
Props): VNode {
         <div class="level">
           <div class="level-item has-text-centered">
             <h1 class="title">
-              <button class="button is-danger" onClick={() => 
updateIsTokenDialogActive(true)} >
+              <button class="button is-danger has-tooltip-bottom"
+                data-tooltip={i18n`change authorization configuration`}
+                onClick={() => updateIsTokenDialogActive(true)} >
                 <div class="icon is-centered"><i class="mdi mdi-lock-reset" 
/></div>
                 <span><Translate>Set access token</Translate></span>
               </button>
@@ -127,8 +129,8 @@ export function CreatePage({ onCreate, onBack, forceId }: 
Props): VNode {
 
           <div class="buttons is-right mt-5">
             {onBack && <button class="button" 
onClick={onBack}><Translate>Cancel</Translate></button>}
-            <AsyncButton onClick={submit} disabled={!isTokenSet && hasErrors} 
data-tooltip={
-              hasErrors ? i18n`Need to complete fields first, check fields 
marked with a star` : 'confirm operation'
+            <AsyncButton onClick={submit} disabled={!isTokenSet || hasErrors} 
data-tooltip={
+              hasErrors ? i18n`Need to complete fields marked with a star and 
choose authorization method` : 'confirm operation'
             }><Translate>Confirm</Translate></AsyncButton>
           </div>
 
diff --git 
a/packages/frontend/src/paths/instance/orders/create/Create.stories.tsx 
b/packages/frontend/src/paths/instance/orders/create/Create.stories.tsx
index 29f6842..daf48c0 100644
--- a/packages/frontend/src/paths/instance/orders/create/Create.stories.tsx
+++ b/packages/frontend/src/paths/instance/orders/create/Create.stories.tsx
@@ -54,9 +54,11 @@ export const Example = createExample(TestedComponent, {
     total_stock: -1
   },{
     id: 't-shirt-2',
+    price: 'TESTKUDOS:1',
     description: 'a xl size t-shirt'
   } as any,{
     id: 't-shirt-3',
+    price: 'TESTKUDOS:1',
     description: 'a s size t-shirt'
   } as any]
 });
diff --git a/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
index 768a1cb..8cf73a7 100644
--- a/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/orders/create/CreatePage.tsx
@@ -238,7 +238,9 @@ export function CreatePage({ onCreate, onBack, 
instanceConfig, instanceInventory
             {inventoryList.length > 0 &&
               <ProductList list={inventoryList.map(asProduct)}
                 actions={[{
-                  name: i18n`Remove`, handler: (e) => 
removeProductFromTheInventoryList(e.product_id!)
+                  name: i18n`Remove`, 
+                  tooltip: i18n`remove this product from the list`,
+                  handler: (e) => 
removeProductFromTheInventoryList(e.product_id!)
                 }]}
               />
             }
@@ -259,7 +261,9 @@ export function CreatePage({ onCreate, onBack, 
instanceConfig, instanceInventory
             {productList.length > 0 &&
               <ProductList list={productList}
                 actions={[{
-                  name: i18n`Remove`, handler: (e, index) => {
+                  name: i18n`Remove`, 
+                  tooltip: i18n`remove this product from the list to be edited 
or discarded`,
+                  handler: (e, index) => {
                     removeFromNewProduct(index);
                     setEditingProduct(e);
                   }
diff --git 
a/packages/frontend/src/paths/instance/products/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
index 78c0f0d..2498d6a 100644
--- a/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/products/create/CreatePage.tsx
@@ -24,7 +24,7 @@ import { AsyncButton } from 
"../../../../components/exception/AsyncButton";
 import { ProductForm } from "../../../../components/product/ProductForm";
 import { MerchantBackend } from "../../../../declaration";
 import { useListener } from "../../../../hooks";
-import { Translate } from "../../../../i18n";
+import { Translate, useTranslator } from "../../../../i18n";
 
 type Entity = MerchantBackend.Products.ProductAddDetail & { product_id: string}
 
@@ -41,6 +41,8 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
     return Promise.reject()
   })
 
+  const i18n = useTranslator()
+
   return <div>
     <section class="section is-main-section">
       <div class="columns">
@@ -50,7 +52,9 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
 
           <div class="buttons is-right mt-5">
             {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
-            <AsyncButton onClick={submitForm} 
disabled={!submitForm}><Translate>Confirm</Translate></AsyncButton>
+            <AsyncButton onClick={submitForm} data-tooltip={
+              !submitForm ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+            } 
disabled={!submitForm}><Translate>Confirm</Translate></AsyncButton>
           </div>
 
         </div>
diff --git 
a/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx 
b/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
index 1dfca99..0c665be 100644
--- a/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
+++ b/packages/frontend/src/paths/instance/products/update/UpdatePage.tsx
@@ -24,7 +24,7 @@ import { AsyncButton } from 
"../../../../components/exception/AsyncButton";
 import { ProductForm } from "../../../../components/product/ProductForm";
 import { MerchantBackend, WithId } from "../../../../declaration";
 import { useListener } from "../../../../hooks";
-import { Translate } from "../../../../i18n";
+import { Translate, useTranslator } from "../../../../i18n";
 
 type Entity = MerchantBackend.Products.ProductDetail & { product_id: string }
 
@@ -40,6 +40,8 @@ export function UpdatePage({ product, onUpdate, onBack }: 
Props): VNode {
     return Promise.resolve()
   })
 
+  const i18n = useTranslator()
+  
   return <div>
     <section class="section">
       <section class="hero is-hero-bar">
@@ -63,7 +65,9 @@ export function UpdatePage({ product, onUpdate, onBack }: 
Props): VNode {
 
           <div class="buttons is-right mt-5">
             {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
-            <AsyncButton onClick={submitForm} 
disabled={!submitForm}><Translate>Confirm</Translate></AsyncButton>
+            <AsyncButton onClick={submitForm} data-tooltip={
+              !submitForm ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+            } 
disabled={!submitForm}><Translate>Confirm</Translate></AsyncButton>
           </div>
         </div>
         <div class="column" />
diff --git 
a/packages/frontend/src/paths/instance/reserves/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/reserves/create/CreatePage.tsx
index cdaf475..ff7b334 100644
--- a/packages/frontend/src/paths/instance/reserves/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/reserves/create/CreatePage.tsx
@@ -79,7 +79,7 @@ function ViewStep({ step, setCurrentStep, reserve, onBack, 
submitForm, setReserv
 
         <div class="buttons is-right mt-5">
           {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
-          <AsyncButton onClick={() => {
+          <AsyncButton class="has-tooltip-left" onClick={() => {
             return 
request<ExchangeBackend.WireResponse>(`${reserve.exchange_url}wire`).then(r => {
               const wireMethods = r.data.accounts.map(a => {
                 const match = PAYTO_WIRE_METHOD_LOOKUP.exec(a.payto_uri)
@@ -91,7 +91,9 @@ function ViewStep({ step, setCurrentStep, reserve, onBack, 
submitForm, setReserv
             }).catch((r: any) => {
               setExchangeQueryError(r.message)
             })
-          }} disabled={hasErrors} ><Translate>Next</Translate></AsyncButton>
+          }} data-tooltip={
+            hasErrors ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+          } disabled={hasErrors} ><Translate>Next</Translate></AsyncButton>
         </div>
       </Fragment>
     }
@@ -110,7 +112,9 @@ function ViewStep({ step, setCurrentStep, reserve, onBack, 
submitForm, setReserv
         </FormProvider>
         <div class="buttons is-right mt-5">
           {onBack && <button class="button" onClick={() => 
setCurrentStep(Steps.EXCHANGE)} ><Translate>Back</Translate></button>}
-          <AsyncButton onClick={submitForm} disabled={hasErrors} 
><Translate>Confirm</Translate></AsyncButton>
+          <AsyncButton onClick={submitForm} data-tooltip={
+              hasErrors ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+            } disabled={hasErrors} 
><Translate>Confirm</Translate></AsyncButton>
         </div>
       </Fragment>
 
diff --git a/packages/frontend/src/paths/instance/reserves/list/Table.tsx 
b/packages/frontend/src/paths/instance/reserves/list/Table.tsx
index 243910d..5977b8b 100644
--- a/packages/frontend/src/paths/instance/reserves/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/reserves/list/Table.tsx
@@ -69,7 +69,7 @@ export function CardTable({ instances, onCreate, onSelect, 
onNewTip, onDelete }:
         <div class="card-header-icon" aria-label="more options">
           <span class="has-tooltip-left" data-tooltip={i18n`add new reserve`}>
 
-            <button class="button is-info" type="button" onClick={onCreate}>
+            <button class="button is-info" type="button" onClick={onCreate} >
               <span class="icon is-small" ><i class="mdi mdi-plus mdi-36px" 
/></span>
             </button>
           </span>
@@ -96,6 +96,7 @@ interface TableProps {
 }
 
 function Table({ instances, onNewTip, onSelect, onDelete }: TableProps): VNode 
{
+  const i18n = useTranslator()
   return (
     <div class="table-container">
       <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
@@ -119,12 +120,16 @@ function Table({ instances, onNewTip, onSelect, onDelete 
}: TableProps): VNode {
               <td onClick={(): void => onSelect(i)} style={{ cursor: 'pointer' 
}} >{i.committed_amount}</td>
               <td class="is-actions-cell right-sticky">
                 <div class="buttons is-right">
-                  <button class="button is-small is-danger jb-modal" 
type="button" onClick={(): void => onDelete(i)}>
+                  <button class="button is-small is-danger"
+                    data-tooltip={i18n`delete selected reserve from the 
database`}
+                    type="button" onClick={(): void => onDelete(i)}>
                     Delete
-                </button>
-                  <button class="button is-small is-info jb-modal" 
type="button" onClick={(): void => onNewTip(i)}>
+                  </button>
+                  <button class="button is-small is-info"
+                    data-tooltip={i18n`authorize new tip from selected 
reserve`}
+                    type="button" onClick={(): void => onNewTip(i)}>
                     New Tip
-                </button>
+                  </button>
                 </div>
               </td>
             </tr>
@@ -144,6 +149,7 @@ function EmptyTable(): VNode {
 }
 
 function TableWithoutFund({ instances, onSelect, onDelete }: TableProps): 
VNode {
+  const i18n = useTranslator()
   return (
     <div class="table-container">
       <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
@@ -163,9 +169,11 @@ function TableWithoutFund({ instances, onSelect, onDelete 
}: TableProps): VNode
               <td onClick={(): void => onSelect(i)} style={{ cursor: 'pointer' 
}} >{i.merchant_initial_amount}</td>
               <td class="is-actions-cell right-sticky">
                 <div class="buttons is-right">
-                  <button class="button is-small is-danger jb-modal" 
type="button" onClick={(): void => onDelete(i)}>
+                  <button class="button is-small is-danger jb-modal" 
type="button"
+                    data-tooltip={i18n`delete selected reserve from the 
database`}
+                    onClick={(): void => onDelete(i)}>
                     Delete
-                </button>
+                  </button>
                 </div>
               </td>
             </tr>
diff --git 
a/packages/frontend/src/paths/instance/transfers/create/CreatePage.tsx 
b/packages/frontend/src/paths/instance/transfers/create/CreatePage.tsx
index f6e3b4f..cab3b9f 100644
--- a/packages/frontend/src/paths/instance/transfers/create/CreatePage.tsx
+++ b/packages/frontend/src/paths/instance/transfers/create/CreatePage.tsx
@@ -94,7 +94,9 @@ export function CreatePage({ accounts, onCreate, onBack }: 
Props): VNode {
 
           <div class="buttons is-right mt-5">
             {onBack && <button class="button" onClick={onBack} 
><Translate>Cancel</Translate></button>}
-            <AsyncButton disabled={hasErrors} onClick={submitForm} 
><Translate>Confirm</Translate></AsyncButton>
+            <AsyncButton disabled={hasErrors} data-tooltip={
+              hasErrors ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+            } onClick={submitForm} 
><Translate>Confirm</Translate></AsyncButton>
           </div>
 
         </div>
diff --git a/packages/frontend/src/paths/instance/transfers/list/Table.tsx 
b/packages/frontend/src/paths/instance/transfers/list/Table.tsx
index 128e71f..f1a9c7e 100644
--- a/packages/frontend/src/paths/instance/transfers/list/Table.tsx
+++ b/packages/frontend/src/paths/instance/transfers/list/Table.tsx
@@ -94,7 +94,9 @@ function Table({ instances, onLoadMoreAfter, onDelete, 
onLoadMoreBefore, hasMore
   const i18n = useTranslator()
   return (
     <div class="table-container">
-      {onLoadMoreBefore && <button class="button is-fullwidth" 
disabled={!hasMoreBefore} onClick={onLoadMoreBefore}><Translate>load newer 
transfers</Translate></button>}
+      {onLoadMoreBefore && <button class="button is-fullwidth" 
+      data-tooltip={i18n`load more transfers before the first one`}
+      disabled={!hasMoreBefore} onClick={onLoadMoreBefore}><Translate>load 
newer transfers</Translate></button>}
       <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
         <thead>
           <tr>
@@ -119,13 +121,15 @@ function Table({ instances, onLoadMoreAfter, onDelete, 
onLoadMoreBefore, hasMore
               <td>{i.verified ? i18n`yes` : i18n`no`}</td>
               <td>{i.execution_time ? (i.execution_time.t_ms == 'never' ? 
i18n`never` : format(i.execution_time.t_ms, 'yyyy/MM/dd HH:mm:ss')) : 
i18n`unknown`}</td>
               <td>
-                {i.verified === undefined ? <button class="button is-danger 
is-small" onClick={() => onDelete(i)}>Delete</button> : undefined}
+                {i.verified === undefined ? <button class="button is-danger 
is-small has-tooltip-left" 
+                data-tooltip={i18n`delete selected transfer from the database`}
+                onClick={() => onDelete(i)}>Delete</button> : undefined}
               </td>
             </tr>
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && <button class="button is-fullwidth" 
disabled={!hasMoreAfter} onClick={onLoadMoreAfter}><Translate>load older 
transfers</Translate></button>}
+      {onLoadMoreAfter && <button class="button is-fullwidth" 
data-tooltip={i18n`load more transfer after the last one`} 
disabled={!hasMoreAfter} onClick={onLoadMoreAfter}><Translate>load older 
transfers</Translate></button>}
     </div>)
 }
 
diff --git a/packages/frontend/src/paths/instance/update/UpdatePage.tsx 
b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
index 5367e5d..7612d6f 100644
--- a/packages/frontend/src/paths/instance/update/UpdatePage.tsx
+++ b/packages/frontend/src/paths/instance/update/UpdatePage.tsx
@@ -95,12 +95,12 @@ export function UpdatePage({ onUpdate, onChangeAuth, 
selected, onBack }: Props):
   }
   const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== 
undefined)
   const submit = async (): Promise<void> => {
-    schema.validateSync(value, { abortEarly: false })
     await onUpdate(schema.cast(value));
     await onBack()
     return Promise.resolve()
   }
   const [active, setActive] = useState(false);
+  const i18n = useTranslator()
 
   return <div>
     <section class="section">
@@ -117,7 +117,9 @@ export function UpdatePage({ onUpdate, onChangeAuth, 
selected, onBack }: Props):
             <div class="level-right">
               <div class="level-item">
                 <h1 class="title">
-                  <button class="button is-danger" onClick={(): void => { 
setActive(!active); }} >
+                  <button class="button is-danger" 
+                    data-tooltip={i18n`Change the authorization method use for 
this instance.`}
+                    onClick={(): void => { setActive(!active); }} >
                     <div class="icon is-left"><i class="mdi mdi-lock-reset" 
/></div>
                     <span><Translate>Manage access token</Translate></span>
                   </button>
@@ -154,7 +156,9 @@ export function UpdatePage({ onUpdate, onChangeAuth, 
selected, onBack }: Props):
           <div class="buttons is-right mt-4">
             <button class="button" onClick={onBack} data-tooltip="cancel 
operation"><Translate>Cancel</Translate></button>
 
-            <AsyncButton onClick={submit} disabled={hasErrors} 
><Translate>Confirm</Translate></AsyncButton>
+            <AsyncButton onClick={submit} data-tooltip={
+              hasErrors ? i18n`Need to complete fields marked with a star` : 
'confirm operation'
+            } disabled={hasErrors} 
><Translate>Confirm</Translate></AsyncButton>
           </div>
         </div>
         <div class="column" />

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