@sealcode/sealgen 0.7.15 → 0.8.0

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.
Files changed (104) hide show
  1. package/@types/forms/controls/big-radio-group.d.ts +15 -0
  2. package/@types/forms/controls/checkbox.d.ts +8 -0
  3. package/@types/forms/controls/checkboxed-list-input.d.ts +2 -2
  4. package/@types/forms/controls/controls.d.ts +5 -0
  5. package/@types/forms/controls/derived.d.ts +11 -0
  6. package/@types/forms/controls/dropdown.d.ts +2 -2
  7. package/@types/forms/controls/editable-collection-subset.d.ts +2 -2
  8. package/@types/forms/controls/html.d.ts +6 -3
  9. package/@types/forms/controls/radio.d.ts +16 -0
  10. package/@types/forms/controls/tickable.d.ts +26 -0
  11. package/@types/forms/fields/boolean.d.ts +17 -0
  12. package/@types/forms/fields/checkboxed-list.d.ts +7 -3
  13. package/@types/forms/fields/collection-field.d.ts +6 -2
  14. package/@types/forms/fields/email.d.ts +3 -2
  15. package/@types/forms/fields/enum.d.ts +8 -4
  16. package/@types/forms/fields/field.d.ts +12 -4
  17. package/@types/forms/fields/number.d.ts +3 -2
  18. package/@types/forms/fields/pick-from-list.d.ts +6 -5
  19. package/@types/forms/fields/regexp.d.ts +3 -2
  20. package/@types/forms/fields/simple-form-field.d.ts +3 -1
  21. package/@types/forms/form.d.ts +6 -5
  22. package/@types/forms/multiform.d.ts +2 -2
  23. package/@types/page/list.d.ts +2 -2
  24. package/@types/page/mountable-with-fields.d.ts +4 -2
  25. package/lib/forms/controls/big-radio-group.js +37 -0
  26. package/lib/forms/controls/big-radio-group.js.map +1 -0
  27. package/lib/forms/controls/checkbox.js +18 -0
  28. package/lib/forms/controls/checkbox.js.map +1 -0
  29. package/lib/forms/controls/checkboxed-list-input.js.map +1 -1
  30. package/lib/forms/controls/controls.js +15 -0
  31. package/lib/forms/controls/controls.js.map +1 -1
  32. package/lib/forms/controls/derived.js +70 -0
  33. package/lib/forms/controls/derived.js.map +1 -0
  34. package/lib/forms/controls/dropdown.js.map +1 -1
  35. package/lib/forms/controls/editable-collection-subset.js.map +1 -1
  36. package/lib/forms/controls/html.js +11 -3
  37. package/lib/forms/controls/html.js.map +1 -1
  38. package/lib/forms/controls/radio.js +29 -0
  39. package/lib/forms/controls/radio.js.map +1 -0
  40. package/lib/forms/controls/simple-input.js +3 -1
  41. package/lib/forms/controls/simple-input.js.map +1 -1
  42. package/lib/forms/controls/textarea.js +3 -1
  43. package/lib/forms/controls/textarea.js.map +1 -1
  44. package/lib/forms/controls/tickable.js +72 -0
  45. package/lib/forms/controls/tickable.js.map +1 -0
  46. package/lib/forms/fields/boolean.js +45 -0
  47. package/lib/forms/fields/boolean.js.map +1 -0
  48. package/lib/forms/fields/checkboxed-list.js +2 -1
  49. package/lib/forms/fields/checkboxed-list.js.map +1 -1
  50. package/lib/forms/fields/collection-field.js +2 -0
  51. package/lib/forms/fields/collection-field.js.map +1 -1
  52. package/lib/forms/fields/email.js +3 -1
  53. package/lib/forms/fields/email.js.map +1 -1
  54. package/lib/forms/fields/enum.js +2 -1
  55. package/lib/forms/fields/enum.js.map +1 -1
  56. package/lib/forms/fields/field.js +9 -2
  57. package/lib/forms/fields/field.js.map +1 -1
  58. package/lib/forms/fields/number.js +2 -1
  59. package/lib/forms/fields/number.js.map +1 -1
  60. package/lib/forms/fields/pick-from-list.js +2 -1
  61. package/lib/forms/fields/pick-from-list.js.map +1 -1
  62. package/lib/forms/fields/regexp.js +2 -1
  63. package/lib/forms/fields/regexp.js.map +1 -1
  64. package/lib/forms/fields/simple-form-field.js +5 -0
  65. package/lib/forms/fields/simple-form-field.js.map +1 -1
  66. package/lib/forms/form.js +9 -5
  67. package/lib/forms/form.js.map +1 -1
  68. package/lib/forms/multiform.js.map +1 -1
  69. package/lib/mount.js +3 -2
  70. package/lib/mount.js.map +1 -1
  71. package/lib/page/mountable-with-fields.js +10 -0
  72. package/lib/page/mountable-with-fields.js.map +1 -1
  73. package/lib/templates/form.js +3 -1
  74. package/lib/templates/form.js.map +1 -1
  75. package/lib/tests/manual/multiform.js.map +1 -1
  76. package/package.json +2 -2
  77. package/src/forms/controls/big-radio-group.ts +63 -0
  78. package/src/forms/controls/checkbox.ts +19 -0
  79. package/src/forms/controls/checkboxed-list-input.ts +1 -1
  80. package/src/forms/controls/controls.ts +5 -0
  81. package/src/forms/controls/derived.ts +81 -0
  82. package/src/forms/controls/dropdown.ts +1 -1
  83. package/src/forms/controls/editable-collection-subset.ts +1 -1
  84. package/src/forms/controls/html.ts +21 -3
  85. package/src/forms/controls/radio.ts +43 -0
  86. package/src/forms/controls/simple-input.ts +4 -1
  87. package/src/forms/controls/textarea.ts +3 -1
  88. package/src/forms/controls/tickable.ts +112 -0
  89. package/src/forms/fields/boolean.ts +55 -0
  90. package/src/forms/fields/checkboxed-list.ts +7 -2
  91. package/src/forms/fields/collection-field.ts +8 -4
  92. package/src/forms/fields/email.ts +6 -2
  93. package/src/forms/fields/enum.ts +9 -4
  94. package/src/forms/fields/field.ts +32 -3
  95. package/src/forms/fields/number.ts +6 -3
  96. package/src/forms/fields/pick-from-list.ts +7 -3
  97. package/src/forms/fields/regexp.ts +4 -2
  98. package/src/forms/fields/simple-form-field.ts +11 -1
  99. package/src/forms/form.ts +27 -13
  100. package/src/forms/multiform.ts +4 -2
  101. package/src/mount.ts +3 -2
  102. package/src/page/mountable-with-fields.ts +18 -2
  103. package/src/templates/form.ts +3 -1
  104. package/src/tests/manual/multiform.ts +2 -2
