ballerina-core 1.0.61 → 1.0.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/forms/domains/collection/domains/selection/state.ts +3 -3
- package/src/forms/domains/parser/domains/built-ins/state.ts +15 -8
- package/src/forms/domains/parser/domains/renderer/state.ts +7 -12
- package/src/forms/domains/parser/domains/types/state.ts +48 -10
- package/src/forms/domains/parser/domains/validator/state.ts +12 -1
- package/src/forms/domains/parser/state.tsx +11 -9
- package/src/forms/domains/primitives/domains/enum/state.ts +6 -6
- package/src/forms/domains/primitives/domains/enum/template.tsx +4 -4
- package/src/forms/domains/primitives/domains/enum-multiselect/state.ts +1 -1
- package/src/forms/domains/primitives/domains/enum-multiselect/template.tsx +12 -10
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Sum } from "../../../../../../main";
|
|
1
|
+
import { Sum, Value } from "../../../../../../main";
|
|
2
2
|
import { CollectionReference } from "../reference/state"
|
|
3
3
|
|
|
4
|
-
export type CollectionSelection<Element extends CollectionReference
|
|
5
|
-
export const CollectionSelection = <Element extends CollectionReference
|
|
4
|
+
export type CollectionSelection<Element extends CollectionReference | Value<CollectionReference>> = Sum<Element, "no selection">;
|
|
5
|
+
export const CollectionSelection = <Element extends CollectionReference | Value<CollectionReference>>() => Sum<Element, "no selection">();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Map, List, Set, OrderedMap
|
|
1
|
+
import { Map, List, Set, OrderedMap } from "immutable"
|
|
2
2
|
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
3
3
|
import { CollectionSelection } from "../../../collection/domains/selection/state";
|
|
4
4
|
import { BasicFun } from "../../../../../fun/state";
|
|
@@ -6,12 +6,13 @@ import { InjectedPrimitives, Maybe, ParsedType, TypeName } from "../../../../../
|
|
|
6
6
|
import { ValueOrErrors } from "../../../../../collections/domains/valueOrErrors/state";
|
|
7
7
|
|
|
8
8
|
export const PrimitiveTypes =
|
|
9
|
-
[
|
|
9
|
+
[
|
|
10
|
+
"guid", //resolves to string
|
|
11
|
+
"string",
|
|
10
12
|
"number",
|
|
11
13
|
"boolean",
|
|
12
14
|
"maybeBoolean",
|
|
13
15
|
"Date",
|
|
14
|
-
"CollectionReference",
|
|
15
16
|
"base64File",
|
|
16
17
|
"secret",
|
|
17
18
|
] as const
|
|
@@ -21,7 +22,9 @@ export const GenericTypes = [
|
|
|
21
22
|
"SingleSelection",
|
|
22
23
|
"MultiSelection",
|
|
23
24
|
"List",
|
|
24
|
-
"Map"
|
|
25
|
+
"Map",
|
|
26
|
+
"Union"
|
|
27
|
+
] as const
|
|
25
28
|
export type GenericType = (typeof GenericTypes)[number]
|
|
26
29
|
|
|
27
30
|
export type ApiConverter<T> = { fromAPIRawValue: BasicFun<any, T>, toAPIRawValue: BasicFun<[T, boolean], any> }
|
|
@@ -35,7 +38,6 @@ export type BuiltInApiConverters = {
|
|
|
35
38
|
"base64File": ApiConverter<string>
|
|
36
39
|
"secret": ApiConverter<string>
|
|
37
40
|
"Date": ApiConverter<Maybe<Date>>
|
|
38
|
-
"CollectionReference": ApiConverter<CollectionReference>
|
|
39
41
|
"SingleSelection": ApiConverter<CollectionSelection<any>>
|
|
40
42
|
"MultiSelection": ApiConverter<OrderedMap<string, any>>
|
|
41
43
|
"List": ApiConverter<List<any>>,
|
|
@@ -73,7 +75,6 @@ export const builtInsFromFieldViews = (fieldViews: any): BuiltIns => {
|
|
|
73
75
|
["maybeBoolean", { renderers: Set(["maybeBoolean"]), defaultValue: undefined }] as [string, PrimitiveBuiltIn],
|
|
74
76
|
["date", { renderers: Set(["date"]), defaultValue: undefined }] as [string, PrimitiveBuiltIn],
|
|
75
77
|
["Date", { renderers: Set(["date"]), defaultValue: undefined }] as [string, PrimitiveBuiltIn],
|
|
76
|
-
["CollectionReference", { renderers: Set(["enumSingleSelection", "enumMultiSelection", "streamSingleSelection", "streamMultiSelection"]), defaultValue: CollectionReference.Default("", "") }] as [string, PrimitiveBuiltIn],
|
|
77
78
|
["base64File", { renderers: Set(["base64File"]), defaultValue: "" }] as [string, PrimitiveBuiltIn],
|
|
78
79
|
["secret", { renderers: Set(["secret"]), defaultValue: "" }] as [string, PrimitiveBuiltIn],
|
|
79
80
|
]),
|
|
@@ -81,7 +82,8 @@ export const builtInsFromFieldViews = (fieldViews: any): BuiltIns => {
|
|
|
81
82
|
["SingleSelection", { defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
|
|
82
83
|
["MultiSelection", { defaultValue: Map() }] as [string, GenericBuiltIn],
|
|
83
84
|
["List", { defaultValue: List() }] as [string, GenericBuiltIn],
|
|
84
|
-
["Map", { defaultValue: List() }] as [string, GenericBuiltIn]
|
|
85
|
+
["Map", { defaultValue: List() }] as [string, GenericBuiltIn],
|
|
86
|
+
["Union", { defaultValue: Map() }] as [string, GenericBuiltIn],
|
|
85
87
|
]),
|
|
86
88
|
"renderers": {
|
|
87
89
|
"boolean": Set(),
|
|
@@ -147,6 +149,9 @@ export const fromAPIRawValue = <T extends { [key in keyof T]: { type: any; state
|
|
|
147
149
|
if (t.kind == "primitive") {
|
|
148
150
|
return converters[t.value].fromAPIRawValue(raw)
|
|
149
151
|
}
|
|
152
|
+
if(t.kind == "union") {
|
|
153
|
+
return CollectionReference.Default(raw, raw, "enum")
|
|
154
|
+
}
|
|
150
155
|
if (t.kind == "application") {
|
|
151
156
|
if (t.value == "SingleSelection") {
|
|
152
157
|
return CollectionSelection().Updaters.left(
|
|
@@ -191,7 +196,9 @@ export const fromAPIRawValue = <T extends { [key in keyof T]: { type: any; state
|
|
|
191
196
|
export const toAPIRawValue = <T extends { [key in keyof T]: { type: any; state: any; }}>(t: ParsedType<T>, types: Map<TypeName, ParsedType<T>>, builtIns: BuiltIns, converters: ApiConverters<T>, injectedPrimitives?: InjectedPrimitives<T>) => (raw: any, formState: any) : ValueOrErrors<any, string> => {
|
|
192
197
|
if (t.kind == "primitive")
|
|
193
198
|
return ValueOrErrors.Operations.Return(converters[t.value as string | keyof T].toAPIRawValue([raw, formState.modifiedByUser]))
|
|
194
|
-
|
|
199
|
+
if(t.kind == "union"){
|
|
200
|
+
return ValueOrErrors.Operations.Return(raw.id)
|
|
201
|
+
}
|
|
195
202
|
if (t.kind == "application") {
|
|
196
203
|
if (t.value == "SingleSelection") {
|
|
197
204
|
const result = converters[t.value].toAPIRawValue([raw, formState.modifiedByUser])
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { List, Map, OrderedMap, Set } from "immutable";
|
|
2
|
-
import { Base64FileForm, BaseEnumContext, BasicFun, BooleanForm, BoolExpr, CollectionReference, CollectionSelection, CommonFormState, DateForm, DateFormState, EnumForm, EnumFormState, EnumMultiselectForm, EnumOptionsSources, FormLabel, Guid, InfiniteMultiselectDropdownForm, InjectedPrimitives, ListFieldState, ListForm, MapFieldState, MapForm, Maybe, MaybeBooleanForm, NumberForm, ParsedForms, ParsedType, SearchableInfiniteStreamForm, SearchableInfiniteStreamState, SecretForm, StringForm, Template, Unit, Value } from "../../../../../../main";
|
|
2
|
+
import { Base64FileForm, BaseEnumContext, BasicFun, BasicPredicate, BooleanForm, BoolExpr, CollectionReference, CollectionSelection, CommonFormState, DateForm, DateFormState, EnumForm, EnumFormState, EnumMultiselectForm, EnumOptionsSources, FormLabel, Guid, InfiniteMultiselectDropdownForm, InjectedPrimitives, ListFieldState, ListForm, MapFieldState, MapForm, Maybe, MaybeBooleanForm, NumberForm, OrderedMapRepo, ParsedForms, ParsedType, SearchableInfiniteStreamForm, SearchableInfiniteStreamState, SecretForm, StringForm, Template, Unit, Value } from "../../../../../../main";
|
|
3
3
|
import { ValueOrErrors } from "../../../../../collections/domains/valueOrErrors/state";
|
|
4
4
|
|
|
5
5
|
type Form = {
|
|
@@ -128,11 +128,6 @@ export const ParsedRenderer = {
|
|
|
128
128
|
console.error(`Invalid field type ${JSON.stringify(fieldType)} for field ${JSON.stringify(field)}`)
|
|
129
129
|
throw new Error("Invalid field type")
|
|
130
130
|
},
|
|
131
|
-
ParseOptions: (leafPredicates: any, options: any) => {
|
|
132
|
-
const result = options.map((_: any) => ([_[0].id, [_[0], (_[1] as BoolExpr<any>).eval<any>(leafPredicates)]]));
|
|
133
|
-
const resultMap = result.reduce((a: any, b: any) => a.set(b[0], b[1]), OrderedMap<any, any>());
|
|
134
|
-
return resultMap;
|
|
135
|
-
},
|
|
136
131
|
FormViewToViewKind: (viewName: string | undefined, formViews: Record<string, any>, formNames: Set<string>) => {
|
|
137
132
|
if (viewName == undefined) {
|
|
138
133
|
throw Error(`cannot resolve view ${viewName}`) // TODO -- better error handling
|
|
@@ -223,18 +218,18 @@ export const ParsedRenderer = {
|
|
|
223
218
|
.withView(formViews[viewKind][viewName]())
|
|
224
219
|
.mapContext<any & CommonFormState & Value<string>>(_ => ({ ..._, label: label, tooltip }))
|
|
225
220
|
if (viewKind == "enumSingleSelection" && rendererConfig.kind == "enum")
|
|
226
|
-
return EnumForm<any & FormLabel & BaseEnumContext<
|
|
221
|
+
return EnumForm<any & FormLabel & BaseEnumContext<Value<CollectionReference>>, Unit, Value<CollectionReference>>()
|
|
227
222
|
.withView(formViews[viewKind][viewName]())
|
|
228
|
-
.mapContext<any & EnumFormState<any & BaseEnumContext<
|
|
223
|
+
.mapContext<any & EnumFormState<any & BaseEnumContext<Value<CollectionReference>>, Value<CollectionReference>> & Value<CollectionSelection<Value<CollectionReference>>>>(_ => ({
|
|
229
224
|
..._, label: label, tooltip, getOptions: () => {
|
|
230
|
-
return ((enumOptionsSources as any)(rendererConfig.options)() as Promise<any>).then(options =>
|
|
225
|
+
return ((enumOptionsSources as any)(rendererConfig.options)() as Promise<any>).then(options => Map(options.map((o: {value: CollectionReference}) => [o.value.id, o])))
|
|
231
226
|
}
|
|
232
227
|
}))
|
|
233
228
|
if (viewKind == "enumMultiSelection" && rendererConfig.kind == "enum")
|
|
234
|
-
return EnumMultiselectForm<any & FormLabel & BaseEnumContext<
|
|
229
|
+
return EnumMultiselectForm<any & FormLabel & BaseEnumContext<Value<CollectionReference>>, Unit, Value<CollectionReference>>()
|
|
235
230
|
.withView(formViews[viewKind][viewName]() )
|
|
236
|
-
.mapContext<any & EnumFormState<any & BaseEnumContext<
|
|
237
|
-
..._, label: label, tooltip, getOptions: () => ((enumOptionsSources as any)(rendererConfig.options)() as Promise<any>).then(options =>
|
|
231
|
+
.mapContext<any & EnumFormState<any & BaseEnumContext<Value<CollectionReference>>, Value<CollectionReference>> & Value<OrderedMap<Guid, CollectionReference>>>(_ => ({
|
|
232
|
+
..._, label: label, tooltip, getOptions: () => ((enumOptionsSources as any)(rendererConfig.options)() as Promise<any>).then(options => OrderedMap(options.map((o: {value: CollectionReference}) => [o.value.id, o])))
|
|
238
233
|
}))
|
|
239
234
|
if (viewKind == "streamSingleSelection")
|
|
240
235
|
return SearchableInfiniteStreamForm<CollectionReference, any & FormLabel, Unit>()
|
|
@@ -2,12 +2,14 @@ import { Set, List, Map, OrderedMap } from "immutable";
|
|
|
2
2
|
import { GenericType, GenericTypes, PrimitiveTypes } from "../built-ins/state";
|
|
3
3
|
import { InjectedPrimitives } from "../injectables/state";
|
|
4
4
|
import { ValueOrErrors } from "../../../../../collections/domains/valueOrErrors/state";
|
|
5
|
+
import { Value } from "../../../../../value/state";
|
|
5
6
|
|
|
6
7
|
export const isString = (_: any): _ is string => typeof _ == "string"
|
|
7
8
|
export const isObject = (_: any): _ is Object => typeof _ == "object"
|
|
8
9
|
export const isGenericType = (_: any): _ is GenericType => _ && GenericTypes.includes(_)
|
|
9
10
|
export const hasFun = (_: any): _ is { fun: string } => isObject(_) && "fun" in _ && isString(_.fun)
|
|
10
11
|
export const hasArgs = (_: any): _ is { args: Array<any> } => isObject(_) && "args" in _ && Array.isArray(_.args)
|
|
12
|
+
export type CaseName = string;
|
|
11
13
|
export type FieldName = string;
|
|
12
14
|
export type TypeName = string;
|
|
13
15
|
export type RawType<T> = {
|
|
@@ -18,13 +20,26 @@ export const RawType = {
|
|
|
18
20
|
isMaybeExtendedType: <T>(type: RawType<T>): type is RawType<T> & {extends: unknown} => "extends" in type,
|
|
19
21
|
isExtendedType: <T>(type: RawType<T>): type is RawType<T> & {extends: Array<TypeName>} => "extends" in type && Array.isArray(type.extends) && type.extends.length == 1 && (isString(type.extends[0])) ,
|
|
20
22
|
hasFields: <T>(type: RawType<T>): type is {fields: any} => "fields" in type,
|
|
23
|
+
isMaybeUnion: (_: any): _ is RawUnionType => isObject(_) && "fun" in _ && "args" in _ && _.fun == "Union" && Array.isArray(_["args"]) && _["args"].every(__ => typeof __ == "object" && "case" in __ && "fields" in __),
|
|
21
24
|
}
|
|
22
25
|
export type RawApplicationType<T> = {
|
|
23
26
|
fun?: GenericType;
|
|
24
27
|
args?: Array<RawFieldType<T>>;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export type
|
|
30
|
+
export type RawUnionCase = {
|
|
31
|
+
case?: string;
|
|
32
|
+
fields?: Object;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type RawUnionType = {
|
|
36
|
+
fun?: "Union";
|
|
37
|
+
args?: Array<RawUnionCase>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type RawFormType = {fields?: Object}
|
|
41
|
+
|
|
42
|
+
export type RawFieldType<T> = RawApplicationType<T> | string | PrimitiveTypeName<T> | RawUnionType | RawFormType | RawUnionCase;
|
|
28
43
|
export const RawFieldType = {
|
|
29
44
|
isMaybePrimitive: (_: any) => isString(_),
|
|
30
45
|
isPrimitive: <T>(_: RawFieldType<T>, injectedPrimitives: InjectedPrimitives<T> | undefined): _ is PrimitiveTypeName<T> => Boolean(PrimitiveTypes.some(__ => _ == __) || injectedPrimitives?.injectedPrimitives.has(_ as keyof T)),
|
|
@@ -36,24 +51,32 @@ export const RawFieldType = {
|
|
|
36
51
|
isMap: <T>(_: RawFieldType<T>): _ is {fun: "Map", args: Array<RawFieldType<T>>} => RawFieldType.isApplication(_) && _.fun == "Map" && _.args.length == 2,
|
|
37
52
|
isSingleSelection: <T>(_: RawFieldType<T>): _ is {fun: "SingleSelection", args: Array<RawFieldType<T>>} => RawFieldType.isApplication(_) && _.fun == "SingleSelection" && _.args.length == 1,
|
|
38
53
|
isMultiSelection: <T>(_: RawFieldType<T>): _ is {fun: "MultiSelection", args: Array<RawFieldType<T>>} => RawFieldType.isApplication(_) && _.fun == "MultiSelection" && _.args.length == 1,
|
|
54
|
+
isUnionCase: <T>(_: RawFieldType<T>): _ is {case: string, fields: object} => typeof _ == "object" && "case" in _ && "fields" in _,
|
|
55
|
+
isUnion: <T>(_: RawFieldType<T>): _ is {fun: "Union", args: Array<{case: string, fields: object}>} => hasFun(_) && isGenericType(_.fun) && hasArgs(_) && _.fun == "Union" && _.args.length > 1 && _.args.every(__ => typeof __ == "object" && "case" in __ && "fields" in __),
|
|
56
|
+
isForm: <T>(_: RawFieldType<T>): _ is {fields: Object} => typeof _ == "object" && "fields" in _ && isObject(_.fields),
|
|
39
57
|
}
|
|
40
58
|
|
|
41
|
-
export type PrimitiveTypeName<T> = "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "
|
|
59
|
+
export type PrimitiveTypeName<T> = "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "base64File" | "secret" | keyof T | "guid";
|
|
60
|
+
export type FormFields<T> = Map<FieldName, ParsedType<T>>
|
|
42
61
|
export type ParsedType<T> =
|
|
43
|
-
| { kind: "
|
|
62
|
+
| { kind: "unionCase", name: CaseName, fields: ParsedType<T> }
|
|
63
|
+
| { kind: "form"; value: TypeName; fields: FormFields<T> }
|
|
44
64
|
| { kind: "lookup"; name: TypeName; }
|
|
45
|
-
| { kind: "primitive"; value: PrimitiveTypeName<T>}
|
|
46
|
-
| { kind: "application"; value: GenericType; args: Array<ParsedType<T>>;
|
|
47
|
-
}
|
|
65
|
+
| { kind: "primitive"; value: PrimitiveTypeName<T> ;}
|
|
66
|
+
| { kind: "application"; value: GenericType; args: Array<ParsedType<T>>; }
|
|
67
|
+
| { kind: "union"; args: Map<CaseName, ParsedType<T>> }
|
|
48
68
|
|
|
49
69
|
export const ParsedType = {
|
|
50
70
|
Default: {
|
|
51
|
-
|
|
71
|
+
unionCase: <T>(name: CaseName, fields: ParsedType<T>): ParsedType<T> => ({ kind: "unionCase", name, fields }),
|
|
72
|
+
form: <T>(value: TypeName, fields: FormFields<T>): ParsedType<T> => ({ kind: "form", value, fields }),
|
|
52
73
|
primitive: <T>(name: PrimitiveTypeName<T> | keyof T): ParsedType<T> => ({ kind: "primitive", value: name }),
|
|
53
74
|
application: <T>(value: GenericType, args: Array<ParsedType<T>>): ParsedType<T> => ({ kind: "application", value, args }),
|
|
75
|
+
union: <T>(args: Map<CaseName, ParsedType<T>>): ParsedType<T> => ({ kind: "union", args }),
|
|
54
76
|
lookup: <T>(name: string): ParsedType<T> => ({ kind: "lookup", name }),
|
|
55
77
|
},
|
|
56
78
|
Operations: {
|
|
79
|
+
//TODO: Add cases
|
|
57
80
|
Equals: <T>(fst: ParsedType<T>, snd: ParsedType<T>): boolean =>
|
|
58
81
|
fst.kind == "form" && snd.kind == "form" ? fst.value == snd.value :
|
|
59
82
|
fst.kind == "lookup" && snd.kind == "lookup" ? fst.name == snd.name :
|
|
@@ -65,9 +88,8 @@ export const ParsedType = {
|
|
|
65
88
|
false,
|
|
66
89
|
|
|
67
90
|
ParseRawFieldType: <T>(fieldName: TypeName, rawFieldType: RawFieldType<T>, types: Set<TypeName>, injectedPrimitives?: InjectedPrimitives<T>) : ValueOrErrors<ParsedType<T>, string> => {
|
|
68
|
-
|
|
69
91
|
if (RawFieldType.isPrimitive(rawFieldType, injectedPrimitives))
|
|
70
|
-
return ValueOrErrors.Default.return(ParsedType.Default.primitive(rawFieldType))
|
|
92
|
+
return ValueOrErrors.Default.return(ParsedType.Default.primitive(rawFieldType == "guid" ? "string" : rawFieldType))
|
|
71
93
|
if (RawFieldType.isSingleSelection(rawFieldType))
|
|
72
94
|
return ParsedType.Operations.ParseRawFieldType(fieldName, rawFieldType.args[0], types, injectedPrimitives).Then(parsedArgs =>
|
|
73
95
|
ValueOrErrors.Default.return(ParsedType.Default.application("SingleSelection", [parsedArgs]))
|
|
@@ -86,9 +108,25 @@ export const ParsedType = {
|
|
|
86
108
|
ValueOrErrors.Default.return(ParsedType.Default.application("Map", [parsedArgs0, parsedArgs1]))
|
|
87
109
|
)
|
|
88
110
|
)
|
|
111
|
+
if(RawFieldType.isForm(rawFieldType))
|
|
112
|
+
return ValueOrErrors.Operations
|
|
113
|
+
.All(List(Object.entries(rawFieldType.fields).map(([fieldName, fieldType]) => ParsedType.Operations.ParseRawFieldType(fieldName, fieldType as RawFieldType<T>, types, injectedPrimitives)
|
|
114
|
+
.Then(parsedField => ValueOrErrors.Default.return([fieldName, parsedField] as const))
|
|
115
|
+
)))
|
|
116
|
+
.Then(parsedFields => ValueOrErrors.Default.return(Map(parsedFields.map(([fieldName, parsedField]) => [fieldName, parsedField]))))
|
|
117
|
+
.Then(parsedField => ValueOrErrors.Default.return<ParsedType<T>, string>(ParsedType.Default.form(fieldName, parsedField)))
|
|
118
|
+
if(RawFieldType.isUnionCase(rawFieldType))
|
|
119
|
+
return ParsedType.Operations.ParseRawFieldType(rawFieldType.case, rawFieldType.fields, types, injectedPrimitives).Then(parsedFields =>
|
|
120
|
+
ValueOrErrors.Default.return(ParsedType.Default.unionCase(rawFieldType.case, parsedFields))
|
|
121
|
+
)
|
|
122
|
+
if(RawFieldType.isUnion(rawFieldType))
|
|
123
|
+
return ValueOrErrors.Operations.All(List(
|
|
124
|
+
rawFieldType.args.map(_ => ParsedType.Operations.ParseRawFieldType(_.case, _, types, injectedPrimitives).Map(parsedFields => ({name: _.case, fields: parsedFields})))))
|
|
125
|
+
.Then(parsedFields => ValueOrErrors.Default.return(ParsedType.Default.union(Map(parsedFields.toArray().map(_ => [_.name, _.fields] as const)))))
|
|
126
|
+
|
|
89
127
|
if(RawFieldType.isLookup(rawFieldType, types))
|
|
90
128
|
return ValueOrErrors.Default.return(ParsedType.Default.lookup(rawFieldType))
|
|
91
129
|
return ValueOrErrors.Default.throw(List([`Invalid type ${JSON.stringify(rawFieldType)} for field ${JSON.stringify(fieldName)}`]))
|
|
92
130
|
}
|
|
93
131
|
}
|
|
94
|
-
}
|
|
132
|
+
}
|
|
@@ -94,8 +94,17 @@ export const FormsConfig = {
|
|
|
94
94
|
let parsedTypes: Map<TypeName, ParsedType<T>> = Map();
|
|
95
95
|
const rawTypesFromConfig = formsConfig.types;
|
|
96
96
|
const rawTypeNames = Set(Object.keys(rawTypesFromConfig))
|
|
97
|
-
Object.entries(
|
|
97
|
+
Object.entries(rawTypesFromConfig).forEach(([rawTypeName, rawType]) => {
|
|
98
98
|
const parsedType: ParsedType<T> = { kind: "form", value: rawTypeName, fields: Map() };
|
|
99
|
+
if (RawFieldType.isUnion(rawType)){
|
|
100
|
+
const parsingResult = ParsedType.Operations.ParseRawFieldType(rawTypeName, rawType, rawTypeNames, injectedPrimitives)
|
|
101
|
+
if(parsingResult.kind == "errors"){
|
|
102
|
+
errors = errors.concat(parsingResult.errors.toArray());
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
parsedTypes = parsedTypes.set(rawTypeName, parsingResult.value)
|
|
106
|
+
return
|
|
107
|
+
}
|
|
99
108
|
|
|
100
109
|
if (!RawType.hasFields(rawType)){
|
|
101
110
|
errors = errors.push(`missing 'fields' in type ${rawTypeName}: expected object`);
|
|
@@ -136,6 +145,7 @@ export const FormsConfig = {
|
|
|
136
145
|
enums = enums.set(enumOptionName, enumOption)
|
|
137
146
|
)
|
|
138
147
|
|
|
148
|
+
|
|
139
149
|
let streams: Map<string, TypeName> = Map();
|
|
140
150
|
Object.entries(formsConfig.apis.searchableStreams).forEach(([searchableStreamName, searchableStream]) =>
|
|
141
151
|
streams = streams.set(searchableStreamName, searchableStream)
|
|
@@ -193,6 +203,7 @@ export const FormsConfig = {
|
|
|
193
203
|
forms = forms.set(formName, parsedForm);
|
|
194
204
|
})
|
|
195
205
|
|
|
206
|
+
|
|
196
207
|
let launchers: ParsedFormJSON<T>["launchers"] = {
|
|
197
208
|
create: Map<string, Launcher>(),
|
|
198
209
|
edit: Map<string, Launcher>(),
|
|
@@ -121,7 +121,7 @@ export type EntityApis = {
|
|
|
121
121
|
export type EnumName = string
|
|
122
122
|
|
|
123
123
|
|
|
124
|
-
export type EnumOptionsSources = BasicFun<EnumName, BasicFun<Unit, Promise<Array<
|
|
124
|
+
export type EnumOptionsSources = BasicFun<EnumName, BasicFun<Unit, Promise<Array<{value: CollectionReference}>>>>
|
|
125
125
|
export const parseForms =
|
|
126
126
|
<LeafPredicates, T extends { [key in keyof T]: { type: any; state: any; }; },>(
|
|
127
127
|
builtIns: BuiltIns,
|
|
@@ -155,6 +155,7 @@ export const parseForms =
|
|
|
155
155
|
}
|
|
156
156
|
seen = seen.add(formDef.name)
|
|
157
157
|
formDef.fields.forEach((field, fieldName) => {
|
|
158
|
+
// TODO add a union case
|
|
158
159
|
if (field.type.kind == "lookup" || field.type.kind == "form") {
|
|
159
160
|
traverse(formsConfig.forms.get(field.renderer)!)
|
|
160
161
|
}
|
|
@@ -187,6 +188,7 @@ export const parseForms =
|
|
|
187
188
|
traverse(form)
|
|
188
189
|
})
|
|
189
190
|
|
|
191
|
+
|
|
190
192
|
formProcessingOrder.forEach(formName => {
|
|
191
193
|
const formConfig = formsConfig.forms.get(formName)!
|
|
192
194
|
const formFieldRenderers = formConfig.fields.map(field => field.renderer).toObject()
|
|
@@ -241,7 +243,8 @@ export const parseForms =
|
|
|
241
243
|
const initialState = parsedForm.initialFormState
|
|
242
244
|
const api = {
|
|
243
245
|
get: (id: string) => entityApis.get(launcher.api)(id).then((raw: any) => {
|
|
244
|
-
|
|
246
|
+
const x =fromAPIRawValue(parsedForm.formDef.type , formsConfig.types, builtIns, apiConverters, injectedPrimitives)(raw)
|
|
247
|
+
return x
|
|
245
248
|
}),
|
|
246
249
|
update: (id: any, parsed: any) => {
|
|
247
250
|
return parsed.kind =="errors" ? Promise.reject(parsed.errors) : entityApis.update(launcher.api)(id, parsed.value)
|
|
@@ -285,13 +288,12 @@ export const parseForms =
|
|
|
285
288
|
const form = parsedForm.form
|
|
286
289
|
const initialState = parsedForm.initialFormState
|
|
287
290
|
const api = {
|
|
288
|
-
default: (_: Unit) =>
|
|
289
|
-
.then((raw: any) =>
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
},
|
|
291
|
+
default: (_: Unit) =>
|
|
292
|
+
entityApis.default(launcher.api)(unit).then((raw: any) =>
|
|
293
|
+
fromAPIRawValue(parsedForm.formDef.type , formsConfig.types, builtIns, apiConverters, injectedPrimitives)(raw)),
|
|
294
|
+
create: (parsed: any) =>
|
|
295
|
+
parsed.kind == "errors" ? Promise.reject(parsed.errors) : entityApis.create(launcher.api)(parsed.value)
|
|
296
|
+
,
|
|
295
297
|
}
|
|
296
298
|
parsedLaunchers.create = parsedLaunchers.create.set(
|
|
297
299
|
launcherName,
|
|
@@ -8,17 +8,17 @@ import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
|
8
8
|
import { OnChange, CommonFormState } from "../../../singleton/state";
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
export type BaseEnumContext<
|
|
12
|
-
export type EnumFormState<Context, Element extends CollectionReference
|
|
11
|
+
export type BaseEnumContext<Element extends Value<CollectionReference>> = { getOptions:() => Promise<OrderedMap<Guid, Element>> }
|
|
12
|
+
export type EnumFormState<Context, Element extends Value<CollectionReference>> =
|
|
13
13
|
{ commonFormState: CommonFormState,
|
|
14
|
-
customFormState: { options: Synchronized<Unit, OrderedMap<Guid,
|
|
15
|
-
export const EnumFormState = <Context extends BaseEnumContext<
|
|
16
|
-
Default: (): EnumFormState<Context, Element
|
|
14
|
+
customFormState: { options: Synchronized<Unit, OrderedMap<Guid, Element>>; }; };
|
|
15
|
+
export const EnumFormState = <Context extends BaseEnumContext<Value<Element>>, Element extends CollectionReference>() => ({
|
|
16
|
+
Default: (): EnumFormState<Context, Value<Element>> => ({
|
|
17
17
|
commonFormState: CommonFormState.Default(),
|
|
18
18
|
customFormState: { options: Synchronized.Default(unit) }
|
|
19
19
|
}),
|
|
20
20
|
});
|
|
21
|
-
export type EnumView<Context extends FormLabel & BaseEnumContext<
|
|
21
|
+
export type EnumView<Context extends FormLabel & BaseEnumContext<Element>, Element extends Value<CollectionReference>, ForeignMutationsExpected> = View<
|
|
22
22
|
Context & Value<CollectionSelection<Element>> & EnumFormState<Context, Element> &
|
|
23
23
|
{ activeOptions: "loading" | Array<Element>; } & { disabled:boolean }, EnumFormState<Context, Element>,
|
|
24
24
|
ForeignMutationsExpected & {
|
|
@@ -9,7 +9,7 @@ import { FieldValidation, FieldValidationWithPath, FormValidatorSynchronized, On
|
|
|
9
9
|
import { BaseEnumContext, EnumFormState, EnumView } from "./state";
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
export const EnumForm = <Context extends FormLabel & BaseEnumContext<
|
|
12
|
+
export const EnumForm = <Context extends FormLabel & BaseEnumContext<Element>, ForeignMutationsExpected, Element extends Value<CollectionReference>>(
|
|
13
13
|
validation?: BasicFun<CollectionSelection<Element>, Promise<FieldValidation>>
|
|
14
14
|
) => {
|
|
15
15
|
const Co = CoTypedFactory<Context & Value<CollectionSelection<Element>> & { disabled:boolean }, EnumFormState<Context, Element>>()
|
|
@@ -20,7 +20,7 @@ export const EnumForm = <Context extends FormLabel & BaseEnumContext<Context, El
|
|
|
20
20
|
context={{
|
|
21
21
|
...props.context,
|
|
22
22
|
activeOptions: !AsyncState.Operations.hasValue(props.context.customFormState.options.sync) ? "loading"
|
|
23
|
-
: props.context.customFormState.options.sync.value.valueSeq().
|
|
23
|
+
: props.context.customFormState.options.sync.value.valueSeq().toArray()
|
|
24
24
|
}}
|
|
25
25
|
foreignMutations={{
|
|
26
26
|
...props.foreignMutations,
|
|
@@ -30,7 +30,7 @@ export const EnumForm = <Context extends FormLabel & BaseEnumContext<Context, El
|
|
|
30
30
|
if (newSelection == undefined)
|
|
31
31
|
return props.foreignMutations.onChange(replaceWith(CollectionSelection<Element>().Default.right("no selection")), List());
|
|
32
32
|
else
|
|
33
|
-
return props.foreignMutations.onChange(replaceWith(CollectionSelection<Element>().Default.left(newSelection
|
|
33
|
+
return props.foreignMutations.onChange(replaceWith(CollectionSelection<Element>().Default.left(newSelection)), List());
|
|
34
34
|
|
|
35
35
|
}
|
|
36
36
|
}} />
|
|
@@ -42,7 +42,7 @@ export const EnumForm = <Context extends FormLabel & BaseEnumContext<Context, El
|
|
|
42
42
|
Co.Template<ForeignMutationsExpected & { onChange: OnChange<CollectionSelection<Element>>; }>(
|
|
43
43
|
Co.GetState().then(current =>
|
|
44
44
|
{
|
|
45
|
-
return Synchronize<Unit, OrderedMap<Guid,
|
|
45
|
+
return Synchronize<Unit, OrderedMap<Guid, Element>>(current.getOptions, () => "transient failure", 5, 50)
|
|
46
46
|
.embed(_ => _.customFormState.options,
|
|
47
47
|
_ => current => ({ ...current, customFormState: { ...current.customFormState, options: _(current.customFormState.options) } })
|
|
48
48
|
)}
|
|
@@ -8,7 +8,7 @@ import { OnChange } from "../../../singleton/state";
|
|
|
8
8
|
import { BaseEnumContext, EnumFormState } from "../enum/state";
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
export type EnumMultiselectView<Context extends FormLabel & BaseEnumContext<
|
|
11
|
+
export type EnumMultiselectView<Context extends FormLabel & BaseEnumContext<Element>, Element extends Value<CollectionReference>, ForeignMutationsExpected> = View<
|
|
12
12
|
Context & Value<OrderedMap<Guid, Element>> & EnumFormState<Context, Element> & {
|
|
13
13
|
selectedIds: Array<Guid>;
|
|
14
14
|
activeOptions: "loading" | Array<Element>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { List, OrderedMap } from "immutable";
|
|
2
|
-
import { AsyncState, BasicFun,
|
|
2
|
+
import { AsyncState, BasicFun, CoTypedFactory, Guid, OrderedMapRepo, replaceWith, Synchronize, Unit, ValidateRunner } from "../../../../../../main";
|
|
3
3
|
import { Template } from "../../../../../template/state";
|
|
4
4
|
import { Value } from "../../../../../value/state";
|
|
5
5
|
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
6
6
|
import { FormLabel } from "../../../singleton/domains/form-label/state";
|
|
7
|
-
import { FieldValidation, FieldValidationWithPath,
|
|
7
|
+
import { FieldValidation, FieldValidationWithPath, OnChange,} from "../../../singleton/state";
|
|
8
8
|
import { BaseEnumContext, EnumFormState } from "../enum/state";
|
|
9
9
|
import { EnumMultiselectView } from "./state";
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
export const EnumMultiselectForm = <Context extends FormLabel & BaseEnumContext<
|
|
12
|
+
export const EnumMultiselectForm = <Context extends FormLabel & BaseEnumContext<Element>, ForeignMutationsExpected, Element extends Value<CollectionReference>>(
|
|
13
13
|
validation?: BasicFun<OrderedMap<Guid, Element>, Promise<FieldValidation>>
|
|
14
14
|
) => {
|
|
15
15
|
const Co = CoTypedFactory<Context & Value<OrderedMap<Guid, Element>> & EnumFormState<Context, Element> & { disabled:boolean }, EnumFormState<Context, Element>>()
|
|
@@ -17,9 +17,9 @@ export const EnumMultiselectForm = <Context extends FormLabel & BaseEnumContext<
|
|
|
17
17
|
<props.view {...props}
|
|
18
18
|
context={{
|
|
19
19
|
...props.context,
|
|
20
|
-
selectedIds: props.context.value.map(_ => _.id).valueSeq().toArray(),
|
|
20
|
+
selectedIds: props.context.value.map(_ => _.value.id).valueSeq().toArray(),
|
|
21
21
|
activeOptions: !AsyncState.Operations.hasValue(props.context.customFormState.options.sync) ? "loading"
|
|
22
|
-
: props.context.customFormState.options.sync.value.valueSeq().
|
|
22
|
+
: props.context.customFormState.options.sync.value.valueSeq().toArray()
|
|
23
23
|
}}
|
|
24
24
|
foreignMutations={{
|
|
25
25
|
...props.foreignMutations,
|
|
@@ -27,13 +27,15 @@ export const EnumMultiselectForm = <Context extends FormLabel & BaseEnumContext<
|
|
|
27
27
|
if (!AsyncState.Operations.hasValue(props.context.customFormState.options.sync)) return
|
|
28
28
|
const options = props.context.customFormState.options.sync.value
|
|
29
29
|
const newSelection = _
|
|
30
|
-
.flatMap(_ => {
|
|
30
|
+
.flatMap(_ => {
|
|
31
31
|
const selectedItem = options.get(_);
|
|
32
|
-
if (selectedItem != undefined)
|
|
32
|
+
if (selectedItem != undefined) {
|
|
33
|
+
const item: [string, Element] = [selectedItem.value.id, selectedItem];
|
|
34
|
+
return [item];
|
|
35
|
+
}
|
|
33
36
|
return [];
|
|
34
37
|
});
|
|
35
|
-
|
|
36
|
-
props.foreignMutations.onChange(replaceWith(OrderedMapRepo.Default.fromSmallIdentifiables(newSelection)), List());
|
|
38
|
+
props.foreignMutations.onChange(replaceWith(OrderedMap<string, Element>(newSelection)), List());
|
|
37
39
|
}
|
|
38
40
|
}}
|
|
39
41
|
/>
|
|
@@ -44,7 +46,7 @@ export const EnumMultiselectForm = <Context extends FormLabel & BaseEnumContext<
|
|
|
44
46
|
),
|
|
45
47
|
Co.Template<ForeignMutationsExpected & { onChange: OnChange<OrderedMap<Guid, Element>>; }>(
|
|
46
48
|
Co.GetState().then(current =>
|
|
47
|
-
Synchronize<Unit, OrderedMap<Guid,
|
|
49
|
+
Synchronize<Unit, OrderedMap<Guid, Element>>(current.getOptions, () => "transient failure", 5, 50)
|
|
48
50
|
.embed(_ => _.customFormState.options, _ => current => ({ ...current, customFormState: { ...current.customFormState, options: _(current.customFormState.options) } }))
|
|
49
51
|
),
|
|
50
52
|
{
|