merchant-backoffice

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

commit 2560ef581f3be82b563695c22cef8de130519ede
parent 6c363c92e2e371e8a961965c7f3534be9e32e994
Author: Sebastian <sebasjm@gmail.com>
Date:   Mon,  1 Mar 2021 16:17:56 -0300

fixed some comments

Diffstat:
Mpackages/frontend/preact.config.js | 9++++++---
Mpackages/frontend/src/components/auth/index.tsx | 4++--
Apackages/frontend/src/components/menu/LangSelector.tsx | 48++++++++++++++++++++++++++++++++++++++++++++++++
Apackages/frontend/src/components/menu/NavigationBar.tsx | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackages/frontend/src/components/menu/SideBar.tsx | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackages/frontend/src/components/menu/index.tsx | 19+++++++++++++++++++
Dpackages/frontend/src/components/navbar/index.tsx | 94-------------------------------------------------------------------------------
Dpackages/frontend/src/components/sidebar/index.tsx | 103-------------------------------------------------------------------------------
Mpackages/frontend/src/index.tsx | 44++++++++++++++++++++++++--------------------
Mpackages/frontend/src/routes/instances/list/Table.tsx | 6+++---
Mpackages/frontend/src/routes/instances/list/View.tsx | 29-----------------------------
Mpackages/frontend/src/routes/instances/update/UpdatePage.tsx | 32+-------------------------------
Mpackages/frontend/src/scss/_aside.scss | 4++--
Mpackages/frontend/src/template.html | 2+-
Mpackages/frontend/tests/header.test.tsx | 2+-
15 files changed, 269 insertions(+), 289 deletions(-)

