gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: fix AML spa memo and fix #861


From: gnunet
Subject: [taler-wallet-core] branch master updated: fix AML spa memo and fix #8615
Date: Fri, 12 Apr 2024 04:49:05 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 9bafc6864 fix AML spa memo and fix #8615
9bafc6864 is described below

commit 9bafc6864b9e0ef237b6975165f23ba31f0d8d88
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Thu Apr 11 23:48:55 2024 -0300

    fix AML spa memo and fix #8615
---
 packages/aml-backoffice-ui/package.json            | 13 ++--
 packages/aml-backoffice-ui/src/App.tsx             | 62 ++++++++++++---
 packages/aml-backoffice-ui/src/context/config.ts   |  2 +-
 packages/aml-backoffice-ui/src/hooks/useCases.ts   | 87 ++++++++++------------
 packages/aml-backoffice-ui/src/hooks/useOfficer.ts | 21 +++---
 packages/aml-backoffice-ui/src/pages/Cases.tsx     | 25 ++-----
 .../merchant-backoffice-ui/src/hooks/webhooks.ts   |  1 -
 .../src/components/BankDetailsByPaytoType.tsx      | 14 +++-
 .../src/cta/Withdraw/state.ts                      |  1 +
 pnpm-lock.yaml                                     |  6 +-
 10 files changed, 129 insertions(+), 103 deletions(-)

diff --git a/packages/aml-backoffice-ui/package.json 
b/packages/aml-backoffice-ui/package.json
index b4df017ea..9be44bd76 100644
--- a/packages/aml-backoffice-ui/package.json
+++ b/packages/aml-backoffice-ui/package.json
@@ -29,24 +29,23 @@
     "history": "4.10.1",
     "jed": "1.1.1",
     "preact": "10.11.3",
