ballerina-core 1.0.11 → 1.0.14
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/main.ts +2 -0
- package/package.json +1 -1
- package/src/coroutines/state.ts +4 -4
- package/src/forms/domains/launcher/domains/merger/state.ts +31 -3
- package/src/forms/domains/parser/coroutines/runner.ts +4 -3
- package/src/forms/domains/parser/domains/built-ins/state.ts +203 -0
- package/src/forms/domains/parser/domains/types/domains/converter/state.ts +1 -0
- package/src/forms/domains/parser/domains/types/state.ts +31 -0
- package/src/forms/domains/parser/domains/validator/state.ts +28 -80
- package/src/forms/domains/parser/state.tsx +47 -87
- package/src/fun/domains/updater/domains/caseUpdater/state.ts +5 -5
package/main.ts
CHANGED
|
@@ -95,6 +95,8 @@ export * from "./src/forms/domains/parser/state"
|
|
|
95
95
|
export * from "./src/forms/domains/parser/template"
|
|
96
96
|
export * from "./src/forms/domains/parser/coroutines/runner"
|
|
97
97
|
export * from "./src/forms/domains/parser/domains/validator/state"
|
|
98
|
+
export * from "./src/forms/domains/parser/domains/built-ins/state"
|
|
99
|
+
export * from "./src/forms/domains/parser/domains/types/state"
|
|
98
100
|
export * from "./src/forms/domains/launcher/domains/edit/state"
|
|
99
101
|
export * from "./src/forms/domains/launcher/domains/edit/template"
|
|
100
102
|
export * from "./src/forms/domains/launcher/domains/edit/coroutines/runner"
|
package/package.json
CHANGED
package/src/coroutines/state.ts
CHANGED
|
@@ -243,10 +243,10 @@ export const Coroutine = {
|
|
|
243
243
|
return CoroutineStep.Result(nextState, step.result);
|
|
244
244
|
else {
|
|
245
245
|
if (step.excludeOthers) {
|
|
246
|
-
console.log(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
);
|
|
246
|
+
// console.log(
|
|
247
|
+
// `exclude others detected, killing ${ps.length - 1
|
|
248
|
+
// } other coroutines`
|
|
249
|
+
// );
|
|
250
250
|
return CoroutineStep.MapState(
|
|
251
251
|
step.next([context, deltaT]),
|
|
252
252
|
((_) => thenMaybe(nextState, _) || id)
|
|
@@ -1,9 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { merge } from 'immutable'
|
|
2
|
+
|
|
3
|
+
const INITIAL_CONFIG = {
|
|
4
|
+
types: {},
|
|
5
|
+
forms: {},
|
|
6
|
+
apis: {
|
|
7
|
+
enumOptions: {},
|
|
8
|
+
searchableStreams: {},
|
|
9
|
+
entities: {},
|
|
10
|
+
},
|
|
11
|
+
mappings: {},
|
|
12
|
+
launchers: {}
|
|
13
|
+
}
|
|
2
14
|
|
|
3
15
|
export const FormsConfigMerger = {
|
|
4
16
|
Default:{
|
|
5
|
-
merge:(formsConfigs:any
|
|
6
|
-
|
|
17
|
+
merge: (formsConfigs: any): any => {
|
|
18
|
+
if (!formsConfigs || formsConfigs.length === 0) {
|
|
19
|
+
return {...INITIAL_CONFIG};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return formsConfigs.reduce((acc: any, current: any) => {
|
|
23
|
+
return {
|
|
24
|
+
types: merge(acc.types, current.types),
|
|
25
|
+
forms: merge(acc.forms, current.forms),
|
|
26
|
+
apis: {
|
|
27
|
+
enumOptions: merge(acc.apis.enumOptions, current.apis.enumOptions),
|
|
28
|
+
searchableStreams: merge(acc.apis.searchableStreams, current.apis.searchableStreams),
|
|
29
|
+
entities: merge(acc.apis.entities, current.apis.entities),
|
|
30
|
+
},
|
|
31
|
+
mappings: merge(acc.mappings, current.mappings),
|
|
32
|
+
launchers: merge(acc.launchers, current.launchers),
|
|
33
|
+
}
|
|
34
|
+
}, {...INITIAL_CONFIG})
|
|
7
35
|
}
|
|
8
36
|
}
|
|
9
37
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { AsyncState, FormsConfig, Sum, Synchronize, Unit } from "../../../../../main"
|
|
1
|
+
import { AsyncState, builtInsFromFieldViews, FormsConfig, Sum, Synchronize, Unit } from "../../../../../main"
|
|
2
2
|
import { CoTypedFactory } from "../../../../coroutines/builder"
|
|
3
|
-
import {
|
|
3
|
+
import { FormParsingResult, FormsParserContext, FormsParserState, parseForms } from "../state"
|
|
4
4
|
|
|
5
5
|
export const LoadValidateAndParseFormsConfig = () => {
|
|
6
6
|
const Co = CoTypedFactory<FormsParserContext, FormsParserState>()
|
|
@@ -9,12 +9,13 @@ export const LoadValidateAndParseFormsConfig = () => {
|
|
|
9
9
|
Co.GetState().then(current =>
|
|
10
10
|
Synchronize<Unit, FormParsingResult>(async() => {
|
|
11
11
|
const formsConfig = await current.getFormsConfig()
|
|
12
|
-
const builtIns = builtInsFromFieldViews(current.fieldViews)
|
|
12
|
+
const builtIns = builtInsFromFieldViews(current.fieldViews, current.fieldTypeConverters)
|
|
13
13
|
const validationResult = FormsConfig.Default.validateAndParseAPIResponse(builtIns)(formsConfig)
|
|
14
14
|
if (validationResult.kind == "r")
|
|
15
15
|
return Sum.Default.right(validationResult.value)
|
|
16
16
|
return parseForms(
|
|
17
17
|
builtIns,
|
|
18
|
+
current.fieldTypeConverters,
|
|
18
19
|
current.containerFormView,
|
|
19
20
|
current.nestedContainerFormView,
|
|
20
21
|
current.fieldViews,
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { Map, List, Set, OrderedMap } from "immutable"
|
|
2
|
+
import { CollectionReference } from "../../../collection/domains/reference/state";
|
|
3
|
+
import { CollectionSelection } from "../../../collection/domains/selection/state";
|
|
4
|
+
import { BasicFun } from "../../../../../fun/state";
|
|
5
|
+
import { Option, Sum } from "../../../../../collections/domains/sum/state"
|
|
6
|
+
import { Type, TypeDefinition, TypeName } from "../../../../../../main";
|
|
7
|
+
|
|
8
|
+
export const PrimitiveTypes =
|
|
9
|
+
["string",
|
|
10
|
+
"number",
|
|
11
|
+
"boolean",
|
|
12
|
+
"maybeBoolean",
|
|
13
|
+
"Date",
|
|
14
|
+
"CollectionReference"] as const
|
|
15
|
+
export type PrimitiveType = (typeof PrimitiveTypes)[number]
|
|
16
|
+
|
|
17
|
+
export const GenericTypes = [
|
|
18
|
+
"SingleSelection",
|
|
19
|
+
"MultiSelection",
|
|
20
|
+
"List"] as const
|
|
21
|
+
export type GenericType = (typeof GenericTypes)[number]
|
|
22
|
+
|
|
23
|
+
export type ApiConverter<T> = { fromAPIRawValue: BasicFun<any, T>, toAPIRawValue: BasicFun<T, any> }
|
|
24
|
+
export type ApiConverters = {
|
|
25
|
+
"string": ApiConverter<string>
|
|
26
|
+
"number": ApiConverter<number>
|
|
27
|
+
"boolean": ApiConverter<boolean>
|
|
28
|
+
"maybeBoolean": ApiConverter<boolean | undefined>
|
|
29
|
+
"Date": ApiConverter<Date>
|
|
30
|
+
"CollectionReference": ApiConverter<CollectionReference>
|
|
31
|
+
"SingleSelection": ApiConverter<CollectionSelection<any>>
|
|
32
|
+
"MultiSelection": ApiConverter<OrderedMap<string, any>>
|
|
33
|
+
"List": ApiConverter<List<any>>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type PrimitiveBuiltIn = { renderers: Set<keyof BuiltIns["renderers"]>, apiConverters: ApiConverter<any>, defaultValue: any }
|
|
37
|
+
export type GenericBuiltIn = { defaultValue: any, apiConverters: ApiConverter<any> }
|
|
38
|
+
export type BuiltIns = {
|
|
39
|
+
primitives: Map<string, PrimitiveBuiltIn>;
|
|
40
|
+
generics: Map<string, GenericBuiltIn>;
|
|
41
|
+
renderers: {
|
|
42
|
+
boolean: Set<string>;
|
|
43
|
+
maybeBoolean: Set<string>;
|
|
44
|
+
number: Set<string>;
|
|
45
|
+
string: Set<string>;
|
|
46
|
+
date: Set<string>;
|
|
47
|
+
enumSingleSelection: Set<string>;
|
|
48
|
+
enumMultiSelection: Set<string>;
|
|
49
|
+
streamSingleSelection: Set<string>;
|
|
50
|
+
streamMultiSelection: Set<string>;
|
|
51
|
+
list: Set<string>;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const builtInsFromFieldViews = (fieldViews: any, fieldTypeConverters: ApiConverters): BuiltIns => {
|
|
56
|
+
let builtins: BuiltIns = {
|
|
57
|
+
"primitives": Map<string, PrimitiveBuiltIn>([
|
|
58
|
+
["string", { renderers: Set(["string"]), apiConverters: fieldTypeConverters["string"], defaultValue: "" }] as [string, PrimitiveBuiltIn],
|
|
59
|
+
["number", { renderers: Set(["number"]), apiConverters: fieldTypeConverters["number"], defaultValue: 0 }] as [string, PrimitiveBuiltIn],
|
|
60
|
+
["boolean", { renderers: Set(["boolean"]), apiConverters: fieldTypeConverters["boolean"], defaultValue: false }],
|
|
61
|
+
["maybeBoolean", { renderers: Set(["maybeBoolean"]), apiConverters: fieldTypeConverters["maybeBoolean"], defaultValue: undefined }] as [string, PrimitiveBuiltIn],
|
|
62
|
+
["date", { renderers: Set(["date"]), apiConverters: fieldTypeConverters["Date"], defaultValue: new Date(Date.now()) }] as [string, PrimitiveBuiltIn],
|
|
63
|
+
["Date", { renderers: Set(["date"]), apiConverters: fieldTypeConverters["Date"], defaultValue: new Date(Date.now()) }] as [string, PrimitiveBuiltIn],
|
|
64
|
+
["CollectionReference", { renderers: Set(["enumSingleSelection", "enumMultiSelection", "streamSingleSelection", "streamMultiSelection"]), apiConverters: fieldTypeConverters["CollectionReference"], defaultValue: CollectionReference.Default("", "") }] as [string, PrimitiveBuiltIn]
|
|
65
|
+
]),
|
|
66
|
+
"generics": Map([
|
|
67
|
+
["SingleSelection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
|
|
68
|
+
["Multiselection", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: Map() }] as [string, GenericBuiltIn],
|
|
69
|
+
["List", { apiConverters: fieldTypeConverters["SingleSelection"], defaultValue: [] }] as [string, GenericBuiltIn]
|
|
70
|
+
]),
|
|
71
|
+
"renderers": {
|
|
72
|
+
"boolean": Set(),
|
|
73
|
+
"maybeBoolean": Set(),
|
|
74
|
+
"date": Set(),
|
|
75
|
+
"enumMultiSelection": Set(),
|
|
76
|
+
"enumSingleSelection": Set(),
|
|
77
|
+
"streamMultiSelection": Set(),
|
|
78
|
+
"streamSingleSelection": Set(),
|
|
79
|
+
"number": Set(),
|
|
80
|
+
"string": Set(),
|
|
81
|
+
"list": Set(),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
Object.keys(builtins.renderers).forEach((_categoryName) => {
|
|
85
|
+
const categoryName = _categoryName as keyof BuiltIns["renderers"]
|
|
86
|
+
if (categoryName in fieldViews) {
|
|
87
|
+
Object.keys(fieldViews[categoryName]).forEach(viewName => {
|
|
88
|
+
builtins.renderers[categoryName] = builtins.renderers[categoryName].add(viewName)
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
return builtins
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
export const defaultValue = (types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns) => (t: TypeName): any => {
|
|
97
|
+
let primitive = builtIns.primitives.get(t)
|
|
98
|
+
if (primitive != undefined) {
|
|
99
|
+
return primitive.defaultValue
|
|
100
|
+
} else {
|
|
101
|
+
let generic = builtIns.generics.get(t)
|
|
102
|
+
if (generic != undefined) {
|
|
103
|
+
return generic.defaultValue
|
|
104
|
+
} else {
|
|
105
|
+
let custom = types.get(t)
|
|
106
|
+
if (custom != undefined) {
|
|
107
|
+
let res = {} as any
|
|
108
|
+
custom.fields.forEach((field, fieldName) => {
|
|
109
|
+
res[fieldName] = defaultValue(types, builtIns)(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
return res
|
|
113
|
+
} else {
|
|
114
|
+
throw `cannot find type ${t} when resolving defaultValue`
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const fromAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters) => (raw:any) : any => {
|
|
121
|
+
// alert(JSON.stringify(t))
|
|
122
|
+
if (raw == undefined) {
|
|
123
|
+
console.warn(`instantiating default value for type ${JSON.stringify(t)}: the value was undefined so something is missing from the API response`)
|
|
124
|
+
return defaultValue(types, builtIns)(t.kind == "primitive" ? t.value : t.kind == "lookup" ? t.name : t.value)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (t.kind == "primitive") {
|
|
128
|
+
return converters[t.value].fromAPIRawValue(raw)
|
|
129
|
+
} else if (t.kind == "application") { // application here means "generic type application"
|
|
130
|
+
if (t.value == "SingleSelection" && t.args.length == 1) {
|
|
131
|
+
let result = converters[t.value].fromAPIRawValue(raw)
|
|
132
|
+
result = CollectionSelection().Updaters.left(
|
|
133
|
+
fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))(result)
|
|
134
|
+
return result
|
|
135
|
+
}
|
|
136
|
+
if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
|
|
137
|
+
let result = converters["MultiSelection"].fromAPIRawValue(raw)
|
|
138
|
+
result = result.map(fromAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))
|
|
139
|
+
return result
|
|
140
|
+
}
|
|
141
|
+
if (t.value == "List" && t.args.length == 1) {
|
|
142
|
+
let result = converters[t.value].fromAPIRawValue(raw)
|
|
143
|
+
result = result.map(fromAPIRawValue(
|
|
144
|
+
PrimitiveTypes.some(_ => _ == t.args[0]) ?
|
|
145
|
+
{ kind:"primitive", value:t.args[0] as PrimitiveType }
|
|
146
|
+
: { kind:"lookup", name:t.args[0] }
|
|
147
|
+
, types, builtIns, converters))
|
|
148
|
+
return result
|
|
149
|
+
}
|
|
150
|
+
} else { // t.kind == lookup: we are dealing with a record/object
|
|
151
|
+
let result:any = {...raw}
|
|
152
|
+
const tDef = types.get(t.name)!
|
|
153
|
+
tDef.fields.forEach((fieldType, fieldName) => {
|
|
154
|
+
const fieldValue = raw[fieldName]
|
|
155
|
+
result[fieldName] = fromAPIRawValue(fieldType, types, builtIns, converters)(fieldValue)
|
|
156
|
+
})
|
|
157
|
+
return result
|
|
158
|
+
}
|
|
159
|
+
console.error(`unsupported type ${JSON.stringify(t)}, returning the raw value right away`)
|
|
160
|
+
return raw
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
export const toAPIRawValue = (t:Type, types:Map<TypeName, TypeDefinition>, builtIns:BuiltIns, converters:ApiConverters) => (raw:any) : any => {
|
|
165
|
+
if (t.kind == "primitive") {
|
|
166
|
+
return converters[t.value].toAPIRawValue(raw as never)
|
|
167
|
+
} else if (t.kind == "application") { // application here means "generic type application"
|
|
168
|
+
if (t.value == "SingleSelection" && t.args.length == 1) {
|
|
169
|
+
let result = converters[t.value].toAPIRawValue(raw)
|
|
170
|
+
if (result != undefined)
|
|
171
|
+
result = toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters)(result)
|
|
172
|
+
return result
|
|
173
|
+
}
|
|
174
|
+
if ((t.value == "Multiselection" || t.value == "MultiSelection") && t.args.length == 1) {
|
|
175
|
+
// alert(`MultiSelect ${JSON.stringify(t)} ${JSON.stringify(raw)}`)
|
|
176
|
+
let result = converters["MultiSelection"].toAPIRawValue(raw)
|
|
177
|
+
// alert(`MultiSelect result1 = ${JSON.stringify(result)}`)
|
|
178
|
+
// alert(`${JSON.stringify(t.args[0])}`)
|
|
179
|
+
result = result.map(toAPIRawValue({ kind:"lookup", name:t.args[0] }, types, builtIns, converters))
|
|
180
|
+
// alert(`MultiSelect result2 = ${JSON.stringify(result)}`)
|
|
181
|
+
return result
|
|
182
|
+
}
|
|
183
|
+
if (t.value == "List" && t.args.length == 1) {
|
|
184
|
+
let result = converters[t.value].toAPIRawValue(raw)
|
|
185
|
+
result = result.map(toAPIRawValue(
|
|
186
|
+
PrimitiveTypes.some(_ => _ == t.args[0]) ?
|
|
187
|
+
{ kind:"primitive", value:t.args[0] as PrimitiveType }
|
|
188
|
+
: { kind:"lookup", name:t.args[0] },
|
|
189
|
+
// { kind:"lookup", name:t.args[0] },
|
|
190
|
+
types, builtIns, converters))
|
|
191
|
+
return result
|
|
192
|
+
}
|
|
193
|
+
} else { // t.kind == lookup: we are dealing with a record/object
|
|
194
|
+
let result:any = {...raw}
|
|
195
|
+
const tDef = types.get(t.name)!
|
|
196
|
+
tDef.fields.forEach((fieldType, fieldName) => {
|
|
197
|
+
const fieldValue = raw[fieldName]
|
|
198
|
+
result[fieldName] = toAPIRawValue(fieldType, types, builtIns, converters)(fieldValue)
|
|
199
|
+
})
|
|
200
|
+
return result
|
|
201
|
+
}
|
|
202
|
+
return defaultValue(types, builtIns)(t.value)
|
|
203
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// export type
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { OrderedMap } from "immutable";
|
|
2
|
+
|
|
3
|
+
export type FieldName = string;
|
|
4
|
+
export type TypeName = string;
|
|
5
|
+
export type TypeDefinition = {
|
|
6
|
+
extends: Array<TypeName>;
|
|
7
|
+
name: TypeName;
|
|
8
|
+
fields: OrderedMap<FieldName, Type>;
|
|
9
|
+
};
|
|
10
|
+
export type Type = {
|
|
11
|
+
kind: "lookup"; name: TypeName;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "primitive"; value: "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "CollectionReference";
|
|
14
|
+
} | {
|
|
15
|
+
kind: "application"; value: TypeName; args: Array<TypeName>;
|
|
16
|
+
};
|
|
17
|
+
export const Type = {
|
|
18
|
+
Default: {
|
|
19
|
+
lookup: (name: TypeName): Type => ({ kind: "lookup", name })
|
|
20
|
+
},
|
|
21
|
+
Operations: {
|
|
22
|
+
Equals: (fst: Type, snd: Type): boolean =>
|
|
23
|
+
fst.kind == "lookup" && snd.kind == "lookup" ? fst.name == snd.name :
|
|
24
|
+
fst.kind == "primitive" && snd.kind == "primitive" ? fst.value == snd.value :
|
|
25
|
+
fst.kind == "application" && snd.kind == "application" ?
|
|
26
|
+
fst.value == snd.value &&
|
|
27
|
+
fst.args.length == snd.args.length &&
|
|
28
|
+
fst.args.every((v, i) => v == snd.args[i]) :
|
|
29
|
+
false
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -1,35 +1,6 @@
|
|
|
1
1
|
import { Set, Map, OrderedMap } from "immutable";
|
|
2
|
-
import { BoolExpr, FormsConfigMerger, MappingPaths, Sum } from "../../../../../../main";
|
|
2
|
+
import { BoolExpr, BuiltIns, FieldName, FormsConfigMerger, MappingPaths, Sum, Type, TypeDefinition, TypeName } from "../../../../../../main";
|
|
3
3
|
|
|
4
|
-
export type FieldName = string;
|
|
5
|
-
export type TypeName = string;
|
|
6
|
-
export type TypeDefinition = {
|
|
7
|
-
extends: Array<TypeName>;
|
|
8
|
-
name: TypeName;
|
|
9
|
-
fields: OrderedMap<FieldName, Type>;
|
|
10
|
-
};
|
|
11
|
-
export type Type = {
|
|
12
|
-
kind: "lookup"; name: TypeName;
|
|
13
|
-
} | {
|
|
14
|
-
kind: "primitive"; value: "string" | "number" | "maybeBoolean" | "boolean" | "Date" | "CollectionReference";
|
|
15
|
-
} | {
|
|
16
|
-
kind: "application"; value: TypeName; args: Array<TypeName>;
|
|
17
|
-
};
|
|
18
|
-
export const Type = {
|
|
19
|
-
Default: {
|
|
20
|
-
lookup: (name: TypeName): Type => ({ kind: "lookup", name })
|
|
21
|
-
},
|
|
22
|
-
Operations: {
|
|
23
|
-
Equals: (fst: Type, snd: Type): boolean =>
|
|
24
|
-
fst.kind == "lookup" && snd.kind == "lookup" ? fst.name == snd.name :
|
|
25
|
-
fst.kind == "primitive" && snd.kind == "primitive" ? fst.value == snd.value :
|
|
26
|
-
fst.kind == "application" && snd.kind == "application" ?
|
|
27
|
-
fst.value == snd.value &&
|
|
28
|
-
fst.args.length == snd.args.length &&
|
|
29
|
-
fst.args.every((v, i) => v == snd.args[i]) :
|
|
30
|
-
false
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
4
|
export type FieldConfig = {
|
|
34
5
|
renderer: string;
|
|
35
6
|
label: string
|
|
@@ -91,37 +62,12 @@ export type FormsConfig = {
|
|
|
91
62
|
};
|
|
92
63
|
export type FormValidationError = string;
|
|
93
64
|
|
|
94
|
-
export type PrimitiveBuiltIn = { renderers: Set<keyof BuiltIns["renderers"]>, defaultValue: any }
|
|
95
|
-
export type GenericBuiltIn = { defaultValue: any }
|
|
96
|
-
export type BuiltIns = {
|
|
97
|
-
primitives: Map<string, PrimitiveBuiltIn>;
|
|
98
|
-
generics: Map<string, GenericBuiltIn>;
|
|
99
|
-
renderers: {
|
|
100
|
-
BooleanViews: Set<string>;
|
|
101
|
-
MaybeBooleanViews: Set<string>;
|
|
102
|
-
NumberViews: Set<string>;
|
|
103
|
-
StringViews: Set<string>;
|
|
104
|
-
DateViews: Set<string>;
|
|
105
|
-
EnumViews: Set<string>;
|
|
106
|
-
EnumMultiselectViews: Set<string>;
|
|
107
|
-
InfiniteStreamViews: Set<string>;
|
|
108
|
-
InfiniteStreamMultiselectViews: Set<string>;
|
|
109
|
-
ListViews: Set<string>;
|
|
110
|
-
};
|
|
111
|
-
};
|
|
112
|
-
|
|
113
65
|
export type FormValidationResult = Sum<FormsConfig, Array<FormValidationError>>
|
|
114
66
|
export const FormsConfig = {
|
|
115
67
|
Default: {
|
|
116
|
-
validateAndParseAPIResponse: (builtIns: BuiltIns) => (
|
|
68
|
+
validateAndParseAPIResponse: (builtIns: BuiltIns) => (fc: any): FormValidationResult => {
|
|
117
69
|
let errors: Array<FormValidationError> = [];
|
|
118
|
-
|
|
119
|
-
alert("formsConfig is an array!")
|
|
120
|
-
const merged = FormsConfigMerger.Default.merge(formsConfig, errors)
|
|
121
|
-
formsConfig = merged[0]
|
|
122
|
-
errors = merged[0]
|
|
123
|
-
}
|
|
124
|
-
|
|
70
|
+
const formsConfig = Array.isArray(fc) ? FormsConfigMerger.Default.merge(fc) : fc;
|
|
125
71
|
let types: Map<TypeName, TypeDefinition> = Map();
|
|
126
72
|
if ("types" in formsConfig == false) {
|
|
127
73
|
errors.push("the formsConfig does not contain a 'types' field");
|
|
@@ -346,57 +292,59 @@ export const FormsConfig = {
|
|
|
346
292
|
if (fieldTypeDef.value == "maybeBoolean") {
|
|
347
293
|
// alert(JSON.stringify(fieldConfig["renderer"]))
|
|
348
294
|
// alert(JSON.stringify(builtIns.renderers.MaybeBooleanViews))
|
|
349
|
-
if (!builtIns.renderers.
|
|
295
|
+
if (!builtIns.renderers.maybeBoolean.has(fieldConfig["renderer"]))
|
|
350
296
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
351
297
|
} else if (fieldTypeDef.value == "boolean") {
|
|
352
|
-
if (!builtIns.renderers.
|
|
298
|
+
if (!builtIns.renderers.boolean.has(fieldConfig["renderer"]))
|
|
353
299
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
354
300
|
} else if (fieldTypeDef.value == "number") {
|
|
355
|
-
if (!builtIns.renderers.
|
|
301
|
+
if (!builtIns.renderers.number.has(fieldConfig["renderer"]))
|
|
356
302
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
357
303
|
} else if (fieldTypeDef.value == "string") {
|
|
358
|
-
if (!builtIns.renderers.
|
|
304
|
+
if (!builtIns.renderers.string.has(fieldConfig["renderer"]))
|
|
359
305
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
360
306
|
} else if (fieldTypeDef.value == "Date") {
|
|
361
|
-
if (!builtIns.renderers.
|
|
307
|
+
if (!builtIns.renderers.date.has(fieldConfig["renderer"])) {
|
|
308
|
+
alert(JSON.stringify(builtIns.renderers))
|
|
362
309
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
363
|
-
|
|
310
|
+
}
|
|
311
|
+
} else {
|
|
364
312
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
365
313
|
}
|
|
366
314
|
} else if (fieldTypeDef?.kind == "application") {
|
|
367
315
|
if (fieldTypeDef?.value == "SingleSelection") {
|
|
368
|
-
if (!builtIns.renderers.
|
|
369
|
-
!builtIns.renderers.
|
|
316
|
+
if (!builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"]) &&
|
|
317
|
+
!builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"]))
|
|
370
318
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
371
319
|
} else if (fieldTypeDef?.value == "Multiselection") {
|
|
372
|
-
if (!builtIns.renderers.
|
|
373
|
-
!builtIns.renderers.
|
|
320
|
+
if (!builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) &&
|
|
321
|
+
!builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"]))
|
|
374
322
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
375
323
|
} else if (fieldTypeDef?.value == "List") {
|
|
376
|
-
if (!builtIns.renderers.
|
|
324
|
+
if (!builtIns.renderers.list.has(fieldConfig["renderer"]))
|
|
377
325
|
errors.push(`field ${fieldName} of form ${formName} references non-existing ${fieldTypeDef.value} 'renderer' ${fieldConfig["renderer"]}`);
|
|
378
326
|
}
|
|
379
327
|
if (fieldTypeDef.args.length < 1)
|
|
380
328
|
errors.push(`field ${fieldName} of form ${formName} should have one type argument}`);
|
|
381
329
|
else if (
|
|
382
|
-
(builtIns.renderers.
|
|
330
|
+
(builtIns.renderers.list.has(fieldConfig["renderer"])) && "elementRenderer" in fieldConfig != true)
|
|
383
331
|
errors.push(`field ${fieldName} of form ${formName} is missing the 'elementRenderer' property`);
|
|
384
332
|
else if (
|
|
385
|
-
(builtIns.renderers.
|
|
386
|
-
builtIns.renderers.
|
|
333
|
+
(builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) ||
|
|
334
|
+
builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"])) && "options" in fieldConfig != true)
|
|
387
335
|
errors.push(`field ${fieldName} of form ${formName} is missing the 'options' property`);
|
|
388
336
|
else if (
|
|
389
|
-
(builtIns.renderers.
|
|
390
|
-
builtIns.renderers.
|
|
337
|
+
(builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"]) ||
|
|
338
|
+
builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"])) && "stream" in fieldConfig != true)
|
|
391
339
|
errors.push(`field ${fieldName} of form ${formName} is missing the 'stream' property`);
|
|
392
|
-
else if ((builtIns.renderers.
|
|
393
|
-
builtIns.renderers.
|
|
340
|
+
else if ((builtIns.renderers.enumMultiSelection.has(fieldConfig["renderer"]) ||
|
|
341
|
+
builtIns.renderers.enumSingleSelection.has(fieldConfig["renderer"])) && (enums.get(fieldConfig["options"])) != fieldTypeDef.args[0]) {
|
|
394
342
|
if (enums.has(fieldConfig["options"]))
|
|
395
343
|
errors.push(`field ${fieldName} of form ${formName} references an enum api with type ${enums.get(fieldConfig["options"])} when ${fieldTypeDef.args[0]} was expected`);
|
|
396
344
|
else
|
|
397
345
|
errors.push(`field ${fieldName} of form ${formName} references a non-existing enum api`);
|
|
398
|
-
} else if ((builtIns.renderers.
|
|
399
|
-
builtIns.renderers.
|
|
346
|
+
} else if ((builtIns.renderers.streamMultiSelection.has(fieldConfig["renderer"]) ||
|
|
347
|
+
builtIns.renderers.streamSingleSelection.has(fieldConfig["renderer"])) && (streams.get(fieldConfig["stream"])) != fieldTypeDef.args[0]) {
|
|
400
348
|
if (streams.has(fieldConfig["stream"]))
|
|
401
349
|
errors.push(`field ${fieldName} of form ${formName} references an api with type ${streams.get(fieldConfig["stream"])} when ${fieldTypeDef.args[0]} was expected`);
|
|
402
350
|
else
|
|
@@ -415,7 +363,7 @@ export const FormsConfig = {
|
|
|
415
363
|
Object.keys(configFormDef["fields"]).forEach(fieldName => {
|
|
416
364
|
const fieldConfig = configFormDef["fields"][fieldName]
|
|
417
365
|
const fieldTypeDef = formTypeDef?.fields.get(fieldName);
|
|
418
|
-
if (fieldTypeDef && fieldTypeDef.kind == "application" && fieldTypeDef.value == "List" && (builtIns.renderers.
|
|
366
|
+
if (fieldTypeDef && fieldTypeDef.kind == "application" && fieldTypeDef.value == "List" && (builtIns.renderers.list.has(fieldConfig["renderer"]))) {
|
|
419
367
|
let elementRenderer = fieldConfig["elementRenderer"]
|
|
420
368
|
let elementType = fieldTypeDef.args[0]
|
|
421
369
|
const rendererHasType = (elementRenderer: string, elementType: string): Array<string> => {
|
|
@@ -570,8 +518,8 @@ export const FormsConfig = {
|
|
|
570
518
|
})
|
|
571
519
|
|
|
572
520
|
if (errors.length > 0) {
|
|
573
|
-
console.
|
|
574
|
-
console.
|
|
521
|
+
console.error("parsing errors")
|
|
522
|
+
console.error(errors)
|
|
575
523
|
return Sum.Default.right(errors);
|
|
576
524
|
}
|
|
577
525
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Collection, Map, OrderedMap, OrderedSet, Set } from "immutable";
|
|
2
|
-
import { BoolExpr, Unit, PromiseRepo, Guid, LeafPredicatesEvaluators, Predicate, FormsConfig, BuiltIns, FormDef, Sum, BasicFun, Template, unit, EditFormState, EditFormTemplate, ApiErrors, CreateFormTemplate, EntityFormTemplate, SharedFormState, CreateFormState, Entity, EditFormContext, CreateFormContext, MappedEntityFormTemplate, Mapping, FormValidationResult, Synchronized, simpleUpdater,
|
|
2
|
+
import { BoolExpr, Unit, PromiseRepo, Guid, LeafPredicatesEvaluators, Predicate, FormsConfig, BuiltIns, FormDef, Sum, BasicFun, Template, unit, EditFormState, EditFormTemplate, ApiErrors, CreateFormTemplate, EntityFormTemplate, SharedFormState, CreateFormState, Entity, EditFormContext, CreateFormContext, MappedEntityFormTemplate, Mapping, FormValidationResult, Synchronized, simpleUpdater, PrimitiveType, GenericType, ApiConverter, TypeName, ListFieldState, ListForm, TypeDefinition, ApiConverters, defaultValue, fromAPIRawValue, toAPIRawValue } from "../../../../main";
|
|
3
3
|
import { Value } from "../../../value/state";
|
|
4
4
|
import { CollectionReference } from "../collection/domains/reference/state";
|
|
5
5
|
import { CollectionSelection } from "../collection/domains/selection/state";
|
|
@@ -26,43 +26,43 @@ const parseOptions = (leafPredicates: any, options: any) => {
|
|
|
26
26
|
export const FieldView = //<Context, FieldViews extends DefaultFieldViews, EnumFieldConfigs extends {}, EnumSources extends {}>() => <ViewType extends keyof FieldViews, ViewName extends keyof FieldViews[ViewType]>
|
|
27
27
|
(fieldViews: any, viewType: any, viewName: any, fieldName: string, label: string, enumFieldConfigs: any, enumSources: any, leafPredicates: any): any => // FieldView<Context, FieldViews, ViewType, ViewName> =>
|
|
28
28
|
{
|
|
29
|
-
if (viewType == "
|
|
29
|
+
if (viewType == "maybeBoolean")
|
|
30
30
|
return MaybeBooleanForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
31
31
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
32
32
|
.mapContext<any & SharedFormState & Value<boolean>>(_ => ({ ..._, label: label })) as any
|
|
33
|
-
if (viewType == "
|
|
33
|
+
if (viewType == "boolean")
|
|
34
34
|
return BooleanForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
35
35
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
36
36
|
.mapContext<any & SharedFormState & Value<boolean>>(_ => ({ ..._, label: label })) as any
|
|
37
|
-
if (viewType == "
|
|
37
|
+
if (viewType == "date")
|
|
38
38
|
return DateForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
39
39
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
40
40
|
.mapContext<any & DateFormState & Value<Date>>(_ => ({ ..._, label: label })) as any
|
|
41
|
-
if (viewType == "
|
|
41
|
+
if (viewType == "number")
|
|
42
42
|
return NumberForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
43
43
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
44
44
|
.mapContext<any & SharedFormState & Value<number>>(_ => ({ ..._, label: label })) as any
|
|
45
|
-
if (viewType == "
|
|
45
|
+
if (viewType == "string")
|
|
46
46
|
return StringForm<any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
47
47
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
48
48
|
.mapContext<any & SharedFormState & Value<string>>(_ => ({ ..._, label: label })) as any
|
|
49
|
-
if (viewType == "
|
|
49
|
+
if (viewType == "enumSingleSelection")
|
|
50
50
|
return EnumForm<any & FormLabel & BaseEnumContext<any, CollectionReference>, Unit, CollectionReference>(_ => PromiseRepo.Default.mock(() => []))
|
|
51
51
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
52
52
|
.mapContext<any & EnumFormState<any & BaseEnumContext<any, CollectionReference>, CollectionReference> & Value<CollectionSelection<CollectionReference>>>(_ => ({
|
|
53
53
|
..._, label: label, getOptions: () => ((enumFieldConfigs as any)((enumSources as any)[fieldName]) as Promise<any>).then(options => parseOptions(leafPredicates, options))
|
|
54
54
|
})) as any
|
|
55
|
-
if (viewType == "
|
|
55
|
+
if (viewType == "enumMultiSelection")
|
|
56
56
|
return EnumMultiselectForm<any & FormLabel & BaseEnumContext<any, CollectionReference>, Unit, CollectionReference>(_ => PromiseRepo.Default.mock(() => []))
|
|
57
57
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
58
58
|
.mapContext<any & EnumFormState<any & BaseEnumContext<any, CollectionReference>, CollectionReference> & Value<OrderedMap<Guid, CollectionReference>>>(_ => ({
|
|
59
59
|
..._, label: label, getOptions: () => ((enumFieldConfigs as any)((enumSources as any)[fieldName]) as Promise<any>).then(options => parseOptions(leafPredicates, options))
|
|
60
60
|
})) as any
|
|
61
|
-
if (viewType == "
|
|
61
|
+
if (viewType == "streamSingleSelection")
|
|
62
62
|
return SearchableInfiniteStreamForm<CollectionReference, any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
63
63
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
64
64
|
.mapContext<any & SearchableInfiniteStreamState<CollectionReference> & Value<CollectionSelection<CollectionReference>>>(_ => ({ ..._, label: label })) as any
|
|
65
|
-
if (viewType == "
|
|
65
|
+
if (viewType == "streamMultiSelection")
|
|
66
66
|
return InfiniteMultiselectDropdownForm<CollectionReference, any & FormLabel, Unit>(_ => PromiseRepo.Default.mock(() => []))
|
|
67
67
|
.withView(((fieldViews as any)[viewType] as any)[viewName]() as any)
|
|
68
68
|
.mapContext<any & FormLabel & SharedFormState & SearchableInfiniteStreamState<CollectionReference> & Value<OrderedMap<Guid, CollectionReference>>>(_ => ({ ..._, label: label })) as any
|
|
@@ -71,19 +71,19 @@ export const FieldView = //<Context, FieldViews extends DefaultFieldViews, EnumF
|
|
|
71
71
|
|
|
72
72
|
export const FieldFormState = //<Context, FieldViews extends DefaultFieldViews, InfiniteStreamSources extends {}, InfiniteStreamConfigs extends {}>() => <ViewType extends keyof FieldViews, ViewName extends keyof FieldViews[ViewType]>
|
|
73
73
|
(fieldViews: any, viewType: any, viewName: any, fieldName: string, InfiniteStreamSources: any, infiniteStreamConfigs: any): any => {
|
|
74
|
-
if (viewType == "
|
|
74
|
+
if (viewType == "maybeBoolean" || viewType == "boolean" || viewType == "number" || viewType == "string")
|
|
75
75
|
return SharedFormState.Default();
|
|
76
|
-
if (viewType == "
|
|
76
|
+
if (viewType == "date")
|
|
77
77
|
return DateFormState.Default("");
|
|
78
|
-
if (viewType == "
|
|
78
|
+
if (viewType == "enumSingleSelection" || viewType == "enumMultiSelection")
|
|
79
79
|
return ({ ...EnumFormState<any, any>().Default(), ...SharedFormState.Default() });
|
|
80
|
-
if (viewType == "
|
|
80
|
+
if (viewType == "streamSingleSelection" || viewType == "streamMultiSelection") {
|
|
81
81
|
return ({
|
|
82
82
|
...SearchableInfiniteStreamState<any>().Default("", (InfiniteStreamSources as any)((infiniteStreamConfigs as any)[fieldName])
|
|
83
83
|
), ...SharedFormState.Default()
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
|
-
if (viewType == "
|
|
86
|
+
if (viewType == "list")
|
|
87
87
|
return ListFieldState<any, any>().Default(Map())
|
|
88
88
|
return `error: the view for ${viewType as string}::${viewName as string} cannot be found when creating the corresponding field form state`;
|
|
89
89
|
};
|
|
@@ -91,10 +91,13 @@ export const FieldFormState = //<Context, FieldViews extends DefaultFieldViews,
|
|
|
91
91
|
export type ParsedForm = {
|
|
92
92
|
initialFormState: any,
|
|
93
93
|
formConfig: any,
|
|
94
|
+
formName: string,
|
|
95
|
+
formDef: FormDef,
|
|
94
96
|
visibleFields: any,
|
|
95
97
|
disabledFields: any,
|
|
96
98
|
}
|
|
97
99
|
export const ParseForm = (
|
|
100
|
+
formName: string,
|
|
98
101
|
formDef: FormDef,
|
|
99
102
|
containerFormView: any,
|
|
100
103
|
nestedContainerFormView: any,
|
|
@@ -146,8 +149,6 @@ export const ParseForm = (
|
|
|
146
149
|
}
|
|
147
150
|
});
|
|
148
151
|
const formConfig: any = {};
|
|
149
|
-
console.log(fieldsViewsConfig)
|
|
150
|
-
console.log(Object.keys(fieldsViewsConfig))
|
|
151
152
|
Object.keys(fieldsViewsConfig).forEach(fieldName => {
|
|
152
153
|
const label = formDef.fields.get(fieldName)!.label
|
|
153
154
|
const viewName = (fieldsViewsConfig as any)[fieldName];
|
|
@@ -156,7 +157,7 @@ export const ParseForm = (
|
|
|
156
157
|
formConfig[fieldName] = otherForm.form.withView(nestedContainerFormView).mapContext<any>(_ => ({ ..._, label: label }))
|
|
157
158
|
} else {
|
|
158
159
|
const viewType = fieldNameToViewCategory(fieldName) as any
|
|
159
|
-
if (viewType == "
|
|
160
|
+
if (viewType == "list") {
|
|
160
161
|
const elementRendererName = formFieldElementRenderers[fieldName]
|
|
161
162
|
const field = type.fields.get(fieldName)!
|
|
162
163
|
const initialElementValue = defaultValue(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.args[0])
|
|
@@ -188,7 +189,7 @@ export const ParseForm = (
|
|
|
188
189
|
if (typeof formConfig[fieldName] == "string") {
|
|
189
190
|
debugger
|
|
190
191
|
const err = formConfig[fieldName]
|
|
191
|
-
console.
|
|
192
|
+
console.error(`error processing field ${fieldName}`, err)
|
|
192
193
|
formConfig[fieldName] = (props: any) => <>Error: field {fieldName} with {viewName} could not be instantiated</>
|
|
193
194
|
throw err
|
|
194
195
|
}
|
|
@@ -203,6 +204,8 @@ export const ParseForm = (
|
|
|
203
204
|
|
|
204
205
|
return ({
|
|
205
206
|
initialFormState,
|
|
207
|
+
formName,
|
|
208
|
+
formDef,
|
|
206
209
|
formConfig,
|
|
207
210
|
visibleFields,
|
|
208
211
|
disabledFields,
|
|
@@ -215,44 +218,6 @@ export const parseVisibleFields = (
|
|
|
215
218
|
visibleFields.map(([fieldName, boolExpr]) => ([fieldName, boolExpr.eval<any>(leafPredicates)]) as any)
|
|
216
219
|
);
|
|
217
220
|
|
|
218
|
-
export const builtInsFromFieldViews = (fieldViews: any): BuiltIns => {
|
|
219
|
-
let builtins: BuiltIns = {
|
|
220
|
-
"primitives": Map([
|
|
221
|
-
["string", { renderers: Set(["StringViews"]), defaultValue: "" }] as [string, PrimitiveBuiltIn],
|
|
222
|
-
["number", { renderers: Set(["NumberViews"]), defaultValue: 0 }],
|
|
223
|
-
["boolean", { renderers: Set(["BooleanViews"]), defaultValue: false }],
|
|
224
|
-
["maybeBoolean", { renderers: Set(["MaybeBooleanViews"]), defaultValue: undefined }],
|
|
225
|
-
["Date", { renderers: Set(["DateViews"]), defaultValue: new Date(Date.now()) }],
|
|
226
|
-
["CollectionReference", { renderers: Set(["EnumViews"]), defaultValue: CollectionReference.Default("", "") }]]),
|
|
227
|
-
"generics": Map([
|
|
228
|
-
["SingleSelection", { defaultValue: CollectionSelection().Default.right("no selection") }] as [string, GenericBuiltIn],
|
|
229
|
-
["Multiselection", { defaultValue: Map() }],
|
|
230
|
-
["List", { defaultValue: [] }]
|
|
231
|
-
]),
|
|
232
|
-
"renderers": {
|
|
233
|
-
"BooleanViews": Set(),
|
|
234
|
-
"MaybeBooleanViews": Set(),
|
|
235
|
-
"DateViews": Set(),
|
|
236
|
-
"EnumMultiselectViews": Set(),
|
|
237
|
-
"EnumViews": Set(),
|
|
238
|
-
"InfiniteStreamMultiselectViews": Set(),
|
|
239
|
-
"InfiniteStreamViews": Set(),
|
|
240
|
-
"NumberViews": Set(),
|
|
241
|
-
"StringViews": Set(),
|
|
242
|
-
"ListViews": Set(),
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
Object.keys(builtins.renderers).forEach((_categoryName) => {
|
|
246
|
-
const categoryName = _categoryName as keyof BuiltIns["renderers"]
|
|
247
|
-
if (categoryName in fieldViews) {
|
|
248
|
-
Object.keys(fieldViews[categoryName]).forEach(viewName => {
|
|
249
|
-
builtins.renderers[categoryName] = builtins.renderers[categoryName].add(viewName)
|
|
250
|
-
})
|
|
251
|
-
}
|
|
252
|
-
})
|
|
253
|
-
return builtins
|
|
254
|
-
}
|
|
255
|
-
|
|
256
221
|
export type EditLauncherContext<Entity, FormState, ExtraContext> =
|
|
257
222
|
Omit<
|
|
258
223
|
EditFormContext<Entity, FormState> &
|
|
@@ -307,10 +272,13 @@ export type EntityApis = {
|
|
|
307
272
|
get: BasicFun<EntityName, BasicFun<Guid, Promise<any>>>
|
|
308
273
|
}
|
|
309
274
|
export type EnumName = string
|
|
275
|
+
|
|
276
|
+
|
|
310
277
|
export type EnumOptionsSources = BasicFun<EnumName, Promise<Array<[CollectionReference, BoolExpr<Unit>]>>>
|
|
311
278
|
export const parseForms =
|
|
312
279
|
<LeafPredicates,>(
|
|
313
280
|
builtIns: BuiltIns,
|
|
281
|
+
apiConverters: ApiConverters,
|
|
314
282
|
containerFormView: any,
|
|
315
283
|
nestedContainerFormView: any,
|
|
316
284
|
fieldViews: any,
|
|
@@ -324,31 +292,6 @@ export const parseForms =
|
|
|
324
292
|
let seen = Set<string>()
|
|
325
293
|
let formProcessingOrder = OrderedSet<string>()
|
|
326
294
|
|
|
327
|
-
const defaultValue = (t: TypeName): any => {
|
|
328
|
-
let primitive = builtIns.primitives.get(t)
|
|
329
|
-
if (primitive != undefined) {
|
|
330
|
-
return primitive.defaultValue
|
|
331
|
-
} else {
|
|
332
|
-
let generic = builtIns.generics.get(t)
|
|
333
|
-
if (generic != undefined) {
|
|
334
|
-
return generic.defaultValue
|
|
335
|
-
} else {
|
|
336
|
-
let custom = formsConfig.types.get(t)
|
|
337
|
-
if (custom != undefined) {
|
|
338
|
-
let res = {} as any
|
|
339
|
-
custom.fields.forEach((field, fieldName) => {
|
|
340
|
-
res[fieldName] = defaultValue(field.kind == "primitive" ? field.value : field.kind == "lookup" ? field.name : field.value)
|
|
341
|
-
}
|
|
342
|
-
)
|
|
343
|
-
return res
|
|
344
|
-
} else {
|
|
345
|
-
errors.push(`cannot find type ${t} when resolving defaultValue`)
|
|
346
|
-
return undefined
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
295
|
let parsedLaunchers: ParsedLaunchers = {
|
|
353
296
|
create: Map(),
|
|
354
297
|
edit: Map(),
|
|
@@ -384,6 +327,7 @@ export const parseForms =
|
|
|
384
327
|
|
|
385
328
|
try {
|
|
386
329
|
const parsedForm = ParseForm(
|
|
330
|
+
formName,
|
|
387
331
|
formConfig,
|
|
388
332
|
containerFormView,
|
|
389
333
|
nestedContainerFormView,
|
|
@@ -398,7 +342,7 @@ export const parseForms =
|
|
|
398
342
|
leafPredicates,
|
|
399
343
|
formFieldVisibilities,
|
|
400
344
|
formFieldDisabled,
|
|
401
|
-
defaultValue,
|
|
345
|
+
defaultValue(formsConfig.types, builtIns),
|
|
402
346
|
formConfig.typeDef,
|
|
403
347
|
)
|
|
404
348
|
const formBuilder = Form<any, any, any, any>().Default<any>()
|
|
@@ -422,8 +366,13 @@ export const parseForms =
|
|
|
422
366
|
const form = parsedForm.form
|
|
423
367
|
const initialState = parsedForm.initialFormState
|
|
424
368
|
const api = {
|
|
425
|
-
get: entityApis.get(launcher.api)
|
|
426
|
-
|
|
369
|
+
get: (id:string) => entityApis.get(launcher.api)(id).then((raw: any) => {
|
|
370
|
+
// alert(JSON.stringify(raw))
|
|
371
|
+
// alert(JSON.stringify(parsedForm.formDef.type))
|
|
372
|
+
const parsed = fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(raw)
|
|
373
|
+
return parsed
|
|
374
|
+
}),
|
|
375
|
+
update: (value:any) => entityApis.update(launcher.api)(toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(value))
|
|
427
376
|
}
|
|
428
377
|
parsedLaunchers.edit = parsedLaunchers.edit.set(
|
|
429
378
|
launcherName,
|
|
@@ -444,8 +393,18 @@ export const parseForms =
|
|
|
444
393
|
const form = parsedForm.form
|
|
445
394
|
const initialState = parsedForm.initialFormState
|
|
446
395
|
const api = {
|
|
447
|
-
create:
|
|
448
|
-
|
|
396
|
+
create: (value:any) => {
|
|
397
|
+
// alert(`type = ${JSON.stringify(parsedForm.formDef.type)}`)
|
|
398
|
+
// alert(`value = ${JSON.stringify(value)}`)
|
|
399
|
+
const raw = toAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(value)
|
|
400
|
+
alert(`raw = ${JSON.stringify(raw.interests)}`)
|
|
401
|
+
return entityApis.create(launcher.api)(raw)
|
|
402
|
+
},
|
|
403
|
+
default: (_: Unit) => entityApis.default(launcher.api)(unit)
|
|
404
|
+
.then((raw: any) => {
|
|
405
|
+
const parsed = fromAPIRawValue({ kind: "lookup", name: parsedForm.formDef.type }, formsConfig.types, builtIns, apiConverters)(raw)
|
|
406
|
+
return parsed
|
|
407
|
+
})
|
|
449
408
|
}
|
|
450
409
|
parsedLaunchers.create = parsedLaunchers.create.set(
|
|
451
410
|
launcherName,
|
|
@@ -502,6 +461,7 @@ export type FormsParserContext = {
|
|
|
502
461
|
containerFormView: any,
|
|
503
462
|
nestedContainerFormView: any,
|
|
504
463
|
fieldViews: any,
|
|
464
|
+
fieldTypeConverters: ApiConverters,
|
|
505
465
|
infiniteStreamSources: InfiniteStreamSources,
|
|
506
466
|
enumOptionsSources: EnumOptionsSources,
|
|
507
467
|
entityApis: EntityApis,
|
|
@@ -35,10 +35,10 @@ const X = {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const visitor =
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
// const visitor =
|
|
39
|
+
// X.Updaters.y.l(LeftValue.Updaters.value(_ => _ + 1)).then(
|
|
40
|
+
// X.Updaters.y.r(RightValue.Updaters.value(_ => !_))
|
|
41
|
+
// )
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
console.log(visitor)
|
|
44
|
+
// console.log(visitor)
|