anastasis-webui: hotfix behavior of back button on country selection screen

This commit is contained in:
Florian Dold 2021-11-08 16:10:22 +01:00
parent 8da58bd494
commit 16662b194d
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
2 changed files with 119 additions and 71 deletions

View File

@ -1,58 +1,81 @@
/* eslint-disable @typescript-eslint/camelcase */
import { BackupStates, RecoveryStates } from "anastasis-core";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useAnastasisContext } from "../../context/anastasis";
import { AnastasisClientFrame, withProcessLabel } from "./index";
export function ContinentSelectionScreen(): VNode {
const reducer = useAnastasisContext()
const reducer = useAnastasisContext();
//FIXME: remove this when #7056 is fixed
const countryFromReducer = (reducer?.currentReducerState as any).selected_country || ""
const [countryCode, setCountryCode] = useState( countryFromReducer )
// FIXME: remove this when #7056 is fixed
const countryFromReducer =
(reducer?.currentReducerState as any).selected_country || "";
const [countryCode, setCountryCode] = useState(countryFromReducer);
if (!reducer || !reducer.currentReducerState || !("continents" in reducer.currentReducerState)) {
return <div />
if (
!reducer ||
!reducer.currentReducerState ||
!("continents" in reducer.currentReducerState)
) {
return <div />;
}
const selectContinent = (continent: string): void => {
reducer.transition("select_continent", { continent })
reducer.transition("select_continent", { continent });
};
const selectCountry = (country: string): void => {
setCountryCode(country)
setCountryCode(country);
};
const continentList = reducer.currentReducerState.continents || [];
const countryList = reducer.currentReducerState.countries || [];
const theContinent = reducer.currentReducerState.selected_continent || ""
const theContinent = reducer.currentReducerState.selected_continent || "";
// const cc = reducer.currentReducerState.selected_country || "";
const theCountry = countryList.find(c => c.code === countryCode)
const theCountry = countryList.find((c) => c.code === countryCode);
const selectCountryAction = () => {
//selection should be when the select box changes it value
if (!theCountry) return;
reducer.transition("select_country", {
country_code: countryCode,
currencies: [theCountry.currency],
})
}
});
};
// const step1 = reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
// reducer.currentReducerState.recovery_state === RecoveryStates.ContinentSelecting;
const errors = !theCountry ? "Select a country" : undefined
const errors = !theCountry ? "Select a country" : undefined;
const handleBack = async () => {
// We want to go to the start, even if we already selected
// a country.
// FIXME: What if we don't want to lose all information here?
// Can we do some kind of soft reset?
reducer.reset();
};
return (
<AnastasisClientFrame hideNext={errors} title={withProcessLabel(reducer, "Where do you live?")} onNext={selectCountryAction}>
<div class="columns" >
<AnastasisClientFrame
hideNext={errors}
title={withProcessLabel(reducer, "Where do you live?")}
onNext={selectCountryAction}
onBack={handleBack}
>
<div class="columns">
<div class="column is-one-third">
<div class="field">
<label class="label">Continent</label>
<div class="control is-expanded has-icons-left">
<div class="select is-fullwidth" >
<select onChange={(e) => selectContinent(e.currentTarget.value)} value={theContinent} >
<option key="none" disabled selected value=""> Choose a continent </option>
{continentList.map(prov => (
<div class="select is-fullwidth">
<select
onChange={(e) => selectContinent(e.currentTarget.value)}
value={theContinent}
>
<option key="none" disabled selected value="">
{" "}
Choose a continent{" "}
</option>
{continentList.map((prov) => (
<option key={prov.name} value={prov.name}>
{prov.name}
</option>
@ -68,10 +91,17 @@ export function ContinentSelectionScreen(): VNode {
<div class="field">
<label class="label">Country</label>
<div class="control is-expanded has-icons-left">
<div class="select is-fullwidth" >
<select onChange={(e) => selectCountry((e.target as any).value)} disabled={!theContinent} value={theCountry?.code || ""}>
<option key="none" disabled selected value=""> Choose a country </option>
{countryList.map(prov => (
<div class="select is-fullwidth">
<select
onChange={(e) => selectCountry((e.target as any).value)}
disabled={!theContinent}
value={theCountry?.code || ""}
>
<option key="none" disabled selected value="">
{" "}
Choose a country{" "}
</option>
{countryList.map((prov) => (
<option key={prov.name} value={prov.code}>
{prov.name}
</option>
@ -93,12 +123,15 @@ export function ContinentSelectionScreen(): VNode {
</div>
<div class="column is-two-third">
<p>
Your location will help us to determine which personal information
ask you for the next step.
Your location will help us to determine which personal information
to ask you for the next step.
</p>
<p>
You should choose the country that issued most of your long-term
legal documents or personal identifiers.
</p>
</div>
</div>
</AnastasisClientFrame>
);
}

View File

@ -1,23 +1,22 @@
import { BackupStates, RecoveryStates } from "anastasis-core";
import {
BackupStates,
RecoveryStates
} from "anastasis-core";
import {
ComponentChildren, Fragment,
ComponentChildren,
Fragment,
FunctionalComponent,
h,
VNode
VNode,
} from "preact";
import {
useErrorBoundary
} from "preact/hooks";
import { useErrorBoundary } from "preact/hooks";
import { AsyncButton } from "../../components/AsyncButton";
import { Menu } from "../../components/menu";
import { Notifications } from "../../components/Notifications";
import { AnastasisProvider, useAnastasisContext } from "../../context/anastasis";
import {
AnastasisProvider,
useAnastasisContext,
} from "../../context/anastasis";
import {
AnastasisReducerApi,
useAnastasisReducer
useAnastasisReducer,
} from "../../hooks/use-anastasis-reducer";
import { AttributeEntryScreen } from "./AttributeEntryScreen";
import { AuthenticationEditorScreen } from "./AuthenticationEditorScreen";
@ -50,6 +49,10 @@ export function withProcessLabel(
interface AnastasisClientFrameProps {
onNext?(): void;
/**
* Override for the "back" functionality.
*/
onBack?(): Promise<void>;
title: string;
children: ComponentChildren;
/**
@ -116,9 +119,27 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
<section class="section is-main-section">
{props.children}
{!props.hideNav ? (
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
<button class="button" onClick={() => reducer.back()}>Back</button>
<AsyncButton class="button is-info" data-tooltip={props.hideNext} onClick={next} disabled={props.hideNext !== undefined}>Next</AsyncButton>
<div
style={{
marginTop: "2em",
display: "flex",
justifyContent: "space-between",
}}
>
<button
class="button"
onClick={() => (props.onBack ?? reducer.back)()}
>
Back
</button>
<AsyncButton
class="button is-info"
data-tooltip={props.hideNext}
onClick={next}
disabled={props.hideNext !== undefined}
>
Next
</AsyncButton>
</div>
) : null}
</section>
@ -139,7 +160,7 @@ const AnastasisClient: FunctionalComponent = () => {
};
function AnastasisClientImpl(): VNode {
const reducer = useAnastasisContext()
const reducer = useAnastasisContext();
if (!reducer) {
return <p>Fatal: Reducer must be in context.</p>;
}
@ -155,27 +176,19 @@ function AnastasisClientImpl(): VNode {
state.backup_state === BackupStates.CountrySelecting ||
state.recovery_state === RecoveryStates.CountrySelecting
) {
return (
<ContinentSelectionScreen />
);
return <ContinentSelectionScreen />;
}
if (
state.backup_state === BackupStates.UserAttributesCollecting ||
state.recovery_state === RecoveryStates.UserAttributesCollecting
) {
return (
<AttributeEntryScreen />
);
return <AttributeEntryScreen />;
}
if (state.backup_state === BackupStates.AuthenticationsEditing) {
return (
<AuthenticationEditorScreen />
);
return <AuthenticationEditorScreen />;
}
if (state.backup_state === BackupStates.PoliciesReviewing) {
return (
<ReviewPoliciesScreen />
);
return <ReviewPoliciesScreen />;
}
if (state.backup_state === BackupStates.SecretEditing) {
return <SecretEditorScreen />;
@ -194,15 +207,11 @@ function AnastasisClientImpl(): VNode {
}
if (state.recovery_state === RecoveryStates.SecretSelecting) {
return (
<SecretSelectionScreen />
);
return <SecretSelectionScreen />;
}
if (state.recovery_state === RecoveryStates.ChallengeSelecting) {
return (
<ChallengeOverviewScreen />
);
return <ChallengeOverviewScreen />;
}
if (state.recovery_state === RecoveryStates.ChallengeSolving) {
@ -210,9 +219,7 @@ function AnastasisClientImpl(): VNode {
}
if (state.recovery_state === RecoveryStates.RecoveryFinished) {
return (
<RecoveryFinishedScreen />
);
return <RecoveryFinishedScreen />;
}
if (state.recovery_state === RecoveryStates.ChallengePaying) {
return <ChallengePayingScreen />;
@ -222,7 +229,9 @@ function AnastasisClientImpl(): VNode {
<AnastasisClientFrame hideNav title="Bug">
<p>Bug: Unknown state.</p>
<div class="buttons is-right">
<button class="button" onClick={() => reducer.reset()}>Reset</button>
<button class="button" onClick={() => reducer.reset()}>
Reset
</button>
</div>
</AnastasisClientFrame>
);
@ -234,11 +243,17 @@ function AnastasisClientImpl(): VNode {
function ErrorBanner(): VNode | null {
const reducer = useAnastasisContext();
if (!reducer || !reducer.currentError) return null;
return (<Notifications removeNotification={reducer.dismissError} notifications={[{
type: "ERROR",
message: `Error code: ${reducer.currentError.code}`,
description: reducer.currentError.hint
}]} />
return (
<Notifications
removeNotification={reducer.dismissError}
notifications={[
{
type: "ERROR",
message: `Error code: ${reducer.currentError.code}`,
description: reducer.currentError.hint,
},
]}
/>
);
}