diff options
Diffstat (limited to 'packages/anastasis-webui/src/components/menu')
4 files changed, 507 insertions, 270 deletions
diff --git a/packages/anastasis-webui/src/components/menu/LangSelector.tsx b/packages/anastasis-webui/src/components/menu/LangSelector.tsx index 0f91abd7e..5990d758d 100644 --- a/packages/anastasis-webui/src/components/menu/LangSelector.tsx +++ b/packages/anastasis-webui/src/components/menu/LangSelector.tsx @@ -1,73 +1,92 @@ /* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL - 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 + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero 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 + GNU Anastasis 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. + A PARTICULAR PURPOSE. See the GNU Affero 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/> + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ + * + * @author Sebastian Javier Marchano (sebasjm) + */ import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import langIcon from '../../assets/icons/languageicon.svg'; -import { useTranslationContext } from "../../context/translation"; -import { strings as messages } from '../../i18n/strings' +import langIcon from "../../assets/icons/languageicon.svg"; +import { useTranslationContext } from "../../context/translation.js"; +import { strings as messages } from "../../i18n/strings.js"; type LangsNames = { - [P in keyof typeof messages]: string -} + [P in keyof typeof messages]: string; +}; const names: LangsNames = { - es: 'Español [es]', - en: 'English [en]', - fr: 'Français [fr]', - de: 'Deutsch [de]', - sv: 'Svenska [sv]', - it: 'Italiano [it]', -} + es: "Español [es]", + en: "English [en]", + fr: "Français [fr]", + de: "Deutsch [de]", + sv: "Svenska [sv]", + it: "Italiano [it]", +}; function getLangName(s: keyof LangsNames | string): string { - if (names[s]) return names[s] - return String(s) + if (names[s]) return names[s]; + return String(s); } export function LangSelector(): VNode { - const [updatingLang, setUpdatingLang] = useState(false) - const { lang, changeLanguage } = useTranslationContext() + const [updatingLang, setUpdatingLang] = useState(false); + const { lang, changeLanguage } = useTranslationContext(); - return <div class="dropdown is-active "> - <div class="dropdown-trigger"> - <button class="button has-tooltip-left" - data-tooltip="change language selection" - 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" /> + return ( + <div class="dropdown is-active "> + <div class="dropdown-trigger"> + <button + class="button has-tooltip-left" + data-tooltip="change language selection" + 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 + key={l} + class="dropdown-item" + value={l} + onClick={() => { + changeLanguage(l); + setUpdatingLang(false); + }} + > + {getLangName(l)} + </a> + ))} + </div> </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 key={l} class="dropdown-item" value={l} onClick={() => { changeLanguage(l); setUpdatingLang(false) }}>{getLangName(l)}</a>)} - </div> - </div>} - </div> -}
\ No newline at end of file + ); +} diff --git a/packages/anastasis-webui/src/components/menu/NavigationBar.tsx b/packages/anastasis-webui/src/components/menu/NavigationBar.tsx index e1bb4c7c0..42b7a23e2 100644 --- a/packages/anastasis-webui/src/components/menu/NavigationBar.tsx +++ b/packages/anastasis-webui/src/components/menu/NavigationBar.tsx @@ -1,27 +1,25 @@ /* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL - 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 + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero 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 + GNU Anastasis 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. + A PARTICULAR PURPOSE. See the GNU Affero 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/> + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ + * + * @author Sebastian Javier Marchano (sebasjm) + */ -import { h, VNode } from 'preact'; -import logo from '../../assets/logo.jpeg'; -import { LangSelector } from './LangSelector'; +import { h, VNode } from "preact"; interface Props { onMobileMenu: () => void; @@ -29,30 +27,59 @@ interface Props { } export function NavigationBar({ onMobileMenu, title }: 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 }}>{title}</span> - - <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" onClick={(e) => { - onMobileMenu() - e.stopPropagation() - }}> - <span aria-hidden="true" /> - <span aria-hidden="true" /> - <span aria-hidden="true" /> - </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" style={{ paddingTop: 4, paddingBottom: 4 }}> - <LangSelector /> + 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 }}> + {title} + </span> + <a + href="mailto:contact@anastasis.lu" + style={{ alignSelf: "center", padding: "0.5em" }} + > + Contact us + </a> + <a + href="https://bugs.anastasis.lu/" + style={{ alignSelf: "center", padding: "0.5em" }} + > + Report a bug + </a> + {/* <a + style={{ + alignSelf: "center", + padding: "0.5em", + }} + > + Settings + </a> */} + {/* <a + role="button" + class="navbar-burger" + aria-label="menu" + aria-expanded="false" + onClick={(e) => { + onMobileMenu(); + e.stopPropagation(); + }} + > + <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" style={{ paddingTop: 4, paddingBottom: 4 }}> + {/* <LangSelector /> */} + </div> </div> </div> - </div> - </nav> + </nav> ); -}
\ No newline at end of file +} diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx b/packages/anastasis-webui/src/components/menu/SideBar.tsx index df582a5d0..31bc3c7a7 100644 --- a/packages/anastasis-webui/src/components/menu/SideBar.tsx +++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx @@ -1,169 +1,329 @@ /* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL - 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 + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero 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 + GNU Anastasis 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. + A PARTICULAR PURPOSE. See the GNU Affero 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/> + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** -* -* @author Sebastian Javier Marchano (sebasjm) -*/ - + * + * @author Sebastian Javier Marchano (sebasjm) + */ -import { Fragment, h, VNode } from 'preact'; -import { BackupStates, RecoveryStates } from '../../../../anastasis-core/lib'; -import { useAnastasisContext } from '../../context/anastasis'; -import { Translate } from '../../i18n'; -import { LangSelector } from './LangSelector'; +import { BackupStates, RecoveryStates } from "@gnu-taler/anastasis-core"; +import { Fragment, h, VNode } from "preact"; +import { useAnastasisContext } from "../../context/anastasis.js"; +import { useTranslationContext } from "../../context/translation.js"; interface Props { mobile?: boolean; } +const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : "dev"; +const GIT_HASH = + typeof __GIT_HASH__ !== "undefined" + ? __GIT_HASH__.substring(0, 7) + : undefined; +const VERSION_WITH_HASH = GIT_HASH ? `${VERSION}-${GIT_HASH}` : VERSION; + export function Sidebar({ mobile }: Props): VNode { - // const config = useConfigContext(); - const config = { version: 'none' } - const process = { env: { __VERSION__: '0.0.0' } } - const reducer = useAnastasisContext()! + const reducer = useAnastasisContext()!; + const { i18n } = useTranslationContext(); + + function saveSession(): void { + const state = reducer.exportState(); + const link = document.createElement("a"); + link.download = "anastasis.json"; + link.href = `data:text/plain,${state}`; + link.click(); + } return ( <aside class="aside is-placed-left is-expanded"> - {mobile && <div class="footer" onClick={(e) => { return e.stopImmediatePropagation() }}> + {/* {mobile && <div class="footer" onClick={(e) => { return e.stopImmediatePropagation() }}> <LangSelector /> - </div>} + </div>} */} <div class="aside-tools"> <div class="aside-tools-label"> - <div><b>Anastasis</b> Reducer</div> - <div class="is-size-7 has-text-right" style={{ lineHeight: 0, marginTop: -10 }}> - {process.env.__VERSION__} ({config.version}) + <div> + <b>Anastasis</b> + </div> + <div + class="is-size-7 has-text-right" + style={{ lineHeight: 0, marginTop: -10 }} + > + Version {VERSION_WITH_HASH} </div> </div> </div> <div class="menu is-menu-main"> - {!reducer.currentReducerState && + {!reducer.currentReducerState && ( <p class="menu-label"> - <Translate>Backup or Recorver</Translate> + <i18n.Translate>Backup or Recorver</i18n.Translate> </p> - } + )} <ul class="menu-list"> - {!reducer.currentReducerState && + {!reducer.currentReducerState && ( <li> <div class="ml-4"> - <span class="menu-item-label"><Translate>Start one options</Translate></span> - </div> - </li> - } - {reducer.currentReducerState && reducer.currentReducerState.backup_state ? <Fragment> - <li class={reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>Continent selection</Translate></span> + <span class="menu-item-label"> + <i18n.Translate>Select one option</i18n.Translate> + </span> </div> </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.CountrySelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>Country selection</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.UserAttributesCollecting ? 'is-active' : ''}> + )} + {reducer.currentReducerState?.reducer_type === "backup" ? ( + <Fragment> + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.ContinentSelecting || + reducer.currentReducerState.backup_state === + BackupStates.CountrySelecting + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Location</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.UserAttributesCollecting + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Personal information</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.AuthenticationsEditing + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Authorization methods</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.PoliciesReviewing + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Policies</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.SecretEditing + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Secret input</i18n.Translate> + </span> + </div> + </li> + {/* <li class={reducer.currentReducerState.backup_state === BackupStates.PoliciesPaying ? 'is-active' : ''}> <div class="ml-4"> - <span class="menu-item-label"><Translate>User attributes</Translate></span> + <span class="menu-item-label"><i18n.Translate>Payment (optional)</i18n.Translate></span> </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.AuthenticationsEditing ? 'is-active' : ''}> + </li> */} + <li + class={ + reducer.currentReducerState.backup_state === + BackupStates.BackupFinished + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Backup completed</i18n.Translate> + </span> + </div> + </li> + {/* <li class={reducer.currentReducerState.backup_state === BackupStates.TruthsPaying ? 'is-active' : ''}> <div class="ml-4"> - <span class="menu-item-label"><Translate>Auth methods</Translate></span> + <span class="menu-item-label"><i18n.Translate>Truth Paying</i18n.Translate></span> </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.PoliciesReviewing ? 'is-active' : ''}> - <div class="ml-4"> + </li> */} + {reducer.currentReducerState.backup_state !== + BackupStates.BackupFinished && ( + <li> + <div class="buttons ml-4"> + <button + class="button is-primary is-right" + onClick={saveSession} + > + Save backup session + </button> + </div> + </li> + )} + {reducer.currentReducerState.backup_state !== + BackupStates.BackupFinished && ( + <li> + <div class="buttons ml-4"> + <button + class="button is-danger is-right" + onClick={() => reducer.reset()} + > + Reset session + </button> + </div> + </li> + )} + </Fragment> + ) : ( + reducer.currentReducerState?.reducer_type === "recovery" && ( + <Fragment> + <li + class={ + reducer.currentReducerState.recovery_state === + RecoveryStates.ContinentSelecting || + reducer.currentReducerState.recovery_state === + RecoveryStates.CountrySelecting + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Location</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.recovery_state === + RecoveryStates.UserAttributesCollecting + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Personal information</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.recovery_state === + RecoveryStates.SecretSelecting + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Secret selection</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.recovery_state === + RecoveryStates.ChallengeSelecting || + reducer.currentReducerState.recovery_state === + RecoveryStates.ChallengeSolving + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Solve Challenges</i18n.Translate> + </span> + </div> + </li> + <li + class={ + reducer.currentReducerState.recovery_state === + RecoveryStates.RecoveryFinished + ? "is-active" + : "" + } + > + <div class="ml-4"> + <span class="menu-item-label"> + <i18n.Translate>Secret recovered</i18n.Translate> + </span> + </div> + </li> + {reducer.currentReducerState.recovery_state !== + RecoveryStates.RecoveryFinished && ( + <li> + <div class="buttons ml-4"> + <button + class="button is-primary is-right" + onClick={saveSession} + > + Save recovery session + </button> + </div> + </li> + )} + {reducer.currentReducerState.recovery_state === + RecoveryStates.RecoveryFinished ? ( + <Fragment /> + ) : ( + <li> + <div class="buttons ml-4"> + <button + class="button is-danger is-right" + onClick={() => reducer.reset()} + > + Reset session + </button> + </div> + </li> + )} + </Fragment> + ) + )} - <span class="menu-item-label"><Translate>PoliciesReviewing</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.SecretEditing ? 'is-active' : ''}> - <div class="ml-4"> - - <span class="menu-item-label"><Translate>SecretEditing</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.PoliciesPaying ? 'is-active' : ''}> - <div class="ml-4"> - - <span class="menu-item-label"><Translate>PoliciesPaying</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.BackupFinished ? 'is-active' : ''}> - <div class="ml-4"> - - <span class="menu-item-label"><Translate>BackupFinished</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.backup_state === BackupStates.TruthsPaying ? 'is-active' : ''}> - <div class="ml-4"> - - <span class="menu-item-label"><Translate>TruthsPaying</Translate></span> - </div> - </li> - </Fragment> : (reducer.currentReducerState && reducer.currentReducerState?.recovery_state && <Fragment> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>TruthsPaying</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.CountrySelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>CountrySelecting</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.UserAttributesCollecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>UserAttributesCollecting</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.SecretSelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>SecretSelecting</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSelecting ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>ChallengeSelecting</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.ChallengeSolving ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>ChallengeSolving</Translate></span> - </div> - </li> - <li class={reducer.currentReducerState.recovery_state === RecoveryStates.RecoveryFinished ? 'is-active' : ''}> - <div class="ml-4"> - <span class="menu-item-label"><Translate>RecoveryFinished</Translate></span> - </div> - </li> - </Fragment>)} - {reducer.currentReducerState && - <li> + {/* <li> <div class="buttons ml-4"> - <button class="button is-danger is-right" onClick={() => reducer.reset()}>Reset session</button> + <button class="button is-info is-right" >Manage providers</button> </div> - </li> - } - + </li> */} </ul> </div> </aside> ); } - diff --git a/packages/anastasis-webui/src/components/menu/index.tsx b/packages/anastasis-webui/src/components/menu/index.tsx index febcd79c8..957ab2977 100644 --- a/packages/anastasis-webui/src/components/menu/index.tsx +++ b/packages/anastasis-webui/src/components/menu/index.tsx @@ -1,55 +1,67 @@ /* - This file is part of GNU Taler - (C) 2021 Taler Systems S.A. + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL - 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 + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero 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 + GNU Anastasis 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. + A PARTICULAR PURPOSE. See the GNU Affero 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/> + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ import { ComponentChildren, Fragment, h, VNode } from "preact"; -import Match from 'preact-router/match'; +import { Match } from "preact-router/match.js"; import { useEffect, useState } from "preact/hooks"; -import { NavigationBar } from "./NavigationBar"; -import { Sidebar } from "./SideBar"; - - - +import { NavigationBar } from "./NavigationBar.js"; +import { Sidebar } from "./SideBar.js"; interface MenuProps { title: string; } -function WithTitle({ title, children }: { title: string; children: ComponentChildren }): VNode { +function WithTitle({ + title, + children, +}: { + title: string; + children: ComponentChildren; +}): VNode { useEffect(() => { - document.title = `Taler Backoffice: ${title}` - }, [title]) - return <Fragment>{children}</Fragment> + document.title = `${title}`; + }, [title]); + return <Fragment>{children}</Fragment>; } export function Menu({ title }: MenuProps): VNode { - const [mobileOpen, setMobileOpen] = useState(false) - - return <Match>{({ path }: { path: string }) => { - const titleWithSubtitle = title // title ? title : (!admin ? getInstanceTitle(path, instance) : getAdminTitle(path, instance)) - return (<WithTitle title={titleWithSubtitle}> - <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> - <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={titleWithSubtitle} /> - - <Sidebar mobile={mobileOpen} /> - - </div> - </WithTitle> - ) - }}</Match> - + const [mobileOpen, setMobileOpen] = useState(false); + + return ( + <Match> + {({ path }: { path: string }) => { + const titleWithSubtitle = title; // title ? title : (!admin ? getInstanceTitle(path, instance) : getAdminTitle(path, instance)) + return ( + <WithTitle title={titleWithSubtitle}> + <div + class={mobileOpen ? "has-aside-mobile-expanded" : ""} + onClick={() => setMobileOpen(false)} + > + <NavigationBar + onMobileMenu={() => setMobileOpen(!mobileOpen)} + title={titleWithSubtitle} + /> + + <Sidebar mobile={mobileOpen} /> + </div> + </WithTitle> + ); + }} + </Match> + ); } interface NotYetReadyAppMenuProps { @@ -60,37 +72,57 @@ interface NotYetReadyAppMenuProps { interface NotifProps { notification?: Notification; } -export function NotificationCard({ notification: n }: NotifProps): VNode | null { - if (!n) return null - return <div class="notification"> - <div class="columns is-vcentered"> - <div class="column is-12"> - <article class={n.type === 'ERROR' ? "message is-danger" : (n.type === 'WARN' ? "message is-warning" : "message is-info")}> - <div class="message-header"> - <p>{n.message}</p> - </div> - {n.description && - <div class="message-body"> - {n.description} - </div>} - </article> +export function NotificationCard({ + notification: n, +}: NotifProps): VNode | null { + if (!n) return null; + return ( + <div class="notification"> + <div class="columns is-vcentered"> + <div class="column is-12"> + <article + class={ + n.type === "ERROR" + ? "message is-danger" + : n.type === "WARN" + ? "message is-warning" + : "message is-info" + } + > + <div class="message-header"> + <p>{n.message}</p> + </div> + {n.description && <div class="message-body">{n.description}</div>} + </article> + </div> </div> </div> - </div> + ); } -export function NotYetReadyAppMenu({ onLogout, title }: NotYetReadyAppMenuProps): VNode { - const [mobileOpen, setMobileOpen] = useState(false) +export function NotYetReadyAppMenu({ + onLogout, + title, +}: NotYetReadyAppMenuProps): VNode { + const [mobileOpen, setMobileOpen] = useState(false); useEffect(() => { - document.title = `Taler Backoffice: ${title}` - }, [title]) - - return <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() => setMobileOpen(false)}> - <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} title={title} /> - {onLogout && <Sidebar mobile={mobileOpen} />} - </div> - + document.title = `Taler Backoffice: ${title}`; + }, [title]); + + return ( + <div + class="has-aside-mobile-expanded" + // class={mobileOpen ? "has-aside-mobile-expanded" : ""} + onClick={() => setMobileOpen(false)} + > + <NavigationBar + onMobileMenu={() => setMobileOpen(!mobileOpen)} + title={title} + /> + {onLogout && <Sidebar mobile={mobileOpen} />} + </div> + ); } export interface Notification { @@ -99,6 +131,5 @@ export interface Notification { type: MessageType; } -export type ValueOrFunction<T> = T | ((p: T) => T) -export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS' - +export type ValueOrFunction<T> = T | ((p: T) => T); +export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS"; |