@sealcode/sealgen 0.19.17 → 0.19.20
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/add-crud.test.d.ts +1 -0
- package/@types/controllers/sealgen-table.stimulus.d.ts +13 -0
- package/@types/forms/controls/table.d.ts +2 -0
- package/@types/index.d.ts +1 -0
- package/lib/controllers/sealgen-table.stimulus.js +98 -0
- package/lib/forms/controls/table.js +49 -43
- package/lib/generate-routes.js +11 -2
- package/lib/mount.js +8 -10
- package/lib/templates/form.js +2 -2
- package/lib/templates/jdd-editor.js +2 -0
- package/lib/templates/long-running-process.js +2 -0
- package/lib/templates/multiform.js +2 -0
- package/lib/templates/page.js +2 -0
- package/lib/templates/post.js +2 -0
- package/lib/templates/redirect.js +2 -0
- package/lib/templates/shared/collection-list.js +2 -1
- package/lib/templates/shared/item-delete.js +2 -0
- package/lib/templates/stateful-page.js +2 -0
- package/package.json +1 -1
- package/src/add-crud.test.ts +44 -0
- package/src/add-crud.ts +1 -1
- package/src/controllers/sealgen-table.stimulus.ts +115 -0
- package/src/forms/controls/table.ts +94 -81
- package/src/generate-routes.ts +13 -2
- package/src/index.ts +2 -0
- package/src/mount.ts +8 -12
- package/src/templates/form.ts +2 -2
- package/src/templates/jdd-editor.ts +2 -0
- package/src/templates/long-running-process.ts +2 -0
- package/src/templates/multiform.ts +2 -0
- package/src/templates/page.ts +2 -0
- package/src/templates/post.ts +2 -0
- package/src/templates/redirect.ts +2 -0
- package/src/templates/shared/collection-list.ts +2 -1
- package/src/templates/shared/item-delete.ts +2 -0
- package/src/templates/stateful-page.ts +2 -0
- package/lib/controllers/table-add-button.stimulus.js +0 -35
- package/src/controllers/table-add-button.stimulus.ts +0 -35
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { Controller } from "stimulus";
|
|
3
|
+
|
|
4
|
+
export default class TableController extends Controller {
|
|
5
|
+
static targets = ["table", "template"];
|
|
6
|
+
declare tableTarget: HTMLTableElement;
|
|
7
|
+
declare templateTarget: HTMLTemplateElement;
|
|
8
|
+
|
|
9
|
+
getTbody() {
|
|
10
|
+
const tbody = this.element
|
|
11
|
+
.closest("turbo-frame")
|
|
12
|
+
?.querySelector("tbody");
|
|
13
|
+
if (!tbody) {
|
|
14
|
+
throw new Error("tbody not found");
|
|
15
|
+
}
|
|
16
|
+
return tbody;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
getRowIndex(tr: HTMLTableRowElement) {
|
|
20
|
+
let result = 0;
|
|
21
|
+
for (const child of Array.from(this.getTbody().children)) {
|
|
22
|
+
if (child == tr) {
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
result++;
|
|
26
|
+
}
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
addRow() {
|
|
31
|
+
const tbody = this.getTbody();
|
|
32
|
+
const orig_template = this.templateTarget.innerHTML;
|
|
33
|
+
const placeholder = this.element.getAttribute("data-table-placeholder");
|
|
34
|
+
if (!placeholder) {
|
|
35
|
+
throw new Error("Could not find placeholder attribute");
|
|
36
|
+
}
|
|
37
|
+
this.templateTarget.innerHTML = orig_template.replaceAll(
|
|
38
|
+
placeholder,
|
|
39
|
+
String(tbody.querySelectorAll("tr").length)
|
|
40
|
+
);
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
42
|
+
tbody.appendChild((this.templateTarget.cloneNode(true) as any).content);
|
|
43
|
+
this.templateTarget.innerHTML = orig_template;
|
|
44
|
+
this.reindex();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
swapRows(index_a: number, index_b: number) {
|
|
48
|
+
const tbody = this.getTbody();
|
|
49
|
+
const [a, b] = [index_a, index_b].sort().reverse(); // we want them in descending order
|
|
50
|
+
tbody.insertBefore(tbody.children[a], tbody.children[b]);
|
|
51
|
+
this.reindex();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
moveUp(e: MouseEvent) {
|
|
55
|
+
const target = e.target as HTMLButtonElement;
|
|
56
|
+
const tr = target.closest("tr");
|
|
57
|
+
if (!tr) {
|
|
58
|
+
console.error("Not within a tr");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const index_a = this.getRowIndex(tr);
|
|
62
|
+
if (index_a < 0) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const index_b = index_a - 1;
|
|
66
|
+
this.swapRows(index_a, index_b);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
moveDown(e: MouseEvent) {
|
|
70
|
+
const target = e.target as HTMLButtonElement;
|
|
71
|
+
const tr = target.closest("tr");
|
|
72
|
+
if (!tr) {
|
|
73
|
+
console.error("Not within a tr");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const index_a = this.getRowIndex(tr);
|
|
77
|
+
if (index_a < 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const index_b = index_a + 1;
|
|
81
|
+
this.swapRows(index_a, index_b);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
reindex() {
|
|
85
|
+
let result = 0;
|
|
86
|
+
|
|
87
|
+
// assign proper number to each input within a tr by changing input names
|
|
88
|
+
for (const tr of Array.from(this.getTbody().children)) {
|
|
89
|
+
tr.querySelectorAll("input").forEach((input) => {
|
|
90
|
+
input.setAttribute(
|
|
91
|
+
"name",
|
|
92
|
+
(input.getAttribute("name") || "").replace(
|
|
93
|
+
/[(\d+)](?!.*\d)/, // last number in a regex
|
|
94
|
+
result.toString()
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
result++;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// disable up/down buttons for first/last items
|
|
102
|
+
// first reset all states to enabled
|
|
103
|
+
this.element
|
|
104
|
+
.querySelectorAll(
|
|
105
|
+
`[data-action="sealgen-table#moveUp"], [data-action="sealgen-table#moveDown"]`
|
|
106
|
+
)
|
|
107
|
+
.forEach((e: HTMLButtonElement) => (e.disabled = false));
|
|
108
|
+
// then disable the ones at the top and bottom
|
|
109
|
+
this.element
|
|
110
|
+
.querySelectorAll(
|
|
111
|
+
'tr:first-child [data-action="sealgen-table#moveUp"], tr:last-child [data-action="sealgen-table#moveDown"]'
|
|
112
|
+
)
|
|
113
|
+
.forEach((e: HTMLButtonElement) => (e.disabled = true));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -21,6 +21,7 @@ export type TableControlOptions<F extends Record<string, FormField>> = {
|
|
|
21
21
|
[field_name in keyof F]: FormControl;
|
|
22
22
|
};
|
|
23
23
|
allow_removing?: boolean;
|
|
24
|
+
allow_reordering?: boolean;
|
|
24
25
|
label_add?: string;
|
|
25
26
|
label: string;
|
|
26
27
|
label_remove?: string;
|
|
@@ -62,8 +63,8 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
62
63
|
| null,
|
|
63
64
|
row_index: number | string
|
|
64
65
|
) => {
|
|
65
|
-
return typeof row_index == "number"
|
|
66
|
-
|
|
66
|
+
return typeof row_index == "number" ?
|
|
67
|
+
{
|
|
67
68
|
data: {
|
|
68
69
|
raw_values:
|
|
69
70
|
(Object.fromEntries(
|
|
@@ -78,7 +79,7 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
78
79
|
field_messages: {},
|
|
79
80
|
},
|
|
80
81
|
}
|
|
81
|
-
:
|
|
82
|
+
: {};
|
|
82
83
|
};
|
|
83
84
|
|
|
84
85
|
const make_row = async (
|
|
@@ -89,7 +90,7 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
89
90
|
>;
|
|
90
91
|
}
|
|
91
92
|
| null,
|
|
92
|
-
row_index: number | string
|
|
93
|
+
row_index: number | string // when string, it's a placeholder, it will not parse as a number
|
|
93
94
|
) => {
|
|
94
95
|
return /* HTML */ tempstream`<tr>
|
|
95
96
|
${Promise.all(
|
|
@@ -108,33 +109,42 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
108
109
|
)
|
|
109
110
|
)}
|
|
110
111
|
${
|
|
111
|
-
this.options.allow_removing
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
112
|
+
this.options.allow_removing ?
|
|
113
|
+
/* HTML */ `<td>
|
|
114
|
+
<button onclick="this.closest('tr').remove()">
|
|
115
|
+
remove
|
|
116
|
+
</button>
|
|
117
|
+
<noscript>
|
|
118
|
+
<input
|
|
119
|
+
type="submit"
|
|
120
|
+
data-turbo-frame="${this.getFrameID()}"
|
|
121
|
+
value="${this.options.label_remove ||
|
|
122
|
+
"remove"}"
|
|
123
|
+
form="${fctx.form_id}"
|
|
124
|
+
formnovalidate
|
|
125
|
+
formaction="${this.getActionURL(
|
|
126
|
+
this.table_field.name,
|
|
127
|
+
{
|
|
128
|
+
remove: {
|
|
129
|
+
index: row_index,
|
|
130
|
+
},
|
|
131
|
+
}
|
|
132
|
+
)}"
|
|
133
|
+
/>
|
|
134
|
+
</noscript>
|
|
135
|
+
</td>`
|
|
136
|
+
: ""
|
|
137
|
+
}${
|
|
138
|
+
this.options.allow_reordering ?
|
|
139
|
+
/* HTML */ `<td>
|
|
140
|
+
<button data-action="sealgen-table#moveUp">
|
|
141
|
+
↑
|
|
142
|
+
</button>
|
|
143
|
+
<button data-action="sealgen-table#moveDown">
|
|
144
|
+
↓
|
|
145
|
+
</button>
|
|
146
|
+
</td>`
|
|
147
|
+
: ""
|
|
138
148
|
}
|
|
139
149
|
</tr>`;
|
|
140
150
|
};
|
|
@@ -145,60 +155,62 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
145
155
|
"form-input__wrapper",
|
|
146
156
|
"form-input__wrapper--type--table",
|
|
147
157
|
"form-input__wrapper--options-count--" + rows.length.toString(),
|
|
148
|
-
...(rows.length >= 5
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
...(rows.length >= 10
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
...(rows.length >= 15
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
...(rows.length >= 20
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
...(rows.length >= 5 ?
|
|
159
|
+
["form-input__wrapper--options-count--5-or-more"]
|
|
160
|
+
: []),
|
|
161
|
+
...(rows.length >= 10 ?
|
|
162
|
+
["form-input__wrapper--options-count--10-or-more"]
|
|
163
|
+
: []),
|
|
164
|
+
...(rows.length >= 15 ?
|
|
165
|
+
["form-input__wrapper--options-count--15-or-more"]
|
|
166
|
+
: []),
|
|
167
|
+
...(rows.length >= 20 ?
|
|
168
|
+
["form-input__wrapper--options-count--20-or-more"]
|
|
169
|
+
: []),
|
|
160
170
|
].join(" ")}"
|
|
161
171
|
>
|
|
162
172
|
<label>${this.options.label || this.table_field.label}</label>
|
|
163
|
-
<div
|
|
164
|
-
|
|
173
|
+
<div
|
|
174
|
+
class="table__wrapper"
|
|
175
|
+
data-controller="sealgen-table"
|
|
176
|
+
data-table-placeholder="${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}"
|
|
177
|
+
>
|
|
178
|
+
<table data-sealgen-table-target="table">
|
|
165
179
|
<tbody>
|
|
166
180
|
${rows?.map((row, index) => make_row(row, index))}
|
|
167
181
|
</tbody>
|
|
168
182
|
</table>
|
|
169
|
-
<template>
|
|
183
|
+
<template data-sealgen-table-target="template">
|
|
170
184
|
${make_row(null, TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER)}
|
|
171
185
|
</template>
|
|
172
186
|
|
|
173
187
|
${
|
|
174
188
|
/* because of https://github.com/ljharb/qs/issues/252 we have to
|
|
175
189
|
put the indexes in the field names */
|
|
176
|
-
this.options.allow_adding
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
</noscript>`
|
|
201
|
-
: ""
|
|
190
|
+
this.options.allow_adding ?
|
|
191
|
+
/* HTML */ `<button
|
|
192
|
+
data-action="click->sealgen-table#addRow"
|
|
193
|
+
>
|
|
194
|
+
${this.options.label_add || "add"}
|
|
195
|
+
</button>
|
|
196
|
+
<noscript>
|
|
197
|
+
<input
|
|
198
|
+
type="submit"
|
|
199
|
+
value="add"
|
|
200
|
+
form="${fctx.form_id}"
|
|
201
|
+
formnovalidate
|
|
202
|
+
formaction="${this.getActionURL(
|
|
203
|
+
this.table_field.name,
|
|
204
|
+
{
|
|
205
|
+
insert: {
|
|
206
|
+
index: rows.length,
|
|
207
|
+
value: {},
|
|
208
|
+
},
|
|
209
|
+
}
|
|
210
|
+
)}"
|
|
211
|
+
/>
|
|
212
|
+
</noscript>`
|
|
213
|
+
: ""
|
|
202
214
|
}
|
|
203
215
|
</div>
|
|
204
216
|
</turbo-frame>`;
|
|
@@ -221,11 +233,13 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
221
233
|
const field_name = ctx.$body.field_name;
|
|
222
234
|
if (
|
|
223
235
|
!is(action, predicates.object) ||
|
|
224
|
-
!is(field_name, predicates.string)
|
|
236
|
+
!is(field_name, predicates.string) ||
|
|
237
|
+
field_name !== this.table_field.name
|
|
225
238
|
) {
|
|
226
239
|
await next();
|
|
227
240
|
return;
|
|
228
241
|
}
|
|
242
|
+
|
|
229
243
|
if (
|
|
230
244
|
this.options.allow_adding &&
|
|
231
245
|
hasShape(
|
|
@@ -235,16 +249,13 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
235
249
|
action
|
|
236
250
|
)
|
|
237
251
|
) {
|
|
238
|
-
if (field_name !== this.table_field.name) {
|
|
239
|
-
await next();
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
252
|
if (!ctx.$body[this.table_field.name]) {
|
|
243
253
|
ctx.$body[this.table_field.name] = {};
|
|
244
254
|
}
|
|
245
255
|
(ctx.$body[this.table_field.name] as any)[action.insert.index] =
|
|
246
256
|
await this.options.make_new_row(ctx);
|
|
247
257
|
}
|
|
258
|
+
|
|
248
259
|
if (
|
|
249
260
|
hasShape(
|
|
250
261
|
{
|
|
@@ -253,10 +264,6 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
253
264
|
action
|
|
254
265
|
)
|
|
255
266
|
) {
|
|
256
|
-
if (field_name !== this.table_field.name) {
|
|
257
|
-
await next();
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
267
|
if (!ctx.$body[this.table_field.name]) {
|
|
261
268
|
ctx.$body[this.table_field.name] = {};
|
|
262
269
|
}
|
|
@@ -270,6 +277,7 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
270
277
|
)
|
|
271
278
|
);
|
|
272
279
|
}
|
|
280
|
+
|
|
273
281
|
ctx.override_reaction = {
|
|
274
282
|
action: "stay",
|
|
275
283
|
content: await form.render(
|
|
@@ -310,4 +318,9 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
310
318
|
this.options.label_add = value;
|
|
311
319
|
return this;
|
|
312
320
|
}
|
|
321
|
+
|
|
322
|
+
setAllowReordering(value: boolean) {
|
|
323
|
+
this.options.allow_reordering = value;
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
313
326
|
}
|
package/src/generate-routes.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { walkDir } from "./utils/walk.js";
|
|
|
5
5
|
import { importPath } from "./utils/import-path.js";
|
|
6
6
|
import { assertType, predicates } from "@sealcode/ts-predicates";
|
|
7
7
|
import { unescape_url_params } from "./utils/escape-url-params.js";
|
|
8
|
-
import { formatWithPrettier } from "./utils/prettier.js";
|
|
9
8
|
import { Templates } from "./templates/templates.js";
|
|
9
|
+
import { formatWithPrettier } from "./utils/prettier.js";
|
|
10
10
|
|
|
11
11
|
const target_locreq = _locreq(process.cwd());
|
|
12
12
|
|
|
@@ -67,6 +67,13 @@ export function sortRoutes<T extends { url: string }>(urls: T[]): T[] {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
const getPathToBuiltFile = (filePath: string) => {
|
|
71
|
+
const rootPath = target_locreq.resolve("");
|
|
72
|
+
const relativePath = relative(rootPath, filePath);
|
|
73
|
+
const distPath = relativePath.replace(/^src[\\/]/, "dist/");
|
|
74
|
+
return distPath.replace(/\.(ts|tsx)$/, ".js");
|
|
75
|
+
};
|
|
76
|
+
|
|
70
77
|
export async function generateRoutes(): Promise<void> {
|
|
71
78
|
const files = await Promise.all(
|
|
72
79
|
(await walkDir(target_locreq.resolve("src/back/routes")))
|
|
@@ -79,6 +86,7 @@ export async function generateRoutes(): Promise<void> {
|
|
|
79
86
|
.map(async (fullpath) => ({
|
|
80
87
|
fullpath,
|
|
81
88
|
actionName: await extractActionName(fullpath),
|
|
89
|
+
module_path: getPathToBuiltFile(fullpath),
|
|
82
90
|
// trailing slash is important here, as it enables to use the entire path while building relative URLs. For example, while visiting /users/123, the path ./add-photo leads to /users/add-photo. While visiting /users/123/ (note the trailing slash), the path ./add-photo leads to /users/123/add-photo
|
|
83
91
|
url: unescape_url_params(
|
|
84
92
|
"/" +
|
|
@@ -98,11 +106,12 @@ export async function generateRoutes(): Promise<void> {
|
|
|
98
106
|
|
|
99
107
|
type URLTree = {
|
|
100
108
|
actionName?: string;
|
|
109
|
+
module_path?: string;
|
|
101
110
|
children: { [key: string]: URLTree };
|
|
102
111
|
};
|
|
103
112
|
|
|
104
113
|
const url_tree: URLTree = { children: {} };
|
|
105
|
-
sortRoutes(files).forEach(({ actionName, url }) => {
|
|
114
|
+
sortRoutes(files).forEach(({ actionName, url, module_path }) => {
|
|
106
115
|
const elements = url.split("/").filter((e) => e != "");
|
|
107
116
|
let pointer: URLTree = url_tree;
|
|
108
117
|
for (const [index, element] of elements.entries()) {
|
|
@@ -113,6 +122,7 @@ export async function generateRoutes(): Promise<void> {
|
|
|
113
122
|
if (index == elements.length - 1) {
|
|
114
123
|
(pointer as unknown as { actionName: string }).actionName =
|
|
115
124
|
actionName;
|
|
125
|
+
pointer.module_path = module_path;
|
|
116
126
|
}
|
|
117
127
|
}
|
|
118
128
|
});
|
|
@@ -121,6 +131,7 @@ export async function generateRoutes(): Promise<void> {
|
|
|
121
131
|
|
|
122
132
|
export type URLTree = {
|
|
123
133
|
actionName?: string;
|
|
134
|
+
module_path?: string;
|
|
124
135
|
children: { [key: string]: URLTree };
|
|
125
136
|
};
|
|
126
137
|
export const url_tree = ${JSON.stringify(url_tree)};
|
package/src/index.ts
CHANGED
package/src/mount.ts
CHANGED
|
@@ -25,16 +25,6 @@ export function mount(
|
|
|
25
25
|
): void {
|
|
26
26
|
const raw_url = typeof url === "string" ? url : url.rawURL;
|
|
27
27
|
|
|
28
|
-
const imageRouter = new KoaResponsiveImageRouter({
|
|
29
|
-
staticPath: "/tmp",
|
|
30
|
-
thumbnailSize: 10,
|
|
31
|
-
cacheManagerResolutionThreshold: 10,
|
|
32
|
-
imageStoragePath: "/tmp",
|
|
33
|
-
smartCropStoragePath: "/tmp",
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const fileManager = new FileManager("/tmp", "/uploaded_files");
|
|
37
|
-
|
|
38
28
|
const args =
|
|
39
29
|
use_dummy_app ?
|
|
40
30
|
[
|
|
@@ -44,8 +34,14 @@ export function mount(
|
|
|
44
34
|
// regard
|
|
45
35
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
36
|
ctx.$app = {
|
|
47
|
-
fileManager,
|
|
48
|
-
imageRouter
|
|
37
|
+
fileManager: new FileManager("/tmp", "/uploaded_files"),
|
|
38
|
+
imageRouter: new KoaResponsiveImageRouter({
|
|
39
|
+
staticPath: "/tmp",
|
|
40
|
+
thumbnailSize: 10,
|
|
41
|
+
cacheManagerResolutionThreshold: 10,
|
|
42
|
+
imageStoragePath: "/tmp",
|
|
43
|
+
smartCropStoragePath: "/tmp",
|
|
44
|
+
}),
|
|
49
45
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
50
46
|
Logger: new Proxy(
|
|
51
47
|
{},
|
package/src/templates/form.ts
CHANGED
|
@@ -46,13 +46,13 @@ export async function formTemplate(
|
|
|
46
46
|
): Promise<string> {
|
|
47
47
|
const params = { ...defaults, ..._params };
|
|
48
48
|
const content = `import type { Context } from "koa";
|
|
49
|
-
import type { FormData } from "@sealcode/sealgen";
|
|
49
|
+
import type { FormData, BreadcrumbLabel } from "@sealcode/sealgen";
|
|
50
50
|
import { Form, Controls } from "@sealcode/sealgen";
|
|
51
51
|
import html from "src/back/html.js";
|
|
52
|
-
|
|
53
52
|
${params.postimport}
|
|
54
53
|
|
|
55
54
|
export const actionName = "${action_name}";
|
|
55
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
56
56
|
|
|
57
57
|
const getFields = ${params.get_fields};
|
|
58
58
|
|
|
@@ -58,12 +58,14 @@ import type { FieldNames } from "sealious";
|
|
|
58
58
|
import { TempstreamJSX } from "tempstream";
|
|
59
59
|
import type ${collectionClassName} from "src/back/collections/${collection_name}.js";
|
|
60
60
|
import { EditJDDField } from "@sealcode/jdd-editor";
|
|
61
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
61
62
|
import html from "src/back/html.js";
|
|
62
63
|
import { registry } from "src/back/jdd-components/registry.js";
|
|
63
64
|
import { makeJDDContext } from "src/back/jdd-context.js";
|
|
64
65
|
import { defaultHead } from "src/back/defaultHead.js";
|
|
65
66
|
|
|
66
67
|
export const actionName = "${actionName}";
|
|
68
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${actionName}";
|
|
67
69
|
|
|
68
70
|
export default new (class JDDCreatePreviewPage extends EditJDDField<${collectionClassName}> {
|
|
69
71
|
getCollection(ctx: Context) {
|
|
@@ -9,10 +9,12 @@ export async function LongRunningProcessTemplate(
|
|
|
9
9
|
return `import { Context } from "koa";
|
|
10
10
|
import { TempstreamJSX } from "tempstream";
|
|
11
11
|
import { Page } from "@sealcode/sealgen";
|
|
12
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
12
13
|
import html from "${rel("src/back/html.js")}";
|
|
13
14
|
import { LongRunningProcess } from "sealious";
|
|
14
15
|
|
|
15
16
|
export const actionName = "${action_name}";
|
|
17
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
16
18
|
|
|
17
19
|
export default new (class PatroniteAutoImportStatusPage extends Page {
|
|
18
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -8,9 +8,11 @@ export async function multiformTemplate(
|
|
|
8
8
|
return `import { Context } from "koa";
|
|
9
9
|
import html from "${rel("src/back/html.js")}";
|
|
10
10
|
import { Controls, Fields, Form, FormMessage, Multiform } from "@sealcode/sealgen";
|
|
11
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
11
12
|
import { FlatTemplatable } from "tempstream";
|
|
12
13
|
|
|
13
14
|
export const actionName = "${action_name}";
|
|
15
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
14
16
|
|
|
15
17
|
const fields1 = {
|
|
16
18
|
email: new Fields.TextBasedSimpleField(true),
|
package/src/templates/page.ts
CHANGED
|
@@ -2,9 +2,11 @@ export async function pageTemplate(action_name: string): Promise<string> {
|
|
|
2
2
|
return `import type { Context } from "koa";
|
|
3
3
|
import { TempstreamJSX } from "tempstream";
|
|
4
4
|
import { Page } from "@sealcode/sealgen";
|
|
5
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
5
6
|
import html from "src/back/html.js";
|
|
6
7
|
|
|
7
8
|
export const actionName = "${action_name}";
|
|
9
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
8
10
|
|
|
9
11
|
export default new (class ${action_name}Page extends Page {
|
|
10
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
package/src/templates/post.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export async function postTemplate(action_name: string): Promise<string> {
|
|
2
2
|
return `import type { Context } from "koa";
|
|
3
3
|
import { Mountable } from "@sealcode/sealgen";
|
|
4
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
4
5
|
import type Router from "@koa/router";
|
|
5
6
|
|
|
6
7
|
export const actionName = "${action_name}";
|
|
8
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
7
9
|
|
|
8
10
|
export default new (class ${action_name}Redirect extends Mountable {
|
|
9
11
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export async function redirectTemplate(action_name: string): Promise<string> {
|
|
2
2
|
return `import type { Context } from "koa";
|
|
3
3
|
import { Mountable } from "@sealcode/sealgen";
|
|
4
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
4
5
|
import type Router from "@koa/router";
|
|
5
6
|
|
|
6
7
|
export const actionName = "${action_name}";
|
|
8
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
7
9
|
|
|
8
10
|
export default new (class ${action_name}Redirect extends Mountable {
|
|
9
11
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -118,7 +118,7 @@ import type { FlatTemplatable, Templatable } from "tempstream";
|
|
|
118
118
|
import { TempstreamJSX, tempstream } from "tempstream";
|
|
119
119
|
import { ${uppercase_collection} } from "src/back/collections/collections.js";
|
|
120
120
|
import html from "src/back/html.js";
|
|
121
|
-
import type { ListFilterRender, FormDisplayInfo } from "@sealcode/sealgen";
|
|
121
|
+
import type { ListFilterRender, FormDisplayInfo, BreadcrumbLabel } from "@sealcode/sealgen";
|
|
122
122
|
import {
|
|
123
123
|
SealiousItemListPage,
|
|
124
124
|
BaseListPageFields,
|
|
@@ -130,6 +130,7 @@ ${hooks.post_import_js}
|
|
|
130
130
|
${field_import_string}
|
|
131
131
|
|
|
132
132
|
export const actionName = "${action_name}";
|
|
133
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
133
134
|
|
|
134
135
|
const filterFields:{
|
|
135
136
|
field: keyof (typeof ${uppercase_collection})["fields"];
|
|
@@ -10,6 +10,7 @@ export function itemDeleteTemplate(
|
|
|
10
10
|
const result = `import type { Context } from "koa";
|
|
11
11
|
import { Mountable } from "@sealcode/sealgen";
|
|
12
12
|
import type Router from "@koa/router";
|
|
13
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
13
14
|
|
|
14
15
|
import { ${toPascalCase(collection_name)} } from "${importPath(
|
|
15
16
|
"src/back/collections/collections.js"
|
|
@@ -20,6 +21,7 @@ import { ${list_action_name}URL } from "${importPath(
|
|
|
20
21
|
)}";
|
|
21
22
|
|
|
22
23
|
export const actionName = "${delete_action_name}";
|
|
24
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${delete_action_name}";
|
|
23
25
|
|
|
24
26
|
export default new (class ${delete_action_name}Redirect extends Mountable {
|
|
25
27
|
canAccess = async (ctx: Context) => {
|
|
@@ -9,9 +9,11 @@ export async function statefulPageTemplate(
|
|
|
9
9
|
return formatWithPrettier(`import { TempstreamJSX, Templatable } from "tempstream";
|
|
10
10
|
import { Context } from "koa";
|
|
11
11
|
import { StatefulPage, StatefulPageActionArgument } from "@sealcode/sealgen";
|
|
12
|
+
import type { BreadcrumbLabel } from "@sealcode/sealgen";
|
|
12
13
|
import html from "${rel("src/back/html.js")}";
|
|
13
14
|
|
|
14
15
|
export const actionName = "${action_name}";
|
|
16
|
+
export const breadcrumbLabel: BreadcrumbLabel = "${action_name}";
|
|
15
17
|
|
|
16
18
|
const actions = {
|
|
17
19
|
add: ({ state, inputs }: StatefulPageActionArgument<State>) => {
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Controller } from "stimulus";
|
|
2
|
-
class table_add_button_stimulus_default extends Controller {
|
|
3
|
-
constructor() {
|
|
4
|
-
super(...arguments);
|
|
5
|
-
this.defaultRowsNumber = 20;
|
|
6
|
-
}
|
|
7
|
-
static {
|
|
8
|
-
this.targets = ["textarea"];
|
|
9
|
-
}
|
|
10
|
-
addRow() {
|
|
11
|
-
const template = this.element.closest("turbo-frame")?.querySelector("template");
|
|
12
|
-
if (!template) {
|
|
13
|
-
throw new Error("Couldn't find template");
|
|
14
|
-
}
|
|
15
|
-
const tbody = this.element.closest("turbo-frame")?.querySelector("tbody");
|
|
16
|
-
if (!tbody) {
|
|
17
|
-
throw new Error("tbody not found");
|
|
18
|
-
}
|
|
19
|
-
const orig_template = template.innerHTML;
|
|
20
|
-
const placeholder = this.element.getAttribute("data-table-placeholder");
|
|
21
|
-
if (!placeholder) {
|
|
22
|
-
throw new Error("Could find placeholder attribute");
|
|
23
|
-
}
|
|
24
|
-
template.innerHTML = orig_template.replaceAll(
|
|
25
|
-
placeholder,
|
|
26
|
-
String(tbody.querySelectorAll("tr").length)
|
|
27
|
-
);
|
|
28
|
-
tbody.appendChild(template.cloneNode(true).content);
|
|
29
|
-
template.innerHTML = orig_template;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export {
|
|
33
|
-
table_add_button_stimulus_default as default
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=table-add-button.stimulus.js.map
|