import { List, OrderedMap, OrderedSet, Map } from "immutable"; import { BasicUpdater, id, BasicPredicate, SimpleCallback, Unit, Debounced, Synchronized, unit, replaceWith, CoTypedFactory, Debounce, Synchronize, BasicFun, FormFieldPredicateEvaluation, FormFieldPredicateEvaluations, FieldName, PredicateValue, ValueRecord, Delta, ParsedType, FormLayout, PredicateFormLayout, Sum, AsyncState, } from "../../../../main"; import { Template, View } from "../../../template/state"; import { Value } from "../../../value/state"; export type ToPathUnions = a[keyof a]; export type Paths = { [f in keyof Entity]: f extends keyof NestedPaths ? [f, ToPathUnions] : [f]; }; export type ValidationError = string; export type FieldValidation = Array; export type Path = Array; export type ValidationErrorWithPath = [Path, ValidationError]; export type FieldValidationWithPath = Array; export const FieldValidationWithPath = { Default: { fromFieldValidation: (_: FieldValidation): FieldValidationWithPath => _.map((_) => [[], _]), }, }; export type FormValidatorSynchronized = Synchronized< Unit, FieldValidationWithPath >; export type CommonFormState = { modifiedByUser: boolean; validation: Debounced; }; export const CommonFormState = { Default: (): CommonFormState => ({ modifiedByUser: false, // start the validation so that it immediately runs and registers the first errors such as missing values and such validation: Debounced.Updaters.Template.value( Synchronized.Updaters.value(replaceWith(unit)), )(Debounced.Default(Synchronized.Default(unit))), }), }; export type EntityFormState< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = { formFieldStates: { [f in Fields]: { customFormState: FieldStates[f]; commonFormState: CommonFormState; formFieldStates: FieldStates[f]; elementFormStates: FieldStates[f]; }; }; commonFormState: CommonFormState; }; export type EntityFormContext< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = Context & EntityFormState & { disabled: boolean; visible: boolean; elementVisibilities: FormFieldPredicateEvaluation[] | undefined; elementDisabledFields: FormFieldPredicateEvaluation | undefined; extraContext: any; visibilities: FormFieldPredicateEvaluation | undefined; disabledFields: FormFieldPredicateEvaluation | undefined; label?: string; type: ParsedType; layout: PredicateFormLayout; globalConfiguration: | Sum | AsyncState; } & Value & { rootValue: ValueRecord }; export type OnChange = ( updater: BasicUpdater, delta: Delta, ) => void; export type EntityFormForeignMutationsExpected< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = ForeignMutationsExpected & { onChange: OnChange; }; export type FieldTemplates< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = { [f in Fields]: EmbeddedFieldTemplate< Fields, FieldStates, Context, ForeignMutationsExpected >; }; export type EntityFormView< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = View< EntityFormContext, EntityFormState, EntityFormForeignMutationsExpected< Fields, FieldStates, Context, ForeignMutationsExpected >, { EmbeddedFields: FieldTemplates< Fields, FieldStates, Context, ForeignMutationsExpected >; VisibleFieldKeys: OrderedSet; DisabledFieldKeys: OrderedSet; FieldLabels: Map; } >; export type EntityFormTemplate< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = Template< EntityFormContext, EntityFormState, EntityFormForeignMutationsExpected< Fields, FieldStates, Context, ForeignMutationsExpected >, EntityFormView >; export type EmbeddedFieldTemplate< Fields extends keyof FieldStates, FieldStates, Context, ForeignMutationsExpected, > = Template< EntityFormContext & { disabled: boolean; }, EntityFormState, EntityFormForeignMutationsExpected< Fields, FieldStates, Context, ForeignMutationsExpected > >; export type FormStateFromEntity = { formFieldStates: { [f in keyof E]: f extends keyof S ? { customFormState: S[f]; commonFormState: CommonFormState } : { customFormState: Unit; commonFormState: CommonFormState }; }; } & { commonFormState: CommonFormState }; // type OtherNestedThing = { x:boolean, y:string } // type Address = { city:string, street:string, number:number, other:OtherNestedThing } // type Person = { name:string, surname:string, birthday:Date, address:Address, other:OtherNestedThing } // type OtherNestedThingPaths = Paths // type AddressPaths = Paths // type PersonPaths = ToPathUnions> // const f = (_:PersonPaths) => { // if (_[0] == "name") return // if (_[0] == "surname") return // if (_[0] == "birthday") return // if (_[0] == "address") { // _[1][0] == "city" // if (_[1][0] == "other") { // _[1][1][0] == "x" // } // return // } // _[1][0] == "x" // }