diff --git a/packages/frontend/preact.config.js b/packages/frontend/preact.config.js @@ -19,13 +19,16 @@ * @author Sebastian Javier Marchano (sebasjm) */ -// import { DefinePlugin } from 'webpack'; -// import { config } from 'dotenv'; -// const { parsed } = config(); +import { DefinePlugin } from 'webpack'; export default { webpack(config, env, helpers, options) { config.node.process = 'mock' + config.plugins.push( + new DefinePlugin({ + 'process.env.__VERSION__': JSON.stringify(require("./package.json").version), + }), + ); config.resolve.extensions.push('.po'); config.module.rules.push({ enforce: 'pre', diff --git a/packages/frontend/src/components/auth/index.tsx b/packages/frontend/src/components/auth/index.tsx @@ -39,8 +39,8 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode { const i18n = useMessageTemplate() return <div class="columns is-centered"> - <div class="column is-two-thirds "> - <div class="modal-card"> + <div class="column is-two-thirds " > + <div class="modal-card" style={{width:'100%',margin:0 }}> {withMessage && <div class={withMessage.type === 'ERROR' ? "notification is-danger" : "notification is-info"}> <div class="columns is-vcentered"> <div class="column is-12"> diff --git a/packages/frontend/src/components/menu/LangSelector.tsx b/packages/frontend/src/components/menu/LangSelector.tsx @@ -0,0 +1,47 @@ +import { h, VNode } from "preact"; +import { useContext, useState } from "preact/hooks"; +import { BackendContext } from "../../context/backend"; +import langIcon from '../../assets/icons/languageicon.svg' +import * as messages from '../../messages' + +interface Props { +} + +type LangsNames = { + [P in keyof typeof messages]: string +} + +const names: LangsNames = { + es: 'Español [es]', + en: 'English [en]', +} + +function getLangName(s: keyof LangsNames | string) { + if (s === 'es' || s === 'en') return names[s] + return s +} + +export function LangSelector(): VNode { + const [updatingLang, setUpdatingLang] = useState(false) + const { lang, setLang } = useContext(BackendContext) + return <div class="dropdown is-active "> + <div class="dropdown-trigger"> + <button class="button" aria-haspopup="true" aria-controls="dropdown-menu" onClick={() => setUpdatingLang(!updatingLang)}> + <div class="icon is-small is-left"> + <img src={langIcon} /> + </div> + <span>{getLangName(lang)}</span> + <div class="icon is-right"> + <i class="mdi mdi-chevron-down" /> + </div> + </button> + </div> + {updatingLang && <div class="dropdown-menu" id="dropdown-menu" role="menu"> + <div class="dropdown-content"> + {Object.keys(messages) + .filter((l) => l !== lang) + .map(l => <a class="dropdown-item" value={l} onClick={() => { setLang(l); setUpdatingLang(false) }}>{getLangName(l)}</a>)} + </div> + </div>} + </div> +} +\ No newline at end of file diff --git a/packages/frontend/src/components/menu/NavigationBar.tsx b/packages/frontend/src/components/menu/NavigationBar.tsx @@ -0,0 +1,54 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { h, VNode } from 'preact'; +import logo from '../../assets/logo.jpeg'; +import { LangSelector } from './LangSelector'; + +interface Props { + onMobileMenu: () => void; +} + +export function NavigationBar({ onMobileMenu }: Props): VNode { + return (<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation"> + <div class="navbar-brand"> + <span class="navbar-item" style={{ fontSize: 24, fontWeight: 900 }}>Instances</span> + + <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" onClick={onMobileMenu}> + <span aria-hidden="true"></span> + <span aria-hidden="true"></span> + <span aria-hidden="true"></span> + </a> + </div> + + <div class="navbar-menu "> + <a class="navbar-start is-justify-content-center is-flex-grow-1" href="https://taler.net"> + <img src={logo} style={{ height: 50, maxHeight: 50 }} /> + </a> + <div class="navbar-end"> + <div class="navbar-item"> + <LangSelector /> + </div> + </div> + </div> + </nav> + ); +} +\ No newline at end of file diff --git a/packages/frontend/src/components/menu/SideBar.tsx b/packages/frontend/src/components/menu/SideBar.tsx @@ -0,0 +1,107 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + + +import { h, VNode } from 'preact'; +import { useContext } from 'preact/hooks'; +import { BackendContext, useConfigContext } from '../../context/backend'; +import { LangSelector } from './LangSelector'; + +interface Props { + onLogout: () => void; + onClick: () => void; + mobile?: boolean; +} + +export function Sidebar({ onLogout, onClick }: Props): VNode { + const config = useConfigContext(); + const backend = useContext(BackendContext); + + return ( + <aside class="aside is-placed-left is-expanded" onClick={onClick}> + <div class="footer" onClick={(e)=>{return e.stopImmediatePropagation()}}> + <LangSelector /> + </div> + <div class="aside-tools"> + <div class="aside-tools-label"> + <div><b>Taler</b> Merchant Office</div> + <div class="is-size-7 has-text-right " style={{ lineHeight: 0, marginTop: -10 }}>v{process.env.__VERSION__} ({config.version})</div> + </div> + </div> + <div class="menu is-menu-main"> + <p class="menu-label">General</p> + <ul class="menu-list"> + <li> + <a href="/" class="is-active router-link-active has-icon"> + <span class="icon"><i class="mdi mdi-desktop-mac" /></span> + <span class="menu-item-label">Instances</span> + </a> + </li> + </ul> + <p class="menu-label">Instance</p> + <ul class="menu-list"> + <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> + </a> + </li> + <li> + <a href="/profile" class="has-icon"> + <span class="icon"><i class="mdi mdi-account-circle" /></span> + <span class="menu-item-label">Inventory</span> + </a> + </li> + <li> + <a href="/profile" class="has-icon"> + <span class="icon"><i class="mdi mdi-account-circle" /></span> + <span class="menu-item-label">Tipping</span> + </a> + </li> + </ul> + <p class="menu-label">Connection</p> + <ul class="menu-list"> + <li> + <div> + <span style={{ width: '3rem' }} class="icon"><i class="mdi mdi-currency-eur" /></span> + <span class="menu-item-label">{config.currency}</span> + </div> + </li> + <li> + <div > + <span style={{ width: '3rem' }} class="icon"><i class="mdi mdi-web" /></span> + <span class="menu-item-label"> + {new URL(backend.url).hostname} / default + </span> + </div> + </li> + {!backend.token ? null : <li> + <a class="has-icon is-state-info is-hoverable" onClick={(): void => onLogout()}> + <span class="icon"><i class="mdi mdi-logout default"></i></span> + <span class="menu-item-label">Log out</span> + </a> + </li>} + </ul> + </div> + </aside> + ); +} + diff --git a/packages/frontend/src/components/menu/index.tsx b/packages/frontend/src/components/menu/index.tsx @@ -0,0 +1,18 @@ +import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { NavigationBar } from "./NavigationBar"; +import { Sidebar } from "./SideBar"; + +interface Props { + sidebar?: boolean; + onLogout: () => void; +} + +export function Menu({ sidebar, onLogout }: Props): VNode { + const [mobileOpen, setMobileOpen] = useState(false) + return <div class={mobileOpen ? "has-aside-mobile-expanded" : ""}> + <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} /> + {sidebar && <Sidebar onLogout={onLogout} mobile={mobileOpen} onClick={() => setMobileOpen(false)} />} + </div> + +} +\ No newline at end of file diff --git a/packages/frontend/src/components/navbar/index.tsx b/packages/frontend/src/components/navbar/index.tsx @@ -1,93 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - -import { h, VNode } from 'preact'; -import * as messages from '../../messages' -import logo from '../../assets/logo.jpeg'; -import langIcon from '../../assets/icons/languageicon.svg' -import { useState } from 'preact/hooks'; - -interface Props { - lang: string; - setLang: (l: string) => void; -} - -type LangsNames = { - [P in keyof typeof messages]: string -} - -const names: LangsNames = { - es: 'Español [es]', - en: 'English [en]', -} - -function getLangName(s: keyof LangsNames | string) { - if (s === 'es' || s === 'en') return names[s] - return s -} - - -export function NavigationBar({ lang, setLang }: Props): VNode { - const [updatingLang, setUpdatingLang] = useState(false) - return (<nav class="navbar is-fixed-top" role="navigation" aria-label="main navigation"> - <div class="navbar-brand"> - <a class="navbar-item" href="https://taler.net"> - <img src={logo} style={{ height: 50, maxHeight: 50 }} /> - </a> - - <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample"> - <span aria-hidden="true" /> - <span aria-hidden="true" /> - <span aria-hidden="true" /> - </a> - </div> - - <div class="navbar-menu"> - - <div class="navbar-end"> - <div class="navbar-item"> - - <div class="dropdown is-active "> - <div class="dropdown-trigger"> - <button class="button" aria-haspopup="true" aria-controls="dropdown-menu" onClick={() => setUpdatingLang(!updatingLang)}> - <div class="icon is-small is-left"> - <img src={langIcon} /> - </div> - <span>{getLangName(lang)}</span> - <div class="icon is-right"> - <i class="mdi mdi-chevron-down" /> - </div> - </button> - </div> - { updatingLang && <div class="dropdown-menu" id="dropdown-menu" role="menu"> - <div class="dropdown-content"> - {Object.keys(messages) - .filter((l) => l !== lang) - .map(l => <a class="dropdown-item" value={l} onClick={() => {setLang(l); setUpdatingLang(false)}}>{getLangName(l)}</a>)} - </div> - </div> } - </div> - </div> - </div> - </div> - </nav> - ); -} -\ No newline at end of file diff --git a/packages/frontend/src/components/sidebar/index.tsx b/packages/frontend/src/components/sidebar/index.tsx @@ -1,103 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - - -import { h, VNode } from 'preact'; -import { useContext } from 'preact/hooks'; -import { BackendContext, useConfigContext } from '../../context/backend'; - -interface Props { - onLogout: () => void; -} - -export function Sidebar({ onLogout }: Props): VNode { - const config = useConfigContext(); - const backend = useContext(BackendContext); - return ( - <aside class="aside is-placed-left is-expanded"> - <div class="aside-tools"> - <div class="aside-tools-label"> - <span><b>Taler</b> Merchant Backend</span> - </div> - </div> - <div class="menu is-menu-main"> - <p class="menu-label">General</p> - <ul class="menu-list"> - <li> - <a href="/" class="is-active router-link-active has-icon"> - <span class="icon"><i class="mdi mdi-desktop-mac" /></span> - <span class="menu-item-label">Instances</span> - </a> - </li> - </ul> - <p class="menu-label">Instance</p> - <ul class="menu-list"> - <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> - </a> - </li> - <li> - <a href="/profile" class="has-icon"> - <span class="icon"><i class="mdi mdi-account-circle" /></span> - <span class="menu-item-label">Inventory</span> - </a> - </li> - <li> - <a href="/profile" class="has-icon"> - <span class="icon"><i class="mdi mdi-account-circle" /></span> - <span class="menu-item-label">Tipping</span> - </a> - </li> - </ul> - <p class="menu-label">Connection</p> - <ul class="menu-list"> - <li> - <div> - <span class="icon"><i class="mdi mdi-currency-eur" /></span> - <span class="menu-item-label">{config.currency}</span> - </div> - </li> - <li> - <div> - <span class="icon"><i class="mdi mdi-web" /></span> - <span class="menu-item-label">{backend.url}</span> - </div> - </li> - <li> - <div> - <span class="icon">V</span> - <span class="menu-item-label">{config.version}</span> - </div> - </li> - <li> - <a class="has-icon is-state-info is-hoverable" onClick={(): void => onLogout()}> - <span class="icon"><i class="mdi mdi-logout default"></i></span> - <span class="menu-item-label">Log out</span> - </a> - </li> - </ul> - </div> - </aside> - ); -} - diff --git a/packages/frontend/src/index.tsx b/packages/frontend/src/index.tsx @@ -26,8 +26,6 @@ import { useCallback, useContext, useEffect, useMemo, useState } from "preact/ho import { Route, route } from 'preact-router'; import { MessageProvider, useMessageTemplate } from 'preact-messages'; -import { Sidebar } from './components/sidebar'; -import { NavigationBar } from './components/navbar'; import { Notifications } from './components/notifications'; import * as messages from './messages' import { useBackendContextState } from './hooks'; @@ -38,6 +36,7 @@ import { hasKey, onTranslationError } from "./utils/functions"; import LoginPage from './routes/login'; import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes"; +import { Menu } from "./components/menu"; export enum RootPaths { root = '/', @@ -71,7 +70,7 @@ export default function Application(): VNode { function ApplicationStatusRoutes(): VNode { const { notifications, pushNotification, removeNotification } = useNotifications() - const { lang, setLang, changeBackend, updateToken, token } = useContext(BackendContext) + const { changeBackend, updateToken, token } = useContext(BackendContext) const backendConfig = useBackendConfig(); const i18n = useMessageTemplate() @@ -84,25 +83,31 @@ function ApplicationStatusRoutes(): VNode { const v = backendConfig.data?.currency + ' ' + backendConfig.data?.version const ctx = useMemo(() => ({ currency: backendConfig.data?.currency || '', version: backendConfig.data?.version || '' }), [v]) - if (!token) { - return <div id="app"> - <NavigationBar lang={lang} setLang={setLang} /> - <LoginPage - onConfirm={(url: string, token?: string) => { - changeBackend(url) - if (token) updateToken(token) - route(RootPaths.list_instances) - }} - /> - </div> - } - if (!backendConfig.data) { + if (!backendConfig.error) return <div class="is-loading"></div> - if (backendConfig.unauthorized) return <div class="asd">asd </div> + + if (backendConfig.unauthorized) { + return <div id="app"> + <Menu onLogout={() => { + cleaners.forEach(c => c()) + route(RootPaths.list_instances) + }} /> + <LoginPage + onConfirm={(url: string, token?: string) => { + changeBackend(url) + if (token) updateToken(token) + route(RootPaths.list_instances) + }} + /> + </div> + } return <div id="app"> - <NavigationBar lang={lang} setLang={setLang} /> + <Menu onLogout={() => { + cleaners.forEach(c => c()) + route(RootPaths.list_instances) + }} /> <LoginPage withMessage={{ message: i18n`Couldnt access the server`, @@ -120,8 +125,7 @@ function ApplicationStatusRoutes(): VNode { return <div id="app" class="has-navbar-fixed-top"> <ConfigContext.Provider value={ctx}> - <NavigationBar lang={lang} setLang={setLang} /> - <Sidebar onLogout={() => { + <Menu sidebar onLogout={() => { cleaners.forEach(c => c()) route(RootPaths.list_instances) }} /> diff --git a/packages/frontend/src/routes/instances/list/Table.tsx b/packages/frontend/src/routes/instances/list/Table.tsx @@ -111,15 +111,15 @@ function Table({ rowSelection, rowSelectionHandler, instances, onUpdate, onDelet </thead> <tbody> {instances.map(i => { - return <tr onClick={(): void => onUpdate(i.id)} style={{cursor: 'pointer'}}> + return <tr> <td class="is-checkbox-cell"> <label class="b-checkbox checkbox"> <input type="checkbox" checked={rowSelection.indexOf(i.id) != -1} onClick={(): void => rowSelectionHandler(toggleSelected(i.id))} /> <span class="check" /> </label> </td> - <td >{i.id}</td> - <td >{i.name}</td> + <td onClick={(): void => onUpdate(i.id)} style={{cursor: 'pointer'}} >{i.id}</td> + <td onClick={(): void => onUpdate(i.id)} style={{cursor: 'pointer'}} >{i.name}</td> <td class="is-actions-cell"> <div class="buttons is-right"> <button class="button is-small is-danger jb-modal" type="button" onClick={(): void => onDelete(i)}> diff --git a/packages/frontend/src/routes/instances/list/View.tsx b/packages/frontend/src/routes/instances/list/View.tsx @@ -36,36 +36,7 @@ interface Props { export function View({ instances, isLoading, onCreate, onDelete, onUpdate, selected }: Props): VNode { return <div id="app"> - <section class="section is-title-bar"> - <div class="level"> - <div class="level-left"> - <div class="level-item"> - <ul> - <li><Message id="Merchant" /></li> - <li><Message id="Instances" /></li> - </ul> - </div> - </div> - </div> - </section> - - <section class={isLoading ? "hero is-hero-bar" : "hero is-hero-bar is-loading"}> - <div class="hero-body"> - <div class="level"> - <div class="level-left"> - <div class="level-item"> - <h1 class="title"> - <Message id="List of configured instances" /> - </h1> - </div> - </div> - <div class="level-right" style="display: none;"> - <div class="level-item" /> - </div> - </div> - </div> - </section> <section class="section is-main-section"> <CardTable instances={instances} onDelete={onDelete} onUpdate={onUpdate} selected={selected} onCreate={onCreate} /> </section> diff --git a/packages/frontend/src/routes/instances/update/UpdatePage.tsx b/packages/frontend/src/routes/instances/update/UpdatePage.tsx @@ -75,37 +75,7 @@ export function UpdatePage({ onUpdate, isLoading, selected, onBack }: Props): VN const config = useContext(ConfigContext) return <div> - <section class="section is-title-bar"> - - <div class="level"> - <div class="level-left"> - <div class="level-item"> - <ul> - <li><Message id="Merchant" /></li> - <li><Message id="Instances" /></li> - </ul> - </div> - </div> - </div> - </section> - - <section class={isLoading ? "hero is-hero-bar" : "hero is-hero-bar is-loading"}> - <div class="hero-body"> - <div class="level"> - <div class="level-left"> - <div class="level-item"> - <h1 class="title"> - <Message id="Update this instance" /> - </h1> - </div> - </div> - <div class="level-right" style="display: none;"> - <div class="level-item" /> - </div> - </div> - </div> - </section> - + <section class="section is-main-section"> <div class="columns"> <div class="column" /> diff --git a/packages/frontend/src/scss/_aside.scss b/packages/frontend/src/scss/_aside.scss @@ -171,8 +171,8 @@ aside.aside { } } } - html.has-aside-mobile-expanded { - nav.navbar { + div.has-aside-mobile-expanded { + nav.navbar { margin-left: $aside-mobile-width; } aside.aside { 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 class="has-navbar-fixed-top"> + <body> <% preact.bodyEnd %> </body> </html> diff --git a/packages/frontend/tests/header.test.tsx b/packages/frontend/tests/header.test.tsx @@ -20,7 +20,7 @@ */ import { h } from 'preact'; -import { Sidebar, } from '../src/components/sidebar'; +import { Sidebar } from '../src/components/menu/SideBar'; // See: https://github.com/preactjs/enzyme-adapter-preact-pure import { shallow } from 'enzyme'; import * as backend from '../src/context/backend';