diff options
Diffstat (limited to 'packages/merchant-backoffice-ui')
4 files changed, 111 insertions, 19 deletions
diff --git a/packages/merchant-backoffice-ui/src/components/exception/login.tsx b/packages/merchant-backoffice-ui/src/components/exception/login.tsx index 42c5e89d0..984b6fe06 100644 --- a/packages/merchant-backoffice-ui/src/components/exception/login.tsx +++ b/packages/merchant-backoffice-ui/src/components/exception/login.tsx @@ -20,7 +20,7 @@ */ import { useTranslationContext } from "@gnu-taler/web-util/browser"; -import { h, VNode } from "preact"; +import { ComponentChildren, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useBackendContext } from "../../context/backend.js"; import { useInstanceContext } from "../../context/instance.js"; @@ -40,7 +40,7 @@ function getTokenValuePart(t: string): string { } function normalizeToken(r: string): string { - return `secret-token:${encodeURIComponent(r)}`; + return `secret-token:${r}`; } function cleanUp(s: string): string { @@ -53,7 +53,7 @@ function cleanUp(s: string): string { export function LoginModal({ onConfirm, withMessage }: Props): VNode { const { url: backendUrl, token: baseToken } = useBackendContext(); - const { admin, token: instanceToken } = useInstanceContext(); + const { admin, token: instanceToken, id } = useInstanceContext(); const testLogin = useCredentialsChecker(); const currentToken = getTokenValuePart( (!admin ? baseToken : instanceToken) ?? "", @@ -63,6 +63,78 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { const [url, setURL] = useState(cleanUp(backendUrl)); const { i18n } = useTranslationContext(); + if (admin && id !== "default") { + //admin trying to access another instance + return (<div class="columns is-centered" style={{ margin: "auto" }}> + <div class="column is-two-thirds "> + <div class="modal-card" style={{ width: "100%", margin: 0 }}> + <header + class="modal-card-head" + style={{ border: "1px solid", borderBottom: 0 }} + > + <p class="modal-card-title">{i18n.str`Login required`}</p> + </header> + <section + class="modal-card-body" + style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }} + > + <p> + <i18n.Translate>Need the access token for the instance.</i18n.Translate> + </p> + <div class="field is-horizontal"> + <div class="field-label is-normal"> + <label class="label"> + <i18n.Translate>Access Token</i18n.Translate> + </label> + </div> + <div class="field-body"> + <div class="field"> + <p class="control is-expanded"> + <input + class="input" + type="password" + placeholder={"set new access token"} + name="token" + onKeyPress={(e) => + e.keyCode === 13 + ? onConfirm(url, normalizeToken(token)) + : null + } + value={token} + onInput={(e): void => setToken(e?.currentTarget.value)} + /> + </p> + </div> + </div> + </div> + </section> + <footer + class="modal-card-foot " + style={{ + justifyContent: "flex-end", + border: "1px solid", + borderTop: 0, + }} + > + <AsyncButton + onClick={async () => { + const secretToken = normalizeToken(token); + const { valid, cause } = await testLogin(`${url}/instances/${id}`, secretToken); + if (valid) { + onConfirm(url, secretToken); + } else { + onConfirm(url); + } + }} + > + <i18n.Translate>Confirm</i18n.Translate> + </AsyncButton> + </footer> + </div> + </div> + </div>) + } + return ( <div class="columns is-centered" style={{ margin: "auto" }}> <div class="column is-two-thirds "> @@ -137,8 +209,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { borderTop: 0, }} > - <button - class="button is-info" + <AsyncButton onClick={async () => { const secretToken = normalizeToken(token); const { valid, cause } = await testLogin(url, secretToken); @@ -150,10 +221,24 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { }} > <i18n.Translate>Confirm</i18n.Translate> - </button> + </AsyncButton> </footer> </div> </div> </div> ); } + +function AsyncButton({onClick, children}:{onClick: () => Promise<void>, children: ComponentChildren}):VNode { + const [running, setRunning] = useState(false) + return <button class="button is-info" disabled={running} onClick={() => { + setRunning(true) + onClick().then(() => { + setRunning(false) + }).catch(() => { + setRunning(false) + }) + }}> + {children} + </button> +} diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx b/packages/merchant-backoffice-ui/src/components/menu/index.tsx index 56573b8ca..2beaf6956 100644 --- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx +++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx @@ -130,7 +130,12 @@ export function Menu({ )} {mimic && ( - <nav class="level"> + <nav class="level" style={{ + zIndex: 100, + position:"fixed", + width:"50%", + marginLeft: "20%" + }}> <div class="level-item has-text-centered has-background-warning"> <p class="is-size-5"> You are viewing the instance <b>"{instance}"</b>.{" "} diff --git a/packages/merchant-backoffice-ui/src/hooks/index.ts b/packages/merchant-backoffice-ui/src/hooks/index.ts index 316620cf7..10e77716e 100644 --- a/packages/merchant-backoffice-ui/src/hooks/index.ts +++ b/packages/merchant-backoffice-ui/src/hooks/index.ts @@ -21,6 +21,7 @@ import { StateUpdater, useCallback, useState } from "preact/hooks"; import { ValueOrFunction } from "../utils/types.js"; +import { useMemoryStorage } from "@gnu-taler/web-util/browser"; const calculateRootPath = () => { const rootPath = @@ -52,14 +53,15 @@ export function useBackendURL( export function useBackendDefaultToken( initialValue?: string, -): [string | undefined, StateUpdater<string | undefined>] { - return useLocalStorage("backend-token", initialValue); +): [string | undefined, ((d:string | undefined) => void)] { + const {update, value} = useMemoryStorage(`backend-token`, initialValue) + return [value, update]; } export function useBackendInstanceToken( id: string, -): [string | undefined, StateUpdater<string | undefined>] { - const [token, setToken] = useLocalStorage(`backend-token-${id}`); +): [string | undefined, ((d:string | undefined) => void)] { + const {update:setToken, value:token, reset} = useMemoryStorage(`backend-token-${id}`) const [defaultToken, defaultSetToken] = useBackendDefaultToken(); // instance named 'default' use the default token @@ -67,15 +69,16 @@ export function useBackendInstanceToken( return [defaultToken, defaultSetToken]; } function updateToken( - value: - | (string | undefined) - | ((s: string | undefined) => string | undefined), + value: (string | undefined) ): void { - setToken((p) => { - const toStore = value instanceof Function ? value(p) : value; - return toStore; - }); + console.log("seeting token", value) + if (value === undefined) { + reset() + } else { + setToken(value) + } } + console.log("token", token) return [token, updateToken]; } diff --git a/packages/merchant-backoffice-ui/src/paths/notfound/index.tsx b/packages/merchant-backoffice-ui/src/paths/notfound/index.tsx index b58948dbd..061a67025 100644 --- a/packages/merchant-backoffice-ui/src/paths/notfound/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/notfound/index.tsx @@ -25,7 +25,6 @@ import { Link } from "preact-router"; export default function NotFoundPage(): VNode { return ( <div> - <h1>Error 404</h1> <p>That page doesn't exist.</p> <Link href="/"> <h4>Back to Home</h4> |