diff options
author | Sebastian <sebasjm@gmail.com> | 2023-10-04 14:36:03 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-10-04 14:36:03 -0300 |
commit | 851b2da39c3297ede3d267f3d2534cac213261c1 (patch) | |
tree | 51ee03238cb7d87d21e57c0cdf245a0bc04681f0 /packages/merchant-backoffice-ui/src | |
parent | 535b990215bdd861df5cf6215a5f72a47576f89b (diff) | |
download | wallet-core-851b2da39c3297ede3d267f3d2534cac213261c1.tar.xz |
fixing issues reported by Christian, wip
Diffstat (limited to 'packages/merchant-backoffice-ui/src')
21 files changed, 181 insertions, 81 deletions
diff --git a/packages/merchant-backoffice-ui/src/Application.tsx b/packages/merchant-backoffice-ui/src/Application.tsx index 1a7617643..f0a7de53b 100644 --- a/packages/merchant-backoffice-ui/src/Application.tsx +++ b/packages/merchant-backoffice-ui/src/Application.tsx @@ -60,7 +60,7 @@ export function Application(): VNode { * @returns */ function ApplicationStatusRoutes(): VNode { - const { url: backendURL, updateToken, changeBackend } = useBackendContext(); + const { changeBackend, selected: backendSelected } = useBackendContext(); const result = useBackendConfig(); const { i18n } = useTranslationContext(); @@ -69,7 +69,7 @@ function ApplicationStatusRoutes(): VNode { : { currency: "unknown", version: "unknown" }; const ctx = useMemo(() => ({ currency, version }), [currency, version]); - if (!backendURL) { + if (!backendSelected) { return ( <Fragment> <NotConnectedAppMenu title="Welcome!" /> diff --git a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx index c2a9d3b18..f5372db8d 100644 --- a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx +++ b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx @@ -87,9 +87,9 @@ export enum InstancePaths { bank_update = "/bank/:bid/update", bank_new = "/bank/new", - product_list = "/products", - product_update = "/product/:pid/update", - product_new = "/product/new", + inventory_list = "/inventory", + inventory_update = "/inventory/:pid/update", + inventory_new = "/inventory/new", order_list = "/orders", order_new = "/order/new", @@ -347,42 +347,42 @@ export function InstanceRoutes({ onLoadError={ServerErrorRedirectTo(InstancePaths.error)} /> {/** - * Product pages + * Inventory pages */} <Route - path={InstancePaths.product_list} + path={InstancePaths.inventory_list} component={ProductListPage} onUnauthorized={LoginPageAccessDenied} onLoadError={ServerErrorRedirectTo(InstancePaths.server)} onCreate={() => { - route(InstancePaths.product_new); + route(InstancePaths.inventory_new); }} onSelect={(id: string) => { - route(InstancePaths.product_update.replace(":pid", id)); + route(InstancePaths.inventory_update.replace(":pid", id)); }} onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} /> <Route - path={InstancePaths.product_update} + path={InstancePaths.inventory_update} component={ProductUpdatePage} onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.product_list)} + onLoadError={ServerErrorRedirectTo(InstancePaths.inventory_list)} onConfirm={() => { - route(InstancePaths.product_list); + route(InstancePaths.inventory_list); }} onBack={() => { - route(InstancePaths.product_list); + route(InstancePaths.inventory_list); }} onNotFound={IfAdminCreateDefaultOr(NotFoundPage)} /> <Route - path={InstancePaths.product_new} + path={InstancePaths.inventory_new} component={ProductCreatePage} onConfirm={() => { - route(InstancePaths.product_list); + route(InstancePaths.inventory_list); }} onBack={() => { - route(InstancePaths.product_list); + route(InstancePaths.inventory_list); }} /> {/** @@ -405,7 +405,7 @@ export function InstanceRoutes({ path={InstancePaths.bank_update} component={BankAccountUpdatePage} onUnauthorized={LoginPageAccessDenied} - onLoadError={ServerErrorRedirectTo(InstancePaths.product_list)} + onLoadError={ServerErrorRedirectTo(InstancePaths.inventory_list)} onConfirm={() => { route(InstancePaths.bank_list); }} diff --git a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx index 012d14977..1d18685c5 100644 --- a/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx +++ b/packages/merchant-backoffice-ui/src/components/form/InputStock.tsx @@ -212,10 +212,7 @@ export function InputStock<T>({ withTimestampSupport /> - <InputGroup<Entity> - name="address" - label={i18n.str`Delivery address`} - > + <InputGroup<Entity> name="address" label={i18n.str`Warehouse address`}> <InputLocation name="address" /> </InputGroup> </FormProvider> diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx index 3d5f20c85..402134096 100644 --- a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx +++ b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx @@ -49,7 +49,7 @@ export function Sidebar({ isPasswordOk }: Props): VNode { const config = useConfigContext(); - const { url: backendURL } = useBackendContext() + const { url: backendURL, resetBackend } = useBackendContext() const { i18n } = useTranslationContext(); const kycStatus = useInstanceKYCDetails(); const needKYC = kycStatus.ok && kycStatus.data.type === "redirect"; @@ -80,7 +80,7 @@ export function Sidebar({ </div> </div> <div class="menu is-menu-main"> - {isPasswordOk && instance ? ( + {instance ? ( <Fragment> <ul class="menu-list"> <li> @@ -94,12 +94,12 @@ export function Sidebar({ </a> </li> <li> - <a href={"/products"} class="has-icon"> + <a href={"/inventory"} class="has-icon"> <span class="icon"> <i class="mdi mdi-shopping" /> </span> <span class="menu-item-label"> - <i18n.Translate>Products</i18n.Translate> + <i18n.Translate>Inventory</i18n.Translate> </span> </a> </li> @@ -243,7 +243,7 @@ export function Sidebar({ </span> </div> </li> - {isPasswordOk && admin && !mimic && ( + {admin && !mimic && ( <Fragment> <p class="menu-label"> <i18n.Translate>Instances</i18n.Translate> @@ -270,7 +270,7 @@ export function Sidebar({ </li> </Fragment> )} - {isPasswordOk && + {isPasswordOk ? <li> <a class="has-icon is-state-info is-hoverable" @@ -283,8 +283,21 @@ export function Sidebar({ <i18n.Translate>Log out</i18n.Translate> </span> </a> - </li> - } + </li> : + <li> + <a + class="has-icon is-state-info is-hoverable" + onClick={(): void => resetBackend()} + > + <span class="icon"> + <i class="mdi mdi-logout default" /> + </span> + <span class="menu-item-label"> + <i18n.Translate>Change server</i18n.Translate> + </span> + </a> + </li> + } </ul> </div> </aside> diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx b/packages/merchant-backoffice-ui/src/components/menu/index.tsx index cb318906f..b8ac2c9ab 100644 --- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx +++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx @@ -30,11 +30,11 @@ function getInstanceTitle(path: string, id: string): string { return `${id}: Orders`; case InstancePaths.order_new: return `${id}: New order`; - case InstancePaths.product_list: - return `${id}: Products`; - case InstancePaths.product_new: + case InstancePaths.inventory_list: + return `${id}: Inventory`; + case InstancePaths.inventory_new: return `${id}: New product`; - case InstancePaths.product_update: + case InstancePaths.inventory_update: return `${id}: Update product`; case InstancePaths.reserves_new: return `${id}: New reserve`; diff --git a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx index 8bebbd298..e91e8c876 100644 --- a/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx +++ b/packages/merchant-backoffice-ui/src/components/product/ProductForm.tsx @@ -146,9 +146,9 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) { /> <InputNumber<Entity> name="minimum_age" - label={i18n.str`Age restricted`} + label={i18n.str`Age restriction`} tooltip={i18n.str`is this product restricted for customer below certain age?`} - help={i18n.str`can be overridden by the order configuration`} + help={i18n.str`minimum age of the buyer`} /> <Input<Entity> name="unit" @@ -165,7 +165,7 @@ export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) { name="stock" label={i18n.str`Stock`} alreadyExist={alreadyExist} - tooltip={i18n.str`product inventory for products with finite supply (for internal use only)`} + tooltip={i18n.str`inventory for products with finite supply (for internal use only)`} /> <InputTaxes<Entity> name="taxes" diff --git a/packages/merchant-backoffice-ui/src/context/backend.ts b/packages/merchant-backoffice-ui/src/context/backend.ts index 056f9a192..d4a9abd5f 100644 --- a/packages/merchant-backoffice-ui/src/context/backend.ts +++ b/packages/merchant-backoffice-ui/src/context/backend.ts @@ -20,35 +20,55 @@ */ import { createContext, h, VNode } from "preact"; -import { useContext } from "preact/hooks"; +import { useContext, useState } from "preact/hooks"; import { LoginToken } from "../declaration.js"; import { useBackendDefaultToken, useBackendURL } from "../hooks/index.js"; +import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser"; +import { codecForBoolean } from "@gnu-taler/taler-util"; interface BackendContextType { url: string, + selected: boolean; token?: LoginToken; updateToken: (token: LoginToken | undefined) => void; changeBackend: (url: string) => void; + resetBackend: () => void; } const BackendContext = createContext<BackendContextType>({ url: "", + selected: false, token: undefined, updateToken: () => null, changeBackend: () => null, + resetBackend: () => null, }); +const BACKEND_SELECTED = buildStorageKey("backend-selected", codecForBoolean()); + function useBackendContextState( defaultUrl?: string, ): BackendContextType { - const [url, changeBackend] = useBackendURL(defaultUrl); + const [url, changeBackend2] = useBackendURL(defaultUrl); const [token, updateToken] = useBackendDefaultToken(); + const {value, update} = useLocalStorage(BACKEND_SELECTED) + + function changeBackend(s:string) { + changeBackend2(s) + update(true) + } + + function resetBackend() { + update(false) + } return { url, token, + selected: value ?? false, updateToken, - changeBackend + changeBackend, + resetBackend }; } diff --git a/packages/merchant-backoffice-ui/src/declaration.d.ts b/packages/merchant-backoffice-ui/src/declaration.d.ts index c3e6ea3da..dc53e3e83 100644 --- a/packages/merchant-backoffice-ui/src/declaration.d.ts +++ b/packages/merchant-backoffice-ui/src/declaration.d.ts @@ -1327,7 +1327,7 @@ export namespace MerchantBackend { otp_device_id: string; // Human-readable description for the device. - otp_description: string; + otp_device_description: string; // A base64-encoded key otp_key: string; @@ -1341,7 +1341,7 @@ export namespace MerchantBackend { interface OtpDevicePatchDetails { // Human-readable description for the device. - otp_description: string; + otp_device_description: string; // A base64-encoded key otp_key: string | undefined; diff --git a/packages/merchant-backoffice-ui/src/hooks/index.ts b/packages/merchant-backoffice-ui/src/hooks/index.ts index ee696779f..498e4eb78 100644 --- a/packages/merchant-backoffice-ui/src/hooks/index.ts +++ b/packages/merchant-backoffice-ui/src/hooks/index.ts @@ -31,7 +31,8 @@ const calculateRootPath = () => { typeof window !== undefined ? window.location.origin + window.location.pathname : "/"; - return rootPath; + + return rootPath.replace("webui/",""); }; const loginTokenCodec = buildCodecForObject<LoginToken>() diff --git a/packages/merchant-backoffice-ui/src/hooks/otp.ts b/packages/merchant-backoffice-ui/src/hooks/otp.ts index 3544b4881..93eefeea5 100644 --- a/packages/merchant-backoffice-ui/src/hooks/otp.ts +++ b/packages/merchant-backoffice-ui/src/hooks/otp.ts @@ -30,13 +30,13 @@ const useSWR = _useSWR as unknown as SWRHook; const MOCKED_DEVICES: Record<string, MerchantBackend.OTP.OtpDeviceAddDetails> = { "1": { - otp_description: "first device", + otp_device_description: "first device", otp_algorithm: 1, otp_device_id: "1", otp_key: "123", }, "2": { - otp_description: "second device", + otp_device_description: "second device", otp_algorithm: 0, otp_device_id: "2", otp_key: "456", diff --git a/packages/merchant-backoffice-ui/src/hooks/product.ts b/packages/merchant-backoffice-ui/src/hooks/product.ts index 8ecaefaa6..e06ea8ed8 100644 --- a/packages/merchant-backoffice-ui/src/hooks/product.ts +++ b/packages/merchant-backoffice-ui/src/hooks/product.ts @@ -26,6 +26,9 @@ import _useSWR, { SWRHook, useSWRConfig } from "swr"; const useSWR = _useSWR as unknown as SWRHook; export interface ProductAPI { + getProduct: ( + id: string, + ) => Promise<void>; createProduct: ( data: MerchantBackend.Products.ProductAddDetail, ) => Promise<void>; @@ -66,7 +69,7 @@ export function useProductAPI(): ProductAPI { data, }); - return await mutateAll(/.*"\/private\/products.*/); + return await mutateAll(/.*\/private\/products.*/); }; const deleteProduct = async (productId: string): Promise<void> => { @@ -88,7 +91,17 @@ export function useProductAPI(): ProductAPI { return await mutateAll(/.*"\/private\/products.*/); }; - return { createProduct, updateProduct, deleteProduct, lockProduct }; + const getProduct = async ( + productId: string, + ): Promise<void> => { + await request(`/private/products/${productId}`, { + method: "GET", + }); + + return + }; + + return { createProduct, updateProduct, deleteProduct, lockProduct, getProduct }; } export function useInstanceProducts(): HttpResponse< diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx index cbfe1d573..db73217ed 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx @@ -66,7 +66,7 @@ export function CardTable({ <span class="icon"> <i class="mdi mdi-shopping" /> </span> - <i18n.Translate>Products</i18n.Translate> + <i18n.Translate>Inventory</i18n.Translate> </p> <div class="card-header-icon" aria-label="more options"> <span @@ -142,7 +142,7 @@ function Table({ <i18n.Translate>Taxes</i18n.Translate> </th> <th> - <i18n.Translate>Profit</i18n.Translate> + <i18n.Translate>Sales</i18n.Translate> </th> <th> <i18n.Translate>Stock</i18n.Translate> @@ -190,18 +190,21 @@ function Table({ src={i.image ? i.image : emptyImage} style={{ border: "solid black 1px", - width: 100, - height: 100, + maxHeight: "2em", + width: "auto", + height: "auto", }} /> </td> <td + class="has-tooltip-right" + data-tooltip={i.description} onClick={() => rowSelection !== i.id && rowSelectionHandler(i.id) } style={{ cursor: "pointer" }} > - {i.description} + {i.description.length > 30 ? i.description.substring(0, 30) + "..." : i.description} </td> <td onClick={() => diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx index 85c50e5ed..274a7c2ea 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx @@ -53,7 +53,7 @@ export default function ProductList({ onNotFound, }: Props): VNode { const result = useInstanceProducts(); - const { deleteProduct, updateProduct } = useProductAPI(); + const { deleteProduct, updateProduct, getProduct } = useProductAPI(); const [deleting, setDeleting] = useState<MerchantBackend.Products.ProductDetail & WithId | null>(null); const [notif, setNotif] = useState<Notification | undefined>(undefined); @@ -74,11 +74,61 @@ export default function ProductList({ return onNotFound(); return onLoadError(result); } + const [errorId, setErrorId] = useState<string | undefined>( + undefined, + ); + + const [productId, setProductId] = useState<string>() + async function testIfProductExistAndSelect(orderId: string | undefined): Promise<void> { + if (!orderId) { + setErrorId(i18n.str`Enter a product id`); + return; + } + try { + await getProduct(orderId); + onSelect(orderId); + setErrorId(undefined); + } catch { + setErrorId(i18n.str`product not found`); + } + } return ( <section class="section is-main-section"> <NotificationCard notification={notif} /> + <div class="level"> + <div class="level-left"> + <div class="level-item"> + <div class="field has-addons"> + <div class="control"> + <input + class={errorId ? "input is-danger" : "input"} + type="text" + value={productId ?? ""} + onChange={(e) => setProductId(e.currentTarget.value)} + placeholder={i18n.str`product id`} + /> + {errorId && <p class="help is-danger">{errorId}</p>} + </div> + <span + class="has-tooltip-bottom" + data-tooltip={i18n.str`jump to product with the given product ID`} + > + <button + class="button" + onClick={(e) => testIfProductExistAndSelect(productId)} + > + <span class="icon"> + <i class="mdi mdi-arrow-right" /> + </span> + </button> + </span> + </div> + </div> + </div> + </div> + <CardTable instances={result.data} onCreate={onCreate} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx index 2201e75a5..0d2bb2c30 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { HttpError, RequestError, useApiContext, useTranslationContext } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; import { StateUpdater, useEffect, useState } from "preact/hooks"; import { AsyncButton } from "../../../../components/exception/AsyncButton.js"; @@ -35,6 +35,7 @@ import { PAYTO_WIRE_METHOD_LOOKUP, URL_REGEX, } from "../../../../utils/constants.js"; +import { useBackendBaseRequest } from "../../../../hooks/backend.js"; type Entity = MerchantBackend.Rewards.ReserveCreateRequest; @@ -65,6 +66,7 @@ function ViewStep({ setReserve, }: ViewProps): VNode { const { i18n } = useTranslationContext(); + const {request} = useApiContext() const [wireMethods, setWireMethods] = useState<Array<string>>([]); const [exchangeQueryError, setExchangeQueryError] = useState< string | undefined @@ -123,19 +125,26 @@ function ViewStep({ <AsyncButton class="has-tooltip-left" onClick={() => { - return fetch(`${reserve.exchange_url}wire`) - .then((r) => r.json()) + if (!reserve.exchange_url) { + return Promise.resolve(); + } + + return request<any>(reserve.exchange_url, "keys") //</div>fetch(`${reserve.exchange_url}wire`) .then((r) => { - const wireMethods = r.accounts.map((a: any) => { - const match = PAYTO_WIRE_METHOD_LOOKUP.exec(a.payto_uri); - return (match && match[1]) || ""; - }); + if (r.loading) return; + if (r.ok) { + const wireMethods = r.data.accounts.map((a: any) => { + const match = PAYTO_WIRE_METHOD_LOOKUP.exec(a.payto_uri); + return (match && match[1]) || ""; + }); + } setWireMethods(wireMethods); setCurrentStep(Steps.WIRE_METHOD); return; }) - .catch((r: any) => { - setExchangeQueryError(r.message); + .catch((r: RequestError<{}>) => { + console.log(r.cause) + setExchangeQueryError(r.cause.message); }); }} data-tooltip={ diff --git a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx index bdc86d226..cebc1ade6 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx @@ -70,8 +70,8 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { : state.otp_key.length !== 32 ? i18n.str`size of the key should be 32` : undefined, - otp_description: !state.otp_description ? i18n.str`required` - : !/[a-zA-Z0-9]*/.test(state.otp_description) + otp_device_description: !state.otp_device_description ? i18n.str`required` + : !/[a-zA-Z0-9]*/.test(state.otp_device_description) ? i18n.str`no valid. only characters and numbers` : undefined, @@ -103,7 +103,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { tooltip={i18n.str`Internal id on the system`} /> <Input<Entity> - name="otp_description" + name="otp_device_description" label={i18n.str`Descripiton`} tooltip={i18n.str`Useful to identify the device physically`} /> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatedSuccessfully.tsx index 22ae55677..db3842711 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatedSuccessfully.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatedSuccessfully.tsx @@ -77,7 +77,7 @@ export function CreatedSuccessfully({ <input class="input" readonly - value={entity.otp_description} + value={entity.otp_device_description} /> </p> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/validators/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/validators/update/UpdatePage.tsx index 585c12e11..79be9802f 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/validators/update/UpdatePage.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/validators/update/UpdatePage.tsx @@ -87,7 +87,7 @@ export function UpdatePage({ device, onUpdate, onBack }: Props): VNode { errors={errors} > <Input<Entity> - name="otp_description" + name="otp_device_description" label={i18n.str`Description`} tooltip={i18n.str`dddd`} /> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/validators/update/index.tsx b/packages/merchant-backoffice-ui/src/paths/instance/validators/update/index.tsx index 9a27ccfee..52f6c6c29 100644 --- a/packages/merchant-backoffice-ui/src/paths/instance/validators/update/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/instance/validators/update/index.tsx @@ -80,7 +80,7 @@ export default function UpdateValidator({ device={{ id: vid, otp_algorithm: result.data.otp_algorithm, - otp_description: result.data.device_description, + otp_device_description: result.data.device_description, otp_key: undefined, otp_ctr: result.data.otp_ctr }} diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx b/packages/merchant-backoffice-ui/src/paths/login/index.tsx index 9948307e4..a9e3c3a1b 100644 --- a/packages/merchant-backoffice-ui/src/paths/login/index.tsx +++ b/packages/merchant-backoffice-ui/src/paths/login/index.tsx @@ -52,7 +52,7 @@ function cleanUp(s: string): string { } export function LoginPage({ onConfirm }: Props): VNode { - const { url: backendURL, changeBackend } = useBackendContext(); + const { url: backendURL, changeBackend, resetBackend } = useBackendContext(); const { admin, id } = useInstanceContext(); const { requestNewLoginToken } = useCredentialsChecker(); const [token, setToken] = useState(""); @@ -73,10 +73,9 @@ export function LoginPage({ onConfirm }: Props): VNode { }, [backendURL, id, token]) async function changeServer() { - changeBackend("") + resetBackend() } - console.log(admin, id) if (admin && id !== "default") { //admin trying to access another instance return (<div class="columns is-centered" style={{ margin: "auto" }}> @@ -211,10 +210,7 @@ export function LoginPage({ onConfirm }: Props): VNode { borderTop: 0, }} > - <AsyncButton - - onClick={changeServer} - > + <AsyncButton onClick={changeServer}> <i18n.Translate>Change server</i18n.Translate> </AsyncButton> @@ -304,11 +300,8 @@ export function ConnectionPage({ onConfirm }: { onConfirm: (s: string) => void } borderTop: 0, }} > - <AsyncButton - disabled={backendURL === url} - onClick={doConnect} - > - <i18n.Translate>Try again</i18n.Translate> + <AsyncButton onClick={doConnect}> + <i18n.Translate>Connect</i18n.Translate> </AsyncButton> </footer> </div> diff --git a/packages/merchant-backoffice-ui/src/schemas/index.ts b/packages/merchant-backoffice-ui/src/schemas/index.ts index 4be77595b..c97d41204 100644 --- a/packages/merchant-backoffice-ui/src/schemas/index.ts +++ b/packages/merchant-backoffice-ui/src/schemas/index.ts @@ -22,6 +22,7 @@ import { isAfter, isFuture } from "date-fns"; import * as yup from "yup"; import { AMOUNT_REGEX, PAYTO_REGEX } from "../utils/constants.js"; +import { Amounts } from "@gnu-taler/taler-util"; yup.setLocale({ mixed: { @@ -38,7 +39,7 @@ function listOfPayToUrisAreValid(values?: (string | undefined)[]): boolean { } function currencyWithAmountIsValid(value?: string): boolean { - return !!value && AMOUNT_REGEX.test(value); + return !!value && Amounts.parse(value) !== undefined; } function currencyGreaterThan0(value?: string) { if (value) { diff --git a/packages/merchant-backoffice-ui/src/utils/constants.ts b/packages/merchant-backoffice-ui/src/utils/constants.ts index fea9cb7e2..7c4e288b3 100644 --- a/packages/merchant-backoffice-ui/src/utils/constants.ts +++ b/packages/merchant-backoffice-ui/src/utils/constants.ts @@ -25,7 +25,7 @@ export const PAYTO_REGEX = export const PAYTO_WIRE_METHOD_LOOKUP = /payto:\/\/([a-zA-Z][a-zA-Z0-9-.]+)\/.*/; -export const AMOUNT_REGEX = /^[a-zA-Z][a-zA-Z]*:[0-9][0-9,]*\.?[0-9,]*$/; +export const AMOUNT_REGEX = /^[a-zA-Z][a-zA-Z]{1,11}:[0-9][0-9,]*\.?[0-9,]*$/; export const INSTANCE_ID_LOOKUP = /\/instances\/([^/]*)\/?$/; |