diff options
Diffstat (limited to 'packages/merchant-backoffice-ui')
4 files changed, 65 insertions, 16 deletions
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx index e5118c722..dbf4e2409 100644 --- a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx +++ b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx @@ -23,7 +23,7 @@ import { InputProps, useField } from "./useField.js"; export interface Props<T> extends InputProps<T> { expand?: boolean; - inputType?: "text" | "number"; + inputType?: "text" | "number" | "password"; addonBefore?: ComponentChildren; addonAfter?: ComponentChildren; toStr?: (v?: any) => string; diff --git a/packages/merchant-backoffice-ui/src/components/modal/index.tsx b/packages/merchant-backoffice-ui/src/components/modal/index.tsx index c9c7d0ce5..875e89e92 100644 --- a/packages/merchant-backoffice-ui/src/components/modal/index.tsx +++ b/packages/merchant-backoffice-ui/src/components/modal/index.tsx @@ -20,7 +20,7 @@ */ import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; -import { ComponentChildren, h, VNode } from "preact"; +import { ComponentChildren, Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useInstanceContext } from "../../context/instance.js"; import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants.js"; @@ -65,16 +65,25 @@ export function ConfirmModal({ <section class="modal-card-body">{children}</section> <footer class="modal-card-foot"> <div class="buttons is-right" style={{ width: "100%" }}> - <button class="button " onClick={onCancel}> - <i18n.Translate>Cancel</i18n.Translate> - </button> - <button - class={danger ? "button is-danger " : "button is-info "} - disabled={disabled} - onClick={onConfirm} - > - <i18n.Translate>{label}</i18n.Translate> - </button> + {onConfirm ? ( + <Fragment> + <button class="button " onClick={onCancel}> + <i18n.Translate>Cancel</i18n.Translate> + </button> + + <button + class={danger ? "button is-danger " : "button is-info "} + disabled={disabled} + onClick={onConfirm} + > + <i18n.Translate>{label}</i18n.Translate> + </button> + </Fragment> + ) : ( + <button class="button " onClick={onCancel}> + <i18n.Translate>Close</i18n.Translate> + </button> + )} </div> </footer> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx index 66ac72ff5..a6b616907 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx @@ -96,20 +96,30 @@ export function QrPage({ template, id: templateId, onBack }: Props): VNode { : template.pos_algorithm === 2 ? `otpauth://totp/${issuer}:${templateId}?secret=${template.pos_key}&issuer=${issuer}&algorithm=SHA1&digits=8&period=30` : undefined; + + const keySlice = template.pos_key?.substring(0, 4); + + const oauthUriWithoutSecret = !template.pos_algorithm + ? undefined + : template.pos_algorithm === 1 + ? `otpauth://totp/${issuer}:${templateId}?secret=${keySlice}...&issuer=${issuer}&algorithm=SHA1&digits=8&period=30` + : template.pos_algorithm === 2 + ? `otpauth://totp/${issuer}:${templateId}?secret=${keySlice}...&issuer=${issuer}&algorithm=SHA1&digits=8&period=30` + : undefined; return ( <div> {oauthUri && ( <ConfirmModal description="Setup TOTP" active={setupTOTP} - onConfirm={() => { + onCancel={() => { setSetupTOTP(false); }} > <p>Scan this qr code with your TOTP device</p> <QR text={oauthUri} /> <pre style={{ textAlign: "center" }}> - <a href={oauthUri}>{oauthUri}</a> + <a href={oauthUri}>{oauthUriWithoutSecret}</a> </pre> </ConfirmModal> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx index e34e2c746..9fcfcc4bf 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx @@ -57,6 +57,7 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { const { i18n } = useTranslationContext(); const backend = useBackendContext(); + const [showKey, setShowKey] = useState(false); const [state, setState] = useState<Partial<Entity>>(template); const errors: FormErrors<Entity> = { @@ -161,14 +162,26 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { convert={(v) => Number(v)} /> {state.pos_algorithm && state.pos_algorithm > 0 ? ( - <Input<Entity> + <InputWithAddon<Entity> name="pos_key" label={i18n.str`Point-of-sale key`} + inputType={showKey ? "text" : "password"} help="" + expand tooltip={i18n.str`Useful to validate the purchase`} + addonAfter={ + <span class="icon"> + {showKey ? ( + <i class="mdi mdi-eye" /> + ) : ( + <i class="mdi mdi-eye-off" /> + )} + </span> + } side={ - <span data-tooltip={i18n.str`generate random secret key`}> + <span> <button + data-tooltip={i18n.str`generate random secret key`} class="button is-info mr-3" onClick={(e) => { const pos_key = randomBase32Key(); @@ -177,6 +190,23 @@ export function UpdatePage({ template, onUpdate, onBack }: Props): VNode { > <i18n.Translate>random</i18n.Translate> </button> + <button + data-tooltip={ + showKey + ? i18n.str`show secret key` + : i18n.str`hide secret key` + } + class="button is-info mr-3" + onClick={(e) => { + setShowKey(!showKey); + }} + > + {showKey ? ( + <i18n.Translate>hide</i18n.Translate> + ) : ( + <i18n.Translate>show</i18n.Translate> + )} + </button> </span> } /> |