merchant-backoffice

ZZZ: Inactive/Deprecated
Log | Files | Refs | Submodules | README

commit 9316f178fa73bb9b42a62eaf5d499a1d3de86346
parent 4a0c66159442b96cf6e19a05c51a194b52dddc6e
Author: Sebastian <sebasjm@gmail.com>
Date:   Mon, 24 May 2021 11:20:45 -0300

change token using modal

Diffstat:
MCHANGELOG.md | 19++++++++++++++++++-
Mpackages/frontend/src/components/form/Input.tsx | 2+-
Mpackages/frontend/src/components/form/InputSecured.tsx | 74++++++++++++++++----------------------------------------------------------
Mpackages/frontend/src/components/modal/index.tsx | 62++++++++++++++++++++++++++++++++++++++------------------------
Mpackages/frontend/src/paths/instance/reserves/list/AutorizeTipModal.tsx | 4++--
Mpackages/frontend/src/paths/instance/update/UpdatePage.tsx | 1-
Mpackages/frontend/src/scss/main.scss | 12++++++++++--
7 files changed, 85 insertions(+), 89 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -31,9 +31,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - react routing refactor to use query parameters from history - create taler ui - contract terms in the wallet - - when backoffice get a response of the merchant that have info about the reponse of the exchange, the error is not readed correctly... see wire transfer + - when backoffice get a response of the merchant that have info about the reponsse of the exchange, the error is not readed correctly... see wire transfer - when creating the first default instance, the page keeps reloading preventing for filling the form - + - payto auto remove (add if is missing) + - back cancel in all dialog (order) + - transfer use the tabs instead of three state + - spining while working, + - disabled button grey out + - add timeout to the request + - hash + + - delete button, without + - delete transaction if verified is missing + + - update instance + - auth token: status => external/managed + + + - price not required: product page has required field that should not be required + - animation on load ## [Unreleased] - fixed bug when updating token and not admin diff --git a/packages/frontend/src/components/form/Input.tsx b/packages/frontend/src/components/form/Input.tsx @@ -22,7 +22,7 @@ import { ComponentChildren, h, VNode } from "preact"; import { useField, InputProps } from "./useField"; interface Props<T> extends InputProps<T> { - inputType?: 'text' | 'number' | 'multiline'; + inputType?: 'text' | 'number' | 'multiline' | 'password'; expand?: boolean; toStr?: (v?: any) => string; fromStr?: (s: string) => any; diff --git a/packages/frontend/src/components/form/InputSecured.tsx b/packages/frontend/src/components/form/InputSecured.tsx @@ -21,6 +21,7 @@ import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { Translate } from "../../i18n"; +import { UpdateTokenModal } from "../modal"; import { InputProps, useField } from "./useField"; export type Props<T> = InputProps<T>; @@ -39,7 +40,7 @@ export function InputSecured<T>({ name, readonly, placeholder, tooltip, label, h const { error, value, initial, onChange, toStr, fromStr } = useField<T>(name); const [active, setActive] = useState(false); - const [newValue, setNuewValue] = useState("") + const [newValue, setNuewValue] = useState(""); return <Fragment> <div class="field is-horizontal"> @@ -52,65 +53,22 @@ export function InputSecured<T>({ name, readonly, placeholder, tooltip, label, h </label> </div> <div class="field-body is-flex-grow-3"> - {!active ? - <Fragment> - <div class="field has-addons"> - <button class="button" onClick={(): void => { setActive(!active); }} > - <div class="icon is-left"><i class="mdi mdi-lock-reset" /></div> - <span><Translate>Manage token</Translate></span> - </button> - <TokenStatus prev={initial} post={value} /> - </div> - </Fragment> : - <Fragment> - <div class="field has-addons"> - <div class="control"> - <a class="button is-static">secret-token:</a> - </div> - <div class="control is-expanded"> - <input class="input" type="text" - placeholder={placeholder} readonly={readonly || !active} - disabled={readonly || !active} - name={String(name)} value={newValue} - onInput={(e): void => { - setNuewValue(e.currentTarget.value) - }} /> - {help} - </div> - <div class="control"> - <button class="button is-info" disabled={fromStr(newValue) === value} onClick={(): void => { onChange(fromStr(newValue)); setActive(!active); setNuewValue(""); }} > - <div class="icon is-left"><i class="mdi mdi-lock-outline" /></div> - <span><Translate>Update</Translate></span> - </button> - </div> - </div> - </Fragment> - } + <div class="field has-addons"> + <button class="button" onClick={(): void => { setActive(!active); }} > + <div class="icon is-left"><i class="mdi mdi-lock-reset" /></div> + <span><Translate>Manage token</Translate></span> + </button> + <TokenStatus prev={initial} post={value} /> + </div> {error ? <p class="help is-danger">{error}</p> : null} </div> </div> - {active && - <div class="field is-horizontal"> - <div class="field-body is-flex-grow-3"> - <div class="level" style={{ width: '100%' }}> - <div class="level-right is-flex-grow-1"> - <div class="level-item"> - <button class="button is-danger" disabled={null === value || undefined === value} onClick={(): void => { onChange(null!); setActive(!active); setNuewValue(""); }} > - <div class="icon is-left"><i class="mdi mdi-lock-open-variant" /></div> - <span><Translate>Remove</Translate></span> - </button> - </div> - <div class="level-item"> - <button class="button " onClick={(): void => { onChange(initial!); setActive(!active); setNuewValue(""); }} > - <div class="icon is-left"><i class="mdi mdi-lock-open-variant" /></div> - <span><Translate>Cancel</Translate></span> - </button> - </div> - </div> - - </div> - </div> - </div> - } + {active && <UpdateTokenModal oldToken={initial} + onCancel={() => { onChange(initial!); setActive(false); }} + onClear={() => { onChange(null!); setActive(false); }} + onConfirm={(newToken) => { + onChange(newToken as any); setActive(false) + }} + />} </Fragment >; } diff --git a/packages/frontend/src/components/modal/index.tsx b/packages/frontend/src/components/modal/index.tsx @@ -22,6 +22,7 @@ import { ComponentChildren, h, VNode } from "preact"; import { useState } from "preact/hooks"; +import { useInstanceContext } from "../../context/instance"; import { Translate, useTranslator } from "../../i18n"; import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants"; import { FormProvider } from "../form/FormProvider"; @@ -80,7 +81,7 @@ export function ContinueModal({ active, description, onCancel, onConfirm, childr </div> } -export function ClearConfirmModal({ description, onCancel, onClear, onConfirm, children, disabled }: Props & { onClear?: () => void }): VNode { +export function ClearConfirmModal({ description, onCancel, onClear, onConfirm, children }: Props & { onClear?: () => void }): VNode { return <div class="modal is-active"> <div class="modal-background " onClick={onCancel} /> <div class="modal-card"> @@ -88,13 +89,15 @@ export function ClearConfirmModal({ description, onCancel, onClear, onConfirm, c {!description ? null : <p class="modal-card-title">{description}</p>} <button class="delete " aria-label="close" onClick={onCancel} /> </header> - <section class="modal-card-body"> + <section class="modal-card-body is-main-section"> {children} </section> <footer class="modal-card-foot"> - <button class="button " onClick={onCancel} ><Translate>Cancel</Translate></button> - <button class="button is-danger" onClick={onClear} disabled={disabled} ><Translate>Clear</Translate></button> - <button class="button is-info" onClick={onConfirm} disabled={disabled} ><Translate>Confirm</Translate></button> + {onClear && <button class="button is-danger" onClick={onClear} disabled={onClear === undefined} ><Translate>Clear</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} disabled={onConfirm === undefined} ><Translate>Confirm</Translate></button> + </div> </footer> </div> <button class="modal-close is-large " aria-label="close" onClick={onCancel} /> @@ -115,43 +118,54 @@ export function DeleteModal({ element, onCancel, onConfirm }: DeleteModalProps): } interface UpdateTokenModalProps { - element: { id: string, name: string }; oldToken?: string; onCancel: () => void; onConfirm: (value: string) => void; onClear: () => void; } -export function UpdateTokenModal({ element, onCancel, onClear, onConfirm, oldToken }: UpdateTokenModalProps): VNode { - type State = { old_token: string, new_token: string } +export function UpdateTokenModal({ onCancel, onClear, onConfirm, oldToken }: UpdateTokenModalProps): VNode { + type State = { old_token: string, new_token: string, repeat_token: string } const [form, setValue] = useState<Partial<State>>({ - old_token: '', new_token: '' + old_token: '', new_token: '', repeat_token: '', }) const i18n = useTranslator() + + const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token const errors = { - old_token: oldToken && oldToken !== form.old_token ? i18n`should be the same` : undefined, - new_token: !form.new_token ? i18n`should be the same` : (form.new_token === form.old_token ? i18n`cannot be the same as before` : undefined), + old_token: hasInputTheCorrectOldToken ? i18n`is not the same as the current token` : undefined, + new_token: !form.new_token ? i18n`cannot be empty` : (form.new_token === form.old_token ? i18n`cannot be the same as the old token` : undefined), + repeat_token: form.new_token !== form.repeat_token ? i18n`is not the same` : undefined } - const text = i18n`You are updating the authorization token from instance ${element.name} with id ${element.id}` + const hasErrors = Object.keys(errors).some(k => (errors as any)[k] !== undefined) + + const instance = useInstanceContext() - return <ClearConfirmModal description="update_token" + const text = i18n`You are updating the authorization token from instance with id ${instance.id}` + + return <ClearConfirmModal description={text} onCancel={onCancel} - onConfirm={() => onConfirm(form.new_token!)} - onClear={onClear} - disabled={!!errors.new_token || !!errors.old_token} + onConfirm={!hasErrors ? () => onConfirm(form.new_token!) : undefined} + onClear={!hasInputTheCorrectOldToken && oldToken ? onClear : undefined} > - <p>{text}</p> - <FormProvider errors={errors} object={form} valueHandler={setValue}> - <Input name="old_token" label={i18n`Old token`} tooltip={i18n`token currently in use`} /> - <Input name="new_token" label={i18n`New token`} tooltip={i18n`next token to be used`} /> - </FormProvider> - <p><Translate>Clearing the auth token will mean public access to the instance</Translate></p> + <div class="columns"> + <div class="column" /> + <div class="column is-four-fifths" > + <FormProvider errors={errors} object={form} valueHandler={setValue}> + { oldToken && <Input<State> name="old_token" label={i18n`Old token`} tooltip={i18n`token currently in use`} inputType="password"/> } + <Input<State> name="new_token" label={i18n`New token`} tooltip={i18n`next token to be used`} inputType="password"/> + <Input<State> name="repeat_token" label={i18n`Repeat token`} tooltip={i18n`confirm the same token`} inputType="password"/> + </FormProvider> + <p><Translate>Clearing the auth token will mean public access to the instance</Translate></p> + </div> + <div class="column" /> + </div> </ClearConfirmModal> } -export function LoadingModal({ onCancel }: { onCancel: () => void}): VNode { +export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode { const i18n = useTranslator() return <div class={"modal is-active"}> <div class="modal-background " onClick={onCancel} /> @@ -160,7 +174,7 @@ export function LoadingModal({ onCancel }: { onCancel: () => void}): VNode { <p class="modal-card-title"><Translate>Operation is taking to much time</Translate></p> </header> <section class="modal-card-body"> - <p><Translate>You can wait a little longer or abort the request to the backend. If the problem persist + <p><Translate>You can wait a little longer or abort the request to the backend. If the problem persist contact the administrator.</Translate></p> <p>{i18n`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p> </section> diff --git a/packages/frontend/src/paths/instance/reserves/list/AutorizeTipModal.tsx b/packages/frontend/src/paths/instance/reserves/list/AutorizeTipModal.tsx @@ -30,7 +30,7 @@ import { useTranslator } from "../../../../i18n"; import { AuthorizeTipSchema } from "../../../../schemas"; import { CreatedSuccessfully } from "./CreatedSuccessfully"; -interface AutorizaTipModalProps { +interface AuthorizeTipModalProps { onCancel: () => void; onConfirm: (value: MerchantBackend.Tips.TipCreateRequest) => void; tipAuthorized?: { @@ -39,7 +39,7 @@ interface AutorizaTipModalProps { }; } -export function AuthorizeTipModal({ onCancel, onConfirm, tipAuthorized }: AutorizaTipModalProps): VNode { +export function AuthorizeTipModal({ onCancel, onConfirm, tipAuthorized }: AuthorizeTipModalProps): VNode { // const result = useOrderDetails(id) type State = MerchantBackend.Tips.TipCreateRequest const [form, setValue] = useState<Partial<State>>({}) diff --git a/packages/frontend/src/paths/instance/update/UpdatePage.tsx b/packages/frontend/src/paths/instance/update/UpdatePage.tsx @@ -77,7 +77,6 @@ export function UpdatePage({ onUpdate, selected, onBack }: Props): VNode { 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 = async (): Promise<void> => { // use conversion instead of this const newToken = value.auth_token; diff --git a/packages/frontend/src/scss/main.scss b/packages/frontend/src/scss/main.scss @@ -47,6 +47,8 @@ @import "fonts/nunito.css"; @import "icons/materialdesignicons-4.9.95.min.css"; +$tooltip-color: red; + @import "../../node_modules/@creativebulma/bulma-tooltip/dist/bulma-tooltip.min.css"; @import "../../node_modules/bulma-timeline/dist/css/bulma-timeline.min.css"; @@ -154,4 +156,11 @@ tr:hover .right-sticky { input:read-only { cursor: initial; -} -\ No newline at end of file +} + +span.icon[data-tooltip]:before { + z-index: 1000; + max-width: 250px; + transform: inherit; + // white-space: normal; +}