anastasis-webui: make it compile again
This commit is contained in:
parent
04356cd23f
commit
7d24d2254b
@ -96,6 +96,7 @@ const { fetch } = fetchPonyfill({});
|
|||||||
|
|
||||||
export * from "./reducer-types.js";
|
export * from "./reducer-types.js";
|
||||||
export * as validators from "./validators.js";
|
export * as validators from "./validators.js";
|
||||||
|
export * from "./challenge-feedback-types.js";
|
||||||
|
|
||||||
const logger = new Logger("anastasis-core:index.ts");
|
const logger = new Logger("anastasis-core:index.ts");
|
||||||
|
|
||||||
|
@ -20,214 +20,197 @@
|
|||||||
* @author Sebastian Javier Marchano (sebasjm)
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RecoveryStates, ReducerState } from 'anastasis-core';
|
import { RecoveryStates, ReducerState } from "anastasis-core";
|
||||||
import { createExample, reducerStatesExample } from '../../utils';
|
import { createExample, reducerStatesExample } from "../../utils";
|
||||||
import { ChallengeOverviewScreen as TestedComponent } from './ChallengeOverviewScreen';
|
import { ChallengeOverviewScreen as TestedComponent } from "./ChallengeOverviewScreen";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: 'Pages/recovery/ChallengeOverviewScreen',
|
title: "Pages/recovery/ChallengeOverviewScreen",
|
||||||
component: TestedComponent,
|
component: TestedComponent,
|
||||||
args: {
|
args: {
|
||||||
order: 5,
|
order: 5,
|
||||||
},
|
},
|
||||||
argTypes: {
|
argTypes: {
|
||||||
onUpdate: { action: 'onUpdate' },
|
onUpdate: { action: "onUpdate" },
|
||||||
onBack: { action: 'onBack' },
|
onBack: { action: "onBack" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OneUnsolvedPolicy = createExample(TestedComponent, {
|
export const OneUnsolvedPolicy = createExample(TestedComponent, {
|
||||||
...reducerStatesExample.challengeSelecting,
|
...reducerStatesExample.challengeSelecting,
|
||||||
recovery_information: {
|
recovery_information: {
|
||||||
policies: [[{ uuid: '1' }]],
|
policies: [[{ uuid: "1" }]],
|
||||||
challenges: [{
|
challenges: [
|
||||||
cost: 'USD:1',
|
{
|
||||||
instructions: 'just go for it',
|
cost: "USD:1",
|
||||||
type: 'question',
|
instructions: "just go for it",
|
||||||
uuid: '1',
|
type: "question",
|
||||||
}]
|
uuid: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
export const SomePoliciesOneSolved = createExample(TestedComponent, {
|
export const SomePoliciesOneSolved = createExample(TestedComponent, {
|
||||||
...reducerStatesExample.challengeSelecting,
|
...reducerStatesExample.challengeSelecting,
|
||||||
recovery_information: {
|
recovery_information: {
|
||||||
policies: [[{ uuid: '1' }, { uuid: '2' }], [{ uuid: 'uuid-3' }]],
|
policies: [[{ uuid: "1" }, { uuid: "2" }], [{ uuid: "uuid-3" }]],
|
||||||
challenges: [{
|
challenges: [
|
||||||
cost: 'USD:1',
|
{
|
||||||
instructions: 'this question cost 1 USD',
|
cost: "USD:1",
|
||||||
type: 'question',
|
instructions: "this question cost 1 USD",
|
||||||
uuid: '1',
|
type: "question",
|
||||||
}, {
|
uuid: "1",
|
||||||
cost: 'USD:0',
|
},
|
||||||
instructions: 'answering this question is free',
|
{
|
||||||
type: 'question',
|
cost: "USD:0",
|
||||||
uuid: '2',
|
instructions: "answering this question is free",
|
||||||
}, {
|
type: "question",
|
||||||
cost: 'USD:1',
|
uuid: "2",
|
||||||
instructions: 'this question is already answered',
|
},
|
||||||
type: 'question',
|
{
|
||||||
uuid: 'uuid-3',
|
cost: "USD:1",
|
||||||
}]
|
instructions: "this question is already answered",
|
||||||
|
type: "question",
|
||||||
|
uuid: "uuid-3",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
challenge_feedback: {
|
challenge_feedback: {
|
||||||
'uuid-3': {
|
"uuid-3": {
|
||||||
state: 'solved'
|
state: "solved",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
export const OneBadConfiguredPolicy = createExample(TestedComponent, {
|
export const OneBadConfiguredPolicy = createExample(TestedComponent, {
|
||||||
...reducerStatesExample.challengeSelecting,
|
...reducerStatesExample.challengeSelecting,
|
||||||
recovery_information: {
|
recovery_information: {
|
||||||
policies: [[{ uuid: '1' }, { uuid: '2' }]],
|
policies: [[{ uuid: "1" }, { uuid: "2" }]],
|
||||||
challenges: [{
|
challenges: [
|
||||||
cost: 'USD:1',
|
{
|
||||||
instructions: 'this policy has a missing uuid (the other auth method)',
|
cost: "USD:1",
|
||||||
type: 'totp',
|
instructions: "this policy has a missing uuid (the other auth method)",
|
||||||
uuid: '1',
|
type: "totp",
|
||||||
}],
|
uuid: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
|
export const OnePolicyWithAllTheChallenges = createExample(TestedComponent, {
|
||||||
...reducerStatesExample.challengeSelecting,
|
...reducerStatesExample.challengeSelecting,
|
||||||
recovery_information: {
|
recovery_information: {
|
||||||
policies: [[
|
policies: [
|
||||||
{ uuid: '1' },
|
[
|
||||||
{ uuid: '2' },
|
{ uuid: "1" },
|
||||||
{ uuid: '3' },
|
{ uuid: "2" },
|
||||||
{ uuid: '4' },
|
{ uuid: "3" },
|
||||||
{ uuid: '5' },
|
{ uuid: "4" },
|
||||||
{ uuid: '6' },
|
{ uuid: "5" },
|
||||||
{ uuid: '7' },
|
{ uuid: "6" },
|
||||||
{ uuid: '8' },
|
{ uuid: "7" },
|
||||||
]],
|
{ uuid: "8" },
|
||||||
challenges: [{
|
],
|
||||||
cost: 'USD:1',
|
],
|
||||||
instructions: 'Does P equals NP?',
|
challenges: [
|
||||||
type: 'question',
|
{
|
||||||
uuid: '1',
|
cost: "USD:1",
|
||||||
},{
|
instructions: "Does P equals NP?",
|
||||||
cost: 'USD:1',
|
type: "question",
|
||||||
instructions: 'SMS to 555-555',
|
uuid: "1",
|
||||||
type: 'sms',
|
},
|
||||||
uuid: '2',
|
{
|
||||||
},{
|
cost: "USD:1",
|
||||||
cost: 'USD:1',
|
instructions: "SMS to 555-555",
|
||||||
instructions: 'Email to qwe@asd.com',
|
type: "sms",
|
||||||
type: 'email',
|
uuid: "2",
|
||||||
uuid: '3',
|
},
|
||||||
},{
|
{
|
||||||
cost: 'USD:1',
|
cost: "USD:1",
|
||||||
|
instructions: "Email to qwe@asd.com",
|
||||||
|
type: "email",
|
||||||
|
uuid: "3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cost: "USD:1",
|
||||||
instructions: 'Enter 8 digits code for "Anastasis"',
|
instructions: 'Enter 8 digits code for "Anastasis"',
|
||||||
type: 'totp',
|
type: "totp",
|
||||||
uuid: '4',
|
uuid: "4",
|
||||||
},{//
|
},
|
||||||
cost: 'USD:0',
|
{
|
||||||
instructions: 'Wire transfer from ASDXCVQWE123123 with holder Florian',
|
//
|
||||||
type: 'iban',
|
cost: "USD:0",
|
||||||
uuid: '5',
|
instructions: "Wire transfer from ASDXCVQWE123123 with holder Florian",
|
||||||
},{
|
type: "iban",
|
||||||
cost: 'USD:1',
|
uuid: "5",
|
||||||
instructions: 'Join a video call',
|
},
|
||||||
type: 'video',//Enter 8 digits code for "Anastasis"
|
{
|
||||||
uuid: '7',
|
cost: "USD:1",
|
||||||
},{
|
instructions: "Join a video call",
|
||||||
},{
|
type: "video", //Enter 8 digits code for "Anastasis"
|
||||||
cost: 'USD:1',
|
uuid: "7",
|
||||||
instructions: 'Letter to address in postal code DE123123',
|
},
|
||||||
type: 'post',//Enter 8 digits code for "Anastasis"
|
{},
|
||||||
uuid: '8',
|
{
|
||||||
},{
|
cost: "USD:1",
|
||||||
cost: 'USD:1',
|
instructions: "Letter to address in postal code DE123123",
|
||||||
instructions: 'instruction for an unknown type of challenge',
|
type: "post", //Enter 8 digits code for "Anastasis"
|
||||||
type: 'new-type-of-challenge',
|
uuid: "8",
|
||||||
uuid: '6',
|
},
|
||||||
}],
|
{
|
||||||
|
cost: "USD:1",
|
||||||
|
instructions: "instruction for an unknown type of challenge",
|
||||||
|
type: "new-type-of-challenge",
|
||||||
|
uuid: "6",
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
} as ReducerState);
|
} as ReducerState);
|
||||||
|
|
||||||
|
export const OnePolicyWithAllTheChallengesInDifferentState = createExample(
|
||||||
export const OnePolicyWithAllTheChallengesInDifferentState = createExample(TestedComponent, {
|
TestedComponent,
|
||||||
|
{
|
||||||
...reducerStatesExample.challengeSelecting,
|
...reducerStatesExample.challengeSelecting,
|
||||||
|
recovery_state: RecoveryStates.ChallengeSelecting,
|
||||||
recovery_information: {
|
recovery_information: {
|
||||||
policies: [[
|
policies: [
|
||||||
{ uuid: '1' },
|
[
|
||||||
{ uuid: '2' },
|
{ uuid: "1" },
|
||||||
{ uuid: '3' },
|
{ uuid: "2" },
|
||||||
{ uuid: '4' },
|
{ uuid: "3" },
|
||||||
{ uuid: '5' },
|
{ uuid: "4" },
|
||||||
{ uuid: '6' },
|
{ uuid: "5" },
|
||||||
{ uuid: '7' },
|
{ uuid: "6" },
|
||||||
{ uuid: '8' },
|
{ uuid: "7" },
|
||||||
{ uuid: '9' },
|
{ uuid: "8" },
|
||||||
{ uuid: '10' },
|
{ uuid: "9" },
|
||||||
]],
|
{ uuid: "10" },
|
||||||
challenges: [{
|
],
|
||||||
cost: 'USD:1',
|
],
|
||||||
|
challenges: [
|
||||||
|
{
|
||||||
|
cost: "USD:1",
|
||||||
instructions: 'in state "solved"',
|
instructions: 'in state "solved"',
|
||||||
type: 'question',
|
type: "question",
|
||||||
uuid: '1',
|
uuid: "1",
|
||||||
},{
|
},
|
||||||
cost: 'USD:1',
|
{
|
||||||
instructions: 'in state "hint"',
|
cost: "USD:1",
|
||||||
type: 'question',
|
instructions: 'in state "message"',
|
||||||
uuid: '2',
|
type: "question",
|
||||||
},{
|
uuid: "2",
|
||||||
cost: 'USD:1',
|
},
|
||||||
instructions: 'in state "details"',
|
],
|
||||||
type: 'question',
|
|
||||||
uuid: '3',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "body"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '4',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "redirect"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '5',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "server-failure"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '6',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "truth-unknown"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '7',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "rate-limit-exceeded"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '8',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "authentication-timeout"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '9',
|
|
||||||
},{
|
|
||||||
cost: 'USD:1',
|
|
||||||
instructions: 'in state "external-instructions"',
|
|
||||||
type: 'question',
|
|
||||||
uuid: '10',
|
|
||||||
}],
|
|
||||||
},
|
},
|
||||||
challenge_feedback: {
|
challenge_feedback: {
|
||||||
1: { state: 'solved' },
|
1: { state: "solved" },
|
||||||
2: { state: 'hint' },
|
2: { state: "message", message: "Security question was not solved correctly" },
|
||||||
3: { state: 'details' },
|
// FIXME: add missing feedback states here!
|
||||||
4: { state: 'body' },
|
},
|
||||||
5: { state: 'redirect' },
|
} as ReducerState,
|
||||||
6: { state: 'server-failure' },
|
);
|
||||||
7: { state: 'truth-unknown' },
|
export const NoPolicies = createExample(
|
||||||
8: { state: 'rate-limit-exceeded' },
|
TestedComponent,
|
||||||
9: { state: 'authentication-timeout' },
|
reducerStatesExample.challengeSelecting,
|
||||||
10: { state: 'external-instructions' },
|
);
|
||||||
}
|
|
||||||
} as ReducerState);
|
|
||||||
export const NoPolicies = createExample(TestedComponent, reducerStatesExample.challengeSelecting);
|
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
/* eslint-disable @typescript-eslint/camelcase */
|
/* eslint-disable @typescript-eslint/camelcase */
|
||||||
import { ChallengeFeedback } from "anastasis-core";
|
import { ChallengeFeedback, ChallengeFeedbackStatus } from "anastasis-core";
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { useAnastasisContext } from "../../context/anastasis";
|
import { useAnastasisContext } from "../../context/anastasis";
|
||||||
import { AnastasisClientFrame } from "./index";
|
import { AnastasisClientFrame } from "./index";
|
||||||
import { authMethods, KnownAuthMethods } from "./authMethod";
|
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||||
|
|
||||||
export function ChallengeOverviewScreen(): VNode {
|
export function ChallengeOverviewScreen(): VNode {
|
||||||
const reducer = useAnastasisContext()
|
const reducer = useAnastasisContext();
|
||||||
|
|
||||||
if (!reducer) {
|
if (!reducer) {
|
||||||
return <div>no reducer in context</div>
|
return <div>no reducer in context</div>;
|
||||||
}
|
}
|
||||||
if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) {
|
if (
|
||||||
return <div>invalid state</div>
|
!reducer.currentReducerState ||
|
||||||
|
reducer.currentReducerState.recovery_state === undefined
|
||||||
|
) {
|
||||||
|
return <div>invalid state</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const policies = reducer.currentReducerState.recovery_information?.policies ?? [];
|
const policies =
|
||||||
const knownChallengesArray = reducer.currentReducerState.recovery_information?.challenges ?? [];
|
reducer.currentReducerState.recovery_information?.policies ?? [];
|
||||||
const challengeFeedback = reducer.currentReducerState?.challenge_feedback ?? {};
|
const knownChallengesArray =
|
||||||
|
reducer.currentReducerState.recovery_information?.challenges ?? [];
|
||||||
|
const challengeFeedback =
|
||||||
|
reducer.currentReducerState?.challenge_feedback ?? {};
|
||||||
|
|
||||||
const knownChallengesMap: {
|
const knownChallengesMap: {
|
||||||
[uuid: string]: {
|
[uuid: string]: {
|
||||||
@ -32,51 +38,80 @@ export function ChallengeOverviewScreen(): VNode {
|
|||||||
type: ch.type,
|
type: ch.type,
|
||||||
cost: ch.cost,
|
cost: ch.cost,
|
||||||
instructions: ch.instructions,
|
instructions: ch.instructions,
|
||||||
feedback: challengeFeedback[ch.uuid]
|
feedback: challengeFeedback[ch.uuid],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const policiesWithInfo = policies.map(row => {
|
const policiesWithInfo = policies.map((row) => {
|
||||||
let isPolicySolved = true
|
let isPolicySolved = true;
|
||||||
const challenges = row.map(({ uuid }) => {
|
const challenges = row
|
||||||
|
.map(({ uuid }) => {
|
||||||
const info = knownChallengesMap[uuid];
|
const info = knownChallengesMap[uuid];
|
||||||
const isChallengeSolved = info?.feedback?.state === 'solved'
|
const isChallengeSolved = info?.feedback?.state === "solved";
|
||||||
isPolicySolved = isPolicySolved && isChallengeSolved
|
isPolicySolved = isPolicySolved && isChallengeSolved;
|
||||||
return { info, uuid, isChallengeSolved }
|
return { info, uuid, isChallengeSolved };
|
||||||
}).filter(ch => ch.info !== undefined)
|
|
||||||
|
|
||||||
return { isPolicySolved, challenges }
|
|
||||||
})
|
})
|
||||||
|
.filter((ch) => ch.info !== undefined);
|
||||||
|
|
||||||
const atLeastThereIsOnePolicySolved = policiesWithInfo.find(p => p.isPolicySolved) !== undefined
|
return { isPolicySolved, challenges };
|
||||||
|
});
|
||||||
|
|
||||||
const errors = !atLeastThereIsOnePolicySolved ? "Solve one policy before proceeding" : undefined;
|
const atLeastThereIsOnePolicySolved =
|
||||||
|
policiesWithInfo.find((p) => p.isPolicySolved) !== undefined;
|
||||||
|
|
||||||
|
const errors = !atLeastThereIsOnePolicySolved
|
||||||
|
? "Solve one policy before proceeding"
|
||||||
|
: undefined;
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
|
<AnastasisClientFrame hideNext={errors} title="Recovery: Solve challenges">
|
||||||
{!policies.length ? <p class="block">
|
{!policies.length ? (
|
||||||
|
<p class="block">
|
||||||
No policies found, try with another version of the secret
|
No policies found, try with another version of the secret
|
||||||
</p> : (policies.length === 1 ? <p class="block">
|
</p>
|
||||||
One policy found for this secret. You need to solve all the challenges in order to recover your secret.
|
) : policies.length === 1 ? (
|
||||||
</p> : <p class="block">
|
<p class="block">
|
||||||
We have found {policies.length} polices. You need to solve all the challenges from one policy in order
|
One policy found for this secret. You need to solve all the challenges
|
||||||
to recover your secret.
|
in order to recover your secret.
|
||||||
</p>)}
|
</p>
|
||||||
|
) : (
|
||||||
|
<p class="block">
|
||||||
|
We have found {policies.length} polices. You need to solve all the
|
||||||
|
challenges from one policy in order to recover your secret.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
{policiesWithInfo.map((policy, policy_index) => {
|
{policiesWithInfo.map((policy, policy_index) => {
|
||||||
const tableBody = policy.challenges.map(({ info, uuid }) => {
|
const tableBody = policy.challenges.map(({ info, uuid }) => {
|
||||||
const isFree = !info.cost || info.cost.endsWith(':0')
|
const isFree = !info.cost || info.cost.endsWith(":0");
|
||||||
const method = authMethods[info.type as KnownAuthMethods]
|
const method = authMethods[info.type as KnownAuthMethods];
|
||||||
return (
|
return (
|
||||||
<div key={uuid} class="block" style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div
|
||||||
<div style={{display:'flex', alignItems:'center'}}>
|
key={uuid}
|
||||||
<span class="icon">
|
class="block"
|
||||||
{method?.icon}
|
style={{ display: "flex", justifyContent: "space-between" }}
|
||||||
</span>
|
>
|
||||||
<span>
|
<div
|
||||||
{info.instructions}
|
style={{
|
||||||
</span>
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", alignItems: "center" }}>
|
||||||
|
<span class="icon">{method?.icon}</span>
|
||||||
|
<span>{info.instructions}</span>
|
||||||
|
</div>
|
||||||
|
{info.feedback?.state === ChallengeFeedbackStatus.Message ? (
|
||||||
|
<div>
|
||||||
|
<p>{info.feedback.message}</p>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{method && info.feedback?.state !== "solved" ? (
|
{method && info.feedback?.state !== "solved" ? (
|
||||||
<a class="button" onClick={() => reducer.transition("select_challenge", { uuid })}>
|
<a
|
||||||
|
class="button"
|
||||||
|
onClick={() =>
|
||||||
|
reducer.transition("select_challenge", { uuid })
|
||||||
|
}
|
||||||
|
>
|
||||||
{isFree ? "Solve" : `Pay and Solve`}
|
{isFree ? "Solve" : `Pay and Solve`}
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
@ -86,26 +121,36 @@ export function ChallengeOverviewScreen(): VNode {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
});
|
||||||
|
|
||||||
const policyName = policy.challenges.map(x => x.info.type).join(" + ");
|
const policyName = policy.challenges
|
||||||
const opa = !atLeastThereIsOnePolicySolved ? undefined : ( policy.isPolicySolved ? undefined : '0.6')
|
.map((x) => x.info.type)
|
||||||
|
.join(" + ");
|
||||||
|
const opa = !atLeastThereIsOnePolicySolved
|
||||||
|
? undefined
|
||||||
|
: policy.isPolicySolved
|
||||||
|
? undefined
|
||||||
|
: "0.6";
|
||||||
return (
|
return (
|
||||||
<div key={policy_index} class="box" style={{
|
<div
|
||||||
opacity: opa
|
key={policy_index}
|
||||||
}}>
|
class="box"
|
||||||
|
style={{
|
||||||
|
opacity: opa,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<h3 class="subtitle">
|
<h3 class="subtitle">
|
||||||
Policy #{policy_index + 1}: {policyName}
|
Policy #{policy_index + 1}: {policyName}
|
||||||
</h3>
|
</h3>
|
||||||
{policy.challenges.length === 0 && <p>
|
{policy.challenges.length === 0 && (
|
||||||
This policy doesn't have challenges.
|
<p>This policy doesn't have challenges.</p>
|
||||||
</p>}
|
)}
|
||||||
{policy.challenges.length === 1 && <p>
|
{policy.challenges.length === 1 && (
|
||||||
This policy just have one challenge.
|
<p>This policy just have one challenge.</p>
|
||||||
</p>}
|
)}
|
||||||
{policy.challenges.length > 1 && <p>
|
{policy.challenges.length > 1 && (
|
||||||
This policy have {policy.challenges.length} challenges.
|
<p>This policy have {policy.challenges.length} challenges.</p>
|
||||||
</p>}
|
)}
|
||||||
{tableBody}
|
{tableBody}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -16,7 +16,7 @@ export function CountrySelectionScreen(): VNode {
|
|||||||
currencies: [x.currency],
|
currencies: [x.currency],
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame hideNext title={withProcessLabel(reducer, "Select Country")} >
|
<AnastasisClientFrame hideNext={"FIXME"} title={withProcessLabel(reducer, "Select Country")} >
|
||||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
{reducer.currentReducerState.countries!.map((x: any) => (
|
{reducer.currentReducerState.countries!.map((x: any) => (
|
||||||
<div key={x.name}>
|
<div key={x.name}>
|
||||||
|
@ -13,7 +13,7 @@ export function TruthsPayingScreen(): VNode {
|
|||||||
const payments = reducer.currentReducerState.payments ?? [];
|
const payments = reducer.currentReducerState.payments ?? [];
|
||||||
return (
|
return (
|
||||||
<AnastasisClientFrame
|
<AnastasisClientFrame
|
||||||
hideNext
|
hideNext={"FIXME"}
|
||||||
title="Backup: Truths Paying"
|
title="Backup: Truths Paying"
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
|
Loading…
Reference in New Issue
Block a user