aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/anastasis-webui/src/components/AsyncButton.tsx2
-rw-r--r--packages/anastasis-webui/src/components/Notifications.tsx59
-rw-r--r--packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx7
-rw-r--r--packages/anastasis-webui/src/pages/home/SolveScreen.tsx9
-rw-r--r--packages/anastasis-webui/src/pages/home/StartScreen.tsx4
-rw-r--r--packages/anastasis-webui/src/pages/home/index.tsx32
6 files changed, 84 insertions, 29 deletions
diff --git a/packages/anastasis-webui/src/components/AsyncButton.tsx b/packages/anastasis-webui/src/components/AsyncButton.tsx
index af85016e8..bb2cc0fd8 100644
--- a/packages/anastasis-webui/src/components/AsyncButton.tsx
+++ b/packages/anastasis-webui/src/components/AsyncButton.tsx
@@ -26,7 +26,7 @@ import { useAsync } from "../hooks/async";
type Props = {
children: ComponentChildren;
- disabled: boolean;
+ disabled?: boolean;
onClick?: () => Promise<void>;
[rest: string]: any;
};
diff --git a/packages/anastasis-webui/src/components/Notifications.tsx b/packages/anastasis-webui/src/components/Notifications.tsx
new file mode 100644
index 000000000..c916020d7
--- /dev/null
+++ b/packages/anastasis-webui/src/components/Notifications.tsx
@@ -0,0 +1,59 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { h, VNode } from "preact";
+
+export interface Notification {
+ message: string;
+ description?: string | VNode;
+ type: MessageType;
+}
+
+export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS'
+
+interface Props {
+ notifications: Notification[];
+ removeNotification?: (n: Notification) => void;
+}
+
+function messageStyle(type: MessageType): string {
+ switch (type) {
+ case "INFO": return "message is-info";
+ case "WARN": return "message is-warning";
+ case "ERROR": return "message is-danger";
+ case "SUCCESS": return "message is-success";
+ default: return "message"
+ }
+}
+
+export function Notifications({ notifications, removeNotification }: Props): VNode {
+ return <div class="block">
+ {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)} />
+ </div>
+ {n.description && <div class="message-body">
+ {n.description}
+ </div>}
+ </article>)}
+ </div>
+} \ No newline at end of file
diff --git a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
index 3740592b1..a61ef9efa 100644
--- a/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/RecoveryFinishedScreen.tsx
@@ -15,15 +15,18 @@ export function RecoveryFinishedScreen(): VNode {
if (!reducer.currentReducerState || reducer.currentReducerState.recovery_state === undefined) {
return <div>invalid state</div>
}
- const encodedSecret = reducer.currentReducerState.core_secret?.value
+ const encodedSecret = reducer.currentReducerState.core_secret
if (!encodedSecret) {
return <AnastasisClientFrame title="Recovery Problem" hideNav>
<p>
Secret not found
</p>
+ <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
+ <button class="button" onClick={() => reducer.back()}>Back</button>
+ </div>
</AnastasisClientFrame>
}
- const secret = bytesToString(decodeCrock(encodedSecret))
+ const secret = bytesToString(decodeCrock(encodedSecret.value))
return (
<AnastasisClientFrame title="Recovery Finished" hideNav>
<p>
diff --git a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
index df55de6ab..fae1b5631 100644
--- a/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/SolveScreen.tsx
@@ -6,6 +6,7 @@ import {
ChallengeFeedbackStatus,
ChallengeInfo,
} from "../../../../anastasis-core/lib";
+import { AsyncButton } from "../../components/AsyncButton";
import { TextInput } from "../../components/fields/TextInput";
import { useAnastasisContext } from "../../context/anastasis";
@@ -106,8 +107,8 @@ export function SolveScreen(): VNode {
? SolveUndefinedEntry
: dialogMap[selectedChallenge.type] ?? SolveUnsupportedEntry;
- function onNext(): void {
- reducer?.transition("solve_challenge", { answer });
+ async function onNext(): Promise<void> {
+ return reducer?.transition("solve_challenge", { answer });
}
function onCancel(): void {
reducer?.back();
@@ -136,9 +137,9 @@ export function SolveScreen(): VNode {
<button class="button" onClick={onCancel}>
Cancel
</button>
- <button class="button is-info" onClick={onNext}>
+ <AsyncButton onClick={onNext} disabled={false}>
Confirm
- </button>
+ </AsyncButton>
</div>
</AnastasisClientFrame>
);
diff --git a/packages/anastasis-webui/src/pages/home/StartScreen.tsx b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
index 6e97eb586..d53df4cae 100644
--- a/packages/anastasis-webui/src/pages/home/StartScreen.tsx
+++ b/packages/anastasis-webui/src/pages/home/StartScreen.tsx
@@ -25,10 +25,10 @@ export function StartScreen(): VNode {
<span>Recover a secret</span>
</button>
- <button class="button">
+ {/* <button class="button">
<div class="icon"><i class="mdi mdi-file" /></div>
<span>Restore a session</span>
- </button>
+ </button> */}
</div>
</div>
diff --git a/packages/anastasis-webui/src/pages/home/index.tsx b/packages/anastasis-webui/src/pages/home/index.tsx
index 346738c26..6ebc2a6e9 100644
--- a/packages/anastasis-webui/src/pages/home/index.tsx
+++ b/packages/anastasis-webui/src/pages/home/index.tsx
@@ -15,6 +15,7 @@ import {
} from "preact/hooks";
import { AsyncButton } from "../../components/AsyncButton";
import { Menu } from "../../components/menu";
+import { Notifications } from "../../components/Notifications";
import { AnastasisProvider, useAnastasisContext } from "../../context/anastasis";
import {
AnastasisReducerApi,
@@ -96,18 +97,11 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
return <p>Fatal: Reducer must be in context.</p>;
}
const next = async (): Promise<void> => {
- return new Promise(async (res, rej) => {
- try {
- if (props.onNext) {
- await props.onNext();
- } else {
- await reducer.transition("next", {});
- }
- res()
- } catch {
- rej()
- }
- })
+ if (props.onNext) {
+ await props.onNext();
+ } else {
+ await reducer.transition("next", {});
+ }
};
const handleKeyPress = (
e: h.JSX.TargetedKeyboardEvent<HTMLDivElement>,
@@ -120,8 +114,8 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode {
<Menu title="Anastasis" />
<div class="home" onKeyPress={(e) => handleKeyPress(e)}>
<h1 class="title">{props.title}</h1>
+ <ErrorBanner />
<section class="section is-main-section">
- <ErrorBanner />
{props.children}
{!props.hideNav ? (
<div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}>
@@ -242,13 +236,11 @@ const AnastasisClientImpl: FunctionalComponent = () => {
function ErrorBanner(): VNode | null {
const reducer = useAnastasisContext();
if (!reducer || !reducer.currentError) return null;
- return (
- <div id="error">
- <p>Error: {JSON.stringify(reducer.currentError)}</p>
- <button onClick={() => reducer.dismissError()}>
- Dismiss Error
- </button>
- </div>
+ return (<Notifications removeNotification={reducer.dismissError} notifications={[{
+ type: "ERROR",
+ message: `Error code: ${reducer.currentError.code}`,
+ description: reducer.currentError.hint
+ }]} />
);
}