@sealcode/sealgen 0.15.56 → 0.15.58-beta
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="koa__router" />
|
|
2
2
|
import Router from "@koa/router";
|
|
3
|
+
import { Context } from "koa";
|
|
3
4
|
import { FlatTemplatable } from "tempstream";
|
|
4
5
|
import { FormField } from "../fields/field.js";
|
|
5
6
|
import { Table as TableField } from "../fields/table.js";
|
|
@@ -13,9 +14,14 @@ export type TableControlOptions<F extends Record<string, FormField>> = {
|
|
|
13
14
|
label_add?: string;
|
|
14
15
|
label: string;
|
|
15
16
|
label_remove?: string;
|
|
16
|
-
} & {
|
|
17
|
-
allow_adding:
|
|
18
|
-
}
|
|
17
|
+
} & ({
|
|
18
|
+
allow_adding: false;
|
|
19
|
+
} | {
|
|
20
|
+
allow_adding: true;
|
|
21
|
+
make_new_row: (ctx: Context) => Promise<{
|
|
22
|
+
[field_name in keyof F]: unknown;
|
|
23
|
+
}>;
|
|
24
|
+
});
|
|
19
25
|
export declare class Table<F extends Record<string, FormField>> extends FormControl {
|
|
20
26
|
table_field: TableField<F>;
|
|
21
27
|
options: TableControlOptions<F>;
|
|
@@ -2,6 +2,7 @@ import { hasShape, is, predicates } from "@sealcode/ts-predicates";
|
|
|
2
2
|
import qs from "qs";
|
|
3
3
|
import { tempstream } from "tempstream";
|
|
4
4
|
import { FormControl } from "./form-control.js";
|
|
5
|
+
const TO_REPLACE = "____$$$$";
|
|
5
6
|
class Table extends FormControl {
|
|
6
7
|
constructor(table_field, options) {
|
|
7
8
|
super();
|
|
@@ -24,7 +25,7 @@ class Table extends FormControl {
|
|
|
24
25
|
${Object.entries(this.table_field.columns).map(([key]) => {
|
|
25
26
|
return tempstream`<td>${this.options.render_fields[key](
|
|
26
27
|
fctx,
|
|
27
|
-
`${this.table_field.name}[][${key}]`,
|
|
28
|
+
`${this.table_field.name}[${row_index}][${key}]`,
|
|
28
29
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
29
30
|
row?.[key] || ""
|
|
30
31
|
)}</td>`;
|
|
@@ -32,13 +33,19 @@ class Table extends FormControl {
|
|
|
32
33
|
${this.options.allow_removing ? (
|
|
33
34
|
/* HTML */
|
|
34
35
|
`<td>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
<button
|
|
37
|
+
onclick="this.closest('tr').remove()"
|
|
38
|
+
>
|
|
39
|
+
remove
|
|
40
|
+
</button>
|
|
41
|
+
<noscript>
|
|
42
|
+
<input
|
|
43
|
+
type="submit"
|
|
44
|
+
data-turbo-frame="${this.getFrameID()}"
|
|
45
|
+
value="${this.options.label_remove || "remove"}"
|
|
46
|
+
form="${fctx.form_id}"
|
|
47
|
+
formnovalidate
|
|
48
|
+
formaction="${this.getActionURL(
|
|
42
49
|
this.table_field.name,
|
|
43
50
|
{
|
|
44
51
|
remove: {
|
|
@@ -46,7 +53,8 @@ class Table extends FormControl {
|
|
|
46
53
|
}
|
|
47
54
|
}
|
|
48
55
|
)}"
|
|
49
|
-
|
|
56
|
+
/>
|
|
57
|
+
</noscript>
|
|
50
58
|
</td>`
|
|
51
59
|
) : ""}
|
|
52
60
|
</tr>`
|
|
@@ -71,14 +79,39 @@ class Table extends FormControl {
|
|
|
71
79
|
${rows?.map((row, index) => make_row(row, index))}
|
|
72
80
|
</tbody>
|
|
73
81
|
</table>
|
|
74
|
-
<template> ${make_row(null,
|
|
75
|
-
|
|
82
|
+
<template> ${make_row(null, TO_REPLACE)} </template>
|
|
83
|
+
|
|
84
|
+
${/* because of https://github.com/ljharb/qs/issues/252 we have to
|
|
85
|
+
put the indexes in the field names */
|
|
86
|
+
this.options.allow_adding ? (
|
|
76
87
|
/* HTML */
|
|
77
88
|
`<button
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
onclick="const template = this.closest('turbo-frame').querySelector('template');
|
|
90
|
+
const tbody = this.closest('turbo-frame').querySelector('tbody');
|
|
91
|
+
const orig_template = template.innerHTML;
|
|
92
|
+
template.innerHTML = orig_template.replaceAll('${TO_REPLACE}', tbody.querySelectorAll('tr').length);
|
|
93
|
+
tbody.appendChild(template.cloneNode(true).content);
|
|
94
|
+
template.innerHTML = orig_template;"
|
|
95
|
+
>
|
|
96
|
+
add
|
|
97
|
+
</button>
|
|
98
|
+
<noscript>
|
|
99
|
+
<input
|
|
100
|
+
type="submit"
|
|
101
|
+
value="${this.options.label_add || "add"}"
|
|
102
|
+
form="${fctx.form_id}"
|
|
103
|
+
formnovalidate
|
|
104
|
+
formaction="${this.getActionURL(
|
|
105
|
+
this.table_field.name,
|
|
106
|
+
{
|
|
107
|
+
insert: {
|
|
108
|
+
index: rows.length,
|
|
109
|
+
value: {}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
)}"
|
|
113
|
+
/>
|
|
114
|
+
</noscript>`
|
|
82
115
|
) : ""}
|
|
83
116
|
</div>
|
|
84
117
|
</turbo-frame>`;
|
|
@@ -100,6 +133,21 @@ class Table extends FormControl {
|
|
|
100
133
|
await next();
|
|
101
134
|
return;
|
|
102
135
|
}
|
|
136
|
+
if (this.options.allow_adding && hasShape(
|
|
137
|
+
{
|
|
138
|
+
insert: predicates.shape({ index: predicates.string })
|
|
139
|
+
},
|
|
140
|
+
action
|
|
141
|
+
)) {
|
|
142
|
+
if (field_name !== this.table_field.name) {
|
|
143
|
+
await next();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!ctx.$body[this.table_field.name]) {
|
|
147
|
+
ctx.$body[this.table_field.name] = {};
|
|
148
|
+
}
|
|
149
|
+
ctx.$body[this.table_field.name][action.insert.index] = await this.options.make_new_row(ctx);
|
|
150
|
+
}
|
|
103
151
|
if (hasShape(
|
|
104
152
|
{
|
|
105
153
|
remove: predicates.shape({ index: predicates.string })
|
package/package.json
CHANGED
|
@@ -28,7 +28,17 @@ export type TableControlOptions<F extends Record<string, FormField>> = {
|
|
|
28
28
|
label_add?: string;
|
|
29
29
|
label: string;
|
|
30
30
|
label_remove?: string;
|
|
31
|
-
} &
|
|
31
|
+
} & (
|
|
32
|
+
| { allow_adding: false }
|
|
33
|
+
| {
|
|
34
|
+
allow_adding: true;
|
|
35
|
+
make_new_row: (
|
|
36
|
+
ctx: Context
|
|
37
|
+
) => Promise<{ [field_name in keyof F]: unknown }>;
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const TO_REPLACE = "____$$$$";
|
|
32
42
|
|
|
33
43
|
export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
34
44
|
role = <const>"input";
|
|
@@ -56,13 +66,13 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
56
66
|
>;
|
|
57
67
|
}
|
|
58
68
|
| null,
|
|
59
|
-
row_index: number
|
|
69
|
+
row_index: number | string
|
|
60
70
|
) => {
|
|
61
71
|
return /* HTML */ tempstream`<tr>
|
|
62
72
|
${Object.entries(this.table_field.columns).map(([key]) => {
|
|
63
73
|
return tempstream`<td>${this.options.render_fields[key](
|
|
64
74
|
fctx,
|
|
65
|
-
`${this.table_field.name}[][${key}]`,
|
|
75
|
+
`${this.table_field.name}[${row_index}][${key}]`,
|
|
66
76
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
67
77
|
(row?.[key] as string) || ""
|
|
68
78
|
)}</td>`;
|
|
@@ -70,22 +80,29 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
70
80
|
${
|
|
71
81
|
this.options.allow_removing
|
|
72
82
|
? /* HTML */ `<td>
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
{
|
|
83
|
-
remove
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
<button
|
|
84
|
+
onclick="this.closest('tr').remove()"
|
|
85
|
+
>
|
|
86
|
+
remove
|
|
87
|
+
</button>
|
|
88
|
+
<noscript>
|
|
89
|
+
<input
|
|
90
|
+
type="submit"
|
|
91
|
+
data-turbo-frame="${this.getFrameID()}"
|
|
92
|
+
value="${this.options
|
|
93
|
+
.label_remove || "remove"}"
|
|
94
|
+
form="${fctx.form_id}"
|
|
95
|
+
formnovalidate
|
|
96
|
+
formaction="${this.getActionURL(
|
|
97
|
+
this.table_field.name,
|
|
98
|
+
{
|
|
99
|
+
remove: {
|
|
100
|
+
index: row_index,
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
)}"
|
|
104
|
+
/>
|
|
105
|
+
</noscript>
|
|
89
106
|
</td>`
|
|
90
107
|
: ""
|
|
91
108
|
}
|
|
@@ -119,14 +136,42 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
119
136
|
${rows?.map((row, index) => make_row(row, index))}
|
|
120
137
|
</tbody>
|
|
121
138
|
</table>
|
|
122
|
-
<template> ${make_row(null,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
139
|
+
<template> ${make_row(null, TO_REPLACE)} </template>
|
|
140
|
+
|
|
141
|
+
${
|
|
142
|
+
/* because of https://github.com/ljharb/qs/issues/252 we have to
|
|
143
|
+
put the indexes in the field names */
|
|
144
|
+
this.options.allow_adding
|
|
145
|
+
? /* HTML */ `<button
|
|
146
|
+
onclick="const template = this.closest('turbo-frame').querySelector('template');
|
|
147
|
+
const tbody = this.closest('turbo-frame').querySelector('tbody');
|
|
148
|
+
const orig_template = template.innerHTML;
|
|
149
|
+
template.innerHTML = orig_template.replaceAll('${TO_REPLACE}', tbody.querySelectorAll('tr').length);
|
|
150
|
+
tbody.appendChild(template.cloneNode(true).content);
|
|
151
|
+
template.innerHTML = orig_template;"
|
|
152
|
+
>
|
|
153
|
+
add
|
|
154
|
+
</button>
|
|
155
|
+
<noscript>
|
|
156
|
+
<input
|
|
157
|
+
type="submit"
|
|
158
|
+
value="${this.options.label_add ||
|
|
159
|
+
"add"}"
|
|
160
|
+
form="${fctx.form_id}"
|
|
161
|
+
formnovalidate
|
|
162
|
+
formaction="${this.getActionURL(
|
|
163
|
+
this.table_field.name,
|
|
164
|
+
{
|
|
165
|
+
insert: {
|
|
166
|
+
index: rows.length,
|
|
167
|
+
value: {},
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
)}"
|
|
171
|
+
/>
|
|
172
|
+
</noscript>`
|
|
173
|
+
: ""
|
|
174
|
+
}
|
|
130
175
|
</div>
|
|
131
176
|
</turbo-frame>`;
|
|
132
177
|
}
|
|
@@ -153,6 +198,25 @@ export class Table<F extends Record<string, FormField>> extends FormControl {
|
|
|
153
198
|
await next();
|
|
154
199
|
return;
|
|
155
200
|
}
|
|
201
|
+
if (
|
|
202
|
+
this.options.allow_adding &&
|
|
203
|
+
hasShape(
|
|
204
|
+
{
|
|
205
|
+
insert: predicates.shape({ index: predicates.string }),
|
|
206
|
+
},
|
|
207
|
+
action
|
|
208
|
+
)
|
|
209
|
+
) {
|
|
210
|
+
if (field_name !== this.table_field.name) {
|
|
211
|
+
await next();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (!ctx.$body[this.table_field.name]) {
|
|
215
|
+
ctx.$body[this.table_field.name] = {};
|
|
216
|
+
}
|
|
217
|
+
(ctx.$body[this.table_field.name] as any)[action.insert.index] =
|
|
218
|
+
await this.options.make_new_row(ctx);
|
|
219
|
+
}
|
|
156
220
|
if (
|
|
157
221
|
hasShape(
|
|
158
222
|
{
|