merchant-backoffice

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

commit cdc8080d082209492ff8b217cd71d7978a34661b
parent 877bcbb0a5ed1c560ee8ff41270dc6d0664c98e9
Author: Sebastian <sebasjm@gmail.com>
Date:   Thu, 25 Feb 2021 19:02:31 -0300

more fixes

Diffstat:
MCHANGELOG.md | 6+++---
Mpackages/frontend/src/ApplicationReadyRoutes.tsx | 12+++++++-----
Mpackages/frontend/src/InstanceRoutes.tsx | 46+++++++++++++++-------------------------------
Mpackages/frontend/src/components/auth/index.tsx | 92+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mpackages/frontend/src/components/sidebar/index.tsx | 10++--------
Mpackages/frontend/src/context/backend.ts | 5++++-
Mpackages/frontend/src/index.tsx | 48++++++++++++++++++++++++++++--------------------
Mpackages/frontend/src/messages/en.po | 7+++++++
Mpackages/frontend/src/messages/es.po | 182+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mpackages/frontend/src/routes/instances/details/index.tsx | 2+-
Mpackages/frontend/src/routes/instances/list/index.tsx | 24+++++++++++++++++++-----
Mpackages/frontend/src/routes/instances/update/UpdatePage.tsx | 3++-
Mpackages/frontend/src/routes/instances/update/index.tsx | 1-
Mpackages/frontend/src/template.html | 2+-
Mpackages/frontend/src/utils/types.ts | 1-
Mpackages/frontend/tests/header.test.tsx | 12+++++++++---
16 files changed, 320 insertions(+), 133 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feature: input as date format - bug: there is missing a mutate call when updating to remove the instance from cache - submit form on key press == enter + - (WIP) remove checkbox from auth token, use button (manage auth) + - (WIP) auth token config as popup with 3 actions (clear (sure?), cancel, set token) - add order section - add product section @@ -24,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - configure eslint - configure prettier - prune scss styles to reduce size + - create a loading page to be use when the data is not ready ## [0.0.2] - 2021-02-25 - REFACTOR: remove react-i18n and implement messageformat @@ -31,10 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - REFACTOR: remove yup from input form defitions - added PORT environment variable for `make dev` and `make serve` - added `make dist` and `make install` - - remove checkbox from auth token, use button (manage auth) - - auth token config as popup with 3 actions (clear (sure?), cancel, set token) - remove last '/' on the backend url - - change button on table row from "edit" to "view" - what happend if cannot access the config - reorder the fields from the address/juriction section (take example) - save every auth token of different instances diff --git a/packages/frontend/src/ApplicationReadyRoutes.tsx b/packages/frontend/src/ApplicationReadyRoutes.tsx @@ -31,6 +31,7 @@ import NotFoundPage from './routes/notfound'; import LoginPage from './routes/login'; import InstanceListPage from './routes/instances/list'; import InstanceCreatePage from "./routes/instances/create"; +import { Notifications } from './components/notifications'; export function ApplicationReadyRoutes({ pushNotification, addTokenCleaner }: { pushNotification: (n: Notification) => void; addTokenCleaner: any; }): VNode { const { changeBackend, updateToken } = useContext(BackendContext); @@ -60,10 +61,11 @@ export function ApplicationReadyRoutes({ pushNotification, addTokenCleaner }: { withMessage={{ message: i18n`Access denied`, description: i18n`Check your token is valid`, type: 'ERROR', }} onConfirm={updateLoginStatus} />} - onError={(error: SwrError) => { - pushNotification({ message: i18n`error`, params: error, type: 'ERROR' }); - return <div />; - }} /> + onQueryError={(error: SwrError) => <LoginPage + withMessage={{ message: i18n`Problem reaching the server`, description: i18n`Got message: ${error.message} from: ${error.backend} (hasToken: ${error.hasToken})`, type: 'ERROR', }} + onConfirm={updateLoginStatus} />} + + /> <Route path={RootPaths.new_instance} component={InstanceCreatePage} @@ -75,7 +77,7 @@ export function ApplicationReadyRoutes({ pushNotification, addTokenCleaner }: { }} onError={(error: any) => { - pushNotification({ message: i18n`create_error`, type: 'ERROR', params: error }); + pushNotification({ message: i18n`create_error`, type: 'ERROR' }); }} /> <Route path={RootPaths.instance_id_route} component={InstanceRoutes} diff --git a/packages/frontend/src/InstanceRoutes.tsx b/packages/frontend/src/InstanceRoutes.tsx @@ -20,7 +20,7 @@ */ import { h, VNode } from 'preact'; -import { useCallback, useContext, useEffect } from "preact/hooks"; +import { useCallback, useContext, useEffect, useMemo } from "preact/hooks"; import { Route, Router, route } from 'preact-router'; import { useMessageTemplate } from 'preact-messages'; import { useBackendInstanceToken } from './hooks'; @@ -55,51 +55,35 @@ export function InstanceRoutes({ id, pushNotification, addTokenCleaner }: Props) updateToken(token); }; - return <InstanceContext.Provider value={{ id, token }}> - <Router> - {/* <Route path={InstancePaths.details} - component={InstanceDetailsPage} - pushNotification={pushNotification} - - onUnauthorized={() => <LoginPage - withMessage={{ message: i18n`Access denied`, description: i18n`Check your token is valid`, type: 'ERROR', }} - onConfirm={updateLoginStatus} />} - - onUpdate={() => { - route(`/instance/${id}/update`); - }} - - onDelete={() => { - route(`/instances`); - }} + const value = useMemo(() => ({ id, token }), [id, token]) - onLoadError={(e: SwrError) => { - pushNotification({ message: i18n`update_load_error`, type: 'ERROR', params: e }); - route(`/instance/${id}/`); - return <div />; - }} /> */} + return <InstanceContext.Provider value={value}> + <Router> <Route path={InstancePaths.update} component={InstanceUpdatePage} - // pushNotification={pushNotification} + onUnauthorized={() => <LoginPage withMessage={{ message: i18n`Access denied`, description: i18n`Check your token is valid`, type: 'ERROR', }} onConfirm={updateLoginStatus} />} - onLoadError={(e: SwrError) => { - pushNotification({ message: i18n`update_load_error`, type: 'ERROR', params: e }); - route(`/instances`); - return <div />; - }} + + onLoadError={(error: SwrError) => <LoginPage + withMessage={{ message: i18n`Problem reaching the server`, description: i18n`Got message: ${error.message} from: ${error.backend} (hasToken: ${error.hasToken})`, type: 'ERROR', }} + onConfirm={updateLoginStatus} />} + onBack={() => { route(`/instances`); }} + onConfirm={() => { pushNotification({ message: i18n`create_success`, type: 'SUCCESS' }); route(`/instances`); }} + onUpdateError={(e: Error) => { - pushNotification({ message: i18n`update_error`, type: 'ERROR', params: e }); - }} /> + pushNotification({ message: i18n`update_error`, type: 'ERROR' }); + }} + /> <Route default component={NotFoundPage} /> </Router> diff --git a/packages/frontend/src/components/auth/index.tsx b/packages/frontend/src/components/auth/index.tsx @@ -20,7 +20,7 @@ */ import { h, VNode } from "preact"; -import { Message } from "preact-messages"; +import { useMessageTemplate } from "preact-messages"; import { useContext, useState } from "preact/hooks"; import { BackendContext } from "../../context/backend"; import { Notification } from "../../utils/types"; @@ -36,61 +36,65 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { const [url, setURL] = useState(backend.url) // const [updatingToken, setUpdatingToken] = useState(false) // const toggleUpdatingToken = (): void => setUpdatingToken(v => !v) + const i18n = useMessageTemplate() - return <div class="modal is-active is-clipped"> - <div class="modal-background" /> - <div class="modal-card"> - {withMessage && <div class={withMessage.type === 'ERROR' ? "notification is-danger" : "notification is-info"}> - <div class="columns is-vcentered"> - <div class="column is-12"> - <div> - <p><strong>{withMessage.message}</strong></p> - {withMessage.description} + return <div class="columns is-centered"> + <div class="column is-two-thirds "> + <div class="modal-card"> + {withMessage && <div class={withMessage.type === 'ERROR' ? "notification is-danger" : "notification is-info"}> + <div class="columns is-vcentered"> + <div class="column is-12"> + <div> + <p><strong>{withMessage.message}</strong></p> + {withMessage.description} + </div> </div> </div> - </div> - </div>} - <header class="modal-card-head"> - <p class="modal-card-title">Login required</p> - </header> - <section class="modal-card-body"> - Please enter your auth token. Token should have "secret-token:" and start with Bearer or ApiKey - <div class="field is-horizontal"> - <div class="field-label is-normal"> - <label class="label">URL</label> - </div> - <div class="field-body"> - <div class="field"> - <p class="control is-expanded"> - <input class="input" type="text" placeholder="set new url" name="id" value={url} onInput={(e): void => setURL(e?.currentTarget.value)} /> - </p> + </div>} + <header class="modal-card-head" style={{border: '1px solid', borderBottom: 0}}> + <p class="modal-card-title">{i18n`Login required`}</p> + </header> + <section class="modal-card-body" style={{border: '1px solid', borderTop: 0, borderBottom: 0}}> + {i18n`Please enter your auth token. Token should have "secret-token:" and start with Bearer or ApiKey`} + <div class="field is-horizontal"> + <div class="field-label is-normal"> + <label class="label">URL</label> + </div> + <div class="field-body"> + <div class="field"> + <p class="control is-expanded"> + <input class="input" type="text" placeholder="set new url" name="id" value={url} onInput={(e): void => setURL(e?.currentTarget.value)} /> + </p> + </div> </div> </div> - </div> - <div class="field is-horizontal"> - <div class="field-label is-normal"> - <label class="label">Token</label> - </div> - <div class="field-body"> - {/* <div class="field has-addons"> + <div class="field is-horizontal"> + <div class="field-label is-normal"> + <label class="label">Token</label> + </div> + <div class="field-body"> + {/* <div class="field has-addons"> <label class="b-checkbox checkbox"> <input type="checkbox" checked={updatingToken} onClick={toggleUpdatingToken} /> <span class="check" /> </label> */} - <div class="field"> - <p class="control is-expanded"> - <input class="input" type="text" placeholder={true ? "set new token" : "hidden token value"} name="id" value={token} onInput={(e): void => setToken(e?.currentTarget.value)} /> - </p> + <div class="field"> + <p class="control is-expanded"> + <input class="input" type="text" placeholder={true ? "set new token" : "hidden token value"} name="id" value={token} onInput={(e): void => setToken(e?.currentTarget.value)} /> + </p> + </div> </div> </div> - </div> - </section> - <footer class="modal-card-foot " style={{ justifyContent: 'flex-end' }}> - <button class="button is-info" onClick={(): void => { - onConfirm(url, token ? token : undefined); - }} >Confirm</button> - </footer> + </section> + <footer class="modal-card-foot " style={{ justifyContent: 'flex-end', border: '1px solid', borderTop: 0 }} > + <button class="button is-info" onClick={(): void => { + onConfirm(url, token ? token : undefined); + }} >Confirm</button> + </footer> + </div> </div> </div> + + // </div> } \ No newline at end of file diff --git a/packages/frontend/src/components/sidebar/index.tsx b/packages/frontend/src/components/sidebar/index.tsx @@ -22,14 +22,14 @@ import { h, VNode } from 'preact'; import { useContext } from 'preact/hooks'; -import { BackendContext, ConfigContext } from '../../context/backend'; +import { BackendContext, useConfigContext } from '../../context/backend'; interface Props { onLogout: () => void; } export function Sidebar({ onLogout }: Props): VNode { - const config = useContext(ConfigContext); + const config = useConfigContext(); const backend = useContext(BackendContext); return ( <aside class="aside is-placed-left is-expanded"> @@ -51,12 +51,6 @@ export function Sidebar({ onLogout }: Props): VNode { <p class="menu-label">Instance</p> <ul class="menu-list"> <li> - <a href="/instances" class="has-icon"> - <span class="icon"><i class="mdi mdi-table" /></span> - <span class="menu-item-label">Details</span> - </a> - </li> - <li> <a href="/forms" class="has-icon"> <span class="icon"><i class="mdi mdi-square-edit-outline" /></span> <span class="menu-item-label">Orders</span> diff --git a/packages/frontend/src/context/backend.ts b/packages/frontend/src/context/backend.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { createContext } from 'preact' -import { StateUpdater } from 'preact/hooks' +import { StateUpdater, useContext } from 'preact/hooks' export interface BackendContextType { url: string; @@ -50,6 +50,9 @@ export const BackendContext = createContext<BackendContextType>({ export const ConfigContext = createContext<ConfigContextType>(null!) +export const useConfigContext = () => useContext(ConfigContext); + + export const InstanceContext = createContext<InstanceContextType>({ id: '', token: undefined, diff --git a/packages/frontend/src/index.tsx b/packages/frontend/src/index.tsx @@ -73,29 +73,39 @@ function ApplicationStatusRoutes(): VNode { const { notifications, pushNotification, removeNotification } = useNotifications() const { lang, setLang, changeBackend, updateToken } = useContext(BackendContext) const backendConfig = useBackendConfig(); - const i18n = useMessageTemplate('') - - const LoginWithError = () => <LoginPage - withMessage={{ - message: i18n`Couldnt access the server`, - type: 'ERROR', - description: !backendConfig.data && backendConfig.error ? i18n`Got message: ${backendConfig.error.message} from: ${backendConfig.error.backend} (hasToken: ${backendConfig.error.hasToken})` : undefined, - }} - onConfirm={(url: string, token?: string) => { - changeBackend(url) - if (token) updateToken(token) - route(RootPaths.list_instances) - }} - /> + const i18n = useMessageTemplate() + const cleaner = useCallback(() => { updateToken(undefined) }, []) const [cleaners, setCleaners] = useState([cleaner]) const addTokenCleaner = (c: () => void) => setCleaners(cs => [...cs, c]) const addTokenCleanerNemo = useCallback((c: () => void) => { addTokenCleaner(c) }, [cleaner]) - const ctx = useMemo(() => ({ currency: backendConfig.data?.currency || '', version: backendConfig.data?.version || '' }), [backendConfig.data?.currency, backendConfig.data?.version]) + const v = backendConfig.data?.currency + ' ' + backendConfig.data?.version + const ctx = useMemo(() => ({ currency: backendConfig.data?.currency || '', version: backendConfig.data?.version || '' }), [v]) - return <div id="app"> + if (!backendConfig.data) { + if (!backendConfig.error) return <div class="is-loading"></div> + if (backendConfig.unauthorized) return <div class="asd">asd </div> + + return <div id="app"> + <NavigationBar lang={lang} setLang={setLang} /> + <LoginPage + withMessage={{ + message: i18n`Couldnt access the server`, + type: 'ERROR', + description: !backendConfig.data && backendConfig.error ? i18n`Got message: ${backendConfig.error.message} from: ${backendConfig.error.backend} (hasToken: ${backendConfig.error.hasToken})` : undefined, + }} + onConfirm={(url: string, token?: string) => { + changeBackend(url) + if (token) updateToken(token) + route(RootPaths.list_instances) + }} + /> + </div> + } + + return <div id="app" class="has-navbar-fixed-top"> <ConfigContext.Provider value={ctx}> <NavigationBar lang={lang} setLang={setLang} /> <Sidebar onLogout={() => { @@ -103,10 +113,8 @@ function ApplicationStatusRoutes(): VNode { route(RootPaths.list_instances) }} /> <Notifications notifications={notifications} removeNotification={removeNotification} /> - {!ctx.currency ? - <Route default component={LoginWithError} /> : - <Route default component={ApplicationReadyRoutes} pushNotification={pushNotification} addTokenCleaner={addTokenCleanerNemo} /> - } + <Route default component={ApplicationReadyRoutes} pushNotification={pushNotification} addTokenCleaner={addTokenCleanerNemo} /> : + {/* <Route default component={LoginWithError} /> */} </ConfigContext.Provider> </div> } diff --git a/packages/frontend/src/messages/en.po b/packages/frontend/src/messages/en.po @@ -23,6 +23,9 @@ msgstr "There is no instances yet, add more pressing the + sign" msgid "Invalid payment address" msgstr "Invalid payment address" +msgid "Problem reaching the server" +msgstr "Problem reaching the server" + msgid "The value %s is invalid for a payment url" msgstr "The value \"%s\" is invalid for a payment url" @@ -206,7 +209,11 @@ msgstr "Update" msgid "Instance details" msgstr "Instance details" +msgid "Login required" +msgstr "Login required" +msgid "Please enter your auth token. Token should have \"secret-token:\" and start with Bearer or ApiKey" +msgstr "Please enter your auth token. Token should have \"secret-token:\" and start with Bearer or ApiKey" diff --git a/packages/frontend/src/messages/es.po b/packages/frontend/src/messages/es.po @@ -2,15 +2,9 @@ msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" -"Language: pl\n" +"Language: es\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgid "Time: %1 second" -msgid_plural "Time: %1 seconds" -msgstr[0] "Czas: %1 sekunda" -msgstr[1] "Czas: %1 sekundy" -msgstr[2] "Czas: %1 sekund" - msgid "Hi" msgstr "Hola" @@ -18,5 +12,177 @@ msgid "List of configured instances" msgstr "Lista de instancias configuradas" msgid "There is no instances yet, add more pressing the + sign" -msgstr "No hay instancias todavía, agregá mas presionando el signo +" +msgstr "Lodavía no hay instancias, puedes agregar mas presionando el signo +" + +msgid "Invalid payment address" +msgstr "Dirección de pago invalido" + +msgid "Problem reaching the server" +msgstr "Hubo problemas intentando llegar al servidor" + +msgid "The value %s is invalid for a payment url" +msgstr "El valor \"%s\" es una dirección de pago invalido" + +# msgctxt "fields.instance.name" +# msgid "placeholder" +# msgstr "" + +# |msgctxt "fields" +# |msgctxt "instance" +# msgctxt "fields.instance.id.label" + +msgid "fields.instance.id.label" +msgstr "Id" + +msgid "fields.instance.name.label" +msgstr "Nombre" + +msgid "fields.instance.merchant_pub.label" +msgstr "Clave publica" + +msgid "fields.instance.payment_targets.label" +msgstr "Dirección de pago" + +msgid "fields.instance.auth_token.label" +msgstr "Token de autorización" + +msgid "fields.instance.auth_token.tooltip" +msgstr "Use this token to secure an instance with a password" + +msgid "fields.instance.payto_uris.label" +msgstr "Dirección de cuenta" + +msgid "fields.instance.payto_uris.help" +msgstr "x-taler-bank/bank.taler:5882/blogger" + +msgid "fields.instance.default_max_deposit_fee.label" +msgstr "Máximo cobro por deposito" + +msgid "fields.instance.default_max_wire_fee.label" +msgstr "Máximo cobro por transferencia bancaria" + +msgid "fields.instance.default_wire_fee_amortization.label" +msgstr "Cobro por transferencia" + +msgid "fields.instance.address.label" +msgstr "Dirección" + +msgid "fields.instance.address.country.label" +msgstr "País" + +msgid "fields.instance.address.country_subdivision.label" +msgstr "País suvdivisión" + +msgid "fields.instance.address.district.label" +msgstr "Distrito" + +msgid "fields.instance.address.town.label" +msgstr "Ciudad" + +msgid "fields.instance.address.town_location.label" +msgstr "Ubicación" + +msgid "fields.instance.address.post_code.label" +msgstr "Código postal" + +msgid "fields.instance.address.street.label" +msgstr "Calle" + +msgid "fields.instance.address.building_name.label" +msgstr "Nombre de edificio" + +msgid "fields.instance.address.building_number.label" +msgstr "Numero de edificio" + +msgid "fields.instance.address.address_lines.label" +msgstr "Linea de dirección" + +msgid "fields.instance.jurisdiction.label" +msgstr "Juridiscción" + +msgid "fields.instance.jurisdiction.country.label" +msgstr "País" + +msgid "fields.instance.jurisdiction.country_subdivision.label" +msgstr "Country Subdivision" + +msgid "fields.instance.jurisdiction.district.label" +msgstr "District" + +msgid "fields.instance.jurisdiction.town.label" +msgstr "Town" + +msgid "fields.instance.jurisdiction.town_location.label" +msgstr "Town Location" + +msgid "fields.instance.jurisdiction.post_code.label" +msgstr "Post code" + +msgid "fields.instance.jurisdiction.street.label" +msgstr "Street" + +msgid "fields.instance.jurisdiction.building_name.label" +msgstr "Building Name" + +msgid "fields.instance.jurisdiction.building_number.label" +msgstr "Building Number" + +msgid "fields.instance.jurisdiction.address_lines.label" +msgstr "Adress Line" + +msgid "fields.instance.default_pay_delay.label" +msgstr "Demora de pago" + +msgid "fields.instance.default_wire_transfer_delay.label" +msgstr "Demora de transferencia" + +msgid "Couldnt access the server" +msgstr "Sin acceso a servidor" + +msgid "Got message: %s from: %s (hasToken: %s)" +msgstr "Se recibió el mensaje \"%s\" desde %s" + +msgid "Merchant" +msgstr "Mercader" + +msgid "Instances" +msgstr "Instancias" + +msgid "Update this instance" +msgstr "Actualizar esta instancia" + +msgid "Cancel" +msgstr "Cancelar" + +msgid "Clear" +msgstr "Limpiar" + +msgid "Confirm" +msgstr "Confirmar" + +msgid "fields.instance.old_token.label" +msgstr "Token previo" + +msgid "fields.instance.new_token.label" +msgstr "Token nuevo" + + +msgid "Access denied" +msgstr "Acceso denegado" + +msgid "Check your token is valid" +msgstr "Verifica que el token sea válido" + +msgid "delete" +msgstr "Borrar" + +msgid "update" +msgstr "Actualizar" + +msgid "Login required" +msgstr "Login requerido" + +msgid "Please enter your auth token. Token should have \"secret-token:\" and start with Bearer or ApiKey" +msgstr "Por favor, ingrese su token de autorización. El token debe contender \"secret-token:\" y comenzar con Bearer o ApiKey" + diff --git a/packages/frontend/src/routes/instances/details/index.tsx b/packages/frontend/src/routes/instances/details/index.tsx @@ -60,7 +60,7 @@ export default function Detail({ onUpdate, onLoadError, onUnauthorized, pushNoti pushNotification({ message: 'delete_success', type: 'SUCCESS' }) onDelete() } catch (error) { - pushNotification({ message: 'delete_error', type: 'ERROR', params: error }) + pushNotification({ message: 'delete_error', type: 'ERROR' }) } setDeleting(false) }} diff --git a/packages/frontend/src/routes/instances/list/index.tsx b/packages/frontend/src/routes/instances/list/index.tsx @@ -30,12 +30,12 @@ import { DeleteModal } from '../../../components/modal'; interface Props { pushNotification: (n: Notification) => void; onUnauthorized: () => VNode; - onError: (e: SwrError) => VNode; + onQueryError: (e: SwrError) => VNode; onCreate: () => void; onUpdate: (id: string) => void; } -export default function Instances({ pushNotification, onUnauthorized, onError, onCreate, onUpdate }: Props): VNode { +export default function Instances({ pushNotification, onUnauthorized, onQueryError, onCreate, onUpdate }: Props): VNode { const list = useBackendInstances() const [deleting, setDeleting] = useState<MerchantBackend.Instances.Instance | null>(null) const { deleteInstance } = useBackendInstanceMutateAPI() @@ -45,11 +45,25 @@ export default function Instances({ pushNotification, onUnauthorized, onError, o if (!list.data) { if (list.unauthorized) return onUnauthorized() - if (list.error) return onError(list.error) + if (list.error) return onQueryError(list.error) + return <div id="app"> + <section class="section is-title-bar"> + + <div class="level"> + <div class="level-left"> + <div class="level-item"> + <ul> + <li>loading</li> + </ul> + </div> + </div> + </div> + </section> + </div> } return <Fragment> - <View instances={list.data?.instances || []} + <View instances={list.data.instances} isLoading={isLoadingTheList} onDelete={setDeleting} onCreate={onCreate} @@ -64,7 +78,7 @@ export default function Instances({ pushNotification, onUnauthorized, onError, o await deleteInstance() pushNotification({ message: 'delete_success', type: 'SUCCESS' }) } catch (e) { - pushNotification({ message: 'delete_error', type: 'ERROR', params: error }) + pushNotification({ message: 'delete_error', type: 'ERROR' }) } setDeleting(null) }} diff --git a/packages/frontend/src/routes/instances/update/UpdatePage.tsx b/packages/frontend/src/routes/instances/update/UpdatePage.tsx @@ -34,6 +34,7 @@ import { ConfigContext } from "../../../context/backend"; import { InputArray } from "../../../components/form/InputArray"; import { InputDuration } from "../../../components/form/InputDuration"; import { InputCurrency } from "../../../components/form/InputCurrency"; +import { InputPayto } from "../../../components/form/InputPayto"; type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage @@ -116,7 +117,7 @@ export function UpdatePage({ onUpdate, isLoading, selected, onBack }: Props): VN <InputSecured<Entity> name="auth_token" /> - <InputArray<Entity> name="payto_uris" /> + <InputPayto<Entity> name="payto_uris" /> <InputCurrency<Entity> name="default_max_deposit_fee" currency={config.currency} /> diff --git a/packages/frontend/src/routes/instances/update/index.tsx b/packages/frontend/src/routes/instances/update/index.tsx @@ -54,7 +54,6 @@ export default function Update({ onBack, onConfirm, onLoadError, onUpdateError, onUpdate={(d: MerchantBackend.Instances.InstanceReconfigurationMessage): Promise<void> => { return updateInstance(d).then(onConfirm).catch(onUpdateError) }} /> - <input type="checkbox" checked={updatingToken !== null} onClick={() => setUpdatingToken(!updatingToken ? "caca": null)} /> {updatingToken && <UpdateTokenModal oldToken={updatingToken} element={{ id, name: details.data.name }} diff --git a/packages/frontend/src/template.html b/packages/frontend/src/template.html @@ -9,7 +9,7 @@ <link rel="apple-touch-icon" href="/assets/icons/apple-touch-icon.png"> <% preact.headEnd %> </head> - <body> + <body class="has-navbar-fixed-top"> <% preact.bodyEnd %> </body> </html> diff --git a/packages/frontend/src/utils/types.ts b/packages/frontend/src/utils/types.ts @@ -22,7 +22,6 @@ export interface Notification { message: string; description?: string; type: MessageType; - params?: any; } export type ValueOrFunction<T> = T | ((p: T) => T) diff --git a/packages/frontend/tests/header.test.tsx b/packages/frontend/tests/header.test.tsx @@ -20,13 +20,19 @@ */ import { h } from 'preact'; -import { Sidebar } from '../src/components/sidebar'; +import { Sidebar, } from '../src/components/sidebar'; // See: https://github.com/preactjs/enzyme-adapter-preact-pure import { shallow } from 'enzyme'; +import * as backend from '../src/context/backend'; describe('Initial Test of the Sidebar', () => { + beforeEach(() => { + jest.spyOn(backend, 'useConfigContext').mockImplementation(() => ({ version: '', currency: '' })); + }) test('Sidbar renders anchors with text', () => { - const context = shallow(<Sidebar />); - expect(context.find('a').map( a => a.text())).toEqual(["Instances", "Details", "Orders", "Inventory", "Tipping", "About"]); + + const context = shallow(<Sidebar onLogout={() => {}} />); + + expect(context.find('a').map( a => a.text())).toEqual(["Instances", "Details", "Orders", "Inventory", "Tipping", "Log out"]); }); });