aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/aml-backoffice-ui/src/Dashboard.tsx43
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_11e.ts1
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_1e.ts1
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_4e.ts3
-rw-r--r--packages/aml-backoffice-ui/src/forms/simplest.ts3
-rw-r--r--packages/aml-backoffice-ui/src/handlers/InputDate.tsx11
-rw-r--r--packages/aml-backoffice-ui/src/pages.ts17
-rw-r--r--packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.stories.tsx94
-rw-r--r--packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx72
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseDetails.tsx226
-rw-r--r--packages/aml-backoffice-ui/src/pages/Cases.tsx26
-rw-r--r--packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx10
-rw-r--r--packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx51
-rw-r--r--packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx60
-rw-r--r--packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx204
-rw-r--r--packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx7
-rw-r--r--packages/aml-backoffice-ui/src/pages/index.stories.ts2
-rw-r--r--packages/aml-backoffice-ui/src/route.ts14
-rw-r--r--packages/aml-backoffice-ui/src/stories.test.ts4
-rw-r--r--packages/aml-backoffice-ui/src/stories.tsx7
20 files changed, 533 insertions, 323 deletions
diff --git a/packages/aml-backoffice-ui/src/Dashboard.tsx b/packages/aml-backoffice-ui/src/Dashboard.tsx
index 5d86836d4..d111ae145 100644
--- a/packages/aml-backoffice-ui/src/Dashboard.tsx
+++ b/packages/aml-backoffice-ui/src/Dashboard.tsx
@@ -1,17 +1,12 @@
-import { Footer, GlobalNotificationsBanner, Header, LangSelector, notifyError, notifyException, useNotifications, useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Dialog, Transition } from "@headlessui/react";
-import { UserIcon, XCircleIcon } from "@heroicons/react/20/solid";
-import { CheckCircleIcon, XMarkIcon } from "@heroicons/react/24/outline";
-import { InformationCircleIcon } from "@heroicons/react/24/solid";
-import { ComponentChildren, Fragment, VNode, h } from "preact";
-import { useEffect, useErrorBoundary, useState } from "preact/hooks";
-import logo from "./assets/logo-2021.svg";
-import { Pages } from "./pages.js";
-import { PageEntry, Router, useCurrentLocation } from "./route.js";
-import { uiSettings } from "./settings.js";
import { TranslatedString } from "@gnu-taler/taler-util";
+import { Footer, GlobalNotificationsBanner, Header, notifyError, notifyException, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ComponentChildren, Fragment, 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 { Pages } from "./pages.js";
+import { PageEntry, useChangeLocation, useCurrentLocation } from "./route.js";
+import { uiSettings } from "./settings.js";
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(" ");
@@ -101,7 +96,7 @@ function LeftMenu() {
"group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
)}
>
- <InformationCircleIcon
+ {/* <InformationCircleIcon
class={classNames(
Pages.cases.url === currentLocation?.path
? "text-white"
@@ -109,7 +104,11 @@ function LeftMenu() {
"h-6 w-6 shrink-0",
)}
aria-hidden="true"
- />
+ /> */}
+ <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="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" />
+ </svg>
+
Cases
</a>
</li>
@@ -123,7 +122,11 @@ function LeftMenu() {
"group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold",
)}
>
- <UserIcon
+ <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="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
+ </svg>
+
+ {/* <UserIcon
class={classNames(
Pages.officer.url === currentLocation?.path
? "text-white"
@@ -131,7 +134,7 @@ function LeftMenu() {
"h-6 w-6 shrink-0",
)}
aria-hidden="true"
- />
+ /> */}
Account
</a>
</li>
@@ -233,6 +236,7 @@ function Navigation(): VNode {
Pages.officer,
Pages.cases
]
+ const location = useChangeLocation();
return (
<div class="flex gap-y-5 w-48 bg-indigo-600 divide-y rounded-r-lg divide-cyan-800 overflow-y-auto overflow-x-clip">
@@ -241,10 +245,13 @@ function Navigation(): VNode {
<li>
<ul role="list" class="-mx-2 space-y-1">
{pageList.map(p => {
+
return <li>
- {/* <!-- Current: "bg-indigo-700 text-white", Default: "text-indigo-200 hover:text-white hover:bg-indigo-700" --> */}
- <a href="#" class="bg-indigo-700 text-white group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
- <img src={p.icon} />
+ {/* <!-- Current: "bg-indigo-700 text-white",
+ Default: "text-indigo-200 hover:text-white hover:bg-indigo-700" --> */}
+ <a href={p.url} data-selected={location == p.url}
+ class="data-[selected=true]:bg-indigo-700 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 />}
{p.name}
</a>
</li>
diff --git a/packages/aml-backoffice-ui/src/forms/902_11e.ts b/packages/aml-backoffice-ui/src/forms/902_11e.ts
index a91e7a866..5507c72dc 100644
--- a/packages/aml-backoffice-ui/src/forms/902_11e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_11e.ts
@@ -52,7 +52,6 @@ export const v1 = (current: State): FlexibleForm<Form902_11.Form> => ({
name: "businessEstablisher",
label: "Persons" as TranslatedString,
required: true,
- tooltip: "hola" as TranslatedString,
placeholder: "this is the placeholder" as TranslatedString,
fields: [
{
diff --git a/packages/aml-backoffice-ui/src/forms/902_1e.ts b/packages/aml-backoffice-ui/src/forms/902_1e.ts
index 167d1ac19..c212efb1a 100644
--- a/packages/aml-backoffice-ui/src/forms/902_1e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_1e.ts
@@ -220,7 +220,6 @@ export const v1 = (current: State): FlexibleForm<Form902_1.Form> => ({
name: "businessEstablisher",
label: "Persons" as TranslatedString,
required: true,
- tooltip: "hola" as TranslatedString,
placeholder: "this is the placeholder" as TranslatedString,
fields: [
{
diff --git a/packages/aml-backoffice-ui/src/forms/902_4e.ts b/packages/aml-backoffice-ui/src/forms/902_4e.ts
index cecd74390..7c47a8746 100644
--- a/packages/aml-backoffice-ui/src/forms/902_4e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_4e.ts
@@ -1,11 +1,10 @@
import { AbsoluteTime, TranslatedString } from "@gnu-taler/taler-util";
-import { ArrowRightIcon } from "@heroicons/react/24/outline";
-import { ChevronRightIcon } from "@heroicons/react/24/solid";
import { h as create } from "preact";
import { FormState } from "../handlers/FormProvider.js";
import { State } from "../pages/AntiMoneyLaunderingForm.js";
import { FlexibleForm } from "./index.js";
import { Simplest, resolutionSection } from "./simplest.js";
+import { ArrowRightIcon, ChevronRightIcon } from "../pages/Cases.js";
export const v1 = (current: State): FlexibleForm<Form902_4.Form> => ({
versionId: "2023-05-15",
diff --git a/packages/aml-backoffice-ui/src/forms/simplest.ts b/packages/aml-backoffice-ui/src/forms/simplest.ts
index 023c1765f..6497f3949 100644
--- a/packages/aml-backoffice-ui/src/forms/simplest.ts
+++ b/packages/aml-backoffice-ui/src/forms/simplest.ts
@@ -7,9 +7,10 @@ import {
import { FormState } from "../handlers/FormProvider.js";
import { DoubleColumnFormSection } from "../handlers/forms.js";
import { State } from "../pages/AntiMoneyLaunderingForm.js";
-import { amlStateConverter } from "../pages/CaseDetails.js";
+
import { AmlExchangeBackend } from "../types.js";
import { FlexibleForm } from "./index.js";
+import { amlStateConverter } from "../pages/ShowConsolidated.js";
export const v1 = (current: State): FlexibleForm<Simplest.Form> => ({
versionId: "2023-05-25",
diff --git a/packages/aml-backoffice-ui/src/handlers/InputDate.tsx b/packages/aml-backoffice-ui/src/handlers/InputDate.tsx
index 1fd81aad9..0f286e001 100644
--- a/packages/aml-backoffice-ui/src/handlers/InputDate.tsx
+++ b/packages/aml-backoffice-ui/src/handlers/InputDate.tsx
@@ -1,6 +1,5 @@
import { AbsoluteTime } from "@gnu-taler/taler-util";
import { InputLine, UIFormProps } from "./InputLine.js";
-import { CalendarIcon } from "@heroicons/react/24/outline";
import { VNode, h } from "preact";
import { format, parse } from "date-fns";
@@ -13,7 +12,11 @@ export function InputDate<T extends object, K extends keyof T>(
type="text"
after={{
type: "icon",
- icon: <CalendarIcon class="h-6 w-6" />,
+ // icon: <CalendarIcon class="h-6 w-6" />,
+ icon: <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="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5" />
+ </svg>
+
}}
converter={{
//@ts-ignore
@@ -27,8 +30,8 @@ export function InputDate<T extends object, K extends keyof T>(
return !v || !v.t_ms
? ""
: v.t_ms === "never"
- ? "never"
- : format(v.t_ms, pattern);
+ ? "never"
+ : format(v.t_ms, pattern);
},
}}
{...props}
diff --git a/packages/aml-backoffice-ui/src/pages.ts b/packages/aml-backoffice-ui/src/pages.ts
index 17ede651d..109cd31d0 100644
--- a/packages/aml-backoffice-ui/src/pages.ts
+++ b/packages/aml-backoffice-ui/src/pages.ts
@@ -1,24 +1,24 @@
import { TranslatedString } from "@gnu-taler/taler-util";
import { AntiMoneyLaunderingForm } from "./pages/AntiMoneyLaunderingForm.js";
import { CaseDetails } from "./pages/CaseDetails.js";
-import { Cases } from "./pages/Cases.js";
+import { Cases, HomeIcon, PeopleIcon } from "./pages/Cases.js";
import { NewFormEntry } from "./pages/NewFormEntry.js";
import { Officer } from "./pages/Officer.js";
import { PageEntry, pageDefinition } from "./route.js";
-import homeLogo from "./assets/home.svg";
-import peopleLogo from "./assets/people.svg";
+// import homeLogo from "./assets/home.svg";
+// import peopleLogo from "./assets/people.svg";
const cases: PageEntry = {
url: "#/cases",
view: Cases,
name: "Cases" as TranslatedString,
- icon: homeLogo,
+ Icon: HomeIcon,
};
const officer: PageEntry = {
url: "#/officer",
view: Officer,
name: "Officer" as TranslatedString,
- icon: peopleLogo,
+ Icon: PeopleIcon,
};
const account: PageEntry<{ account: string }> = {
@@ -35,17 +35,10 @@ const newFormEntry: PageEntry<{ account?: string; type?: string }> = {
// icon: () => undefined,
};
-const form: PageEntry<{ number?: string }> = {
- url: pageDefinition("#/form/:number?"),
- view: AntiMoneyLaunderingForm,
- name: "Form" as TranslatedString,
- // icon: () => undefined,
-};
export const Pages = {
cases,
officer,
account,
- form,
newFormEntry,
};
diff --git a/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.stories.tsx b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.stories.tsx
new file mode 100644
index 000000000..a14966cc0
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.stories.tsx
@@ -0,0 +1,94 @@
+/*
+ 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import {
+ AntiMoneyLaunderingForm as TestedComponent,
+} from "./AntiMoneyLaunderingForm.js";
+
+export default {
+ title: "aml form",
+};
+
+export const SimpleComment = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 0,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const Identification = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 1,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const OperationalLegalEntity = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 2,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const Foundations = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 3,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const DelcarationOfTrusts = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 4,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const InformationOnLifeInsurance = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 5,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const DeclarationOfBeneficialOwner = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 6,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const CustomerProfile = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 7,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+export const RiskProfile = tests.createExample(TestedComponent, {
+ account: "the_account",
+ selectedForm: 8,
+ onSubmit: async (justification, newState, newThreshold) => {
+ alert(JSON.stringify({justification, newState, newThreshold}, undefined, 2))
+ }
+});
+
diff --git a/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx
index c3fb7dafe..5d2a3dffe 100644
--- a/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx
+++ b/packages/aml-backoffice-ui/src/pages/AntiMoneyLaunderingForm.tsx
@@ -1,3 +1,5 @@
+import { AbsoluteTime, AmountJson, Amounts } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { h } from "preact";
import { NiceForm } from "../NiceForm.js";
import { v1 as form_902_11e_v1 } from "../forms/902_11e.js";
@@ -9,30 +11,63 @@ import { v1 as form_902_4e_v1 } from "../forms/902_4e.js";
import { v1 as form_902_5e_v1 } from "../forms/902_5e.js";
import { v1 as form_902_9e_v1 } from "../forms/902_9e.js";
import { v1 as simplest } from "../forms/simplest.js";
-import { DocumentDuplicateIcon } from "@heroicons/react/24/solid";
-import { AbsoluteTime } from "@gnu-taler/taler-util";
-import { AmountJson, Amounts } from "@gnu-taler/taler-util";
+import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
-export function AntiMoneyLaunderingForm({ number }: { number?: string }) {
- const selectedForm = Number.parseInt(number ?? "0", 10);
- if (Number.isNaN(selectedForm)) {
- return <div>WHAT! {number}</div>;
- }
+export type Justification = {
+ // form index in the list of forms
+ index: number;
+ // form name
+ name: string;
+ // form values
+ value: any;
+}
+
+export function AntiMoneyLaunderingForm({ account, selectedForm, onSubmit }: { account: string, selectedForm: number, onSubmit: (justification: Justification, state: AmlExchangeBackend.AmlState, threshold: AmountJson) => Promise<void>; }) {
+ const { i18n } = useTranslationContext()
const showingFrom = allForms[selectedForm].impl;
- const storedValue = {
+ const formName = allForms[selectedForm].name
+ const initial = {
fullName: "loggedIn_user_fullname",
when: AbsoluteTime.now(),
+ state: AmlExchangeBackend.AmlState.pending,
+ threshold: Amounts.parseOrThrow("KUDOS:1000"),
};
return (
<NiceForm
- initial={storedValue}
- form={showingFrom({
- state: AmlExchangeBackend.AmlState.pending,
- threshold: Amounts.parseOrThrow("USD:10"),
- })}
- onUpdate={() => {}}
- />
+ initial={initial}
+ form={showingFrom(initial)}
+ onUpdate={() => { }}
+ onSubmit={(formValue) => {
+ if (formValue.state === undefined || formValue.threshold === undefined) return;
+ const st = formValue.state;
+ const amount = formValue.threshold;
+
+ const justification = {
+ index: selectedForm,
+ name: formName,
+ value: formValue
+ }
+
+ onSubmit(justification, st, amount);
+ }}
+ >
+ <div class="mt-6 flex items-center justify-end gap-x-6">
+ <a
+ // type="button"
+ href={Pages.account.url({ account })}
+ class="text-sm font-semibold leading-6 text-gray-900"
+ >
+ <i18n.Translate>Cancel</i18n.Translate>
+ </a>
+ <button
+ type="submit"
+ class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Confirm</i18n.Translate>
+ </button>
+ </div>
+ </NiceForm>
);
}
@@ -41,6 +76,11 @@ export interface State {
threshold: AmountJson;
}
+const DocumentDuplicateIcon = <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="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 01-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 011.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 00-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 01-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5a3.375 3.375 0 00-3.375-3.375H9.75" />
+</svg>
+
+
export const allForms = [
{
name: "Simple comment",
diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
index f618a3592..1f8d6ac5e 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
@@ -2,24 +2,20 @@ import {
AbsoluteTime,
AmountJson,
Amounts,
- PaytoString,
TalerError,
TranslatedString,
- assertUnreachable,
+ assertUnreachable
} from "@gnu-taler/taler-util";
import { ErrorLoading, Loading, useTranslationContext } from "@gnu-taler/web-util/browser";
-import { ArrowDownCircleIcon, ClockIcon } from "@heroicons/react/20/solid";
import { format } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { NiceForm } from "../NiceForm.js";
-import { FlexibleForm } from "../forms/index.js";
-import { UIFormField } from "../handlers/forms.js";
import { useCaseDetails } from "../hooks/useCaseDetails.js";
import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
+import { ShowConsolidated } from "./ShowConsolidated.js";
-type AmlEvent = AmlFormEvent | KycCollectionEvent | KycExpirationEvent;
+export type AmlEvent = AmlFormEvent | KycCollectionEvent | KycExpirationEvent;
type AmlFormEvent = {
type: "aml-form";
when: AbsoluteTime;
@@ -47,7 +43,7 @@ function selectSooner(a: WithTime, b: WithTime) {
return AbsoluteTime.cmp(a.when, b.when);
}
-function getEventsFromAmlHistory(
+export function getEventsFromAmlHistory(
aml: AmlExchangeBackend.AmlDecisionDetail[],
kyc: AmlExchangeBackend.KycDetail[],
): AmlEvent[] {
@@ -113,12 +109,16 @@ 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"
>
- New AML form
+ <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">
- Case history
+ <i18n.Translate>
+ Case history
+ </i18n.Translate>
</h1>
</header>
<div class="flow-root">
@@ -187,11 +187,18 @@ export function CaseDetails({ account }: { account: string }) {
}
case "kyc-collection": {
return (
- <ArrowDownCircleIcon class="h-8 w-8 text-green-700" />
+ // <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 <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>
+
}
}
})()}
@@ -217,7 +224,7 @@ export function CaseDetails({ account }: { account: string }) {
</ul>
</div>
{selected && <ShowEventDetails event={selected} />}
- {selected && <ShowConsolidated history={events} until={selected} />}
+ {selected && <ShowConsolidated history={events} until={selected.when} />}
</div>
);
}
@@ -226,197 +233,4 @@ function ShowEventDetails({ event }: { event: AmlEvent }): VNode {
return <div>type {event.type}</div>;
}
-function ShowConsolidated({
- history,
- until,
-}: {
- history: AmlEvent[];
- until: AmlEvent;
-}): VNode {
- const cons = getConsolidated(history, until.when);
-
- const form: FlexibleForm<Consolidated> = {
- versionId: "1",
- behavior: (form) => {
- return {
- aml: {
- threshold: {
- hidden: !form.aml
- },
- since: {
- hidden: !form.aml
- },
- state: {
- hidden: !form.aml
- }
- }
- };
- },
- design: [
- {
- title: "AML" as TranslatedString,
- fields: [
- {
- type: "amount",
- props: {
- label: "Threshold" as TranslatedString,
- name: "aml.threshold",
- },
- },
- {
- type: "choiceHorizontal",
- props: {
- label: "State" as TranslatedString,
- name: "aml.state",
- converter: amlStateConverter,
- choices: [
- {
- label: "Frozen" as TranslatedString,
- value: AmlExchangeBackend.AmlState.frozen,
- },
- {
- label: "Pending" as TranslatedString,
- value: AmlExchangeBackend.AmlState.pending,
- },
- {
- label: "Normal" as TranslatedString,
- value: AmlExchangeBackend.AmlState.normal,
- },
- ],
- },
- },
- ],
- },
- Object.entries(cons.kyc).length > 0
- ? {
- title: "KYC" as TranslatedString,
- fields: Object.entries(cons.kyc).map(([key, field]) => {
- const result: UIFormField = {
- type: "text",
- props: {
- label: key as TranslatedString,
- name: `kyc.${key}.value`,
- help: `${field.provider} since ${field.since.t_ms === "never"
- ? "never"
- : format(field.since.t_ms, "dd/MM/yyyy")
- }` as TranslatedString,
- },
- };
- return result;
- }),
- }
- : undefined,
- ],
- };
- return (
- <Fragment>
- <h1 class="text-base font-semibold leading-7 text-black">
- Consolidated information after{" "}
- {until.when.t_ms === "never"
- ? "never"
- : format(until.when.t_ms, "dd MMMM yyyy")}
- </h1>
- <NiceForm
- key={`${String(Date.now())}`}
- form={form}
- initial={cons}
- onUpdate={() => { }}
- />
- </Fragment>
- );
-}
-interface Consolidated {
- aml: {
- state: AmlExchangeBackend.AmlState;
- threshold: AmountJson;
- since: AbsoluteTime;
- };
- kyc: {
- [field: string]: {
- value: any;
- provider: string;
- since: AbsoluteTime;
- };
- };
-}
-
-function getConsolidated(
- history: AmlEvent[],
- when: AbsoluteTime,
-): Consolidated {
- const initial: Consolidated = {
- aml: {
- state: AmlExchangeBackend.AmlState.normal,
- threshold: {
- currency: "ARS",
- value: 1000,
- fraction: 0,
- },
- since: AbsoluteTime.never()
- },
- kyc: {},
- };
- return history.reduce((prev, cur) => {
- if (AbsoluteTime.cmp(when, cur.when) < 0) {
- return prev;
- }
- switch (cur.type) {
- case "kyc-expiration": {
- cur.fields.forEach((field) => {
- delete prev.kyc[field];
- });
- break;
- }
- case "aml-form": {
- prev.aml = {
- since: cur.when,
- state: cur.state,
- threshold: cur.threshold
- }
- break;
- }
- case "kyc-collection": {
- Object.keys(cur.values).forEach((field) => {
- prev.kyc[field] = {
- value: (cur.values as any)[field],
- provider: cur.provider,
- since: cur.when,
- };
- });
- break;
- }
- }
- return prev;
- }, initial);
-}
-
-export const amlStateConverter = {
- toStringUI: stringifyAmlState,
- fromStringUI: parseAmlState,
-};
-
-function stringifyAmlState(s: AmlExchangeBackend.AmlState | undefined): string {
- if (s === undefined) return "";
- switch (s) {
- case AmlExchangeBackend.AmlState.normal:
- return "normal";
- case AmlExchangeBackend.AmlState.pending:
- return "pending";
- case AmlExchangeBackend.AmlState.frozen:
- return "frozen";
- }
-}
-
-function parseAmlState(s: string | undefined): AmlExchangeBackend.AmlState {
- switch (s) {
- case "normal":
- return AmlExchangeBackend.AmlState.normal;
- case "pending":
- return AmlExchangeBackend.AmlState.pending;
- case "frozen":
- return AmlExchangeBackend.AmlState.frozen;
- default:
- throw Error(`unknown AML state: ${s}`);
- }
-}
diff --git a/packages/aml-backoffice-ui/src/pages/Cases.tsx b/packages/aml-backoffice-ui/src/pages/Cases.tsx
index 624f2c985..64cacf68c 100644
--- a/packages/aml-backoffice-ui/src/pages/Cases.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Cases.tsx
@@ -6,8 +6,9 @@ import { createNewForm } from "../handlers/forms.js";
import { useCases } from "../hooks/useCases.js";
import { Pages } from "../pages.js";
import { AmlExchangeBackend } from "../types.js";
-import { amlStateConverter } from "./CaseDetails.js";
+
import { Officer } from "./Officer.js";
+import { amlStateConverter } from "./ShowConsolidated.js";
export function Cases() {
const { i18n } = useTranslationContext();
@@ -43,10 +44,14 @@ export function Cases() {
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<h1 class="text-base font-semibold leading-6 text-gray-900">
+ <i18n.Translate>
Cases
+ </i18n.Translate>
</h1>
<p class="mt-2 text-sm text-gray-700">
+ <i18n.Translate>
A list of all the account with the status
+ </i18n.Translate>
</p>
</div>
<form.Provider
@@ -166,6 +171,25 @@ export function Cases() {
);
}
+export const PeopleIcon = () => <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="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z" />
+</svg>
+
+export const HomeIcon = () => <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="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" />
+</svg>
+
+
+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">
+<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
+</svg>
+
+
+export const ArrowRightIcon = () => <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="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
+</svg>
+
+
function Pagination() {
return (
<nav class="flex items-center justify-between px-4 sm:px-0">
diff --git a/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx b/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx
index b3d04d97e..ff800ebdc 100644
--- a/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx
+++ b/packages/aml-backoffice-ui/src/pages/HandleAccountNotReady.tsx
@@ -2,6 +2,7 @@ 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,
@@ -24,14 +25,11 @@ export function HandleAccountNotReady({
onRemoveAccount={() => {
officer.forget();
}}
- onAccountUnlocked={(pwd) => {
- officer.tryUnlock(pwd);
+ onAccountUnlocked={async (pwd) => {
+ await officer.tryUnlock(pwd);
}}
/>
);
}
- return <div>
- some
- </div>
- throw Error(`unexpected account state ${(officer as any).state}`);
+ assertUnreachable(officer)
}
diff --git a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
index b291ffbee..e70536cb2 100644
--- a/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
+++ b/packages/aml-backoffice-ui/src/pages/NewFormEntry.tsx
@@ -1,5 +1,5 @@
import { VNode, h } from "preact";
-import { allForms } from "./AntiMoneyLaunderingForm.js";
+import { AntiMoneyLaunderingForm, allForms } from "./AntiMoneyLaunderingForm.js";
import { Pages } from "../pages.js";
import { NiceForm } from "../NiceForm.js";
import { AbsoluteTime, Amounts, TalerExchangeApi, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
@@ -31,60 +31,27 @@ export function NewFormEntry({
if (Number.isNaN(selectedForm)) {
return <div>WHAT! {type}</div>;
}
- const showingFrom = allForms[selectedForm].impl;
- const formName = allForms[selectedForm].name
- const initial = {
- fullName: "loggedIn_user_fullname",
- when: AbsoluteTime.now(),
- state: AmlExchangeBackend.AmlState.pending,
- threshold: Amounts.parseOrThrow("KUDOS:1000"),
- };
+
const { api } = useExchangeApiContext()
return (
- <NiceForm
- initial={initial}
- form={showingFrom(initial)}
- onSubmit={(formValue) => {
- if (formValue.state === undefined || formValue.threshold === undefined) return;
-
- const justification = {
- index: selectedForm,
- name: formName,
- value: formValue
- }
+ <AntiMoneyLaunderingForm
+ account={account}
+ selectedForm={selectedForm}
+ onSubmit={async (justification, new_state, new_threshold) => {
const decision: TalerExchangeApi.AmlDecision = {
justification: JSON.stringify(justification),
decision_time: TalerProtocolTimestamp.now(),
h_payto: account,
- new_state: formValue.state,
- new_threshold: Amounts.stringify(formValue.threshold),
+ new_state,
+ new_threshold: Amounts.stringify(new_threshold),
officer_sig: "",
kyc_requirements: undefined
}
- // const signature = buildDecisionSignature(officer.account.signingKey, decision);
- // decision.officer_sig = signature
api.addDecisionDetails(officer.account, decision);
- // alert(JSON.stringify(formValue));
}}
- >
- <div class="mt-6 flex items-center justify-end gap-x-6">
- <a
- // type="button"
- href={Pages.account.url({ account })}
- class="text-sm font-semibold leading-6 text-gray-900"
- >
- Cancel
- </a>
- <button
- type="submit"
- class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
- >
- Confirm
- </button>
- </div>
- </NiceForm>
+ />
);
}
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx
new file mode 100644
index 000000000..1a86e8e98
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx
@@ -0,0 +1,60 @@
+/*
+ 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/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { addDays } from "date-fns";
+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";
+
+export default {
+ title: "show consolidated",
+};
+
+export const WithEmptyHistory = tests.createExample(TestedComponent, {
+ history: getEventsFromAmlHistory([],[]),
+ until: AbsoluteTime.now()
+});
+
+export const WithSomeEvents = tests.createExample(TestedComponent, {
+ history: getEventsFromAmlHistory([{
+ decider_pub: "123",
+ decision_time: { t_s: 1 },
+ justification: "yes",
+ new_state: 1,
+ new_threshold: "USD:10",
+ }],[{
+ collection_time: AbsoluteTime.toProtocolTimestamp(
+ AbsoluteTime.subtractDuraction(AbsoluteTime.now(), Duration.fromPrettyString("1d"))
+ ),
+ expiration_time: { t_s: "never"},
+ provider_section: "asd",
+ attributes: {
+ email: "sebasjm@qwe.com"
+ }
+ }]),
+ until: AbsoluteTime.now()
+});
+
+
+
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
new file mode 100644
index 000000000..0efc68632
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
@@ -0,0 +1,204 @@
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { NiceForm } from "../NiceForm.js";
+import { FlexibleForm } from "../forms/index.js";
+import { UIFormField } from "../handlers/forms.js";
+import { AmlEvent } from "./CaseDetails.js";
+import { AmlExchangeBackend } from "../types.js";
+import { AbsoluteTime, AmountJson, TranslatedString } from "@gnu-taler/taler-util";
+import { format } from "date-fns";
+
+export function ShowConsolidated({
+ history,
+ until,
+}: {
+ history: AmlEvent[];
+ until: AbsoluteTime;
+}): VNode {
+ const cons = getConsolidated(history, until);
+
+ const form: FlexibleForm<Consolidated> = {
+ versionId: "1",
+ behavior: (form) => {
+ return {
+ aml: {
+ threshold: {
+ hidden: !form.aml
+ },
+ since: {
+ hidden: !form.aml
+ },
+ state: {
+ hidden: !form.aml
+ }
+ }
+ };
+ },
+ design: [
+ {
+ title: "AML" as TranslatedString,
+ fields: [
+ {
+ type: "amount",
+ props: {
+ label: "Threshold" as TranslatedString,
+ name: "aml.threshold",
+ },
+ },
+ {
+ type: "choiceHorizontal",
+ props: {
+ label: "State" as TranslatedString,
+ name: "aml.state",
+ converter: amlStateConverter,
+ choices: [
+ {
+ label: "Frozen" as TranslatedString,
+ value: AmlExchangeBackend.AmlState.frozen,
+ },
+ {
+ label: "Pending" as TranslatedString,
+ value: AmlExchangeBackend.AmlState.pending,
+ },
+ {
+ label: "Normal" as TranslatedString,
+ value: AmlExchangeBackend.AmlState.normal,
+ },
+ ],
+ },
+ },
+ ],
+ },
+ Object.entries(cons.kyc).length > 0
+ ? {
+ title: "KYC" as TranslatedString,
+ fields: Object.entries(cons.kyc).map(([key, field]) => {
+ const result: UIFormField = {
+ type: "text",
+ props: {
+ label: key as TranslatedString,
+ name: `kyc.${key}.value`,
+ help: `${field.provider} since ${field.since.t_ms === "never"
+ ? "never"
+ : format(field.since.t_ms, "dd/MM/yyyy")
+ }` as TranslatedString,
+ },
+ };
+ return result;
+ }),
+ }
+ : undefined,
+ ],
+ };
+ return (
+ <Fragment>
+ <h1 class="text-base font-semibold leading-7 text-black">
+ Consolidated information
+ {until.t_ms === "never"
+ ? ""
+ : `after ${format(until.t_ms, "dd MMMM yyyy")}` }
+ </h1>
+ <NiceForm
+ key={`${String(Date.now())}`}
+ form={form}
+ initial={cons}
+ onUpdate={() => { }}
+ />
+ </Fragment>
+ );
+}
+
+interface Consolidated {
+ aml: {
+ state: AmlExchangeBackend.AmlState;
+ threshold: AmountJson;
+ since: AbsoluteTime;
+ };
+ kyc: {
+ [field: string]: {
+ value: any;
+ provider: string;
+ since: AbsoluteTime;
+ };
+ };
+}
+
+function getConsolidated(
+ history: AmlEvent[],
+ when: AbsoluteTime,
+): Consolidated {
+ const initial: Consolidated = {
+ aml: {
+ state: AmlExchangeBackend.AmlState.normal,
+ threshold: {
+ currency: "ARS",
+ value: 1000,
+ fraction: 0,
+ },
+ since: AbsoluteTime.never()
+ },
+ kyc: {},
+ };
+ return history.reduce((prev, cur) => {
+ if (AbsoluteTime.cmp(when, cur.when) < 0) {
+ return prev;
+ }
+ switch (cur.type) {
+ case "kyc-expiration": {
+ cur.fields.forEach((field) => {
+ delete prev.kyc[field];
+ });
+ break;
+ }
+ case "aml-form": {
+ prev.aml = {
+ since: cur.when,
+ state: cur.state,
+ threshold: cur.threshold
+ }
+ break;
+ }
+ case "kyc-collection": {
+ Object.keys(cur.values).forEach((field) => {
+ prev.kyc[field] = {
+ value: (cur.values as any)[field],
+ provider: cur.provider,
+ since: cur.when,
+ };
+ });
+ break;
+ }
+ }
+ return prev;
+ }, initial);
+}
+
+export const amlStateConverter = {
+ toStringUI: stringifyAmlState,
+ fromStringUI: parseAmlState,
+};
+
+function stringifyAmlState(s: AmlExchangeBackend.AmlState | undefined): string {
+ if (s === undefined) return "";
+ switch (s) {
+ case AmlExchangeBackend.AmlState.normal:
+ return "normal";
+ case AmlExchangeBackend.AmlState.pending:
+ return "pending";
+ case AmlExchangeBackend.AmlState.frozen:
+ return "frozen";
+ }
+}
+
+function parseAmlState(s: string | undefined): AmlExchangeBackend.AmlState {
+ switch (s) {
+ case "normal":
+ return AmlExchangeBackend.AmlState.normal;
+ case "pending":
+ return AmlExchangeBackend.AmlState.pending;
+ case "frozen":
+ return AmlExchangeBackend.AmlState.frozen;
+ default:
+ throw Error(`unknown AML state: ${s}`);
+ }
+}
diff --git a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
index a6570ffcc..ba5aa7b1f 100644
--- a/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
+++ b/packages/aml-backoffice-ui/src/pages/UnlockAccount.tsx
@@ -7,7 +7,7 @@ export function UnlockAccount({
onAccountUnlocked,
onRemoveAccount,
}: {
- onAccountUnlocked: (password: string) => void;
+ onAccountUnlocked: (password: string) => Promise<void>;
onRemoveAccount: () => void;
}): VNode {
const { i18n } = useTranslationContext()
@@ -30,13 +30,10 @@ export function UnlockAccount({
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-[480px] ">
<div class="bg-gray-100 px-6 py-6 shadow sm:rounded-lg sm:px-12">
<Form.Provider
- initialValue={{
- password: "qwe",
- }}
+ initialValue={{}}
onSubmit={async (v) => {
try {
await onAccountUnlocked(v.password!);
-
notifyInfo("Account unlocked" as TranslatedString);
} catch (e) {
if (e instanceof UnwrapKeyError) {
diff --git a/packages/aml-backoffice-ui/src/pages/index.stories.ts b/packages/aml-backoffice-ui/src/pages/index.stories.ts
new file mode 100644
index 000000000..e31e13a28
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/pages/index.stories.ts
@@ -0,0 +1,2 @@
+export * as a1 from "./ShowConsolidated.stories.js";
+export * as a2 from "./AntiMoneyLaunderingForm.stories.js";
diff --git a/packages/aml-backoffice-ui/src/route.ts b/packages/aml-backoffice-ui/src/route.ts
index 4c3331668..9176ab5e4 100644
--- a/packages/aml-backoffice-ui/src/route.ts
+++ b/packages/aml-backoffice-ui/src/route.ts
@@ -49,14 +49,14 @@ export type PageEntry<T = unknown> = T extends Record<string, string>
url: PageDefinition<T>;
view: (props: T) => VNode;
name: TranslatedString,
- icon?: string,
+ Icon?: () => VNode,
}
: T extends unknown
? {
url: string;
view: (props: {}) => VNode;
name: TranslatedString,
- icon?: string,
+ Icon?: () => VNode,
}
: never;
@@ -124,6 +124,16 @@ export function useCurrentLocation(pageList: Array<PageEntry<any>>) {
return currentLocation;
}
+export function useChangeLocation() {
+ const [location, setLocation] = useState(window.location.hash)
+ useEffect(() => {
+ return history.listen(() => {
+ setLocation(window.location.hash)
+ });
+ }, []);
+ return location;
+}
+
function doestUrlMatchToRoute(
url: string,
route: string,
diff --git a/packages/aml-backoffice-ui/src/stories.test.ts b/packages/aml-backoffice-ui/src/stories.test.ts
index 4e24967e4..3b1d0267d 100644
--- a/packages/aml-backoffice-ui/src/stories.test.ts
+++ b/packages/aml-backoffice-ui/src/stories.test.ts
@@ -23,7 +23,7 @@ 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";
-// import * as pages from "./pages/index.stories.js";
+import * as pages from "./pages/index.stories.js";
import { ComponentChildren, Fragment, VNode, h as create } from "preact";
// import { BackendStateProviderTesting } from "./context/backend.js";
@@ -31,7 +31,7 @@ import { ComponentChildren, Fragment, VNode, h as create } from "preact";
setupI18n("en", { en: {} });
describe("All the examples:", () => {
- const cms = parseGroupImport({});
+ const cms = parseGroupImport({pages});
cms.forEach((group) => {
describe(`Example for group "${group.title}:"`, () => {
group.list.forEach((component) => {
diff --git a/packages/aml-backoffice-ui/src/stories.tsx b/packages/aml-backoffice-ui/src/stories.tsx
index b6c0c1f07..5ef54309c 100644
--- a/packages/aml-backoffice-ui/src/stories.tsx
+++ b/packages/aml-backoffice-ui/src/stories.tsx
@@ -20,17 +20,16 @@
*/
import { strings } from "./i18n/strings.js";
-// import * as pages from "./pages/index.stories.js";
+import * as pages from "./pages/index.stories.js";
// import * as components from "./components/index.examples.js";
import { renderStories } from "@gnu-taler/web-util/browser";
-// import "./scss/main.scss";
+import "./scss/main.css";
function main(): void {
renderStories(
- // { pages, components },
- {},
+ {pages},
{
strings,
},