summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-11-05 18:04:22 -0300
committerSebastian <sebasjm@gmail.com>2023-11-05 18:04:22 -0300
commitb58d53dd93bd8e97aecc28fae788c5c7051fd73d (patch)
tree7a402fafa4ae19a64f10eeb3042147f5f4733081 /packages
parent31cf3187e447e2c4ec8a473362c5bacc07a874f1 (diff)
downloadwallet-core-b58d53dd93bd8e97aecc28fae788c5c7051fd73d.tar.gz
wallet-core-b58d53dd93bd8e97aecc28fae788c5c7051fd73d.tar.bz2
wallet-core-b58d53dd93bd8e97aecc28fae788c5c7051fd73d.zip
sharing components in web-util
Diffstat (limited to 'packages')
-rw-r--r--packages/aml-backoffice-ui/src/App.tsx11
-rw-r--r--packages/aml-backoffice-ui/src/Dashboard.tsx26
-rw-r--r--packages/aml-backoffice-ui/src/account.ts128
-rw-r--r--packages/aml-backoffice-ui/src/context/config.ts89
-rw-r--r--packages/aml-backoffice-ui/src/handlers/Caption.tsx7
-rw-r--r--packages/aml-backoffice-ui/src/hooks/useBackend.ts27
-rw-r--r--packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts103
-rw-r--r--packages/aml-backoffice-ui/src/hooks/useCases.ts126
-rw-r--r--packages/aml-backoffice-ui/src/hooks/useOfficer.ts20
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseDetails.tsx83
-rw-r--r--packages/aml-backoffice-ui/src/pages/Cases.tsx46
-rw-r--r--packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx19
-rw-r--r--packages/aml-backoffice-ui/src/pages/Officer.tsx4
-rw-r--r--packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx3
-rw-r--r--packages/aml-backoffice-ui/src/utils/errors.tsx77
-rw-r--r--packages/demobank-ui/src/components/Cashouts/index.ts2
-rw-r--r--packages/demobank-ui/src/components/Cashouts/views.tsx5
-rw-r--r--packages/demobank-ui/src/components/EmptyComponentExample/index.ts5
-rw-r--r--packages/demobank-ui/src/components/Routing.tsx4
-rw-r--r--packages/demobank-ui/src/components/Transactions/index.ts5
-rw-r--r--packages/demobank-ui/src/components/app.tsx1
-rw-r--r--packages/demobank-ui/src/context/config.ts2
-rw-r--r--packages/demobank-ui/src/pages/AccountPage/index.ts4
-rw-r--r--packages/demobank-ui/src/pages/AccountPage/views.tsx2
-rw-r--r--packages/demobank-ui/src/pages/BankFrame.tsx10
-rw-r--r--packages/demobank-ui/src/pages/LoginForm.tsx6
-rw-r--r--packages/demobank-ui/src/pages/OperationState/index.ts4
-rw-r--r--packages/demobank-ui/src/pages/OperationState/views.tsx8
-rw-r--r--packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx4
-rw-r--r--packages/demobank-ui/src/pages/PublicHistoriesPage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/QrCodeSection.tsx2
-rw-r--r--packages/demobank-ui/src/pages/RegistrationPage.tsx4
-rw-r--r--packages/demobank-ui/src/pages/ShowAccountDetails.tsx6
-rw-r--r--packages/demobank-ui/src/pages/UpdateAccountPassword.tsx8
-rw-r--r--packages/demobank-ui/src/pages/WalletWithdrawForm.tsx4
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx4
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx2
-rw-r--r--packages/demobank-ui/src/pages/WithdrawalQRCode.tsx6
-rw-r--r--packages/demobank-ui/src/pages/admin/Account.tsx4
-rw-r--r--packages/demobank-ui/src/pages/admin/AccountForm.tsx4
-rw-r--r--packages/demobank-ui/src/pages/admin/AccountList.tsx4
-rw-r--r--packages/demobank-ui/src/pages/admin/AdminHome.tsx2
-rw-r--r--packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx4
-rw-r--r--packages/demobank-ui/src/pages/admin/RemoveAccount.tsx10
-rw-r--r--packages/demobank-ui/src/pages/business/CreateCashout.tsx10
-rw-r--r--packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx10
-rw-r--r--packages/demobank-ui/tailwind.config.js8
-rw-r--r--packages/web-util/src/assets/lang.svg (renamed from packages/demobank-ui/src/assets/lang.svg)0
-rw-r--r--packages/web-util/src/components/Attention.tsx (renamed from packages/demobank-ui/src/components/Attention.tsx)13
-rw-r--r--packages/web-util/src/components/CopyButton.tsx (renamed from packages/demobank-ui/src/components/CopyButton.tsx)2
-rw-r--r--packages/web-util/src/components/ErrorLoading.tsx (renamed from packages/demobank-ui/src/components/ErrorLoading.tsx)5
-rw-r--r--packages/web-util/src/components/LangSelector.tsx (renamed from packages/demobank-ui/src/components/LangSelector.tsx)12
-rw-r--r--packages/web-util/src/components/Loading.tsx (renamed from packages/demobank-ui/src/components/Loading.tsx)0
-rw-r--r--packages/web-util/src/components/ShowInputErrorLabel.tsx (renamed from packages/demobank-ui/src/components/ShowInputErrorLabel.tsx)0
-rw-r--r--packages/web-util/src/components/ShowLocalNotification.tsx (renamed from packages/demobank-ui/src/components/ShowLocalNotification.tsx)24
-rw-r--r--packages/web-util/src/components/index.ts7
-rw-r--r--packages/web-util/src/declaration.d.ts35
57 files changed, 439 insertions, 584 deletions
diff --git a/packages/aml-backoffice-ui/src/App.tsx b/packages/aml-backoffice-ui/src/App.tsx
index 600131219..0e29279ff 100644
--- a/packages/aml-backoffice-ui/src/App.tsx
+++ b/packages/aml-backoffice-ui/src/App.tsx
@@ -1,12 +1,19 @@
import { TranslationProvider } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
-import { Dashboard } from "./Dashboard.js";
+import { ExchangeAmlFrame, Main } from "./Dashboard.js";
import "./scss/main.css";
+import { ExchangeApiProvider } from "./context/config.js";
+import { getInitialBackendBaseURL } from "./hooks/useBackend.js";
export function App(): VNode {
+ const baseUrl = getInitialBackendBaseURL();
return (
<TranslationProvider source={{}}>
- <Dashboard />
+ <ExchangeApiProvider baseUrl={baseUrl} frameOnError={ExchangeAmlFrame}>
+ <ExchangeAmlFrame>
+ <Main />
+ </ExchangeAmlFrame>
+ </ExchangeApiProvider>
</TranslationProvider>
);
}
diff --git a/packages/aml-backoffice-ui/src/Dashboard.tsx b/packages/aml-backoffice-ui/src/Dashboard.tsx
index 6794ca1f8..bd8a48c45 100644
--- a/packages/aml-backoffice-ui/src/Dashboard.tsx
+++ b/packages/aml-backoffice-ui/src/Dashboard.tsx
@@ -182,7 +182,7 @@ function LeftMenu() {
);
}
-export function Dashboard({
+export function ExchangeAmlFrame({
children,
}: {
children?: ComponentChildren;
@@ -211,21 +211,25 @@ export function Dashboard({
}}
/>
<Notifications />
- <main class="py-10 px-4 sm:px-6 lg:px-8">
- <div class="mx-auto max-w-3xl">
- <Router
- pageList={pageList}
- onNotFound={() => {
- return <div>not found</div>;
- }}
- />
- </div>
- </main>
+ {children}
</div>
</Fragment>
);
}
+export function Main(): VNode {
+ return <main class="py-10 px-4 sm:px-6 lg:px-8">
+ <div class="mx-auto max-w-3xl">
+ <Router
+ pageList={pageList}
+ onNotFound={() => {
+ return <div>not found</div>;
+ }}
+ />
+ </div>
+ </main>
+}
+
const pageList = Object.values(Pages);
function NavigationBar({
diff --git a/packages/aml-backoffice-ui/src/account.ts b/packages/aml-backoffice-ui/src/account.ts
deleted file mode 100644
index 615d843c4..000000000
--- a/packages/aml-backoffice-ui/src/account.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import {
- Amounts,
- TalerSignaturePurpose,
- amountToBuffer,
- bufferForUint32,
- buildSigPS,
- createEddsaKeyPair,
- decodeCrock,
- decryptWithDerivedKey,
- eddsaGetPublic,
- eddsaSign,
- encodeCrock,
- encryptWithDerivedKey,
- getRandomBytesF,
- hash,
- hashTruncate32,
- stringToBytes,
- timestampRoundedToBuffer
-} from "@gnu-taler/taler-util";
-import { AmlExchangeBackend } from "./types.js";
-
-export interface Account {
- accountId: AccountId;
- signingKey: SigningKey;
-}
-
-/**
- * Restore previous session and unlock account with password
- *
- * @param salt string from which crypto params will be derived
- * @param key secured private key
- * @param password password for the private key
- * @returns
- */
-export async function unlockAccount(
- account: LockedAccount,
- password: string,
-): Promise<Account> {
- const rawKey = decodeCrock(account);
- const rawPassword = stringToBytes(password);
-
- const signingKey = (await decryptWithDerivedKey(
- rawKey,
- rawPassword,
- password,
- ).catch((e: Error) => {
- throw new UnwrapKeyError(e.message);
- })) as SigningKey;
-
- const publicKey = eddsaGetPublic(signingKey);
-
- const accountId = encodeCrock(publicKey) as AccountId;
-
- return { accountId, signingKey };
-}
-
-export function buildQuerySignature(key: SigningKey): string {
- const sigBlob = buildSigPS(
- TalerSignaturePurpose.TALER_SIGNATURE_AML_QUERY,
- ).build();
-
- return encodeCrock(eddsaSign(sigBlob, key));
-}
-
-export function buildDecisionSignature(
- key: SigningKey,
- decision: AmlExchangeBackend.AmlDecision,
-): string {
- const zero = new Uint8Array(new ArrayBuffer(64))
-
- const sigBlob = buildSigPS(TalerSignaturePurpose.TALER_SIGNATURE_AML_DECISION)
- //TODO: new need the null terminator, also in the exchange
- .put(hash(stringToBytes(decision.justification)))//check null
- .put(timestampRoundedToBuffer(decision.decision_time))
- .put(amountToBuffer(decision.new_threshold))
- .put(decodeCrock(decision.h_payto))
- .put(zero) //kyc_requirement
- .put(bufferForUint32(decision.new_state))
- .build();
-
- return encodeCrock(eddsaSign(sigBlob, key));
-}
-
-declare const opaque_Account: unique symbol;
-export type LockedAccount = string & { [opaque_Account]: true };
-
-declare const opaque_AccountId: unique symbol;
-export type AccountId = string & { [opaque_AccountId]: true };
-
-declare const opaque_SigningKey: unique symbol;
-export type SigningKey = Uint8Array & { [opaque_SigningKey]: true };
-
-/**
- * Create new account (secured private key)
- * secured with the given password
- *
- * @param sessionId
- * @param password
- * @returns
- */
-export async function createNewAccount(
- password: string,
-): Promise<Account & { safe: LockedAccount }> {
- const { eddsaPriv, eddsaPub } = createEddsaKeyPair();
-
- const key = stringToBytes(password);
-
- const protectedPrivKey = await encryptWithDerivedKey(
- getRandomBytesF(24),
- key,
- eddsaPriv,
- password,
- );
-
- const signingKey = eddsaPriv as SigningKey;
- const accountId = encodeCrock(eddsaPub) as AccountId;
- const safe = encodeCrock(protectedPrivKey) as LockedAccount;
-
- return { accountId, signingKey, safe };
-}
-
-export class UnwrapKeyError extends Error {
- public cause: string;
- constructor(cause: string) {
- super(`Recovering private key failed on: ${cause}`);
- this.cause = cause;
- }
-}
diff --git a/packages/aml-backoffice-ui/src/context/config.ts b/packages/aml-backoffice-ui/src/context/config.ts
new file mode 100644
index 000000000..2866717de
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/context/config.ts
@@ -0,0 +1,89 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 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 { TalerExchangeApi, TalerExchangeHttpClient, TalerError } from "@gnu-taler/taler-util";
+import { BrowserHttpLib, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ComponentChildren, createContext, FunctionComponent, h, VNode } from "preact";
+import { useContext, useEffect, useState } from "preact/hooks";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export type Type = {
+ url: URL,
+ config: TalerExchangeApi.ExchangeVersionResponse,
+ api: TalerExchangeHttpClient,
+};
+
+const Context = createContext<Type>(undefined as any);
+
+export const useExchangeApiContext = (): Type => useContext(Context);
+
+export type ConfigResult = undefined
+ | { type: "ok", config: TalerExchangeApi.ExchangeVersionResponse }
+ | { type: "incompatible", result: TalerExchangeApi.ExchangeVersionResponse, supported: string }
+ | { type: "error", error: TalerError }
+
+export const ExchangeApiProvider = ({
+ baseUrl,
+ children,
+ frameOnError,
+}: {
+ baseUrl: string,
+ children: ComponentChildren;
+ frameOnError: FunctionComponent<{ children: ComponentChildren }>,
+}): VNode => {
+ const [checked, setChecked] = useState<ConfigResult>()
+ const { i18n } = useTranslationContext();
+ const url = new URL(baseUrl)
+ const api = new TalerExchangeHttpClient(url.href, new BrowserHttpLib())
+ useEffect(() => {
+ api.getConfig()
+ .then((resp) => {
+ if (api.isCompatible(resp.body.version)) {
+ setChecked({ type: "ok", config: resp.body });
+ } else {
+ setChecked({ type: "incompatible", result: resp.body, supported: api.PROTOCOL_VERSION })
+ }
+ })
+ .catch((error: unknown) => {
+ if (error instanceof TalerError) {
+ setChecked({ type: "error", error });
+ }
+ });
+ }, []);
+
+ if (checked === undefined) {
+ return h(frameOnError, { children: h("div", {}, "loading...") })
+ }
+ if (checked.type === "error") {
+ return h(frameOnError, { children: h(ErrorLoading, { error: checked.error, showDetail: true }) })
+ }
+ if (checked.type === "incompatible") {
+ return h(frameOnError, { children: h("div", {}, i18n.str`the bank backend is not supported. supported version "${checked.supported}", server version "${checked.result.version}"`) })
+ }
+ const value: Type = {
+ url, config: checked.config, api
+ }
+ return h(Context.Provider, {
+ value,
+ children,
+ });
+};
+
diff --git a/packages/aml-backoffice-ui/src/handlers/Caption.tsx b/packages/aml-backoffice-ui/src/handlers/Caption.tsx
index fbf154d89..8facddec3 100644
--- a/packages/aml-backoffice-ui/src/handlers/Caption.tsx
+++ b/packages/aml-backoffice-ui/src/handlers/Caption.tsx
@@ -1,11 +1,8 @@
+import { TranslatedString } from "@gnu-taler/taler-util";
import { VNode, h } from "preact";
import {
- IconAddon,
- InputLine,
- LabelWithTooltipMaybeRequired,
- UIFormProps,
+ LabelWithTooltipMaybeRequired
} from "./InputLine.js";
-import { TranslatedString } from "@gnu-taler/taler-util";
interface Props {
label: TranslatedString;
diff --git a/packages/aml-backoffice-ui/src/hooks/useBackend.ts b/packages/aml-backoffice-ui/src/hooks/useBackend.ts
index b9d66fca6..95277a915 100644
--- a/packages/aml-backoffice-ui/src/hooks/useBackend.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useBackend.ts
@@ -1,3 +1,4 @@
+import { canonicalizeBaseUrl } from "@gnu-taler/taler-util";
import {
HttpResponseOk,
RequestOptions,
@@ -5,9 +6,6 @@ import {
} from "@gnu-taler/web-util/browser";
import { useCallback } from "preact/hooks";
import { uiSettings } from "../settings.js";
-import { canonicalizeBaseUrl } from "@gnu-taler/taler-util";
-import { useOfficer } from "./useOfficer.js";
-import { buildQuerySignature } from "../account.js";
interface useBackendType {
request: <T>(
@@ -35,7 +33,7 @@ export function usePublicBackend(): useBackendType {
);
const fetcher = useCallback(
- function fetcherImpl<T>([endpoint, talerAmlOfficerSignature]: [string,string]): Promise<HttpResponseOk<T>> {
+ function fetcherImpl<T>([endpoint, talerAmlOfficerSignature]: [string, string]): Promise<HttpResponseOk<T>> {
return requestHandler<T>(baseUrl, endpoint, {
talerAmlOfficerSignature
});
@@ -66,18 +64,29 @@ export function usePublicBackend(): useBackendType {
export function getInitialBackendBaseURL(): string {
const overrideUrl =
typeof localStorage !== "undefined"
- ? localStorage.getItem("exchange-aml-base-url")
+ ? localStorage.getItem("exchange-base-url")
: undefined;
+
+ let result: string;
+
if (!overrideUrl) {
//normal path
if (!uiSettings.backendBaseURL) {
console.error(
"ERROR: backendBaseURL was overridden by a setting file and missing. Setting value to 'window.origin'",
);
- return canonicalizeBaseUrl(window.origin);
+ result = window.origin
+ } else {
+ result = uiSettings.backendBaseURL;
}
- return canonicalizeBaseUrl(uiSettings.backendBaseURL);
+ } else {
+ // testing/development path
+ result = overrideUrl
+ }
+ try {
+ return canonicalizeBaseUrl(result)
+ } catch (e) {
+ //fall back
+ return canonicalizeBaseUrl(window.origin)
}
- // testing/development path
- return canonicalizeBaseUrl(overrideUrl);
}
diff --git a/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts b/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts
index 980a35f21..9db1e2aec 100644
--- a/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts
@@ -1,34 +1,29 @@
import {
HttpResponse,
- HttpResponseOk,
- RequestError
+ HttpResponseOk
} from "@gnu-taler/web-util/browser";
import { AmlExchangeBackend } from "../types.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import { AmountString, OfficerAccount, PaytoString, TalerExchangeApi, TalerExchangeResultByMethod, TalerHttpError } from "@gnu-taler/taler-util";
import _useSWR, { SWRHook, useSWRConfig } from "swr";
-import { AccountId } from "../account.js";
+import { useExchangeApiContext } from "../context/config.js";
import { usePublicBackend } from "./useBackend.js";
+import { useOfficer } from "./useOfficer.js";
const useSWR = _useSWR as unknown as SWRHook;
-export function useCaseDetails(
- account: AccountId,
- paytoHash: string,
- signature: string | undefined,
-): HttpResponse<
- AmlExchangeBackend.AmlDecisionDetails,
- AmlExchangeBackend.AmlError
-> {
- const { fetcher } = usePublicBackend();
+export function useCaseDetails(paytoHash: string) {
+ const officer = useOfficer();
+ const session = officer.state === "ready" ? officer.account : undefined;
- const { data, error } = useSWR<
- HttpResponseOk<AmlExchangeBackend.AmlDecisionDetails>,
- RequestError<AmlExchangeBackend.AmlError>
->( [
- `aml/${account}/decision/${(paytoHash)}`,
- signature,
-],
-fetcher, {
+ const { api } = useExchangeApiContext();
+
+ async function fetcher([officer, account]: [OfficerAccount, PaytoString]) {
+ return await api.getDecisionDetails(officer, account)
+ }
+
+ const { data, error } = useSWR<TalerExchangeResultByMethod<"getDecisionDetails">, TalerHttpError>(
+ !session ? undefined : [session, paytoHash], fetcher, {
refreshInterval: 0,
refreshWhenHidden: false,
revalidateOnFocus: false,
@@ -41,11 +36,11 @@ fetcher, {
});
if (data) return data;
- if (error) return error.cause;
- return { loading: true };
+ if (error) return error;
+ return undefined;
}
-const example1: AmlExchangeBackend.AmlDecisionDetails = {
+const example1: TalerExchangeApi.AmlDecisionDetails = {
aml_history: [
{
justification: "Lack of documentation",
@@ -54,7 +49,7 @@ const example1: AmlExchangeBackend.AmlDecisionDetails = {
t_s: Date.now() / 1000,
},
new_state: 2,
- new_threshold: "USD:0",
+ new_threshold: "USD:0" as AmountString,
},
{
justification: "Doing a transfer of high amount",
@@ -63,7 +58,7 @@ const example1: AmlExchangeBackend.AmlDecisionDetails = {
t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 6,
},
new_state: 1,
- new_threshold: "USD:2000",
+ new_threshold: "USD:2000" as AmountString,
},
{
justification: "Account is known to the system",
@@ -72,7 +67,7 @@ const example1: AmlExchangeBackend.AmlDecisionDetails = {
t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 9,
},
new_state: 0,
- new_threshold: "USD:100",
+ new_threshold: "USD:100" as AmountString,
},
],
kyc_attributes: [
@@ -103,60 +98,4 @@ const example1: AmlExchangeBackend.AmlDecisionDetails = {
],
};
-export const exampleResponse: HttpResponse<AmlExchangeBackend.AmlDecisionDetails,AmlExchangeBackend.AmlError> = {
- ok: true,
- data: example1,
-}
-
-
-export function useAmlCasesAPI(): AmlCaseAPI {
- const { request } = usePublicBackend();
- const mutateAll = useMatchMutate();
-
- const updateDecision = async (
- officer: AccountId,
- data: AmlExchangeBackend.AmlDecision,
- ): Promise<HttpResponseOk<void>> => {
- const res = await request<void>(`aml/${officer}/decision`, {
- method: "POST",
- data,
- contentType: "json",
- });
- await mutateAll(/.*aml.*/);
- return res;
- };
-
- return {
- updateDecision,
- };
-}
-
-export interface AmlCaseAPI {
- updateDecision: (
- officer: AccountId,
- data: AmlExchangeBackend.AmlDecision,
- ) => Promise<HttpResponseOk<void>>;
-}
-
-function useMatchMutate(): (
- re: RegExp,
- value?: unknown,
-) => Promise<any> {
- const { cache, mutate } = useSWRConfig();
-
- if (!(cache instanceof Map)) {
- throw new Error(
- "matchMutate requires the cache provider to be a Map instance",
- );
- }
-
- return function matchRegexMutate(re: RegExp, value?: unknown) {
- const allKeys = Array.from(cache.keys());
- const keys = allKeys.filter((key) => re.test(key));
- const mutations = keys.map((key) => {
- return mutate(key, value, true);
- });
- return Promise.all(mutations);
- };
-}
diff --git a/packages/aml-backoffice-ui/src/hooks/useCases.ts b/packages/aml-backoffice-ui/src/hooks/useCases.ts
index c07bd5f18..2a133f46d 100644
--- a/packages/aml-backoffice-ui/src/hooks/useCases.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useCases.ts
@@ -1,16 +1,13 @@
-import { useEffect, useState } from "preact/hooks";
+import { useState } from "preact/hooks";
-import { AmlExchangeBackend } from "../types.js";
import {
- HttpResponse,
- HttpResponseOk,
- HttpResponsePaginated,
- RequestError,
+ HttpResponsePaginated
} from "@gnu-taler/web-util/browser";
+import { AmlExchangeBackend } from "../types.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import { AmountString, OfficerAccount, TalerExchangeApi, TalerExchangeResultByMethod, TalerHttpError } from "@gnu-taler/taler-util";
import _useSWR, { SWRHook } from "swr";
-import { usePublicBackend } from "./useBackend.js";
-import { AccountId, buildQuerySignature } from "../account.js";
+import { useExchangeApiContext } from "../context/config.js";
import { useOfficer } from "./useOfficer.js";
const useSWR = _useSWR as unknown as SWRHook;
@@ -22,59 +19,49 @@ const MAX_RESULT_SIZE = PAGE_SIZE * 2 - 1;
* @param args
* @returns
*/
-export function useCases(
- account: AccountId,
- state: AmlExchangeBackend.AmlState,
- signature: string | undefined,
-): HttpResponsePaginated<
- AmlExchangeBackend.AmlRecords,
- AmlExchangeBackend.AmlError
-> {
- const { paginatedFetcher } = usePublicBackend();
+export function useCases(state: AmlExchangeBackend.AmlState) {
+ const officer = useOfficer();
+ const session = officer.state === "ready" ? officer.account : undefined;
+ const { api } = useExchangeApiContext();
- const [page, setPage] = useState(1);
+ const [offset, setOffet] = useState<string>();
+
+ async function fetcher([officer, state, offset]: [OfficerAccount, AmlExchangeBackend.AmlState, string | undefined]) {
+ return await api.getDecisionsByState(officer, state, {
+ order: "asc", offset, limit: MAX_RESULT_SIZE
+ })
+ }
- const {
- data: afterData,
- error: afterError,
- isValidating: loadingAfter,
- } = useSWR<
- HttpResponseOk<AmlExchangeBackend.AmlRecords>,
- RequestError<AmlExchangeBackend.AmlError>
- >(
- [
- `aml/${account}/decisions/${AmlExchangeBackend.AmlState[state]}`,
- page,
- PAGE_SIZE,
- signature,
- ],
- paginatedFetcher,
+ const { data, error } = useSWR<TalerExchangeResultByMethod<"getDecisionsByState">, TalerHttpError>(
+ !session ? undefined : [session, state, offset],
+ fetcher,
);
- const [lastAfter, setLastAfter] = useState<
- HttpResponse<AmlExchangeBackend.AmlRecords, AmlExchangeBackend.AmlError>
- >({ loading: true });
+ // const [lastAfter, setLastAfter] = useState<
+ // HttpResponse<AmlExchangeBackend.AmlRecords, AmlExchangeBackend.AmlError>
+ // >({ loading: true });
- useEffect(() => {
- if (afterData) setLastAfter(afterData);
- }, [afterData]);
+ // useEffect(() => {
+ // if (afterData) setLastAfter(afterData);
+ // }, [afterData]);
- if (afterError) {
- return afterError.cause;
- }
+ // if (afterError) {
+ // return afterError.cause;
+ // }
// if the query returns less that we ask, then we have reach the end or beginning
- const isReachingEnd =
- afterData && afterData.data && afterData.data.records.length < PAGE_SIZE;
- const isReachingStart = false;
+ const isLastPage =
+ data && data.type === "ok" && data.body.records.length < PAGE_SIZE;
+ const isFirstPage = !offset;
const pagination = {
- isReachingEnd,
- isReachingStart,
+ isLastPage,
+ isFirstPage,
loadMore: () => {
- if (!afterData || isReachingEnd) return;
- if (afterData.data && afterData.data.records.length < MAX_RESULT_SIZE) {
- setPage(page + 1);
+ if (isLastPage || data?.type !== "ok") return;
+ const list = data.body.records
+ if (list.length < MAX_RESULT_SIZE) {
+ // setOffset(list[list.length-1].account_name);
}
},
loadMorePrev: () => {
@@ -82,65 +69,62 @@ export function useCases(
},
};
- const records = !afterData
- ? []
- : ((afterData ?? lastAfter).data ?? { records: [] }).records;
- if (loadingAfter) return { loading: true, data: { records } };
- if (afterData) {
- return { ok: true, data: { records }, ...pagination };
+ // const public_accountslist = data?.type !== "ok" ? [] : data.body.public_accounts;
+ if (data) {
+ if (data.type === "fail") {
+ return { data }
+ }
+ return { data, pagination }
+ }
+ if (error) {
+ return error;
}
- return { loading: true };
+ return undefined;
}
-const example1: AmlExchangeBackend.AmlRecords = {
+const example1: TalerExchangeApi.AmlRecords = {
records: [
{
current_state: 0,
h_payto: "QWEQWEQWEQWEWQE",
rowid: 1,
- threshold: "USD 100",
+ threshold: "USD 100" as AmountString,
},
{
current_state: 1,
h_payto: "ASDASDASD",
rowid: 1,
- threshold: "USD 100",
+ threshold: "USD 100" as AmountString,
},
{
current_state: 2,
h_payto: "ZXCZXCZXCXZC",
rowid: 1,
- threshold: "USD 1000",
+ threshold: "USD 1000" as AmountString,
},
{
current_state: 0,
h_payto: "QWEQWEQWEQWEWQE",
rowid: 1,
- threshold: "USD 100",
+ threshold: "USD 100" as AmountString,
},
{
current_state: 1,
h_payto: "ASDASDASD",
rowid: 1,
- threshold: "USD 100",
+ threshold: "USD 100" as AmountString,
},
{
current_state: 2,
h_payto: "ZXCZXCZXCXZC",
rowid: 1,
- threshold: "USD 1000",
+ threshold: "USD 1000" as AmountString,
},
].map((e, idx) => {
e.rowid = idx;
- e.threshold = `${e.threshold}${idx}`;
+ e.threshold = `${e.threshold}${idx}` as AmountString;
return e;
}),
};
-export const exampleResponse: HttpResponsePaginated<AmlExchangeBackend.AmlRecords,AmlExchangeBackend.AmlError> = {
- ok: true,
- data: example1,
- loadMore: () => {},
- loadMorePrev: () => {},
-}
diff --git a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
index 4ec43569b..0747170e8 100644
--- a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
+++ b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts
@@ -1,17 +1,15 @@
import {
AbsoluteTime,
Codec,
+ LockedAccount,
+ OfficerAccount,
buildCodecForObject,
codecForAbsoluteTime,
codecForString,
+ createNewOfficerAccount,
+ unlockOfficerAccount,
} from "@gnu-taler/taler-util";
import {
- Account,
- LockedAccount,
- createNewAccount,
- unlockAccount,
-} from "../account.js";
-import {
buildStorageKey,
useLocalStorage,
useMemoryStorage,
@@ -43,7 +41,7 @@ interface OfficerLocked {
}
interface OfficerReady {
state: "ready";
- account: Account;
+ account: OfficerAccount;
forget: () => void;
lock: () => void;
}
@@ -52,7 +50,7 @@ const OFFICER_KEY = buildStorageKey("officer", codecForOfficer());
const ACCOUNT_KEY = "account";
export function useOfficer(): OfficerState {
- const accountStorage = useMemoryStorage<Account>(ACCOUNT_KEY);
+ const accountStorage = useMemoryStorage<OfficerAccount>(ACCOUNT_KEY);
const officerStorage = useLocalStorage(OFFICER_KEY);
const officer = officerStorage.value;
@@ -62,13 +60,13 @@ export function useOfficer(): OfficerState {
return {
state: "not-found",
create: async (pwd: string) => {
- const { accountId, safe, signingKey } = await createNewAccount(pwd);
+ const { id, safe, signingKey } = await createNewOfficerAccount(pwd);
officerStorage.update({
account: safe,
when: AbsoluteTime.now(),
});
- accountStorage.update({ accountId, signingKey });
+ accountStorage.update({ id, signingKey });
},
};
}
@@ -80,7 +78,7 @@ export function useOfficer(): OfficerState {
officerStorage.reset();
},
tryUnlock: async (pwd: string) => {
- const ac = await unlockAccount(officer.account, pwd);
+ const ac = await unlockOfficerAccount(officer.account, pwd);
accountStorage.update(ac);
},
};
diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
index ce820d612..f618a3592 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
@@ -1,24 +1,23 @@
-import { Fragment, VNode, h } from "preact";
import {
AbsoluteTime,
AmountJson,
Amounts,
+ PaytoString,
+ TalerError,
TranslatedString,
+ assertUnreachable,
} from "@gnu-taler/taler-util";
-import { format } from "date-fns";
+import { ErrorLoading, Loading, useTranslationContext } from "@gnu-taler/web-util/browser";
import { ArrowDownCircleIcon, ClockIcon } from "@heroicons/react/20/solid";
+import { format } from "date-fns";
+import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { NiceForm } from "../NiceForm.js";
import { FlexibleForm } from "../forms/index.js";
import { UIFormField } from "../handlers/forms.js";
+import { useCaseDetails } from "../hooks/useCaseDetails.js";
import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
-import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { useOfficer } from "../hooks/useOfficer.js";
-import { buildQuerySignature } from "../account.js";
-import { useCaseDetails } from "../hooks/useCaseDetails.js";
-import { handleNotOkResult } from "../utils/errors.js";
type AmlEvent = AmlFormEvent | KycCollectionEvent | KycExpirationEvent;
type AmlFormEvent = {
@@ -85,30 +84,33 @@ function getEventsFromAmlHistory(
return ae.concat(ke).sort(selectSooner);
}
-export function CaseDetails({ account: paytoHash }: { account: string }) {
+export function CaseDetails({ account }: { account: string }) {
const [selected, setSelected] = useState<AmlEvent | undefined>(undefined);
- const officer = useOfficer();
const { i18n } = useTranslationContext();
- if (officer.state !== "ready") {
- return <HandleAccountNotReady officer={officer} />;
+ const details = useCaseDetails(account)
+ if (!details) {
+ return <Loading />
}
- const signature =
- officer.state === "ready"
- ? buildQuerySignature(officer.account.signingKey)
- : undefined;
- const details = useCaseDetails(officer.account.accountId, paytoHash, signature)
- if (!details.ok && !details.loading) {
- return handleNotOkResult(i18n)(details);
+ if (details instanceof TalerError) {
+ return <ErrorLoading error={details} />
}
- const aml_history = details.loading ? [] : details.data.aml_history
- const kyc_attributes = details.loading ? [] : details.data.kyc_attributes
- const events = getEventsFromAmlHistory(aml_history,kyc_attributes);
-
+ if (details.type === "fail") {
+ switch (details.case) {
+ case "unauthorized":
+ case "officer-not-found":
+ case "officer-disabled": return <div />
+ default: assertUnreachable(details)
+ }
+ }
+ const { aml_history, kyc_attributes } = details.body
+
+ const events = getEventsFromAmlHistory(aml_history, kyc_attributes);
+
return (
<div>
<a
- href={Pages.newFormEntry.url({ account: paytoHash })}
+ href={Pages.newFormEntry.url({ account })}
class="m-4 block rounded-md w-fit border-0 px-3 py-2 text-center text-sm bg-indigo-700 text-white shadow-sm hover:bg-indigo-700"
>
New AML form
@@ -287,23 +289,22 @@ function ShowConsolidated({
},
Object.entries(cons.kyc).length > 0
? {
- title: "KYC" as TranslatedString,
- fields: Object.entries(cons.kyc).map(([key, field]) => {
- const result: UIFormField = {
- type: "text",
- props: {
- label: key as TranslatedString,
- name: `kyc.${key}.value`,
- help: `${field.provider} since ${
- field.since.t_ms === "never"
- ? "never"
- : format(field.since.t_ms, "dd/MM/yyyy")
+ title: "KYC" as TranslatedString,
+ fields: Object.entries(cons.kyc).map(([key, field]) => {
+ const result: UIFormField = {
+ type: "text",
+ props: {
+ label: key as TranslatedString,
+ name: `kyc.${key}.value`,
+ help: `${field.provider} since ${field.since.t_ms === "never"
+ ? "never"
+ : format(field.since.t_ms, "dd/MM/yyyy")
}` as TranslatedString,
- },
- };
- return result;
- }),
- }
+ },
+ };
+ return result;
+ }),
+ }
: undefined,
],
};
@@ -319,7 +320,7 @@ function ShowConsolidated({
key={`${String(Date.now())}`}
form={form}
initial={cons}
- onUpdate={() => {}}
+ onUpdate={() => { }}
/>
</Fragment>
);
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx
index 990c0d2d4..5f79db71e 100644
--- a/packages/aml-backoffice-ui/src/pages/Cases.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -1,4 +1,5 @@
-import { TranslatedString } from "@gnu-taler/taler-util";
+import { TalerError, TranslatedString, assertUnreachable } from "@gnu-taler/taler-util";
+import { ErrorLoading, Loading, useTranslationContext } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { createNewForm } from "../handlers/forms.js";
@@ -7,34 +8,37 @@ import { useOfficer } from "../hooks/useOfficer.js";
import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
import { amlStateConverter } from "./CaseDetails.js";
-import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
-import { buildQuerySignature } from "../account.js";
-import { handleNotOkResult } from "../utils/errors.js";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
export function Cases() {
- const officer = useOfficer();
const { i18n } = useTranslationContext();
- if (officer.state !== "ready") {
- return <HandleAccountNotReady officer={officer} />;
- }
- const form = createNewForm<{
- state: AmlExchangeBackend.AmlState;
- }>();
- const signature =
- officer.state === "ready"
- ? buildQuerySignature(officer.account.signingKey)
- : undefined;
+ const form = createNewForm<{ state: AmlExchangeBackend.AmlState }>();
+
const initial = AmlExchangeBackend.AmlState.pending;
const [stateFilter, setStateFilter] = useState(initial);
- const list = useCases(officer.account.accountId, stateFilter, signature);
- if (!list.ok && !list.loading) {
- return handleNotOkResult(i18n)(list);
+ const list = useCases(stateFilter);
+
+ if (!list) {
+ return <Loading />
+ }
+
+ if (list instanceof TalerError) {
+ return <ErrorLoading error={list} />
}
- const records = list.loading ? [] : list.data.records
+
+ if (list.data.type === "fail") {
+ switch (list.data.case) {
+ case "unauthorized":
+ case "officer-not-found":
+ case "officer-disabled": return <div />
+ default: assertUnreachable(list.data)
+ }
+ }
+
+ const { records } = list.data.body
+
return (
<div>
<div class="px-4 sm:px-6 lg:px-8">
@@ -52,7 +56,7 @@ export function Cases() {
onUpdate={(v) => {
setStateFilter(v.state ?? initial);
}}
- onSubmit={(v) => {}}
+ onSubmit={(v) => { }}
>
<form.InputChoiceHorizontal
name="state"
diff --git a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
index 429cfb9ca..fa79bb476 100644
--- a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
+++ b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
@@ -2,12 +2,11 @@ import { VNode, h } from "preact";
import { allForms } from "./AntiMoneyLaunderingForm.js";
import { Pages } from "../pages.js";
import { NiceForm } from "../NiceForm.js";
-import { AbsoluteTime, Amounts, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
+import { AbsoluteTime, Amounts, TalerExchangeApi, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
import { AmlExchangeBackend } from "../types.js";
-import { useAmlCasesAPI } from "../hooks/useCaseDetails.js";
import { useOfficer } from "../hooks/useOfficer.js";
import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
-import { buildDecisionSignature, buildQuerySignature } from "../account.js";
+import { useExchangeApiContext } from "../context/config.js";
export function NewFormEntry({
account,
@@ -40,21 +39,21 @@ export function NewFormEntry({
state: AmlExchangeBackend.AmlState.pending,
threshold: Amounts.parseOrThrow("KUDOS:1000"),
};
- const api = useAmlCasesAPI()
-
+ const { api } = useExchangeApiContext()
+
return (
<NiceForm
initial={initial}
form={showingFrom(initial)}
onSubmit={(formValue) => {
if (formValue.state === undefined || formValue.threshold === undefined) return;
-
+
const justification = {
index: selectedForm,
name: formName,
value: formValue
}
- const decision: AmlExchangeBackend.AmlDecision = {
+ const decision: TalerExchangeApi.AmlDecision = {
justification: JSON.stringify(justification),
decision_time: TalerProtocolTimestamp.now(),
h_payto: account,
@@ -63,9 +62,9 @@ export function NewFormEntry({
officer_sig: "",
kyc_requirements: undefined
}
- const signature = buildDecisionSignature(officer.account.signingKey, decision);
- decision.officer_sig = signature
- api.updateDecision(officer.account.accountId, decision);
+ // const signature = buildDecisionSignature(officer.account.signingKey, decision);
+ // decision.officer_sig = signature
+ api.addDecisionDetails(officer.account, decision);
// alert(JSON.stringify(formValue));
}}
diff --git a/packages/aml-backoffice-ui/src/pages/Officer.tsx b/packages/aml-backoffice-ui/src/pages/Officer.tsx
index 5320369e4..4af34805a 100644
--- a/packages/aml-backoffice-ui/src/pages/Officer.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Officer.tsx
@@ -14,12 +14,12 @@ export function Officer() {
Public key
</h1>
<div class="max-w-xl text-base leading-7 text-gray-700 lg:max-w-lg">
- <p class="mt-6 font-mono break-all">{officer.account.accountId}</p>
+ <p class="mt-6 font-mono break-all">{officer.account.id}</p>
</div>
<p>
<a
href={`mailto:aml@exchange.taler.net?body=${encodeURIComponent(
- `I want my AML account\n\n\nPubKey: ${officer.account.accountId}`,
+ `I want my AML account\n\n\nPubKey: ${officer.account.id}`,
)}`}
target="_blank"
rel="noreferrer"
diff --git a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
index 39f8addd3..83d8767fb 100644
--- a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
+++ b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
@@ -1,7 +1,6 @@
-import { TranslatedString } from "@gnu-taler/taler-util";
+import { TranslatedString, UnwrapKeyError } from "@gnu-taler/taler-util";
import { notifyError, notifyInfo } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
-import { UnwrapKeyError } from "../account.js";
import { createNewForm } from "../handlers/forms.js";
export function UnlockAccount({
diff --git a/packages/aml-backoffice-ui/src/utils/errors.tsx b/packages/aml-backoffice-ui/src/utils/errors.tsx
deleted file mode 100644
index b67d61a5f..000000000
--- a/packages/aml-backoffice-ui/src/utils/errors.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import {
- ErrorType,
- HttpResponse,
- HttpResponsePaginated,
- notifyError,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
-import { VNode, h } from "preact";
-import { Loading } from "./Loading.js";
-import { HttpStatusCode, TranslatedString } from "@gnu-taler/taler-util";
-import { AmlExchangeBackend } from "../types.js";
-
-export function handleNotOkResult<Error extends AmlExchangeBackend.AmlError>(
- i18n: ReturnType<typeof useTranslationContext>["i18n"],
-): <T>(
- result: HttpResponsePaginated<T, Error> | HttpResponse<T, Error>,
-) => VNode {
- return function handleNotOkResult2<T>(
- result: HttpResponsePaginated<T, Error> | HttpResponse<T, Error>,
- ): VNode {
- if (result.loading) return <Loading />;
- if (!result.ok) {
- switch (result.type) {
- case ErrorType.TIMEOUT: {
- notifyError(i18n.str`Request timeout, try again later.`, undefined);
- break;
- }
- case ErrorType.CLIENT: {
- if (result.status === HttpStatusCode.Unauthorized) {
- notifyError(i18n.str`Wrong credentials`, undefined);
- return <div> not authorized</div>;
- }
- const errorData = result.payload;
- notifyError(
- i18n.str`Could not load due to a client error`,
- errorData.hint as TranslatedString,
- JSON.stringify(result),
- );
- break;
- }
- case ErrorType.SERVER: {
- notifyError(
- i18n.str`Server returned with error`,
- result.payload.hint as TranslatedString,
- JSON.stringify(result.payload),
- );
- break;
- }
- case ErrorType.UNREADABLE: {
- notifyError(
- i18n.str`Unexpected error.`,
- `Response from ${result.info?.url} is unreadable, http status: ${result.status}` as TranslatedString,
- JSON.stringify(result),
- );
- break;
- }
- case ErrorType.UNEXPECTED: {
- notifyError(
- i18n.str`Unexpected error.`,
- `Diagnostic from ${result.info?.url} is "${result.message}"` as TranslatedString,
- JSON.stringify(result),
- );
- break;
- }
- default: {
- assertUnreachable(result);
- }
- }
-
- return <div>error</div>;
- }
- return <div />;
- };
-}
-export function assertUnreachable(x: never): never {
- throw new Error("Didn't expect to get here");
-}
diff --git a/packages/demobank-ui/src/components/Cashouts/index.ts b/packages/demobank-ui/src/components/Cashouts/index.ts
index 09839e753..6cbb1247d 100644
--- a/packages/demobank-ui/src/components/Cashouts/index.ts
+++ b/packages/demobank-ui/src/components/Cashouts/index.ts
@@ -15,7 +15,7 @@
*/
import { HttpError, utils } from "@gnu-taler/web-util/browser";
-import { Loading } from "../Loading.js";
+import { Loading } from "@gnu-taler/web-util/browser";
// import { compose, StateViewMap } from "../../utils/index.js";
// import { wxApi } from "../../wxApi.js";
import { AbsoluteTime, AmountJson, TalerCoreBankErrorsByMethod, TalerCorebankApi, TalerError } from "@gnu-taler/taler-util";
diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx
index 89f173b0d..76a3a90df 100644
--- a/packages/demobank-ui/src/components/Cashouts/views.tsx
+++ b/packages/demobank-ui/src/components/Cashouts/views.tsx
@@ -18,10 +18,9 @@ import { Fragment, h, VNode } from "preact";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { State } from "./index.js";
import { format } from "date-fns";
-import { Amounts } from "@gnu-taler/taler-util";
+import { Amounts, assertUnreachable } from "@gnu-taler/taler-util";
import { RenderAmount } from "../../pages/PaytoWireTransferForm.js";
-import { assertUnreachable } from "../Routing.js";
-import { Attention } from "../Attention.js";
+import { Attention } from "@gnu-taler/web-util/browser";
export function LoadingUriView({ error }: State.LoadingUriError): VNode {
const { i18n } = useTranslationContext();
diff --git a/packages/demobank-ui/src/components/EmptyComponentExample/index.ts b/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
index 013904ff3..d80e6bdf9 100644
--- a/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
+++ b/packages/demobank-ui/src/components/EmptyComponentExample/index.ts
@@ -14,10 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Loading } from "../../components/Loading.js";
-import { HookError, utils } from "@gnu-taler/web-util/browser";
-//import { compose, StateViewMap } from "../../utils/index.js";
-//import { wxApi } from "../../wxApi.js";
+import { HookError, Loading, utils } from "@gnu-taler/web-util/browser";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
diff --git a/packages/demobank-ui/src/components/Routing.tsx b/packages/demobank-ui/src/components/Routing.tsx
index c94e74201..65a7b6e86 100644
--- a/packages/demobank-ui/src/components/Routing.tsx
+++ b/packages/demobank-ui/src/components/Routing.tsx
@@ -323,7 +323,3 @@ function Redirect({ to }: { to: string }): VNode {
}, []);
return <div>being redirected to {to}</div>;
}
-
-export function assertUnreachable(x: never): never {
- throw new Error("Didn't expect to get here");
-}
diff --git a/packages/demobank-ui/src/components/Transactions/index.ts b/packages/demobank-ui/src/components/Transactions/index.ts
index 3c4fb5ce9..b95aa4cb1 100644
--- a/packages/demobank-ui/src/components/Transactions/index.ts
+++ b/packages/demobank-ui/src/components/Transactions/index.ts
@@ -14,10 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { HttpError, utils } from "@gnu-taler/web-util/browser";
-import { Loading } from "../Loading.js";
-// import { compose, StateViewMap } from "../../utils/index.js";
-// import { wxApi } from "../../wxApi.js";
+import { Loading, utils } from "@gnu-taler/web-util/browser";
import { AbsoluteTime, AmountJson, TalerError } from "@gnu-taler/taler-util";
import { useComponentState } from "./state.js";
import { LoadingUriView, ReadyView } from "./views.js";
diff --git a/packages/demobank-ui/src/components/app.tsx b/packages/demobank-ui/src/components/app.tsx
index 55e1178fe..f79bd96b0 100644
--- a/packages/demobank-ui/src/components/app.tsx
+++ b/packages/demobank-ui/src/components/app.tsx
@@ -72,6 +72,7 @@ function getInitialBackendBaseURL(): string {
? localStorage.getItem("bank-base-url")
: undefined;
let result: string;
+
if (!overrideUrl) {
//normal path
if (!bankUiSettings.backendBaseURL) {
diff --git a/packages/demobank-ui/src/context/config.ts b/packages/demobank-ui/src/context/config.ts
index a31d914b8..a55af719d 100644
--- a/packages/demobank-ui/src/context/config.ts
+++ b/packages/demobank-ui/src/context/config.ts
@@ -18,7 +18,7 @@ import { TalerCorebankApi, TalerCoreBankHttpClient, TalerError } from "@gnu-tale
import { BrowserHttpLib, useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, createContext, FunctionComponent, h, VNode } from "preact";
import { useContext, useEffect, useState } from "preact/hooks";
-import { ErrorLoading } from "../components/ErrorLoading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
/**
*
diff --git a/packages/demobank-ui/src/pages/AccountPage/index.ts b/packages/demobank-ui/src/pages/AccountPage/index.ts
index 87ed878b0..3a3001ad4 100644
--- a/packages/demobank-ui/src/pages/AccountPage/index.ts
+++ b/packages/demobank-ui/src/pages/AccountPage/index.ts
@@ -16,8 +16,8 @@
import { AbsoluteTime, AmountJson, TalerCorebankApi, TalerError } from "@gnu-taler/taler-util";
import { utils } from "@gnu-taler/web-util/browser";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { LoginForm } from "../LoginForm.js";
import { useComponentState } from "./state.js";
import { InvalidIbanView, ReadyView } from "./views.js";
diff --git a/packages/demobank-ui/src/pages/AccountPage/views.tsx b/packages/demobank-ui/src/pages/AccountPage/views.tsx
index 8fff37624..0f5236192 100644
--- a/packages/demobank-ui/src/pages/AccountPage/views.tsx
+++ b/packages/demobank-ui/src/pages/AccountPage/views.tsx
@@ -16,7 +16,7 @@
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { Attention } from "../../components/Attention.js";
+import { Attention } from "@gnu-taler/web-util/browser";
import { Transactions } from "../../components/Transactions/index.js";
import { useSettings } from "../../hooks/settings.js";
import { PaymentOptions } from "../PaymentOptions.js";
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx
index c0babd0c9..5561d7b42 100644
--- a/packages/demobank-ui/src/pages/BankFrame.tsx
+++ b/packages/demobank-ui/src/pages/BankFrame.tsx
@@ -14,15 +14,11 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, TalerError, TranslatedString, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
-import { notifyError, notifyException, useNotifications, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Amounts, TalerError, TranslatedString } from "@gnu-taler/taler-util";
+import { Attention, LangSelector, Loading, notifyError, notifyException, useNotifications, useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, Fragment, VNode, h } from "preact";
import { useEffect, useErrorBoundary, useState } from "preact/hooks";
import logo from "../assets/logo-2021.svg";
-import { Attention } from "../components/Attention.js";
-import { CopyButton } from "../components/CopyButton.js";
-import { LangSelector } from "../components/LangSelector.js";
-import { Loading } from "../components/Loading.js";
import { useAccountDetails } from "../hooks/access.js";
import { useBackendState } from "../hooks/backend.js";
import { getAllBooleanSettings, getLabelForSetting, useSettings } from "../hooks/settings.js";
@@ -179,7 +175,7 @@ export function BankFrame({
</li>
: undefined}
<li>
- <LangSelector />
+ <LangSelector supportedLangs={["en", "es", "de"]} />
</li>
<li>
<div class="text-xs font-semibold leading-6 text-gray-400">
diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx b/packages/demobank-ui/src/pages/LoginForm.tsx
index f21e98343..707c1e688 100644
--- a/packages/demobank-ui/src/pages/LoginForm.tsx
+++ b/packages/demobank-ui/src/pages/LoginForm.tsx
@@ -18,15 +18,15 @@ import { TranslatedString } from "@gnu-taler/taler-util";
import { Notification, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useBackendState } from "../hooks/backend.js";
import { bankUiSettings } from "../settings.js";
import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
import { doAutoFocus } from "./PaytoWireTransferForm.js";
-import { Attention } from "../components/Attention.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { Attention } from "@gnu-taler/web-util/browser";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
/**
diff --git a/packages/demobank-ui/src/pages/OperationState/index.ts b/packages/demobank-ui/src/pages/OperationState/index.ts
index b17b0d787..120fd7b45 100644
--- a/packages/demobank-ui/src/pages/OperationState/index.ts
+++ b/packages/demobank-ui/src/pages/OperationState/index.ts
@@ -16,8 +16,8 @@
import { AbsoluteTime, AmountJson, TalerCoreBankErrorsByMethod, TalerError, TalerErrorDetail, TranslatedString, WithdrawUriResult } from "@gnu-taler/taler-util";
import { utils } from "@gnu-taler/web-util/browser";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { useComponentState } from "./state.js";
import { AbortedView, ConfirmedView, FailedView, InvalidPaytoView, InvalidReserveView, InvalidWithdrawalView, NeedConfirmationView, ReadyView } from "./views.js";
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx b/packages/demobank-ui/src/pages/OperationState/views.tsx
index e623b0dc2..2c4019de2 100644
--- a/packages/demobank-ui/src/pages/OperationState/views.tsx
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -19,13 +19,13 @@ import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-ta
import { Fragment, VNode, h } from "preact";
import { useEffect, useMemo, useState } from "preact/hooks";
import { QR } from "../../components/QR.js";
-import { ShowInputErrorLabel } from "../../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useSettings } from "../../hooks/settings.js";
import { undefinedIfEmpty } from "../../utils.js";
import { State } from "./index.js";
-import { ShowLocalNotification } from "../../components/ShowLocalNotification.js";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Attention } from "../../components/Attention.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Attention } from "@gnu-taler/web-util/browser";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
export function InvalidPaytoView({ payto, onClose }: State.InvalidPayto) {
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index 31592039f..55eba423c 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -32,7 +32,7 @@ import {
import { Fragment, Ref, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { mutate } from "swr";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useBackendState } from "../hooks/backend.js";
import {
@@ -41,7 +41,7 @@ import {
withRuntimeErrorHandling
} from "../utils.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
const logger = new Logger("PaytoWireTransferForm");
diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
index d33353180..d441d002e 100644
--- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
+++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
@@ -18,7 +18,7 @@ import { Logger, TalerError } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { Loading } from "../components/Loading.js";
+import { Loading } from "@gnu-taler/web-util/browser";
import { Transactions } from "../components/Transactions/index.js";
import { usePublicAccounts } from "../hooks/access.js";
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index 22bf604f2..e8c1a0e6e 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -29,7 +29,7 @@ import { QR } from "../components/QR.js";
import { useBankCoreApiContext } from "../context/config.js";
import { withRuntimeErrorHandling } from "../utils.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
export function QrCodeSection({
withdrawUri,
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index c2eca25e8..e8969afb9 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -20,13 +20,13 @@ import {
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useBackendState } from "../hooks/backend.js";
import { bankUiSettings } from "../settings.js";
import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { getRandomPassword, getRandomUsername } from "./rnd.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
const logger = new Logger("RegistrationPage");
diff --git a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
index c07802273..43fd39205 100644
--- a/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/ShowAccountDetails.tsx
@@ -2,8 +2,8 @@ import { TalerCorebankApi, TalerError, TranslatedString } from "@gnu-taler/taler
import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { ErrorLoading } from "../components/ErrorLoading.js";
-import { Loading } from "../components/Loading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useAccountDetails } from "../hooks/access.js";
import { useBackendState } from "../hooks/backend.js";
@@ -12,7 +12,7 @@ import { LoginForm } from "./LoginForm.js";
import { ProfileNavigation } from "./ProfileNavigation.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
import { AccountForm } from "./admin/AccountForm.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
export function ShowAccountDetails({
account,
diff --git a/packages/demobank-ui/src/pages/UpdateAccountPassword.tsx b/packages/demobank-ui/src/pages/UpdateAccountPassword.tsx
index d30216f3f..759182997 100644
--- a/packages/demobank-ui/src/pages/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/UpdateAccountPassword.tsx
@@ -1,14 +1,14 @@
import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useBackendState } from "../hooks/backend.js";
import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { doAutoFocus } from "./PaytoWireTransferForm.js";
import { ProfileNavigation } from "./ProfileNavigation.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
export function UpdateAccountPassword({
account: accountName,
@@ -63,7 +63,7 @@ export function UpdateAccountPassword({
})
case "old-password-invalid-or-not-allowed": return notify({
type: "error",
- title: current ?
+ title: current ?
i18n.str`This user have no right on to change the password.` :
i18n.str`This user have no right on to change the password or the old password doesn't match.`
})
@@ -79,7 +79,7 @@ export function UpdateAccountPassword({
return (
<Fragment>
- <ShowLocalNotification notification={notification} />
+ <ShowLocalNotification notification={notification} />
{accountIsTheCurrentUser ?
<ProfileNavigation current="credentials" /> :
<h1 class="text-base font-semibold leading-6 text-gray-900">
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index e3a713fdd..9a45e6285 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -29,7 +29,7 @@ import {
import { Fragment, VNode, h } from "preact";
import { forwardRef } from "preact/compat";
import { useState } from "preact/hooks";
-import { Attention } from "../components/Attention.js";
+import { Attention } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useBackendState } from "../hooks/backend.js";
import { useSettings } from "../hooks/settings.js";
@@ -37,7 +37,7 @@ import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { OperationState } from "./OperationState/index.js";
import { InputAmount, doAutoFocus } from "./PaytoWireTransferForm.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
const logger = new Logger("WalletWithdrawForm");
const RefAmount = forwardRef(InputAmount);
diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
index b548c0d16..f34e8a919 100644
--- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
@@ -31,13 +31,13 @@ import {
import { Fragment, VNode, h } from "preact";
import { useMemo, useState } from "preact/hooks";
import { mutate } from "swr";
-import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useSettings } from "../hooks/settings.js";
import { undefinedIfEmpty, withRuntimeErrorHandling } from "../utils.js";
import { RenderAmount } from "./PaytoWireTransferForm.js";
import { assertUnreachable } from "./WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
const logger = new Logger("WithdrawalConfirmationQuestion");
diff --git a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
index 4620e5456..5ed57a0f7 100644
--- a/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalOperationPage.tsx
@@ -23,7 +23,7 @@ import {
useTranslationContext
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { Attention } from "../components/Attention.js";
+import { Attention } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../context/config.js";
import { useSettings } from "../hooks/settings.js";
import { WithdrawalQRCode } from "./WithdrawalQRCode.js";
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index bdd8ea585..52e3c63ee 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -23,9 +23,9 @@ import {
} from "@gnu-taler/taler-util";
import { notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { Attention } from "../components/Attention.js";
-import { ErrorLoading } from "../components/ErrorLoading.js";
-import { Loading } from "../components/Loading.js";
+import { Attention } from "@gnu-taler/web-util/browser";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { useWithdrawalDetails } from "../hooks/access.js";
import { QrCodeSection } from "./QrCodeSection.js";
import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js";
diff --git a/packages/demobank-ui/src/pages/admin/Account.tsx b/packages/demobank-ui/src/pages/admin/Account.tsx
index 19189bec4..588d945ba 100644
--- a/packages/demobank-ui/src/pages/admin/Account.tsx
+++ b/packages/demobank-ui/src/pages/admin/Account.tsx
@@ -1,8 +1,8 @@
import { Amounts, TalerError } from "@gnu-taler/taler-util";
import { notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { useAccountDetails } from "../../hooks/access.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
import { LoginForm } from "../LoginForm.js";
diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
index fa3a28057..7311d826e 100644
--- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
@@ -1,11 +1,11 @@
import { ComponentChildren, Fragment, VNode, h } from "preact";
-import { ShowInputErrorLabel } from "../../components/ShowInputErrorLabel.js";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { PartialButDefined, RecursivePartial, WithIntermediate, undefinedIfEmpty, validateIBAN } from "../../utils.js";
import { useEffect, useRef, useState } from "preact/hooks";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { PaytoString, TalerCorebankApi, buildPayto, parsePaytoUri } from "@gnu-taler/taler-util";
import { doAutoFocus } from "../PaytoWireTransferForm.js";
-import { CopyButton } from "../../components/CopyButton.js";
+import { CopyButton } from "@gnu-taler/web-util/browser";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/;
diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx b/packages/demobank-ui/src/pages/admin/AccountList.tsx
index be5194e6d..2aefde715 100644
--- a/packages/demobank-ui/src/pages/admin/AccountList.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx
@@ -1,8 +1,8 @@
import { Amounts, TalerError } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useBusinessAccounts } from "../../hooks/circuit.js";
import { RenderAmount } from "../PaytoWireTransferForm.js";
diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
index a30cae547..9bc2ee571 100644
--- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
@@ -2,7 +2,7 @@ import { AmountString, Amounts, TalerCorebankApi, TalerError } from "@gnu-taler/
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
import { Transactions } from "../../components/Transactions/index.js";
import { useLastMonitorInfo } from "../../hooks/circuit.js";
import { RenderAmount } from "../PaytoWireTransferForm.js";
diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
index 3f4364c16..0369a6283 100644
--- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
@@ -3,14 +3,14 @@ import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-ta
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { mutate } from "swr";
-import { Attention } from "../../components/Attention.js";
+import { Attention } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useBackendState } from "../../hooks/backend.js";
import { withRuntimeErrorHandling } from "../../utils.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
import { getRandomPassword } from "../rnd.js";
import { AccountForm, AccountFormData } from "./AccountForm.js";
-import { ShowLocalNotification } from "../../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
export function CreateNewAccount({
onCancel,
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index fa9693941..01136fdaf 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -2,10 +2,10 @@ import { Amounts, TalerError, TranslatedString } from "@gnu-taler/taler-util";
import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { Attention } from "../../components/Attention.js";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
-import { ShowInputErrorLabel } from "../../components/ShowInputErrorLabel.js";
+import { Attention } from "@gnu-taler/web-util/browser";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useAccountDetails } from "../../hooks/access.js";
import { useBackendState } from "../../hooks/backend.js";
@@ -13,7 +13,7 @@ import { undefinedIfEmpty } from "../../utils.js";
import { LoginForm } from "../LoginForm.js";
import { doAutoFocus } from "../PaytoWireTransferForm.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
export function RemoveAccount({
account,
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 5c284be24..735d84847 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -25,10 +25,10 @@ import {
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { mutate } from "swr";
-import { Attention } from "../../components/Attention.js";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
-import { ShowInputErrorLabel } from "../../components/ShowInputErrorLabel.js";
+import { Attention } from "@gnu-taler/web-util/browser";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useAccountDetails } from "../../hooks/access.js";
import { useBackendState } from "../../hooks/backend.js";
@@ -43,7 +43,7 @@ import {
import { LoginForm } from "../LoginForm.js";
import { InputAmount } from "../PaytoWireTransferForm.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
interface Props {
account: string;
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
index a8b57b90c..80e585cf5 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
@@ -25,10 +25,10 @@ import { format } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { mutate } from "swr";
-import { Attention } from "../../components/Attention.js";
-import { ErrorLoading } from "../../components/ErrorLoading.js";
-import { Loading } from "../../components/Loading.js";
-import { ShowInputErrorLabel } from "../../components/ShowInputErrorLabel.js";
+import { Attention } from "@gnu-taler/web-util/browser";
+import { ErrorLoading } from "@gnu-taler/web-util/browser";
+import { Loading } from "@gnu-taler/web-util/browser";
+import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useBackendState } from "../../hooks/backend.js";
import {
@@ -39,7 +39,7 @@ import {
withRuntimeErrorHandling
} from "../../utils.js";
import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { ShowLocalNotification } from "../../components/ShowLocalNotification.js";
+import { ShowLocalNotification } from "@gnu-taler/web-util/browser";
interface Props {
id: string;
diff --git a/packages/demobank-ui/tailwind.config.js b/packages/demobank-ui/tailwind.config.js
index 01f058b2e..ec51dfbb8 100644
--- a/packages/demobank-ui/tailwind.config.js
+++ b/packages/demobank-ui/tailwind.config.js
@@ -1,6 +1,12 @@
/** @type {import('tailwindcss').Config} */
export default {
- content: ["./src/**/*.{html,tsx}"],
+ content: {
+ relative: true,
+ files: [
+ "./src/**/*.{html,tsx}",
+ "./node_modules/@gnu-taler/web-util/src/**/*.{html,tsx}"
+ ],
+ },
theme: {
extend: {},
},
diff --git a/packages/demobank-ui/src/assets/lang.svg b/packages/web-util/src/assets/lang.svg
index dd72ce65e..dd72ce65e 100644
--- a/packages/demobank-ui/src/assets/lang.svg
+++ b/packages/web-util/src/assets/lang.svg
diff --git a/packages/demobank-ui/src/components/Attention.tsx b/packages/web-util/src/components/Attention.tsx
index 57d0a4199..b85230a1b 100644
--- a/packages/demobank-ui/src/components/Attention.tsx
+++ b/packages/web-util/src/components/Attention.tsx
@@ -1,12 +1,11 @@
-import { TranslatedString } from "@gnu-taler/taler-util";
+import { TranslatedString, assertUnreachable } from "@gnu-taler/taler-util";
import { ComponentChildren, Fragment, VNode, h } from "preact";
-import { assertUnreachable } from "./Routing.js";
-interface Props {
- type?: "info" | "success" | "warning" | "danger",
- onClose?: () => void,
- title: TranslatedString,
- children?: ComponentChildren ,
+interface Props {
+ type?: "info" | "success" | "warning" | "danger",
+ onClose?: () => void,
+ title: TranslatedString,
+ children?: ComponentChildren,
}
export function Attention({ type = "info", title, children, onClose }: Props): VNode {
return <div class={`group attention-${type} mt-2 shadow-lg`}>
diff --git a/packages/demobank-ui/src/components/CopyButton.tsx b/packages/web-util/src/components/CopyButton.tsx
index ca1ceaa8a..0096da365 100644
--- a/packages/demobank-ui/src/components/CopyButton.tsx
+++ b/packages/web-util/src/components/CopyButton.tsx
@@ -1,8 +1,6 @@
import { h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
-
-
export function CopyIcon(): VNode {
return (
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
diff --git a/packages/demobank-ui/src/components/ErrorLoading.tsx b/packages/web-util/src/components/ErrorLoading.tsx
index 84e72c5a1..02f2a3282 100644
--- a/packages/demobank-ui/src/components/ErrorLoading.tsx
+++ b/packages/web-util/src/components/ErrorLoading.tsx
@@ -15,11 +15,10 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { TalerError, TalerErrorCode } from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { TalerError, TalerErrorCode, assertUnreachable } from "@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import { Attention } from "./Attention.js";
-import { assertUnreachable } from "./Routing.js";
+import { useTranslationContext } from "../index.browser.js";
export function ErrorLoading({ error, showDetail }: { error: TalerError, showDetail?: boolean }): VNode {
const { i18n } = useTranslationContext()
diff --git a/packages/demobank-ui/src/components/LangSelector.tsx b/packages/web-util/src/components/LangSelector.tsx
index 7cf0300df..a8d910129 100644
--- a/packages/demobank-ui/src/components/LangSelector.tsx
+++ b/packages/web-util/src/components/LangSelector.tsx
@@ -21,12 +21,12 @@
import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { strings as messages } from "../i18n/strings.js";
+// import { strings as messages } from "../i18n/strings.js";
import langIcon from "../assets/lang.svg";
+import { useTranslationContext } from "../index.browser.js";
type LangsNames = {
- [P in keyof typeof messages]: string;
+ [P: string]: string;
};
const names: LangsNames = {
@@ -43,7 +43,7 @@ function getLangName(s: keyof LangsNames | string): string {
return String(s);
}
-export function LangSelector(): VNode {
+export function LangSelector({ supportedLangs }: { supportedLangs: string[] }): VNode {
const [updatingLang, setUpdatingLang] = useState(false);
const { lang, changeLanguage } = useTranslationContext();
const [hidden, setHidden] = useState(true);
@@ -70,7 +70,7 @@ export function LangSelector(): VNode {
setHidden((h) => !h);
}}>
<span class="flex items-center">
- <img src={langIcon} alt="" class="h-5 w-5 flex-shrink-0 rounded-full" />
+ <img alt="language" class="h-5 w-5 flex-shrink-0 rounded-full" src={langIcon} />
<span class="ml-3 block truncate">{getLangName(lang)}</span>
</span>
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
@@ -82,7 +82,7 @@ export function LangSelector(): VNode {
{!hidden &&
<ul class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" tabIndex={-1} role="listbox" aria-labelledby="listbox-label" aria-activedescendant="listbox-option-3">
- {Object.keys(messages)
+ {supportedLangs
.filter((l) => l !== lang)
.map((lang) => (
<li class="text-gray-900 hover:bg-indigo-600 hover:text-white cursor-pointer relative select-none py-2 pl-3 pr-9" role="option"
diff --git a/packages/demobank-ui/src/components/Loading.tsx b/packages/web-util/src/components/Loading.tsx
index b567e9056..b567e9056 100644
--- a/packages/demobank-ui/src/components/Loading.tsx
+++ b/packages/web-util/src/components/Loading.tsx
diff --git a/packages/demobank-ui/src/components/ShowInputErrorLabel.tsx b/packages/web-util/src/components/ShowInputErrorLabel.tsx
index c5840cad9..c5840cad9 100644
--- a/packages/demobank-ui/src/components/ShowInputErrorLabel.tsx
+++ b/packages/web-util/src/components/ShowInputErrorLabel.tsx
diff --git a/packages/demobank-ui/src/components/ShowLocalNotification.tsx b/packages/web-util/src/components/ShowLocalNotification.tsx
index bb62a48f0..cb947e536 100644
--- a/packages/demobank-ui/src/components/ShowLocalNotification.tsx
+++ b/packages/web-util/src/components/ShowLocalNotification.tsx
@@ -1,7 +1,7 @@
-import { Notification } from "@gnu-taler/web-util/browser";
import { h, Fragment, VNode } from "preact";
import { Attention } from "./Attention.js";
-import { useSettings } from "../hooks/settings.js";
+import { Notification } from "../index.browser.js";
+// import { useSettings } from "../hooks/settings.js";
export function ShowLocalNotification({ notification }: { notification?: Notification }): VNode {
if (!notification) return <Fragment />
@@ -17,7 +17,7 @@ export function ShowLocalNotification({ notification }: { notification?: Notific
{notification.message.description}
</div>
}
- <MaybeShowDebugInfo info={notification.message.debug} />
+ {/* <MaybeShowDebugInfo info={notification.message.debug} /> */}
</Attention>
</div>
</div>
@@ -31,13 +31,13 @@ export function ShowLocalNotification({ notification }: { notification?: Notific
}
-function MaybeShowDebugInfo({ info }: { info: any }): VNode {
- const [settings] = useSettings()
- if (settings.showDebugInfo) {
- return <pre class="whitespace-break-spaces ">
- {info}
- </pre>
- }
- return <Fragment />
-}
+// function MaybeShowDebugInfo({ info }: { info: any }): VNode {
+// const [settings] = useSettings()
+// if (settings.showDebugInfo) {
+// return <pre class="whitespace-break-spaces ">
+// {info}
+// </pre>
+// }
+// return <Fragment />
+// }
diff --git a/packages/web-util/src/components/index.ts b/packages/web-util/src/components/index.ts
index 9441e971d..8344d4a7a 100644
--- a/packages/web-util/src/components/index.ts
+++ b/packages/web-util/src/components/index.ts
@@ -1 +1,8 @@
export * as utils from "./utils.js";
+export * from "./Attention.js";
+export * from "./CopyButton.js";
+export * from "./ErrorLoading.js";
+export * from "./LangSelector.js";
+export * from "./Loading.js";
+export * from "./ShowInputErrorLabel.js";
+export * from "./ShowLocalNotification.js";
diff --git a/packages/web-util/src/declaration.d.ts b/packages/web-util/src/declaration.d.ts
new file mode 100644
index 000000000..c8ba3d576
--- /dev/null
+++ b/packages/web-util/src/declaration.d.ts
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 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/>
+ */
+
+declare module "*.css" {
+ const mapping: Record<string, string>;
+ export default mapping;
+}
+declare module "*.svg" {
+ const content: any;
+ export default content;
+}
+declare module "*.jpeg" {
+ const content: any;
+ export default content;
+}
+declare module "*.png" {
+ const content: any;
+ export default content;
+}
+
+declare const __VERSION__: string;
+declare const __GIT_HASH__: string;