aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-11-05 14:56:03 -0300
committerSebastian <sebasjm@gmail.com>2021-11-05 14:56:28 -0300
commita9d2a4654b414a01a53a0d79f1f90a5102564710 (patch)
treea5dc5c76ea7ffeaec101169699302a40e0c63131
parentd43ab6af87f2729b37548336d42ffce0ed3c879e (diff)
feedback state rendering
-rw-r--r--packages/anastasis-webui/src/components/Notifications.tsx4
-rw-r--r--packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx108
-rw-r--r--packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx116
-rw-r--r--packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx1
-rw-r--r--packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx2
-rw-r--r--packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx193
-rw-r--r--packages/anastasis-webui/src/pages/home/SolveScreen.tsx81
7 files changed, 428 insertions, 77 deletions
diff --git a/packages/anastasis-webui/src/components/Notifications.tsx b/packages/anastasis-webui/src/components/Notifications.tsx
index c916020d7..097ebb4de 100644
--- a/packages/anastasis-webui/src/components/Notifications.tsx
+++ b/packages/anastasis-webui/src/components/Notifications.tsx
@@ -46,10 +46,10 @@ function messageStyle(type: MessageType): string {
export function Notifications({ notifications, removeNotification }: Props): VNode {
return <div class="block">
- {notifications.map((n,i) => <article key={i} class={messageStyle(n.type)}>
+ {notifications.map((n, i) => <article key={i} class={messageStyle(n.type)}>
<div class="message-header">
<p>{n.message}</p>
- <button class="delete" onClick={() => removeNotification && removeNotification(n)} />
+ {removeNotification && <button class="delete" onClick={() => removeNotification && removeNotification(n)} />}
</div>
{n.description && <div class="message-body">
{n.description}
diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
index 48115c798..e001ed157 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.stories.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
@@ -20,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { RecoveryStates, ReducerState } from "anastasis-core";
+import { ChallengeFeedbackStatus, RecoveryStates, ReducerState } from "anastasis-core";
import { createExample, reducerStatesExample } from "../../utils";
import { ChallengeOverviewScreen as TestedComponent } from "./ChallengeOverviewScreen";
@@ -176,16 +175,15 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
recovery_information: {
policies: [
[
- { uuid: "1" },
- { uuid: "2" },
- { uuid: "3" },
- { uuid: "4" },
- { uuid: "5" },
- { uuid: "6" },
- { uuid: "7" },
- { uuid: "8" },
- { uuid: "9" },
- { uuid: "10" },
+ { uuid: "uuid-1" },
+ { uuid: "uuid-2" },
+ { uuid: "uuid-3" },
+ { uuid: "uuid-4" },
+ { uuid: "uuid-5" },
+ { uuid: "uuid-6" },
+ { uuid: "uuid-7" },
+ { uuid: "uuid-8" },
+ { uuid: "uuid-9" },
],
],
challenges: [
@@ -193,20 +191,96 @@ export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
cost: "USD:1",
instructions: 'in state "solved"',
type: "question",
- uuid: "1",
+ uuid: "uuid-1",
},
{
cost: "USD:1",
instructions: 'in state "message"',
type: "question",
- uuid: "2",
+ uuid: "uuid-2",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "auth iban"',
+ type: "question",
+ uuid: "uuid-3",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "payment "',
+ type: "question",
+ uuid: "uuid-4",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "rate limit"',
+ type: "question",
+ uuid: "uuid-5",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "redirect"',
+ type: "question",
+ uuid: "uuid-6",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "server failure"',
+ type: "question",
+ uuid: "uuid-7",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "truth unknown"',
+ type: "question",
+ uuid: "uuid-8",
+ },
+ {
+ cost: "USD:1",
+ instructions: 'in state "unsupported"',
+ type: "question",
+ uuid: "uuid-9",
},
],
},
challenge_feedback: {
- 1: { state: "solved" },
- 2: { state: "message", message: "Security question was not solved correctly" },
- // FIXME: add missing feedback states here!
+ "uuid-1": { state: ChallengeFeedbackStatus.Solved.toString() },
+ "uuid-2": {
+ state: ChallengeFeedbackStatus.Message.toString(),
+ message: 'Challenge should be solved'
+ },
+ "uuid-3": {
+ state: ChallengeFeedbackStatus.AuthIban.toString(),
+ challenge_amount: "EUR:1",
+ credit_iban: "DE12345789000",
+ business_name: "Data Loss Incorporated",
+ wire_transfer_subject: "Anastasis 987654321"
+ },
+ "uuid-4": {
+ state: ChallengeFeedbackStatus.Payment.toString(),
+ taler_pay_uri: "taler://pay/...",
+ provider: "https://localhost:8080/",
+ payment_secret: "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+ },
+ "uuid-5": {
+ state: ChallengeFeedbackStatus.RateLimitExceeded.toString(),
+ // "error_code": 8121
+ },
+ "uuid-6": {
+ state: ChallengeFeedbackStatus.Redirect.toString(),
+ redirect_url: "https://videoconf.example.com/",
+ http_status: 303
+ },
+ "uuid-7": {
+ state: ChallengeFeedbackStatus.ServerFailure.toString(),
+ http_status: 500,
+ error_response: "some error message or error object",
+ },
+ "uuid-8": {
+ state: ChallengeFeedbackStatus.TruthUnknown.toString(),
+ // "error_code": 8108
+ },
+ "uuid-9": { state: ChallengeFeedbackStatus.Unsupported.toString() },
},
} as ReducerState,
);
diff --git a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
index ed34bbde2..598999f2e 100644
--- a/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ChallengeOverviewScreen.tsx
@@ -12,27 +12,24 @@ function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
switch (feedback.state) {
case ChallengeFeedbackStatus.Message:
return (
- <div>
- <p>{feedback.message}</p>
- </div>
+ <div class="block has-text-danger">{feedback.message}</div>
);
+ case ChallengeFeedbackStatus.Solved:
+ return <div />
case ChallengeFeedbackStatus.Pending:
case ChallengeFeedbackStatus.AuthIban:
return null;
+ case ChallengeFeedbackStatus.ServerFailure:
+ return <div class="block has-text-danger">Server error.</div>;
case ChallengeFeedbackStatus.RateLimitExceeded:
- return <div>Rate limit exceeded.</div>;
- case ChallengeFeedbackStatus.Redirect:
- return <div>Redirect (FIXME: not supported)</div>;
+ return <div class="block has-text-danger">There were to many failed attempts.</div>;
case ChallengeFeedbackStatus.Unsupported:
- return <div>Challenge not supported by client.</div>;
+ return <div class="block has-text-danger">This client doesn't support solving this type of challenge. Use another version or contact the provider.</div>;
case ChallengeFeedbackStatus.TruthUnknown:
- return <div>Truth unknown</div>;
+ return <div class="block has-text-danger">Provider doesn't recognize the challenge of the policy. Contact the provider for further information.</div>;
+ case ChallengeFeedbackStatus.Redirect:
default:
- return (
- <div>
- <pre>{JSON.stringify(feedback)}</pre>
- </div>
- );
+ return <div />;
}
}
@@ -113,6 +110,77 @@ export function ChallengeOverviewScreen(): VNode {
const tableBody = policy.challenges.map(({ info, uuid }) => {
const isFree = !info.cost || info.cost.endsWith(":0");
const method = authMethods[info.type as KnownAuthMethods];
+
+ if (!method) {
+ return <div
+ key={uuid}
+ class="block"
+ style={{ display: "flex", justifyContent: "space-between" }}
+ >
+ <div style={{ display: "flex", alignItems: "center" }}>
+ <span>unknown challenge</span>
+ </div>
+
+ </div>
+ }
+
+ function ChallengeButton({ id, feedback }: { id: string; feedback?: ChallengeFeedback }): VNode {
+ function selectChallenge(): void {
+ if (reducer) reducer.transition("select_challenge", { uuid: id })
+ }
+ if (!feedback) {
+ return <div>
+ <button class="button" onClick={selectChallenge}>
+ Solve
+ </button>
+ </div>
+ }
+ switch (feedback.state) {
+ case ChallengeFeedbackStatus.ServerFailure:
+ case ChallengeFeedbackStatus.Unsupported:
+ case ChallengeFeedbackStatus.TruthUnknown:
+ case ChallengeFeedbackStatus.RateLimitExceeded: return <div />
+ case ChallengeFeedbackStatus.AuthIban:
+ case ChallengeFeedbackStatus.Payment: return <div>
+ <button class="button" onClick={selectChallenge}>
+ Pay
+ </button>
+ </div>
+ case ChallengeFeedbackStatus.Redirect: return <div>
+ <button class="button" onClick={selectChallenge}>
+ Go to {feedback.redirect_url}
+ </button>
+ </div>
+ case ChallengeFeedbackStatus.Solved: return <div>
+ <div class="tag is-success is-large">
+ Solved
+ </div>
+ </div>
+ default: return <div>
+ <button class="button" onClick={selectChallenge}>
+ Solve
+ </button>
+ </div>
+
+ }
+ // return <div>
+ // {feedback.state !== "solved" ? (
+ // <a
+ // class="button"
+ // onClick={() =>
+
+ // }
+ // >
+ // {isFree ? "Solve" : `Pay and Solve`}
+ // </a>
+ // ) : null}
+ // {feedback.state === "solved" ? (
+ // // <div class="block is-success" > Solved </div>
+ // <div class="tag is-success is-large">Solved</div>
+
+ // ) : null}
+ // </div>
+ }
return (
<div
key={uuid}
@@ -131,21 +199,9 @@ export function ChallengeOverviewScreen(): VNode {
</div>
<OverviewFeedbackDisplay feedback={info.feedback} />
</div>
- <div>
- {method && info.feedback?.state !== "solved" ? (
- <a
- class="button"
- onClick={() =>
- reducer.transition("select_challenge", { uuid })
- }
- >
- {isFree ? "Solve" : `Pay and Solve`}
- </a>
- ) : null}
- {info.feedback?.state === "solved" ? (
- <a class="button is-success"> Solved </a>
- ) : null}
- </div>
+
+ <ChallengeButton id={uuid} feedback={info.feedback} />
+
</div>
);
});
@@ -156,8 +212,8 @@ export function ChallengeOverviewScreen(): VNode {
const opa = !atLeastThereIsOnePolicySolved
? undefined
: policy.isPolicySolved
- ? undefined
- : "0.6";
+ ? undefined
+ : "0.6";
return (
<div
key={policy_index}
diff --git a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
index f93963f67..aa98b5dd9 100644
--- a/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/ReviewPoliciesScreen.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useAnastasisContext } from "../../context/anastasis";
diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
index 8aa5ed2f7..cf38d3f18 100644
--- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx
@@ -104,7 +104,7 @@ function ChooseAnotherProviderScreen({ providers, selected, onChange }: { select
function SelectOtherVersionProviderScreen({ providers, provider, version, onConfirm, onCancel }: { onCancel: () => void; provider: string; version: number; providers: string[]; onConfirm: (prov: string, v: number) => Promise<void>; }): VNode {
const [otherProvider, setOtherProvider] = useState<string>(provider);
- const [otherVersion, setOtherVersion] = useState(`${version}`);
+ const [otherVersion, setOtherVersion] = useState(version > 0 ? String(version) : "");
return (
<AnastasisClientFrame hideNav title="Recovery: Select secret">
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
index cb6561b3f..05c4bfa42 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.stories.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable @typescript-eslint/camelcase */
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
@@ -20,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { ReducerState } from 'anastasis-core';
+import { ChallengeFeedbackStatus, ReducerState } from 'anastasis-core';
import { createExample, reducerStatesExample } from '../../utils';
import { SolveScreen as TestedComponent } from './SolveScreen';
@@ -50,7 +49,8 @@ export const NotSupportedChallenge = createExample(TestedComponent, {
}],
policies: [],
},
- selected_challenge_uuid: 'ASDASDSAD!1'
+ selected_challenge_uuid: 'ASDASDSAD!1',
+
} as ReducerState);
export const MismatchedChallengeId = createExample(TestedComponent, {
@@ -78,7 +78,8 @@ export const SmsChallenge = createExample(TestedComponent, {
}],
policies: [],
},
- selected_challenge_uuid: 'ASDASDSAD!1'
+ selected_challenge_uuid: 'ASDASDSAD!1',
+
} as ReducerState);
export const QuestionChallenge = createExample(TestedComponent, {
@@ -92,7 +93,8 @@ export const QuestionChallenge = createExample(TestedComponent, {
}],
policies: [],
},
- selected_challenge_uuid: 'ASDASDSAD!1'
+ selected_challenge_uuid: 'ASDASDSAD!1',
+
} as ReducerState);
export const EmailChallenge = createExample(TestedComponent, {
@@ -106,7 +108,8 @@ export const EmailChallenge = createExample(TestedComponent, {
}],
policies: [],
},
- selected_challenge_uuid: 'ASDASDSAD!1'
+ selected_challenge_uuid: 'ASDASDSAD!1',
+
} as ReducerState);
export const PostChallenge = createExample(TestedComponent, {
@@ -120,5 +123,181 @@ export const PostChallenge = createExample(TestedComponent, {
}],
policies: [],
},
- selected_challenge_uuid: 'ASDASDSAD!1'
+ selected_challenge_uuid: 'ASDASDSAD!1',
+
+} as ReducerState);
+
+
+export const QuestionChallengeMessageFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.Message,
+ message: 'Challenge should be solved'
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengeServerFailureFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.ServerFailure,
+ http_status: 500,
+ error_response: "Couldn't connect to mysql"
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengeRedirectFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.Redirect,
+ http_status: 302,
+ redirect_url: 'http://video.taler.net'
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengeMessageRateLimitExceededFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.RateLimitExceeded,
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengeUnsupportedFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.Unsupported,
+ http_status: 500,
+ unsupported_method: 'Question'
+ }
+ }
+
} as ReducerState);
+
+export const QuestionChallengeTruthUnknownFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.TruthUnknown,
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengeAuthIbanFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.AuthIban,
+ challenge_amount: "EUR:1",
+ credit_iban: "DE12345789000",
+ business_name: "Data Loss Incorporated",
+ wire_transfer_subject: "Anastasis 987654321"
+ }
+ }
+
+} as ReducerState);
+
+export const QuestionChallengePaymentFeedback = createExample(TestedComponent, {
+ ...reducerStatesExample.challengeSolving,
+ recovery_information: {
+ challenges: [{
+ cost: 'USD:1',
+ instructions: 'does P equals NP?',
+ type: 'question',
+ uuid: 'ASDASDSAD!1'
+ }],
+ policies: [],
+ },
+ selected_challenge_uuid: 'ASDASDSAD!1',
+ challenge_feedback: {
+ 'ASDASDSAD!1': {
+ state: ChallengeFeedbackStatus.Payment,
+ taler_pay_uri : "taler://pay/...",
+ provider : "https://localhost:8080/",
+ payment_secret : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
+ }
+ }
+} as ReducerState);
+
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index bc1a88db3..35db5ead0 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -8,31 +8,67 @@ import {
} from "../../../../anastasis-core/lib";
import { AsyncButton } from "../../components/AsyncButton";
import { TextInput } from "../../components/fields/TextInput";
+import { Notifications } from "../../components/Notifications";
import { useAnastasisContext } from "../../context/anastasis";
-function SolveOverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
+function SolveOverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }): VNode {
const { feedback } = props;
if (!feedback) {
- return null;
+ return <div />;
}
switch (feedback.state) {
case ChallengeFeedbackStatus.Message:
- return (
- <div>
- <p>{feedback.message}</p>
- </div>
- );
- case ChallengeFeedbackStatus.Pending:
+ return (<Notifications notifications={[{
+ type: "INFO",
+ message: `Message from provider`,
+ description: feedback.message
+ }]} />);
+ case ChallengeFeedbackStatus.Payment:
+ return <Notifications notifications={[{
+ type: "INFO",
+ message: `Message from provider`,
+ description: <span>
+ To pay you can <a href={feedback.taler_pay_uri}>click here</a>
+ </span>
+ }]} />
case ChallengeFeedbackStatus.AuthIban:
- return null;
+ return <Notifications notifications={[{
+ type: "INFO",
+ message: `Message from provider`,
+ description: `Need to send a wire transfer to "${feedback.business_name}"`
+ }]} />;
+ case ChallengeFeedbackStatus.ServerFailure:
+ return (<Notifications notifications={[{
+ type: "ERROR",
+ message: `Server error: Code ${feedback.http_status}`,
+ description: feedback.error_response
+ }]} />);
case ChallengeFeedbackStatus.RateLimitExceeded:
- return <div>Rate limit exceeded.</div>;
+ return (<Notifications notifications={[{
+ type: "ERROR",
+ message: `Message from provider`,
+ description: "There were to many failed attempts."
+ }]} />);
case ChallengeFeedbackStatus.Redirect:
- return <div>Redirect (FIXME: not supported)</div>;
+ return (<Notifications notifications={[{
+ type: "INFO",
+ message: `Message from provider`,
+ description: <span>
+ Please visit this link: <a>{feedback.redirect_url}</a>
+ </span>
+ }]} />);
case ChallengeFeedbackStatus.Unsupported:
- return <div>Challenge not supported by client.</div>;
+ return (<Notifications notifications={[{
+ type: "ERROR",
+ message: `This client doesn't support solving this type of challenge`,
+ description: `Use another version or contact the provider. Type of challenge "${feedback.unsupported_method}"`
+ }]} />);
case ChallengeFeedbackStatus.TruthUnknown:
- return <div>Truth unknown</div>;
+ return (<Notifications notifications={[{
+ type: "ERROR",
+ message: `Provider doesn't recognize the type of challenge`,
+ description: "Contact the provider for further information"
+ }]} />);
default:
return (
<div>
@@ -79,8 +115,8 @@ export function SolveScreen(): VNode {
<AnastasisClientFrame hideNav title="Recovery problem">
<div>invalid state</div>
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
- <button class="button" onClick={() => reducer.back()}>Back</button>
- </div>
+ <button class="button" onClick={() => reducer.back()}>Back</button>
+ </div>
</AnastasisClientFrame>
);
}
@@ -114,17 +150,23 @@ export function SolveScreen(): VNode {
reducer?.back();
}
+ const feedback = challengeFeedback[selectedUuid]
+ const shouldHideConfirm = feedback?.state === ChallengeFeedbackStatus.RateLimitExceeded
+ || feedback?.state === ChallengeFeedbackStatus.Redirect
+ || feedback?.state === ChallengeFeedbackStatus.Unsupported
+ || feedback?.state === ChallengeFeedbackStatus.TruthUnknown
+
return (
<AnastasisClientFrame hideNav title="Recovery: Solve challenge">
<SolveOverviewFeedbackDisplay
- feedback={challengeFeedback[selectedUuid]}
+ feedback={feedback}
/>
<SolveDialog
id={selectedUuid}
answer={answer}
setAnswer={setAnswer}
challenge={selectedChallenge}
- feedback={challengeFeedback[selectedUuid]}
+ feedback={feedback}
/>
<div
@@ -137,9 +179,9 @@ export function SolveScreen(): VNode {
<button class="button" onClick={onCancel}>
Cancel
</button>
- <AsyncButton class="button is-info" onClick={onNext}>
+ {!shouldHideConfirm && <AsyncButton class="button is-info" onClick={onNext}>
Confirm
- </AsyncButton>
+ </AsyncButton>}
</div>
</AnastasisClientFrame>
);
@@ -160,6 +202,7 @@ function SolveSmsEntry({
}: SolveEntryProps): VNode {
return (
<Fragment>
+
<p>
An sms has been sent to "<b>{challenge.instructions}</b>". Type the code
below