@solidstarters/solid-core-ui 1.1.211 → 1.1.212

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 (373) hide show
  1. package/dist/components/Svg/DevDocs.tsx +9 -0
  2. package/dist/components/Svg/DocsSvg.tsx +9 -0
  3. package/dist/components/Svg/ExcelSvg.tsx +15 -0
  4. package/dist/components/Svg/FieldSvg.tsx +9 -0
  5. package/dist/components/Svg/FileSvg.tsx +18 -0
  6. package/dist/components/Svg/HomePageModuleSvg.tsx +179 -0
  7. package/dist/components/Svg/ModelSvg.tsx +9 -0
  8. package/dist/components/Svg/ModuleSvg.tsx +9 -0
  9. package/dist/components/Svg/PDFSvg.tsx +15 -0
  10. package/dist/components/Svg/RightArrowSvg.tsx +9 -0
  11. package/dist/components/Svg/SettingsSvg.tsx +9 -0
  12. package/dist/components/auth/AuthLayout.tsx +223 -0
  13. package/dist/components/auth/ForgotPasswordThankYou.tsx +33 -0
  14. package/dist/components/auth/GoogleAuthChecking.tsx +63 -0
  15. package/dist/components/auth/SolidChangeForcePassword.tsx +222 -0
  16. package/dist/components/auth/SolidForgotPassword.tsx +127 -0
  17. package/dist/components/auth/SolidInitialLoginOtp.tsx +271 -0
  18. package/dist/components/auth/SolidInitiateRegisterOtp.tsx +218 -0
  19. package/dist/components/auth/SolidLogin.d.ts.map +1 -1
  20. package/dist/components/auth/SolidLogin.js +14 -8
  21. package/dist/components/auth/SolidLogin.js.map +1 -1
  22. package/dist/components/auth/SolidLogin.tsx +428 -0
  23. package/dist/components/auth/SolidOTPVerify.tsx +133 -0
  24. package/dist/components/auth/SolidRegister.tsx +454 -0
  25. package/dist/components/auth/SolidResetPassword.tsx +194 -0
  26. package/dist/components/common/AuthBanner.tsx +41 -0
  27. package/dist/components/common/AutoCompleteField.tsx +79 -0
  28. package/dist/components/common/BackButton.tsx +72 -0
  29. package/dist/components/common/CancelButton.tsx +61 -0
  30. package/dist/components/common/CodeEditor.tsx +38 -0
  31. package/dist/components/common/CreateButton.tsx +17 -0
  32. package/dist/components/common/DownloadProgressToast.tsx +55 -0
  33. package/dist/components/common/DropzonePlaceholder.tsx +31 -0
  34. package/dist/components/common/DropzoneUpload.tsx +11 -0
  35. package/dist/components/common/FileReaderExt.tsx +20 -0
  36. package/dist/components/common/GeneralSettings.tsx +1225 -0
  37. package/dist/components/common/HeaderDynamicTitles.tsx +13 -0
  38. package/dist/components/common/MarkdownViewer.tsx +84 -0
  39. package/dist/components/common/MultipleSelectAutoCompleteField.tsx +64 -0
  40. package/dist/components/common/NotFound.tsx +22 -0
  41. package/dist/components/common/SingleSelectAutoCompleteField.tsx +73 -0
  42. package/dist/components/common/SocialMediaLogin.tsx +53 -0
  43. package/dist/components/common/SolidAdmin.tsx +6 -0
  44. package/dist/components/common/SolidBreadcrumb.tsx +129 -0
  45. package/dist/components/common/SolidExport.tsx +563 -0
  46. package/dist/components/common/SolidExportStepper.tsx +135 -0
  47. package/dist/components/common/SolidFieldTooltip.tsx +23 -0
  48. package/dist/components/common/SolidFormHeader.tsx +25 -0
  49. package/dist/components/common/SolidFormStepper.tsx +350 -0
  50. package/dist/components/common/SolidModuleHome.tsx +128 -0
  51. package/dist/components/common/SolidPopupContainer.tsx +37 -0
  52. package/dist/components/common/SolidSettings/LlmSettings/AnthropicProviderComponent.tsx +45 -0
  53. package/dist/components/common/SolidSettings/LlmSettings/OpenAiProviderComponent.tsx +45 -0
  54. package/dist/components/common/SolidSettings/SettingDropzoneActivePlaceholder.tsx +20 -0
  55. package/dist/components/common/SolidSettings/SettingsImageRemoveButton.tsx +15 -0
  56. package/dist/components/common/SolidSettings/SolidUploadedImage.tsx +16 -0
  57. package/dist/components/common/SolidThemeLink.tsx +6 -0
  58. package/dist/components/common/SolidThemeProvider.tsx +44 -0
  59. package/dist/components/common/StepperArrows/ActiveArrowStep.tsx +18 -0
  60. package/dist/components/common/StepperArrows/ActiveBeforeStepArrow.tsx +18 -0
  61. package/dist/components/common/StepperArrows/InactiveStepArrow.tsx +19 -0
  62. package/dist/components/common/error.tsx +30 -0
  63. package/dist/components/common/useHandleFormCustomButtonClick.ts +40 -0
  64. package/dist/components/common/useHandleListCustomButtonClick.ts +42 -0
  65. package/dist/components/core/chatter/SolidChatter.tsx +248 -0
  66. package/dist/components/core/chatter/SolidChatterAuditMessage.tsx +35 -0
  67. package/dist/components/core/chatter/SolidChatterCustomMessage.tsx +46 -0
  68. package/dist/components/core/chatter/SolidChatterDateDivider.tsx +16 -0
  69. package/dist/components/core/chatter/SolidChatterHeader.tsx +218 -0
  70. package/dist/components/core/chatter/SolidChatterMessageBox.tsx +163 -0
  71. package/dist/components/core/chatter/SolidMessageComposer.tsx +146 -0
  72. package/dist/components/core/common/AvatarWidget.tsx +55 -0
  73. package/dist/components/core/common/DateFieldViewComponent.tsx +36 -0
  74. package/dist/components/core/common/FilterComponent.tsx +458 -0
  75. package/dist/components/core/common/LoadDynamicJsxComponent.tsx +70 -0
  76. package/dist/components/core/common/PDFViewer.tsx +117 -0
  77. package/dist/components/core/common/SolidAccountSettings/SolidAccountSettings.tsx +89 -0
  78. package/dist/components/core/common/SolidAccountSettings/SolidChangePassword.tsx +188 -0
  79. package/dist/components/core/common/SolidAccountSettings/SolidNotifications.tsx +139 -0
  80. package/dist/components/core/common/SolidAccountSettings/SolidPersonalInfo.tsx +311 -0
  81. package/dist/components/core/common/SolidCreateButton.tsx +48 -0
  82. package/dist/components/core/common/SolidGenericImport/DocumentSvg.tsx +15 -0
  83. package/dist/components/core/common/SolidGenericImport/SolidGenericImport.tsx +64 -0
  84. package/dist/components/core/common/SolidGenericImport/SolidImportDropzone.tsx +125 -0
  85. package/dist/components/core/common/SolidGenericImport/SolidImportInstructions.tsx +122 -0
  86. package/dist/components/core/common/SolidGenericImport/SolidImportStepper.tsx +217 -0
  87. package/dist/components/core/common/SolidGenericImport/SolidImportTransaction.tsx +205 -0
  88. package/dist/components/core/common/SolidGenericImport/SolidImportTransactionStatus.tsx +158 -0
  89. package/dist/components/core/common/SolidGenericImport/SolidImportWrapper.tsx +29 -0
  90. package/dist/components/core/common/SolidGlobalSearchElement.tsx +1470 -0
  91. package/dist/components/core/common/SolidLayoutViews.tsx +87 -0
  92. package/dist/components/core/common/SolidListViewOptions.tsx +31 -0
  93. package/dist/components/core/common/SolidLoaders/SolidCircularLoader.tsx +7 -0
  94. package/dist/components/core/common/SolidPasswordHelperText.tsx +34 -0
  95. package/dist/components/core/common/SolidSaveCustomFilterForm.tsx +75 -0
  96. package/dist/components/core/common/SolidSearchBox.tsx +17 -0
  97. package/dist/components/core/common/SolidViewLayoutManager.ts +421 -0
  98. package/dist/components/core/common/SolidXAiIframe.tsx +77 -0
  99. package/dist/components/core/dashboard/SolidDashboard.tsx +332 -0
  100. package/dist/components/core/dashboard/SolidDashboardBody.tsx +117 -0
  101. package/dist/components/core/dashboard/SolidDashboardFilterRequired.tsx +28 -0
  102. package/dist/components/core/dashboard/SolidDashboardHeader.tsx +10 -0
  103. package/dist/components/core/dashboard/SolidDashboardLoading.tsx +55 -0
  104. package/dist/components/core/dashboard/SolidDashboardNotAvailable.tsx +32 -0
  105. package/dist/components/core/dashboard/SolidDashboardRenderError.tsx +29 -0
  106. package/dist/components/core/dashboard/SolidDashboardVariable.tsx +256 -0
  107. package/dist/components/core/dashboard/SolidQuestionRenderer.tsx +78 -0
  108. package/dist/components/core/dashboard/chart-renderers/ChartJsRenderer.tsx +18 -0
  109. package/dist/components/core/dashboard/chart-renderers/PrimeReactDatatableRenderer.tsx +54 -0
  110. package/dist/components/core/dashboard/chart-renderers/init-chartjs.ts +25 -0
  111. package/dist/components/core/dashboard/dashboard-utils.ts +39 -0
  112. package/dist/components/core/extension/solid-core/CustomIcon/StatusIcon.tsx +17 -0
  113. package/dist/components/core/extension/solid-core/dashboardQuestion/ChartFormPreviewWidget.tsx +36 -0
  114. package/dist/components/core/extension/solid-core/emailTemplate/emailFormTypeChangeHandler.ts +18 -0
  115. package/dist/components/core/extension/solid-core/emailTemplate/emailFormTypeLoad.ts +18 -0
  116. package/dist/components/core/extension/solid-core/modelMetadata/list/DeleteModelRowAction.tsx +114 -0
  117. package/dist/components/core/extension/solid-core/modelMetadata/list/GenerateModelCodeRowAction.tsx +213 -0
  118. package/dist/components/core/extension/solid-core/moduleMetadata/list/DeleteModuleRowAction.tsx +138 -0
  119. package/dist/components/core/extension/solid-core/moduleMetadata/list/GenerateModuleCodeRowAction.tsx +209 -0
  120. package/dist/components/core/extension/solid-core/roleMetadata/RolePermissionsManyToManyFieldWidget.tsx +131 -0
  121. package/dist/components/core/field/FieldListViewData.tsx +313 -0
  122. package/dist/components/core/filter/SolidBooleanFilterElement.tsx +30 -0
  123. package/dist/components/core/filter/SolidFilterFields.tsx +131 -0
  124. package/dist/components/core/filter/SolidManyToManyFilterElement.tsx +64 -0
  125. package/dist/components/core/filter/SolidManyToOneFilterElement.tsx +61 -0
  126. package/dist/components/core/filter/SolidSelectionDynamicFilterElement.tsx +50 -0
  127. package/dist/components/core/filter/SolidSelectionStaticFilterElement.tsx +32 -0
  128. package/dist/components/core/filter/SolidVarInputsFilterElement.tsx +209 -0
  129. package/dist/components/core/filter/fields/SolidBigintField.tsx +9 -0
  130. package/dist/components/core/filter/fields/SolidBooleanField.tsx +68 -0
  131. package/dist/components/core/filter/fields/SolidComputedField.tsx +23 -0
  132. package/dist/components/core/filter/fields/SolidDateField.tsx +63 -0
  133. package/dist/components/core/filter/fields/SolidDatetimeField.tsx +54 -0
  134. package/dist/components/core/filter/fields/SolidDecimalField.tsx +9 -0
  135. package/dist/components/core/filter/fields/SolidExternalIdField.tsx +52 -0
  136. package/dist/components/core/filter/fields/SolidFloatField.tsx +9 -0
  137. package/dist/components/core/filter/fields/SolidIdField.tsx +46 -0
  138. package/dist/components/core/filter/fields/SolidIntField.tsx +61 -0
  139. package/dist/components/core/filter/fields/SolidLongTextField.tsx +9 -0
  140. package/dist/components/core/filter/fields/SolidMediaMultipleField.tsx +60 -0
  141. package/dist/components/core/filter/fields/SolidMediaSingleField.tsx +62 -0
  142. package/dist/components/core/filter/fields/SolidRelationField.tsx +17 -0
  143. package/dist/components/core/filter/fields/SolidRichTextField.tsx +9 -0
  144. package/dist/components/core/filter/fields/SolidSelectionDynamicField.tsx +52 -0
  145. package/dist/components/core/filter/fields/SolidSelectionStaticField.tsx +54 -0
  146. package/dist/components/core/filter/fields/SolidShortTextField.tsx +60 -0
  147. package/dist/components/core/filter/fields/SolidTimeField.tsx +48 -0
  148. package/dist/components/core/filter/fields/SolidUuidField.tsx +51 -0
  149. package/dist/components/core/filter/fields/relations/SolidRelationManyToManyField.tsx +62 -0
  150. package/dist/components/core/filter/fields/relations/SolidRelationManyToOneField.tsx +84 -0
  151. package/dist/components/core/form/SolidFormActionHeader.tsx +497 -0
  152. package/dist/components/core/form/SolidFormFieldRender.tsx +53 -0
  153. package/dist/components/core/form/SolidFormFieldRenderExtension.tsx +26 -0
  154. package/dist/components/core/form/SolidFormFooter.tsx +162 -0
  155. package/dist/components/core/form/SolidFormLayouts.tsx +104 -0
  156. package/dist/components/core/form/SolidFormUserViewLayout.tsx +84 -0
  157. package/dist/components/core/form/SolidFormView.tsx +1856 -0
  158. package/dist/components/core/form/SolidFormViewContextMenuHeaderButton.tsx +52 -0
  159. package/dist/components/core/form/SolidFormViewNormalHeaderButton.tsx +52 -0
  160. package/dist/components/core/form/SolidFormViewShimmerLoading.tsx +109 -0
  161. package/dist/components/core/form/fields/ISolidField.tsx +71 -0
  162. package/dist/components/core/form/fields/SolidBooleanField.tsx +434 -0
  163. package/dist/components/core/form/fields/SolidDateField.tsx +247 -0
  164. package/dist/components/core/form/fields/SolidDateTimeField.tsx +229 -0
  165. package/dist/components/core/form/fields/SolidDecimalField.tsx +171 -0
  166. package/dist/components/core/form/fields/SolidEmailField.tsx +176 -0
  167. package/dist/components/core/form/fields/SolidIntegerField.tsx +282 -0
  168. package/dist/components/core/form/fields/SolidJsonField.tsx +185 -0
  169. package/dist/components/core/form/fields/SolidLongTextField.tsx +618 -0
  170. package/dist/components/core/form/fields/SolidMediaMultipleField.tsx +663 -0
  171. package/dist/components/core/form/fields/SolidMediaSingleField.tsx +547 -0
  172. package/dist/components/core/form/fields/SolidPasswordField.tsx +390 -0
  173. package/dist/components/core/form/fields/SolidRelationField.tsx +56 -0
  174. package/dist/components/core/form/fields/SolidRichTextField.tsx +188 -0
  175. package/dist/components/core/form/fields/SolidSelectionDynamicField.tsx +340 -0
  176. package/dist/components/core/form/fields/SolidSelectionStaticField.tsx +462 -0
  177. package/dist/components/core/form/fields/SolidShortTextField.tsx +399 -0
  178. package/dist/components/core/form/fields/SolidTimeField.tsx +245 -0
  179. package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.tsx +453 -0
  180. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +1036 -0
  181. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.tsx +627 -0
  182. package/dist/components/core/form/fields/relations/widgets/helpers/InlineRelationEntityDialog.tsx +38 -0
  183. package/dist/components/core/form/fields/relations/widgets/helpers/useRelationEntityHandler.ts +64 -0
  184. package/dist/components/core/form/fields/widgets/SolidAiInteractionMessageFieldFormWidget.tsx +135 -0
  185. package/dist/components/core/form/fields/widgets/SolidAiInteractionMetadataFieldFormWidget.tsx +144 -0
  186. package/dist/components/core/form/fields/widgets/SolidIconEditWidget.tsx +265 -0
  187. package/dist/components/core/form/fields/widgets/SolidIconViewWidget.tsx +32 -0
  188. package/dist/components/core/form/fields/widgets/SolidRelationFieldAvatarFormWidget.tsx +50 -0
  189. package/dist/components/core/form/fields/widgets/SolidS3FileViewerWidget.tsx +222 -0
  190. package/dist/components/core/form/fields/widgets/SolidShortTextFieldAvatarWidget.tsx +70 -0
  191. package/dist/components/core/form/widgets/CustomHtml.tsx +20 -0
  192. package/dist/components/core/kanban/KanbanBoard.tsx +150 -0
  193. package/dist/components/core/kanban/KanbanCard.tsx +279 -0
  194. package/dist/components/core/kanban/KanbanColumn.tsx +139 -0
  195. package/dist/components/core/kanban/KanbanUserViewLayout.tsx +84 -0
  196. package/dist/components/core/kanban/SolidKanbanView.tsx +894 -0
  197. package/dist/components/core/kanban/SolidKanbanViewConfigure.tsx +154 -0
  198. package/dist/components/core/kanban/SolidKanbanViewFields.tsx +164 -0
  199. package/dist/components/core/kanban/SolidManyToOneFilterElement.tsx +59 -0
  200. package/dist/components/core/kanban/SolidSelectionDynamicFilterElement.tsx +50 -0
  201. package/dist/components/core/kanban/SolidSelectionStaticFilterElement.tsx +32 -0
  202. package/dist/components/core/kanban/SolidVarInputsFilterElement.tsx +184 -0
  203. package/dist/components/core/kanban/kanban-fields/SolidBigintKanbanField.tsx +9 -0
  204. package/dist/components/core/kanban/kanban-fields/SolidBooleanKanbanField.tsx +16 -0
  205. package/dist/components/core/kanban/kanban-fields/SolidComputedKanbanField.tsx +23 -0
  206. package/dist/components/core/kanban/kanban-fields/SolidDateKanbanField.tsx +14 -0
  207. package/dist/components/core/kanban/kanban-fields/SolidDatetimeKanbanField.tsx +13 -0
  208. package/dist/components/core/kanban/kanban-fields/SolidDecimalKanbanField.tsx +9 -0
  209. package/dist/components/core/kanban/kanban-fields/SolidExternalIdKanbanField.tsx +12 -0
  210. package/dist/components/core/kanban/kanban-fields/SolidFloatKanbanField.tsx +9 -0
  211. package/dist/components/core/kanban/kanban-fields/SolidIdKanbanField.tsx +14 -0
  212. package/dist/components/core/kanban/kanban-fields/SolidIntKanbanField.tsx +20 -0
  213. package/dist/components/core/kanban/kanban-fields/SolidLongTextKanbanField.tsx +9 -0
  214. package/dist/components/core/kanban/kanban-fields/SolidMediaMultipleKanbanField.tsx +140 -0
  215. package/dist/components/core/kanban/kanban-fields/SolidMediaSingleKanbanField.tsx +164 -0
  216. package/dist/components/core/kanban/kanban-fields/SolidRelationKanbanField.tsx +13 -0
  217. package/dist/components/core/kanban/kanban-fields/SolidRichTextKanbanField.tsx +9 -0
  218. package/dist/components/core/kanban/kanban-fields/SolidSelectionDynamicKanbanField.tsx +14 -0
  219. package/dist/components/core/kanban/kanban-fields/SolidSelectionStaticKanbanField.tsx +14 -0
  220. package/dist/components/core/kanban/kanban-fields/SolidShortTextKanbanField.tsx +121 -0
  221. package/dist/components/core/kanban/kanban-fields/SolidTimeKanbanField.tsx +12 -0
  222. package/dist/components/core/kanban/kanban-fields/SolidUuidKanbanField.tsx +13 -0
  223. package/dist/components/core/kanban/kanban-fields/relations/SolidRelationManyToOneKanbanField.tsx +16 -0
  224. package/dist/components/core/list/ListViewRowActionPopup.tsx +41 -0
  225. package/dist/components/core/list/SolidColumnSelector/SolidListColumnSelector.tsx +242 -0
  226. package/dist/components/core/list/SolidEmptyListViewPlaceholder.tsx +111 -0
  227. package/dist/components/core/list/SolidListView.tsx +2007 -0
  228. package/dist/components/core/list/SolidListViewColumn.tsx +165 -0
  229. package/dist/components/core/list/SolidListViewConfigure.tsx +339 -0
  230. package/dist/components/core/list/SolidListViewHeaderButton.tsx +31 -0
  231. package/dist/components/core/list/SolidListViewHeaderContextMenuButton.tsx +30 -0
  232. package/dist/components/core/list/SolidListViewRowButtonContextMenu.tsx +41 -0
  233. package/dist/components/core/list/SolidListViewShimmerLoading.tsx +78 -0
  234. package/dist/components/core/list/SolidListingHeader.tsx +42 -0
  235. package/dist/components/core/list/SolidManyToOneFilterElement.tsx +60 -0
  236. package/dist/components/core/list/SolidSelectionDynamicFilterElement.tsx +50 -0
  237. package/dist/components/core/list/SolidSelectionStaticFilterElement.tsx +32 -0
  238. package/dist/components/core/list/SolidTableRowCell.tsx +35 -0
  239. package/dist/components/core/list/SolidVarInputsFilterElement.tsx +184 -0
  240. package/dist/components/core/list/columns/SolidBigintColumn.tsx +9 -0
  241. package/dist/components/core/list/columns/SolidBooleanColumn.tsx +90 -0
  242. package/dist/components/core/list/columns/SolidComputedColumn.tsx +27 -0
  243. package/dist/components/core/list/columns/SolidDateColumn.tsx +90 -0
  244. package/dist/components/core/list/columns/SolidDatetimeColumn.tsx +79 -0
  245. package/dist/components/core/list/columns/SolidDecimalColumn.tsx +9 -0
  246. package/dist/components/core/list/columns/SolidExternalIdColumn.tsx +80 -0
  247. package/dist/components/core/list/columns/SolidFloatColumn.tsx +9 -0
  248. package/dist/components/core/list/columns/SolidIdColumn.tsx +79 -0
  249. package/dist/components/core/list/columns/SolidIntColumn.tsx +87 -0
  250. package/dist/components/core/list/columns/SolidLongTextColumn.tsx +9 -0
  251. package/dist/components/core/list/columns/SolidMediaMultipleColumn.tsx +301 -0
  252. package/dist/components/core/list/columns/SolidMediaSingleColumn.tsx +170 -0
  253. package/dist/components/core/list/columns/SolidRelationColumn.tsx +21 -0
  254. package/dist/components/core/list/columns/SolidRichTextColumn.tsx +9 -0
  255. package/dist/components/core/list/columns/SolidSelectionDynamicColumn.tsx +80 -0
  256. package/dist/components/core/list/columns/SolidSelectionStaticColumn.tsx +81 -0
  257. package/dist/components/core/list/columns/SolidShortTextColumn.tsx +160 -0
  258. package/dist/components/core/list/columns/SolidTimeColumn.tsx +78 -0
  259. package/dist/components/core/list/columns/SolidUuidColumn.tsx +79 -0
  260. package/dist/components/core/list/columns/relations/SolidRelationManyToManyColumn.tsx +106 -0
  261. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.tsx +117 -0
  262. package/dist/components/core/list/columns/relations/SolidRelationOneToManyColumn.tsx +110 -0
  263. package/dist/components/core/list/widgets/SolidManyToManyRelationAvatarListWidget.tsx +30 -0
  264. package/dist/components/core/list/widgets/SolidManyToOneRelationAvatarListWidget.tsx +30 -0
  265. package/dist/components/core/list/widgets/SolidShortTextAvatarWidget.tsx +70 -0
  266. package/dist/components/core/list/widgets/SolidShortTextFieldImageRenderModeWidget.tsx +21 -0
  267. package/dist/components/core/locales/SolidChatterLocaleTabView.tsx +91 -0
  268. package/dist/components/core/locales/SolidLocale.tsx +127 -0
  269. package/dist/components/core/model/CreateModel.tsx +495 -0
  270. package/dist/components/core/model/FieldMetaData.tsx +263 -0
  271. package/dist/components/core/model/FieldMetaDataForm.tsx +3509 -0
  272. package/dist/components/core/model/FieldSelector.tsx +62 -0
  273. package/dist/components/core/model/ModelListViewData.tsx +384 -0
  274. package/dist/components/core/model/ModelMetaData.tsx +921 -0
  275. package/dist/components/core/module/CreateModule.tsx +617 -0
  276. package/dist/components/core/module/ModuleListViewData.tsx +431 -0
  277. package/dist/components/core/solid-ai/SolidAiMainWrapper.tsx +8 -0
  278. package/dist/components/core/solid-ai/SolidXAIIcon.tsx +37 -0
  279. package/dist/components/core/users/CreateUser.tsx +467 -0
  280. package/dist/components/core/users/CreateUserRole.tsx +212 -0
  281. package/dist/components/core/users/UserListView.tsx +376 -0
  282. package/dist/components/layout/AdminLayout.tsx +57 -0
  283. package/dist/components/layout/AdminSidebar.tsx +65 -0
  284. package/dist/components/layout/AppConfig.tsx +104 -0
  285. package/dist/components/layout/AppSidebar.tsx +232 -0
  286. package/dist/components/layout/ButtonLoader.tsx +7 -0
  287. package/dist/components/layout/CustomPagination.tsx +55 -0
  288. package/dist/components/layout/DashboardHeader.tsx +89 -0
  289. package/dist/components/layout/FilterMenu.tsx +122 -0
  290. package/dist/components/layout/Footer.tsx +13 -0
  291. package/dist/components/layout/GlobalSearch.tsx +37 -0
  292. package/dist/components/layout/Header.tsx +8 -0
  293. package/dist/components/layout/Layout.tsx +205 -0
  294. package/dist/components/layout/ListingHeader.tsx +204 -0
  295. package/dist/components/layout/Loader.tsx +16 -0
  296. package/dist/components/layout/UserSidebar.tsx +53 -0
  297. package/dist/components/layout/context/layoutcontext.tsx +52 -0
  298. package/dist/components/layout/navbar-one.tsx +258 -0
  299. package/dist/components/layout/navbar-two-menu.tsx +72 -0
  300. package/dist/components/layout/navbar-two.tsx +37 -0
  301. package/dist/components/layout/user-profile-menu.tsx +213 -0
  302. package/dist/components/layout/user-profile.tsx +7 -0
  303. package/dist/components/modelsComponents/filterIcon.tsx +9 -0
  304. package/dist/constants/error-messages.ts +238 -0
  305. package/dist/declarations.d.ts +22 -0
  306. package/dist/helpers/AppTitle.tsx +12 -0
  307. package/dist/helpers/ToastContainer.tsx +94 -0
  308. package/dist/helpers/autoCompleteVirtualScroll.ts +41 -0
  309. package/dist/helpers/countries.tsx +260 -0
  310. package/dist/helpers/downloadFileWithProgress.ts +91 -0
  311. package/dist/helpers/downloadMediaFile.tsx +21 -0
  312. package/dist/helpers/getAcceptedFileTypes.tsx +22 -0
  313. package/dist/helpers/getRandomColors.tsx +68 -0
  314. package/dist/helpers/helpers.ts +61 -0
  315. package/dist/helpers/hydrateRelationRules.ts +120 -0
  316. package/dist/helpers/permissions.ts +7 -0
  317. package/dist/helpers/registry.ts +337 -0
  318. package/dist/helpers/resendOtpHelper.tsx +5 -0
  319. package/dist/helpers/revalidate.ts +7 -0
  320. package/dist/helpers/rolesHelper.ts +17 -0
  321. package/dist/helpers/solidIcons.tsx +1831 -0
  322. package/dist/helpers/updatePasswordField.ts +41 -0
  323. package/dist/index.ts +421 -0
  324. package/dist/nextAuth/authProviders.d.ts.map +1 -1
  325. package/dist/nextAuth/authProviders.js +6 -5
  326. package/dist/nextAuth/authProviders.js.map +1 -1
  327. package/dist/nextAuth/authProviders.tsx +232 -0
  328. package/dist/nextAuth/handleLogout.tsx +39 -0
  329. package/dist/nextAuth/refreshAccessToken.tsx +28 -0
  330. package/dist/redux/api/aiInteractionApi.ts +59 -0
  331. package/dist/redux/api/authApi.ts +131 -0
  332. package/dist/redux/api/dashboardApi.ts +56 -0
  333. package/dist/redux/api/dashboardQuestionApi.ts +17 -0
  334. package/dist/redux/api/exportTemplateApi.tsx +59 -0
  335. package/dist/redux/api/fetchBaseQuery.tsx +118 -0
  336. package/dist/redux/api/fieldApi.ts +86 -0
  337. package/dist/redux/api/importTransactionApi.tsx +69 -0
  338. package/dist/redux/api/mediaApi.ts +55 -0
  339. package/dist/redux/api/mediaStorageProviderApi.ts +55 -0
  340. package/dist/redux/api/modelApi.ts +80 -0
  341. package/dist/redux/api/moduleApi.ts +72 -0
  342. package/dist/redux/api/permissionApi.ts +32 -0
  343. package/dist/redux/api/pincodeApi.tsx +56 -0
  344. package/dist/redux/api/roleApi.ts +58 -0
  345. package/dist/redux/api/solidActionApi.ts +66 -0
  346. package/dist/redux/api/solidChatterMessageApi.ts +25 -0
  347. package/dist/redux/api/solidEntityApi.tsx +164 -0
  348. package/dist/redux/api/solidMenuApi.ts +71 -0
  349. package/dist/redux/api/solidServiceApi.ts +31 -0
  350. package/dist/redux/api/solidSettingsApi.tsx +83 -0
  351. package/dist/redux/api/solidViewApi.ts +73 -0
  352. package/dist/redux/api/stateApi.tsx +56 -0
  353. package/dist/redux/api/testApi.ts +21 -0
  354. package/dist/redux/api/userApi.ts +135 -0
  355. package/dist/redux/features/authSlice.ts +19 -0
  356. package/dist/redux/features/dataViewSlice.ts +26 -0
  357. package/dist/redux/features/navbarSlice.ts +21 -0
  358. package/dist/redux/features/popupSlice.ts +37 -0
  359. package/dist/redux/features/settingsSlice.ts +60 -0
  360. package/dist/redux/features/themeSlice.ts +17 -0
  361. package/dist/redux/features/userSlice.ts +28 -0
  362. package/dist/redux/hooks/useSolidPopup.ts +20 -0
  363. package/dist/redux/store/defaultStoreConfig.ts +62 -0
  364. package/dist/styles.ts +4 -0
  365. package/dist/types/handlebars.d.ts +4 -0
  366. package/dist/types/index.d.ts +76 -0
  367. package/dist/types/layout.d.ts +94 -0
  368. package/dist/types/next-auth.d.ts +0 -0
  369. package/dist/types/next.d.ts +46 -0
  370. package/dist/types/solid-core.d.ts +320 -0
  371. package/package.json +1 -1
  372. package/src/components/auth/SolidLogin.tsx +26 -13
  373. package/src/nextAuth/authProviders.tsx +9 -5