-    "swr": "2.0.3"
+    "swr": "2.2.2"
   },
   "devDependencies": {
-    "eslint": "^8.56.0",
-    "@typescript-eslint/eslint-plugin": "^6.19.0",
-    "@typescript-eslint/parser": "^6.19.0",
-    "eslint-config-prettier": "^9.1.0",
-    "eslint-plugin-react": "^7.33.2",
-
     "@gnu-taler/pogen": "^0.0.5",
     "@tailwindcss/forms": "^0.5.3",
     "@tailwindcss/typography": "^0.5.9",
     "@types/chai": "^4.3.0",
     "@types/history": "^4.7.8",
     "@types/mocha": "^10.0.1",
+    "@typescript-eslint/eslint-plugin": "^6.19.0",
+    "@typescript-eslint/parser": "^6.19.0",
     "autoprefixer": "^10.4.14",
     "chai": "^4.3.6",
     "esbuild": "^0.19.9",
+    "eslint": "^8.56.0",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-react": "^7.33.2",
     "mocha": "^9.2.0",
     "po2json": "^0.4.5",
     "postcss": "^8.4.23",
diff --git a/packages/aml-backoffice-ui/src/App.tsx 
b/packages/aml-backoffice-ui/src/App.tsx
index d461934c0..5244476d7 100644
--- a/packages/aml-backoffice-ui/src/App.tsx
+++ b/packages/aml-backoffice-ui/src/App.tsx
@@ -6,9 +6,11 @@ import { ExchangeApiProvider } from "./context/config.js";
 import { getInitialBackendBaseURL } from "./hooks/useBackend.js";
 import { HashPathProvider, Router } from "./route.js";
 import { Pages } from "./pages.js";
+import { SWRConfig } from "swr";
 
-const pageList = Object.values(Pages);
+const WITH_LOCAL_STORAGE_CACHE = false;
 
+const pageList = Object.values(Pages);
 
 export function App(): VNode {
   const baseUrl = getInitialBackendBaseURL();
@@ -16,17 +18,57 @@ export function App(): VNode {
     <TranslationProvider source={{}}>
       <ExchangeApiProvider baseUrl={baseUrl} frameOnError={ExchangeAmlFrame}>
         <HashPathProvider>
-          <ExchangeAmlFrame>
-            <Router
-              pageList={pageList}
-              onNotFound={() => {
-                window.location.href = Pages.cases.url
-                return <div>not found</div>;
-              }}
-            />
-          </ExchangeAmlFrame>
+          <SWRConfig
+            value={{
+              provider: WITH_LOCAL_STORAGE_CACHE
+                ? localStorageProvider
+                : undefined,
+              // normally, do not revalidate
+              revalidateOnFocus: false,
+              revalidateOnReconnect: false,
+              revalidateIfStale: false,
+              revalidateOnMount: undefined,
+              focusThrottleInterval: undefined,
+
+              // normally, do not refresh
+              refreshInterval: undefined,
+              dedupingInterval: 2000,
+              refreshWhenHidden: false,
+              refreshWhenOffline: false,
+
+              // ignore errors
+              shouldRetryOnError: false,
+              errorRetryCount: 0,
+              errorRetryInterval: undefined,
+
+              // do not go to loading again if already has data
+              keepPreviousData: true,
+            }}
+          >
+
+            <ExchangeAmlFrame>
+              <Router
+                pageList={pageList}
+                onNotFound={() => {
+                  window.location.href = Pages.cases.url
+                  return <div>not found</div>;
+                }}
+              />
+            </ExchangeAmlFrame>
+          </SWRConfig>
         </HashPathProvider>
       </ExchangeApiProvider>
     </TranslationProvider>
   );
 }
+
+
+function localStorageProvider(): Map<unknown, unknown> {
+  const map = new Map(JSON.parse(localStorage.getItem("app-cache") || "[]"));
+
+  window.addEventListener("beforeunload", () => {
+    const appCache = JSON.stringify(Array.from(map.entries()));
+    localStorage.setItem("app-cache", appCache);
+  });
+  return map;
+}
diff --git a/packages/aml-backoffice-ui/src/context/config.ts 
b/packages/aml-backoffice-ui/src/context/config.ts
index 7004225eb..42f73428a 100644
--- a/packages/aml-backoffice-ui/src/context/config.ts
+++ b/packages/aml-backoffice-ui/src/context/config.ts
@@ -67,7 +67,7 @@ export const ExchangeApiProvider = ({
       .then((resp) => {
         if (resp.type === "fail") {
           setChecked({ type: "error", error: 
TalerError.fromUncheckedDetail(resp.detail) });
-        }else if (api.isCompatible(resp.body.version)) {
+        } else if (api.isCompatible(resp.body.version)) {
           setChecked({ type: "ok", config: resp.body });
         } else {
           setChecked({ type: "incompatible", result: resp.body, supported: 
api.PROTOCOL_VERSION })
diff --git a/packages/aml-backoffice-ui/src/hooks/useCases.ts 
b/packages/aml-backoffice-ui/src/hooks/useCases.ts
index 68deb7db9..2bc9b5f0f 100644
--- a/packages/aml-backoffice-ui/src/hooks/useCases.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useCases.ts
@@ -1,14 +1,18 @@
 import { useState } from "preact/hooks";
 
 // FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import { AmountString, HttpStatusCode, OfficerAccount, OperationFail, 
TalerExchangeApi, TalerExchangeResultByMethod, TalerHttpError } from 
"@gnu-taler/taler-util";
+import { OfficerAccount, OfficerId, OperationOk, TalerExchangeResultByMethod, 
TalerHttpError, decodeCrock, encodeCrock } from "@gnu-taler/taler-util";
 import _useSWR, { SWRHook } from "swr";
 import { useExchangeApiContext } from "../context/config.js";
-import { useOfficer } from "./useOfficer.js";
 import { AmlExchangeBackend } from "../utils/types.js";
+import { useOfficer } from "./useOfficer.js";
 const useSWR = _useSWR as unknown as SWRHook;
 
-const PAGE_SIZE = 10;
+export const PAGINATED_LIST_SIZE = 10;
+// when doing paginated request, ask for one more
+// and use it to know if there are more to request
+export const PAGINATED_LIST_REQUEST = PAGINATED_LIST_SIZE + 1;
+
 /**
  * FIXME: mutate result when balance change (transaction )
  * @param account
@@ -24,69 +28,56 @@ export function useCases(state: 
AmlExchangeBackend.AmlState) {
 
   async function fetcher([officer, state, offset]: [OfficerAccount, 
AmlExchangeBackend.AmlState, string | undefined]) {
     return await api.getDecisionsByState(officer, state, {
-      order: "asc", offset, limit: PAGE_SIZE + 1
+      order: "asc", offset, limit: PAGINATED_LIST_REQUEST
     })
   }
 
   const { data, error } = 
useSWR<TalerExchangeResultByMethod<"getDecisionsByState">, TalerHttpError>(
-    !session ? undefined : [session, state, offset],
+    !session ? undefined : [session, state, offset, "getDecisionsByState"],
     fetcher,
   );
 
-  // const [lastAfter, setLastAfter] = useState<
-  //   HttpResponse<AmlExchangeBackend.AmlRecords, AmlExchangeBackend.AmlError>
-  // >({ loading: true });
+  if (error) return error;
+  if (data === undefined) return undefined;
+  if (data.type !== "ok") return data;
 
-  // useEffect(() => {
-  //   if (afterData) setLastAfter(afterData);
-  // }, [afterData]);
+  return buildPaginatedResult(data.body.records, offset, setOffset, (d) => 
String(d.rowid));
+}
 
-  // if (afterError) {
-  //   return afterError.cause;
-  // }
+type PaginatedResult<T> = OperationOk<T> & {
+  isLastPage: boolean;
+  isFirstPage: boolean;
+  loadNext(): void;
+  loadFirst(): void;
+}
+
+//TODO: consider sending this to web-util
+export function buildPaginatedResult<R, OffId>(data: R[], offset: OffId | 
undefined, setOffset: (o: OffId | undefined) => void, getId: (r: R) => OffId): 
PaginatedResult<R[]> {
 
-  // if the query returns less that we ask, then we have reach the end or 
beginning
-  const isLastPage =
-    data && data.type === "ok" && data.body.records.length <= PAGE_SIZE;
-  const isFirstPage = !offset;
+  const isLastPage = data.length < PAGINATED_LIST_REQUEST;
+  const isFirstPage = offset === undefined;
 
-  const pagination = {
+  const result = structuredClone(data);
+  if (result.length == PAGINATED_LIST_REQUEST) {
+    result.pop();
+  }
+  return {
+    type: "ok",
+    body: result,
     isLastPage,
     isFirstPage,
-    loadMore: () => {
-      if (isLastPage || data?.type !== "ok") return;
-      const list = data.body.records
-      setOffset(String(list[list.length - 1].rowid));
+    loadNext: () => {
+      if (!result.length) return;
+      const id = getId(result[result.length - 1])
+      setOffset(id);
     },
-    reset: () => {
-      setOffset(undefined)
+    loadFirst: () => {
+      setOffset(undefined);
     },
   };
-
-  // const public_accountslist = data?.type !== "ok" ? [] : 
data.body.public_accounts;
-  if (!session) {
-    return {
-      data: {
-        type: "fail",
-        case: HttpStatusCode.Unauthorized,
-        detail: {}
-      } as OperationFail<never>
-    }
-  }
-
-  if (data) {
-    if (data.type === "fail") {
-      return { data }
-    }
-    const records = isLastPage ? data.body.records : 
removeLastElement(data.body.records)
-    return { data: { type: "ok" as const, body: { records } }, pagination }
-  }
-  if (error) {
-    return error;
-  }
-  return undefined;
 }
 
+
 function removeLastElement<T>(list: Array<T>): Array<T> {
   if (list.length === 0) {
     return list;
diff --git a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts 
b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
index fe989f3eb..1bf2b308b 100644
--- a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
@@ -8,19 +8,17 @@ import {
   buildCodecForObject,
   codecForAbsoluteTime,
   codecForString,
-  codecOptional,
   createNewOfficerAccount,
   decodeCrock,
   encodeCrock,
-  unlockOfficerAccount,
+  unlockOfficerAccount
 } from "@gnu-taler/taler-util";
 import {
   buildStorageKey,
-  useLocalStorage,
-  useMemoryStorage,
+  useLocalStorage
 } from "@gnu-taler/web-util/browser";
 import { useMemo } from "preact/hooks";
-import { useExchangeApiContext, useMaybeExchangeApiContext } from 
"../context/config.js";
+import { useMaybeExchangeApiContext } from "../context/config.js";
 
 export interface Officer {
   account: LockedAccount;
@@ -66,7 +64,6 @@ interface OfficerReady {
 
 const OFFICER_KEY = buildStorageKey("officer", codecForOfficer());
 const DEV_ACCOUNT_KEY = buildStorageKey("account-dev", 
codecForOfficerAccount());
-const ACCOUNT_KEY = "account";
 
 export function useOfficer(): OfficerState {
   const exchangeContext = useMaybeExchangeApiContext();
@@ -74,18 +71,18 @@ export function useOfficer(): OfficerState {
   const accountStorage = useLocalStorage(DEV_ACCOUNT_KEY);
   const account = useMemo(() => {
     if (!accountStorage.value) return undefined
+
     return {
       id: accountStorage.value.id as OfficerId,
       signingKey: decodeCrock(accountStorage.value.strKey) as SigningKey
     }
-  }, [accountStorage.value])
-
-
-  // const accountStorage = useMemoryStorage<OfficerAccount>(ACCOUNT_KEY);
-  // const account = accountStorage.value;
+  }, [accountStorage.value?.id, accountStorage.value?.strKey])
 
   const officerStorage = useLocalStorage(OFFICER_KEY);
-  const officer = officerStorage.value;
+  const officer = useMemo(() => {
+    if (!officerStorage.value) return undefined
+    return officerStorage.value
+  }, [officerStorage.value?.account, officerStorage.value?.when.t_ms])
 
   if (officer === undefined) {
     return {
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx 
b/packages/aml-backoffice-ui/src/pages/Cases.tsx
index faef0ca54..061286f51 100644
--- a/packages/aml-backoffice-ui/src/pages/Cases.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -70,7 +70,7 @@ export function CasesUI({
             onUpdate={(v) => {
               onChangeFilter(v.state ?? filter);
             }}
-            onSubmit={(_v) => {}}
+            onSubmit={(_v) => { }}
           >
             <form.InputChoiceHorizontal
               name="state"
@@ -182,6 +182,7 @@ export function CasesUI({
 }
 
 export function Cases() {
+
   const [stateFilter, setStateFilter] = useState(
     AmlExchangeBackend.AmlState.pending,
   );
@@ -195,33 +196,23 @@ export function Cases() {
     return <ErrorLoading error={list} />;
   }
 
-  if (list.data.type === "fail") {
-    switch (list.data.case) {
+  if (list.type === "fail") {
+    switch (list.case) {
       case HttpStatusCode.Unauthorized:
       case HttpStatusCode.Forbidden:
       case HttpStatusCode.NotFound:
       case HttpStatusCode.Conflict:
         return <Officer />;
       default:
-        assertUnreachable(list.data);
+        assertUnreachable(list);
     }
   }
 
-  const { records } = list.data.body;
-
   return (
     <CasesUI
-      records={records}
-      onFirstPage={
-        list.pagination && !list.pagination.isFirstPage
-          ? list.pagination.reset
-          : undefined
-      }
-      onNext={
-        list.pagination && !list.pagination.isLastPage
-          ? list.pagination.loadMore
-          : undefined
-      }
+      records={list.body}
+      onFirstPage={list.isFirstPage ? undefined : list.loadFirst}
+      onNext={list.isLastPage ? undefined : list.loadNext}
       filter={stateFilter}
       onChangeFilter={setStateFilter}
     />
diff --git a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts 
b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
index ff0d8b8a9..df53c06bc 100644
--- a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
@@ -16,7 +16,6 @@
 import {
   useMerchantApiContext
 } from "@gnu-taler/web-util/browser";
-import { useState } from "preact/hooks";
 import { PAGINATED_LIST_REQUEST } from "../utils/constants.js";
 
 // FIX default import https://github.com/microsoft/TypeScript/issues/49189
diff --git 
a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx 
b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
index 3bcf2d6ba..007c840c6 100644
--- 
a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
+++ 
b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
@@ -42,14 +42,19 @@ export interface BankDetailsProps {
 export function BankDetailsByPaytoType({
   subject,
   amount,
-  accounts,
+  accounts: unsortedAccounts,
 }: BankDetailsProps): VNode {
   const { i18n } = useTranslationContext();
   const [index, setIndex] = useState(0)
-  // const [currency, setCurrency] = useState(amount.currency)
-  if (!accounts.length) {
+
+  if (!unsortedAccounts.length) {
     return <div>the exchange account list is empty</div>
   }
+
+  const accounts = unsortedAccounts.sort((a, b) => {
+    return (b.priority ?? 0) - (a.priority ?? 0)
+  })
+
   const selectedAccount = accounts[index];
   const altCurrency = selectedAccount.currencySpecification?.name
 
@@ -83,12 +88,13 @@ export function BankDetailsByPaytoType({
       {accounts.length > 1 ?
         <Fragment>
           {accounts.map((ac, acIdx) => {
+            const accountLabel = ac.bankLabel ?? `Account #${acIdx + 1}`
             return <Button key={acIdx} variant={acIdx === index ? "contained" 
: "outlined"}
               onClick={async () => {
                 setIndex(acIdx)
               }}
             >
-              <i18n.Translate>Account #{acIdx+1} 
({ac.currencySpecification?.name ?? amount.currency})</i18n.Translate>
+              {accountLabel} ({ac.currencySpecification?.name ?? 
amount.currency})
             </Button>
           })}
 
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts 
b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
index 51859d6a7..7486d5f97 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
@@ -454,6 +454,7 @@ function exchangeSelectionState(
       altCurrencies.length === 0
         ? []
         : [toBeReceived.currency, ...altCurrencies];
+
     const convAccount = amountHook.response.accounts.find((c) => {
       return (
         c.currencySpecification &&
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6f53c7d90..b1c5511c8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.0'
+lockfileVersion: '6.1'
 
 settings:
   autoInstallPeers: true
@@ -57,8 +57,8 @@ importers:
         specifier: 10.11.3
         version: 10.11.3
       swr:
-        specifier: 2.0.3
-        version: 2.0.3(react@18.2.0)
+        specifier: 2.2.2
+        version: 2.2.2(react@18.2.0)
     devDependencies:
       '@gnu-taler/pogen':
         specifier: ^0.0.5

-- 
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]