From 8407a1d52e3a89f9c005f9820586d2d0a123c177 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 4 Dec 2023 09:43:03 -0300 Subject: api sync, withdrawal info without password, account creation WIP --- .../demobank-ui/src/components/Cashouts/views.tsx | 41 +++--- .../src/components/ErrorLoadingWithDebug.tsx | 9 ++ packages/demobank-ui/src/hooks/access.ts | 31 +++-- packages/demobank-ui/src/pages/BankFrame.tsx | 11 -- .../demobank-ui/src/pages/OperationState/state.ts | 9 +- .../demobank-ui/src/pages/RegistrationPage.tsx | 24 ++-- packages/demobank-ui/src/pages/WireTransfer.tsx | 3 +- .../src/pages/WithdrawalConfirmationQuestion.tsx | 153 ++++++++++++--------- .../demobank-ui/src/pages/WithdrawalQRCode.tsx | 7 +- .../src/pages/account/ShowAccountDetails.tsx | 15 +- .../demobank-ui/src/pages/admin/AccountForm.tsx | 124 +++++++++++++++-- .../demobank-ui/src/pages/admin/AccountList.tsx | 4 +- packages/demobank-ui/src/pages/admin/AdminHome.tsx | 3 +- .../src/pages/admin/CreateNewAccount.tsx | 33 +++-- .../demobank-ui/src/pages/admin/RemoveAccount.tsx | 3 +- .../src/pages/business/CreateCashout.tsx | 5 +- .../src/pages/business/ShowCashoutDetails.tsx | 5 +- packages/demobank-ui/src/stories.test.ts | 3 +- packages/demobank-ui/src/utils.ts | 4 +- 19 files changed, 318 insertions(+), 169 deletions(-) create mode 100644 packages/demobank-ui/src/components/ErrorLoadingWithDebug.tsx diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx b/packages/demobank-ui/src/components/Cashouts/views.tsx index 59bb4a16b..115a2e014 100644 --- a/packages/demobank-ui/src/components/Cashouts/views.tsx +++ b/packages/demobank-ui/src/components/Cashouts/views.tsx @@ -21,6 +21,7 @@ import { Fragment, h, VNode } from "preact"; import { RenderAmount } from "../../pages/PaytoWireTransferForm.js"; import { State } from "./index.js"; import { useConversionInfo } from "../../hooks/circuit.js"; +import { ErrorLoadingWithDebug } from "../ErrorLoadingWithDebug.js"; export function LoadingUriView({ error }: State.LoadingUriError): VNode { const { i18n } = useTranslationContext(); @@ -57,7 +58,7 @@ export function ReadyView({ cashouts, onSelected }: State.Ready): VNode { return } if (resp instanceof TalerError) { - return + return } if (!cashouts.length) return
const txByDate = cashouts.reduce((prev, cur) => { @@ -105,9 +106,9 @@ export function ReadyView({ cashouts, onSelected }: State.Ready): VNode { return ( { - e.preventDefault(); - onSelected(item.id); - }} class="relative py-2 pl-2 pr-2 text-sm "> + e.preventDefault(); + onSelected(item.id); + }} class="relative py-2 pl-2 pr-2 text-sm ">
{creationTime}
{/*
Amount
@@ -132,26 +133,26 @@ export function ReadyView({ cashouts, onSelected }: State.Ready): VNode {
*/} { - e.preventDefault(); - onSelected(item.id); - }}class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 cursor-pointer">{confirmationTime} + e.preventDefault(); + onSelected(item.id); + }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 cursor-pointer">{confirmationTime} { - e.preventDefault(); - onSelected(item.id); - }}class="hidden sm:table-cell px-3 py-3.5 text-sm text-red-600 cursor-pointer"> + e.preventDefault(); + onSelected(item.id); + }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-red-600 cursor-pointer"> { - e.preventDefault(); - onSelected(item.id); - }}class="hidden sm:table-cell px-3 py-3.5 text-sm text-green-600 cursor-pointer"> + e.preventDefault(); + onSelected(item.id); + }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-green-600 cursor-pointer"> - { - e.preventDefault(); - onSelected(item.id); - }}class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 cursor-pointer">{item.status} { - e.preventDefault(); - onSelected(item.id); - }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"> + e.preventDefault(); + onSelected(item.id); + }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 cursor-pointer">{item.status} + { + e.preventDefault(); + onSelected(item.id); + }} class="hidden sm:table-cell px-3 py-3.5 text-sm text-gray-500 break-all min-w-md"> {item.subject} ) diff --git a/packages/demobank-ui/src/components/ErrorLoadingWithDebug.tsx b/packages/demobank-ui/src/components/ErrorLoadingWithDebug.tsx new file mode 100644 index 000000000..8cdac4561 --- /dev/null +++ b/packages/demobank-ui/src/components/ErrorLoadingWithDebug.tsx @@ -0,0 +1,9 @@ +import { ErrorLoading } from "@gnu-taler/web-util/browser"; +import { usePreferences } from "../hooks/preferences.js"; +import { VNode, h } from "preact"; +import { TalerError } from "@gnu-taler/taler-util"; + +export function ErrorLoadingWithDebug({ error }: { error: TalerError }): VNode { + const [pref] = usePreferences(); + return +} diff --git a/packages/demobank-ui/src/hooks/access.ts b/packages/demobank-ui/src/hooks/access.ts index 1e09c444a..fc1cff129 100644 --- a/packages/demobank-ui/src/hooks/access.ts +++ b/packages/demobank-ui/src/hooks/access.ts @@ -14,8 +14,8 @@ GNU Taler; see the file COPYING. If not, see */ -import { AccessToken, TalerBankIntegrationResultByMethod, TalerCoreBankResultByMethod, TalerHttpError } from "@gnu-taler/taler-util"; -import { useState } from "preact/hooks"; +import { AccessToken, TalerBankIntegrationResultByMethod, TalerCoreBankResultByMethod, TalerHttpError, WithdrawalOperationStatus } from "@gnu-taler/taler-util"; +import { useEffect, useState } from "preact/hooks"; import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js"; import { useBackendState } from "./backend.js"; @@ -56,18 +56,17 @@ export function useAccountDetails(account: string) { return undefined; } -// FIXME: should poll export function useWithdrawalDetails(wid: string) { - // const { state: credentials } = useBackendState(); const { api } = useBankCoreApiContext(); + const [latestStatus, setLatestStatus] = useState() - async function fetcher([wid]: [string]) { - return await api.getIntegrationAPI().getWithdrawalOperationById(wid) + async function fetcher([wid, old_state]: [string, WithdrawalOperationStatus | undefined]) { + return await api.getWithdrawalById(wid, old_state === undefined ? undefined : { old_state, timeoutMs: 15000 }) } - const { data, error } = useSWR, TalerHttpError>( - [wid, "getWithdrawalById"], fetcher, { - refreshInterval: 1000, + const { data, error } = useSWR, TalerHttpError>( + [wid, latestStatus, "getWithdrawalById"], fetcher, { + refreshInterval: 3000, refreshWhenHidden: false, revalidateOnFocus: false, revalidateOnReconnect: false, @@ -78,6 +77,14 @@ export function useWithdrawalDetails(wid: string) { keepPreviousData: true, }); + const currentStatus = data !== undefined && data.type === "ok" ? data.body.status : undefined; + + useEffect(() => { + if (currentStatus !== undefined && currentStatus !== latestStatus) { + setLatestStatus(currentStatus) + } + }, [currentStatus]) + if (data) return data; if (error) return error; return undefined; @@ -110,12 +117,12 @@ export function useTransactionDetails(account: string, tid: number) { return undefined; } -export function usePublicAccounts(filterAccount: string |undefined ,initial?: number) { +export function usePublicAccounts(filterAccount: string | undefined, initial?: number) { const [offset, setOffset] = useState(initial); const { api } = useBankCoreApiContext(); - async function fetcher([account, txid]: [string | undefined , number | undefined]) { - return await api.getPublicAccounts({account},{ + async function fetcher([account, txid]: [string | undefined, number | undefined]) { + return await api.getPublicAccounts({ account }, { limit: MAX_RESULT_SIZE, offset: txid ? String(txid) : undefined, order: "asc" diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx b/packages/demobank-ui/src/pages/BankFrame.tsx index 1762c6b56..0ac9ed8f1 100644 --- a/packages/demobank-ui/src/pages/BankFrame.tsx +++ b/packages/demobank-ui/src/pages/BankFrame.tsx @@ -132,17 +132,6 @@ export function BankFrame({ ); } -function MaybeShowDebugInfo({ info }: { info: any }): VNode { - const [settings] = usePreferences() - if (settings.showDebugInfo) { - return
-      {info}
-    
- } - return -} - - function WelcomeAccount({ account: accountName }: { account: string }): VNode { const { i18n } = useTranslationContext(); return diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts b/packages/demobank-ui/src/pages/OperationState/state.ts index da924104a..57ede87a7 100644 --- a/packages/demobank-ui/src/pages/OperationState/state.ts +++ b/packages/demobank-ui/src/pages/OperationState/state.ts @@ -134,6 +134,7 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive if (result.type === "fail") { switch (result.case) { + case "invalid-id": case "not-found": { return { status: "aborted", @@ -144,7 +145,7 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive }, } } - default: assertUnreachable(result.case) + default: assertUnreachable(result) } } @@ -180,9 +181,9 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive status: "ready", error: undefined, uri: parsedUri, - onClose: !creds ? (async () => { - onClose(); - return undefined + onClose: !creds ? (async () => { + onClose(); + return undefined }) : doAbort, } } diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx index 2de6de373..e1d32002b 100644 --- a/packages/demobank-ui/src/pages/RegistrationPage.tsx +++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx @@ -96,7 +96,7 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on : undefined, }); - async function doRegistrationAndLogin(name: string, username: string, password: string) { + async function doRegistrationAndLogin(name: string, username: string, password: string, onComplete: () => void) { await handleError(async () => { const creationResponse = await api.createAccount("" as AccessToken, { name, username, password }); if (creationResponse.type === "fail") { @@ -137,6 +137,12 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on description: creationResponse.detail.hint as TranslatedString, debug: creationResponse.detail, }) + case "user-cant-set-debt": return notify({ + type: "error", + title: i18n.str`Only admin is allow to set debt limit.`, + description: creationResponse.detail.hint as TranslatedString, + debug: creationResponse.detail, + }) default: assertUnreachable(creationResponse) } } @@ -165,16 +171,18 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on default: assertUnreachable(resp) } } + onComplete() }) } async function doRegistrationStep() { if (!username || !password || !name) return; - await doRegistrationAndLogin(name, username, password) - setUsername(undefined); - setPassword(undefined); - setRepeatPassword(undefined); - onComplete(); + await doRegistrationAndLogin(name, username, password, () => { + setUsername(undefined); + setPassword(undefined); + setRepeatPassword(undefined); + onComplete(); + }) } async function doRandomRegistration(tries: number = 3) { @@ -183,8 +191,8 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on const pass = settings.simplePasswordForRandomAccounts ? "123" : getRandomPassword(); const username = `_${user.first}-${user.second}_` const name = `${user.first}, ${user.second}` - await doRegistrationAndLogin(name, username, pass) - onComplete(); + await doRegistrationAndLogin(name, username, pass, onComplete) + } return ( diff --git a/packages/demobank-ui/src/pages/WireTransfer.tsx b/packages/demobank-ui/src/pages/WireTransfer.tsx index 5e6081b11..a68c085c9 100644 --- a/packages/demobank-ui/src/pages/WireTransfer.tsx +++ b/packages/demobank-ui/src/pages/WireTransfer.tsx @@ -8,6 +8,7 @@ import { assertUnreachable } from "./WithdrawalOperationPage.js"; import { LoginForm } from "./LoginForm.js"; import { PaytoWireTransferForm } from "./PaytoWireTransferForm.js"; import { useBackendState } from "../hooks/backend.js"; +import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js"; export function WireTransfer({ toAccount, onRegister, onCancel, onSuccess }: { onSuccess?: () => void; toAccount?: string, onCancel?: () => void, onRegister?: () => void }): VNode { const { i18n } = useTranslationContext(); @@ -19,7 +20,7 @@ export function WireTransfer({ toAccount, onRegister, onCancel, onSuccess }: { o return } if (result instanceof TalerError) { - return + return } if (result.type === "fail") { switch (result.case) { diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx index e21c0917b..f8913f0ec 100644 --- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx @@ -25,13 +25,14 @@ import { WithdrawUriResult } from "@gnu-taler/taler-util"; import { + Attention, ErrorLoading, Loading, notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser"; -import { Fragment, VNode, h } from "preact"; +import { ComponentChildren, Fragment, VNode, h } from "preact"; import { useMemo, useState } from "preact/hooks"; import { mutate } from "swr"; import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser"; @@ -45,6 +46,7 @@ import { useBackendState } from "../hooks/backend.js"; import { useWithdrawalDetails } from "../hooks/access.js"; import { OperationState } from "./OperationState/index.js"; import { OperationNotFound } from "./WithdrawalQRCode.js"; +import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js"; const logger = new Logger("WithdrawalConfirmationQuestion"); @@ -54,6 +56,7 @@ interface Props { details: { account: PaytoUri, reserve: string, + username: string, amount: AmountJson, } } @@ -75,15 +78,16 @@ export function WithdrawalConfirmationQuestion({ return } if (withdrawalInfo instanceof TalerError) { - return + return } if (withdrawalInfo.type === "fail") { - switch(withdrawalInfo.case) { - case "not-found": return - default: assertUnreachable(withdrawalInfo.case) + switch (withdrawalInfo.case) { + case "not-found": return + case "invalid-id": return + default: assertUnreachable(withdrawalInfo) } } - + const captchaNumbers = useMemo(() => { return { a: Math.floor(Math.random() * 10), @@ -200,67 +204,70 @@ export function WithdrawalConfirmationQuestion({
-
-
-

Answer the next question to authorize the wire transfer.

-
-
{ - e.preventDefault() - }} - > -
- -
-
- +
+
+

Answer the next question to authorize the wire transfer.

+
+ { + e.preventDefault() + }} + > +
+ + +
+
+ { - setCaptchaAnswer(e.currentTarget.value) - }} - /> + name="answer" + id="answer" + autocomplete="off" + onChange={(e): void => { + setCaptchaAnswer(e.currentTarget.value) + }} + /> +
+
-
-
-
- - -
+
+ + +
- -
+ +
+
@@ -325,6 +332,26 @@ export function WithdrawalConfirmationQuestion({
- + ); } + +export function ShouldBeSameUser({ username, children }: { username: string, children: ComponentChildren }): VNode { + const { state: credentials } = useBackendState(); + const { i18n } = useTranslationContext() + if (credentials.status === "loggedOut") { + return +

You should login as "{username}"

+
+ } + if (credentials.username !== username) { + return +

+ You can switch to account "{username}" and complete the operation. +

+
+ } + return + {children} + +} \ No newline at end of file diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx index 0c3d83c3b..f07790493 100644 --- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx +++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx @@ -30,6 +30,7 @@ import { useWithdrawalDetails } from "../hooks/access.js"; import { QrCodeSection } from "./QrCodeSection.js"; import { WithdrawalConfirmationQuestion } from "./WithdrawalConfirmationQuestion.js"; import { assertUnreachable } from "./WithdrawalOperationPage.js"; +import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js"; const logger = new Logger("WithdrawalQRCode"); @@ -53,12 +54,13 @@ export function WithdrawalQRCode({ return } if (result instanceof TalerError) { - return + return } if (result.type === "fail") { switch (result.case) { + case "invalid-id": case "not-found": return - default: assertUnreachable(result.case) + default: assertUnreachable(result) } } @@ -159,6 +161,7 @@ export function WithdrawalQRCode({ (); + const [submitAccount, setSubmitAccount] = useState(); const [notification, notify, handleError] = useLocalNotification() const result = useAccountDetails(account); @@ -39,7 +40,7 @@ export function ShowAccountDetails({ return } if (result instanceof TalerError) { - return + return } if (result.type === "fail") { switch (result.case) { @@ -55,15 +56,7 @@ export function ShowAccountDetails({ const resp = await api.updateAccount({ token: creds.token, username: account, - }, { - cashout_payto_uri: submitAccount.cashout_payto_uri, - challenge_contact_data: undefinedIfEmpty({ - email: submitAccount.contact_data?.email, - phone: submitAccount.contact_data?.phone, - }), - is_taler_exchange: false, - name: submitAccount.name, - }); + }, submitAccount); if (resp.type === "ok") { notifyInfo(i18n.str`Account updated`); diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx b/packages/demobank-ui/src/pages/admin/AccountForm.tsx index c2afb195a..c8abde74b 100644 --- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx +++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx @@ -1,10 +1,13 @@ -import { PaytoString, TalerCorebankApi, buildPayto, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; +import { AmountString, Amounts, PaytoString, TalerCorebankApi, buildPayto, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util"; import { CopyButton, ShowInputErrorLabel, useTranslationContext } from "@gnu-taler/web-util/browser"; import { ComponentChildren, Fragment, VNode, h } from "preact"; import { useState } from "preact/hooks"; import { PartialButDefined, RecursivePartial, WithIntermediate, undefinedIfEmpty, validateIBAN } from "../../utils.js"; -import { doAutoFocus } from "../PaytoWireTransferForm.js"; +import { InputAmount, doAutoFocus } from "../PaytoWireTransferForm.js"; import { assertUnreachable } from "../WithdrawalOperationPage.js"; +import { useBackendContext } from "../../context/backend.js"; +import { useBankCoreApiContext } from "../../context/config.js"; +import { getRandomPassword } from "../rnd.js"; const IBAN_REGEX = /^[A-Z][A-Z0-9]*$/; const EMAIL_REGEX = @@ -13,6 +16,11 @@ const REGEX_JUST_NUMBERS_REGEX = /^\+[0-9 ]*$/; export type AccountFormData = TalerCorebankApi.AccountData & { username: string } +type MM = { + "create": (a: TalerCorebankApi.RegisterAccountRequest | undefined) => void, + "update": (a: TalerCorebankApi.AccountReconfiguration | undefined) => void, + "show": undefined +} /** * Create valid account object to update or create * Take template as initial values for the form @@ -21,7 +29,7 @@ export type AccountFormData = TalerCorebankApi.AccountData & { username: string * @param param0 * @returns */ -export function AccountForm({ +export function AccountForm({ template, username, purpose, @@ -34,9 +42,10 @@ export function AccountForm({ children: ComponentChildren, username?: string, noCashout?: boolean, + admin?: boolean, template: TalerCorebankApi.AccountData | undefined; - onChange: (a: AccountFormData | undefined) => void; - purpose: "create" | "update" | "show"; + onChange: MM[T]; + purpose: T; }): VNode { const initial = initializeFromTemplate(username, template); const [form, setForm] = useState(initial); @@ -45,11 +54,20 @@ export function AccountForm({ >(undefined); const { i18n } = useTranslationContext(); + const { config } = useBankCoreApiContext() + const [debitAmount, setDebitAmount] = useState() + + const [isExchange, setIsExchange] = useState(); + const [isPublic, setIsPublic] = useState(); + function updateForm(newForm: typeof initial): void { const parsed = !newForm.cashout_payto_uri ? undefined : buildPayto("iban", newForm.cashout_payto_uri, undefined);; + const trimmedAmountStr = debitAmount?.trim(); + const parsedAmount = Amounts.parse(`${config.currency}:${trimmedAmountStr}`); + const errors = undefinedIfEmpty>({ cashout_payto_uri: (!newForm.cashout_payto_uri ? undefined @@ -74,20 +92,52 @@ export function AccountForm({ ? i18n.str`phone number can't have other than numbers` : undefined, }), + debit_threshold: !trimmedAmountStr + ? i18n.str`required` + : !parsedAmount + ? i18n.str`not valid` + : Amounts.isZero(parsedAmount) + ? i18n.str`should be greater than 0` + : undefined, name: !newForm.name ? i18n.str`required` : undefined, username: !newForm.username ? i18n.str`required` : undefined, }); setErrors(errors); setForm(newForm); + if (!onChange) return; + if (errors) { onChange(undefined) } else { - const cashout = !newForm.cashout_payto_uri? undefined :buildPayto("iban", newForm.cashout_payto_uri, undefined) - const account: AccountFormData = { - ...newForm as any, - cashout_payto_uri: !cashout ? undefined : stringifyPaytoUri(cashout) + const cashout = !newForm.cashout_payto_uri ? undefined : buildPayto("iban", newForm.cashout_payto_uri, undefined) + const cashoutURI = !cashout ? undefined : stringifyPaytoUri(cashout) + switch (purpose) { + case "create": { + const result: TalerCorebankApi.RegisterAccountRequest = { + cashout_payto_uri: cashoutURI, + name: newForm.name!, + password: getRandomPassword(), + username: newForm.username!, + challenge_contact_data: undefinedIfEmpty({ + email: newForm.contact_data?.email, + phone: newForm.contact_data?.phone, + }), + debit_threshold: newForm.debit_threshold as AmountString, + // , + // internal_payto_uri + } + onChange(result) + return; + } + case "update": { + const result: TalerCorebankApi.AccountReconfiguration = { + cashout_payto_uri: cashoutURI + } + onChange(result as any) + return; + } + case "show": } - onChange(account); } } @@ -181,7 +231,6 @@ export function AccountForm({ for="email" > {i18n.str`Email`} - {purpose === "create" && *}
{i18n.str`Phone`} - {purpose === "create" && *}
- {!noCashout &&
{ form.cashout_payto_uri = e.currentTarget.value as PaytoString; if (!form.cashout_payto_uri) { - form.cashout_payto_uri= undefined + form.cashout_payto_uri = undefined } updateForm(structuredClone(form)); }} @@ -286,6 +332,54 @@ export function AccountForm({
} +
+ + { + setDebitAmount(e); + }} + /> + +

allow user debt

+
+ +
+
+ + + Is an exchange + + + +
+
+ +
+
+ + + Is public + + + +
+
+
{children} diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx b/packages/demobank-ui/src/pages/admin/AccountList.tsx index 8350cefd9..71f18a3db 100644 --- a/packages/demobank-ui/src/pages/admin/AccountList.tsx +++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx @@ -7,6 +7,8 @@ import { useBankCoreApiContext } from "../../context/config.js"; import { useBusinessAccounts } from "../../hooks/circuit.js"; import { RenderAmount } from "../PaytoWireTransferForm.js"; import { assertUnreachable } from "../WithdrawalOperationPage.js"; +import { usePreferences } from "../../hooks/preferences.js"; +import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; interface Props { onCreateAccount: () => void; @@ -26,7 +28,7 @@ export function AccountList({ onRemoveAccount, onShowAccountDetails, onUpdateAcc return } if (result instanceof TalerError) { - return + return } if (result.data.type === "fail") { switch (result.data.case) { diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx b/packages/demobank-ui/src/pages/admin/AdminHome.tsx index b1acb8160..28078bc09 100644 --- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx +++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx @@ -9,6 +9,7 @@ import { WireTransfer } from "../WireTransfer.js"; import { AccountList } from "./AccountList.js"; import { useBankCoreApiContext } from "../../context/config.js"; import { format, getDate, getHours, getMonth, getYear, setDate, setHours, setMonth, setYear, sub } from "date-fns"; +import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; /** @@ -90,7 +91,7 @@ function Metrics(): VNode { const resp = useLastMonitorInfo(params.current, params.previous, metricType); if (!resp) return ; if (resp instanceof TalerError) { - return + return } if (resp.current.type !== "ok" || resp.previous.type !== "ok") { return diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx index 2b0be6056..6ff723a31 100644 --- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx @@ -17,31 +17,33 @@ export function CreateNewAccount({ onCreateSuccess: () => void; }): VNode { const { i18n } = useTranslationContext(); - // const { createAccount } = useAdminAccountAPI(); const { state: credentials } = useBackendState() const token = credentials.status !== "loggedIn" ? undefined : credentials.token const { api } = useBankCoreApiContext(); - const [submitAccount, setSubmitAccount] = useState(); + const [submitAccount, setSubmitAccount] = useState(); const [notification, notify, handleError] = useLocalNotification() async function doCreate() { if (!submitAccount || !token) return; await handleError(async () => { - const account: TalerCorebankApi.RegisterAccountRequest = { - cashout_payto_uri: submitAccount.cashout_payto_uri, - challenge_contact_data: submitAccount.contact_data, - internal_payto_uri: submitAccount.payto_uri, - name: submitAccount.name, - username: submitAccount.username,//FIXME: not in account data - password: getRandomPassword(), - }; + // const account: TalerCorebankApi.RegisterAccountRequest = { + // cashout_payto_uri: submitAccount.cashout_payto_uri, + // challenge_contact_data: submitAccount.challenge_contact_data, + // internal_payto_uri: submitAccount.internal_payto_uri, + // debit_threshold: submitAccount.debit_threshold, + // is_public: submitAccount.is_public, + // is_taler_exchange: submitAccount.is_taler_exchange, + // name: submitAccount.name, + // username: submitAccount.username, + // password: getRandomPassword(), + // }; - const resp = await api.createAccount(token, account); + const resp = await api.createAccount(token, submitAccount); if (resp.type === "ok") { mutate(() => true)// clean account list notifyInfo( - i18n.str`Account created with password "${account.password}". The user must change the password on the next login.`, + i18n.str`Account created with password "${submitAccount.password}". The user must change the password on the next login.`, ); onCreateSuccess(); } else { @@ -82,6 +84,12 @@ export function CreateNewAccount({ description: resp.detail.hint as TranslatedString, debug: resp.detail, }) + case "user-cant-set-debt": return notify({ + type: "error", + title: i18n.str`Only admin is allow to set debt limit.`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + }) default: assertUnreachable(resp) } } @@ -105,6 +113,7 @@ export function CreateNewAccount({
{ setSubmitAccount(a); diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx index 051a86ad6..5ee887128 100644 --- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx +++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx @@ -9,6 +9,7 @@ import { undefinedIfEmpty } from "../../utils.js"; import { LoginForm } from "../LoginForm.js"; import { doAutoFocus } from "../PaytoWireTransferForm.js"; import { assertUnreachable } from "../WithdrawalOperationPage.js"; +import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; export function RemoveAccount({ account, @@ -34,7 +35,7 @@ export function RemoveAccount({ return } if (result instanceof TalerError) { - return + return } if (result.type === "fail") { switch (result.case) { diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx b/packages/demobank-ui/src/pages/business/CreateCashout.tsx index 67fc47e60..b2ff41e63 100644 --- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx +++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx @@ -49,6 +49,7 @@ import { LoginForm } from "../LoginForm.js"; import { InputAmount, RenderAmount, doAutoFocus } from "../PaytoWireTransferForm.js"; import { assertUnreachable } from "../WithdrawalOperationPage.js"; import { getRandomPassword, getRandomUsername } from "../rnd.js"; +import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; interface Props { account: string; @@ -97,7 +98,7 @@ export function CreateCashout({ return } if (resultAccount instanceof TalerError) { - return + return } if (resultAccount.type === "fail") { switch (resultAccount.case) { @@ -111,7 +112,7 @@ export function CreateCashout({ } if (info instanceof TalerError) { - return + return } const conversionInfo = info.body.conversion_rate diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx index 6fd9eb18c..fcbf0c408 100644 --- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx +++ b/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx @@ -42,6 +42,7 @@ import { import { assertUnreachable } from "../WithdrawalOperationPage.js"; import { LocalNotificationBanner } from "@gnu-taler/web-util/browser"; import { RenderAmount } from "../PaytoWireTransferForm.js"; +import { ErrorLoadingWithDebug } from "../../components/ErrorLoadingWithDebug.js"; interface Props { id: string; @@ -70,7 +71,7 @@ export function ShowCashoutDetails({ return } if (result instanceof TalerError) { - return + return } if (result.type === "fail") { switch (result.case) { @@ -86,7 +87,7 @@ export function ShowCashoutDetails({ } if (info instanceof TalerError) { - return + return } const errors = undefinedIfEmpty({ diff --git a/packages/demobank-ui/src/stories.test.ts b/packages/demobank-ui/src/stories.test.ts index fac363e5b..a060a6b48 100644 --- a/packages/demobank-ui/src/stories.test.ts +++ b/packages/demobank-ui/src/stories.test.ts @@ -18,7 +18,7 @@ * * @author Sebastian Javier Marchano (sebasjm) */ -import { AccessToken, TalerCorebankApi, setupI18n } from "@gnu-taler/taler-util"; +import { AccessToken, AmountString, TalerCorebankApi, setupI18n } from "@gnu-taler/taler-util"; import { parseGroupImport } from "@gnu-taler/web-util/browser"; import * as tests from "@gnu-taler/web-util/testing"; import * as components from "./components/index.examples.js"; @@ -74,6 +74,7 @@ function DefaultTestingContext({ num_fractional_normal_digits: 2, num_fractional_trailing_zero_digits: 2, }, + default_debit_threshold: "ARS:10" as AmountString, version: "1:0:0", } const ctx2 = create(BankCoreApiProviderTesting, { diff --git a/packages/demobank-ui/src/utils.ts b/packages/demobank-ui/src/utils.ts index 18abf28a9..805d68660 100644 --- a/packages/demobank-ui/src/utils.ts +++ b/packages/demobank-ui/src/utils.ts @@ -108,12 +108,12 @@ export async function withRuntimeErrorHandling(i18n: Translator, cb: () => Pr ? error.message : JSON.stringify(error)) as TranslatedString ) - } + } } } -export function buildRequestErrorMessage( i18n: Translator, cause: TalerError): ErrorNotification { +export function buildRequestErrorMessage(i18n: Translator, cause: TalerError): ErrorNotification { let result: ErrorNotification; switch (cause.errorDetail.code) { case TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT: { -- cgit v1.2.3