@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: boolean;
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
- <input
36
- type="submit"
37
- data-turbo-frame="${this.getFrameID()}"
38
- value="${this.options.label_remove || "remove"}"
39
- form="${fctx.form_id}"
40
- formnovalidate
41
- formaction="${this.getActionURL(
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, rows.length)} </template>
75
- ${this.options.allow_adding ? (
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
- onclick="this.closest('turbo-frame').querySelector('tbody').appendChild(this.closest('turbo-frame').querySelector('template').cloneNode(true).content)"
79
- >
80
- add
81
- </button>`
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.15.56",
3
+ "version": "0.15.58-beta",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",
@@ -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
- } & { allow_adding: boolean };
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
- <input
74
- type="submit"
75
- data-turbo-frame="${this.getFrameID()}"
76
- value="${this.options.label_remove ||
77
- "remove"}"
78
- form="${fctx.form_id}"
79
- formnovalidate
80
- formaction="${this.getActionURL(
81
- this.table_field.name,
82
- {
83
- remove: {
84
- index: row_index,
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, rows.length)} </template>
123
- ${this.options.allow_adding
124
- ? /* HTML */ `<button
125
- onclick="this.closest('turbo-frame').querySelector('tbody').appendChild(this.closest('turbo-frame').querySelector('template').cloneNode(true).content)"
126
- >
127
- add
128
- </button>`
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
  {