@sealcode/sealgen 0.18.10 → 0.19.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 (378) hide show
  1. package/.eslintrc.cjs +7 -2
  2. package/.xunit +74 -69
  3. package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
  4. package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
  5. package/@types/builders/colors-builder.d.ts +1 -1
  6. package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
  7. package/@types/builders/fonts-builder.d.ts +1 -1
  8. package/@types/controllers/table-add-button.d.ts +6 -0
  9. package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
  10. package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
  11. package/@types/crud-field-snippets.d.ts +1 -3
  12. package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
  13. package/@types/forms/controls/array.d.ts +1 -3
  14. package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  15. package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
  16. package/@types/forms/controls/autocomplete.d.ts +1 -1
  17. package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
  18. package/@types/forms/controls/checkbox-group.d.ts +3 -3
  19. package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
  20. package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
  21. package/@types/forms/controls/controls.d.ts +2 -2
  22. package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
  23. package/@types/forms/controls/derived-frame.d.ts +0 -2
  24. package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
  25. package/@types/forms/controls/dropdown.d.ts +1 -1
  26. package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
  27. package/@types/forms/controls/file.d.ts +1 -2
  28. package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
  29. package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
  30. package/@types/forms/controls/form-control.d.ts +7 -4
  31. package/@types/forms/controls/image.d.ts +19 -0
  32. package/@types/forms/controls/image.test.d.ts +1 -0
  33. package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
  34. package/@types/forms/controls/multiple-files.d.ts +3 -1
  35. package/@types/forms/controls/multiple-images.d.ts +19 -0
  36. package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
  37. package/@types/forms/controls/number.d.ts +1 -1
  38. package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
  39. package/@types/forms/controls/photo.d.ts +3 -5
  40. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
  41. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
  42. package/@types/forms/controls/simple-input.d.ts +5 -4
  43. package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  44. package/@types/forms/controls/single-reference.d.ts +3 -2
  45. package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
  46. package/@types/forms/controls/table.d.ts +8 -3
  47. package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
  48. package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
  49. package/@types/forms/controls/textarea.d.ts +3 -3
  50. package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
  51. package/@types/forms/fields/boolean.d.ts +6 -1
  52. package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
  53. package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
  54. package/@types/forms/fields/checkboxed-list.d.ts +3 -1
  55. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
  56. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
  57. package/@types/forms/fields/collection-field.d.ts +8 -1
  58. package/@types/forms/fields/color.d.ts +4 -0
  59. package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
  60. package/@types/forms/fields/coordinates.d.ts +14 -0
  61. package/@types/forms/fields/date.d.ts +13 -0
  62. package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
  63. package/@types/forms/fields/datetime.d.ts +14 -0
  64. package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +24 -0
  65. package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
  66. package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
  67. package/@types/forms/fields/email.d.ts +3 -0
  68. package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
  69. package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
  70. package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
  71. package/@types/forms/fields/field.d.ts +37 -5
  72. package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
  73. package/@types/forms/fields/fields.d.ts +23 -8
  74. package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
  75. package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
  76. package/@types/forms/fields/file.d.ts +11 -5
  77. package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
  78. package/@types/forms/fields/float.d.ts +4 -0
  79. package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
  80. package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
  81. package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
  82. package/@types/forms/fields/html.d.ts +6 -0
  83. package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
  84. package/@types/forms/fields/image.d.ts +5 -0
  85. package/@types/forms/fields/int.d.ts +6 -0
  86. package/@types/forms/fields/json.d.ts +13 -0
  87. package/@types/forms/fields/markdown.d.ts +6 -0
  88. package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
  89. package/@types/forms/fields/multiple-files.d.ts +3 -1
  90. package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
  91. package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
  92. package/@types/forms/fields/number.d.ts +3 -1
  93. package/@types/forms/fields/password.d.ts +6 -0
  94. package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
  95. package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
  96. package/@types/forms/fields/pick-from-list.d.ts +4 -3
  97. package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
  98. package/@types/forms/fields/proxy-field.d.ts +3 -1
  99. package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
  100. package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
  101. package/@types/forms/fields/regexp.d.ts +6 -1
  102. package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
  103. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
  104. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
  105. package/@types/forms/fields/simple-form-field.d.ts +23 -3
  106. package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
  107. package/@types/forms/fields/single-reference.d.ts +19 -0
  108. package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
  109. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
  110. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
  111. package/@types/forms/fields/structured-array.d.ts +19 -10
  112. package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
  113. package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
  114. package/@types/forms/fields/table.d.ts +3 -0
  115. package/@types/forms/fields/text.d.ts +6 -0
  116. package/@types/forms/fields/url.d.ts +6 -0
  117. package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
  118. package/@types/forms/form-types.d.ts +2 -0
  119. package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
  120. package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
  121. package/@types/forms/form.d.ts +10 -8
  122. package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
  123. package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
  124. package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
  125. package/@types/forms/form.test.d.ts +2 -2
  126. package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
  127. package/@types/forms/multiform.d.ts +1 -2
  128. package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
  129. package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
  130. package/@types/index.d.ts +2 -2
  131. package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
  132. package/@types/mount.d.ts +0 -1
  133. package/@types/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
  134. package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
  135. package/@types/page/list.d.ts +2 -2
  136. package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
  137. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
  138. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
  139. package/@types/page/mountable-with-fields.d.ts +3 -3
  140. package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
  141. package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
  142. package/@types/page/mountable.d.ts +0 -1
  143. package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  144. package/@types/page/page.d.ts +0 -1
  145. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  146. package/@types/page/props-parser.d.ts +0 -1
  147. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  148. package/@types/page/stateful-page.d.ts +0 -1
  149. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  150. package/@types/templates/shared/shared-crud-form-fields.d.ts +0 -67
  151. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  152. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  153. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  154. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  155. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  156. package/@types/utils/wrap-attributes.d.ts +3 -0
  157. package/README.md +5 -0
  158. package/assets/file-icon.svg +5 -0
  159. package/lib/add-crud.js +80 -89
  160. package/lib/add-list-route.test.js +1 -1
  161. package/lib/add-route.js +0 -7
  162. package/lib/build.js +3 -1
  163. package/lib/cli.js +2 -5
  164. package/lib/controllers/table-add-button.stimulus.js +35 -0
  165. package/lib/forms/controls/array.js +20 -16
  166. package/lib/forms/controls/big-radio-group.js +2 -2
  167. package/lib/forms/controls/checkbox-group.js +7 -7
  168. package/lib/forms/controls/checkboxed-list-input.js +9 -2
  169. package/lib/forms/controls/controls.js +2 -2
  170. package/lib/forms/controls/derived-frame.js +5 -1
  171. package/lib/forms/controls/derived.js +1 -1
  172. package/lib/forms/controls/dropdown.js +4 -1
  173. package/lib/forms/controls/editable-collection-subset.js +2 -2
  174. package/lib/forms/controls/file.js +26 -2
  175. package/lib/forms/controls/file.test.js +2 -2
  176. package/lib/forms/controls/hidden-input.js +4 -1
  177. package/lib/forms/controls/{photo.js → image.js} +6 -7
  178. package/lib/forms/controls/{photo.test.js → image.test.js} +6 -21
  179. package/lib/forms/controls/multiple-files.js +10 -1
  180. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  181. package/lib/forms/controls/simple-input.js +13 -12
  182. package/lib/forms/controls/single-reference.js +4 -0
  183. package/lib/forms/controls/table.js +66 -24
  184. package/lib/forms/controls/textarea.js +4 -2
  185. package/lib/forms/controls/tickable.js +13 -5
  186. package/lib/forms/fields/boolean.js +14 -0
  187. package/lib/forms/fields/checkboxed-list.js +4 -0
  188. package/lib/forms/fields/collection-field.js +9 -0
  189. package/lib/forms/fields/color.js +10 -0
  190. package/lib/forms/fields/coordinates.js +49 -0
  191. package/lib/forms/fields/date.js +34 -0
  192. package/lib/forms/fields/datetime.js +46 -0
  193. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  194. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  195. package/lib/forms/fields/email.js +7 -0
  196. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  197. package/lib/forms/fields/field.js +32 -4
  198. package/lib/forms/fields/field.test.js +5 -5
  199. package/lib/forms/fields/fields.js +23 -8
  200. package/lib/forms/fields/file.js +33 -9
  201. package/lib/forms/fields/file.test.js +4 -16
  202. package/lib/forms/fields/float.js +10 -0
  203. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  204. package/lib/forms/fields/html.js +14 -0
  205. package/lib/forms/fields/image.js +13 -0
  206. package/lib/forms/fields/int.js +23 -0
  207. package/lib/forms/fields/json.js +31 -0
  208. package/lib/forms/fields/markdown.js +14 -0
  209. package/lib/forms/fields/multiple-files.js +4 -0
  210. package/lib/forms/fields/number.js +6 -0
  211. package/lib/forms/fields/password.js +13 -0
  212. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  213. package/lib/forms/fields/pick-from-list.js +6 -2
  214. package/lib/forms/fields/proxy-field.js +3 -0
  215. package/lib/forms/fields/regexp.js +14 -0
  216. package/lib/forms/fields/simple-form-field.js +60 -2
  217. package/lib/forms/fields/single-reference.js +44 -0
  218. package/lib/forms/fields/structured-array.js +63 -12
  219. package/lib/forms/fields/table.js +28 -1
  220. package/lib/forms/fields/text.js +17 -0
  221. package/lib/forms/fields/url.js +17 -0
  222. package/lib/forms/form.js +30 -13
  223. package/lib/forms/form.test.js +3 -4
  224. package/lib/forms/multiform.js +4 -2
  225. package/lib/forms/multiform.test.js +3 -3
  226. package/lib/generate-stimulus.js +1 -0
  227. package/lib/index.js +1 -0
  228. package/lib/make-hidden-inputs.js +1 -1
  229. package/lib/mount.js +11 -0
  230. package/lib/notifier.js +0 -1
  231. package/lib/page/list.js +15 -8
  232. package/lib/page/mountable-with-fields.js +14 -6
  233. package/lib/page/mountable-with-fields.test.js +1 -1
  234. package/lib/templates/form.js +8 -9
  235. package/lib/templates/multiform.js +4 -4
  236. package/lib/templates/page.js +0 -2
  237. package/lib/templates/shared/collection-create-form.js +28 -40
  238. package/lib/templates/shared/collection-edit-form.js +40 -77
  239. package/lib/templates/shared/collection-list.js +12 -20
  240. package/lib/templates/shared/shared-crud-form-fields.js +27 -95
  241. package/lib/test_utils/test-on-real-app.js +3 -3
  242. package/lib/utils/extract-fields-from-collection.js +60 -20
  243. package/lib/utils/make-slug.js +1 -1
  244. package/lib/utils/wrap-attributes.js +20 -0
  245. package/package.json +4 -3
  246. package/src/add-crud.ts +86 -97
  247. package/src/add-list-route.test.ts +1 -1
  248. package/src/add-route.ts +0 -7
  249. package/src/build.ts +3 -1
  250. package/src/cli.ts +3 -5
  251. package/src/controllers/table-add-button.stimulus.ts +35 -0
  252. package/src/forms/controls/array.ts +23 -20
  253. package/src/forms/controls/autocomplete.ts +1 -1
  254. package/src/forms/controls/big-radio-group.ts +2 -2
  255. package/src/forms/controls/checkbox-group.ts +9 -9
  256. package/src/forms/controls/checkboxed-list-input.ts +27 -15
  257. package/src/forms/controls/controls.ts +2 -2
  258. package/src/forms/controls/derived-frame.ts +5 -1
  259. package/src/forms/controls/derived.ts +1 -1
  260. package/src/forms/controls/dropdown.ts +5 -2
  261. package/src/forms/controls/editable-collection-subset.ts +2 -2
  262. package/src/forms/controls/file.test.ts +4 -2
  263. package/src/forms/controls/file.ts +31 -5
  264. package/src/forms/controls/form-control.ts +7 -2
  265. package/src/forms/controls/hidden-input.ts +4 -1
  266. package/src/forms/controls/{photo.test.ts → image.test.ts} +5 -22
  267. package/src/forms/controls/{photo.ts → image.ts} +3 -5
  268. package/src/forms/controls/multiple-files.ts +18 -1
  269. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +1 -1
  270. package/src/forms/controls/number.ts +1 -1
  271. package/src/forms/controls/simple-input.ts +18 -34
  272. package/src/forms/controls/single-reference.ts +10 -2
  273. package/src/forms/controls/table.ts +90 -31
  274. package/src/forms/controls/textarea.ts +6 -4
  275. package/src/forms/controls/tickable.ts +13 -5
  276. package/src/forms/fields/boolean.ts +23 -1
  277. package/src/forms/fields/checkboxed-list.ts +11 -2
  278. package/src/forms/fields/collection-field.ts +16 -1
  279. package/src/forms/fields/color.ts +9 -0
  280. package/src/forms/fields/coordinates.ts +66 -0
  281. package/src/forms/fields/date.ts +50 -0
  282. package/src/forms/fields/datetime.ts +66 -0
  283. package/src/forms/fields/deep-reverse-single-reference-list.ts +136 -0
  284. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  285. package/src/forms/fields/email.ts +9 -0
  286. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  287. package/src/forms/fields/field.test.ts +5 -5
  288. package/src/forms/fields/field.ts +94 -8
  289. package/src/forms/fields/fields.ts +23 -8
  290. package/src/forms/fields/file.test.ts +4 -16
  291. package/src/forms/fields/file.ts +43 -15
  292. package/src/forms/fields/float.ts +9 -0
  293. package/src/forms/fields/get-field-for-sealious.ts +304 -0
  294. package/src/forms/fields/html.ts +15 -0
  295. package/src/forms/fields/image.ts +12 -0
  296. package/src/forms/fields/int.ts +25 -0
  297. package/src/forms/fields/json.ts +48 -0
  298. package/src/forms/fields/markdown.ts +15 -0
  299. package/src/forms/fields/multiple-files.ts +10 -1
  300. package/src/forms/fields/number.ts +8 -1
  301. package/src/forms/fields/password.ts +17 -0
  302. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  303. package/src/forms/fields/pick-from-list.ts +7 -3
  304. package/src/forms/fields/proxy-field.ts +6 -1
  305. package/src/forms/fields/regexp.ts +27 -1
  306. package/src/forms/fields/simple-form-field.ts +95 -7
  307. package/src/forms/fields/single-reference.ts +62 -0
  308. package/src/forms/fields/structured-array.ts +115 -18
  309. package/src/forms/fields/table.ts +32 -1
  310. package/src/forms/fields/text.ts +18 -0
  311. package/src/forms/fields/url.ts +20 -0
  312. package/src/forms/form-types.ts +2 -0
  313. package/src/forms/form.test.ts +3 -4
  314. package/src/forms/form.ts +37 -16
  315. package/src/forms/forms.css +0 -85
  316. package/src/forms/multiform.test.ts +3 -3
  317. package/src/forms/multiform.ts +2 -0
  318. package/src/generate-stimulus.ts +1 -0
  319. package/src/index.ts +2 -1
  320. package/src/make-hidden-inputs.ts +1 -1
  321. package/src/mount.ts +14 -0
  322. package/src/notifier.ts +0 -1
  323. package/src/page/list.ts +15 -8
  324. package/src/page/mountable-with-fields.test.ts +1 -1
  325. package/src/page/mountable-with-fields.ts +18 -9
  326. package/src/register-external.ts +1 -1
  327. package/src/templates/form.ts +8 -9
  328. package/src/templates/multiform.ts +4 -4
  329. package/src/templates/page.ts +0 -2
  330. package/src/templates/shared/collection-create-form.ts +30 -66
  331. package/src/templates/shared/collection-edit-form.ts +41 -102
  332. package/src/templates/shared/collection-list.ts +12 -20
  333. package/src/templates/shared/item-delete.ts +0 -1
  334. package/src/templates/shared/shared-crud-form-fields.ts +37 -171
  335. package/src/test_utils/test-on-real-app.ts +4 -3
  336. package/src/utils/extract-fields-from-collection.ts +76 -25
  337. package/src/utils/make-slug.ts +1 -1
  338. package/src/utils/wrap-attributes.ts +17 -0
  339. package/lib/add-verbose-crud.js +0 -119
  340. package/lib/crud-field-snippets.js +0 -52
  341. package/lib/find-css-includes.js +0 -3
  342. package/lib/forms/controls/reverse-single-reference.js +0 -1
  343. package/lib/forms/fields/enum-multiple.js +0 -47
  344. package/lib/forms/fields/enum-multiple.test.js +0 -27
  345. package/lib/forms/fields/enum.js +0 -41
  346. package/lib/forms/fields/enum.test.js +0 -21
  347. package/lib/forms/fields/reverse-single-reference.js +0 -17
  348. package/lib/templates/shared/handlers/boolean.js +0 -14
  349. package/lib/templates/shared/handlers/date.js +0 -8
  350. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  351. package/lib/templates/shared/handlers/default.js +0 -49
  352. package/lib/templates/shared/handlers/enum.js +0 -19
  353. package/lib/templates/shared/handlers/file.js +0 -23
  354. package/lib/templates/shared/handlers/image.js +0 -32
  355. package/lib/templates/shared/handlers/int.js +0 -11
  356. package/lib/templates/shared/handlers/jdd.js +0 -10
  357. package/lib/templates/shared/handlers/single-reference.js +0 -12
  358. package/lib/templates/shared/handlers/structured-array.js +0 -33
  359. package/src/add-verbose-crud.ts +0 -138
  360. package/src/crud-field-snippets.ts +0 -57
  361. package/src/find-css-includes.ts +0 -3
  362. package/src/forms/controls/reverse-single-reference.ts +0 -50
  363. package/src/forms/fields/enum-multiple.test.ts +0 -31
  364. package/src/forms/fields/enum-multiple.ts +0 -62
  365. package/src/forms/fields/enum.test.ts +0 -25
  366. package/src/forms/fields/enum.ts +0 -56
  367. package/src/forms/fields/reverse-single-reference.ts +0 -20
  368. package/src/templates/shared/handlers/boolean.ts +0 -18
  369. package/src/templates/shared/handlers/date.ts +0 -12
  370. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  371. package/src/templates/shared/handlers/default.ts +0 -64
  372. package/src/templates/shared/handlers/enum.ts +0 -23
  373. package/src/templates/shared/handlers/file.ts +0 -27
  374. package/src/templates/shared/handlers/image.ts +0 -45
  375. package/src/templates/shared/handlers/int.ts +0 -15
  376. package/src/templates/shared/handlers/jdd.ts +0 -14
  377. package/src/templates/shared/handlers/single-reference.ts +0 -16
  378. package/src/templates/shared/handlers/structured-array.ts +0 -42