package/lib/mount.js CHANGED
@@ -24,8 +24,9 @@ function mount(router, url, mountable) {
24
24
  });
25
25
  router.use(url, async (ctx, next) => {
26
26
  ctx.set("content-type", "text/html;charset=utf-8");
27
- if (!(await mountable.canAccess(ctx)).canAccess) {
28
- ctx.body = "no access";
27
+ const access_result = await mountable.canAccess(ctx);
28
+ if (!access_result.canAccess) {
29
+ ctx.body = access_result.message || "no access";
29
30
  return;
30
31
  }
31
32
  await next();
package/lib/mount.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":";;;AAEA,uCAAuC;AAGvC,KAAK,UAAU,iBAAiB,CAAC,GAAY,EAAE,IAAc;IAC5D,MAAM,IAAI,EAAE,CAAC;IACb,IAAI,GAAG,CAAC,IAAI,YAAY,OAAO,EAAE;QAChC,mEAAmE;QACnE,GAAG,CAAC,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC;KAC1B;IACD,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,KAAK,CAAC,MAAc,EAAE,GAAW,EAAE,SAAoB;IACtE,MAAM,CAAC,GAAG,CACT,GAAG,EACH,sBAAW,CAAC,cAAc,EAAE,EAC5B,sBAAW,CAAC,SAAS,EAAE,EACvB,iBAAiB,CACjB,CAAC;IACF,SAAS,CAAC,IAAI,EAAE,CAAC;IAEjB,yCAAyC;IACzC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACjC,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC;YACrB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;SAC9B;QACD,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACnC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;QACnD,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,EAAE;YAChD,GAAG,CAAC,IAAI,GAAG,WAAW,CAAC;YACvB,OAAO;SACP;QACD,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC;AA7BD,sBA6BC"}
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":";;;AAEA,uCAAuC;AAGvC,KAAK,UAAU,iBAAiB,CAAC,GAAY,EAAE,IAAc;IAC5D,MAAM,IAAI,EAAE,CAAC;IACb,IAAI,GAAG,CAAC,IAAI,YAAY,OAAO,EAAE;QAChC,mEAAmE;QACnE,GAAG,CAAC,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC;KAC1B;IACD,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,KAAK,CAAC,MAAc,EAAE,GAAW,EAAE,SAAoB;IACtE,MAAM,CAAC,GAAG,CACT,GAAG,EACH,sBAAW,CAAC,cAAc,EAAE,EAC5B,sBAAW,CAAC,SAAS,EAAE,EACvB,iBAAiB,CACjB,CAAC;IACF,SAAS,CAAC,IAAI,EAAE,CAAC;IAEjB,yCAAyC;IACzC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAChD,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YACjC,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC;YACrB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;SAC9B;QACD,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACnC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACrD,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE;YAC7B,GAAG,CAAC,IAAI,GAAG,aAAa,CAAC,OAAO,IAAI,WAAW,CAAC;YAChD,OAAO;SACP;QACD,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC;AA9BD,sBA8BC"}
@@ -58,6 +58,16 @@ class MountableWithFields extends mountable_1.Mountable {
58
58
  ${data.messages.map((message) => `<div class="form-message form-message--${message.type}">${message.text}</div>`)}
59
59
  </div>`;
60
60
  }
61
+ async getParsedValues(ctx) {
62
+ const raw_values = this.extractRawValues(ctx);
63
+ const result = {};
64
+ const promises = Object.entries(this.fields).map(async ([key, field]) => {
65
+ const { parsed } = await field.getValue(ctx, raw_values);
66
+ result[key] = parsed;
67
+ });
68
+ await Promise.all(promises);
69
+ return result;
70
+ }
61
71
  }
62
72
  exports.MountableWithFields = MountableWithFields;
63
73
  //# sourceMappingURL=mountable-with-fields.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mountable-with-fields.js","sourceRoot":"","sources":["../../src/page/mountable-with-fields.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mountable-with-fields.js","sourceRoot":"","sources":["../../src/page/mountable-with-fields.ts"],"names":[],"mappings":"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"}
@@ -16,7 +16,9 @@ const fields = {
16
16
  password: new Fields.SimpleFormField(true),
17
17
  };
18
18
 
19
- export default new (class ${action_name}Form extends Form<typeof fields> {
19
+ export const ${action_name}Shape = Fields.fieldsToShape(fields);
20
+
21
+ export default new (class ${action_name}Form extends Form<typeof fields, void> {
20
22
  defaultSuccessMessage = "Formularz wypełniony poprawnie";
21
23
  fields = fields;
22
24
 
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/templates/form.ts"],"names":[],"mappings":";;;AAAA,sDAAuD;AAEhD,KAAK,UAAU,YAAY,CACjC,WAAmB,EACnB,eAAuB;IAEvB,MAAM,GAAG,GAAG,6BAAe,CAAC,eAAe,CAAC,CAAC;IAC7C,OAAO;;oBAEY,GAAG,CAAC,eAAe,CAAC;yBACf,GAAG,CAAC,kCAAkC,CAAC;;6BAEnC,WAAW;;;;;;;4BAOZ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAkCjB,WAAW;;;CAGhC,CAAC;AACF,CAAC;AAvDD,oCAuDC"}
1
+ {"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/templates/form.ts"],"names":[],"mappings":";;;AAAA,sDAAuD;AAEhD,KAAK,UAAU,YAAY,CACjC,WAAmB,EACnB,eAAuB;IAEvB,MAAM,GAAG,GAAG,6BAAe,CAAC,eAAe,CAAC,CAAC;IAC7C,OAAO;;oBAEY,GAAG,CAAC,eAAe,CAAC;yBACf,GAAG,CAAC,kCAAkC,CAAC;;6BAEnC,WAAW;;;;;;;eAOzB,WAAW;;4BAEE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAkCjB,WAAW;;;CAGhC,CAAC;AACF,CAAC;AAzDD,oCAyDC"}
@@ -1 +1 @@
1
- {"version":3,"file":"multiform.js","sourceRoot":"","sources":["../../../src/tests/manual/multiform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"multiform.js","sourceRoot":"","sources":["../../../src/tests/manual/multiform.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sealcode/sealgen",
3
- "version": "0.7.15",
3
+ "version": "0.8.0",
4
4
  "description": "Module to automate adding routes and collections to a sealious application",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {
@@ -38,7 +38,7 @@
38
38
  "types": "./@types/index.d.ts",
39
39
  "dependencies": {
40
40
  "@koa/router": "^10.1.1",
41
- "@sealcode/ts-predicates": "^0.4.0",
41
+ "@sealcode/ts-predicates": "^0.4.1",
42
42
  "esbuild": "^0.15.5",
43
43
  "esbuild-sass-plugin": "^2.3.1",
44
44
  "koa": "^2.13.0",
@@ -0,0 +1,63 @@
1
+ import { Context } from "koa";
2
+ import { FlatTemplatable, tempstream } from "tempstream";
3
+ import { FormField } from "../fields/field";
4
+ import { FormDataValue } from "../form";
5
+ import { FormFieldControl } from "./form-field-control";
6
+
7
+ export class BigRadioGroup extends FormFieldControl {
8
+ constructor(
9
+ public field: FormField,
10
+ public options: Record<
11
+ string,
12
+ {
13
+ description:
14
+ | FlatTemplatable
15
+ | ((
16
+ ctx: Context,
17
+ data: Record<string, FormDataValue>,
18
+ messages: [],
19
+ feld_name_prefix: string,
20
+ form_id: string
21
+ ) => FlatTemplatable);
22
+ }
23
+ >
24
+ ) {
25
+ super([field]);
26
+ }
27
+
28
+ async render(
29
+ ctx: Context,
30
+ data: Record<string, FormDataValue>,
31
+ messages: [],
32
+ field_name_prefix: string,
33
+ form_id: string
34
+ ): Promise<FlatTemplatable> {
35
+ const { raw: current_value } = await this.field.getValue(ctx, data);
36
+ return tempstream/* HTML */ `<div class="bigradios">
37
+ ${Object.entries(this.options).map(([key, { description }]) => {
38
+ const id = `${this.field.name}-radio-${key}`;
39
+ return tempstream/* HTML */ `<input
40
+ type="radio"
41
+ name="${this.field.name}"
42
+ value="${key}"
43
+ id="${id}"
44
+ style="display: none"
45
+ ${this.field.required ? "required" : ""}
46
+ ${key == current_value ? "checked" : ""}
47
+ />
48
+ <div class="bigradio">
49
+ ${typeof description == "function"
50
+ ? description(
51
+ ctx,
52
+ data,
53
+ messages,
54
+ field_name_prefix,
55
+ form_id
56
+ )
57
+ : description}
58
+ <label class="bigradio__cta" for="${id}">Wybierz</label>
59
+ </div>`;
60
+ })}
61
+ </div>`;
62
+ }
63
+ }
@@ -0,0 +1,19 @@
1
+ import { Context } from "koa";
2
+ import { FormDataValue } from "../form";
3
+ import { Tickable } from "./tickable";
4
+
5
+ export class Checkbox extends Tickable<boolean> {
6
+ type = <const>"checkbox";
7
+
8
+ isChecked(
9
+ _ctx: Context,
10
+ _data: Record<string, FormDataValue>,
11
+ value: boolean
12
+ ): boolean {
13
+ return value;
14
+ }
15
+
16
+ getValueAttribute(): string {
17
+ return "";
18
+ }
19
+ }
@@ -8,7 +8,7 @@ import { FormFieldControl } from "./controls";
8
8
 
9
9
  export class CheckboxedListInput extends FormFieldControl {
10
10
  constructor(
11
- public field: ChekboxedListField,
11
+ public field: ChekboxedListField<boolean>,
12
12
  public options: { label: string } = { label: field.name }
13
13
  ) {
14
14
  super([field]);
@@ -11,3 +11,8 @@ export { HTML } from "./html";
11
11
  export { HiddenInput } from "./hidden-input";
12
12
  export { Textarea } from "./textarea";
13
13
  export { FieldGroup } from "./field-group";
14
+ export * from "./derived";
15
+ export * from "./tickable";
16
+ export * from "./checkbox";
17
+ export * from "./radio";
18
+ export * from "./big-radio-group";
@@ -0,0 +1,81 @@
1
+ import { randomUUID } from "crypto";
2
+ import { FlatTemplatable, tempstream } from "tempstream";
3
+ import { FormField } from "../fields/field";
4
+ import { FormControl } from "./form-control";
5
+
6
+ export class Derived<
7
+ Consts extends Record<string, unknown> | undefined
8
+ > extends FormControl {
9
+ role = <const>"decoration";
10
+
11
+ constructor(
12
+ public fields: FormField[],
13
+ public _render: (
14
+ values: Record<string, string>,
15
+ consts: Consts
16
+ ) => string,
17
+ public consts: Consts
18
+ ) {
19
+ super();
20
+ }
21
+
22
+ render(): FlatTemplatable {
23
+ const id = "A" + randomUUID(); // the A makes it always a valid id, as it cannot start with a number
24
+ return tempstream/* HTML */ `<div>
25
+ <script>
26
+ (function () {
27
+ const consts = {
28
+ ${Object.entries(this.consts || {})
29
+ .map(([key, value]) => {
30
+ return `"${key}": ${
31
+ typeof value === "object"
32
+ ? JSON.stringify(value)
33
+ : (value as string).toString()
34
+ }`;
35
+ })
36
+ .join(",")},
37
+ };
38
+ const form = document.currentScript.closest("form");
39
+ const render = ${this._render.toString()};
40
+ function getValues() {
41
+ return Object.fromEntries(
42
+ ${JSON.stringify(
43
+ this.fields.map((field) => field.name)
44
+ )}.map((field_name) => {
45
+ let input = form.querySelector(
46
+ \`input[name="\${field_name}"]\`
47
+ );
48
+ if (input.type === "radio") {
49
+ input = form.querySelector(
50
+ \`input[name="\${field_name}"]:checked\`
51
+ );
52
+ }
53
+ return [field_name, input.value];
54
+ })
55
+ );
56
+ }
57
+ function setupWatcher(field_name) {
58
+ form.querySelectorAll(
59
+ \`input[name="\${field_name}"]\`
60
+ ).forEach((input) => {
61
+ input.onchange = () => {
62
+ document.querySelector("#${id}").innerHTML =
63
+ render(getValues(), consts);
64
+ };
65
+ });
66
+ }
67
+ ${JSON.stringify(
68
+ this.fields.map((field) => field.name)
69
+ )}.forEach(setupWatcher);
70
+ setTimeout(
71
+ () =>
72
+ (document.querySelector("#${id}").innerHTML =
73
+ render(getValues(), consts)),
74
+ 0
75
+ );
76
+ })();
77
+ </script>
78
+ <div id="${id}">${this._render({}, this.consts)}</div>
79
+ </div>`;
80
+ }
81
+ }
@@ -7,7 +7,7 @@ import { FormFieldControl } from "./controls";
7
7
 
8
8
  export class Dropdown extends FormFieldControl {
9
9
  constructor(
10
- public field: PickFromListField,
10
+ public field: PickFromListField<boolean>,
11
11
  public options: {
12
12
  label: string;
13
13
  autosubmit?: boolean;
@@ -14,7 +14,7 @@ import { FormFieldControl } from "./controls";
14
14
  */
15
15
  export class EditableCollectionSubset extends FormFieldControl {
16
16
  constructor(
17
- public field: PickFromListField,
17
+ public field: PickFromListField<false>,
18
18
  public actionname: string,
19
19
  public listLabel?: string,
20
20
  public selectLabel?: string
@@ -2,17 +2,35 @@ import { Context } from "koa";
2
2
  import { FlatTemplatable } from "tempstream";
3
3
  import { FormControl } from "./controls";
4
4
 
5
+ type Renderer = ((ctx: Context) => FlatTemplatable) | FlatTemplatable;
6
+
5
7
  export class HTML extends FormControl {
6
- role = <const>"decoration";
8
+ role = (<const>"decoration") as "decoration" | "submit";
9
+ public renderer: Renderer;
7
10
 
8
- constructor(public renderer: ((ctx: Context) => FlatTemplatable) | string) {
11
+ constructor(role: "decoration" | "submit", renderer: Renderer);
12
+ constructor(renderer: Renderer);
13
+ constructor(
14
+ role_or_renderer: "decoration" | "submit" | Renderer,
15
+ renderer_or_undefined?:
16
+ | ((ctx: Context) => FlatTemplatable)
17
+ | FlatTemplatable
18
+ ) {
9
19
  super();
20
+ if (arguments.length == 2) {
21
+ this.role = role_or_renderer as "decoration" | "submit";
22
+ this.renderer = renderer_or_undefined as Renderer;
23
+ } else {
24
+ this.renderer = role_or_renderer;
25
+ }
10
26
  }
11
27
 
12
28
  async render(ctx: Context): Promise<FlatTemplatable> {
13
29
  if (typeof this.renderer === "string") {
14
30
  return this.renderer;
15
31
  }
16
- return this.renderer(ctx);
32
+ return typeof this.renderer == "function"
33
+ ? this.renderer(ctx)
34
+ : this.renderer;
17
35
  }
18
36
  }
@@ -0,0 +1,43 @@
1
+ import { Context } from "koa";
2
+ import { FormField } from "../fields/field";
3
+ import { FormDataValue } from "../form";
4
+ import { Tickable } from "./tickable";
5
+
6
+ export class Radio extends Tickable<string> {
7
+ type = <const>"radio";
8
+
9
+ constructor(
10
+ public field: FormField<boolean, string>,
11
+ public value: string,
12
+ options: { label?: string }
13
+ ) {
14
+ super(field, options);
15
+ }
16
+
17
+ makeInputID(): string {
18
+ return this.field.name + "-" + this.value.replaceAll(/\W/g, "-");
19
+ }
20
+
21
+ getValueAttribute(): string {
22
+ return this.value;
23
+ }
24
+
25
+ getWrapperClasses(
26
+ ctx: Context,
27
+ data: Record<string, FormDataValue>,
28
+ value: string
29
+ ): string[] {
30
+ return [
31
+ ...super.getWrapperClasses(ctx, data, value),
32
+ this.value.replaceAll(/\W/g, "-"),
33
+ ];
34
+ }
35
+
36
+ isChecked(
37
+ _ctx: Context,
38
+ _data: Record<string, FormDataValue>,
39
+ value: string
40
+ ): boolean {
41
+ return this.value === value;
42
+ }
43
+ }
@@ -45,7 +45,10 @@ export class SimpleInput extends FormFieldControl {
45
45
  form_id: string
46
46
  ): Promise<FlatTemplatable> {
47
47
  const id = this.options.id || this.field.name;
48
- const label = this.options.label || this.field.name;
48
+ const label =
49
+ this.options.label != undefined
50
+ ? this.options.label
51
+ : this.field.name;
49
52
  const type = this.options.type || "text";
50
53
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
51
54
  const { parsed, raw, valid, message } = await this.field.getValue(
@@ -23,7 +23,9 @@ export class Textarea extends FormFieldControl {
23
23
  return inputWrapper(
24
24
  [name, getRequiredClass(required)],
25
25
  /* HTML */ ` <label for="${name}"
26
- >${this.options.label || name}</label
26
+ >${this.options.label != undefined
27
+ ? this.options.label
28
+ : name}</label
27
29
  >
28
30
  <textarea
29
31
  name="${name}"
@@ -0,0 +1,112 @@
1
+ import { Context } from "koa";
2
+ import { FlatTemplatable } from "tempstream";
3
+ import { attribute } from "../../sanitize";
4
+ import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper";
5
+ import { FormField } from "../fields/field";
6
+ import { FormDataValue } from "../form";
7
+ import { FormFieldControl } from "./controls";
8
+
9
+ export abstract class Tickable<T extends unknown> extends FormFieldControl {
10
+ constructor(
11
+ public field: FormField<boolean, T>,
12
+ public options: {
13
+ id?: string;
14
+ label?: string;
15
+ hide_errors?: boolean;
16
+ readonly?: boolean;
17
+ } = {}
18
+ ) {
19
+ super([field]);
20
+ }
21
+
22
+ public type: "checkbox" | "radio";
23
+
24
+ abstract getValueAttribute(
25
+ ctx: Context,
26
+ data: Record<string, FormDataValue>,
27
+ value: T
28
+ ): string;
29
+
30
+ abstract isChecked(
31
+ ctx: Context,
32
+ data: Record<string, FormDataValue>,
33
+ value: T
34
+ ): boolean;
35
+
36
+ makeInputID(): string {
37
+ return this.options.id || this.field.name;
38
+ }
39
+
40
+ getWrapperClasses(
41
+ ctx: Context,
42
+ data: Record<string, FormDataValue>,
43
+ value: T
44
+ ): string[] {
45
+ return [
46
+ this.makeInputID(),
47
+ this.type,
48
+ this.field.name.replaceAll(/\W/g, "-"),
49
+ getRequiredClass(this.field.required),
50
+ ...(this.isChecked(ctx, data, value) ? ["checked"] : []),
51
+ ];
52
+ }
53
+
54
+ async render<Fields extends Record<string, FormField>>(
55
+ ctx: Context,
56
+ data: Record<string, FormDataValue>,
57
+ _: unknown[],
58
+ field_prefix: string,
59
+ form_id: string
60
+ ): Promise<FlatTemplatable> {
61
+ const id = this.makeInputID();
62
+ const label =
63
+ this.options.label != undefined
64
+ ? this.options.label
65
+ : this.field.name;
66
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
67
+ const { parsed, valid, message } = await this.field.getValue(ctx, data);
68
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
69
+ const readonly = this.options.readonly || false;
70
+ const required = this.field.required;
71
+
72
+ return inputWrapper(
73
+ this.getWrapperClasses(ctx, data, parsed),
74
+
75
+ /* HTML */ `
76
+ <input
77
+ id="${id}"
78
+ type="${this.type}"
79
+ name="${field_prefix}${this.field.name}"
80
+ value="${attribute(
81
+ this.getValueAttribute(ctx, data, parsed)
82
+ )}"
83
+ ${form_id ? `form="${form_id}"` : ""}
84
+ ${this.isChecked(ctx, data, parsed) ? "checked" : ""}
85
+ ${readonly ? "readonly" : ""}
86
+ ${required ? "required" : ""}
87
+ onchange="this.closest('form').querySelectorAll('.form-input__wrapper--${this
88
+ .field
89
+ .name}').forEach(e=>e.setAttribute('data-checked','false'));
90
+ this.closest('.form-input__wrapper').setAttribute('data-checked',this.checked);"
91
+ />
92
+
93
+ <label for="${id}">${label}</label>
94
+ <script>
95
+ (function () {
96
+ let wrapper = document.currentScript.closest(
97
+ ".form-input__wrapper"
98
+ );
99
+ wrapper.setAttribute(
100
+ "data-checked",
101
+ wrapper.querySelector("input").checked.toString()
102
+ );
103
+ })();
104
+ </script>
105
+
106
+ ${~valid && !this.options.hide_errors
107
+ ? `<div class="input__error">${message}</div>`
108
+ : ""}
109
+ `
110
+ );
111
+ }
112
+ }
@@ -0,0 +1,55 @@
1
+ import { is, predicates } from "@sealcode/ts-predicates";
2
+ import { Context } from "koa";
3
+ import { FormDataValue } from "../form";
4
+ import { FieldParseResult, FormField } from "./field";
5
+
6
+ const truthy = ["true", "on", "yes", "1"];
7
+ const falsy = ["false", "off", "no", "0"];
8
+
9
+ export class Boolean<Required extends boolean> extends FormField<
10
+ Required,
11
+ boolean
12
+ > {
13
+ predicate = predicates.boolean;
14
+ constructor(required: Required, public error_message: string = "") {
15
+ super(required);
16
+ }
17
+
18
+ public async isValueValid(
19
+ _: Context,
20
+ value: boolean
21
+ ): Promise<{ valid: boolean; message: string }> {
22
+ if (this.required && !value) {
23
+ return { valid: false, message: this.error_message };
24
+ }
25
+ return { valid: true, message: "" };
26
+ }
27
+
28
+ async parse(
29
+ _: Context,
30
+ value: FormDataValue
31
+ ): Promise<FieldParseResult<boolean>> {
32
+ if (is(value, predicates.boolean)) {
33
+ return { parsable: true, parsed_value: value, error: null };
34
+ } else if (
35
+ is(value, predicates.string) &&
36
+ [...truthy, ...falsy].includes(value)
37
+ ) {
38
+ return {
39
+ parsable: true,
40
+ parsed_value: truthy.includes(value),
41
+ error: null,
42
+ };
43
+ } else {
44
+ return {
45
+ parsable: false,
46
+ parsed_value: null,
47
+ error: "Please enter a boolean",
48
+ };
49
+ }
50
+ }
51
+
52
+ public getEmptyValue(): boolean {
53
+ return false;
54
+ }
55
+ }
@@ -7,9 +7,12 @@ import {
7
7
  FormFieldValidationResponse,
8
8
  } from "./field";
9
9
 
10
- export class ChekboxedListField extends FormField<Record<string, "on">> {
10
+ export class ChekboxedListField<Required extends boolean> extends FormField<
11
+ Required,
12
+ Record<string, "on">
13
+ > {
11
14
  constructor(
12
- public required: boolean = false,
15
+ public required: Required,
13
16
  public generateOptions: (
14
17
  ctx: Context
15
18
  ) => Promise<Record<string, string> | { [i: string]: string }>,
@@ -19,6 +22,8 @@ export class ChekboxedListField extends FormField<Record<string, "on">> {
19
22
  super(required);
20
23
  }
21
24
 
25
+ predicate = predicates.array(predicates.string); // TODO: this is probably wrong
26
+
22
27
  public async isValueValid(
23
28
  _: Context,
24
29
  value: unknown
@@ -1,3 +1,4 @@
1
+ import { predicates } from "@sealcode/ts-predicates";
1
2
  import { Context } from "koa";
2
3
  import { Depromisify, Field, FieldOutput } from "sealious";
3
4
  import { FormDataValue } from "../form";
@@ -8,13 +9,16 @@ import {
8
9
  FormFieldValidationResponse,
9
10
  } from "./field";
10
11
 
11
- export class CollectionField<F extends Field> extends FormField<
12
- FieldOutput<F>
13
- > {
14
- constructor(required: boolean, public sealiousField: F) {
12
+ export class CollectionField<
13
+ F extends Field,
14
+ Required extends boolean
15
+ > extends FormField<Required, FieldOutput<F>> {
16
+ constructor(required: Required, public sealiousField: F) {
15
17
  super(required);
16
18
  }
17
19
 
20
+ predicate = predicates.unknown;
21
+
18
22
  async parse(
19
23
  ctx: Context,
20
24
  raw_value: FormDataValue
@@ -1,8 +1,12 @@
1
+ import { predicates } from "@sealcode/ts-predicates";
1
2
  import { RegExpField } from "./regexp";
2
3
 
3
- export class EmailField extends RegExpField {
4
+ export class EmailField<
5
+ Required extends boolean
6
+ > extends RegExpField<Required> {
7
+ predicate = predicates.string;
4
8
  constructor(
5
- required = false,
9
+ required: Required,
6
10
  public error_message = "Please enter a proper email address",
7
11
  public default_value = ""
8
12
  ) {