gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 02/19: no-fix: move pagestate provider to app compon


From: gnunet
Subject: [taler-wallet-core] 02/19: no-fix: move pagestate provider to app component and move some common hooks to web-utils
Date: Wed, 07 Dec 2022 20:08:30 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit 8e6bf990069b9c3ae033321b5aeb4d46fa6501e6
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed Dec 7 09:06:10 2022 -0300

    no-fix: move pagestate provider to app component and move some common hooks 
to web-utils
---
 packages/demobank-ui/src/components/app.tsx        |   5 +-
 packages/demobank-ui/src/context/pageState.ts      | 121 +++++++
 packages/demobank-ui/src/context/translation.ts    |   4 +-
 packages/demobank-ui/src/declaration.d.ts          |  49 +++
 packages/demobank-ui/src/hooks/index.ts            |  10 +-
 packages/demobank-ui/src/pages/home/index.tsx      | 384 +++++----------------
 packages/demobank-ui/src/settings.ts               |  27 ++
 packages/web-util/src/hooks/index.ts               |   3 +
 .../{demobank-ui => web-util}/src/hooks/useLang.ts |   0
 .../src/hooks/useLocalStorage.ts                   |   0
 packages/web-util/src/index.browser.ts             |  37 +-
 packages/web-util/src/live-reload.ts               |   2 +-
 12 files changed, 306 insertions(+), 336 deletions(-)

diff --git a/packages/demobank-ui/src/components/app.tsx 
b/packages/demobank-ui/src/components/app.tsx
index 49b218205..91410a485 100644
--- a/packages/demobank-ui/src/components/app.tsx
+++ b/packages/demobank-ui/src/components/app.tsx
@@ -1,11 +1,14 @@
 import { h, FunctionalComponent } from "preact";
+import { PageStateProvider } from "../context/pageState.js";
 import { TranslationProvider } from "../context/translation.js";
 import { BankHome } from "../pages/home/index.js";
 
 const App: FunctionalComponent = () => {
   return (
     <TranslationProvider>
-      <BankHome />
+      <PageStateProvider>
+        <BankHome />
+      </PageStateProvider>
     </TranslationProvider>
   );
 };
diff --git a/packages/demobank-ui/src/context/pageState.ts 
b/packages/demobank-ui/src/context/pageState.ts
new file mode 100644
index 000000000..3d7ccd85b
--- /dev/null
+++ b/packages/demobank-ui/src/context/pageState.ts
@@ -0,0 +1,121 @@
+/*
+ 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/>
+ */
+
+import { hooks } from "@gnu-taler/web-util/lib/index.browser";
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { StateUpdater, useContext } from "preact/hooks";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export type Type = {
+  pageState: PageStateType;
+  pageStateSetter: StateUpdater<PageStateType>;
+};
+const initial: Type = {
+  pageState: {
+    isLoggedIn: false,
+    isRawPayto: false,
+    showPublicHistories: false,
+    withdrawalInProgress: false,
+  },
+  pageStateSetter: () => {
+    null;
+  },
+};
+const Context = createContext<Type>(initial);
+
+export const usePageContext = (): Type => useContext(Context);
+
+export const PageStateProvider = ({
+  children,
+}: {
+  children: ComponentChildren;
+}): VNode => {
+  const [pageState, pageStateSetter] = usePageState();
+
+  return h(Context.Provider, {
+    value: { pageState, pageStateSetter },
+    children,
+  });
+};
+
+/**
+ * Wrapper providing defaults.
+ */
+function usePageState(
+  state: PageStateType = {
+    isLoggedIn: false,
+    isRawPayto: false,
+    showPublicHistories: false,
+    withdrawalInProgress: false,
+  },
+): [PageStateType, StateUpdater<PageStateType>] {
+  const ret = hooks.useNotNullLocalStorage("page-state", 
JSON.stringify(state));
+  const retObj: PageStateType = JSON.parse(ret[0]);
+
+  const retSetter: StateUpdater<PageStateType> = function (val) {
+    const newVal =
+      val instanceof Function
+        ? JSON.stringify(val(retObj))
+        : JSON.stringify(val);
+
+    ret[1](newVal);
+  };
+
+  //when moving from one page to another
+  //clean up the info and error bar
+  function removeLatestInfo(val: any): ReturnType<typeof retSetter> {
+    const updater = typeof val === "function" ? val : (c: any) => val;
+    return retSetter((current: any) => {
+      const cleanedCurrent: PageStateType = {
+        ...current,
+        info: undefined,
+        errors: undefined,
+        timestamp: new Date().getTime(),
+      };
+      return updater(cleanedCurrent);
+    });
+  }
+
+  return [retObj, removeLatestInfo];
+}
+
+/**
+ * Track page state.
+ */
+export interface PageStateType {
+  isLoggedIn: boolean;
+  isRawPayto: boolean;
+  showPublicHistories: boolean;
+  withdrawalInProgress: boolean;
+  error?: {
+    description?: string;
+    title: string;
+    debug?: string;
+  };
+
+  info?: string;
+  talerWithdrawUri?: string;
+  /**
+   * Not strictly a presentational value, could
+   * be moved in a future "withdrawal state" object.
+   */
+  withdrawalId?: string;
+  timestamp?: number;
+}
diff --git a/packages/demobank-ui/src/context/translation.ts 
b/packages/demobank-ui/src/context/translation.ts
index a50f81b86..478bdbde0 100644
--- a/packages/demobank-ui/src/context/translation.ts
+++ b/packages/demobank-ui/src/context/translation.ts
@@ -22,7 +22,7 @@
 import { i18n, setupI18n } from "@gnu-taler/taler-util";
 import { createContext, h, VNode } from "preact";
 import { useContext, useEffect } from "preact/hooks";
