diff options
Diffstat (limited to 'packages/anastasis-webui/src')
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 +  }]} />    );  } | 