@@ -0,0 +1,1856 @@
1
+ "use client";
2
+
3
+ import { permissionExpression } from "../../../helpers/permissions";
4
+ import { createSolidEntityApi } from "../../../redux/api/solidEntityApi";
5
+ import { useGetSolidViewLayoutQuery } from "../../../redux/api/solidViewApi";
6
+ import { useLazyCheckIfPermissionExistsQuery } from "../../../redux/api/userApi";
7
+ import { FetchBaseQueryError } from "@reduxjs/toolkit/dist/query";
8
+ import { useFormik } from "formik";
9
+ import { usePathname, useRouter, useSearchParams } from "next/navigation";
10
+ import "primeflex/primeflex.css";
11
+ import { Button } from "primereact/button";
12
+ import { Dialog } from "primereact/dialog";
13
+ import { TabPanel, TabView } from "primereact/tabview";
14
+ import { Toast } from "primereact/toast";
15
+ import qs from "qs";
16
+ import React, { ChangeEvent, useEffect, useMemo, useRef, useState } from "react";
17
+ import * as Yup from "yup";
18
+ import { FormikObject, ISolidField, SolidFieldProps } from "./fields/ISolidField";
19
+ import { SolidBooleanField } from "./fields/SolidBooleanField";
20
+ import { SolidDateField } from "./fields/SolidDateField";
21
+ import { SolidDateTimeField } from "./fields/SolidDateTimeField";
22
+ import { SolidDecimalField } from "./fields/SolidDecimalField";
23
+ import { SolidIntegerField } from "./fields/SolidIntegerField";
24
+ import { SolidJsonField } from "./fields/SolidJsonField";
25
+ import { SolidLongTextField } from "./fields/SolidLongTextField";
26
+ import { SolidMediaMultipleField } from "./fields/SolidMediaMultipleField";
27
+ import { SolidMediaSingleField } from "./fields/SolidMediaSingleField";
28
+ import { SolidRelationField } from "./fields/SolidRelationField";
29
+ import { SolidRichTextField } from "./fields/SolidRichTextField";
30
+ import { SolidSelectionDynamicField } from "./fields/SolidSelectionDynamicField";
31
+ import { SolidSelectionStaticField } from "./fields/SolidSelectionStaticField";
32
+ import { SolidShortTextField } from "./fields/SolidShortTextField";
33
+ import { SolidTimeField } from "./fields/SolidTimeField";
34
+ import { SolidUiEvent } from "../../../types";
35
+ import { getExtensionComponent, getExtensionFunction } from "../../../helpers/registry";
36
+ import { SolidFormWidgetProps, SolidLoadForm, SolidUiEventResponse } from "../../../types/solid-core";
37
+ import { SolidPasswordField } from "./fields/SolidPasswordField";
38
+ import { SolidEmailField } from "./fields/SolidEmailField";
39
+ import { Panel } from "primereact/panel";
40
+ import { SolidFormUserViewLayout } from "./SolidFormUserViewLayout";
41
+ import Lightbox from "yet-another-react-lightbox";
42
+ import Counter from "yet-another-react-lightbox/plugins/counter";
43
+ import Download from "yet-another-react-lightbox/plugins/download";
44
+ import Video from "yet-another-react-lightbox/plugins/video";
45
+ import "yet-another-react-lightbox/styles.css";
46
+ import "yet-another-react-lightbox/plugins/counter.css";
47
+ import { SolidFormActionHeader } from "./SolidFormActionHeader";
48
+ import { SolidFormViewShimmerLoading } from "./SolidFormViewShimmerLoading";
49
+ import { useSelector } from "react-redux";
50
+ import { hasAnyRole } from "../../../helpers/rolesHelper";
51
+ import SolidChatterLocaleTabView from "../locales/SolidChatterLocaleTabView";
52
+ import { ConfirmDialog } from "primereact/confirmdialog";
53
+ import { SolidXAIIcon } from "../solid-ai/SolidXAIIcon";
54
+ import { ERROR_MESSAGES } from "../../../constants/error-messages";
55
+ import { useLazyGetMcpUrlQuery, useLazyGetSolidSettingsQuery } from "../../../redux/api/solidSettingsApi";
56
+ import { SolidFormFooter } from "./SolidFormFooter";
57
+
58
+ export type SolidFormViewProps = {
59
+ moduleName: string;
60
+ modelName: string;
61
+ id: string;
62
+ embeded: boolean;
63
+ handlePopupClose?: any,
64
+ customCreateHandler?: any
65
+ inlineCreateAutoSave?: boolean,
66
+ customLayout?: any,
67
+ parentData?: any,
68
+ redirectToPath?: string,
69
+ onEmbeddedFormSave?: () => void,
70
+ };
71
+
72
+
73
+ interface ErrorResponseData {
74
+ message: string;
75
+ statusCode: number;
76
+ error: string;
77
+ }
78
+
79
+ const getLayoutFields = (node: any): any => {
80
+ let fields = [];
81
+
82
+ if (node.type === "field") {
83
+ fields.push(node);
84
+ }
85
+
86
+ if (node.children && Array.isArray(node.children)) {
87
+ for (const child of node.children) {
88
+ fields = fields.concat(getLayoutFields(child));
89
+ }
90
+ }
91
+
92
+ return fields;
93
+ }
94
+
95
+ export const getLayoutFieldsAsObject = (layout: any[]): any => {
96
+ const allFields = layout.flatMap(getLayoutFields);
97
+ return allFields.reduce((result, field) => {
98
+ if (field.attrs.name) {
99
+ result[field.attrs.name] = { ...field };
100
+ }
101
+ return result;
102
+ }, {});
103
+ }
104
+ export const getActualFieldMetadata = (key: string, solidFieldsMetadata: Record<string, any>) => {
105
+ if (solidFieldsMetadata[key]) {
106
+ return solidFieldsMetadata[key];
107
+ }
108
+
109
+ if (key.endsWith("Confirm")) {
110
+ const baseKey = key.slice(0, -"Confirm".length); // Remove "Confirm"
111
+ if (solidFieldsMetadata[baseKey]) {
112
+ return solidFieldsMetadata[baseKey];
113
+ }
114
+ }
115
+
116
+ return null; // or handle fallback
117
+ };
118
+
119
+
120
+ const fieldFactory = (type: string, fieldContext: SolidFieldProps, setLightboxUrls?: any, setOpenLightbox?: any): ISolidField | null => {
121
+ if (type === 'shortText') {
122
+ return new SolidShortTextField(fieldContext);
123
+ }
124
+ if (type === 'longText') {
125
+ return new SolidLongTextField(fieldContext);
126
+ }
127
+ if (type === 'int' || type === 'bigint') {
128
+ return new SolidIntegerField(fieldContext);
129
+ }
130
+ if (type === 'decimal' || type === 'float') {
131
+ return new SolidDecimalField(fieldContext);
132
+ }
133
+ if (type === 'boolean') {
134
+ return new SolidBooleanField(fieldContext);
135
+ }
136
+ if (type === 'richText') {
137
+ return new SolidRichTextField(fieldContext);
138
+ }
139
+ if (type === 'date') {
140
+ return new SolidDateField(fieldContext);
141
+ }
142
+ if (type === 'datetime') {
143
+ return new SolidDateTimeField(fieldContext);
144
+ }
145
+ if (type === 'time') {
146
+ return new SolidTimeField(fieldContext);
147
+ }
148
+ if (type === 'json') {
149
+ return new SolidJsonField(fieldContext);
150
+ }
151
+ if (type === 'selectionStatic') {
152
+ return new SolidSelectionStaticField(fieldContext);
153
+ }
154
+ if (type === 'selectionDynamic') {
155
+ return new SolidSelectionDynamicField(fieldContext);
156
+ }
157
+ if (type === 'relation') {
158
+ return new SolidRelationField(fieldContext);
159
+ }
160
+ if (type === 'mediaSingle') {
161
+ return new SolidMediaSingleField(fieldContext, setLightboxUrls, setOpenLightbox);
162
+ }
163
+ if (type === 'mediaMultiple') {
164
+ return new SolidMediaMultipleField(fieldContext, setLightboxUrls, setOpenLightbox);
165
+ }
166
+ if (type === 'password') {
167
+ return new SolidPasswordField(fieldContext);
168
+ }
169
+ if (type === 'email') {
170
+ return new SolidEmailField(fieldContext);
171
+ }
172
+ return null;
173
+ }
174
+
175
+ // solidFieldsMetadata={solidFieldsMetadata} solidView={solidView}
176
+ const SolidField = ({ formik, field, fieldMetadata, initialEntityData, solidFormViewMetaData, modelName, readOnly, viewMode, onChange, onBlur, parentData, setLightboxUrls, setOpenLightbox, onEmbeddedFormSave }: any) => {
177
+ const fieldContext: SolidFieldProps = {
178
+ // field metadata - coming from the field-metadata table.
179
+ fieldMetadata: fieldMetadata,
180
+ // field layout - coming from view.layout
181
+ field: field,
182
+ // initial data
183
+ data: initialEntityData,
184
+ // complete form view metadata - this includes layout of the whole form & metadata about all fields in the corresponding model.
185
+ solidFormViewMetaData: solidFormViewMetaData,
186
+ modelName: modelName,
187
+ readOnly: readOnly,
188
+ viewMode: viewMode,
189
+ onChange: onChange,
190
+ onBlur: onBlur
191
+ }
192
+ if (parentData) {
193
+ fieldContext.parentData = parentData;
194
+ }
195
+ if (onEmbeddedFormSave) {
196
+ fieldContext.onEmbeddedFormSave = onEmbeddedFormSave;
197
+ }
198
+ const solidField = fieldFactory(fieldMetadata?.type, fieldContext, setLightboxUrls, setOpenLightbox);
199
+
200
+ return solidField?.render(formik);
201
+ };
202
+
203
+ const SolidGroup = ({ children, attrs }: any) => {
204
+
205
+ const className = attrs.className;
206
+
207
+ return (
208
+ <div className={className}>
209
+ {attrs.label && <p>{attrs.label}</p>}
210
+ <div className="grid">{children}</div>
211
+ </div>
212
+ // <div className={className}>
213
+ // <div className="s_group">
214
+ // <fieldset>
215
+ // {attrs.label && <p className="s_group_heading">{attrs.label}</p>}
216
+ // <div className="grid">{children}</div>
217
+ // </fieldset>
218
+ // </div>
219
+
220
+ // </div>
221
+ // <div className="formgrid grid">
222
+ // {children}
223
+ // </div>
224
+ );
225
+ };
226
+
227
+ const SolidRow = ({ children, attrs }: any) => {
228
+
229
+ const className = attrs.className;
230
+
231
+ return (
232
+ // <div className={`row ${className}`}>
233
+
234
+ // <div className="s_group">
235
+ // <fieldset>
236
+ // {attrs.label && <p className="s_group_heading">{attrs.label}</p>}
237
+ // <div className="grid">{children}</div>
238
+ // </fieldset>
239
+ // </div>
240
+
241
+ // </div>
242
+ <div className={`row ${className}`}>
243
+ {attrs.label && <p >{attrs.label}</p>}
244
+ <div className="grid">{children}</div>
245
+ </div>
246
+ // <div>{children}</div>
247
+ );
248
+ };
249
+
250
+ const SolidColumn = ({ children, attrs }: any) => {
251
+ const className = attrs.className;
252
+
253
+ return (
254
+ // first fieldset ui
255
+
256
+ // <div className={`${className}`}>
257
+ // <div className="s_group">
258
+ // <fieldset>
259
+ // {attrs.label && <p className="s_group_heading">{attrs.label}</p>}
260
+ // <div className="grid">{children}</div>
261
+ // </fieldset>
262
+ // </div>
263
+ // </div>
264
+
265
+ //second fieldset ui
266
+ // <div className={`${className}`}>
267
+ // {attrs.label && <p>{attrs.label}</p>}
268
+ // <div className="grid">{children}</div>
269
+ // </div>
270
+
271
+ //figma fieldset ui
272
+ attrs.label ?
273
+ <div className={`${className}`}>
274
+ <Panel header={attrs.label} className="solid-column-panel">
275
+ <div className="grid">{children}</div>
276
+ </Panel>
277
+ {/* <div className="p-fieldset">
278
+ <div className="solid-fieldset-header">
279
+ <div>{attrs.label}</div>
280
+ </div>
281
+ <div className="grid solid-fieldset-content">{children}</div>
282
+ </div> */}
283
+ </div>
284
+ :
285
+ <div className={`${className}`}>
286
+ <div className="grid">{children}</div>
287
+ </div>
288
+ );
289
+ };
290
+
291
+ const SolidSheet = ({ children }: any) => (
292
+ <div className="p-fluid p-grid">
293
+ {children}
294
+ </div>
295
+ );
296
+
297
+ const SolidNotebook = ({ children, activeTab, embeded }: any) => {
298
+ // const childrenArray = children;
299
+ // const childrenArray = React.Children.toArray(children).filter(Boolean);
300
+ const childrenArray = React.Children.toArray(children).filter(child => !!child);
301
+
302
+ const router = useRouter();
303
+
304
+ // Local state to manage active tab in embedded context
305
+ const [localActiveTab, setLocalActiveTab] = useState(activeTab);
306
+
307
+ const activeIndex = useMemo(() => {
308
+ return childrenArray.findIndex((child: any) => {
309
+ return child.key === (embeded ? localActiveTab : activeTab);
310
+ });
311
+ }, [childrenArray, activeTab, localActiveTab, embeded]);
312
+
313
+ const handleTabChange = (e: any) => {
314
+ const selectedChild = childrenArray[e.index] as any;
315
+ const newTabLabel = selectedChild?.key;
316
+
317
+ if (newTabLabel) {
318
+ if (!embeded) {
319
+ const currentUrl = new URL(window.location.href);
320
+ currentUrl.searchParams.set('activeTab', newTabLabel);
321
+ const updatedPath = currentUrl.toString();
322
+ router.push(updatedPath);
323
+ } else {
324
+ // Update the active tab state locally for embedded view
325
+ setLocalActiveTab(newTabLabel);
326
+ }
327
+ }
328
+ };
329
+
330
+
331
+ return (
332
+ <div className="solid-tab-view w-full">
333
+ <TabView activeIndex={activeIndex >= 0 ? activeIndex : 0} onTabChange={handleTabChange}>
334
+ {/* {children} */}
335
+ {childrenArray}
336
+ </TabView>
337
+ </div>
338
+ )
339
+ };
340
+
341
+ const SolidDynamicWidget = ({ widgetName, formik, field, solidFormViewMetaData, solidFormViewData }: any) => {
342
+ const solidView = solidFormViewMetaData.data.solidView;
343
+ const solidFieldsMetadata = solidFormViewMetaData.data.solidFieldsMetadata;
344
+
345
+ let DynamicWidget = getExtensionComponent(widgetName);
346
+
347
+ const widgetProps: SolidFormWidgetProps = {
348
+ formData: formik.values,
349
+ field: field,
350
+ fieldsMetadata: solidFieldsMetadata,
351
+ viewMetadata: solidView,
352
+ formViewData: solidFormViewData
353
+ }
354
+
355
+ return (
356
+ <div className="solid-tab-view w-full">
357
+ {DynamicWidget && <DynamicWidget {...widgetProps} />}
358
+ </div>
359
+ )
360
+ };
361
+
362
+
363
+ const SolidPage = ({ attrs, children, key, formik, fields }: any) => {
364
+ const fieldsName = fields.map((f: any) => f.attrs.name);
365
+ const errorCount = formik.submitCount > 0 ? fieldsName.filter((name: any) => !!formik.errors[name]).length : 0;
366
+ const label = (
367
+ <span style={{ color: errorCount > 0 ? 'red' : 'inherit' }}>
368
+ {attrs.label}{errorCount > 0 && ` (${errorCount})`}
369
+ </span>
370
+ );
371
+
372
+
373
+ return (
374
+
375
+ <TabPanel key={key} header={label} >
376
+ <div className="p-fluid">{children}</div>
377
+ </TabPanel>
378
+ )
379
+
380
+ };
381
+
382
+ // Original code...
383
+ // const addLevelToGroups = (layout: any, level = 1) => {
384
+ // return layout.map((element: any) => {
385
+ // if (element.type === "group") {
386
+ // // Add the level to the group's attrs
387
+ // element.attrs = {
388
+ // ...element.attrs,
389
+ // level: level, // Add level information to the attrs
390
+ // // className: level === 1 ? 'col-12' : 'col-6', // Assign className based on level
391
+ // };
392
+ // } else {
393
+ // element.children = addLevelToGroups(element.children, level);
394
+ // }
395
+ // // If the element has children, recursively apply this logic
396
+ // // if (element.children) {
397
+ // // element.children = addLevelToGroups(element.children, level + 1);
398
+ // // }
399
+
400
+ // return element;
401
+ // });
402
+ // };
403
+
404
+ // Fix for immutable objects.
405
+ // const addLevelToGroups = (layout: any, level = 1): any[] => {
406
+ // return layout.map((element: any) => {
407
+ // // Create a new object for immutability
408
+ // const updatedElement = { ...element };
409
+
410
+ // if (updatedElement.type === "group") {
411
+ // // Add level to attrs, creating a new object for immutability
412
+ // updatedElement.attrs = {
413
+ // ...updatedElement.attrs,
414
+ // level: level, // Add level information
415
+ // };
416
+ // }
417
+
418
+ // // If the element has children, recursively apply this logic
419
+ // if (updatedElement.children) {
420
+ // updatedElement.children = addLevelToGroups(updatedElement.children, level + 1);
421
+ // }
422
+
423
+ // return updatedElement;
424
+ // });
425
+ // };
426
+
427
+ const SolidFormView = (params: SolidFormViewProps) => {
428
+ const { user } = useSelector((state: any) => state.auth);
429
+ const pathname = usePathname();
430
+ const router = useRouter();
431
+ const toast = useRef<Toast>(null);
432
+ const searchParams = useSearchParams();
433
+ const [confirmVisible, setConfirmVisible] = useState(false);
434
+ const confirmResolveRef = useRef<(value: boolean) => void>();
435
+ const [redirectToList, setRedirectToList] = useState(false);
436
+ const [selectedLocale, setSelectedLocale] = useState<string | null>('en');
437
+ const [defaultEntityLocaleId, setDefaultEntityLocaleId] = useState<string | null>(null);
438
+ const [isDeleteDialogVisible, setDeleteDialogVisible] = useState(false);
439
+ const [isLayoutDialogVisible, setLayoutDialogVisible] = useState(false);
440
+ const [published, setPublished] = useState<string | null>(null);
441
+ const [actionsAllowed, setActionsAllowed] = useState<string[]>([]);
442
+ const [viewMode, setViewMode] = useState<"view" | "edit">(params.embeded === true ? "edit" : "view");
443
+ const [createMode, setCreateMode] = useState<boolean>(false);
444
+ const [openLightbox, setOpenLightbox] = useState(false);
445
+ const [lightboxUrls, setLightboxUrls] = useState([]);
446
+ const [isShowChatter, setShowChatter] = useState(false);
447
+ const [chatterLocaleWidth, setChatterLocaleWidth] = useState(380); // default width
448
+ const [isResizingChatterLocale, setIsResizingChatterLocale] = useState(false);
449
+
450
+ const [solidWorkflowFieldValue, setSolidWorkflowFieldValue] = useState<string>("");
451
+ const [defaultTabViewOptionIndex, setDefaultTabViewOptionIndex] = useState<number>(1);
452
+ const errorFields: string[] = [];
453
+
454
+ const [triggerCheckIfPermissionExists] = useLazyCheckIfPermissionExistsQuery();
455
+
456
+ const [mcpUrl, setMcpUrl] = useState<string | null>(null);
457
+ const [getMcpUrl] = useLazyGetMcpUrlQuery();
458
+
459
+ // when rendering the form view we will optionally get action params...
460
+ // these we can bubble up in the event that is being raised onFormLayoutLoad, onFormDataLoad & onFormLoad
461
+ const actionName = searchParams.get('actionName');
462
+ const actionType = searchParams.get('actionType');
463
+ const actionContext = searchParams.get('actionContext');
464
+
465
+ const [trigger, { data: solidSettingsData }] = useLazyGetSolidSettingsQuery();
466
+ useEffect(() => {
467
+ trigger("") // Fetch settings on mount
468
+ }, [])
469
+
470
+ useEffect(() => {
471
+ if (solidSettingsData?.data?.mcpEnabled && solidSettingsData?.data?.mcpServerUrl) {
472
+ enableSolidXAiPanel();
473
+ }
474
+ }, [solidSettingsData]);
475
+
476
+
477
+ const enableSolidXAiPanel = async () => {
478
+ try {
479
+ const queryData = {
480
+ showHeader: "false",
481
+ inListView: "false"
482
+ };
483
+ const queryString = qs.stringify({ ...queryData }, { encodeValuesOnly: true });
484
+ const response = await getMcpUrl(queryString).unwrap();
485
+ console.log("response", response);
486
+ if (response && response?.data?.mcpUrl) {
487
+ setMcpUrl(response?.data?.mcpUrl);
488
+ }
489
+ } catch (error) {
490
+
491
+ }
492
+ }
493
+
494
+ const op = useRef(null);
495
+ useEffect(() => {
496
+ const stored = localStorage.getItem('chatter_locale_width');
497
+ if (stored) {
498
+ setChatterLocaleWidth(parseInt(stored, 10));
499
+ }
500
+ }, []);
501
+ useEffect(() => {
502
+ const handleMouseMove = (e: MouseEvent) => {
503
+ if (!isResizingChatterLocale) return;
504
+ const newWidth = window.innerWidth - e.clientX;
505
+ const clampedWidth = Math.max(280, Math.min(newWidth, 700));
506
+ setChatterLocaleWidth(clampedWidth);
507
+ localStorage.setItem('chatter_locale_width', clampedWidth.toString());
508
+ };
509
+
510
+ const handleMouseUp = () => {
511
+ setIsResizingChatterLocale(false);
512
+ };
513
+
514
+ if (isResizingChatterLocale) {
515
+ window.addEventListener('mousemove', handleMouseMove);
516
+ window.addEventListener('mouseup', handleMouseUp);
517
+ }
518
+
519
+ return () => {
520
+ window.removeEventListener('mousemove', handleMouseMove);
521
+ window.removeEventListener('mouseup', handleMouseUp);
522
+ };
523
+ }, [isResizingChatterLocale]);
524
+
525
+
526
+ useEffect(() => {
527
+ const mode = searchParams.get('viewMode');
528
+ const locale = searchParams.get('locale');
529
+ const defaultEntityLocaleIdn = searchParams.get('defaultEntityLocaleId');
530
+ if (params.id === 'new' && !locale) {
531
+ setViewMode('edit');
532
+ setCreateMode(true);
533
+ return;
534
+ }
535
+
536
+ if (locale) {
537
+ setSelectedLocale(locale);
538
+ }
539
+
540
+ if (defaultEntityLocaleIdn) {
541
+ setDefaultEntityLocaleId(defaultEntityLocaleIdn);
542
+ }
543
+
544
+ // Set the viewMode based on the URL
545
+ if (mode === 'view' || mode === 'edit') {
546
+ setViewMode(mode);
547
+ } else {
548
+ setViewMode('view'); // Default to 'view' if no valid mode is provided
549
+ }
550
+ }, [searchParams, params.id]);
551
+
552
+ // function that updates view mode
553
+ const updateViewMode = (newMode: "view" | "edit") => {
554
+ setViewMode(newMode);
555
+ const params = new URLSearchParams(searchParams.toString());
556
+ params.set("viewMode", newMode);
557
+ router.push(`${pathname}?${params.toString()}`, { scroll: false });
558
+ };
559
+
560
+ useEffect(() => {
561
+ const fetchPermissions = async () => {
562
+ if (params.modelName) {
563
+ const permissionNames = [
564
+ permissionExpression(params.modelName, 'create'),
565
+ permissionExpression(params.modelName, 'delete'),
566
+ permissionExpression(params.modelName, 'update'),
567
+ permissionExpression(params.modelName, 'findOne'),
568
+ permissionExpression(params.modelName, 'publish'),
569
+ permissionExpression(params.modelName, 'unpublish'),
570
+ permissionExpression('chatterMessage', 'findMany')
571
+ ]
572
+ const queryData = {
573
+ permissionNames: permissionNames
574
+ };
575
+ const queryString = qs.stringify(queryData, {
576
+ encodeValuesOnly: true
577
+ });
578
+ const response = await triggerCheckIfPermissionExists(queryString);
579
+ setActionsAllowed(response.data.data);
580
+ }
581
+ };
582
+ fetchPermissions();
583
+ }, [params.modelName]);
584
+
585
+ // Create the RTK slices for this entitor (const id of fieldValue) {
586
+ // if (!isInt(id)) {
587
+ // errors.push({ field: this.fieldMetadata.name, error: `Invalid ids in ${ commandFieldName } ` });
588
+ // }
589
+ // }y
590
+ const entityApi = createSolidEntityApi(params.modelName);
591
+ const {
592
+ useCreateSolidEntityMutation,
593
+ useDeleteSolidEntityMutation,
594
+ useGetSolidEntityByIdQuery,
595
+ useUpdateSolidEntityMutation,
596
+ usePatchUpdateSolidEntityMutation,
597
+ usePublishSolidEntityMutation,
598
+ useUnpublishSolidEntityMutation
599
+ } = entityApi;
600
+
601
+ const [
602
+ createEntity,
603
+ { isSuccess: isEntityCreateSuccess, isError: isEntityCreateError, error: entityCreateError },
604
+ ] = useCreateSolidEntityMutation();
605
+
606
+ const [
607
+ updateEntity,
608
+ { isSuccess: isEntityUpdateSuceess, isError: isEntityUpdateError, error: entityUpdateError },
609
+ ] = useUpdateSolidEntityMutation();
610
+
611
+ const [
612
+ deleteEntity,
613
+ { isSuccess: isEntityDeleteSuceess, isError: isEntityDeleteError, error: entityDeleteError },
614
+ ] = useDeleteSolidEntityMutation();
615
+
616
+ const [
617
+ patchEntity,
618
+ { isSuccess: isEntityPatchSuceess, isError: isEntityPatchError, error: entityPatchError },
619
+ ] = usePatchUpdateSolidEntityMutation();
620
+
621
+ const [
622
+ publishSolidEntity,
623
+ { isSuccess: isEntityPublishedSuccess, isError: isEntityPublishedError, error: entityPublishedError },
624
+ ] = usePublishSolidEntityMutation();
625
+
626
+ const [
627
+ unpublishSolidEntity,
628
+ { isSuccess: isEntityUnpublishedSuccess, isError: isEntityUnpublishedError, error: entityUnpublishedError },
629
+ ] = useUnpublishSolidEntityMutation();
630
+
631
+ // - - - - - - - - - - - -- - - - - - - - - - - - METADATA here
632
+ // Get the form view layout & metadata first.
633
+ const formViewMetaDataQs = qs.stringify({ ...params, viewType: 'form', defaultEntityLocaleId: defaultEntityLocaleId }, {
634
+ encodeValuesOnly: true,
635
+ });
636
+ const [formViewMetaData, setFormViewMetaData] = useState({});
637
+ const [formViewLayout, setFormViewLayout] = useState<any>(null);
638
+ const {
639
+ data: solidFormViewMetaData,
640
+ isLoading: solidFormViewMetaDataIsLoading
641
+ } = useGetSolidViewLayoutQuery(formViewMetaDataQs);
642
+ const [refreshChatterMessage, setRefreshChatterMessage] = useState<boolean>(true);
643
+ useEffect(() => {
644
+ if (
645
+ isEntityCreateSuccess == true ||
646
+ isEntityUpdateSuceess == true ||
647
+ isEntityDeleteSuceess == true ||
648
+ isEntityPatchSuceess == true ||
649
+ isEntityPublishedSuccess == true ||
650
+ isEntityUnpublishedSuccess == true
651
+ ) {
652
+ setRefreshChatterMessage(true);
653
+ if (params.embeded == true && params.onEmbeddedFormSave) {
654
+ params.onEmbeddedFormSave();
655
+ }
656
+ // Close The pop in case the form is used in embeded form
657
+ if (params.embeded == true) {
658
+ params.handlePopupClose()
659
+ }
660
+ if (redirectToList === true) {
661
+ if (params.redirectToPath) {
662
+ router.push(params.redirectToPath);
663
+ window.location.reload();
664
+ } else {
665
+ const segments = pathname.split('/').filter(Boolean); // Split and filter empty segments
666
+ const newPath = '/' + segments.slice(0, -2).join('/') + '/list'; // Remove last segment and add "/all"
667
+ router.push(newPath);
668
+ }
669
+ }
670
+ }
671
+ }, [isEntityCreateSuccess, isEntityUpdateSuceess, isEntityDeleteSuceess, isEntityPatchSuceess, isEntityPublishedSuccess, isEntityUnpublishedSuccess]);
672
+
673
+ useEffect(() => {
674
+
675
+ if (solidFormViewMetaData?.data?.solidView?.model?.internationalisation) {
676
+ setDefaultTabViewOptionIndex(0)
677
+ const matchedLocale = solidFormViewMetaData?.data?.applicableLocales?.find((x: any) => x.isDefault === 'yes');
678
+ //this is to attach default locale when adding data in popup view where relations exists
679
+ if (!selectedLocale && matchedLocale && !searchParams.get('locale')) {
680
+ setSelectedLocale(matchedLocale.locale);
681
+ }
682
+ }
683
+
684
+ }, [params.modelName, solidFormViewMetaData])
685
+
686
+ function isFetchBaseQueryErrorWithErrorResponse(error: any): error is FetchBaseQueryError & { data: ErrorResponseData } {
687
+ return error && typeof error === 'object' && 'data' in error && 'message' in error.data;
688
+ }
689
+
690
+ useEffect(() => {
691
+ const handleError = (errorToast: any) => {
692
+ let errorMessage: any = [ERROR_MESSAGES.ERROR_OCCURED];
693
+
694
+ if (isFetchBaseQueryErrorWithErrorResponse(errorToast)) {
695
+ errorMessage = errorToast.data.message;
696
+ } else {
697
+ errorMessage = [ERROR_MESSAGES.SOMETHING_WRONG];
698
+ }
699
+
700
+ toast.current?.show({
701
+ severity: 'error',
702
+ summary: 'Error',
703
+ detail: errorMessage,
704
+ sticky: true,
705
+ //@ts-ignore
706
+ content: () => (
707
+ <div className="flex flex-column align-items-left" style={{ flex: "1" }}>
708
+ {Array.isArray(errorMessage) ? (
709
+ errorMessage.map((message, index) => (
710
+ <div className="flex align-items-center gap-2" key={index}>
711
+ <span className="font-bold text-900">{message.trim()}</span>
712
+ </div>
713
+ ))
714
+ ) : (
715
+ <div className="flex align-items-center gap-2">
716
+ <span className="font-bold text-900">{errorMessage?.trim()}</span>
717
+ </div>
718
+ )}
719
+ </div>
720
+ ),
721
+ });
722
+ };
723
+
724
+ // Check and handle errors from each API operation
725
+ if (isEntityCreateError) {
726
+ handleError(entityCreateError);
727
+ } else if (isEntityDeleteError) {
728
+ handleError(entityDeleteError);
729
+ } else if (isEntityUpdateError) {
730
+ handleError(entityUpdateError);
731
+ } else if (isEntityPatchError) {
732
+ handleError(entityPatchError);
733
+ } else if (isEntityPublishedError) {
734
+ handleError(entityPublishedError);
735
+ } else if (isEntityUnpublishedError) {
736
+ handleError(entityUnpublishedError);
737
+ }
738
+ }, [
739
+ isEntityCreateError,
740
+ isEntityDeleteError,
741
+ isEntityUpdateError,
742
+ isEntityPatchError,
743
+ isEntityPublishedError,
744
+ isEntityUnpublishedError
745
+ ]);
746
+
747
+ const showToast = (severity: "success" | "error", summary: string, detail: string) => {
748
+ toast.current?.show({
749
+ severity,
750
+ summary,
751
+ detail,
752
+ ...(severity === "error"
753
+ ? { sticky: true } // stays until user closes
754
+ : { life: 3000 }),
755
+ });
756
+ };
757
+
758
+ const confirmDialogWithPromise = () => {
759
+ return new Promise<boolean>((resolve) => {
760
+ confirmResolveRef.current = resolve;
761
+ setConfirmVisible(true);
762
+ });
763
+ };
764
+
765
+ const onFormikSubmit = async (values: any) => {
766
+ const solidView = solidFormViewMetaData.data.solidView;
767
+ const solidFieldsMetadata = solidFormViewMetaData.data.solidFieldsMetadata;
768
+ const layoutFieldsObj = getLayoutFieldsAsObject([formViewLayout]);
769
+ try {
770
+ let formData = new FormData();
771
+
772
+ // Iterate through the keys in the values object
773
+ Object.entries(values).forEach(([key, value]) => {
774
+
775
+ const fieldMetadata = solidFieldsMetadata[key];
776
+ // const fieldMetadata = getActualFieldMetadata(key, solidFieldsMetadata);
777
+ const fieldContext: SolidFieldProps = {
778
+ fieldMetadata: fieldMetadata,
779
+ field: layoutFieldsObj[key],
780
+ data: initialEntityData,
781
+ solidFormViewMetaData: solidFormViewMetaData,
782
+ modelName: params.modelName
783
+ }
784
+ let solidField = fieldFactory(fieldMetadata?.type, fieldContext);
785
+ // Append each field to the FormData
786
+ if (value !== undefined && value !== null && solidField) {
787
+ solidField.updateFormData(value, formData);
788
+ }
789
+ if (value !== undefined && value !== null && key.endsWith("Confirm")) {
790
+ formData.append(key, String(value))
791
+ }
792
+
793
+ });
794
+
795
+ let solidWorkflowField = solidFormViewMetaData?.data?.solidView?.layout?.attrs?.workflowField;
796
+ if (params.id !== "new") {
797
+ if (solidFormViewMetaData?.data?.solidFormViewWorkflowData) {
798
+ if (solidFormViewMetaData?.data?.solidFieldsMetadata?.[solidWorkflowField]?.type === "selectionStatic") {
799
+ formData.append(solidWorkflowField, solidWorkflowFieldValue);
800
+ }
801
+ if (solidFormViewMetaData?.data?.solidFieldsMetadata?.[solidWorkflowField]?.type === "many-to-one") {
802
+ formData.append(`${solidWorkflowField}Id`, solidWorkflowFieldValue);
803
+ }
804
+ }
805
+ }
806
+ if (solidFormViewMetaData?.data?.solidView?.model?.internationalisation) {
807
+ if (selectedLocale && !formData.has('localeName')) {
808
+ formData.append('localeName', selectedLocale);
809
+ }
810
+ if (defaultEntityLocaleId) {
811
+ formData.append('defaultEntityLocaleId', defaultEntityLocaleId.toString());
812
+ }
813
+ }
814
+ if (solidFormViewMetaData?.data?.solidView?.model?.draftPublishWorkflow) {
815
+ if (published) {
816
+ formData.append('publishedAt', published);
817
+ }
818
+ }
819
+ if (params.inlineCreateAutoSave === true) {
820
+ params.customCreateHandler(formData);
821
+ } else {
822
+ if (params.id === 'new') {
823
+ // default locale
824
+ const result = await createEntity(formData).unwrap();
825
+ showToast("success", ERROR_MESSAGES.FORM_SAVED, ERROR_MESSAGES.FORM_SAVED_SUCCESSFULLY);
826
+ // if (!params.embeded && result?.data?.id) {
827
+ // const newPathname = pathname.replace(/new$/, result.data.id);
828
+
829
+ // const params = new URLSearchParams(searchParams.toString());
830
+ // params.set("viewMode", "view");
831
+
832
+ // const updatedUrl = `${newPathname}?${params.toString()}`;
833
+ // await router.push(updatedUrl, { scroll: false });
834
+
835
+ // setViewMode("view")
836
+ // }
837
+ if (!params.embeded) {
838
+ const currentUrl = new URL(window.location.href);
839
+ currentUrl.pathname = currentUrl.pathname.replace(/new$/, result?.data?.id);
840
+ currentUrl.searchParams.set('viewMode', 'view');
841
+ const updatedUrl = currentUrl.toString();
842
+ router.push(updatedUrl);
843
+ setViewMode("view")
844
+ }
845
+ return result;
846
+ }
847
+ else {
848
+ // updateEntity({ id: +params.id, data: formData });
849
+ const result = await updateEntity({ id: +params.id, data: formData }).unwrap();
850
+ // const result = await updateEntity({ id: +params.id, data: formData }).unwrap();
851
+ if (!params.embeded) {
852
+ showToast("success", ERROR_MESSAGES.FORM_UPDATE, ERROR_MESSAGES.FORM_UPDATE_SUCCESSFULLY);
853
+ if (result?.statusCode === 200) {
854
+ updateViewMode("view")
855
+ }
856
+ }
857
+ return result;
858
+
859
+ }
860
+ }
861
+
862
+ } catch (err) {
863
+ console.error(ERROR_MESSAGES.ENTITY_FAILED, err);
864
+ }
865
+ }
866
+
867
+ const showFieldError = () => {
868
+ if (errorFields?.length === 0) return;
869
+ errorFields.forEach((error) => {
870
+ toast?.current?.show({
871
+ severity: "error",
872
+ summary: "Metadata Error",
873
+ detail: error,
874
+ life: 3000,
875
+ });
876
+
877
+ });
878
+
879
+ // errorFields.length = 0;
880
+ };
881
+ useEffect(() => {
882
+ if (errorFields?.length > 0) {
883
+ showFieldError();
884
+ }
885
+ }, [errorFields])
886
+
887
+
888
+ // - - - - - - - - - - - -- - - - - - - - - - - - DATA here
889
+ // Fetch the actual data here.
890
+ // This is the initial value of this form, will come from an API call in the case of edit.
891
+ let layoutFields = [];
892
+ let toPopulate = [];
893
+ let toPopulateMedia = [];
894
+ if (solidFormViewMetaData && formViewLayout) {
895
+ const solidView = solidFormViewMetaData.data.solidView;
896
+ const solidFieldsMetadata = solidFormViewMetaData.data.solidFieldsMetadata;
897
+ layoutFields = [formViewLayout].flatMap(getLayoutFields);
898
+ for (let i = 0; i < layoutFields?.length; i++) {
899
+ const formLayoutField = layoutFields[i];
900
+ const fieldMetadata = solidFieldsMetadata[formLayoutField.attrs.name];
901
+ if (fieldMetadata?.type === 'relation') {
902
+ toPopulate.push(fieldMetadata.name);
903
+ }
904
+ if (fieldMetadata?.type === 'mediaSingle' || fieldMetadata?.type === 'mediaMultiple') {
905
+ toPopulateMedia.push(fieldMetadata.name);
906
+ }
907
+ }
908
+ if (formViewLayout.attrs?.workflowField && solidFieldsMetadata[formViewLayout.attrs.workflowField]?.type === 'relation' && solidFieldsMetadata[formViewLayout.attrs.workflowField]?.relationType === 'many-to-one') {
909
+ toPopulate.push(solidFieldsMetadata[formViewLayout.attrs.workflowField].name);
910
+ }
911
+ }
912
+ // TODO: Possible optimisation here, we are firing 2 queries to load the form view data object.
913
+ // once without populate & populateMedia and then again once after that.
914
+ const formViewDataQs = qs.stringify({ populate: toPopulate, populateMedia: toPopulateMedia }, {
915
+ encodeValuesOnly: true,
916
+ });
917
+ const [initialEntityData, setInitialEntityData] = useState({});
918
+ const {
919
+ data: solidFormViewData,
920
+ isLoading: solidFormViewDataIsLoading,
921
+ refetch: refetchSolidFormViewData,
922
+ } = useGetSolidEntityByIdQuery({ id: params.id, qs: formViewDataQs }, {
923
+ skip: params.id === 'new'
924
+ });
925
+ useEffect(() => {
926
+ if (params.id !== 'new') {
927
+ refetchSolidFormViewData()
928
+ }
929
+ }, [formViewDataQs])
930
+
931
+ useEffect(() => {
932
+ if (solidFormViewMetaData) {
933
+ if (params.customLayout) {
934
+ setFormViewLayout(params.customLayout);
935
+ } else {
936
+ setFormViewLayout(solidFormViewMetaData?.data?.solidView?.layout);
937
+ }
938
+ setPublished(solidFormViewData?.data?.publishedAt);
939
+ setFormViewMetaData(solidFormViewMetaData);
940
+ }
941
+ }, [solidFormViewMetaData]);
942
+
943
+ // useEffect(() => {
944
+ // const handleOnFormLayoutLoadEvent = async () => {
945
+ // if (solidFormViewMetaData) {
946
+ // // let formLayout = solidFormViewMetaData;
947
+ // // let customLayout = params?.customLayout;
948
+ // const onFormLayoutLoadHandlerExtensionFunction = solidFormViewMetaData?.data?.solidView?.layout?.onFormLayoutLoad;
949
+ // // let dynamicExtensionFunction = null;
950
+ // let formLayout = solidFormViewMetaData?.data?.solidView?.layout;
951
+ // if (params.customLayout) {
952
+ // formLayout = params.customLayout;
953
+ // }
954
+ // const event: SolidLoadForm = {
955
+ // parentData: params?.parentData,
956
+ // fieldsMetadata: solidFormViewMetaData,
957
+ // formData: solidFormViewData?.data,
958
+ // type: 'onFormLayoutLoad',
959
+ // viewMetadata: solidFormViewMetaData?.data?.solidView,
960
+ // formViewLayout: formLayout,
961
+ // queryParams: {
962
+ // actionName,
963
+ // actionType,
964
+ // actionContext
965
+ // }
966
+ // }
967
+ // if (onFormLayoutLoadHandlerExtensionFunction) {
968
+ // const dynamicExtensionFunction = getExtensionFunction(onFormLayoutLoadHandlerExtensionFunction);
969
+ // if (dynamicExtensionFunction) {
970
+ // try {
971
+ // const updatedFormLayout: SolidUiEventResponse = await dynamicExtensionFunction(event);
972
+ // if (updatedFormLayout && updatedFormLayout?.layoutChanged && updatedFormLayout?.newLayout) {
973
+ // setFormViewLayout(updatedFormLayout.newLayout);
974
+ // // const newFormLayout = {
975
+ // // ...formLayout,
976
+ // // data: {
977
+ // // ...formLayout.data,
978
+ // // solidView: {
979
+ // // ...formLayout.data.solidView,
980
+ // // layout: updatedFormLayout.newLayout
981
+ // // }
982
+ // // }
983
+ // // };
984
+ // // formLayout = newFormLayout;
985
+ // // customLayout = updatedFormLayout.newLayout;
986
+ // }
987
+ // } catch (error) {
988
+ // console.error(ERROR_MESSAGES.DYNAMIC_FUNCTION_ERROR, error);
989
+ // }
990
+ // }
991
+ // }
992
+ // // setFormViewMetaData(formLayout);
993
+ // // if (params.customLayout) {
994
+ // // setFormViewLayout(customLayout);
995
+ // // } else {
996
+ // // setFormViewLayout(formLayout.data.solidView.layout);
997
+ // // }
998
+ // }
999
+ // };
1000
+ // const handleOnFormDataLoadEvent = async () => {
1001
+ // const onFormDataLoadHandlerExtensionFunction = solidFormViewMetaData?.data?.solidView?.layout?.onFormDataLoad;
1002
+ // // let dynamicExtensionFunction = null;
1003
+ // let formViewData = solidFormViewData?.data;
1004
+
1005
+ // let formLayout = solidFormViewMetaData?.data?.solidView?.layout;
1006
+ // if (params.customLayout) {
1007
+ // formLayout = params.customLayout;
1008
+ // }
1009
+
1010
+ // const event: SolidLoadForm = {
1011
+ // fieldsMetadata: solidFormViewMetaData,
1012
+ // formData: solidFormViewData?.data,
1013
+ // type: "onFormDataLoad",
1014
+ // viewMetadata: solidFormViewMetaData?.data?.solidView,
1015
+ // formViewLayout: formLayout,
1016
+ // queryParams: {
1017
+ // actionName,
1018
+ // actionType,
1019
+ // actionContext
1020
+ // }
1021
+ // };
1022
+ // if (onFormDataLoadHandlerExtensionFunction) {
1023
+ // const dynamicExtensionFunction = getExtensionFunction(onFormDataLoadHandlerExtensionFunction);
1024
+ // if (dynamicExtensionFunction) {
1025
+ // const updatedFormData: SolidUiEventResponse = await dynamicExtensionFunction(event);
1026
+
1027
+ // if (updatedFormData && updatedFormData?.dataChanged && updatedFormData?.newFormData) {
1028
+ // formViewData = updatedFormData.newFormData;
1029
+ // }
1030
+ // }
1031
+ // if (formViewData) {
1032
+ // setInitialEntityData(formViewData);
1033
+ // }
1034
+ // }
1035
+ // };
1036
+ // const handleOnFormLoadEvent = async () => {
1037
+ // const onFormLoadHandlerExtensionFunction = solidFormViewMetaData?.data?.solidView?.layout?.onFormLoad;
1038
+ // // let dynamicExtensionFunction = null;
1039
+ // let localFormViewMetadata = solidFormViewMetaData;
1040
+ // // let customLayout = params?.customLayout;
1041
+ // let formViewData = solidFormViewData?.data;
1042
+
1043
+ // let formLayout = solidFormViewMetaData?.data?.solidView?.layout;
1044
+ // if (params.customLayout) {
1045
+ // formLayout = params.customLayout;
1046
+ // }
1047
+
1048
+ // const event: SolidLoadForm = {
1049
+ // parentData: params?.parentData,
1050
+ // fieldsMetadata: solidFormViewMetaData,
1051
+ // formData: solidFormViewData?.data,
1052
+ // type: 'onFormLoad',
1053
+ // viewMetadata: solidFormViewMetaData?.data?.solidView,
1054
+ // formViewLayout: formViewLayout,
1055
+ // queryParams: {
1056
+ // actionName,
1057
+ // actionType,
1058
+ // actionContext
1059
+ // }
1060
+ // };
1061
+
1062
+ // if (onFormLoadHandlerExtensionFunction) {
1063
+ // const dynamicExtensionFunction = getExtensionFunction(onFormLoadHandlerExtensionFunction);
1064
+ // if (dynamicExtensionFunction) {
1065
+ // try {
1066
+ // const result: SolidUiEventResponse = await dynamicExtensionFunction(event);
1067
+ // if (result && result?.layoutChanged && result?.newLayout) {
1068
+ // // const newLocalFormViewMetadata = {
1069
+ // // ...localFormViewMetadata,
1070
+ // // data: {
1071
+ // // ...localFormViewMetadata.data,
1072
+ // // solidView: {
1073
+ // // ...localFormViewMetadata.data.solidView,
1074
+ // // layout: result.newLayout
1075
+ // // }
1076
+ // // }
1077
+ // // };
1078
+ // // localFormViewMetadata = newLocalFormViewMetadata;
1079
+ // // customLayout = result.newLayout;
1080
+ // // setFormViewMetaData(localFormViewMetadata);
1081
+
1082
+ // setFormViewLayout(result.newLayout);
1083
+ // // if (params.customLayout) {
1084
+ // // setFormViewLayout(customLayout);
1085
+ // // } else {
1086
+ // // setFormViewLayout(localFormViewMetadata.data.solidView.layout);
1087
+ // // }
1088
+ // }
1089
+ // if (result && result?.dataChanged && result?.newFormData) {
1090
+ // formViewData = result.newFormData;
1091
+ // setInitialEntityData(formViewData);
1092
+ // }
1093
+ // } catch (error) {
1094
+ // console.error(ERROR_MESSAGES.ON_FORM_LOAD, error);
1095
+ // }
1096
+ // }
1097
+ // }
1098
+ // };
1099
+
1100
+ // handleOnFormLayoutLoadEvent();
1101
+ // handleOnFormDataLoadEvent();
1102
+ // handleOnFormLoadEvent();
1103
+ // }, [solidFormViewMetaData, solidFormViewData]);
1104
+
1105
+
1106
+ useEffect(() => {
1107
+ const runFormEvents = async () => {
1108
+ if (!solidFormViewMetaData) return;
1109
+
1110
+ /** ----------------------------
1111
+ * 1. Initialize working state
1112
+ * ----------------------------- */
1113
+ let workingLayout = params.customLayout ?? solidFormViewMetaData?.data?.solidView?.layout;
1114
+ let workingFormData = solidFormViewData?.data;
1115
+ const baseEvent = {
1116
+ parentData: params?.parentData,
1117
+ fieldsMetadata: solidFormViewMetaData,
1118
+ viewMetadata: solidFormViewMetaData?.data?.solidView,
1119
+ queryParams: {
1120
+ actionName,
1121
+ actionType,
1122
+ actionContext,
1123
+ },
1124
+ };
1125
+
1126
+ /** ----------------------------
1127
+ * 2. onFormLayoutLoad
1128
+ * ----------------------------- */
1129
+ const onFormLayoutLoadFn =
1130
+ solidFormViewMetaData?.data?.solidView?.layout?.onFormLayoutLoad;
1131
+
1132
+ if (onFormLayoutLoadFn) {
1133
+ const fn = getExtensionFunction(onFormLayoutLoadFn);
1134
+ if (fn) {
1135
+ try {
1136
+ const result: SolidUiEventResponse = await fn({
1137
+ ...baseEvent,
1138
+ type: "onFormLayoutLoad",
1139
+ formData: workingFormData,
1140
+ formViewLayout: workingLayout,
1141
+ });
1142
+
1143
+ if (result?.layoutChanged && result?.newLayout) {
1144
+ workingLayout = result.newLayout;
1145
+ }
1146
+ } catch (e) {
1147
+ console.error(ERROR_MESSAGES.DYNAMIC_FUNCTION_ERROR, e);
1148
+ }
1149
+ }
1150
+ }
1151
+
1152
+ /** ----------------------------
1153
+ * 3. onFormDataLoad
1154
+ * ----------------------------- */
1155
+ const onFormDataLoadFn =
1156
+ solidFormViewMetaData?.data?.solidView?.layout?.onFormDataLoad;
1157
+
1158
+ if (onFormDataLoadFn) {
1159
+ const fn = getExtensionFunction(onFormDataLoadFn);
1160
+ if (fn) {
1161
+ try {
1162
+ const result: SolidUiEventResponse = await fn({
1163
+ ...baseEvent,
1164
+ type: "onFormDataLoad",
1165
+ formData: workingFormData,
1166
+ formViewLayout: workingLayout, // ✅ UPDATED layout
1167
+ });
1168
+
1169
+ if (result?.dataChanged && result?.newFormData) {
1170
+ workingFormData = result.newFormData;
1171
+ }
1172
+ } catch (e) {
1173
+ console.error(ERROR_MESSAGES.DYNAMIC_FUNCTION_ERROR, e);
1174
+ }
1175
+ }
1176
+ }
1177
+
1178
+ /** ----------------------------
1179
+ * 4. onFormLoad
1180
+ * ----------------------------- */
1181
+ const onFormLoadFn =
1182
+ solidFormViewMetaData?.data?.solidView?.layout?.onFormLoad;
1183
+
1184
+ if (onFormLoadFn) {
1185
+ const fn = getExtensionFunction(onFormLoadFn);
1186
+ if (fn) {
1187
+ try {
1188
+ const result: SolidUiEventResponse = await fn({
1189
+ ...baseEvent,
1190
+ type: "onFormLoad",
1191
+ formData: workingFormData,
1192
+ formViewLayout: workingLayout, // ✅ FINAL layout
1193
+ });
1194
+
1195
+ if (result?.layoutChanged && result?.newLayout) {
1196
+ workingLayout = result.newLayout;
1197
+ }
1198
+
1199
+ if (result?.dataChanged && result?.newFormData) {
1200
+ workingFormData = result.newFormData;
1201
+ }
1202
+ } catch (e) {
1203
+ console.error(ERROR_MESSAGES.ON_FORM_LOAD, e);
1204
+ }
1205
+ }
1206
+ }
1207
+
1208
+ /** ----------------------------
1209
+ * 5. Commit once to React state
1210
+ * ----------------------------- */
1211
+ if (workingLayout) {
1212
+ setFormViewLayout(workingLayout);
1213
+ }
1214
+
1215
+ if (workingFormData) {
1216
+ setInitialEntityData(workingFormData);
1217
+ }
1218
+ };
1219
+
1220
+ runFormEvents();
1221
+ }, [solidFormViewMetaData, solidFormViewData]);
1222
+
1223
+
1224
+ useEffect(() => {
1225
+ if (solidFormViewData) {
1226
+ setInitialEntityData(solidFormViewData.data);
1227
+ }
1228
+ }, [solidFormViewData]);
1229
+
1230
+ let formik: FormikObject;
1231
+
1232
+ // If either the metadata or the data of this form is loading, then we simply render a loading screen...
1233
+ if (solidFormViewMetaDataIsLoading || solidFormViewDataIsLoading || !formViewLayout) {
1234
+ formik = useFormik({
1235
+ initialValues: {},
1236
+ validationSchema: Yup.object(),
1237
+ enableReinitialize: true,
1238
+ onSubmit: onFormikSubmit,
1239
+ });
1240
+
1241
+ return <SolidFormViewShimmerLoading />;
1242
+ }
1243
+ // At this point everything required to render the form is loaded, so we go ahead and start rendering things dynamically...
1244
+ else {
1245
+
1246
+ // Initialize formik...
1247
+ const solidView = solidFormViewMetaData.data.solidView;
1248
+ const solidFieldsMetadata = solidFormViewMetaData.data.solidFieldsMetadata;
1249
+
1250
+ const validationSchema = {};
1251
+ const initialValues = {};
1252
+
1253
+ for (let i = 0; i < layoutFields?.length; i++) {
1254
+ const formLayoutField = layoutFields[i];
1255
+ const fieldMetadata = solidFieldsMetadata[formLayoutField.attrs.name];
1256
+ const fieldContext: SolidFieldProps = {
1257
+ fieldMetadata: fieldMetadata,
1258
+ field: formLayoutField,
1259
+ data: initialEntityData,
1260
+ solidFormViewMetaData: solidFormViewMetaData,
1261
+ modelName: params.modelName
1262
+ }
1263
+ if (params.parentData) {
1264
+ fieldContext.parentData = params.parentData;
1265
+ }
1266
+ let solidField = fieldFactory(fieldMetadata?.type, fieldContext);
1267
+ if (!fieldMetadata?.type) {
1268
+ const errorMessage = formLayoutField?.attrs?.label ? formLayoutField?.attrs?.label : formLayoutField.attrs.name;
1269
+ if (!errorFields.includes(errorMessage)) {
1270
+ // errorFields.push(errorMessage);
1271
+ }
1272
+ }
1273
+ if (solidField) {
1274
+ // @ts-ignore
1275
+ validationSchema[formLayoutField.attrs.name] = solidField.validationSchema();
1276
+ // @ts-ignore
1277
+ initialValues[formLayoutField.attrs.name] = solidField.initialValue();
1278
+
1279
+ }
1280
+ }
1281
+
1282
+ formik = useFormik({
1283
+ initialValues: initialValues,
1284
+ validationSchema: Yup.object(validationSchema),
1285
+ enableReinitialize: true,
1286
+ onSubmit: onFormikSubmit,
1287
+ });
1288
+
1289
+ const formFieldOnXXX = async (event: ChangeEvent<HTMLInputElement>, eventType: string) => {
1290
+
1291
+ // Invoke the formik change
1292
+ if (eventType === 'onFieldChange') {
1293
+ formik.handleChange(event);
1294
+ }
1295
+
1296
+ // get details from the form event
1297
+ const { name: fieldName, value, type, checked } = event.target;
1298
+
1299
+ // TODO: check if there is a change handler registered with this form view, load it and fire it.
1300
+ let changeHandler = solidView.layout.attrs[eventType];
1301
+ if (!changeHandler) {
1302
+ changeHandler = solidView.layout[eventType];
1303
+ }
1304
+
1305
+ if (changeHandler) {
1306
+ // Get hold of the dynamic module...
1307
+ // const dynamicChangeHandler = await loadDynamicModule(changeHandler);
1308
+ const dynamicChangeHandler = getExtensionFunction(changeHandler);
1309
+
1310
+ // Invoke the dynamic module...
1311
+ if (dynamicChangeHandler) {
1312
+ const event: SolidUiEvent = {
1313
+ fieldsMetadata: solidFieldsMetadata,
1314
+ formData: formik.values,
1315
+ modifiedField: fieldName,
1316
+ modifiedFieldValue: value,
1317
+ // @ts-ignore
1318
+ // TODO: HP & OR: This will be fixed once we figure out how to get types exported from solid-core-ui
1319
+ type: eventType,
1320
+ viewMetadata: solidView,
1321
+ formViewLayout: formViewLayout,
1322
+ queryParams: {
1323
+ actionName,
1324
+ actionContext,
1325
+ actionType
1326
+ }
1327
+ }
1328
+
1329
+ // Invoke the dynamic change handler:
1330
+ // TODO: encapsulate in try/catch, catch the exception render in the UI as an error & stop form rendering.
1331
+ const updatedFormInfo: SolidUiEventResponse = await dynamicChangeHandler(event);
1332
+
1333
+ // If dataChanged is true, update Formik values
1334
+ if (updatedFormInfo?.dataChanged && updatedFormInfo.newFormData) {
1335
+ // This does one field at a time.
1336
+ // TODO: does the below fire change events again?
1337
+ Object.entries(updatedFormInfo.newFormData).forEach(([key, newValue]) => {
1338
+ formik.setFieldValue(key, newValue);
1339
+ });
1340
+
1341
+ // This does all at once.
1342
+ // formik.setValues({
1343
+ // ...formik.values,
1344
+ // ...updatedFormInfo.newFormData
1345
+ // });
1346
+ }
1347
+
1348
+ // if layout has changed then we need to re-render.
1349
+ if (updatedFormInfo?.layoutChanged && updatedFormInfo.newLayout) {
1350
+ // setFormViewMetaData({ ...formViewMetaData, layout: updatedFormInfo.newLayout });
1351
+
1352
+ // TODO: this will trigger a useEffect dependent on formViewMetadata that invokes setFormViewLayout,
1353
+ // TODO: which means that this will not work if custom layout has been injected as a prop.
1354
+ setFormViewLayout(updatedFormInfo.newLayout);
1355
+ // setFormViewMetaData((prevMetaData: any) => {
1356
+ // const updatedFormViewMetadata = {
1357
+ // ...prevMetaData,
1358
+ // data: {
1359
+ // ...prevMetaData.data,
1360
+ // solidView: {
1361
+ // ...prevMetaData.data.solidView,
1362
+ // layout: updatedFormInfo.newLayout,
1363
+ // },
1364
+ // },
1365
+ // };
1366
+ // return updatedFormViewMetadata;
1367
+ // });
1368
+ }
1369
+ }
1370
+ else {
1371
+ // TODO: Show an error popup and stop form rendering ideallly...
1372
+ console.log(ERROR_MESSAGES.UNABLE_LOAD_DYNAMIC_MODULE, changeHandler);
1373
+ }
1374
+ }
1375
+ }
1376
+
1377
+ // Now render the form dynamically...
1378
+ const renderFormElementDynamically: any = (element: any, recursiveFVMD: any) => {
1379
+ let { type, attrs, body, children } = element;
1380
+
1381
+ // const key = attrs?.name ?? generateRandomKey();
1382
+ const key = attrs?.label;
1383
+ let visible = attrs?.visible;
1384
+ if (visible === undefined || visible === null) {
1385
+ visible = true;
1386
+ }
1387
+ // console.log(`Resolved visibility of form element ${ key } to ${ visible } `);
1388
+ // console.log(`Form element ${ key }: `, attrs);
1389
+ const visibleToRole = attrs?.roles || [];
1390
+
1391
+ if (visibleToRole.length > 0) {
1392
+ if (!hasAnyRole(user?.user?.roles, visibleToRole)) {
1393
+ return <></>
1394
+ }
1395
+ }
1396
+
1397
+ switch (type) {
1398
+ case "form":
1399
+ if (!children)
1400
+ children = [];
1401
+ return <div key={key}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</div>;
1402
+ case "div":
1403
+ if (!children)
1404
+ children = [];
1405
+ return <div key={key} {...attrs}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</div>
1406
+ case "span":
1407
+ return <span key={key} {...attrs}>{body}</span>
1408
+ case "p":
1409
+ return <p key={key} className={attrs?.className} {...attrs}>{body}</p>
1410
+ case "h1":
1411
+ return <h1 key={key} {...attrs}>{body}</h1>
1412
+ case "h2":
1413
+ return <h2 key={key} {...attrs}>{body}</h2>
1414
+ case "ul":
1415
+ if (!children)
1416
+ children = [];
1417
+ return <ul key={key} {...attrs}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</ul>
1418
+ case "li":
1419
+ return <li key={key} {...attrs}>{body}</li>
1420
+ case "sheet":
1421
+ return <SolidSheet key={key}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</SolidSheet>;
1422
+ case "group":
1423
+ if (visible === true) {
1424
+ return <SolidGroup key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</SolidGroup>;
1425
+ }
1426
+ case "row":
1427
+ if (visible === true) {
1428
+ return <SolidRow key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</SolidRow>;
1429
+ }
1430
+ case "column":
1431
+ if (visible === true) {
1432
+ return <SolidColumn key={key} attrs={attrs}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</SolidColumn>;
1433
+ }
1434
+ case "field": {
1435
+ if (visible === true) {
1436
+
1437
+ // const fieldMetadata = solidFieldsMetadata[attrs.name];
1438
+ const fieldMetadata = recursiveFVMD.data.solidFieldsMetadata[attrs.name];
1439
+ // Read only permission if there is no update permission on model and router doesnt contains new
1440
+ const readOnlyPermission = !actionsAllowed.includes(`${permissionExpression(params.modelName, 'update')}`) && params.id !== "new";
1441
+ return <SolidField
1442
+ key={attrs.name}
1443
+ field={element}
1444
+ formik={formik}
1445
+ fieldMetadata={fieldMetadata}
1446
+ initialEntityData={solidFormViewData ? solidFormViewData.data : {}}
1447
+ solidFormViewMetaData={recursiveFVMD}
1448
+ modelName={params.modelName}
1449
+ readOnly={readOnlyPermission}
1450
+ viewMode={viewMode}
1451
+ onChange={formFieldOnXXX}
1452
+ onBlur={formFieldOnXXX}
1453
+ setLightboxUrls={setLightboxUrls}
1454
+ setOpenLightbox={setOpenLightbox}
1455
+ parentData={params.parentData}
1456
+ onEmbeddedFormSave={() => setRefreshChatterMessage(true)}
1457
+ />;
1458
+ }
1459
+ }
1460
+ case "notebook":
1461
+ if (visible === true) {
1462
+ return <SolidNotebook key={key} activeTab={searchParams.get("activeTab") || ""} embeded={params.embeded}>{children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD, formik))}</SolidNotebook>;
1463
+ }
1464
+ case "page":
1465
+ if (visible === true) {
1466
+ const fields = children.flatMap((child: any) => getLayoutFields(child));
1467
+ const pageChildren = children.map((element: any) => renderFormElementDynamically(element, recursiveFVMD));
1468
+ return SolidPage({ children: pageChildren, attrs: attrs, key: key, formik: formik, fields });
1469
+ }
1470
+ case "custom":
1471
+ if (visible === true) {
1472
+ const widgetName = attrs?.widget;
1473
+ const fieldMetadata = recursiveFVMD.data.solidFieldsMetadata[attrs.name];
1474
+
1475
+ if (widgetName) {
1476
+ // widgetName, formik, field, fieldMetadata, solidFormViewMetaData
1477
+ return <SolidDynamicWidget
1478
+ key={key}
1479
+ widgetName={widgetName}
1480
+ field={element}
1481
+ formik={formik}
1482
+ fieldMetadata={fieldMetadata}
1483
+ solidFormViewMetaData={recursiveFVMD}
1484
+ solidFormViewData={solidFormViewData}
1485
+ />
1486
+ }
1487
+ }
1488
+
1489
+ default:
1490
+ return null;
1491
+ }
1492
+ };
1493
+
1494
+ const renderFormDynamically = (recursiveFVMD: any, formViewLayout: any) => {
1495
+ if (!recursiveFVMD) {
1496
+ return;
1497
+ }
1498
+ if (!recursiveFVMD.data) {
1499
+ return;
1500
+ }
1501
+ const solidView = recursiveFVMD.data.solidView;
1502
+ const solidFieldsMetadata = recursiveFVMD.data.solidFieldsMetadata;
1503
+ if (!solidView || !solidFieldsMetadata) {
1504
+ return;
1505
+ }
1506
+ const updatedLayout = [formViewLayout];
1507
+ const dynamicForm = updatedLayout.map((element: any) => renderFormElementDynamically(element, recursiveFVMD));
1508
+
1509
+ return dynamicForm;
1510
+ };
1511
+
1512
+ const handleDeleteEntity = async () => {
1513
+ deleteEntity(solidFormViewData.data.id);
1514
+ setDeleteDialogVisible(false);
1515
+ if (params.embeded == true) {
1516
+ setRedirectToList(false)
1517
+
1518
+ } else {
1519
+ setRedirectToList(true)
1520
+
1521
+ }
1522
+ // router.back();
1523
+ }
1524
+
1525
+ const onDeleteClose = () => {
1526
+ setDeleteDialogVisible(false);
1527
+ }
1528
+
1529
+ const dynamicHeader = solidView.layout?.header;
1530
+ let DynamicHeaderComponent = null;
1531
+ if (dynamicHeader) {
1532
+ DynamicHeaderComponent = getExtensionComponent(dynamicHeader);
1533
+ }
1534
+ const customFormComponentEdit = solidView.layout.attrs.customFormComponentEdit;
1535
+ const customFormComponentNew = solidView.layout.attrs.customFormComponentNew;
1536
+ let DynamicFormComponentEdit = null;
1537
+ let DynamicFormComponentNew = null;
1538
+ if (customFormComponentEdit) {
1539
+ DynamicFormComponentEdit = getExtensionComponent(customFormComponentEdit);
1540
+ }
1541
+ if (customFormComponentNew) {
1542
+ DynamicFormComponentNew = getExtensionComponent(customFormComponentNew);
1543
+ }
1544
+
1545
+ const handleChatterExpandClick = (option?: string) => {
1546
+ setShowChatter(true);
1547
+ if (option === 'info') {
1548
+ setDefaultTabViewOptionIndex(0);
1549
+ } else if (option === 'chatter') {
1550
+ setDefaultTabViewOptionIndex(1);
1551
+ setRefreshChatterMessage(true);
1552
+ } else {
1553
+ setDefaultTabViewOptionIndex(2);
1554
+ }
1555
+ };
1556
+
1557
+ //en 4 null
1558
+ const handleLocaleChangeRedirect = (
1559
+ locale: string,
1560
+ defaultEntityLocaleId: string,
1561
+ viewMode: string,
1562
+ ) => {
1563
+ let newViewMode = viewMode;
1564
+ const defaultApplicableLocales = solidFormViewMetaData?.data?.applicableLocales || [];
1565
+ //fr 4
1566
+ const matchingLocale = defaultApplicableLocales.find(
1567
+ (loc: any) =>
1568
+ loc.defaultEntityLocaleId &&
1569
+ loc.entityId &&
1570
+ loc.locale === locale
1571
+ );
1572
+ // Extract the base path from the current pathname, removing query params if any
1573
+ const basePath = pathname.split('?')[0];
1574
+
1575
+ // Determine entity part of the path (new or existing entityId)
1576
+ const entityPart = matchingLocale?.entityId ?? 'new';
1577
+ if (entityPart === 'new' && viewMode === 'view') {
1578
+ newViewMode = 'edit'
1579
+ } else if (entityPart !== 'new' && viewMode === 'view') {
1580
+ newViewMode = 'view'
1581
+ } else {
1582
+ newViewMode = 'edit'
1583
+ }
1584
+ // Construct new pathname using existing basePath and replacing entity segment
1585
+ const updatedPath = basePath.replace(/\/form\/[^/]+/, `/form/${entityPart}`);
1586
+
1587
+ const queryParams = new URLSearchParams({
1588
+ viewMode: newViewMode,
1589
+ locale,
1590
+ defaultEntityLocaleId,
1591
+ });
1592
+
1593
+ router.push(`${updatedPath}?${queryParams.toString()}`, { scroll: false });
1594
+ };
1595
+
1596
+ const handleConfirmAccept = () => {
1597
+ confirmResolveRef.current?.(true);
1598
+ setConfirmVisible(false);
1599
+ };
1600
+
1601
+ const handleConfirmReject = () => {
1602
+ confirmResolveRef.current?.(false);
1603
+ setConfirmVisible(false);
1604
+ };
1605
+ const handleDraftPublishWorkFlow = async (type: "publish" | "unpublish") => {
1606
+ const userChoice = await confirmDialogWithPromise();
1607
+ if (!userChoice) return;
1608
+
1609
+ // const finalPublishedValue =
1610
+ // type === "publish" ? new Date().toISOString() : "";
1611
+
1612
+ // setPublished(finalPublishedValue);
1613
+
1614
+ // const formdata = new FormData();
1615
+ // formdata.append("publishedAt", finalPublishedValue);
1616
+
1617
+ let result;
1618
+
1619
+ if (type === "publish") {
1620
+ result = await publishSolidEntity(params.id).unwrap();
1621
+ showToast("success", ERROR_MESSAGES.SAVED, ERROR_MESSAGES.MARK_PUBLISH);
1622
+ } else {
1623
+ result = await unpublishSolidEntity(params.id).unwrap();
1624
+ showToast("success", ERROR_MESSAGES.SAVED, ERROR_MESSAGES.MARK_UNPUBLISH);
1625
+ }
1626
+
1627
+ console.log("publish/unpublish result", result);
1628
+
1629
+ // Set updated publish value from API response
1630
+ setPublished(result?.data?.publishedAt);
1631
+ };
1632
+
1633
+
1634
+ const isVideoOrAudio = (url: string) => {
1635
+ // Remove query params if present
1636
+ const cleanUrl = url.split("?")[0];
1637
+ const ext = cleanUrl.split(".").pop()?.toLowerCase();
1638
+
1639
+ // Combined list of supported media extensions
1640
+ const mediaExt = ["mp4", "webm", "ogg", "mov", "mp3", "wav", "m4a", "aac"];
1641
+
1642
+ return ext ? mediaExt.includes(ext) : false;
1643
+ };
1644
+
1645
+ const controlsList = ["nodownload", "nofullscreen", "noremoteplayback"];
1646
+ const slides = lightboxUrls.map((item: any) => {
1647
+ const url = item.src || item.downloadUrl || "";
1648
+ if (isVideoOrAudio(url)) {
1649
+ return {
1650
+ type: "video" as const,
1651
+ sources: [{ src: url, type: "video/mp4", }],
1652
+ };
1653
+ }
1654
+ return { src: url };
1655
+ });
1656
+
1657
+ const hasMedia = slides.some((s) => s.type === "video");
1658
+
1659
+
1660
+
1661
+ return (
1662
+ <div className="solid-form-wrapper">
1663
+ <Toast ref={toast} />
1664
+ <div className="solid-form-section" style={{ borderRight: params.embeded !== true ? '1px solid var(--primary-light-color)' : '' }} >
1665
+ <form style={{ width: '100%' }} onSubmit={formik.handleSubmit}>
1666
+ <SolidFormActionHeader
1667
+ formik={formik}
1668
+ formData={solidFormViewData?.data}
1669
+ params={params}
1670
+ actionsAllowed={actionsAllowed}
1671
+ formViewLayout={formViewLayout}
1672
+ solidView={solidView}
1673
+ solidFormViewMetaData={solidFormViewMetaData}
1674
+ initialEntityData={solidFormViewData ? solidFormViewData.data : {}}
1675
+ setDeleteDialogVisible={setDeleteDialogVisible}
1676
+ setLayoutDialogVisible={setLayoutDialogVisible}
1677
+ setRedirectToList={setRedirectToList}
1678
+ viewMode={viewMode}
1679
+ setViewMode={setViewMode}
1680
+ solidWorkflowFieldValue={solidWorkflowFieldValue}
1681
+ setSolidWorkflowFieldValue={setSolidWorkflowFieldValue}
1682
+ draftEnabled={solidFormViewMetaData?.data?.solidView?.model?.draftPublishWorkflow}
1683
+ publish={published}
1684
+ internationalisationEnabled={solidFormViewMetaData?.data?.solidView?.model?.internationalisation}
1685
+ handleDraftPublishWorkFlow={handleDraftPublishWorkFlow}
1686
+ onStepperUpdate={() => setRefreshChatterMessage(true)}
1687
+ />
1688
+ <div className={`px-4 py-3 md:p-4 solid-form-content ${params.embeded === true ? 'h-auto' : ''}`} style={{ maxHeight: params.embeded === true ? '80vh' : '', overflowY: 'auto' }}>
1689
+ {DynamicHeaderComponent && <DynamicHeaderComponent />}
1690
+ {params.id === 'new' && DynamicFormComponentNew ? (
1691
+ <DynamicFormComponentNew params={params} />
1692
+ ) : params.id !== 'new' && DynamicFormComponentEdit ? (
1693
+ <DynamicFormComponentEdit params={params} />
1694
+ ) : (
1695
+ renderFormDynamically(formViewMetaData, formViewLayout)
1696
+ )}
1697
+ </div>
1698
+
1699
+ </form>
1700
+ <SolidFormFooter params={params}></SolidFormFooter>
1701
+ </div>
1702
+ {params.embeded !== true &&
1703
+ <div className={`chatter-section ${isShowChatter === false ? 'collapsed' : 'open'}`} style={{ width: chatterLocaleWidth }}>
1704
+ {isShowChatter && (
1705
+ <div
1706
+ style={{
1707
+ width: 5,
1708
+ cursor: 'col-resize',
1709
+ position: 'absolute',
1710
+ left: 0,
1711
+ top: 0,
1712
+ bottom: 0,
1713
+ zIndex: 9,
1714
+ }}
1715
+ onMouseDown={() => setIsResizingChatterLocale(true)}
1716
+ />
1717
+ )}
1718
+ {isShowChatter === true &&
1719
+ <Button
1720
+ icon="pi pi-angle-double-right"
1721
+ size="small"
1722
+ text
1723
+ className="chatter-collapse-btn"
1724
+ style={{ width: 30, height: 30, aspectRatio: '1/1' }}
1725
+ onClick={() => setShowChatter(false)}
1726
+ />
1727
+ }
1728
+ {isShowChatter === false ?
1729
+ <div className="flex flex-column gap-2 justify-content-center p-2">
1730
+ {/*if solidview Internationalisation is enabled then show the locale tab */}
1731
+ {solidFormViewMetaData?.data?.solidView?.model?.draftPublishWorkflow &&
1732
+ <div className="chatter-collapsed-content" onClick={() => handleChatterExpandClick('info')}>
1733
+ Info
1734
+ </div>}
1735
+ <div className="chatter-collapsed-content" onClick={() => handleChatterExpandClick('chatter')}>
1736
+ Audit Trail
1737
+ </div>
1738
+ {
1739
+ mcpUrl &&
1740
+ (
1741
+ <div className="chatter-collapsed-content" onClick={() => handleChatterExpandClick('solidx-ai')}>
1742
+ <div className="flex gap-2"> <SolidXAIIcon /> SolidX AI </div>
1743
+ </div>
1744
+ )
1745
+ }
1746
+ <Button
1747
+ icon="pi pi-chevron-left"
1748
+ size="small"
1749
+ className="px-0"
1750
+ style={{ width: 30 }}
1751
+ onClick={() => handleChatterExpandClick('default')}
1752
+ />
1753
+ </div>
1754
+ :
1755
+ <SolidChatterLocaleTabView
1756
+ createMode={createMode}
1757
+ setSelectedLocale={setSelectedLocale}
1758
+ selectedLocale={selectedLocale}
1759
+ solidFormViewMetaData={solidFormViewMetaData}
1760
+ id={params.id}
1761
+ refreshChatterMessage={refreshChatterMessage}
1762
+ setRefreshChatterMessage={setRefreshChatterMessage}
1763
+ activeTab={defaultTabViewOptionIndex}
1764
+ viewMode={viewMode}
1765
+ defaultEntityLocaleId={defaultEntityLocaleId}
1766
+ handleLocaleChangeRedirect={handleLocaleChangeRedirect}
1767
+ solidFormViewData={solidFormViewData}
1768
+ published={published}
1769
+ actionsAllowed={actionsAllowed}
1770
+ mcpUrl={mcpUrl}
1771
+ />
1772
+ }
1773
+ </div>
1774
+ }
1775
+
1776
+ <Dialog
1777
+ visible={isDeleteDialogVisible}
1778
+ header="Confirm Delete"
1779
+ className="solid-confirm-dialog"
1780
+ modal
1781
+ footer={() => (
1782
+ <div className="flex justify-content-center">
1783
+ <Button label="Yes" icon="pi pi-check" className='small-button' severity="danger" autoFocus onClick={() => handleDeleteEntity()} />
1784
+ <Button label="No" icon="pi pi-times" className='small-button' onClick={onDeleteClose} />
1785
+ </div>
1786
+ )}
1787
+ onHide={() => setDeleteDialogVisible(false)}
1788
+ >
1789
+ <p>Are you sure you want to delete?</p>
1790
+ </Dialog>
1791
+ <Dialog
1792
+ visible={isLayoutDialogVisible}
1793
+ header="Change Form Layout"
1794
+ modal
1795
+ onHide={() => setLayoutDialogVisible(false)}
1796
+ style={{ width: '50vw' }}
1797
+ breakpoints={{
1798
+ '960px': '80vw',
1799
+ '641px': '95vw'
1800
+ }}
1801
+ contentClassName="p-3 pt-0 lg:p-4"
1802
+ >
1803
+ <SolidFormUserViewLayout solidFormViewMetaData={solidFormViewMetaData} setLayoutDialogVisible={setLayoutDialogVisible} />
1804
+ </Dialog>
1805
+ {openLightbox &&
1806
+ <Lightbox
1807
+ open={openLightbox}
1808
+ plugins={
1809
+ hasMedia
1810
+ ? [Counter, Download, Video] // add Video plugin if needed
1811
+ : [Counter, Download]
1812
+ }
1813
+ close={() => setOpenLightbox(false)}
1814
+ slides={[...slides]}
1815
+ {...(hasMedia && {
1816
+ video: {
1817
+ controls: true,
1818
+ playsInline: true,
1819
+ autoPlay: false,
1820
+ loop: false,
1821
+ muted: false,
1822
+ disablePictureInPicture: false,
1823
+ disableRemotePlayback: false,
1824
+ controlsList: controlsList.join(" "),
1825
+ crossOrigin: "anonymous",
1826
+ preload: "auto",
1827
+ },
1828
+ })}
1829
+ />
1830
+ }
1831
+
1832
+ <ConfirmDialog
1833
+ visible={confirmVisible}
1834
+ onHide={() => setConfirmVisible(false)}
1835
+ header="Confirmation"
1836
+ acceptLabel="Yes, confrim"
1837
+ rejectLabel="No, cancel"
1838
+ acceptClassName="p-button-danger"
1839
+ rejectClassName="p-button-text"
1840
+ position="center"
1841
+ accept={handleConfirmAccept}
1842
+ reject={handleConfirmReject}
1843
+ message={
1844
+ <div className="flex flex-col items-center justify-center text-center space-y-3">
1845
+ <p className="text-gray-800 text-base">
1846
+ Are you sure you want to {published !== null ? 'unpublish' : 'publish'}?
1847
+ </p>
1848
+ </div>
1849
+ }
1850
+ />
1851
+ </div>
1852
+ );
1853
+ }
1854
+ };
1855
+
1856
+ export default SolidFormView;