[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-wallet-core] branch master updated: working on array input
From: |
gnunet |
Subject: |
[taler-wallet-core] branch master updated: working on array input |
Date: |
Mon, 09 Dec 2024 14:50:23 +0100 |
This is an automated email from the git hooks/post-receive script.
sebasjm pushed a commit to branch master
in repository wallet-core.
The following commit(s) were added to refs/heads/master by this push:
new 9f401ff16 working on array input
9f401ff16 is described below
commit 9f401ff1601181f9476f10b6a42daf1fc372115c
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon Dec 9 10:50:02 2024 -0300
working on array input
---
.../src/pages/ShowConsolidated.tsx | 1 -
packages/kyc-ui/src/forms.json | 376 ++++++++++++++++++++-
packages/kyc-ui/src/hooks/form.ts | 1 +
packages/kyc-ui/src/pages/FillForm.tsx | 88 ++---
packages/kyc-ui/src/pages/TriggerKyc.tsx | 188 ++++++++---
packages/web-util/src/forms/InputArray.stories.tsx | 81 ++++-
packages/web-util/src/forms/InputArray.tsx | 83 +++--
packages/web-util/src/forms/InputLine.tsx | 2 +-
packages/web-util/src/forms/forms.ts | 5 +-
9 files changed, 683 insertions(+), 142 deletions(-)
diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
index fcec8609a..6ec6b787a 100644
--- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
+++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx
@@ -69,7 +69,6 @@ export function ShowConsolidated({
const formConfig: FormConfiguration = {
type: "double-column",
design: Object.entries(fixed).length > 0 ? [
-
{
title: i18n.str`KYC collected info`,
fields: Object.entries(fixed).map(([key, field]) => {
diff --git a/packages/kyc-ui/src/forms.json b/packages/kyc-ui/src/forms.json
index b0c198574..8e7d6bcdc 100644
--- a/packages/kyc-ui/src/forms.json
+++ b/packages/kyc-ui/src/forms.json
@@ -12,34 +12,34 @@
"description": "Establishment of the beneficial owner of the
assets and/or controlling person",
"fields": [
{
- "type": "choiceStacked",
"id": "LEGAL_ENTITY_TYPE",
"label": "The customer is",
"required": true,
+ "type": "choiceStacked",
"choices": [
{
"label": "a natural person and there are no doubts that
this person is the sole beneficial owner of the assets",
- "value": "natural"
+ "value": "NATURAL"
},
{
"label": "a foundation (or a similar construct; incl.
underlying companies)",
- "value": "foundation"
+ "value": "FOUNDATION"
},
{
"label": "an operation legal entity or partnership",
- "value": "legal-entity"
+ "value": "OPERATIONAL"
},
{
"label": "a trust (incl. underlying companies)",
- "value": "trust"
+ "value": "TRUST"
},
{
"label": "a life insurance policy with separately managed
accounts/securities accounts",
- "value": "insurance"
+ "value": "LIFEINSURANCE"
},
{
"label": "all other cases",
- "value": "other"
+ "value": "OTHER"
}
]
}
@@ -66,7 +66,7 @@
"choices": [
{
"label": "natural",
- "value": "natural"
+ "value": "NATURAL"
}
]
}
@@ -77,7 +77,7 @@
},
{
"label": "VQF legal entity form",
- "id": "vqf-legal-entity",
+ "id": "vqf-operational",
"version": 1,
"config": {
"type": "double-column",
@@ -93,7 +93,7 @@
"choices": [
{
"label": "legal entity",
- "value": "natural"
+ "value": "NATURAL"
}
]
}
@@ -120,7 +120,7 @@
"choices": [
{
"label": "foundation",
- "value": "natural"
+ "value": "NATURAL"
}
]
}
@@ -147,7 +147,7 @@
"choices": [
{
"label": "trust",
- "value": "natural"
+ "value": "NATURAL"
}
]
}
@@ -174,7 +174,7 @@
"choices": [
{
"label": "insurance",
- "value": "natural"
+ "value": "NATURAL"
}
]
}
@@ -201,9 +201,357 @@
"choices": [
{
"label": "other",
- "value": "natural"
+ "value": "NATURAL"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "label": "GLS Onboarding form",
+ "id": "gls-onboarding",
+ "version": 1,
+ "config": {
+ "type": "double-column",
+ "design": [
+ {
+ "title": "Personal information",
+ "fields": [
+ {
+ "type": "text",
+ "id": "PERSON_FULL_NAME",
+ "label": "Full name",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "PERSON_LAST_NAME",
+ "label": "Last name",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "CONTACT_PHONE",
+ "label": "Phone",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "CONTACT_EMAIL",
+ "label": "E-Mail",
+ "required": true
+ },
+ {
+ "type": "toggle",
+ "id": "ACCEPTED_TERMS_OF_SERVICE",
+ "label": "I accept terms of service",
+ "required": true
+ }
+ ]
+ },
+ {
+ "title": "Business information",
+ "fields": [
+ {
+ "type": "text",
+ "id": "BUSINESS_DISPLAY_NAME",
+ "label": "Name",
+ "required": true
+ },
+ {
+ "type": "selectOne",
+ "id": "BUSINESS_TYPE",
+ "label": "The company type is",
+ "required": true,
+ "choices": [
+ {
+ "label": "GmbH",
+ "value": "GMBH"
+ },
+ {
+ "label": "ug",
+ "value": "UG"
+ },
+ {
+ "label": "an operation legal entity or partnership",
+ "value": "OPERATIONAL"
+ },
+ {
+ "label": "ohg",
+ "value": "OHG"
+ },
+ {
+ "label": "kg",
+ "value": "KG"
+ },
+ {
+ "label": "eg",
+ "value": "EG"
+ },
+ {
+ "label": "eV",
+ "value": "EV"
+ },
+ {
+ "label": "PartG",
+ "value": "PARTG"
+ },
+ {
+ "label": "ek",
+ "value": "EK"
+ },
+ {
+ "label": "AG (nicht börsennotiert)",
+ "value": "AGNB"
+ },
+ {
+ "label": "AG (börsennotiert)",
+ "value": "AGB"
+ },
+ {
+ "label": "GbR",
+ "value": "GBR"
+ },
+ {
+ "label": "n.e.V.",
+ "value": "NEV"
+ },
+ {
+ "label": "Partei",
+ "value": "PARTEI"
+ },
+ {
+ "label": "GmbH i.G.",
+ "value": "GMBHIG"
+ },
+ {
+ "label": "eG. i.G.",
+ "value": "EGIG"
+ },
+ {
+ "label": "e.V. i.G.",
+ "value": "EVIG"
+ },
+ {
+ "label": "Other",
+ "value": "OTHER"
}
]
+ },
+ {
+ "type": "text",
+ "id": "BUSINESS_REGISTRATION_ID",
+ "label": "Registration ID",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "BUSINESS_LEGAL_JURISDICTION",
+ "label": "Legal jurisdiction",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "BUSINESS_REGISTRATION_DATE",
+ "label": "Founding date",
+ "required": true
+ },
+ {
+ "type": "toggle",
+ "id": "BUSINESS_IS_NON_PROFIT",
+ "label": "I this company a non-profit?",
+ "required": true
+ }
+ ]
+ },
+ {
+ "title": "Business industry",
+ "fields": [
+ {
+ "type": "selectOne",
+ "id": "BUSINESS_INDUSTRY",
+ "label": "Industry",
+ "choices": [{
+ "label": "Car",
+ "value": "CAR"
+ },{
+ "label": "Food",
+ "value": "FOOD"
+ },{
+ "description": "preventing... not doing it",
+ "label": "Money laundry",
+ "value": "MONEY"
+ }],
+ "required": true
+ }
+ ]
+ },
+ {
+ "title": "Adress",
+ "fields": [
+ {
+ "type": "text",
+ "id": "ADDRESS_STREET_NAME",
+ "label": "Street name",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_STREET_NUMBER",
+ "label": "Street number",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_BUILDING_NAME",
+ "label": "Building name",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_BUILDING_NUMBER",
+ "label": "Building number",
+ "required": true
+ },
+ {
+ "type": "textArea",
+ "id": "ADDRESS_LINES",
+ "label": "Additional address reference",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_TOWN_LOCATION",
+ "label": "Building number",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_TOWN_DISTRICT",
+ "label": "Building number",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_COUNTRY_SUBDIVISION",
+ "label": "Building number",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "ADDRESS_COUNTRY_CC",
+ "label": "Building number",
+ "required": true
+ }
+ ]
+ },
+ {
+ "title": "Tax information",
+ "fields": [
+ {
+ "type": "text",
+ "id": "TAX_COUNTRY_CC",
+ "label": "Country tax",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "TAX_ID",
+ "label": "Tax identifier",
+ "required": true
+ },
+ {
+ "type": "toggle",
+ "id": "TAX_IS_USA_LAW",
+ "label": "Is business founded or under USA law?",
+ "required": true
+ },
+ {
+ "type": "toggle",
+ "id": "TAX_IS_ACTIVE",
+ "label": "Is the business economically active?",
+ "required": true
+ },
+ {
+ "type": "toggle",
+ "id": "TAX_IS_DEDUCTED",
+ "label": "Is the business economically active",
+ "required": true
+ }
+ ]
+ },
+ {
+ "title": "Representatives",
+ "fields": [
+ {
+ "type": "array",
+ "id": "BUSINESS_LEGAL_REPRESENTATIVES",
+ "labelFieldId": "CONTACT_PHONE",
+ "label": "List of natural persons that are legal
representatives or shareholders",
+ "fields": [
+ {
+ "type": "text",
+ "id": "PERSON_FULL_NAME",
+ "label": "Name",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "PERSON_DATE_OF_BIRTH",
+ "label": "Date of birth",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "CONTACT_PHONE",
+ "label": "Phone",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "CONTACT_EMAIL",
+ "label": "E-Mail",
+ "required": true
+ },
+ {
+ "type": "text",
+ "id": "PERSON_NATIONALITY_CC",
+ "label": "Nationality",
+ "required": true
+ },
+ {
+ "id": "PERSON_BUSINESS_REPRESENTATIVE_TYPE",
+ "label": "Full name",
+ "required": true,
+ "type": "choiceStacked",
+ "choices": [
+ {
+ "label": "Individual",
+ "value": "INDIVIDUAL"
+ },
+ {
+ "label": "Authorized to represent",
+ "value": "AUTHORIZED"
+ },
+ {
+ "label": "Majority",
+ "value": "MAJORITY"
+ },
+ {
+ "label": "In pair",
+ "value": "IN_PAIR"
+ },
+ {
+ "label": "Other",
+ "value": "OTHERS"
+ }
+ ]
+ }
+ ],
+ "required": true
}
]
}
diff --git a/packages/kyc-ui/src/hooks/form.ts
b/packages/kyc-ui/src/hooks/form.ts
index 452deabaf..c2f5b41b5 100644
--- a/packages/kyc-ui/src/hooks/form.ts
+++ b/packages/kyc-ui/src/hooks/form.ts
@@ -92,6 +92,7 @@ function constructFormHandler<T>(
const path = fieldId.split(".");
function updater(newValue: unknown) {
+ console.log("----",path, newValue)
updateForm(setValueDeeper(form, path, newValue));
}
diff --git a/packages/kyc-ui/src/pages/FillForm.tsx
b/packages/kyc-ui/src/pages/FillForm.tsx
index 52b893e40..760603318 100644
--- a/packages/kyc-ui/src/pages/FillForm.tsx
+++ b/packages/kyc-ui/src/pages/FillForm.tsx
@@ -24,6 +24,7 @@ import {
import {
Button,
FormMetadata,
+ FormProvider,
InternationalizationAPI,
LocalNotificationBanner,
RenderAllFieldsByUiConfig,
@@ -89,13 +90,8 @@ export function FillForm({
: undefined;
const { forms } = useUiFormsContext();
- const allForms = customForm ? [...forms, customForm] : forms
- const theForm = searchForm(
- i18n,
- allForms,
- formId,
- requirement.context,
- );
+ const allForms = customForm ? [...forms, customForm] : forms;
+ const theForm = searchForm(i18n, allForms, formId, requirement.context);
if (!theForm) {
return <div>form with id {formId} not found</div>;
}
@@ -107,12 +103,13 @@ export function FillForm({
const requiredFields: Array<UIHandlerId> = [];
theForm.config.design.forEach((section) => {
- Array.prototype.push.apply(shape, getShapeFromFields(section.fields));
+ Array.prototype.push.apply(shape, getShapeFromFields(section.fields, ""));
Array.prototype.push.apply(
requiredFields,
getRequiredFields(section.fields),
);
});
+
const [form, state] = useFormState<FormType>(shape, {}, (st) => {
const partialErrors = undefinedIfEmpty<FormErrors<FormType>>({});
@@ -186,43 +183,44 @@ export function FillForm({
<div class="rounded-lg bg-white px-5 py-6 shadow m-4">
<LocalNotificationBanner notification={notification} />
<div class="space-y-10 divide-y -mt-5 divide-gray-900/10">
- {theForm.config.design.map((section, i) => {
- if (!section) return <Fragment />;
- return (
- <div
- key={i}
- class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3"
- >
- <div class="px-4 sm:px-0">
- <h2 class="text-base font-semibold leading-7 text-gray-900">
- {section.title}
- </h2>
- {section.description && (
- <p class="mt-1 text-sm leading-6 text-gray-600">
- {section.description}
- </p>
- )}
- </div>
- <div class="bg-white shadow-sm ring-1 ring-gray-900/5 rounded-md
md:col-span-2">
- <div class="p-3">
- <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8
sm:grid-cols-6">
- <RenderAllFieldsByUiConfig
- key={i}
- fields={convertUiField(
- i18n,
- section.fields,
- form,
- getConverterById,
- )}
- />
+ {theForm.config.design.map((section, i) => {
+ if (!section) return <Fragment />;
+ return (
+ <div
+ key={i}
+ class="grid grid-cols-1 gap-x-8 gap-y-8 pt-5 md:grid-cols-3"
+ >
+ <div class="px-4 sm:px-0">
+ <h2 class="text-base font-semibold leading-7 text-gray-900">
+ {section.title}
+ </h2>
+ {section.description && (
+ <p class="mt-1 text-sm leading-6 text-gray-600">
+ {section.description}
+ </p>
+ )}
+ </div>
+ <div class="bg-white shadow-sm ring-1 ring-gray-900/5
rounded-md md:col-span-2">
+ <div class="p-3">
+ <div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8
sm:grid-cols-6">
+ <RenderAllFieldsByUiConfig
+ key={i}
+ fields={convertUiField(
+ i18n,
+ section.fields,
+ form,
+ getConverterById,
+ )}
+ />
+ </div>
</div>
</div>
</div>
- </div>
- );
- })}
+ );
+ })}
</div>
+ <pre>{JSON.stringify(state.result, undefined, 2)}</pre>
<div class="mt-6 flex items-center justify-end gap-x-6">
<button
onClick={onComplete}
@@ -262,7 +260,10 @@ function getRequiredFields(fields: UIFormElementConfig[]):
Array<UIHandlerId> {
});
return shape;
}
-function getShapeFromFields(fields: UIFormElementConfig[]): Array<UIHandlerId>
{
+function getShapeFromFields(
+ fields: UIFormElementConfig[],
+ parent: string,
+): Array<UIHandlerId> {
const shape: Array<UIHandlerId> = [];
fields.forEach((field) => {
if ("id" in field) {
@@ -273,7 +274,10 @@ function getShapeFromFields(fields:
UIFormElementConfig[]): Array<UIHandlerId> {
}
shape.push(field.id);
} else if (field.type === "group") {
- Array.prototype.push.apply(shape, getShapeFromFields(field.fields));
+ Array.prototype.push.apply(
+ shape,
+ getShapeFromFields(field.fields, parent),
+ );
}
});
return shape;
diff --git a/packages/kyc-ui/src/pages/TriggerKyc.tsx
b/packages/kyc-ui/src/pages/TriggerKyc.tsx
index c7d2fa4cb..ce4730011 100644
--- a/packages/kyc-ui/src/pages/TriggerKyc.tsx
+++ b/packages/kyc-ui/src/pages/TriggerKyc.tsx
@@ -131,25 +131,25 @@ export function TriggerKyc({ onKycStarted }: Props):
VNode {
useEffect(() => {
if (!kycAccount) return;
- const paytoHash = kycAccount
+ const paytoHash = kycAccount;
async function check() {
- const {signingKey} = await accountPromise;
+ const { signingKey } = await accountPromise;
const result = await lib.exchange.checkKycStatus(signingKey, paytoHash);
if (result.type === "ok") {
if (result.body) {
- onKycStarted(result.body.access_token)
+ onKycStarted(result.body.access_token);
} else {
- console.log("empty body")
+ console.log("empty body");
}
} else {
- switch(result.case) {
- case HttpStatusCode.Forbidden:{
+ switch (result.case) {
+ case HttpStatusCode.Forbidden: {
notify({
type: "error",
title: i18n.str`could not create token`,
description: i18n.str`access denied`,
when: AbsoluteTime.now(),
- })
+ });
}
case HttpStatusCode.NotFound: {
notify({
@@ -157,7 +157,7 @@ export function TriggerKyc({ onKycStarted }: Props): VNode {
title: i18n.str`could not create token`,
description: i18n.str`not found`,
when: AbsoluteTime.now(),
- })
+ });
}
case HttpStatusCode.Conflict: {
notify({
@@ -165,49 +165,52 @@ export function TriggerKyc({ onKycStarted }: Props):
VNode {
title: i18n.str`could not create token`,
description: i18n.str`conflict`,
when: AbsoluteTime.now(),
- })
-
+ });
}
}
}
}
- check()
+ check();
}, [kycAccount]);
- const submitHandler =
- theForm === undefined || state.status === "fail"
- ? undefined
- : withErrorHandler(
- async () => {
- const account = await accountPromise;
+ function triggerAmount(amount:AmountJson) {
+ return withErrorHandler(
+ async () => {
+ const account = await accountPromise;
- return lib.exchange.notifyKycBalanceLimit(
- account,
- Amounts.stringify(state.result.amount),
- );
- },
- (res) => {
- notify({
- type: "info",
- title: i18n.str`No kyc required`,
- when: AbsoluteTime.now(),
- });
- },
- (fail) => {
- switch (fail.case) {
- case HttpStatusCode.Forbidden:
- return i18n.str`Access denied trying to test balance.`;
- case HttpStatusCode.UnavailableForLegalReasons:
- setKycAccount(fail.body.h_payto);
- return i18n.str`Unavailable For Legal Reasons`;
- default:
- assertUnreachable(fail);
- }
- },
+ return lib.exchange.notifyKycBalanceLimit(
+ account,
+ Amounts.stringify(amount),
);
+ },
+ (res) => {
+ notify({
+ type: "info",
+ title: i18n.str`No kyc required`,
+ when: AbsoluteTime.now(),
+ });
+ },
+ (fail) => {
+ switch (fail.case) {
+ case HttpStatusCode.Forbidden:
+ return i18n.str`Access denied trying to test balance.`;
+ case HttpStatusCode.UnavailableForLegalReasons:
+ setKycAccount(fail.body.h_payto);
+ return i18n.str`Unavailable For Legal Reasons`;
+ default:
+ assertUnreachable(fail);
+ }
+ },
+ )
+ }
+
+ const sendFormValue =
+ theForm === undefined || state.status === "fail"
+ ? undefined
+ : triggerAmount(state.result.amount);
if (kycAccount) {
- return <div>loading...</div>
+ return <div>loading...</div>;
}
return (
@@ -260,13 +263,114 @@ export function TriggerKyc({ onKycStarted }: Props):
VNode {
</button>
<Button
type="submit"
- handler={submitHandler}
+ handler={sendFormValue}
// disabled={!submitHandler}
class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
<i18n.Translate>Confirm</i18n.Translate>
</Button>
</div>
+
+ <div class="grid grid-cols-1 gap-x-8 gap-y-4 ">
+ <p>
+ <i18n.Translate>
+ This actions will trigger wallet balance kyc above 1000000
+ threshold, the exchange should be properly configured to trigger
the
+ desired kyc flow.
+ </i18n.Translate>
+ </p>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000070`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger TOPS Terms of service</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000080`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger GLS onboarding</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000000`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF Start</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000010`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF Natural</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000020`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF operational</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000030`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF foundation</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000040`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF insurance</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000050`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF trust</i18n.Translate>
+ </Button>
+ </div>
+ <div>
+ <Button
+ type="submit"
+
handler={triggerAmount(Amounts.parseOrThrow(`${config.currency}:1000060`))}
+ // disabled={!submitHandler}
+ class="disabled:opacity-50 disabled:cursor-default rounded-md
bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm
hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2
focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ <i18n.Translate>Trigger VQF other</i18n.Translate>
+ </Button>
+ </div>
+
+ </div>
</div>
);
}
diff --git a/packages/web-util/src/forms/InputArray.stories.tsx
b/packages/web-util/src/forms/InputArray.stories.tsx
index fc6889189..6f478fd07 100644
--- a/packages/web-util/src/forms/InputArray.stories.tsx
+++ b/packages/web-util/src/forms/InputArray.stories.tsx
@@ -61,20 +61,21 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
{
type: "array",
label: "People" as TranslatedString,
- fields: [ {
- id: "name" as UIHandlerId,
- type: "text",
- required: true,
- label: "Name" as TranslatedString,
- },
- {
- id: "age" as UIHandlerId,
- type: "integer",
- required: true,
- label: "Age" as TranslatedString,
- },
- ],
- id: "name" as UIHandlerId,
+ fields: [
+ {
+ id: "name" as UIHandlerId,
+ type: "text",
+ required: true,
+ label: "Name" as TranslatedString,
+ },
+ {
+ id: "age" as UIHandlerId,
+ type: "integer",
+ required: true,
+ label: "Age" as TranslatedString,
+ },
+ ],
+ id: "people" as UIHandlerId,
labelFieldId: "name" as UIHandlerId,
},
],
@@ -82,7 +83,57 @@ const form: FlexibleForm_Deprecated<TargetObject> = {
],
};
-export const SimpleComment = tests.createExample(TestedComponent, {
+export const FormWithArray = tests.createExample(TestedComponent, {
initial,
form,
});
+
+const initial2: any = {
+};
+
+const form2: FlexibleForm_Deprecated<TargetObject> = {
+ design: [
+ {
+ title: "Personal information" as TranslatedString,
+ fields: [
+ {
+ type: "text",
+ id: "PERSON_FULL_NAME" as UIHandlerId,
+ label: "Full name",
+ required: true,
+ },
+ ],
+ },
+ {
+ title: "Representatives" as TranslatedString,
+ fields: [
+ {
+ type: "array",
+ id: "BUSINESS_LEGAL_REPRESENTATIVES" as UIHandlerId,
+ labelFieldId: "PERSON_FULL_NAME" as UIHandlerId,
+ label:
+ "List of natural persons that are legal representatives or
shareholders",
+ fields: [
+ {
+ type: "text",
+ id: "PERSON_FULL_NAME" as UIHandlerId,
+ label: "Name",
+ required: true,
+ },
+ {
+ type: "text",
+ id: "PERSON_DATE_OF_BIRTH" as UIHandlerId,
+ label: "Date of birth",
+ required: true,
+ },
+ ],
+ },
+ ],
+ },
+ ],
+};
+
+export const NonMixingProperties = tests.createExample(TestedComponent, {
+ initial: initial2,
+ form: form2,
+});
diff --git a/packages/web-util/src/forms/InputArray.tsx
b/packages/web-util/src/forms/InputArray.tsx
index 6b14a65b7..5db185561 100644
--- a/packages/web-util/src/forms/InputArray.tsx
+++ b/packages/web-util/src/forms/InputArray.tsx
@@ -5,6 +5,7 @@ import { FormProvider, UIFormProps } from "./FormProvider.js";
import { LabelWithTooltipMaybeRequired } from "./InputLine.js";
import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js";
import { useField } from "./useField.js";
+import { UIFormElementConfig, UIHandlerId } from "./ui-form.js";
function Option({
label,
@@ -79,6 +80,28 @@ export function noHandlerPropsAndNoContextForField(
);
}
+function getShapeFromFields(
+ fields: UIFormElementConfig[],
+): Array<UIHandlerId> {
+ const shape: Array<UIHandlerId> = [];
+ fields.forEach((field) => {
+ if ("id" in field) {
+ // FIXME: this should be a validation when loading the form
+ // consistency check
+ if (shape.indexOf(field.id) !== -1) {
+ throw Error(`already present: ${field.id}`);
+ }
+ shape.push(field.id);
+ } else if (field.type === "group") {
+ Array.prototype.push.apply(
+ shape,
+ getShapeFromFields(field.fields),
+ );
+ }
+ });
+ return shape;
+}
+
export function InputArray<T extends object, K extends keyof T>(
props: {
fields: UIFormField[];
@@ -102,6 +125,16 @@ export function InputArray<T extends object, K extends
keyof T>(
const selected =
selectedIndex === undefined ? undefined : list[selectedIndex];
+ const shape: Array<UIHandlerId> = [];
+ const requiredFields: Array<UIHandlerId> = [];
+
+ Array.prototype.push.apply(shape, getShapeFromFields(fields));
+ Array.prototype.push.apply(
+ requiredFields,
+ getRequiredFields(fields),
+ );
+
+
return (
<div class="sm:col-span-6">
<LabelWithTooltipMaybeRequired
@@ -153,36 +186,36 @@ export function InputArray<T extends object, K extends
keyof T>(
* This form provider act as a substate of the parent form
* Consider creating an InnerFormProvider since not every feature is
expected
*/
- <FormProvider
- initial={selected}
- readOnly={state.disabled}
- computeFormState={(v) => {
- // current state is ignored
- // the state is defined by the parent form
+ // <FormProvider
+ // initial={selected ?? {}}
+ // readOnly={state.disabled}
+ // computeFormState={(v) => {
+ // // current state is ignored
+ // // the state is defined by the parent form
- // elements should be present in the state object since this is
expected to be an array
- //@ts-ignore
- // return state.elements[selectedIndex];
- return {};
- }}
- onSubmit={(v) => {
- const newValue = [...list];
- newValue.splice(selectedIndex, 1, v);
- onChange(newValue as any);
- setSelectedIndex(undefined);
- }}
- onUpdate={(v) => {
- const newValue = [...list];
- newValue.splice(selectedIndex, 1, v);
- onChange(newValue as any);
- }}
- >
+ // // elements should be present in the state object since this
is expected to be an array
+ // //@ts-ignore
+ // // return state.elements[selectedIndex];
+ // return {};
+ // }}
+ // onSubmit={(v) => {
+ // const newValue = [...list];
+ // newValue.splice(selectedIndex, 1, v);
+ // onChange(newValue as any);
+ // setSelectedIndex(undefined);
+ // }}
+ // onUpdate={(v) => {
+ // const newValue = [...list];
+ // newValue.splice(selectedIndex, 1, v);
+ // onChange(newValue as any);
+ // }}
+ // >
<div class="px-4 py-6">
<div class="grid grid-cols-1 gap-y-8 ">
- <RenderAllFieldsByUiConfig fields={fields} />
+ <RenderAllFieldsByUiConfig fields={fields} />
</div>
</div>
- </FormProvider>
+ // </FormProvider>
)}
{selectedIndex !== undefined && (
<div class="flex items-center justify-end gap-x-6">
diff --git a/packages/web-util/src/forms/InputLine.tsx
b/packages/web-util/src/forms/InputLine.tsx
index 4c0176195..db5e00551 100644
--- a/packages/web-util/src/forms/InputLine.tsx
+++ b/packages/web-util/src/forms/InputLine.tsx
@@ -164,7 +164,7 @@ export function InputLine<T extends object, K extends keyof
T>(
//FIXME: remove deprecated
const fieldCtx = useField<T, K>(props.name);
const { value, onChange, state, error } =
- props.handler ?? fieldCtx ??
noHandlerPropsAndNoContextForField(props.name);
+ props.handler ?? noHandlerPropsAndNoContextForField(props.name);
// const [text, setText] = useState("");
const fromString: (s: string) => any =
diff --git a/packages/web-util/src/forms/forms.ts
b/packages/web-util/src/forms/forms.ts
index 70c090fb1..ce9b9e258 100644
--- a/packages/web-util/src/forms/forms.ts
+++ b/packages/web-util/src/forms/forms.ts
@@ -19,7 +19,7 @@ import {
UIFieldElementDescription,
} from "../index.browser.js";
import { assertUnreachable, TranslatedString } from "@gnu-taler/taler-util";
-import { UIFormFieldBaseConfig, UIFormElementConfig } from "./ui-form.js";
+import { UIFormFieldBaseConfig, UIFormElementConfig, UIHandlerId } from
"./ui-form.js";
import { HtmlIframe } from "./HtmlIframe.js";
/**
* Constrain the type with the ui props
@@ -215,7 +215,7 @@ export function convertUiField(
fields: convertUiField(
i18n_,
config.fields,
- form,
+ (form as any)[config.id].value ?? {},
getConverterById,
),
},
@@ -349,6 +349,7 @@ function converInputFieldsProps(
getConverterById: GetConverterById,
) {
const names = p.id.split(".");
+ console.log("NAMES", names, getValueDeeper2(form, names), form !== undefined)
return {
converter: getConverterById(p.converterId, p),
handler: getValueDeeper2(form, names),
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-wallet-core] branch master updated: working on array input,
gnunet <=