robobyte-front-builder 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/jsconfig.json +28 -0
  2. package/next.config.js +75 -0
  3. package/package.json +163 -0
  4. package/public/fonts/NotoSansArabic-VariableFont_wdth,wght.ttf +0 -0
  5. package/public/fonts/font.js +2 -0
  6. package/public/fonts/logo.js +2 -0
  7. package/public/images/appicon.png +0 -0
  8. package/public/images/appicon1.png +0 -0
  9. package/public/images/asiacell.png +0 -0
  10. package/public/images/avatars/1.png +0 -0
  11. package/public/images/avatars/3.png +0 -0
  12. package/public/images/avatars/4.png +0 -0
  13. package/public/images/avatars/5.png +0 -0
  14. package/public/images/cards/trophy.png +0 -0
  15. package/public/images/favicon.png +0 -0
  16. package/public/images/favicon1.png +0 -0
  17. package/public/images/icons/bag.png +0 -0
  18. package/public/images/icons/briefcase.png +0 -0
  19. package/public/images/icons/calendar.png +0 -0
  20. package/public/images/icons/dashboard.png +0 -0
  21. package/public/images/icons/dollar.png +0 -0
  22. package/public/images/icons/person.png +0 -0
  23. package/public/images/icons/profit.png +0 -0
  24. package/public/images/icons/setting.png +0 -0
  25. package/public/images/misc/chart.png +0 -0
  26. package/public/images/misc/paypal.png +0 -0
  27. package/public/images/pages/401.png +0 -0
  28. package/public/images/pages/404.png +0 -0
  29. package/public/images/pages/500.png +0 -0
  30. package/public/images/pages/auth-v2-forgot-password-illustration-bordered-dark.png +0 -0
  31. package/public/images/pages/auth-v2-forgot-password-illustration-bordered-light.png +0 -0
  32. package/public/images/pages/auth-v2-forgot-password-illustration-dark.png +0 -0
  33. package/public/images/pages/auth-v2-forgot-password-illustration-light.png +0 -0
  34. package/public/images/pages/auth-v2-forgot-password-mask-dark.png +0 -0
  35. package/public/images/pages/auth-v2-forgot-password-mask-light.png +0 -0
  36. package/public/images/pages/auth-v2-login-illustration-bordered-dark.png +0 -0
  37. package/public/images/pages/auth-v2-login-illustration-bordered-light.png +0 -0
  38. package/public/images/pages/auth-v2-login-illustration-dark.png +0 -0
  39. package/public/images/pages/auth-v2-login-illustration-light.png +0 -0
  40. package/public/images/pages/auth-v2-login-mask-dark.png +0 -0
  41. package/public/images/pages/auth-v2-login-mask-light.png +0 -0
  42. package/public/images/pages/auth-v2-register-illustration-bordered-dark.png +0 -0
  43. package/public/images/pages/auth-v2-register-illustration-bordered-light.png +0 -0
  44. package/public/images/pages/auth-v2-register-illustration-dark.png +0 -0
  45. package/public/images/pages/auth-v2-register-illustration-light.png +0 -0
  46. package/public/images/pages/auth-v2-register-mask-dark.png +0 -0
  47. package/public/images/pages/auth-v2-register-mask-light.png +0 -0
  48. package/public/images/pages/misc-401-object.png +0 -0
  49. package/public/images/pages/misc-404-object.png +0 -0
  50. package/public/images/pages/misc-500-object.png +0 -0
  51. package/public/images/pages/misc-coming-soon-object.png +0 -0
  52. package/public/images/pages/misc-mask-dark.png +0 -0
  53. package/public/images/pages/misc-mask-light.png +0 -0
  54. package/public/images/white.jpg +0 -0
  55. package/public/images/zain.png +0 -0
  56. package/public/locales/ar.json +35 -0
  57. package/public/navigationTest/Navigation.json +13 -0
  58. package/public/vercel.svg +4 -0
  59. package/src/@core/components/auth/AclGuard.js +55 -0
  60. package/src/@core/components/auth/AuthGuard.js +40 -0
  61. package/src/@core/components/auth/GuestGuard.js +30 -0
  62. package/src/@core/components/custom-inputs/Horizontal.jsx +143 -0
  63. package/src/@core/components/custom-inputs/Image.jsx +78 -0
  64. package/src/@core/components/custom-inputs/Vertical.jsx +113 -0
  65. package/src/@core/components/customizer/index.jsx +470 -0
  66. package/src/@core/components/customizer/styles.module.css +169 -0
  67. package/src/@core/components/mui/Avatar.jsx +41 -0
  68. package/src/@core/components/mui/Badge.jsx +20 -0
  69. package/src/@core/components/mui/IconButton.jsx +74 -0
  70. package/src/@core/components/mui/TabList.jsx +60 -0
  71. package/src/@core/components/option-menu/index.jsx +137 -0
  72. package/src/@core/components/scroll-to-top/index.jsx +43 -0
  73. package/src/@core/components/spinner/index.js +26 -0
  74. package/src/@core/components/window-wrapper/index.js +27 -0
  75. package/src/@core/contexts/settingsContext.jsx +98 -0
  76. package/src/@core/hooks/useBgColor.js +63 -0
  77. package/src/@core/hooks/useImageVariant.js +27 -0
  78. package/src/@core/hooks/useLayoutInit.js +37 -0
  79. package/src/@core/hooks/useObjectCookie.js +18 -0
  80. package/src/@core/hooks/useSettings.jsx +15 -0
  81. package/src/@core/layouts/BlankLayout.js +37 -0
  82. package/src/@core/layouts/BlankLayoutWithAppBar.js +51 -0
  83. package/src/@core/layouts/HorizontalLayout.jsx +151 -0
  84. package/src/@core/layouts/Layout.js +39 -0
  85. package/src/@core/layouts/VerticalLayout.jsx +124 -0
  86. package/src/@core/layouts/components/blank-layout-with-appBar/index.js +115 -0
  87. package/src/@core/layouts/components/horizontal/app-bar-content/index.js +67 -0
  88. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavGroup.js +352 -0
  89. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavItems.js +21 -0
  90. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavLink.js +195 -0
  91. package/src/@core/layouts/components/horizontal/navigation/index.js +31 -0
  92. package/src/@core/layouts/components/shared-components/LanguageDropdown.js +96 -0
  93. package/src/@core/layouts/components/shared-components/ModeToggler.js +32 -0
  94. package/src/@core/layouts/components/shared-components/NotificationDropdown.js +226 -0
  95. package/src/@core/layouts/components/shared-components/UserDropdown.js +177 -0
  96. package/src/@core/layouts/components/shared-components/footer/FooterContent.js +46 -0
  97. package/src/@core/layouts/components/shared-components/footer/index.js +61 -0
  98. package/src/@core/layouts/components/vertical/appBar/index.js +74 -0
  99. package/src/@core/layouts/components/vertical/navigation/Drawer.js +122 -0
  100. package/src/@core/layouts/components/vertical/navigation/VerticalNavGroup.js +435 -0
  101. package/src/@core/layouts/components/vertical/navigation/VerticalNavHeader.js +180 -0
  102. package/src/@core/layouts/components/vertical/navigation/VerticalNavItems.js +26 -0
  103. package/src/@core/layouts/components/vertical/navigation/VerticalNavLink.js +258 -0
  104. package/src/@core/layouts/components/vertical/navigation/VerticalNavSectionTitle.js +102 -0
  105. package/src/@core/layouts/components/vertical/navigation/index.js +169 -0
  106. package/src/@core/layouts/utils.js +69 -0
  107. package/src/@core/styles/Table.module.css +93 -0
  108. package/src/@core/styles/horizontal/menuItemStyles.js +100 -0
  109. package/src/@core/styles/horizontal/menuRootStyles.js +19 -0
  110. package/src/@core/styles/libs/fullcalendar/index.js +461 -0
  111. package/src/@core/styles/libs/keen-slider/index.js +111 -0
  112. package/src/@core/styles/libs/react-apexcharts/index.js +107 -0
  113. package/src/@core/styles/libs/react-cleave/index.js +33 -0
  114. package/src/@core/styles/libs/react-credit-cards/index.js +11 -0
  115. package/src/@core/styles/libs/react-datepicker/index.js +388 -0
  116. package/src/@core/styles/libs/react-draft-wysiwyg/index.js +144 -0
  117. package/src/@core/styles/libs/react-dropzone/index.js +76 -0
  118. package/src/@core/styles/libs/react-hot-toast/index.js +37 -0
  119. package/src/@core/styles/libs/recharts/index.js +47 -0
  120. package/src/@core/styles/stepper.js +103 -0
  121. package/src/@core/styles/vertical/menuItemStyles.js +138 -0
  122. package/src/@core/styles/vertical/menuSectionStyles.js +54 -0
  123. package/src/@core/styles/vertical/navigationCustomStyles.js +62 -0
  124. package/src/@core/svg/ContentCompact.jsx +17 -0
  125. package/src/@core/svg/ContentWide.jsx +17 -0
  126. package/src/@core/svg/DirectionLtr.jsx +93 -0
  127. package/src/@core/svg/DirectionRtl.jsx +93 -0
  128. package/src/@core/svg/LayoutCollapsed.jsx +59 -0
  129. package/src/@core/svg/LayoutHorizontal.jsx +42 -0
  130. package/src/@core/svg/LayoutVertical.jsx +59 -0
  131. package/src/@core/svg/Logo.jsx +76 -0
  132. package/src/@core/svg/SkinBordered.jsx +54 -0
  133. package/src/@core/svg/SkinDefault.jsx +59 -0
  134. package/src/@core/tailwind/plugin.js +78 -0
  135. package/src/@core/theme/ThemeComponent.js +63 -0
  136. package/src/@core/theme/ThemeOptions.js +71 -0
  137. package/src/@core/theme/breakpoints/index.js +11 -0
  138. package/src/@core/theme/colorSchemes.js +326 -0
  139. package/src/@core/theme/customShadows.js +11 -0
  140. package/src/@core/theme/globalStyles.js +81 -0
  141. package/src/@core/theme/index.js +42 -0
  142. package/src/@core/theme/overrides/accordion.js +51 -0
  143. package/src/@core/theme/overrides/accordion.jsx +85 -0
  144. package/src/@core/theme/overrides/alerts.js +110 -0
  145. package/src/@core/theme/overrides/alerts.jsx +180 -0
  146. package/src/@core/theme/overrides/autocomplete.js +14 -0
  147. package/src/@core/theme/overrides/autocomplete.jsx +68 -0
  148. package/src/@core/theme/overrides/avatar.js +38 -0
  149. package/src/@core/theme/overrides/avatars.js +27 -0
  150. package/src/@core/theme/overrides/backdrop.js +22 -0
  151. package/src/@core/theme/overrides/badges.js +16 -0
  152. package/src/@core/theme/overrides/breadcrumbs.js +11 -0
  153. package/src/@core/theme/overrides/button-group.js +84 -0
  154. package/src/@core/theme/overrides/button.js +93 -0
  155. package/src/@core/theme/overrides/buttonGroup.js +9 -0
  156. package/src/@core/theme/overrides/card.js +83 -0
  157. package/src/@core/theme/overrides/checkbox.jsx +95 -0
  158. package/src/@core/theme/overrides/chip.js +72 -0
  159. package/src/@core/theme/overrides/dataGrid.js +114 -0
  160. package/src/@core/theme/overrides/dateTimePicker.js +65 -0
  161. package/src/@core/theme/overrides/dialog.js +120 -0
  162. package/src/@core/theme/overrides/divider.js +13 -0
  163. package/src/@core/theme/overrides/drawer.js +20 -0
  164. package/src/@core/theme/overrides/fab.js +13 -0
  165. package/src/@core/theme/overrides/form-control-label.js +19 -0
  166. package/src/@core/theme/overrides/icon-button.js +145 -0
  167. package/src/@core/theme/overrides/index.js +103 -0
  168. package/src/@core/theme/overrides/input.js +72 -0
  169. package/src/@core/theme/overrides/link.js +9 -0
  170. package/src/@core/theme/overrides/list.js +44 -0
  171. package/src/@core/theme/overrides/menu.js +25 -0
  172. package/src/@core/theme/overrides/pagination.js +41 -0
  173. package/src/@core/theme/overrides/paper.js +9 -0
  174. package/src/@core/theme/overrides/popover.js +16 -0
  175. package/src/@core/theme/overrides/progress.js +38 -0
  176. package/src/@core/theme/overrides/radio.jsx +80 -0
  177. package/src/@core/theme/overrides/rating.js +16 -0
  178. package/src/@core/theme/overrides/rating.jsx +32 -0
  179. package/src/@core/theme/overrides/select.js +19 -0
  180. package/src/@core/theme/overrides/select.jsx +52 -0
  181. package/src/@core/theme/overrides/slider.js +97 -0
  182. package/src/@core/theme/overrides/snackbar.js +19 -0
  183. package/src/@core/theme/overrides/switch.js +73 -0
  184. package/src/@core/theme/overrides/switches.js +25 -0
  185. package/src/@core/theme/overrides/table-pagination.js +39 -0
  186. package/src/@core/theme/overrides/table.js +81 -0
  187. package/src/@core/theme/overrides/tabs.js +30 -0
  188. package/src/@core/theme/overrides/timeline.js +80 -0
  189. package/src/@core/theme/overrides/toggle-button.js +33 -0
  190. package/src/@core/theme/overrides/toggleButton.js +16 -0
  191. package/src/@core/theme/overrides/tooltip.js +21 -0
  192. package/src/@core/theme/overrides/typography.js +13 -0
  193. package/src/@core/theme/palette/index.js +107 -0
  194. package/src/@core/theme/shadows/index.js +61 -0
  195. package/src/@core/theme/shadows.js +12 -0
  196. package/src/@core/theme/spacing/index.js +3 -0
  197. package/src/@core/theme/spacing.js +5 -0
  198. package/src/@core/theme/typography/index.js +65 -0
  199. package/src/@core/theme/typography.js +84 -0
  200. package/src/@core/utils/create-emotion-cache.js +5 -0
  201. package/src/@core/utils/hex-to-rgba.js +11 -0
  202. package/src/@core/utils/serverHelpers.js +45 -0
  203. package/src/@menu/components/RouterLink.jsx +18 -0
  204. package/src/@menu/components/horizontal-menu/HorizontalNav.jsx +88 -0
  205. package/src/@menu/components/horizontal-menu/Menu.jsx +83 -0
  206. package/src/@menu/components/horizontal-menu/MenuButton.jsx +100 -0
  207. package/src/@menu/components/horizontal-menu/MenuItem.jsx +183 -0
  208. package/src/@menu/components/horizontal-menu/SubMenu.jsx +418 -0
  209. package/src/@menu/components/horizontal-menu/SubMenuContent.jsx +41 -0
  210. package/src/@menu/components/horizontal-menu/VerticalNavInHorizontal.jsx +20 -0
  211. package/src/@menu/components/vertical-menu/Menu.jsx +161 -0
  212. package/src/@menu/components/vertical-menu/MenuButton.jsx +95 -0
  213. package/src/@menu/components/vertical-menu/MenuItem.jsx +180 -0
  214. package/src/@menu/components/vertical-menu/MenuSection.jsx +124 -0
  215. package/src/@menu/components/vertical-menu/NavCollapseIcons.jsx +70 -0
  216. package/src/@menu/components/vertical-menu/NavHeader.jsx +39 -0
  217. package/src/@menu/components/vertical-menu/SubMenu.jsx +420 -0
  218. package/src/@menu/components/vertical-menu/SubMenuContent.jsx +101 -0
  219. package/src/@menu/components/vertical-menu/VerticalNav.jsx +216 -0
  220. package/src/@menu/contexts/horizontalNavContext.jsx +29 -0
  221. package/src/@menu/contexts/verticalNavContext.jsx +65 -0
  222. package/src/@menu/defaultConfigs.js +12 -0
  223. package/src/@menu/hooks/useHorizontalMenu.jsx +19 -0
  224. package/src/@menu/hooks/useHorizontalNav.jsx +19 -0
  225. package/src/@menu/hooks/useMediaQuery.jsx +29 -0
  226. package/src/@menu/hooks/useVerticalMenu.jsx +19 -0
  227. package/src/@menu/hooks/useVerticalNav.jsx +19 -0
  228. package/src/@menu/horizontal-menu/index.jsx +8 -0
  229. package/src/@menu/styles/StyledBackdrop.jsx +15 -0
  230. package/src/@menu/styles/StyledMenuIcon.jsx +12 -0
  231. package/src/@menu/styles/StyledMenuLabel.jsx +16 -0
  232. package/src/@menu/styles/StyledMenuPrefix.jsx +10 -0
  233. package/src/@menu/styles/StyledMenuSectionLabel.jsx +21 -0
  234. package/src/@menu/styles/StyledMenuSuffix.jsx +10 -0
  235. package/src/@menu/styles/StyledSubMenuContent.jsx +43 -0
  236. package/src/@menu/styles/horizontal/StyledHorizontalMenu.jsx +13 -0
  237. package/src/@menu/styles/horizontal/StyledHorizontalMenuItem.jsx +26 -0
  238. package/src/@menu/styles/horizontal/StyledHorizontalNav.jsx +11 -0
  239. package/src/@menu/styles/horizontal/StyledHorizontalNavExpandIcon.jsx +33 -0
  240. package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContent.jsx +18 -0
  241. package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContentWrapper.jsx +10 -0
  242. package/src/@menu/styles/horizontal/horizontalUl.module.css +15 -0
  243. package/src/@menu/styles/styles.module.css +5 -0
  244. package/src/@menu/styles/vertical/StyledVerticalMenu.jsx +16 -0
  245. package/src/@menu/styles/vertical/StyledVerticalMenuItem.jsx +28 -0
  246. package/src/@menu/styles/vertical/StyledVerticalMenuSection.jsx +23 -0
  247. package/src/@menu/styles/vertical/StyledVerticalNav.jsx +67 -0
  248. package/src/@menu/styles/vertical/StyledVerticalNavBgColorContainer.jsx +15 -0
  249. package/src/@menu/styles/vertical/StyledVerticalNavContainer.jsx +23 -0
  250. package/src/@menu/styles/vertical/StyledVerticalNavExpandIcon.jsx +25 -0
  251. package/src/@menu/styles/vertical/verticalNavBgImage.module.css +10 -0
  252. package/src/@menu/svg/ChevronRight.jsx +9 -0
  253. package/src/@menu/svg/Close.jsx +12 -0
  254. package/src/@menu/svg/RadioCircle.jsx +12 -0
  255. package/src/@menu/svg/RadioCircleMarked.jsx +13 -0
  256. package/src/@menu/utils/menuClasses.js +44 -0
  257. package/src/@menu/utils/menuUtils.jsx +145 -0
  258. package/src/@menu/vertical-menu/index.jsx +11 -0
  259. package/src/configs/Permissions/PermissionsActions.json +6 -0
  260. package/src/configs/Permissions/PermissionsSubjects.json +107 -0
  261. package/src/configs/acl.js +115 -0
  262. package/src/configs/auth.js +5 -0
  263. package/src/configs/aws-exports.js +30 -0
  264. package/src/configs/firebase.js +25 -0
  265. package/src/configs/i18n.js +34 -0
  266. package/src/configs/izColors.json +11 -0
  267. package/src/configs/primaryColorConfig.js +35 -0
  268. package/src/configs/themeConfig.js +44 -0
  269. package/src/context/AuthContext.js +179 -0
  270. package/src/context/BuilderContext.jsx +209 -0
  271. package/src/context/SystemContext.js +99 -0
  272. package/src/hooks/useAuth.js +4 -0
  273. package/src/layouts/UserLayout.js +94 -0
  274. package/src/layouts/UserThemeOptions.js +191 -0
  275. package/src/layouts/components/Direction.js +30 -0
  276. package/src/layouts/components/HtmlTooltip.js +15 -0
  277. package/src/layouts/components/Translations.js +11 -0
  278. package/src/layouts/components/UserDropdown.js +217 -0
  279. package/src/layouts/components/UserIcon.js +40 -0
  280. package/src/layouts/components/acl/Can.js +6 -0
  281. package/src/layouts/components/acl/CanViewNavGroup.js +36 -0
  282. package/src/layouts/components/acl/CanViewNavLink.js +17 -0
  283. package/src/layouts/components/acl/CanViewNavSectionTitle.js +17 -0
  284. package/src/layouts/components/horizontal/AppBarContent.js +39 -0
  285. package/src/layouts/components/horizontal/ServerSideNavItems.js +44 -0
  286. package/src/layouts/components/mui/StepperComps.js +55 -0
  287. package/src/layouts/components/vertical/AppBarContent.js +35 -0
  288. package/src/layouts/components/vertical/ServerSideNavItems.js +44 -0
  289. package/src/lib/index.js +75 -0
  290. package/src/lib/navigation/NavigationExtensionContext.jsx +81 -0
  291. package/src/lib/navigation/mergeNavExtensions.js +66 -0
  292. package/src/lib/navigation/useNavExtension.js +54 -0
  293. package/src/lib/providers/RoboByteFrontBuilderProvider.jsx +57 -0
  294. package/src/libs/ApexCharts.jsx +5 -0
  295. package/src/libs/ReactPlayer.jsx +5 -0
  296. package/src/libs/Recharts.jsx +4 -0
  297. package/src/libs/auth.js +124 -0
  298. package/src/libs/styles/AppFullCalendar.js +505 -0
  299. package/src/libs/styles/AppKeenSlider.js +116 -0
  300. package/src/libs/styles/AppReactApexCharts.jsx +110 -0
  301. package/src/libs/styles/AppReactDatepicker.jsx +470 -0
  302. package/src/libs/styles/AppReactDropzone.js +76 -0
  303. package/src/libs/styles/AppReactToastify.jsx +108 -0
  304. package/src/libs/styles/AppRecharts.js +55 -0
  305. package/src/libs/styles/inputOtp.module.css +39 -0
  306. package/src/libs/styles/tiptapEditor.css +72 -0
  307. package/src/navigation/horizontal/index.js +246 -0
  308. package/src/navigation/vertical/index.js +253 -0
  309. package/src/pages/401.js +70 -0
  310. package/src/pages/404.js +67 -0
  311. package/src/pages/500.js +68 -0
  312. package/src/pages/[slug].js +115 -0
  313. package/src/pages/_app.js +148 -0
  314. package/src/pages/_document.js +72 -0
  315. package/src/pages/api/navigation/regenerate-registry.js +116 -0
  316. package/src/pages/api/navigation/save.js +218 -0
  317. package/src/pages/authModule/acl/index.js +48 -0
  318. package/src/pages/authModule/forgot-password/index.js +228 -0
  319. package/src/pages/authModule/permissions/rolePermissions/[id]/rolePermissionsUser/index.js +392 -0
  320. package/src/pages/authModule/permissions/rolePermissions/index.js +343 -0
  321. package/src/pages/authModule/permissions/systemPermissions/index.js +354 -0
  322. package/src/pages/authModule/privacy/index.js +721 -0
  323. package/src/pages/authModule/users/index.js +210 -0
  324. package/src/pages/index.js +44 -0
  325. package/src/pages/login/index.js +328 -0
  326. package/src/pages/mainHome/index.js +181 -0
  327. package/src/pages/navigatorBuilder/index.jsx +2070 -0
  328. package/src/pages/reportModule/reportBuilder/index.js +1361 -0
  329. package/src/pages/reportModule/reportBuilder/reportViewer/index.js +187 -0
  330. package/src/pages/reportModule/reportBuilder/reports/index.js +198 -0
  331. package/src/pages/viewBuilder/index.jsx +94 -0
  332. package/src/pages/viewBuilder/viewPage/index.jsx +46 -0
  333. package/src/pages/viewBuilder/views/index.js +146 -0
  334. package/src/pages/viewer/[id]/index.js +88 -0
  335. package/src/services/ContentTypes.js +10 -0
  336. package/src/services/DeleteService.js +77 -0
  337. package/src/services/Endpoints/BunnyEndpoints.js +26 -0
  338. package/src/services/Endpoints/CaseEndpoints.js +29 -0
  339. package/src/services/Endpoints/CaseTypeEndpoints.js +29 -0
  340. package/src/services/Endpoints/ContactsEndpoints.js +81 -0
  341. package/src/services/Endpoints/CourtEndpoints.js +29 -0
  342. package/src/services/Endpoints/FilterEndpoints.js +31 -0
  343. package/src/services/Endpoints/NavigatorEndpoints.js +21 -0
  344. package/src/services/Endpoints/ReportBuilderEndpoints.js +45 -0
  345. package/src/services/Endpoints/UiBuilderEndpoints.js +37 -0
  346. package/src/services/Endpoints/UserTableTemplateEndpoints.js +26 -0
  347. package/src/services/Endpoints/UsersEndpoints.js +142 -0
  348. package/src/services/Endpoints/ViewEndpoints.js +28 -0
  349. package/src/services/Endpoints/ViewPermissionEndpoints.js +37 -0
  350. package/src/services/Endpoints/ViewPermissionRoleEndpoints.js +39 -0
  351. package/src/services/Endpoints/ViewPermissionRoleItemsEndpoints.js +32 -0
  352. package/src/services/Endpoints/ViewPermissionRoleUsersEndpoints.js +28 -0
  353. package/src/services/Endpoints/WidgetEndpoints.js +28 -0
  354. package/src/services/Endpoints.js +49 -0
  355. package/src/services/External/BunnyCdn/BunnyUploadFile.js +168 -0
  356. package/src/services/GetService.js +67 -0
  357. package/src/services/MetaDataTemplate/index.js +5 -0
  358. package/src/services/PatchService.js +83 -0
  359. package/src/services/PostService.js +81 -0
  360. package/src/services/StreamService.js +82 -0
  361. package/src/services/UpdateService.js +82 -0
  362. package/src/services/auth/AuthService.js +47 -0
  363. package/src/services/auth/GetUsersService.js +38 -0
  364. package/src/services/auth/PostRegisterUser.js +29 -0
  365. package/src/services/auth/PostResetPasswordService.js +28 -0
  366. package/src/services/auth/PutAccountService.js +29 -0
  367. package/src/services/auth/PutRefreshToken.js +69 -0
  368. package/src/services/auth/RefreshToken.js +0 -0
  369. package/src/services/builderHelper/actionExecutor.js +73 -0
  370. package/src/services/builderHelper/builderHelper.js +99 -0
  371. package/src/services/builderHelper/index.js +2 -0
  372. package/src/services/builderHelper/jsExecutor.js +115 -0
  373. package/src/services/builderHelper/layoutHelpers.js +231 -0
  374. package/src/services/builderHelper/nodeFactory.js +44 -0
  375. package/src/services/builderHelper/resolveProps.js +34 -0
  376. package/src/services/builderHelper/tree.js +131 -0
  377. package/src/services/components/UniversalNestedAutocomplete.js +331 -0
  378. package/src/services/components/agGridAutoComplete.js +172 -0
  379. package/src/services/components/universalAutoComplete.js +207 -0
  380. package/src/services/enums/ReportBuilderTypeEnum.js +18 -0
  381. package/src/services/helper/FilterFormat.js +70 -0
  382. package/src/services/helper/FormatCurrencyIQD.js +11 -0
  383. package/src/services/helper/datagridEditComponents.js +38 -0
  384. package/src/services/helper/dateFormat.js +30 -0
  385. package/src/services/helper/formData.js +21 -0
  386. package/src/services/helper/getFieldByType.js +0 -0
  387. package/src/services/helper/getPropByString.js +18 -0
  388. package/src/services/helper/handleChange.js +26 -0
  389. package/src/services/helper/helper.js +105 -0
  390. package/src/services/helper/multiSelectEditor.js +226 -0
  391. package/src/services/helper/translateOrderReturnStatus.js +12 -0
  392. package/src/services/helper/translateRole.js +24 -0
  393. package/src/services/helper/translateStatus.js +12 -0
  394. package/src/services/helper/translateTransferReceiptType.js +67 -0
  395. package/src/services/helper/translsateStoreProductTransfer.js +40 -0
  396. package/src/services/helper/translsateStoreType.js +25 -0
  397. package/src/services/helper/useInterval.js +21 -0
  398. package/src/services/helper/yupCutomization.js +15 -0
  399. package/src/services/reportData/fetchReportData.js +210 -0
  400. package/src/views/ConfirmDialog.js +178 -0
  401. package/src/views/builder/JSEditor.js +226 -0
  402. package/src/views/builder/inspector/Inspector.jsx +63 -0
  403. package/src/views/builder/inspector/Tabs/ComponentActionsTab.jsx +117 -0
  404. package/src/views/builder/inspector/Tabs/MainTab.jsx +95 -0
  405. package/src/views/builder/inspector/Tabs/RulesTab.jsx +79 -0
  406. package/src/views/builder/inspector/Tabs/StyleTab.jsx +79 -0
  407. package/src/views/builder/inspector/definitions/autocomplete/main.js +25 -0
  408. package/src/views/builder/inspector/definitions/breadcrumb/main.js +9 -0
  409. package/src/views/builder/inspector/definitions/button/actions.js +12 -0
  410. package/src/views/builder/inspector/definitions/button/main.js +14 -0
  411. package/src/views/builder/inspector/definitions/button/rules.js +5 -0
  412. package/src/views/builder/inspector/definitions/button/style.js +32 -0
  413. package/src/views/builder/inspector/definitions/button.actions.js +12 -0
  414. package/src/views/builder/inspector/definitions/card/main.js +11 -0
  415. package/src/views/builder/inspector/definitions/cell/main.js +4 -0
  416. package/src/views/builder/inspector/definitions/checkbox/actions.js +1 -0
  417. package/src/views/builder/inspector/definitions/checkbox/main.js +13 -0
  418. package/src/views/builder/inspector/definitions/checkbox/rules.js +8 -0
  419. package/src/views/builder/inspector/definitions/checkbox/style.js +38 -0
  420. package/src/views/builder/inspector/definitions/checkboxFields.js +0 -0
  421. package/src/views/builder/inspector/definitions/column/main.js +9 -0
  422. package/src/views/builder/inspector/definitions/column-group/main.js +18 -0
  423. package/src/views/builder/inspector/definitions/common/actions.js +1 -0
  424. package/src/views/builder/inspector/definitions/common/main.js +14 -0
  425. package/src/views/builder/inspector/definitions/common/rules.js +8 -0
  426. package/src/views/builder/inspector/definitions/common/style.js +39 -0
  427. package/src/views/builder/inspector/definitions/common.advanced.js +8 -0
  428. package/src/views/builder/inspector/definitions/common.main.js +14 -0
  429. package/src/views/builder/inspector/definitions/common.style.js +33 -0
  430. package/src/views/builder/inspector/definitions/commonMainFields.js +18 -0
  431. package/src/views/builder/inspector/definitions/container/actions.js +1 -0
  432. package/src/views/builder/inspector/definitions/container/main.js +4 -0
  433. package/src/views/builder/inspector/definitions/container/rules.js +4 -0
  434. package/src/views/builder/inspector/definitions/container/style.js +32 -0
  435. package/src/views/builder/inspector/definitions/datepicker/actions.js +1 -0
  436. package/src/views/builder/inspector/definitions/datepicker/main.js +28 -0
  437. package/src/views/builder/inspector/definitions/datepicker/rules.js +8 -0
  438. package/src/views/builder/inspector/definitions/datepicker/style.js +38 -0
  439. package/src/views/builder/inspector/definitions/datepicker.main.js +28 -0
  440. package/src/views/builder/inspector/definitions/divider/actions.js +1 -0
  441. package/src/views/builder/inspector/definitions/divider/main.js +23 -0
  442. package/src/views/builder/inspector/definitions/divider/rules.js +4 -0
  443. package/src/views/builder/inspector/definitions/divider/style.js +9 -0
  444. package/src/views/builder/inspector/definitions/dropdown/actions.js +10 -0
  445. package/src/views/builder/inspector/definitions/dropdown/main.js +19 -0
  446. package/src/views/builder/inspector/definitions/dropdown/rules.js +8 -0
  447. package/src/views/builder/inspector/definitions/dropdown/style.js +38 -0
  448. package/src/views/builder/inspector/definitions/header/actions.js +1 -0
  449. package/src/views/builder/inspector/definitions/header/main.js +29 -0
  450. package/src/views/builder/inspector/definitions/header/rules.js +4 -0
  451. package/src/views/builder/inspector/definitions/header/style.js +12 -0
  452. package/src/views/builder/inspector/definitions/header-cell/main.js +5 -0
  453. package/src/views/builder/inspector/definitions/image/actions.js +1 -0
  454. package/src/views/builder/inspector/definitions/image/main.js +13 -0
  455. package/src/views/builder/inspector/definitions/image/rules.js +4 -0
  456. package/src/views/builder/inspector/definitions/image/style.js +12 -0
  457. package/src/views/builder/inspector/definitions/index.js +407 -0
  458. package/src/views/builder/inspector/definitions/input/actions.js +1 -0
  459. package/src/views/builder/inspector/definitions/input/main.js +14 -0
  460. package/src/views/builder/inspector/definitions/input/rules.js +8 -0
  461. package/src/views/builder/inspector/definitions/input/style.js +32 -0
  462. package/src/views/builder/inspector/definitions/label/actions.js +1 -0
  463. package/src/views/builder/inspector/definitions/label/main.js +24 -0
  464. package/src/views/builder/inspector/definitions/label/rules.js +4 -0
  465. package/src/views/builder/inspector/definitions/label/style.js +12 -0
  466. package/src/views/builder/inspector/definitions/layout/actions.js +1 -0
  467. package/src/views/builder/inspector/definitions/layout/main.js +6 -0
  468. package/src/views/builder/inspector/definitions/layout/rules.js +3 -0
  469. package/src/views/builder/inspector/definitions/layout/style.js +7 -0
  470. package/src/views/builder/inspector/definitions/layout-cell/actions.js +1 -0
  471. package/src/views/builder/inspector/definitions/layout-cell/main.js +7 -0
  472. package/src/views/builder/inspector/definitions/layout-cell/rules.js +3 -0
  473. package/src/views/builder/inspector/definitions/layout-cell/style.js +44 -0
  474. package/src/views/builder/inspector/definitions/link/actions.js +1 -0
  475. package/src/views/builder/inspector/definitions/link/main.js +29 -0
  476. package/src/views/builder/inspector/definitions/link/rules.js +4 -0
  477. package/src/views/builder/inspector/definitions/link/style.js +11 -0
  478. package/src/views/builder/inspector/definitions/menu/actions.js +3 -0
  479. package/src/views/builder/inspector/definitions/menu/main.js +16 -0
  480. package/src/views/builder/inspector/definitions/menu/rules.js +4 -0
  481. package/src/views/builder/inspector/definitions/menu/style.js +33 -0
  482. package/src/views/builder/inspector/definitions/number/actions.js +10 -0
  483. package/src/views/builder/inspector/definitions/number/main.js +29 -0
  484. package/src/views/builder/inspector/definitions/number/rules.js +8 -0
  485. package/src/views/builder/inspector/definitions/number/style.js +32 -0
  486. package/src/views/builder/inspector/definitions/progress-circle/actions.js +1 -0
  487. package/src/views/builder/inspector/definitions/progress-circle/main.js +18 -0
  488. package/src/views/builder/inspector/definitions/progress-circle/rules.js +4 -0
  489. package/src/views/builder/inspector/definitions/progress-circle/style.js +5 -0
  490. package/src/views/builder/inspector/definitions/progress-line/actions.js +1 -0
  491. package/src/views/builder/inspector/definitions/progress-line/main.js +16 -0
  492. package/src/views/builder/inspector/definitions/progress-line/rules.js +4 -0
  493. package/src/views/builder/inspector/definitions/progress-line/style.js +6 -0
  494. package/src/views/builder/inspector/definitions/radio/actions.js +10 -0
  495. package/src/views/builder/inspector/definitions/radio/main.js +16 -0
  496. package/src/views/builder/inspector/definitions/radio/rules.js +8 -0
  497. package/src/views/builder/inspector/definitions/radio/style.js +32 -0
  498. package/src/views/builder/inspector/definitions/reportViewer/main.js +12 -0
  499. package/src/views/builder/inspector/definitions/richtext/actions.js +10 -0
  500. package/src/views/builder/inspector/definitions/richtext/main.js +21 -0
  501. package/src/views/builder/inspector/definitions/richtext/rules.js +8 -0
  502. package/src/views/builder/inspector/definitions/richtext/style.js +32 -0
  503. package/src/views/builder/inspector/definitions/signature/actions.js +1 -0
  504. package/src/views/builder/inspector/definitions/signature/main.js +13 -0
  505. package/src/views/builder/inspector/definitions/signature/rules.js +8 -0
  506. package/src/views/builder/inspector/definitions/signature/style.js +26 -0
  507. package/src/views/builder/inspector/definitions/table/main.js +9 -0
  508. package/src/views/builder/inspector/definitions/tag/actions.js +10 -0
  509. package/src/views/builder/inspector/definitions/tag/main.js +17 -0
  510. package/src/views/builder/inspector/definitions/tag/rules.js +8 -0
  511. package/src/views/builder/inspector/definitions/tag/style.js +32 -0
  512. package/src/views/builder/inspector/definitions/textarea/actions.js +1 -0
  513. package/src/views/builder/inspector/definitions/textarea/main.js +16 -0
  514. package/src/views/builder/inspector/definitions/textarea/rules.js +8 -0
  515. package/src/views/builder/inspector/definitions/textarea/style.js +32 -0
  516. package/src/views/builder/inspector/definitions/time/actions.js +10 -0
  517. package/src/views/builder/inspector/definitions/time/main.js +18 -0
  518. package/src/views/builder/inspector/definitions/time/rules.js +8 -0
  519. package/src/views/builder/inspector/definitions/time/style.js +32 -0
  520. package/src/views/builder/inspector/definitions/toggle/actions.js +10 -0
  521. package/src/views/builder/inspector/definitions/toggle/main.js +26 -0
  522. package/src/views/builder/inspector/definitions/toggle/rules.js +8 -0
  523. package/src/views/builder/inspector/definitions/toggle/style.js +32 -0
  524. package/src/views/builder/inspector/fields/BooleanEditor.jsx +30 -0
  525. package/src/views/builder/inspector/fields/ExpressionEditor.jsx +35 -0
  526. package/src/views/builder/inspector/fields/FieldWrapper.jsx +15 -0
  527. package/src/views/builder/inspector/fields/ItemsEditor.jsx +118 -0
  528. package/src/views/builder/inspector/fields/OptionsEditor.jsx +118 -0
  529. package/src/views/builder/inspector/fields/SelectEditor.jsx +32 -0
  530. package/src/views/builder/inspector/fields/TabsEditor.jsx +128 -0
  531. package/src/views/builder/inspector/fields/TextEditor.jsx +28 -0
  532. package/src/views/builder/inspector/fields/TextFieldEditor.jsx +0 -0
  533. package/src/views/builder/sidebar/Sidebar.jsx +20 -0
  534. package/src/views/builder/sidebar/SidebarTabs.jsx +50 -0
  535. package/src/views/builder/sidebar/tabs/ActionsTab.jsx +94 -0
  536. package/src/views/builder/sidebar/tabs/Components/ComponentItem.jsx +69 -0
  537. package/src/views/builder/sidebar/tabs/Components/ComponentsTab.jsx +89 -0
  538. package/src/views/builder/sidebar/tabs/Components/GroupLevelAutocomplete.jsx +269 -0
  539. package/src/views/builder/sidebar/tabs/Components/componentCatalog.js +69 -0
  540. package/src/views/builder/sidebar/tabs/TreeTab.jsx +205 -0
  541. package/src/views/builder/sidebar/tabs/ViewTab.jsx +121 -0
  542. package/src/views/builder/viewer/Canvas.jsx +7 -0
  543. package/src/views/builder/viewer/ComponentRenderer.jsx +166 -0
  544. package/src/views/builder/viewer/DropZone.jsx +60 -0
  545. package/src/views/builder/viewer/ProductionViewer.jsx +155 -0
  546. package/src/views/builder/viewer/SaveViewDialog.jsx +60 -0
  547. package/src/views/builder/viewer/SaveWidgetDialog.jsx +142 -0
  548. package/src/views/builder/viewer/Viewer.jsx +83 -0
  549. package/src/views/builder/viewer/ViewerComponentWrapper.jsx +238 -0
  550. package/src/views/builder/viewer/ViewerToolbar.jsx +89 -0
  551. package/src/views/builder/viewer/renderers/AutoCompleteRenderer.jsx +57 -0
  552. package/src/views/builder/viewer/renderers/BreadcrumbRenderer.jsx +32 -0
  553. package/src/views/builder/viewer/renderers/ButtonRenderer.jsx +55 -0
  554. package/src/views/builder/viewer/renderers/CardRenderer.jsx +76 -0
  555. package/src/views/builder/viewer/renderers/CellRenderer.jsx +71 -0
  556. package/src/views/builder/viewer/renderers/CheckboxRenderer.jsx +27 -0
  557. package/src/views/builder/viewer/renderers/ColumnGroupRenderer.jsx +96 -0
  558. package/src/views/builder/viewer/renderers/ColumnRenderer.jsx +71 -0
  559. package/src/views/builder/viewer/renderers/ContainerRenderer.jsx +111 -0
  560. package/src/views/builder/viewer/renderers/DatePickerRenderer.jsx +49 -0
  561. package/src/views/builder/viewer/renderers/DividerRenderer.jsx +22 -0
  562. package/src/views/builder/viewer/renderers/DropdownRenderer.jsx +63 -0
  563. package/src/views/builder/viewer/renderers/HeaderCellRenderer.jsx +78 -0
  564. package/src/views/builder/viewer/renderers/HeaderRenderer.jsx +23 -0
  565. package/src/views/builder/viewer/renderers/ImageRenderer.jsx +26 -0
  566. package/src/views/builder/viewer/renderers/InputRenderer.jsx +34 -0
  567. package/src/views/builder/viewer/renderers/LabelRenderer.jsx +23 -0
  568. package/src/views/builder/viewer/renderers/LayoutCellRenderer.jsx +162 -0
  569. package/src/views/builder/viewer/renderers/LayoutContextMenu.jsx +173 -0
  570. package/src/views/builder/viewer/renderers/LayoutRenderer.jsx +51 -0
  571. package/src/views/builder/viewer/renderers/LinkRenderer.jsx +24 -0
  572. package/src/views/builder/viewer/renderers/MenuRenderer.jsx +291 -0
  573. package/src/views/builder/viewer/renderers/NumberFormatRenderer.jsx +80 -0
  574. package/src/views/builder/viewer/renderers/ProgressCircleRenderer.jsx +47 -0
  575. package/src/views/builder/viewer/renderers/ProgressLineRenderer.jsx +36 -0
  576. package/src/views/builder/viewer/renderers/RadioGroupRenderer.jsx +57 -0
  577. package/src/views/builder/viewer/renderers/RepeaterRenderer.jsx +94 -0
  578. package/src/views/builder/viewer/renderers/ReportViewerRenderer.jsx +15 -0
  579. package/src/views/builder/viewer/renderers/RichTextRenderer.jsx +76 -0
  580. package/src/views/builder/viewer/renderers/SignatureRenderer.jsx +89 -0
  581. package/src/views/builder/viewer/renderers/TabRenderer.jsx +82 -0
  582. package/src/views/builder/viewer/renderers/TableRenderer.jsx +92 -0
  583. package/src/views/builder/viewer/renderers/TagPickerRenderer.jsx +67 -0
  584. package/src/views/builder/viewer/renderers/TextAreaRenderer.jsx +37 -0
  585. package/src/views/builder/viewer/renderers/TextRenderer.jsx +9 -0
  586. package/src/views/builder/viewer/renderers/TimePickerRenderer.jsx +49 -0
  587. package/src/views/builder/viewer/renderers/ToggleRenderer.jsx +46 -0
  588. package/src/views/builder/viewer/renderers/WizardRenderer.jsx +88 -0
  589. package/src/views/builder/viewer/renderers/WizardStepRenderer.jsx +72 -0
  590. package/src/views/customFilter/CustomFilterDialog.js +1142 -0
  591. package/src/views/genericTable/BuilderExpressionParams.js +193 -0
  592. package/src/views/genericTable/FixedFilterDialog.js +447 -0
  593. package/src/views/genericTable/GenericForm.js +301 -0
  594. package/src/views/genericTable/QueryEditor.js +99 -0
  595. package/src/views/genericTable/RegexTextEditor.js +182 -0
  596. package/src/views/genericTable/ReportBuilderSaveDialog.js +153 -0
  597. package/src/views/genericTable/RoutingSettingDialog.js +189 -0
  598. package/src/views/genericTable/SGrid.js +2168 -0
  599. package/src/views/genericTable/SearchFilterDialog.js +247 -0
  600. package/src/views/genericTable/TAGGrid.js +1046 -0
  601. package/src/views/genericTable/cellEditors/autocompleteEditor.js +229 -0
  602. package/src/views/genericTable/cellRenderers/imageRenderer.js +14 -0
  603. package/src/views/genericTable/statusBar/rowCountStatusBar.js +37 -0
  604. package/src/views/genericTable/template/addTemplate.js +187 -0
  605. package/src/views/genericTable/toolPanels/CustomColumnsToolPanel.js +43 -0
  606. package/src/views/pages/auth/FooterIllustrationsV2.js +40 -0
  607. package/src/views/pages/misc/FooterIllustrations.js +47 -0
  608. package/src/views/pages/misc/muiTable/CustomPagination.js +34 -0
  609. package/src/views/pages/users/UserManageDialog.js +283 -0
  610. package/src/views/pages/users/UserViewPage.js +199 -0
  611. package/src/views/users/AddUserNameDialog.js +162 -0
  612. package/src/views/users/ContactManage.js +449 -0
  613. package/src/views/users/ResetPasswordDialog.js +242 -0
  614. package/styles/globals.css +71 -0
