diff options
18 files changed, 792 insertions, 589 deletions
diff --git a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx index 44cd0ce82..ca7f9b0b5 100644 --- a/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx +++ b/packages/aml-backoffice-ui/src/ExchangeAmlFrame.tsx @@ -208,7 +208,12 @@ export function ExchangeAmlFrame({ <div class="-mt-32 flex grow "> {officer?.state !== "ready" ? undefined : <Navigation />} <div class="flex mx-auto my-4"> - <main class="block rounded-lg bg-white px-5 py-6 shadow " style={{minWidth: 300}} >{children}</main> + <main + class="block rounded-lg bg-white px-5 py-6 shadow " + style={{ minWidth: 300 }} + > + {children} + </main> </div> </div> @@ -225,7 +230,11 @@ function Navigation(): VNode { const { i18n } = useTranslationContext(); const pageList = [ { route: privatePages.profile, Icon: PeopleIcon, label: i18n.str`Profile` }, - { route: privatePages.investigation, Icon: ToInvestigateIcon, label: i18n.str`Investigation` }, + { + route: privatePages.investigation, + Icon: ToInvestigateIcon, + label: i18n.str`Investigation`, + }, { route: privatePages.active, Icon: HomeIcon, label: i18n.str`Active` }, ]; const { path } = useNavigationContext(); diff --git a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx index 8b54c1861..cf6922e1a 100644 --- a/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx +++ b/packages/aml-backoffice-ui/src/pages/CaseDetails.tsx @@ -227,26 +227,26 @@ export function CaseDetails({ account }: { account: string }) { const events = getEventsFromAmlHistory(accountDetails, i18n, allForms); - if (showForm !== undefined) { - return ( - <DefaultForm - readOnly={true} - initial={showForm.justification.value} - form={showForm.metadata as any} // FIXME: HERE - > - <div class="mt-6 flex items-center justify-end gap-x-6"> - <button - class="text-sm font-semibold leading-6 text-gray-900" - onClick={() => { - setShowForm(undefined); - }} - > - <i18n.Translate>Cancel</i18n.Translate> - </button> - </div> - </DefaultForm> - ); - } + // if (showForm !== undefined) { + // return ( + // <DefaultForm + // readOnly={true} + // initial={showForm.justification.value} + // form={showForm.metadata as any} // FIXME: HERE + // > + // <div class="mt-6 flex items-center justify-end gap-x-6"> + // <button + // class="text-sm font-semibold leading-6 text-gray-900" + // onClick={() => { + // setShowForm(undefined); + // }} + // > + // <i18n.Translate>Cancel</i18n.Translate> + // </button> + // </div> + // </DefaultForm> + // ); + // } return ( <div class="min-w-60"> @@ -390,8 +390,8 @@ export function CaseDetails({ account }: { account: string }) { onSelect={(e) => { switch (e.type) { case "aml-form": { - const { justification, metadata } = e; - setShowForm({ justification, metadata }); + // const { justification, metadata } = e; + // setShowForm({ justification, metadata }); break; } case "kyc-collection": @@ -423,87 +423,104 @@ export function CaseDetails({ account }: { account: string }) { function ShowDecisionInfo({ decision, - startOpen + startOpen, }: { decision: TalerExchangeApi.AmlDecision; - startOpen?: boolean, + startOpen?: boolean; }): VNode { const { i18n } = useTranslationContext(); const { config } = useExchangeApiContext(); - const [opened, setOpened] = useState(startOpen ?? false) - + const [opened, setOpened] = useState(startOpen ?? false); function Header() { - return <ul role="list" class="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl"> - <li class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"> - <div class="flex min-w-0 gap-x-4"> - <div class="flex mt-2 rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> - <div class="pointer-events-none bg-gray-200 inset-y-0 flex items-center px-3"> - <i18n.Translate>Since</i18n.Translate> - </div> - <div class="p-2 disabled:bg-gray-200 text-right rounded-md rounded-l-none data-[left=true]:text-left w-full py-1.5 pl-3 text-gray-900 placeholder:text-gray-400 sm:text-sm sm:leading-6"> - <Time - format="dd/MM/yyyy HH:mm:ss" - timestamp={AbsoluteTime.fromProtocolTimestamp( - decision.decision_time, - )} - /> + return ( + <ul + role="list" + class="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl" + > + <li class="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"> + <div class="flex min-w-0 gap-x-4"> + <div class="flex mt-2 rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> + <div class="pointer-events-none bg-gray-200 inset-y-0 flex items-center px-3"> + <i18n.Translate>Since</i18n.Translate> + </div> + <div class="p-2 disabled:bg-gray-200 text-right rounded-md rounded-l-none data-[left=true]:text-left w-full py-1.5 pl-3 text-gray-900 placeholder:text-gray-400 sm:text-sm sm:leading-6"> + <Time + format="dd/MM/yyyy HH:mm:ss" + timestamp={AbsoluteTime.fromProtocolTimestamp( + decision.decision_time, + )} + /> + </div> </div> </div> - </div> - <div class="flex shrink-0 items-center gap-x-4"> - <div class="flex mt-2 rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> - <div class="pointer-events-none bg-gray-200 inset-y-0 flex items-center px-3"> - {AbsoluteTime.isExpired( - AbsoluteTime.fromProtocolTimestamp( - decision.limits.expiration_time, - ), - ) ? ( - <i18n.Translate>Expired</i18n.Translate> - ) : ( - <i18n.Translate>Expires</i18n.Translate> - )} - </div> - <div class="p-2 disabled:bg-gray-200 text-right rounded-md rounded-l-none data-[left=true]:text-left w-full py-1.5 pl-3 text-gray-900 placeholder:text-gray-400 sm:text-sm sm:leading-6"> - <Time - format="dd/MM/yyyy HH:mm:ss" - timestamp={AbsoluteTime.fromProtocolTimestamp( - decision.limits.expiration_time, + <div class="flex shrink-0 items-center gap-x-4"> + <div class="flex mt-2 rounded-md shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> + <div class="pointer-events-none bg-gray-200 inset-y-0 flex items-center px-3"> + {AbsoluteTime.isExpired( + AbsoluteTime.fromProtocolTimestamp( + decision.limits.expiration_time, + ), + ) ? ( + <i18n.Translate>Expired</i18n.Translate> + ) : ( + <i18n.Translate>Expires</i18n.Translate> )} - /> + </div> + <div class="p-2 disabled:bg-gray-200 text-right rounded-md rounded-l-none data-[left=true]:text-left w-full py-1.5 pl-3 text-gray-900 placeholder:text-gray-400 sm:text-sm sm:leading-6"> + <Time + format="dd/MM/yyyy HH:mm:ss" + timestamp={AbsoluteTime.fromProtocolTimestamp( + decision.limits.expiration_time, + )} + /> + </div> </div> </div> - </div> - </li> - </ul> + </li> + </ul> + ); } if (!opened) { - return <div class="mt-4 cursor-pointer" onClick={() => setOpened(true)}> - <Header /> - </div> + return ( + <div class="mt-4 cursor-pointer" onClick={() => setOpened(true)}> + <Header /> + </div> + ); } - const balanceLimit = decision.limits.rules.find(r => r.operation_type === "BALANCE") + const balanceLimit = decision.limits.rules.find( + (r) => r.operation_type === "BALANCE", + ); return ( <div> - <div class="mt-4 cursor-pointer" onClick={() => setOpened(false)}> <Header /> </div> - {!decision.justification ? undefined : + {!decision.justification ? undefined : ( <div> - <label for="comment" class="block text-sm font-medium leading-6 text-gray-900">Description</label> + <label + for="comment" + class="block text-sm font-medium leading-6 text-gray-900" + > + Description + </label> <div class="mt-2"> - <textarea rows={2} name="comment" id="comment" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"> + <textarea + rows={2} + name="comment" + id="comment" + class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" + > {decision.justification} </textarea> </div> </div> - } + )} - {!balanceLimit ? undefined : + {!balanceLimit ? undefined : ( <div class="px-4"> <div class="flex mt-2 rounded-md w-fit shadow-sm border-0 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600"> <div class="whitespace-nowrap pointer-events-none bg-gray-200 inset-y-0 items-center px-3 flex"> @@ -514,21 +531,30 @@ function ShowDecisionInfo({ value={Amounts.parseOrThrow(balanceLimit.threshold)} spec={config.currency_specification} /> - </div> </div> </div> - - } + )} <div class="w-full px-4 pt-4"> - <table class="min-w-full divide-y divide-gray-300"> <thead class="bg-gray-50"> <tr> - <th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6"><i18n.Translate>Operation</i18n.Translate></th> - <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900"><i18n.Translate>Timeframe</i18n.Translate></th> - <th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6"><i18n.Translate>Amount</i18n.Translate></th> + <th + scope="col" + class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6" + > + <i18n.Translate>Operation</i18n.Translate> + </th> + <th + scope="col" + class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900" + > + <i18n.Translate>Timeframe</i18n.Translate> + </th> + <th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6"> + <i18n.Translate>Amount</i18n.Translate> + </th> </tr> </thead> <tbody class="divide-y divide-gray-200"> @@ -536,16 +562,18 @@ function ShowDecisionInfo({ if (r.operation_type === "BALANCE") return; return ( <tr> - <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 text-left">{r.operation_type}</td> + <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 text-left"> + {r.operation_type} + </td> <td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500"> {r.timeframe.d_us === "forever" ? "" : formatDuration( - intervalToDuration({ - start: 0, - end: r.timeframe.d_us / 1000, - }), - )} + intervalToDuration({ + start: 0, + end: r.timeframe.d_us / 1000, + }), + )} </td> <td class=" relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 text-right"> <RenderAmount @@ -559,7 +587,6 @@ function ShowDecisionInfo({ </tbody> </table> </div> - </div> ); } @@ -781,13 +808,13 @@ function InputAmount( if ( sep_pos !== -1 && l - sep_pos - 1 > - config.currency_specification.num_fractional_input_digits + config.currency_specification.num_fractional_input_digits ) { e.currentTarget.value = e.currentTarget.value.substring( 0, sep_pos + - config.currency_specification.num_fractional_input_digits + - 1, + config.currency_specification.num_fractional_input_digits + + 1, ); } onChange(e.currentTarget.value); @@ -825,9 +852,9 @@ function parseJustification( listOfAllKnownForms: FormMetadata[], ): | OperationOk<{ - justification: Justification; - metadata: FormMetadata; - }> + justification: Justification; + metadata: FormMetadata; + }> | OperationFail<ParseJustificationFail> { try { const justification = JSON.parse(s); @@ -875,212 +902,212 @@ function parseJustification( const THRESHOLD_2000_WEEK: (currency: string) => TalerExchangeApi.KycRule[] = ( currency, ) => [ - { - operation_type: "WITHDRAW", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + { + operation_type: "WITHDRAW", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "DEPOSIT", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "DEPOSIT", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "AGGREGATE", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "AGGREGATE", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "MERGE", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "MERGE", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "BALANCE", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "BALANCE", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "CLOSE", - threshold: `${currency}:2000`, - timeframe: { - d_us: 7 * 24 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "CLOSE", + threshold: `${currency}:2000`, + timeframe: { + d_us: 7 * 24 * 60 * 60 * 1000 * 1000, }, - ]; + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, +]; const THRESHOLD_100_HOUR: (currency: string) => TalerExchangeApi.KycRule[] = ( currency, ) => [ - { - operation_type: "WITHDRAW", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + { + operation_type: "WITHDRAW", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "DEPOSIT", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "DEPOSIT", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "AGGREGATE", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "AGGREGATE", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "MERGE", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "MERGE", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "BALANCE", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "BALANCE", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - { - operation_type: "CLOSE", - threshold: `${currency}:100`, - timeframe: { - d_us: 1 * 60 * 60 * 1000 * 1000, - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "CLOSE", + threshold: `${currency}:100`, + timeframe: { + d_us: 1 * 60 * 60 * 1000 * 1000, }, - ]; + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, +]; const FREEZE_RULES: (currency: string) => TalerExchangeApi.KycRule[] = ( currency, ) => [ - { - operation_type: "WITHDRAW", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + { + operation_type: "WITHDRAW", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - { - operation_type: "DEPOSIT", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "DEPOSIT", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - { - operation_type: "AGGREGATE", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "AGGREGATE", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - { - operation_type: "MERGE", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "MERGE", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - { - operation_type: "BALANCE", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "BALANCE", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - { - operation_type: "CLOSE", - threshold: `${currency}:0`, - timeframe: { - d_us: "forever", - }, - measures: ["verboten"], - display_priority: 1, - exposed: true, - is_and_combinator: true, + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, + { + operation_type: "CLOSE", + threshold: `${currency}:0`, + timeframe: { + d_us: "forever", }, - ]; + measures: ["verboten"], + display_priority: 1, + exposed: true, + is_and_combinator: true, + }, +]; diff --git a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx index e53c74aa5..21c14fee3 100644 --- a/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx +++ b/packages/aml-backoffice-ui/src/pages/ShowConsolidated.tsx @@ -22,13 +22,17 @@ import { import { DefaultForm, FormConfiguration, + RenderAllFieldsByUiConfig, UIFormElementConfig, UIHandlerId, + convertUiField, + getConverterById, useTranslationContext, } from "@gnu-taler/web-util/browser"; import { format } from "date-fns"; import { Fragment, VNode, h } from "preact"; import { AmlEvent } from "./CaseDetails.js"; +import { getShapeFromFields, useFormState } from "../hooks/form.js"; /** * the exchange doesn't hava a consistent api @@ -63,7 +67,7 @@ export function ShowConsolidated({ const fixed = fixProvidedInfo(cons.kyc); - const form: FormConfiguration = { + const formConfig: FormConfiguration = { type: "double-column", design: [ Object.entries(fixed).length > 0 @@ -73,8 +77,9 @@ export function ShowConsolidated({ const result: UIFormElementConfig = { type: "text", label: key as TranslatedString, - id: `kyc.${key}.value` as UIHandlerId, - name: `kyc.${key}.value`, + id: `${key}.value` as UIHandlerId, + name: `${key}.value`, + disabled: true, help: `At ${ field.since.t_ms === "never" ? "never" @@ -87,21 +92,55 @@ export function ShowConsolidated({ : undefined!, ], }; + const shape: Array<UIHandlerId> = []; + + formConfig.design.forEach((section) => { + Array.prototype.push.apply(shape, getShapeFromFields(section.fields)); + }); + + const [form, state] = useFormState<{}>(shape, fixed, (result) => { + return { status: "ok", errors: undefined, result }; + }); + return ( <Fragment> - {/* <h1 class="text-base font-semibold leading-7 text-black"> - Consolidated information{" "} - {until.t_ms === "never" - ? "" - : `after ${format(until.t_ms, "dd MMMM yyyy")}`} - </h1> */} - <DefaultForm - key={`${String(Date.now())}`} - form={form as any} - initial={cons} - readOnly - onUpdate={() => {}} - /> + <div class="space-y-10 divide-y -mt-5 divide-gray-900/10"> + {formConfig.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> </Fragment> ); } diff --git a/packages/web-util/src/forms/DefaultForm.tsx b/packages/web-util/src/forms/DefaultForm.tsx index 338460170..239577e24 100644 --- a/packages/web-util/src/forms/DefaultForm.tsx +++ b/packages/web-util/src/forms/DefaultForm.tsx @@ -1,12 +1,21 @@ +import { TranslatedString } from "@gnu-taler/taler-util"; import { Fragment, VNode, h } from "preact"; +import { + UIFormElementConfig, + getConverterById, + useTranslationContext, +} from "../index.browser.js"; import { FormProvider, FormProviderProps, FormState } from "./FormProvider.js"; -import { RenderAllFieldsByUiConfig, UIFormField } from "./forms.js"; -import { TranslatedString } from "@gnu-taler/taler-util"; +import { + RenderAllFieldsByUiConfig, + UIFormField, + convertUiField, +} from "./forms.js"; // import { FlexibleForm } from "./ui-form.js"; /** * Flexible form uses a DoubleColumForm for design - * and may have a dynamic properties defined by + * and may have a dynamic properties defined by * behavior function. */ export interface FlexibleForm_Deprecated<T extends object> { @@ -16,17 +25,19 @@ export interface FlexibleForm_Deprecated<T extends object> { /** * Double column form - * + * * Form with sections, every sections have a title and may * have a description. * Every sections contain a set of fields. */ -export type DoubleColumnForm_Deprecated = Array<DoubleColumnFormSection_Deprecated | undefined>; +export type DoubleColumnForm_Deprecated = Array< + DoubleColumnFormSection_Deprecated | undefined +>; export type DoubleColumnFormSection_Deprecated = { title: TranslatedString; description?: TranslatedString; - fields: UIFormField[]; + fields: UIFormElementConfig[]; }; /** @@ -40,20 +51,25 @@ export function DefaultForm<T extends object>({ onSubmit, children, readOnly, -}: Omit<FormProviderProps<T>, "computeFormState"> & { form: FlexibleForm_Deprecated<T> }): VNode { +}: Omit<FormProviderProps<T>, "computeFormState"> & { + form: FlexibleForm_Deprecated<T>; +}): VNode { + const { i18n } = useTranslationContext(); return ( <FormProvider initial={initial} onUpdate={onUpdate} onSubmit={onSubmit} readOnly={readOnly} - // computeFormState={form.behavior} > <div class="space-y-10 divide-y -mt-5 divide-gray-900/10"> {form.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 + 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} @@ -69,7 +85,12 @@ export function DefaultForm<T extends object>({ <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( + i18n, + section.fields, + form, + getConverterById, + )} /> </div> </div> diff --git a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx index 6b792bfee..dcaf1cec9 100644 --- a/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx +++ b/packages/web-util/src/forms/InputAbsoluteTime.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Absolute Time", @@ -38,23 +39,29 @@ export namespace Simplest { type TargetObject = { today: AbsoluteTime; -} +}; const initial: TargetObject = { - today: AbsoluteTime.now() -} + today: AbsoluteTime.now(), +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "absoluteTimeText", - properties: { - label: "label of the field" as TranslatedString, - name: "today", - pattern: "dd/MM/yyyy HH:mm" - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "absoluteTimeText", + label: "label of the field" as TranslatedString, + id: ".today" as UIHandlerId, + name: "today", + pattern: "dd/MM/yyyy HH:mm", + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputAmount.stories.tsx b/packages/web-util/src/forms/InputAmount.stories.tsx index f05887515..052b22813 100644 --- a/packages/web-util/src/forms/InputAmount.stories.tsx +++ b/packages/web-util/src/forms/InputAmount.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Amount", @@ -38,22 +39,29 @@ export namespace Simplest { type TargetObject = { amount: AmountJson; -} +}; const initial: TargetObject = { - amount: Amounts.parseOrThrow("USD:10") -} + amount: Amounts.parseOrThrow("USD:10"), +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "amount", - properties: { - label: "label of the field" as TranslatedString, - name: "amount", - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "amount", + label: "label of the field" as TranslatedString, + id: ".amount" as UIHandlerId, + currency: "ARS", + name: "amount", + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputArray.stories.tsx b/packages/web-util/src/forms/InputArray.stories.tsx index 143e73f02..31bad66a4 100644 --- a/packages/web-util/src/forms/InputArray.stories.tsx +++ b/packages/web-util/src/forms/InputArray.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Array", @@ -41,39 +42,35 @@ type TargetObject = { name: string; age: number; }[]; -} +}; const initial: TargetObject = { - people: [{ - name: "me", - age: 17, - }] -} + people: [ + { + name: "me", + age: 17, + }, + ], +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "array", - properties: { - label: "People" as TranslatedString, - name: "comment", - fields: [{ - type: "text", - properties: { - label: "the name" as TranslatedString, - name: "name", - } - }, { - type: "integer", - properties: { - label: "the age" as TranslatedString, - name: "age", - } - }], - labelField: "name" - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "array", + label: "People" as TranslatedString, + name: "comment", + fields: [], + id: ".name" as UIHandlerId, + labelFieldId: "name" as UIHandlerId, + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx index 786dfe5bc..4d3745fe5 100644 --- a/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx +++ b/packages/web-util/src/forms/InputChoiceHorizontal.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Choice Horizontal", @@ -38,32 +39,42 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "0" -} + comment: "0", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "choiceHorizontal", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - choices: [{ - label: "first choice" as TranslatedString, - value: "1" - }, { - label: "second choice" as TranslatedString, - value: "2" - }, { - label: "third choice" as TranslatedString, - value: "3" - },], - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "choiceHorizontal", + label: "label of the field" as TranslatedString, + id: ".commnet" as UIHandlerId, + name: "comment", + choices: [ + { + label: "first choice" as TranslatedString, + value: "1", + }, + { + label: "second choice" as TranslatedString, + value: "2", + }, + { + label: "third choice" as TranslatedString, + value: "3", + }, + ], + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx index 9a634d05c..8d57b3689 100644 --- a/packages/web-util/src/forms/InputChoiceStacked.stories.tsx +++ b/packages/web-util/src/forms/InputChoiceStacked.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Choice Stacked", @@ -38,32 +39,42 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "choiceStacked", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - choices: [{ - label: "first choice" as TranslatedString, - value: "1" - }, { - label: "second choice" as TranslatedString, - value: "2" - }, { - label: "third choice" as TranslatedString, - value: "3" - },], - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "choiceStacked", + label: "label of the field" as TranslatedString, + name: "comment", + id: ".comment" as UIHandlerId, + choices: [ + { + label: "first choice" as TranslatedString, + value: "1", + }, + { + label: "second choice" as TranslatedString, + value: "2", + }, + { + label: "third choice" as TranslatedString, + value: "3", + }, + ], + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputFile.stories.tsx b/packages/web-util/src/forms/InputFile.stories.tsx index eff18d071..591b4e2af 100644 --- a/packages/web-util/src/forms/InputFile.stories.tsx +++ b/packages/web-util/src/forms/InputFile.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input File", @@ -38,27 +39,33 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "file", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - required: true, - maxBites: 2 * 1024 * 1024, - accept: ".png", - tooltip: "this is a very long tooltip that explain what the field does without being short" as TranslatedString, - help: "Max size of 2 mega bytes" as TranslatedString, - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "file", + label: "label of the field" as TranslatedString, + name: "comment", + required: true, + id: ".comment" as UIHandlerId, + accept: ".png", + tooltip: + "this is a very long tooltip that explain what the field does without being short" as TranslatedString, + help: "Max size of 2 mega bytes" as TranslatedString, + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputInteger.stories.tsx b/packages/web-util/src/forms/InputInteger.stories.tsx index 378736a24..e6b78c242 100644 --- a/packages/web-util/src/forms/InputInteger.stories.tsx +++ b/packages/web-util/src/forms/InputInteger.stories.tsx @@ -25,31 +25,37 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Integer", }; - type TargetObject = { age: number; -} +}; const initial: TargetObject = { age: 5, -} +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "integer", - properties: { - label: "label of the field" as TranslatedString, - name: "age", - tooltip: "just numbers" as TranslatedString, - }, - }] - }] -} - -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "integer", + label: "label of the field" as TranslatedString, + name: "age", + id: ".comment" as UIHandlerId, + tooltip: "just numbers" as TranslatedString, + }, + ], + }, + ], +}; + +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputLine.stories.tsx b/packages/web-util/src/forms/InputLine.stories.tsx index dea5c142a..16530ff2b 100644 --- a/packages/web-util/src/forms/InputLine.stories.tsx +++ b/packages/web-util/src/forms/InputLine.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Line", @@ -38,22 +39,28 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "text", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "text", + label: "label of the field" as TranslatedString, + name: "comment", + id: ".comment" as UIHandlerId, + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputLine.tsx b/packages/web-util/src/forms/InputLine.tsx index eb3238ef9..a89d2e24e 100644 --- a/packages/web-util/src/forms/InputLine.tsx +++ b/packages/web-util/src/forms/InputLine.tsx @@ -68,7 +68,13 @@ export function LabelWithTooltipMaybeRequired({ return WithTooltip; } -export function RenderAddon({ disabled, addon }: { disabled?: boolean, addon: Addon }): VNode { +export function RenderAddon({ + disabled, + addon, +}: { + disabled?: boolean; + addon: Addon; +}): VNode { switch (addon.type) { case "text": { return ( @@ -154,7 +160,7 @@ type InputType = "text" | "text-area" | "password" | "email" | "number"; export function InputLine<T extends object, K extends keyof T>( props: { type: InputType } & UIFormProps<T, K>, ): VNode { - const { name, placeholder, before, after, converter, type } = props; + const { name, placeholder, before, after, converter, type, disabled } = props; //FIXME: remove deprecated const fieldCtx = useField<T, K>(props.name); const { value, onChange, state, error } = @@ -222,7 +228,7 @@ export function InputLine<T extends object, K extends keyof T>( <InputWrapper<T, K> {...props} help={props.help ?? state.help} - disabled={state.disabled ?? false} + disabled={disabled ?? false} error={showError ? error : undefined} > <textarea @@ -234,7 +240,7 @@ export function InputLine<T extends object, K extends keyof T>( placeholder={placeholder ? placeholder : undefined} value={toString(value) ?? ""} // defaultValue={toString(value)} - disabled={state.disabled} + disabled={disabled ?? false} aria-invalid={showError} // aria-describedby="email-error" class={clazz} @@ -247,7 +253,7 @@ export function InputLine<T extends object, K extends keyof T>( <InputWrapper<T, K> {...props} help={props.help ?? state.help} - disabled={state.disabled ?? false} + disabled={disabled ?? false} error={showError ? error : undefined} > <input @@ -262,7 +268,7 @@ export function InputLine<T extends object, K extends keyof T>( // onChange(fromString(value as any)); // }} // defaultValue={toString(value)} - disabled={state.disabled} + disabled={disabled ?? false} aria-invalid={showError} // aria-describedby="email-error" class={clazz} diff --git a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx index ab17545f5..a85259786 100644 --- a/packages/web-util/src/forms/InputSelectMultiple.stories.tsx +++ b/packages/web-util/src/forms/InputSelectMultiple.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Select Multiple", @@ -39,52 +40,66 @@ export namespace Simplest { type TargetObject = { pets: string[]; things: string[]; -} +}; const initial: TargetObject = { pets: [], things: [], -} +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "selectMultiple", - properties: { - label: "allow diplicates" as TranslatedString, - name: "pets", - placeholder: "search..." as TranslatedString, - choices: [{ - label: "one label" as TranslatedString, - value: "one" - }, { - label: "two label" as TranslatedString, - value: "two" - }, { - label: "five label" as TranslatedString, - value: "five" - }] - }, - }, { - type: "selectMultiple", - properties: { - label: "unique values" as TranslatedString, - name: "things", - unique: true, - placeholder: "search..." as TranslatedString, - choices: [{ - label: "one label" as TranslatedString, - value: "one" - }, { - label: "two label" as TranslatedString, - value: "two" - }, { - label: "five label" as TranslatedString, - value: "five" - }] - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "selectMultiple", + label: "allow diplicates" as TranslatedString, + name: "pets", + id: ".pets" as UIHandlerId, + placeholder: "search..." as TranslatedString, + choices: [ + { + label: "one label" as TranslatedString, + value: "one", + }, + { + label: "two label" as TranslatedString, + value: "two", + }, + { + label: "five label" as TranslatedString, + value: "five", + }, + ], + }, + { + type: "selectMultiple", + label: "unique values" as TranslatedString, + name: "things", + id: ".things" as UIHandlerId, + unique: true, + placeholder: "search..." as TranslatedString, + choices: [ + { + label: "one label" as TranslatedString, + value: "one", + }, + { + label: "two label" as TranslatedString, + value: "two", + }, + { + label: "five label" as TranslatedString, + value: "five", + }, + ], + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputSelectOne.stories.tsx b/packages/web-util/src/forms/InputSelectOne.stories.tsx index 2ebde3096..f6b2354c5 100644 --- a/packages/web-util/src/forms/InputSelectOne.stories.tsx +++ b/packages/web-util/src/forms/InputSelectOne.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Select One", @@ -38,33 +39,43 @@ export namespace Simplest { type TargetObject = { things: string; -} +}; const initial: TargetObject = { - things: "one" -} + things: "one", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "selectOne", - properties: { - label: "label of the field" as TranslatedString, - name: "things", - placeholder: "search..." as TranslatedString, - choices: [{ - label: "one label" as TranslatedString, - value: "one" - }, { - label: "two label" as TranslatedString, - value: "two" - }, { - label: "five label" as TranslatedString, - value: "five" - }] - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "selectOne", + label: "label of the field" as TranslatedString, + name: "things", + id: ".things" as UIHandlerId, + placeholder: "search..." as TranslatedString, + choices: [ + { + label: "one label" as TranslatedString, + value: "one", + }, + { + label: "two label" as TranslatedString, + value: "two", + }, + { + label: "five label" as TranslatedString, + value: "five", + }, + ], + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputText.stories.tsx b/packages/web-util/src/forms/InputText.stories.tsx index 60b6ca224..8e2b415ac 100644 --- a/packages/web-util/src/forms/InputText.stories.tsx +++ b/packages/web-util/src/forms/InputText.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Text", @@ -38,22 +39,28 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "text", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "text", + label: "label of the field" as TranslatedString, + id: ".comment" as UIHandlerId, + name: "comment", + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputTextArea.stories.tsx b/packages/web-util/src/forms/InputTextArea.stories.tsx index ab1a695f5..d36e87fc5 100644 --- a/packages/web-util/src/forms/InputTextArea.stories.tsx +++ b/packages/web-util/src/forms/InputTextArea.stories.tsx @@ -25,6 +25,7 @@ import { DefaultForm as TestedComponent, FlexibleForm_Deprecated, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Text Area", @@ -38,22 +39,28 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "text", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "text", + label: "label of the field" as TranslatedString, + id: ".comment" as UIHandlerId, + name: "comment", + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); diff --git a/packages/web-util/src/forms/InputToggle.stories.tsx b/packages/web-util/src/forms/InputToggle.stories.tsx index fcc57ffe2..ae9161645 100644 --- a/packages/web-util/src/forms/InputToggle.stories.tsx +++ b/packages/web-util/src/forms/InputToggle.stories.tsx @@ -25,6 +25,7 @@ import { FlexibleForm_Deprecated, DefaultForm as TestedComponent, } from "./DefaultForm.js"; +import { UIHandlerId } from "./ui-form.js"; export default { title: "Input Toggle", @@ -38,22 +39,28 @@ export namespace Simplest { type TargetObject = { comment: string; -} +}; const initial: TargetObject = { - comment: "some initial comment" -} + comment: "some initial comment", +}; const form: FlexibleForm_Deprecated<TargetObject> = { - design: [{ - title: "this is a simple form" as TranslatedString, - fields: [{ - type: "toggle", - properties: { - label: "label of the field" as TranslatedString, - name: "comment", - }, - }] - }] -} + design: [ + { + title: "this is a simple form" as TranslatedString, + fields: [ + { + type: "toggle", + label: "label of the field" as TranslatedString, + name: "comment", + id: ".comment" as UIHandlerId, + }, + ], + }, + ], +}; -export const SimpleComment = tests.createExample(TestedComponent, { initial, form }); +export const SimpleComment = tests.createExample(TestedComponent, { + initial, + form, +}); |