From 9fb6536fbc91adaf7a8a80860fcef5e1f80bfb3b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 3 Nov 2021 18:56:19 +0100 Subject: [PATCH] anastasis-webui: show feedback in solution screen --- .../pages/home/ChallengeOverviewScreen.tsx | 4 +- .../src/pages/home/SolveScreen.tsx | 177 +++++++++++++----- 2 files changed, 135 insertions(+), 46 deletions(-) diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx index 69dbce037..7bafbe06a 100644 --- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx @@ -5,7 +5,7 @@ import { useAnastasisContext } from "../../context/anastasis"; import { AnastasisClientFrame } from "./index"; import { authMethods, KnownAuthMethods } from "./authMethod"; -function FeedbackDisplay(props: { feedback?: ChallengeFeedback }) { +function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) { const { feedback } = props; if (!feedback) { return null; @@ -130,7 +130,7 @@ export function ChallengeOverviewScreen(): VNode { {method?.icon} {info.instructions} - +
{method && info.feedback?.state !== "solved" ? ( diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx index b0cfa9bb0..d4d9271b4 100644 --- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx @@ -1,38 +1,89 @@ import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { AnastasisClientFrame } from "."; -import { ChallengeFeedback, ChallengeInfo } from "../../../../anastasis-core/lib"; +import { + ChallengeFeedback, + ChallengeFeedbackStatus, + ChallengeInfo, +} from "../../../../anastasis-core/lib"; import { TextInput } from "../../components/fields/TextInput"; import { useAnastasisContext } from "../../context/anastasis"; +function SolveOverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) { + const { feedback } = props; + if (!feedback) { + return null; + } + switch (feedback.state) { + case ChallengeFeedbackStatus.Message: + return ( +
+

{feedback.message}

+
+ ); + case ChallengeFeedbackStatus.Pending: + case ChallengeFeedbackStatus.AuthIban: + return null; + case ChallengeFeedbackStatus.RateLimitExceeded: + return
Rate limit exceeded.
; + case ChallengeFeedbackStatus.Redirect: + return
Redirect (FIXME: not supported)
; + case ChallengeFeedbackStatus.Unsupported: + return
Challenge not supported by client.
; + case ChallengeFeedbackStatus.TruthUnknown: + return
Truth unknown
; + default: + return ( +
+
{JSON.stringify(feedback)}
+
+ ); + } +} + export function SolveScreen(): VNode { - const reducer = useAnastasisContext() + const reducer = useAnastasisContext(); const [answer, setAnswer] = useState(""); if (!reducer) { - return -
no reducer in context
-
+ return ( + +
no reducer in context
+
+ ); } - if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) { - return -
invalid state
-
+ if ( + !reducer.currentReducerState || + reducer.currentReducerState.recovery_state === undefined + ) { + return ( + +
invalid state
+
+ ); } if (!reducer.currentReducerState.recovery_information) { - return -
no recovery information found
-
+ return ( + +
no recovery information found
+
+ ); } if (!reducer.currentReducerState.selected_challenge_uuid) { - return -
invalid state
-
+ return ( + +
invalid state
+
+ ); } const chArr = reducer.currentReducerState.recovery_information.challenges; - const challengeFeedback = reducer.currentReducerState.challenge_feedback ?? {}; + const challengeFeedback = + reducer.currentReducerState.challenge_feedback ?? {}; const selectedUuid = reducer.currentReducerState.selected_challenge_uuid; const challenges: { [uuid: string]: ChallengeInfo; @@ -47,31 +98,44 @@ export function SolveScreen(): VNode { email: SolveEmailEntry, post: SolvePostEntry, }; - const SolveDialog = selectedChallenge === undefined ? SolveUndefinedEntry : dialogMap[selectedChallenge.type] ?? SolveUnsupportedEntry; + const SolveDialog = + selectedChallenge === undefined + ? SolveUndefinedEntry + : dialogMap[selectedChallenge.type] ?? SolveUnsupportedEntry; function onNext(): void { - reducer?.transition("solve_challenge", { answer }) + reducer?.transition("solve_challenge", { answer }); } function onCancel(): void { - reducer?.back() + reducer?.back(); } - return ( - + + + feedback={challengeFeedback[selectedUuid]} + /> -
- - +
+ +
); @@ -85,38 +149,61 @@ export interface SolveEntryProps { setAnswer: (s: string) => void; } -function SolveSmsEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode { - return ( -

An sms has been sent to "{challenge.instructions}". Type the code below

- -
+function SolveSmsEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { + return ( + +

+ An sms has been sent to "{challenge.instructions}". Type the code + below +

+ +
); } -function SolveQuestionEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode { +function SolveQuestionEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { return (

Type the answer to the following question:

-
-        {challenge.instructions}
-      
+
{challenge.instructions}
); } -function SolvePostEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode { +function SolvePostEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { return ( -

instruction for post type challenge "{challenge.instructions}"

+

+ instruction for post type challenge "{challenge.instructions}" +

); } -function SolveEmailEntry({ challenge, answer, setAnswer }: SolveEntryProps): VNode { +function SolveEmailEntry({ + challenge, + answer, + setAnswer, +}: SolveEntryProps): VNode { return ( -

An email has been sent to "{challenge.instructions}". Type the code below

+

+ An email has been sent to "{challenge.instructions}". Type the + code below +

); @@ -126,7 +213,8 @@ function SolveUnsupportedEntry(props: SolveEntryProps): VNode { return (

- The challenge selected is not supported for this UI. Please update this version or try using another policy. + The challenge selected is not supported for this UI. Please update this + version or try using another policy.

Challenge type: {props.challenge.type} @@ -136,9 +224,10 @@ function SolveUnsupportedEntry(props: SolveEntryProps): VNode { } function SolveUndefinedEntry(props: SolveEntryProps): VNode { return ( - +

- There is no challenge information for id "{props.id}". Try resetting the recovery session. + There is no challenge information for id "{props.id}". Try + resetting the recovery session.

);