@@ -0,0 +1,2168 @@
1
+ /**
2
+ * SGrid: Server-side data grid wrapper around AG Grid for Mazajak
3
+ *
4
+ * What this component does
5
+ * - Renders an AG Grid in server-side row model mode with optional grouping, pivoting, and aggregation.
6
+ * - Fetches data from ReportBuilderEndpoints.Post.GenericGet for grouped, streamed, and paged requests.
7
+ * - Applies a unified filtering system (Tfilter) coming from multiple sources: external props, builder model, and local UI state.
8
+ * - Supports a global quick search term that behaves smartly for numeric vs. text fields.
9
+ * - Manages templates (save/load) for column layout, filters, and settings.
10
+ * - Exports data to PDF/Excel with current columns, order, and applied filters.
11
+ * - Integrates with dashboard/report builder contexts and honors time zone and formatting.
12
+ *
13
+ * Key props of interest
14
+ * - builderData: Provides selected fields, initial filters, and meta used to construct column definitions and filters.
15
+ * - filter: External filter object merged with local filters (Filter.LocalTfilter) and builder filters.
16
+ * - groupBy: Initial grouping configuration for server-side grouping.
17
+ * - actions: Optional cell renderer for Actions column.
18
+ * - refresh / externalTimer: Triggers to refresh the grid’s data.
19
+ * - fixedTIncludes: Extra includes to send with requests (controls data shape/joins on server).
20
+ * - reportTitle, pageName, uniqueIdPath, columnsConfig: Presentation/behavior options.
21
+ *
22
+ * Data flow overview
23
+ * 1) Column definitions are derived from builderData.selectedFields (+ extraCols) and user templates.
24
+ * 2) AG Grid is initialized with server-side datasource; getRowsFromApi constructs the request payload:
25
+ * - Merges filters in this order: LocalTfilter (component state) + builder filters + fixed filters from props.
26
+ * - Adds search term filters based on searchTermRef and searchFieldsRef metadata.
27
+ * - Translates group/pivot/value columns, sort model, and pagination into the expected backend format.
28
+ * 3) Data is requested via ReportBuilderEndpoints.Post.GenericGet. Responses may contain rows and aggregations.
29
+ * 4) Grid updates, status bar shows counts/aggregations, and export functions can read current viewer state.
30
+ *
31
+ * Quick search behavior (important)
32
+ * - searchTermRef holds the current string. If it parses to a finite number, we search numeric (Int) fields with a numeric value.
33
+ * - Otherwise, we search only non-Int fields using the raw string. This prevents type errors on the backend and improves matches.
34
+ * - searchFieldsRef is metadata describing which fields are searchable and their propertyType.
35
+ *
36
+ * Filters (Tfilter)
37
+ * - Filter object has LocalTfilter for user-added filters. Builder filters and fixed filters are merged with it.
38
+ * - Each filter item typically has: { path, friendlyName, value, method, dtoClassName, modelClassName, afterSelect }.
39
+ * - Grouping adds implicit Equals filters for the currently expanded group keys when requesting child levels.
40
+ *
41
+ * Exports
42
+ * - PDF export uses current visible columns (in order) and transformed cell values, includes a summary of active filters.
43
+ * - Excel export is supported (see FileExcelOutline usage) to dump the current dataset.
44
+ *
45
+ * Implementation notes
46
+ * - Uses themeQuartz from ag-grid-community with a custom accent color.
47
+ * - Maintains gridApi refs to read column state, sorting, and to trigger refreshServerSide.
48
+ * - Be cautious when modifying getRowsFromApi: it is responsible for composing the exact backend payload.
49
+ * - When adjusting quick search logic, keep numeric vs. text handling aligned with backend expectations.
50
+ */
51
+ // ** React Imports
52
+ // ** Next Import
53
+
54
+ // ** MUI Imports
55
+ import Box from '@mui/material/Box'
56
+ import Grid from '@mui/material/Grid'
57
+
58
+ // ** Icons Imports
59
+ // ** Store Imports
60
+ // ** Custom Components Imports
61
+ import {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'
62
+ import {Endpoints, Services} from 'src/services/Endpoints'
63
+ import {
64
+ Autocomplete, Checkbox,
65
+ CircularProgress,
66
+ Dialog,
67
+ FormControl, FormControlLabel,
68
+ IconButton,
69
+ MenuItem,
70
+ Select,
71
+ TextField,
72
+ Tooltip,
73
+ Chip,
74
+ Stack,
75
+ Popper,
76
+ Paper,
77
+ List,
78
+ ListItemButton,
79
+ ClickAwayListener
80
+ } from '@mui/material'
81
+ import {AgGridReact} from "ag-grid-react";
82
+ import {Edit, FilterAlt, PrintOutlined, RefreshOutlined, Save, SaveAs, Close} from "@mui/icons-material";
83
+ import {getRandomInt, Helper} from "services/helper/helper";
84
+ import PostService from 'services/PostService'
85
+ import handleChange from 'services/helper/handleChange'
86
+ import {DotsVerticalCircleOutline, FileExcelOutline} from 'mdi-material-ui'
87
+ import AddTemplateDialog from './template/addTemplate'
88
+ import UpdateService from 'services/UpdateService'
89
+ import {useRouter} from 'next/router'
90
+ import {SystemContext} from 'context/SystemContext'
91
+ import {AuthContext} from 'context/AuthContext'
92
+ import moment from "moment-timezone"
93
+ import numeral from 'numeral'
94
+ import CustomFilterDialog from "views/customFilter/CustomFilterDialog";
95
+ import CustomStatusBar from "views/genericTable/statusBar/rowCountStatusBar";
96
+ import StreamService from "services/StreamService";
97
+ import {themeQuartz} from 'ag-grid-community';
98
+ import {ReportBuilderEndpoints} from "services/Endpoints/ReportBuilderEndpoints";
99
+ import {debounce} from "lodash";
100
+ import jsPDF from "jspdf";
101
+ import "jspdf-autotable";
102
+ import arabicFontBase64 from "../../../public/fonts/font";
103
+ import {FilterFormat} from "services/helper/FilterFormat";
104
+
105
+ // ** Utils Import
106
+
107
+ // ** Actions Imports
108
+
109
+ // ** Custom Components Imports
110
+ const defaultFinalRequest = {
111
+ groupBy: null,
112
+ endpoint: null,
113
+ filter: {},
114
+ params: {}
115
+ }
116
+ const SGrid = props => {
117
+ // ** State
118
+ const appContext = useContext(SystemContext);
119
+ const imageBaseUrl = appContext?.settings?.imagesStorageServer;
120
+ const agTheme = themeQuartz
121
+ .withParams({
122
+ accentColor: "#FF1185"
123
+ });
124
+
125
+ const {
126
+ externalTimer,
127
+ isSingle,
128
+ minimized,
129
+ setData,
130
+ builderModel,
131
+ expireReport,
132
+ filter: externalFilter,
133
+ actions,
134
+ refresh,
135
+ height,
136
+ extraCols,
137
+ setOutGridApi,
138
+ setEventRowSelected,
139
+ pageName,
140
+ paramsPage,
141
+ fixedTIncludes,
142
+ groupBy,
143
+ noPurge,
144
+ reportTitle,
145
+ uniqueIdPath,
146
+ columnsConfig,
147
+ dataAsObject = false
148
+ } = props
149
+ const groupEndPoint = ReportBuilderEndpoints.Post.GenericGet;
150
+ const streamEndPoint = ReportBuilderEndpoints.Post.GenericGet;
151
+ const pagedEndPoint = ReportBuilderEndpoints.Post.GenericGet;
152
+ const [responseType, setResponseType] = useState()
153
+ const [pagedAgg, setPagedAgg] = useState()
154
+ const [colDefs, setColDefs] = useState([])
155
+ const [gridApi, setGridApi] = useState(null)
156
+ const [includes, setIncludes] = useState([])
157
+ const [isPagination, setIsPagination] = useState(true)
158
+ const [templates, setTemplates] = useState([])
159
+ const [timerValue, setTimerValue] = useState(0)
160
+ const [localRefresh, setLocalRefresh] = useState(false)
161
+ const [selectedTemplate, setSelectedTemplate] = useState(null)
162
+ const [localClasName, setLocalClasName] = useState(null)
163
+ const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
164
+ const router = useRouter()
165
+ const authValues = useContext(AuthContext)
166
+ const [isTemplateEditing, setIsTemplateEditing] = useState(false)
167
+ const [isDownloading, setIsDownloading] = useState(false)
168
+ const [finalRequestObject, setFinalRequestObject] = useState(defaultFinalRequest)
169
+ const [selectedFields, setSelectedFields] = useState([])
170
+ const [selectParams, setSelectParams] = useState([])
171
+ const [selectTFilter, setSelectTFilter] = useState([])
172
+ const [builderTFilter, setBuilderTFilter] = useState([])
173
+ const [searchTerm, setSearchTerm] = useState('');
174
+ const [selectedSearchObjects, setSelectedSearchObjects] = useState([]);
175
+ const [tRouting, setTRouting] = useState([]);
176
+ const [builderData, setBuilderData] = useState(null);
177
+
178
+ // Search grouping name for OR groups
179
+ const SEARCH_GROUP_NAME = 'searchGroup';
180
+
181
+ // UI refs/states for search popover
182
+ const searchInputRef = useRef(null);
183
+ const [searchPopoverOpen, setSearchPopoverOpen] = useState(false);
184
+ const [searchPopoverAnchor, setSearchPopoverAnchor] = useState(null);
185
+
186
+ const searchTermRef = useRef('');
187
+ const searchFieldsRef = useRef([]); // metadata only, no value
188
+ const lastRowRef = useRef({});
189
+
190
+ const [Filter, setFilter] = useState({
191
+ Tfilter: [],
192
+ LocalTfilter: [],
193
+ })
194
+ const [openDialogs, setOpenDialogs] = useState({
195
+ addTemplate: false,
196
+ CustomFilter: false,
197
+ })
198
+ const getDefaultColDefs = () => {
199
+ return [
200
+ {
201
+ field: 'Actions',
202
+ sortable: false,
203
+ width: 60,
204
+ pinned: 'left',
205
+ enableRowGroup: false,
206
+ cellRenderer: (params) => {
207
+ if (params.node.group) {
208
+ return <Box sx={{display: 'flex', alignItems: 'center'}}>
209
+ <IconButton
210
+ sx={{color: 'primary.light'}}
211
+ onClick={() => {
212
+ const groupKeys = getParentKeys(params.node.parent)
213
+ groupKeys.push(params.node.key)
214
+ params.api.refreshServerSide({purge: !noPurge, route: groupKeys});
215
+ }}
216
+ >
217
+ <RefreshOutlined/>
218
+ </IconButton>
219
+ </Box>
220
+ }
221
+ if (actions != null) return actions(params)
222
+ }
223
+ },
224
+ ]
225
+ }
226
+ const autoGroupColumnDef = {
227
+ headerName: 'My Group',
228
+ sortable: false,
229
+ minWidth: 220,
230
+ }
231
+
232
+ const applyValueFormatter = (formatterString) => {
233
+ return function (params) {
234
+ return new Function("params", "moment", "userTimeZone", "enumTrans", "numeral", formatterString)(
235
+ params,
236
+ moment,
237
+ userTimeZone,
238
+ Helper.enumTrans,
239
+ numeral,
240
+ );
241
+ };
242
+ };
243
+
244
+ const handlePDFExport = async () => {
245
+ if (!gridApi) return;
246
+
247
+ // Build filter summary from current filters
248
+ const activeTFilters = Filter?.LocalTfilter ?? [];
249
+ const activeFixedTFilter = builderData?.filter?.LocalTfilter ?? []
250
+ const activeFilters = [...activeFixedTFilter, ...activeTFilters]
251
+ const filterSummary = activeFilters.map(f => {
252
+ const field = f.friendlyName.replace('>', '.') || f.path;
253
+ const method = f.method || "=";
254
+ let value = f.value;
255
+
256
+ // Handle special types
257
+ if (Array.isArray(value)) {
258
+ value = value.map(v => (v?.name ?? v)).join(", ");
259
+ } else if (typeof value === "object" && value?.name) {
260
+ value = value.name;
261
+ } else if (value == null || value === "") {
262
+ value = "—";
263
+ }
264
+
265
+ return `${field} ${method} ${value}`;
266
+ }).join(" | ");
267
+
268
+ // 1. Get visible columns in current AG Grid order
269
+ const colState = gridApi.getColumnState();
270
+ let orderedVisibleCols = colState
271
+ .filter(c => !c.hide)
272
+ .map(c => {
273
+ if (c.colId === "ag-Grid-AutoColumn") {
274
+ return {...autoGroupColumnDef, field: "__autoGroup"};
275
+ }
276
+ // ✅ handle groupCount separately
277
+ if (c.colId === "IZ_groupCount") {
278
+ return {field: "IZ_groupCount", headerName: "Group Count"};
279
+ }
280
+ return colDefs.find(cd => cd.field === c.colId);
281
+ })
282
+ .filter(Boolean);
283
+
284
+ // ✅ 2. Handle pivot mode
285
+ if (gridApi.isPivotMode()) {
286
+ const pivotResultCols = gridApi.getPivotResultColumns();
287
+ if (pivotResultCols && pivotResultCols.length > 0) {
288
+ pivotResultCols.forEach(pivotCol => {
289
+ orderedVisibleCols.push({
290
+ field: pivotCol.getColId(),
291
+ headerName: pivotCol.getColDef().headerName,
292
+ isPivot: true,
293
+ });
294
+ });
295
+ }
296
+ }
297
+
298
+ // reverse for RTL
299
+ orderedVisibleCols = orderedVisibleCols.reverse();
300
+
301
+ // 2. Get rows
302
+ const rows = gridApi.getDisplayedRowCount()
303
+ ? Array.from({length: gridApi.getDisplayedRowCount()})
304
+ .map((_, i) => gridApi.getDisplayedRowAtIndex(i)?.data)
305
+ : [];
306
+
307
+ // 3. Setup jsPDF
308
+ const doc = new jsPDF("landscape");
309
+ doc.addFileToVFS("NotoSansArabic-Regular.ttf", arabicFontBase64);
310
+ doc.addFont("NotoSansArabic-Regular.ttf", "NotoSansArabic", "normal");
311
+ doc.setFont("NotoSansArabic");
312
+
313
+ doc.setFontSize(14);
314
+ if (reportTitle) {
315
+ doc.text(String(reportTitle), doc.internal.pageSize.getWidth() - 14, 15, {
316
+ align: "right",
317
+ });
318
+ }
319
+ // ✅ Add filters summary if exists
320
+ if (filterSummary) {
321
+ doc.setFontSize(9);
322
+ doc.setTextColor(100); // gray
323
+ const lines = doc.splitTextToSize(filterSummary, doc.internal.pageSize.getWidth() - 30);
324
+ doc.text(lines, doc.internal.pageSize.getWidth() - 14, 25, {align: "right"});
325
+ }
326
+ // 4. Build header
327
+ const head = [
328
+ orderedVisibleCols.map(c =>
329
+ /image|logo|url/i.test(c.field) ? "" : (c.headerName)
330
+ )
331
+ ];
332
+
333
+ // 5. Build body
334
+ const body = await Promise.all(
335
+ rows.map(async row =>
336
+ Promise.all(
337
+ orderedVisibleCols.map(async c => {
338
+ if (c.field === "__autoGroup") {
339
+ return row?.[gridApi.getRowGroupColumns()[0]?.getColId()] ?? "";
340
+ }
341
+ if (c.field === "IZ_groupCount") {
342
+ const val = row?.groupCount ?? row?.IZ_groupCount ?? "";
343
+ return val ? numeral(Number(val)).format("0,0") : "";
344
+ }
345
+
346
+ // ✅ Pivot values
347
+ if (c.isPivot) {
348
+ const val = row?.[c.field];
349
+ return val == null ? "" : numeral(Number(val).toFixed(2)).format("0,0.00");
350
+ }
351
+
352
+ // normal values
353
+ const val = row?.[c.field] ?? "";
354
+ const isImageField = /image|logo|url/i.test(c.field);
355
+ if (isImageField && val) {
356
+ const img = await loadImage(val);
357
+ if (img) return {isImage: true, image: img};
358
+ return "";
359
+ }
360
+ return String(val);
361
+ })
362
+ )
363
+ )
364
+ );
365
+
366
+ // 6. Render table
367
+ doc.autoTable({
368
+ head,
369
+ body,
370
+ startY: filterSummary ? 35 : 25, // push table down if filters exist
371
+ styles: {
372
+ font: "NotoSansArabic",
373
+ fontSize: 10,
374
+ halign: "right",
375
+ valign: "middle"
376
+ },
377
+ headStyles: {
378
+ fillColor: [63, 81, 181],
379
+ textColor: [255, 255, 255],
380
+ halign: "right",
381
+ valign: "middle"
382
+ },
383
+ bodyStyles: {
384
+ halign: "right",
385
+ valign: "middle"
386
+ },
387
+ alternateRowStyles: {fillColor: [245, 245, 245]},
388
+
389
+ didParseCell: (data) => {
390
+ // ✅ Handle images
391
+ if (data.cell.raw?.isImage) {
392
+ data.cell.styles.minCellHeight = 18;
393
+ data.cell.text = [];
394
+ return;
395
+ }
396
+
397
+ const val = data.cell.raw ?? data.cell.text?.[0];
398
+
399
+ // ⛔ Ignore falsy / empty
400
+ if (val == null || val === "") return;
401
+
402
+ // ✅ PURE number check (no letters or spaces)
403
+ const isPureNumber =
404
+ typeof val === "number" ||
405
+ (typeof val === "string" && /^[+-]?\d+(\.\d+)?$/.test(val.trim()));
406
+
407
+ if (isPureNumber) {
408
+ const num = parseFloat(val);
409
+ if (!isNaN(num)) {
410
+ data.cell.text = [numeral(num.toFixed(2)).format("0,0.00")];
411
+ }
412
+ return;
413
+ }
414
+
415
+ // ✅ STRICT date check (ISO, yyyy-mm-dd, or recognizable formats)
416
+ const isIsoDate =
417
+ typeof val === "string" &&
418
+ /^\d{4}-\d{2}-\d{2}(T.*)?$/.test(val.trim());
419
+
420
+ const isLikelyDate =
421
+ isIsoDate ||
422
+ moment(val, [
423
+ "YYYY-MM-DD",
424
+ "DD/MM/YYYY",
425
+ "MM/DD/YYYY",
426
+ "YYYY/MM/DD",
427
+ "DD-MM-YYYY",
428
+ "MM-DD-YYYY",
429
+ ], true).isValid();
430
+
431
+ if (isLikelyDate) {
432
+ const m = moment.utc(val).tz(userTimeZone);
433
+ data.cell.text = [m.format("DD/MM/YYYY - A hh:mm")];
434
+ return;
435
+ }
436
+
437
+ // ✅ Otherwise: leave text as is
438
+ },
439
+
440
+ didDrawCell: (data) => {
441
+ // ✅ Draw images
442
+ if (data.cell.raw?.isImage) {
443
+ const {base64, mimeType} = data.cell.raw.image;
444
+ if (base64) {
445
+ const format = mimeType.includes("jpeg") ? "JPEG" : "PNG";
446
+ const size = 12;
447
+ const x = data.cell.x + (data.cell.width - size) / 2;
448
+ const y = data.cell.y + (data.cell.height - size) / 2;
449
+ doc.addImage(base64, format, x, y, size, size);
450
+ }
451
+ }
452
+ },
453
+ });
454
+
455
+
456
+ // 7. Print Aggregations if available
457
+ if (pagedAgg && pagedAgg.length > 0) {
458
+ const aggRow = pagedAgg[0];
459
+
460
+ const aggHead = [
461
+ orderedVisibleCols.map(c => /image|logo|url/i.test(c.field) ? "" : (c.headerName || ""))
462
+ ];
463
+ const aggBody = [
464
+ orderedVisibleCols.map(c => {
465
+ if (c.field === "__autoGroup") return "";
466
+ if (c.field === "IZ_groupCount") {
467
+ const val = aggRow["groupCount"] ?? aggRow["IZ_groupCount"];
468
+ return val ? numeral(Number(val)).format("0,0") : "";
469
+ }
470
+ const val = aggRow[c.field];
471
+ if (val == null) return "";
472
+ if (typeof val === "number" && !isNaN(val)) {
473
+ return numeral(val.toFixed(2)).format("0,0.00");
474
+ }
475
+ return String(val);
476
+ })
477
+ ];
478
+
479
+ doc.autoTable({
480
+ head: aggHead,
481
+ body: aggBody,
482
+ startY: doc.lastAutoTable.finalY + 10,
483
+ styles: {
484
+ font: "NotoSansArabic",
485
+ fontSize: 10,
486
+ halign: "right",
487
+ valign: "middle",
488
+ },
489
+ headStyles: {
490
+ fillColor: [33, 150, 243],
491
+ textColor: [255, 255, 255],
492
+ halign: "right",
493
+ },
494
+ bodyStyles: {
495
+ halign: "right",
496
+ },
497
+ });
498
+ }
499
+
500
+
501
+ // 7. Footer
502
+ const date = new Date().toLocaleString("ar-IQ");
503
+ doc.setFontSize(8);
504
+ doc.text(
505
+ `تاريخ الإنشاء: ${date}`,
506
+ doc.internal.pageSize.getWidth() - 14,
507
+ doc.internal.pageSize.height - 10,
508
+ {align: "right"}
509
+ );
510
+
511
+ doc.save("report.pdf");
512
+ };
513
+
514
+ // Utility to fetch + encode image
515
+ async function loadImage(val) {
516
+ try {
517
+ const imageUrl = `${imageBaseUrl}/${val}`;
518
+ const resp = await fetch(imageUrl);
519
+ const blob = await resp.blob();
520
+ const mimeType = blob.type || "image/png";
521
+
522
+ return await new Promise(resolve => {
523
+ const reader = new FileReader();
524
+ reader.onload = () => resolve({base64: reader.result, mimeType});
525
+ reader.readAsDataURL(blob);
526
+ });
527
+ } catch (e) {
528
+ console.warn("Image load failed:", val, e);
529
+ return null;
530
+ }
531
+ }
532
+
533
+
534
+ const processColumns = (columns) => {
535
+ return columns.map((col) => {
536
+ let processedColumn = {
537
+ ...col,
538
+ valueFormatter: col.valueFormatter
539
+ ? applyValueFormatter(col.valueFormatter)
540
+ : undefined,
541
+ };
542
+
543
+ // If the column has children, process them recursively
544
+ if (col.children && Array.isArray(col.children)) {
545
+ processedColumn.children = processColumns(col.children);
546
+ }
547
+
548
+ return processedColumn;
549
+ });
550
+ };
551
+
552
+ async function handleResetColsToStudio() {
553
+ try {
554
+ setBuilderTFilter(builderData?.filter?.Tfilter ?? [])
555
+ console.log(builderModel)
556
+ const allowedAggFuncs = ["sum", "avg", "min", "max"];
557
+ const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
558
+ let defaultCols = getDefaultColDefs()
559
+ const routingSettings = builderData?.routingSettings || [];
560
+
561
+ setTRouting(routingSettings)
562
+ // Build visible colDefs: exclude collection containers and any leaf field marked as hidden
563
+ let localColDefs = builderData.selectedFields
564
+ .filter(x => x.propertyType != 'Collection' && x.hidden !== true)
565
+ .map(col => {
566
+
567
+ const propertyType = col.propertyType ?? col.field?.propertyType;
568
+ const propPath = col.headerName ?? col.path;
569
+ const fieldName = col.headerName ?? col.path.replace(/\./g, '_');
570
+ const externalColConfig = (columnsConfig ?? []).find(x => x.field === fieldName)?.config ?? {}
571
+ const headerName = col.title ?? col.headerName ?? col.path;
572
+ const hasRouting = routingSettings.some(r => r.fieldName === fieldName);
573
+ let valueFormatter = null;
574
+ // Handle valueFormatter as string
575
+ if (propertyType === 'DateTime') {
576
+ if (propPath.toLowerCase().endsWith('time')) {
577
+ valueFormatter =
578
+ `return params?.value != null ? moment.utc(params.value).tz('${userTimeZone}').format('LT') : ''`;
579
+ } else {
580
+ valueFormatter =
581
+ `return params?.value != null ? moment.utc(params.value).tz('${userTimeZone}').format('DD/MM/yyyy hh:mm A') : ''`;
582
+ }
583
+ }
584
+
585
+ if (propertyType === 'Double') {
586
+ valueFormatter =
587
+ `return params?.value != null ? numeral(params.value.toFixed(2)).format('0,0') : ''`;
588
+ }
589
+
590
+ if (propertyType === 'Enum') {
591
+ const enumName = col.field?.enumName || col.field?.propertyName || 'Enum';
592
+ valueFormatter =
593
+ `return params?.value != null ? enumTrans('${enumName}', params.value) : ''`;
594
+ }
595
+
596
+ const isNumericAgg = (propertyType === 'Int' || propertyType === 'Double') &&
597
+ !col.field?.path?.toLowerCase().endsWith('id');
598
+
599
+ const isImage = col.image === true;
600
+ return {
601
+ field: fieldName,
602
+ headerName: headerName,
603
+ enableRowGroup: true,
604
+ sortable: true,
605
+ enablePivot: true,
606
+ enableValue: isNumericAgg,
607
+ cellRenderer: isImage ? 'imageCell' : (hasRouting ? 'routingCell' : (propertyType === 'Bool'
608
+ ? "agCheckboxCellRenderer"
609
+ : null)),
610
+ width: isImage ? 90 : undefined,
611
+ cellStyle: isImage ? {display: 'flex', alignItems: 'center', justifyContent: 'center'} : undefined,
612
+ allowedAggFuncs: isNumericAgg ? allowedAggFuncs : [],
613
+ valueFormatter: valueFormatter
614
+ ? applyValueFormatter(valueFormatter)
615
+ : undefined,
616
+ ...externalColConfig
617
+ };
618
+ });
619
+
620
+
621
+ const localSelectedFields = trimSelectedFields(builderData.selectedFields);
622
+
623
+
624
+ setSelectedFields(localSelectedFields);
625
+
626
+ const localSelectTFilter = builderData.selectedFields.filter(x => x.type === 'computed').map(x => ({
627
+ friendlyName: x.title,
628
+ path: x.path,
629
+ afterSelect: true,
630
+ propertyType: x.propertyType,
631
+ enumName: x.enumName
632
+
633
+ }))
634
+ setSelectTFilter(localSelectTFilter)
635
+ const searchGroupName = 'searchGroup';
636
+ const localSearchFilterFields = builderData?.searchFilter ?? [];
637
+
638
+ const localSearchFilter = localSearchFilterFields.map(f => ({
639
+ path: f.path,
640
+ value: '',
641
+ isWithinCollection: f.isWithinCollection ?? false,
642
+ collectionMethod: f.isWithinCollection ? 'Any' : null,
643
+ method: f.propertyType === 'String' ? 'Contains' : 'Equals',
644
+ collectionPath: getCollectionPath(f.fullPath, f.path, f.isWithinCollection),
645
+ // isWithinOrGroup: true,
646
+ // orGroupName: searchGroupName,
647
+ propertyType: f.propertyType,
648
+ friendlyName: builderData.selectedFields.find(x => x.path === f.path)?.title ?? f.path,
649
+ }))
650
+ searchFieldsRef.current = localSearchFilter;
651
+ const localSelectParams = builderData.selectionParams.map((x, index) => ({
652
+ id: index,
653
+ PropertyType: x.propertyType,
654
+ value: x.value
655
+ }))
656
+ setSelectParams(localSelectParams);
657
+ if (extraCols != null) {
658
+ localColDefs = [...extraCols, ...localColDefs];
659
+ }
660
+ localColDefs = [...localColDefs, ...defaultCols];
661
+ setColDefs([
662
+ {
663
+ field: 'IZ_groupCount',
664
+ headerName: 'Group Count',
665
+ sortable: true,
666
+ hide: true,
667
+ valueGetter: (params) => params.data?.groupCount
668
+ },
669
+ ...localColDefs
670
+ ]);
671
+ } catch (error) {
672
+ console.error('Error in handleResetColsToStudio:', error);
673
+ }
674
+ }
675
+
676
+ function getCollectionPath(fullPath, path, isWithinCollection) {
677
+ if (!isWithinCollection) return null;
678
+ if (typeof fullPath !== 'string' || typeof path !== 'string') return null;
679
+
680
+ // 1) remove the first segment (e.g., "Orders." from "Orders.Items.Product.Name")
681
+ let mid = fullPath.replace(/^[^.]+\.?/, "");
682
+
683
+ // 2) remove trailing `path` (with optional preceding dot)
684
+ const esc = s => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
685
+ const tail = new RegExp(`(?:\\.)?${esc(path)}$`);
686
+ mid = mid.replace(tail, "");
687
+
688
+ // clean up stray leading/trailing dots
689
+ mid = mid.replace(/^\.|\.$/g, "");
690
+
691
+ return mid || null;
692
+ }
693
+
694
+ async function handleGetRawColumns(rawSql) {
695
+ try {
696
+ let response = null
697
+
698
+ response = await Services.PostService(Endpoints.ReportBuilder.Post.GetRawColumns, false, {
699
+ rawSql: rawSql
700
+ }, {})
701
+
702
+ if (response) {
703
+ let defaultCols = getDefaultColDefs()
704
+ let tableCols = [...response.data]
705
+ tableCols = processColumns(tableCols)
706
+ let localColDefs = [...tableCols, ...defaultCols]
707
+ if (extraCols != null) {
708
+ localColDefs = [...extraCols, ...localColDefs]
709
+ }
710
+ const localSelectTFilter = response.data.map(x => ({
711
+ friendlyName: x.fieldName,
712
+ path: x.path,
713
+ afterSelect: true,
714
+ propertyType: x.type,
715
+ }))
716
+ setSelectTFilter(localSelectTFilter)
717
+ setColDefs(localColDefs)
718
+ } else {
719
+ setColDefs([])
720
+ }
721
+ } catch (error) {
722
+
723
+ } finally {
724
+ }
725
+ }
726
+
727
+ const ImageCell = (props) => {
728
+ const {value} = props;
729
+ if (!value) return <span/>;
730
+ let src = String(value);
731
+ try {
732
+ if (imageBaseUrl && !/^https?:\/\//i.test(src)) {
733
+ src = `${imageBaseUrl}/${src}`;
734
+ }
735
+ } catch {
736
+ }
737
+ const size = 50;
738
+ return (
739
+ <img
740
+ src={src}
741
+ alt=""
742
+ style={{width: size, height: size, objectFit: 'contain', borderRadius: 4}}
743
+ onDoubleClick={() => window.open(src, "_blank", "noopener,noreferrer")}
744
+ onError={(e) => {
745
+ e.currentTarget.style.visibility = 'hidden';
746
+ }}
747
+ />
748
+ );
749
+ };
750
+
751
+ const RoutingCell = (props) => {
752
+ const {value, colDef, context, data} = props;
753
+ const {tRouting} = context;
754
+ const fieldName = colDef.field;
755
+
756
+ const routing = tRouting?.find(r => r.fieldName === fieldName || r.headerName === fieldName);
757
+ if (!routing) return <span>{value}</span>;
758
+
759
+ // Determine behavior based on routing.type
760
+ const type = routing.type || 'Route';
761
+
762
+ // Build finalRoute for Route type
763
+ let finalRoute = null;
764
+ if (type === 'Route') {
765
+ if (routing.script) {
766
+ try {
767
+ const fn = new Function("row", routing.script);
768
+ finalRoute = fn(data);
769
+ } catch (err) {
770
+ console.error("Routing script error:", err);
771
+ finalRoute = "#";
772
+ }
773
+ } else if (routing.pattern) {
774
+ finalRoute = routing.pattern.replace(/\{\{(.*?)\}\}/g, (_, key) => {
775
+ const val = data?.[key];
776
+ return val != null ? val : `:${key}`;
777
+ });
778
+ }
779
+ }
780
+
781
+ const handleClick = () => {
782
+ if (type === 'Filter') {
783
+ try {
784
+ // Prepare payload to pass via window.name (works across new tabs without session)
785
+ const raw = routing.externalFilterJson || '';
786
+ const replaced = raw.replace(/\{\{(.*?)\}\}/g, (_, key) => {
787
+ const v = data?.[key];
788
+ return v != null ? String(v) : '';
789
+ });
790
+ let externalFilter = null;
791
+ try {
792
+ externalFilter = replaced ? JSON.parse(replaced) : null;
793
+ } catch (e) {
794
+ console.error('Invalid externalFilterJson after replacement', e);
795
+ }
796
+
797
+ const builderId = context?.builderId;
798
+ const payload = {
799
+ pageId: routing.pageId ?? null,
800
+ externalFilter,
801
+ id: builderId ?? null
802
+ };
803
+
804
+ const base = '/reportBuilder/reportViewer';
805
+ const url = builderId ? `${base}?id=${encodeURIComponent(builderId)}&useWindowName=1` : `${base}?useWindowName=1`;
806
+ // Open the new tab and set its window.name with a prefixed base64 JSON payload
807
+ const child = window.open(url, "_blank"); // do not use noopener because we need to set name
808
+ if (child) {
809
+ try {
810
+ const json = JSON.stringify(payload);
811
+ const b64 = typeof btoa !== 'undefined' ? btoa(unescape(encodeURIComponent(json))) : json;
812
+ child.name = `RB:${b64}`;
813
+ } catch (e) {
814
+ // as a fallback, put minimal info in URL (may be long for large filters)
815
+ try {
816
+ const fallback = encodeURIComponent(JSON.stringify(payload));
817
+ child.location.href = builderId ? `${base}?id=${encodeURIComponent(builderId)}&payload=${fallback}` : `${base}?payload=${fallback}`;
818
+ } catch {}
819
+ }
820
+ }
821
+ } catch (e) {
822
+ console.error('Filter routing error', e);
823
+ }
824
+ } else {
825
+ if (finalRoute && finalRoute !== '#') {
826
+ window.open(finalRoute, "_blank", "noopener,noreferrer");
827
+ }
828
+ }
829
+ };
830
+
831
+ return (
832
+ <span
833
+ style={{
834
+ color: '#1976d2',
835
+ fontWeight: 600,
836
+ cursor: 'pointer',
837
+ }}
838
+ onClick={handleClick}
839
+ >
840
+ {value}
841
+ </span>
842
+ );
843
+ };
844
+
845
+
846
+ function trimSelectedFields(fields, level = 1) {
847
+ return fields.map(col => {
848
+ const trimmed = {
849
+ ...col,
850
+ path: col.path,
851
+ headerName: col.headerName ?? col.path.replace(/\./g, '_')
852
+ };
853
+
854
+ if (col.children && col.children.length > 0) {
855
+ trimmed.children = trimSelectedFields(col.children, level + 1);
856
+ }
857
+
858
+ return trimmed;
859
+ });
860
+ }
861
+
862
+ function getParentKeys(parentNode) {
863
+ const keys = [];
864
+ let currentNode = parentNode;
865
+ while (currentNode?.data) {
866
+ keys.unshift(currentNode.key); // Prepend to keep the order of ancestors
867
+ currentNode = currentNode.parent;
868
+ }
869
+ return keys;
870
+ }
871
+
872
+ // function getValueAtPath(obj, path) {
873
+ // // Split the path into parts based on the dot notation
874
+ // const parts = path.split('.');
875
+ // // Traverse the object according to the path
876
+ // let current = obj;
877
+ //
878
+ // for (let part of parts) {
879
+ // if (current === null || current === undefined) {
880
+ // return 'null'; // If any part is null/undefined, return 'null'
881
+ // }
882
+ // current = current[part];
883
+ // }
884
+ //
885
+ // // If the final value is null, return 'null', otherwise return the value
886
+ // return current === null ? 'null' : current;
887
+ // }
888
+
889
+ const getRowId = (params) => {
890
+ try {
891
+ let itemRowId = getValueByPath(params.data, uniqueIdPath);
892
+ let rowId = itemRowId + getRandomInt(1, 999999999999).toString()
893
+ return noPurge ? itemRowId : rowId
894
+ } catch (error) {
895
+ console.error(error)
896
+ }
897
+
898
+ };
899
+ const handleGetSortObject = (colId, sort, isGrouping, isPivot) => {
900
+ const computedField = builderData.selectedFields.find(x => x.headerName === colId)
901
+ const isComputedField = builderData.selectedFields.some(x => x.headerName === colId && x.type === 'computed')
902
+ if (colId == "IZ_groupCount") {
903
+ return {
904
+ columnName: 'groupCount',
905
+ sortDirection: sort === 'asc' ? 'Ascending' : 'Descending',
906
+ afterGroupBy: isGrouping === true && !isComputedField,
907
+ afterSelect: isComputedField
908
+
909
+ }
910
+ }
911
+ if (isPivot || colId.endsWith("groupCount")) {
912
+ return {
913
+ columnName: colId,
914
+ sortDirection: sort === 'asc' ? 'Ascending' : 'Descending',
915
+ afterGroupBy: isGrouping === true && !isComputedField,
916
+ afterSelect: isComputedField
917
+
918
+ }
919
+ }
920
+ const field = {path: colId, afterSelect: true}
921
+ return {
922
+ columnName: computedField ? computedField.path : colId,
923
+ sortDirection: sort === 'asc' ? 'Ascending' : 'Descending',
924
+ afterGroupBy: isGrouping === true,
925
+ afterSelect: isComputedField
926
+ }
927
+ }
928
+
929
+ const sideBarConfig = useMemo(() => ({
930
+ toolPanels: [
931
+ {
932
+ id: 'columns',
933
+ labelDefault: 'Columns',
934
+ labelKey: 'columns',
935
+ iconKey: 'columns',
936
+ toolPanel: 'agColumnsToolPanel',
937
+ toolPanelParams: {
938
+ suppressRowGroups: groupBy != null,
939
+ suppressValues: groupBy != null,
940
+ },
941
+ minWidth: 225,
942
+ },
943
+
944
+ ],
945
+ position: 'left',
946
+ // ← optionally open this panel by default on init
947
+ defaultToolPanel: 'columns',
948
+ }), [groupBy]); // only re-create if groupBy changes
949
+ const handleGetAggregationObject = (agg) => {
950
+
951
+ const matchedCol = builderData.selectedFields.find(col => {
952
+ const cleanedColPath = col.headerName || col.path.replace(/\./g, '_');
953
+ return cleanedColPath?.toLowerCase() === agg.field?.toLowerCase();
954
+ });
955
+
956
+ if (matchedCol) {
957
+
958
+ } else {
959
+ console.warn(`No match found for aggregation field "${agg.field}"`);
960
+ }
961
+ return {
962
+ path: matchedCol.headerName || matchedCol?.path,
963
+ method: agg.aggFunc,
964
+ afterSelect: matchedCol.type === 'computed'
965
+ // afterSelect: matchedCol?.afterSelect // Uncomment if needed
966
+ };
967
+ };
968
+ const handleGetPath = (colId) => {
969
+ return colId.replace(/_/g, '.')
970
+ }
971
+
972
+ function getMatchedColByPath(path) {
973
+ if (!path) return undefined;
974
+
975
+ const matchedCol = builderData.selectedFields.find(col => {
976
+ const cleanedColPath = col.headerName || col.path.replace(/\./g, '_');
977
+ return cleanedColPath?.toLowerCase() === path.replace(/\./g, '_').toLowerCase();
978
+ });
979
+
980
+ if (matchedCol) {
981
+ const cleanedColPath = matchedCol.path.replace(/\./g, '_');
982
+ return cleanedColPath;
983
+ }
984
+
985
+ console.warn(`No match found for: ${path}`);
986
+ return path.replace(/\./g, '_'); // fallback to flattened path
987
+ }
988
+
989
+ function convertToNestedObject(flatObject) {
990
+ const resultObject = {};
991
+
992
+ Object.keys(flatObject).forEach(path => {
993
+ const value = flatObject[path];
994
+
995
+ // Case-insensitive match with transformed col.path
996
+ const matchedCol = builderData.selectedFields.find(col => {
997
+ const cleanedColPath = col.headerName ?? col.path.replace(/\./g, '_');
998
+ return cleanedColPath.toLowerCase() === path.toLowerCase();
999
+ });
1000
+
1001
+ if (path.startsWith("pivot_")) {
1002
+ const cleanedPath = path.substring(6); // Remove "pivot_"
1003
+ resultObject[cleanedPath] = value;
1004
+ } else {
1005
+ const newPath = matchedCol?.headerName ?? matchedCol?.path?.replace(/\./g, '_') ?? path;
1006
+ resultObject[newPath] = value;
1007
+ }
1008
+ });
1009
+
1010
+ return resultObject;
1011
+ }
1012
+
1013
+
1014
+ function returnAdditionalPivotCols(flatCols) {
1015
+ const resultFields = new Set();
1016
+ flatCols.forEach(row => {
1017
+ Object.keys(row).forEach(key => {
1018
+ if (!key.startsWith("pivot_") && key !== "groupCount" && !builderData.selectedFields.some(
1019
+ col => col.headerName === key
1020
+ )) {
1021
+ resultFields.add(key);
1022
+ }
1023
+ });
1024
+ });
1025
+
1026
+ const distinctFields = Array.from(resultFields);
1027
+ return distinctFields;
1028
+ }
1029
+
1030
+ const createServerSideDatasource = (getRowsFromApi) => {
1031
+ return {
1032
+ getRows: (params) => {
1033
+ const isPivotMode = params.api.isPivotMode()
1034
+ // Fetch data from API based on request
1035
+ getRowsFromApi(params)
1036
+ .then((response) => {
1037
+ if (response.success) {
1038
+ // Supply rows for requested block to grid
1039
+ params.success({
1040
+ rowData: response.rows,
1041
+ rowCount: response.total,
1042
+ pivotResultFields: isPivotMode ? response.pivotColResult : null
1043
+ });
1044
+ } else {
1045
+ params.fail();
1046
+ }
1047
+ })
1048
+ .catch((e) => {
1049
+
1050
+ console.log(e)
1051
+ params.fail()
1052
+ });
1053
+ },
1054
+ };
1055
+ }
1056
+
1057
+ const getRowsFromApi = useCallback(
1058
+ async params => {
1059
+ setFinalRequestObject(defaultFinalRequest)
1060
+ const fixedTFilter = externalFilter?.fixedTFilter ?? externalFilter?.fixedTfilter ?? []
1061
+ const localFixedTFilter = Filter?.fixedTFilter ?? []
1062
+ let localFilter = externalFilter ? {...externalFilter} : {}
1063
+ localFilter = {...localFilter, ...Filter}
1064
+
1065
+ let localTFilter = localFilter?.Tfilter ? [...localFilter?.Tfilter] : []
1066
+ localTFilter = localFilter?.TFilter ? [...localTFilter, ...localFilter?.TFilter] : [...localTFilter]
1067
+ localTFilter = [...localTFilter, ...fixedTFilter, ...localFixedTFilter, ...builderTFilter]
1068
+
1069
+ // Apply explicit user-selected search filters (selectedSearchObjects), grouped by path
1070
+ if ((selectedSearchObjects?.length ?? 0) > 0) {
1071
+ const byPath = selectedSearchObjects.reduce((acc, item) => {
1072
+ const key = item.path;
1073
+ if (!acc[key]) acc[key] = [];
1074
+ acc[key].push(item);
1075
+ return acc;
1076
+ }, {});
1077
+
1078
+ const grouped = [];
1079
+ Object.keys(byPath).forEach(path => {
1080
+ const items = byPath[path];
1081
+ if (items.length <= 1) {
1082
+ // Single value: push without OR grouping flags
1083
+ const single = {...items[0]};
1084
+ delete single.isWithinOrGroup;
1085
+ delete single.orGroupName;
1086
+ grouped.push(single);
1087
+ } else {
1088
+ // Multiple values for same path: mark each as OR group member
1089
+ items.forEach(it => {
1090
+ grouped.push({
1091
+ ...it,
1092
+ isWithinOrGroup: true,
1093
+ orGroupName: path
1094
+ });
1095
+ });
1096
+ }
1097
+ });
1098
+
1099
+ localTFilter = [...localTFilter, ...grouped];
1100
+ }
1101
+
1102
+ localTFilter = localTFilter.filter(x => x.value !== null && x.value !== undefined && x.value !== '')
1103
+
1104
+ delete localFilter.Tfilter
1105
+ delete localFilter.fixedTfilter
1106
+ delete localFilter.fixedTFilter
1107
+ delete localFilter.LocalTfilter
1108
+ delete localFilter.localTfilter
1109
+ localFilter = localFilter ?? {}
1110
+ const request = params.request
1111
+ const pageNumber = request.endRow / (request.endRow - request.startRow) // Calculate the page number
1112
+ const pageSize = request.endRow - request.startRow // Calculate the page size
1113
+ let aggregators = request.valueCols.filter(x => x.id != 'groupCount').map(agg => handleGetAggregationObject(agg))
1114
+ let updateAggregation = true
1115
+ if (colDefs && gridApi) {
1116
+ let resultColDef = [...colDefs]
1117
+ if (request.rowGroupCols.length > 0) {
1118
+ }
1119
+ // gridApi.setGridOption('columnDefs', resultColDef)
1120
+ // gridApi.applyColumnState({state: colState});
1121
+ }
1122
+ // Build tFilter safely: remove fixed from preformatted lists and merge a single fixed source
1123
+ // 1) Strip fixed items from local Tfilter/TFilter (they may already be formatted by CustomFilterDialog)
1124
+ let nonFixedLocal = Array.isArray(localTFilter) ? localTFilter.filter(it => !(it && it.fixed === true && it.value === null)) : []
1125
+
1126
+ // 2) Choose ONE fixed source by priority: component state -> external -> builder
1127
+ const extFixed = Array.isArray(externalFilter?.fixedTFilter)
1128
+ ? externalFilter.fixedTFilter
1129
+ : (Array.isArray(externalFilter?.fixedTfilter) ? externalFilter.fixedTfilter : [])
1130
+ const fixedSource = (Array.isArray(Filter?.fixedTFilter) && Filter.fixedTFilter.length > 0)
1131
+ ? Filter.fixedTFilter
1132
+ : (extFixed.length > 0 ? extFixed : (Array.isArray(builderTFilter) ? builderTFilter : []))
1133
+
1134
+ // 3) Merge and format once
1135
+ const mergedForFormat = [...nonFixedLocal]
1136
+ console.log("Merged for format:", mergedForFormat)
1137
+ let formattedT = FilterFormat(mergedForFormat)
1138
+
1139
+ let data = {
1140
+ ...localFilter,
1141
+ tFilter: formattedT,
1142
+ aggregators: aggregators,
1143
+ pivotCols: request.pivotCols.map(x => handleGetPath(x.field))
1144
+ }
1145
+ // Exclude any tFilter entries with null value before sending the request (per requirement)
1146
+ if (Array.isArray(data.tFilter)) {
1147
+ data.tFilter = data.tFilter.filter(f => f == null ? false : f.value !== null);
1148
+ }
1149
+ try {
1150
+ if (request.rowGroupCols.length !== request.groupKeys.length) {
1151
+ if (request.rowGroupCols.length > 1 && request.groupKeys.length > 0) {
1152
+ updateAggregation = false
1153
+ }
1154
+ let tFilters = request.groupKeys.map((x, index) => ({
1155
+ path: request.rowGroupCols[index].id.replace(/_/g, '.'),
1156
+ value: request.groupKeys[index] === 'null' ? null : request.groupKeys[index],
1157
+ method: 'Equals',
1158
+ dtoClassName: '',
1159
+ modelClassName: '',
1160
+ afterSelect: builderData.selectedFields.some(col => col.headerName === request.rowGroupCols[index].id && col.type === 'computed')
1161
+ }))
1162
+ const groupByColId = handleGetPath(params.request.rowGroupCols[params.parentNode.level + 1]?.id)
1163
+ const rowGroupColsIds = request.rowGroupCols.map(value => value.id)
1164
+ const valueColsIds = request.valueCols.map(value => value.id)
1165
+ const groupOrderCols = [...rowGroupColsIds, ...valueColsIds]
1166
+ let isGroupCountOrder = true;
1167
+ // if (rowGroupColsIds.length > 1 && params.request.sortModel.length > 1) {
1168
+ // isGroupCountOrder = false;
1169
+ // }
1170
+ request.sortModel = (request.sortModel ?? []).map(x => ({
1171
+ ...x,
1172
+ colId: x?.colId?.endsWith("_groupCount")
1173
+ ? x.colId.replace("_groupCount", "_groupCount")
1174
+ : x.colId
1175
+ }));
1176
+ const aggIds = request.valueCols.map(vc => vc.id);
1177
+
1178
+ const groupOrderColdIds = request.sortModel.filter(x => groupOrderCols.includes(x.colId) || ((x.colId == "IZ_groupCount" || x.colId.endsWith("groupCount") || aggIds.some(id => x.colId.toLowerCase().endsWith(id.toLowerCase()))) && isGroupCountOrder))
1179
+ let orderBy = groupOrderColdIds.map(sort => handleGetSortObject(sort.colId, sort.sort, true, aggIds.some(id => sort.colId.toLowerCase().endsWith(id.toLowerCase()))))
1180
+ data = {
1181
+ ...data,
1182
+ tFilter: [...tFilters, ...data.tFilter],
1183
+ orderBy: orderBy
1184
+ }
1185
+
1186
+ // if (updateAggregation !== true) {
1187
+ // data.aggregators = []
1188
+ // }
1189
+ data.selectFields = selectedFields
1190
+ data.selectParams = selectParams
1191
+ data.rawSql = builderData.rawSql
1192
+
1193
+ const response = await Services.PostService(groupEndPoint, false, data, {
1194
+ groupBy: groupByColId,
1195
+ page: isSingle ? 1 : pageNumber,
1196
+ pageSize: isSingle ? 1 : pageSize,
1197
+ getType: isPagination ? 'GroupingPagination' : 'GroupingNoPagination',
1198
+ sourceModel: builderData.reportSource.fullName,
1199
+
1200
+ })
1201
+
1202
+ if (setData != null) {
1203
+ if (isSingle) {
1204
+ const rowObj = response.data[0]
1205
+ setData(dataAsObject ? toNestedByUnderscore(rowObj) : rowObj)
1206
+ } else {
1207
+ const resp = dataAsObject
1208
+ ? {...response, data: (response.data || []).map(toNestedByUnderscore)}
1209
+ : response
1210
+ setData(resp)
1211
+ }
1212
+ }
1213
+ setFinalRequestObject({
1214
+ groupBy: groupByColId,
1215
+ endpoint: groupEndPoint,
1216
+ filter: data,
1217
+ params: {}
1218
+ })
1219
+ const pivotColResult = []
1220
+ if (request.pivotCols.length > 0) {
1221
+ if (response?.pivotCols.length > 0) {
1222
+ pivotColResult.push('groupCount')
1223
+ const responsePivotCol = response.pivotCols.map(x => x.field) ?? []
1224
+ pivotColResult.push(...responsePivotCol)
1225
+ const additionalPivotCols = returnAdditionalPivotCols(response.data)
1226
+ pivotColResult.push(...additionalPivotCols)
1227
+
1228
+ }
1229
+ }
1230
+
1231
+ response.data = response.data.map(r => {
1232
+ return convertToNestedObject(r)
1233
+ })
1234
+ if (response.aggregation != null && updateAggregation === true) {
1235
+ const flatAggs = flattenObject(response.aggregation)
1236
+ setPagedAgg([flatAggs])
1237
+ }
1238
+
1239
+ return {
1240
+ success: true,
1241
+ rows: Array.isArray(response.data) ? response.data : [], // Always return an array to AG Grid
1242
+ total: response.totalCount, // Total number of rows available from the server
1243
+ pivotColResult: pivotColResult.length > 0 ? pivotColResult : null
1244
+ }
1245
+ } else {
1246
+ if (request.groupKeys.length > 0) {
1247
+ let tFilters = request.groupKeys.map((x, index) => ({
1248
+ path: handleGetPath(request.rowGroupCols[index].id),
1249
+ value: request.groupKeys[index] === 'null' ? null : request.groupKeys[index],
1250
+ method: 'Equals',
1251
+ dtoClassName: '',
1252
+ modelClassName: '',
1253
+ afterSelect: builderData.selectedFields.some(col => col.headerName === request.rowGroupCols[index].id && col.type === 'computed')
1254
+
1255
+ }))
1256
+ updateAggregation = false
1257
+
1258
+ data = {
1259
+ ...data,
1260
+ tFilter: [...tFilters, ...data.tFilter]
1261
+ }
1262
+ }
1263
+ let orderBy = request.sortModel.filter(x => !x.colId.endsWith("IZ_groupCount")).map(sort => handleGetSortObject(sort.colId, sort.sort, false))
1264
+ if (data.tIncludes != null)
1265
+ data = {
1266
+ ...data,
1267
+ tIncludes: [...data.tIncludes, ...includes],
1268
+ orderBy: orderBy
1269
+ }
1270
+ else {
1271
+ data = {
1272
+ ...data,
1273
+ tIncludes: [...includes],
1274
+ orderBy: orderBy
1275
+ }
1276
+ if (fixedTIncludes != null) {
1277
+ data.tIncludes = [...data.tIncludes, ...fixedTIncludes]
1278
+ }
1279
+ }
1280
+ if (updateAggregation !== true) {
1281
+ data.aggregators = []
1282
+ }
1283
+ data.selectFields = selectedFields
1284
+ data.selectParams = selectParams
1285
+ data.lastRowParams = lastRowRef.current[pageNumber];
1286
+
1287
+ data.isPaginationByFilter = builderData?.isRaw === false
1288
+ if (data.lastRowParams == null && pageNumber > 1 && data.isPaginationByFilter)
1289
+ return {
1290
+ success: true,
1291
+ rows: [],
1292
+ rowCount: undefined // <== This keeps the grid in "loading" state
1293
+ }
1294
+ data.rawSql = builderData?.rawSql
1295
+ console.log(builderData)
1296
+ const response = await Services.PostService(pagedEndPoint, false, data, {
1297
+ ...paramsPage,
1298
+ page: isSingle ? 1 : pageNumber,
1299
+ pageSize: isSingle ? 1 : pageSize,
1300
+ getType: isPagination ? (builderData?.isRaw ? 'SqlPagination' : 'Pagination') : (builderData?.isRaw ? 'SqlNoPagination' : 'NoPagination'),
1301
+ sourceModel: builderData?.reportSource?.fullName,
1302
+
1303
+ })
1304
+
1305
+ if (setData != null) {
1306
+ if (isSingle) {
1307
+ const rowObj = response.data[0]
1308
+ setData(dataAsObject ? toNestedByUnderscore(rowObj) : rowObj)
1309
+ } else {
1310
+ const resp = dataAsObject
1311
+ ? {...response, data: (response.data || []).map(toNestedByUnderscore)}
1312
+ : response
1313
+ setData(resp)
1314
+ }
1315
+ }
1316
+ lastRowRef.current = {...lastRowRef.current, [pageNumber + 1]: response.lastRowParams};
1317
+ setFinalRequestObject({
1318
+ groupBy: null,
1319
+ endpoint: pagedEndPoint,
1320
+ getType: 'Pagination',
1321
+ filter: data,
1322
+ sourceModel: builderData?.reportSource?.fullName,
1323
+ params: paramsPage ?? {}
1324
+ })
1325
+ if (responseType == null) setResponseType(response.className)
1326
+ if (responseType == null) setLocalClasName(response.className)
1327
+ if (response.aggregation != null && updateAggregation === true) {
1328
+ const flatAggs = flattenObject(response.aggregation)
1329
+ setPagedAgg([flatAggs])
1330
+ }
1331
+
1332
+ return {
1333
+ success: true,
1334
+ rows: Array.isArray(response.data) ? response.data : [], // Always return an array to AG Grid
1335
+ total: response.totalCount,
1336
+ rowCount: response.totalCount,
1337
+ }
1338
+ }
1339
+ } catch (error) {
1340
+ console.log(error)
1341
+ return {success: false}
1342
+ }
1343
+ },
1344
+ [externalFilter, includes, paramsPage, Filter, selectedFields, isPagination, selectedSearchObjects, builderData]
1345
+ )
1346
+ const datasource = useMemo(() => createServerSideDatasource(getRowsFromApi), [getRowsFromApi]);
1347
+
1348
+
1349
+ const onGridReady = useCallback((params) => {
1350
+ setGridApi(params.api)
1351
+ if (setOutGridApi != null)
1352
+ setOutGridApi(params.api)
1353
+ // Create datasource with a reference to the API function
1354
+ // const datasource = createServerSideDatasource(getRowsFromApi);
1355
+
1356
+ // // Register the datasource with the grid
1357
+ // params.api.setGridOption("serverSideDatasource", datasource);
1358
+ }, []);
1359
+
1360
+ const onRowSelected = (event) => {
1361
+ if (setEventRowSelected != null) {
1362
+ setEventRowSelected(event)
1363
+ }
1364
+ };
1365
+
1366
+ function flattenObject(obj, prefix = '', result = {}) {
1367
+ for (const key in obj) {
1368
+ if (!Object.hasOwn(obj, key)) continue;
1369
+
1370
+ const value = obj[key];
1371
+ const fullKey = prefix ? `${prefix}.${key}` : key;
1372
+
1373
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
1374
+ flattenObject(value, fullKey, result);
1375
+ } else {
1376
+ const matchedPath = getMatchedColByPath(fullKey);
1377
+ const finalKey = matchedPath ?? fullKey; // fallback to original if no match
1378
+
1379
+
1380
+ result[finalKey] = value;
1381
+ }
1382
+ }
1383
+ return result;
1384
+ }
1385
+
1386
+ function flattenArray(arr) {
1387
+ let result = [];
1388
+
1389
+ function traverse(item) {
1390
+ if (!item.children) {
1391
+ // If the item does not have children or the children array is empty, add it to the result
1392
+ result.push(item);
1393
+ } else {
1394
+ // If the item has children, recursively traverse each child
1395
+ item.children.forEach(child => traverse(child));
1396
+ }
1397
+ }
1398
+
1399
+ arr.forEach(item => traverse(item));
1400
+ return result;
1401
+ }
1402
+
1403
+ function getValueByPath(object, path) {
1404
+ try {
1405
+ if (path == undefined)
1406
+ return getRandomInt(1, 999999999999).toString()
1407
+ let id = path.split('.').reduce((acc, key) => acc && acc[key], object);
1408
+ if (id === undefined)
1409
+ return getRandomInt(1, 999999999999).toString()
1410
+ else
1411
+ return id
1412
+
1413
+ } catch (error) {
1414
+
1415
+ }
1416
+ }
1417
+
1418
+ function handleFilterChange(field, value) {
1419
+ handleChange(setFilter, field, value)
1420
+ }
1421
+
1422
+ async function handleGetTemplates() {
1423
+ try {
1424
+ let response = null
1425
+ let data = {
1426
+ tFilter: [
1427
+ {
1428
+ method: 'Equals',
1429
+ path: 'pageName',
1430
+ value: 'Builder' + builderData?.id
1431
+ },
1432
+ {
1433
+ method: 'Equals',
1434
+ path: 'UserId',
1435
+ value: authValues?.user?.id,
1436
+ },
1437
+ ]
1438
+ }
1439
+ response = await PostService(Endpoints.UserTableTemplates.Post.GetAllPagedByFilter, false, data)
1440
+
1441
+ if (response) {
1442
+ setTemplates(response.data)
1443
+
1444
+ } else {
1445
+ setTemplates([])
1446
+ }
1447
+ } catch (error) {
1448
+
1449
+ }
1450
+ }
1451
+
1452
+ const handleToggleDialogs = dialog => {
1453
+ handleChange(setOpenDialogs, dialog, !openDialogs[dialog])
1454
+ }
1455
+
1456
+
1457
+ async function handleSaveTemplate() {
1458
+ try {
1459
+ let response = null;
1460
+ {
1461
+ let data = {
1462
+ ...selectedTemplate,
1463
+ value: gridApi.getColumnState(),
1464
+ userId: authValues?.user?.id,
1465
+ filterValue: Filter,
1466
+ pageName: 'Builder' + builderData?.id
1467
+ }
1468
+ response = await UpdateService(Endpoints.UserTableTemplates.Put.UpdateTemplate, true, data, {
1469
+ id: selectedTemplate?.id
1470
+ })
1471
+
1472
+ if (response)
1473
+ handleGetTemplates();
1474
+ }
1475
+ } catch (error) {
1476
+
1477
+ }
1478
+ }
1479
+
1480
+ async function handleCSVExport() {
1481
+ try {
1482
+ let response = null;
1483
+ {
1484
+ setIsDownloading(true)
1485
+ const cols = gridApi
1486
+ .getColumnDefs()
1487
+ const flatCols = flattenArray(cols)
1488
+ const visibleCols = flatCols // all column definitions
1489
+ .filter(colDef =>
1490
+ gridApi.getColumnState().some(
1491
+ col => col.colId === colDef.field && col.hide !== true
1492
+ )
1493
+ )
1494
+ const visibleFields = visibleCols
1495
+ .filter(x => x?.path)
1496
+ .map(x => x.path);
1497
+
1498
+ let data = {
1499
+ ...finalRequestObject.filter,
1500
+ isExcelExport: true,
1501
+ visibleFields: visibleFields,
1502
+ }
1503
+ const isPivotOff = !gridApi.isPivotMode()
1504
+ if (isPivotOff) {
1505
+ data.pivotCols = []
1506
+ }
1507
+ response = await StreamService(streamEndPoint, true, data, {
1508
+ ...finalRequestObject.params,
1509
+ groupBy: finalRequestObject.groupBy,
1510
+ getType: 'Stream',
1511
+ sourceModel: builderData.reportSource.fullName
1512
+
1513
+ }, null,
1514
+ progress => {
1515
+ console.log(`Downloaded: ${progress}%`)
1516
+ })
1517
+
1518
+ }
1519
+ } catch (error) {
1520
+ console.log(error)
1521
+ } finally {
1522
+ setIsDownloading(false)
1523
+ }
1524
+ }
1525
+
1526
+ const restoreState = () => {
1527
+ if (gridApi !== null && colDefs !== null && selectedTemplate != null) {
1528
+ gridApi.applyColumnState({
1529
+ state: selectedTemplate.value,
1530
+ applyOrder: true,
1531
+ });
1532
+ }
1533
+ if (selectedTemplate.filterValue != null && (Filter.Tfilter == null || Filter.Tfilter.length == 0)) {
1534
+ setFilter(selectedTemplate.filterValue);
1535
+ }
1536
+ };
1537
+
1538
+ const debouncedRefresh = useMemo(
1539
+ () => debounce(() => {
1540
+ if (gridApi) gridApi.refreshServerSide({purge: true});
1541
+ }, 400),
1542
+ [gridApi]
1543
+ );
1544
+
1545
+ // cleanup debounce on unmount
1546
+ useEffect(() => () => debouncedRefresh.cancel(), [debouncedRefresh]);
1547
+
1548
+ const handlePickSearchField = (selectedField) => {
1549
+ if (!selectedField) return;
1550
+ const term = (searchTerm || '').trim();
1551
+ if (!term) return;
1552
+
1553
+ const propType = (selectedField.propertyType || '').toLowerCase();
1554
+ let valueToUse = term;
1555
+ if (propType === 'int') {
1556
+ const n = Number(term);
1557
+ if (!Number.isFinite(n)) {
1558
+ return; // ignore invalid numeric term for Int fields
1559
+ }
1560
+ valueToUse = Math.trunc(n);
1561
+ }
1562
+
1563
+ const newObj = {
1564
+ ...selectedField,
1565
+ value: valueToUse
1566
+ };
1567
+
1568
+ setSelectedSearchObjects(prev => [...prev, newObj]);
1569
+ console.log(newObj)
1570
+ setSearchTerm('');
1571
+ setSearchPopoverOpen(false);
1572
+ debouncedRefresh();
1573
+ };
1574
+
1575
+
1576
+ useEffect(() => {
1577
+ if (builderData) {
1578
+
1579
+ if (builderData.isRaw) {
1580
+ handleGetRawColumns(builderData.rawSql)
1581
+ } else {
1582
+ handleResetColsToStudio()
1583
+ }
1584
+ }
1585
+ }, [builderData]);
1586
+
1587
+ useEffect(() => {
1588
+ if (builderModel != null) {
1589
+ console.log(builderModel)
1590
+ let rawSql = builderModel.rawSql;
1591
+ if (builderModel.isRaw === true) {
1592
+ const localSelectParams = builderModel.selectionParams.map((x, index) => ({
1593
+ id: index,
1594
+ PropertyType: x.propertyType,
1595
+ value: x.value
1596
+ }));
1597
+
1598
+ rawSql = rawSql.replace(/@(\d+)/g, (_, index) => {
1599
+ const param = localSelectParams[parseInt(index)];
1600
+ if (!param) return _;
1601
+
1602
+ // Add quotes for strings and dates
1603
+ if (typeof param.value === 'string') {
1604
+ return `'${param.value}'`;
1605
+ }
1606
+
1607
+ return param.value;
1608
+ });
1609
+ }
1610
+ setBuilderData({...builderModel, rawSql: rawSql})
1611
+ setFilter(preValue => ({
1612
+ ...preValue,
1613
+ LocalTfilter: [...(builderModel?.filter?.fixedTFilter || [])]
1614
+ }))
1615
+ }
1616
+ }, [builderModel]);
1617
+
1618
+ useEffect(() => {
1619
+ // In non-raw mode, changing selection params should not alter builderData to avoid unnecessary rerenders/fetches
1620
+ if (builderModel?.isRaw !== true) return;
1621
+
1622
+ if (selectParams.length > 0) {
1623
+ let rawSql = builderModel.rawSql;
1624
+ const localSelectParams = {...selectParams};
1625
+ rawSql = rawSql.replace(/@(\d+)/g, (_, index) => {
1626
+ const param = localSelectParams[parseInt(index)];
1627
+ if (!param) return _;
1628
+ // Add quotes for strings and dates
1629
+ if (typeof param.value === 'string') {
1630
+ return `'${param.value}'`;
1631
+ }
1632
+ return param.value;
1633
+ });
1634
+ // Only update if rawSql actually changed to prevent redundant state updates
1635
+ setBuilderData(prev => {
1636
+ if (prev?.rawSql === rawSql) return prev;
1637
+ return {...builderModel, rawSql};
1638
+ });
1639
+ }
1640
+ }, [selectParams, builderModel?.isRaw]);
1641
+
1642
+ useEffect(() => {
1643
+
1644
+ if (gridApi !== null) {
1645
+ gridApi.refreshServerSide({purge: !noPurge})
1646
+ lastRowRef.current = {}
1647
+ }
1648
+ }, [refresh, externalFilter, localRefresh, Filter]);
1649
+
1650
+ useEffect(() => {
1651
+ if (gridApi != null && colDefs != null)
1652
+ handleGetTemplates()
1653
+ }, [gridApi, colDefs])
1654
+
1655
+ useEffect(() => {
1656
+ if (colDefs.length > 0 && selectedTemplate != null) {
1657
+ restoreState()
1658
+ }
1659
+ }, [selectedTemplate])
1660
+ useEffect(() => {
1661
+ if (selectedTemplate == null && templates.length > 0 && colDefs.length > 0) {
1662
+ const userDefined = templates.find(x => x.isDefault === true)
1663
+ if (userDefined != null)
1664
+ setSelectedTemplate(userDefined)
1665
+ else {
1666
+ const systemDefined = templates.find(x => x.type === "UserPredefined")
1667
+ if (systemDefined != null)
1668
+ setSelectedTemplate(systemDefined)
1669
+ else {
1670
+ const anyTemplate = templates[0]
1671
+ setSelectedTemplate(anyTemplate)
1672
+ }
1673
+ }
1674
+ }
1675
+ }, [templates, colDefs])
1676
+
1677
+ useEffect(() => {
1678
+ if (!timerValue || isNaN(timerValue) || timerValue == 0) {
1679
+
1680
+ return;
1681
+ }
1682
+ // Convert minutes to milliseconds
1683
+ const interval = (timerValue) * 60 * 1000;
1684
+
1685
+ const timeout = setInterval(() => {
1686
+ setLocalRefresh(prev => !prev); // Toggle value
1687
+ }, interval);
1688
+
1689
+ return () => clearTimeout(timeout); // Cleanup
1690
+ }, [timerValue]); // re-ru
1691
+
1692
+ useEffect(() => {
1693
+ if (!externalTimer || isNaN(externalTimer) || externalTimer == 0) {
1694
+
1695
+ return;
1696
+ }
1697
+ // Convert minutes to milliseconds
1698
+ const interval = (externalTimer) * 60 * 1000;
1699
+
1700
+ const timeout = setInterval(() => {
1701
+ setLocalRefresh(prev => !prev); // Toggle value
1702
+ }, interval);
1703
+
1704
+ return () => clearTimeout(timeout); // Cleanup
1705
+ }, [externalTimer]); // re// n after each refresh or change in value
1706
+
1707
+ return (
1708
+ <Grid item container size={12}>
1709
+ <Grid container item
1710
+ sx={{backgroundColor: '#fafafb', justifyContent: 'space-between'}} padding={2}
1711
+ size={12}
1712
+ >
1713
+ <Box sx={{display: 'flex'}}>
1714
+ {(builderData?.id != null && minimized !== true) &&
1715
+ <Box sx={{minWidth: '250px'}}>
1716
+
1717
+ <FormControl fullWidth>
1718
+ <Autocomplete
1719
+ size={'small'}
1720
+ value={selectedTemplate}
1721
+ fullWidth
1722
+ disableClearable
1723
+ options={templates}
1724
+ onChange={(e, value) => {
1725
+ setSelectedTemplate(value)
1726
+ }
1727
+ }
1728
+ getOptionLabel={option => option.name}
1729
+ renderInput={params => (
1730
+ <TextField
1731
+ label='شكل النموذج'
1732
+ {...params}
1733
+ onMouseDown={() => {
1734
+ handleGetTemplates()
1735
+ }}
1736
+ />
1737
+ )}
1738
+ />
1739
+ </FormControl>
1740
+ </Box>
1741
+ }
1742
+ <Box sx={{ml: '5px'}}>
1743
+ <Tooltip title='مؤقت' placement={'top'}>
1744
+ <Select variant={'outlined'} value={timerValue} onChange={(e) => setTimerValue(e.target.value)}
1745
+ defaultValue={0} size={'small'}
1746
+ color='primary' sx={{width: '60px'}}>
1747
+ <MenuItem key={1} value={0}>No</MenuItem>
1748
+ <MenuItem key={2} value={0.1667}>10s</MenuItem>
1749
+ <MenuItem key={2} value={0.5}>30s</MenuItem>
1750
+ <MenuItem key={2} value={1}>1m</MenuItem>
1751
+ <MenuItem key={2} value={2}>2m</MenuItem>
1752
+ <MenuItem key={2} value={5}>5m</MenuItem>
1753
+ <MenuItem key={3} value={15}>15m</MenuItem>
1754
+ <MenuItem key={4} value={30}>30m</MenuItem>
1755
+ </Select>
1756
+ </Tooltip>
1757
+ </Box>
1758
+ </Box>
1759
+ {((searchFieldsRef?.current?.length ?? []) > 0) &&
1760
+ <Box sx={{flex: 1, px: 1, minWidth: minimized ? 140 : 300, display: 'flex', alignItems: 'center'}}>
1761
+ {/*<Tooltip title={'اكتب كلمة البحث ثم اختر الحقل'}>*/}
1762
+ <Box sx={{position: 'relative', width: '100%'}}>
1763
+ <TextField
1764
+ label={'بحث'}
1765
+ fullWidth
1766
+ size={'small'}
1767
+ value={searchTerm}
1768
+ inputRef={searchInputRef}
1769
+ onFocus={(e) => {
1770
+ if ((e.target.value || '').length > 0) {
1771
+ setSearchPopoverAnchor(e.currentTarget);
1772
+ setSearchPopoverOpen(true);
1773
+ }
1774
+ }}
1775
+ onChange={(e) => {
1776
+ const v = e.target.value;
1777
+ setSearchTerm(v);
1778
+ setSearchPopoverAnchor(e.currentTarget);
1779
+ setSearchPopoverOpen((v || '').length > 0);
1780
+ }}
1781
+ onKeyDown={(e) => {
1782
+ if (e.key === 'Enter') {
1783
+ e.preventDefault();
1784
+ const term = (searchTerm || '').trim();
1785
+ if (!term) return;
1786
+ const fields = searchFieldsRef?.current ?? [];
1787
+ if (fields.length === 0) return;
1788
+ handlePickSearchField(fields[0]);
1789
+ } else if (e.key === 'Escape') {
1790
+ setSearchPopoverOpen(false);
1791
+ }
1792
+ }}
1793
+ InputProps={{
1794
+ startAdornment: (
1795
+ <Box sx={{display: 'flex', gap: 0.5, flexWrap: 'wrap'}}>
1796
+ {(() => {
1797
+ const byPath = selectedSearchObjects.reduce((acc, it) => {
1798
+ const key = it.path;
1799
+ if (!acc[key]) acc[key] = {meta: it, values: []};
1800
+ acc[key].values.push(String(it.value));
1801
+ return acc;
1802
+ }, {});
1803
+ return Object.keys(byPath).map(path => {
1804
+ const g = byPath[path];
1805
+ const labelBase = g.meta.friendlyName || g.meta.path;
1806
+ const valueLabel = g.values.reduce((acc, val, idx) => {
1807
+ if (idx > 0) acc.push(<strong key={`sep-${idx}`}> أو </strong>);
1808
+ acc.push(val);
1809
+ return acc;
1810
+ }, []);
1811
+ return (
1812
+ <Chip
1813
+ key={`group-${path}`}
1814
+ size="small"
1815
+ label={
1816
+ <span>
1817
+ <strong>{labelBase}</strong>: {valueLabel}
1818
+ </span>
1819
+ } onDelete={() => {
1820
+ setSelectedSearchObjects(prev => prev.filter(it => it.path !== path));
1821
+ debouncedRefresh();
1822
+ }}
1823
+ deleteIcon={
1824
+ <Box sx={{
1825
+ display: 'flex',
1826
+ alignItems: 'center',
1827
+ px: 0.5,
1828
+ bgcolor: 'error.main',
1829
+ color: (theme) => theme.palette.error.contrastText,
1830
+ height: '100%',
1831
+ alignSelf: 'stretch',
1832
+ borderTopRightRadius: '4px',
1833
+ borderBottomRightRadius: '4px'
1834
+ }}>
1835
+ <Close fontSize="small"/>
1836
+ </Box>
1837
+ }
1838
+ sx={{
1839
+ mr: 0.5,
1840
+ borderRadius: '8px',
1841
+ '& .MuiChip-deleteIcon': {
1842
+ margin: 0
1843
+ }
1844
+ }}
1845
+ />
1846
+ );
1847
+ });
1848
+ })()}
1849
+ </Box>
1850
+ )
1851
+ }}
1852
+ />
1853
+
1854
+ <ClickAwayListener onClickAway={() => setSearchPopoverOpen(false)}>
1855
+ <Popper
1856
+ open={searchPopoverOpen}
1857
+ anchorEl={searchPopoverAnchor}
1858
+ placement="bottom-start"
1859
+ style={{zIndex: 1300, width: searchInputRef?.current?.offsetWidth || undefined}}
1860
+ >
1861
+ <Paper elevation={3} sx={{mt: 0.5, maxHeight: 240, overflowY: 'auto'}}>
1862
+ <List dense>
1863
+ {(searchFieldsRef?.current ?? []).map((option, i) => (
1864
+ <ListItemButton key={`${option.path}-${i}`} onClick={() => handlePickSearchField(option)}>
1865
+ <Box sx={{display: 'flex', flexDirection: 'column'}}>
1866
+ <Box sx={{fontSize: 14, fontWeight: 500}}>{option.friendlyName || option.path}</Box>
1867
+ {/*<Box sx={{fontSize: 12, color: 'text.secondary'}}>{option.path}</Box>*/}
1868
+ </Box>
1869
+ </ListItemButton>
1870
+ ))}
1871
+ {((searchFieldsRef?.current ?? []).length === 0) && (
1872
+ <ListItemButton disabled>
1873
+ <Box sx={{px: 1, py: 0.5, color: 'text.secondary'}}>لا توجد حقول للبحث</Box>
1874
+ </ListItemButton>
1875
+ )}
1876
+ </List>
1877
+ </Paper>
1878
+ </Popper>
1879
+ </ClickAwayListener>
1880
+ </Box>
1881
+ {/*</Tooltip>*/}
1882
+ </Box>}
1883
+ <Box sx={{display: 'flex', justifyContent: 'center'}}>
1884
+ {<Box>
1885
+ <Tooltip title={'جميع البيانات'}>
1886
+ <Checkbox
1887
+ checked={!isPagination}
1888
+ onChange={e => setIsPagination(!e.target.checked)}
1889
+ color="primary"
1890
+ />
1891
+ </Tooltip>
1892
+ </Box>}
1893
+ {streamEndPoint && !builderData?.isRaw === true && minimized !== true &&
1894
+ <Box>
1895
+ <Tooltip title='تصدير'>
1896
+ <IconButton
1897
+ disabled={isDownloading}
1898
+ onClick={handleCSVExport}
1899
+ color='primary'
1900
+ >
1901
+ {isDownloading ? <CircularProgress size={24}/> : <FileExcelOutline/>}
1902
+ </IconButton>
1903
+ </Tooltip>
1904
+ </Box>
1905
+ }
1906
+ {minimized !== true && !isPagination &&
1907
+ <Box>
1908
+ <Tooltip title="تصدير PDF">
1909
+ <IconButton onClick={handlePDFExport} color="primary">
1910
+ <PrintOutlined/>
1911
+ </IconButton>
1912
+ </Tooltip>
1913
+ </Box>
1914
+ }
1915
+ {
1916
+ builderData?.id != null && minimized !== true && <>
1917
+ <Box>
1918
+ <Tooltip title='حفظ النموذج'>
1919
+ <IconButton disabled={selectedTemplate == null} onClick={() => {
1920
+ handleSaveTemplate()
1921
+ }} color='primary'>
1922
+ <Save/>
1923
+ </IconButton>
1924
+ </Tooltip>
1925
+ </Box>
1926
+ <Box>
1927
+ <Tooltip title='حفظ بأسم'>
1928
+ <IconButton onClick={() => {
1929
+ setIsTemplateEditing(false)
1930
+ handleToggleDialogs('addTemplate')
1931
+ }} color='primary'>
1932
+ <SaveAs/>
1933
+ </IconButton>
1934
+ </Tooltip>
1935
+ </Box>
1936
+
1937
+ <Box>
1938
+ <Tooltip title='تعديل'>
1939
+ <IconButton disabled={selectedTemplate == null}
1940
+ onClick={() => {
1941
+ setIsTemplateEditing(true)
1942
+ handleToggleDialogs('addTemplate')
1943
+ }}
1944
+ color='primary'
1945
+ >
1946
+ <Edit/>
1947
+ </IconButton>
1948
+ </Tooltip>
1949
+ </Box>
1950
+ </>
1951
+ }
1952
+ {<Box>
1953
+
1954
+ <IconButton color={'primary'} onClick={() => handleToggleDialogs('CustomFilter')}>
1955
+ <FilterAlt/>
1956
+ </IconButton>
1957
+ </Box>
1958
+ }
1959
+ <Box>
1960
+ <Tooltip title='اعادة تحميل'>
1961
+ <IconButton onClick={() => setLocalRefresh(!localRefresh)}>
1962
+ <RefreshOutlined/>
1963
+ </IconButton>
1964
+ </Tooltip>
1965
+ </Box>
1966
+
1967
+ </Box>
1968
+ </Grid>
1969
+ <div style={{width: "100%", height: minimized === true ? "0px" : height ?? "70vh", direction: 'ltr'}}>
1970
+ <AgGridReact
1971
+
1972
+ debug={false}
1973
+ columnHoverHighlight={true}
1974
+ theme={agTheme}
1975
+ enableRtl={true}
1976
+ columnDefs={colDefs}
1977
+ rowModelType={"serverSide"}
1978
+ onGridReady={onGridReady}
1979
+ maxConcurrentDatasourceRequests={0}
1980
+ cacheBlockSize={100}
1981
+ onRowSelected={onRowSelected}
1982
+ // getChildCount={getChildCount}
1983
+ sideBar={sideBarConfig}
1984
+ context={{tRouting, builderId: builderData?.id}} // pass routing and builder id
1985
+ gridOptions={{
1986
+ enableRangeSelection: true,
1987
+ enableCharts: true,
1988
+ }}
1989
+ rowSelection="multiple"
1990
+ statusBar={{
1991
+ statusPanels: [
1992
+ // { statusPanel: 'agTotalRowCountComponent' },
1993
+ {
1994
+ statusPanel: CustomStatusBar,
1995
+ align: 'left',
1996
+ },
1997
+
1998
+ // { statusPanel: 'agFilteredRowCountComponent' },
1999
+ // { statusPanel: 'agSelectedRowCountComponent' },
2000
+ ],
2001
+ }}
2002
+ groupHeaderHeight={25}
2003
+ // onChartCreated={x => console.log(x)}
2004
+ headerHeight={25}
2005
+ autoGroupColumnDef={autoGroupColumnDef}
2006
+ getRowId={getRowId}
2007
+ serverSideDatasource={datasource}
2008
+ blockLoadDebounceMillis={200}
2009
+ pinnedBottomRowData={pagedAgg}
2010
+ suppressRowClickSelection={true}
2011
+ serverSidePivotResultFieldSeparator={"_"}
2012
+ pivotKeySeparator={"_"}
2013
+ getRowStyle={(row) => {
2014
+ if (row.node.group) {
2015
+ return {fontWeight: 'bold'};
2016
+ }
2017
+ if (expireReport) {
2018
+ if (row.node?.data?.expireDate && new Date(row.node.data.expireDate) <= new Date()) {
2019
+ return {background: '#FF625F'};
2020
+ }
2021
+ if (row.node?.data?.expireDate) {
2022
+ const expireDate = new Date(row.node.data.expireDate);
2023
+ const currentDate = new Date();
2024
+ const diffInDays = (expireDate - currentDate) / (1000 * 60 * 60 * 24); // Convert milliseconds to days
2025
+
2026
+ if (diffInDays > 10) {
2027
+ return {background: '#8AFF8A'};
2028
+ } else if (diffInDays > 0) {
2029
+ return {background: '#fcfd74'};
2030
+ }
2031
+ }
2032
+ }
2033
+ }}
2034
+
2035
+ components={{
2036
+ routingCell: RoutingCell,
2037
+ imageCell: ImageCell,
2038
+ customStatusBar: CustomStatusBar,
2039
+ // agColumnsToolPanel: CustomColumnsToolPanel
2040
+
2041
+ }}
2042
+
2043
+
2044
+ onSortChanged={params => {
2045
+ const sm = params.columns;
2046
+ if (sm.length == 1 && sm.some(s => s.colId === 'IZ_groupCount')) {
2047
+ params.api.refreshServerSide({purge: true})
2048
+ }
2049
+ }}
2050
+ />
2051
+ </div>
2052
+ <Dialog
2053
+ fullWidth
2054
+ open={openDialogs?.addTemplate && builderData?.id != null}
2055
+ maxWidth='md'
2056
+ scroll='body'
2057
+ onClose={() => {
2058
+ handleToggleDialogs('addTemplate')
2059
+ }}
2060
+ >
2061
+ <AddTemplateDialog
2062
+ filterValue={Filter}
2063
+ handleToggleDialogs={handleToggleDialogs}
2064
+ pageName={'Builder' + builderData?.id}
2065
+ item={isTemplateEditing === true ? selectedTemplate : null}
2066
+ template={gridApi?.getColumnState()}
2067
+ userId={authValues?.user?.id}/>
2068
+ </Dialog>
2069
+ <Dialog
2070
+ fullWidth
2071
+ open={openDialogs.CustomFilter}
2072
+ maxWidth='xl'
2073
+ scroll='body'
2074
+ // onClose={() => handleToggleDialogs('CustomFilter')}
2075
+ >
2076
+ <CustomFilterDialog
2077
+ handleToggleDialogs={handleToggleDialogs}
2078
+ Filter={[...(Filter?.LocalTfilter || [])]}
2079
+ handleFilterChange={handleFilterChange}
2080
+ className={builderData?.reportSource?.fullName}
2081
+ LocalFilter={false}
2082
+ selectTFilter={selectTFilter}
2083
+ selectParamsMeta={builderData?.selectionParams || []}
2084
+ selectParamsValues={selectParams}
2085
+ onSelectParamsSave={(list) => {
2086
+ // list is array of { index, value, type }
2087
+ setSelectParams(prev => {
2088
+ const arr = [...(prev || [])];
2089
+ (list || []).forEach(item => {
2090
+ const i = item.index;
2091
+ const type = item.type;
2092
+ const current = arr[i] || {id: i, PropertyType: type, value: null};
2093
+ arr[i] = {...current, PropertyType: current.PropertyType || type, value: item.value};
2094
+ });
2095
+ return arr;
2096
+ });
2097
+ }}
2098
+ />
2099
+ </Dialog>
2100
+
2101
+
2102
+ </Grid>
2103
+
2104
+ )
2105
+ }
2106
+
2107
+
2108
+ export default SGrid
2109
+
2110
+
2111
+ // Helper: convert a flat object with underscore-delimited keys into a nested object
2112
+ function toNestedByUnderscore(input) {
2113
+ if (input == null) return input;
2114
+
2115
+ if (Array.isArray(input)) {
2116
+ return input.map(v => (v && typeof v === 'object') ? toNestedByUnderscore(v) : v);
2117
+ }
2118
+
2119
+ if (typeof input !== 'object') return input;
2120
+
2121
+ const result = {};
2122
+
2123
+ const setNested = (target, parts, value) => {
2124
+ let ref = target;
2125
+ for (let i = 0; i < parts.length - 1; i++) {
2126
+ const key = Helper.toCamelCaseDotNet(parts[i]);
2127
+ if (!ref[key] || typeof ref[key] !== 'object' || Array.isArray(ref[key])) {
2128
+ ref[key] = {};
2129
+ }
2130
+ ref = ref[key];
2131
+ }
2132
+
2133
+ const last = Helper.toCamelCaseDotNet(parts[parts.length - 1]);
2134
+ const existing = ref[last];
2135
+ if (
2136
+ existing && typeof existing === 'object' && !Array.isArray(existing) &&
2137
+ value && typeof value === 'object' && !Array.isArray(value)
2138
+ ) {
2139
+ ref[last] = {...existing, ...value};
2140
+ } else {
2141
+ ref[last] = value;
2142
+ }
2143
+ };
2144
+
2145
+ for (const [key, val] of Object.entries(input)) {
2146
+ const nestedVal = (val && typeof val === 'object') ? toNestedByUnderscore(val) : val;
2147
+ const parts = String(key).split('_').filter(Boolean);
2148
+ if (parts.length === 0) continue;
2149
+
2150
+ if (parts.length === 1) {
2151
+ const k = Helper.toCamelCaseDotNet(parts[0]);
2152
+ const existing = result[k];
2153
+ if (
2154
+ existing && typeof existing === 'object' &&
2155
+ nestedVal && typeof nestedVal === 'object'
2156
+ ) {
2157
+ result[k] = {...existing, ...nestedVal};
2158
+ } else {
2159
+ result[k] = nestedVal;
2160
+ }
2161
+ } else {
2162
+ setNested(result, parts, nestedVal);
2163
+ }
2164
+ }
2165
+
2166
+ return result;
2167
+ }
2168
+