commit f787a00dd4937bd22255247a6a01aca3ce4ab882
parent 929e8f389ea8eec3bb942c111f8e37efffba2d63
Author: Sebastian <sebasjm@gmail.com>
Date: Thu, 18 Feb 2021 09:46:00 -0300
add duration as human readable
Diffstat:
8 files changed, 50 insertions(+), 19 deletions(-)
diff --git a/README.md b/README.md
@@ -53,3 +53,5 @@ Use the browser to navigate into `http://localhost:8080`
* Yup: schema builder for value parsing and validation
+* Date-fns: library for manipulating javascript date
+
diff --git a/TODO b/TODO
@@ -14,11 +14,14 @@ Already done:
* add the information popup into the fields to help with the description (like https://b2b.dab-bank.de/smartbroker/)
* take default lang from the browser for localization
* take the currency from merchant-backend
-
-Next to do:
- * implement proper error handling
* change the input PayTO URI to a string field with a + button to add more
* refactor update page
+ * Login button should be centered
+ * format duration as human readable
+
+Next to do:
+ * implement proper error handling
+ * PATCH payto uri not working as expeced
Queue:
* replace Yup and type definition with a taler-library for the purpose (first wait Florian to refactor wallet core)
@@ -27,6 +30,7 @@ Queue:
* add copyright headers to every source file
* add more doc style comments
* check the field names in forms dont break spaces
- * add default values to some fields: default_max_deposit_fee, default_max_wire_fee, default_wire_fee_amortization, default_pay_delay, default_wire_transfer_delay
- * Login button should be centered
* update spanish lang
+
+Added
+ * save every auth token of different instances
diff --git a/package.json b/package.json
@@ -28,6 +28,7 @@
},
"dependencies": {
"axios": "^0.21.1",
+ "date-fns": "^2.17.0",
"preact": "^10.3.1",
"preact-i18n": "2.3.1-preactx",
"preact-router": "^3.2.1",
diff --git a/src/components/modal/index.tsx b/src/components/modal/index.tsx
@@ -11,21 +11,21 @@ interface Props {
}
export default function ConfirmModal({ active, description, onCancel, onConfirm, children, danger }: Props): VNode {
- return <div class={active ? "modal is-active is-clipped" : "modal"}>
- <div class="modal-background jb-modal-close" onClick={onCancel} />
+ return <div class={active ? "modal is-active" : "modal"}>
+ <div class="modal-background " onClick={onCancel} />
<div class="modal-card">
<header class="modal-card-head">
<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} />
+ <button class="delete " 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} ><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>
+ <button class="button " onClick={onCancel} ><Text id="cancel" /></button>
+ <button class={danger ? "button is-danger " : "button is-info "} onClick={onConfirm} ><Text id="confirm" /></button>
</footer>
</div>
- <button class="modal-close is-large jb-modal-close" aria-label="close" onClick={onCancel} />
+ <button class="modal-close is-large " aria-label="close" onClick={onCancel} />
</div>
}
\ No newline at end of file
diff --git a/src/components/yup/YupField.tsx b/src/components/yup/YupField.tsx
@@ -3,6 +3,14 @@ import { Text, useText } from "preact-i18n";
import { useState } from "preact/hooks";
import { useBackendConfig } from "../hooks/backend";
import useBackend from "../hooks/useBackend";
+import { intervalToDuration, formatDuration } from 'date-fns'
+
+function readableDuration(duration: number): string {
+ return formatDuration(intervalToDuration({ start: 0, end: duration }))
+}
+
+// customFormatDuration({ start: 0, end: 10800 * 1000}) // 3 hours
+// customFormatDuration({ start: 0, end: 108000 * 1000}) // 1 day 6 hours
interface Props {
name: string;
@@ -43,7 +51,7 @@ export default function YupField(name: string, field: string, errors: any, objec
case 'amount': return <YupInputWithAddon {...values} addon={currency} onChange={(v: string): void => values.onChange(`${currency}:${v}`)} value={values.value?.split(':')[1]} />;
case 'url': return <YupInputWithAddon {...values} addon={`${backend.url}/private/instances/`} />;
case 'secured': return <YupInputSecured {...values} />;
- case 'duration': return <YupInput {...values} value={object && object[field]?.d_ms} />;
+ case 'duration': return <YupInputWithAddon addon={readableDuration(values.value?.d_ms)} atTheEnd {...values} value={`${values.value?.d_ms / 1000 || ''}`} onChange={(v: string): void => values.onChange({ d_ms: (parseInt(v, 10) * 1000) || undefined } as any)} />;
default: return <YupInput {...values} />;
}
@@ -155,7 +163,7 @@ function YupInputArray({ name, readonly, value, errors, onChange }: Props): VNod
</div>
}
-function YupInputWithAddon({ name, readonly, value, errors, onChange, addon }: Props & { addon: string }): VNode {
+function YupInputWithAddon({ name, readonly, value, errors, onChange, addon, atTheEnd }: Props & { addon: string; atTheEnd?: boolean }): VNode {
const dict = useText({
placeholder: `fields.instance.${name}.placeholder`,
tooltip: `fields.instance.${name}.tooltip`,
@@ -173,9 +181,9 @@ function YupInputWithAddon({ name, readonly, value, errors, onChange, addon }: P
<div class="field-body">
<div class="field">
<div class="field has-addons">
- <div class="control">
+ { !atTheEnd && <div class="control">
<a class="button is-static">{addon}</a>
- </div>
+ </div> }
<p class="control is-expanded">
<input class={errors[name] ? "input is-danger" : "input"} type="text"
placeholder={dict.placeholder} readonly={readonly}
@@ -183,6 +191,9 @@ function YupInputWithAddon({ name, readonly, value, errors, onChange, addon }: P
onChange={(e): void => onChange(e.currentTarget.value)} />
<Text id={`fields.instance.${name}.help`} />
</p>
+ { atTheEnd && <div class="control">
+ <a class="button is-static">{addon}</a>
+ </div> }
</div>
{errors[name] ? <p class="help is-danger"><Text id={`validation.${errors[name].type}`} fields={errors[name].params}>{errors[name].message}</Text></p> : null}
</div>
diff --git a/src/i18n/index.ts b/src/i18n/index.ts
@@ -164,10 +164,12 @@ export default {
label: 'Max fee amortization',
},
default_pay_delay: {
- label: 'Pay delay'
+ label: 'Pay delay',
+ tooltip: 'value expressed in seconds',
},
default_wire_transfer_delay: {
- label: 'Wire transfer delay'
+ label: 'Wire transfer delay',
+ tooltip: 'value expressed in seconds',
},
address: {
label: 'Address',
diff --git a/src/routes/instances/Update.tsx b/src/routes/instances/Update.tsx
@@ -18,8 +18,14 @@ interface KeyValue {
}
function convert(from: MerchantBackend.Instances.QueryInstancesResponse): MerchantBackend.Instances.InstanceReconfigurationMessage {
- const payto_uris = from.accounts.map(a => a.payto_uri)
- return {default_pay_delay: { d_ms: 1000 }, ...from, payto_uris, };
+ const { accounts, ...rest} = from
+ const payto_uris = accounts.filter(a => a.active).map(a => a.payto_uri)
+ const defaults = {
+ default_wire_fee_amortization: 1,
+ default_pay_delay: { d_ms: 1000*60*60 }, //one hour
+ default_wire_transfer_delay: { d_ms: 1000*60*60*2 }, //two hours
+ }
+ return { ...defaults, ...rest, payto_uris };
}
export default function UpdateModal({ onUpdate, isLoading, selected, goBack }: Props): VNode {
diff --git a/yarn.lock b/yarn.lock
@@ -5128,6 +5128,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
+date-fns@^2.17.0:
+ version "2.17.0"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.17.0.tgz#afa55daea539239db0a64e236ce716ef3d681ba1"
+ integrity sha512-ZEhqxUtEZeGgg9eHNSOAJ8O9xqSgiJdrL0lzSSfMF54x6KXWJiOH/xntSJ9YomJPrYH/p08t6gWjGWq1SDJlSA==
+
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"