@sealcode/sealgen 0.15.34 → 0.15.36
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/.xunit +59 -57
- package/@types/src/forms/controls/controls.d.ts +1 -0
- package/@types/src/forms/controls/form-control.d.ts +2 -1
- package/@types/src/forms/controls/table.d.ts +42 -0
- package/@types/src/forms/fields/fields.d.ts +1 -0
- package/@types/src/forms/fields/table.d.ts +14 -0
- package/@types/src/templates/form.d.ts +5 -0
- package/@types/src/templates/shared/collection-edit-form.d.ts +1 -0
- package/@types/src/templates/shared/collection-list.d.ts +1 -0
- package/@types/src/templates/shared/confirm-item-delete.d.ts +1 -0
- package/@types/src/templates/shared/handlers/boolean.d.ts +2 -0
- package/@types/src/templates/shared/handlers/date.d.ts +2 -0
- package/@types/src/templates/shared/handlers/deep-reverse-single-reference.d.ts +2 -0
- package/@types/src/templates/shared/handlers/default.d.ts +2 -0
- package/@types/src/templates/shared/handlers/enum.d.ts +2 -0
- package/@types/src/templates/shared/handlers/file.d.ts +2 -0
- package/@types/src/templates/shared/handlers/image.d.ts +2 -0
- package/@types/src/templates/shared/handlers/int.d.ts +2 -0
- package/@types/src/templates/shared/handlers/jdd.d.ts +2 -0
- package/@types/src/templates/shared/handlers/single-reference.d.ts +2 -0
- package/@types/src/templates/shared/handlers/structured-array.d.ts +2 -0
- package/@types/src/templates/shared/item-delete.d.ts +1 -0
- package/@types/src/templates/shared/shared-crud-form-fields.d.ts +67 -0
- package/@types/src/utils/extract-fields-from-collection.d.ts +12 -2
- package/@types/src/utils/with-fallback.d.ts +1 -1
- package/lib/add-crud.js +131 -0
- package/lib/cli.js +2 -0
- package/lib/forms/controls/controls.js +1 -0
- package/lib/forms/controls/form-control.js +2 -2
- package/lib/forms/controls/multiple-photos.js +2 -1
- package/lib/forms/controls/single-reference.test.js +1 -1
- package/lib/forms/controls/table.js +164 -0
- package/lib/forms/fields/boolean.js +1 -1
- package/lib/forms/fields/field.js +4 -1
- package/lib/forms/fields/fields.js +1 -0
- package/lib/forms/fields/table.js +63 -0
- package/lib/forms/form.js +7 -6
- package/lib/page/default-list-filters.js +1 -0
- package/lib/templates/form.js +25 -16
- package/lib/templates/list.js +6 -167
- package/lib/templates/shared/collection-create-form.js +86 -0
- package/lib/templates/shared/collection-edit-form.js +157 -0
- package/lib/templates/shared/collection-list.js +226 -0
- package/lib/templates/shared/confirm-item-delete.js +74 -0
- package/lib/templates/shared/handlers/boolean.js +14 -0
- package/lib/templates/shared/handlers/date.js +8 -0
- package/lib/templates/shared/handlers/deep-reverse-single-reference.js +209 -0
- package/lib/templates/shared/handlers/default.js +50 -0
- package/lib/templates/shared/handlers/enum.js +19 -0
- package/lib/templates/shared/handlers/file.js +18 -0
- package/lib/templates/shared/handlers/image.js +32 -0
- package/lib/templates/shared/handlers/int.js +11 -0
- package/lib/templates/shared/handlers/jdd.js +10 -0
- package/lib/templates/shared/handlers/single-reference.js +12 -0
- package/lib/templates/shared/handlers/structured-array.js +33 -0
- package/lib/templates/shared/item-delete.js +43 -0
- package/lib/templates/shared/shared-crud-form-fields.js +108 -0
- package/lib/utils/extract-fields-from-collection.js +31 -5
- package/lib/utils/write-file.js +11 -0
- package/package.json +2 -1
- package/src/add-crud.ts +153 -0
- package/src/cli.ts +2 -0
- package/src/forms/controls/controls.ts +1 -0
- package/src/forms/controls/form-control.ts +3 -2
- package/src/forms/controls/multiple-photos.ts +1 -0
- package/src/forms/controls/single-reference.test.ts +1 -1
- package/src/forms/controls/table.ts +208 -0
- package/src/forms/fields/boolean.ts +1 -1
- package/src/forms/fields/field.ts +4 -1
- package/src/forms/fields/fields.ts +1 -0
- package/src/forms/fields/table.ts +91 -0
- package/src/forms/form.ts +13 -7
- package/src/page/default-list-filters.ts +1 -0
- package/src/templates/form.ts +24 -15
- package/src/templates/list.ts +6 -174
- package/src/templates/shared/collection-create-form.ts +121 -0
- package/src/templates/shared/collection-edit-form.ts +196 -0
- package/src/templates/shared/collection-list.ts +252 -0
- package/src/templates/shared/confirm-item-delete.ts +78 -0
- package/src/templates/shared/handlers/boolean.ts +18 -0
- package/src/templates/shared/handlers/date.ts +12 -0
- package/src/templates/shared/handlers/deep-reverse-single-reference.ts +244 -0
- package/src/templates/shared/handlers/default.ts +58 -0
- package/src/templates/shared/handlers/enum.ts +23 -0
- package/src/templates/shared/handlers/file.ts +22 -0
- package/src/templates/shared/handlers/image.ts +45 -0
- package/src/templates/shared/handlers/int.ts +15 -0
- package/src/templates/shared/handlers/jdd.ts +14 -0
- package/src/templates/shared/handlers/single-reference.ts +16 -0
- package/src/templates/shared/handlers/structured-array.ts +42 -0
- package/src/templates/shared/item-delete.ts +45 -0
- package/src/templates/shared/shared-crud-form-fields.ts +179 -0
- package/src/utils/extract-fields-from-collection.ts +45 -6
- package/src/utils/with-fallback.ts +1 -1
- package/src/utils/write-file.ts +8 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { toKebabCase, toPascalCase } from "js-convert-case";
|
|
2
|
+
import extract_fields_from_collection from "../../../utils/extract-fields-from-collection.js";
|
|
3
|
+
import {
|
|
4
|
+
FieldHandler,
|
|
5
|
+
FieldHandlerResult,
|
|
6
|
+
} from "../shared-crud-form-fields.js";
|
|
7
|
+
|
|
8
|
+
export const deep_reverse_single_reference_handler: FieldHandler<
|
|
9
|
+
FieldHandlerResult,
|
|
10
|
+
Partial<FieldHandlerResult>
|
|
11
|
+
> = async (
|
|
12
|
+
collection_name,
|
|
13
|
+
{
|
|
14
|
+
name,
|
|
15
|
+
target,
|
|
16
|
+
referencing_collection,
|
|
17
|
+
intermediary_field_that_points_there,
|
|
18
|
+
referencing_field,
|
|
19
|
+
},
|
|
20
|
+
___,
|
|
21
|
+
{ is_required_expr, fields_var }
|
|
22
|
+
) => {
|
|
23
|
+
if (
|
|
24
|
+
!referencing_collection ||
|
|
25
|
+
!target ||
|
|
26
|
+
!intermediary_field_that_points_there ||
|
|
27
|
+
!referencing_field
|
|
28
|
+
) {
|
|
29
|
+
console.warn(
|
|
30
|
+
"missing referencing_collection, target, intermediary_field_that_points_there, or referencing_field member in extracted field info"
|
|
31
|
+
);
|
|
32
|
+
return { field: "" };
|
|
33
|
+
}
|
|
34
|
+
const referencing_fields = await extract_fields_from_collection(
|
|
35
|
+
referencing_collection
|
|
36
|
+
);
|
|
37
|
+
if (referencing_fields.length == 2) {
|
|
38
|
+
// just a regular n-to-n intermediary collection
|
|
39
|
+
const post_create = (get_id: string) => `{
|
|
40
|
+
const item_id = ${get_id};
|
|
41
|
+
// First, we remove links refering to current item
|
|
42
|
+
const {items: existing_links } = (await ctx.$app.collections["${referencing_collection}"]
|
|
43
|
+
.list(ctx.$context)
|
|
44
|
+
.filter({"${referencing_field}": item_id})
|
|
45
|
+
.fetch()
|
|
46
|
+
)
|
|
47
|
+
const should_exist_ids = Object.entries(
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
49
|
+
(data["${name}"] as unknown as Record<string, string>) || {}
|
|
50
|
+
)
|
|
51
|
+
.filter(([, value]) => value === "on")
|
|
52
|
+
.map(([key]) => key);
|
|
53
|
+
const to_delete = existing_links.filter(
|
|
54
|
+
(link) => !should_exist_ids.includes(link.get("${intermediary_field_that_points_there}"))
|
|
55
|
+
);
|
|
56
|
+
const to_create_ids = should_exist_ids.filter(
|
|
57
|
+
(id) => !existing_links.map(({ id }) => id).includes(id)
|
|
58
|
+
);
|
|
59
|
+
await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
|
|
60
|
+
// Then, we iterate over all selected values and insert appropriate missing links
|
|
61
|
+
const promises = to_create_ids.map(async (id) => {
|
|
62
|
+
await ctx.$app.collections["${toKebabCase(referencing_collection)}"].create(
|
|
63
|
+
ctx.$context,
|
|
64
|
+
{
|
|
65
|
+
"${referencing_field}": item_id,
|
|
66
|
+
"${intermediary_field_that_points_there}": id,
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
await Promise.all(promises);
|
|
71
|
+
}`;
|
|
72
|
+
return {
|
|
73
|
+
field: `${name}: new Fields.CheckboxedListField(${is_required_expr}, async (ctx) => {
|
|
74
|
+
const { items } = await ctx.$app.collections["${target}"]
|
|
75
|
+
.list(ctx.$context)
|
|
76
|
+
.fetch();
|
|
77
|
+
|
|
78
|
+
return items.map((s) => ({
|
|
79
|
+
label: s.get("name"),
|
|
80
|
+
value: s.id,
|
|
81
|
+
}));
|
|
82
|
+
})`,
|
|
83
|
+
controls: `new Controls.CheckboxedListInput(${fields_var}.${name}, {
|
|
84
|
+
label: "${name}",
|
|
85
|
+
})`,
|
|
86
|
+
post_edit: post_create(`await this.getID(ctx)`),
|
|
87
|
+
post_create: post_create(`created.id`),
|
|
88
|
+
initial_value_edit: `Object.fromEntries((item.get("${name}") || []).map(id=>[id, "on"]))`,
|
|
89
|
+
sealious_value: () => "",
|
|
90
|
+
};
|
|
91
|
+
} else {
|
|
92
|
+
// probably an n-to-n intermediary collection with an additional attribute
|
|
93
|
+
const initial_value_function_name = `get${toPascalCase(
|
|
94
|
+
name
|
|
95
|
+
)}TableInitialValues`;
|
|
96
|
+
const post_create = (get_id: string) => `{
|
|
97
|
+
const item_id = ${get_id};
|
|
98
|
+
// First, we remove links refering to current item
|
|
99
|
+
const { items: to_delete } = await ctx.$app.collections[
|
|
100
|
+
"${toKebabCase(referencing_collection)}"
|
|
101
|
+
]
|
|
102
|
+
.list(ctx.$context)
|
|
103
|
+
.filter({ "${referencing_field}": item_id })
|
|
104
|
+
.fetch();
|
|
105
|
+
await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
|
|
106
|
+
|
|
107
|
+
// Then, we iterate over all selected values and insert appropriate entries for the subcategories relation
|
|
108
|
+
|
|
109
|
+
const promises = data["${name}"]
|
|
110
|
+
.filter((s) => s.selected == true)
|
|
111
|
+
.map(async (link_info) => {
|
|
112
|
+
await ctx.$app.collections["${toKebabCase(referencing_collection)}"].create(
|
|
113
|
+
ctx.$context,
|
|
114
|
+
{
|
|
115
|
+
"${referencing_field}": item_id,
|
|
116
|
+
"${intermediary_field_that_points_there}": String(link_info["${intermediary_field_that_points_there}"]),
|
|
117
|
+
${referencing_fields
|
|
118
|
+
.filter(
|
|
119
|
+
({ type }) => type !== "single-reference"
|
|
120
|
+
)
|
|
121
|
+
.map(
|
|
122
|
+
(field) =>
|
|
123
|
+
`"${field.name}": link_info["${field.name}"]`
|
|
124
|
+
)
|
|
125
|
+
.join(",\n")}
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
await Promise.all(promises);
|
|
131
|
+
}`;
|
|
132
|
+
const initial_value = `(await ${initial_value_function_name}(ctx,item)) as unknown as FormDataValue`;
|
|
133
|
+
return {
|
|
134
|
+
imports: {
|
|
135
|
+
shared: `import type { CollectionItem } from "sealious"; import type { Context } from "koa";`,
|
|
136
|
+
edit: `import {${initial_value_function_name}} from "../shared.js"; import type { FormDataValue } from "@sealcode/sealgen";`,
|
|
137
|
+
},
|
|
138
|
+
field: `
|
|
139
|
+
${name}: new Fields.Table({
|
|
140
|
+
selected: new Fields.Boolean(false),
|
|
141
|
+
"${referencing_field}": new Fields.SimpleFormField(true),
|
|
142
|
+
"${intermediary_field_that_points_there}": new Fields.SimpleFormField(true),
|
|
143
|
+
${referencing_fields
|
|
144
|
+
.filter(({ type }) => type !== "single-reference")
|
|
145
|
+
.map(
|
|
146
|
+
(field) =>
|
|
147
|
+
`${field.name}: new Fields.SimpleFormField(true)`
|
|
148
|
+
)
|
|
149
|
+
.join(",\n")}
|
|
150
|
+
})`,
|
|
151
|
+
controls: `
|
|
152
|
+
new Controls.Table(${fields_var}.${name}, {
|
|
153
|
+
render_fields: {
|
|
154
|
+
selected: (fctx, name, value) => /* HTML */ \`<input
|
|
155
|
+
type="checkbox"
|
|
156
|
+
name=\${name}
|
|
157
|
+
\${value?.toString() == "true" ? "checked" : ""}
|
|
158
|
+
form="\${fctx.form_id}"
|
|
159
|
+
autocomplete="off"
|
|
160
|
+
/>\`,
|
|
161
|
+
"${referencing_field}": (fctx, name, value) => /* HTML */ \`<input
|
|
162
|
+
type="hidden"
|
|
163
|
+
name=\${name}
|
|
164
|
+
value="\${value}"
|
|
165
|
+
form="\${fctx.form_id}"
|
|
166
|
+
/>\`,
|
|
167
|
+
"${intermediary_field_that_points_there}": (fctx, name, value) => /* HTML */ \`<input
|
|
168
|
+
type="hidden"
|
|
169
|
+
name=\${name}
|
|
170
|
+
value="\${value}"
|
|
171
|
+
form="\${fctx.form_id}"
|
|
172
|
+
/>\`,
|
|
173
|
+
${referencing_fields
|
|
174
|
+
.filter(
|
|
175
|
+
({ type }) => type !== "single-reference"
|
|
176
|
+
)
|
|
177
|
+
.map(
|
|
178
|
+
(field) =>
|
|
179
|
+
`${field.name}: (fctx, name, value) => /* HTML */ \`<input
|
|
180
|
+
name=\${name}
|
|
181
|
+
value="\${value}"
|
|
182
|
+
form="\${fctx.form_id}"
|
|
183
|
+
autocomplete="off"
|
|
184
|
+
/>\``
|
|
185
|
+
)
|
|
186
|
+
.join(",\n")}
|
|
187
|
+
},
|
|
188
|
+
allow_adding: false,
|
|
189
|
+
})`,
|
|
190
|
+
top_level_shared: `export async function ${initial_value_function_name}(
|
|
191
|
+
ctx: Context,
|
|
192
|
+
item: CollectionItem<typeof ${toPascalCase(
|
|
193
|
+
collection_name
|
|
194
|
+
)}>
|
|
195
|
+
) {
|
|
196
|
+
// convert from an array to array-like object
|
|
197
|
+
return Object.fromEntries(
|
|
198
|
+
await Promise.all([
|
|
199
|
+
ctx.$app.collections["${toKebabCase(target)}"].list(ctx.$context).fetch(),
|
|
200
|
+
ctx.$app.collections["${toKebabCase(
|
|
201
|
+
referencing_collection
|
|
202
|
+
)}"].list(ctx.$context).fetch(),
|
|
203
|
+
]).then(([{ items: targets }, { items: links }]) =>
|
|
204
|
+
targets
|
|
205
|
+
.map((target) => {
|
|
206
|
+
return {
|
|
207
|
+
selected: (item.get("${name}") || []).includes(
|
|
208
|
+
target.id
|
|
209
|
+
)
|
|
210
|
+
? "on"
|
|
211
|
+
: "off",
|
|
212
|
+
"${referencing_field}": item.id,
|
|
213
|
+
"${intermediary_field_that_points_there}": target.id,
|
|
214
|
+
${referencing_fields
|
|
215
|
+
.filter(
|
|
216
|
+
({ type }) =>
|
|
217
|
+
type !== "single-reference"
|
|
218
|
+
)
|
|
219
|
+
.map(
|
|
220
|
+
(
|
|
221
|
+
field
|
|
222
|
+
) => `"${field.name}": links
|
|
223
|
+
.find(
|
|
224
|
+
(e) =>
|
|
225
|
+
e.get("${intermediary_field_that_points_there}") == target.id &&
|
|
226
|
+
e.get("${referencing_field}") == item.id
|
|
227
|
+
)
|
|
228
|
+
?.get("rank") || 0,`
|
|
229
|
+
)
|
|
230
|
+
.join(",\n")}
|
|
231
|
+
};
|
|
232
|
+
})
|
|
233
|
+
.entries()
|
|
234
|
+
)
|
|
235
|
+
);
|
|
236
|
+
}`,
|
|
237
|
+
|
|
238
|
+
initial_value_edit: initial_value,
|
|
239
|
+
initial_value_create: initial_value,
|
|
240
|
+
post_edit: post_create(`await this.getID(ctx)`),
|
|
241
|
+
post_create: post_create(`created.id`),
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { toPascalCase } from "js-convert-case";
|
|
2
|
+
import {
|
|
3
|
+
FieldHandler,
|
|
4
|
+
FieldHandlerResult,
|
|
5
|
+
} from "../shared-crud-form-fields.js";
|
|
6
|
+
|
|
7
|
+
export const default_handler: FieldHandler<
|
|
8
|
+
Record<string, never>,
|
|
9
|
+
FieldHandlerResult
|
|
10
|
+
> = async (collection_name, { name, is_readonly, is_required }) => {
|
|
11
|
+
const required_s = `${toPascalCase(
|
|
12
|
+
collection_name
|
|
13
|
+
)}.fields.${name}.required`;
|
|
14
|
+
const fields_var = `${toPascalCase(collection_name)}FormFields`;
|
|
15
|
+
const fallback_value_initial = `""`;
|
|
16
|
+
const fallback_value_sealious = `""`;
|
|
17
|
+
|
|
18
|
+
const main_value_initial = `item.get("${name}")`;
|
|
19
|
+
const main_value_sealious = `data["${name}"]`;
|
|
20
|
+
const parsed_value = main_value_initial;
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
is_required,
|
|
24
|
+
name,
|
|
25
|
+
post_create: "",
|
|
26
|
+
imports: { shared: "", edit: "" },
|
|
27
|
+
hide_field: is_readonly,
|
|
28
|
+
field: `${name}: new Fields.CollectionField(${required_s}, ${toPascalCase(
|
|
29
|
+
collection_name
|
|
30
|
+
)}.fields.${name})`,
|
|
31
|
+
hide_control: is_readonly,
|
|
32
|
+
controls: `new Controls.SimpleInput(${fields_var}.${name}, { label: "${name}"})`,
|
|
33
|
+
is_required_expr: `${toPascalCase(
|
|
34
|
+
collection_name
|
|
35
|
+
)}.fields.${name}.required`,
|
|
36
|
+
fields_var,
|
|
37
|
+
top_level_shared: "",
|
|
38
|
+
hide_initial_value_edit: is_readonly,
|
|
39
|
+
initial_value_edit: {
|
|
40
|
+
fallback_value: fallback_value_initial,
|
|
41
|
+
main_value: main_value_initial,
|
|
42
|
+
parsed_value,
|
|
43
|
+
},
|
|
44
|
+
hide_initial_value_create: is_readonly,
|
|
45
|
+
initial_value_create: "",
|
|
46
|
+
pre_edit: "",
|
|
47
|
+
post_edit: "",
|
|
48
|
+
pre_create: "",
|
|
49
|
+
main_value_sealious,
|
|
50
|
+
fallback_value_sealious,
|
|
51
|
+
sealious_value: (result: FieldHandlerResult) => {
|
|
52
|
+
return result.is_required
|
|
53
|
+
? `${result.name}: ${result.main_value_sealious}`
|
|
54
|
+
: `${result.name}: ${result.main_value_sealious} != null ? ${result.main_value_sealious} : ${result.fallback_value_sealious}`;
|
|
55
|
+
},
|
|
56
|
+
hide_sealious_value: is_readonly,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { toPascalCase } from "js-convert-case";
|
|
2
|
+
import {
|
|
3
|
+
FieldHandler,
|
|
4
|
+
FieldHandlerResult,
|
|
5
|
+
} from "../shared-crud-form-fields.js";
|
|
6
|
+
|
|
7
|
+
export const enum_handler: FieldHandler<
|
|
8
|
+
FieldHandlerResult,
|
|
9
|
+
Partial<FieldHandlerResult>
|
|
10
|
+
> = async (collection_name, { name }, _, { fields_var }) => ({
|
|
11
|
+
// this assertion and import is only necessary because required fields
|
|
12
|
+
// in Sealious lose the type information. Once this is fixed, we can remove this import here
|
|
13
|
+
imports: { shared: `import type { FieldTypes } from "sealious";` },
|
|
14
|
+
field: `${name}: new Fields.PickFromListField(
|
|
15
|
+
${toPascalCase(collection_name)}.fields["${name}"].required,
|
|
16
|
+
async (ctx) =>
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
18
|
+
(${toPascalCase(collection_name)}.fields["${name}"])
|
|
19
|
+
.getAllowedValues(ctx.$app)
|
|
20
|
+
.map((value) => ({ value, label: value }))
|
|
21
|
+
)`,
|
|
22
|
+
controls: `new Controls.Dropdown(${fields_var}.${name}, { label: "${name}"})`,
|
|
23
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { toCamelCase } from "js-convert-case";
|
|
2
|
+
import {
|
|
3
|
+
FieldHandler,
|
|
4
|
+
FieldHandlerResult,
|
|
5
|
+
} from "../shared-crud-form-fields.js";
|
|
6
|
+
|
|
7
|
+
export const file_handler: FieldHandler<
|
|
8
|
+
FieldHandlerResult,
|
|
9
|
+
Partial<FieldHandlerResult>
|
|
10
|
+
> = async (_, { name, is_required }, __, { is_required_expr }) => {
|
|
11
|
+
const tempname = toCamelCase("prepared-" + name);
|
|
12
|
+
return {
|
|
13
|
+
field: `${name}: new Fields.File(${is_required_expr}, TheFileManager)`,
|
|
14
|
+
initial_value_edit: `${name}: {old: item.get("${name}")}`,
|
|
15
|
+
pre_edit: `const ${tempname} = data.${name}.new || data.${name}.old;
|
|
16
|
+
if(!${tempname}){
|
|
17
|
+
throw new Error("Missing field: ${name}")
|
|
18
|
+
}`,
|
|
19
|
+
fallback_value_sealious: "null",
|
|
20
|
+
...(is_required ? { main_value_sealious: tempname } : {}),
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { toCamelCase } from "js-convert-case";
|
|
2
|
+
import {
|
|
3
|
+
FieldHandler,
|
|
4
|
+
FieldHandlerResult,
|
|
5
|
+
} from "../shared-crud-form-fields.js";
|
|
6
|
+
|
|
7
|
+
export const image_handler: FieldHandler<
|
|
8
|
+
FieldHandlerResult,
|
|
9
|
+
Partial<FieldHandlerResult>
|
|
10
|
+
> = async (
|
|
11
|
+
_,
|
|
12
|
+
{ name, is_required },
|
|
13
|
+
importPath,
|
|
14
|
+
{ is_required_expr, fields_var }
|
|
15
|
+
) => {
|
|
16
|
+
const tempname = toCamelCase("prepared-" + name);
|
|
17
|
+
return {
|
|
18
|
+
imports: {
|
|
19
|
+
shared: `import { imageRouter } from "${importPath(
|
|
20
|
+
"src/back/image-router.js"
|
|
21
|
+
)}";
|
|
22
|
+
import { TheFileManager } from "${importPath(
|
|
23
|
+
"src/back/file-manager.js"
|
|
24
|
+
)}";`,
|
|
25
|
+
},
|
|
26
|
+
field: `${name}: new Fields.File(${is_required_expr}, TheFileManager)`,
|
|
27
|
+
controls: `new Controls.Photo(${fields_var}.${name}, imageRouter, {
|
|
28
|
+
label: "${name}",
|
|
29
|
+
})`,
|
|
30
|
+
initial_value_edit: `{old: item.get("${name}")}`,
|
|
31
|
+
pre_edit:
|
|
32
|
+
`const ${tempname} = data.${name}.new || data.${name}.old ` +
|
|
33
|
+
(is_required
|
|
34
|
+
? `; if(!${tempname}){
|
|
35
|
+
throw new Error("Missing field: ${name}")
|
|
36
|
+
}`
|
|
37
|
+
: " || undefined;"),
|
|
38
|
+
pre_create: `const ${tempname} = data.${name}.new || data.${name}.old;
|
|
39
|
+
if(!${tempname}){
|
|
40
|
+
throw new Error("Missing field: ${name}")
|
|
41
|
+
}`,
|
|
42
|
+
fallback_value_sealious: "null",
|
|
43
|
+
sealious_value: () => `${name}: ${tempname}`,
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldHandler,
|
|
3
|
+
FieldHandlerResult,
|
|
4
|
+
} from "../shared-crud-form-fields.js";
|
|
5
|
+
|
|
6
|
+
export const int_handler: FieldHandler<
|
|
7
|
+
FieldHandlerResult,
|
|
8
|
+
Partial<FieldHandlerResult>
|
|
9
|
+
> = async (_, { name }, __, { is_required_expr, fields_var }) => ({
|
|
10
|
+
field: `${name}: new Fields.NumberField(${is_required_expr}, 0)`,
|
|
11
|
+
controls: `new Controls.Number(${fields_var}.${name}, { label: "${name}" })`,
|
|
12
|
+
initial_value_edit: {
|
|
13
|
+
parsed_value: `String(item.get("${name}"))`,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldHandler,
|
|
3
|
+
FieldHandlerResult,
|
|
4
|
+
} from "../shared-crud-form-fields.js";
|
|
5
|
+
|
|
6
|
+
export const jdd_handler: FieldHandler<
|
|
7
|
+
FieldHandlerResult,
|
|
8
|
+
Partial<FieldHandlerResult>
|
|
9
|
+
> = async (_, { name }) => ({
|
|
10
|
+
field: ``,
|
|
11
|
+
initial_value_edit: "",
|
|
12
|
+
controls: "",
|
|
13
|
+
sealious_value: () => `${name}: []`,
|
|
14
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldHandler,
|
|
3
|
+
FieldHandlerResult,
|
|
4
|
+
} from "../shared-crud-form-fields.js";
|
|
5
|
+
|
|
6
|
+
export const single_reference_handler: FieldHandler<
|
|
7
|
+
FieldHandlerResult,
|
|
8
|
+
Partial<FieldHandlerResult>
|
|
9
|
+
> = async (_, { name }, __, { fields_var }) => {
|
|
10
|
+
return {
|
|
11
|
+
controls: `new Controls.SingleReferenceDropdown(${fields_var}.${name}, {
|
|
12
|
+
label: "${name}",
|
|
13
|
+
getLabel: (item)=>item.id
|
|
14
|
+
})`,
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldHandler,
|
|
3
|
+
FieldHandlerResult,
|
|
4
|
+
} from "../shared-crud-form-fields.js";
|
|
5
|
+
|
|
6
|
+
export const structured_array_handler: FieldHandler<
|
|
7
|
+
FieldHandlerResult,
|
|
8
|
+
Partial<FieldHandlerResult>
|
|
9
|
+
> = async (_, { name, subfields }, __, { fields_var }) => ({
|
|
10
|
+
field: `${name}: new Fields.Table({
|
|
11
|
+
${subfields
|
|
12
|
+
.map(
|
|
13
|
+
(subfield) =>
|
|
14
|
+
`${subfield.name}: new Fields.SimpleFormField(true)`
|
|
15
|
+
)
|
|
16
|
+
.join(",\n")}
|
|
17
|
+
})`,
|
|
18
|
+
controls: `new Controls.Table(${fields_var}.${name}, {
|
|
19
|
+
label: "${name}",
|
|
20
|
+
render_fields: {
|
|
21
|
+
${subfields
|
|
22
|
+
.map(
|
|
23
|
+
({
|
|
24
|
+
name,
|
|
25
|
+
}) => `"${name}": (fctx, name, value) => /* HTML */ \`<input
|
|
26
|
+
name="\${name}"
|
|
27
|
+
value="\${value}"
|
|
28
|
+
form="\${fctx.form_id}"
|
|
29
|
+
autocomplete="off"
|
|
30
|
+
/>\``
|
|
31
|
+
)
|
|
32
|
+
.join(",\n")}
|
|
33
|
+
|
|
34
|
+
},
|
|
35
|
+
allow_adding: true,
|
|
36
|
+
allow_removing: true,
|
|
37
|
+
make_new_row: async () => ({
|
|
38
|
+
${subfields.map(({ name }) => `"${name}": ""`).join(",\n")}
|
|
39
|
+
}),
|
|
40
|
+
})`,
|
|
41
|
+
fallback_value_sealious: `[]`,
|
|
42
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { toKebabCase, toPascalCase } from "js-convert-case";
|
|
2
|
+
import { curryImportPath } from "../../utils/import-path.js";
|
|
3
|
+
import { formatWithPrettier } from "../../utils/prettier.js";
|
|
4
|
+
|
|
5
|
+
export function itemDeleteTemplate(
|
|
6
|
+
delete_action_name: string,
|
|
7
|
+
collection_name: string,
|
|
8
|
+
newfilefullpath: string,
|
|
9
|
+
list_action_name: string
|
|
10
|
+
): Promise<string> {
|
|
11
|
+
const importPath = curryImportPath(newfilefullpath);
|
|
12
|
+
const result = `import type { Context } from "koa";
|
|
13
|
+
import { Mountable } from "@sealcode/sealgen";
|
|
14
|
+
import type Router from "@koa/router";
|
|
15
|
+
|
|
16
|
+
import { ${toPascalCase(collection_name)} } from "${importPath(
|
|
17
|
+
"src/back/collections/collections.js"
|
|
18
|
+
)}";
|
|
19
|
+
|
|
20
|
+
import { ${list_action_name}URL } from "${importPath(
|
|
21
|
+
"src/back/routes/urls.js"
|
|
22
|
+
)}";
|
|
23
|
+
|
|
24
|
+
export const actionName = "${delete_action_name}";
|
|
25
|
+
|
|
26
|
+
export default new (class ${delete_action_name}Redirect extends Mountable {
|
|
27
|
+
canAccess = async (ctx: Context) => {
|
|
28
|
+
const policy = ${toPascalCase(collection_name)}.getPolicy("edit");
|
|
29
|
+
const response = await policy.check(ctx.$context);
|
|
30
|
+
return { canAccess: response?.allowed || false, message: response?.reason || "" };
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
mount(router: Router, path: string) {
|
|
34
|
+
router.get(path, async (ctx) => {
|
|
35
|
+
await ctx.$app.collections["${toKebabCase(
|
|
36
|
+
collection_name
|
|
37
|
+
)}"].removeByID(ctx.$context, ctx.params.id);
|
|
38
|
+
ctx.status = 302;
|
|
39
|
+
ctx.redirect(${list_action_name}URL);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
})();
|
|
43
|
+
`;
|
|
44
|
+
return formatWithPrettier(result);
|
|
45
|
+
}
|