changes from feedback
better backup and recovery ending screen async button on modal and solve challenges use providers name when possible
This commit is contained in:
parent
0ac7433ea7
commit
4a83e9639d
@ -59,16 +59,16 @@ export function AttributeEntryScreen(): VNode {
|
||||
<ConfirmModal
|
||||
active
|
||||
onCancel={() => setAskUserIfSure(false)}
|
||||
description="You can not forget what you had entered"
|
||||
description="The values in the form must be correct"
|
||||
label="I am sure"
|
||||
cancelLabel="Wait, I want to check"
|
||||
onConfirm={() => reducer.transition("enter_user_attributes", {
|
||||
identity_attributes: attrs,
|
||||
})}
|
||||
}).then(() => setAskUserIfSure(false) )}
|
||||
>
|
||||
You personal information is used to define the location where your
|
||||
secret will be safely stored. If you forget what you have entered or
|
||||
if there is a misspell you will be unable to recover your secret again.
|
||||
if there is a misspell you will be unable to recover your secret.
|
||||
</ConfirmModal>
|
||||
) : null}
|
||||
|
||||
|
@ -49,13 +49,13 @@ export const WithDetails = createExample(TestedComponent, {
|
||||
...reducerStatesExample.backupFinished,
|
||||
secret_name: "super_secret",
|
||||
success_details: {
|
||||
"http://anastasis.net": {
|
||||
"https://anastasis.demo.taler.net/": {
|
||||
policy_expiration: {
|
||||
t_ms: "never",
|
||||
},
|
||||
policy_version: 0,
|
||||
},
|
||||
"http://taler.net": {
|
||||
"https://kudos.demo.anastasis.lu/": {
|
||||
policy_expiration: {
|
||||
t_ms: new Date().getTime() + 60 * 60 * 24 * 1000,
|
||||
},
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { AuthenticationProviderStatusOk } from "anastasis-core";
|
||||
import { format } from "date-fns";
|
||||
import { h, VNode } from "preact";
|
||||
import { useAnastasisContext } from "../../context/anastasis";
|
||||
@ -15,33 +16,28 @@ export function BackupFinishedScreen(): VNode {
|
||||
return <div>invalid state</div>;
|
||||
}
|
||||
const details = reducer.currentReducerState.success_details;
|
||||
const providers = reducer.currentReducerState.authentication_providers ?? {}
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Backup finished">
|
||||
{reducer.currentReducerState.secret_name ? (
|
||||
<p>
|
||||
Your backup of secret{" "}
|
||||
<b>"{reducer.currentReducerState.secret_name}"</b> was successful.
|
||||
</p>
|
||||
) : (
|
||||
<p>Your secret was successfully backed up.</p>
|
||||
)}
|
||||
<AnastasisClientFrame hideNav title="Backup success!">
|
||||
<p>Your backup is complete.</p>
|
||||
|
||||
{details && (
|
||||
<div class="block">
|
||||
<p>The backup is stored by the following providers:</p>
|
||||
{Object.keys(details).map((x, i) => {
|
||||
const sd = details[x];
|
||||
{Object.keys(details).map((url, i) => {
|
||||
const sd = details[url];
|
||||
const p = providers[url] as AuthenticationProviderStatusOk
|
||||
return (
|
||||
<div key={i} class="box">
|
||||
{x}
|
||||
<a href={url} target="_blank" rel="noreferrer">{p.business_name}</a>
|
||||
<p>
|
||||
version {sd.policy_version}
|
||||
{sd.policy_expiration.t_ms !== "never"
|
||||
? ` expires at: ${format(
|
||||
sd.policy_expiration.t_ms,
|
||||
"dd-MM-yyyy",
|
||||
)}`
|
||||
new Date(sd.policy_expiration.t_ms),
|
||||
"dd-MM-yyyy",
|
||||
)}`
|
||||
: " without expiration date"}
|
||||
</p>
|
||||
</div>
|
||||
@ -49,17 +45,6 @@ export function BackupFinishedScreen(): VNode {
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
marginTop: "2em",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<button class="button" onClick={() => reducer.back()}>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</AnastasisClientFrame>
|
||||
);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { h, VNode } from "preact";
|
||||
import { useAnastasisContext } from "../../context/anastasis";
|
||||
import { AnastasisClientFrame } from "./index";
|
||||
import { authMethods, KnownAuthMethods } from "./authMethod";
|
||||
import { AsyncButton } from "../../components/AsyncButton";
|
||||
|
||||
function OverviewFeedbackDisplay(props: { feedback?: ChallengeFeedback }) {
|
||||
const { feedback } = props;
|
||||
@ -150,13 +151,15 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
id: string;
|
||||
feedback?: ChallengeFeedback;
|
||||
}): VNode {
|
||||
function selectChallenge(): void {
|
||||
if (reducer) reducer.transition("select_challenge", { uuid: id });
|
||||
async function selectChallenge(): Promise<void> {
|
||||
if (reducer) {
|
||||
return reducer.transition("select_challenge", { uuid: id });
|
||||
}
|
||||
}
|
||||
if (!feedback) {
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
<AsyncButton
|
||||
class="button"
|
||||
disabled={
|
||||
atLeastThereIsOnePolicySolved && !policy.isPolicySolved
|
||||
@ -164,7 +167,7 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
onClick={selectChallenge}
|
||||
>
|
||||
Solve
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -178,7 +181,7 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
case ChallengeFeedbackStatus.Payment:
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
<AsyncButton
|
||||
class="button"
|
||||
disabled={
|
||||
atLeastThereIsOnePolicySolved && !policy.isPolicySolved
|
||||
@ -186,13 +189,13 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
onClick={selectChallenge}
|
||||
>
|
||||
Pay
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
);
|
||||
case ChallengeFeedbackStatus.Redirect:
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
<AsyncButton
|
||||
class="button"
|
||||
disabled={
|
||||
atLeastThereIsOnePolicySolved && !policy.isPolicySolved
|
||||
@ -200,7 +203,7 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
onClick={selectChallenge}
|
||||
>
|
||||
Go to {feedback.redirect_url}
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
);
|
||||
case ChallengeFeedbackStatus.Solved:
|
||||
@ -212,7 +215,7 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
default:
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
<AsyncButton
|
||||
class="button"
|
||||
disabled={
|
||||
atLeastThereIsOnePolicySolved && !policy.isPolicySolved
|
||||
@ -220,7 +223,7 @@ export function ChallengeOverviewScreen(): VNode {
|
||||
onClick={selectChallenge}
|
||||
>
|
||||
Solve
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { ComponentChildren, h, VNode } from "preact";
|
||||
import { AsyncButton } from "../../components/AsyncButton";
|
||||
|
||||
export interface ConfirmModelProps {
|
||||
active?: boolean;
|
||||
description?: string;
|
||||
onCancel?: () => void;
|
||||
onConfirm?: () => void;
|
||||
onConfirm?: () => Promise<void>;
|
||||
label?: string;
|
||||
cancelLabel?: string;
|
||||
children?: ComponentChildren;
|
||||
@ -33,13 +34,13 @@ export function ConfirmModal({
|
||||
{cancelLabel}
|
||||
</button>
|
||||
<div class="buttons is-right" style={{ width: "100%" }}>
|
||||
<button
|
||||
<AsyncButton
|
||||
class={danger ? "button is-danger " : "button is-info "}
|
||||
disabled={disabled}
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</AsyncButton>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
@ -1,10 +1,18 @@
|
||||
import { bytesToString, decodeCrock } from "@gnu-taler/taler-util";
|
||||
import { h, VNode } from "preact";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { QR } from "../../components/QR";
|
||||
import { useAnastasisContext } from "../../context/anastasis";
|
||||
import { AnastasisClientFrame } from "./index";
|
||||
|
||||
export function RecoveryFinishedScreen(): VNode {
|
||||
const reducer = useAnastasisContext();
|
||||
const [copied, setCopied] = useState(false)
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setCopied(false)
|
||||
},1000)
|
||||
}, [copied])
|
||||
|
||||
if (!reducer) {
|
||||
return <div>no reducer in context</div>;
|
||||
@ -15,6 +23,7 @@ export function RecoveryFinishedScreen(): VNode {
|
||||
) {
|
||||
return <div>invalid state</div>;
|
||||
}
|
||||
const secretName = reducer.currentReducerState.recovery_document?.secret_name;
|
||||
const encodedSecret = reducer.currentReducerState.core_secret;
|
||||
if (!encodedSecret) {
|
||||
return (
|
||||
@ -35,19 +44,33 @@ export function RecoveryFinishedScreen(): VNode {
|
||||
);
|
||||
}
|
||||
const secret = bytesToString(decodeCrock(encodedSecret.value));
|
||||
const contentURI = `data:${encodedSecret.mime},${secret}`
|
||||
// const fileName = encodedSecret['filename']
|
||||
// data:plain/text;base64,asdasd
|
||||
return (
|
||||
<AnastasisClientFrame title="Recovery Finished" hideNav>
|
||||
<p>Your secret: {secret}</p>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "2em",
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<button class="button" onClick={() => reducer.back()}>
|
||||
Back
|
||||
<AnastasisClientFrame title="Recovery Success" hideNav>
|
||||
<h2 class="subtitle">Your secret was recovered</h2>
|
||||
{secretName && <p class="block">
|
||||
<b>Secret name:</b> {secretName}
|
||||
</p>}
|
||||
<div class="block buttons" disabled={copied}>
|
||||
<button class="button" onClick={() => {
|
||||
navigator.clipboard.writeText(secret);
|
||||
setCopied(true)
|
||||
}}>
|
||||
{ !copied ? 'Copy' : 'Copied'}
|
||||
</button>
|
||||
<a class="button is-info" download="secret.txt" href={contentURI}>
|
||||
<div class="icon is-small ">
|
||||
<i class="mdi mdi-download" />
|
||||
</div>
|
||||
<span>
|
||||
Save as
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="block">
|
||||
<QR text={secret} />
|
||||
</div>
|
||||
</AnastasisClientFrame>
|
||||
);
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { AuthenticationProviderStatus, AuthenticationProviderStatusOk } from "anastasis-core";
|
||||
import { h, VNode } from "preact";
|
||||
import { useState } from "preact/hooks";
|
||||
import { AsyncButton } from "../../components/AsyncButton";
|
||||
@ -38,15 +39,13 @@ export function SecretSelectionScreen(): VNode {
|
||||
});
|
||||
}
|
||||
|
||||
const providerList = Object.keys(
|
||||
reducer.currentReducerState.authentication_providers ?? {},
|
||||
);
|
||||
const provs = reducer.currentReducerState.authentication_providers ?? {};
|
||||
const recoveryDocument = reducer.currentReducerState.recovery_document;
|
||||
|
||||
if (!recoveryDocument) {
|
||||
return (
|
||||
<ChooseAnotherProviderScreen
|
||||
providers={providerList}
|
||||
providers={provs}
|
||||
selected=""
|
||||
onChange={(newProv) => doSelectVersion(newProv, 0)}
|
||||
/>
|
||||
@ -56,7 +55,7 @@ export function SecretSelectionScreen(): VNode {
|
||||
if (selectingVersion) {
|
||||
return (
|
||||
<SelectOtherVersionProviderScreen
|
||||
providers={providerList}
|
||||
providers={provs}
|
||||
provider={recoveryDocument.provider_url}
|
||||
version={recoveryDocument.version}
|
||||
onCancel={() => setSelectingVersion(false)}
|
||||
@ -69,12 +68,15 @@ export function SecretSelectionScreen(): VNode {
|
||||
return <AddingProviderScreen onCancel={() => setManageProvider(false)} />;
|
||||
}
|
||||
|
||||
const provierInfo = provs[recoveryDocument.provider_url] as AuthenticationProviderStatusOk
|
||||
return (
|
||||
<AnastasisClientFrame title="Recovery: Select secret">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="box" style={{ border: "2px solid green" }}>
|
||||
<h1 class="subtitle">{recoveryDocument.provider_url}</h1>
|
||||
<h1 class="subtitle">
|
||||
{provierInfo.business_name}
|
||||
</h1>
|
||||
<div class="block">
|
||||
{currentVersion === 0 ? (
|
||||
<p>Set to recover the latest version</p>
|
||||
@ -111,7 +113,7 @@ function ChooseAnotherProviderScreen({
|
||||
onChange,
|
||||
}: {
|
||||
selected: string;
|
||||
providers: string[];
|
||||
providers: { [url: string]: AuthenticationProviderStatus };
|
||||
onChange: (prov: string) => void;
|
||||
}): VNode {
|
||||
return (
|
||||
@ -132,11 +134,13 @@ function ChooseAnotherProviderScreen({
|
||||
{" "}
|
||||
Choose a provider{" "}
|
||||
</option>
|
||||
{providers.map((prov) => (
|
||||
<option key={prov} value={prov}>
|
||||
{prov}
|
||||
{Object.keys(providers).map((url) => {
|
||||
const p = providers[url]
|
||||
if (!("methods" in p)) return null
|
||||
return <option key={url} value={url}>
|
||||
{p.business_name}
|
||||
</option>
|
||||
))}
|
||||
})}
|
||||
</select>
|
||||
<div class="icon is-small is-left">
|
||||
<i class="mdi mdi-earth" />
|
||||
@ -158,20 +162,21 @@ function SelectOtherVersionProviderScreen({
|
||||
onCancel: () => void;
|
||||
provider: string;
|
||||
version: number;
|
||||
providers: string[];
|
||||
providers: { [url: string]: AuthenticationProviderStatus };
|
||||
onConfirm: (prov: string, v: number) => Promise<void>;
|
||||
}): VNode {
|
||||
const [otherProvider, setOtherProvider] = useState<string>(provider);
|
||||
const [otherVersion, setOtherVersion] = useState(
|
||||
version > 0 ? String(version) : "",
|
||||
);
|
||||
const otherProviderInfo = providers[otherProvider] as AuthenticationProviderStatusOk
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Recovery: Select secret">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<div class="box">
|
||||
<h1 class="subtitle">Provider {otherProvider}</h1>
|
||||
<h1 class="subtitle">Provider {otherProviderInfo.business_name}</h1>
|
||||
<div class="block">
|
||||
{version === 0 ? (
|
||||
<p>Set to recover the latest version</p>
|
||||
@ -193,11 +198,13 @@ function SelectOtherVersionProviderScreen({
|
||||
{" "}
|
||||
Choose a provider{" "}
|
||||
</option>
|
||||
{providers.map((prov) => (
|
||||
<option key={prov} value={prov}>
|
||||
{prov}
|
||||
{Object.keys(providers).map((url) => {
|
||||
const p = providers[url]
|
||||
if (!("methods" in p)) return null
|
||||
return <option key={url} value={url}>
|
||||
{p.business_name}
|
||||
</option>
|
||||
))}
|
||||
})}
|
||||
</select>
|
||||
<div class="icon is-small is-left">
|
||||
<i class="mdi mdi-earth" />
|
||||
@ -242,7 +249,6 @@ function SelectOtherVersionProviderScreen({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">.</div>
|
||||
</div>
|
||||
</AnastasisClientFrame>
|
||||
);
|
||||
|
@ -10,6 +10,7 @@ import { AuthMethodSolveProps } from "./index";
|
||||
|
||||
export function AuthMethodEmailSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
const [answer, setAnswer] = useState("");
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
const reducer = useAnastasisContext();
|
||||
if (!reducer) {
|
||||
@ -86,14 +87,30 @@ export function AuthMethodEmailSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="Email challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>
|
||||
An email has been sent to "<b>{selectedChallenge.instructions}</b>".
|
||||
Type the code below.
|
||||
<b>Here we need to add the code "{selectedUuid}"</b>
|
||||
An email has been sent to "<b>{selectedChallenge.instructions}</b>". The
|
||||
message has and identification code and recovery code that starts with "<b>A-</b>".
|
||||
Wait the message to arrive and the enter the recovery code below.
|
||||
</p>
|
||||
<TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
|
||||
{!expanded ? <p>
|
||||
The identification code in the email should start with "{selectedUuid.substring(0, 10)}"
|
||||
<span class="icon has-tooltip-top" data-tooltip="click to expand" onClick={() => setExpanded(e => !e)}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
</p>
|
||||
: <p>
|
||||
The identification code in the email is "{selectedUuid}"
|
||||
<span class="icon has-tooltip-top" data-tooltip="click to show less code" onClick={() => setExpanded(e => !e)}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
</p>}
|
||||
<TextInput label="Answer"
|
||||
grabFocus
|
||||
bind={[answer, setAnswer]}
|
||||
placeholder="A-1234567812345678"
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
|
@ -86,7 +86,7 @@ export function AuthMethodIbanSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="IBAN Challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>Send a wire transfer to the address,</p>
|
||||
<button class="button">Check</button>
|
||||
|
@ -86,7 +86,7 @@ export function AuthMethodPostSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="Postal Challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>Wait for the answer</p>
|
||||
<TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
|
||||
|
@ -86,9 +86,15 @@ export function AuthMethodQuestionSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="Question challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>Answer the question please</p>
|
||||
<p>
|
||||
In this challenge you need to provide the answer for the next question:
|
||||
</p>
|
||||
<pre>
|
||||
{selectedChallenge.instructions}
|
||||
</pre>
|
||||
<p>Type the answer below</p>
|
||||
<TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
|
||||
|
||||
<div
|
||||
|
@ -11,6 +11,7 @@ import { AuthMethodSolveProps } from "./index";
|
||||
export function AuthMethodSmsSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
const [answer, setAnswer] = useState("");
|
||||
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const reducer = useAnastasisContext();
|
||||
if (!reducer) {
|
||||
return (
|
||||
@ -86,13 +87,30 @@ export function AuthMethodSmsSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="SMS Challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>
|
||||
An sms has been sent to "<b>{selectedChallenge.instructions}</b>". Type
|
||||
the code below
|
||||
An sms has been sent to "<b>{selectedChallenge.instructions}</b>". The
|
||||
message has and identification code and recovery code that starts with "<b>A-</b>".
|
||||
Wait the message to arrive and the enter the recovery code below.
|
||||
</p>
|
||||
<TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
|
||||
{!expanded ? <p>
|
||||
The identification code in the SMS should start with "{selectedUuid.substring(0, 10)}"
|
||||
<span class="icon has-tooltip-top" data-tooltip="click to expand" onClick={() => setExpanded(e => !e)}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
</p>
|
||||
: <p>
|
||||
The identification code in the SMS is "{selectedUuid}"
|
||||
<span class="icon has-tooltip-top" data-tooltip="click to show less code" onClick={() => setExpanded(e => !e)}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
</p>}
|
||||
<TextInput label="Answer"
|
||||
grabFocus
|
||||
bind={[answer, setAnswer]}
|
||||
placeholder="A-1234567812345678"
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
|
@ -86,7 +86,7 @@ export function AuthMethodTotpSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
feedback?.state === ChallengeFeedbackStatus.TruthUnknown;
|
||||
|
||||
return (
|
||||
<AnastasisClientFrame hideNav title="Add email authentication">
|
||||
<AnastasisClientFrame hideNav title="TOTP Challenge">
|
||||
<SolveOverviewFeedbackDisplay feedback={feedback} />
|
||||
<p>enter the totp solution</p>
|
||||
<TextInput label="Answer" grabFocus bind={[answer, setAnswer]} />
|
||||
@ -110,3 +110,4 @@ export function AuthMethodTotpSolve({ id }: AuthMethodSolveProps): VNode {
|
||||
</AnastasisClientFrame>
|
||||
);
|
||||
}
|
||||
// NKE8 VD857T X033X6RG WEGPYP6D70 Q7YE XN8D2 ZN79SCN 231B4QK0
|
||||
|
@ -101,7 +101,7 @@ const base = {
|
||||
"http://localhost:8086/": {
|
||||
http_status: 200,
|
||||
annual_fee: "COL:0",
|
||||
business_name: "ana",
|
||||
business_name: "Anastasis Local",
|
||||
currency: "COL",
|
||||
liability_limit: "COL:10",
|
||||
methods: [
|
||||
@ -125,7 +125,7 @@ const base = {
|
||||
"https://kudos.demo.anastasis.lu/": {
|
||||
http_status: 200,
|
||||
annual_fee: "COL:0",
|
||||
business_name: "ana",
|
||||
business_name: "Anastasis Kudo",
|
||||
currency: "COL",
|
||||
liability_limit: "COL:10",
|
||||
methods: [
|
||||
@ -145,7 +145,7 @@ const base = {
|
||||
"https://anastasis.demo.taler.net/": {
|
||||
http_status: 200,
|
||||
annual_fee: "COL:0",
|
||||
business_name: "ana",
|
||||
business_name: "Anastasis Demo",
|
||||
currency: "COL",
|
||||
liability_limit: "COL:10",
|
||||
methods: [
|
||||
@ -180,9 +180,6 @@ const base = {
|
||||
hint: "request to provider failed",
|
||||
},
|
||||
},
|
||||
// expiration: {
|
||||
// d_ms: 1792525051855 // check t_ms
|
||||
// },
|
||||
} as Partial<ReducerState>;
|
||||
|
||||
export const reducerStatesExample = {
|
||||
|
Loading…
Reference in New Issue
Block a user