anastasis-webui: hotfix behavior of back button on country selection screen
This commit is contained in:
parent
8da58bd494
commit
16662b194d
@ -1,58 +1,81 @@
|
|||||||
/* eslint-disable @typescript-eslint/camelcase */
|
/* eslint-disable @typescript-eslint/camelcase */
|
||||||
|
import { BackupStates, RecoveryStates } from "anastasis-core";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { AnastasisClientFrame, withProcessLabel } from "./index";
|
import { AnastasisClientFrame, withProcessLabel } from "./index";
|
||||||
|
|
||||||
export function ContinentSelectionScreen(): VNode {
|
export function ContinentSelectionScreen(): VNode {
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext();
|
||||||
|
|
||||||
//FIXME: remove this when #7056 is fixed
|
// FIXME: remove this when #7056 is fixed
|
||||||
const countryFromReducer = (reducer?.currentReducerState as any).selected_country || ""
|
const countryFromReducer =
|
||||||
const [countryCode, setCountryCode] = useState( countryFromReducer )
|
(reducer?.currentReducerState as any).selected_country || "";
|
||||||
|
const [countryCode, setCountryCode] = useState(countryFromReducer);
|
||||||
|
|
||||||
if (!reducer || !reducer.currentReducerState || !("continents" in reducer.currentReducerState)) {
|
if (
|
||||||
return <div />
|
!reducer ||
|
||||||
|
!reducer.currentReducerState ||
|
||||||
|
!("continents" in reducer.currentReducerState)
|
||||||
|
) {
|
||||||
|
return <div />;
|
||||||
}
|
}
|
||||||
const selectContinent = (continent: string): void => {
|
const selectContinent = (continent: string): void => {
|
||||||
reducer.transition("select_continent", { continent })
|
reducer.transition("select_continent", { continent });
|
||||||
};
|
};
|
||||||
const selectCountry = (country: string): void => {
|
const selectCountry = (country: string): void => {
|
||||||
setCountryCode(country)
|
setCountryCode(country);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const continentList = reducer.currentReducerState.continents || [];
|
const continentList = reducer.currentReducerState.continents || [];
|
||||||
const countryList = reducer.currentReducerState.countries || [];
|
const countryList = reducer.currentReducerState.countries || [];
|
||||||
const theContinent = reducer.currentReducerState.selected_continent || ""
|
const theContinent = reducer.currentReducerState.selected_continent || "";
|
||||||
// const cc = reducer.currentReducerState.selected_country || "";
|
// const cc = reducer.currentReducerState.selected_country || "";
|
||||||
const theCountry = countryList.find(c => c.code === countryCode)
|
const theCountry = countryList.find((c) => c.code === countryCode);
|
||||||
const selectCountryAction = () => {
|
const selectCountryAction = () => {
|
||||||
//selection should be when the select box changes it value
|
//selection should be when the select box changes it value
|
||||||
if (!theCountry) return;
|
if (!theCountry) return;
|
||||||
reducer.transition("select_country", {
|
reducer.transition("select_country", {
|
||||||
country_code: countryCode,
|
country_code: countryCode,
|
||||||
currencies: [theCountry.currency],
|
currencies: [theCountry.currency],
|
||||||
})
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// const step1 = reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
|
// const step1 = reducer.currentReducerState.backup_state === BackupStates.ContinentSelecting ||
|
||||||
// reducer.currentReducerState.recovery_state === RecoveryStates.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 (
|
return (
|
||||||
<AnastasisClientFrame hideNext={errors} title={withProcessLabel(reducer, "Where do you live?")} onNext={selectCountryAction}>
|
<AnastasisClientFrame
|
||||||
|
hideNext={errors}
|
||||||
<div class="columns" >
|
title={withProcessLabel(reducer, "Where do you live?")}
|
||||||
|
onNext={selectCountryAction}
|
||||||
|
onBack={handleBack}
|
||||||
|
>
|
||||||
|
<div class="columns">
|
||||||
<div class="column is-one-third">
|
<div class="column is-one-third">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Continent</label>
|
<label class="label">Continent</label>
|
||||||
<div class="control is-expanded has-icons-left">
|
<div class="control is-expanded has-icons-left">
|
||||||
<div class="select is-fullwidth" >
|
<div class="select is-fullwidth">
|
||||||
<select onChange={(e) => selectContinent(e.currentTarget.value)} value={theContinent} >
|
<select
|
||||||
<option key="none" disabled selected value=""> Choose a continent </option>
|
onChange={(e) => selectContinent(e.currentTarget.value)}
|
||||||
{continentList.map(prov => (
|
value={theContinent}
|
||||||
|
>
|
||||||
|
<option key="none" disabled selected value="">
|
||||||
|
{" "}
|
||||||
|
Choose a continent{" "}
|
||||||
|
</option>
|
||||||
|
{continentList.map((prov) => (
|
||||||
<option key={prov.name} value={prov.name}>
|
<option key={prov.name} value={prov.name}>
|
||||||
{prov.name}
|
{prov.name}
|
||||||
</option>
|
</option>
|
||||||
@ -68,10 +91,17 @@ export function ContinentSelectionScreen(): VNode {
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Country</label>
|
<label class="label">Country</label>
|
||||||
<div class="control is-expanded has-icons-left">
|
<div class="control is-expanded has-icons-left">
|
||||||
<div class="select is-fullwidth" >
|
<div class="select is-fullwidth">
|
||||||
<select onChange={(e) => selectCountry((e.target as any).value)} disabled={!theContinent} value={theCountry?.code || ""}>
|
<select
|
||||||
<option key="none" disabled selected value=""> Choose a country </option>
|
onChange={(e) => selectCountry((e.target as any).value)}
|
||||||
{countryList.map(prov => (
|
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}>
|
<option key={prov.name} value={prov.code}>
|
||||||
{prov.name}
|
{prov.name}
|
||||||
</option>
|
</option>
|
||||||
@ -93,12 +123,15 @@ export function ContinentSelectionScreen(): VNode {
|
|||||||
</div>
|
</div>
|
||||||
<div class="column is-two-third">
|
<div class="column is-two-third">
|
||||||
<p>
|
<p>
|
||||||
Your location will help us to determine which personal information
|
Your location will help us to determine which personal information
|
||||||
ask you for the next step.
|
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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</AnastasisClientFrame>
|
</AnastasisClientFrame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
|
import { BackupStates, RecoveryStates } from "anastasis-core";
|
||||||
import {
|
import {
|
||||||
BackupStates,
|
ComponentChildren,
|
||||||
RecoveryStates
|
Fragment,
|
||||||
} from "anastasis-core";
|
|
||||||
import {
|
|
||||||
ComponentChildren, Fragment,
|
|
||||||
FunctionalComponent,
|
FunctionalComponent,
|
||||||
h,
|
h,
|
||||||
VNode
|
VNode,
|
||||||
} from "preact";
|
} from "preact";
|
||||||
import {
|
import { useErrorBoundary } from "preact/hooks";
|
||||||
useErrorBoundary
|
|
||||||
} from "preact/hooks";
|
|
||||||
import { AsyncButton } from "../../components/AsyncButton";
|
import { AsyncButton } from "../../components/AsyncButton";
|
||||||
import { Menu } from "../../components/menu";
|
import { Menu } from "../../components/menu";
|
||||||
import { Notifications } from "../../components/Notifications";
|
import { Notifications } from "../../components/Notifications";
|
||||||
import { AnastasisProvider, useAnastasisContext } from "../../context/anastasis";
|
import {
|
||||||
|
AnastasisProvider,
|
||||||
|
useAnastasisContext,
|
||||||
|
} from "../../context/anastasis";
|
||||||
import {
|
import {
|
||||||
AnastasisReducerApi,
|
AnastasisReducerApi,
|
||||||
useAnastasisReducer
|
useAnastasisReducer,
|
||||||
} from "../../hooks/use-anastasis-reducer";
|
} from "../../hooks/use-anastasis-reducer";
|
||||||
import { AttributeEntryScreen } from "./AttributeEntryScreen";
|
import { AttributeEntryScreen } from "./AttributeEntryScreen";
|
||||||
import { AuthenticationEditorScreen } from "./AuthenticationEditorScreen";
|
import { AuthenticationEditorScreen } from "./AuthenticationEditorScreen";
|
||||||
@ -50,6 +49,10 @@ export function withProcessLabel(
|
|||||||
|
|
||||||
interface AnastasisClientFrameProps {
|
interface AnastasisClientFrameProps {
|
||||||
onNext?(): void;
|
onNext?(): void;
|
||||||
|
/**
|
||||||
|
* Override for the "back" functionality.
|
||||||
|
*/
|
||||||
|
onBack?(): Promise<void>;
|
||||||
title: string;
|
title: string;
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
/**
|
/**
|
||||||
@ -116,9 +119,27 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
|
|||||||
<section class="section is-main-section">
|
<section class="section is-main-section">
|
||||||
{props.children}
|
{props.children}
|
||||||
{!props.hideNav ? (
|
{!props.hideNav ? (
|
||||||
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
|
<div
|
||||||
<button class="button" onClick={() => reducer.back()}>Back</button>
|
style={{
|
||||||
<AsyncButton class="button is-info" data-tooltip={props.hideNext} onClick={next} disabled={props.hideNext !== undefined}>Next</AsyncButton>
|
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>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
@ -139,7 +160,7 @@ const AnastasisClient: FunctionalComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function AnastasisClientImpl(): VNode {
|
function AnastasisClientImpl(): VNode {
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext();
|
||||||
if (!reducer) {
|
if (!reducer) {
|
||||||
return <p>Fatal: Reducer must be in context.</p>;
|
return <p>Fatal: Reducer must be in context.</p>;
|
||||||
}
|
}
|
||||||
@ -155,27 +176,19 @@ function AnastasisClientImpl(): VNode {
|
|||||||
state.backup_state === BackupStates.CountrySelecting ||
|
state.backup_state === BackupStates.CountrySelecting ||
|
||||||
state.recovery_state === RecoveryStates.CountrySelecting
|
state.recovery_state === RecoveryStates.CountrySelecting
|
||||||
) {
|
) {
|
||||||
return (
|
return <ContinentSelectionScreen />;
|
||||||
<ContinentSelectionScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
state.backup_state === BackupStates.UserAttributesCollecting ||
|
state.backup_state === BackupStates.UserAttributesCollecting ||
|
||||||
state.recovery_state === RecoveryStates.UserAttributesCollecting
|
state.recovery_state === RecoveryStates.UserAttributesCollecting
|
||||||
) {
|
) {
|
||||||
return (
|
return <AttributeEntryScreen />;
|
||||||
<AttributeEntryScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (state.backup_state === BackupStates.AuthenticationsEditing) {
|
if (state.backup_state === BackupStates.AuthenticationsEditing) {
|
||||||
return (
|
return <AuthenticationEditorScreen />;
|
||||||
<AuthenticationEditorScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (state.backup_state === BackupStates.PoliciesReviewing) {
|
if (state.backup_state === BackupStates.PoliciesReviewing) {
|
||||||
return (
|
return <ReviewPoliciesScreen />;
|
||||||
<ReviewPoliciesScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (state.backup_state === BackupStates.SecretEditing) {
|
if (state.backup_state === BackupStates.SecretEditing) {
|
||||||
return <SecretEditorScreen />;
|
return <SecretEditorScreen />;
|
||||||
@ -194,15 +207,11 @@ function AnastasisClientImpl(): VNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.recovery_state === RecoveryStates.SecretSelecting) {
|
if (state.recovery_state === RecoveryStates.SecretSelecting) {
|
||||||
return (
|
return <SecretSelectionScreen />;
|
||||||
<SecretSelectionScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.recovery_state === RecoveryStates.ChallengeSelecting) {
|
if (state.recovery_state === RecoveryStates.ChallengeSelecting) {
|
||||||
return (
|
return <ChallengeOverviewScreen />;
|
||||||
<ChallengeOverviewScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.recovery_state === RecoveryStates.ChallengeSolving) {
|
if (state.recovery_state === RecoveryStates.ChallengeSolving) {
|
||||||
@ -210,9 +219,7 @@ function AnastasisClientImpl(): VNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.recovery_state === RecoveryStates.RecoveryFinished) {
|
if (state.recovery_state === RecoveryStates.RecoveryFinished) {
|
||||||
return (
|
return <RecoveryFinishedScreen />;
|
||||||
<RecoveryFinishedScreen />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (state.recovery_state === RecoveryStates.ChallengePaying) {
|
if (state.recovery_state === RecoveryStates.ChallengePaying) {
|
||||||
return <ChallengePayingScreen />;
|
return <ChallengePayingScreen />;
|
||||||
@ -222,7 +229,9 @@ function AnastasisClientImpl(): VNode {
|
|||||||
<AnastasisClientFrame hideNav title="Bug">
|
<AnastasisClientFrame hideNav title="Bug">
|
||||||
<p>Bug: Unknown state.</p>
|
<p>Bug: Unknown state.</p>
|
||||||
<div class="buttons is-right">
|
<div class="buttons is-right">
|
||||||
<button class="button" onClick={() => reducer.reset()}>Reset</button>
|
<button class="button" onClick={() => reducer.reset()}>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</AnastasisClientFrame>
|
</AnastasisClientFrame>
|
||||||
);
|
);
|
||||||
@ -234,11 +243,17 @@ function AnastasisClientImpl(): VNode {
|
|||||||
function ErrorBanner(): VNode | null {
|
function ErrorBanner(): VNode | null {
|
||||||
const reducer = useAnastasisContext();
|
const reducer = useAnastasisContext();
|
||||||
if (!reducer || !reducer.currentError) return null;
|
if (!reducer || !reducer.currentError) return null;
|
||||||
return (<Notifications removeNotification={reducer.dismissError} notifications={[{
|
return (
|
||||||
type: "ERROR",
|
<Notifications
|
||||||
message: `Error code: ${reducer.currentError.code}`,
|
removeNotification={reducer.dismissError}
|
||||||
description: reducer.currentError.hint
|
notifications={[
|
||||||
}]} />
|
{
|
||||||
|
type: "ERROR",
|
||||||
|
message: `Error code: ${reducer.currentError.code}`,
|
||||||
|
description: reducer.currentError.hint,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user