@sealcode/sealgen 0.19.0 → 0.19.2
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/fields/deep-reverse-single-reference-list.d.ts +1 -5
- package/@types/forms/fields/file.d.ts +1 -1
- package/@types/forms/fields/password.d.ts +1 -2
- package/@types/forms/fields/simple-form-field.d.ts +1 -1
- package/@types/forms/fields/single-reference.d.ts +1 -1
- package/@types/register-external.d.ts +2 -2
- package/@types/templates/form.d.ts +1 -3
- package/@types/templates/jdd-component.d.ts +1 -1
- package/@types/templates/page.d.ts +1 -1
- package/@types/templates/shared/shared-crud-form-fields.d.ts +1 -1
- package/@types/templates/templates.d.ts +1 -21
- package/eslint.config.mjs +56 -0
- package/lib/add-crud.js +1 -4
- package/lib/add-jdd-component.js +3 -3
- package/lib/add-route.js +2 -2
- package/lib/build.js +3 -3
- package/lib/builders/backend-ts-builder.js +0 -1
- package/lib/builders/colors-builder.js +11 -8
- package/lib/builders/fonts-builder.js +0 -1
- package/lib/builders/frontend-ts-builder.js +0 -1
- package/lib/cli.js +2 -2
- package/lib/components/tabs.js +36 -36
- package/lib/esbuild-plugins/rewrite-asset-imports.js +7 -10
- package/lib/forms/controls/array.js +5 -6
- package/lib/forms/controls/checkboxed-list-input.js +1 -2
- package/lib/forms/controls/checkboxed-list-input.test.js +6 -6
- package/lib/forms/controls/derived-frame.js +3 -3
- package/lib/forms/controls/dropdown.js +1 -2
- package/lib/forms/controls/file.test.js +1 -1
- package/lib/forms/controls/form-control.js +1 -1
- package/lib/forms/controls/image.test.js +2 -2
- package/lib/forms/controls/single-reference.test.js +1 -1
- package/lib/forms/controls/table.js +10 -15
- package/lib/forms/controls/textarea.js +1 -1
- package/lib/forms/fields/deep-reverse-single-reference-list.js +1 -1
- package/lib/forms/fields/field.test.js +3 -3
- package/lib/forms/fields/file.js +1 -1
- package/lib/forms/fields/file.test.js +1 -1
- package/lib/forms/fields/password.js +1 -1
- package/lib/forms/fields/simple-form-field.js +2 -1
- package/lib/forms/fields/single-reference.js +1 -1
- package/lib/forms/fields/structured-array.js +0 -2
- package/lib/forms/fields/table.js +1 -1
- package/lib/forms/form.js +0 -1
- package/lib/forms/form.test.js +2 -3
- package/lib/forms/multiform.js +6 -7
- package/lib/forms/multiform.test.js +2 -2
- package/lib/generate-collections.js +2 -3
- package/lib/generate-components.js +2 -3
- package/lib/generate-routes.js +3 -5
- package/lib/generate-routes.test.js +7 -16
- package/lib/generate-stimulus.js +4 -5
- package/lib/get-fonts.js +29 -27
- package/lib/make-env.js +1 -1
- package/lib/make-hidden-inputs.js +4 -4
- package/lib/mount.js +0 -1
- package/lib/notifier.js +3 -3
- package/lib/page/list.js +5 -7
- package/lib/page/mountable.js +0 -1
- package/lib/page/page.js +0 -1
- package/lib/register-external.js +4 -4
- package/lib/templates/form.js +1 -1
- package/lib/templates/jdd-component.js +1 -1
- package/lib/templates/jdd-editor.js +1 -1
- package/lib/templates/page.js +1 -1
- package/lib/templates/shared/collection-create-form.js +4 -5
- package/lib/templates/shared/collection-edit-form.js +4 -5
- package/lib/templates/shared/collection-list.js +2 -2
- package/lib/templates/shared/shared-crud-form-fields.js +3 -5
- package/lib/test_utils/exec_async.js +3 -3
- package/lib/test_utils/test-on-real-app.js +9 -11
- package/lib/utils/write-file.js +1 -1
- package/package.json +9 -8
- package/src/add-collection.ts +1 -3
- package/src/add-crud.ts +2 -7
- package/src/add-jdd-component.ts +4 -5
- package/src/add-route.ts +3 -6
- package/src/build.ts +3 -3
- package/src/builders/backend-ts-builder.ts +0 -1
- package/src/builders/builder.ts +4 -1
- package/src/builders/colors-builder.ts +11 -9
- package/src/builders/css-builder.ts +4 -1
- package/src/builders/fonts-builder.ts +0 -1
- package/src/builders/frontend-ts-builder.ts +0 -1
- package/src/cli.ts +2 -2
- package/src/components/tabs.ts +38 -37
- package/src/components/toggle-modal.ts +1 -1
- package/src/controllers/table-add-button.stimulus.ts +1 -1
- package/src/esbuild-plugins/rewrite-asset-imports.ts +7 -10
- package/src/forms/controls/array.ts +12 -16
- package/src/forms/controls/autocomplete.ts +1 -1
- package/src/forms/controls/big-radio-group.ts +2 -2
- package/src/forms/controls/checkbox-group.ts +1 -1
- package/src/forms/controls/checkboxed-list-input.test.ts +6 -6
- package/src/forms/controls/checkboxed-list-input.ts +18 -22
- package/src/forms/controls/derived-frame.ts +11 -10
- package/src/forms/controls/derived.ts +6 -5
- package/src/forms/controls/dropdown.ts +8 -11
- package/src/forms/controls/editable-collection-subset.ts +2 -1
- package/src/forms/controls/field-group.ts +1 -1
- package/src/forms/controls/file.test.ts +1 -1
- package/src/forms/controls/file.ts +4 -7
- package/src/forms/controls/form-control.ts +1 -1
- package/src/forms/controls/hidden-input.ts +1 -0
- package/src/forms/controls/html.ts +1 -0
- package/src/forms/controls/image.test.ts +2 -2
- package/src/forms/controls/image.ts +1 -1
- package/src/forms/controls/multiple-files.ts +5 -7
- package/src/forms/controls/multiple-images.ts +1 -1
- package/src/forms/controls/simple-input.ts +8 -4
- package/src/forms/controls/single-reference.test.ts +1 -1
- package/src/forms/controls/single-reference.ts +1 -1
- package/src/forms/controls/table.ts +16 -21
- package/src/forms/controls/textarea.ts +1 -1
- package/src/forms/controls/tickable.ts +0 -2
- package/src/forms/fields/boolean.ts +4 -1
- package/src/forms/fields/checkboxed-list.ts +1 -1
- package/src/forms/fields/collection-field.ts +5 -2
- package/src/forms/fields/color.ts +1 -1
- package/src/forms/fields/coordinates.ts +2 -2
- package/src/forms/fields/deep-reverse-single-reference-list.ts +2 -8
- package/src/forms/fields/deep-reverse-single-reference-table.ts +1 -1
- package/src/forms/fields/email.ts +1 -1
- package/src/forms/fields/enum-multiple-sealious.ts +1 -1
- package/src/forms/fields/existing-sealious-value.ts +1 -1
- package/src/forms/fields/field.test.ts +3 -3
- package/src/forms/fields/field.ts +6 -5
- package/src/forms/fields/file.test.ts +1 -1
- package/src/forms/fields/file.ts +2 -2
- package/src/forms/fields/float.ts +1 -1
- package/src/forms/fields/get-field-for-sealious.ts +97 -64
- package/src/forms/fields/int.ts +1 -1
- package/src/forms/fields/number.ts +2 -2
- package/src/forms/fields/password.ts +2 -6
- package/src/forms/fields/pick-from-list-sealious.ts +1 -1
- package/src/forms/fields/pick-from-list.ts +1 -1
- package/src/forms/fields/proxy-field.ts +1 -0
- package/src/forms/fields/simple-form-field.ts +13 -5
- package/src/forms/fields/single-reference.ts +2 -2
- package/src/forms/fields/structured-array.ts +2 -6
- package/src/forms/fields/table.ts +7 -15
- package/src/forms/fields/text.ts +1 -1
- package/src/forms/fields/url.ts +1 -1
- package/src/forms/form-types.ts +3 -4
- package/src/forms/form.test.ts +2 -3
- package/src/forms/form.ts +5 -7
- package/src/forms/multiform.test.ts +6 -6
- package/src/forms/multiform.ts +10 -10
- package/src/generate-collections.ts +2 -3
- package/src/generate-components.ts +2 -3
- package/src/generate-routes.test.ts +7 -16
- package/src/generate-routes.ts +6 -10
- package/src/generate-stimulus.ts +4 -6
- package/src/get-fonts.ts +32 -30
- package/src/make-env.ts +1 -1
- package/src/make-hidden-inputs.ts +8 -7
- package/src/mount.ts +2 -7
- package/src/notifier.ts +4 -6
- package/src/page/default-list-filters.ts +1 -0
- package/src/page/list.ts +18 -20
- package/src/page/mountable-with-fields.ts +3 -3
- package/src/page/mountable.ts +0 -1
- package/src/page/page.ts +2 -3
- package/src/page/props-parser.ts +1 -1
- package/src/page/sealious-list.ts +1 -1
- package/src/page/stateful-page.ts +6 -10
- package/src/register-external.ts +4 -4
- package/src/templates/form.ts +1 -2
- package/src/templates/jdd-component.ts +1 -1
- package/src/templates/jdd-editor.ts +2 -4
- package/src/templates/list.ts +0 -1
- package/src/templates/page.ts +1 -4
- package/src/templates/shared/collection-create-form.ts +5 -6
- package/src/templates/shared/collection-edit-form.ts +5 -6
- package/src/templates/shared/collection-list.ts +2 -2
- package/src/templates/shared/shared-crud-form-fields.ts +4 -9
- package/src/templates/templates.ts +5 -1
- package/src/test_utils/exec_async.ts +3 -4
- package/src/test_utils/test-on-real-app.ts +9 -11
- package/src/utils/browser-creator.js +0 -1
- package/src/utils/exec.ts +0 -1
- package/src/utils/input-wrapper.ts +1 -1
- package/src/utils/wrap-attributes.ts +1 -1
- package/src/utils/write-file.ts +1 -1
- package/.eslintrc.cjs +0 -44
|
@@ -17,7 +17,7 @@ export type DefaultCheckboxOptions = {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export class CheckboxGroup<
|
|
20
|
-
Options extends DefaultCheckboxOptions = DefaultCheckboxOptions
|
|
20
|
+
Options extends DefaultCheckboxOptions = DefaultCheckboxOptions,
|
|
21
21
|
> extends FormFieldControl {
|
|
22
22
|
constructor(
|
|
23
23
|
public field: CheckboxedListField<boolean, string>,
|
|
@@ -23,7 +23,7 @@ describe("checkboxed-list", () => {
|
|
|
23
23
|
|
|
24
24
|
it("sends the values", async () => {
|
|
25
25
|
const port = await getPort();
|
|
26
|
-
console.
|
|
26
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
27
27
|
const app = new Koa();
|
|
28
28
|
const router = new Router();
|
|
29
29
|
|
|
@@ -71,7 +71,7 @@ describe("checkboxed-list", () => {
|
|
|
71
71
|
describe("behavior with (non)required", () => {
|
|
72
72
|
it("allows to send a form when no value is selected and fiels is not required", async () => {
|
|
73
73
|
const port = await getPort();
|
|
74
|
-
console.
|
|
74
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
75
75
|
const app = new Koa();
|
|
76
76
|
const router = new Router();
|
|
77
77
|
|
|
@@ -118,7 +118,7 @@ describe("checkboxed-list", () => {
|
|
|
118
118
|
|
|
119
119
|
it("does not allow to send a form when no value is selected and field IS required", async () => {
|
|
120
120
|
const port = await getPort();
|
|
121
|
-
console.
|
|
121
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
122
122
|
const app = new Koa();
|
|
123
123
|
const router = new Router();
|
|
124
124
|
|
|
@@ -166,7 +166,7 @@ describe("checkboxed-list", () => {
|
|
|
166
166
|
|
|
167
167
|
it("allows to send a form when no value is selected and field IS required", async () => {
|
|
168
168
|
const port = await getPort();
|
|
169
|
-
console.
|
|
169
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
170
170
|
const app = new Koa();
|
|
171
171
|
const router = new Router();
|
|
172
172
|
|
|
@@ -215,7 +215,7 @@ describe("checkboxed-list", () => {
|
|
|
215
215
|
|
|
216
216
|
it("renders the label", async () => {
|
|
217
217
|
const port = await getPort();
|
|
218
|
-
console.
|
|
218
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
219
219
|
const app = new Koa();
|
|
220
220
|
const router = new Router();
|
|
221
221
|
|
|
@@ -258,7 +258,7 @@ describe("checkboxed-list", () => {
|
|
|
258
258
|
|
|
259
259
|
it("groups checkboxes based on the value of the 'group' attribute", async () => {
|
|
260
260
|
const port = await getPort();
|
|
261
|
-
console.
|
|
261
|
+
console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
|
|
262
262
|
const app = new Koa();
|
|
263
263
|
const router = new Router();
|
|
264
264
|
|
|
@@ -8,7 +8,7 @@ import { FormControlContext } from "./form-control.js";
|
|
|
8
8
|
import { FormFieldControl } from "./form-field-control.js";
|
|
9
9
|
|
|
10
10
|
export class CheckboxedListInput<
|
|
11
|
-
Values extends string
|
|
11
|
+
Values extends string,
|
|
12
12
|
> extends FormFieldControl {
|
|
13
13
|
constructor(
|
|
14
14
|
public field: CheckboxedListField<boolean, Values>,
|
|
@@ -54,7 +54,6 @@ export class CheckboxedListInput<
|
|
|
54
54
|
if (!groups[option.group]) {
|
|
55
55
|
groups[option.group] = [];
|
|
56
56
|
}
|
|
57
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
58
57
|
groups[option.group]!.push(option);
|
|
59
58
|
}
|
|
60
59
|
}
|
|
@@ -67,7 +66,7 @@ export class CheckboxedListInput<
|
|
|
67
66
|
getRequiredClass(required),
|
|
68
67
|
...this.generateCountBasedClasses(options.length),
|
|
69
68
|
],
|
|
70
|
-
tempstream/* HTML */ `<label
|
|
69
|
+
tempstream /* HTML */ `<label
|
|
71
70
|
>${this.options.label || this.field.name}</label
|
|
72
71
|
>
|
|
73
72
|
${~valid && fctx.validate
|
|
@@ -77,26 +76,23 @@ export class CheckboxedListInput<
|
|
|
77
76
|
${isVisible
|
|
78
77
|
? Object.entries(groups).map(
|
|
79
78
|
([group_label, options]) =>
|
|
80
|
-
tempstream/* HTML */ ` <h3>
|
|
79
|
+
tempstream /* HTML */ ` <h3>
|
|
81
80
|
${group_label}
|
|
82
81
|
</h3>
|
|
83
82
|
|
|
84
|
-
${
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
98
|
-
}`
|
|
99
|
-
)
|
|
83
|
+
${options!.map(({ value, label }) =>
|
|
84
|
+
this.renderOption({
|
|
85
|
+
name,
|
|
86
|
+
value,
|
|
87
|
+
label,
|
|
88
|
+
form_id: fctx.form_id,
|
|
89
|
+
checked:
|
|
90
|
+
pickedValues.includes(
|
|
91
|
+
value
|
|
92
|
+
),
|
|
93
|
+
})
|
|
94
|
+
)}`
|
|
95
|
+
)
|
|
100
96
|
: ""}
|
|
101
97
|
${isVisible
|
|
102
98
|
? ungroupped.map(({ value, label }) =>
|
|
@@ -107,7 +103,7 @@ export class CheckboxedListInput<
|
|
|
107
103
|
form_id: fctx.form_id,
|
|
108
104
|
checked: pickedValues.includes(value),
|
|
109
105
|
})
|
|
110
|
-
|
|
106
|
+
)
|
|
111
107
|
: ""}
|
|
112
108
|
</ul>`
|
|
113
109
|
);
|
|
@@ -126,7 +122,7 @@ export class CheckboxedListInput<
|
|
|
126
122
|
label?: string;
|
|
127
123
|
checked: boolean;
|
|
128
124
|
}) {
|
|
129
|
-
return tempstream/* HTML */ `<li>
|
|
125
|
+
return tempstream /* HTML */ `<li>
|
|
130
126
|
${inputWrapper(
|
|
131
127
|
"checkbox",
|
|
132
128
|
[name],
|
|
@@ -25,15 +25,16 @@ export class DerivedFrame extends Derived<{
|
|
|
25
25
|
) {
|
|
26
26
|
super(
|
|
27
27
|
fields,
|
|
28
|
-
async (values, consts) =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
async (values, consts) =>
|
|
29
|
+
/* HTML */ `<turbo-frame
|
|
30
|
+
id="${consts.frame_id}"
|
|
31
|
+
src="./${consts.frame_id}?${Object.entries({
|
|
32
|
+
...consts,
|
|
33
|
+
...(values || {}),
|
|
34
|
+
})
|
|
35
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
36
|
+
.join("&")}"
|
|
37
|
+
></turbo-frame>`,
|
|
37
38
|
async (fctx) => ({
|
|
38
39
|
form_id: fctx.form_id,
|
|
39
40
|
field_name_prefix: fctx.field_name_prefix,
|
|
@@ -44,7 +45,7 @@ export class DerivedFrame extends Derived<{
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
renderBackendResponseFrame(_ctx: Context, content: FlatTemplatable) {
|
|
47
|
-
return tempstream/* HTML */ `<turbo-frame
|
|
48
|
+
return tempstream /* HTML */ `<turbo-frame
|
|
48
49
|
id="${this.frame_id}"
|
|
49
50
|
target="_top"
|
|
50
51
|
>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-redundant-type-constituents: off */
|
|
1
2
|
import { randomUUID } from "crypto";
|
|
2
3
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
3
4
|
import { FormField } from "../fields/field.js";
|
|
@@ -5,7 +6,7 @@ import { FormDataValue } from "../form-types.js";
|
|
|
5
6
|
import { FormControl, FormControlContext } from "./form-control.js";
|
|
6
7
|
|
|
7
8
|
export class Derived<
|
|
8
|
-
Consts extends Record<string, unknown | undefined
|
|
9
|
+
Consts extends Record<string, unknown | undefined>,
|
|
9
10
|
> extends FormControl {
|
|
10
11
|
role = <const>"decoration";
|
|
11
12
|
|
|
@@ -17,7 +18,7 @@ export class Derived<
|
|
|
17
18
|
) => Promise<FlatTemplatable>,
|
|
18
19
|
public getConsts: (
|
|
19
20
|
fctx: FormControlContext
|
|
20
|
-
) => Promise<Consts> = async () => ({} as Consts
|
|
21
|
+
) => Promise<Consts> = async () => ({}) as Consts
|
|
21
22
|
) {
|
|
22
23
|
super();
|
|
23
24
|
}
|
|
@@ -44,7 +45,7 @@ export class Derived<
|
|
|
44
45
|
`render(${values_code}, consts)
|
|
45
46
|
.then(result=>document.querySelector("#${id}").innerHTML=result)`;
|
|
46
47
|
|
|
47
|
-
return tempstream/* HTML */ `<div>
|
|
48
|
+
return tempstream /* HTML */ `<div>
|
|
48
49
|
<script>
|
|
49
50
|
(function () {
|
|
50
51
|
const consts = ${"{" +
|
|
@@ -54,8 +55,8 @@ export class Derived<
|
|
|
54
55
|
typeof value === "object"
|
|
55
56
|
? JSON.stringify(value)
|
|
56
57
|
: typeof value == "string"
|
|
57
|
-
|
|
58
|
-
|
|
58
|
+
? '"' + value.toString() + '"'
|
|
59
|
+
: (value as string).toString()
|
|
59
60
|
}`;
|
|
60
61
|
})
|
|
61
62
|
.join(",") +
|
|
@@ -46,7 +46,7 @@ export class FreeformDropdown extends SimpleInput {
|
|
|
46
46
|
((original.onchange as string | undefined) ||
|
|
47
47
|
"") + ";this.form.submit();",
|
|
48
48
|
],
|
|
49
|
-
|
|
49
|
+
]
|
|
50
50
|
: []),
|
|
51
51
|
]),
|
|
52
52
|
} as Record<string, string>;
|
|
@@ -62,17 +62,14 @@ export class FreeformDropdown extends SimpleInput {
|
|
|
62
62
|
data
|
|
63
63
|
);
|
|
64
64
|
return /* HTML */ tempstream`<select ${attributes_str}>
|
|
65
|
-
${
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
(value || "") == picked_value ? "selected" : ""
|
|
72
|
-
}>${label}</option>`
|
|
73
|
-
)
|
|
65
|
+
${Promise.resolve(this.generateOptions(ctx)).then((options) =>
|
|
66
|
+
options.map(
|
|
67
|
+
({ value, label }) =>
|
|
68
|
+
`<option value="${attribute(value)}" ${
|
|
69
|
+
(value || "") == picked_value ? "selected" : ""
|
|
70
|
+
}>${label}</option>`
|
|
74
71
|
)
|
|
75
|
-
}
|
|
72
|
+
)}
|
|
76
73
|
</select>`;
|
|
77
74
|
}
|
|
78
75
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-base-to-string: off */
|
|
1
2
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
2
3
|
import { attribute } from "../../sanitize.js";
|
|
3
4
|
import { PickFromListField } from "../fields/pick-from-list.js";
|
|
@@ -27,7 +28,7 @@ export class EditableCollectionSubset extends FormFieldControl {
|
|
|
27
28
|
fctx.data.raw_values
|
|
28
29
|
);
|
|
29
30
|
|
|
30
|
-
return tempstream/* HTML */ `<div>
|
|
31
|
+
return tempstream /* HTML */ `<div>
|
|
31
32
|
<ul>
|
|
32
33
|
${Promise.resolve(this.field.generateOptions(fctx.ctx)).then(
|
|
33
34
|
(options) =>
|
|
@@ -41,7 +41,7 @@ export class FieldGroup extends FormFieldControl {
|
|
|
41
41
|
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
|
|
42
42
|
const { label, classes } = this.options;
|
|
43
43
|
|
|
44
|
-
return tempstream/* HTML */ `
|
|
44
|
+
return tempstream /* HTML */ `
|
|
45
45
|
<div
|
|
46
46
|
class="field-group ${(classes || []).join(" ")}"
|
|
47
47
|
${this.options.containerID
|
|
@@ -27,7 +27,7 @@ describe("file-control", () => {
|
|
|
27
27
|
|
|
28
28
|
it("doesn't require image input if it already has old-value", async () => {
|
|
29
29
|
const port = await getPort();
|
|
30
|
-
console.
|
|
30
|
+
console.info(`Using port ${port} for image.test.ts`);
|
|
31
31
|
const app = new Koa();
|
|
32
32
|
const router = new Router();
|
|
33
33
|
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
/* eslint
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
1
|
+
/* eslint @typescript-eslint/no-unsafe-assignment: off, @typescript-eslint/no-unsafe-argument: off, @typescript-eslint/no-unsafe-member-access: off, @typescript-eslint/no-unsafe-call: off */
|
|
5
2
|
import { Context } from "koa";
|
|
6
3
|
import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
|
|
7
4
|
import { FlatTemplatable, tempstream } from "tempstream";
|
|
@@ -27,7 +24,7 @@ export class File extends SimpleInput {
|
|
|
27
24
|
}
|
|
28
25
|
if (file instanceof PathFilePointer) {
|
|
29
26
|
const filename = await file.getOriginalFilename();
|
|
30
|
-
return tempstream/* HTML */ `<div class="${class_name}">
|
|
27
|
+
return tempstream /* HTML */ `<div class="${class_name}">
|
|
31
28
|
<div class="${class_name}__icon">
|
|
32
29
|
<picture>
|
|
33
30
|
<img
|
|
@@ -44,7 +41,7 @@ export class File extends SimpleInput {
|
|
|
44
41
|
</div>
|
|
45
42
|
</div>`;
|
|
46
43
|
}
|
|
47
|
-
return tempstream/* HTML */ `<div class="${class_name}">
|
|
44
|
+
return tempstream /* HTML */ `<div class="${class_name}">
|
|
48
45
|
${file.getOriginalFilename()}
|
|
49
46
|
</div>`;
|
|
50
47
|
}
|
|
@@ -57,7 +54,7 @@ export class File extends SimpleInput {
|
|
|
57
54
|
if (parsed === null) {
|
|
58
55
|
parsed = { old: null, new: null };
|
|
59
56
|
}
|
|
60
|
-
return tempstream/* HTML */ `${this.renderFilePreview(
|
|
57
|
+
return tempstream /* HTML */ `${this.renderFilePreview(
|
|
61
58
|
fctx.ctx,
|
|
62
59
|
parsed.old
|
|
63
60
|
)}
|
|
@@ -26,6 +26,6 @@ export abstract class FormControl {
|
|
|
26
26
|
): FlatTemplatable | Promise<FlatTemplatable>;
|
|
27
27
|
abstract role: "input" | "decoration" | "messages" | "submit";
|
|
28
28
|
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
30
|
mount(_router: Router, _form: Form<any, any>) {}
|
|
31
31
|
}
|
|
@@ -12,6 +12,7 @@ export class HTML extends FormControl {
|
|
|
12
12
|
constructor(role: "decoration" | "submit", renderer: Renderer);
|
|
13
13
|
constructor(renderer: Renderer);
|
|
14
14
|
constructor(
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
|
15
16
|
role_or_renderer: "decoration" | "submit" | Renderer,
|
|
16
17
|
renderer_or_undefined?: Renderer | FlatTemplatable
|
|
17
18
|
) {
|
|
@@ -27,7 +27,7 @@ describe("photo-control", () => {
|
|
|
27
27
|
|
|
28
28
|
it("sends the old photo if it wasn't changed and it has an initial value", async () => {
|
|
29
29
|
const port = await getPort();
|
|
30
|
-
console.
|
|
30
|
+
console.info(`Using port ${port} for photo.test.ts`);
|
|
31
31
|
const app = new Koa();
|
|
32
32
|
const router = new Router();
|
|
33
33
|
|
|
@@ -78,7 +78,7 @@ describe("photo-control", () => {
|
|
|
78
78
|
|
|
79
79
|
it("doesn't require image input if it already has old-value", async () => {
|
|
80
80
|
const port = await getPort();
|
|
81
|
-
console.
|
|
81
|
+
console.info(`Using port ${port} for photo.test.ts`);
|
|
82
82
|
const app = new Koa();
|
|
83
83
|
const router = new Router();
|
|
84
84
|
|
|
@@ -28,7 +28,7 @@ export class Image extends File {
|
|
|
28
28
|
if (!file) {
|
|
29
29
|
return empty_container;
|
|
30
30
|
}
|
|
31
|
-
return tempstream/* HTML */ `<div class="${class_name}">
|
|
31
|
+
return tempstream /* HTML */ `<div class="${class_name}">
|
|
32
32
|
${ctx.$app.imageRouter.image(await file.getPath(), {
|
|
33
33
|
resolutions: [100, 200],
|
|
34
34
|
sizesAttr: "100px",
|
|
@@ -105,7 +105,7 @@ export class MultipleFiles extends FormFieldControl {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
renderFrame(_ctx: Context, content?: FlatTemplatable) {
|
|
108
|
-
return tempstream/* HTML */ `<turbo-frame
|
|
108
|
+
return tempstream /* HTML */ `<turbo-frame
|
|
109
109
|
${content ? "" : `src="./${this.getFrameRelativeURL()}"`}
|
|
110
110
|
id="${this.getFrameID()}"
|
|
111
111
|
target="_top"
|
|
@@ -168,7 +168,7 @@ export class MultipleFiles extends FormFieldControl {
|
|
|
168
168
|
if (!(file instanceof PathFilePointer)) {
|
|
169
169
|
return "";
|
|
170
170
|
}
|
|
171
|
-
return tempstream/* HTML */ `<li class="file-list-item">
|
|
171
|
+
return tempstream /* HTML */ `<li class="file-list-item">
|
|
172
172
|
<a
|
|
173
173
|
class="file-list-item__preview"
|
|
174
174
|
href="${file.getURL()}"
|
|
@@ -215,9 +215,7 @@ export class MultipleFiles extends FormFieldControl {
|
|
|
215
215
|
async renderFrameContent(ctx: Context): Promise<FlatTemplatable> {
|
|
216
216
|
const files = (
|
|
217
217
|
await Promise.all(
|
|
218
|
-
(
|
|
219
|
-
await this.getFileItems(ctx)
|
|
220
|
-
)
|
|
218
|
+
(await this.getFileItems(ctx))
|
|
221
219
|
.filter((item) => item) // filter out undefineds
|
|
222
220
|
.map(async (item: CollectionItem<Collection>) => [
|
|
223
221
|
item,
|
|
@@ -226,13 +224,13 @@ export class MultipleFiles extends FormFieldControl {
|
|
|
226
224
|
)
|
|
227
225
|
).filter(([_, f]) => f !== null) as [
|
|
228
226
|
CollectionItem<Collection>,
|
|
229
|
-
FilePointer
|
|
227
|
+
FilePointer,
|
|
230
228
|
][];
|
|
231
229
|
|
|
232
230
|
return inputWrapper(
|
|
233
231
|
"multiple-files",
|
|
234
232
|
["multiple-files", this.field.name, ...this.getClassModifiers()],
|
|
235
|
-
tempstream/* HTML */ `
|
|
233
|
+
tempstream /* HTML */ `
|
|
236
234
|
<label>${this.options.label || this.field.name}</label>
|
|
237
235
|
<ul class="multiple-files__list">
|
|
238
236
|
${files.map(([item, file]) =>
|
|
@@ -33,7 +33,7 @@ export class MultipleImages extends MultipleFiles {
|
|
|
33
33
|
if (!path) {
|
|
34
34
|
return "missing file";
|
|
35
35
|
}
|
|
36
|
-
return tempstream/* HTML */ `<li>
|
|
36
|
+
return tempstream /* HTML */ `<li>
|
|
37
37
|
<a href="${file.getURL()}" data-turbo="false">
|
|
38
38
|
${this.imageRouter.image(path, {
|
|
39
39
|
resolutions: [150, 300],
|
|
@@ -22,10 +22,14 @@ export type SimpleInputOptions = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export class SimpleInput<
|
|
25
|
-
Options extends SimpleInputOptions = SimpleInputOptions
|
|
25
|
+
Options extends SimpleInputOptions = SimpleInputOptions,
|
|
26
26
|
> extends FormFieldControl {
|
|
27
27
|
options: SimpleInputOptions;
|
|
28
|
-
constructor(
|
|
28
|
+
constructor(
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
public field: FormField<boolean, any>,
|
|
31
|
+
options?: Options
|
|
32
|
+
) {
|
|
29
33
|
super([field]);
|
|
30
34
|
this.options = options || {};
|
|
31
35
|
}
|
|
@@ -117,7 +121,7 @@ export class SimpleInput<
|
|
|
117
121
|
return inputWrapper(
|
|
118
122
|
"simple-input",
|
|
119
123
|
this.getWrapperModifiers(),
|
|
120
|
-
tempstream/* HTML */ `
|
|
124
|
+
tempstream /* HTML */ `
|
|
121
125
|
${label ? `<label for="${id}">${label}</label>` : ""}
|
|
122
126
|
${await this.preInput(fctx, fctx.data.raw_values)}
|
|
123
127
|
${this.renderInput(
|
|
@@ -131,7 +135,7 @@ export class SimpleInput<
|
|
|
131
135
|
message,
|
|
132
136
|
fctx.data.field_messages?.[this.field.name]
|
|
133
137
|
?.message,
|
|
134
|
-
|
|
138
|
+
]
|
|
135
139
|
.filter((e) => !!e)
|
|
136
140
|
.join(" · ")}</div>`
|
|
137
141
|
: ""}
|
|
@@ -39,7 +39,7 @@ describe("single-reference.test", () => {
|
|
|
39
39
|
const form_file_path = "src/back/routes/some-form.form.ts";
|
|
40
40
|
await test_app.addFile(
|
|
41
41
|
form_file_path,
|
|
42
|
-
await formTemplate("SomeForm",
|
|
42
|
+
await formTemplate("SomeForm", {
|
|
43
43
|
postimport: `import {Comments} from "../collections/collections.js"; import {Fields} from "@sealcode/sealgen";`,
|
|
44
44
|
fields: `article: new Fields.CollectionField(true, Comments.fields.article),`,
|
|
45
45
|
controls: `new Controls.SingleReferenceDropdown(fields.article, {getLabel: item=>item.get("title")}),`,
|
|
@@ -6,7 +6,7 @@ import { Collection, CollectionItem } from "sealious";
|
|
|
6
6
|
export class SingleReferenceDropdown<
|
|
7
7
|
TargetCollection extends Collection,
|
|
8
8
|
F extends SealiousFieldTypes.SingleReference,
|
|
9
|
-
Required extends boolean
|
|
9
|
+
Required extends boolean,
|
|
10
10
|
> extends FreeformDropdown {
|
|
11
11
|
constructor(
|
|
12
12
|
public field: CollectionField<F, Required>,
|
|
@@ -77,7 +77,7 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
77
77
|
messages: [],
|
|
78
78
|
field_messages: {},
|
|
79
79
|
},
|
|
80
|
-
|
|
80
|
+
}
|
|
81
81
|
: {};
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -92,25 +92,20 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
92
92
|
row_index: number | string
|
|
93
93
|
) => {
|
|
94
94
|
return /* HTML */ tempstream`<tr>
|
|
95
|
-
${(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
${Promise.all(
|
|
96
|
+
Object.entries(this.table_field.columns)
|
|
97
|
+
.map(([column_name]) => {
|
|
98
|
+
const inner_fctx = get_row_fctx(row, row_index);
|
|
99
|
+
return tempstream`<td>${this.options.subfield_controls[
|
|
100
|
+
column_name
|
|
101
|
+
].render({ ...fctx, ...inner_fctx })}</td>`;
|
|
102
|
+
})
|
|
103
|
+
.map(async (html) =>
|
|
104
|
+
(await html).replaceAll(
|
|
105
|
+
TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
|
|
106
|
+
row_index.toString()
|
|
107
|
+
)
|
|
107
108
|
)
|
|
108
|
-
)
|
|
109
|
-
).map((html) =>
|
|
110
|
-
html.replaceAll(
|
|
111
|
-
TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
|
|
112
|
-
row_index.toString()
|
|
113
|
-
)
|
|
114
109
|
)}
|
|
115
110
|
${
|
|
116
111
|
this.options.allow_removing
|
|
@@ -138,13 +133,13 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
138
133
|
)}"
|
|
139
134
|
/>
|
|
140
135
|
</noscript>
|
|
141
|
-
|
|
136
|
+
</td>`
|
|
142
137
|
: ""
|
|
143
138
|
}
|
|
144
139
|
</tr>`;
|
|
145
140
|
};
|
|
146
141
|
|
|
147
|
-
return tempstream/* HTML */ `<turbo-frame
|
|
142
|
+
return tempstream /* HTML */ `<turbo-frame
|
|
148
143
|
id="${this.getFrameID()}"
|
|
149
144
|
class="${[
|
|
150
145
|
"form-input__wrapper",
|
|
@@ -65,7 +65,6 @@ export abstract class Tickable<T> extends FormFieldControl {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
69
68
|
const {
|
|
70
69
|
parsed: _parsed,
|
|
71
70
|
valid,
|
|
@@ -88,7 +87,6 @@ export abstract class Tickable<T> extends FormFieldControl {
|
|
|
88
87
|
? this.options.label
|
|
89
88
|
: this.field.name;
|
|
90
89
|
|
|
91
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
92
90
|
const readonly = this.options.readonly || false;
|
|
93
91
|
const required = this.field.required;
|
|
94
92
|
|
|
@@ -14,7 +14,10 @@ export class Boolean<Required extends boolean> extends FormField<
|
|
|
14
14
|
Checkbox
|
|
15
15
|
> {
|
|
16
16
|
predicate = predicates.boolean;
|
|
17
|
-
constructor(
|
|
17
|
+
constructor(
|
|
18
|
+
required: Required,
|
|
19
|
+
public error_message: string = ""
|
|
20
|
+
) {
|
|
18
21
|
super(required);
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -14,9 +14,12 @@ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.j
|
|
|
14
14
|
export class CollectionField<
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
16
|
F extends Field<any>,
|
|
17
|
-
Required extends boolean
|
|
17
|
+
Required extends boolean,
|
|
18
18
|
> extends FormField<Required, ExtractFieldDecoded<F> | null, SimpleInput> {
|
|
19
|
-
constructor(
|
|
19
|
+
constructor(
|
|
20
|
+
required: Required,
|
|
21
|
+
public sealiousField: F
|
|
22
|
+
) {
|
|
20
23
|
super(required);
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -7,7 +7,7 @@ import { SimpleFormField } from "./simple-form-field.js";
|
|
|
7
7
|
|
|
8
8
|
export class Coordinates<
|
|
9
9
|
Required extends boolean,
|
|
10
|
-
DefaultControl extends FormControl = SimpleInput
|
|
10
|
+
DefaultControl extends FormControl = SimpleInput,
|
|
11
11
|
> extends SimpleFormField<Required, DefaultControl, [number, number]> {
|
|
12
12
|
async parse(
|
|
13
13
|
_: Context,
|
|
@@ -26,7 +26,7 @@ export class Coordinates<
|
|
|
26
26
|
return {
|
|
27
27
|
parsed_value: raw_value.map((e) => parseFloat(e)) as [
|
|
28
28
|
number,
|
|
29
|
-
number
|
|
29
|
+
number,
|
|
30
30
|
],
|
|
31
31
|
parsable: true,
|
|
32
32
|
error: null,
|