diff options
author | Florian Dold <florian@dold.me> | 2021-11-08 16:51:23 +0100 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2021-11-08 16:51:23 +0100 |
commit | 6a0c5263bba435b3ab3a8cda335ceadf7cdd4664 (patch) | |
tree | d043fb1ceef7cbba9f28151a9117460f25706ab4 | |
parent | 16662b194d214fad6ccc244261ed1c02e197a390 (diff) |
anastasis-webui: ui tweaks
5 files changed, 194 insertions, 91 deletions
diff --git a/packages/anastasis-core/src/index.ts b/packages/anastasis-core/src/index.ts index 3be0d7b76..f88e6e8bc 100644 --- a/packages/anastasis-core/src/index.ts +++ b/packages/anastasis-core/src/index.ts @@ -109,13 +109,23 @@ export * from "./challenge-feedback-types.js"; const logger = new Logger("anastasis-core:index.ts"); -function getContinents(): ContinentInfo[] { +function getContinents( + opts: { requireProvider?: boolean } = {}, +): ContinentInfo[] { + const currenciesWithProvider = new Set<string>(); + anastasisData.providersList.anastasis_provider.forEach((x) => { + currenciesWithProvider.add(x.currency); + }); const continentSet = new Set<string>(); const continents: ContinentInfo[] = []; for (const country of anastasisData.countriesList.countries) { if (continentSet.has(country.continent)) { continue; } + if (opts.requireProvider && !currenciesWithProvider.has(country.currency)) { + // Country's currency doesn't have any providers => skip + continue; + } continentSet.add(country.continent); continents.push({ ...{ name_i18n: country.continent_i18n }, @@ -148,9 +158,18 @@ export class ReducerError extends Error { * Get countries for a continent, abort with ReducerError * exception when continent doesn't exist. */ -function getCountries(continent: string): CountryInfo[] { +function getCountries( + continent: string, + opts: { requireProvider?: boolean } = {}, +): CountryInfo[] { + const currenciesWithProvider = new Set<string>(); + anastasisData.providersList.anastasis_provider.forEach((x) => { + currenciesWithProvider.add(x.currency); + }); const countries = anastasisData.countriesList.countries.filter( - (x) => x.continent === continent, + (x) => + x.continent === continent && + (!opts.requireProvider || currenciesWithProvider.has(x.currency)), ); if (countries.length <= 0) { throw new ReducerError({ @@ -164,14 +183,18 @@ function getCountries(continent: string): CountryInfo[] { export async function getBackupStartState(): Promise<ReducerStateBackup> { return { backup_state: BackupStates.ContinentSelecting, - continents: getContinents(), + continents: getContinents({ + requireProvider: true, + }), }; } export async function getRecoveryStartState(): Promise<ReducerStateRecovery> { return { recovery_state: RecoveryStates.ContinentSelecting, - continents: getContinents(), + continents: getContinents({ + requireProvider: true, + }), }; } @@ -1073,7 +1096,9 @@ async function backupSelectContinent( state: ReducerStateBackup, args: ActionArgsSelectContinent, ): Promise<ReducerStateBackup | ReducerStateError> { - const countries = getCountries(args.continent); + const countries = getCountries(args.continent, { + requireProvider: true, + }); if (countries.length <= 0) { return { code: TalerErrorCode.ANASTASIS_REDUCER_INPUT_INVALID, @@ -1092,7 +1117,9 @@ async function recoverySelectContinent( state: ReducerStateRecovery, args: ActionArgsSelectContinent, ): Promise<ReducerStateRecovery | ReducerStateError> { - const countries = getCountries(args.continent); + const countries = getCountries(args.continent, { + requireProvider: true, + }); return { ...state, recovery_state: RecoveryStates.CountrySelecting, diff --git a/packages/anastasis-webui/src/components/menu/NavigationBar.tsx b/packages/anastasis-webui/src/components/menu/NavigationBar.tsx index c07f04ab6..02004c105 100644 --- a/packages/anastasis-webui/src/components/menu/NavigationBar.tsx +++ b/packages/anastasis-webui/src/components/menu/NavigationBar.tsx @@ -15,13 +15,13 @@ */ /** -* -* @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"; +import logo from "../../assets/logo.jpeg"; +import { LangSelector } from "./LangSelector"; interface Props { onMobileMenu: () => void; @@ -29,27 +29,51 @@ 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 "> - <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.li/" + style={{ alignSelf: "center", padding: "0.5em" }} + > + Report a bug + </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 72655662f..a40f4be09 100644 --- a/packages/anastasis-webui/src/components/menu/SideBar.tsx +++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx @@ -44,9 +44,9 @@ export function Sidebar({ mobile }: Props): VNode { </div>} */} <div class="aside-tools"> <div class="aside-tools-label"> - <div><b>Anastasis</b> Reducer</div> + <div><b>Anastasis</b></div> <div class="is-size-7 has-text-right" style={{ lineHeight: 0, marginTop: -10 }}> - {process.env.__VERSION__} ({config.version}) + Version {process.env.__VERSION__} ({config.version}) </div> </div> </div> diff --git a/packages/anastasis-webui/src/components/menu/index.tsx b/packages/anastasis-webui/src/components/menu/index.tsx index febcd79c8..89add9603 100644 --- a/packages/anastasis-webui/src/components/menu/index.tsx +++ b/packages/anastasis-webui/src/components/menu/index.tsx @@ -15,41 +15,53 @@ */ import { ComponentChildren, Fragment, h, VNode } from "preact"; -import Match from 'preact-router/match'; +import Match from "preact-router/match"; import { useEffect, useState } from "preact/hooks"; import { NavigationBar } from "./NavigationBar"; import { Sidebar } from "./SideBar"; - - - 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,56 @@ 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={mobileOpen ? "has-aside-mobile-expanded" : ""} + onClick={() => setMobileOpen(false)} + > + <NavigationBar + onMobileMenu={() => setMobileOpen(!mobileOpen)} + title={title} + /> + {onLogout && <Sidebar mobile={mobileOpen} />} + </div> + ); } export interface Notification { @@ -99,6 +130,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"; diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx index 464950b60..f7731ba00 100644 --- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx @@ -123,13 +123,35 @@ export function ContinentSelectionScreen(): VNode { </div> <div class="column is-two-third"> <p> - Your location will help us to determine which personal information - to ask you for the next step. + Your choice will help us with asking the right information to unique + identify you when you want to recover your backed up secrets. </p> <p> - You should choose the country that issued most of your long-term - legal documents or personal identifiers. + Choose the country that issued most of your long-term legal + documents or personal identifiers. </p> + <div + style={{ + border: "1px solid gray", + borderRadius: "0.5em", + backgroundColor: "#fbfcbd", + padding: "0.5em", + }} + > + <p> + If you just want to try out Anastasis, we recomment that you + choose <b>Testcontinent</b> with <b>Demoland</b>. For this special + country, you will be asked for a simple number and not real, + personal identifiable information. + </p> + {/* + <p> + Because of the diversity of personally identifying information in + different countries and cultures, we do not support all countries + yet. If you want to improve the supported countries,{" "} + <a href="mailto:contact@anastasis.lu">contact us</a>. + </p> */} + </div> </div> </div> </AnastasisClientFrame> |