summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-04-30 14:21:01 -0300
committerSebastian <sebasjm@gmail.com>2024-04-30 14:21:15 -0300
commit20d2861508df18da18e66c94a5a268067565121b (patch)
tree24421fb8c797d50d5ad6bc7c6ff6460f469b5e11 /packages
parent84adb1e78e49057cdcee15c71ad788f56bb0fff9 (diff)
downloadwallet-core-20d2861508df18da18e66c94a5a268067565121b.tar.gz
wallet-core-20d2861508df18da18e66c94a5a268067565121b.tar.bz2
wallet-core-20d2861508df18da18e66c94a5a268067565121b.zip
testing aml form as json
Diffstat (limited to 'packages')
-rw-r--r--packages/aml-backoffice-ui/src/App.tsx10
-rw-r--r--packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx4
-rw-r--r--packages/aml-backoffice-ui/src/context/settings.ts44
-rw-r--r--packages/aml-backoffice-ui/src/context/ui-forms.ts507
-rw-r--r--packages/aml-backoffice-ui/src/context/ui-settings.ts (renamed from packages/aml-backoffice-ui/src/settings.ts)58
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_11e.ts22
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_12e.ts130
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_13e.ts162
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_15e.ts44
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_1e.ts343
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_4e.ts116
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_5e.ts70
-rw-r--r--packages/aml-backoffice-ui/src/forms/902_9e.ts30
-rw-r--r--packages/aml-backoffice-ui/src/forms/declaration.ts73
-rw-r--r--packages/aml-backoffice-ui/src/forms/index.ts95
-rw-r--r--packages/aml-backoffice-ui/src/forms/simplest.ts70
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseDetails.tsx31
-rw-r--r--packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx39
-rw-r--r--packages/aml-backoffice-ui/src/pages/CreateAccount.tsx1
-rw-r--r--packages/aml-backoffice-ui/src/pages/Officer.tsx4
-rw-r--r--packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx168
-rw-r--r--packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx6
-rw-r--r--packages/web-util/src/forms/Calendar.tsx253
-rw-r--r--packages/web-util/src/forms/InputAbsoluteTime.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputAbsoluteTime.tsx10
-rw-r--r--packages/web-util/src/forms/InputAmount.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputArray.stories.tsx6
-rw-r--r--packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputChoiceStacked.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputFile.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputInteger.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputLine.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputSelectMultiple.stories.tsx4
-rw-r--r--packages/web-util/src/forms/InputSelectMultiple.tsx2
-rw-r--r--packages/web-util/src/forms/InputSelectOne.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputText.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputTextArea.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputToggle.stories.tsx2
-rw-r--r--packages/web-util/src/forms/InputToggle.tsx2
-rw-r--r--packages/web-util/src/forms/forms.ts46
40 files changed, 1424 insertions, 948 deletions
diff --git a/packages/aml-backoffice-ui/src/App.tsx b/packages/aml-backoffice-ui/src/App.tsx
index d55de776b..9ccf21755 100644
--- a/packages/aml-backoffice-ui/src/App.tsx
+++ b/packages/aml-backoffice-ui/src/App.tsx
@@ -25,23 +25,23 @@ import { useEffect, useState } from "preact/hooks";
import { SWRConfig } from "swr";
import { ExchangeAmlFrame } from "./ExchangeAmlFrame.js";
import { Routing } from "./Routing.js";
-import { SettingsProvider } from "./context/settings.js";
+import { UiSettingsProvider } from "./context/ui-settings.js";
import { strings } from "./i18n/strings.js";
import "./scss/main.css";
-import { UiSettings, fetchSettings } from "./settings.js";
+import { UiSettings, fetchUiSettings } from "./context/ui-settings.js";
const WITH_LOCAL_STORAGE_CACHE = false;
export function App(): VNode {
const [settings, setSettings] = useState<UiSettings>();
useEffect(() => {
- fetchSettings(setSettings);
+ fetchUiSettings(setSettings);
}, []);
if (!settings) return <Loading />;
const baseUrl = getInitialBackendBaseURL(settings.backendBaseURL);
return (
- <SettingsProvider value={settings}>
+ <UiSettingsProvider value={settings}>
<TranslationProvider
source={strings}
completeness={{
@@ -86,7 +86,7 @@ export function App(): VNode {
</SWRConfig>
</ExchangeApiProvider>
</TranslationProvider>
- </SettingsProvider>
+ </UiSettingsProvider>
);
}
diff --git a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
index 66eb3df36..772fd1b70 100644
--- a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
+++ b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx
@@ -26,7 +26,7 @@ import {
import { ComponentChildren, VNode, h } from "preact";
import { useEffect, useErrorBoundary } from "preact/hooks";
import { privatePages } from "./Routing.js";
-import { useSettingsContext } from "./context/settings.js";
+import { useUiSettingsContext } from "./context/ui-settings.js";
import { OfficerState } from "./hooks/officer.js";
import {
getAllBooleanPreferences,
@@ -133,7 +133,7 @@ export function ExchangeAmlFrame({
}, [error]);
const [preferences, updatePreferences] = usePreferences();
- const settings = useSettingsContext()
+ const settings = useUiSettingsContext()
return (
<div
diff --git a/packages/aml-backoffice-ui/src/context/settings.ts b/packages/aml-backoffice-ui/src/context/settings.ts
deleted file mode 100644
index 6c61a7b4a..000000000
--- a/packages/aml-backoffice-ui/src/context/settings.ts
+++ /dev/null
@@ -1,44 +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/>
- */
-
-import { ComponentChildren, createContext, h, VNode } from "preact";
-import { useContext } from "preact/hooks";
-import { UiSettings } from "../settings.js";
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-export type Type = UiSettings;
-
-const initial: UiSettings = {};
-const Context = createContext<Type>(initial);
-
-export const useSettingsContext = (): Type => useContext(Context);
-
-export const SettingsProvider = ({
- children,
- value,
-}: {
- value: UiSettings;
- children: ComponentChildren;
-}): VNode => {
- return h(Context.Provider, {
- value,
- children,
- });
-};
diff --git a/packages/aml-backoffice-ui/src/context/ui-forms.ts b/packages/aml-backoffice-ui/src/context/ui-forms.ts
new file mode 100644
index 000000000..2e0b8a76d
--- /dev/null
+++ b/packages/aml-backoffice-ui/src/context/ui-forms.ts
@@ -0,0 +1,507 @@
+/*
+ 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/>
+ */
+
+import {
+ buildCodecForObject,
+ buildCodecForUnion,
+ Codec,
+ codecForBoolean,
+ codecForConstString,
+ codecForList,
+ codecForNumber,
+ codecForString,
+ codecForTimestamp,
+ codecOptional,
+ Integer,
+ TalerProtocolTimestamp,
+} from "@gnu-taler/taler-util";
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { useContext } from "preact/hooks";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export type Type = UiForms;
+
+const defaultForms: UiForms = {
+ forms: []
+};
+const Context = createContext<Type>(defaultForms);
+
+export type BaseForm = Record<string, unknown>;
+
+export const useUiFormsContext = (): Type => useContext(Context);
+
+export const UiFormsProvider = ({
+ children,
+ value,
+}: {
+ value: UiForms;
+ children: ComponentChildren;
+}): VNode => {
+ return h(Context.Provider, {
+ value,
+ children,
+ });
+};
+
+export type FormMetadata = {
+ label: string;
+ id: string;
+ version: number;
+ config: FlexibleForm;
+};
+
+type FlexibleForm = DoubleColumnForm;
+
+export interface DoubleColumnForm {
+ type: "double-column";
+ design: Array<DoubleColumnFormSection>;
+ // behavior?: (form: Partial<T>) => FormState<T>;
+}
+
+export type DoubleColumnFormSection = {
+ title: string;
+ description?: string;
+ fields: UIFormFieldConfig[];
+};
+
+// export interface BaseForm {
+// state: TalerExchangeApi.AmlState;
+// threshold: AmountJson;
+// }
+
+export interface UiForms {
+ // Where libeufin backend is localted
+ // default: window.origin without "webui/"
+ forms: Array<FormMetadata>;
+}
+
+export type UIFormFieldConfig =
+ | UIFormFieldConfigAbsoluteTime
+ | UIFormFieldConfigAmount
+ | UIFormFieldConfigArray
+ | UIFormFieldConfigCaption
+ | UIFormFieldConfigChoiseHorizontal
+ | UIFormFieldConfigChoiseStacked
+ | UIFormFieldConfigFile
+ | UIFormFieldConfigGroup
+ | UIFormFieldConfigInteger
+ | UIFormFieldConfigSelectMultiple
+ | UIFormFieldConfigSelectOne
+ | UIFormFieldConfigText
+ | UIFormFieldConfigTextArea
+ | UIFormFieldConfigToggle;
+
+type UIFormFieldConfigAbsoluteTime = {
+ type: "absoluteTime";
+ properties: UIFormFieldBaseConfig & {
+ max?: TalerProtocolTimestamp;
+ min?: TalerProtocolTimestamp;
+ pattern: string;
+ };
+};
+
+type UIFormFieldConfigAmount = {
+ type: "amount";
+ properties: UIFormFieldBaseConfig & {
+ max?: Integer;
+ min?: Integer;
+ currency: string;
+ };
+};
+
+type UIFormFieldConfigArray = {
+ type: "array";
+ properties: UIFormFieldBaseConfig & {
+ // id of the field shown when the array is collapsed
+ labelFieldId: UIHandlerId;
+ fields: UIFormFieldConfig[];
+ };
+};
+
+type UIFormFieldConfigCaption = {
+ type: "caption";
+ properties: UIFieldBaseDescription;
+};
+
+type UIFormFieldConfigGroup = {
+ type: "group";
+ properties: UIFormFieldBaseConfig & {
+ fields: UIFormFieldConfig[];
+ };
+};
+
+type UIFormFieldConfigChoiseHorizontal = {
+ type: "choiceHorizontal";
+ properties: UIFormFieldBaseConfig & {
+ choices: Array<SelectUiChoice>;
+ };
+};
+
+type UIFormFieldConfigChoiseStacked = {
+ type: "choiceStacked";
+ properties: UIFormFieldBaseConfig & {
+ choices: Array<SelectUiChoice>;
+ };
+};
+
+type UIFormFieldConfigFile = {
+ type: "file";
+ properties: UIFormFieldBaseConfig & {
+ maxBytes?: Integer;
+ minBytes?: Integer;
+ // comma-separated list of one or more file types
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept#unique_file_type_specifiers
+ accept?: string;
+ };
+};
+type UIFormFieldConfigInteger = {
+ type: "integer";
+ properties: UIFormFieldBaseConfig & {
+ max?: Integer;
+ min?: Integer;
+ };
+};
+
+interface SelectUiChoice {
+ label: string;
+ description?: string;
+ value: string;
+}
+
+type UIFormFieldConfigSelectMultiple = {
+ type: "selectMultiple";
+ properties: UIFormFieldBaseConfig & {
+ max?: Integer;
+ min?: Integer;
+ unique?: boolean;
+ choices: Array<SelectUiChoice>;
+ };
+};
+type UIFormFieldConfigSelectOne = {
+ type: "selectOne";
+ properties: UIFormFieldBaseConfig & {
+ choices: Array<SelectUiChoice>;
+ };
+};
+type UIFormFieldConfigText = {
+ type: "text";
+ properties: UIFormFieldBaseConfig;
+};
+type UIFormFieldConfigTextArea = {
+ type: "textArea";
+ properties: UIFormFieldBaseConfig;
+};
+type UIFormFieldConfigToggle = {
+ type: "toggle";
+ properties: UIFormFieldBaseConfig;
+};
+
+type UIFieldBaseDescription = {
+ /* label if the field, visible for the user */
+ label: string;
+ /* long text to be shown on user demand */
+ tooltip?: string;
+
+ /* short text to be shown close to the field */
+ help?: string;
+
+ /* if the field should be initialy hidden */
+ hidden?: boolean;
+ /* ui element to show before */
+ addonBeforeId?: string;
+ /* ui element to show after */
+ addonAfterId?: string;
+};
+
+type UIFormFieldBaseConfig = UIFieldBaseDescription & {
+ /* example to be shown inside the field */
+ placeholder?: string;
+
+ /* show a mark as required */
+ required?: boolean;
+
+ /* readonly and dim */
+ disabled?: boolean;
+
+ /* name of the field, useful for a11y */
+ name: string;
+
+ /* conversion id to conver the string into the value type
+ the id should be known to the ui impl
+ */
+ converterId?: string;
+
+ /* property id of the form */
+ id: UIHandlerId;
+};
+
+declare const __handlerId: unique symbol;
+export type UIHandlerId = string & { [__handlerId]: true };
+
+// FIXME: validate well formed ui field id
+const codecForUiFieldId = codecForString as () => Codec<UIHandlerId>;
+
+const codecForUIFormFieldBaseConfigTemplate = <
+ T extends UIFormFieldBaseConfig,
+>() =>
+ buildCodecForObject<T>()
+ .property("id", codecForUiFieldId())
+ .property("addonAfterId", codecOptional(codecForString()))
+ .property("addonBeforeId", codecOptional(codecForString()))
+ .property("converterId", codecOptional(codecForString()))
+ .property("disabled", codecOptional(codecForBoolean()))
+ .property("hidden", codecOptional(codecForBoolean()))
+ .property("required", codecOptional(codecForBoolean()))
+ .property("help", codecOptional(codecForString()))
+ .property("label", codecForString())
+ .property("name", codecForString())
+ .property("placeholder", codecOptional(codecForString()))
+ .property("tooltip", codecOptional(codecForString()));
+
+const codecForUIFormFieldBaseConfig = (): Codec<UIFormFieldBaseConfig> =>
+ codecForUIFormFieldBaseConfigTemplate().build("UIFieldToggleProperties");
+
+const codecForUIFormFieldAbsoluteTimeConfig = (): Codec<
+ UIFormFieldConfigAbsoluteTime["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<
+ UIFormFieldConfigAbsoluteTime["properties"]
+ >()
+ .property("pattern", codecForString())
+ .property("max", codecOptional(codecForTimestamp))
+ .property("min", codecOptional(codecForTimestamp))
+ .build("UIFormFieldConfigAbsoluteTime.properties");
+
+const codecForUiFormFieldAbsoluteTime =
+ (): Codec<UIFormFieldConfigAbsoluteTime> =>
+ buildCodecForObject<UIFormFieldConfigAbsoluteTime>()
+ .property("type", codecForConstString("absoluteTime"))
+ .property("properties", codecForUIFormFieldAbsoluteTimeConfig())
+ .build("UIFormFieldConfigAbsoluteTime");
+
+const codecForUIFormFieldAmountConfig = (): Codec<
+ UIFormFieldConfigAmount["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigAmount["properties"]>()
+ .property("currency", codecForString())
+ .property("max", codecOptional(codecForNumber()))
+ .property("min", codecOptional(codecForNumber()))
+ .build("UIFormFieldConfigAmount.properties");
+
+const codecForUiFormFieldAmount = (): Codec<UIFormFieldConfigAmount> =>
+ buildCodecForObject<UIFormFieldConfigAmount>()
+ .property("type", codecForConstString("amount"))
+ .property("properties", codecForUIFormFieldAmountConfig())
+ .build("UIFormFieldConfigAmount");
+
+const codecForUIFormFieldArrayConfig = (): Codec<
+ UIFormFieldConfigArray["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigArray["properties"]>()
+ .property("labelFieldId", codecForUiFieldId())
+ .property("fields", codecForList(codecForUiFormField()))
+ .build("UIFormFieldConfigArray.properties");
+
+const codecForUiFormFieldArray = (): Codec<UIFormFieldConfigArray> =>
+ buildCodecForObject<UIFormFieldConfigArray>()
+ .property("type", codecForConstString("array"))
+ .property("properties", codecForUIFormFieldArrayConfig())
+ .build("UIFormFieldConfigArray");
+
+const codecForUiFormFieldCaption = (): Codec<UIFormFieldConfigCaption> =>
+ buildCodecForObject<UIFormFieldConfigCaption>()
+ .property("type", codecForConstString("caption"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigCaption");
+
+const codecForUiFormSelectUiChoice = (): Codec<SelectUiChoice> =>
+ buildCodecForObject<SelectUiChoice>()
+ .property("description", codecForString())
+ .property("label", codecForString())
+ .property("value", codecForString())
+ .build("SelectUiChoice");
+
+const codecForUIFormFieldWithChoiseConfig = (): Codec<
+ UIFormFieldConfigChoiseHorizontal["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<
+ UIFormFieldConfigChoiseHorizontal["properties"]
+ >()
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
+ .build("UIFormFieldConfigChoiseHorizontal.properties");
+
+const codecForUiFormFieldChoiceHorizontal =
+ (): Codec<UIFormFieldConfigChoiseHorizontal> =>
+ buildCodecForObject<UIFormFieldConfigChoiseHorizontal>()
+ .property("type", codecForConstString("choiceHorizontal"))
+ .property("properties", codecForUIFormFieldWithChoiseConfig())
+ .build("UIFormFieldConfigChoiseHorizontal");
+
+const codecForUiFormFieldChoiceStacked =
+ (): Codec<UIFormFieldConfigChoiseStacked> =>
+ buildCodecForObject<UIFormFieldConfigChoiseStacked>()
+ .property("type", codecForConstString("choiceStacked"))
+ .property("properties", codecForUIFormFieldWithChoiseConfig())
+ .build("UIFormFieldConfigChoiseStacked");
+
+const codecForUiFormFieldFile = (): Codec<UIFormFieldConfigFile> =>
+ buildCodecForObject<UIFormFieldConfigFile>()
+ .property("type", codecForConstString("file"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigFile");
+
+const codecForUIFormFieldWithFieldsConfig = (): Codec<
+ UIFormFieldConfigGroup["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<UIFormFieldConfigGroup["properties"]>()
+ .property("fields", codecForList(codecForUiFormField()))
+ .build("UIFormFieldConfigGroup.properties");
+
+const codecForUiFormFieldGroup = (): Codec<UIFormFieldConfigGroup> =>
+ buildCodecForObject<UIFormFieldConfigGroup>()
+ .property("type", codecForConstString("group"))
+ .property("properties", codecForUIFormFieldWithFieldsConfig())
+ .build("UiFormFieldGroup");
+
+const codecForUiFormFieldInteger = (): Codec<UIFormFieldConfigInteger> =>
+ buildCodecForObject<UIFormFieldConfigInteger>()
+ .property("type", codecForConstString("integer"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigInteger");
+
+const codecForUIFormFieldSelectMultipleConfig = (): Codec<
+ UIFormFieldConfigSelectMultiple["properties"]
+> =>
+ codecForUIFormFieldBaseConfigTemplate<
+ UIFormFieldConfigSelectMultiple["properties"]
+ >()
+ .property("max", codecOptional(codecForNumber()))
+ .property("min", codecOptional(codecForNumber()))
+ .property("unique", codecOptional(codecForBoolean()))
+ .property("choices", codecForList(codecForUiFormSelectUiChoice()))
+ .build("UIFormFieldConfigSelectMultiple.properties");
+
+const codecForUiFormFieldSelectMultiple =
+ (): Codec<UIFormFieldConfigSelectMultiple> =>
+ buildCodecForObject<UIFormFieldConfigSelectMultiple>()
+ .property("type", codecForConstString("selectMultiple"))
+ .property("properties", codecForUIFormFieldSelectMultipleConfig())
+ .build("UiFormFieldSelectMultiple");
+
+const codecForUiFormFieldSelectOne = (): Codec<UIFormFieldConfigSelectOne> =>
+ buildCodecForObject<UIFormFieldConfigSelectOne>()
+ .property("type", codecForConstString("selectOne"))
+ .property("properties", codecForUIFormFieldWithChoiseConfig())
+ .build("UIFormFieldConfigSelectOne");
+
+const codecForUiFormFieldText = (): Codec<UIFormFieldConfigText> =>
+ buildCodecForObject<UIFormFieldConfigText>()
+ .property("type", codecForConstString("text"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigText");
+
+const codecForUiFormFieldTextArea = (): Codec<UIFormFieldConfigTextArea> =>
+ buildCodecForObject<UIFormFieldConfigTextArea>()
+ .property("type", codecForConstString("textArea"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigTextArea");
+
+const codecForUiFormFieldToggle = (): Codec<UIFormFieldConfigToggle> =>
+ buildCodecForObject<UIFormFieldConfigToggle>()
+ .property("type", codecForConstString("toggle"))
+ .property("properties", codecForUIFormFieldBaseConfig())
+ .build("UIFormFieldConfigToggle");
+
+const codecForUiFormField = (): Codec<UIFormFieldConfig> =>
+ buildCodecForUnion<UIFormFieldConfig>()
+ .discriminateOn("type")
+ .alternative("absoluteTime", codecForUiFormFieldAbsoluteTime())
+ .alternative("amount", codecForUiFormFieldAmount())
+ .alternative("array", codecForUiFormFieldArray())
+ .alternative("caption", codecForUiFormFieldCaption())
+ .alternative("choiceHorizontal", codecForUiFormFieldChoiceHorizontal())
+ .alternative("choiceStacked", codecForUiFormFieldChoiceStacked())
+ .alternative("file", codecForUiFormFieldFile())
+ .alternative("group", codecForUiFormFieldGroup())
+ .alternative("integer", codecForUiFormFieldInteger())
+ .alternative("selectMultiple", codecForUiFormFieldSelectMultiple())
+ .alternative("selectOne", codecForUiFormFieldSelectOne())
+ .alternative("text", codecForUiFormFieldText())
+ .alternative("textArea", codecForUiFormFieldTextArea())
+ .alternative("toggle", codecForUiFormFieldToggle())
+ .build("UIFormField");
+
+const codecForDoubleColumnFormSection = (): Codec<DoubleColumnFormSection> =>
+ buildCodecForObject<DoubleColumnFormSection>()
+ .property("title", codecForString())
+ .property("description", codecForString())
+ .property("fields", codecForList(codecForUiFormField()))
+ .build("DoubleColumnFormSection");
+
+const codecForDoubleColumnForm = (): Codec<DoubleColumnForm> =>
+ buildCodecForObject<DoubleColumnForm>()
+ .property("type", codecForConstString("double-column"))
+ .property("design", codecForList(codecForDoubleColumnFormSection()))
+ .build("DoubleColumnForm");
+
+const codecForFlexibleForm = (): Codec<FlexibleForm> =>
+ buildCodecForUnion<FlexibleForm>()
+ .discriminateOn("type")
+ .alternative("double-column", codecForDoubleColumnForm())
+ .build<FlexibleForm>("FlexibleForm");
+
+const codecForFormMetadata = (): Codec<FormMetadata> =>
+ buildCodecForObject<FormMetadata>()
+ .property("label", codecForString())
+ .property("id", codecForString())
+ .property("version", codecForNumber())
+ .property("config", codecForFlexibleForm())
+ .build("FormMetadata");
+
+const codecForUIForms = (): Codec<UiForms> =>
+ buildCodecForObject<UiForms>()
+ .property("forms", codecForList(codecForFormMetadata()))
+ .build("UiForms");
+
+function removeUndefineField<T extends object>(obj: T): T {
+ const keys = Object.keys(obj) as Array<keyof T>;
+ return keys.reduce((prev, cur) => {
+ if (typeof prev[cur] === "undefined") {
+ delete prev[cur];
+ }
+ return prev;
+ }, obj);
+}
+
+export function fetchUiForms(listener: (s: UiForms) => void): void {
+ fetch("./forms.json")
+ .then((resp) => resp.json())
+ .then((json) => codecForUIForms().decode(json))
+ .then((result) =>
+ listener({
+ ...defaultForms,
+ ...removeUndefineField(result),
+ }),
+ )
+ .catch((e) => {
+ console.log("failed to fetch forms", e);
+ listener(defaultForms);
+ });
+}
diff --git a/packages/aml-backoffice-ui/src/settings.ts b/packages/aml-backoffice-ui/src/context/ui-settings.ts
index a4a693d7d..aa318a918 100644
--- a/packages/aml-backoffice-ui/src/settings.ts
+++ b/packages/aml-backoffice-ui/src/context/ui-settings.ts
@@ -14,13 +14,41 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
- import {
- Codec,
- buildCodecForObject,
- canonicalizeBaseUrl,
- codecForString,
- codecOptional
-} from "@gnu-taler/taler-util";
+import { buildCodecForObject, canonicalizeBaseUrl, Codec, codecForString, codecOptional } from "@gnu-taler/taler-util";
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { useContext } from "preact/hooks";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export type Type = UiSettings;
+
+/**
+ * Global settings for the UI.
+ */
+const defaultSettings: UiSettings = {
+ backendBaseURL: buildDefaultBackendBaseURL(),
+ signupEmail: undefined,
+};
+
+const Context = createContext<Type>(defaultSettings);
+
+export const useUiSettingsContext = (): Type => useContext(Context);
+
+export const UiSettingsProvider = ({
+ children,
+ value,
+}: {
+ value: UiSettings;
+ children: ComponentChildren;
+}): VNode => {
+ return h(Context.Provider, {
+ value,
+ children,
+ });
+};
export interface UiSettings {
// Where libeufin backend is localted
@@ -32,15 +60,7 @@ export interface UiSettings {
signupEmail?: string;
}
-/**
- * Global settings for the bank UI.
- */
-const defaultSettings: UiSettings = {
- backendBaseURL: buildDefaultBackendBaseURL(),
- signupEmail: undefined,
-};
-
-const codecForBankUISettings = (): Codec<UiSettings> =>
+const codecForUISettings = (): Codec<UiSettings> =>
buildCodecForObject<UiSettings>()
.property("backendBaseURL", codecOptional(codecForString()))
.property("signupEmail", codecOptional(codecForString()))
@@ -56,10 +76,10 @@ function removeUndefineField<T extends object>(obj: T): T {
}, obj);
}
-export function fetchSettings(listener: (s: UiSettings) => void): void {
+export function fetchUiSettings(listener: (s: UiSettings) => void): void {
fetch("./settings.json")
.then((resp) => resp.json())
- .then((json) => codecForBankUISettings().decode(json))
+ .then((json) => codecForUISettings().decode(json))
.then((result) =>
listener({
...defaultSettings,
@@ -79,7 +99,7 @@ function buildDefaultBackendBaseURL(): string | undefined {
window.location.origin,
).href;
/**
- * By default, bank backend serves the html content
+ * By default, backend serves the html content
* from the /webui root.
*/
return canonicalizeBaseUrl(currentLocation.replace("/webui", ""));
diff --git a/packages/aml-backoffice-ui/src/forms/902_11e.ts b/packages/aml-backoffice-ui/src/forms/902_11e.ts
index ee4323f77..7cf710741 100644
--- a/packages/aml-backoffice-ui/src/forms/902_11e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_11e.ts
@@ -13,11 +13,11 @@
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 type { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_11.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title:
@@ -27,14 +27,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "contractingPartner",
label: i18n.str`Contracting partner`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "declares",
label:
i18n.str`The contracting partner hereby declares that`,
@@ -60,7 +60,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
name: "people",
label: i18n.str`People`,
required: true,
@@ -68,7 +68,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "lastName",
label: i18n.str`Last name(s)`,
required: true,
@@ -76,7 +76,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "firstName",
label: i18n.str`First name(s)`,
required: true,
@@ -84,7 +84,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label: i18n.str`Actual address of domicile`,
required: true,
@@ -96,7 +96,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "fiduciaryAssets",
label: i18n.str`Fiduciary holding assets`,
help: i18n.str`Is a third person the beneficial owner of the assets held in the account/securities account?`,
@@ -117,7 +117,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
behavior: function formBehavior(
v: Partial<Form902_11.Form>,
diff --git a/packages/aml-backoffice-ui/src/forms/902_12e.ts b/packages/aml-backoffice-ui/src/forms/902_12e.ts
index 0c14f6ee7..5aa3f4cf9 100644
--- a/packages/aml-backoffice-ui/src/forms/902_12e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_12e.ts
@@ -14,25 +14,25 @@
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";
+import type { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_12.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title: i18n.str`Foundations`,
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "contractingPartner",
label: i18n.str`Contracting partner`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "knownAs",
label:
i18n.str`The undersigned hereby declare(s) that as board member of the foundation, or of the highest supervisory body of an underlying company of a foundation, known as`,
@@ -40,7 +40,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "foundation.name",
label:
i18n.str`Name and information pertaining to the foundation`,
@@ -48,7 +48,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "foundation.type",
label: i18n.str`Type of foundation`,
choices: [
@@ -65,7 +65,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "foundation.revocability",
label: i18n.str`Revocability`,
choices: [
@@ -82,7 +82,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to the (ultimate economic, not fiduciary) founder (individual(s) or entity/ies)`,
labelField: "fullName",
@@ -90,7 +90,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -98,7 +98,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -106,28 +106,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfDeath",
label: i18n.str`Date of death`,
help: i18n.str`if deceased`,
@@ -135,7 +135,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToRevoke",
required: true,
label:
@@ -157,7 +157,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`If the foundation results from the restructuring of pre-existing foundation (re-settlement) or the merger of pre-existing foundations, the following information pertaining to the (actual) founder(s) of the pre-existing foundation(s) has to be given`,
labelField: "fullName",
@@ -165,7 +165,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -173,7 +173,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -181,28 +181,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfDeath",
label: i18n.str`Date of death`,
help: i18n.str`if deceased`,
@@ -213,7 +213,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Pertaining to the beneficiary/-ies at the time of the signing of this form`,
labelField: "fullName",
@@ -221,7 +221,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -229,7 +229,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -237,28 +237,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToClaim",
label:
i18n.str`Has the beneficiary an actual right to claim distribution?`,
@@ -276,7 +276,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`in addition to certain beneficiaries or if there is/are no defined beneficiary/ies pertaining to (a) group(s) of beneficiaries (e.g. descendants of the founder) known at the time of the signing of this form`,
name: "beneficiaryExtra",
@@ -287,7 +287,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to further persons having the right to determine or nominate representatives (e.g.) members of the foundation board), if these representatives may dispose over the assets or have the right to change the distribution of the assets or the nomination of beneficiaries`,
labelField: "fullName",
@@ -295,7 +295,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -303,7 +303,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -311,28 +311,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToClaim",
label:
i18n.str`has the person the right to revoke the foundation?`,
@@ -350,7 +350,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`in addition to certain beneficiaries or if there is/are no defined beneficiary/ies pertaining to (a) group(s) of beneficiaries (e.g. descendants of the founder) known at the time of the signing of this form`,
name: "beneficiaryExtra",
@@ -361,39 +361,39 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "signature",
label: i18n.str`Signature`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
- behavior: function formBehavior(
- v: Partial<Form902_12.Form>,
- ): FormState<Form902_12.Form> {
- return {
- founders: {
- elements: (v.founders ?? []).map(() => {
- return {
- rightToRevoke: {
- hidden: v.foundation?.revocability !== "revocable",
- },
- };
- }),
- },
- withRightToNominate: {
- elements: (v.withRightToNominate ?? []).map(() => {
- return {
- rightToRevoke: {
- hidden: v.foundation?.revocability !== "revocable",
- },
- };
- }),
- },
- };
- },
+ // behavior: function formBehavior(
+ // v: Partial<Form902_12.Form>,
+ // ): FormState<Form902_12.Form> {
+ // return {
+ // founders: {
+ // elements: (v.founders ?? []).map(() => {
+ // return {
+ // rightToRevoke: {
+ // hidden: v.foundation?.revocability !== "revocable",
+ // },
+ // };
+ // }),
+ // },
+ // withRightToNominate: {
+ // elements: (v.withRightToNominate ?? []).map(() => {
+ // return {
+ // rightToRevoke: {
+ // hidden: v.foundation?.revocability !== "revocable",
+ // },
+ // };
+ // }),
+ // },
+ // };
+ // },
});
namespace Form902_12 {
diff --git a/packages/aml-backoffice-ui/src/forms/902_13e.ts b/packages/aml-backoffice-ui/src/forms/902_13e.ts
index a4851002e..d71266489 100644
--- a/packages/aml-backoffice-ui/src/forms/902_13e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_13e.ts
@@ -14,25 +14,25 @@
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";
+import type { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_13.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title: i18n.str`Declaration for trusts`,
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "contractingPartner",
label: i18n.str`Contracting partner`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "knownAs",
label:
i18n.str`The undersigned hereby declare(s) that as trustee or a member of highest supervisory body of an underlying company of a trust known as`,
@@ -40,7 +40,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "trust.name",
label:
i18n.str`Name and information pertaining to the trust`,
@@ -48,7 +48,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "trust.type",
label: i18n.str`Type of trust`,
choices: [
@@ -65,7 +65,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "trust.revocability",
label: i18n.str`Revocability`,
choices: [
@@ -82,7 +82,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to the (ultimate economic, not fiduciary) settlor of the trust (individual(s) or entity/ies)`,
labelField: "fullName",
@@ -90,7 +90,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -98,7 +98,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -106,14 +106,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -122,14 +122,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfDeath",
label: i18n.str`Date of death`,
pattern: "dd/MM/yyyy",
@@ -139,7 +139,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToRevoke",
required: true,
label:
@@ -161,7 +161,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`If the trust results from the restructuring of pre-existing trust (re-settlement) or the merger of pre-existing trusts, the following information pertaining to the (actual) settlor of the pre-existing trust(s) has to be given`,
labelField: "fullName",
@@ -169,7 +169,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -177,7 +177,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -185,14 +185,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -201,14 +201,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfDeath",
label: i18n.str`Date of death`,
pattern: "dd/MM/yyyy",
@@ -221,7 +221,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Pertaining to the beneficiary/-ies at the time of the signing of this form`,
labelField: "fullName",
@@ -229,7 +229,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -237,7 +237,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -245,14 +245,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -261,14 +261,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToClaim",
label:
i18n.str`Has the beneficiary an actual right to claim distribution?`,
@@ -286,7 +286,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`in addition to certain beneficiaries or if there is/are no defined beneficiary/ies pertaining to (a) group(s) of beneficiaries (e.g. descendants of the settlor) known at the time of the signing of this form`,
name: "beneficiaryExtra",
@@ -297,7 +297,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to the protector(s) as well as (a) further person(s) having the right to revoke the trust (in case of revocable trusts) or to appoint the trustee of a trust`,
labelField: "asd",
@@ -308,7 +308,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to the protectors`,
labelField: "fullName",
@@ -316,7 +316,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -324,7 +324,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -332,28 +332,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToClaim",
label:
i18n.str`Does the protector have the right to revoke the trust?`,
@@ -374,7 +374,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "array",
- props: {
+ properties: {
label:
i18n.str`Information pertaining to further persons`,
labelField: "fullName",
@@ -382,7 +382,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -390,7 +390,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label:
i18n.str`Actual address of domicile/registered office`,
@@ -398,28 +398,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "country",
label: i18n.str`Country`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "rightToClaim",
label:
i18n.str`Has this further person the right to revoke the trust?`,
@@ -440,48 +440,48 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "signature",
label: i18n.str`Signature`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
- behavior: function formBehavior(
- v: Partial<Form902_13.Form>,
- ): FormState<Form902_13.Form> {
- return {
- settlors: {
- elements: (v.settlors ?? []).map(() => {
- return {
- rightToRevoke: {
- hidden: v.foundation?.revocability !== "revocable",
- },
- };
- }),
- },
- protectors: {
- elements: (v.protectors ?? []).map(() => {
- return {
- rightToRevoke: {
- hidden: v.foundation?.revocability !== "revocable",
- },
- };
- }),
- },
- furtherPersons: {
- elements: (v.furtherPersons ?? []).map(() => {
- return {
- rightToRevoke: {
- hidden: v.foundation?.revocability !== "revocable",
- },
- };
- }),
- },
- };
- },
+ // behavior: function formBehavior(
+ // v: Partial<Form902_13.Form>,
+ // ): FormState<Form902_13.Form> {
+ // return {
+ // settlors: {
+ // elements: (v.settlors ?? []).map(() => {
+ // return {
+ // rightToRevoke: {
+ // hidden: v.foundation?.revocability !== "revocable",
+ // },
+ // };
+ // }),
+ // },
+ // protectors: {
+ // elements: (v.protectors ?? []).map(() => {
+ // return {
+ // rightToRevoke: {
+ // hidden: v.foundation?.revocability !== "revocable",
+ // },
+ // };
+ // }),
+ // },
+ // furtherPersons: {
+ // elements: (v.furtherPersons ?? []).map(() => {
+ // return {
+ // rightToRevoke: {
+ // hidden: v.foundation?.revocability !== "revocable",
+ // },
+ // };
+ // }),
+ // },
+ // };
+ // },
});
namespace Form902_13 {
diff --git a/packages/aml-backoffice-ui/src/forms/902_15e.ts b/packages/aml-backoffice-ui/src/forms/902_15e.ts
index 915b7dbf7..eeda166c1 100644
--- a/packages/aml-backoffice-ui/src/forms/902_15e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_15e.ts
@@ -14,11 +14,11 @@
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";
+import type { InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_15.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title:
@@ -26,14 +26,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "contractingPartner",
label: i18n.str`Contracting partner`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "contractualRelationship",
label:
i18n.str`Name or number of the contractual relationship between the contracting party and the financial intermediary`,
@@ -41,33 +41,33 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "insurancePolicy",
label: i18n.str`Insurance policy`,
},
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`The contracting partner confirms in accordance with Art. 41a SRO Regulations that it is a licensed and state-supervised insurance company and that it has entered into the above-mentioned contractual relationship the assets connected to the life insurance policy also mentioned above.`,
},
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`In relation with the above insurance policy, the contracting partner gives the following further details`,
},
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`Policy holder`,
fields: [
{
type: "text",
- props: {
+ properties: {
name: "holder.fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -75,7 +75,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "holder.address",
label:
i18n.str`Actual address of domicile/registered office (incl. country)`,
@@ -83,7 +83,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "holder.dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -92,7 +92,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "holder.nationality",
label: i18n.str`Nationality`,
},
@@ -102,13 +102,13 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before:
i18n.str`Person actually (not in a fiduciary capacity) paying the premiums (to be filled in if not identical with point 1 above)`,
fields: [
{
type: "text",
- props: {
+ properties: {
name: "premiumPayer.fullName",
label:
i18n.str`Last name(s), first name(s)/entity`,
@@ -116,7 +116,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "premiumPayer.address",
label:
i18n.str`Actual address of domicile/registered office (incl. country)`,
@@ -124,7 +124,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "premiumPayer.dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -133,7 +133,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "premiumPayer.nationality",
label: i18n.str`Nationality`,
},
@@ -143,28 +143,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`The contracting partner hereby undertakes to automatically inform the financial intermediary of any changes. The contracting partner hereby also declares having been given permission by the above individuals and/or entities to transmit their data to the financial intermediary`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "signature",
label: i18n.str`Signature`,
},
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`It is a criminal offense to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, document forgery)`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
});
diff --git a/packages/aml-backoffice-ui/src/forms/902_1e.ts b/packages/aml-backoffice-ui/src/forms/902_1e.ts
index 1e7c54f25..58ef7e2e8 100644
--- a/packages/aml-backoffice-ui/src/forms/902_1e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_1e.ts
@@ -14,20 +14,19 @@
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 type { InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_1.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title: i18n.str`Information on customer`,
- description:
- i18n.str`The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the member act as director of a domiciliary company, this domiciliary company is the customer.`,
+ description: i18n.str`The customer is the person with whom the member concludes the contract with regard to the financial service provided (civil law). Does the member act as director of a domiciliary company, this domiciliary company is the customer.`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
name: "customerType",
label: i18n.str`Type of customer`,
required: true,
@@ -45,7 +44,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.fullName",
label: i18n.str`Full name`,
required: true,
@@ -53,7 +52,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.address",
label: i18n.str`Residential address`,
required: true,
@@ -61,21 +60,21 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "integer",
- props: {
+ properties: {
name: "naturalCustomer.telephone",
label: i18n.str`Telephone`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.email",
label: i18n.str`E-mail`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "naturalCustomer.dateOfBirth",
label: i18n.str`Date of birth`,
required: true,
@@ -84,7 +83,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.nationality",
label: i18n.str`Nationality`,
required: true,
@@ -92,7 +91,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.document",
label: i18n.str`Identification document`,
required: true,
@@ -100,7 +99,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "file",
- props: {
+ properties: {
name: "naturalCustomer.documentAttachment",
label: i18n.str`Document attachment`,
required: true,
@@ -111,28 +110,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.companyName",
label: i18n.str`Company name`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.office",
label: i18n.str`Registered office`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "naturalCustomer.companyDocument",
label: i18n.str`Company identification document`,
},
},
{
type: "file",
- props: {
+ properties: {
name: "naturalCustomer.companyDocumentAttachment",
label: i18n.str`Document attachment`,
required: true,
@@ -143,7 +142,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.companyName",
label: i18n.str`Company name`,
required: true,
@@ -151,7 +150,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.domicile",
label: i18n.str`Domicile`,
required: true,
@@ -159,28 +158,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.contactPerson",
label: i18n.str`Contact person`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.telephone",
label: i18n.str`Telephone`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.email",
label: i18n.str`E-mail`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "legalCustomer.document",
label: i18n.str`Identification document`,
help: i18n.str`Not older than 12 month`,
@@ -188,7 +187,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "file",
- props: {
+ properties: {
name: "legalCustomer.documentAttachment",
label: i18n.str`Document attachment`,
required: true,
@@ -200,14 +199,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
],
},
{
- title:
- i18n.str`Information on the natural persons who establish the business relationship for legal entities and partnerships`,
- description:
- i18n.str`For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified.`,
+ title: i18n.str`Information on the natural persons who establish the business relationship for legal entities and partnerships`,
+ description: i18n.str`For legal entities and partnerships the identity of the natural persons who establish the business relationship must be verified.`,
fields: [
{
type: "array",
- props: {
+ properties: {
name: "businessEstablisher",
label: i18n.str`Persons`,
required: true,
@@ -215,7 +212,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "fullName",
label: i18n.str`Full name`,
required: true,
@@ -223,7 +220,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label: i18n.str`Residential address`,
required: true,
@@ -231,7 +228,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
required: true,
@@ -240,7 +237,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
required: true,
@@ -248,19 +245,17 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "typeOfAuthorization",
- label:
- i18n.str`Type of authorization (signatory of representation)`,
+ label: i18n.str`Type of authorization (signatory of representation)`,
required: true,
},
},
{
type: "file",
- props: {
+ properties: {
name: "documentAttachment",
- label:
- i18n.str`Identification document attachment`,
+ label: i18n.str`Identification document attachment`,
required: true,
maxBites: 2 * 1024 * 1024,
accept: ".png",
@@ -269,7 +264,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "powerOfAttorneyArrangements",
label: i18n.str`Power of attorney arrangements`,
required: true,
@@ -291,7 +286,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "powerOfAttorneyArrangementsOther",
label: i18n.str`Power of attorney arrangements`,
required: true,
@@ -308,7 +303,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "absoluteTime",
- props: {
+ properties: {
name: "acceptance.when",
pattern: "dd/MM/yyyy",
label: i18n.str`Date (conclusion of contract)`,
@@ -317,7 +312,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "acceptance.acceptedBy",
label: i18n.str`Accepted by`,
required: true,
@@ -327,13 +322,11 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
value: "face-to-face",
},
{
- label:
- i18n.str`Correspondence: authenticated copy of identification document obtained`,
+ label: i18n.str`Correspondence: authenticated copy of identification document obtained`,
value: "correspondence-document",
},
{
- label:
- i18n.str`Correspondence: residential address validated`,
+ label: i18n.str`Correspondence: residential address validated`,
value: "correspondence-address",
},
],
@@ -341,7 +334,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
name: "acceptance.typeOfCorrespondence",
label: i18n.str`Type of correspondence service`,
choices: [
@@ -366,7 +359,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "acceptance.thirdPartyFullName",
label: i18n.str`Third party full name`,
required: true,
@@ -374,7 +367,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "acceptance.thirdPartyAddress",
label: i18n.str`Third party address`,
required: true,
@@ -382,16 +375,16 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "selectMultiple",
- props: {
+ properties: {
name: "acceptance.language",
label: i18n.str`Languages`,
- choices: uiForms.currencies(i18n),
+ choices: ["asd"],
unique: true,
},
},
{
type: "textArea",
- props: {
+ properties: {
name: "acceptance.furtherInformation",
label: i18n.str`Further information`,
},
@@ -399,36 +392,30 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
],
},
{
- title:
- i18n.str`Information on the beneficial owner of the assets and/or controlling person`,
- description:
- i18n.str`Establishment of the beneficial owner of the assets and/or controlling person`,
+ title: i18n.str`Information on the beneficial owner of the assets and/or controlling person`,
+ description: i18n.str`Establishment of the beneficial owner of the assets and/or controlling person`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
name: "establishment",
label: i18n.str`The customer is`,
required: true,
choices: [
{
- label:
- i18n.str`a natural person and there are no doubts that this person is the sole beneficial owner of the assets`,
+ label: i18n.str`a natural person and there are no doubts that this person is the sole beneficial owner of the assets`,
value: "natural",
},
{
- label:
- i18n.str`a foundation (or a similar construct; incl. underlying companies)`,
+ label: i18n.str`a foundation (or a similar construct; incl. underlying companies)`,
value: "foundation",
},
{
- label:
- i18n.str`a trust (incl. underlying companies)`,
+ label: i18n.str`a trust (incl. underlying companies)`,
value: "trust",
},
{
- label:
- i18n.str`a life insurance policy with separately managed accounts/securities accounts`,
+ label: i18n.str`a life insurance policy with separately managed accounts/securities accounts`,
value: "insurance-wrapper",
},
{
@@ -441,14 +428,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
],
},
{
- title:
- i18n.str`Evaluation with regard to embargo procedures/terrorism lists on establishing the business relationship`,
- description:
- i18n.str`Verification whether the customer, beneficial owners of the assets, controlling persons, authorized representatives or other involved persons are listed on an embargo/terrorism list (date of verification/result)`,
+ title: i18n.str`Evaluation with regard to embargo procedures/terrorism lists on establishing the business relationship`,
+ description: i18n.str`Verification whether the customer, beneficial owners of the assets, controlling persons, authorized representatives or other involved persons are listed on an embargo/terrorism list (date of verification/result)`,
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "embargoEvaluation",
help: i18n.str`The evaluation must be made at the beginning of the business relationship and has to be repeated in the case of permanent business relationship every time the according lists are updated.`,
label: i18n.str`Evaluation`,
@@ -457,14 +442,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
],
},
{
- title:
- i18n.str`In the case of cash transactions/occasional customers: Information on type and purpose of business relationship`,
- description:
- i18n.str`These details are only necessary for occasional customers, i.e. money exchange, money and asset transfer or other cash transactions provided that no customer profile (VQF doc. No. 902.5) is created`,
+ title: i18n.str`In the case of cash transactions/occasional customers: Information on type and purpose of business relationship`,
+ description: i18n.str`These details are only necessary for occasional customers, i.e. money exchange, money and asset transfer or other cash transactions provided that no customer profile (VQF doc. No. 902.5) is created`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
name: "cashTransactions.typeOfBusiness",
label: i18n.str`Type of business relationship`,
choices: [
@@ -477,8 +460,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
value: "money-and-asset-transfer",
},
{
- label:
- i18n.str`Other cash transactions. Specify below`,
+ label: i18n.str`Other cash transactions. Specify below`,
value: "other",
},
],
@@ -486,7 +468,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "cashTransactions.otherTypeOfBusiness",
required: true,
label: i18n.str`Specify other cash transactions:`,
@@ -494,108 +476,107 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
name: "cashTransactions.purpose",
- label:
- i18n.str`Purpose of the business relationship (purpose of service requested)`,
+ label: i18n.str`Purpose of the business relationship (purpose of service requested)`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
- behavior: function formBehavior(
- v: Partial<Form902_1.Form>,
- ): FormState<Form902_1.Form> {
- return {
- fullName: {
- disabled: true,
- },
- businessEstablisher: {
- elements: (v.businessEstablisher ?? []).map((be) => {
- return {
- powerOfAttorneyArrangementsOther: {
- hidden: be.powerOfAttorneyArrangements !== "other",
- },
- };
- }),
- },
- acceptance: {
- thirdPartyFullName: {
- hidden: v.acceptance?.typeOfCorrespondence !== "third-party",
- },
- thirdPartyAddress: {
- hidden: v.acceptance?.typeOfCorrespondence !== "third-party",
- },
- },
- cashTransactions: {
- otherTypeOfBusiness: {
- hidden: v.cashTransactions?.typeOfBusiness !== "other",
- },
- },
- naturalCustomer: {
- fullName: {
- hidden: v.customerType !== "natural",
- },
- address: {
- hidden: v.customerType !== "natural",
- },
- telephone: {
- hidden: v.customerType !== "natural",
- },
- email: {
- hidden: v.customerType !== "natural",
- },
- dateOfBirth: {
- hidden: v.customerType !== "natural",
- },
- nationality: {
- hidden: v.customerType !== "natural",
- },
- document: {
- hidden: v.customerType !== "natural",
- },
- companyName: {
- hidden: v.customerType !== "natural",
- },
- office: {
- hidden: v.customerType !== "natural",
- },
- companyDocument: {
- hidden: v.customerType !== "natural",
- },
- companyDocumentAttachment: {
- hidden: v.customerType !== "natural",
- },
- documentAttachment: {
- hidden: v.customerType !== "natural",
- },
- },
- legalCustomer: {
- companyName: {
- hidden: v.customerType !== "legal",
- },
- contactPerson: {
- hidden: v.customerType !== "legal",
- },
- document: {
- hidden: v.customerType !== "legal",
- },
- domicile: {
- hidden: v.customerType !== "legal",
- },
- email: {
- hidden: v.customerType !== "legal",
- },
- telephone: {
- hidden: v.customerType !== "legal",
- },
- documentAttachment: {
- hidden: v.customerType !== "legal",
- },
- },
- };
- },
+ // behavior: function formBehavior(
+ // v: Partial<Form902_1.Form>,
+ // ): FormState<Form902_1.Form> {
+ // return {
+ // fullName: {
+ // disabled: true,
+ // },
+ // businessEstablisher: {
+ // elements: (v.businessEstablisher ?? []).map((be) => {
+ // return {
+ // powerOfAttorneyArrangementsOther: {
+ // hidden: be.powerOfAttorneyArrangements !== "other",
+ // },
+ // };
+ // }),
+ // },
+ // acceptance: {
+ // thirdPartyFullName: {
+ // hidden: v.acceptance?.typeOfCorrespondence !== "third-party",
+ // },
+ // thirdPartyAddress: {
+ // hidden: v.acceptance?.typeOfCorrespondence !== "third-party",
+ // },
+ // },
+ // cashTransactions: {
+ // otherTypeOfBusiness: {
+ // hidden: v.cashTransactions?.typeOfBusiness !== "other",
+ // },
+ // },
+ // naturalCustomer: {
+ // fullName: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // address: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // telephone: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // email: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // dateOfBirth: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // nationality: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // document: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // companyName: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // office: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // companyDocument: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // companyDocumentAttachment: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // documentAttachment: {
+ // hidden: v.customerType !== "natural",
+ // },
+ // },
+ // legalCustomer: {
+ // companyName: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // contactPerson: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // document: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // domicile: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // email: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // telephone: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // documentAttachment: {
+ // hidden: v.customerType !== "legal",
+ // },
+ // },
+ // };
+ // },
});
namespace Form902_1 {
@@ -647,11 +628,11 @@ namespace Form902_1 {
interface BeneficialOwner {
establishment:
- | "natural-person"
- | "foundation"
- | "trust"
- | "insurance-wrapper"
- | "other";
+ | "natural-person"
+ | "foundation"
+ | "trust"
+ | "insurance-wrapper"
+ | "other";
}
interface CashTransactions {
diff --git a/packages/aml-backoffice-ui/src/forms/902_4e.ts b/packages/aml-backoffice-ui/src/forms/902_4e.ts
index 46803333b..7a3af8731 100644
--- a/packages/aml-backoffice-ui/src/forms/902_4e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_4e.ts
@@ -14,13 +14,13 @@
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 type { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
import { h as create } from "preact";
-import { BaseForm } from "./declaration.js";
+import { BaseForm } from "../context/ui-forms.js";
import { ArrowRightIcon, ChevronRightIcon } from "./icons.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_4.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title: i18n.str`Risk Profile AMLA`,
@@ -29,7 +29,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`The member performs additional clarifications if the business relationship or the transaction is classified as increased risk (Art. 56 SRO Regulations)`,
before: create(ArrowRightIcon, { class: "h-6 w-6" }),
@@ -37,7 +37,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "customer",
label: i18n.str`Customer`,
help: i18n.str`Pursuant identification form (VQF doc. Nr. 902.1) numeral 1`,
@@ -51,7 +51,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`This evaluation has to be completed by all members for every business relationship`,
before: create(ArrowRightIcon, { class: "h-6 w-6" }),
@@ -59,7 +59,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Foreign PEP`,
// tooltip:
// i18n.str`Definition see Art. 7 lit. g numeral 1 SRO Regulations`,
@@ -81,7 +81,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label:
i18n.str`Domestic PEP and PEP of International Organizations`,
// tooltip:
@@ -110,7 +110,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
label:
i18n.str`The decision of the Senior executive body on the acceptance of a business relationship with a PEP was obtained on`,
name: "pep.when",
@@ -126,7 +126,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`This evaluation has to be completed by all members for every business relationship`,
before: create(ArrowRightIcon, { class: "h-6 w-6" }),
@@ -134,7 +134,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: '"High risk" or non-cooperative country' as TranslatedString,
help: 'Is the customer, the beneficial owner or the controlling person or authorized representative in a country considered by the FATF "high risk" or non-cooperative and for which FATF requires increased diligence?' as TranslatedString,
name: "highRisk.evaluation",
@@ -154,7 +154,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
label:
i18n.str`The decision of the Senior executive body on the acceptance of a business relationship with a PEP was obtained on`,
name: "highRisk.when",
@@ -169,7 +169,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`This evaluation has to be completed by all members who have in total more than 20 customers for every business relationship. At least two risk categories have to be chosen and assessed`,
before: create(ArrowRightIcon, { class: "h-6 w-6" }),
@@ -177,12 +177,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`a) Country risk (nationality)`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Domicile/residential address`,
name: "evaluation.nationality.address",
choices: [
@@ -204,7 +204,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Nationality`,
name: "evaluation.nationality.nationality",
choices: [
@@ -222,7 +222,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.nationality.risk",
choices: [
@@ -249,12 +249,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`b) Country risk (business activity)`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Place of business activity`,
name: "evaluation.business.place",
choices: [
@@ -272,7 +272,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.business.risk",
choices: [
@@ -299,19 +299,19 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`c) Country risk (payments)`,
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Country of origin and destination of frequent payments (if known)`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.payments.risk",
choices: [
@@ -338,12 +338,12 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`d) Industry risk`,
fields: [
{
type: "choiceStacked",
- props: {
+ properties: {
label:
i18n.str`Nature of customer's business activity`,
name: "evaluation.industry.nature",
@@ -362,7 +362,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.payments.risk",
choices: [
@@ -399,19 +399,19 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`e) Contact risk`,
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Types of contact to the customer/ beneficial owner of the assets`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.contact.risk",
choices: [
@@ -438,19 +438,19 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`f) Product risk`,
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Nature of services and products requested by the customer`,
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.product.risk",
choices: [
@@ -497,19 +497,19 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before: i18n.str`g) Criteria defined by the member`,
fields: [
{
type: "text",
- props: {
+ properties: {
label: i18n.str`Criteria definition`,
name: "evaluation.custom.definition",
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk level`,
name: "evaluation.custom.risk",
choices: [
@@ -533,20 +533,20 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Overall assessment of the business relationship`,
},
},
{
type: "group",
- props: {
+ properties: {
before:
i18n.str`A business relationship is classified as increased risk if:`,
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Business relationship with PEP pursuant to numeral 1 (no exception possible)`,
before: create(ChevronRightIcon, { class: "h-6 w-6" }),
@@ -554,7 +554,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
label:
'Relationship with a person from a "high risk" or non-cooperative country according to numeral 2 (no exceptions possible)' as TranslatedString,
before: create(ChevronRightIcon, { class: "h-6 w-6" }),
@@ -562,7 +562,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Min. one criterion pursuant to numeral 3 was assessed with risk 2 or min. two criteria pursuant to numeral 3 were assessed with risk 1 (exception: justification by the member below why the business relationship overall does not have to be classified as increased risk despite the fact that individual risk criteria are increased)`,
before: create(ChevronRightIcon, { class: "h-6 w-6" }),
@@ -573,7 +573,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Justification for differing risk assessment`,
name: "evaluation.overall.justification",
@@ -581,7 +581,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Risk classified`,
name: "evaluation.overall.risk",
choices: [
@@ -600,7 +600,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "absoluteTime",
- props: {
+ properties: {
label:
i18n.str`The decision of the Senior executive body on the acceptance of a business relationship with a PEP was obtained on`,
name: "evaluation.when",
@@ -616,19 +616,19 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "group",
- props: {
+ properties: {
before: i18n.str`Criteria`,
fields: [
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`Classification as as increased risk is compulsory if`,
},
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-6 h-6" }),
label:
i18n.str`Transactions for which assets with an equivalent value of CHF 100'000.- or more are physically introduced at the beginning of the business relationship, either at once or in a staggered manner`,
@@ -636,7 +636,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-6 h-6" }),
label:
'Money and asset transfers ("money transfer") whereby a single transaction or multiple transactions which appear to be related reach or exceed the amount of CHF 5,000.-' as TranslatedString,
@@ -644,7 +644,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-6 h-6" }),
label:
'Payments from or to a country that is considered to be "high risk" or non-cooperative by the FATF and for which increased diligence is required' as TranslatedString,
@@ -655,13 +655,13 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "group",
- props: {
+ properties: {
before:
i18n.str`Additional criteria defined by the member`,
fields: [
{
type: "caption",
- props: {
+ properties: {
before: create(ArrowRightIcon, { class: "w-6 h-6" }),
label:
i18n.str`All members have to define min. 1 additional criterion for every business relationship to identify unusual transactions`,
@@ -669,20 +669,20 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Description`,
name: "criteria.additional",
},
},
{
type: "group",
- props: {
+ properties: {
before:
i18n.str`Possible criteria (Art. 59 para. 2 SRO Regulations)`,
fields: [
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-4 h-4" }),
label:
i18n.str`the amount of inflowing and outflowing assets`,
@@ -690,7 +690,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-4 h-4" }),
label:
i18n.str`type, volume and frequency of transactions usual to the business relationship (considerable variance would be unusual)`,
@@ -698,7 +698,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-4 h-4" }),
label:
i18n.str`type, volume and frequency of transactions usual to comparable business relationships (considerable variance would be unusual)`,
@@ -706,7 +706,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-4 h-4" }),
label:
i18n.str`description of expected transaction patterns which the client notify the member of (considerable variance would be unusual)`,
@@ -714,7 +714,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
before: create(ChevronRightIcon, { class: "w-4 h-4" }),
label:
'The country of origin or destination of payments, especially in the case of payments from or to a country considered by the FATF as "high risk" or non-cooperative' as TranslatedString,
@@ -728,7 +728,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
behavior: function formBehavior(
// v: Partial<Form902_4.Form>,
diff --git a/packages/aml-backoffice-ui/src/forms/902_5e.ts b/packages/aml-backoffice-ui/src/forms/902_5e.ts
index efe47b213..e66a4f94d 100644
--- a/packages/aml-backoffice-ui/src/forms/902_5e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_5e.ts
@@ -13,11 +13,11 @@
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 type { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_5.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) => ({
design: [
{
title: i18n.str`Customer Profile`,
@@ -26,7 +26,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
name: "customer",
label: i18n.str`Customer`,
help: i18n.str`Pursuant Identification Form (VQF doc. No. 902.1) numeral 1`,
@@ -39,7 +39,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Profession, business activities`,
name: "businessActivity",
help: i18n.str`former, current, potentially planned`,
@@ -52,7 +52,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Income and assets, liabilities`,
name: "financial",
help: i18n.str`estimated`,
@@ -65,7 +65,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "text",
- props: {
+ properties: {
label: i18n.str`Nature`,
name: "originOfAssets.nature",
help: i18n.str`nature of the involved assets`,
@@ -73,22 +73,22 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "selectOne",
- props: {
+ properties: {
name: "originOfAssets.currency",
label: i18n.str`Currency`,
- choices: uiForms.currencies(i18n),
+ choices: ["change me"],
},
},
{
type: "integer",
- props: {
+ properties: {
label: i18n.str`Amount`,
name: "originOfAssets.amount",
},
},
{
type: "choiceStacked",
- props: {
+ properties: {
label: i18n.str`Category`,
name: "originOfAssets.category",
choices: [
@@ -113,7 +113,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
label: i18n.str`Other category`,
name: "originOfAssets.categoryOther",
required: true,
@@ -121,7 +121,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Detailed description of the origins/economical background of the assets involved in the business relationship`,
name: "originOfAssets.details",
@@ -135,7 +135,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Purpose of the business relationship`,
name: "nature.purpose",
help: i18n.str`nature of the involved assets`,
@@ -143,7 +143,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Information on the planned development of the business relationship and the assets`,
name: "nature.plan",
@@ -151,7 +151,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Especially in the case of cash or money and asset transfer transactions with regular customers: Details on usual business volume, Information on the beneficiaries, (Full name, address, bank account)`,
name: "nature.cashOrMoneyTransfer",
@@ -164,7 +164,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Relation of the customer to the beneficial owner involved in the business relationship`,
name: "relations.beneficialOwners",
@@ -172,7 +172,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Relation of the customer to the controlling persons involved in the business relationship`,
name: "relations.controllingPersons",
@@ -180,7 +180,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Relation of the customer to the authorized signatories involved in the business relationship`,
name: "relations.authorizedSignatories",
@@ -188,7 +188,7 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label:
i18n.str`Relation of the customer to other persons involved in the business relationship`,
name: "relations.otherPersons",
@@ -196,14 +196,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Relation to other AMLA-Files`,
name: "relations.withOtherAmlaFiles",
},
},
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Introducer / agents / references`,
name: "relations.references",
},
@@ -215,26 +215,26 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
label: i18n.str`Other relevant information`,
name: "furtherInformation",
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
- behavior: function formBehavior(
- v: Partial<Form902_5.Form>,
- ): FormState<Form902_5.Form> {
- return {
- originOfAssets: {
- categoryOther: {
- hidden: v.originOfAssets?.category !== "other",
- },
- },
- };
- },
+ // behavior: function formBehavior(
+ // v: Partial<Form902_5.Form>,
+ // ): FormState<Form902_5.Form> {
+ // return {
+ // originOfAssets: {
+ // categoryOther: {
+ // hidden: v.originOfAssets?.category !== "other",
+ // },
+ // },
+ // };
+ // },
});
namespace Form902_5 {
diff --git a/packages/aml-backoffice-ui/src/forms/902_9e.ts b/packages/aml-backoffice-ui/src/forms/902_9e.ts
index 62fca5647..297ec86b1 100644
--- a/packages/aml-backoffice-ui/src/forms/902_9e.ts
+++ b/packages/aml-backoffice-ui/src/forms/902_9e.ts
@@ -14,11 +14,11 @@
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 { BaseForm } from "./declaration.js";
+import { FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
+import { BaseForm } from "../context/ui-forms.js";
import { resolutionSection } from "./simplest.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Form902_9.Form> => ({
+export const v1 = (i18n: InternationalizationAPI) =>({
design: [
{
title:
@@ -26,42 +26,42 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
fields: [
{
type: "textArea",
- props: {
+ properties: {
name: "contractingPartner",
label: i18n.str`Contracting partner`,
},
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`The contracting partner hereby declares that the person(s) listed below is/are the beneficial owner(s) of the assets involved in the business relationship. If the contracting partner is also the sole beneficial owner of the assets, the contracting partner's detail must be set out below`,
},
},
{
type: "array",
- props: {
+ properties: {
label: i18n.str`Persons`,
labelField: "surname",
name: "persons",
fields: [
{
type: "text",
- props: {
+ properties: {
name: "surname",
label: i18n.str`Surname(s)`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "firstName",
label: i18n.str`First name(s)`,
},
},
{
type: "absoluteTime",
- props: {
+ properties: {
name: "dateOfBirth",
label: i18n.str`Date of birth`,
pattern: "dd/MM/yyyy",
@@ -70,14 +70,14 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "text",
- props: {
+ properties: {
name: "nationality",
label: i18n.str`Nationality`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "address",
label: i18n.str`Actual address of domicile`,
},
@@ -87,28 +87,28 @@ export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): Flexib
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`The contracting partner hereby undertakes to inform automatically of any changes to the information contained herein`,
},
},
{
type: "text",
- props: {
+ properties: {
name: "signature",
label: i18n.str`Signature`,
},
},
{
type: "caption",
- props: {
+ properties: {
label:
i18n.str`It is a criminal offense to deliberately provide false information on this form (article 251 of the Swiss Criminal Code, document forgery)`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
behavior: function formBehavior(
// v: Partial<Form902_9.Form>,
diff --git a/packages/aml-backoffice-ui/src/forms/declaration.ts b/packages/aml-backoffice-ui/src/forms/declaration.ts
deleted file mode 100644
index c467f537b..000000000
--- a/packages/aml-backoffice-ui/src/forms/declaration.ts
+++ /dev/null
@@ -1,73 +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/>
- */
-
-import type { AmountJson, TalerExchangeApi, TranslatedString } from "@gnu-taler/taler-util";
-import type {
- FlexibleForm,
- InternationalizationAPI,
-} from "@gnu-taler/web-util/browser";
-
-/**
- * import entry point without hard reference.
- *
- * 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.
- */
-
-export interface BaseForm {
- state: TalerExchangeApi.AmlState;
- threshold: AmountJson;
-}
-
-export type FormMetadata<T extends BaseForm> = {
- label: TranslatedString;
- id: string;
- version: number;
- impl: (current: T) => FlexibleForm<T>;
-};
-
-interface LabelValue {
- label: TranslatedString;
- value: string;
-}
-
-export interface UiForms {
- currencies: (i18n: InternationalizationAPI) => LabelValue[];
- languages: (i18n: InternationalizationAPI) => LabelValue[];
- forms: (i18n: InternationalizationAPI) => Array<FormMetadata<BaseForm>>;
-}
-
-/**
- * Global settings for the UI.
- */
-const defaultUIForms: UiForms = {
- currencies: () => [],
- languages: () => [],
- forms: () => [],
-};
-
-declare global {
- // eslint-disable-next-line no-var
- var amlExchangeBackoffice: UiForms;
-}
-
-export const uiForms: UiForms =
- "amlExchangeBackoffice" in globalThis
- ? globalThis.amlExchangeBackoffice
- : defaultUIForms;
diff --git a/packages/aml-backoffice-ui/src/forms/index.ts b/packages/aml-backoffice-ui/src/forms/index.ts
index 6c5f5d767..b32978c29 100644
--- a/packages/aml-backoffice-ui/src/forms/index.ts
+++ b/packages/aml-backoffice-ui/src/forms/index.ts
@@ -14,15 +14,7 @@
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";
-import { v1 as form_902_13e_v1 } from "./902_13e.js";
-import { v1 as form_902_15e_v1 } from "./902_15e.js";
-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 { BaseForm, FormMetadata } from "./declaration.js";
+import { FormMetadata } from "../context/ui-forms.js";
import { v1 as simplest } from "./simplest.js";
const languages = (i18n: InternationalizationAPI) => [
@@ -137,52 +129,52 @@ const languages = (i18n: InternationalizationAPI) => [
];
-const forms: (i18n: InternationalizationAPI) => Array<FormMetadata<BaseForm>> = (i18n) => [
+const forms: (i18n: InternationalizationAPI) => Array<FormMetadata> = (i18n) => [
{
label: i18n.str`Simple comment`,
id: "simple_comment",
version: 1,
- impl: simplest(i18n),
- }, {
- label: i18n.str`Identification form`,
- id: "902.1e",
- version: 1,
- impl: form_902_1e_v1(i18n),
- }, {
- label: i18n.str`Operational legal entity or partnership`,
- id: "902.11e",
- version: 1,
- impl: form_902_11e_v1(i18n),
- }, {
- label: i18n.str`Foundations`,
- id: "902.12e",
- version: 1,
- impl: form_902_12e_v1(i18n),
- }, {
- label: i18n.str`Declaration for trusts`,
- id: "902.13e",
- version: 1,
- impl: form_902_13e_v1(i18n),
- }, {
- label: i18n.str`Information on life insurance policies`,
- id: "902.15e",
- version: 1,
- impl: form_902_15e_v1(i18n),
- }, {
- label: i18n.str`Declaration of beneficial owner`,
- id: "902.9e",
- version: 1,
- impl: form_902_9e_v1(i18n),
- }, {
- label: i18n.str`Customer profile`,
- id: "902.5e",
- version: 1,
- impl: form_902_5e_v1(i18n),
- }, {
- label: i18n.str`Risk profile`,
- id: "902.4e",
- version: 1,
- impl: form_902_4e_v1(i18n),
+ config: simplest(i18n),
+ // }, {
+ // label: i18n.str`Identification form`,
+ // id: "902.1e",
+ // version: 1,
+ // config: form_902_1e_v1(i18n),
+ // }, {
+ // label: i18n.str`Operational legal entity or partnership`,
+ // id: "902.11e",
+ // version: 1,
+ // config: form_902_11e_v1(i18n),
+ // }, {
+ // label: i18n.str`Foundations`,
+ // id: "902.12e",
+ // version: 1,
+ // config: form_902_12e_v1(i18n),
+ // }, {
+ // label: i18n.str`Declaration for trusts`,
+ // id: "902.13e",
+ // version: 1,
+ // config: form_902_13e_v1(i18n),
+ // }, {
+ // label: i18n.str`Information on life insurance policies`,
+ // id: "902.15e",
+ // version: 1,
+ // config: form_902_15e_v1(i18n),
+ // }, {
+ // label: i18n.str`Declaration of beneficial owner`,
+ // id: "902.9e",
+ // version: 1,
+ // config: form_902_9e_v1(i18n),
+ // }, {
+ // label: i18n.str`Customer profile`,
+ // id: "902.5e",
+ // version: 1,
+ // config: form_902_5e_v1(i18n),
+ // }, {
+ // label: i18n.str`Risk profile`,
+ // id: "902.4e",
+ // version: 1,
+ // config: form_902_4e_v1(i18n),
},
];
@@ -214,4 +206,3 @@ const currencies = (i18n: InternationalizationAPI) => [
},
];
-globalThis.amlExchangeBackoffice = { currencies, languages, forms }
diff --git a/packages/aml-backoffice-ui/src/forms/simplest.ts b/packages/aml-backoffice-ui/src/forms/simplest.ts
index 6455b6f41..d32c759cb 100644
--- a/packages/aml-backoffice-ui/src/forms/simplest.ts
+++ b/packages/aml-backoffice-ui/src/forms/simplest.ts
@@ -13,74 +13,68 @@
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import {
- TalerExchangeApi,
- type TranslatedString
-} from "@gnu-taler/taler-util";
-import type { DoubleColumnFormSection, FlexibleForm, FormState, InternationalizationAPI } from "@gnu-taler/web-util/browser";
-import { amlStateConverter } from "../utils/converter.js";
-import { BaseForm } from "./declaration.js";
+import type {
+ InternationalizationAPI
+} from "@gnu-taler/web-util/browser";
+import { BaseForm, DoubleColumnForm, DoubleColumnFormSection, UIHandlerId } from "../context/ui-forms.js";
-export const v1 = (i18n: InternationalizationAPI) => (current: BaseForm): FlexibleForm<Simplest.Form> => ({
+export const v1 = (i18n: InternationalizationAPI): DoubleColumnForm => ({
+ type: "double-column" as const,
design: [
{
title: i18n.str`Simple form`,
fields: [
{
type: "textArea",
- props: {
+ properties: {
+ id: ".comment" as UIHandlerId,
name: "comment",
label: i18n.str`Comments`,
},
},
],
},
- resolutionSection(current, i18n),
+ resolutionSection(i18n),
],
- behavior: function formBehavior(
- v: Partial<Simplest.Form>,
- ): FormState<Simplest.Form> {
- return {
- comment: {
- help: ((v.comment?.length ?? 0) > 100 ? "keep it short" : "") as TranslatedString,
- },
- threshold: {
- disabled: v.state === TalerExchangeApi.AmlState.frozen,
- },
- };
- },
+ // behavior: function formBehavior(
+ // v: Partial<Simplest.Form>,
+ // ): FormState<Simplest.Form> {
+ // return {
+ // comment: {
+ // help: ((v.comment?.length ?? 0) > 100 ? "keep it short" : "") as TranslatedString,
+ // },
+ // threshold: {
+ // disabled: v.state === TalerExchangeApi.AmlState.frozen,
+ // },
+ // };
+ // },
});
-export namespace Simplest {
- export interface Form extends BaseForm {
- comment: string;
- }
-}
-
-export function resolutionSection(current: BaseForm, i18n: InternationalizationAPI): DoubleColumnFormSection {
+export function resolutionSection(
+ i18n: InternationalizationAPI,
+): DoubleColumnFormSection {
return {
title: i18n.str`Resolution`,
- description: `Current state is ${amlStateConverter.toStringUI(
- current.state,
- )} and threshold at ` as TranslatedString,
fields: [
{
type: "choiceHorizontal",
- props: {
+ properties: {
+ id: ".state" as UIHandlerId,
name: "state",
label: i18n.str`New state`,
+ converterId: "TalerExchangeApi.AmlState",
choices: [
{
- value: TalerExchangeApi.AmlState.frozen,
+ value: "frozen",
label: i18n.str`Frozen`,
},
{
- value: TalerExchangeApi.AmlState.pending,
+ value: "pending",
label: i18n.str`Pending`,
},
{
- value: TalerExchangeApi.AmlState.normal,
+ value: "normal",
label: i18n.str`Normal`,
},
],
@@ -88,7 +82,9 @@ export function resolutionSection(current: BaseForm, i18n: InternationalizationA
},
{
type: "amount",
- props: {
+ properties: {
+ id: ".threshold" as UIHandlerId,
+ currency: "USD",
name: "threshold",
label: i18n.str`New threshold`,
},
diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
index e16a6a103..1ad8c9453 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx
@@ -34,6 +34,7 @@ import {
import {
DefaultForm,
ErrorLoading,
+ FlexibleForm,
InternationalizationAPI,
Loading,
useTranslationContext,
@@ -42,9 +43,9 @@ import { format } from "date-fns";
import { VNode, h } from "preact";
import { useState } from "preact/hooks";
import { privatePages } from "../Routing.js";
-import { BaseForm, FormMetadata, uiForms } from "../forms/declaration.js";
import { useCaseDetails } from "../hooks/useCaseDetails.js";
import { ShowConsolidated } from "./ShowConsolidated.js";
+import { FormMetadata, useUiFormsContext } from "../context/ui-forms.js";
export type AmlEvent =
| AmlFormEvent
@@ -56,7 +57,7 @@ type AmlFormEvent = {
when: AbsoluteTime;
title: TranslatedString;
justification: Justification;
- metadata: FormMetadata<BaseForm>;
+ metadata: FormMetadata;
state: TalerExchangeApi.AmlState;
threshold: AmountJson;
};
@@ -115,9 +116,10 @@ export function getEventsFromAmlHistory(
aml: TalerExchangeApi.AmlDecisionDetail[],
kyc: TalerExchangeApi.KycDetail[],
i18n: InternationalizationAPI,
+ forms: FormMetadata[],
): AmlEvent[] {
const ae: AmlEvent[] = aml.map((a) => {
- const just = parseJustification(a.justification, uiForms.forms(i18n));
+ const just = parseJustification(a.justification, forms);
return {
type: just.type === "ok" ? "aml-form" : "aml-form-error",
state: a.new_state,
@@ -156,11 +158,13 @@ export function CaseDetails({ account }: { account: string }) {
const [selected, setSelected] = useState<AbsoluteTime>(AbsoluteTime.now());
const [showForm, setShowForm] = useState<{
justification: Justification;
- metadata: FormMetadata<BaseForm>;
+ metadata: FormMetadata;
}>();
const { i18n } = useTranslationContext();
const details = useCaseDetails(account);
+ const {forms} = useUiFormsContext()
+
if (!details) {
return <Loading />;
}
@@ -180,14 +184,14 @@ export function CaseDetails({ account }: { account: string }) {
}
const { aml_history, kyc_attributes } = details.body;
- const events = getEventsFromAmlHistory(aml_history, kyc_attributes, i18n);
+ const events = getEventsFromAmlHistory(aml_history, kyc_attributes, i18n, forms);
if (showForm !== undefined) {
return (
<DefaultForm
readOnly={true}
initial={showForm.justification.value}
- form={showForm.metadata.impl(showForm.justification.value)}
+ form={showForm.metadata as any} // FIXME: HERE
>
<div class="mt-6 flex items-center justify-end gap-x-6">
<button
@@ -243,11 +247,7 @@ export function CaseDetails({ account }: { account: string }) {
);
}
-function AmlStateBadge({
- state,
-}: {
- state: TalerExchangeApi.AmlState;
-}): VNode {
+function AmlStateBadge({ state }: { state: TalerExchangeApi.AmlState }): VNode {
switch (state) {
case TalerExchangeApi.AmlState.normal: {
return (
@@ -389,11 +389,10 @@ function ShowTimeline({
);
}
-
-export type Justification<T extends BaseForm = BaseForm> = {
+export type Justification<T = Record<string, unknown>> = {
// form values
value: T;
-} & Omit<Omit<FormMetadata<BaseForm>, "icon">, "impl">;
+} & Omit<Omit<FormMetadata, "icon">, "config">;
type SimpleFormMetadata = {
version?: number;
@@ -414,11 +413,11 @@ type ParseJustificationFail =
function parseJustification(
s: string,
- listOfAllKnownForms: FormMetadata<BaseForm>[],
+ listOfAllKnownForms: FormMetadata[],
):
| OperationOk<{
justification: Justification;
- metadata: FormMetadata<BaseForm>;
+ metadata: FormMetadata;
}>
| OperationFail<ParseJustificationFail> {
try {
diff --git a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
index 47c8f8ab4..64bfb90f1 100644
--- a/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CaseUpdate.tsx
@@ -15,27 +15,29 @@
*/
import {
AbsoluteTime,
+ AmountJson,
Amounts,
HttpStatusCode,
TalerExchangeApi,
TalerProtocolTimestamp,
- assertUnreachable
+ assertUnreachable,
} from "@gnu-taler/taler-util";
import {
Button,
LocalNotificationBanner,
RenderAllFieldsByUiConfig,
+ UIFormField,
useExchangeApiContext,
useLocalNotificationHandler,
- useTranslationContext
+ useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { privatePages } from "../Routing.js";
-import { BaseForm, uiForms } from "../forms/declaration.js";
+import { UIFormFieldConfig, useUiFormsContext } from "../context/ui-forms.js";
import { useFormState } from "../hooks/form.js";
import { useOfficer } from "../hooks/officer.js";
-import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
import { Justification } from "./CaseDetails.js";
+import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
export function CaseUpdate({
account,
@@ -53,7 +55,7 @@ export function CaseUpdate({
// const [notification, notify, handleError] = useLocalNotification();
const [notification, withErrorHandler] = useLocalNotificationHandler();
const { config } = useExchangeApiContext();
-
+ const { forms } = useUiFormsContext();
const initial = {
when: AbsoluteTime.now(),
state: TalerExchangeApi.AmlState.pending,
@@ -63,12 +65,12 @@ export function CaseUpdate({
if (officer.state !== "ready") {
return <HandleAccountNotReady officer={officer} />;
}
- const theForm = uiForms.forms(i18n).find((v) => v.id === formId);
+ const theForm = forms.find((v) => v.id === formId);
if (!theForm) {
return <div>form with id {formId} not found</div>;
}
- const [form, state] = useFormState<BaseForm>(initial, (st) => {
+ const [form, state] = useFormState(initial, (st) => {
return {
status: "ok",
result: st as any,
@@ -76,8 +78,6 @@ export function CaseUpdate({
};
});
- const ff = theForm.impl(state.result as any);
-
const validatedForm = state.status === "fail" ? undefined : state.result;
const submitHandler =
@@ -97,8 +97,11 @@ export function CaseUpdate({
justification: JSON.stringify(justification),
decision_time: TalerProtocolTimestamp.now(),
h_payto: account,
- new_state: justification.value.state,
- new_threshold: Amounts.stringify(justification.value.threshold),
+ new_state: justification.value
+ .state as TalerExchangeApi.AmlState,
+ new_threshold: Amounts.stringify(
+ justification.value.threshold as AmountJson,
+ ),
kyc_requirements: undefined,
};
@@ -122,13 +125,15 @@ export function CaseUpdate({
},
);
- // const asd = ff.design[0]?.fields[0]?.props
-
+ function convertUiField(_f: UIFormFieldConfig[]): UIFormField[] {
+ return [];
+ }
+
return (
<Fragment>
<LocalNotificationBanner notification={notification} />
<div class="space-y-10 divide-y -mt-5 divide-gray-900/10">
- {ff.design.map((section, i) => {
+ {theForm.config.design.map((section, i) => {
if (!section) return <Fragment />;
return (
<div
@@ -150,7 +155,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={section.fields}
+ fields={convertUiField(section.fields)}
/>
</div>
</div>
@@ -180,11 +185,11 @@ export function CaseUpdate({
}
export function SelectForm({ account }: { account: string }) {
- const { i18n } = useTranslationContext();
+ const { forms } = useUiFormsContext();
return (
<div>
<pre>New form for account: {account.substring(0, 16)}...</pre>
- {uiForms.forms(i18n).map((form) => {
+ {forms.map((form) => {
return (
<a
key={form.id}
diff --git a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
index a8a853bc1..abcaaa2a6 100644
--- a/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
+++ b/packages/aml-backoffice-ui/src/pages/CreateAccount.tsx
@@ -118,7 +118,6 @@ export function CreateAccount(): VNode {
async () => officer.create(form.password!.value!),
() => {},
);
- form.password;
return (
<div class="flex min-h-full flex-col ">
<LocalNotificationBanner notification={notification} />
diff --git a/packages/aml-backoffice-ui/src/pages/Officer.tsx b/packages/aml-backoffice-ui/src/pages/Officer.tsx
index ad8ae1ed3..39359cd5e 100644
--- a/packages/aml-backoffice-ui/src/pages/Officer.tsx
+++ b/packages/aml-backoffice-ui/src/pages/Officer.tsx
@@ -20,11 +20,11 @@ import {
import { h } from "preact";
import { useOfficer } from "../hooks/officer.js";
import { HandleAccountNotReady } from "./HandleAccountNotReady.js";
-import { useSettingsContext } from "../context/settings.js";
+import { useUiSettingsContext } from "../context/ui-settings.js";
export function Officer() {
const officer = useOfficer();
- const settings = useSettingsContext();
+ const settings = useUiSettingsContext();
const { lib } = useExchangeApiContext();
const { i18n } = useTranslationContext();
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx
index 11b25575b..714bf6580 100644
--- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.stories.tsx
@@ -19,13 +19,16 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { AbsoluteTime, AmountString, Duration, TranslatedString } from "@gnu-taler/taler-util";
+import {
+ AbsoluteTime,
+ AmountString,
+ 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 { ShowConsolidated as TestedComponent } from "./ShowConsolidated.js";
export default {
title: "show consolidated",
@@ -36,81 +39,94 @@ const nullTranslator: InternationalizationAPI = {
singular: (str: TemplateStringsArray) => str.join() as TranslatedString,
translate: (str: TemplateStringsArray) => [str.join()] as TranslatedString[],
Translate: () => undefined as unknown,
-}
+};
export const WithEmptyHistory = tests.createExample(TestedComponent, {
- history: getEventsFromAmlHistory([], [], nullTranslator),
- until: AbsoluteTime.now()
+ history: getEventsFromAmlHistory([], [], nullTranslator, []),
+ until: AbsoluteTime.now(),
});
export const WithSomeEvents = tests.createExample(TestedComponent, {
- history: getEventsFromAmlHistory([
- {
- "decider_pub": "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
- "justification": "{\"index\":0,\"name\":\"Simple comment\",\"value\":{\"fullName\":\"loggedIn_user_fullname\",\"when\":{\"t_ms\":1700207199558},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"comment\":\"test\"}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700208199
- }
- },
- {
- "decider_pub": "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
- "justification": "{\"index\":0,\"name\":\"Simple comment\",\"value\":{\"fullName\":\"loggedIn_user_fullname\",\"when\":{\"t_ms\":1700207199558},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"comment\":\"test\"}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700208211
- }
- },
- {
- "decider_pub": "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
- "justification": "{\"index\":0,\"name\":\"Simple comment\",\"value\":{\"fullName\":\"loggedIn_user_fullname\",\"when\":{\"t_ms\":1700207199558},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"comment\":\"test\"}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700208220
- }
- },
- {
- "decider_pub": "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
- "justification": "{\"index\":4,\"name\":\"Declaration for trusts (902.13e)\",\"value\":{\"fullName\":\"loggedIn_user_fullname\",\"when\":{\"t_ms\":1700208362854},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"contractingPartner\":\"f\",\"knownAs\":\"a\",\"trust\":{\"name\":\"b\",\"type\":\"discretionary\",\"revocability\":\"irrevocable\"}}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700208385
- }
- },
- {
- "decider_pub": "6CD3J8XSKWQPFFDJY4SP4RK2D7T7WW7JRJDTXHNZY7YKGXDCE2QG",
- "justification": "{\"id\":\"simple_comment\",\"label\":\"Simple comment\",\"version\":1,\"value\":{\"when\":{\"t_ms\":1700488420810},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"comment\":\"qwe\"}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700488423
- }
- },
- {
- "decider_pub": "6CD3J8XSKWQPFFDJY4SP4RK2D7T7WW7JRJDTXHNZY7YKGXDCE2QG",
- "justification": "{\"id\":\"simple_comment\",\"label\":\"Simple comment\",\"version\":1,\"value\":{\"when\":{\"t_ms\":1700488671251},\"state\":1,\"threshold\":{\"currency\":\"STATER\",\"fraction\":0,\"value\":0},\"comment\":\"asd asd asd \"}}",
- "new_threshold": "STATER:0" as AmountString,
- "new_state": 1,
- "decision_time": {
- "t_s": 1700488677
- }
- }
- ], [{
- collection_time: AbsoluteTime.toProtocolTimestamp(
- AbsoluteTime.subtractDuraction(AbsoluteTime.now(), Duration.fromPrettyString("1d"))
- ),
- expiration_time: { t_s: "never" },
- provider_section: "asd",
- attributes: {
- email: "sebasjm@qwdde.com"
- }
- }], nullTranslator),
- until: AbsoluteTime.now()
+ history: getEventsFromAmlHistory(
+ [
+ {
+ decider_pub: "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
+ justification:
+ '{"index":0,"name":"Simple comment","value":{"fullName":"loggedIn_user_fullname","when":{"t_ms":1700207199558},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"comment":"test"}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700208199,
+ },
+ },
+ {
+ decider_pub: "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
+ justification:
+ '{"index":0,"name":"Simple comment","value":{"fullName":"loggedIn_user_fullname","when":{"t_ms":1700207199558},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"comment":"test"}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700208211,
+ },
+ },
+ {
+ decider_pub: "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
+ justification:
+ '{"index":0,"name":"Simple comment","value":{"fullName":"loggedIn_user_fullname","when":{"t_ms":1700207199558},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"comment":"test"}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700208220,
+ },
+ },
+ {
+ decider_pub: "JD70N2XZ8FZKB7C146ZWR6XBDCS4Z84PJKJMPB73PMJ2B1X35ZFG",
+ justification:
+ '{"index":4,"name":"Declaration for trusts (902.13e)","value":{"fullName":"loggedIn_user_fullname","when":{"t_ms":1700208362854},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"contractingPartner":"f","knownAs":"a","trust":{"name":"b","type":"discretionary","revocability":"irrevocable"}}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700208385,
+ },
+ },
+ {
+ decider_pub: "6CD3J8XSKWQPFFDJY4SP4RK2D7T7WW7JRJDTXHNZY7YKGXDCE2QG",
+ justification:
+ '{"id":"simple_comment","label":"Simple comment","version":1,"value":{"when":{"t_ms":1700488420810},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"comment":"qwe"}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700488423,
+ },
+ },
+ {
+ decider_pub: "6CD3J8XSKWQPFFDJY4SP4RK2D7T7WW7JRJDTXHNZY7YKGXDCE2QG",
+ justification:
+ '{"id":"simple_comment","label":"Simple comment","version":1,"value":{"when":{"t_ms":1700488671251},"state":1,"threshold":{"currency":"STATER","fraction":0,"value":0},"comment":"asd asd asd "}}',
+ new_threshold: "STATER:0" as AmountString,
+ new_state: 1,
+ decision_time: {
+ t_s: 1700488677,
+ },
+ },
+ ],
+ [
+ {
+ collection_time: AbsoluteTime.toProtocolTimestamp(
+ AbsoluteTime.subtractDuraction(
+ AbsoluteTime.now(),
+ Duration.fromPrettyString("1d"),
+ ),
+ ),
+ expiration_time: { t_s: "never" },
+ provider_section: "asd",
+ attributes: {
+ email: "sebasjm@qwdde.com",
+ },
+ },
+ ],
+ nullTranslator,
+ [],
+ ),
+ until: AbsoluteTime.now(),
});
-
-
-
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
index 1115414c0..0169572bf 100644
--- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
@@ -62,14 +62,14 @@ export function ShowConsolidated({
fields: [
{
type: "amount",
- props: {
+ properties: {
label: i18n.str`Threshold`,
name: "aml.threshold",
},
},
{
type: "choiceHorizontal",
- props: {
+ properties: {
label: i18n.str`State`,
name: "aml.state",
choices: [
@@ -96,7 +96,7 @@ export function ShowConsolidated({
fields: Object.entries(cons.kyc).map(([key, field]) => {
const result: UIFormField = {
type: "text",
- props: {
+ properties: {
label: key as TranslatedString,
name: `kyc.${key}.value`,
help: `${field.provider} since ${
diff --git a/packages/web-util/src/forms/Calendar.tsx b/packages/web-util/src/forms/Calendar.tsx
index a0df639f3..b08129f56 100644
--- a/packages/web-util/src/forms/Calendar.tsx
+++ b/packages/web-util/src/forms/Calendar.tsx
@@ -1,20 +1,40 @@
-import { AbsoluteTime } from "@gnu-taler/taler-util"
-import { add as dateAdd, sub as dateSub, eachDayOfInterval, endOfMonth, endOfWeek, format, getMonth, getYear, isSameDay, isSameMonth, startOfDay, startOfMonth, startOfWeek } from "date-fns"
-import { VNode, h } from "preact"
-import { useState } from "preact/hooks"
-import { useTranslationContext } from "../index.browser.js"
+import { AbsoluteTime } from "@gnu-taler/taler-util";
+import {
+ add as dateAdd,
+ sub as dateSub,
+ eachDayOfInterval,
+ endOfMonth,
+ endOfWeek,
+ format,
+ getMonth,
+ getYear,
+ isSameDay,
+ isSameMonth,
+ startOfDay,
+ startOfMonth,
+ startOfWeek,
+} from "date-fns";
+import { VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { useTranslationContext } from "../index.browser.js";
-export function Calendar({ value, onChange }: { value: AbsoluteTime | undefined, onChange: (v: AbsoluteTime) => void }): VNode {
- const today = startOfDay(new Date())
- const selected = !value ? today : new Date(AbsoluteTime.toStampMs(value))
- const [showingDate, setShowingDate] = useState(selected)
- const month = getMonth(showingDate)
- const year = getYear(showingDate)
+export function Calendar({
+ value,
+ onChange,
+}: {
+ value: AbsoluteTime | undefined;
+ onChange: (v: AbsoluteTime) => void;
+}): VNode {
+ const today = startOfDay(new Date());
+ const selected = !value ? today : new Date(AbsoluteTime.toStampMs(value));
+ const [showingDate, setShowingDate] = useState(selected);
+ const month = getMonth(showingDate);
+ const year = getYear(showingDate);
const start = startOfWeek(startOfMonth(showingDate));
const end = endOfWeek(endOfMonth(showingDate));
const daysInMonth = eachDayOfInterval({ start, end });
- const { i18n } = useTranslationContext()
+ const { i18n } = useTranslationContext();
const monthNames = [
i18n.str`January`,
i18n.str`February`,
@@ -28,92 +48,139 @@ export function Calendar({ value, onChange }: { value: AbsoluteTime | undefined,
i18n.str`October`,
i18n.str`November`,
i18n.str`December`,
- ]
- return <div class="text-center p-2">
- <div class="flex items-center text-gray-900">
- <button type="button" class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
- onClick={() => {
- setShowingDate(dateSub(showingDate, { years: 1 }))
- }}>
- <span class="sr-only">
- {i18n.str`Previous year`}
- </span>
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
- </svg>
- </button>
- <div class="flex-auto text-sm font-semibold">{year}</div>
- <button type="button" class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
- onClick={() => {
- setShowingDate(dateAdd(showingDate, { years: 1 }))
- }}>
- <span class="sr-only">
- {i18n.str`Next year`}
- </span>
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
- </svg>
- </button>
- </div>
- <div class="mt-4 flex items-center text-gray-900">
- <button type="button" class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
- onClick={() => {
- setShowingDate(dateSub(showingDate, { months: 1 }))
- }}>
- <span class="sr-only">
- {i18n.str`Previous month`}
- </span>
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z" clip-rule="evenodd" />
- </svg>
- </button>
- <div class="flex-auto text-sm font-semibold">{monthNames[month]}</div>
- <button type="button" class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 rounded-sm "
- onClick={() => {
- setShowingDate(dateAdd(showingDate, { months: 1 }))
- }}>
- <span class="sr-only">
- {i18n.str`Next month`}
- </span>
- <svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
- <path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
- </svg>
- </button>
- </div>
- <div class="mt-6 grid grid-cols-7 text-xs leading-6 text-gray-500">
- <div>M</div>
- <div>T</div>
- <div>W</div>
- <div>T</div>
- <div>F</div>
- <div>S</div>
- <div>S</div>
- </div>
- <div class="isolate mt-2">
- <div class="grid grid-cols-7 gap-px rounded-lg bg-gray-200 text-sm shadow ring-1 ring-gray-200">
- {daysInMonth.map(current => (
- <button type="button"
- data-month={isSameMonth(current, showingDate)}
- data-today={isSameDay(current, today)}
- data-selected={isSameDay(current, selected)}
- onClick={() => {
- onChange(AbsoluteTime.fromStampMs(current.getTime()))
- }}
- class="text-gray-400 hover:bg-gray-700 focus:z-10 py-1.5
+ ];
+ return (
+ <div class="text-center p-2">
+ <div class="flex items-center text-gray-900">
+ <button
+ type="button"
+ class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
+ onClick={() => {
+ setShowingDate(dateSub(showingDate, { years: 1 }));
+ }}
+ >
+ <span class="sr-only">{i18n.str`Previous year`}</span>
+ <svg
+ class="h-5 w-5"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ aria-hidden="true"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
+ clip-rule="evenodd"
+ />
+ </svg>
+ </button>
+ <div class="flex-auto text-sm font-semibold">{year}</div>
+ <button
+ type="button"
+ class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
+ onClick={() => {
+ setShowingDate(dateAdd(showingDate, { years: 1 }));
+ }}
+ >
+ <span class="sr-only">{i18n.str`Next year`}</span>
+ <svg
+ class="h-5 w-5"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ aria-hidden="true"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
+ clip-rule="evenodd"
+ />
+ </svg>
+ </button>
+ </div>
+ <div class="mt-4 flex items-center text-gray-900">
+ <button
+ type="button"
+ class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 round-sm"
+ onClick={() => {
+ setShowingDate(dateSub(showingDate, { months: 1 }));
+ }}
+ >
+ <span class="sr-only">{i18n.str`Previous month`}</span>
+ <svg
+ class="h-5 w-5"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ aria-hidden="true"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
+ clip-rule="evenodd"
+ />
+ </svg>
+ </button>
+ <div class="flex-auto text-sm font-semibold">{monthNames[month]}</div>
+ <button
+ type="button"
+ class="flex px-4 flex-none items-center justify-center p-1.5 text-gray-400 hover:text-gray-500 ring-2 rounded-sm "
+ onClick={() => {
+ setShowingDate(dateAdd(showingDate, { months: 1 }));
+ }}
+ >
+ <span class="sr-only">{i18n.str`Next month`}</span>
+ <svg
+ class="h-5 w-5"
+ viewBox="0 0 20 20"
+ fill="currentColor"
+ aria-hidden="true"
+ >
+ <path
+ fill-rule="evenodd"
+ d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
+ clip-rule="evenodd"
+ />
+ </svg>
+ </button>
+ </div>
+ <div class="mt-6 grid grid-cols-7 text-xs leading-6 text-gray-500">
+ <div>M</div>
+ <div>T</div>
+ <div>W</div>
+ <div>T</div>
+ <div>F</div>
+ <div>S</div>
+ <div>S</div>
+ </div>
+ <div class="isolate mt-2">
+ <div class="grid grid-cols-7 gap-px rounded-lg bg-gray-200 text-sm shadow ring-1 ring-gray-200">
+ {daysInMonth.map((current, idx) => (
+ <button
+ type="button"
+ key={idx}
+ data-month={isSameMonth(current, showingDate)}
+ data-today={isSameDay(current, today)}
+ data-selected={isSameDay(current, selected)}
+ onClick={() => {
+ onChange(AbsoluteTime.fromStampMs(current.getTime()));
+ }}
+ class="text-gray-400 hover:bg-gray-700 focus:z-10 py-1.5
data-[month=false]:bg-gray-100 data-[month=true]:bg-white
data-[today=true]:font-semibold
data-[month=true]:text-gray-900
data-[today=true]:bg-red-300 data-[today=true]:hover:bg-red-200
data-[month=true]:hover:bg-gray-200
- data-[selected=true]:!bg-blue-400 data-[selected=true]:hover:!bg-blue-300 ">
- <time dateTime={format(current, "yyyy-MM-dd")}
- class="mx-auto flex h-7 w-7 py-4 px-5 sm:px-8 items-center justify-center rounded-full">
- {format(current, "dd")}
- </time>
- </button>
- ))}
+ data-[selected=true]:!bg-blue-400 data-[selected=true]:hover:!bg-blue-300 "
+ >
+ <time
+ dateTime={format(current, "yyyy-MM-dd")}
+ class="mx-auto flex h-7 w-7 py-4 px-5 sm:px-8 items-center justify-center rounded-full"
+ >
+ {format(current, "dd")}
+ </time>
+ </button>
+ ))}
+ </div>
+ {daysInMonth.length < 40 ? <div class="w-7 h-7 m-1.5" /> : undefined}
</div>
- {daysInMonth.length < 40 ? <div class="w-7 h-7 m-1.5" /> : undefined}
</div>
- </div>
+ );
}
diff --git a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
index 6245cf27c..3887efe37 100644
--- a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
+++ b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "absoluteTime",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "today",
pattern: "dd/MM/yyyy HH:mm"
diff --git a/packages/web-util/src/forms/InputAbsoluteTime.tsx b/packages/web-util/src/forms/InputAbsoluteTime.tsx
index 772ab1813..f5fd4fc50 100644
--- a/packages/web-util/src/forms/InputAbsoluteTime.tsx
+++ b/packages/web-util/src/forms/InputAbsoluteTime.tsx
@@ -10,15 +10,15 @@ import { useField } from "./useField.js";
import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
export function InputAbsoluteTime<T extends object, K extends keyof T>(
- props: { pattern?: string } & UIFormProps<T, K>,
+ properties: { pattern?: string } & UIFormProps<T, K>,
): VNode {
- const pattern = props.pattern ?? "dd/MM/yyyy";
+ const pattern = properties.pattern ?? "dd/MM/yyyy";
const [open, setOpen] = useState(false);
//FIXME: remove deprecated
- const fieldCtx = useField<T, K>(props.name);
+ const fieldCtx = useField<T, K>(properties.name);
const { value, onChange } =
- props.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(props.name);
+ properties.handler ?? fieldCtx ?? noHandlerPropsAndNoContextForField(properties.name);
return (
<Fragment>
<InputLine<T, K>
@@ -66,7 +66,7 @@ export function InputAbsoluteTime<T extends object, K extends keyof T>(
: format(v.t_ms, pattern);
},
}}
- {...props}
+ {...properties}
/>
{open && (
<Dialog onClose={() => setOpen(false)}>
diff --git a/packages/web-util/src/forms/InputAmount.stories.tsx b/packages/web-util/src/forms/InputAmount.stories.tsx
index c9f12a437..d5073ed86 100644
--- a/packages/web-util/src/forms/InputAmount.stories.tsx
+++ b/packages/web-util/src/forms/InputAmount.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "amount",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "amount",
},
diff --git a/packages/web-util/src/forms/InputArray.stories.tsx b/packages/web-util/src/forms/InputArray.stories.tsx
index 8dbd3ff07..eb61b04e3 100644
--- a/packages/web-util/src/forms/InputArray.stories.tsx
+++ b/packages/web-util/src/forms/InputArray.stories.tsx
@@ -54,18 +54,18 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "array",
- props: {
+ properties: {
label: "People" as TranslatedString,
name: "comment",
fields: [{
type: "text",
- props: {
+ properties: {
label: "the name" as TranslatedString,
name: "name",
}
}, {
type: "integer",
- props: {
+ properties: {
label: "the age" as TranslatedString,
name: "age",
}
diff --git a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
index b950d3d02..e1da89353 100644
--- a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
+++ b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "choiceHorizontal",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
choices: [{
diff --git a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
index ed5170d17..89f252e96 100644
--- a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
+++ b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "choiceStacked",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
choices: [{
diff --git a/packages/web-util/src/forms/InputFile.stories.tsx b/packages/web-util/src/forms/InputFile.stories.tsx
index ba06debf9..9d9ad0bd7 100644
--- a/packages/web-util/src/forms/InputFile.stories.tsx
+++ b/packages/web-util/src/forms/InputFile.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "file",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
required: true,
diff --git a/packages/web-util/src/forms/InputInteger.stories.tsx b/packages/web-util/src/forms/InputInteger.stories.tsx
index bd1a467ab..04a6d1049 100644
--- a/packages/web-util/src/forms/InputInteger.stories.tsx
+++ b/packages/web-util/src/forms/InputInteger.stories.tsx
@@ -43,7 +43,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "integer",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "age",
tooltip: "just numbers" as TranslatedString,
diff --git a/packages/web-util/src/forms/InputLine.stories.tsx b/packages/web-util/src/forms/InputLine.stories.tsx
index da41a221e..1c62a6164 100644
--- a/packages/web-util/src/forms/InputLine.stories.tsx
+++ b/packages/web-util/src/forms/InputLine.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "text",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
},
diff --git a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
index 6ce5445c0..b1649fecf 100644
--- a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
+++ b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx
@@ -50,7 +50,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "selectMultiple",
- props: {
+ properties: {
label: "allow diplicates" as TranslatedString,
name: "pets",
placeholder: "search..." as TranslatedString,
@@ -67,7 +67,7 @@ const form: FlexibleForm<TargetObject> = {
},
}, {
type: "selectMultiple",
- props: {
+ properties: {
label: "unique values" as TranslatedString,
name: "things",
unique: true,
diff --git a/packages/web-util/src/forms/InputSelectMultiple.tsx b/packages/web-util/src/forms/InputSelectMultiple.tsx
index 972389cb3..12e88fcc1 100644
--- a/packages/web-util/src/forms/InputSelectMultiple.tsx
+++ b/packages/web-util/src/forms/InputSelectMultiple.tsx
@@ -1,10 +1,10 @@
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
import { UIFormProps } from "./FormProvider.js";
+import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { ChoiceS } from "./InputChoiceStacked.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";
import { useField } from "./useField.js";
-import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
export function InputSelectMultiple<T extends object, K extends keyof T>(
props: {
diff --git a/packages/web-util/src/forms/InputSelectOne.stories.tsx b/packages/web-util/src/forms/InputSelectOne.stories.tsx
index 9e9029a77..f87aeda66 100644
--- a/packages/web-util/src/forms/InputSelectOne.stories.tsx
+++ b/packages/web-util/src/forms/InputSelectOne.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "selectOne",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "things",
placeholder: "search..." as TranslatedString,
diff --git a/packages/web-util/src/forms/InputText.stories.tsx b/packages/web-util/src/forms/InputText.stories.tsx
index 04ab8a1c6..8eced7736 100644
--- a/packages/web-util/src/forms/InputText.stories.tsx
+++ b/packages/web-util/src/forms/InputText.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "text",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
},
diff --git a/packages/web-util/src/forms/InputTextArea.stories.tsx b/packages/web-util/src/forms/InputTextArea.stories.tsx
index c8c3eb088..6713548a8 100644
--- a/packages/web-util/src/forms/InputTextArea.stories.tsx
+++ b/packages/web-util/src/forms/InputTextArea.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "text",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
},
diff --git a/packages/web-util/src/forms/InputToggle.stories.tsx b/packages/web-util/src/forms/InputToggle.stories.tsx
index ca6857618..e10098718 100644
--- a/packages/web-util/src/forms/InputToggle.stories.tsx
+++ b/packages/web-util/src/forms/InputToggle.stories.tsx
@@ -48,7 +48,7 @@ const form: FlexibleForm<TargetObject> = {
title: "this is a simple form" as TranslatedString,
fields: [{
type: "toggle",
- props: {
+ properties: {
label: "label of the field" as TranslatedString,
name: "comment",
},
diff --git a/packages/web-util/src/forms/InputToggle.tsx b/packages/web-util/src/forms/InputToggle.tsx
index c56efec3a..58386045c 100644
--- a/packages/web-util/src/forms/InputToggle.tsx
+++ b/packages/web-util/src/forms/InputToggle.tsx
@@ -1,8 +1,8 @@
import { VNode, h } from "preact";
import { UIFormProps } from "./FormProvider.js";
+import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";
import { useField } from "./useField.js";
-import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
export function InputToggle<T extends object, K extends keyof T>(
props: UIFormProps<T, K>,
diff --git a/packages/web-util/src/forms/forms.ts b/packages/web-util/src/forms/forms.ts
index d2ff9c37e..6bda2f674 100644
--- a/packages/web-util/src/forms/forms.ts
+++ b/packages/web-util/src/forms/forms.ts
@@ -38,20 +38,32 @@ type FieldType<T extends object = any, K extends keyof T = any> = {
* List all the form fields so typescript can type-check the form instance
*/
export type UIFormField =
- | { type: "group"; props: FieldType["group"] }
- | { type: "caption"; props: FieldType["caption"] }
- | { type: "array"; props: FieldType["array"] }
- | { type: "file"; props: FieldType["file"] }
- | { type: "amount"; props: FieldType["amount"] }
- | { type: "selectOne"; props: FieldType["selectOne"] }
- | { type: "selectMultiple"; props: FieldType["selectMultiple"] }
- | { type: "text"; props: FieldType["text"] }
- | { type: "textArea"; props: FieldType["textArea"] }
- | { type: "choiceStacked"; props: FieldType["choiceStacked"] }
- | { type: "choiceHorizontal"; props: FieldType["choiceHorizontal"] }
- | { type: "integer"; props: FieldType["integer"] }
- | { type: "toggle"; props: FieldType["toggle"] }
- | { type: "absoluteTime"; props: FieldType["absoluteTime"] };
+ | { type: "group"; properties: FieldType["group"] }
+ | { type: "caption"; properties: FieldType["caption"] }
+ | { type: "array"; properties: FieldType["array"] }
+ | { type: "file"; properties: FieldType["file"] }
+ | { type: "amount"; properties: FieldType["amount"] }
+ | { type: "selectOne"; properties: FieldType["selectOne"] }
+ | {
+ type: "selectMultiple";
+ properties: FieldType["selectMultiple"];
+ }
+ | { type: "text"; properties: FieldType["text"] }
+ | { type: "textArea"; properties: FieldType["textArea"] }
+ | {
+ type: "choiceStacked";
+ properties: FieldType["choiceStacked"];
+ }
+ | {
+ type: "choiceHorizontal";
+ properties: FieldType["choiceHorizontal"];
+ }
+ | { type: "integer"; properties: FieldType["integer"] }
+ | { type: "toggle"; properties: FieldType["toggle"] }
+ | {
+ type: "absoluteTime";
+ properties: FieldType["absoluteTime"];
+ };
type FieldComponentFunction<key extends keyof FieldType> = (
props: FieldType[key],
@@ -102,7 +114,7 @@ export function RenderAllFieldsByUiConfig({
const Component = UIFormConfiguration[
field.type
] as FieldComponentFunction<any>;
- return Component(field.props);
+ return Component(field.properties);
}),
);
}
@@ -115,8 +127,8 @@ export function RenderAllFieldsByUiConfig({
/**
* Helper function that created a typed object.
- *
- * @returns
+ *
+ * @returns
*/
// export function createNewForm<T extends object>() {
// const res: FormSet<T> = {