@sealcode/sealgen 0.19.32 → 0.19.34
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/@types/forms/controls/dropdown.d.ts +2 -2
- package/@types/forms/fields/CollectionField.d.ts +1 -0
- package/@types/forms/fields/boolean.d.ts +1 -2
- package/@types/forms/fields/collection-field.d.ts +12 -5
- package/@types/forms/fields/coordinates.d.ts +2 -2
- package/@types/forms/fields/date.d.ts +1 -2
- package/@types/forms/fields/datetime.d.ts +1 -2
- package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +1 -1
- package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +1 -2
- package/@types/forms/fields/enum-multiple-sealious.d.ts +1 -2
- package/@types/forms/fields/field.d.ts +6 -2
- package/@types/forms/fields/fields.d.ts +1 -0
- package/@types/forms/fields/file.d.ts +4 -3
- package/@types/forms/fields/int.d.ts +1 -2
- package/@types/forms/fields/json.d.ts +1 -2
- package/@types/forms/fields/phone-number-with-country-code.d.ts +1 -2
- package/@types/forms/fields/regexp.d.ts +1 -2
- package/@types/forms/fields/simple-form-field.d.ts +2 -3
- package/@types/forms/fields/single-reference.d.ts +2 -3
- package/@types/forms/fields/structured-array.d.ts +1 -2
- package/@types/forms/fields/structured.d.ts +19 -0
- package/@types/forms/fields/text.d.ts +1 -2
- package/@types/forms/fields/url.d.ts +1 -2
- package/lib/forms/controls/checkboxed-list-input.test.js +3 -3
- package/lib/forms/controls/field-group.js +3 -1
- package/lib/forms/controls/simple-input.js +6 -4
- package/lib/forms/fields/boolean.js +2 -6
- package/lib/forms/fields/collection-field.js +49 -5
- package/lib/forms/fields/coordinates.js +1 -5
- package/lib/forms/fields/date.js +1 -8
- package/lib/forms/fields/datetime.js +1 -8
- package/lib/forms/fields/deep-reverse-single-reference-list.js +1 -1
- package/lib/forms/fields/deep-reverse-single-reference-table.js +1 -1
- package/lib/forms/fields/enum-multiple-sealious.js +1 -5
- package/lib/forms/fields/field.js +17 -4
- package/lib/forms/fields/fields.js +1 -0
- package/lib/forms/fields/file.js +6 -6
- package/lib/forms/fields/int.js +1 -8
- package/lib/forms/fields/json.js +1 -5
- package/lib/forms/fields/phone-number-with-country-code.js +1 -5
- package/lib/forms/fields/regexp.js +1 -5
- package/lib/forms/fields/simple-form-field.js +6 -16
- package/lib/forms/fields/single-reference.js +2 -6
- package/lib/forms/fields/structured-array.js +1 -5
- package/lib/forms/fields/structured.js +107 -0
- package/lib/forms/fields/text.js +1 -5
- package/lib/forms/fields/url.js +2 -6
- package/lib/forms/form.js +2 -1
- package/lib/templates/shared/collection-create-form.js +4 -0
- package/lib/templates/shared/collection-edit-form.js +5 -0
- package/lib/utils/input-wrapper.js +2 -2
- package/package.json +3 -2
- package/src/forms/controls/checkboxed-list-input.test.ts +3 -3
- package/src/forms/controls/dropdown.ts +1 -1
- package/src/forms/controls/field-group.ts +9 -7
- package/src/forms/controls/simple-input.ts +19 -15
- package/src/forms/controls/textarea.ts +1 -1
- package/src/forms/fields/boolean.ts +2 -7
- package/src/forms/fields/collection-field.ts +88 -11
- package/src/forms/fields/coordinates.ts +3 -7
- package/src/forms/fields/date.ts +1 -11
- package/src/forms/fields/datetime.ts +1 -11
- package/src/forms/fields/deep-reverse-single-reference-list.ts +1 -1
- package/src/forms/fields/deep-reverse-single-reference-table.ts +1 -2
- package/src/forms/fields/enum-multiple-sealious.ts +1 -6
- package/src/forms/fields/field.ts +26 -6
- package/src/forms/fields/fields.ts +1 -0
- package/src/forms/fields/file.ts +9 -9
- package/src/forms/fields/int.ts +1 -11
- package/src/forms/fields/json.ts +2 -7
- package/src/forms/fields/phone-number-with-country-code.ts +3 -6
- package/src/forms/fields/regexp.ts +1 -6
- package/src/forms/fields/simple-form-field.ts +6 -22
- package/src/forms/fields/single-reference.ts +7 -10
- package/src/forms/fields/structured-array.ts +2 -7
- package/src/forms/fields/structured.ts +151 -0
- package/src/forms/fields/text.ts +1 -6
- package/src/forms/fields/url.ts +2 -9
- package/src/forms/form.ts +2 -1
- package/src/templates/shared/collection-create-form.ts +4 -0
- package/src/templates/shared/collection-edit-form.ts +5 -0
- package/src/utils/input-wrapper.ts +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { t } from "../../utils/translate.js";
|
|
3
3
|
import { wrapAttribute, wrapKeyName } from "../../utils/wrap-attributes.js";
|
|
4
|
+
import { getProperty } from "dot-prop";
|
|
4
5
|
function fieldsToShape(obj) {
|
|
5
6
|
return Object.fromEntries(
|
|
6
7
|
Object.entries(obj).map(([key, value]) => [key, value.predicate])
|
|
@@ -27,6 +28,13 @@ class FormField {
|
|
|
27
28
|
this.label = label;
|
|
28
29
|
return this;
|
|
29
30
|
}
|
|
31
|
+
getValuePath() {
|
|
32
|
+
return (this.value_path || this.name).replaceAll("][", ".").replaceAll("[", ".");
|
|
33
|
+
}
|
|
34
|
+
setValuePath(path) {
|
|
35
|
+
this.value_path = path;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
30
38
|
async _validate(ctx, value) {
|
|
31
39
|
if (value === "" || value === null || value === void 0) {
|
|
32
40
|
if (this.required) {
|
|
@@ -52,7 +60,7 @@ class FormField {
|
|
|
52
60
|
return { valid: true, message: "" };
|
|
53
61
|
}
|
|
54
62
|
async getParsedValue(ctx, all_form_values, validate = false) {
|
|
55
|
-
const raw = all_form_values
|
|
63
|
+
const raw = getProperty(all_form_values, this.getValuePath());
|
|
56
64
|
if (raw == void 0 || raw == null || raw == "") {
|
|
57
65
|
return {
|
|
58
66
|
parsed: null,
|
|
@@ -80,7 +88,7 @@ class FormField {
|
|
|
80
88
|
parsed: parsed_value,
|
|
81
89
|
...validate ? { valid } : {},
|
|
82
90
|
message,
|
|
83
|
-
raw
|
|
91
|
+
raw
|
|
84
92
|
};
|
|
85
93
|
} else {
|
|
86
94
|
return { parsed: parsed_value, raw, message: "parsed" };
|
|
@@ -98,9 +106,14 @@ class FormField {
|
|
|
98
106
|
getSealiousCreateValue(fctx) {
|
|
99
107
|
throw new Error("This field does not have a default sealious mapping");
|
|
100
108
|
}
|
|
101
|
-
|
|
109
|
+
parsedToSealious(parsed) {
|
|
102
110
|
throw new Error("This field does not have a default sealious mapping");
|
|
103
111
|
}
|
|
112
|
+
sealiousValueToForm(ctx, sealiousValue, item) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`Field '${this.name}' does not have a default sealious mapping`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
104
117
|
async postSealiousCreate(ctx, created_item, form_data) {
|
|
105
118
|
}
|
|
106
119
|
async postSealiousEdit(ctx, edited_item, form_data) {
|
|
@@ -111,7 +124,7 @@ class FormField {
|
|
|
111
124
|
)})`;
|
|
112
125
|
}
|
|
113
126
|
generateCreateValueGetter(field_info, vars) {
|
|
114
|
-
return `${wrapKeyName(field_info.name)}: await ${vars.form_fields}${wrapAttribute(field_info.name)}.
|
|
127
|
+
return `${wrapKeyName(field_info.name)}: await ${vars.form_fields}${wrapAttribute(field_info.name)}.parsedToSealious(data${wrapAttribute(field_info.name)})`;
|
|
115
128
|
}
|
|
116
129
|
generateInitialValue(field_info, vars) {
|
|
117
130
|
return `${wrapKeyName(field_info.name)}: await ${vars.form_fields}${wrapAttribute(field_info.name)}.sealiousValueToForm(ctx, item.get("${field_info.name}"))`;
|
package/lib/forms/fields/file.js
CHANGED
|
@@ -2,6 +2,7 @@ import { hasFieldOfType, is, predicates } from "@sealcode/ts-predicates";
|
|
|
2
2
|
import { PathFilePointer } from "@sealcode/file-manager";
|
|
3
3
|
import { FormField } from "./field.js";
|
|
4
4
|
import { File as FileControl } from "../controls/file.js";
|
|
5
|
+
import { ImageValue } from "sealious";
|
|
5
6
|
class File extends FormField {
|
|
6
7
|
constructor(required) {
|
|
7
8
|
super(required);
|
|
@@ -27,7 +28,7 @@ class File extends FormField {
|
|
|
27
28
|
raw_value,
|
|
28
29
|
"old",
|
|
29
30
|
predicates.instanceOf(PathFilePointer)
|
|
30
|
-
) ? await ctx.$app.fileManager.toPointer(raw_value.old) : null;
|
|
31
|
+
) && raw_value.old ? await ctx.$app.fileManager.toPointer(raw_value.old) : null;
|
|
31
32
|
const new_file = hasFieldOfType(
|
|
32
33
|
raw_value,
|
|
33
34
|
"new",
|
|
@@ -56,11 +57,7 @@ class File extends FormField {
|
|
|
56
57
|
getControl() {
|
|
57
58
|
return new FileControl(this, { label: this.name, autocomplete: false });
|
|
58
59
|
}
|
|
59
|
-
async
|
|
60
|
-
const { parsed: value } = await this.getParsedValue(
|
|
61
|
-
fctx.ctx,
|
|
62
|
-
fctx.data.raw_values
|
|
63
|
-
);
|
|
60
|
+
async parsedToSealious(value) {
|
|
64
61
|
const pointer = value?.new || value?.old || void 0;
|
|
65
62
|
if (this.required && !pointer) {
|
|
66
63
|
throw new Error("File is required, but no value is provided");
|
|
@@ -71,6 +68,9 @@ class File extends FormField {
|
|
|
71
68
|
if (!sealiousValue) {
|
|
72
69
|
return {};
|
|
73
70
|
}
|
|
71
|
+
if (sealiousValue instanceof ImageValue) {
|
|
72
|
+
return { old: sealiousValue.toFile() };
|
|
73
|
+
}
|
|
74
74
|
if (typeof sealiousValue == "string") {
|
|
75
75
|
sealiousValue = await ctx.$app.fileManager.fromToken(sealiousValue);
|
|
76
76
|
}
|
package/lib/forms/fields/int.js
CHANGED
|
@@ -3,14 +3,7 @@ class Int extends NumberBasedSimpleField {
|
|
|
3
3
|
constructor(required) {
|
|
4
4
|
super(required, "number");
|
|
5
5
|
}
|
|
6
|
-
async
|
|
7
|
-
const { parsed } = await this.getParsedValue(
|
|
8
|
-
fctx.ctx,
|
|
9
|
-
fctx.data.raw_values
|
|
10
|
-
);
|
|
11
|
-
if (parsed == null) {
|
|
12
|
-
return void 0;
|
|
13
|
-
}
|
|
6
|
+
async parsedToSealious(parsed) {
|
|
14
7
|
if (isNaN(parsed)) {
|
|
15
8
|
return void 0;
|
|
16
9
|
} else
|
package/lib/forms/fields/json.js
CHANGED
|
@@ -17,11 +17,7 @@ class JSONField extends SimpleFormField {
|
|
|
17
17
|
parsed_value: JSON.parse(raw_value)
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
-
async
|
|
21
|
-
const { parsed } = await this.getParsedValue(
|
|
22
|
-
fctx.ctx,
|
|
23
|
-
fctx.data.raw_values
|
|
24
|
-
);
|
|
20
|
+
async parsedToSealious(parsed) {
|
|
25
21
|
return parsed;
|
|
26
22
|
}
|
|
27
23
|
}
|
|
@@ -42,11 +42,7 @@ class PhoneNumberWithCountryCode extends FormField {
|
|
|
42
42
|
)
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
|
-
async
|
|
46
|
-
const { parsed } = await this.getParsedValue(
|
|
47
|
-
fctx.ctx,
|
|
48
|
-
fctx.data.raw_values
|
|
49
|
-
);
|
|
45
|
+
async parsedToSealious(parsed) {
|
|
50
46
|
if (!parsed) {
|
|
51
47
|
return "";
|
|
52
48
|
}
|
|
@@ -39,11 +39,7 @@ class RegExpField extends FormField {
|
|
|
39
39
|
getControl() {
|
|
40
40
|
return new SimpleInput(this, { label: this.label || this.name });
|
|
41
41
|
}
|
|
42
|
-
async
|
|
43
|
-
const { parsed } = await this.getParsedValue(
|
|
44
|
-
fctx.ctx,
|
|
45
|
-
fctx.data.raw_values
|
|
46
|
-
);
|
|
42
|
+
async parsedToSealious(parsed) {
|
|
47
43
|
return parsed || "";
|
|
48
44
|
}
|
|
49
45
|
async sealiousValueToForm(ctx, sealious_value) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { predicates } from "@sealcode/ts-predicates";
|
|
2
2
|
import { FormField } from "./field.js";
|
|
3
3
|
import { SimpleInput } from "../controls/simple-input.js";
|
|
4
|
+
import { Textarea } from "../controls/controls.js";
|
|
4
5
|
class SimpleFormField extends FormField {
|
|
5
6
|
constructor(required, type = "text") {
|
|
6
7
|
super(required);
|
|
@@ -27,22 +28,15 @@ class TextBasedSimpleField extends SimpleFormField {
|
|
|
27
28
|
error: null
|
|
28
29
|
};
|
|
29
30
|
}
|
|
30
|
-
async
|
|
31
|
-
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
const { parsed } = await this.getParsedValue(
|
|
35
|
-
fctx.ctx,
|
|
36
|
-
fctx.data.raw_values
|
|
37
|
-
);
|
|
38
|
-
return parsed || "";
|
|
31
|
+
async parsedToSealious(value) {
|
|
32
|
+
return value || "";
|
|
39
33
|
}
|
|
40
34
|
async postSealiousCreate(_ctx, _created_item, _formData) {
|
|
41
35
|
}
|
|
42
36
|
async postSealiousEdit(_ctx, _edited_item, _formData) {
|
|
43
37
|
}
|
|
44
38
|
getControl() {
|
|
45
|
-
return new
|
|
39
|
+
return new Textarea(this, {
|
|
46
40
|
label: this.label || this.name,
|
|
47
41
|
type: this.type
|
|
48
42
|
});
|
|
@@ -59,12 +53,8 @@ class NumberBasedSimpleField extends SimpleFormField {
|
|
|
59
53
|
error: null
|
|
60
54
|
};
|
|
61
55
|
}
|
|
62
|
-
async
|
|
63
|
-
|
|
64
|
-
fctx.ctx,
|
|
65
|
-
fctx.data.raw_values
|
|
66
|
-
);
|
|
67
|
-
return parsed || 0;
|
|
56
|
+
async parsedToSealious(value) {
|
|
57
|
+
return value || 0;
|
|
68
58
|
}
|
|
69
59
|
async postSealiousCreate() {
|
|
70
60
|
}
|
|
@@ -8,12 +8,8 @@ class SingleReference extends CollectionField {
|
|
|
8
8
|
getLabel: (item) => item.id
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
|
-
async
|
|
12
|
-
|
|
13
|
-
fctx.ctx,
|
|
14
|
-
fctx.data.raw_values
|
|
15
|
-
);
|
|
16
|
-
return parsed || void 0;
|
|
11
|
+
async parsedToSealious(parsed) {
|
|
12
|
+
return parsed || "";
|
|
17
13
|
}
|
|
18
14
|
async sealiousValueToForm(_ctx, value) {
|
|
19
15
|
return value || void 0;
|
|
@@ -32,11 +32,7 @@ class StructuredArray extends Table {
|
|
|
32
32
|
generateFieldDeclaration(_field_info, vars) {
|
|
33
33
|
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
|
|
34
34
|
}
|
|
35
|
-
async
|
|
36
|
-
const { parsed } = await this.getParsedValue(
|
|
37
|
-
fctx.ctx,
|
|
38
|
-
fctx.data.raw_values
|
|
39
|
-
);
|
|
35
|
+
async parsedToSealious(parsed) {
|
|
40
36
|
return parsed || this.getEmptyValue();
|
|
41
37
|
}
|
|
42
38
|
async sealiousValueToForm(ctx, sealiousValue) {
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { is, predicates } from "@sealcode/ts-predicates";
|
|
2
|
+
import { FormField } from "./field.js";
|
|
3
|
+
import { FieldGroup } from "../controls/controls.js";
|
|
4
|
+
import { sealiousFieldToFormField } from "./collection-field.js";
|
|
5
|
+
class StructuredSealiousField extends FormField {
|
|
6
|
+
constructor(sealiousField) {
|
|
7
|
+
super(false);
|
|
8
|
+
this.sealiousField = sealiousField;
|
|
9
|
+
}
|
|
10
|
+
getEmptyValue() {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
async parse(ctx, raw_value) {
|
|
14
|
+
const sealiousField = this.sealiousField;
|
|
15
|
+
if (!is(raw_value, predicates.object)) {
|
|
16
|
+
raw_value = {};
|
|
17
|
+
}
|
|
18
|
+
const results = await Promise.all(
|
|
19
|
+
Object.entries(sealiousField.fields).map(async ([key, field]) => {
|
|
20
|
+
const formfield = sealiousFieldToFormField(
|
|
21
|
+
field,
|
|
22
|
+
key,
|
|
23
|
+
this.name
|
|
24
|
+
);
|
|
25
|
+
return [
|
|
26
|
+
key,
|
|
27
|
+
await formfield.parse(
|
|
28
|
+
ctx,
|
|
29
|
+
raw_value[key] || ""
|
|
30
|
+
)
|
|
31
|
+
];
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
const parsable = results.every(([, r]) => r.parsable);
|
|
35
|
+
if (parsable) {
|
|
36
|
+
return {
|
|
37
|
+
parsable,
|
|
38
|
+
error: null,
|
|
39
|
+
parsed_value: Object.fromEntries(
|
|
40
|
+
results.map(([key, value]) => [key, value.parsed_value])
|
|
41
|
+
)
|
|
42
|
+
};
|
|
43
|
+
} else
|
|
44
|
+
return {
|
|
45
|
+
parsable: false,
|
|
46
|
+
parsed_value: null,
|
|
47
|
+
error: results.map(([, r]) => r.error).join("; ")
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async parsedToSealious(parsed) {
|
|
51
|
+
return Object.fromEntries(
|
|
52
|
+
await Promise.all(
|
|
53
|
+
Object.entries(parsed).map(
|
|
54
|
+
async ([key, value]) => {
|
|
55
|
+
const sealious_field = this.sealiousField.fields[key];
|
|
56
|
+
const formfield = sealiousFieldToFormField(
|
|
57
|
+
sealious_field,
|
|
58
|
+
key,
|
|
59
|
+
this.name
|
|
60
|
+
);
|
|
61
|
+
return [key, await formfield.parsedToSealious(value)];
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
async sealiousValueToForm(ctx, sealiousValue, item) {
|
|
68
|
+
return Object.fromEntries(
|
|
69
|
+
await Promise.all(
|
|
70
|
+
Object.entries(
|
|
71
|
+
sealiousValue || {}
|
|
72
|
+
).map(async ([key, value]) => {
|
|
73
|
+
const sealious_field = this.sealiousField.fields[key];
|
|
74
|
+
const formfield = sealiousFieldToFormField(
|
|
75
|
+
sealious_field,
|
|
76
|
+
key,
|
|
77
|
+
this.name
|
|
78
|
+
);
|
|
79
|
+
return [
|
|
80
|
+
key,
|
|
81
|
+
await formfield.sealiousValueToForm(ctx, value, item)
|
|
82
|
+
];
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
getControl() {
|
|
88
|
+
const structured = this.sealiousField;
|
|
89
|
+
return new FieldGroup(
|
|
90
|
+
Object.keys(structured.fields).map((key) => {
|
|
91
|
+
return sealiousFieldToFormField(
|
|
92
|
+
structured.fields[key],
|
|
93
|
+
key,
|
|
94
|
+
this.name
|
|
95
|
+
).setLabel(key).getControl();
|
|
96
|
+
}),
|
|
97
|
+
{ label: this.name }
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
generateFieldDeclaration(_field_info, vars) {
|
|
101
|
+
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export {
|
|
105
|
+
StructuredSealiousField
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=structured.js.map
|
package/lib/forms/fields/text.js
CHANGED
|
@@ -3,11 +3,7 @@ class Text extends TextBasedSimpleField {
|
|
|
3
3
|
constructor(required) {
|
|
4
4
|
super(required, "text");
|
|
5
5
|
}
|
|
6
|
-
async
|
|
7
|
-
const { parsed } = await this.getParsedValue(
|
|
8
|
-
fctx.ctx,
|
|
9
|
-
fctx.data.raw_values
|
|
10
|
-
);
|
|
6
|
+
async parsedToSealious(parsed) {
|
|
11
7
|
return parsed || this.getEmptyValue();
|
|
12
8
|
}
|
|
13
9
|
}
|
package/lib/forms/fields/url.js
CHANGED
|
@@ -3,12 +3,8 @@ class URLField extends TextBasedSimpleField {
|
|
|
3
3
|
constructor(required) {
|
|
4
4
|
super(required, "text");
|
|
5
5
|
}
|
|
6
|
-
async
|
|
7
|
-
|
|
8
|
-
fctx.ctx,
|
|
9
|
-
fctx.data.raw_values
|
|
10
|
-
);
|
|
11
|
-
return parsed || null;
|
|
6
|
+
async parsedToSealious(parsed) {
|
|
7
|
+
return parsed || "";
|
|
12
8
|
}
|
|
13
9
|
}
|
|
14
10
|
export {
|
package/lib/forms/form.js
CHANGED
|
@@ -199,10 +199,11 @@ class Form extends MountableWithFields {
|
|
|
199
199
|
});
|
|
200
200
|
router.get(path, async (ctx) => {
|
|
201
201
|
ctx.type = "html";
|
|
202
|
+
const raw_values = await this.extractRawValues(ctx);
|
|
202
203
|
ctx.body = await this.render(
|
|
203
204
|
ctx,
|
|
204
205
|
{
|
|
205
|
-
raw_values
|
|
206
|
+
raw_values,
|
|
206
207
|
messages: [],
|
|
207
208
|
field_messages: {}
|
|
208
209
|
},
|
|
@@ -33,6 +33,10 @@ async function createItemFormTemplate(create_action_name, newfilefullpath, colle
|
|
|
33
33
|
onsubmit: `
|
|
34
34
|
async onSubmit(ctx: Context, formData: FormData) {
|
|
35
35
|
const fctx = this.makeFormControlContext(ctx, formData, true);
|
|
36
|
+
const data = await this.getParsedValues(ctx);
|
|
37
|
+
if (!data) {
|
|
38
|
+
throw new Error("Error when parsing the form values");
|
|
39
|
+
}
|
|
36
40
|
|
|
37
41
|
const created = await ctx.$app.collections["${toKebabCase(
|
|
38
42
|
collection_name
|
|
@@ -49,6 +49,11 @@ async function editItemFormTemplate(edit_action_name, newfilefullpath, collectio
|
|
|
49
49
|
throw new Error("Unknown id: " + id);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const data = await this.getParsedValues(ctx);
|
|
53
|
+
if (!data) {
|
|
54
|
+
throw new Error("Error when parsing the form values");
|
|
55
|
+
}
|
|
56
|
+
|
|
52
57
|
|
|
53
58
|
item.setMultipleExtraSafe(
|
|
54
59
|
{
|
|
@@ -7,13 +7,13 @@ function getModifierClasses(modifiers) {
|
|
|
7
7
|
return modifiers.map((m) => "form-input__wrapper--" + m).join(" ");
|
|
8
8
|
}
|
|
9
9
|
async function inputWrapper(type, modifiers, input) {
|
|
10
|
-
return tempstream`<
|
|
10
|
+
return tempstream`<label
|
|
11
11
|
class="form-input form-input--type-${type} form-input__wrapper ${getModifierClasses(
|
|
12
12
|
modifiers
|
|
13
13
|
)}"
|
|
14
14
|
>
|
|
15
15
|
${input}
|
|
16
|
-
</
|
|
16
|
+
</label>`;
|
|
17
17
|
}
|
|
18
18
|
async function autoWrapInput(field, input) {
|
|
19
19
|
return inputWrapper(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sealcode/sealgen",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.34",
|
|
4
4
|
"description": "Module to automate adding routes and collections to a sealious application",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"core-js-pure": "^3.49.0",
|
|
70
70
|
"country-codes-list": "^2.0.0",
|
|
71
71
|
"deepmerge": "^4.3.1",
|
|
72
|
+
"dot-prop": "^10.2.0",
|
|
72
73
|
"esbuild": "^0.20.0",
|
|
73
74
|
"escape-goat": "^4.0.0",
|
|
74
75
|
"fonsta": "^1.1.1",
|
|
@@ -93,7 +94,7 @@
|
|
|
93
94
|
"peerDependencies": {
|
|
94
95
|
"koa": "^2.13.0",
|
|
95
96
|
"koa-responsive-image-router": "^0.2.24",
|
|
96
|
-
"sealious": "^0.21.
|
|
97
|
+
"sealious": "^0.21.43",
|
|
97
98
|
"stimulus": "^3.2.2"
|
|
98
99
|
}
|
|
99
100
|
}
|
|
@@ -62,8 +62,8 @@ describe("checkboxed-list", () => {
|
|
|
62
62
|
const context = await browser.newContext();
|
|
63
63
|
page = await context.newPage();
|
|
64
64
|
await page.goto(`http://localhost:${port}`);
|
|
65
|
-
await page.getByLabel("CO").check();
|
|
66
|
-
await page.getByLabel("DE").check();
|
|
65
|
+
await page.getByLabel("CO", { exact: true }).check();
|
|
66
|
+
await page.getByLabel("DE", { exact: true }).check();
|
|
67
67
|
await page.getByRole("button", { name: "Wyślij" }).click();
|
|
68
68
|
assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
|
|
69
69
|
});
|
|
@@ -206,7 +206,7 @@ describe("checkboxed-list", () => {
|
|
|
206
206
|
const context = await browser.newContext();
|
|
207
207
|
page = await context.newPage();
|
|
208
208
|
await page.goto(`http://localhost:${port}`);
|
|
209
|
-
await page.getByLabel("DE").check();
|
|
209
|
+
await page.getByLabel("DE", { exact: true }).check();
|
|
210
210
|
await page.getByRole("button", { name: "Wyślij" }).click();
|
|
211
211
|
await sleep(100);
|
|
212
212
|
assert(submit_called);
|
|
@@ -17,7 +17,7 @@ export type DropdownOption = { value: string; label: string };
|
|
|
17
17
|
|
|
18
18
|
export class FreeformDropdown<ParsedValue> extends SimpleInput {
|
|
19
19
|
constructor(
|
|
20
|
-
public field: FormField<boolean, ParsedValue
|
|
20
|
+
public field: FormField<boolean, ParsedValue>,
|
|
21
21
|
public _generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
|
|
22
22
|
public options: DropdownOptions = {
|
|
23
23
|
label: field.label || field.name,
|
|
@@ -43,17 +43,19 @@ export class FieldGroup extends FormFieldControl {
|
|
|
43
43
|
|
|
44
44
|
return tempstream /* HTML */ `
|
|
45
45
|
<div
|
|
46
|
-
class="field-group ${(classes || []).join(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
class="field-group form-input__wrapper ${(classes || []).join(
|
|
47
|
+
" "
|
|
48
|
+
)}"
|
|
49
|
+
${this.options.containerID ?
|
|
50
|
+
`id="${this.options.containerID}"`
|
|
51
|
+
: ""}
|
|
50
52
|
>
|
|
51
53
|
${this.preLabelContainer()}
|
|
52
54
|
<div class="field-group__label-container">
|
|
53
55
|
${this.preLabel()}
|
|
54
|
-
${label
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
${label ?
|
|
57
|
+
tempstream`<label ${this.getGroupLabelProps()}>${label}</label>`
|
|
58
|
+
: ""}
|
|
57
59
|
${this.postLabel()}
|
|
58
60
|
</div>
|
|
59
61
|
${this.preFields()}
|
|
@@ -127,26 +127,30 @@ export class SimpleInput<
|
|
|
127
127
|
fctx.data.raw_values,
|
|
128
128
|
true
|
|
129
129
|
);
|
|
130
|
+
|
|
130
131
|
return inputWrapper(
|
|
131
132
|
"simple-input",
|
|
132
133
|
this.getWrapperModifiers(),
|
|
133
134
|
tempstream /* HTML */ `
|
|
134
135
|
${label ? `<label for="${id}">${label}</label>` : ""}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
136
|
+
<div class="simple-input__inner-wrapper">
|
|
137
|
+
${await this.preInput(fctx, fctx.data.raw_values)}
|
|
138
|
+
${this.renderInput(
|
|
139
|
+
fctx.ctx,
|
|
140
|
+
renderAttributes(await this.getInputAttributes(fctx)),
|
|
141
|
+
fctx.data.raw_values
|
|
142
|
+
)}
|
|
143
|
+
${this.postInput(fctx.ctx)}
|
|
144
|
+
${~valid && !this.options.hide_errors && fctx.validate ?
|
|
145
|
+
`<div class="input__error">${[
|
|
146
|
+
message,
|
|
147
|
+
fctx.data.field_messages?.[this.field.name]
|
|
148
|
+
?.message,
|
|
149
|
+
]
|
|
150
|
+
.filter((e) => !!e)
|
|
151
|
+
.join(" · ")}</div>`
|
|
152
|
+
: ""}
|
|
153
|
+
</div>
|
|
150
154
|
`
|
|
151
155
|
);
|
|
152
156
|
}
|
|
@@ -49,7 +49,7 @@ export class Textarea extends SimpleInput {
|
|
|
49
49
|
attributes: string,
|
|
50
50
|
data: Record<string, FormDataValue>
|
|
51
51
|
) {
|
|
52
|
-
// eslint-disable-next-line
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
53
53
|
const { parsed: value } = await this.field.getParsedValue(ctx, data);
|
|
54
54
|
return /* HTML */ `<textarea ${attributes}>
|
|
55
55
|
${value ? String(value) : ""}</textarea
|
|
@@ -3,7 +3,6 @@ import { Context } from "koa";
|
|
|
3
3
|
import { Checkbox } from "../controls/checkbox.js";
|
|
4
4
|
import { FormDataValue } from "../form-types.js";
|
|
5
5
|
import { FieldParseResult, FormField } from "./field.js";
|
|
6
|
-
import { FormControlContext } from "../controls/form-control.js";
|
|
7
6
|
|
|
8
7
|
const truthy = ["true", "on", "yes", "1"];
|
|
9
8
|
const falsy = ["false", "off", "no", "0"];
|
|
@@ -71,12 +70,8 @@ export class Boolean<Required extends boolean> extends FormField<
|
|
|
71
70
|
return new Checkbox(this, { label: this.label || this.name });
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
async
|
|
75
|
-
|
|
76
|
-
fctx.ctx,
|
|
77
|
-
fctx.data.raw_values
|
|
78
|
-
);
|
|
79
|
-
return !!parsed;
|
|
73
|
+
async parsedToSealious(value: boolean): Promise<boolean> {
|
|
74
|
+
return !!value;
|
|
80
75
|
}
|
|
81
76
|
|
|
82
77
|
async sealiousValueToForm(
|