@yuuvis/client-framework 0.6.5

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 (392) hide show
  1. package/README.md +62 -0
  2. package/actions/README.md +3 -0
  3. package/actions/index.d.ts +6 -0
  4. package/actions/lib/actions/copy-action/copy-action.d.ts +17 -0
  5. package/actions/lib/actions/cut-action/cut-action.d.ts +17 -0
  6. package/actions/lib/actions/delete-action/delete/delete.component.d.ts +22 -0
  7. package/actions/lib/actions/delete-action/delete-action.d.ts +17 -0
  8. package/actions/lib/actions/download-action/download-action.d.ts +17 -0
  9. package/actions/lib/actions.icon.d.ts +7 -0
  10. package/actions/lib/actions.interface.d.ts +86 -0
  11. package/actions/lib/actions.module.d.ts +8 -0
  12. package/actions/lib/actions.service.d.ts +38 -0
  13. package/actions/lib/components/contextmenu/contextmenu.component.d.ts +11 -0
  14. package/app-bar/README.md +3 -0
  15. package/app-bar/index.d.ts +1 -0
  16. package/app-bar/lib/app-bar.component.d.ts +47 -0
  17. package/clipboard/README.md +3 -0
  18. package/clipboard/index.d.ts +1 -0
  19. package/clipboard/lib/clipboard.component.d.ts +16 -0
  20. package/common/README.md +3 -0
  21. package/common/index.d.ts +5 -0
  22. package/common/lib/components/focus-indicator/focus-indicator.component.d.ts +7 -0
  23. package/common/lib/components/token-input/token-input.component.d.ts +55 -0
  24. package/common/lib/components/token-input/token-input.interface.d.ts +8 -0
  25. package/common/lib/directives/busy-overlay.directive.d.ts +25 -0
  26. package/common/lib/directives/click-double.directive.d.ts +17 -0
  27. package/common/lib/directives/container-size.directive.d.ts +30 -0
  28. package/common/lib/directives/drag-select.directive.d.ts +21 -0
  29. package/common/lib/directives/file-drop-zone/file-drop-zone.directive.d.ts +18 -0
  30. package/common/lib/directives/file-drop-zone/file-drop-zone.interface.d.ts +5 -0
  31. package/common/lib/directives/focus-within.directive.d.ts +36 -0
  32. package/common/lib/directives/index.d.ts +8 -0
  33. package/common/lib/directives/light-dismiss.directive.d.ts +19 -0
  34. package/common/lib/directives/longpress.directive.d.ts +13 -0
  35. package/common/lib/directives/noop-value-accessor.directive.d.ts +10 -0
  36. package/esm2022/actions/index.mjs +7 -0
  37. package/esm2022/actions/lib/actions/copy-action/copy-action.mjs +31 -0
  38. package/esm2022/actions/lib/actions/cut-action/cut-action.mjs +30 -0
  39. package/esm2022/actions/lib/actions/delete-action/delete/delete.component.mjs +67 -0
  40. package/esm2022/actions/lib/actions/delete-action/delete-action.mjs +44 -0
  41. package/esm2022/actions/lib/actions/download-action/download-action.mjs +33 -0
  42. package/esm2022/actions/lib/actions.icon.mjs +8 -0
  43. package/esm2022/actions/lib/actions.interface.mjs +19 -0
  44. package/esm2022/actions/lib/actions.module.mjs +16 -0
  45. package/esm2022/actions/lib/actions.service.mjs +89 -0
  46. package/esm2022/actions/lib/components/contextmenu/contextmenu.component.mjs +27 -0
  47. package/esm2022/actions/yuuvis-client-framework-actions.mjs +5 -0
  48. package/esm2022/app-bar/index.mjs +2 -0
  49. package/esm2022/app-bar/lib/app-bar.component.mjs +89 -0
  50. package/esm2022/app-bar/yuuvis-client-framework-app-bar.mjs +5 -0
  51. package/esm2022/clipboard/index.mjs +2 -0
  52. package/esm2022/clipboard/lib/clipboard.component.mjs +48 -0
  53. package/esm2022/clipboard/yuuvis-client-framework-clipboard.mjs +5 -0
  54. package/esm2022/common/index.mjs +6 -0
  55. package/esm2022/common/lib/components/focus-indicator/focus-indicator.component.mjs +41 -0
  56. package/esm2022/common/lib/components/token-input/token-input.component.mjs +324 -0
  57. package/esm2022/common/lib/components/token-input/token-input.interface.mjs +2 -0
  58. package/esm2022/common/lib/directives/busy-overlay.directive.mjs +88 -0
  59. package/esm2022/common/lib/directives/click-double.directive.mjs +61 -0
  60. package/esm2022/common/lib/directives/container-size.directive.mjs +56 -0
  61. package/esm2022/common/lib/directives/drag-select.directive.mjs +114 -0
  62. package/esm2022/common/lib/directives/file-drop-zone/file-drop-zone.directive.mjs +153 -0
  63. package/esm2022/common/lib/directives/file-drop-zone/file-drop-zone.interface.mjs +2 -0
  64. package/esm2022/common/lib/directives/focus-within.directive.mjs +81 -0
  65. package/esm2022/common/lib/directives/index.mjs +9 -0
  66. package/esm2022/common/lib/directives/light-dismiss.directive.mjs +44 -0
  67. package/esm2022/common/lib/directives/longpress.directive.mjs +36 -0
  68. package/esm2022/common/lib/directives/noop-value-accessor.directive.mjs +42 -0
  69. package/esm2022/common/yuuvis-client-framework-common.mjs +5 -0
  70. package/esm2022/forms/index.mjs +19 -0
  71. package/esm2022/forms/lib/elements/catalog/catalog.component.mjs +118 -0
  72. package/esm2022/forms/lib/elements/datetime/datetime.component.mjs +82 -0
  73. package/esm2022/forms/lib/elements/datetime-range/datetime-range.component.mjs +166 -0
  74. package/esm2022/forms/lib/elements/number/number.component.mjs +195 -0
  75. package/esm2022/forms/lib/elements/number-range/number-range.component.mjs +176 -0
  76. package/esm2022/forms/lib/elements/organization/organization.component.mjs +268 -0
  77. package/esm2022/forms/lib/elements/string/string.component.mjs +254 -0
  78. package/esm2022/forms/lib/form-input/form-input.component.mjs +88 -0
  79. package/esm2022/forms/lib/forms.module.mjs +58 -0
  80. package/esm2022/forms/yuuvis-client-framework-forms.mjs +5 -0
  81. package/esm2022/icons/index.mjs +4 -0
  82. package/esm2022/icons/lib/icon.service.mjs +59 -0
  83. package/esm2022/icons/lib/icons.mjs +31 -0
  84. package/esm2022/icons/lib/object-type-icon/object-type-icon.component.mjs +29 -0
  85. package/esm2022/icons/yuuvis-client-framework-icons.mjs +5 -0
  86. package/esm2022/index.mjs +2 -0
  87. package/esm2022/lib/yuuvis-client-framework.module.mjs +15 -0
  88. package/esm2022/list/index.mjs +3 -0
  89. package/esm2022/list/lib/list-item.directive.mjs +72 -0
  90. package/esm2022/list/lib/list.component.mjs +133 -0
  91. package/esm2022/list/yuuvis-client-framework-list.mjs +5 -0
  92. package/esm2022/metadata-form/index.mjs +4 -0
  93. package/esm2022/metadata-form/lib/metadata-default-templates/metadata-default-templates.component.mjs +31 -0
  94. package/esm2022/metadata-form/lib/metadata-form-element-registry.service.mjs +99 -0
  95. package/esm2022/metadata-form/lib/metadata-form-field/metadata-form-field.component.mjs +126 -0
  96. package/esm2022/metadata-form/lib/object-metadata-element-template.directive.mjs +52 -0
  97. package/esm2022/metadata-form/yuuvis-client-framework-metadata-form.mjs +5 -0
  98. package/esm2022/object-details/index.mjs +7 -0
  99. package/esm2022/object-details/lib/object-audit/object-audit.component.mjs +195 -0
  100. package/esm2022/object-details/lib/object-details-shell/object-details-shell.component.mjs +127 -0
  101. package/esm2022/object-details/lib/object-details.component.mjs +61 -0
  102. package/esm2022/object-details/lib/object-metadata/form-section-group.pipe.mjs +17 -0
  103. package/esm2022/object-details/lib/object-metadata/object-metadata.component.mjs +201 -0
  104. package/esm2022/object-details/lib/object-metadata/object-metadata.interface.mjs +2 -0
  105. package/esm2022/object-details/yuuvis-client-framework-object-details.mjs +5 -0
  106. package/esm2022/object-flavor/index.mjs +6 -0
  107. package/esm2022/object-flavor/lib/abstract-apply-create-flavor/abstract-apply-create-flavor.component.mjs +25 -0
  108. package/esm2022/object-flavor/lib/abstract-apply-object-flavor/abstract-apply-object-flavor.component.mjs +21 -0
  109. package/esm2022/object-flavor/lib/flavor-chip/flavor-chip.component.mjs +35 -0
  110. package/esm2022/object-flavor/lib/object-flavor/object-flavor.component.mjs +93 -0
  111. package/esm2022/object-flavor/lib/object-flavor-picker/object-flavor-picker.component.mjs +43 -0
  112. package/esm2022/object-flavor/yuuvis-client-framework-object-flavor.mjs +5 -0
  113. package/esm2022/object-form/index.mjs +5 -0
  114. package/esm2022/object-form/lib/form-scripting.api.interface.mjs +2 -0
  115. package/esm2022/object-form/lib/form-scripting.service.mjs +160 -0
  116. package/esm2022/object-form/lib/object-form-element/object-form-element.component.mjs +87 -0
  117. package/esm2022/object-form/lib/object-form-extension.interface.mjs +36 -0
  118. package/esm2022/object-form/lib/object-form-group/object-form-group.component.mjs +85 -0
  119. package/esm2022/object-form/lib/object-form-script/form-scripting-element-extension/form-scripting-element-extension.component.mjs +23 -0
  120. package/esm2022/object-form/lib/object-form-script/object-form-script.service.mjs +115 -0
  121. package/esm2022/object-form/lib/object-form-script/object-form-scripting-scope.mjs +251 -0
  122. package/esm2022/object-form/lib/object-form-translate.service.mjs +73 -0
  123. package/esm2022/object-form/lib/object-form.component.mjs +627 -0
  124. package/esm2022/object-form/lib/object-form.interface.mjs +9 -0
  125. package/esm2022/object-form/lib/object-form.model.mjs +20 -0
  126. package/esm2022/object-form/lib/object-form.service.mjs +127 -0
  127. package/esm2022/object-form/lib/object-form.utils.mjs +55 -0
  128. package/esm2022/object-form/lib/object-form.validation.mjs +48 -0
  129. package/esm2022/object-form/yuuvis-client-framework-object-form.mjs +5 -0
  130. package/esm2022/object-preview/index.mjs +3 -0
  131. package/esm2022/object-preview/lib/components/index.mjs +3 -0
  132. package/esm2022/object-preview/lib/components/object-email-preview/object-email-preview.component.mjs +45 -0
  133. package/esm2022/object-preview/lib/components/object-preview/object-preview.component.mjs +78 -0
  134. package/esm2022/object-preview/lib/services/object-preview.service.mjs +92 -0
  135. package/esm2022/object-preview/yuuvis-client-framework-object-preview.mjs +5 -0
  136. package/esm2022/object-summary/index.mjs +5 -0
  137. package/esm2022/object-summary/lib/multi-object-summary/multi-object-summary.component.mjs +33 -0
  138. package/esm2022/object-summary/lib/object-summary/object-summary.component.mjs +273 -0
  139. package/esm2022/object-summary/lib/object-summary-data/object-summary-data.component.mjs +80 -0
  140. package/esm2022/object-summary/lib/object-summary.module.mjs +15 -0
  141. package/esm2022/object-summary/yuuvis-client-framework-object-summary.mjs +5 -0
  142. package/esm2022/pagination/index.mjs +3 -0
  143. package/esm2022/pagination/lib/pagination.component.mjs +48 -0
  144. package/esm2022/pagination/lib/pagination.interface.mjs +2 -0
  145. package/esm2022/pagination/yuuvis-client-framework-pagination.mjs +5 -0
  146. package/esm2022/panel/index.mjs +2 -0
  147. package/esm2022/panel/lib/panel.component.mjs +20 -0
  148. package/esm2022/panel/yuuvis-client-framework-panel.mjs +5 -0
  149. package/esm2022/renderer/index.mjs +11 -0
  150. package/esm2022/renderer/lib/property-renderer/abstract.renderer.mjs +29 -0
  151. package/esm2022/renderer/lib/property-renderer/datetime.renderer.mjs +13 -0
  152. package/esm2022/renderer/lib/property-renderer/decimal.renderer.component.mjs +12 -0
  153. package/esm2022/renderer/lib/property-renderer/filesize.renderer.component.mjs +28 -0
  154. package/esm2022/renderer/lib/property-renderer/icon.renderer.component.mjs +23 -0
  155. package/esm2022/renderer/lib/property-renderer/integer.renderer.component.mjs +12 -0
  156. package/esm2022/renderer/lib/property-renderer/organization.renderer.mjs +19 -0
  157. package/esm2022/renderer/lib/property-renderer/string.renderer.component.mjs +12 -0
  158. package/esm2022/renderer/lib/property-renderer/unknown.renderer.mjs +12 -0
  159. package/esm2022/renderer/lib/renderer.directive.mjs +51 -0
  160. package/esm2022/renderer/lib/services/renderer/renderer.interface.mjs +2 -0
  161. package/esm2022/renderer/lib/services/renderer/renderer.service.mjs +84 -0
  162. package/esm2022/renderer/yuuvis-client-framework-renderer.mjs +5 -0
  163. package/esm2022/sequence-list/index.mjs +6 -0
  164. package/esm2022/sequence-list/lib/due-date-picker/due-date-picker.component.mjs +99 -0
  165. package/esm2022/sequence-list/lib/sequence-list-template-manage/sequence-list-template-manage.component.mjs +183 -0
  166. package/esm2022/sequence-list/lib/sequence-list-templates/sequence-list-templates.component.mjs +114 -0
  167. package/esm2022/sequence-list/lib/sequence-list.component.mjs +146 -0
  168. package/esm2022/sequence-list/lib/sequence-list.interface.mjs +2 -0
  169. package/esm2022/sequence-list/yuuvis-client-framework-sequence-list.mjs +5 -0
  170. package/esm2022/simple-search/index.mjs +3 -0
  171. package/esm2022/simple-search/lib/simple-search/simple-search.component.mjs +111 -0
  172. package/esm2022/simple-search/lib/simple-search/simple-search.interface.mjs +2 -0
  173. package/esm2022/simple-search/yuuvis-client-framework-simple-search.mjs +5 -0
  174. package/esm2022/tile-list/index.mjs +11 -0
  175. package/esm2022/tile-list/lib/tile/tile.component.mjs +53 -0
  176. package/esm2022/tile-list/lib/tile-config/action-select/action-select.component.mjs +22 -0
  177. package/esm2022/tile-list/lib/tile-config/icon-select/icon-select.component.mjs +33 -0
  178. package/esm2022/tile-list/lib/tile-config/property-select/property-select.component.mjs +91 -0
  179. package/esm2022/tile-list/lib/tile-config/tile-config-tile/tile-config-tile.component.mjs +66 -0
  180. package/esm2022/tile-list/lib/tile-config/tile-config-trigger/tile-config-trigger.component.mjs +46 -0
  181. package/esm2022/tile-list/lib/tile-config/tile-config.component.mjs +156 -0
  182. package/esm2022/tile-list/lib/tile-extension/directive/tile-extension.directive.mjs +37 -0
  183. package/esm2022/tile-list/lib/tile-extension/extensions/email.extension.mjs +42 -0
  184. package/esm2022/tile-list/lib/tile-extension/tile-extension.service.mjs +35 -0
  185. package/esm2022/tile-list/lib/tile-list/tile-list.component.mjs +510 -0
  186. package/esm2022/tile-list/lib/tile-list/tile-list.interface.mjs +2 -0
  187. package/esm2022/tile-list/yuuvis-client-framework-tile-list.mjs +5 -0
  188. package/esm2022/token-search/index.mjs +3 -0
  189. package/esm2022/token-search/token-search.component.mjs +78 -0
  190. package/esm2022/token-search/token-search.interface.mjs +2 -0
  191. package/esm2022/token-search/yuuvis-client-framework-token-search.mjs +5 -0
  192. package/esm2022/tree/index.mjs +3 -0
  193. package/esm2022/tree/lib/tree-node/tree-node.component.mjs +65 -0
  194. package/esm2022/tree/lib/tree.component.mjs +148 -0
  195. package/esm2022/tree/lib/tree.interface.mjs +2 -0
  196. package/esm2022/tree/lib/tree.service.mjs +95 -0
  197. package/esm2022/tree/yuuvis-client-framework-tree.mjs +5 -0
  198. package/esm2022/upload-progress/index.mjs +2 -0
  199. package/esm2022/upload-progress/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.mjs +49 -0
  200. package/esm2022/upload-progress/lib/upload-progress/upload-progress.component.mjs +37 -0
  201. package/esm2022/upload-progress/yuuvis-client-framework-upload-progress.mjs +5 -0
  202. package/esm2022/user-avatar/index.mjs +3 -0
  203. package/esm2022/user-avatar/lib/user-avatar.component.mjs +69 -0
  204. package/esm2022/user-avatar/lib/user-avatar.module.mjs +24 -0
  205. package/esm2022/user-avatar/yuuvis-client-framework-user-avatar.mjs +5 -0
  206. package/esm2022/yuuvis-client-framework.mjs +5 -0
  207. package/fesm2022/yuuvis-client-framework-actions.mjs +333 -0
  208. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -0
  209. package/fesm2022/yuuvis-client-framework-app-bar.mjs +96 -0
  210. package/fesm2022/yuuvis-client-framework-app-bar.mjs.map +1 -0
  211. package/fesm2022/yuuvis-client-framework-clipboard.mjs +55 -0
  212. package/fesm2022/yuuvis-client-framework-clipboard.mjs.map +1 -0
  213. package/fesm2022/yuuvis-client-framework-common.mjs +1020 -0
  214. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -0
  215. package/fesm2022/yuuvis-client-framework-forms.mjs +1355 -0
  216. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -0
  217. package/fesm2022/yuuvis-client-framework-icons.mjs +123 -0
  218. package/fesm2022/yuuvis-client-framework-icons.mjs.map +1 -0
  219. package/fesm2022/yuuvis-client-framework-list.mjs +209 -0
  220. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -0
  221. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +302 -0
  222. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -0
  223. package/fesm2022/yuuvis-client-framework-object-details.mjs +583 -0
  224. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -0
  225. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +200 -0
  226. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -0
  227. package/fesm2022/yuuvis-client-framework-object-form.mjs +1664 -0
  228. package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -0
  229. package/fesm2022/yuuvis-client-framework-object-preview.mjs +213 -0
  230. package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -0
  231. package/fesm2022/yuuvis-client-framework-object-summary.mjs +397 -0
  232. package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -0
  233. package/fesm2022/yuuvis-client-framework-pagination.mjs +55 -0
  234. package/fesm2022/yuuvis-client-framework-pagination.mjs.map +1 -0
  235. package/fesm2022/yuuvis-client-framework-panel.mjs +27 -0
  236. package/fesm2022/yuuvis-client-framework-panel.mjs.map +1 -0
  237. package/fesm2022/yuuvis-client-framework-renderer.mjs +262 -0
  238. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -0
  239. package/fesm2022/yuuvis-client-framework-sequence-list.mjs +519 -0
  240. package/fesm2022/yuuvis-client-framework-sequence-list.mjs.map +1 -0
  241. package/fesm2022/yuuvis-client-framework-simple-search.mjs +118 -0
  242. package/fesm2022/yuuvis-client-framework-simple-search.mjs.map +1 -0
  243. package/fesm2022/yuuvis-client-framework-tile-list.mjs +1036 -0
  244. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -0
  245. package/fesm2022/yuuvis-client-framework-token-search.mjs +85 -0
  246. package/fesm2022/yuuvis-client-framework-token-search.mjs.map +1 -0
  247. package/fesm2022/yuuvis-client-framework-tree.mjs +307 -0
  248. package/fesm2022/yuuvis-client-framework-tree.mjs.map +1 -0
  249. package/fesm2022/yuuvis-client-framework-upload-progress.mjs +84 -0
  250. package/fesm2022/yuuvis-client-framework-upload-progress.mjs.map +1 -0
  251. package/fesm2022/yuuvis-client-framework-user-avatar.mjs +96 -0
  252. package/fesm2022/yuuvis-client-framework-user-avatar.mjs.map +1 -0
  253. package/fesm2022/yuuvis-client-framework.mjs +22 -0
  254. package/fesm2022/yuuvis-client-framework.mjs.map +1 -0
  255. package/forms/README.md +3 -0
  256. package/forms/index.d.ts +9 -0
  257. package/forms/lib/elements/catalog/catalog.component.d.ts +68 -0
  258. package/forms/lib/elements/datetime/datetime.component.d.ts +32 -0
  259. package/forms/lib/elements/datetime-range/datetime-range.component.d.ts +51 -0
  260. package/forms/lib/elements/number/number.component.d.ts +77 -0
  261. package/forms/lib/elements/number-range/number-range.component.d.ts +66 -0
  262. package/forms/lib/elements/organization/organization.component.d.ts +93 -0
  263. package/forms/lib/elements/string/string.component.d.ts +104 -0
  264. package/forms/lib/form-input/form-input.component.d.ts +48 -0
  265. package/forms/lib/forms.module.d.ts +16 -0
  266. package/icons/README.md +5 -0
  267. package/icons/index.d.ts +3 -0
  268. package/icons/lib/icon.service.d.ts +38 -0
  269. package/icons/lib/icons.d.ts +1 -0
  270. package/icons/lib/object-type-icon/object-type-icon.component.d.ts +11 -0
  271. package/index.d.ts +1 -0
  272. package/lib/yuuvis-client-framework.module.d.ts +7 -0
  273. package/list/README.md +3 -0
  274. package/list/index.d.ts +2 -0
  275. package/list/lib/list-item.directive.d.ts +15 -0
  276. package/list/lib/list.component.d.ts +36 -0
  277. package/metadata-form/README.md +21 -0
  278. package/metadata-form/index.d.ts +3 -0
  279. package/metadata-form/lib/metadata-default-templates/metadata-default-templates.component.d.ts +5 -0
  280. package/metadata-form/lib/metadata-form-element-registry.service.d.ts +47 -0
  281. package/metadata-form/lib/metadata-form-field/metadata-form-field.component.d.ts +31 -0
  282. package/metadata-form/lib/object-metadata-element-template.directive.d.ts +27 -0
  283. package/object-details/README.md +28 -0
  284. package/object-details/index.d.ts +6 -0
  285. package/object-details/lib/object-audit/object-audit.component.d.ts +59 -0
  286. package/object-details/lib/object-details-shell/object-details-shell.component.d.ts +51 -0
  287. package/object-details/lib/object-details.component.d.ts +36 -0
  288. package/object-details/lib/object-metadata/form-section-group.pipe.d.ts +8 -0
  289. package/object-details/lib/object-metadata/object-metadata.component.d.ts +48 -0
  290. package/object-details/lib/object-metadata/object-metadata.interface.d.ts +26 -0
  291. package/object-flavor/README.md +3 -0
  292. package/object-flavor/index.d.ts +5 -0
  293. package/object-flavor/lib/abstract-apply-create-flavor/abstract-apply-create-flavor.component.d.ts +12 -0
  294. package/object-flavor/lib/abstract-apply-object-flavor/abstract-apply-object-flavor.component.d.ts +12 -0
  295. package/object-flavor/lib/flavor-chip/flavor-chip.component.d.ts +17 -0
  296. package/object-flavor/lib/object-flavor/object-flavor.component.d.ts +26 -0
  297. package/object-flavor/lib/object-flavor-picker/object-flavor-picker.component.d.ts +10 -0
  298. package/object-form/README.md +3 -0
  299. package/object-form/index.d.ts +4 -0
  300. package/object-form/lib/form-scripting.api.interface.d.ts +131 -0
  301. package/object-form/lib/form-scripting.service.d.ts +30 -0
  302. package/object-form/lib/object-form-element/object-form-element.component.d.ts +22 -0
  303. package/object-form/lib/object-form-extension.interface.d.ts +22 -0
  304. package/object-form/lib/object-form-group/object-form-group.component.d.ts +22 -0
  305. package/object-form/lib/object-form-script/form-scripting-element-extension/form-scripting-element-extension.component.d.ts +10 -0
  306. package/object-form/lib/object-form-script/object-form-script.service.d.ts +45 -0
  307. package/object-form/lib/object-form-script/object-form-scripting-scope.d.ts +50 -0
  308. package/object-form/lib/object-form-translate.service.d.ts +15 -0
  309. package/object-form/lib/object-form.component.d.ts +60 -0
  310. package/object-form/lib/object-form.interface.d.ts +113 -0
  311. package/object-form/lib/object-form.model.d.ts +18 -0
  312. package/object-form/lib/object-form.service.d.ts +39 -0
  313. package/object-form/lib/object-form.utils.d.ts +20 -0
  314. package/object-form/lib/object-form.validation.d.ts +21 -0
  315. package/object-preview/README.md +3 -0
  316. package/object-preview/index.d.ts +2 -0
  317. package/object-preview/lib/components/index.d.ts +2 -0
  318. package/object-preview/lib/components/object-email-preview/object-email-preview.component.d.ts +16 -0
  319. package/object-preview/lib/components/object-preview/object-preview.component.d.ts +13 -0
  320. package/object-preview/lib/services/object-preview.service.d.ts +37 -0
  321. package/object-summary/README.md +3 -0
  322. package/object-summary/index.d.ts +4 -0
  323. package/object-summary/lib/multi-object-summary/multi-object-summary.component.d.ts +7 -0
  324. package/object-summary/lib/object-summary/object-summary.component.d.ts +73 -0
  325. package/object-summary/lib/object-summary-data/object-summary-data.component.d.ts +11 -0
  326. package/object-summary/lib/object-summary.module.d.ts +7 -0
  327. package/package.json +173 -0
  328. package/pagination/README.md +3 -0
  329. package/pagination/index.d.ts +2 -0
  330. package/pagination/lib/pagination.component.d.ts +18 -0
  331. package/pagination/lib/pagination.interface.d.ts +5 -0
  332. package/panel/README.md +3 -0
  333. package/panel/index.d.ts +1 -0
  334. package/panel/lib/panel.component.d.ts +12 -0
  335. package/renderer/README.md +5 -0
  336. package/renderer/index.d.ts +10 -0
  337. package/renderer/lib/property-renderer/abstract.renderer.d.ts +14 -0
  338. package/renderer/lib/property-renderer/datetime.renderer.d.ts +6 -0
  339. package/renderer/lib/property-renderer/decimal.renderer.component.d.ts +6 -0
  340. package/renderer/lib/property-renderer/filesize.renderer.component.d.ts +7 -0
  341. package/renderer/lib/property-renderer/icon.renderer.component.d.ts +6 -0
  342. package/renderer/lib/property-renderer/integer.renderer.component.d.ts +6 -0
  343. package/renderer/lib/property-renderer/organization.renderer.d.ts +7 -0
  344. package/renderer/lib/property-renderer/string.renderer.component.d.ts +6 -0
  345. package/renderer/lib/property-renderer/unknown.renderer.d.ts +6 -0
  346. package/renderer/lib/renderer.directive.d.ts +17 -0
  347. package/renderer/lib/services/renderer/renderer.interface.d.ts +8 -0
  348. package/renderer/lib/services/renderer/renderer.service.d.ts +35 -0
  349. package/sequence-list/README.md +3 -0
  350. package/sequence-list/index.d.ts +5 -0
  351. package/sequence-list/lib/due-date-picker/due-date-picker.component.d.ts +28 -0
  352. package/sequence-list/lib/sequence-list-template-manage/sequence-list-template-manage.component.d.ts +52 -0
  353. package/sequence-list/lib/sequence-list-templates/sequence-list-templates.component.d.ts +36 -0
  354. package/sequence-list/lib/sequence-list.component.d.ts +43 -0
  355. package/sequence-list/lib/sequence-list.interface.d.ts +16 -0
  356. package/simple-search/README.md +3 -0
  357. package/simple-search/index.d.ts +2 -0
  358. package/simple-search/lib/simple-search/simple-search.component.d.ts +55 -0
  359. package/simple-search/lib/simple-search/simple-search.interface.d.ts +4 -0
  360. package/styles/client-framework.scss +27 -0
  361. package/tile-list/README.md +3 -0
  362. package/tile-list/index.d.ts +10 -0
  363. package/tile-list/lib/tile/tile.component.d.ts +22 -0
  364. package/tile-list/lib/tile-config/action-select/action-select.component.d.ts +13 -0
  365. package/tile-list/lib/tile-config/icon-select/icon-select.component.d.ts +11 -0
  366. package/tile-list/lib/tile-config/property-select/property-select.component.d.ts +25 -0
  367. package/tile-list/lib/tile-config/tile-config-tile/tile-config-tile.component.d.ts +20 -0
  368. package/tile-list/lib/tile-config/tile-config-trigger/tile-config-trigger.component.d.ts +17 -0
  369. package/tile-list/lib/tile-config/tile-config.component.d.ts +47 -0
  370. package/tile-list/lib/tile-extension/directive/tile-extension.directive.d.ts +11 -0
  371. package/tile-list/lib/tile-extension/extensions/email.extension.d.ts +10 -0
  372. package/tile-list/lib/tile-extension/tile-extension.service.d.ts +16 -0
  373. package/tile-list/lib/tile-list/tile-list.component.d.ts +116 -0
  374. package/tile-list/lib/tile-list/tile-list.interface.d.ts +18 -0
  375. package/token-search/README.md +3 -0
  376. package/token-search/index.d.ts +2 -0
  377. package/token-search/token-search.component.d.ts +22 -0
  378. package/token-search/token-search.interface.d.ts +4 -0
  379. package/tree/README.md +3 -0
  380. package/tree/index.d.ts +2 -0
  381. package/tree/lib/tree-node/tree-node.component.d.ts +21 -0
  382. package/tree/lib/tree.component.d.ts +53 -0
  383. package/tree/lib/tree.interface.d.ts +11 -0
  384. package/tree/lib/tree.service.d.ts +35 -0
  385. package/upload-progress/README.md +3 -0
  386. package/upload-progress/index.d.ts +1 -0
  387. package/upload-progress/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.d.ts +17 -0
  388. package/upload-progress/lib/upload-progress/upload-progress.component.d.ts +16 -0
  389. package/user-avatar/README.md +3 -0
  390. package/user-avatar/index.d.ts +2 -0
  391. package/user-avatar/lib/user-avatar.component.d.ts +44 -0
  392. package/user-avatar/lib/user-avatar.module.d.ts +8 -0