-import { useLang } from "../hooks/useLang.js";
+import { hooks } from "@gnu-taler/web-util/lib/index.browser";
 import { strings } from "../i18n/strings.js";
 
 interface Type {
@@ -70,7 +70,7 @@ export const TranslationProvider = ({
   children,
   forceLang,
 }: Props): VNode => {
-  const [lang, changeLanguage, isSaved] = useLang(initial);
+  const [lang, changeLanguage, isSaved] = hooks.useLang(initial);
   useEffect(() => {
     if (forceLang) {
       changeLanguage(forceLang);
diff --git a/packages/demobank-ui/src/declaration.d.ts 
b/packages/demobank-ui/src/declaration.d.ts
index 00b3d41d5..084686bd2 100644
--- a/packages/demobank-ui/src/declaration.d.ts
+++ b/packages/demobank-ui/src/declaration.d.ts
@@ -18,3 +18,52 @@ declare module "jed" {
   const x: any;
   export = x;
 }
+
+/**********************************************
+ * Type definitions for states and API calls. *
+ *********************************************/
+
+/**
+ * Has the information to reach and
+ * authenticate at the bank's backend.
+ */
+interface BackendStateType {
+  url?: string;
+  username?: string;
+  password?: string;
+}
+
+/**
+ * Request body of POST /transactions.
+ *
+ * If the amount appears twice: both as a Payto parameter and
+ * in the JSON dedicate field, the one on the Payto URI takes
+ * precedence.
+ */
+interface TransactionRequestType {
+  paytoUri: string;
+  amount?: string; // with currency.
+}
+
+/**
+ * Request body of /register.
+ */
+interface CredentialsRequestType {
+  username?: string;
+  password?: string;
+  repeatPassword?: string;
+}
+
+/**
+ * Request body of /register.
+ */
+// interface LoginRequestType {
+//   username: string;
+//   password: string;
+// }
+
+interface WireTransferRequestType {
+  iban?: string;
+  subject?: string;
+  amount?: string;
+}
diff --git a/packages/demobank-ui/src/hooks/index.ts 
b/packages/demobank-ui/src/hooks/index.ts
index b4191d182..c6e3fe8c1 100644
--- a/packages/demobank-ui/src/hooks/index.ts
+++ b/packages/demobank-ui/src/hooks/index.ts
@@ -20,7 +20,7 @@
  */
 
 import { StateUpdater } from "preact/hooks";
-import { useLocalStorage, useNotNullLocalStorage } from "./useLocalStorage.js";
+import { hooks } from "@gnu-taler/web-util/lib/index.browser";
 export type ValueOrFunction<T> = T | ((p: T) => T);
 
 const calculateRootPath = () => {
@@ -34,11 +34,11 @@ const calculateRootPath = () => {
 export function useBackendURL(
   url?: string,
 ): [string, boolean, StateUpdater<string>, () => void] {
-  const [value, setter] = useNotNullLocalStorage(
+  const [value, setter] = hooks.useNotNullLocalStorage(
     "backend-url",
     url || calculateRootPath(),
   );
-  const [triedToLog, setTriedToLog] = useLocalStorage("tried-login");
+  const [triedToLog, setTriedToLog] = hooks.useLocalStorage("tried-login");
 
   const checkedSetter = (v: ValueOrFunction<string>) => {
     setTriedToLog("yes");
@@ -55,13 +55,13 @@ export function useBackendDefaultToken(): [
   string | undefined,
   StateUpdater<string | undefined>,
 ] {
-  return useLocalStorage("backend-token");
+  return hooks.useLocalStorage("backend-token");
 }
 
 export function useBackendInstanceToken(
   id: string,
 ): [string | undefined, StateUpdater<string | undefined>] {
-  const [token, setToken] = useLocalStorage(`backend-token-${id}`);
+  const [token, setToken] = hooks.useLocalStorage(`backend-token-${id}`);
   const [defaultToken, defaultSetToken] = useBackendDefaultToken();
 
   // instance named 'default' use the default token
diff --git a/packages/demobank-ui/src/pages/home/index.tsx 
b/packages/demobank-ui/src/pages/home/index.tsx
index 8b2ffefac..a64c4abe3 100644
--- a/packages/demobank-ui/src/pages/home/index.tsx
+++ b/packages/demobank-ui/src/pages/home/index.tsx
@@ -27,44 +27,14 @@ import {
 } from "preact/hooks";
 import talerLogo from "../../assets/logo-white.svg";
 import { LangSelectorLikePy as LangSelector } from 
"../../components/menu/LangSelector.js";
-import {
-  useLocalStorage,
-  useNotNullLocalStorage,
-} from "../../hooks/useLocalStorage.js";
-// import { Translate, useTranslator } from "../../i18n/index.js";
 import { useTranslationContext } from "../../context/translation.js";
 import { Amounts, HttpStatusCode, parsePaytoUri } from "@gnu-taler/taler-util";
 import { createHashHistory } from "history";
 import Router, { Route, route } from "preact-router";
 import { QrCodeSection } from "./QrCodeSection.js";
-
-interface BankUiSettings {
-  allowRegistrations: boolean;
-  showDemoNav: boolean;
-  bankName: string;
-  demoSites: [string, string][];
-}
-
-/**
- * Global settings for the demobank UI.
- */
-const defaultSettings: BankUiSettings = {
-  allowRegistrations: true,
-  bankName: "Taler Bank",
-  showDemoNav: true,
-  demoSites: [
-    ["Landing", "https://demo.taler.net/";],
-    ["Bank", "https://bank.demo.taler.net/";],
-    ["Essay Shop", "https://shop.demo.taler.net/";],
-    ["Donations", "https://donations.demo.taler.net/";],
-    ["Survey", "https://survey.demo.taler.net/";],
-  ],
-};
-
-const bankUiSettings: BankUiSettings =
-  "talerDemobankSettings" in globalThis
-    ? (globalThis as any).talerDemobankSettings
-    : defaultSettings;
+import { hooks } from "@gnu-taler/web-util/lib/index.browser";
+import { bankUiSettings } from "../../settings.js";
+import { PageStateType, usePageContext } from "../../context/pageState.js";
 
 /**
  * FIXME:
@@ -90,94 +60,6 @@ const bankUiSettings: BankUiSettings =
 /************
  * Contexts *
  ***********/
-const CurrencyContext = createContext<any>(null);
-type PageContextType = [PageStateType, StateUpdater<PageStateType>];
-const PageContextDefault: PageContextType = [
-  {
-    isLoggedIn: false,
-    isRawPayto: false,
-    showPublicHistories: false,
-
-    withdrawalInProgress: false,
-  },
-  () => {
-    null;
-  },
-];
-const PageContext = createContext<PageContextType>(PageContextDefault);
-
-/**********************************************
- * Type definitions for states and API calls. *
- *********************************************/
-
-/**
- * Has the information to reach and
- * authenticate at the bank's backend.
- */
-interface BackendStateType {
-  url?: string;
-  username?: string;
-  password?: string;
-}
-
-/**
- * Request body of POST /transactions.
- *
- * If the amount appears twice: both as a Payto parameter and
- * in the JSON dedicate field, the one on the Payto URI takes
- * precedence.
- */
-interface TransactionRequestType {
-  paytoUri: string;
-  amount?: string; // with currency.
-}
-
-/**
- * Request body of /register.
- */
-interface CredentialsRequestType {
-  username?: string;
-  password?: string;
-  repeatPassword?: string;
-}
-
-/**
- * Request body of /register.
- */
-// interface LoginRequestType {
-//   username: string;
-//   password: string;
-// }
-
-interface WireTransferRequestType {
-  iban?: string;
-  subject?: string;
-  amount?: string;
-}
-
-/**
- * Track page state.
- */
-interface PageStateType {
-  isLoggedIn: boolean;
-  isRawPayto: boolean;
-  showPublicHistories: boolean;
-  withdrawalInProgress: boolean;
-  error?: {
-    description?: string;
-    title: string;
-    debug?: string;
-  };
-
-  info?: string;
-  talerWithdrawUri?: string;
-  /**
-   * Not strictly a presentational value, could
-   * be moved in a future "withdrawal state" object.
-   */
-  withdrawalId?: string;
-  timestamp?: number;
-}
 
 /**
  * Bank account specific information.
@@ -294,7 +176,7 @@ async function postToBackend(
 }
 
 function useTransactionPageNumber(): [number, StateUpdater<number>] {
-  const ret = useNotNullLocalStorage("transaction-page", "0");
+  const ret = hooks.useNotNullLocalStorage("transaction-page", "0");
   const retObj = JSON.parse(ret[0]);
   const retSetter: StateUpdater<number> = function (val) {
     const newVal =
@@ -347,7 +229,10 @@ const getBankBackendBaseUrl = (): string => {
 function useShowPublicAccount(
   state?: string,
 ): [string | undefined, StateUpdater<string | undefined>] {
-  const ret = useLocalStorage("show-public-account", JSON.stringify(state));
+  const ret = hooks.useLocalStorage(
+    "show-public-account",
+    JSON.stringify(state),
+  );
   const retObj: string | undefined = ret[0] ? JSON.parse(ret[0]) : ret[0];
   const retSetter: StateUpdater<string | undefined> = function (val) {
     const newVal =
@@ -367,7 +252,7 @@ type RawPaytoInputTypeOpt = RawPaytoInputType | undefined;
 function useRawPaytoInputType(
   state?: RawPaytoInputType,
 ): [RawPaytoInputTypeOpt, StateUpdater<RawPaytoInputTypeOpt>] {
-  const ret = useLocalStorage("raw-payto-input-state", state);
+  const ret = hooks.useLocalStorage("raw-payto-input-state", state);
   const retObj: RawPaytoInputTypeOpt = ret[0];
   const retSetter: StateUpdater<RawPaytoInputTypeOpt> = function (val) {
     const newVal = val instanceof Function ? val(retObj) : val;
@@ -387,7 +272,7 @@ type WireTransferRequestTypeOpt = WireTransferRequestType | 
undefined;
 function useWireTransferRequestType(
   state?: WireTransferRequestType,
 ): [WireTransferRequestTypeOpt, StateUpdater<WireTransferRequestTypeOpt>] {
-  const ret = useLocalStorage(
+  const ret = hooks.useLocalStorage(
     "wire-transfer-request-state",
     JSON.stringify(state),
   );
@@ -413,7 +298,7 @@ type CredentialsRequestTypeOpt = CredentialsRequestType | 
undefined;
 function useCredentialsRequestType(
   state?: CredentialsRequestType,
 ): [CredentialsRequestTypeOpt, StateUpdater<CredentialsRequestTypeOpt>] {
-  const ret = useLocalStorage(
+  const ret = hooks.useLocalStorage(
     "credentials-request-state",
     JSON.stringify(state),
   );
@@ -439,7 +324,7 @@ type BackendStateTypeOpt = BackendStateType | undefined;
 function useBackendState(
   state?: BackendStateType,
 ): [BackendStateTypeOpt, StateUpdater<BackendStateTypeOpt>] {
-  const ret = useLocalStorage("backend-state", JSON.stringify(state));
+  const ret = hooks.useLocalStorage("backend-state", JSON.stringify(state));
   const retObj: BackendStateTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0];
   const retSetter: StateUpdater<BackendStateTypeOpt> = function (val) {
     const newVal =
@@ -451,67 +336,6 @@ function useBackendState(
   return [retObj, retSetter];
 }
 
-/**
- * Keep mere business information, like account balance or
- * transactions history.
- */
-// type AccountStateTypeOpt = AccountStateType | undefined;
-// function useAccountState(
-//   state?: AccountStateType,
-// ): [AccountStateTypeOpt, StateUpdater<AccountStateTypeOpt>] {
-//   const ret = useLocalStorage("account-state", JSON.stringify(state));
-//   const retObj: AccountStateTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0];
-//   const retSetter: StateUpdater<AccountStateTypeOpt> = function (val) {
-//     const newVal =
-//       val instanceof Function
-//         ? JSON.stringify(val(retObj))
-//         : JSON.stringify(val);
-//     ret[1](newVal);
-//   };
-//   return [retObj, retSetter];
-// }
-
-/**
- * Wrapper providing defaults.
- */
-function usePageState(
-  state: PageStateType = {
-    isLoggedIn: false,
-    isRawPayto: false,
-    showPublicHistories: false,
-    withdrawalInProgress: false,
-  },
-): [PageStateType, StateUpdater<PageStateType>] {
-  const ret = useNotNullLocalStorage("page-state", JSON.stringify(state));
-  const retObj: PageStateType = JSON.parse(ret[0]);
-
-  const retSetter: StateUpdater<PageStateType> = function (val) {
-    const newVal =
-      val instanceof Function
-        ? JSON.stringify(val(retObj))
-        : JSON.stringify(val);
-
-    ret[1](newVal);
-  };
-
-  //when moving from one page to another
-  //clean up the info and error bar
-  function removeLatestInfo(val: any): ReturnType<typeof retSetter> {
-    const updater = typeof val === "function" ? val : (c: any) => val;
-    return retSetter((current: any) => {
-      const cleanedCurrent: PageStateType = {
-        ...current,
-        info: undefined,
-        errors: undefined,
-        timestamp: new Date().getTime(),
-      };
-      return updater(cleanedCurrent);
-    });
-  }
-
-  return [retObj, removeLatestInfo];
-}
-
 /**
  * Request preparators.
  *
@@ -1045,7 +869,7 @@ function StatusBanner(Props: any): VNode | null {
 
 function BankFrame(Props: any): VNode {
   const { i18n } = useTranslationContext();
-  const [pageState, pageStateSetter] = useContext(PageContext);
+  const { pageState, pageStateSetter } = usePageContext();
   console.log("BankFrame state", pageState);
   const logOut = (
     <div class="logout">
@@ -1164,19 +988,16 @@ function ShowInputErrorLabel({
 }
 
 function PaytoWireTransfer(Props: any): VNode {
-  const currency = useContext(CurrencyContext);
-  const [pageState, pageStateSetter] = useContext(PageContext); // NOTE: used 
for go-back button?
+  const { pageState, pageStateSetter } = usePageContext(); // NOTE: used for 
go-back button?
+
   const [submitData, submitDataSetter] = useWireTransferRequestType();
-  // const [rawPaytoInput, rawPaytoInputSetter] = useRawPaytoInputType();
+
   const [rawPaytoInput, rawPaytoInputSetter] = useState<string | undefined>(
     undefined,
   );
   const { i18n } = useTranslationContext();
-  const { focus, backendState } = Props;
-  const amountRegex = "^[0-9]+(.[0-9]+)?$";
+  const { focus, backendState, currency } = Props;
   const ibanRegex = "^[A-Z][A-Z][0-9]+$";
-  const receiverInput = "";
-  const subjectInput = "";
   let transactionData: TransactionRequestType;
   const ref = useRef<HTMLInputElement>(null);
   useEffect(() => {
@@ -1213,7 +1034,7 @@ function PaytoWireTransfer(Props: any): VNode {
   if (!pageState.isRawPayto)
     return (
       <div>
-        <div class="pure-form" name="wire-transfer-form">
+        <form class="pure-form" name="wire-transfer-form">
           <p>
             <label for="iban">{i18n.str`Receiver IBAN:`}</label>&nbsp;
             <input
@@ -1260,6 +1081,16 @@ function PaytoWireTransfer(Props: any): VNode {
             />
             <br />
             <label for="amount">{i18n.str`Amount:`}</label>&nbsp;
+            <input
+              type="text"
+              readonly
+              class="currency-indicator"
+              size={currency.length}
+              maxLength={currency.length}
+              tabIndex={-1}
+              value={currency}
+            />
+            &nbsp;
             <input
               type="number"
               name="amount"
@@ -1267,7 +1098,6 @@ function PaytoWireTransfer(Props: any): VNode {
               placeholder="amount"
               required
               value={submitData?.amount ?? ""}
-              pattern={amountRegex}
               onInput={(e): void => {
                 submitDataSetter((submitData: any) => ({
                   ...submitData,
@@ -1275,16 +1105,6 @@ function PaytoWireTransfer(Props: any): VNode {
                 }));
               }}
             />
-            &nbsp;
-            <input
-              type="text"
-              readonly
-              class="currency-indicator"
-              size={currency.length}
-              maxLength={currency.length}
-              tabIndex={-1}
-              value={currency}
-            />
             <ShowInputErrorLabel
               message={errorsWire?.amount}
               isDirty={submitData?.amount !== undefined}
@@ -1349,7 +1169,7 @@ function PaytoWireTransfer(Props: any): VNode {
               }}
             />
           </p>
-        </div>
+        </form>
         <p>
           <a
             href="/account"
@@ -1460,7 +1280,7 @@ function PaytoWireTransfer(Props: any): VNode {
  * Not providing a back button, only abort.
  */
 function TalerWithdrawalConfirmationQuestion(Props: any): VNode {
-  const [pageState, pageStateSetter] = useContext(PageContext);
+  const { pageState, pageStateSetter } = usePageContext();
   const { backendState } = Props;
   const { i18n } = useTranslationContext();
   const captchaNumbers = {
@@ -1474,7 +1294,7 @@ function TalerWithdrawalConfirmationQuestion(Props: any): 
VNode {
       <h1 class="nav">{i18n.str`Confirm Withdrawal`}</h1>
       <article>
         <div class="challenge-div">
-          <form class="challenge-form">
+          <form class="challenge-form" noValidate>
             <div class="pure-form" id="captcha" name="capcha-form">
               <h2>{i18n.str`Authorize withdrawal by solving challenge`}</h2>
               <p>
@@ -1562,8 +1382,8 @@ function TalerWithdrawalConfirmationQuestion(Props: any): 
VNode {
  */
 function TalerWithdrawalQRCode(Props: any): VNode {
   // turns true when the wallet POSTed the reserve details:
-  const [pageState, pageStateSetter] = useContext(PageContext);
-  const { withdrawalId, talerWithdrawUri, accountLabel, backendState } = Props;
+  const { pageState, pageStateSetter } = usePageContext();
+  const { withdrawalId, talerWithdrawUri, backendState } = Props;
   const { i18n } = useTranslationContext();
   const abortButton = (
     <a
@@ -1647,29 +1467,35 @@ function TalerWithdrawalQRCode(Props: any): VNode {
 }
 
 function WalletWithdraw(Props: any): VNode {
-  const { backendState, pageStateSetter, focus } = Props;
-  const currency = useContext(CurrencyContext);
+  const { backendState, pageStateSetter, focus, currency } = Props;
   const { i18n } = useTranslationContext();
   let submitAmount = "5.00";
-  const amountRegex = "^[0-9]+(.[0-9]+)?$";
 
   const ref = useRef<HTMLInputElement>(null);
   useEffect(() => {
     if (focus) ref.current?.focus();
   }, [focus]);
   return (
-    <div id="reserve-form" class="pure-form" name="tform">
+    <form id="reserve-form" class="pure-form" name="tform">
       <p>
         <label for="withdraw-amount">{i18n.str`Amount to withdraw:`}</label>
         &nbsp;
+        <input
+          type="text"
+          readonly
+          class="currency-indicator"
+          size={currency.length}
+          maxLength={currency.length}
+          tabIndex={-1}
+          value={currency}
+        />
+        &nbsp;
         <input
           type="number"
           ref={ref}
           id="withdraw-amount"
           name="withdraw-amount"
           value={submitAmount}
-          pattern={amountRegex}
-          class="amount"
           onChange={(e): void => {
             // FIXME: validate using 'parseAmount()',
             // deactivate submit button as long as
@@ -1677,16 +1503,6 @@ function WalletWithdraw(Props: any): VNode {
             submitAmount = e.currentTarget.value;
           }}
         />
-        &nbsp;
-        <input
-          type="text"
-          readonly
-          class="currency-indicator"
-          size={currency.length}
-          maxLength={currency.length}
-          tabIndex={-1}
-          value={currency}
-        />
       </p>
       <p>
         <div>
@@ -1712,7 +1528,7 @@ function WalletWithdraw(Props: any): VNode {
           />
         </div>
       </p>
-    </div>
+    </form>
   );
 }
 
@@ -1721,8 +1537,7 @@ function WalletWithdraw(Props: any): VNode {
  * then specify the details trigger the action.
  */
 function PaymentOptions(Props: any): VNode {
-  const { backendState, pageStateSetter, focus } = Props;
-  const currency = useContext(CurrencyContext);
+  const { backendState, pageStateSetter, currency } = Props;
   const { i18n } = useTranslationContext();
 
   const [tab, setTab] = useState<"charge-wallet" | "wire-transfer">(
@@ -1756,6 +1571,7 @@ function PaymentOptions(Props: any): VNode {
             <WalletWithdraw
               backendState={backendState}
               focus
+              currency={currency}
               pageStateSetter={pageStateSetter}
             />
           </div>
@@ -1766,6 +1582,7 @@ function PaymentOptions(Props: any): VNode {
             <PaytoWireTransfer
               backendState={backendState}
               focus
+              currency={currency}
               pageStateSetter={pageStateSetter}
             />
           </div>
@@ -1819,7 +1636,7 @@ function LoginForm(Props: any): VNode {
 
   return (
     <div class="login-div">
-      <form action="javascript:void(0);" class="login-form">
+      <form action="javascript:void(0);" class="login-form" noValidate>
         <div class="pure-form">
           <h2>{i18n.str`Please login!`}</h2>
           <p class="unameFieldLabel loginFieldLabel formFieldLabel">
@@ -1903,7 +1720,7 @@ function LoginForm(Props: any): VNode {
  */
 function RegistrationForm(Props: any): VNode {
   // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  const [pageState, pageStateSetter] = useContext(PageContext);
+  const { pageState, pageStateSetter } = usePageContext();
   const [submitData, submitDataSetter] = useCredentialsRequestType();
   const { i18n } = useTranslationContext();
 
@@ -1924,7 +1741,7 @@ function RegistrationForm(Props: any): VNode {
       <h1 class="nav">{i18n.str`Welcome to ${bankUiSettings.bankName}!`}</h1>
       <article>
         <div class="register-div">
-          <form action="javascript:void(0);" class="register-form">
+          <form action="javascript:void(0);" class="register-form" noValidate>
             <div class="pure-form">
               <h2>{i18n.str`Please register!`}</h2>
               <p class="unameFieldLabel registerFieldLabel formFieldLabel">
@@ -2140,7 +1957,7 @@ function Account(Props: any): VNode {
     // revalidateOnFocus: false,
     // revalidateOnReconnect: false,
   });
-  const [pageState, setPageState] = useContext(PageContext);
+  const { pageState, pageStateSetter: setPageState } = usePageContext();
   const {
     withdrawalInProgress,
     withdrawalId,
@@ -2275,14 +2092,11 @@ function Account(Props: any): VNode {
       <section id="payments">
         <div class="payments">
           <h2>{i18n.str`Payments`}</h2>
-          {/* FIXME: turn into button! */}
-          <CurrencyContext.Provider value={balance.currency}>
-            {Props.children}
-            <PaymentOptions
-              backendState={backendState}
-              pageStateSetter={setPageState}
-            />
-          </CurrencyContext.Provider>
+          <PaymentOptions
+            currency={balance.currency}
+            backendState={backendState}
+            pageStateSetter={setPageState}
+          />
         </div>
       </section>
       <section id="main">
@@ -2439,71 +2253,61 @@ function PublicHistories(Props: any): VNode {
 }
 
 function PublicHistoriesPage(): VNode {
-  // const [backendState, backendStateSetter] = useBackendState();
-  const [pageState, pageStateSetter] = usePageState();
+  const { pageState, pageStateSetter } = usePageContext();
   // const { i18n } = useTranslationContext();
   return (
     <SWRWithoutCredentials baseUrl={getBankBackendBaseUrl()}>
-      <PageContext.Provider value={[pageState, pageStateSetter]}>
-        <BankFrame>
-          <PublicHistories pageStateSetter={pageStateSetter}>
-            <br />
-            <a
-              class="pure-button"
-              onClick={() => {
-                pageStateSetter((prevState: PageStateType) => ({
-                  ...prevState,
-                  showPublicHistories: false,
-                }));
-              }}
-            >
-              Go back
-            </a>
-          </PublicHistories>
-        </BankFrame>
-      </PageContext.Provider>
+      <BankFrame>
+        <PublicHistories pageStateSetter={pageStateSetter}>
+          <br />
+          <a
+            class="pure-button"
+            onClick={() => {
+              pageStateSetter((prevState: PageStateType) => ({
+                ...prevState,
+                showPublicHistories: false,
+              }));
+            }}
+          >
+            Go back
+          </a>
+        </PublicHistories>
+      </BankFrame>
     </SWRWithoutCredentials>
   );
 }
 
 function RegistrationPage(): VNode {
   const [backendState, backendStateSetter] = useBackendState();
-  const [pageState, pageStateSetter] = usePageState();
   const { i18n } = useTranslationContext();
   if (!bankUiSettings.allowRegistrations) {
     return (
-      <PageContext.Provider value={[pageState, pageStateSetter]}>
-        <BankFrame>
-          <p>{i18n.str`Currently, the bank is not accepting new 
registrations!`}</p>
-        </BankFrame>
-      </PageContext.Provider>
+      <BankFrame>
+        <p>{i18n.str`Currently, the bank is not accepting new 
registrations!`}</p>
+      </BankFrame>
     );
   }
   return (
-    <PageContext.Provider value={[pageState, pageStateSetter]}>
-      <BankFrame>
-        <RegistrationForm backendStateSetter={backendStateSetter} />
-      </BankFrame>
-    </PageContext.Provider>
+    <BankFrame>
+      <RegistrationForm backendStateSetter={backendStateSetter} />
+    </BankFrame>
   );
 }
 
 function AccountPage(): VNode {
   const [backendState, backendStateSetter] = useBackendState();
-  const [pageState, pageStateSetter] = usePageState();
   const { i18n } = useTranslationContext();
+  const { pageState, pageStateSetter } = usePageContext();
 
   if (!pageState.isLoggedIn) {
     return (
-      <PageContext.Provider value={[pageState, pageStateSetter]}>
-        <BankFrame>
-          <h1 class="nav">{i18n.str`Welcome to 
${bankUiSettings.bankName}!`}</h1>
-          <LoginForm
-            pageStateSetter={pageStateSetter}
-            backendStateSetter={backendStateSetter}
-          />
-        </BankFrame>
-      </PageContext.Provider>
+      <BankFrame>
+        <h1 class="nav">{i18n.str`Welcome to ${bankUiSettings.bankName}!`}</h1>
+        <LoginForm
+          pageStateSetter={pageStateSetter}
+          backendStateSetter={backendStateSetter}
+        />
+      </BankFrame>
     );
   }
 
@@ -2525,12 +2329,10 @@ function AccountPage(): VNode {
       password={backendState.password}
       backendUrl={backendState.url}
     >
-      <PageContext.Provider value={[pageState, pageStateSetter]}>
-        <Account
-          accountLabel={backendState.username}
-          backendState={backendState}
-        />
-      </PageContext.Provider>
+      <Account
+        accountLabel={backendState.username}
+        backendState={backendState}
+      />
     </SWRWithCredentials>
   );
 }
diff --git a/packages/demobank-ui/src/settings.ts 
b/packages/demobank-ui/src/settings.ts
new file mode 100644
index 000000000..a63ce347e
--- /dev/null
+++ b/packages/demobank-ui/src/settings.ts
@@ -0,0 +1,27 @@
+export interface BankUiSettings {
+  allowRegistrations: boolean;
+  showDemoNav: boolean;
+  bankName: string;
+  demoSites: [string, string][];
+}
+
+/**
+ * Global settings for the demobank UI.
+ */
+const defaultSettings: BankUiSettings = {
+  allowRegistrations: true,
+  bankName: "Taler Bank",
+  showDemoNav: true,
+  demoSites: [
+    ["Landing", "https://demo.taler.net/";],
+    ["Bank", "https://bank.demo.taler.net/";],
+    ["Essay Shop", "https://shop.demo.taler.net/";],
+    ["Donations", "https://donations.demo.taler.net/";],
+    ["Survey", "https://survey.demo.taler.net/";],
+  ],
+};
+
+export const bankUiSettings: BankUiSettings =
+  "talerDemobankSettings" in globalThis
+    ? (globalThis as any).talerDemobankSettings
+    : defaultSettings;
diff --git a/packages/web-util/src/hooks/index.ts 
b/packages/web-util/src/hooks/index.ts
new file mode 100644
index 000000000..f18d61b9c
--- /dev/null
+++ b/packages/web-util/src/hooks/index.ts
@@ -0,0 +1,3 @@
+
+export { useLang } from "./useLang.js";
+export { useLocalStorage, useNotNullLocalStorage } from "./useLocalStorage.js"
\ No newline at end of file
diff --git a/packages/demobank-ui/src/hooks/useLang.ts 
b/packages/web-util/src/hooks/useLang.ts
similarity index 100%
rename from packages/demobank-ui/src/hooks/useLang.ts
rename to packages/web-util/src/hooks/useLang.ts
diff --git a/packages/demobank-ui/src/hooks/useLocalStorage.ts 
b/packages/web-util/src/hooks/useLocalStorage.ts
similarity index 100%
rename from packages/demobank-ui/src/hooks/useLocalStorage.ts
rename to packages/web-util/src/hooks/useLocalStorage.ts
diff --git a/packages/web-util/src/index.browser.ts 
b/packages/web-util/src/index.browser.ts
index 3b3ab9293..57c97e605 100644
--- a/packages/web-util/src/index.browser.ts
+++ b/packages/web-util/src/index.browser.ts
@@ -1,37 +1,2 @@
-//`ws://localhost:8003/socket`
-export function setupLiveReload(wsURL: string | undefined) {
-  if (!wsURL) return;
-  const ws = new WebSocket(wsURL);
-  ws.addEventListener("message", (message) => {
-    const event = JSON.parse(message.data);
-    if (event.type === "LOG") {
-      console.log(event.message);
-    }
-    if (event.type === "RELOAD") {
-      window.location.reload();
-    }
-    if (event.type === "UPDATE") {
-      const c = document.getElementById("container");
-      if (c) {
-        document.body.removeChild(c);
-      }
-      const d = document.createElement("div");
-      d.setAttribute("id", "container");
-      d.setAttribute("class", "app-container");
-      document.body.appendChild(d);
-      const s = document.createElement("script");
-      s.setAttribute("id", "code");
-      s.setAttribute("type", "application/javascript");
-      s.textContent = atob(event.content);
-      document.body.appendChild(s);
-    }
-  });
-  ws.onerror = (error) => {
-    console.error(error);
-  };
-  ws.onclose = (e) => {
-    setTimeout(setupLiveReload, 500);
-  };
-}
-
+export * as hooks from "./hooks/index.js";
 export { renderStories, parseGroupImport } from "./stories.js";
diff --git a/packages/web-util/src/live-reload.ts 
b/packages/web-util/src/live-reload.ts
index ef4c6f2d6..60c7cb565 100644
--- a/packages/web-util/src/live-reload.ts
+++ b/packages/web-util/src/live-reload.ts
@@ -17,7 +17,7 @@ function setupLiveReload(): void {
     } catch (e) {
       return;
     }
-    console.log("unsupported", event);
+    console.log("unsupported", message);
   });
 
   ws.addEventListener("error", (error) => {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]