taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 35b6e5931ced488031e6e934659278ebd5c63a94
parent 6a744c253098e870983ed46d20d7afdd6bbaaab2
Author: Sebastian <sebasjm@gmail.com>
Date:   Wed, 15 Jan 2025 17:25:23 -0300

properties form

Diffstat:
Mpackages/aml-backoffice-ui/src/hooks/decision-request.ts | 3+++
Mpackages/aml-backoffice-ui/src/pages/AmlDecisionRequestWizard.tsx | 172++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 173 insertions(+), 2 deletions(-)

diff --git a/packages/aml-backoffice-ui/src/hooks/decision-request.ts b/packages/aml-backoffice-ui/src/hooks/decision-request.ts @@ -59,6 +59,7 @@ export interface DecisionRequest { rules: BalanceForm | undefined; deadline: AbsoluteTime | undefined; properties: object | undefined; + custom_properties: object | undefined; custom_events: string[] | undefined; inhibit_events: string[] | undefined; keep_investigating: boolean; @@ -109,6 +110,7 @@ export const codecForDecisionRequest = (): Codec<DecisionRequest> => .property("rules", codecOptional(codecForBalanceForm())) .property("deadline", codecOptional(codecForAbsoluteTime)) .property("properties", codecForAny()) + .property("custom_properties", codecForAny()) .property("justification", codecOptional(codecForString())) .property("custom_events", codecOptional(codecForList(codecForString()))) .property("inhibit_events", codecOptional(codecForList(codecForString()))) @@ -135,6 +137,7 @@ const defaultDecisionRequest: DecisionRequest = { keep_investigating: false, next_measure: undefined, properties: undefined, + custom_properties: undefined, rules: undefined, }; diff --git a/packages/aml-backoffice-ui/src/pages/AmlDecisionRequestWizard.tsx b/packages/aml-backoffice-ui/src/pages/AmlDecisionRequestWizard.tsx @@ -24,9 +24,11 @@ import { FormDesign, FormUI, InternationalizationAPI, + UIFormElementConfig, UIHandlerId, useExchangeApiContext, useForm, + TalerFormAttributes, useTranslationContext, } from "@gnu-taler/web-util/browser"; import { Fragment, h, VNode } from "preact"; @@ -335,6 +337,129 @@ function Rules({ account }: { account?: string }): VNode { ); } +type PropertiesForm = { + defined: { [name: string]: boolean }; + custom: { [name: string]: boolean }; +}; + +const propertiesForm = ( + i18n: InternationalizationAPI, + fields: UIFormElementConfig[], +): FormDesign<PropertiesForm> => ({ + type: "double-column", + sections: [ + { + title: i18n.str`Properties`, + description: i18n.str`props.`, + fields: fields.map((f) => + "id" in f ? { ...f, id: ("defined." + f.id) as UIHandlerId } : f, + ), + }, + { + title: i18n.str`Custom properties`, + description: i18n.str`add properties not listed above`, + fields: [ + { + id: "custom" as UIHandlerId, + type: "array", + label: i18n.str`Fields`, + labelFieldId: "name" as UIHandlerId, + fields: [ + { + type: "text", + label: i18n.str`Name`, + id: "name" as UIHandlerId, + }, + { + type: "text", + label: i18n.str`Value`, + id: "value" as UIHandlerId, + }, + ], + }, + ], + }, + ], +}); + +function fieldsByDialect( + i18n: InternationalizationAPI, + dialect: string | undefined, +): UIFormElementConfig[] { + if (!dialect) return []; + switch (dialect) { + case "testing": { + return [ + { + id: "ACCOUNT_PEP" satisfies keyof TalerFormAttributes.AccountProperties_Testing as UIHandlerId, + label: i18n.str`Public exposed person?`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + ]; + } + case "gls": { + return [ + { + id: "ACCOUNT_REPORTED" satisfies keyof TalerFormAttributes.AccountProperties_GLS as UIHandlerId, + label: i18n.str`Is PEP`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + ]; + } + case "tops": { + return [ + { + id: "ACCOUNT_FROZEN" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`Frozen?`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + { + id: "ACCOUNT_HIGH_RISK" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`High risk?`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + { + id: "ACCOUNT_PEP" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`Public exposed person?`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + { + id: "ACCOUNT_REPORTED" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`Is reported to authorities?`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + { + id: "ACCOUNT_SANCTIONED" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`Is PEP`, + // gana_type: "Boolean", + type: "toggle", + required: true, + }, + { + id: "ACCOUNT_BUSINESS_DOMAIN" satisfies keyof TalerFormAttributes.AccountProperties_TOPS as UIHandlerId, + label: i18n.str`Business domain`, + // gana_type: "Boolean", + type: "text", + }, + ]; + } + default: { + return []; + } + } +} /** * Update account properites * @param param0 @@ -342,10 +467,53 @@ function Rules({ account }: { account?: string }): VNode { */ function Properties({}: {}): VNode { const { i18n } = useTranslationContext(); - const [request] = useCurrentDecisionRequest(); - return <div> not yet impltemented: props</div>; + const [request, updateRequest] = useCurrentDecisionRequest(); + const { config } = useExchangeApiContext(); + const design = propertiesForm( + i18n, + fieldsByDialect(i18n, config.config.aml_spa_dialect), + ); + + const form = useForm<PropertiesForm>(design, { + defined: request.properties, + custom: request.custom_properties, + }); + + onComponentUnload(() => { + updateRequest("properties", form.status.result.defined); + updateRequest("custom_properties", form.status.result.custom); + }); + + return ( + <div> + <FormUI design={design} handler={form.handler} /> + </div> + ); } +type EventsForm = { + trigger: { [name: string]: boolean }; + inhibit: { [name: string]: boolean }; +}; + +const eventsForm = ( + i18n: InternationalizationAPI, + props: string[], +): FormDesign<MeasureForm> => ({ + type: "double-column", + sections: [ + { + title: i18n.str`Custom events`, + description: i18n.str`This events will be triggered by default unless you marked to skip it.`, + fields: [], + }, + { + title: i18n.str`Inhibit`, + description: i18n.str`This events will be triggered by default unless you marked to skip it.`, + fields: [], + }, + ], +}); /** * Trigger additional events * @param param0