@@ -0,0 +1,1664 @@
1
+ import * as i1$1 from '@angular/common';
2
+ import { CommonModule, NgComponentOutlet } from '@angular/common';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, NgZone, signal, Injectable, input, Component, DestroyRef, computed, effect, untracked, ViewEncapsulation, Input, ElementRef, ChangeDetectorRef, output } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import * as i2 from '@angular/forms';
7
+ import { UntypedFormGroup, FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';
8
+ import * as i1$2 from '@yuuvis/client-core';
9
+ import { EventService, UserService, DmsService, SystemService, SearchService, BackendService, TranslateService, NotificationService, AppCacheService, YuvEventType, ApiBase, Operator, DmsObject, Utils, Situation, ContentStreamField, Classification, KeysPipe } from '@yuuvis/client-core';
10
+ import { firstValueFrom, map, forkJoin, debounceTime, of } from 'rxjs';
11
+ import { Router } from '@angular/router';
12
+ import * as i2$1 from '@yuuvis/components/tabs';
13
+ import { YvcTabsModule } from '@yuuvis/components/tabs';
14
+ import { MetadataFormFieldComponent } from '@yuuvis/client-framework/metadata-form';
15
+ import * as i1 from '@yuuvis/components/icon';
16
+ import { YvcIconModule } from '@yuuvis/components/icon';
17
+ import { HttpHeaders } from '@angular/common/http';
18
+ import { map as map$1 } from 'rxjs/operators';
19
+
20
+ class FormScriptingApiService {
21
+ constructor() {
22
+ this.#ngZone = inject(NgZone);
23
+ this.#router = inject(Router);
24
+ this.#eventService = inject(EventService);
25
+ this.#userService = inject(UserService);
26
+ this.#dmsService = inject(DmsService);
27
+ this.#systemService = inject(SystemService);
28
+ this.#searchService = inject(SearchService);
29
+ this.#backend = inject(BackendService);
30
+ this.#translate = inject(TranslateService);
31
+ this.#notifications = inject(NotificationService);
32
+ this.#appCache = inject(AppCacheService);
33
+ this.#activeFormComponents = new Map();
34
+ this.elementExtensions = signal({});
35
+ }
36
+ #ngZone;
37
+ #router;
38
+ #eventService;
39
+ #userService;
40
+ #dmsService;
41
+ #systemService;
42
+ #searchService;
43
+ #backend;
44
+ #translate;
45
+ #notifications;
46
+ #appCache;
47
+ static { this.EVENT_MODEL_CHANGED = 'yuv.event.object-form.model.changed'; }
48
+ #activeFormComponents;
49
+ get api() {
50
+ return this.getApi();
51
+ }
52
+ registerActiveForm(component) {
53
+ const id = component.formOptions()?.formModel?.name || component?.id;
54
+ return id && this.#activeFormComponents.set(id, component);
55
+ }
56
+ unregisterActiveForm(component) {
57
+ const id = component.formOptions()?.formModel?.name || component?.id;
58
+ return id && this.#activeFormComponents.delete(id);
59
+ }
60
+ getApi() {
61
+ const formId = this.formId;
62
+ return {
63
+ elementExtensions: {
64
+ register: (extensions) => {
65
+ extensions.forEach((ext) => {
66
+ if (ext.id)
67
+ this.elementExtensions.set({ ...this.elementExtensions(), [ext.id]: ext });
68
+ });
69
+ }
70
+ },
71
+ events: {
72
+ yuuvisEventType: YuvEventType,
73
+ on: (type) => this.#ngZone.run(() => this.#eventService.on(type)),
74
+ trigger: (type, data) => this.#ngZone.run(() => this.#eventService.trigger(type, data))
75
+ },
76
+ session: {
77
+ getUser: () => this.getCurrentUser(),
78
+ user: {
79
+ get: () => this.getCurrentUser(),
80
+ hasRole: (role) => this.getCurrentUser().authorities?.includes(role) || false
81
+ }
82
+ },
83
+ http: {
84
+ get: (uri, base, options) => this.get(uri, base, options),
85
+ post: (uri, data, base, options) => this.post(uri, data, base, options),
86
+ del: (uri, base, options) => this.del(uri, base, options),
87
+ put: (uri, data, base, options) => this.put(uri, data, base, options)
88
+ },
89
+ form: {
90
+ activeForms: this.#activeFormComponents,
91
+ getValue: (formControlName) => Array.from(this.#activeFormComponents.values()).reduce((prev, cur) => ({ ...prev, ...(cur.formData || {}) }), {})[formControlName],
92
+ setValue: (formControlName, newValue) => this.api.form.modelChange(formControlName, { name: 'value', newValue }),
93
+ modelChange: (formControlName, change) => this.#ngZone.run(() => this.#eventService.trigger(FormScriptingApiService.EVENT_MODEL_CHANGED, {
94
+ formId,
95
+ formControlName,
96
+ change
97
+ }))
98
+ },
99
+ storage: {
100
+ getItem: (key) => firstValueFrom(this.#appCache.getItem(key)),
101
+ setItem: (key, value) => firstValueFrom(this.#appCache.setItem(key, value))
102
+ },
103
+ notifier: {
104
+ success: (text, title) => this.#notifications.success(title, text),
105
+ error: (text, title) => this.#notifications.error(title, text),
106
+ info: (text, title) => this.#notifications.info(title, text),
107
+ warning: (text, title) => this.#notifications.warning(title, text)
108
+ },
109
+ util: {
110
+ translate: (key, data) => this.#translate.instant(key, data)
111
+ }
112
+ };
113
+ }
114
+ get(uri, base, options) {
115
+ return firstValueFrom(this.#backend.get(uri, base || ApiBase.none, options || { observe: 'response' }).pipe(map((res) => {
116
+ return options ? res : { status: res.status, data: res.body };
117
+ })));
118
+ }
119
+ put(uri, data, base, options) {
120
+ return firstValueFrom(this.#backend.put(uri, data, base || ApiBase.none, options));
121
+ }
122
+ post(uri, data, base, options) {
123
+ return firstValueFrom(this.#backend.post(uri, data, base || ApiBase.none, options));
124
+ }
125
+ del(uri, base, options) {
126
+ return firstValueFrom(this.#backend.delete(uri, base || ApiBase.none, options));
127
+ }
128
+ getCurrentUser() {
129
+ return this.#userService.getCurrentUser();
130
+ }
131
+ getDmsObject(id, version) {
132
+ return firstValueFrom(this.#dmsService.getDmsObject(id, version))
133
+ .then((response) => {
134
+ return Promise.resolve(response);
135
+ })
136
+ .catch(this.#handleError);
137
+ }
138
+ /**
139
+ * fetches dms objects from the server that match the given params
140
+ *
141
+ * @param fields - the fields to match. example: {name: 'max', plz: '47111}
142
+ * @param type - the target object type
143
+ */
144
+ getResult(fields, type) {
145
+ const searchQuery = {
146
+ filters: Object.keys(fields).map((f) => ({
147
+ f,
148
+ o: Operator.EQUAL,
149
+ v1: fields[f]
150
+ }))
151
+ };
152
+ if (type)
153
+ searchQuery.types = [type];
154
+ return firstValueFrom(this.#searchService.search(searchQuery))
155
+ .then((res) => {
156
+ return Promise.resolve(res.items.map((resItem) => {
157
+ new DmsObject(resItem);
158
+ }));
159
+ })
160
+ .catch(this.#handleError);
161
+ }
162
+ encodeFileName(filename) {
163
+ return Utils.encodeFileName(filename);
164
+ }
165
+ #handleError(error) {
166
+ return Promise.reject(error.message || error);
167
+ }
168
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormScriptingApiService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
169
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormScriptingApiService }); }
170
+ }
171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormScriptingApiService, decorators: [{
172
+ type: Injectable
173
+ }] });
174
+
175
+ /**
176
+ * Providing an error message when a translation string for an object wasn't found
177
+ */
178
+ class ObjectFormTranslateService {
179
+ constructor() {
180
+ this.translate = inject(TranslateService);
181
+ }
182
+ /**
183
+ * Set the error label if a translation for this string wasn't provided
184
+ * @param error - error message about a missed translation key
185
+ * @param params
186
+ */
187
+ getErrorLabel(error, params) {
188
+ switch (error) {
189
+ case 'daterange':
190
+ return this.translate.instant('yuv.object-form-element.error.daterange.invalid', params);
191
+ case 'daterangeorder':
192
+ return this.translate.instant('yuv.object-form-element.error.daterangeorder.invalid', params);
193
+ case 'numberrange':
194
+ return this.translate.instant('yuv.object-form-element.error.numberrange.invalid', params);
195
+ case 'numberrangeorder':
196
+ return this.translate.instant('yuv.object-form-element.error.numberrangeorder.invalid', params);
197
+ case 'number':
198
+ return this.translate.instant('yuv.object-form-element.error.number', params);
199
+ case 'precision':
200
+ return this.translate.instant('yuv.object-form-element.error.number.precision', params);
201
+ case 'scale':
202
+ return this.translate.instant('yuv.object-form-element.error.number.scale', params);
203
+ case 'regex':
204
+ return this.translate.instant('yuv.object-form-element.error.string.regex.nomatch', params);
205
+ case 'pattern':
206
+ return this.translate.instant('yuv.object-form-element.error.string.regex.nomatch', params);
207
+ case 'classificationemail':
208
+ return this.translate.instant('yuv.object-form-element.error.string.classification.email', params);
209
+ case 'classificationphone':
210
+ return this.translate.instant('yuv.object-form-element.error.string.classification.phone', params);
211
+ case 'classificationurl':
212
+ return this.translate.instant('yuv.object-form-element.error.string.classification.url', params);
213
+ case 'onlyWhitespaces':
214
+ return this.translate.instant('yuv.object-form-element.error.string.whitespaces', params);
215
+ case 'datecontrol':
216
+ return this.translate.instant('yuv.object-form-element.error.date.invalid', params);
217
+ case 'required':
218
+ return this.translate.instant('yuv.object-form-element.error.required', params);
219
+ case 'maxlength':
220
+ return this.translate.instant('yuv.object-form-element.error.maxlength', params);
221
+ case 'minlength':
222
+ return this.translate.instant('yuv.object-form-element.error.minlength', params);
223
+ case 'minmax':
224
+ return this.translate.instant('yuv.object-form-element.error.minmax', params);
225
+ case 'minvalue':
226
+ return this.translate.instant('yuv.object-form-element.error.minvalue', params);
227
+ case 'maxvalue':
228
+ return this.translate.instant('yuv.object-form-element.error.maxvalue', params);
229
+ case 'empty':
230
+ return this.translate.instant('yuv.object-form-element.recent-activities.list.empty', params);
231
+ default:
232
+ return this.translate.instant(error, params);
233
+ }
234
+ }
235
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormTranslateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
236
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormTranslateService, providedIn: 'root' }); }
237
+ }
238
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormTranslateService, decorators: [{
239
+ type: Injectable,
240
+ args: [{
241
+ providedIn: 'root'
242
+ }]
243
+ }] });
244
+
245
+ /**
246
+ * @ignore
247
+ * Extend angulars default FormGroup for implementation of a form group wrapping
248
+ * a form control.
249
+ */
250
+ class ObjectFormControlWrapper extends UntypedFormGroup {
251
+ }
252
+
253
+ /**
254
+ * @ignore
255
+ * Extension of the default angular form group,
256
+ */
257
+ class ObjectFormGroup extends FormGroup {
258
+ }
259
+ /**
260
+ * @ignore
261
+ * Extension of the default angular form control,
262
+ */
263
+ class ObjectFormControl extends FormControl {
264
+ set _eoFormElement(v) {
265
+ this.__eoFormElement = v;
266
+ }
267
+ get _eoFormElement() {
268
+ return this.__eoFormElement;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * @ignore
274
+ * Custom validation class.
275
+ */
276
+ class FormValidation {
277
+ /**
278
+ * Build validators for the given form element to be attached to
279
+ * a reactive formControl.
280
+ *
281
+ * @param formElement - form element object
282
+ * @param situation - form situation to fetch validators for
283
+ */
284
+ static getValidators(formElement, situation) {
285
+ const elmValidators = [];
286
+ const { required, regex } = formElement;
287
+ // apply situation based validations
288
+ switch (situation) {
289
+ case Situation.SEARCH: {
290
+ // TODO: implement general validators for SEARCH situation
291
+ break;
292
+ }
293
+ default: {
294
+ if (required) {
295
+ elmValidators.push(Validators.required);
296
+ }
297
+ if (regex && !formElement.multiselect) {
298
+ elmValidators.push(Validators.pattern(regex));
299
+ }
300
+ break;
301
+ }
302
+ }
303
+ return elmValidators;
304
+ }
305
+ /**
306
+ *
307
+ * @param control - from object control
308
+ * @returns Validation object {eoformScript: {valid: boolean}} or null
309
+ */
310
+ static customScriptingValidation() {
311
+ return (control) => {
312
+ const ctrl = control;
313
+ return ctrl._eoFormElement && ctrl._eoFormElement.error ? { eoformScript: { valid: false } } : null;
314
+ };
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Provides a rendering of form control in `ObjectFormComponent`, `QuickSearchComponent` so wie `SearchFilterFormComponent`.
320
+ */
321
+ class ObjectFormUtils {
322
+ /**
323
+ * Converts a form element object to an ObjectFormControlWrapper which then can be used to
324
+ * render a from control. Result can be used as input for FormElementComponent.
325
+ *
326
+ * @param element - the element object or a json string
327
+ * @param situation - optional property to set up a form situation for the control (default is EDIT)
328
+ * @return the converted ObjectFormControlWrapper or null in case of an error
329
+ */
330
+ static elementToFormControl(formElement, situation) {
331
+ // Create the ObjectFormControlWrapper
332
+ const wrapper = new ObjectFormControlWrapper({});
333
+ const formSituation = situation ? situation : Situation.EDIT;
334
+ wrapper._eoFormControlWrapper = {
335
+ controlName: formElement.name,
336
+ situation: formSituation
337
+ };
338
+ // create the actual form control
339
+ const controlDisabled = !!formElement.readonly;
340
+ const formControl = new ObjectFormControl({
341
+ value: formElement.value,
342
+ disabled: controlDisabled
343
+ }, FormValidation.getValidators(formElement, formSituation));
344
+ // Form elements in SEARCH situation may arrive with a value set to NULL (explicit search for
345
+ // fields that are NOT set). In that case we need to prepare the form control
346
+ if (formSituation === Situation.SEARCH && formElement.value === null) {
347
+ formElement.isNotSetValue = true;
348
+ }
349
+ ObjectFormUtils.updateFormElement(formElement);
350
+ formControl._eoFormElement = formElement;
351
+ wrapper.addControl(formElement.name, formControl);
352
+ return wrapper;
353
+ }
354
+ /**
355
+ * Update a form element after change a form element object.
356
+ * @param formElement - the form element object
357
+ */
358
+ static updateFormElement(formElement) {
359
+ if (formElement.type === 'decimal' && !formElement.scale) {
360
+ formElement.scale = 2;
361
+ }
362
+ if (formElement.type === 'integer' && formElement.id === ContentStreamField.LENGTH) {
363
+ formElement.classifications = [Classification.NUMBER_FILESIZE];
364
+ }
365
+ return formElement;
366
+ }
367
+ }
368
+
369
+ /**
370
+ * @ignore
371
+ */
372
+ class ObjectFormService {
373
+ #formExtensions = [];
374
+ setElementExtensions(formExtensions) {
375
+ this.#formExtensions = formExtensions;
376
+ }
377
+ getElementExtensions(propertyName) {
378
+ return this.#formExtensions.filter((ext) => ext.property === propertyName).map((ext) => ext.cmp);
379
+ }
380
+ /**
381
+ * Converts a form element object to an ObjectFormControlWrapper which then can be used to
382
+ * render a from control. Result can be used as input for FormElementComponent.
383
+ *
384
+ * @param element - the element object or a json string
385
+ * @param situation - optional property to set up a form situation for the control (default is EDIT)
386
+ * @return the converted ObjectFormControlWrapper or null in case of an error
387
+ */
388
+ elementToFormControl(element, situation) {
389
+ let formElement;
390
+ if (typeof element === 'string') {
391
+ try {
392
+ formElement = JSON.parse(element);
393
+ }
394
+ catch (e) {
395
+ console.error('Unable to parse form element from json ', formElement);
396
+ }
397
+ }
398
+ else {
399
+ formElement = element;
400
+ }
401
+ return formElement ? ObjectFormUtils.elementToFormControl(element, situation) : null;
402
+ }
403
+ /**
404
+ * Extract data from an object form based on situation.
405
+ *
406
+ * @param form - form to extract data from
407
+ * @param situation - form situation
408
+ * @param [initialData] - optional form data to match the current values against
409
+ * This is required for editig indexdata (EDIT situation), because we have to compare new values
410
+ * against the initial values. If a property that is contained in the forms initial data is removed
411
+ * (e.g. set to null) then we have to set this null value, because otherwise the server would
412
+ * ignore the changes.
413
+ * @param isTableRowEditForm Flag indicating that the provided form is an inline form used by
414
+ * a forms table element for editing rows. Those need a special handling.
415
+ * @return extracted data as object
416
+ */
417
+ extractFormData(form, situation, initialData, isTableRowEditForm) {
418
+ const extractedData = {};
419
+ this.#getElementValues(extractedData, form, situation || 'EDIT', initialData, isTableRowEditForm);
420
+ return extractedData;
421
+ }
422
+ // Recursive method to get the values from each form control.
423
+ #getElementValues(data, formControl, situation, initialData, isTableRowEditForm) {
424
+ if (!formControl || !formControl.controls) {
425
+ return;
426
+ }
427
+ if (formControl instanceof ObjectFormControlWrapper) {
428
+ const fc = formControl.controls[formControl._eoFormControlWrapper.controlName];
429
+ if (fc._eoFormElement.isNotSetValue === true) {
430
+ // form elements may explicitly set to have NULL value (e.g. from Search form if values are requested that have no values)
431
+ this.#setDataValue(fc._eoFormElement.name, null, data, fc._eoFormElement, !isTableRowEditForm);
432
+ }
433
+ else if (fc.value !== undefined) {
434
+ const val = fc.value;
435
+ switch (situation) {
436
+ case Situation.SEARCH: {
437
+ if (val !== null) {
438
+ this.#setDataValue(fc._eoFormElement.name, val, data, fc._eoFormElement, !!isTableRowEditForm);
439
+ }
440
+ break;
441
+ }
442
+ case Situation.CREATE: {
443
+ if (val !== null) {
444
+ this.#setDataValue(fc._eoFormElement.name, val, data, fc._eoFormElement, !!isTableRowEditForm);
445
+ }
446
+ break;
447
+ }
448
+ case Situation.EDIT: {
449
+ // in edit situation we have to compare new values against the initial values
450
+ // If a property that is contained in the forms initial data is removed (e.g. set to null)
451
+ // then we have to set this null value, because otherwise the server will ignore the changes
452
+ if (val !== null || (initialData && initialData[fc._eoFormElement.name] !== undefined)) {
453
+ // data[fc._eoFormElement.name] = val;
454
+ this.#setDataValue(fc._eoFormElement.name, val, data, fc._eoFormElement, !!isTableRowEditForm);
455
+ }
456
+ break;
457
+ }
458
+ }
459
+ }
460
+ else if (fc._eoFormElement.type === 'boolean') {
461
+ // tri-state boolean fields could have a value of 'undefined' that needs to be transformed
462
+ // into 'null' to be correctly be processed by the backend
463
+ this.#setDataValue(fc._eoFormElement.name, null, data, fc._eoFormElement, !!isTableRowEditForm);
464
+ }
465
+ }
466
+ else {
467
+ Object.keys(formControl.controls).forEach((controlKey) => {
468
+ const formControlKeyed = formControl.controls[controlKey];
469
+ this.#getElementValues(data, formControlKeyed, situation, initialData, isTableRowEditForm);
470
+ });
471
+ }
472
+ }
473
+ #setDataValue(key, value, data, formElement, isTableRowEditForm) {
474
+ data[key] = value;
475
+ if (isTableRowEditForm && formElement.dataMeta) {
476
+ if (formElement._internalType === 'string:organization') {
477
+ data[key + '_title'] = formElement.dataMeta.map((d) => d.title);
478
+ }
479
+ // else if (formElement._internalType === 'string:reference') {
480
+ // data[key + '_title'] = formElement.dataMeta.map((e: ReferenceEntry) => e.title);
481
+ // }
482
+ }
483
+ }
484
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
485
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormService }); }
486
+ }
487
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormService, decorators: [{
488
+ type: Injectable
489
+ }] });
490
+
491
+ /**
492
+ * Class to extend by form element extensions.
493
+ */
494
+ // eslint-disable-next-line @angular-eslint/component-class-suffix
495
+ class ObjectFormElementExtension {
496
+ constructor() {
497
+ this.#formScriptingApiService = inject(FormScriptingApiService);
498
+ this.input = input.required();
499
+ }
500
+ #formScriptingApiService;
501
+ getApi() {
502
+ return this.#formScriptingApiService.getApi();
503
+ }
504
+ getCurrentValue() {
505
+ return this.getApi().form.getValue(this.input().formControlName);
506
+ }
507
+ setValue(value) {
508
+ // only set the value if the value is different. Otherwise the form
509
+ // will end up in an infinite loop
510
+ if (value !== this.getCurrentValue())
511
+ this.getApi().form.setValue(this.input().formControlName, value);
512
+ }
513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormElementExtension, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
514
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: ObjectFormElementExtension, isStandalone: true, selector: "ng-component", inputs: { input: { classPropertyName: "input", publicName: "input", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: '', isInline: true }); }
515
+ }
516
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormElementExtension, decorators: [{
517
+ type: Component,
518
+ args: [{
519
+ template: '',
520
+ standalone: true
521
+ }]
522
+ }] });
523
+
524
+ class FormScriptingElementExtensionComponent extends ObjectFormElementExtension {
525
+ constructor() {
526
+ super(...arguments);
527
+ this.ext = input();
528
+ this.defaultIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M160-120q-33 0-56.5-23.5T80-200v-560q0-33 23.5-56.5T160-840h560q33 0 56.5 23.5T800-760v80h80v80h-80v80h80v80h-80v80h80v80h-80v80q0 33-23.5 56.5T720-120H160Zm0-80h560v-560H160v560Zm80-80h200v-160H240v160Zm240-280h160v-120H480v120Zm-240 80h200v-200H240v200Zm240 200h160v-240H480v240ZM160-760v560-560Z"/></svg>';
529
+ }
530
+ run() {
531
+ this.ext()?.callback();
532
+ }
533
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormScriptingElementExtensionComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
534
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FormScriptingElementExtensionComponent, isStandalone: true, selector: "yuv-form-scripting-element-extension", inputs: { ext: { classPropertyName: "ext", publicName: "ext", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "@let x = ext();\n@if (x) {\n @if (x.icon) {\n <button class=\"secondary\" (click)=\"run()\" [title]=\"x.label\">\n <yvc-icon [svg]=\"x.icon\"></yvc-icon>\n </button>\n } @else if (x.label) {\n <button class=\"secondary\" (click)=\"run()\">{{ x.label }}</button>\n } @else {\n <button class=\"secondary\" (click)=\"run()\">\n <yvc-icon [svg]=\"defaultIcon\"></yvc-icon>\n </button>\n }\n}\n", styles: [":host button{--icon-size: 18px;color:var(--text-color-caption);padding:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i1.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }] }); }
535
+ }
536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormScriptingElementExtensionComponent, decorators: [{
537
+ type: Component,
538
+ args: [{ selector: 'yuv-form-scripting-element-extension', standalone: true, imports: [CommonModule, YvcIconModule], template: "@let x = ext();\n@if (x) {\n @if (x.icon) {\n <button class=\"secondary\" (click)=\"run()\" [title]=\"x.label\">\n <yvc-icon [svg]=\"x.icon\"></yvc-icon>\n </button>\n } @else if (x.label) {\n <button class=\"secondary\" (click)=\"run()\">{{ x.label }}</button>\n } @else {\n <button class=\"secondary\" (click)=\"run()\">\n <yvc-icon [svg]=\"defaultIcon\"></yvc-icon>\n </button>\n }\n}\n", styles: [":host button{--icon-size: 18px;color:var(--text-color-caption);padding:2px}\n"] }]
539
+ }] });
540
+
541
+ class ObjectFormElementComponent {
542
+ constructor() {
543
+ this.#destroyRef = inject(DestroyRef);
544
+ this.#formTranslateService = inject(ObjectFormTranslateService);
545
+ this.#objectFormService = inject(ObjectFormService);
546
+ this.#scriptingApi = inject(FormScriptingApiService);
547
+ this.createForm = signal(false);
548
+ this.extensionComponents = [];
549
+ this.#scriptingExtensions = this.#scriptingApi.elementExtensions;
550
+ this.scriptingExtensions = computed(() => Object.values(this.#scriptingExtensions()).filter((ext) => ext.propertyName === this.formControlName));
551
+ this.scriptExtensionCmp = FormScriptingElementExtensionComponent;
552
+ this.situation = input();
553
+ this.element = input();
554
+ this.#elementEffect = effect(() => {
555
+ const element = this.element();
556
+ untracked(() => {
557
+ this.createForm.set(true);
558
+ element && this.#setElement(this.element());
559
+ });
560
+ });
561
+ }
562
+ #destroyRef;
563
+ #formTranslateService;
564
+ #objectFormService;
565
+ #scriptingApi;
566
+ #scriptingExtensions;
567
+ #elementEffect;
568
+ get extensionComponentInput() {
569
+ const xti = {
570
+ formControlName: this.formControlName || ''
571
+ };
572
+ return xti;
573
+ }
574
+ #setElement(el) {
575
+ if (el && el._eoFormControlWrapper) {
576
+ this.formControlName = el._eoFormControlWrapper.controlName;
577
+ this.formElementRef = el.controls[this.formControlName];
578
+ this.formElementRef._eoFormElement = this.#setGrouping(this.formElementRef?._eoFormElement);
579
+ this.formElementRef?.valueChanges.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(() => this.#setupErrors());
580
+ this.extensionComponents = this.#objectFormService.getElementExtensions(this.formControlName);
581
+ this.createForm.set(false);
582
+ }
583
+ }
584
+ /**
585
+ * formating rules...
586
+ * https://wiki.optimal-systems.de/display/PM/Status+yuuvis+Momentum+-+Flex+client
587
+ */
588
+ #setGrouping(formElement) {
589
+ return { ...formElement, grouping: !!formElement?.classifications?.includes(Classification.NUMBER_DIGIT) };
590
+ }
591
+ onDataMetaChange(data) {
592
+ this.formElementRef._eoFormElement.dataMeta = data;
593
+ }
594
+ #setupErrors() {
595
+ this.errors = undefined;
596
+ if ((this.situation() !== Situation.SEARCH && this.situation() !== Situation.CREATE && this.formElementRef.errors) ||
597
+ ((this.situation() === Situation.SEARCH || this.situation() === Situation.CREATE) &&
598
+ this.formElementRef.errors &&
599
+ (this.formElementRef.dirty || this.formElementRef.touched))) {
600
+ this.errors = Object.keys(this.formElementRef.errors).map((key) => {
601
+ return key === 'eoformScript'
602
+ ? this.formElementRef._eoFormElement.error.msg
603
+ : this.#formTranslateService.getErrorLabel(key, this.formElementRef.errors[key].params);
604
+ });
605
+ }
606
+ }
607
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
608
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ObjectFormElementComponent, isStandalone: true, selector: "yuv-object-form-element", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "yuv-object-form-element" }, ngImport: i0, template: "@let el = element();\n\n@if (!createForm()) {\n @if (el && formElementRef) {\n <div class=\"form-element input\" [formGroup]=\"el\">\n <yuv-metadata-form-field\n [field]=\"formElementRef._eoFormElement\"\n [formControlName]=\"el._eoFormControlWrapper!.controlName\"\n [situation]=\"situation()\"\n ></yuv-metadata-form-field>\n\n <div class=\"ext\">\n @for (cmp of extensionComponents; track $index) {\n <ng-container *ngComponentOutlet=\"cmp; inputs: { input: extensionComponentInput }\"></ng-container>\n }\n @for (scmp of scriptingExtensions(); track $index) {\n <ng-container *ngComponentOutlet=\"scriptExtensionCmp; inputs: { ext: scmp }\"></ng-container>\n }\n </div>\n </div>\n }\n}\n", styles: [":host{flex:1 1 auto}.yuv-object-form-element .form-element{box-sizing:border-box;display:flex;flex-flow:row nowrap}.yuv-object-form-element .form-element .ext{display:flex;flex-flow:row nowrap;gap:2px;align-items:center}.yuv-object-form-element .form-element yuv-metadata-form-field{width:100%}.yuv-object-form-element .form-element .form-field{padding:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2)}.yuv-object-form-element .form-element .form-field .description{border:0;font-size:var(--font-hint);color:var(--text-color-caption);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8)}.yuv-object-form-element .form-element .form-field .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}.yuv-object-form-element .form-element .form-field .table{flex-flow:column;align-items:flex-start;border:1px solid var(--panel-divider-color)}.yuv-object-form-element .form-element .form-field .table .label{padding-bottom:calc(var(--app-pane-padding) / 4)}.yuv-object-form-element .form-element .form-field .table.invalid{border:1px solid var(--color-error)}.yuv-object-form-element .form-element .form-field.inlineError .err-msg{display:none}.yuv-object-form-element .form-element.ng-dirty:not(.ng-invalid)>.form-field:not(.focused)::ng-deep .fe-wrapper>label{background-color:var(--color-dirty-background);color:var(--color-dirty-font)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: MetadataFormFieldComponent, selector: "yuv-metadata-form-field", inputs: ["field", "situation"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], encapsulation: i0.ViewEncapsulation.None }); }
609
+ }
610
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormElementComponent, decorators: [{
611
+ type: Component,
612
+ args: [{ selector: 'yuv-object-form-element', standalone: true, imports: [CommonModule, MetadataFormFieldComponent, NgComponentOutlet, ReactiveFormsModule], encapsulation: ViewEncapsulation.None, host: { class: 'yuv-object-form-element' }, template: "@let el = element();\n\n@if (!createForm()) {\n @if (el && formElementRef) {\n <div class=\"form-element input\" [formGroup]=\"el\">\n <yuv-metadata-form-field\n [field]=\"formElementRef._eoFormElement\"\n [formControlName]=\"el._eoFormControlWrapper!.controlName\"\n [situation]=\"situation()\"\n ></yuv-metadata-form-field>\n\n <div class=\"ext\">\n @for (cmp of extensionComponents; track $index) {\n <ng-container *ngComponentOutlet=\"cmp; inputs: { input: extensionComponentInput }\"></ng-container>\n }\n @for (scmp of scriptingExtensions(); track $index) {\n <ng-container *ngComponentOutlet=\"scriptExtensionCmp; inputs: { ext: scmp }\"></ng-container>\n }\n </div>\n </div>\n }\n}\n", styles: [":host{flex:1 1 auto}.yuv-object-form-element .form-element{box-sizing:border-box;display:flex;flex-flow:row nowrap}.yuv-object-form-element .form-element .ext{display:flex;flex-flow:row nowrap;gap:2px;align-items:center}.yuv-object-form-element .form-element yuv-metadata-form-field{width:100%}.yuv-object-form-element .form-element .form-field{padding:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2)}.yuv-object-form-element .form-element .form-field .description{border:0;font-size:var(--font-hint);color:var(--text-color-caption);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8)}.yuv-object-form-element .form-element .form-field .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}.yuv-object-form-element .form-element .form-field .table{flex-flow:column;align-items:flex-start;border:1px solid var(--panel-divider-color)}.yuv-object-form-element .form-element .form-field .table .label{padding-bottom:calc(var(--app-pane-padding) / 4)}.yuv-object-form-element .form-element .form-field .table.invalid{border:1px solid var(--color-error)}.yuv-object-form-element .form-element .form-field.inlineError .err-msg{display:none}.yuv-object-form-element .form-element.ng-dirty:not(.ng-invalid)>.form-field:not(.focused)::ng-deep .fe-wrapper>label{background-color:var(--color-dirty-background);color:var(--color-dirty-font)!important}\n"] }]
613
+ }] });
614
+
615
+ class ObjectFormGroupComponent {
616
+ constructor() {
617
+ this.types = {
618
+ STACK: 'stack',
619
+ GROUP: 'group',
620
+ FIELDSET: 'fieldset'
621
+ };
622
+ this.isCore = false;
623
+ this.isData = false;
624
+ // @ViewChild('tabView') tabView: TabView;
625
+ // form situation, if not set default will be 'EDIT'
626
+ this.situation = Situation.EDIT;
627
+ this.group = input();
628
+ this.#groupEffect = effect(() => {
629
+ const g = this.group();
630
+ if (g) {
631
+ this.isCore = !!g._eoFormGroup && g._eoFormGroup.label === 'core';
632
+ this.isData = !!g._eoFormGroup && g._eoFormGroup.label === 'data';
633
+ this.groupType = this.#getGroupType();
634
+ }
635
+ });
636
+ this.noGroupLabels = input();
637
+ }
638
+ #groupEffect;
639
+ getHeaderStyleClass(ctrl) {
640
+ return `dirty-${ctrl.dirty} invalid-${ctrl.invalid}`;
641
+ }
642
+ getChildControl(ctrl) {
643
+ return ctrl;
644
+ }
645
+ getObjectFormGroup(control) {
646
+ return control._eoFormGroup;
647
+ }
648
+ getObjectFormControlWrapper(control) {
649
+ return control?._eoFormControlWrapper;
650
+ }
651
+ getElement(control) {
652
+ return control;
653
+ }
654
+ #getGroupType() {
655
+ // may as well be an ObjectFormControlWrapper so check first
656
+ // if we got a real group
657
+ const group = this.group();
658
+ if (group?._eoFormGroup) {
659
+ if (group._eoFormGroup.type === 'o2mGroupStack') {
660
+ // for data section only render as stack (tabs) if we have more than one child
661
+ if (this.isData && Object.keys(group.controls).length === 1) {
662
+ return this.types.GROUP;
663
+ }
664
+ return this.types.STACK;
665
+ }
666
+ if (group._eoFormGroup.type === 'o2mGroup') {
667
+ return group._eoFormGroup.label && !(this.isCore || this.isData) && !this.noGroupLabels && !this.#parentIsStack(group)
668
+ ? this.types.FIELDSET
669
+ : this.types.GROUP;
670
+ }
671
+ return this.types.GROUP;
672
+ }
673
+ else
674
+ return undefined;
675
+ }
676
+ #parentIsStack(group) {
677
+ const parentFormElement = group.parent && group.parent['_eoFormGroup'];
678
+ return parentFormElement && parentFormElement.type === 'o2mGroupStack';
679
+ }
680
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
681
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ObjectFormGroupComponent, isStandalone: true, selector: "yuv-object-form-group", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: false, isRequired: false, transformFunction: null }, group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: false, transformFunction: null }, noGroupLabels: { classPropertyName: "noGroupLabels", publicName: "noGroupLabels", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@let grp = group();\n@if (grp) {\n <div\n class=\"form-element {{ grp._eoFormGroup ? grp._eoFormGroup.type : 'o2mControlWrap' }} align-{{\n grp._eoFormGroup && grp._eoFormGroup.layout ? grp._eoFormGroup.layout.align : ''\n }}\"\n [formGroup]=\"grp\"\n >\n @switch (groupType) {\n <!-- group stacks (tabs) -->\n @case ('stack') {\n <yvc-tabs>\n @for (key of grp.controls | keys; track key) {\n <ng-template\n [yvcTab]=\"{\n id: key,\n headerStyleClass: getHeaderStyleClass(grp.controls[key]),\n label: getObjectFormGroup(grp.controls[key])?.label || ''\n }\"\n >\n <div class=\"stack\" [ngClass]=\"{ stackBase: grp._eoFormGroup?.label === 'data' }\">\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n </div>\n </ng-template>\n }\n </yvc-tabs>\n }\n\n <!-- group with legend -->\n @case ('fieldset') {\n <div class=\"om-group fieldset\">\n <div class=\"legend\">\n <span>{{ grp._eoFormGroup?.label }}</span>\n </div>\n\n <div>\n @for (key of grp.controls | keys; track key) {\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n }\n </div>\n </div>\n }\n <!-- group -->\n @case ('group') {\n @for (key of grp.controls | keys; track key) {\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n }\n }\n }\n </div>\n}\n", styles: [".form-element{box-sizing:border-box}.form-element .fieldset{margin:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2);padding:calc(var(--app-pane-padding) / 4);background:#00000006;border:1px solid rgba(0,0,0,.1)}.dark .form-element .fieldset{background:#ffffff06;border-color:#ffffff1a}.contrast .form-element .fieldset{background-color:transparent;border-color:var(--panel-divider-color)}.form-element .fieldset .legend{margin-bottom:calc(var(--app-pane-padding) / 2)}.form-element .fieldset .legend>span{display:inline-block;font-size:var(--font-hint);border-radius:2px;color:#fff;background-color:#00000038;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 4)}.dark .form-element .fieldset .legend>span{background-color:#ffffff38}.contrast .form-element .fieldset .legend>span{background-color:var(--panel-divider-color);color:var(--panel-background)}.form-element.o2mGroupStack{background:#00000005;border:1px solid rgba(0,0,0,.1)}.dark .form-element.o2mGroupStack{background:#ffffff05;border:1px solid rgba(255,255,255,.1)}.contrast .form-element.o2mGroupStack{background-color:transparent;border-color:var(--panel-divider-color)}.form-element.o2mGroupStack .p-tabview.p-component .p-tabview-panels{background:#fff;overflow:initial}.dark .form-element.o2mGroupStack .p-tabview.p-component .p-tabview-panels{background:#ffffff0a}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav li.p-highlight{border-color:#00000042}.dark .form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav li.p-highlight{border-color:#ffffff42}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav>li:not(.p-highlight):not(.p-disabled):hover{border-color:#00000029}.dark .form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav>li:not(.p-highlight):not(.p-disabled):hover{border-color:#ffffff29}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.dirty-true:not(.invalid-true) a .p-tabview-title{background-color:var(--color-dirty-background);color:var(--color-dirty-font)}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.invalid-true a .p-tabview-title{background-color:var(--color-error);color:#fff}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.invalid-true a .p-tabview-title:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}.form-element.align-column{display:flex;flex-flow:column nowrap;justify-content:flex-start;align-content:stretch;align-items:stretch}.form-element.align-column>*{flex:1 1 auto}.form-element.align-row{display:flex;flex-flow:row wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start}.form-element.align-row>*{flex:1 0 200px;max-width:100%}.form-element.align-row>.fieldset>:not(.legend){display:flex;flex-flow:row wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start}.form-element .stackBase{padding:var(--app-pane-padding);background:var(--panel-background-lightgrey)}.form-element .stackBase>yuv-form-group>.form-element>.fieldset{margin:0;padding:0;border:0;background-color:transparent}.form-element .stackBase>yuv-form-group>.form-element>.fieldset>.legend{display:none}\n"], dependencies: [{ kind: "component", type: ObjectFormGroupComponent, selector: "yuv-object-form-group", inputs: ["situation", "group", "noGroupLabels"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: YvcTabsModule }, { kind: "component", type: i2$1.Tabs, selector: "yvc-tabs", inputs: ["tabs", "layoutSettingsID", "panelOrder", "panelOrderIncludeUnmentioned", "cacheViews", "tabSplitEnabled", "tabRemoveEnabled"], outputs: ["tabSplit", "tabRemove", "tabChange"] }, { kind: "directive", type: i2$1.YvcTabDirective, selector: "[yvcTab]", inputs: ["yvcTab"] }, { kind: "pipe", type: KeysPipe, name: "keys" }, { kind: "component", type: ObjectFormElementComponent, selector: "yuv-object-form-element", inputs: ["situation", "element"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }], encapsulation: i0.ViewEncapsulation.None }); }
682
+ }
683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormGroupComponent, decorators: [{
684
+ type: Component,
685
+ args: [{ selector: 'yuv-object-form-group', standalone: true, imports: [CommonModule, YvcTabsModule, KeysPipe, ObjectFormElementComponent, ReactiveFormsModule], encapsulation: ViewEncapsulation.None, template: "@let grp = group();\n@if (grp) {\n <div\n class=\"form-element {{ grp._eoFormGroup ? grp._eoFormGroup.type : 'o2mControlWrap' }} align-{{\n grp._eoFormGroup && grp._eoFormGroup.layout ? grp._eoFormGroup.layout.align : ''\n }}\"\n [formGroup]=\"grp\"\n >\n @switch (groupType) {\n <!-- group stacks (tabs) -->\n @case ('stack') {\n <yvc-tabs>\n @for (key of grp.controls | keys; track key) {\n <ng-template\n [yvcTab]=\"{\n id: key,\n headerStyleClass: getHeaderStyleClass(grp.controls[key]),\n label: getObjectFormGroup(grp.controls[key])?.label || ''\n }\"\n >\n <div class=\"stack\" [ngClass]=\"{ stackBase: grp._eoFormGroup?.label === 'data' }\">\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n </div>\n </ng-template>\n }\n </yvc-tabs>\n }\n\n <!-- group with legend -->\n @case ('fieldset') {\n <div class=\"om-group fieldset\">\n <div class=\"legend\">\n <span>{{ grp._eoFormGroup?.label }}</span>\n </div>\n\n <div>\n @for (key of grp.controls | keys; track key) {\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n }\n </div>\n </div>\n }\n <!-- group -->\n @case ('group') {\n @for (key of grp.controls | keys; track key) {\n @if (getObjectFormControlWrapper(grp.controls[key])) {\n <yuv-object-form-element [element]=\"getElement(grp.controls[key])\" [situation]=\"situation\"></yuv-object-form-element>\n } @else {\n <yuv-object-form-group [group]=\"getChildControl(grp.controls[key])\" [noGroupLabels]=\"true\" [situation]=\"situation\"></yuv-object-form-group>\n }\n }\n }\n }\n </div>\n}\n", styles: [".form-element{box-sizing:border-box}.form-element .fieldset{margin:calc(var(--app-pane-padding) / 4) calc(var(--app-pane-padding) / 2);padding:calc(var(--app-pane-padding) / 4);background:#00000006;border:1px solid rgba(0,0,0,.1)}.dark .form-element .fieldset{background:#ffffff06;border-color:#ffffff1a}.contrast .form-element .fieldset{background-color:transparent;border-color:var(--panel-divider-color)}.form-element .fieldset .legend{margin-bottom:calc(var(--app-pane-padding) / 2)}.form-element .fieldset .legend>span{display:inline-block;font-size:var(--font-hint);border-radius:2px;color:#fff;background-color:#00000038;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 4)}.dark .form-element .fieldset .legend>span{background-color:#ffffff38}.contrast .form-element .fieldset .legend>span{background-color:var(--panel-divider-color);color:var(--panel-background)}.form-element.o2mGroupStack{background:#00000005;border:1px solid rgba(0,0,0,.1)}.dark .form-element.o2mGroupStack{background:#ffffff05;border:1px solid rgba(255,255,255,.1)}.contrast .form-element.o2mGroupStack{background-color:transparent;border-color:var(--panel-divider-color)}.form-element.o2mGroupStack .p-tabview.p-component .p-tabview-panels{background:#fff;overflow:initial}.dark .form-element.o2mGroupStack .p-tabview.p-component .p-tabview-panels{background:#ffffff0a}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav li.p-highlight{border-color:#00000042}.dark .form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav li.p-highlight{border-color:#ffffff42}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav>li:not(.p-highlight):not(.p-disabled):hover{border-color:#00000029}.dark .form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav>li:not(.p-highlight):not(.p-disabled):hover{border-color:#ffffff29}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.dirty-true:not(.invalid-true) a .p-tabview-title{background-color:var(--color-dirty-background);color:var(--color-dirty-font)}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.invalid-true a .p-tabview-title{background-color:var(--color-error);color:#fff}.form-element.o2mGroupStack .p-tabview.p-component>.p-tabview-nav-container>.p-tabview-nav-content>.p-tabview-nav li.invalid-true a .p-tabview-title:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}.form-element.align-column{display:flex;flex-flow:column nowrap;justify-content:flex-start;align-content:stretch;align-items:stretch}.form-element.align-column>*{flex:1 1 auto}.form-element.align-row{display:flex;flex-flow:row wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start}.form-element.align-row>*{flex:1 0 200px;max-width:100%}.form-element.align-row>.fieldset>:not(.legend){display:flex;flex-flow:row wrap;justify-content:flex-start;align-content:flex-start;align-items:flex-start}.form-element .stackBase{padding:var(--app-pane-padding);background:var(--panel-background-lightgrey)}.form-element .stackBase>yuv-form-group>.form-element>.fieldset{margin:0;padding:0;border:0;background-color:transparent}.form-element .stackBase>yuv-form-group>.form-element>.fieldset>.legend{display:none}\n"] }]
686
+ }], propDecorators: { situation: [{
687
+ type: Input
688
+ }] } });
689
+
690
+ /**
691
+ * @ignore
692
+ */
693
+ class ObjectFormScriptService {
694
+ constructor(logger, backend) {
695
+ this.logger = logger;
696
+ this.backend = backend;
697
+ }
698
+ /**
699
+ * Run a form script.
700
+ * @param scope - the current scripting scope
701
+ * @param script - the script to be executed
702
+ * @param [scriptName] - the scripts name
703
+ */
704
+ runFormScript(scope, script, scriptName) {
705
+ try {
706
+ // Define form script the function
707
+ const formScriptFunction = this.defineFunction('Formscript/' + scriptName, script);
708
+ // run the form script
709
+ const formScriptReturn = formScriptFunction(scope);
710
+ // Check if the form script returns something and may export global scripts
711
+ if (formScriptReturn) {
712
+ this.importGlobalScriptsAndCallInit(scope, formScriptReturn);
713
+ }
714
+ }
715
+ catch (e) {
716
+ if (e instanceof SyntaxError) {
717
+ alert('Syntax error in Form-Script. See console log for details.');
718
+ }
719
+ this.logger.error('Got script error', e);
720
+ }
721
+ }
722
+ /**
723
+ * Define form script function, appending source url as comment.
724
+ * Enables debugging using browser debugging tools (Chrome+Firefox)
725
+ * @see: https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Debug_eval_sources
726
+ *
727
+ * @param name - the name of the script
728
+ * @param script - script to be wrapped in a function
729
+ * @returns the function
730
+ */
731
+ // eslint-disable-next-line @typescript-eslint/ban-types
732
+ defineFunction(name, script) {
733
+ // Appending source url as comment. See https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Debug_eval_sources
734
+ // Enables debugging using browser debugging tools (Chrome+Firefox)
735
+ // The line feed is needed, if the script has a comment in the last line
736
+ return new Function('scope', script + '\n;//# sourceURL=' + name + '.js');
737
+ }
738
+ /**
739
+ * If the script contains global script, this function will import and run them
740
+ * before running the actual script.
741
+ *
742
+ * @param scope - the current scripting scope
743
+ * @param formScriptReturn - the return value of the actual form script
744
+ */
745
+ importGlobalScriptsAndCallInit(scope, formScriptReturn) {
746
+ if (!formScriptReturn.init) {
747
+ return;
748
+ }
749
+ if (formScriptReturn.uses) {
750
+ // collect the global script exports promises
751
+ const exports = [];
752
+ const globals = [];
753
+ // collect Observables for fetching global scripts
754
+ for (const use of formScriptReturn.uses) {
755
+ globals.push(this.resolveGlobalScript(use, scope));
756
+ }
757
+ forkJoin(globals).subscribe((globalReturns) => {
758
+ for (const scriptReturn of globalReturns) {
759
+ exports.push(scriptReturn['exports']);
760
+ }
761
+ // Invoke init function on form script return with the
762
+ // collected exports using javascript apply magic
763
+ formScriptReturn.init.apply(this, exports);
764
+ });
765
+ }
766
+ else {
767
+ // invoke init direct (no use of global scripts)
768
+ formScriptReturn.init();
769
+ }
770
+ }
771
+ /**
772
+ * Fetch global scripts.
773
+ * @param name - the name of the global script
774
+ * @param scope - the current scripting scope
775
+ * @returns
776
+ */
777
+ resolveGlobalScript(name, scope) {
778
+ const requestOptions = {
779
+ headers: new HttpHeaders({
780
+ Accept: 'text/plain'
781
+ }),
782
+ responseType: 'text'
783
+ };
784
+ return this.backend.get(`/script/${name}/script`, undefined, requestOptions).pipe(map$1((res) => {
785
+ // define the global function ...
786
+ const globalScript = this.defineFunction('Global/' + name, res);
787
+ // ... and run it
788
+ return globalScript(scope);
789
+ }));
790
+ }
791
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormScriptService, deps: [{ token: i1$2.Logger }, { token: i1$2.BackendService }], target: i0.ɵɵFactoryTarget.Injectable }); }
792
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormScriptService }); }
793
+ }
794
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormScriptService, decorators: [{
795
+ type: Injectable
796
+ }], ctorParameters: () => [{ type: i1$2.Logger }, { type: i1$2.BackendService }] });
797
+
798
+ /**
799
+ * @ignore
800
+ * This class will be injected as scope into form scripts.
801
+ */
802
+ class ObjectFormScriptingScope {
803
+ /**
804
+ * Constructor
805
+ * @param situation - Current form model situation (could be CREATE, SEARCH or EDIT)
806
+ * @param onScriptingModelChange - callback function to be called when the scripting model changed
807
+ * Be aware to provide an instance method as callback for the scripting scope.
808
+ * @see: https://blog.johnnyreilly.com/2014/04/typescript-instance-methods.html
809
+ *
810
+ * @param api - Plugin API reference
811
+ * @param isTableRowScope - set this to true if the current scripting scope is created for a
812
+ * row editing form from a table element. It will then provide the right parameters for the scripting functions
813
+ */
814
+ // eslint-disable-next-line @typescript-eslint/ban-types
815
+ constructor(situation, onScriptingModelChange, api, isTableRowScope) {
816
+ this.situation = situation;
817
+ this.onScriptingModelChange = onScriptingModelChange;
818
+ this.api = api;
819
+ this.isTableRowScope = isTableRowScope;
820
+ // List of all form fields (elements)
821
+ this.model = {};
822
+ // all data values including invisible elements (READONLY)
823
+ this.data = {};
824
+ // actions passed by BPM forms
825
+ this.actions = {};
826
+ // additional objects provided by the object form
827
+ // used for example to pass dms objects attached to a work item
828
+ // to the script (READONLY)
829
+ // may contain: FormScriptDmsObject, FileEntry
830
+ this.objects = [];
831
+ this.context = { id: '', title: '', objectTypeId: '' };
832
+ }
833
+ /**
834
+ * Sets the internal model and wraps every model element with an observer to be
835
+ * able to track their changes from within a form script
836
+ * @param model
837
+ */
838
+ setModel(model) {
839
+ this.model = {};
840
+ for (const k of Object.keys(model)) {
841
+ this.model[k] = new ScopeElement(model[k], this.onScriptingModelChange);
842
+ }
843
+ }
844
+ /**
845
+ * Returns the observed model. Used for row editing forms of table elements that
846
+ * create their own scripting scope in context of their parent form.
847
+ * @returns the observed scripting scope model
848
+ */
849
+ getModel() {
850
+ return this.model;
851
+ }
852
+ /**
853
+ * Called by the object form when the form model changes.
854
+ * @param change - object with key equals name of the element
855
+ * that changes and value of the new value
856
+ */
857
+ modelChanged(change) {
858
+ // find the changed element in the scopes model
859
+ const propertyName = Object.keys(change)[0];
860
+ if (change[propertyName] === undefined) {
861
+ return;
862
+ }
863
+ if (this.model[propertyName]) {
864
+ const el = this.model[propertyName];
865
+ el.update(change[propertyName], this.model);
866
+ }
867
+ }
868
+ }
869
+ /**
870
+ * @ignore
871
+ */
872
+ class ScopeElement {
873
+ // eslint-disable-next-line @typescript-eslint/ban-types
874
+ constructor(element, onScriptingModelChange) {
875
+ this.element = element;
876
+ this.onScriptingModelChange = onScriptingModelChange;
877
+ if (this.element.value === undefined) {
878
+ this.element.value = null;
879
+ }
880
+ if (this.isProxyable(this.element.value)) {
881
+ this.element.value = this.createProxy(this.element.value);
882
+ }
883
+ }
884
+ isProxyable(value, key) {
885
+ return ((typeof value === 'object' || Array.isArray(value)) &&
886
+ value !== null &&
887
+ !(value instanceof Date) &&
888
+ !value.isProxy &&
889
+ (key ? !key.includes('_meta') : true));
890
+ }
891
+ createProxy(value) {
892
+ const handler = {
893
+ set: (target, key, val) => {
894
+ const previousValue = structuredClone(this.element.value);
895
+ if (this.isProxyable(val, key)) {
896
+ target[key] = this.createProxy(val);
897
+ }
898
+ else {
899
+ target[key] = val;
900
+ }
901
+ if (this.hasValueChanged(this.element.value, previousValue) && !key.includes('_meta')) {
902
+ this.onScriptingModelChange(this.element.name, { newValue: structuredClone(this.element.value), name: 'value' });
903
+ }
904
+ return true;
905
+ },
906
+ // This get trap is only used to find out, if an object is a proxy or not.
907
+ get: (target, key) => {
908
+ if (key === 'isProxy') {
909
+ return true;
910
+ }
911
+ return target[key];
912
+ }
913
+ };
914
+ Object.keys(value).forEach((key) => {
915
+ if (this.isProxyable(value[key], key)) {
916
+ value[key] = this.createProxy(value[key]);
917
+ }
918
+ });
919
+ return new Proxy(value, handler);
920
+ }
921
+ hasValueChanged(value1, value2) {
922
+ return JSON.stringify(value1) !== JSON.stringify(value2);
923
+ }
924
+ update(value, model) {
925
+ const newValue = structuredClone(value);
926
+ if (this.hasValueChanged(this.element.value, value)) {
927
+ if (this.isProxyable(value)) {
928
+ this.element.value = this.createProxy(newValue);
929
+ }
930
+ else {
931
+ this.element.value = newValue;
932
+ }
933
+ if (this.element.onchange) {
934
+ this.element.onchange(this, model);
935
+ }
936
+ }
937
+ }
938
+ set value(value) {
939
+ if (this.hasValueChanged(this.element.value, value)) {
940
+ if (this.isProxyable(value)) {
941
+ this.element.value = this.createProxy(value);
942
+ }
943
+ else {
944
+ this.element.value = value;
945
+ }
946
+ this.onScriptingModelChange(this.element.name, { newValue: structuredClone(this.element.value), name: 'value' });
947
+ }
948
+ }
949
+ get value() {
950
+ return this.element.value;
951
+ }
952
+ set onchange(onchange) {
953
+ this.element.onchange = onchange;
954
+ this.onScriptingModelChange(this.element.name, { newValue: onchange, name: 'onchange' });
955
+ }
956
+ get onchange() {
957
+ return this.element.onchange;
958
+ }
959
+ set required(required) {
960
+ this.element.required = required;
961
+ this.onScriptingModelChange(this.element.name, { newValue: required, name: 'required' });
962
+ }
963
+ get required() {
964
+ return this.element.required;
965
+ }
966
+ set readonly(readonly) {
967
+ this.element.readonly = readonly;
968
+ this.onScriptingModelChange(this.element.name, { newValue: readonly, name: 'readonly' });
969
+ }
970
+ get readonly() {
971
+ return this.element.readonly;
972
+ }
973
+ set error(error) {
974
+ this.element.error = error;
975
+ this.onScriptingModelChange(this.element.name, { newValue: error, name: 'error' });
976
+ }
977
+ get error() {
978
+ return this.element.error;
979
+ }
980
+ set onrowedit(onrowedit) {
981
+ this.element.onrowedit = onrowedit;
982
+ this.onScriptingModelChange(this.element.name, { newValue: onrowedit, name: 'onrowedit' });
983
+ }
984
+ get onrowedit() {
985
+ return this.element.onrowedit;
986
+ }
987
+ setList(obj) {
988
+ if (this.element.setList) {
989
+ this.element.setList(obj);
990
+ }
991
+ }
992
+ applyFilter(obj) {
993
+ if (this.element.applyFilter) {
994
+ this.element.applyFilter(obj);
995
+ }
996
+ }
997
+ setFilter(obj) {
998
+ if (this.element.setFilter) {
999
+ this.element.setFilter(obj);
1000
+ }
1001
+ }
1002
+ get name() {
1003
+ return this.element.name;
1004
+ }
1005
+ get qname() {
1006
+ return this.element.qname;
1007
+ }
1008
+ get label() {
1009
+ return this.element.label;
1010
+ }
1011
+ get description() {
1012
+ return this.element.description;
1013
+ }
1014
+ get type() {
1015
+ return this.element.type;
1016
+ }
1017
+ get multiselect() {
1018
+ return this.element.multiselect;
1019
+ }
1020
+ get codesystem() {
1021
+ return this.element.codesystem;
1022
+ }
1023
+ get minlen() {
1024
+ return this.element.minLength;
1025
+ }
1026
+ get maxlen() {
1027
+ return this.element.maxLength;
1028
+ }
1029
+ get classifications() {
1030
+ return this.element.classifications;
1031
+ }
1032
+ get scale() {
1033
+ return this.element.scale;
1034
+ }
1035
+ get precision() {
1036
+ return this.element.precision;
1037
+ }
1038
+ get withtime() {
1039
+ return this.element.withtime;
1040
+ }
1041
+ get elements() {
1042
+ return this.element.elements;
1043
+ }
1044
+ get aliases() {
1045
+ return this.element.aliases;
1046
+ }
1047
+ }
1048
+
1049
+ class ObjectFormComponent {
1050
+ #elementRef;
1051
+ #systemService;
1052
+ #formScriptService;
1053
+ #formHelperService;
1054
+ #userService;
1055
+ #cdRef;
1056
+ #formScriptingApiService;
1057
+ #skipTranslationsFor;
1058
+ #namePrefix;
1059
+ #formOptionsEffect;
1060
+ #elementExtensionsEffect;
1061
+ #scriptModel;
1062
+ #scriptingScope;
1063
+ #subscriptions;
1064
+ // local store for all the form control references
1065
+ #formControls;
1066
+ #initialValidators;
1067
+ constructor() {
1068
+ this.#elementRef = inject(ElementRef);
1069
+ this.#systemService = inject(SystemService);
1070
+ this.#formScriptService = inject(ObjectFormScriptService);
1071
+ this.#formHelperService = inject(ObjectFormService);
1072
+ this.#userService = inject(UserService);
1073
+ this.#cdRef = inject(ChangeDetectorRef);
1074
+ this.#formScriptingApiService = inject(FormScriptingApiService);
1075
+ this.#skipTranslationsFor = ['core', 'data'];
1076
+ this.#namePrefix = 'fg_';
1077
+ this.gCount = 0;
1078
+ this.id = Utils.uuid();
1079
+ this.formOptions = input();
1080
+ this.#formOptionsEffect = effect(() => {
1081
+ this.#init(this.formOptions());
1082
+ });
1083
+ this.inert = input();
1084
+ this.elementExtensions = input([]);
1085
+ this.#elementExtensionsEffect = effect(() => {
1086
+ this.#formHelperService.setElementExtensions(this.elementExtensions());
1087
+ });
1088
+ /**
1089
+ * There are special scenarios where forms are within a form themselves.
1090
+ * Setting this property to true, will handle the current form in a
1091
+ * slightly different way when it comes to form scripting.
1092
+ */
1093
+ this.isInnerTableForm = input();
1094
+ /**
1095
+ * triggered when the forms state has been changed
1096
+ */
1097
+ this.statusChanged = output();
1098
+ /**
1099
+ * handler to be executed after the form has been set up
1100
+ */
1101
+ this.onFormReady = output();
1102
+ this.#scriptModel = {};
1103
+ this.#subscriptions = [];
1104
+ // local store for all the form control references
1105
+ this.#formControls = {};
1106
+ this.#initialValidators = {};
1107
+ /**
1108
+ * This method will be called each time the script changes its internal model.
1109
+ * It is used to transfer the script changes to the actual form model.
1110
+ *
1111
+ * To ensure the right context, we define an instance method as callback for the scripting scope
1112
+ * @see: https://blog.johnnyreilly.com/2014/04/typescript-instance-methods.html
1113
+ *
1114
+ * @param formControlName
1115
+ * @param change
1116
+ */
1117
+ this.#onScriptingModelChanged = (formControlName, change, formId) => {
1118
+ if (!this.form || (formId && this.id !== formId))
1119
+ return;
1120
+ // find the target control
1121
+ const fc = this.#formControls[formControlName];
1122
+ if (fc) {
1123
+ // change only allowed properties
1124
+ switch (change.name) {
1125
+ case 'value': {
1126
+ if (Array.isArray(change.newValue)) {
1127
+ this.#processArrayValueChange(fc, change);
1128
+ }
1129
+ else {
1130
+ fc._eoFormElement.value = change.newValue;
1131
+ if (fc.value !== change.newValue) {
1132
+ fc.patchValue(change.newValue);
1133
+ fc.updateValueAndValidity();
1134
+ fc.markAsDirty();
1135
+ }
1136
+ }
1137
+ this.form.markAsDirty();
1138
+ break;
1139
+ }
1140
+ case 'required': {
1141
+ fc._eoFormElement.required = change.newValue;
1142
+ // apply new validators
1143
+ // @see: https://scotch.io/tutorials/how-to-implement-conditional-validation-in-angular-2-model-driven-forms
1144
+ fc.setValidators(Validators.compose(this.#getValidators(fc._eoFormElement).concat([this.#initialValidators[fc._eoFormElement.name]])));
1145
+ // need to mark form control as touched because otherwise form validation will not show
1146
+ // error messages
1147
+ fc.markAsTouched();
1148
+ fc.updateValueAndValidity();
1149
+ break;
1150
+ }
1151
+ case 'readonly': {
1152
+ fc._eoFormElement.readonly = change.newValue;
1153
+ if (change.newValue === true) {
1154
+ fc.disable();
1155
+ }
1156
+ else {
1157
+ fc.enable();
1158
+ }
1159
+ break;
1160
+ }
1161
+ case 'error': {
1162
+ fc._eoFormElement.error = change.newValue;
1163
+ fc.markAsTouched();
1164
+ fc.updateValueAndValidity();
1165
+ break;
1166
+ }
1167
+ // new onrowedit function was applied by the script
1168
+ case 'onrowedit': {
1169
+ fc._eoFormElement.onrowedit = change.newValue;
1170
+ break;
1171
+ }
1172
+ // new onchange function was applied by the script
1173
+ case 'onchange': {
1174
+ fc._eoFormElement.onchange = change.newValue;
1175
+ break;
1176
+ }
1177
+ }
1178
+ this.#cdRef.detectChanges();
1179
+ }
1180
+ };
1181
+ this.#formScriptingApiService.formId = this.id;
1182
+ this.#formScriptingApiService.api.events
1183
+ .on(FormScriptingApiService.EVENT_MODEL_CHANGED)
1184
+ .pipe(takeUntilDestroyed())
1185
+ .subscribe((event) => event.data && this.#onScriptingModelChanged(event.data.formControlName, event.data.change, event.data.formId));
1186
+ this.#formScriptingApiService.formId = this.id;
1187
+ }
1188
+ // initialize the form based on the provided form options
1189
+ #init(fo) {
1190
+ this.form = undefined;
1191
+ if (!fo)
1192
+ return;
1193
+ setTimeout(() => {
1194
+ this.#initialValidators = {};
1195
+ this.unsubscribeAll();
1196
+ this.#buildReactiveForm(fo);
1197
+ }, 0);
1198
+ }
1199
+ #initScriptingScope(formOptions, dataFormModel) {
1200
+ const { data, actions, objects, context } = (formOptions || {});
1201
+ if (this.#scriptingScope) {
1202
+ this.#scriptingScope.setModel(this.#scriptModel);
1203
+ /** provide access to actions (used inside of BPM-Forms) */
1204
+ this.#scriptingScope.actions = actions;
1205
+ /** provide access to additional objects (used for example in BPM-Start-Forms to
1206
+ * add data of DMS-Objects to start the process for)
1207
+ */
1208
+ this.#scriptingScope.objects = objects || [];
1209
+ this.#scriptingScope.context = context || { id: '', title: '', objectTypeId: '' };
1210
+ /** provide readonly access to initial form data (which may also contain values that
1211
+ * are not rendered as form elements (invisible values))
1212
+ */
1213
+ this.#scriptingScope.data = data;
1214
+ /** by default, scripting scopes are applied to forms. But table elements create their own scope
1215
+ * for editing rows. Being one of those inner forms should not run the form script again, but
1216
+ * instead just provide the observing abilities of the scripting scope.
1217
+ */
1218
+ if (!this.isInnerTableForm() && dataFormModel) {
1219
+ const scriptName = dataFormModel.name + '_' + dataFormModel.situation;
1220
+ console.debug('executing form script ' + scriptName);
1221
+ this.#formScriptService.runFormScript(this.#scriptingScope, dataFormModel.script, scriptName);
1222
+ }
1223
+ }
1224
+ }
1225
+ focusForm() {
1226
+ this.#elementRef.nativeElement.querySelector('input').focus();
1227
+ }
1228
+ getGroup(id) {
1229
+ return this.form?.get(id);
1230
+ }
1231
+ setFormData(data) {
1232
+ const fo = this.formOptions();
1233
+ if (!fo)
1234
+ return;
1235
+ fo.data = data;
1236
+ setTimeout(() => this.#init(fo), 0);
1237
+ }
1238
+ patchValue(data) {
1239
+ Object.keys(data).forEach((key) => {
1240
+ this.#onScriptingModelChanged(key, {
1241
+ name: 'value',
1242
+ newValue: data[key]
1243
+ });
1244
+ });
1245
+ }
1246
+ /**
1247
+ * Extracts the values from the form model. Each form value is represented by one
1248
+ * property on the result object holding the fields value. The keys (properties) are the `name`
1249
+ * properties of the form element.
1250
+ *
1251
+ * How values are extracted is influenced by the forms situation.
1252
+ *
1253
+ * @return object of key value pairs
1254
+ */
1255
+ getFormData() {
1256
+ return this.#formToData();
1257
+ }
1258
+ getFormElements() {
1259
+ const formElements = {};
1260
+ Object.keys(this.#formControls).forEach((k) => {
1261
+ formElements[k] = this.#formControls[k].__eoFormElement;
1262
+ });
1263
+ return formElements;
1264
+ }
1265
+ setFormPristine() {
1266
+ if (!this.form)
1267
+ return;
1268
+ this.form.markAsPristine();
1269
+ }
1270
+ // reset the form to its initial state
1271
+ resetForm() {
1272
+ const fo = this.formOptions();
1273
+ if (!fo)
1274
+ return;
1275
+ this.setFormData(fo.data);
1276
+ this.#emitFormChangedEvent();
1277
+ }
1278
+ /**
1279
+ * Returns the observed model that was passed to the current form script running. If there is
1280
+ * no form script, this method will return NULL.
1281
+ * @returns
1282
+ */
1283
+ getObservedScriptModel() {
1284
+ return this.#scriptingScope ? this.#scriptingScope.getModel() : null;
1285
+ }
1286
+ // Create a reactive form from the enaio form model
1287
+ #buildReactiveForm(formOptions) {
1288
+ this.#scriptingScope = undefined;
1289
+ this.#scriptModel = {};
1290
+ this.#formControls = {};
1291
+ const formModel = this.#dataToForm(formOptions.formModel, formOptions.data);
1292
+ if (!formModel) {
1293
+ return;
1294
+ }
1295
+ // if a script is available, we'll init the form scripting for the
1296
+ // current form
1297
+ if (this.isInnerTableForm() || (formModel.script && formModel.script.length > 0)) {
1298
+ console.debug('adding form scripting scope');
1299
+ this.#scriptingScope = new ObjectFormScriptingScope(formModel.situation, this.#onScriptingModelChanged, this.#formScriptingApiService.getApi(), this.isInnerTableForm());
1300
+ this.#scriptingScope.objectId = this.formOptions().objectId;
1301
+ }
1302
+ const form = new ObjectFormGroup({});
1303
+ if (formModel?.elements[0]?.elements) {
1304
+ this.#addFormControl(form, formModel.elements[0], 'core');
1305
+ }
1306
+ if (formModel?.elements[1]?.elements) {
1307
+ this.#addFormControl(form, formModel.elements[1], 'data');
1308
+ }
1309
+ this.form = form;
1310
+ this.#formScriptingApiService.registerActiveForm(this);
1311
+ setTimeout(() => {
1312
+ if (!this.form)
1313
+ return;
1314
+ this.initValidators(this.form);
1315
+ this.#subscriptions.push(this.form.valueChanges.pipe(debounceTime(500)).subscribe(() => this.#emitFormChangedEvent()));
1316
+ this.#initScriptingScope(formOptions, formModel);
1317
+ this.onFormReady.emit();
1318
+ this.#emitFormChangedEvent(false);
1319
+ }, 300);
1320
+ }
1321
+ initValidators(form) {
1322
+ if (this.form) {
1323
+ for (const key of Object.keys(form.controls)) {
1324
+ const control = form.controls[key];
1325
+ if (control.controls) {
1326
+ this.initValidators(control);
1327
+ }
1328
+ else {
1329
+ this.#initialValidators[control._eoFormElement.name] = control.validator;
1330
+ control.setValidators(Validators.compose(this.#getValidators(control._eoFormElement).concat([this.#initialValidators[control._eoFormElement.name]])));
1331
+ control.updateValueAndValidity();
1332
+ }
1333
+ }
1334
+ }
1335
+ }
1336
+ #emitFormChangedEvent(compare = true) {
1337
+ // check if indexdata has been changed
1338
+ const currentFormData = this.getFormData();
1339
+ const idxChange = compare ? JSON.stringify(this.formData) !== JSON.stringify(currentFormData) : false;
1340
+ this.formData = currentFormData;
1341
+ if (this.form) {
1342
+ this.statusChanged.emit({
1343
+ invalid: this.form.invalid,
1344
+ dirty: this.form.dirty,
1345
+ data: this.formData,
1346
+ indexdataChanged: idxChange
1347
+ });
1348
+ }
1349
+ }
1350
+ /**
1351
+ * This method will be called each time the script changes its internal model.
1352
+ * It is used to transfer the script changes to the actual form model.
1353
+ *
1354
+ * To ensure the right context, we define an instance method as callback for the scripting scope
1355
+ * @see: https://blog.johnnyreilly.com/2014/04/typescript-instance-methods.html
1356
+ *
1357
+ * @param formControlName
1358
+ * @param change
1359
+ */
1360
+ #onScriptingModelChanged;
1361
+ #processArrayValueChange(fc, change) {
1362
+ const newVal = change.newValue;
1363
+ const targetType = fc._eoFormElement.type;
1364
+ // for some types we have to ensure that meta data are provided as well
1365
+ switch (targetType) {
1366
+ case 'ORGANIZATION': {
1367
+ this.#getDataMeta(fc._eoFormElement, newVal).subscribe((m) => {
1368
+ fc._eoFormElement.dataMeta = m;
1369
+ });
1370
+ break;
1371
+ }
1372
+ case 'TABLE': {
1373
+ const dataToBeProcessed = {};
1374
+ fc._eoFormElement.elements.forEach((e) => {
1375
+ if (e.type === 'ORGANIZATION' || e.type === 'CODESYSTEM') {
1376
+ dataToBeProcessed[e.name] = e;
1377
+ }
1378
+ });
1379
+ if (Object.keys(dataToBeProcessed).length) {
1380
+ newVal.forEach((rowData) => {
1381
+ Object.keys(rowData).forEach((key) => {
1382
+ if (dataToBeProcessed[key]) {
1383
+ this.#getDataMeta(dataToBeProcessed[key], rowData[key]).subscribe((m) => {
1384
+ if (m) {
1385
+ rowData[key + '_meta'] = m;
1386
+ }
1387
+ else {
1388
+ delete rowData[key + '_meta'];
1389
+ }
1390
+ this.#updateArrayValue(fc, newVal);
1391
+ });
1392
+ }
1393
+ });
1394
+ });
1395
+ }
1396
+ break;
1397
+ }
1398
+ }
1399
+ this.#updateArrayValue(fc, newVal);
1400
+ }
1401
+ #updateArrayValue(fc, newValue) {
1402
+ fc._eoFormElement.value = [].concat(newValue);
1403
+ fc.patchValue([].concat(newValue));
1404
+ fc.updateValueAndValidity();
1405
+ fc.markAsDirty();
1406
+ }
1407
+ #getDataMeta(formElement, newValue) {
1408
+ if (newValue) {
1409
+ switch (formElement.type) {
1410
+ case 'ORGANIZATION': {
1411
+ return this.#userService.getUserById(newValue);
1412
+ }
1413
+ }
1414
+ }
1415
+ return of(null);
1416
+ }
1417
+ #patchFormValue(formValue) {
1418
+ let value;
1419
+ if (Array.isArray(formValue)) {
1420
+ value = [];
1421
+ // copy by value for arrays of objects (e.g. table data)
1422
+ formValue.forEach((o) => value.push(JSON.parse(JSON.stringify(o))));
1423
+ }
1424
+ else {
1425
+ value = formValue;
1426
+ }
1427
+ return value;
1428
+ }
1429
+ /**
1430
+ * Recursive method adding a new FormControl (group or control) to a parent form group
1431
+ *
1432
+ * @param parentGroup - the parent group to add the control to
1433
+ * @param formElement - the enaio form model element to create the child control from
1434
+ * @param [useName] - use this name instead of the one from the model
1435
+ */
1436
+ #addFormControl(parentGroup, formElement, useName) {
1437
+ const fo = this.formOptions();
1438
+ if (!fo)
1439
+ return;
1440
+ let ctrl;
1441
+ let name;
1442
+ // add a form group
1443
+ if (formElement.type === 'o2mGroup' || formElement.type === 'o2mGroupStack') {
1444
+ // do not add groups that are empty
1445
+ const isRootGroup = formElement.name && (formElement.name !== 'data' || formElement.name !== 'core');
1446
+ if (!isRootGroup && (!formElement.elements || formElement.elements.length === 0)) {
1447
+ console.error('Found empty form group', formElement);
1448
+ return;
1449
+ }
1450
+ ctrl = new ObjectFormGroup({});
1451
+ ctrl._eoFormGroup = {
1452
+ layout: formElement.layout,
1453
+ type: formElement.type
1454
+ };
1455
+ if (formElement.name) {
1456
+ if (this.#skipTranslationsFor.includes(formElement.name)) {
1457
+ ctrl._eoFormGroup.label = formElement.name;
1458
+ }
1459
+ else if (!formElement.label) {
1460
+ // no label, so try to translate the technical name
1461
+ ctrl._eoFormGroup.label = this.#systemService.getLocalizedResource(`${formElement.name}_label`) || formElement.name;
1462
+ }
1463
+ else {
1464
+ // there is a label so we take this one
1465
+ ctrl._eoFormGroup.label = formElement.label;
1466
+ }
1467
+ }
1468
+ if (useName === 'core' || useName === 'data') {
1469
+ ctrl._eoFormGroup.label = useName;
1470
+ }
1471
+ for (const e of formElement.elements) {
1472
+ this.#addFormControl(ctrl, e);
1473
+ }
1474
+ name = useName || 'fg' + this.gCount++;
1475
+ }
1476
+ else {
1477
+ // add form control
1478
+ // To be able to integrate recursive form controls into the main form,
1479
+ // we have to wrap them in a form group
1480
+ ctrl = new ObjectFormControlWrapper({});
1481
+ ctrl._eoFormControlWrapper = {
1482
+ // the name of the wrapped FormControl
1483
+ controlName: formElement.name,
1484
+ situation: fo.formModel.situation
1485
+ };
1486
+ // do not set a reference as the form controls value
1487
+ // otherwise we could not reset the form
1488
+ const value = formElement?.value
1489
+ ? this.#patchFormValue(formElement?.value)
1490
+ : !Utils.isEmpty(formElement?.defaultvalue) && fo.formModel.situation === Situation.CREATE
1491
+ ? this.#patchFormValue(formElement?.defaultvalue)
1492
+ : formElement?.value;
1493
+ // create the actual form control
1494
+ const controlDisabled = fo.disabled || !!formElement.readonly;
1495
+ const formControl = new ObjectFormControl({
1496
+ value,
1497
+ disabled: controlDisabled
1498
+ });
1499
+ // if form element has a 'label' property it will be shown as is ...
1500
+ if (!formElement.label) {
1501
+ // ... if there is no label but a 'labelKey' property we are going to localize that key ...
1502
+ if (formElement.labelkey) {
1503
+ formElement.label = this.#systemService.getLocalizedResource(`${formElement.labelkey}_label`) || formElement.labelkey;
1504
+ formElement.description = this.#systemService.getLocalizedResource(`${formElement.labelkey}_description`);
1505
+ }
1506
+ else {
1507
+ // ... no 'label' and also no 'labelKey' means that we are showing technical name instead
1508
+ formElement.label = formElement.name;
1509
+ }
1510
+ }
1511
+ formElement.readonly = controlDisabled;
1512
+ // we are using an internal type to distinguish between the components
1513
+ // to be used to render certain form elements
1514
+ formElement._internalType = this.#systemService.getInternalFormElementType(formElement.type, formElement.classifications);
1515
+ formControl._eoFormElement = formElement;
1516
+ this.#formControls[formElement.name] = formControl;
1517
+ if (formElement.type === 'TABLE') {
1518
+ // Add 'onrowedit' property even if it's not set.
1519
+ // This is required because otherwise mobX-Observer would not recognize
1520
+ // changes to this property applied by the form script
1521
+ if (!Object.keys(formControl._eoFormElement).includes('onrowedit')) {
1522
+ formControl._eoFormElement.onrowedit = null;
1523
+ }
1524
+ if (this.#scriptingScope && formControl._eoFormElement.value) {
1525
+ // having a scripting scope and table rows means that we need to set empty
1526
+ // columns to NULL, because otherwise mobX won't be able to track those values
1527
+ const valueFields = formControl._eoFormElement.elements.map((e) => e.name);
1528
+ formControl._eoFormElement.value.forEach((rowValue) => {
1529
+ valueFields.forEach((valueField) => {
1530
+ if (!Object.keys(rowValue).includes(valueField)) {
1531
+ rowValue[valueField] = null;
1532
+ }
1533
+ });
1534
+ });
1535
+ // update form controls value as well to reflect the observed value
1536
+ formControl.patchValue(formControl._eoFormElement.value, {
1537
+ onlySelf: true,
1538
+ emitEvent: false,
1539
+ emitModelToViewChange: false,
1540
+ emitViewToModelChange: false
1541
+ });
1542
+ }
1543
+ }
1544
+ if (formElement._internalType === 'string:organization') {
1545
+ formControl._eoFormElement.setFilter = (filterObject) => {
1546
+ formControl._eoFormElement.filter = filterObject;
1547
+ };
1548
+ }
1549
+ ObjectFormUtils.updateFormElement(formElement);
1550
+ // remove empty descriptions
1551
+ const desc = formControl._eoFormElement.description;
1552
+ if (desc && desc.trim().length === 0) {
1553
+ formControl._eoFormElement.description = null;
1554
+ }
1555
+ // add the form element to the script model that will be injected into
1556
+ // the forms scripting scope later on
1557
+ this.#scriptModel[formElement.name] = formControl._eoFormElement;
1558
+ // apply change listener to the form control, that will trigger
1559
+ // the form elements onChange listener
1560
+ const controlWatch = ctrl.valueChanges.pipe(debounceTime(500));
1561
+ this.#subscriptions.push(controlWatch.subscribe((v) => {
1562
+ if (this.#scriptingScope) {
1563
+ this.#scriptingScope.modelChanged(v);
1564
+ }
1565
+ }));
1566
+ ctrl.addControl(formElement.name, formControl);
1567
+ name = this.#namePrefix + formElement.name;
1568
+ }
1569
+ parentGroup.addControl(name, ctrl);
1570
+ }
1571
+ /**
1572
+ * Build validators for the given form element to be attached to
1573
+ * a reactive formControl.
1574
+ *
1575
+ * @param formElement - form element object
1576
+ */
1577
+ #getValidators(formElement) {
1578
+ const fo = this.formOptions();
1579
+ const elmValidators = FormValidation.getValidators(formElement, fo?.formModel.situation);
1580
+ // add custom validator for script enabled forms
1581
+ if (this.#scriptingScope) {
1582
+ elmValidators.push(FormValidation.customScriptingValidation);
1583
+ }
1584
+ return elmValidators;
1585
+ }
1586
+ /**
1587
+ * Extract the values from the form
1588
+ */
1589
+ #formToData() {
1590
+ const fo = this.formOptions();
1591
+ return fo && this.form ? this.#formHelperService.extractFormData(this.form, fo.formModel.situation, fo.data, this.isInnerTableForm()) : {};
1592
+ }
1593
+ /**
1594
+ * Merge data into a form model.
1595
+ *
1596
+ * @param model - form model
1597
+ * @param data - data object or array of SearchFilter objects in case of a search form
1598
+ */
1599
+ #dataToForm(model, data) {
1600
+ if (model && data) {
1601
+ this.#setElementValues(model.elements, data);
1602
+ }
1603
+ return model;
1604
+ }
1605
+ // recursive method for adding values to model elements
1606
+ #setElementValues(elements, data) {
1607
+ elements?.forEach((element) => {
1608
+ if (this.#hasValue(data, element)) {
1609
+ element.value = this.#getValue(data, element);
1610
+ }
1611
+ else {
1612
+ delete element.value;
1613
+ }
1614
+ if (element.type !== 'TABLE' && element.elements && element.elements.length > 0) {
1615
+ this.#setElementValues(element.elements, data);
1616
+ }
1617
+ });
1618
+ }
1619
+ #hasValue(data, element) {
1620
+ // differ between array of SearchFilters and a form data object
1621
+ if (Array.isArray(data)) {
1622
+ return !!data.find((filter) => filter.property === element.id);
1623
+ }
1624
+ else {
1625
+ return Object.keys(data).includes(element.name);
1626
+ }
1627
+ }
1628
+ #getValue(data, element) {
1629
+ return data[element.name];
1630
+ }
1631
+ ngOnDestroy() {
1632
+ this.unsubscribeAll();
1633
+ this.#formScriptingApiService.unregisterActiveForm(this);
1634
+ }
1635
+ ngAfterViewInit() {
1636
+ this.#cdRef.detectChanges();
1637
+ }
1638
+ // unsubscribe from all value change listeners for the current form
1639
+ // to avoid memory leaks. This method will also be called every time
1640
+ // a new form is rendered to get rid of the old form element subscriptions
1641
+ unsubscribeAll() {
1642
+ if (this.#subscriptions.length) {
1643
+ console.debug('unsubscribed from ' + this.#subscriptions.length + ' value change listeners.');
1644
+ this.#subscriptions.forEach((s) => s.unsubscribe());
1645
+ this.#subscriptions = [];
1646
+ }
1647
+ }
1648
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1649
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: ObjectFormComponent, isStandalone: true, selector: "yuv-object-form", inputs: { formOptions: { classPropertyName: "formOptions", publicName: "formOptions", isSignal: true, isRequired: false, transformFunction: null }, inert: { classPropertyName: "inert", publicName: "inert", isSignal: true, isRequired: false, transformFunction: null }, elementExtensions: { classPropertyName: "elementExtensions", publicName: "elementExtensions", isSignal: true, isRequired: false, transformFunction: null }, isInnerTableForm: { classPropertyName: "isInnerTableForm", publicName: "isInnerTableForm", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { statusChanged: "statusChanged", onFormReady: "onFormReady" }, host: { properties: { "attr.inert": "inert() ? true : null" }, classAttribute: "yuv-object-form" }, providers: [ObjectFormService, ObjectFormScriptService, FormScriptingApiService], ngImport: i0, template: "@let fo = formOptions();\n@if (fo && form) {\n <div class=\"yuv-object-form\" [formGroup]=\"form\">\n <div class=\"form-element-wrap core\">\n <yuv-object-form-group [group]=\"getGroup('core')\" [situation]=\"fo.formModel.situation\"></yuv-object-form-group>\n </div>\n <div class=\"form-element-wrap data\">\n <yuv-object-form-group [group]=\"getGroup('data')\" [situation]=\"fo.formModel.situation\"></yuv-object-form-group>\n </div>\n </div>\n}\n", styles: [".yuv-object-form>.core{padding:calc(var(--app-pane-padding) / 2)}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack{background:transparent;border:0}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack>yuv-object-form-group>.o2mGroup{background-color:var(--panel-background-lightgrey);border-top:1px solid rgba(0,0,0,.1);padding:var(--app-pane-padding)}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack>p-tabview>.p-tabview>.p-tabview-panels{background-color:var(--panel-background-lightgrey)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ObjectFormGroupComponent, selector: "yuv-object-form-group", inputs: ["situation", "group", "noGroupLabels"] }], encapsulation: i0.ViewEncapsulation.None }); }
1650
+ }
1651
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ObjectFormComponent, decorators: [{
1652
+ type: Component,
1653
+ args: [{ selector: 'yuv-object-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, ObjectFormGroupComponent], providers: [ObjectFormService, ObjectFormScriptService, FormScriptingApiService], encapsulation: ViewEncapsulation.None, host: {
1654
+ class: 'yuv-object-form',
1655
+ '[attr.inert]': 'inert() ? true : null'
1656
+ }, template: "@let fo = formOptions();\n@if (fo && form) {\n <div class=\"yuv-object-form\" [formGroup]=\"form\">\n <div class=\"form-element-wrap core\">\n <yuv-object-form-group [group]=\"getGroup('core')\" [situation]=\"fo.formModel.situation\"></yuv-object-form-group>\n </div>\n <div class=\"form-element-wrap data\">\n <yuv-object-form-group [group]=\"getGroup('data')\" [situation]=\"fo.formModel.situation\"></yuv-object-form-group>\n </div>\n </div>\n}\n", styles: [".yuv-object-form>.core{padding:calc(var(--app-pane-padding) / 2)}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack{background:transparent;border:0}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack>yuv-object-form-group>.o2mGroup{background-color:var(--panel-background-lightgrey);border-top:1px solid rgba(0,0,0,.1);padding:var(--app-pane-padding)}.yuv-object-form>.data>yuv-object-form-group>.form-element.o2mGroupStack>p-tabview>.p-tabview>.p-tabview-panels{background-color:var(--panel-background-lightgrey)}\n"] }]
1657
+ }], ctorParameters: () => [] });
1658
+
1659
+ /**
1660
+ * Generated bundle index. Do not edit.
1661
+ */
1662
+
1663
+ export { ObjectFormComponent, ObjectFormControlWrapper, ObjectFormElementExtension, ObjectFormTranslateService };
1664
+ //# sourceMappingURL=yuuvis-client-framework-object-form.mjs.map