aboutsummaryrefslogtreecommitdiff
path: root/packages/aml-backoffice-ui/src
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-05-02 09:57:49 -0300
committerSebastian <sebasjm@gmail.com>2024-05-03 08:44:06 -0300
commitfa4c7039f4ebeb6ad3cf19237ad7b138519ac142 (patch)
treeefa5f9d93961be5b71d6e3a08a33032a3819d5b2 /packages/aml-backoffice-ui/src
parent9e3fc09bb056948d0706386edf52cd3a27b184ba (diff)
downloadwallet-core-fa4c7039f4ebeb6ad3cf19237ad7b138519ac142.tar.xz
removing compiled form ts
Diffstat (limited to 'packages/aml-backoffice-ui/src')
-rw-r--r--packages/aml-backoffice-ui/src/App.tsx5
-rw-r--r--packages/aml-backoffice-ui/src/forms.ts24
-rw-r--r--packages/aml-backoffice-ui/src/forms/index.ts4
-rw-r--r--packages/aml-backoffice-ui/src/forms/simplest.ts4
-rw-r--r--packages/aml-backoffice-ui/src/hooks/form.ts12
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseDetails.tsx5
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx169
7 files changed, 174 insertions, 49 deletions
diff --git a/packages/aml-backoffice-ui/src/App.tsx b/packages/aml-backoffice-ui/src/App.tsx
index 9ccf21755..ae8b574b6 100644
--- a/packages/aml-backoffice-ui/src/App.tsx
+++ b/packages/aml-backoffice-ui/src/App.tsx
@@ -29,15 +29,18 @@ import { UiSettingsProvider } from "./context/ui-settings.js";
import { strings } from "./i18n/strings.js";
import "./scss/main.css";
import { UiSettings, fetchUiSettings } from "./context/ui-settings.js";
+import { UiForms, fetchUiForms } from "./context/ui-forms.js";
const WITH_LOCAL_STORAGE_CACHE = false;
export function App(): VNode {
const [settings, setSettings] = useState<UiSettings>();
+ const [forms, setForms] = useState<UiForms>();
useEffect(() => {
fetchUiSettings(setSettings);
+ fetchUiForms(setForms);
}, []);
- if (!settings) return <Loading />;
+ if (!settings || !forms) return <Loading />;
const baseUrl = getInitialBackendBaseURL(settings.backendBaseURL);
return (
diff --git a/packages/aml-backoffice-ui/src/forms.ts b/packages/aml-backoffice-ui/src/forms.ts
deleted file mode 100644
index 3ecec2bb0..000000000
--- a/packages/aml-backoffice-ui/src/forms.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 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 * from "./forms/index.js";
-
-/**
- * this file is here to have a flat dist folder
- *
- * this file is being build in a bundle separated
- * from the main one.
- */
diff --git a/packages/aml-backoffice-ui/src/forms/index.ts b/packages/aml-backoffice-ui/src/forms/index.ts
index b32978c29..abeebfc6a 100644
--- a/packages/aml-backoffice-ui/src/forms/index.ts
+++ b/packages/aml-backoffice-ui/src/forms/index.ts
@@ -129,10 +129,10 @@ const languages = (i18n: InternationalizationAPI) => [
];
-const forms: (i18n: InternationalizationAPI) => Array<FormMetadata> = (i18n) => [
+export const preloadedForms: (i18n: InternationalizationAPI) => Array<FormMetadata> = (i18n) => [
{
label: i18n.str`Simple comment`,
- id: "simple_comment",
+ id: "__simple_comment",
version: 1,
config: simplest(i18n),
// }, {
diff --git a/packages/aml-backoffice-ui/src/forms/simplest.ts b/packages/aml-backoffice-ui/src/forms/simplest.ts
index d32c759cb..c7ba95462 100644
--- a/packages/aml-backoffice-ui/src/forms/simplest.ts
+++ b/packages/aml-backoffice-ui/src/forms/simplest.ts
@@ -17,7 +17,7 @@
import type {
InternationalizationAPI
} from "@gnu-taler/web-util/browser";
-import { BaseForm, DoubleColumnForm, DoubleColumnFormSection, UIHandlerId } from "../context/ui-forms.js";
+import { DoubleColumnForm, DoubleColumnFormSection, UIHandlerId } from "../context/ui-forms.js";
export const v1 = (i18n: InternationalizationAPI): DoubleColumnForm => ({
type: "double-column" as const,
@@ -84,7 +84,7 @@ export function resolutionSection(
type: "amount",
properties: {
id: ".threshold" as UIHandlerId,
- currency: "USD",
+ currency: "NETZBON",
name: "threshold",
label: i18n.str`New threshold`,
},
diff --git a/packages/aml-backoffice-ui/src/hooks/form.ts b/packages/aml-backoffice-ui/src/hooks/form.ts
index e14e29819..edeae6085 100644
--- a/packages/aml-backoffice-ui/src/hooks/form.ts
+++ b/packages/aml-backoffice-ui/src/hooks/form.ts
@@ -19,8 +19,8 @@ import {
TalerExchangeApi,
TranslatedString,
} from "@gnu-taler/taler-util";
+import { UIFieldHandler } from "@gnu-taler/web-util/browser";
import { useState } from "preact/hooks";
-import { UIField } from "@gnu-taler/web-util/browser";
// export type UIField = {
// value: string | undefined;
@@ -28,13 +28,13 @@ import { UIField } from "@gnu-taler/web-util/browser";
// error: TranslatedString | undefined;
// };
-type FormHandler<T> = {
+export type FormHandler<T> = {
[k in keyof T]?: T[k] extends string
- ? UIField
+ ? UIFieldHandler
: T[k] extends AmountJson
- ? UIField
+ ? UIFieldHandler
: T[k] extends TalerExchangeApi.AmlState
- ? UIField
+ ? UIFieldHandler
: FormHandler<T[k]>;
};
@@ -100,7 +100,7 @@ function constructFormHandler<T>(
return prev;
}
- const field: UIField = {
+ const field: UIFieldHandler = {
// @ts-expect-error FIXME better typing
error: currentError,
// @ts-expect-error FIXME better typing
diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
index 1ad8c9453..62c54d222 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
@@ -34,18 +34,17 @@ import {
import {
DefaultForm,
ErrorLoading,
- FlexibleForm,
InternationalizationAPI,
Loading,
- useTranslationContext,
+ useTranslationContext
} from "@gnu-taler/web-util/browser";
import { format } from "date-fns";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { privatePages } from "../Routing.js";
+import { FormMetadata, useUiFormsContext } from "../context/ui-forms.js";
import { useCaseDetails } from "../hooks/useCaseDetails.js";
import { ShowConsolidated } from "./ShowConsolidated.js";
-import { FormMetadata, useUiFormsContext } from "../context/ui-forms.js";
export type AmlEvent =
| AmlFormEvent
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
index 64bfb90f1..f04d404d0 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
@@ -20,12 +20,14 @@ import {
HttpStatusCode,
TalerExchangeApi,
TalerProtocolTimestamp,
- assertUnreachable,
+ assertUnreachable
} from "@gnu-taler/taler-util";
import {
Button,
+ InternationalizationAPI,
LocalNotificationBanner,
RenderAllFieldsByUiConfig,
+ UIFieldHandler,
UIFormField,
useExchangeApiContext,
useLocalNotificationHandler,
@@ -33,12 +35,40 @@ import {
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { privatePages } from "../Routing.js";
-import { UIFormFieldConfig, useUiFormsContext } from "../context/ui-forms.js";
-import { useFormState } from "../hooks/form.js";
+import {
+ FormMetadata,
+ UIFormFieldConfig,
+ useUiFormsContext,
+} from "../context/ui-forms.js";
+import { preloadedForms } from "../forms/index.js";
+import { FormHandler, useFormState } from "../hooks/form.js";
import { useOfficer } from "../hooks/officer.js";
import { Justification } from "./CaseDetails.js";
import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
+function searchForm(
+ i18n: InternationalizationAPI,
+ forms: FormMetadata[],
+ formId: string,
+): FormMetadata | undefined {
+ {
+ const found = forms.find((v) => v.id === formId);
+ if (found) return found;
+ }
+ {
+ const pf = preloadedForms(i18n);
+ const found = pf.find((v) => v.id === formId);
+ if (found) return found;
+ }
+ return undefined;
+}
+
+type FormType = {
+ when: AbsoluteTime;
+ state: TalerExchangeApi.AmlState;
+ threshold: AmountJson;
+};
+
export function CaseUpdate({
account,
type: formId,
@@ -52,11 +82,10 @@ export function CaseUpdate({
lib: { exchange: api },
} = useExchangeApiContext();
- // const [notification, notify, handleError] = useLocalNotification();
const [notification, withErrorHandler] = useLocalNotificationHandler();
const { config } = useExchangeApiContext();
const { forms } = useUiFormsContext();
- const initial = {
+ const initial: FormType = {
when: AbsoluteTime.now(),
state: TalerExchangeApi.AmlState.pending,
threshold: Amounts.zeroOfCurrency(config.currency),
@@ -65,19 +94,31 @@ export function CaseUpdate({
if (officer.state !== "ready") {
return <HandleAccountNotReady officer={officer} />;
}
- const theForm = forms.find((v) => v.id === formId);
+ const theForm = searchForm(i18n, forms, formId);
if (!theForm) {
return <div>form with id {formId} not found</div>;
}
- const [form, state] = useFormState(initial, (st) => {
+ let defaultValue = initial
+ theForm.config.design.forEach((section) => {
+ section.fields.forEach((field) => {
+ if ("id" in field.properties) {
+ const path = field.properties.id.split(".");
+ defaultValue = setValueDeeper(defaultValue, path, undefined);
+ }
+ });
+ });
+
+
+ const [form, state] = useFormState<FormType>(defaultValue, (st) => {
return {
status: "ok",
result: st as any,
errors: undefined,
};
});
-
+
+ console.log("FORM", form)
const validatedForm = state.status === "fail" ? undefined : state.result;
const submitHandler =
@@ -125,8 +166,73 @@ export function CaseUpdate({
},
);
- function convertUiField(_f: UIFormFieldConfig[]): UIFormField[] {
- return [];
+ function convertUiField(
+ fieldConfig: UIFormFieldConfig[],
+ form: FormHandler<unknown>,
+ ): UIFormField[] {
+ return fieldConfig.map((config) => {
+ switch (config.type) {
+ case "absoluteTime": {
+ return undefined!;
+ }
+ case "amount": {
+ return {
+ type: "amount",
+ properties: {
+ ...(config.properties as any),
+ handler: getValueDeeper(form, config.properties.id.split(".")),
+ },
+ } as UIFormField;
+ }
+ case "array": {
+ return undefined!;
+ }
+ case "caption": {
+ return undefined!;
+ }
+ case "choiceHorizontal": {
+ return {
+ type: "choiceHorizontal",
+ properties: {
+ handler: getValueDeeper(form, config.properties.id.split(".")),
+ choices: config.properties.choices,
+ },
+ } as UIFormField;
+ }
+ case "choiceStacked":
+ case "file":
+ case "group":
+ case "integer":
+ case "selectMultiple":
+ case "selectOne": {
+ return undefined!;
+ }
+ case "text": {
+ return {
+ type: "text",
+ properties: {
+ ...(config.properties as any),
+ handler: getValueDeeper(form, config.properties.id.split(".")),
+ },
+ } as UIFormField;
+ }
+ case "textArea": {
+ return {
+ type: "text",
+ properties: {
+ ...(config.properties as any),
+ handler: getValueDeeper(form, config.properties.id.split(".")),
+ },
+ } as UIFormField;
+ }
+ case "toggle": {
+ return undefined!;
+ }
+ default: {
+ assertUnreachable(config);
+ }
+ }
+ });
}
return (
@@ -155,7 +261,7 @@ export function CaseUpdate({
<div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<RenderAllFieldsByUiConfig
key={i}
- fields={convertUiField(section.fields)}
+ fields={convertUiField(section.fields, form)}
/>
</div>
</div>
@@ -185,7 +291,10 @@ export function CaseUpdate({
}
export function SelectForm({ account }: { account: string }) {
+ const { i18n } = useTranslationContext();
const { forms } = useUiFormsContext();
+ const pf = preloadedForms(i18n);
+
return (
<div>
<pre>New form for account: {account.substring(0, 16)}...</pre>
@@ -200,6 +309,44 @@ export function SelectForm({ account }: { account: string }) {
</a>
);
})}
+ {pf.map((form) => {
+ return (
+ <a
+ key={form.id}
+ href={privatePages.caseUpdate.url({ cid: 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"
+ >
+ {form.label}
+ </a>
+ );
+ })}
</div>
);
}
+
+function getValueDeeper(
+ object: Record<string, any>,
+ names: string[],
+): UIFieldHandler {
+ if (names.length === 0) return object as UIFieldHandler;
+ const [head, ...rest] = names;
+ if (!head) {
+ return getValueDeeper(object, rest);
+ }
+ if (object === undefined) {
+ throw Error("handler not found");
+ }
+ return getValueDeeper(object[head], rest);
+}
+
+function setValueDeeper(object: any, names: string[], value: any): any {
+ if (names.length === 0) return value;
+ const [head, ...rest] = names;
+ if (!head) {
+ return setValueDeeper(object, rest, value);
+ }
+ if (object === undefined) {
+ return { [head]: setValueDeeper({}, rest, value) };
+ }
+ return { ...object, [head]: setValueDeeper(object[head] ?? {}, rest, value) };
+}