@@ -70,11 +70,19 @@ export abstract class Tickable<T> extends FormFieldControl {
70
70
  parsed: _parsed,
71
71
  valid,
72
72
  message,
73
- } = await this.field.getValue(fctx.ctx, fctx.data, true);
73
+ } = await this.field.getParsedValue(
74
+ fctx.ctx,
75
+ fctx.data.raw_values,
76
+ true
77
+ );
74
78
  const parsed = _parsed === null ? this.options.default_value : _parsed;
75
79
 
76
- const value = this.getValueAttribute(fctx.ctx, fctx.data, parsed);
77
- const id = this.makeInputID(fctx.ctx, fctx.data, parsed);
80
+ const value = this.getValueAttribute(
81
+ fctx.ctx,
82
+ fctx.data.raw_values,
83
+ parsed
84
+ );
85
+ const id = this.makeInputID(fctx.ctx, fctx.data.raw_values, parsed);
78
86
  const label =
79
87
  this.options.label != undefined
80
88
  ? this.options.label
@@ -86,7 +94,7 @@ export abstract class Tickable<T> extends FormFieldControl {
86
94
 
87
95
  return inputWrapper(
88
96
  this.type,
89
- this.getWrapperClasses(fctx.ctx, fctx.data, parsed),
97
+ this.getWrapperClasses(fctx.ctx, fctx.data.raw_values, parsed),
90
98
 
91
99
  /* HTML */ `
92
100
  <input
@@ -96,7 +104,7 @@ export abstract class Tickable<T> extends FormFieldControl {
96
104
  this.field.name}"
97
105
  ${value ? `value="${attribute(value)}"` : ""}
98
106
  ${fctx.form_id ? `form="${fctx.form_id}"` : ""}
99
- ${this.isChecked(fctx.ctx, fctx.data, parsed)
107
+ ${this.isChecked(fctx.ctx, fctx.data.raw_values, parsed)
100
108
  ? "checked"
101
109
  : ""}
102
110
  ${readonly ? "readonly" : ""}
@@ -1,14 +1,17 @@
1
1
  import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
+ import { Checkbox } from "../controls/checkbox.js";
3
4
  import { FormDataValue } from "../form-types.js";
4
5
  import { FieldParseResult, FormField } from "./field.js";
6
+ import { FormControlContext } from "../controls/form-control.js";
5
7
 
6
8
  const truthy = ["true", "on", "yes", "1"];
7
9
  const falsy = ["false", "off", "no", "0"];
8
10
 
9
11
  export class Boolean<Required extends boolean> extends FormField<
10
12
  Required,
11
- boolean
13
+ boolean,
14
+ Checkbox
12
15
  > {
13
16
  predicate = predicates.boolean;
14
17
  constructor(required: Required, public error_message: string = "") {
@@ -60,4 +63,23 @@ export class Boolean<Required extends boolean> extends FormField<
60
63
  public getEmptyValue(): boolean {
61
64
  return false;
62
65
  }
66
+
67
+ public getControl(): Checkbox {
68
+ return new Checkbox(this, { label: this.name });
69
+ }
70
+
71
+ async getSealiousCreateValue(fctx: FormControlContext): Promise<boolean> {
72
+ const { parsed } = await this.getParsedValue(
73
+ fctx.ctx,
74
+ fctx.data.raw_values
75
+ );
76
+ return !!parsed;
77
+ }
78
+
79
+ async sealiousValueToForm(
80
+ _: Context,
81
+ value: boolean | null
82
+ ): Promise<FormDataValue> {
83
+ return value ? "true" : "false";
84
+ }
63
85
  }
@@ -1,5 +1,6 @@
1
1
  import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
+ import { CheckboxedListInput } from "../controls/checkboxed-list-input.js";
3
4
  import { FormDataValue } from "../form-types.js";
4
5
  import {
5
6
  FieldParseResult,
@@ -13,9 +14,13 @@ export type CheckboxedListItem = {
13
14
  group?: string;
14
15
  };
15
16
 
16
- export class CheckboxedListField<Required extends boolean> extends FormField<
17
+ export class CheckboxedListField<
18
+ Required extends boolean,
19
+ Values extends string
20
+ > extends FormField<
17
21
  Required,
18
- Record<string, "on">
22
+ Record<Values, "on">,
23
+ CheckboxedListInput<Values>
19
24
  > {
20
25
  constructor(
21
26
  public required: Required,
@@ -67,4 +72,8 @@ export class CheckboxedListField<Required extends boolean> extends FormField<
67
72
  public getEmptyValue(): Record<string, "on"> {
68
73
  return {};
69
74
  }
75
+
76
+ getControl(): CheckboxedListInput<Values> {
77
+ return new CheckboxedListInput(this, { label: this.name });
78
+ }
70
79
  }
@@ -1,6 +1,7 @@
1
1
  import { predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
3
  import { Depromisify, ExtractFieldDecoded, Field } from "sealious";
4
+ import { SimpleInput } from "../controls/controls.js";
4
5
  import { FormDataValue } from "../form-types.js";
5
6
 
6
7
  import {
@@ -8,12 +9,13 @@ import {
8
9
  FormField,
9
10
  FormFieldValidationResponse,
10
11
  } from "./field.js";
12
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
11
13
 
12
14
  export class CollectionField<
13
15
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
16
  F extends Field<any>,
15
17
  Required extends boolean
16
- > extends FormField<Required, ExtractFieldDecoded<F> | null> {
18
+ > extends FormField<Required, ExtractFieldDecoded<F> | null, SimpleInput> {
17
19
  constructor(required: Required, public sealiousField: F) {
18
20
  super(required);
19
21
  }
@@ -62,4 +64,17 @@ export class CollectionField<
62
64
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
63
65
  return "" as unknown as ExtractFieldDecoded<F>;
64
66
  }
67
+
68
+ getControl(): SimpleInput {
69
+ return new SimpleInput(this);
70
+ }
71
+
72
+ generateFieldDeclaration(
73
+ field_info: ExtractedFieldInfo,
74
+ vars: { form_field_types: string; sealious_field: string }
75
+ ): string {
76
+ return `new ${vars.form_field_types}.${this.constructor.name}(${String(
77
+ field_info.is_required
78
+ )}, ${vars.sealious_field})`;
79
+ }
65
80
  }
@@ -0,0 +1,9 @@
1
+ import { TextBasedSimpleField } from "./simple-form-field.js";
2
+
3
+ export class Color<
4
+ Required extends boolean
5
+ > extends TextBasedSimpleField<Required> {
6
+ constructor(required: Required) {
7
+ super(required, "color");
8
+ }
9
+ }
@@ -0,0 +1,66 @@
1
+ import { Context } from "koa";
2
+ import { FormControl, FormControlContext } from "../controls/form-control.js";
3
+ import { SimpleInput } from "../controls/simple-input.js";
4
+ import { FormDataValue } from "../form-types.js";
5
+ import { FieldParseResult } from "./field.js";
6
+ import { SimpleFormField } from "./simple-form-field.js";
7
+
8
+ export class Coordinates<
9
+ Required extends boolean,
10
+ DefaultControl extends FormControl = SimpleInput
11
+ > extends SimpleFormField<Required, DefaultControl, [number, number]> {
12
+ async parse(
13
+ _: Context,
14
+ raw_value: FormDataValue
15
+ ): Promise<FieldParseResult<[number, number]>> {
16
+ if (typeof raw_value == "string") {
17
+ return {
18
+ parsed_value: raw_value
19
+ ?.split(",")
20
+ .map((e) => parseFloat(e)) as [number, number],
21
+ parsable: true,
22
+ error: null,
23
+ };
24
+ }
25
+ if (Array.isArray(raw_value)) {
26
+ return {
27
+ parsed_value: raw_value.map((e) => parseFloat(e)) as [
28
+ number,
29
+ number
30
+ ],
31
+ parsable: true,
32
+ error: null,
33
+ };
34
+ }
35
+ return {
36
+ parsed_value: null,
37
+ parsable: false,
38
+ error: "should be an array or string",
39
+ };
40
+ }
41
+
42
+ async getSealiousCreateValue(
43
+ fctx: FormControlContext
44
+ ): Promise<[number, number] | undefined> {
45
+ const { parsed } = await this.getParsedValue(
46
+ fctx.ctx,
47
+ fctx.data.raw_values
48
+ );
49
+ return parsed || undefined;
50
+ }
51
+
52
+ async postSealiousCreate(): Promise<void> {}
53
+
54
+ async postSealiousEdit(): Promise<void> {}
55
+
56
+ getControl(): DefaultControl {
57
+ return new SimpleInput(this, {
58
+ label: this.name,
59
+ type: this.type,
60
+ }) as unknown as DefaultControl;
61
+ }
62
+
63
+ public getEmptyValue(): [number, number] {
64
+ return [0, 0];
65
+ }
66
+ }
@@ -0,0 +1,50 @@
1
+ import { Context } from "koa";
2
+ import { FormControlContext } from "../controls/form-control.js";
3
+ import { SimpleInput, SimpleInputOptions } from "../controls/simple-input.js";
4
+ import { FormDataValue } from "../form-types.js";
5
+ import { FieldParseResult } from "./field.js";
6
+ import { SimpleFormField } from "./simple-form-field.js";
7
+
8
+ export class DateField<Required extends boolean> extends SimpleFormField<
9
+ Required,
10
+ SimpleInput,
11
+ Date
12
+ > {
13
+ constructor(required: Required) {
14
+ super(required, "date");
15
+ }
16
+
17
+ public getEmptyValue(): Date {
18
+ return new Date("1970-01-01 00:00");
19
+ }
20
+
21
+ async parse(
22
+ ctx: Context,
23
+ raw_value: FormDataValue
24
+ ): Promise<FieldParseResult<Date>> {
25
+ return {
26
+ error: null,
27
+ parsable: true,
28
+ parsed_value: new Date(raw_value as string),
29
+ };
30
+ }
31
+
32
+ getControl(): SimpleInput<SimpleInputOptions> {
33
+ return new SimpleInput(this, { label: this.name, type: this.type });
34
+ }
35
+
36
+ async getSealiousCreateValue(
37
+ fctx: FormControlContext
38
+ ): Promise<string | null> {
39
+ const { parsed } = await this.getParsedValue(
40
+ fctx.ctx,
41
+ fctx.data.raw_values
42
+ );
43
+ if (!parsed) {
44
+ return null;
45
+ }
46
+ return `${parsed.getFullYear()}-${(parsed.getMonth() + 1)
47
+ .toString()
48
+ .padStart(2, "0")}-${parsed.getDate().toString().padStart(2, "0")}`;
49
+ }
50
+ }
@@ -0,0 +1,66 @@
1
+ import { Context } from "koa";
2
+ import { SimpleInput } from "../controls/controls.js";
3
+ import { FormControlContext } from "../controls/form-control.js";
4
+ import { FormDataValue } from "../form-types.js";
5
+ import { FieldParseResult } from "./field.js";
6
+ import { SimpleFormField } from "./simple-form-field.js";
7
+
8
+ function pad(n: number) {
9
+ return String(n).padStart(2, "0");
10
+ }
11
+
12
+ export class DateTime<Required extends boolean> extends SimpleFormField<
13
+ Required,
14
+ SimpleInput,
15
+ Date | null
16
+ > {
17
+ constructor(required: Required) {
18
+ super(required, "datetime-local");
19
+ }
20
+
21
+ public getEmptyValue(): Date | null {
22
+ return null;
23
+ }
24
+
25
+ async parse(
26
+ ctx: Context,
27
+ raw_value: FormDataValue
28
+ ): Promise<FieldParseResult<Date | null>> {
29
+ const parsed_value = new Date(raw_value as string);
30
+ return { parsable: true, error: null, parsed_value };
31
+ }
32
+
33
+ async getSealiousCreateValue(
34
+ fctx: FormControlContext
35
+ ): Promise<number | null> {
36
+ const { parsed } = await this.getParsedValue(
37
+ fctx.ctx,
38
+ fctx.data.raw_values
39
+ );
40
+ if (parsed == null) {
41
+ return null;
42
+ }
43
+ return new Date(parsed).getTime();
44
+ }
45
+
46
+ getControl(): SimpleInput {
47
+ return new SimpleInput(this, {
48
+ label: this.name,
49
+ type: this.type,
50
+ });
51
+ }
52
+
53
+ async sealiousValueToForm(
54
+ ctx: Context,
55
+ value: number | null
56
+ ): Promise<FormDataValue> {
57
+ if (value == null) {
58
+ return "";
59
+ }
60
+ const d = new Date(value);
61
+
62
+ return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(
63
+ d.getDate()
64
+ )}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
65
+ }
66
+ }
@@ -0,0 +1,136 @@
1
+ import { Context } from "koa";
2
+ import { CollectionItem, FieldTypes as SealiousFieldTypes } from "sealious";
3
+ import { FormDataValue, FormData } from "../form-types.js";
4
+ import { CheckboxedListField } from "./checkboxed-list.js";
5
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
6
+ import { wrapKeyName } from "../../utils/wrap-attributes.js";
7
+
8
+ export class DeepReverseSingleReferenceList extends CheckboxedListField<
9
+ false,
10
+ string
11
+ > {
12
+ public item_label_getter: (item: CollectionItem<any>) => string = (item) =>
13
+ item.get("name") as string;
14
+
15
+ constructor(
16
+ public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
17
+ ) {
18
+ super(false, async (ctx: Context) => {
19
+ const { items } = await ctx.$app.collections[
20
+ sealious_field.target_collection
21
+ ]
22
+ .list(ctx.$context)
23
+ .fetch();
24
+
25
+ return items.map((s) => ({
26
+ label: this.item_label_getter(s),
27
+ value: s.id,
28
+ }));
29
+ });
30
+ }
31
+
32
+ setItemLabelGetter(getter: (item: CollectionItem<any>) => string) {
33
+ this.item_label_getter = getter;
34
+ }
35
+
36
+ getSealiousCreateValue(): never {
37
+ throw new Error(
38
+ "This field is not set directly through field value, but instead relies on postSealiousCreate and postSealiousEdit"
39
+ );
40
+ }
41
+
42
+ async postSealiousCreate(
43
+ ctx: Context,
44
+ created_item: CollectionItem<any>,
45
+ form_data: FormData
46
+ ) {
47
+ // First, we remove links refering to current item
48
+ const { items: existing_links } = await ctx.$app.collections[
49
+ this.sealious_field.intermediary_collection
50
+ ]
51
+ .list(ctx.$context)
52
+ .filter({
53
+ [this.sealious_field.referencing_field]: created_item.id,
54
+ })
55
+ .fetch();
56
+ const { parsed: value } = await this.getParsedValue(
57
+ ctx,
58
+ form_data.raw_values,
59
+ false
60
+ );
61
+ const should_exist_ids = Object.entries(value || {})
62
+ .filter(([, value]) => value === "on")
63
+ .map(([key]) => key);
64
+ const to_delete = existing_links.filter(
65
+ (link) =>
66
+ !should_exist_ids.includes(
67
+ link.get(
68
+ this.sealious_field.intermediary_field_that_points_there
69
+ ) as string
70
+ )
71
+ );
72
+ const to_create_ids = should_exist_ids.filter(
73
+ (id) =>
74
+ !existing_links
75
+ .map((link) =>
76
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
77
+ link.get(
78
+ this.sealious_field
79
+ .intermediary_field_that_points_there
80
+ )
81
+ )
82
+ .includes(id)
83
+ );
84
+ await Promise.all(
85
+ to_delete.map((item) => {
86
+ return item.remove(ctx.$context);
87
+ })
88
+ );
89
+ // Then, we iterate over all selected values and insert appropriate missing links
90
+ const promises = to_create_ids.map(async (id) => {
91
+ await this.sealious_field
92
+ .getReferencingCollection()
93
+ .create(ctx.$context, {
94
+ [this.sealious_field.referencing_field]: created_item.id,
95
+ [this.sealious_field.intermediary_field_that_points_there]:
96
+ id,
97
+ });
98
+ });
99
+ await Promise.all(promises);
100
+ }
101
+
102
+ async postSealiousEdit(
103
+ ctx: Context,
104
+ edited_item: CollectionItem<any>,
105
+ value: FormData
106
+ ) {
107
+ return this.postSealiousCreate(ctx, edited_item, value);
108
+ }
109
+
110
+ async sealiousValueToForm(
111
+ _ctx: Context,
112
+ value: string[] | null
113
+ ): Promise<FormDataValue> {
114
+ return Object.fromEntries((value || []).map((id) => [id, "on"]));
115
+ }
116
+
117
+ generateFieldDeclaration(
118
+ _field_info: ExtractedFieldInfo,
119
+ vars: { form_field_types: string; sealious_field: string }
120
+ ): string {
121
+ return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
122
+ }
123
+
124
+ generateCreateValueGetter(
125
+ field_info: ExtractedFieldInfo,
126
+ vars: {
127
+ form_field_types: string;
128
+ sealious_field: string;
129
+ form_fields: string;
130
+ }
131
+ ): string {
132
+ return `${wrapKeyName(
133
+ field_info.name
134
+ )}: undefined /* handled below in postSealiousCreate */`;
135
+ }
136
+ }
@@ -0,0 +1,213 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ import {
3
+ FieldTypes as SealiousFieldTypes,
4
+ Field as SealiousField,
5
+ CollectionItem,
6
+ } from "sealious";
7
+ import { Boolean, TextBasedSimpleField } from "./fields.js";
8
+ import { sealiousToFormField } from "./get-field-for-sealious.js";
9
+ import { Table } from "./table.js";
10
+ import { Table as TableControl } from "../controls/table.js";
11
+ import { Context } from "koa";
12
+ import { FormDataValue, FormData } from "../form-types.js";
13
+ import { FormControlContext } from "../controls/form-control.js";
14
+ import { HiddenInput } from "../controls/hidden-input.js";
15
+ import { FormField } from "./field.js";
16
+
17
+ function getReferencingFields(
18
+ sealious_field: SealiousFieldTypes.DeepReverseSingleReference
19
+ ): Record<string, SealiousField<unknown>> {
20
+ const referencing_collection =
21
+ sealious_field.collection.app.collections[
22
+ sealious_field.referencing_collection
23
+ ];
24
+ if (!referencing_collection) {
25
+ throw new Error(
26
+ "Unknown collection: " + sealious_field.referencing_collection
27
+ );
28
+ }
29
+ return referencing_collection.fields;
30
+ }
31
+
32
+ export class DeepReverseSingleReferenceTable extends Table<
33
+ Record<string, FormField>
34
+ > {
35
+ constructor(
36
+ public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
37
+ ) {
38
+ super({
39
+ selected: new Boolean(false),
40
+ [sealious_field.referencing_field]: new TextBasedSimpleField(true),
41
+ [sealious_field.intermediary_field_that_points_there]:
42
+ new TextBasedSimpleField(true),
43
+ ...Object.fromEntries(
44
+ Object.values(getReferencingFields(sealious_field))
45
+ .filter(
46
+ (field) =>
47
+ !(
48
+ field instanceof
49
+ SealiousFieldTypes.SingleReference
50
+ )
51
+ )
52
+ .map((field) => [field.name, sealiousToFormField(field)])
53
+ ),
54
+ });
55
+ }
56
+
57
+ getControl(): TableControl<any> {
58
+ return new TableControl(this, {
59
+ label: this.name,
60
+ allow_adding: false,
61
+ subfield_controls: {
62
+ selected: this.columns.selected.getControl(),
63
+ [this.sealious_field.referencing_field]: new HiddenInput(
64
+ this.columns[this.sealious_field.referencing_field]
65
+ ),
66
+ [this.sealious_field.intermediary_field_that_points_there]:
67
+ new HiddenInput(
68
+ this.columns[
69
+ this.sealious_field.intermediary_field_that_points_there
70
+ ]
71
+ ),
72
+ ...Object.fromEntries(
73
+ Object.values(getReferencingFields(this.sealious_field))
74
+ .filter(
75
+ (field) =>
76
+ !(
77
+ field instanceof
78
+ SealiousFieldTypes.SingleReference
79
+ )
80
+ )
81
+ .map((field) => [
82
+ field.name,
83
+ this.columns[field.name].getControl(),
84
+ ])
85
+ ),
86
+ },
87
+ });
88
+ }
89
+
90
+ getSealiousCreateValue(_fctx: FormControlContext): Promise<unknown> {
91
+ throw new Error("Method not implemented.");
92
+ }
93
+
94
+ async postSealiousCreate(
95
+ ctx: Context,
96
+ created_item: CollectionItem<any>,
97
+ form_data: FormData
98
+ ): Promise<void> {
99
+ // First, we remove links refering to current item
100
+ const { items: to_delete } = await ctx.$app.collections[
101
+ "${toKebabCase(referencing_collection)}"
102
+ ]
103
+ .list(ctx.$context)
104
+ .filter({ "${referencing_field}": created_item.id })
105
+ .fetch();
106
+ await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
107
+
108
+ // Then, we iterate over all selected values and insert appropriate entries for the subcategories relation
109
+
110
+ const referencing_fields = getReferencingFields(this.sealious_field);
111
+
112
+ const { parsed: value } = await this.getParsedValue(
113
+ ctx,
114
+ form_data.raw_values,
115
+ false
116
+ );
117
+ const promises = (value || [])
118
+ .filter((s) => s.selected == true)
119
+ .map(async (link_info) => {
120
+ await ctx.$app.collections[
121
+ "${toKebabCase(referencing_collection)}"
122
+ ].create(ctx.$context, {
123
+ "${referencing_field}": created_item.id,
124
+ "${intermediary_field_that_points_there}": String(
125
+ link_info["${intermediary_field_that_points_there}"]
126
+ ),
127
+ ...Object.fromEntries(
128
+ Object.values(referencing_fields)
129
+ .filter(
130
+ (field) =>
131
+ !(
132
+ field instanceof
133
+ SealiousFieldTypes.SingleReference
134
+ )
135
+ )
136
+ .map((field) => [field.name, link_info[field.name]])
137
+ ),
138
+ });
139
+ });
140
+
141
+ await Promise.all(promises);
142
+ }
143
+
144
+ postSealiousEdit(
145
+ ctx: Context,
146
+ edited_item: CollectionItem<any>,
147
+ form_data: FormData
148
+ ): Promise<void> {
149
+ return this.postSealiousCreate(ctx, edited_item, form_data);
150
+ }
151
+
152
+ async sealiousValueToForm(
153
+ ctx: Context,
154
+ _value: string[],
155
+ item: CollectionItem<any>
156
+ ): Promise<FormDataValue> {
157
+ // convert from an array to array-like object
158
+ const referencing_fields = getReferencingFields(this.sealious_field);
159
+ return Object.fromEntries(
160
+ await Promise.all([
161
+ this.sealious_field.collection.list(ctx.$context).fetch(),
162
+ this.sealious_field
163
+ .getReferencingCollection()
164
+ .list(ctx.$context)
165
+ .fetch(),
166
+ ]).then(([{ items: targets }, { items: links }]) =>
167
+ targets
168
+ .map((target) => {
169
+ return {
170
+ selected: (
171
+ (item.get(
172
+ this.sealious_field.name
173
+ ) as string[]) || []
174
+ ).includes(target.id)
175
+ ? "on"
176
+ : "off",
177
+ [this.sealious_field.referencing_field]: item.id,
178
+ [this.sealious_field
179
+ .intermediary_field_that_points_there]:
180
+ target.id,
181
+ ...Object.fromEntries(
182
+ Object.values(referencing_fields)
183
+ .filter(
184
+ (field) =>
185
+ !(
186
+ field instanceof
187
+ SealiousFieldTypes.SingleReference
188
+ )
189
+ )
190
+ .map((field) => [
191
+ field.name,
192
+ links
193
+ .find(
194
+ (e) =>
195
+ e.get(
196
+ this.sealious_field
197
+ .intermediary_field_that_points_there
198
+ ) == target.id &&
199
+ e.get(
200
+ this.sealious_field
201
+ .referencing_field
202
+ ) == item.id
203
+ )
204
+ ?.get("rank") || 0,
205
+ ])
206
+ ),
207
+ };
208
+ })
209
+ .entries()
210
+ )
211
+ ) as FormDataValue;
212
+ }
213
+ }