merchant-backoffice

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

commit 43ca7d9ab2aee5ce78b801a9310092d1e38eb317
parent 224cbe6846fbf3ea7652bc2413cdd8fc73535b20
Author: Sebastian <sebasjm@gmail.com>
Date:   Wed, 10 Mar 2021 15:47:34 -0300

tie title to the path #6790

Diffstat:
MCHANGELOG.md | 4++--
Mpackages/frontend/package.json | 2+-
Mpackages/frontend/src/AdminRoutes.tsx | 34+++++++++++++++++-----------------
Mpackages/frontend/src/ApplicationReadyRoutes.tsx | 4++--
Mpackages/frontend/src/InstanceRoutes.tsx | 21++++++++++++++++++++-
Mpackages/frontend/src/components/menu/index.tsx | 59++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mpackages/frontend/src/index.tsx | 39++++++---------------------------------
7 files changed, 100 insertions(+), 63 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -21,9 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - prune scss styles to reduce size - create a loading page to be use when the data is not ready - some way to copy the url of a created instance - - change the admin title to "instances" if we are listing the instances and "settings: $ID" on updating instances - fix mobile: some things are still on the left - - update title with: Taler Backoffice: $PAGE_TITLE - instance id in instance list should be clickable - edit button to go to instance settings - notifications should tale place between title and content, and not disapear @@ -37,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - add transfers section - initial state before login - logout takes you to a initial state, not showing error messages + - change the admin title to "instances" if we are listing the instances and "settings: $ID" on updating instances + - update title with: Taler Backoffice: $PAGE_TITLE ## [0.0.3] - 2021-03-04 - submit form on key press == enter diff --git a/packages/frontend/package.json b/packages/frontend/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "merchant-backoffice", - "version": "0.0.1", + "version": "0.0.4", "license": "MIT", "scripts": { "build": "preact build --no-sw --no-esm", diff --git a/packages/frontend/src/AdminRoutes.tsx b/packages/frontend/src/AdminRoutes.tsx @@ -15,11 +15,11 @@ */ import { h, VNode } from "preact"; import Router, { route, Route } from "preact-router"; -import { RootPaths, Redirect, InstancePaths } from "./index"; +import { Redirect } from "./index"; import { MerchantBackend } from "./declaration"; import { useMessageTemplate } from "preact-messages"; import { Notification } from "./utils/types"; -import { InstanceRoutes } from "./InstanceRoutes"; +import { InstancePaths, InstanceRoutes } from "./InstanceRoutes"; import InstanceListPage from './routes/admin/list'; import InstanceCreatePage from "./routes/admin/create"; @@ -42,6 +42,13 @@ import TransferCreatePage from './routes/instance/transfers/create' import LoginPage from "./routes/login"; import { SwrError } from "./hooks/backend"; +export enum AdminPaths { + root = '/', + list_instances = '/instances', + new_instance = '/new', + instance_id_route = '/instance/:id/:rest*', +} + interface Props { pushNotification: (n: Notification) => void; instances: MerchantBackend.Instances.Instance[] @@ -55,12 +62,12 @@ export function AdminRoutes({ instances, pushNotification, addTokenCleaner }: Pr const updateLoginStatus = () => null; return <Router> - <Route path={RootPaths.root} component={Redirect} to={RootPaths.list_instances} /> + <Route path={AdminPaths.root} component={Redirect} to={AdminPaths.list_instances} /> - <Route path={RootPaths.list_instances} component={InstanceListPage} + <Route path={AdminPaths.list_instances} component={InstanceListPage} onCreate={() => { - route(RootPaths.new_instance); + route(AdminPaths.new_instance); }} instances={instances} @@ -69,31 +76,24 @@ export function AdminRoutes({ instances, pushNotification, addTokenCleaner }: Pr route(`/instance/${id}/update`); }} - // onUnauthorized={() => <LoginPage - // withMessage={{ message: i18n`Access denied`, description: i18n`Check your token is valid`, type: 'ERROR', }} - // onConfirm={updateLoginStatus} />} - - // 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} + <Route path={AdminPaths.new_instance} component={InstanceCreatePage} - onBack={() => route(RootPaths.list_instances)} + onBack={() => route(AdminPaths.list_instances)} onConfirm={() => { pushNotification({ message: i18n`create_success`, type: 'SUCCESS' }); - route(RootPaths.list_instances); + route(AdminPaths.list_instances); }} onError={(error: any) => { pushNotification({ message: i18n`create_error`, type: 'ERROR' }); }} + /> - <Route path={RootPaths.instance_id_route} component={InstanceRoutes} + <Route path={AdminPaths.instance_id_route} component={InstanceRoutes} pushNotification={pushNotification} addTokenCleaner={addTokenCleaner} parent="/instance/:id" diff --git a/packages/frontend/src/ApplicationReadyRoutes.tsx b/packages/frontend/src/ApplicationReadyRoutes.tsx @@ -47,7 +47,7 @@ export function ApplicationReadyRoutes({ pushNotification, addTokenCleaner, clea if (!list.data) { if (list.unauthorized) { return <Fragment> - <Menu onLogout={() => { + <Menu title="Login" onLogout={() => { clearAllTokens(); route('/') }} /> @@ -78,7 +78,7 @@ export function ApplicationReadyRoutes({ pushNotification, addTokenCleaner, clea // query to /config is ok but the URL // doest not match with our pattern return <Fragment> - <Menu onLogout={() => { + <Menu title="Error" onLogout={() => { clearAllTokens(); route('/') }} /> diff --git a/packages/frontend/src/InstanceRoutes.tsx b/packages/frontend/src/InstanceRoutes.tsx @@ -26,7 +26,6 @@ import { useMessageTemplate } from 'preact-messages'; import { useBackendInstanceToken } from './hooks'; import { InstanceContextProvider, useBackendContext } from './context/backend'; import { SwrError } from "./hooks/backend"; -import { InstancePaths } from "./index"; import { Notification } from './utils/types'; import LoginPage from './routes/login'; @@ -49,6 +48,26 @@ import TipUpdatePage from './routes/instance/tips/update' import TransferListPage from './routes/instance/transfers/list' import TransferCreatePage from './routes/instance/transfers/create' +export enum InstancePaths { + details = '/', + update = '/update', + + product_list = '/p', + product_update = '/p/:pid/update', + product_new = '/p/new', + + order_list = '/o', + order_update = '/p/:oid/update', + order_new = '/o/new', + + tips_list = '/r', + tips_update = '/r/:rid/update', + tips_new = '/r/new', + + transfers_list = '/t', + transfers_new = '/t/new', +} + export interface Props { id: string; pushNotification: (n: Notification) => void; diff --git a/packages/frontend/src/components/menu/index.tsx b/packages/frontend/src/components/menu/index.tsx @@ -15,21 +15,66 @@ */ import { h, VNode } from "preact"; -import { useState } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; +import { AdminPaths } from "../../AdminRoutes"; +import { InstancePaths } from "../../InstanceRoutes"; import { NavigationBar } from "./NavigationBar"; import { Sidebar } from "./SideBar"; +import Match from 'preact-router/match'; interface Props { + title?: string; instance?: string; onLogout?: () => void; } -export function Menu({ onLogout, instance }: Props): VNode { +function getInstanceTitle(path: string, id: string): string { + console.log('-->', path, id); + + switch (path) { + case InstancePaths.details: return `${id}` + case InstancePaths.update: return `${id}: Settings` + case InstancePaths.order_list: return `${id}: Orders` + case InstancePaths.order_new: return `${id}: New order` + case InstancePaths.order_update: return `${id}: Update order` + case InstancePaths.product_list: return `${id}: Products` + case InstancePaths.product_new: return `${id}: New product` + case InstancePaths.product_update: return `${id}: Update product` + case InstancePaths.tips_list: return `${id}: Tips` + case InstancePaths.tips_new: return `${id}: New tip` + case InstancePaths.tips_update: return `${id}: Update tip` + case InstancePaths.transfers_list: return `${id}: Transfers` + case InstancePaths.transfers_new: return `${id}: New Transfer` + default: return ''; + } +} + +const INSTANCE_ID_LOOKUP = /^\/instance\/([^/]*)\// +function getAdminTitle(path: string) { + if (path === AdminPaths.new_instance) return `New instance` + if (path === AdminPaths.list_instances) return `Instances` + const match = INSTANCE_ID_LOOKUP.exec(path) + if (match && match[1]) return getInstanceTitle(path.replace(INSTANCE_ID_LOOKUP, '/'), match[1]); + return getInstanceTitle(path, 'default') +} + +export function Menu({ onLogout, title, instance }: Props): VNode { const [mobileOpen, setMobileOpen] = useState(false) - const title = !onLogout ? "Welcome!" : (!instance ? "Admin" : instance) - return <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> - <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={title} /> - {onLogout && <Sidebar onLogout={onLogout} instance={instance} mobile={mobileOpen} />} - </div> + + return <Match>{({ path }: any) => { + const titleWithSubtitle = title ? title : (instance ? getInstanceTitle(path, instance) : getAdminTitle(path)) + + useEffect(() => { + document.title = 'Taler Backoffice: ' + titleWithSubtitle + }, [titleWithSubtitle]) + + return ( + <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> + <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={titleWithSubtitle} /> + {onLogout && <Sidebar onLogout={onLogout} instance={instance} mobile={mobileOpen} />} + </div> + ) + }}</Match> + } \ No newline at end of file diff --git a/packages/frontend/src/index.tsx b/packages/frontend/src/index.tsx @@ -38,33 +38,6 @@ import LoginPage from './routes/login'; import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes"; import { Menu } from "./components/menu"; -export enum RootPaths { - root = '/', - list_instances = '/instances', - new_instance = '/new', - instance_id_route = '/instance/:id/:rest*', -} - -export enum InstancePaths { - details = '/', - update = '/update', - - product_list = '/p', - product_update = '/p/:pid/update', - product_new = '/p/new', - - order_list = '/o', - order_update = '/p/:oid/update', - order_new = '/o/new', - - tips_list = '/r', - tips_update = '/r/:rid/update', - tips_new = '/r/new', - - transfers_list = '/t', - transfers_new = '/t/new', -} - export function Redirect({ to }: { to: string }): null { useEffect(() => { route(to, true) @@ -105,12 +78,12 @@ function ApplicationStatusRoutes(): VNode { if (!triedToLog) { return <div id="app"> - <Menu /> + <Menu title="Welcome!" /> <LoginPage onConfirm={(url: string, token?: string) => { changeBackend(url) if (token) updateToken(token) - route(RootPaths.list_instances) + route('/') }} /> </div> @@ -122,19 +95,19 @@ function ApplicationStatusRoutes(): VNode { if (backendConfig.unauthorized) { return <div id="app"> - <Menu /> + <Menu title="Login" /> <LoginPage onConfirm={(url: string, token?: string) => { changeBackend(url) if (token) updateToken(token) - route(RootPaths.list_instances) + route('/') }} /> </div> } return <div id="app"> - <Menu /> + <Menu title="Error" /> <LoginPage withMessage={{ message: i18n`Couldnt access the server`, @@ -144,7 +117,7 @@ function ApplicationStatusRoutes(): VNode { onConfirm={(url: string, token?: string) => { changeBackend(url) if (token) updateToken(token) - route(RootPaths.list_instances) + route('/') }} /> </div>