diff options
author | Sebastian <sebasjm@gmail.com> | 2024-04-23 11:31:56 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-04-23 11:31:56 -0300 |
commit | cd590b18e856a128af3c31d9e7d4a621ea44024c (patch) | |
tree | b20e8f4a446f4edddf364755032389d267beedb6 /packages/aml-backoffice-ui/src | |
parent | 2b8ae6381776b0d6fc9cc8c0b8275fbdc6d3295b (diff) | |
download | wallet-core-cd590b18e856a128af3c31d9e7d4a621ea44024c.tar.xz |
tidy up: some header missing
Diffstat (limited to 'packages/aml-backoffice-ui/src')
40 files changed, 1018 insertions, 532 deletions
diff --git a/packages/aml-backoffice-ui/src/App.tsx b/packages/aml-backoffice-ui/src/App.tsx index 5244476d7..55f03322d 100644 --- a/packages/aml-backoffice-ui/src/App.tsx +++ b/packages/aml-backoffice-ui/src/App.tsx @@ -1,12 +1,27 @@ +/* + 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 { TranslationProvider } from "@gnu-taler/web-util/browser"; import { h, VNode } from "preact"; -import { ExchangeAmlFrame } from "./Dashboard.js"; -import "./scss/main.css"; +import { SWRConfig } from "swr"; import { ExchangeApiProvider } from "./context/config.js"; +import { ExchangeAmlFrame } from "./Dashboard.js"; import { getInitialBackendBaseURL } from "./hooks/useBackend.js"; -import { HashPathProvider, Router } from "./route.js"; import { Pages } from "./pages.js"; -import { SWRConfig } from "swr"; +import { HashPathProvider, Router } from "./route.js"; +import "./scss/main.css"; const WITH_LOCAL_STORAGE_CACHE = false; @@ -45,12 +60,11 @@ export function App(): VNode { keepPreviousData: true, }} > - <ExchangeAmlFrame> <Router pageList={pageList} onNotFound={() => { - window.location.href = Pages.cases.url + window.location.href = Pages.cases.url; return <div>not found</div>; }} /> @@ -62,7 +76,6 @@ export function App(): VNode { ); } - function localStorageProvider(): Map<unknown, unknown> { const map = new Map(JSON.parse(localStorage.getItem("app-cache") || "[]")); diff --git a/packages/aml-backoffice-ui/src/Dashboard.tsx b/packages/aml-backoffice-ui/src/Dashboard.tsx index 3951b48c7..78980265d 100644 --- a/packages/aml-backoffice-ui/src/Dashboard.tsx +++ b/packages/aml-backoffice-ui/src/Dashboard.tsx @@ -1,17 +1,39 @@ +/* + 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 { TranslatedString } from "@gnu-taler/taler-util"; -import { Footer, ToastBanner, Header, notifyError, notifyException, useTranslationContext } from "@gnu-taler/web-util/browser"; -import { ComponentChildren, Fragment, VNode, h } from "preact"; +import { + Footer, + Header, + ToastBanner, + notifyError, + notifyException, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; +import { ComponentChildren, VNode, h } from "preact"; import { useEffect, useErrorBoundary } from "preact/hooks"; import { useOfficer } from "./hooks/useOfficer.js"; -import { getAllBooleanSettings, getLabelForSetting, useSettings } from "./hooks/useSettings.js"; +import { + getAllBooleanSettings, + getLabelForSetting, + useSettings, +} from "./hooks/useSettings.js"; import { Pages } from "./pages.js"; import { PageEntry, useChangeLocation } from "./route.js"; import { uiSettings } from "./settings.js"; -function classNames(...classes: string[]) { - return classes.filter(Boolean).join(" "); -} - /** * mapping route to view * not found (error page) @@ -37,12 +59,6 @@ function classNames(...classes: string[]) { const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined; -const versionText = VERSION - ? GIT_HASH - ? `v${VERSION} (${GIT_HASH.substring(0, 8)})` - : VERSION - : ""; - /** * TO BE FIXED: * @@ -77,16 +93,16 @@ const versionText = VERSION /** * check this fields - * + * * Signature of Contracting partner, 902_9e * Currency and amount of deposited assets, 902_5e * Signature on declaration of trust, 902.13e * also fundations * also life insurance - * + * * no all state are handled by all the inputs * all the input implementation should respect - * ui props and state + * ui props and state */ export function ExchangeAmlFrame({ @@ -96,114 +112,134 @@ export function ExchangeAmlFrame({ }): VNode { const { i18n } = useTranslationContext(); - const [error, resetError] = useErrorBoundary(); + const [error] = useErrorBoundary(); useEffect(() => { if (error) { if (error instanceof Error) { - notifyException(i18n.str`Internal error, please report.`, error) + notifyException(i18n.str`Internal error, please report.`, error); } else { - notifyError(i18n.str`Internal error, please report.`, String(error) as TranslatedString) + notifyError( + i18n.str`Internal error, please report.`, + String(error) as TranslatedString, + ); } - console.log(error) + console.log(error); // resetError() } - }, [error]) + }, [error]); const officer = useOfficer(); const [settings, updateSettings] = useSettings(); - return (<div class="min-h-full flex flex-col m-0 bg-slate-200" style="min-height: 100vh;"> - <div class="bg-indigo-600 pb-32"> - <Header - title="Exchange" - iconLinkURL={uiSettings.backendBaseURL ?? "#"} - onLogout={officer.state !== "ready" ? undefined : () => { - officer.lock() - }} - sites={[]} - supportedLangs={["en", "es", "de"]} - > - <li> - <div class="text-xs font-semibold leading-6 text-gray-400"> - <i18n.Translate>Preferences</i18n.Translate> - </div> - <ul role="list" class="space-y-1"> - {getAllBooleanSettings().map(set => { - const isOn: boolean = !!settings[set] - return <li class="mt-2 pl-2"> - <div class="flex items-center justify-between"> - <span class="flex flex-grow flex-col"> - <span class="text-sm text-black font-medium leading-6 " id="availability-label"> - {getLabelForSetting(set, i18n)} - </span> - </span> - <button type="button" data-enabled={isOn} class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" role="switch" aria-checked="false" aria-labelledby="availability-label" aria-describedby="availability-description" - - onClick={() => { updateSettings(set, !isOn); }}> - <span aria-hidden="true" data-enabled={isOn} class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"></span> - </button> - </div> - </li> - })} - </ul> - </li> - </Header> - </div> + return ( + <div + class="min-h-full flex flex-col m-0 bg-slate-200" + style="min-height: 100vh;" + > + <div class="bg-indigo-600 pb-32"> + <Header + title="Exchange" + iconLinkURL={uiSettings.backendBaseURL ?? "#"} + onLogout={ + officer.state !== "ready" + ? undefined + : () => { + officer.lock(); + } + } + sites={[]} + supportedLangs={["en", "es", "de"]} + > + <li> + <div class="text-xs font-semibold leading-6 text-gray-400"> + <i18n.Translate>Preferences</i18n.Translate> + </div> + <ul role="list" class="space-y-1"> + {getAllBooleanSettings().map((set) => { + const isOn: boolean = !!settings[set]; + return ( + <li key={set} class="mt-2 pl-2"> + <div class="flex items-center justify-between"> + <span class="flex flex-grow flex-col"> + <span + class="text-sm text-black font-medium leading-6 " + id="availability-label" + > + {getLabelForSetting(set, i18n)} + </span> + </span> + <button + type="button" + data-enabled={isOn} + class="bg-indigo-600 data-[enabled=false]:bg-gray-200 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2" + role="switch" + aria-checked="false" + aria-labelledby="availability-label" + aria-describedby="availability-description" + onClick={() => { + updateSettings(set, !isOn); + }} + > + <span + aria-hidden="true" + data-enabled={isOn} + class="translate-x-5 data-[enabled=false]:translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out" + ></span> + </button> + </div> + </li> + ); + })} + </ul> + </li> + </Header> + </div> - <div class="fixed z-20 w-full"> - <div class="mx-auto w-4/5"> - <ToastBanner /> + <div class="fixed z-20 w-full"> + <div class="mx-auto w-4/5"> + <ToastBanner /> + </div> </div> - </div> - <div class="-mt-32 flex grow "> - {officer.state !== "ready" ? undefined : - <Navigation /> - } - <div class="flex mx-auto my-4"> - <main class="rounded-lg bg-white px-5 py-6 shadow"> - {children} - </main> + <div class="-mt-32 flex grow "> + {officer.state !== "ready" ? undefined : <Navigation />} + <div class="flex mx-auto my-4"> + <main class="rounded-lg bg-white px-5 py-6 shadow">{children}</main> + </div> </div> + <Footer + testingUrlKey="exchange-base-url" + GIT_HASH={GIT_HASH} + VERSION={VERSION} + /> </div> - - <Footer - testingUrlKey="exchange-base-url" - GIT_HASH={GIT_HASH} - VERSION={VERSION} - /> - </div> ); } function Navigation(): VNode { - const { i18n } = useTranslationContext() - const pageList: Array<PageEntry> = [ - Pages.officer, - Pages.cases - ] + const pageList: Array<PageEntry> = [Pages.officer, Pages.cases]; const location = useChangeLocation(); return ( <div class="hidden sm:block min-w-min bg-indigo-600 divide-y rounded-r-lg divide-cyan-800 overflow-y-auto overflow-x-clip"> - <nav class="flex flex-1 flex-col mx-4 mt-4 mb-2"> <ul role="list" class="flex flex-1 flex-col gap-y-7"> <li> <ul role="list" class="-mx-2 space-y-1"> - {pageList.map(p => { - - return <li> - <a href={p.url} data-selected={location == p.url} - class="data-[selected=true]:bg-indigo-700 pr-4 data-[selected=true]:text-white text-indigo-200 hover:text-white hover:bg-indigo-700 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"> - {p.Icon && <p.Icon />} - <span class="hidden md:inline"> - {p.name} - </span> - </a> - </li> - + {pageList.map((p) => { + return ( + <li key={p.url}> + <a + href={p.url} + data-selected={location == p.url} + class="data-[selected=true]:bg-indigo-700 pr-4 data-[selected=true]:text-white text-indigo-200 hover:text-white hover:bg-indigo-700 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold" + > + {p.Icon && <p.Icon />} + <span class="hidden md:inline">{p.name}</span> + </a> + </li> + ); })} {/* <li> <a href="#" class="text-indigo-200 hover:text-white hover:bg-indigo-700 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"> @@ -223,12 +259,8 @@ function Navigation(): VNode { Settings </a> </li> */} - </ul> </nav> </div> - ) - + ); } - - diff --git a/packages/aml-backoffice-ui/src/context/config.ts b/packages/aml-backoffice-ui/src/context/config.ts index 42f73428a..d2bc58578 100644 --- a/packages/aml-backoffice-ui/src/context/config.ts +++ b/packages/aml-backoffice-ui/src/context/config.ts @@ -31,14 +31,14 @@ export type Type = { api: TalerExchangeHttpClient, }; -const Context = createContext<Type>(undefined as any); +const Context = createContext<Type>(undefined!); export const useExchangeApiContext = (): Type => useContext(Context); export const useMaybeExchangeApiContext = (): Type | undefined => useContext(Context); export function ExchangeApiContextTesting({ config, children }: { config: TalerExchangeApi.ExchangeVersionResponse, children?: ComponentChildren; }): VNode { return h(Context.Provider, { - value: { url: new URL("http://testing"), config, api: null as any }, + value: { url: new URL("http://testing"), config, api: null! }, children } ) diff --git a/packages/aml-backoffice-ui/src/declaration.d.ts b/packages/aml-backoffice-ui/src/declaration.d.ts index 6af72042c..663271ec7 100644 --- a/packages/aml-backoffice-ui/src/declaration.d.ts +++ b/packages/aml-backoffice-ui/src/declaration.d.ts @@ -1,3 +1,18 @@ +/* + 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 const __VERSION__: string; declare const __GIT_HASH__: string; diff --git a/packages/aml-backoffice-ui/src/forms.ts b/packages/aml-backoffice-ui/src/forms.ts index cc9e4c7e8..e1fb283d6 100644 --- a/packages/aml-backoffice-ui/src/forms.ts +++ b/packages/aml-backoffice-ui/src/forms.ts @@ -18,7 +18,7 @@ export * from "./forms/index.js"; /** * this file is here to have a flat dist folder - * - * this file is being build in a bundle separated + * + * this file is being build in a bundle separated * from the main one. */ diff --git a/packages/aml-backoffice-ui/src/forms/902_11e.ts b/packages/aml-backoffice-ui/src/forms/902_11e.ts index 71ca8bcf4..b1cdda6ba 100644 --- a/packages/aml-backoffice-ui/src/forms/902_11e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_11e.ts @@ -1,4 +1,18 @@ -import type { TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { BaseForm } from "./declaration.js"; import { resolutionSection } from "./simplest.js"; diff --git a/packages/aml-backoffice-ui/src/forms/902_12e.ts b/packages/aml-backoffice-ui/src/forms/902_12e.ts index 0c08d274c..d5a420177 100644 --- a/packages/aml-backoffice-ui/src/forms/902_12e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_12e.ts @@ -1,7 +1,22 @@ -import type { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 type { AbsoluteTime } from "@gnu-taler/taler-util"; import type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; -import { resolutionSection } from "./simplest.js"; import { BaseForm } from "./declaration.js"; +import { resolutionSection } from "./simplest.js"; export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_12.Form> => ({ design: [ @@ -360,7 +375,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib ): FormState<Form902_12.Form> { return { founders: { - elements: (v.founders ?? []).map((f) => { + elements: (v.founders ?? []).map(() => { return { rightToRevoke: { hidden: v.foundation?.revocability !== "revocable", @@ -369,7 +384,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib }), }, withRightToNominate: { - elements: (v.withRightToNominate ?? []).map((f) => { + elements: (v.withRightToNominate ?? []).map(() => { return { rightToRevoke: { hidden: v.foundation?.revocability !== "revocable", diff --git a/packages/aml-backoffice-ui/src/forms/902_13e.ts b/packages/aml-backoffice-ui/src/forms/902_13e.ts index f69884e0e..9e05e061a 100644 --- a/packages/aml-backoffice-ui/src/forms/902_13e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_13e.ts @@ -1,3 +1,18 @@ +/* + 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 type { AbsoluteTime } from "@gnu-taler/taler-util"; import type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { BaseForm } from "./declaration.js"; @@ -439,7 +454,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib ): FormState<Form902_13.Form> { return { settlors: { - elements: (v.settlors ?? []).map((f) => { + elements: (v.settlors ?? []).map(() => { return { rightToRevoke: { hidden: v.foundation?.revocability !== "revocable", @@ -448,7 +463,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib }), }, protectors: { - elements: (v.protectors ?? []).map((f) => { + elements: (v.protectors ?? []).map(() => { return { rightToRevoke: { hidden: v.foundation?.revocability !== "revocable", @@ -457,7 +472,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib }), }, furtherPersons: { - elements: (v.furtherPersons ?? []).map((f) => { + elements: (v.furtherPersons ?? []).map(() => { return { rightToRevoke: { hidden: v.foundation?.revocability !== "revocable", diff --git a/packages/aml-backoffice-ui/src/forms/902_15e.ts b/packages/aml-backoffice-ui/src/forms/902_15e.ts index 2375de389..72acf8d06 100644 --- a/packages/aml-backoffice-ui/src/forms/902_15e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_15e.ts @@ -1,3 +1,18 @@ +/* + 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 type { AbsoluteTime } from "@gnu-taler/taler-util"; import type { FlexibleForm, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { BaseForm } from "./declaration.js"; diff --git a/packages/aml-backoffice-ui/src/forms/902_1e.ts b/packages/aml-backoffice-ui/src/forms/902_1e.ts index 2287db369..c6d33b9ca 100644 --- a/packages/aml-backoffice-ui/src/forms/902_1e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_1e.ts @@ -1,4 +1,19 @@ -import type { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 type { AbsoluteTime } from "@gnu-taler/taler-util"; import type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { BaseForm, uiForms } from "./declaration.js"; import { resolutionSection } from "./simplest.js"; diff --git a/packages/aml-backoffice-ui/src/forms/902_4e.ts b/packages/aml-backoffice-ui/src/forms/902_4e.ts index b31a8dcba..15446bb27 100644 --- a/packages/aml-backoffice-ui/src/forms/902_4e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_4e.ts @@ -1,9 +1,24 @@ +/* + 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 type { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util"; import type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { h as create } from "preact"; -import { resolutionSection } from "./simplest.js"; import { BaseForm } from "./declaration.js"; import { ArrowRightIcon, ChevronRightIcon } from "./icons.js"; +import { resolutionSection } from "./simplest.js"; export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_4.Form> => ({ design: [ @@ -716,7 +731,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib resolutionSection(current, i18n), ], behavior: function formBehavior( - v: Partial<Form902_4.Form>, + // v: Partial<Form902_4.Form>, ): FormState<Form902_4.Form> { return { }; diff --git a/packages/aml-backoffice-ui/src/forms/902_5e.ts b/packages/aml-backoffice-ui/src/forms/902_5e.ts index 3af03ed22..40dd4d7ad 100644 --- a/packages/aml-backoffice-ui/src/forms/902_5e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_5e.ts @@ -1,4 +1,18 @@ -import type { TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 type { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { BaseForm, uiForms } from "./declaration.js"; import { resolutionSection } from "./simplest.js"; diff --git a/packages/aml-backoffice-ui/src/forms/902_9e.ts b/packages/aml-backoffice-ui/src/forms/902_9e.ts index e0e7a6d65..539e086f5 100644 --- a/packages/aml-backoffice-ui/src/forms/902_9e.ts +++ b/packages/aml-backoffice-ui/src/forms/902_9e.ts @@ -1,7 +1,22 @@ -import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 { AbsoluteTime } from "@gnu-taler/taler-util"; import { FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; -import { resolutionSection } from "./simplest.js"; import { BaseForm } from "./declaration.js"; +import { resolutionSection } from "./simplest.js"; export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_9.Form> => ({ design: [ @@ -96,7 +111,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib resolutionSection(current, i18n), ], behavior: function formBehavior( - v: Partial<Form902_9.Form>, + // v: Partial<Form902_9.Form>, ): FormState<Form902_9.Form> { return { }; diff --git a/packages/aml-backoffice-ui/src/forms/declaration.ts b/packages/aml-backoffice-ui/src/forms/declaration.ts index ec3bc5189..d944a7a53 100644 --- a/packages/aml-backoffice-ui/src/forms/declaration.ts +++ b/packages/aml-backoffice-ui/src/forms/declaration.ts @@ -15,17 +15,20 @@ */ import type { AmountJson, TranslatedString } from "@gnu-taler/taler-util"; -import type { FlexibleForm, InternationalizationAPI } from "@gnu-taler/web-util/browser"; +import type { + FlexibleForm, + InternationalizationAPI, +} from "@gnu-taler/web-util/browser"; import { AmlExchangeBackend } from "../utils/types.js"; /** * import entry point without hard reference. - * - * This file just export types and UI Forms + * + * This file just export types and UI Forms * based on what `globalThis` contains. - * - * `./index.js` must be imported first before - * so `globaThis` will have the correct value. + * + * `./index.js` must be imported first before + * so `globaThis` will have the correct value. */ export interface BaseForm { @@ -34,21 +37,21 @@ export interface BaseForm { } export type FormMetadata<T extends BaseForm> = { - label: TranslatedString, - id: string, - version: number, - impl: (current: T) => FlexibleForm<T> -} + label: TranslatedString; + id: string; + version: number; + impl: (current: T) => FlexibleForm<T>; +}; interface LabelValue { label: TranslatedString; - value: string, + value: string; } export interface UiForms { - currencies: (i18n: InternationalizationAPI) => LabelValue[], - languages: (i18n: InternationalizationAPI) => LabelValue[], - forms: (i18n: InternationalizationAPI) => Array<FormMetadata<BaseForm>>, + currencies: (i18n: InternationalizationAPI) => LabelValue[]; + languages: (i18n: InternationalizationAPI) => LabelValue[]; + forms: (i18n: InternationalizationAPI) => Array<FormMetadata<BaseForm>>; } /** @@ -61,10 +64,11 @@ const defaultUIForms: UiForms = { }; declare global { + // eslint-disable-next-line no-var var amlExchangeBackoffice: UiForms; } export const uiForms: UiForms = "amlExchangeBackoffice" in globalThis - ? (globalThis as any).amlExchangeBackoffice + ? globalThis.amlExchangeBackoffice : defaultUIForms; diff --git a/packages/aml-backoffice-ui/src/forms/icons.tsx b/packages/aml-backoffice-ui/src/forms/icons.tsx index 392790c9c..824f75c8f 100644 --- a/packages/aml-backoffice-ui/src/forms/icons.tsx +++ b/packages/aml-backoffice-ui/src/forms/icons.tsx @@ -1,3 +1,18 @@ +/* + 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 { h } from "preact"; export const ChevronRightIcon = () => <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/aml-backoffice-ui/src/forms/index.ts b/packages/aml-backoffice-ui/src/forms/index.ts index f41122bc7..0a6c1df40 100644 --- a/packages/aml-backoffice-ui/src/forms/index.ts +++ b/packages/aml-backoffice-ui/src/forms/index.ts @@ -1,3 +1,18 @@ +/* + 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 type { InternationalizationAPI } from "@gnu-taler/web-util/browser"; import { v1 as form_902_11e_v1 } from "./902_11e.js"; import { v1 as form_902_12e_v1 } from "./902_12e.js"; @@ -7,8 +22,8 @@ import { v1 as form_902_1e_v1 } from "./902_1e.js"; import { v1 as form_902_4e_v1 } from "./902_4e.js"; import { v1 as form_902_5e_v1 } from "./902_5e.js"; import { v1 as form_902_9e_v1 } from "./902_9e.js"; -import { v1 as simplest } from "./simplest.js"; import { BaseForm, FormMetadata } from "./declaration.js"; +import { v1 as simplest } from "./simplest.js"; const languages = (i18n: InternationalizationAPI) => [ { diff --git a/packages/aml-backoffice-ui/src/forms/simplest.ts b/packages/aml-backoffice-ui/src/forms/simplest.ts index 735ca9bfc..77ed4ebbb 100644 --- a/packages/aml-backoffice-ui/src/forms/simplest.ts +++ b/packages/aml-backoffice-ui/src/forms/simplest.ts @@ -1,11 +1,26 @@ +/* + 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 type { TranslatedString } from "@gnu-taler/taler-util"; import type { DoubleColumnFormSection, FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser"; -import { BaseForm } from "./declaration.js"; import { amlStateConverter } from "../utils/converter.js"; import { AmlExchangeBackend } from "../utils/types.js"; +import { BaseForm } from "./declaration.js"; export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Simplest.Form> => ({ design: [ diff --git a/packages/aml-backoffice-ui/src/hooks/useBackend.ts b/packages/aml-backoffice-ui/src/hooks/useBackend.ts index 7b55568c8..310f7fe59 100644 --- a/packages/aml-backoffice-ui/src/hooks/useBackend.ts +++ b/packages/aml-backoffice-ui/src/hooks/useBackend.ts @@ -31,7 +31,7 @@ export function getInitialBackendBaseURL(): string { console.error( "ERROR: backendBaseURL was overridden by a setting file and missing. Setting value to 'window.origin'", ); - result = typeof (window as any) !== "undefined" ? window.origin : "localhost" + result = typeof window !== "undefined" ? window.origin : "localhost" } else { result = uiSettings.backendBaseURL; } diff --git a/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts b/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts index dbc6763ba..de1c5af17 100644 --- a/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts +++ b/packages/aml-backoffice-ui/src/hooks/useCaseDetails.ts @@ -1,6 +1,20 @@ - +/* + 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 { OfficerAccount, PaytoString, TalerExchangeResultByMethod, TalerHttpError } from "@gnu-taler/taler-util"; // 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 } from "swr"; import { useExchangeApiContext } from "../context/config.js"; import { useOfficer } from "./useOfficer.js"; @@ -34,62 +48,4 @@ export function useCaseDetails(paytoHash: string) { return undefined; } -const example1: TalerExchangeApi.AmlDecisionDetails = { - aml_history: [ - { - justification: "Lack of documentation", - decider_pub: "ASDASDASD", - decision_time: { - t_s: Date.now() / 1000, - }, - new_state: 2, - new_threshold: "USD:0" as AmountString, - }, - { - justification: "Doing a transfer of high amount", - decider_pub: "ASDASDASD", - decision_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 6, - }, - new_state: 1, - new_threshold: "USD:2000" as AmountString, - }, - { - justification: "Account is known to the system", - decider_pub: "ASDASDASD", - decision_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 9, - }, - new_state: 0, - new_threshold: "USD:100" as AmountString, - }, - ], - kyc_attributes: [ - { - collection_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 8, - }, - expiration_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 4, - }, - provider_section: "asdasd", - attributes: { - name: "Sebastian", - }, - }, - { - collection_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 5, - }, - expiration_time: { - t_s: Date.now() / 1000 - 60 * 60 * 24 * 30 * 2, - }, - provider_section: "asdasd", - attributes: { - creditCard: "12312312312", - }, - }, - ], -}; - diff --git a/packages/aml-backoffice-ui/src/hooks/useCases.ts b/packages/aml-backoffice-ui/src/hooks/useCases.ts index 2bc9b5f0f..7c8bb5bc1 100644 --- a/packages/aml-backoffice-ui/src/hooks/useCases.ts +++ b/packages/aml-backoffice-ui/src/hooks/useCases.ts @@ -1,7 +1,22 @@ +/* + 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 { useState } from "preact/hooks"; // FIX default import https://github.com/microsoft/TypeScript/issues/49189 -import { OfficerAccount, OfficerId, OperationOk, TalerExchangeResultByMethod, TalerHttpError, decodeCrock, encodeCrock } from "@gnu-taler/taler-util"; +import { OfficerAccount, OperationOk, TalerExchangeResultByMethod, TalerHttpError } from "@gnu-taler/taler-util"; import _useSWR, { SWRHook } from "swr"; import { useExchangeApiContext } from "../context/config.js"; import { AmlExchangeBackend } from "../utils/types.js"; @@ -76,11 +91,3 @@ export function buildPaginatedResult<R, OffId>(data: R[], offset: OffId | undefi }, }; } - - -function removeLastElement<T>(list: Array<T>): Array<T> { - if (list.length === 0) { - return list; - } - return list.slice(0, -1) -}
\ No newline at end of file diff --git a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts index 1bf2b308b..b49c9db26 100644 --- a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts +++ b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts @@ -1,3 +1,18 @@ +/* + 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 { AbsoluteTime, Codec, diff --git a/packages/aml-backoffice-ui/src/hooks/useSettings.ts b/packages/aml-backoffice-ui/src/hooks/useSettings.ts index f1610576e..55cdafb23 100644 --- a/packages/aml-backoffice-ui/src/hooks/useSettings.ts +++ b/packages/aml-backoffice-ui/src/hooks/useSettings.ts @@ -18,10 +18,7 @@ import { Codec, TranslatedString, buildCodecForObject, - codecForBoolean, - codecForNumber, - codecForString, - codecOptional + codecForBoolean } from "@gnu-taler/taler-util"; import { buildStorageKey, useLocalStorage, useTranslationContext } from "@gnu-taler/web-util/browser"; diff --git a/packages/aml-backoffice-ui/src/index.tsx b/packages/aml-backoffice-ui/src/index.tsx index c2ac4c84b..ad0d394d8 100644 --- a/packages/aml-backoffice-ui/src/index.tsx +++ b/packages/aml-backoffice-ui/src/index.tsx @@ -18,5 +18,8 @@ import { App } from "./App.js"; import { h, render } from "preact"; const app = document.getElementById("app"); - -render(<App />, app as any); +if (!app) { + console.error("could not found app element") +} else { + render(<App />, app); +} diff --git a/packages/aml-backoffice-ui/src/pages.ts b/packages/aml-backoffice-ui/src/pages.ts index 109cd31d0..1c8fdde4a 100644 --- a/packages/aml-backoffice-ui/src/pages.ts +++ b/packages/aml-backoffice-ui/src/pages.ts @@ -1,5 +1,19 @@ +/* + 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 { TranslatedString } from "@gnu-taler/taler-util"; -import { AntiMoneyLaunderingForm } from "./pages/AntiMoneyLaunderingForm.js"; import { CaseDetails } from "./pages/CaseDetails.js"; import { Cases, HomeIcon, PeopleIcon } from "./pages/Cases.js"; import { NewFormEntry } from "./pages/NewFormEntry.js"; diff --git a/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx index c42b1e7af..77d4b8167 100644 --- a/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx +++ b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx @@ -1,3 +1,18 @@ +/* + 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 { AbsoluteTime, AmountJson, @@ -5,11 +20,11 @@ import { Codec, OperationFail, OperationOk, - OperationResult, + TalerErrorDetail, buildCodecForObject, codecForNumber, codecForString, - codecOptional, + codecOptional } from "@gnu-taler/taler-util"; import { DefaultForm, @@ -17,7 +32,7 @@ import { } from "@gnu-taler/web-util/browser"; import { h } from "preact"; import { useExchangeApiContext } from "../context/config.js"; -import { FormMetadata, uiForms } from "../forms/declaration.js"; +import { BaseForm, FormMetadata, uiForms } from "../forms/declaration.js"; import { Pages } from "../pages.js"; import { AmlExchangeBackend } from "../utils/types.js"; @@ -51,10 +66,12 @@ export function AntiMoneyLaunderingForm({ <DefaultForm initial={initial} form={theForm.impl(initial)} - onUpdate={() => { }} + onUpdate={() => {}} onSubmit={(formValue) => { - if (formValue.state === undefined || formValue.threshold === undefined) + if (formValue.state === undefined || formValue.threshold === undefined) { return; + } + const validatedForm = formValue as BaseForm; const st = formValue.state; const amount = formValue.threshold; @@ -62,7 +79,7 @@ export function AntiMoneyLaunderingForm({ id: theForm.id, label: theForm.label, version: theForm.version, - value: formValue, + value: validatedForm, }; onSubmit(justification, st, amount); @@ -86,10 +103,10 @@ export function AntiMoneyLaunderingForm({ ); } -export type Justification<T = any> = { +export type Justification<T extends BaseForm = BaseForm> = { // form values value: T; -} & Omit<Omit<FormMetadata<any>, "icon">, "impl">; +} & Omit<Omit<FormMetadata<BaseForm>, "icon">, "impl">; export function stringifyJustification(j: Justification): string { return JSON.stringify(j); @@ -114,8 +131,10 @@ type ParseJustificationFail = export function parseJustification( s: string, - listOfAllKnownForms: FormMetadata<any>[], -): OperationOk<{ justification: Justification; metadata: FormMetadata<any> }> | OperationFail<ParseJustificationFail> { + listOfAllKnownForms: FormMetadata<BaseForm>[], +): + | OperationOk<{ justification: Justification; metadata: FormMetadata<BaseForm> }> + | OperationFail<ParseJustificationFail> { try { const justification = JSON.parse(s); const info = codecForSimpleFormMetadata().decode(justification); @@ -123,14 +142,14 @@ export function parseJustification( return { type: "fail", case: "id-not-found", - detail: {} as any, + detail: {} as TalerErrorDetail, }; } if (!info.version) { return { type: "fail", case: "version-not-found", - detail: {} as any, + detail: {} as TalerErrorDetail, }; } const found = listOfAllKnownForms.find((f) => { @@ -140,7 +159,7 @@ export function parseJustification( return { type: "fail", case: "form-not-found", - detail: {} as any, + detail: {} as TalerErrorDetail, }; } return { @@ -154,7 +173,7 @@ export function parseJustification( return { type: "fail", case: "not-json", - detail: {} as any, + detail: {} as TalerErrorDetail, }; } } diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx index 0875f047b..a91f3d107 100644 --- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx +++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx @@ -1,3 +1,18 @@ +/* + 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 { AbsoluteTime, AmountJson, @@ -5,27 +20,39 @@ import { HttpStatusCode, TalerError, TranslatedString, - assertUnreachable + assertUnreachable, } from "@gnu-taler/taler-util"; -import { DefaultForm, ErrorLoading, InternationalizationAPI, Loading, useTranslationContext } from "@gnu-taler/web-util/browser"; +import { + DefaultForm, + ErrorLoading, + InternationalizationAPI, + Loading, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { format } from "date-fns"; -import { Fragment, VNode, h } from "preact"; +import { VNode, h } from "preact"; import { useState } from "preact/hooks"; -import { FormMetadata } from "../forms/declaration.js"; +import { BaseForm, FormMetadata, uiForms } from "../forms/declaration.js"; import { useCaseDetails } from "../hooks/useCaseDetails.js"; import { Pages } from "../pages.js"; -import { Justification, parseJustification } from "./AntiMoneyLaunderingForm.js"; -import { ShowConsolidated } from "./ShowConsolidated.js"; import { AmlExchangeBackend } from "../utils/types.js"; -import { uiForms } from "../forms/declaration.js"; +import { + Justification, + parseJustification, +} from "./AntiMoneyLaunderingForm.js"; +import { ShowConsolidated } from "./ShowConsolidated.js"; -export type AmlEvent = AmlFormEvent | AmlFormEventError | KycCollectionEvent | KycExpirationEvent; +export type AmlEvent = + | AmlFormEvent + | AmlFormEventError + | KycCollectionEvent + | KycExpirationEvent; type AmlFormEvent = { type: "aml-form"; when: AbsoluteTime; title: TranslatedString; justification: Justification; - metadata: FormMetadata<any>; + metadata: FormMetadata<BaseForm>; state: AmlExchangeBackend.AmlState; threshold: AmountJson; }; @@ -33,8 +60,8 @@ type AmlFormEventError = { type: "aml-form-error"; when: AbsoluteTime; title: TranslatedString; - justification: undefined, - metadata: undefined, + justification: undefined; + metadata: undefined; state: AmlExchangeBackend.AmlState; threshold: AmountJson; }; @@ -58,17 +85,24 @@ function selectSooner(a: WithTime, b: WithTime) { return AbsoluteTime.cmp(a.when, b.when); } -function titleForJustification(op: ReturnType<typeof parseJustification>, i18n: InternationalizationAPI): TranslatedString { +function titleForJustification( + op: ReturnType<typeof parseJustification>, + i18n: InternationalizationAPI, +): TranslatedString { if (op.type === "ok") { return op.body.justification.label as TranslatedString; } switch (op.case) { - case "not-json": return "error: the justification is not a form" as TranslatedString - case "id-not-found": return "error: justification form's id not found" as TranslatedString - case "version-not-found": return "error: justification form's version not found" as TranslatedString - case "form-not-found": return `error: justification form not found` as TranslatedString + case "not-json": + return i18n.str`error: the justification is not a form`; + case "id-not-found": + return i18n.str`error: justification form's id not found`; + case "version-not-found": + return i18n.str`error: justification form's version not found`; + case "form-not-found": + return i18n.str`error: justification form not found`; default: { - assertUnreachable(op.case) + assertUnreachable(op.case); } } } @@ -79,8 +113,7 @@ export function getEventsFromAmlHistory( i18n: InternationalizationAPI, ): AmlEvent[] { const ae: AmlEvent[] = aml.map((a) => { - - const just = parseJustification(a.justification, uiForms.forms(i18n)) + const just = parseJustification(a.justification, uiForms.forms(i18n)); return { type: just.type === "ok" ? "aml-form" : "aml-form-error", state: a.new_state, @@ -117,47 +150,53 @@ export function getEventsFromAmlHistory( export function CaseDetails({ account }: { account: string }) { const [selected, setSelected] = useState<AbsoluteTime>(AbsoluteTime.now()); - const [showForm, setShowForm] = useState<{ justification: Justification, metadata: FormMetadata<any> }>() + const [showForm, setShowForm] = useState<{ + justification: Justification; + metadata: FormMetadata<BaseForm>; + }>(); const { i18n } = useTranslationContext(); - const details = useCaseDetails(account) + const details = useCaseDetails(account); if (!details) { - return <Loading /> + return <Loading />; } if (details instanceof TalerError) { - return <ErrorLoading error={details} /> + return <ErrorLoading error={details} />; } if (details.type === "fail") { switch (details.case) { case HttpStatusCode.Unauthorized: case HttpStatusCode.Forbidden: case HttpStatusCode.NotFound: - case HttpStatusCode.Conflict: return <div /> - default: assertUnreachable(details) + case HttpStatusCode.Conflict: + return <div />; + default: + assertUnreachable(details); } } - const { aml_history, kyc_attributes } = details.body + const { aml_history, kyc_attributes } = details.body; const events = getEventsFromAmlHistory(aml_history, kyc_attributes, i18n); if (showForm !== undefined) { - return <DefaultForm - readOnly={true} - initial={showForm.justification.value} - form={showForm.metadata.impl(showForm.justification.value)} - > - <div class="mt-6 flex items-center justify-end gap-x-6"> - <button - class="text-sm font-semibold leading-6 text-gray-900" - onClick={() => { - setShowForm(undefined) - }} - > - <i18n.Translate>Cancel</i18n.Translate> - </button> - </div> - - </DefaultForm> + return ( + <DefaultForm + readOnly={true} + initial={showForm.justification.value} + form={showForm.metadata.impl(showForm.justification.value)} + > + <div class="mt-6 flex items-center justify-end gap-x-6"> + <button + class="text-sm font-semibold leading-6 text-gray-900" + onClick={() => { + setShowForm(undefined); + }} + > + <i18n.Translate>Cancel</i18n.Translate> + </button> + </div> + </DefaultForm> + ); } return ( <div> @@ -165,40 +204,46 @@ export function CaseDetails({ account }: { account: string }) { 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" > - <i18n.Translate> - New AML form - </i18n.Translate> + <i18n.Translate>New AML form</i18n.Translate> </a> <header class="flex items-center justify-between border-b border-white/5 px-4 py-4 sm:px-6 sm:py-6 lg:px-8"> <h1 class="text-base font-semibold leading-7 text-black"> <i18n.Translate> - Case history for account <span title={account}>{account.substring(0, 16)}...</span> + Case history for account{" "} + <span title={account}>{account.substring(0, 16)}...</span> </i18n.Translate> </h1> </header> - <ShowTimeline history={events} onSelect={(e) => { - switch (e.type) { - case "aml-form": { - const { justification, metadata } = e - setShowForm({ justification, metadata }) - break; - } - case "kyc-collection": - case "kyc-expiration": { - setSelected(e.when); - break; + <ShowTimeline + history={events} + onSelect={(e) => { + switch (e.type) { + case "aml-form": { + const { justification, metadata } = e; + setShowForm({ justification, metadata }); + break; + } + case "kyc-collection": + case "kyc-expiration": { + setSelected(e.when); + break; + } + case "aml-form-error": } - case "aml-form-error": - } - }} /> + }} + /> {/* {selected && <ShowEventDetails event={selected} />} */} {selected && <ShowConsolidated history={events} until={selected} />} </div> ); } -function AmlStateBadge({ state }: { state: AmlExchangeBackend.AmlState }): VNode { +function AmlStateBadge({ + state, +}: { + state: AmlExchangeBackend.AmlState; +}): VNode { switch (state) { case AmlExchangeBackend.AmlState.normal: { return ( @@ -222,93 +267,120 @@ function AmlStateBadge({ state }: { state: AmlExchangeBackend.AmlState }): VNode ); } } - assertUnreachable(state) + assertUnreachable(state); } -function ShowTimeline({ history, onSelect }: { onSelect: (e: AmlEvent) => void, history: AmlEvent[] }): VNode { - return <div class="flow-root"> - <ul role="list"> - {history.map((e, idx) => { - const isLast = history.length - 1 === idx; - return ( - <li - data-ok={e.type !== "aml-form-error"} - class="hover:bg-gray-200 p-2 rounded data-[ok=true]:cursor-pointer" - onClick={() => { - onSelect(e); - }} - > - <div class="relative pb-6"> - {!isLast ? ( - <span - class="absolute left-4 top-4 -ml-px h-full w-1 bg-gray-200" - aria-hidden="true" - ></span> - ) : undefined} - <div class="relative flex space-x-3"> - {(() => { - switch (e.type) { - case "aml-form-error": - case "aml-form": { - return <div> - <AmlStateBadge state={e.state} /> - <span class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-700 "> - {e.threshold.currency}{" "} - {Amounts.stringifyValue(e.threshold)} - </span> - </div> - } - case "kyc-collection": { - return ( - // <ArrowDownCircleIcon class="h-8 w-8 text-green-700" /> - <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"> - <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> - </svg> - ); - } - case "kyc-expiration": { - // return <ClockIcon class="h-8 w-8 text-gray-700" />; - 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"> - <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" /> - </svg> - +function ShowTimeline({ + history, + onSelect, +}: { + onSelect: (e: AmlEvent) => void; + history: AmlEvent[]; +}): VNode { + return ( + <div class="flow-root"> + <ul role="list"> + {history.map((e, idx) => { + const isLast = history.length - 1 === idx; + return ( + <li + key={idx} + data-ok={e.type !== "aml-form-error"} + class="hover:bg-gray-200 p-2 rounded data-[ok=true]:cursor-pointer" + onClick={() => { + onSelect(e); + }} + > + <div class="relative pb-6"> + {!isLast ? ( + <span + class="absolute left-4 top-4 -ml-px h-full w-1 bg-gray-200" + aria-hidden="true" + ></span> + ) : undefined} + <div class="relative flex space-x-3"> + {(() => { + switch (e.type) { + case "aml-form-error": + case "aml-form": { + return ( + <div> + <AmlStateBadge state={e.state} /> + <span class="inline-flex items-center px-2 py-1 text-xs font-medium text-gray-700 "> + {e.threshold.currency}{" "} + {Amounts.stringifyValue(e.threshold)} + </span> + </div> + ); + } + case "kyc-collection": { + return ( + // <ArrowDownCircleIcon class="h-8 w-8 text-green-700" /> + <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" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M9 12.75l3 3m0 0l3-3m-3 3v-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" + /> + </svg> + ); + } + case "kyc-expiration": { + // return <ClockIcon class="h-8 w-8 text-gray-700" />; + 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" + > + <path + stroke-linecap="round" + stroke-linejoin="round" + d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" + /> + </svg> + ); + } } - } - assertUnreachable(e) - })()} - <div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5"> - {e.type === "aml-form" ? - <span - // href={Pages.newFormEntry.url({ account })} - class="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" - > - {e.title} - </span> - : - <p class="text-sm text-gray-900">{e.title}</p> - } - <div class="whitespace-nowrap text-right text-sm text-gray-500"> - {e.when.t_ms === "never" ? ( - "never" + assertUnreachable(e); + })()} + <div class="flex min-w-0 flex-1 justify-between space-x-4 pt-1.5"> + {e.type === "aml-form" ? ( + <span + // href={Pages.newFormEntry.url({ account })} + class="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" + > + {e.title} + </span> ) : ( - <time dateTime={format(e.when.t_ms, "dd MMM yyyy")}> - {format(e.when.t_ms, "dd MMM yyyy")} - </time> + <p class="text-sm text-gray-900">{e.title}</p> )} + <div class="whitespace-nowrap text-right text-sm text-gray-500"> + {e.when.t_ms === "never" ? ( + "never" + ) : ( + <time dateTime={format(e.when.t_ms, "dd MMM yyyy")}> + {format(e.when.t_ms, "dd MMM yyyy")} + </time> + )} + </div> </div> </div> </div> - </div> - </li> - ); - })} - </ul> - </div> - -} - -function ShowEventDetails({ event }: { event: AmlEvent }): VNode { - return <div>type {event.type}</div>; + </li> + ); + })} + </ul> + </div> + ); } - - diff --git a/packages/aml-backoffice-ui/src/pages/Cases.stories.tsx b/packages/aml-backoffice-ui/src/pages/Cases.stories.tsx index 3b9c8dacf..223cbbb84 100644 --- a/packages/aml-backoffice-ui/src/pages/Cases.stories.tsx +++ b/packages/aml-backoffice-ui/src/pages/Cases.stories.tsx @@ -20,9 +20,7 @@ */ import * as tests from "@gnu-taler/web-util/testing"; -import { - CasesUI as TestedComponent, -} from "./Cases.js"; +import { CasesUI as TestedComponent } from "./Cases.js"; import { AmountString } from "@gnu-taler/taler-util"; import { AmlExchangeBackend } from "../utils/types.js"; @@ -33,10 +31,12 @@ export default { export const OneRow = tests.createExample(TestedComponent, { filter: AmlExchangeBackend.AmlState.normal, onChangeFilter: () => null, - records: [{ - current_state: AmlExchangeBackend.AmlState.normal, - h_payto: "QWEQWEQWEQWE", - rowid: 1, - threshold: "USD:1" as AmountString - }] + records: [ + { + current_state: AmlExchangeBackend.AmlState.normal, + h_payto: "QWEQWEQWEQWE", + rowid: 1, + threshold: "USD:1" as AmountString, + }, + ], }); diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx index 061286f51..7ecc85e44 100644 --- a/packages/aml-backoffice-ui/src/pages/Cases.tsx +++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx @@ -17,7 +17,7 @@ import { HttpStatusCode, TalerError, TalerExchangeApi, - assertUnreachable + assertUnreachable, } from "@gnu-taler/taler-util"; import { ErrorLoading, @@ -70,7 +70,7 @@ export function CasesUI({ onUpdate={(v) => { onChangeFilter(v.state ?? filter); }} - onSubmit={(_v) => { }} + onSubmit={(_v) => {}} > <form.InputChoiceHorizontal name="state" @@ -182,7 +182,6 @@ export function CasesUI({ } export function Cases() { - const [stateFilter, setStateFilter] = useState( AmlExchangeBackend.AmlState.pending, ); diff --git a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx index 603813f8e..568ec81fa 100644 --- a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx +++ b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx @@ -1,3 +1,18 @@ +/* + 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 { TranslatedString } from "@gnu-taler/taler-util"; import { createNewForm, @@ -17,7 +32,7 @@ export function CreateAccount({ password: string; repeat: string; }>(); - const [settings] = useSettings() + const [settings] = useSettings(); return ( <div class="flex min-h-full flex-col "> @@ -39,7 +54,8 @@ export function CreateAccount({ ? undefined : v.password.length < 8 ? i18n.str`should have at least 8 characters` - : !v.password.match(/[a-z]/) && v.password.match(/[A-Z]/) + : !v.password.match(/[a-z]/) && + v.password.match(/[A-Z]/) ? i18n.str`should have lowercase and uppercase characters` : !v.password.match(/\d/) ? i18n.str`should have numbers` diff --git a/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx b/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx index ff800ebdc..c86906929 100644 --- a/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx +++ b/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx @@ -1,8 +1,23 @@ +/* + 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 { assertUnreachable } from "@gnu-taler/taler-util"; import { VNode, h } from "preact"; import { OfficerNotReady } from "../hooks/useOfficer.js"; import { CreateAccount } from "./CreateAccount.js"; import { UnlockAccount } from "./UnlockAccount.js"; -import { assertUnreachable } from "@gnu-taler/taler-util"; export function HandleAccountNotReady({ officer, @@ -31,5 +46,5 @@ export function HandleAccountNotReady({ /> ); } - assertUnreachable(officer) + assertUnreachable(officer); } diff --git a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx index df97cc3a4..7c10132fa 100644 --- a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx +++ b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx @@ -1,12 +1,38 @@ -import { AbsoluteTime, Amounts, HttpStatusCode, TalerExchangeApi, TalerProtocolTimestamp, TranslatedString } from "@gnu-taler/taler-util"; -import { LocalNotificationBanner, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser"; +/* + 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 { + AbsoluteTime, + Amounts, + HttpStatusCode, + TalerExchangeApi, + TalerProtocolTimestamp, + TranslatedString, +} from "@gnu-taler/taler-util"; +import { + LocalNotificationBanner, + useLocalNotification, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { Fragment, VNode, h } from "preact"; import { useExchangeApiContext } from "../context/config.js"; +import { uiForms } from "../forms/declaration.js"; import { useOfficer } from "../hooks/useOfficer.js"; import { Pages } from "../pages.js"; import { AntiMoneyLaunderingForm } from "./AntiMoneyLaunderingForm.js"; import { HandleAccountNotReady } from "./HandleAccountNotReady.js"; -import { uiForms } from "../forms/declaration.js"; export function NewFormEntry({ account, @@ -15,10 +41,10 @@ export function NewFormEntry({ account?: string; type?: string; }): VNode { - const { i18n } = useTranslationContext() + const { i18n } = useTranslationContext(); const officer = useOfficer(); - const { api } = useExchangeApiContext() - const [notification, notify, handleError] = useLocalNotification() + const { api } = useExchangeApiContext(); + const [notification, notify, handleError] = useLocalNotification(); if (!account) { return <div>no account</div>; @@ -38,46 +64,51 @@ export function NewFormEntry({ account={account} formId={type} onSubmit={async (justification, new_state, new_threshold) => { - const decision: Omit<TalerExchangeApi.AmlDecision, "officer_sig"> = { justification: JSON.stringify(justification), decision_time: TalerProtocolTimestamp.now(), h_payto: account, new_state, new_threshold: Amounts.stringify(new_threshold), - kyc_requirements: undefined - } + kyc_requirements: undefined, + }; await handleError(async () => { - const resp = await api.addDecisionDetails(officer.account, decision); + const resp = await api.addDecisionDetails( + officer.account, + decision, + ); if (resp.type === "ok") { window.location.href = Pages.cases.url; return; } switch (resp.case) { case HttpStatusCode.Forbidden: - case HttpStatusCode.Unauthorized: return notify({ - type: "error", - title: i18n.str`Wrong credentials for "${officer.account}"`, - description: resp.detail.hint as TranslatedString, - debug: resp.detail, - when: AbsoluteTime.now(), - }) - case HttpStatusCode.NotFound: return notify({ - type: "error", - title: i18n.str`Officer or account not found`, - description: resp.detail.hint as TranslatedString, - debug: resp.detail, - when: AbsoluteTime.now(), - }) - case HttpStatusCode.Conflict: return notify({ - type: "error", - title: i18n.str`Officer disabled or more recent decision was already submitted.`, - description: resp.detail.hint as TranslatedString, - debug: resp.detail, - when: AbsoluteTime.now(), - }) + case HttpStatusCode.Unauthorized: + return notify({ + type: "error", + title: i18n.str`Wrong credentials for "${officer.account}"`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + when: AbsoluteTime.now(), + }); + case HttpStatusCode.NotFound: + return notify({ + type: "error", + title: i18n.str`Officer or account not found`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + when: AbsoluteTime.now(), + }); + case HttpStatusCode.Conflict: + return notify({ + type: "error", + title: i18n.str`Officer disabled or more recent decision was already submitted.`, + description: resp.detail.hint as TranslatedString, + debug: resp.detail, + when: AbsoluteTime.now(), + }); } - }) + }); }} /> </Fragment> @@ -85,13 +116,14 @@ export function NewFormEntry({ } function SelectForm({ account }: { account: string }) { - const { i18n } = useTranslationContext() + const { i18n } = useTranslationContext(); return ( <div> <pre>New form for account: {account.substring(0, 16)}...</pre> - {uiForms.forms(i18n).map((form, idx) => { + {uiForms.forms(i18n).map((form) => { return ( <a + key={form.id} href={Pages.newFormEntry.url({ account, type: form.id })} class="m-4 block rounded-md w-fit border-0 p-3 py-2 text-center text-sm bg-indigo-700 text-white shadow-sm hover:bg-indigo-600" > diff --git a/packages/aml-backoffice-ui/src/pages/Officer.tsx b/packages/aml-backoffice-ui/src/pages/Officer.tsx index ec8327814..eaa961b90 100644 --- a/packages/aml-backoffice-ui/src/pages/Officer.tsx +++ b/packages/aml-backoffice-ui/src/pages/Officer.tsx @@ -1,9 +1,24 @@ -import { Fragment, h } from "preact"; -import { useOfficer } from "../hooks/useOfficer.js"; -import { HandleAccountNotReady } from "./HandleAccountNotReady.js"; +/* + 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 { useTranslationContext } from "@gnu-taler/web-util/browser"; -import { uiSettings } from "../settings.js"; +import { h } from "preact"; import { getInitialBackendBaseURL } from "../hooks/useBackend.js"; +import { useOfficer } from "../hooks/useOfficer.js"; +import { uiSettings } from "../settings.js"; +import { HandleAccountNotReady } from "./HandleAccountNotReady.js"; export function Officer() { const officer = useOfficer(); diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx index f985e6ff5..fa88277ec 100644 --- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx +++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx @@ -19,24 +19,23 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { addDays } from "date-fns"; +import { AbsoluteTime, Duration, TranslatedString } from "@gnu-taler/taler-util"; +import { InternationalizationAPI } from "@gnu-taler/web-util/browser"; +import * as tests from "@gnu-taler/web-util/testing"; +import { getEventsFromAmlHistory } from "./CaseDetails.js"; import { ShowConsolidated as TestedComponent, } from "./ShowConsolidated.js"; -import * as tests from "@gnu-taler/web-util/testing"; -import { getEventsFromAmlHistory } from "./CaseDetails.js"; -import { AbsoluteTime, Duration } from "@gnu-taler/taler-util"; -import { InternationalizationAPI } from "@gnu-taler/web-util/browser"; export default { title: "show consolidated", }; const nullTranslator: InternationalizationAPI = { - str: (str: any) => str, - singular: (str: any) => str, - translate: (str: any) => str, - Translate: (str: any) => str, + str: (str: TemplateStringsArray) => str.join() as TranslatedString, + singular: (str: TemplateStringsArray) => str.join() as TranslatedString, + translate: (str: TemplateStringsArray) => [str.join()] as TranslatedString[], + Translate: () => undefined as unknown, } export const WithEmptyHistory = tests.createExample(TestedComponent, { diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx index ad350c0e6..15b109bee 100644 --- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx +++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx @@ -1,10 +1,34 @@ -import { AbsoluteTime, AmountJson, TranslatedString } from "@gnu-taler/taler-util"; +/* + 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 { + AbsoluteTime, + AmountJson, + TranslatedString, +} from "@gnu-taler/taler-util"; +import { + DefaultForm, + FlexibleForm, + UIFormField, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; import { format } from "date-fns"; import { Fragment, VNode, h } from "preact"; -import { AmlEvent } from "./CaseDetails.js"; -import { DefaultForm, FlexibleForm, UIFormField, useTranslationContext } from "@gnu-taler/web-util/browser"; import { amlStateConverter } from "../utils/converter.js"; import { AmlExchangeBackend } from "../utils/types.js"; +import { AmlEvent } from "./CaseDetails.js"; export function ShowConsolidated({ history, @@ -22,15 +46,15 @@ export function ShowConsolidated({ return { aml: { threshold: { - hidden: !form.aml + hidden: !form.aml, }, since: { - hidden: !form.aml + hidden: !form.aml, }, state: { - hidden: !form.aml - } - } + hidden: !form.aml, + }, + }, }; }, design: [ @@ -70,29 +94,31 @@ export function ShowConsolidated({ }, Object.entries(cons.kyc).length > 0 ? { - title: i18n.str`KYC`, - 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: i18n.str`KYC`, + 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, ], }; return ( <Fragment> <h1 class="text-base font-semibold leading-7 text-black"> - Consolidated information {until.t_ms === "never" + Consolidated information{" "} + {until.t_ms === "never" ? "" : `after ${format(until.t_ms, "dd MMMM yyyy")}`} </h1> @@ -101,7 +127,7 @@ export function ShowConsolidated({ form={form} initial={cons} readOnly - onUpdate={() => { }} + onUpdate={() => {}} /> </Fragment> ); @@ -115,7 +141,7 @@ interface Consolidated { }; kyc: { [field: string]: { - value: any; + value: unknown; provider: string; since: AbsoluteTime; }; @@ -134,7 +160,7 @@ function getConsolidated( value: 1000, fraction: 0, }, - since: AbsoluteTime.never() + since: AbsoluteTime.never(), }, kyc: {}, }; @@ -153,14 +179,15 @@ function getConsolidated( prev.aml = { since: cur.when, state: cur.state, - threshold: cur.threshold - } + threshold: cur.threshold, + }; break; } case "kyc-collection": { Object.keys(cur.values).forEach((field) => { + const value = (cur.values as Record<string, unknown>)[field]; prev.kyc[field] = { - value: (cur.values as any)[field], + value, provider: cur.provider, since: cur.when, }; @@ -170,4 +197,4 @@ function getConsolidated( } return prev; }, initial); -}
\ No newline at end of file +} diff --git a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx index 1b0342b12..8066155ac 100644 --- a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx +++ b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx @@ -1,3 +1,18 @@ +/* + 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 { TranslatedString, UnwrapKeyError } from "@gnu-taler/taler-util"; import { createNewForm, notifyError, notifyInfo, useTranslationContext } from "@gnu-taler/web-util/browser"; import { VNode, h } from "preact"; @@ -36,8 +51,8 @@ export function UnlockAccount({ } catch (e) { if (e instanceof UnwrapKeyError) { notifyError( - "Could not unlock account" as any, - e.message as any, + i18n.str`Could not unlock account`, + e.message as TranslatedString, ); } else { throw e; diff --git a/packages/aml-backoffice-ui/src/pages/index.stories.ts b/packages/aml-backoffice-ui/src/pages/index.stories.ts index afe73227a..22435178b 100644 --- a/packages/aml-backoffice-ui/src/pages/index.stories.ts +++ b/packages/aml-backoffice-ui/src/pages/index.stories.ts @@ -1,3 +1,18 @@ +/* + 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/> + */ export * as a1 from "./ShowConsolidated.stories.js"; export * as a2 from "./AntiMoneyLaunderingForm.stories.js"; export * as a3 from "./Cases.stories.js"; diff --git a/packages/aml-backoffice-ui/src/route.ts b/packages/aml-backoffice-ui/src/route.ts index f515a590a..ffd54d6af 100644 --- a/packages/aml-backoffice-ui/src/route.ts +++ b/packages/aml-backoffice-ui/src/route.ts @@ -1,19 +1,42 @@ +/* + 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 { TranslatedString } from "@gnu-taler/taler-util"; import { createHashHistory } from "history"; import { ComponentChildren, h as create, createContext, VNode } from "preact"; import { useContext, useEffect, useState } from "preact/hooks"; type ContextType = { - onChange: (listener: () => void) => VoidFunction -} -const nullChangeListener = { onChange: () => () => { } } + onChange: (listener: () => void) => VoidFunction; +}; +const nullChangeListener = { onChange: () => () => {} }; const Context = createContext<ContextType>(nullChangeListener); export const usePathChangeContext = (): ContextType => useContext(Context); -export function HashPathProvider({ children }: { children: ComponentChildren }): VNode { +export function HashPathProvider({ + children, +}: { + children: ComponentChildren; +}): VNode { const history = createHashHistory(); - return create(Context.Provider, { value: { onChange: history.listen }, children }, children) + return create( + Context.Provider, + { value: { onChange: history.listen }, children }, + children, + ); } type PageDefinition<DynamicPart extends Record<string, string>> = { @@ -42,14 +65,17 @@ export function pageDefinition<T extends Record<string, string>>( `page definition pattern ${pattern} doesn't have any parameter`, ); - const vars = patternParams.reduce((prev, cur) => { - const pName = cur.match(/(\w+)/g); + const vars = patternParams.reduce( + (prev, cur) => { + const pName = cur.match(/(\w+)/g); - //skip things like :? in the path pattern - if (!pName || !pName[0]) return prev; - const name = pName[0]; - return { ...prev, [name]: cur }; - }, {} as Record<string, string>); + //skip things like :? in the path pattern + if (!pName || !pName[0]) return prev; + const name = pName[0]; + return { ...prev, [name]: cur }; + }, + {} as Record<string, string>, + ); const f = (values: T): string => replaceAll(pattern, vars, values); f.pattern = pattern; @@ -58,19 +84,19 @@ export function pageDefinition<T extends Record<string, string>>( export type PageEntry<T = unknown> = T extends Record<string, string> ? { - url: PageDefinition<T>; - view: (props: T) => VNode; - name: TranslatedString, - Icon?: () => VNode, - } + url: PageDefinition<T>; + view: (props: T) => VNode; + name: TranslatedString; + Icon?: () => VNode; + } : T extends unknown - ? { - url: string; - view: (props: {}) => VNode; - name: TranslatedString, - Icon?: () => VNode, - } - : never; + ? { + url: string; + view: (props: {}) => VNode; + name: TranslatedString; + Icon?: () => VNode; + } + : never; export function Router({ pageList, @@ -91,27 +117,39 @@ type Location = { path: string; values: Record<string, string>; }; -export function useCurrentLocation(pageList: Array<PageEntry<any>>): Location | undefined { - const [currentLocation, setCurrentLocation] = useState<Location | null | undefined>(null); +export function useCurrentLocation( + pageList: Array<PageEntry<any>>, +): Location | undefined { + const [currentLocation, setCurrentLocation] = useState< + Location | null | undefined + >(null); const path = usePathChangeContext(); useEffect(() => { return path.onChange(() => { - const result = doSync(window.location.hash, new URLSearchParams(window.location.search), pageList); + const result = doSync( + window.location.hash, + new URLSearchParams(window.location.search), + pageList, + ); setCurrentLocation(result); }); }, []); if (currentLocation === null) { - return doSync(window.location.hash, new URLSearchParams(window.location.search), pageList); + return doSync( + window.location.hash, + new URLSearchParams(window.location.search), + pageList, + ); } return currentLocation; } export function useChangeLocation() { - const [location, setLocation] = useState(window.location.hash) - const path = usePathChangeContext() + const [location, setLocation] = useState(window.location.hash); + const path = usePathChangeContext(); useEffect(() => { return path.onChange(() => { - setLocation(window.location.hash) + setLocation(window.location.hash); }); }, []); return location; @@ -125,7 +163,11 @@ export function useChangeLocation() { * @param path * @param params */ -export function doSync(path: string, params: URLSearchParams, pageList: Array<PageEntry<any>>): Location | undefined { +export function doSync( + path: string, + params: URLSearchParams, + pageList: Array<PageEntry<any>>, +): Location | undefined { for (let idx = 0; idx < pageList.length; idx++) { const page = pageList[idx]; if (typeof page.url === "string") { diff --git a/packages/aml-backoffice-ui/src/settings.ts b/packages/aml-backoffice-ui/src/settings.ts index 68f44b4df..600fa0eee 100644 --- a/packages/aml-backoffice-ui/src/settings.ts +++ b/packages/aml-backoffice-ui/src/settings.ts @@ -22,8 +22,7 @@ export interface UiSettings { /** * Global settings for the UI. */ -const defaultSettings: UiSettings = { -}; +const defaultSettings: UiSettings = {}; export const uiSettings: UiSettings = "talerExchangeAmlSettings" in globalThis diff --git a/packages/aml-backoffice-ui/src/stories.test.ts b/packages/aml-backoffice-ui/src/stories.test.ts index eca66cb18..235370e16 100644 --- a/packages/aml-backoffice-ui/src/stories.test.ts +++ b/packages/aml-backoffice-ui/src/stories.test.ts @@ -25,7 +25,7 @@ import * as tests from "@gnu-taler/web-util/testing"; // import * as components from "./components/index.examples.js"; import * as pages from "./pages/index.stories.js"; -import { ComponentChildren, Fragment, VNode, h as create } from "preact"; +import { ComponentChildren, VNode, h as create } from "preact"; import { ExchangeApiContextTesting } from "./context/config.js"; // import { BackendStateProviderTesting } from "./context/backend.js"; @@ -48,7 +48,6 @@ describe("All the examples:", () => { }); }); - function DefaultTestingContext({ children, }: { @@ -61,11 +60,11 @@ function DefaultTestingContext({ name: "ARS", num_fractional_input_digits: 2, num_fractional_normal_digits: 2, - num_fractional_trailing_zero_digits: 2 + num_fractional_trailing_zero_digits: 2, }, name: "taler-exchange", supported_kyc_requirements: [], version: "asd", - } + }; return create(ExchangeApiContextTesting, { config, children }); } diff --git a/packages/aml-backoffice-ui/src/stories.tsx b/packages/aml-backoffice-ui/src/stories.tsx index 1aa6a44ac..017a31ffa 100644 --- a/packages/aml-backoffice-ui/src/stories.tsx +++ b/packages/aml-backoffice-ui/src/stories.tsx @@ -24,39 +24,42 @@ import * as pages from "./pages/index.stories.js"; import { renderStories } from "@gnu-taler/web-util/browser"; -import "./scss/main.css"; -import { h, ComponentChildren, FunctionComponent, VNode } from "preact"; +import { ComponentChildren, FunctionComponent, VNode, h } from "preact"; import { ExchangeApiContextTesting } from "./context/config.js"; +import "./scss/main.css"; function main(): void { renderStories( { pages }, { strings, - getWrapperForGroup + getWrapperForGroup, }, ); } function getWrapperForGroup(): FunctionComponent { return function All({ children }: { children?: ComponentChildren }): VNode { - return <ExchangeApiContextTesting - config={{ - currency: "ARS", - currency_specification: { - alt_unit_names: {}, - name: "ARS", - num_fractional_input_digits: 2, - num_fractional_normal_digits: 2, - num_fractional_trailing_zero_digits: 2 - }, - name: "taler-exchange", - supported_kyc_requirements: [], - version: "asd", - }}> - {children} - </ExchangeApiContextTesting> - } + return ( + <ExchangeApiContextTesting + config={{ + currency: "ARS", + currency_specification: { + alt_unit_names: {}, + name: "ARS", + num_fractional_input_digits: 2, + num_fractional_normal_digits: 2, + num_fractional_trailing_zero_digits: 2, + }, + name: "taler-exchange", + supported_kyc_requirements: [], + version: "asd", + }} + > + {children} + </ExchangeApiContextTesting> + ); + }; } if (document.readyState === "loading") { |