From 2ec2161a7e1c0787b5e9ea14311f19c6b6a52d63 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 22 Oct 2021 01:31:46 -0300 Subject: some storybook exmaples --- .../src/components/menu/SideBar.tsx | 164 +++++++++++++++------ packages/anastasis-webui/src/context/anastasis.ts | 41 ++++++ .../pages/home/AttributeEntryScreen.stories.tsx | 63 ++++++++ .../src/pages/home/AttributeEntryScreen.tsx | 25 +++- .../home/AuthenticationEditorScreen.stories.tsx | 35 +++++ .../src/pages/home/AuthenticationEditorScreen.tsx | 19 ++- .../pages/home/BackupFinishedScreen.stories.tsx | 60 ++++++++ .../src/pages/home/BackupFinishedScreen.tsx | 26 +++- .../pages/home/ChallengeOverviewScreen.stories.tsx | 83 +++++++++++ .../src/pages/home/ChallengeOverviewScreen.tsx | 39 +++-- .../home/ContinentSelectionScreen.stories.tsx | 36 +++++ .../src/pages/home/ContinentSelectionScreen.tsx | 17 ++- .../pages/home/CountrySelectionScreen.stories.tsx | 36 +++++ .../src/pages/home/CountrySelectionScreen.tsx | 20 ++- .../pages/home/PoliciesPayingScreen.stories.tsx | 47 ++++++ .../src/pages/home/PoliciesPayingScreen.tsx | 18 ++- .../pages/home/RecoveryFinishedScreen.stories.tsx | 42 ++++++ .../src/pages/home/RecoveryFinishedScreen.tsx | 24 ++- .../pages/home/ReviewPoliciesScreen.stories.tsx | 81 ++++++++++ .../src/pages/home/ReviewPoliciesScreen.tsx | 42 ++++-- .../src/pages/home/SecretEditorScreen.stories.tsx | 44 ++++++ .../src/pages/home/SecretEditorScreen.tsx | 25 +++- .../pages/home/SecretSelectionScreen.stories.tsx | 50 +++++++ .../src/pages/home/SecretSelectionScreen.tsx | 37 ++++- .../src/pages/home/SolveEmailEntry.tsx | 13 +- .../src/pages/home/SolvePostEntry.tsx | 11 +- .../src/pages/home/SolveQuestionEntry.tsx | 11 +- .../src/pages/home/SolveScreen.stories.tsx | 121 +++++++++++++++ .../anastasis-webui/src/pages/home/SolveScreen.tsx | 32 ++-- .../src/pages/home/SolveSmsEntry.tsx | 13 +- .../src/pages/home/StartScreen.stories.tsx | 35 +++++ .../anastasis-webui/src/pages/home/StartScreen.tsx | 32 +++- .../src/pages/home/TruthsPayingScreen.stories.tsx | 40 +++++ .../src/pages/home/TruthsPayingScreen.tsx | 16 +- packages/anastasis-webui/src/pages/home/index.tsx | 162 +++++++++----------- packages/anastasis-webui/src/utils/index.tsx | 161 ++++++++++++++++++++ 36 files changed, 1452 insertions(+), 269 deletions(-) create mode 100644 packages/anastasis-webui/src/context/anastasis.ts create mode 100644 packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/StartScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/TruthsPayingScreen.stories.tsx create mode 100644 packages/anastasis-webui/src/utils/index.tsx (limited to 'packages/anastasis-webui/src') diff --git a/packages/anastasis-webui/src/components/menu/SideBar.tsx b/packages/anastasis-webui/src/components/menu/SideBar.tsx index 628adb571..df582a5d0 100644 --- a/packages/anastasis-webui/src/components/menu/SideBar.tsx +++ b/packages/anastasis-webui/src/components/menu/SideBar.tsx @@ -20,7 +20,9 @@ */ -import { h, VNode } from 'preact'; +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'; @@ -31,8 +33,9 @@ interface Props { export function Sidebar({ mobile }: Props): VNode { // const config = useConfigContext(); const config = { version: 'none' } - const process = { env : { __VERSION__: '0.0.0'}} - + const process = { env: { __VERSION__: '0.0.0' } } + const reducer = useAnastasisContext()! + return ( diff --git a/packages/anastasis-webui/src/context/anastasis.ts b/packages/anastasis-webui/src/context/anastasis.ts new file mode 100644 index 000000000..e7f93ed43 --- /dev/null +++ b/packages/anastasis-webui/src/context/anastasis.ts @@ -0,0 +1,41 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createContext, h, VNode } from 'preact'; +import { useContext } from 'preact/hooks'; +import { AnastasisReducerApi } from '../hooks/use-anastasis-reducer'; + +type Type = AnastasisReducerApi | undefined; + +const initial = undefined + +const Context = createContext(initial) + +interface Props { + value: AnastasisReducerApi; + children: any; +} + +export const AnastasisProvider = ({ value, children }: Props): VNode => { + return h(Context.Provider, { value, children }); +} + +export const useAnastasisContext = (): Type => useContext(Context); \ No newline at end of file diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx new file mode 100644 index 000000000..d28a6df43 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.stories.tsx @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { AttributeEntryScreen as TestedComponent } from './AttributeEntryScreen'; + + +export default { + title: 'Pages/AttributeEntryScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const WithSomeAttributes = createExample(TestedComponent, { + ...reducerStatesExample.attributeEditing, + required_attributes: [{ + name: 'first', + label: 'first', + type: 'type', + uuid: 'asdasdsa1', + widget: 'wid', + }, { + name: 'pepe', + label: 'second', + type: 'type', + uuid: 'asdasdsa2', + widget: 'wid', + }, { + name: 'pepe2', + label: 'third', + type: 'type', + uuid: 'asdasdsa3', + widget: 'calendar', + }] +} as ReducerState); + +export const Empty = createExample(TestedComponent, { + ...reducerStatesExample.attributeEditing, + required_attributes: undefined +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx index 6f87a3358..2f804f940 100644 --- a/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AttributeEntryScreen.tsx @@ -1,15 +1,24 @@ /* eslint-disable @typescript-eslint/camelcase */ import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import { ReducerStateRecovery, ReducerStateBackup } from "../../../../anastasis-core/lib"; +import { ReducerStateRecovery, ReducerStateBackup, UserAttributeSpec } from "anastasis-core/lib"; +import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer"; import { AnastasisClientFrame, withProcessLabel, LabeledInput } from "./index"; -export function AttributeEntryScreen(props: AttributeEntryProps): VNode { - const { reducer, reducerState: backupState } = props; - const [attrs, setAttrs] = useState>( - props.reducerState.identity_attributes ?? {} - ); +export function AttributeEntryScreen(): VNode { + const reducer = useAnastasisContext() + const state = reducer?.currentReducerState + const currentIdentityAttributes = state && "identity_attributes" in state ? (state.identity_attributes || {}) : {} + const [attrs, setAttrs] = useState>(currentIdentityAttributes); + + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || !("required_attributes" in reducer.currentReducerState)) { + return
invalid state
+ } + return ( - {backupState.required_attributes.map((x: any, i: number) => { + {reducer.currentReducerState.required_attributes?.map((x, i: number) => { return ( void; - spec: any; + spec: UserAttributeSpec; } export function AttributeEntryField(props: AttributeEntryFieldProps): VNode { diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx new file mode 100644 index 000000000..44d3795b2 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.stories.tsx @@ -0,0 +1,35 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../utils'; +import { AuthenticationEditorScreen as TestedComponent } from './AuthenticationEditorScreen'; + + +export default { + title: 'Pages/AuthenticationEditorScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Example = createExample(TestedComponent, reducerStatesExample.authEditing); diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx index fc28942aa..e9ffccbac 100644 --- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx @@ -1,7 +1,8 @@ /* eslint-disable @typescript-eslint/camelcase */ +import { AuthMethod, ReducerStateBackup } from "anastasis-core"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import { AuthMethod, ReducerStateBackup } from "anastasis-core"; +import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisReducerApi } from "../../hooks/use-anastasis-reducer"; import { AuthMethodEmailSetup } from "./AuthMethodEmailSetup"; import { AuthMethodPostSetup } from "./AuthMethodPostSetup"; @@ -9,12 +10,18 @@ import { AuthMethodQuestionSetup } from "./AuthMethodQuestionSetup"; import { AuthMethodSmsSetup } from "./AuthMethodSmsSetup"; import { AnastasisClientFrame } from "./index"; -export function AuthenticationEditorScreen(props: AuthenticationEditorProps): VNode { +export function AuthenticationEditorScreen(): VNode { const [selectedMethod, setSelectedMethod] = useState( undefined ); - const { reducer, backupState } = props; - const providers = backupState.authentication_providers!; + const reducer = useAnastasisContext() + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { + return
invalid state
+ } + const providers = reducer.currentReducerState.authentication_providers!; const authAvailableSet = new Set(); for (const provKey of Object.keys(providers)) { const p = providers[provKey]; @@ -52,14 +59,14 @@ export function AuthenticationEditorScreen(props: AuthenticationEditorProps): VN disabled={!authAvailableSet.has(props.method)} onClick={() => { setSelectedMethod(props.method); - reducer.dismissError(); + if (reducer) reducer.dismissError(); }} > {props.label} ); } - const configuredAuthMethods: AuthMethod[] = backupState.authentication_methods ?? []; + const configuredAuthMethods: AuthMethod[] = reducer.currentReducerState.authentication_methods ?? []; const haveMethodsConfigured = configuredAuthMethods.length; return ( diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx new file mode 100644 index 000000000..65a2b7e13 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.stories.tsx @@ -0,0 +1,60 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { BackupFinishedScreen as TestedComponent } from './BackupFinishedScreen'; + + +export default { + title: 'Pages/BackupFinishedScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Simple = createExample(TestedComponent, reducerStatesExample.backupFinished); + +export const WithName = createExample(TestedComponent, {...reducerStatesExample.backupFinished, + secret_name: 'super_secret', +} as ReducerState); + +export const WithDetails = createExample(TestedComponent, { + ...reducerStatesExample.backupFinished, + secret_name: 'super_secret', + success_details: { + 'http://anastasis.net': { + policy_expiration: { + t_ms: 'never' + }, + policy_version: 0 + }, + 'http://taler.net': { + policy_expiration: { + t_ms: new Date().getTime() + 60*60*24*1000 + }, + policy_version: 1 + }, + } +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx index 6c2770947..218f1d1fd 100644 --- a/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/BackupFinishedScreen.tsx @@ -1,23 +1,33 @@ import { h, VNode } from "preact"; -import { BackupReducerProps, AnastasisClientFrame } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; -export function BackupFinishedScreen(props: BackupReducerProps): VNode { +export function BackupFinishedScreen(): VNode { + const reducer = useAnastasisContext() + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { + return
invalid state
+ } + const details = reducer.currentReducerState.success_details return (

- Your backup of secret "{props.backupState.secret_name ?? "??"}" was + Your backup of secret "{reducer.currentReducerState.secret_name ?? "??"}" was successful.

The backup is stored by the following providers:

-
    - {Object.keys(props.backupState.success_details!).map((x, i) => { - const sd = props.backupState.success_details![x]; + + {details &&
      + {Object.keys(details).map((x, i) => { + const sd = details[x]; return (
    • {x} (Policy version {sd.policy_version})
    • ); })} -
    - +
} +
); } diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx new file mode 100644 index 000000000..4f186c031 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx @@ -0,0 +1,83 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { ChallengeOverviewScreen as TestedComponent } from './ChallengeOverviewScreen'; + + +export default { + title: 'Pages/ChallengeOverviewScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const OneChallenge = createExample(TestedComponent, {...reducerStatesExample.challengeSelecting, + recovery_information: { + policies: [[{uuid:'1'}]], + challenges: [{ + cost: 'USD:1', + instructions: 'just go for it', + type: 'question', + uuid: '1', + }] + }, +} as ReducerState); + +export const MoreChallenges = createExample(TestedComponent, {...reducerStatesExample.challengeSelecting, + recovery_information: { + policies: [[{uuid:'1'}, {uuid:'2'}],[{uuid:'3'}]], + challenges: [{ + cost: 'USD:1', + instructions: 'just go for it', + type: 'question', + uuid: '1', + },{ + cost: 'USD:1', + instructions: 'just go for it', + type: 'question', + uuid: '2', + },{ + cost: 'USD:1', + instructions: 'just go for it', + type: 'question', + uuid: '3', + }] + }, +} as ReducerState); + +export const OneBadConfiguredPolicy = createExample(TestedComponent, {...reducerStatesExample.challengeSelecting, + recovery_information: { + policies: [[{uuid:'2'}]], + challenges: [{ + cost: 'USD:1', + instructions: 'just go for it', + type: 'sasd', + uuid: '1', + }] + }, +} as ReducerState); + +export const NoPolicies = createExample(TestedComponent, reducerStatesExample.challengeSelecting); diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx index 1f108ce6d..c9b52e91b 100644 --- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx @@ -1,10 +1,21 @@ import { h, VNode } from "preact"; -import { RecoveryReducerProps, AnastasisClientFrame } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; + +export function ChallengeOverviewScreen(): VNode { + const reducer = useAnastasisContext() + + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) { + return
invalid state
+ } + + const policies = reducer.currentReducerState.recovery_information?.policies ?? []; + const chArr = reducer.currentReducerState.recovery_information?.challenges ?? []; + const challengeFeedback = reducer.currentReducerState?.challenge_feedback; -export function ChallengeOverviewScreen(props: RecoveryReducerProps): VNode { - const { recoveryState, reducer } = props; - const policies = recoveryState.recovery_information!.policies; - const chArr = recoveryState.recovery_information!.challenges; const challenges: { [uuid: string]: { type: string; @@ -22,15 +33,21 @@ export function ChallengeOverviewScreen(props: RecoveryReducerProps): VNode { return (

Policies

- {policies.map((x, i) => { + {!policies.length &&

+ No policies found +

} + {policies.map((row, i) => { return (

Policy #{i + 1}

- {x.map((x, j) => { - const ch = challenges[x.uuid]; - const feedback = recoveryState.challenge_feedback?.[x.uuid]; + {row.map(column => { + const ch = challenges[column.uuid]; + if (!ch) return
+ There is no challenge for this policy +
+ const feedback = challengeFeedback?.[column.uuid]; return ( -
reducer.transition("select_challenge", { - uuid: x.uuid, + uuid: column.uuid, })} > Solve diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx new file mode 100644 index 000000000..aad37cd7f --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.stories.tsx @@ -0,0 +1,36 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../utils'; +import { ContinentSelectionScreen as TestedComponent } from './ContinentSelectionScreen'; + + +export default { + title: 'Pages/ContinentSelectionScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Backup = createExample(TestedComponent, reducerStatesExample.backupSelectCountry); +export const Recovery = createExample(TestedComponent, reducerStatesExample.recoverySelectCountry); diff --git a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx index 2fed23d4e..ad529a4a7 100644 --- a/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ContinentSelectionScreen.tsx @@ -1,15 +1,16 @@ import { h, VNode } from "preact"; -import { CommonReducerProps, AnastasisClientFrame, withProcessLabel } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame, withProcessLabel } from "./index"; -export function ContinentSelectionScreen(props: CommonReducerProps): VNode { - const { reducer, reducerState } = props; +export function ContinentSelectionScreen(): VNode { + const reducer = useAnastasisContext() + if (!reducer || !reducer.currentReducerState || !("continents" in reducer.currentReducerState)) { + return
+ } const sel = (x: string): void => reducer.transition("select_continent", { continent: x }); return ( - - {reducerState.continents.map((x: any) => ( + + {reducer.currentReducerState.continents.map((x: any) => ( diff --git a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx new file mode 100644 index 000000000..adf36980f --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.stories.tsx @@ -0,0 +1,36 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { createExample, reducerStatesExample } from '../../utils'; +import { CountrySelectionScreen as TestedComponent } from './CountrySelectionScreen'; + + +export default { + title: 'Pages/CountrySelectionScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Backup = createExample(TestedComponent, reducerStatesExample.backupSelectCountry); +export const Recovery = createExample(TestedComponent, reducerStatesExample.recoverySelectCountry); diff --git a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx index dbe4b7616..555622c1d 100644 --- a/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/CountrySelectionScreen.tsx @@ -1,19 +1,23 @@ /* eslint-disable @typescript-eslint/camelcase */ import { h, VNode } from "preact"; -import { CommonReducerProps, AnastasisClientFrame, withProcessLabel } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame, withProcessLabel } from "./index"; -export function CountrySelectionScreen(props: CommonReducerProps): VNode { - const { reducer, reducerState } = props; +export function CountrySelectionScreen(): VNode { + const reducer = useAnastasisContext() + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || !("countries" in reducer.currentReducerState)) { + return
invalid state
+ } const sel = (x: any): void => reducer.transition("select_country", { country_code: x.code, currencies: [x.currency], }); return ( - - {reducerState.countries.map((x: any) => ( + + {reducer.currentReducerState.countries.map((x: any) => ( diff --git a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx new file mode 100644 index 000000000..1a9462b88 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.stories.tsx @@ -0,0 +1,47 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { PoliciesPayingScreen as TestedComponent } from './PoliciesPayingScreen'; + + +export default { + title: 'Pages/PoliciesPayingScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Example = createExample(TestedComponent, reducerStatesExample.policyPay); +export const WithSomePaymentRequest = createExample(TestedComponent, { + ...reducerStatesExample.policyPay, + policy_payment_requests: [{ + payto: 'payto://x-taler-bank/bank.taler/account-a', + provider: 'provider1' + }, { + payto: 'payto://x-taler-bank/bank.taler/account-b', + provider: 'provider2' + }] +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx index be74729eb..8a39cf0e4 100644 --- a/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/PoliciesPayingScreen.tsx @@ -1,9 +1,17 @@ import { h, VNode } from "preact"; -import { BackupReducerProps, AnastasisClientFrame } from "./index"; - -export function PoliciesPayingScreen(props: BackupReducerProps): VNode { - const payments = props.backupState.policy_payment_requests ?? []; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; +export function PoliciesPayingScreen(): VNode { + const reducer = useAnastasisContext() + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { + return
invalid state
+ } + const payments = reducer.currentReducerState.policy_payment_requests ?? []; + return (

@@ -19,7 +27,7 @@ export function PoliciesPayingScreen(props: BackupReducerProps): VNode { ); })} - diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx new file mode 100644 index 000000000..0c1842420 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.stories.tsx @@ -0,0 +1,42 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { RecoveryFinishedScreen as TestedComponent } from './RecoveryFinishedScreen'; + + +export default { + title: 'Pages/RecoveryFinishedScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const NormalEnding = createExample(TestedComponent, { + ...reducerStatesExample.recoveryFinished, + core_secret: { mime: 'text/plain', value: 'hello' } +} as ReducerState); + +export const BadEnding = createExample(TestedComponent, reducerStatesExample.recoveryFinished); diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx index 7ccc511ff..8c8a2c7c8 100644 --- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx @@ -3,13 +3,31 @@ import { decodeCrock } from "@gnu-taler/taler-util"; import { h, VNode } from "preact"; -import { RecoveryReducerProps, AnastasisClientFrame } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; -export function RecoveryFinishedScreen(props: RecoveryReducerProps): VNode { +export function RecoveryFinishedScreen(): VNode { + const reducer = useAnastasisContext() + + if (!reducer) { + return

no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) { + return
invalid state
+ } + const encodedSecret = reducer.currentReducerState.core_secret?.value + if (!encodedSecret) { + return +

+ Secret not found +

+
+ } + const secret = bytesToString(decodeCrock(encodedSecret)) return (

- Secret: {bytesToString(decodeCrock(props.recoveryState.core_secret?.value!))} + Secret: {secret}

); diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx new file mode 100644 index 000000000..b52699e7b --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.stories.tsx @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { ReviewPoliciesScreen as TestedComponent } from './ReviewPoliciesScreen'; + + +export default { + title: 'Pages/ReviewPoliciesScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const HasPoliciesButMethodListIsEmpty = createExample(TestedComponent, { + ...reducerStatesExample.policyReview, + policies: [{ + methods: [{ + authentication_method: 0, + provider: 'asd' + },{ + authentication_method: 1, + provider: 'asd' + }] + },{ + methods: [{ + authentication_method: 1, + provider: 'asd' + }] + }], + authentication_methods: [] +} as ReducerState); + +export const SomePoliciesWithMethods = createExample(TestedComponent, { + ...reducerStatesExample.policyReview, + policies: [{ + methods: [{ + authentication_method: 0, + provider: 'asd' + },{ + authentication_method: 1, + provider: 'asd' + }] + },{ + methods: [{ + authentication_method: 1, + provider: 'asd' + }] + }], + authentication_methods: [{ + challenge: 'asd', + instructions: 'ins', + type: 'type', + },{ + challenge: 'asd2', + instructions: 'ins2', + type: 'type2', + }] +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx index 3e20538d2..b360ccaf0 100644 --- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx @@ -1,35 +1,49 @@ /* eslint-disable @typescript-eslint/camelcase */ import { h, VNode } from "preact"; -import { BackupReducerProps, AnastasisClientFrame } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; + +export function ReviewPoliciesScreen(): VNode { + const reducer = useAnastasisContext() + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { + return
invalid state
+ } + const authMethods = reducer.currentReducerState.authentication_methods ?? []; + const policies = reducer.currentReducerState.policies ?? []; -export function ReviewPoliciesScreen(props: BackupReducerProps): VNode { - const { reducer, backupState } = props; - const authMethods = backupState.authentication_methods!; return ( - {backupState.policies?.map((p, i) => { - const policyName = p.methods - .map((x, i) => authMethods[x.authentication_method].type) - .join(" + "); + {policies.map((p, policy_index) => { + const methods = p.methods + .map(x => authMethods[x.authentication_method] && ({ ...authMethods[x.authentication_method], provider: x.provider })) + .filter(x => !!x) + + const policyName = methods.map(x => x.type).join(" + "); + return ( -
+

- Policy #{i + 1}: {policyName} + Policy #{policy_index + 1}: {policyName}

Required Authentications: + {!methods.length &&

+ No auth method found +

}
    - {p.methods.map((x, i) => { - const m = authMethods[x.authentication_method]; + {methods.map((m, i) => { return (
  • - {m.type} ({m.instructions}) at provider {x.provider} + {m.type} ({m.instructions}) at provider {m.provider}
  • ); })}
diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx new file mode 100644 index 000000000..18560356a --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.stories.tsx @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { SecretEditorScreen as TestedComponent } from './SecretEditorScreen'; + + +export default { + title: 'Pages/SecretEditorScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const WithSecretNamePreselected = createExample(TestedComponent, { + ...reducerStatesExample.secretEdition, + secret_name: 'someSecretName', +} as ReducerState); + +export const WithoutName = createExample(TestedComponent, { + ...reducerStatesExample.secretEdition, +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx index 086d4921d..a5235d66c 100644 --- a/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SecretEditorScreen.tsx @@ -2,18 +2,29 @@ import { encodeCrock, stringToBytes } from "@gnu-taler/taler-util"; import { h, VNode } from "preact"; import { useState } from "preact/hooks"; +import { useAnastasisContext } from "../../context/anastasis"; import { - BackupReducerProps, AnastasisClientFrame, - LabeledInput, + LabeledInput } from "./index"; -export function SecretEditorScreen(props: BackupReducerProps): VNode { - const { reducer } = props; - const [secretName, setSecretName] = useState( - props.backupState.secret_name ?? "", - ); +export function SecretEditorScreen(): VNode { + const reducer = useAnastasisContext() const [secretValue, setSecretValue] = useState(""); + + const currentSecretName = reducer?.currentReducerState + && ("secret_name" in reducer.currentReducerState) + && reducer.currentReducerState.secret_name; + + const [secretName, setSecretName] = useState(currentSecretName || ""); + + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.backup_state === undefined) { + return
invalid state
+ } + const secretNext = (): void => { reducer.runTransaction(async (tx) => { await tx.transition("enter_secret_name", { diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx new file mode 100644 index 000000000..e9c597023 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.stories.tsx @@ -0,0 +1,50 @@ +/* eslint-disable @typescript-eslint/camelcase */ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { ReducerState } from 'anastasis-core'; +import { createExample, reducerStatesExample } from '../../utils'; +import { SecretSelectionScreen as TestedComponent } from './SecretSelectionScreen'; + + +export default { + title: 'Pages/SecretSelectionScreen', + component: TestedComponent, + argTypes: { + onUpdate: { action: 'onUpdate' }, + onBack: { action: 'onBack' }, + }, +}; + +export const Example = createExample(TestedComponent, { + ...reducerStatesExample.secretSelection, + recovery_document: { + provider_url: 'http://anastasis.url/', + secret_name: 'secretName', + version: 1, + }, +} as ReducerState); + + +export const NoRecoveryDocumentFound = createExample(TestedComponent, { + ...reducerStatesExample.secretSelection, + recovery_document: undefined, +} as ReducerState); diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx index 7cb7fdf20..903f57868 100644 --- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx @@ -1,17 +1,29 @@ /* eslint-disable @typescript-eslint/camelcase */ import { h, VNode } from "preact"; import { useState } from "preact/hooks"; -import { RecoveryReducerProps, AnastasisClientFrame } from "./index"; +import { useAnastasisContext } from "../../context/anastasis"; +import { AnastasisClientFrame } from "./index"; -export function SecretSelectionScreen(props: RecoveryReducerProps): VNode { - const { reducer, recoveryState } = props; +export function SecretSelectionScreen(): VNode { const [selectingVersion, setSelectingVersion] = useState(false); - const [otherVersion, setOtherVersion] = useState( - recoveryState.recovery_document?.version ?? 0 - ); - const recoveryDocument = recoveryState.recovery_document!; const [otherProvider, setOtherProvider] = useState(""); + const reducer = useAnastasisContext() + + const currentVersion = reducer?.currentReducerState + && ("recovery_document" in reducer.currentReducerState) + && reducer.currentReducerState.recovery_document?.version; + + const [otherVersion, setOtherVersion] = useState(currentVersion || 0); + + if (!reducer) { + return
no reducer in context
+ } + if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) { + return
invalid state
+ } + function selectVersion(p: string, n: number): void { + if (!reducer) return; reducer.runTransaction(async (tx) => { await tx.transition("change_version", { version: n, @@ -20,12 +32,21 @@ export function SecretSelectionScreen(props: RecoveryReducerProps): VNode { setSelectingVersion(false); }); } + + const recoveryDocument = reducer.currentReducerState.recovery_document + if (!recoveryDocument) { + return ( + +

No recovery document found

+
+ ) + } if (selectingVersion) { return (

Select a different version of the secret