robobyte-front-builder 1.0.17 → 1.0.21

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 (516) hide show
  1. package/README.md +211 -0
  2. package/next.config.js +19 -48
  3. package/package.json +39 -85
  4. package/src/context/BuilderContext.jsx +134 -6
  5. package/src/context/SystemContext.js +2 -2
  6. package/src/hooks/useGlobalStore.js +36 -0
  7. package/src/hooks/useTimerEngine.js +54 -0
  8. package/src/lib/index.js +11 -3
  9. package/src/lib/layouts/BlankLayout.jsx +13 -0
  10. package/src/lib/providers/RoboByteFrontBuilderProvider.jsx +59 -1
  11. package/src/lib/themes/builderTheme.js +41 -0
  12. package/src/pages/_app.js +32 -134
  13. package/src/pages/api/ai.js +87 -0
  14. package/src/pages/builders/report/index.js +1 -0
  15. package/src/pages/builders/report/list/index.js +1 -0
  16. package/src/pages/builders/report/viewer/index.js +1 -0
  17. package/src/pages/index.js +88 -37
  18. package/src/pages/printBuilder/index.jsx +263 -0
  19. package/src/pages/printBuilder/layouts/index.jsx +298 -0
  20. package/src/pages/reportModule/reportBuilder/index.js +723 -563
  21. package/src/pages/reportModule/reportBuilder/reportViewer/index.js +137 -71
  22. package/src/pages/reportModule/reportBuilder/reports/index.js +51 -13
  23. package/src/pages/reportModule/reportBuilder/reportsPermissions/index.js +126 -0
  24. package/src/pages/viewBuilder/index.jsx +117 -32
  25. package/src/pages/viewBuilder/views/index.js +3 -3
  26. package/src/pages/viewer/[id]/index.js +2 -1
  27. package/src/services/DeleteService.js +31 -60
  28. package/src/services/Endpoints/PrintLayoutEndpoints.js +42 -0
  29. package/src/services/Endpoints.js +2 -0
  30. package/src/services/GetService.js +33 -54
  31. package/src/services/PatchService.js +38 -65
  32. package/src/services/PostService.js +37 -63
  33. package/src/services/UpdateService.js +39 -65
  34. package/src/services/builderHelper/actionExecutor.js +141 -25
  35. package/src/services/builderHelper/builderHelper.js +92 -0
  36. package/src/services/builderHelper/colorSchema.js +95 -0
  37. package/src/services/builderHelper/iconResolver.js +50 -0
  38. package/src/services/builderHelper/jsExecutor.js +212 -46
  39. package/src/services/builderHelper/nodeFactory.js +32 -15
  40. package/src/services/builderHelper/numberFormat.js +123 -0
  41. package/src/services/builderHelper/resolveProps.js +73 -4
  42. package/src/services/builderHelper/thresholdEngine.js +77 -0
  43. package/src/services/builderHelper/tree.js +31 -0
  44. package/src/services/components/agGridAutoComplete.js +5 -9
  45. package/src/services/config.js +9 -1
  46. package/src/services/globalStore.js +80 -0
  47. package/src/services/helper/multiSelectEditor.js +5 -9
  48. package/src/services/helper/multiSelectEditorByBuilder.js +241 -0
  49. package/src/services/helper/reportSessionHelper.js +83 -0
  50. package/src/services/reportData/fetchReportData.js +69 -28
  51. package/src/services/routerRef.js +35 -0
  52. package/src/views/ConfirmDialog.js +2 -2
  53. package/src/views/builder/JSEditor.js +105 -107
  54. package/src/views/builder/inspector/Inspector.jsx +6 -9
  55. package/src/views/builder/inspector/Tabs/ComponentActionsTab.jsx +7 -13
  56. package/src/views/builder/inspector/Tabs/MainTab.jsx +143 -25
  57. package/src/views/builder/inspector/Tabs/RulesTab.jsx +9 -24
  58. package/src/views/builder/inspector/Tabs/StyleTab.jsx +9 -24
  59. package/src/views/builder/inspector/definitions/autocomplete/main.js +4 -6
  60. package/src/views/builder/inspector/definitions/banner/actions.js +7 -0
  61. package/src/views/builder/inspector/definitions/banner/main.js +22 -0
  62. package/src/views/builder/inspector/definitions/banner/rules.js +1 -0
  63. package/src/views/builder/inspector/definitions/banner/style.js +1 -0
  64. package/src/views/builder/inspector/definitions/breadcrumb/main.js +43 -6
  65. package/src/views/builder/inspector/definitions/button/main.js +11 -12
  66. package/src/views/builder/inspector/definitions/button/style.js +18 -30
  67. package/src/views/builder/inspector/definitions/checkbox/actions.js +3 -1
  68. package/src/views/builder/inspector/definitions/checkbox/main.js +4 -6
  69. package/src/views/builder/inspector/definitions/common/main.js +13 -2
  70. package/src/views/builder/inspector/definitions/dataGrid/main.js +23 -0
  71. package/src/views/builder/inspector/definitions/dataTableViewer/main.js +46 -0
  72. package/src/views/builder/inspector/definitions/datepicker/actions.js +3 -1
  73. package/src/views/builder/inspector/definitions/datepicker/main.js +6 -14
  74. package/src/views/builder/inspector/definitions/dialog/main.js +36 -0
  75. package/src/views/builder/inspector/definitions/dropdown/main.js +5 -8
  76. package/src/views/builder/inspector/definitions/excelUpload/actions.js +23 -0
  77. package/src/views/builder/inspector/definitions/excelUpload/main.js +17 -0
  78. package/src/views/builder/inspector/definitions/excelUpload/rules.js +1 -0
  79. package/src/views/builder/inspector/definitions/excelUpload/style.js +45 -0
  80. package/src/views/builder/inspector/definitions/header/main.js +10 -1
  81. package/src/views/builder/inspector/definitions/index.js +106 -19
  82. package/src/views/builder/inspector/definitions/input/actions.js +4 -1
  83. package/src/views/builder/inspector/definitions/input/main.js +20 -11
  84. package/src/views/builder/inspector/definitions/kpi/avatarGroup.js +22 -0
  85. package/src/views/builder/inspector/definitions/kpi/badge.js +17 -0
  86. package/src/views/builder/inspector/definitions/kpi/bulletChart.js +47 -0
  87. package/src/views/builder/inspector/definitions/kpi/chart.js +55 -0
  88. package/src/views/builder/inspector/definitions/kpi/colorScale.js +60 -0
  89. package/src/views/builder/inspector/definitions/kpi/comparisonBars.js +41 -0
  90. package/src/views/builder/inspector/definitions/kpi/countdown.js +46 -0
  91. package/src/views/builder/inspector/definitions/kpi/donut.js +51 -0
  92. package/src/views/builder/inspector/definitions/kpi/funnel.js +25 -0
  93. package/src/views/builder/inspector/definitions/kpi/gauge.js +39 -0
  94. package/src/views/builder/inspector/definitions/kpi/heatmapGrid.js +96 -0
  95. package/src/views/builder/inspector/definitions/kpi/iconBox.js +20 -0
  96. package/src/views/builder/inspector/definitions/kpi/metric.js +45 -0
  97. package/src/views/builder/inspector/definitions/kpi/rating.js +27 -0
  98. package/src/views/builder/inspector/definitions/kpi/statusDot.js +18 -0
  99. package/src/views/builder/inspector/definitions/kpi/stepStage.js +65 -0
  100. package/src/views/builder/inspector/definitions/kpi/tagList.js +32 -0
  101. package/src/views/builder/inspector/definitions/kpi/timeline.js +80 -0
  102. package/src/views/builder/inspector/definitions/kpi/trend.js +20 -0
  103. package/src/views/builder/inspector/definitions/label/main.js +10 -1
  104. package/src/views/builder/inspector/definitions/layout/main.js +27 -3
  105. package/src/views/builder/inspector/definitions/number/main.js +6 -14
  106. package/src/views/builder/inspector/definitions/pageNumber/main.js +21 -0
  107. package/src/views/builder/inspector/definitions/popover/main.js +71 -0
  108. package/src/views/builder/inspector/definitions/radio/main.js +5 -8
  109. package/src/views/builder/inspector/definitions/repeater/main.js +31 -0
  110. package/src/views/builder/inspector/definitions/reportViewer/main.js +15 -1
  111. package/src/views/builder/inspector/definitions/richtext/main.js +5 -8
  112. package/src/views/builder/inspector/definitions/signature/main.js +4 -1
  113. package/src/views/builder/inspector/definitions/tag/main.js +5 -8
  114. package/src/views/builder/inspector/definitions/textarea/actions.js +4 -1
  115. package/src/views/builder/inspector/definitions/textarea/main.js +5 -7
  116. package/src/views/builder/inspector/definitions/time/main.js +5 -8
  117. package/src/views/builder/inspector/definitions/toggle/main.js +5 -19
  118. package/src/views/builder/inspector/definitions/treeView/main.js +61 -0
  119. package/src/views/builder/inspector/definitions/viewRenderer/main.js +53 -0
  120. package/src/views/builder/inspector/definitions/wizard/main.js +68 -0
  121. package/src/views/builder/inspector/definitions/wizard-step/main.js +25 -0
  122. package/src/views/builder/inspector/fields/ActionsConfigEditor.jsx +426 -0
  123. package/src/views/builder/inspector/fields/ColorSchemaField.jsx +140 -0
  124. package/src/views/builder/inspector/fields/ColumnFunctionEditor.jsx +238 -0
  125. package/src/views/builder/inspector/fields/ColumnMappingEditor.jsx +105 -0
  126. package/src/views/builder/inspector/fields/ColumnsConfigEditor.jsx +506 -0
  127. package/src/views/builder/inspector/fields/DonutRingsEditorField.jsx +337 -0
  128. package/src/views/builder/inspector/fields/ExtraColsEditor.jsx +618 -0
  129. package/src/views/builder/inspector/fields/FunctionHelpPopover.jsx +295 -0
  130. package/src/views/builder/inspector/fields/IconEditor.jsx +64 -0
  131. package/src/views/builder/inspector/fields/KpiActionField.jsx +223 -0
  132. package/src/views/builder/inspector/fields/MarkersEditorField.jsx +173 -0
  133. package/src/views/builder/inspector/fields/SelectEditor.jsx +9 -5
  134. package/src/views/builder/inspector/fields/SeriesEditorField.jsx +363 -0
  135. package/src/views/builder/inspector/fields/TableColumnsEditor.jsx +104 -0
  136. package/src/views/builder/inspector/fields/ThresholdsEditor.jsx +247 -0
  137. package/src/views/builder/inspector/fields/ValueFunctionsRefPanel.jsx +217 -0
  138. package/src/views/builder/inspector/fields/columnEditorShared.jsx +217 -0
  139. package/src/views/builder/sidebar/Sidebar.jsx +4 -2
  140. package/src/views/builder/sidebar/SidebarTabs.jsx +28 -17
  141. package/src/views/builder/sidebar/tabs/ActionsTab.jsx +7 -3
  142. package/src/views/builder/sidebar/tabs/AiTab/AiPreviewDialog.jsx +193 -0
  143. package/src/views/builder/sidebar/tabs/AiTab/aiProvider.js +49 -0
  144. package/src/views/builder/sidebar/tabs/AiTab/index.jsx +409 -0
  145. package/src/views/builder/sidebar/tabs/AiTab/schemaTransformer.js +102 -0
  146. package/src/views/builder/sidebar/tabs/AiTab/schemaValidator.js +64 -0
  147. package/src/views/builder/sidebar/tabs/AiTab/systemPrompt.js +1151 -0
  148. package/src/views/builder/sidebar/tabs/Components/ComponentsTab.jsx +31 -31
  149. package/src/views/builder/sidebar/tabs/Components/componentCatalog.js +43 -21
  150. package/src/views/builder/sidebar/tabs/Components/printComponentCatalog.js +81 -0
  151. package/src/views/builder/sidebar/tabs/TimersTab.jsx +338 -0
  152. package/src/views/builder/sidebar/tabs/TreeTab.jsx +13 -4
  153. package/src/views/builder/sidebar/tabs/ViewTab.jsx +1 -1
  154. package/src/views/builder/viewer/AdornedLabel.jsx +82 -0
  155. package/src/views/builder/viewer/ComponentRenderer.jsx +98 -24
  156. package/src/views/builder/viewer/DialogsZone.jsx +259 -0
  157. package/src/views/builder/viewer/FieldLabel.jsx +106 -0
  158. package/src/views/builder/viewer/PrintDialog.jsx +481 -0
  159. package/src/views/builder/viewer/ProductionViewer.jsx +80 -5
  160. package/src/views/builder/viewer/Viewer.jsx +106 -8
  161. package/src/views/builder/viewer/ViewerComponentWrapper.jsx +61 -4
  162. package/src/views/builder/viewer/ViewerToolbar.jsx +273 -59
  163. package/src/views/builder/viewer/renderers/AutoCompleteRenderer.jsx +26 -22
  164. package/src/views/builder/viewer/renderers/AvatarGroupRenderer.jsx +112 -0
  165. package/src/views/builder/viewer/renderers/BadgeRenderer.jsx +79 -0
  166. package/src/views/builder/viewer/renderers/BannerRenderer.jsx +62 -0
  167. package/src/views/builder/viewer/renderers/BreadcrumbRenderer.jsx +203 -15
  168. package/src/views/builder/viewer/renderers/BulletChartRenderer.jsx +147 -0
  169. package/src/views/builder/viewer/renderers/ButtonRenderer.jsx +98 -39
  170. package/src/views/builder/viewer/renderers/CardRenderer.jsx +1 -1
  171. package/src/views/builder/viewer/renderers/ChartRenderer.jsx +388 -0
  172. package/src/views/builder/viewer/renderers/CheckboxRenderer.jsx +17 -9
  173. package/src/views/builder/viewer/renderers/ColorScaleRenderer.jsx +300 -0
  174. package/src/views/builder/viewer/renderers/ComparisonBarsRenderer.jsx +133 -0
  175. package/src/views/builder/viewer/renderers/ContainerRenderer.jsx +3 -1
  176. package/src/views/builder/viewer/renderers/CountdownRenderer.jsx +249 -0
  177. package/src/views/builder/viewer/renderers/DataGridRenderer.jsx +380 -0
  178. package/src/views/builder/viewer/renderers/DataTableViewerRenderer.jsx +240 -0
  179. package/src/views/builder/viewer/renderers/DatePickerRenderer.jsx +25 -24
  180. package/src/views/builder/viewer/renderers/DialogRenderer.jsx +327 -0
  181. package/src/views/builder/viewer/renderers/DividerRenderer.jsx +1 -1
  182. package/src/views/builder/viewer/renderers/DonutRenderer.jsx +294 -0
  183. package/src/views/builder/viewer/renderers/DropdownRenderer.jsx +36 -44
  184. package/src/views/builder/viewer/renderers/ExcelUploadRenderer.jsx +639 -0
  185. package/src/views/builder/viewer/renderers/FunnelRenderer.jsx +93 -0
  186. package/src/views/builder/viewer/renderers/GaugeRenderer.jsx +159 -0
  187. package/src/views/builder/viewer/renderers/HeaderRenderer.jsx +31 -9
  188. package/src/views/builder/viewer/renderers/HeatmapGridRenderer.jsx +432 -0
  189. package/src/views/builder/viewer/renderers/IconBoxRenderer.jsx +59 -0
  190. package/src/views/builder/viewer/renderers/ImageRenderer.jsx +1 -1
  191. package/src/views/builder/viewer/renderers/InputRenderer.jsx +75 -18
  192. package/src/views/builder/viewer/renderers/LabelRenderer.jsx +35 -9
  193. package/src/views/builder/viewer/renderers/LayoutCellRenderer.jsx +102 -40
  194. package/src/views/builder/viewer/renderers/LayoutContextMenu.jsx +8 -8
  195. package/src/views/builder/viewer/renderers/LayoutRenderer.jsx +48 -6
  196. package/src/views/builder/viewer/renderers/LinkRenderer.jsx +1 -1
  197. package/src/views/builder/viewer/renderers/MenuRenderer.jsx +2 -2
  198. package/src/views/builder/viewer/renderers/MetricRenderer.jsx +80 -0
  199. package/src/views/builder/viewer/renderers/NumberFormatRenderer.jsx +21 -30
  200. package/src/views/builder/viewer/renderers/PageNumberRenderer.jsx +76 -0
  201. package/src/views/builder/viewer/renderers/PopoverRenderer.jsx +350 -0
  202. package/src/views/builder/viewer/renderers/ProgressCircleRenderer.jsx +1 -1
  203. package/src/views/builder/viewer/renderers/ProgressLineRenderer.jsx +1 -1
  204. package/src/views/builder/viewer/renderers/RadioGroupRenderer.jsx +28 -39
  205. package/src/views/builder/viewer/renderers/RatingRenderer.jsx +80 -0
  206. package/src/views/builder/viewer/renderers/RepeaterRenderer.jsx +297 -38
  207. package/src/views/builder/viewer/renderers/ReportViewerRenderer.jsx +219 -5
  208. package/src/views/builder/viewer/renderers/RichTextRenderer.jsx +60 -66
  209. package/src/views/builder/viewer/renderers/RowActionsCell.jsx +308 -0
  210. package/src/views/builder/viewer/renderers/SignatureRenderer.jsx +33 -62
  211. package/src/views/builder/viewer/renderers/StatusDotRenderer.jsx +75 -0
  212. package/src/views/builder/viewer/renderers/StepStageRenderer.jsx +348 -0
  213. package/src/views/builder/viewer/renderers/TagListRenderer.jsx +115 -0
  214. package/src/views/builder/viewer/renderers/TagPickerRenderer.jsx +31 -45
  215. package/src/views/builder/viewer/renderers/TextAreaRenderer.jsx +25 -18
  216. package/src/views/builder/viewer/renderers/TextRenderer.jsx +7 -1
  217. package/src/views/builder/viewer/renderers/TimePickerRenderer.jsx +25 -24
  218. package/src/views/builder/viewer/renderers/TimelineRenderer.jsx +525 -0
  219. package/src/views/builder/viewer/renderers/ToggleRenderer.jsx +21 -27
  220. package/src/views/builder/viewer/renderers/TreeViewRenderer.jsx +832 -0
  221. package/src/views/builder/viewer/renderers/TrendRenderer.jsx +66 -0
  222. package/src/views/builder/viewer/renderers/ViewRendererRenderer.jsx +315 -0
  223. package/src/views/builder/viewer/renderers/WizardRenderer.jsx +380 -64
  224. package/src/views/builder/viewer/renderers/WizardStepRenderer.jsx +21 -12
  225. package/src/views/builder/viewer/renderers/dataGridComponents.jsx +824 -0
  226. package/src/views/customFilter/CustomFilterDialog.js +1023 -660
  227. package/src/views/customFilter/FixedFilterDialog.js +649 -0
  228. package/src/views/customFilter/SearchFilterDialog.js +248 -0
  229. package/src/views/genericTable/BuilderExpressionParams.js +3 -3
  230. package/src/views/genericTable/ColumnConfiguratorDialog.js +771 -0
  231. package/src/views/genericTable/FixedFilterDialog.js +3 -2
  232. package/src/views/genericTable/FormattingSettingsDialog.js +551 -0
  233. package/src/views/genericTable/ReportSettingsDialog.js +151 -0
  234. package/src/views/genericTable/SGrid.js +1061 -247
  235. package/src/views/genericTable/SearchFilterDialog.js +3 -2
  236. package/src/views/genericTable/TAGGrid.js +83 -69
  237. package/src/views/genericTable/cellEditors/autocompleteEditor.js +5 -9
  238. package/src/views/genericTable/convertStringFunctions.js +336 -0
  239. package/src/views/genericTable/statusBar/rowCountStatusBar.js +3 -1
  240. package/src/views/genericTable/updateRefHelpers.js +424 -0
  241. package/src/views/printBuilder/PrintBuilderViewer.jsx +607 -0
  242. package/src/views/printBuilder/PrintPreviewCanvas.jsx +157 -0
  243. package/src/views/rolePermissions/UpdateReportPermissionDialog.js +316 -0
  244. package/src/@core/components/auth/AclGuard.js +0 -55
  245. package/src/@core/components/auth/AuthGuard.js +0 -40
  246. package/src/@core/components/auth/GuestGuard.js +0 -30
  247. package/src/@core/components/custom-inputs/Horizontal.jsx +0 -143
  248. package/src/@core/components/custom-inputs/Image.jsx +0 -78
  249. package/src/@core/components/custom-inputs/Vertical.jsx +0 -113
  250. package/src/@core/components/customizer/index.jsx +0 -470
  251. package/src/@core/components/customizer/styles.module.css +0 -169
  252. package/src/@core/components/mui/Avatar.jsx +0 -41
  253. package/src/@core/components/mui/Badge.jsx +0 -20
  254. package/src/@core/components/mui/IconButton.jsx +0 -74
  255. package/src/@core/components/mui/TabList.jsx +0 -60
  256. package/src/@core/components/option-menu/index.jsx +0 -137
  257. package/src/@core/components/scroll-to-top/index.jsx +0 -43
  258. package/src/@core/components/spinner/index.js +0 -26
  259. package/src/@core/components/window-wrapper/index.js +0 -27
  260. package/src/@core/contexts/settingsContext.jsx +0 -98
  261. package/src/@core/hooks/useBgColor.js +0 -63
  262. package/src/@core/hooks/useImageVariant.js +0 -27
  263. package/src/@core/hooks/useLayoutInit.js +0 -37
  264. package/src/@core/hooks/useObjectCookie.js +0 -18
  265. package/src/@core/hooks/useSettings.jsx +0 -15
  266. package/src/@core/layouts/BlankLayout.js +0 -37
  267. package/src/@core/layouts/BlankLayoutWithAppBar.js +0 -51
  268. package/src/@core/layouts/HorizontalLayout.jsx +0 -151
  269. package/src/@core/layouts/Layout.js +0 -39
  270. package/src/@core/layouts/VerticalLayout.jsx +0 -124
  271. package/src/@core/layouts/components/blank-layout-with-appBar/index.js +0 -115
  272. package/src/@core/layouts/components/horizontal/app-bar-content/index.js +0 -67
  273. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavGroup.js +0 -352
  274. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavItems.js +0 -21
  275. package/src/@core/layouts/components/horizontal/navigation/HorizontalNavLink.js +0 -195
  276. package/src/@core/layouts/components/horizontal/navigation/index.js +0 -31
  277. package/src/@core/layouts/components/shared-components/LanguageDropdown.js +0 -96
  278. package/src/@core/layouts/components/shared-components/ModeToggler.js +0 -32
  279. package/src/@core/layouts/components/shared-components/NotificationDropdown.js +0 -226
  280. package/src/@core/layouts/components/shared-components/UserDropdown.js +0 -177
  281. package/src/@core/layouts/components/shared-components/footer/FooterContent.js +0 -46
  282. package/src/@core/layouts/components/shared-components/footer/index.js +0 -61
  283. package/src/@core/layouts/components/vertical/appBar/index.js +0 -74
  284. package/src/@core/layouts/components/vertical/navigation/Drawer.js +0 -122
  285. package/src/@core/layouts/components/vertical/navigation/VerticalNavGroup.js +0 -435
  286. package/src/@core/layouts/components/vertical/navigation/VerticalNavHeader.js +0 -180
  287. package/src/@core/layouts/components/vertical/navigation/VerticalNavItems.js +0 -26
  288. package/src/@core/layouts/components/vertical/navigation/VerticalNavLink.js +0 -258
  289. package/src/@core/layouts/components/vertical/navigation/VerticalNavSectionTitle.js +0 -102
  290. package/src/@core/layouts/components/vertical/navigation/index.js +0 -169
  291. package/src/@core/layouts/utils.js +0 -69
  292. package/src/@core/styles/Table.module.css +0 -93
  293. package/src/@core/styles/horizontal/menuItemStyles.js +0 -100
  294. package/src/@core/styles/horizontal/menuRootStyles.js +0 -19
  295. package/src/@core/styles/libs/fullcalendar/index.js +0 -461
  296. package/src/@core/styles/libs/keen-slider/index.js +0 -111
  297. package/src/@core/styles/libs/react-apexcharts/index.js +0 -107
  298. package/src/@core/styles/libs/react-cleave/index.js +0 -33
  299. package/src/@core/styles/libs/react-credit-cards/index.js +0 -11
  300. package/src/@core/styles/libs/react-datepicker/index.js +0 -388
  301. package/src/@core/styles/libs/react-draft-wysiwyg/index.js +0 -144
  302. package/src/@core/styles/libs/react-dropzone/index.js +0 -76
  303. package/src/@core/styles/libs/react-hot-toast/index.js +0 -37
  304. package/src/@core/styles/libs/recharts/index.js +0 -47
  305. package/src/@core/styles/stepper.js +0 -103
  306. package/src/@core/styles/vertical/menuItemStyles.js +0 -138
  307. package/src/@core/styles/vertical/menuSectionStyles.js +0 -54
  308. package/src/@core/styles/vertical/navigationCustomStyles.js +0 -62
  309. package/src/@core/svg/ContentCompact.jsx +0 -17
  310. package/src/@core/svg/ContentWide.jsx +0 -17
  311. package/src/@core/svg/DirectionLtr.jsx +0 -93
  312. package/src/@core/svg/DirectionRtl.jsx +0 -93
  313. package/src/@core/svg/LayoutCollapsed.jsx +0 -59
  314. package/src/@core/svg/LayoutHorizontal.jsx +0 -42
  315. package/src/@core/svg/LayoutVertical.jsx +0 -59
  316. package/src/@core/svg/Logo.jsx +0 -76
  317. package/src/@core/svg/SkinBordered.jsx +0 -54
  318. package/src/@core/svg/SkinDefault.jsx +0 -59
  319. package/src/@core/tailwind/plugin.js +0 -78
  320. package/src/@core/theme/ThemeComponent.js +0 -63
  321. package/src/@core/theme/ThemeOptions.js +0 -71
  322. package/src/@core/theme/breakpoints/index.js +0 -11
  323. package/src/@core/theme/colorSchemes.js +0 -326
  324. package/src/@core/theme/customShadows.js +0 -11
  325. package/src/@core/theme/globalStyles.js +0 -81
  326. package/src/@core/theme/index.js +0 -42
  327. package/src/@core/theme/overrides/accordion.js +0 -51
  328. package/src/@core/theme/overrides/accordion.jsx +0 -85
  329. package/src/@core/theme/overrides/alerts.js +0 -110
  330. package/src/@core/theme/overrides/alerts.jsx +0 -180
  331. package/src/@core/theme/overrides/autocomplete.js +0 -14
  332. package/src/@core/theme/overrides/autocomplete.jsx +0 -68
  333. package/src/@core/theme/overrides/avatar.js +0 -38
  334. package/src/@core/theme/overrides/avatars.js +0 -27
  335. package/src/@core/theme/overrides/backdrop.js +0 -22
  336. package/src/@core/theme/overrides/badges.js +0 -16
  337. package/src/@core/theme/overrides/breadcrumbs.js +0 -11
  338. package/src/@core/theme/overrides/button-group.js +0 -84
  339. package/src/@core/theme/overrides/button.js +0 -93
  340. package/src/@core/theme/overrides/buttonGroup.js +0 -9
  341. package/src/@core/theme/overrides/card.js +0 -83
  342. package/src/@core/theme/overrides/checkbox.jsx +0 -95
  343. package/src/@core/theme/overrides/chip.js +0 -72
  344. package/src/@core/theme/overrides/dataGrid.js +0 -114
  345. package/src/@core/theme/overrides/dateTimePicker.js +0 -65
  346. package/src/@core/theme/overrides/dialog.js +0 -120
  347. package/src/@core/theme/overrides/divider.js +0 -13
  348. package/src/@core/theme/overrides/drawer.js +0 -20
  349. package/src/@core/theme/overrides/fab.js +0 -13
  350. package/src/@core/theme/overrides/form-control-label.js +0 -19
  351. package/src/@core/theme/overrides/icon-button.js +0 -145
  352. package/src/@core/theme/overrides/index.js +0 -103
  353. package/src/@core/theme/overrides/input.js +0 -72
  354. package/src/@core/theme/overrides/link.js +0 -9
  355. package/src/@core/theme/overrides/list.js +0 -44
  356. package/src/@core/theme/overrides/menu.js +0 -25
  357. package/src/@core/theme/overrides/pagination.js +0 -41
  358. package/src/@core/theme/overrides/paper.js +0 -9
  359. package/src/@core/theme/overrides/popover.js +0 -16
  360. package/src/@core/theme/overrides/progress.js +0 -38
  361. package/src/@core/theme/overrides/radio.jsx +0 -80
  362. package/src/@core/theme/overrides/rating.js +0 -16
  363. package/src/@core/theme/overrides/rating.jsx +0 -32
  364. package/src/@core/theme/overrides/select.js +0 -19
  365. package/src/@core/theme/overrides/select.jsx +0 -52
  366. package/src/@core/theme/overrides/slider.js +0 -97
  367. package/src/@core/theme/overrides/snackbar.js +0 -19
  368. package/src/@core/theme/overrides/switch.js +0 -73
  369. package/src/@core/theme/overrides/switches.js +0 -25
  370. package/src/@core/theme/overrides/table-pagination.js +0 -39
  371. package/src/@core/theme/overrides/table.js +0 -81
  372. package/src/@core/theme/overrides/tabs.js +0 -30
  373. package/src/@core/theme/overrides/timeline.js +0 -80
  374. package/src/@core/theme/overrides/toggle-button.js +0 -33
  375. package/src/@core/theme/overrides/toggleButton.js +0 -16
  376. package/src/@core/theme/overrides/tooltip.js +0 -21
  377. package/src/@core/theme/overrides/typography.js +0 -13
  378. package/src/@core/theme/palette/index.js +0 -107
  379. package/src/@core/theme/shadows/index.js +0 -61
  380. package/src/@core/theme/shadows.js +0 -12
  381. package/src/@core/theme/spacing/index.js +0 -3
  382. package/src/@core/theme/spacing.js +0 -5
  383. package/src/@core/theme/typography/index.js +0 -65
  384. package/src/@core/theme/typography.js +0 -84
  385. package/src/@core/utils/create-emotion-cache.js +0 -5
  386. package/src/@core/utils/hex-to-rgba.js +0 -11
  387. package/src/@core/utils/serverHelpers.js +0 -45
  388. package/src/@menu/components/RouterLink.jsx +0 -18
  389. package/src/@menu/components/horizontal-menu/HorizontalNav.jsx +0 -88
  390. package/src/@menu/components/horizontal-menu/Menu.jsx +0 -83
  391. package/src/@menu/components/horizontal-menu/MenuButton.jsx +0 -100
  392. package/src/@menu/components/horizontal-menu/MenuItem.jsx +0 -183
  393. package/src/@menu/components/horizontal-menu/SubMenu.jsx +0 -418
  394. package/src/@menu/components/horizontal-menu/SubMenuContent.jsx +0 -41
  395. package/src/@menu/components/horizontal-menu/VerticalNavInHorizontal.jsx +0 -20
  396. package/src/@menu/components/vertical-menu/Menu.jsx +0 -161
  397. package/src/@menu/components/vertical-menu/MenuButton.jsx +0 -95
  398. package/src/@menu/components/vertical-menu/MenuItem.jsx +0 -180
  399. package/src/@menu/components/vertical-menu/MenuSection.jsx +0 -124
  400. package/src/@menu/components/vertical-menu/NavCollapseIcons.jsx +0 -70
  401. package/src/@menu/components/vertical-menu/NavHeader.jsx +0 -39
  402. package/src/@menu/components/vertical-menu/SubMenu.jsx +0 -420
  403. package/src/@menu/components/vertical-menu/SubMenuContent.jsx +0 -101
  404. package/src/@menu/components/vertical-menu/VerticalNav.jsx +0 -216
  405. package/src/@menu/contexts/horizontalNavContext.jsx +0 -29
  406. package/src/@menu/contexts/verticalNavContext.jsx +0 -65
  407. package/src/@menu/defaultConfigs.js +0 -12
  408. package/src/@menu/hooks/useHorizontalMenu.jsx +0 -19
  409. package/src/@menu/hooks/useHorizontalNav.jsx +0 -19
  410. package/src/@menu/hooks/useMediaQuery.jsx +0 -29
  411. package/src/@menu/hooks/useVerticalMenu.jsx +0 -19
  412. package/src/@menu/hooks/useVerticalNav.jsx +0 -19
  413. package/src/@menu/horizontal-menu/index.jsx +0 -8
  414. package/src/@menu/styles/StyledBackdrop.jsx +0 -15
  415. package/src/@menu/styles/StyledMenuIcon.jsx +0 -12
  416. package/src/@menu/styles/StyledMenuLabel.jsx +0 -16
  417. package/src/@menu/styles/StyledMenuPrefix.jsx +0 -10
  418. package/src/@menu/styles/StyledMenuSectionLabel.jsx +0 -21
  419. package/src/@menu/styles/StyledMenuSuffix.jsx +0 -10
  420. package/src/@menu/styles/StyledSubMenuContent.jsx +0 -43
  421. package/src/@menu/styles/horizontal/StyledHorizontalMenu.jsx +0 -13
  422. package/src/@menu/styles/horizontal/StyledHorizontalMenuItem.jsx +0 -26
  423. package/src/@menu/styles/horizontal/StyledHorizontalNav.jsx +0 -11
  424. package/src/@menu/styles/horizontal/StyledHorizontalNavExpandIcon.jsx +0 -33
  425. package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContent.jsx +0 -18
  426. package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContentWrapper.jsx +0 -10
  427. package/src/@menu/styles/horizontal/horizontalUl.module.css +0 -15
  428. package/src/@menu/styles/styles.module.css +0 -5
  429. package/src/@menu/styles/vertical/StyledVerticalMenu.jsx +0 -16
  430. package/src/@menu/styles/vertical/StyledVerticalMenuItem.jsx +0 -28
  431. package/src/@menu/styles/vertical/StyledVerticalMenuSection.jsx +0 -23
  432. package/src/@menu/styles/vertical/StyledVerticalNav.jsx +0 -67
  433. package/src/@menu/styles/vertical/StyledVerticalNavBgColorContainer.jsx +0 -15
  434. package/src/@menu/styles/vertical/StyledVerticalNavContainer.jsx +0 -23
  435. package/src/@menu/styles/vertical/StyledVerticalNavExpandIcon.jsx +0 -25
  436. package/src/@menu/styles/vertical/verticalNavBgImage.module.css +0 -10
  437. package/src/@menu/svg/ChevronRight.jsx +0 -9
  438. package/src/@menu/svg/Close.jsx +0 -12
  439. package/src/@menu/svg/RadioCircle.jsx +0 -12
  440. package/src/@menu/svg/RadioCircleMarked.jsx +0 -13
  441. package/src/@menu/utils/menuClasses.js +0 -44
  442. package/src/@menu/utils/menuUtils.jsx +0 -145
  443. package/src/@menu/vertical-menu/index.jsx +0 -11
  444. package/src/configs/acl.js +0 -115
  445. package/src/configs/auth.js +0 -5
  446. package/src/configs/aws-exports.js +0 -30
  447. package/src/configs/firebase.js +0 -25
  448. package/src/configs/i18n.js +0 -34
  449. package/src/configs/primaryColorConfig.js +0 -35
  450. package/src/configs/themeConfig.js +0 -44
  451. package/src/layouts/UserLayout.js +0 -94
  452. package/src/layouts/UserThemeOptions.js +0 -191
  453. package/src/layouts/components/Direction.js +0 -30
  454. package/src/layouts/components/HtmlTooltip.js +0 -15
  455. package/src/layouts/components/Translations.js +0 -11
  456. package/src/layouts/components/UserDropdown.js +0 -217
  457. package/src/layouts/components/UserIcon.js +0 -40
  458. package/src/layouts/components/acl/Can.js +0 -6
  459. package/src/layouts/components/acl/CanViewNavGroup.js +0 -36
  460. package/src/layouts/components/acl/CanViewNavLink.js +0 -17
  461. package/src/layouts/components/acl/CanViewNavSectionTitle.js +0 -17
  462. package/src/layouts/components/horizontal/AppBarContent.js +0 -39
  463. package/src/layouts/components/horizontal/ServerSideNavItems.js +0 -44
  464. package/src/layouts/components/mui/StepperComps.js +0 -55
  465. package/src/layouts/components/vertical/AppBarContent.js +0 -35
  466. package/src/layouts/components/vertical/ServerSideNavItems.js +0 -44
  467. package/src/libs/ApexCharts.jsx +0 -5
  468. package/src/libs/ReactPlayer.jsx +0 -5
  469. package/src/libs/Recharts.jsx +0 -4
  470. package/src/libs/auth.js +0 -124
  471. package/src/libs/styles/AppFullCalendar.js +0 -505
  472. package/src/libs/styles/AppKeenSlider.js +0 -116
  473. package/src/libs/styles/AppReactApexCharts.jsx +0 -110
  474. package/src/libs/styles/AppReactDatepicker.jsx +0 -470
  475. package/src/libs/styles/AppReactDropzone.js +0 -76
  476. package/src/libs/styles/AppReactToastify.jsx +0 -108
  477. package/src/libs/styles/AppRecharts.js +0 -55
  478. package/src/libs/styles/inputOtp.module.css +0 -39
  479. package/src/libs/styles/tiptapEditor.css +0 -72
  480. package/src/navigation/horizontal/index.js +0 -246
  481. package/src/navigation/vertical/index.js +0 -253
  482. package/src/pages/401.js +0 -70
  483. package/src/pages/404.js +0 -67
  484. package/src/pages/500.js +0 -68
  485. package/src/pages/[slug].js +0 -115
  486. package/src/pages/_document.js +0 -72
  487. package/src/pages/api/navigation/regenerate-registry.js +0 -116
  488. package/src/pages/api/navigation/save.js +0 -218
  489. package/src/pages/authModule/acl/index.js +0 -48
  490. package/src/pages/authModule/forgot-password/index.js +0 -228
  491. package/src/pages/authModule/permissions/rolePermissions/[id]/rolePermissionsUser/index.js +0 -392
  492. package/src/pages/authModule/permissions/rolePermissions/index.js +0 -343
  493. package/src/pages/authModule/permissions/systemPermissions/index.js +0 -354
  494. package/src/pages/authModule/privacy/index.js +0 -721
  495. package/src/pages/authModule/users/index.js +0 -210
  496. package/src/pages/login/index.js +0 -328
  497. package/src/pages/mainHome/index.js +0 -181
  498. package/src/views/builder/inspector/definitions/cell/main.js +0 -4
  499. package/src/views/builder/inspector/definitions/column/main.js +0 -9
  500. package/src/views/builder/inspector/definitions/column-group/main.js +0 -18
  501. package/src/views/builder/inspector/definitions/header-cell/main.js +0 -5
  502. package/src/views/builder/inspector/definitions/table/main.js +0 -9
  503. package/src/views/builder/viewer/renderers/CellRenderer.jsx +0 -71
  504. package/src/views/builder/viewer/renderers/ColumnGroupRenderer.jsx +0 -96
  505. package/src/views/builder/viewer/renderers/ColumnRenderer.jsx +0 -71
  506. package/src/views/builder/viewer/renderers/HeaderCellRenderer.jsx +0 -78
  507. package/src/views/builder/viewer/renderers/TabRenderer.jsx +0 -82
  508. package/src/views/builder/viewer/renderers/TableRenderer.jsx +0 -92
  509. package/src/views/pages/auth/FooterIllustrationsV2.js +0 -40
  510. package/src/views/pages/misc/FooterIllustrations.js +0 -47
  511. package/src/views/pages/misc/muiTable/CustomPagination.js +0 -34
  512. package/src/views/pages/users/UserManageDialog.js +0 -283
  513. package/src/views/pages/users/UserViewPage.js +0 -199
  514. package/src/views/users/AddUserNameDialog.js +0 -162
  515. package/src/views/users/ContactManage.js +0 -449
  516. package/src/views/users/ResetPasswordDialog.js +0 -242
@@ -1,5 +1,5 @@
1
1
  // ** React Imports
2
- import {useEffect, useState, useContext, useCallback, useMemo} from 'react'
2
+ import {useEffect, useState, useContext, useCallback, useMemo, useRef} from 'react'
3
3
  import {useForm, Controller, useFieldArray, useWatch} from 'react-hook-form'
4
4
  import {yupResolver} from '@hookform/resolvers/yup'
5
5
  import * as yup from 'yup'
@@ -24,9 +24,15 @@ import {
24
24
  ListItemIcon,
25
25
  ListItemText,
26
26
  Chip,
27
- InputAdornment
27
+ Paper,
28
+ InputAdornment,
29
+ Collapse
28
30
  } from '@mui/material'
29
- import {Close, TrashCanOutline, Plus, ArrowLeft, FilterPlus} from 'mdi-material-ui'
31
+ import {Close, TrashCanOutline, Plus, ArrowLeft, FilterPlus, CodeBraces} from 'mdi-material-ui'
32
+ import dynamic from 'next/dynamic'
33
+ import { HelpPopover } from 'views/builder/inspector/fields/FunctionHelpPopover'
34
+
35
+ const MonacoEditor = dynamic(() => import('@monaco-editor/react'), {ssr: false})
30
36
  // ** Context
31
37
  import {SystemContext} from 'context/SystemContext'
32
38
  import {Endpoints, Services} from 'src/services/Endpoints'
@@ -39,6 +45,7 @@ import dayjs from "dayjs";
39
45
  import utc from "dayjs/plugin/utc";
40
46
  import timezone from "dayjs/plugin/timezone";
41
47
  import {debounce} from "lodash";
48
+ import {AuthContext} from "context/AuthContext";
42
49
 
43
50
  dayjs.extend(utc)
44
51
  dayjs.extend(timezone)
@@ -60,7 +67,10 @@ const CustomFilterDialog = props => {
60
67
  onSelectParamChange,
61
68
  selectParamsValues = [],
62
69
  onSelectParamsSave,
70
+ customFilterCode: initialCustomFilterCode,
71
+ isViewer,
63
72
  } = props
73
+ const authContext = useContext(AuthContext)
64
74
  const [IsSubmitting, setIsSubmitting] = useState(false)
65
75
  const [isLoading, setIsLoading] = useState(false)
66
76
  const [FilterObjects, setFilterObject] = useState([])
@@ -70,6 +80,7 @@ const CustomFilterDialog = props => {
70
80
  const [Path, setPath] = useState()
71
81
  const [searchInputs, setSearchInputs] = useState([])
72
82
  const [FriendlyName, setFriendlyName] = useState()
83
+ const [isStartUp, setIsStartup] = useState(true)
73
84
  const [openDialogs, setOpenDialogs] = useState({
74
85
  CustomFilter: false
75
86
  })
@@ -83,11 +94,13 @@ const CustomFilterDialog = props => {
83
94
  })
84
95
  // Temp selection params state: user edits are stored here and only applied on Save
85
96
  const [tempParams, setTempParams] = useState([])
97
+ const [customCode, setCustomCode] = useState('')
98
+ const [showCodeEditor, setShowCodeEditor] = useState(false)
99
+ const initializedRef = useRef(false)
86
100
  const mazajakValues = useContext(SystemContext)
87
101
  const schema = yup.object().shape({
88
102
  Tfilters: yup.array().of(yup.object().shape({}))
89
103
  })
90
- console.log(Filter)
91
104
  // ** Form Initialization
92
105
  const {
93
106
  control,
@@ -115,6 +128,11 @@ const CustomFilterDialog = props => {
115
128
  control,
116
129
  name: 'Tfilters'
117
130
  })
131
+
132
+ const updateCustom = (idx, field, val) => {
133
+ setValue(`Tfilters.${idx}.${field}`, val)
134
+ }
135
+
118
136
  // ** Handle Save
119
137
  const handleSave = data => {
120
138
  // Exclude fixed rows from LocalTfilter to avoid duplication when merged with builder fixed filters
@@ -122,6 +140,78 @@ const CustomFilterDialog = props => {
122
140
  const localOnly = all.filter(f => !f?.fixed)
123
141
  const fixedOnly = all.filter(f => !!f?.fixed)
124
142
  console.log(all)
143
+
144
+ let customFilterResult = []
145
+
146
+ // 1. Process individual custom filters from the list
147
+ all.forEach(f => {
148
+ if (f.isCustom && f.customCode && f.customCode.trim() && f.value !== null && f.value !== '') {
149
+ try {
150
+ const executeCode = new Function('authContext', 'value', 'filters', `
151
+ try {
152
+ return (function(authContext, value, filters) {
153
+ ${f.customCode}
154
+ })(authContext, value, filters);
155
+ } catch (e) {
156
+ console.error('Inner error in customFilterCode:', e);
157
+ return null;
158
+ }
159
+ `)
160
+ const result = executeCode(authContext, f.value, all)
161
+ if (result && typeof result === 'object' && !Array.isArray(result)) {
162
+ // Add value to the object if it's not already set to something else
163
+ if (result.value === undefined || result.value === null) {
164
+ result.value = f.value
165
+ }
166
+ customFilterResult.push(result)
167
+ } else if (Array.isArray(result)) {
168
+ // If the result is an array, process each item to add the value if it's not already set
169
+ const processedResult = result.map(item => {
170
+ if (item && typeof item === 'object' && !Array.isArray(item)) {
171
+ if (item.value === undefined || item.value === null) {
172
+ return {...item, value: f.value}
173
+ }
174
+ }
175
+ return item
176
+ })
177
+ customFilterResult = [...customFilterResult, ...processedResult]
178
+ }
179
+ } catch (error) {
180
+ console.error('Error executing custom filter code for ' + f.friendlyName, error)
181
+ }
182
+ }
183
+ })
184
+
185
+ // 2. Execute main custom code if present
186
+ if (customCode && customCode.trim()) {
187
+ try {
188
+ // Create function with access to authContext
189
+ const executeCode = new Function('authContext', 'filters', `
190
+ let customFilter = [];
191
+ try {
192
+ ${customCode}
193
+ } catch (e) {
194
+ console.error('Inner error in customFilterCode:', e);
195
+ }
196
+ return customFilter;
197
+ `)
198
+ const result = executeCode(authContext, all)
199
+ console.log('Main custom filter result:', result)
200
+
201
+ // Validate that result is an array
202
+ if (result && Array.isArray(result)) {
203
+ customFilterResult = [...customFilterResult, ...result]
204
+ } else if (result && !Array.isArray(result)) {
205
+ alert('Error: Main custom filter must return an array')
206
+ return
207
+ }
208
+ } catch (error) {
209
+ console.error('Error executing main custom filter code:', error)
210
+ alert('Error in main custom filter code: ' + error.message)
211
+ return
212
+ }
213
+ }
214
+
125
215
  // Apply any pending selection parameter edits on Save only
126
216
  if (typeof onSelectParamsSave === 'function') {
127
217
  const converted = (tempParams || []).map((p, idx) => {
@@ -139,15 +229,30 @@ const CustomFilterDialog = props => {
139
229
  onSelectParamsSave(converted);
140
230
  }
141
231
  // Format full list for Tfilter; FilterFormat will skip empty fixed filters per rules
142
- const formatedFilter = FilterFormat(all).filter(
143
- x =>
144
- x.value !== null &&
145
- x.value !== '' &&
146
- !(Array.isArray(x.value) && x.value.length === 0)
147
- );
148
- console.log(formatedFilter)
149
- handleFilterChange('Tfilter', formatedFilter, filterIndex)
232
+ const formattedFilter = FilterFormat(all).filter(x => {
233
+ // Exclude custom filter definitions from the final list sent to the API
234
+ if (x.isCustom) return false;
235
+
236
+ const v = x.value;
237
+
238
+ if (v === null || v === '') return false;
239
+
240
+ if (Array.isArray(v) && v.length === 0) return false;
241
+
242
+ if (typeof v === 'object' && v !== null && !dayjs(v).isValid()) {
243
+ const {fromValue, toValue} = v;
244
+ if (fromValue == null && toValue == null) return false;
245
+ }
246
+
247
+ return true;
248
+ });
249
+
250
+ // Merge custom results
251
+ const finalFilter = [...formattedFilter, ...customFilterResult].filter(x => !x.isCustom);
252
+
253
+ handleFilterChange('Tfilter', finalFilter, filterIndex)
150
254
  handleFilterChange('LocalTfilter', [...localOnly, ...fixedOnly], filterIndex)
255
+ handleFilterChange('customFilterCode', customCode, filterIndex)
151
256
 
152
257
  // Persist fixed rows (raw) so dialog can restore their values on reopen (SGrid consumes fixedTFilter)
153
258
  // handleFilterChange('fixedTFilter', fixedOnly, filterIndex)
@@ -155,7 +260,7 @@ const CustomFilterDialog = props => {
155
260
  }
156
261
 
157
262
  async function handleArrayChange(field, value, index) {
158
- setValue(`Tfilters.${index}.Tfilter`, value)
263
+ setValue(`Tfilters.${index}.${field}`, value)
159
264
  }
160
265
 
161
266
  async function handleGetFilterObject() {
@@ -294,23 +399,30 @@ const CustomFilterDialog = props => {
294
399
  }
295
400
 
296
401
  useEffect(() => {
297
- if (!Filter) return;
298
- console.log(Filter)
402
+ if (!Filter || !Array.isArray(Filter) || isStartUp == false) return
403
+ // Only run if Filter has actual content or has changed meaningfully
404
+ if (Filter.length === 0 && !isStartUp) return
405
+
299
406
  // Helper that maps one list, casting DateTime values to JS Dates
300
407
  const castDateFields = (list = []) =>
301
408
  list.map(item => ({
302
409
  ...item,
303
- value:
304
- item.propertyType === "DateTime" && typeof item.value === "string"
305
- ? dayjs(item.value)
306
- : item.value,
307
- }));
410
+ value: item.propertyType === 'DateTime' && typeof item.value === 'string' ? dayjs(item.value) : item.value
411
+ }))
308
412
  // Build a brand-new object with Tfilter and LocalTfilter fixed
309
- const normalized = castDateFields(Filter);
310
- console.log(normalized)
413
+ const normalized = castDateFields(Filter)
311
414
  // Now reset your RHF form with the real Date objects
312
- reset({Tfilters: normalized});
313
- }, [Filter, reset]);
415
+ reset({Tfilters: normalized})
416
+ setIsStartup(false)
417
+ }, [Filter, isStartUp])
418
+
419
+ // Restore custom filter code when dialog opens (only once)
420
+ useEffect(() => {
421
+ if (initialCustomFilterCode && !initializedRef.current) {
422
+ setCustomCode(initialCustomFilterCode)
423
+ initializedRef.current = true
424
+ }
425
+ }, [initialCustomFilterCode])
314
426
 
315
427
  // Initialize temporary params whenever metadata/values change
316
428
  useEffect(() => {
@@ -323,7 +435,11 @@ const CustomFilterDialog = props => {
323
435
  return {value: existing ?? null, type};
324
436
  })
325
437
  : [];
326
- setTempParams(arr);
438
+
439
+ setTempParams(prev => {
440
+ if (JSON.stringify(prev) === JSON.stringify(arr)) return prev;
441
+ return arr;
442
+ });
327
443
  }, [selectParamsMeta, selectParamsValues]);
328
444
 
329
445
  useEffect(() => {
@@ -386,49 +502,66 @@ const CustomFilterDialog = props => {
386
502
  });
387
503
  };
388
504
  return (
389
- <Grid item size={12} md={6} key={`param-${idx}`}>
390
- {type === 'Bool' ? (
391
- <FormControl fullWidth>
392
- <InputLabel>{label}</InputLabel>
393
- <Select
394
- label={label}
505
+ <Grid key={`param-${idx}`} size={{ xs: 12, md: 6 }}>
506
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
507
+ {type === 'Bool' ? (
508
+ <FormControl fullWidth>
509
+ <InputLabel>{label}</InputLabel>
510
+ <Select
511
+ label={label}
512
+ size='small'
513
+ value={val === true || val === 'true' ? true : val === false || val === 'false' ? false : ''}
514
+ onChange={(e) => setVal(e.target.value === '' ? null : e.target.value)}
515
+ >
516
+ <MenuItem value={''}>الكل</MenuItem>
517
+ <MenuItem value={true}>True</MenuItem>
518
+ <MenuItem value={false}>False</MenuItem>
519
+ </Select>
520
+ </FormControl>
521
+ ) : type === 'DateTime' ? (
522
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
523
+ <DatePicker
524
+ value={val && typeof val === 'string' && val.includes('{{auth.') ? null : (val ? dayjs(val) : null)}
525
+ onChange={(v) => setVal(v ? dayjs(v) : null)}
526
+ slotProps={{
527
+ field: {clearable: true},
528
+ textField: {fullWidth: true, label, size: 'small', variant: 'outlined'}
529
+ }}
530
+ />
531
+ </LocalizationProvider>
532
+ ) : (
533
+ <TextField
534
+ fullWidth
395
535
  size='small'
396
- value={val === true || val === 'true' ? true : val === false || val === 'false' ? false : ''}
536
+ variant='outlined'
537
+ type={val && typeof val === 'string' && val.includes('{{auth.') ? 'text' : 'text'}
538
+ inputProps={{step: type === 'Double' ? 'any' : undefined}}
539
+ label={label}
540
+ value={val ?? ''}
397
541
  onChange={(e) => setVal(e.target.value === '' ? null : e.target.value)}
398
- >
399
- <MenuItem value={''}>-</MenuItem>
400
- <MenuItem value={true}>True</MenuItem>
401
- <MenuItem value={false}>False</MenuItem>
402
- </Select>
403
- </FormControl>
404
- ) : type === 'DateTime' ? (
405
- <LocalizationProvider dateAdapter={AdapterDayjs}>
406
- <DatePicker
407
- value={val ? dayjs(val) : null}
408
- onChange={(v) => setVal(v ? dayjs(v) : null)}
409
- renderInput={(params) => (
410
- <TextField
411
- {...params}
412
- fullWidth
413
- label={label}
414
- size="small"
415
- variant="outlined"
416
- />
417
- )}
418
542
  />
419
- </LocalizationProvider>
420
- ) : (
421
- <TextField
422
- fullWidth
423
- size='small'
424
- variant='outlined'
425
- type={type === 'Int' || type === 'Double' ? 'number' : 'text'}
426
- inputProps={{step: type === 'Double' ? 'any' : undefined}}
427
- label={label}
428
- value={val ?? ''}
429
- onChange={(e) => setVal(e.target.value === '' ? null : e.target.value)}
430
- />
431
- )}
543
+ )}
544
+ <IconButton
545
+ size="small"
546
+ sx={{ml: 1}}
547
+ onClick={() => {
548
+ let authPath = '';
549
+ if (idx === 0) authPath = 'user.id';
550
+ else if (label.toLowerCase().includes('shop')) authPath = 'user.contact.shopId';
551
+ else if (label.toLowerCase().includes('contact')) authPath = 'user.contact.id';
552
+ else if (label.toLowerCase().includes('user')) authPath = 'user.id';
553
+
554
+ if (authPath) {
555
+ setVal(`{{auth.${authPath}}}`);
556
+ } else {
557
+ setVal(`{{auth.user.id}}`);
558
+ }
559
+ }}
560
+ title="Bind to Auth Context"
561
+ >
562
+ <CodeBraces fontSize="small"/>
563
+ </IconButton>
564
+ </Box>
432
565
  </Grid>
433
566
  );
434
567
  })}
@@ -436,650 +569,845 @@ const CustomFilterDialog = props => {
436
569
  </Box>
437
570
  )}
438
571
 
439
- {orderedIndices.map((index) => (
440
- <Grid container spacing={2} mt={1} key={fields[index]?.id ?? index}>
441
- {!Tfilters[index]?.fixed && (
442
- <Grid item size={3}>
443
- <FormControl fullWidth>
572
+ {/*{isViewer && Tfilters.some(row => row?.isMainFilter && !row?.fixed) && (*/}
573
+ {/* <Box sx={{ mb: 4, px: 1 }}>*/}
574
+ {/* <Grid container spacing={2}>*/}
575
+ {/* {orderedIndices.map((index) => {*/}
576
+ {/* const row = Tfilters[index];*/}
577
+ {/* const showAsLabel = isViewer && row?.isMainFilter && !row?.fixed;*/}
578
+ {/* if (!showAsLabel) return null;*/}
579
+
580
+ {/* const valueDisplay = row.method === 'isBetween'*/}
581
+ {/* ? `${row.value?.fromValue ?? ''} - ${row.value?.toValue ?? ''}`*/}
582
+ {/* : (Array.isArray(row.value)*/}
583
+ {/* ? row.value.map(v => v?.name ?? v).join(', ')*/}
584
+ {/* : (row.value?.name ?? row.value ?? ''));*/}
585
+
586
+ {/* return (*/}
587
+ {/* <Grid key={fields[index]?.id ?? index}>*/}
588
+ {/* <Paper variant="outlined" sx={{ p: 2, bgcolor: 'background.default', display: 'flex', flexDirection: 'column', gap: 0.5 }}>*/}
589
+ {/* <Typography variant="caption" sx={{ color: 'text.secondary', fontWeight: 'bold' }}>*/}
590
+ {/* {row.friendlyName}*/}
591
+ {/* </Typography>*/}
592
+ {/* <Typography variant="caption" sx={{ color: 'text.disabled', fontSize: '0.7rem', textTransform: 'uppercase' }}>*/}
593
+ {/* {row.method === 'Equals' ? '=' : (row.method === 'Orlist' ? 'OR' : row.method)}*/}
594
+ {/* </Typography>*/}
595
+ {/* <Typography variant="body2" sx={{ fontWeight: 'medium', color: 'primary.main' }}>*/}
596
+ {/* {valueDisplay}*/}
597
+ {/* </Typography>*/}
598
+ {/* </Paper>*/}
599
+ {/* </Grid>*/}
600
+ {/* );*/}
601
+ {/* })}*/}
602
+ {/* </Grid>*/}
603
+ {/* </Box>*/}
604
+ {/*)}*/}
605
+
606
+ {orderedIndices.map((index) => {
607
+ const row = Tfilters[index];
608
+ const showAsLabel = isViewer && row?.isMainFilter && !row?.fixed;
609
+ if (showAsLabel) return null;
610
+
611
+ if (row?.isCustom) {
612
+ return (
613
+ <Grid container spacing={2} mt={1} key={fields[index]?.id ?? index}>
614
+ <Grid size={{ xs: 11 }}>
444
615
  <Controller
445
- name={`Tfilters.${index}`}
616
+ name={`Tfilters.${index}.value`}
446
617
  control={control}
447
618
  render={({field}) => {
448
- const rowModel = Tfilters[index]
449
- console.log(selectTFilter)
619
+ if (row.valueType === 'Bool') {
620
+ return (
621
+ <FormControl fullWidth>
622
+ <InputLabel>{row.friendlyName || 'القيمة'}</InputLabel>
623
+ <Select
624
+ {...field}
625
+ label={row.friendlyName || 'القيمة'}
626
+ variant='outlined'
627
+ size='small'
628
+ value={field.value === true ? 'true' : (field.value === false ? 'false' : '')}
629
+ onChange={e => {
630
+ field.onChange(e.target.value === '' ? null : (e.target.value === 'true'))
631
+ }}
632
+ >
633
+ <MenuItem value=''>الكل</MenuItem>
634
+ <MenuItem value='true'>نعم</MenuItem>
635
+ <MenuItem value='false'>كلا</MenuItem>
636
+ </Select>
637
+ </FormControl>
638
+ )
639
+ } else if (row.valueType === 'Options') {
640
+ return (
641
+ <FormControl fullWidth>
642
+ <InputLabel>{row.friendlyName || 'القيمة'}</InputLabel>
643
+ <Select
644
+ {...field}
645
+ label={row.friendlyName || 'القيمة'}
646
+ variant='outlined'
647
+ size='small'
648
+ value={field.value || ''}
649
+ onChange={e => {
650
+ field.onChange(e.target.value)
651
+ }}
652
+ >
653
+ {(row.options || []).map((opt, i) => (
654
+ <MenuItem key={i} value={opt}>{opt}</MenuItem>
655
+ ))}
656
+ </Select>
657
+ </FormControl>
658
+ )
659
+ }
450
660
  return (
451
- <Autocomplete
661
+ <TextField
452
662
  {...field}
453
- loading={isLoading}
454
- disabled={!!rowModel?.fixed}
455
- onOpen={() => setOpen(true)}
456
- onClose={() => setOpen(false)}
457
- options={[
458
- ...(!Tfilters[index]?.dtoClassName ? selectTFilter : []),
459
- ...(Tfilters[index]?.localProperty === 'Class'
460
- ? SubFilters[`Tfilters.${index}`] || FilterObjects
461
- : FilterObjects),
462
- ]}
463
- // ✅ option-based label so built-in search works
464
- getOptionLabel={(option) =>
465
- typeof option === 'string'
466
- ? option
467
- : (option?.friendlyName || option?.path || '')
468
- }
469
- // optional: search by both fields
470
- filterOptions={(options, {inputValue}) => {
471
- const q = inputValue.toLowerCase();
472
- return options.filter(
473
- o =>
474
- o?.friendlyName?.toLowerCase().includes(q) ||
475
- o?.path?.toLowerCase().includes(q)
476
- );
477
- }}
478
- // ✅ stable equality even after you mutate path -> ".Id"
479
- isOptionEqualToValue={(opt, val) =>
480
- normalizePath(opt?.path) === normalizePath(val?.path)
481
- }
482
- value={field.value}
483
- onChange={(e, value) => {
484
- field.onChange(value);
485
- handleOptionSelect(value, field, index);
486
- setValue(`Tfilters.${index}.method`, '');
487
- setValue(`Tfilters.${index}.value`, null);
488
- }}
489
- renderOption={(props, option) => (
490
- <ListItem
491
- {...props}
492
- secondaryAction={
493
- option.propertyType === 'Class' ? (
494
- <IconButton
495
- size='small'
496
- onMouseDown={(e) => e.preventDefault()}
497
- onClick={async (e) => {
498
- e.stopPropagation();
499
- await handleOptionSelect(option, field, index);
500
- }}
501
- title='Navigate into'
502
- >
503
- <ArrowLeft fontSize='small'/>
504
- </IconButton>
505
- ) : null
506
- }
507
- >
508
- <ListItemText primary={option.friendlyName}/>
509
- </ListItem>
510
- )}
511
- renderInput={(params) => (
512
- <TextField
513
- {...params}
514
- label="البحث عن"
515
- size="small"
516
- variant="outlined"
517
- helperText={Tfilters[index]?.friendlyName || ''}
518
- />
519
- )}
663
+ fullWidth
664
+ size="small"
665
+ variant="outlined"
666
+ label={row.friendlyName || "Value"}
667
+ type={row.valueType === 'Number' ? 'number' : (row.valueType === 'DateTime' ? 'datetime-local' : 'text')}
668
+ InputLabelProps={row.valueType === 'DateTime' ? {shrink: true} : {}}
520
669
  />
521
670
  )
522
671
  }}
523
672
  />
524
- </FormControl>
673
+ </Grid>
674
+ <Grid sx={{display: 'flex', alignItems: 'center'}} size={{ xs: 1 }}>
675
+ {!Tfilters[index]?.fixed && (
676
+ <IconButton size='small' sx={{color: 'red'}} onClick={() => remove(index)}>
677
+ <TrashCanOutline fontSize='small'/>
678
+ </IconButton>
679
+ )}
680
+ </Grid>
525
681
  </Grid>
526
- )}
682
+ )
683
+ }
527
684
 
528
- {!Tfilters[index]?.fixed && (
529
- <Grid item size={2}>
530
- <FormControl fullWidth>
531
- <InputLabel>العملية</InputLabel>
532
- <Controller
533
- name={`Tfilters.${index}.method`}
534
- control={control}
535
- render={({field}) => (
536
- <Select
537
- {...field}
538
- fullWidth
539
- variant='outlined'
540
- size={'small'}
541
- disabled={!!Tfilters[index]?.fixed}
542
- onChange={e => {
543
- field.onChange(e.target.value)
544
- const value = e.target.value
545
- if (value == 'Orlist' || value == 'NotOrlist') {
546
- setValue(`Tfilters.${index}.isOrList`, true)
547
- setValue(`Tfilters.${index}.checkForNull`, false)
548
- setValue(`Tfilters.${index}.value`, [])
549
- } else if (value == 'checkForNull') {
550
- setValue(`Tfilters.${index}.checkForNull`, true)
551
- setValue(`Tfilters.${index}.isOrList`, false)
552
- setValue(`Tfilters.${index}.value`, null)
553
- } else {
554
- setValue(`Tfilters.${index}.isOrList`, false)
555
- setValue(`Tfilters.${index}.checkForNull`, false)
556
- setValue(`Tfilters.${index}.value`, null)
557
- }
558
- }}
559
- >
560
- {Tfilters[index]?.localProperty == 'String' && <MenuItem value='Contains'>يحتوي</MenuItem>}
561
- {Tfilters[index]?.localProperty == 'String' && (
562
- <MenuItem value='NotContains'>لا يحتوي</MenuItem>
563
- )}
564
- {Tfilters[index]?.localProperty !== 'DateTime' && <MenuItem value='Equals'>=</MenuItem>}
565
- {Tfilters[index]?.localProperty !== 'DateTime' && <MenuItem value='NotEquals'>=!</MenuItem>}
566
-
567
- {((Tfilters[index]?.localProperty == 'String' ||
568
- Tfilters[index]?.localProperty == 'Class' ||
569
- Tfilters[index]?.localProperty == 'Enum') && (Tfilters[index]?.path !== "Id" &&
570
- !Tfilters[index]?.path?.toLowerCase().endsWith(".id")
571
- )) && <MenuItem value='Orlist'> {'كل من'} </MenuItem>}
572
- {((Tfilters[index]?.localProperty == 'String' ||
573
- Tfilters[index]?.localProperty == 'Class' ||
574
- Tfilters[index]?.localProperty == 'Enum') && (Tfilters[index]?.path !== "Id" && !Tfilters[index]?.path?.toLowerCase().endsWith(".id")
575
- )) && (
576
- <MenuItem value='NotOrlist'> {'لا يحتوي على كل من'} </MenuItem>
577
- )}
578
- {(
579
- Tfilters[index]?.localProperty == 'Int' ||
580
- Tfilters[index]?.localProperty == 'Double' ||
581
- Tfilters[index]?.localProperty == 'DateTime') && (
582
- <MenuItem value='GreaterThan'> {'>'} </MenuItem>
583
- )}
584
- {(Tfilters[index]?.localProperty == 'Int' ||
585
- Tfilters[index]?.localProperty == 'Double' ||
586
- Tfilters[index]?.localProperty == 'DateTime') && (
587
- <MenuItem value='isBetween'> {'isBetween'} </MenuItem>
588
- )}
685
+ return (
686
+ <Grid container spacing={2} mt={1} key={fields[index]?.id ?? index}>
687
+ {!Tfilters[index]?.fixed && (
688
+ <Grid size={{ xs: 3 }}>
689
+ <FormControl fullWidth>
690
+ <Controller
691
+ name={`Tfilters.${index}`}
692
+ control={control}
693
+ render={({field}) => {
694
+ const rowModel = Tfilters[index]
695
+ return (
696
+ <Autocomplete
697
+ {...field}
698
+ loading={isLoading}
699
+ disabled={!!rowModel?.fixed}
700
+ onOpen={() => setOpen(true)}
701
+ onClose={() => setOpen(false)}
702
+ options={[
703
+ ...(!Tfilters[index]?.dtoClassName ? selectTFilter : []),
704
+ ...(Tfilters[index]?.localProperty === 'Class'
705
+ ? SubFilters[`Tfilters.${index}`] || FilterObjects
706
+ : FilterObjects),
707
+ ]}
708
+ getOptionLabel={(option) =>
709
+ typeof option === 'string'
710
+ ? option
711
+ : (option?.friendlyName || option?.path || '')
712
+ }
713
+ filterOptions={(options, {inputValue}) => {
714
+ const q = inputValue.toLowerCase();
715
+ return options.filter(
716
+ o =>
717
+ o?.friendlyName?.toLowerCase().includes(q) ||
718
+ o?.path?.toLowerCase().includes(q)
719
+ );
720
+ }}
721
+ isOptionEqualToValue={(opt, val) =>
722
+ normalizePath(opt?.path) === normalizePath(val?.path)
723
+ }
724
+ value={field.value}
725
+ onChange={(e, value) => {
726
+ field.onChange(value);
727
+ handleOptionSelect(value, field, index);
728
+ setValue(`Tfilters.${index}.method`, '');
729
+ setValue(`Tfilters.${index}.value`, null);
730
+ }}
731
+ renderOption={(props, option) => (
732
+ <ListItem
733
+ {...props}
734
+ secondaryAction={
735
+ option.propertyType === 'Class' ? (
736
+ <IconButton
737
+ size='small'
738
+ onMouseDown={(e) => e.preventDefault()}
739
+ onClick={async (e) => {
740
+ e.stopPropagation();
741
+ await handleOptionSelect(option, field, index);
742
+ }}
743
+ title='Navigate into'
744
+ >
745
+ <ArrowLeft fontSize='small'/>
746
+ </IconButton>
747
+ ) : null
748
+ }
749
+ >
750
+ <ListItemText primary={option.friendlyName}/>
751
+ </ListItem>
752
+ )}
753
+ renderInput={(params) => (
754
+ <TextField
755
+ {...params}
756
+ label="البحث عن"
757
+ size="small"
758
+ variant="outlined"
759
+ helperText={Tfilters[index]?.friendlyName || ''}
760
+ />
761
+ )}
762
+ />
763
+ )
764
+ }}
765
+ />
766
+ </FormControl>
767
+ </Grid>
768
+ )}
589
769
 
590
- {((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id")) && (
591
- <MenuItem value="Orlist">{"كل من"}</MenuItem>
592
- )}
770
+ {!Tfilters[index]?.fixed && (
771
+ <Grid size={{ xs: 2 }}>
772
+ <FormControl fullWidth>
773
+ <InputLabel>العملية</InputLabel>
774
+ <Controller
775
+ name={`Tfilters.${index}.method`}
776
+ control={control}
777
+ render={({field}) => (
778
+ <Select
779
+ {...field}
780
+ fullWidth
781
+ variant='outlined'
782
+ size={'small'}
783
+ disabled={!!Tfilters[index]?.fixed}
784
+ onChange={e => {
785
+ field.onChange(e.target.value)
786
+ const value = e.target.value
787
+ if (value == 'Orlist' || value == 'NotOrlist') {
788
+ setValue(`Tfilters.${index}.isOrList`, true)
789
+ setValue(`Tfilters.${index}.checkForNull`, false)
790
+ setValue(`Tfilters.${index}.value`, [])
791
+ } else if (value == 'checkForNull') {
792
+ setValue(`Tfilters.${index}.checkForNull`, true)
793
+ setValue(`Tfilters.${index}.isOrList`, false)
794
+ setValue(`Tfilters.${index}.value`, null)
795
+ } else {
796
+ setValue(`Tfilters.${index}.isOrList`, false)
797
+ setValue(`Tfilters.${index}.checkForNull`, false)
798
+ setValue(`Tfilters.${index}.value`, null)
799
+ }
800
+ }}
801
+ >
802
+ {Tfilters[index]?.localProperty == 'String' && <MenuItem value='Contains'>يحتوي</MenuItem>}
803
+ {Tfilters[index]?.localProperty == 'String' && (
804
+ <MenuItem value='NotContains'>لا يحتوي</MenuItem>
805
+ )}
806
+ {Tfilters[index]?.localProperty !== 'DateTime' && <MenuItem value='Equals'>=</MenuItem>}
807
+ {Tfilters[index]?.localProperty !== 'DateTime' && <MenuItem value='NotEquals'>=!</MenuItem>}
593
808
 
594
- {((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id")) && (
595
- <MenuItem value='NotOrlist'> {'لا يحتوي على كل من'} </MenuItem>
596
- )}
809
+ {((Tfilters[index]?.localProperty == 'String' ||
810
+ Tfilters[index]?.localProperty == 'Class' ||
811
+ Tfilters[index]?.localProperty == 'Enum') && (Tfilters[index]?.path !== "Id" &&
812
+ !Tfilters[index]?.path?.toLowerCase().endsWith(".id")
813
+ )) && <MenuItem value='Orlist'> {'كل من'} </MenuItem>}
814
+ {((Tfilters[index]?.localProperty == 'String' ||
815
+ Tfilters[index]?.localProperty == 'Class' ||
816
+ Tfilters[index]?.localProperty == 'Enum') && (Tfilters[index]?.path !== "Id" && !Tfilters[index]?.path?.toLowerCase().endsWith(".id")
817
+ )) && (
818
+ <MenuItem value='NotOrlist'> {'لا يحتوي على كل من'} </MenuItem>
819
+ )}
820
+ {(
821
+ Tfilters[index]?.localProperty == 'Int' ||
822
+ Tfilters[index]?.localProperty == 'Double' ||
823
+ Tfilters[index]?.localProperty == 'DateTime') && (
824
+ <MenuItem value='GreaterThan'> {'>'} </MenuItem>
825
+ )}
826
+ {(Tfilters[index]?.localProperty == 'Int' ||
827
+ Tfilters[index]?.localProperty == 'Double' ||
828
+ Tfilters[index]?.localProperty == 'DateTime') && (
829
+ <MenuItem value='isBetween'> {'isBetween'} </MenuItem>
830
+ )}
597
831
 
598
- {(Tfilters[index]?.localProperty == 'Int' ||
599
- Tfilters[index]?.localProperty == 'Double' ||
600
- Tfilters[index]?.localProperty == 'DateTime') && (
601
- <MenuItem value='GreaterThanOrEqual'> {'=>'} </MenuItem>
602
- )}
603
- {(Tfilters[index]?.localProperty == 'Int' ||
604
- Tfilters[index]?.localProperty == 'Double' ||
605
- Tfilters[index]?.localProperty == 'DateTime') && (
606
- <MenuItem value='LessThan'> {'<'} </MenuItem>
607
- )}
832
+ {((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id")) && (
833
+ <MenuItem value="Orlist">{"كل من"}</MenuItem>
834
+ )}
608
835
 
609
- {(Tfilters[index]?.localProperty == 'Int' ||
610
- Tfilters[index]?.localProperty == 'Double' ||
611
- Tfilters[index]?.localProperty == 'DateTime') && (
612
- <MenuItem value='LessThanOrEqual'> {'<='} </MenuItem>
613
- )}
836
+ {((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id")) && (
837
+ <MenuItem value='NotOrlist'> {'لا يحتوي على كل من'} </MenuItem>
838
+ )}
614
839
 
615
- {(Tfilters[index]?.localProperty == 'Class') && (
616
- <MenuItem value='checkForNull'> {'لايحتوي على قيمة'} </MenuItem>
617
- )}
618
- </Select>
619
- )}
620
- />
621
- </FormControl>
622
- </Grid>
623
- )}
624
-
625
- {(
626
- (Tfilters[index]?.localProperty === "Int" ||
627
- Tfilters[index]?.localProperty === "Double" ||
628
- Tfilters[index]?.localProperty === "String") &&
629
- (Tfilters[index]?.method !== "NotOrlist" &&
630
- Tfilters[index]?.method !== "Orlist") &&
631
- Tfilters[index]?.isOrList === false &&
632
- Tfilters[index]?.method !== "isBetween"
633
- ) && (
634
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
635
- <Controller
636
- name={`Tfilters.${index}.value`}
637
- control={control}
638
- render={({field}) => (
639
- <TextField
640
- {...field}
641
- type="text"
642
- size="small"
643
- variant="outlined"
644
- fullWidth
645
- label={Tfilters[index]?.friendlyName || 'value'}
646
- placeholder={Tfilters[index]?.friendlyName || 'value'}
647
- />
648
- )}
649
- />
650
- </Grid>
651
- )}
840
+ {(Tfilters[index]?.localProperty == 'Int' ||
841
+ Tfilters[index]?.localProperty == 'Double' ||
842
+ Tfilters[index]?.localProperty == 'DateTime') && (
843
+ <MenuItem value='GreaterThanOrEqual'> {'=>'} </MenuItem>
844
+ )}
845
+ {(Tfilters[index]?.localProperty == 'Int' ||
846
+ Tfilters[index]?.localProperty == 'Double' ||
847
+ Tfilters[index]?.localProperty == 'DateTime') && (
848
+ <MenuItem value='LessThan'> {'<'} </MenuItem>
849
+ )}
652
850
 
653
- {(Tfilters[index]?.localProperty === 'Int' || Tfilters[index]?.localProperty === 'Double') &&
654
- Tfilters[index]?.method === 'isBetween' && (
655
- <Grid item size={Tfilters[index]?.fixed === true ? 6 : 3}>
656
- <Controller
657
- name={`Tfilters.${index}.value.fromValue`}
658
- control={control}
659
- render={({field}) => (
660
- <TextField {...field} type='text' size='small' variant='outlined' fullWidth label='From'/>
661
- )}
662
- />
663
- </Grid>
664
- )}
665
- {(Tfilters[index]?.localProperty === 'Int' || Tfilters[index]?.localProperty === 'Double') &&
666
- Tfilters[index]?.method === 'isBetween' && (
667
- <Grid item size={Tfilters[index]?.fixed === true ? 6 : 3}>
668
- <Controller
669
- name={`Tfilters.${index}.value.toValue`}
670
- control={control}
671
- render={({field}) => (
672
- <TextField {...field} type='text' size='small' variant='outlined' fullWidth label='To'/>
673
- )}
674
- />
851
+ {(Tfilters[index]?.localProperty == 'Int' ||
852
+ Tfilters[index]?.localProperty == 'Double' ||
853
+ Tfilters[index]?.localProperty == 'DateTime') && (
854
+ <MenuItem value='LessThanOrEqual'> {'<='} </MenuItem>
855
+ )}
856
+
857
+ {(Tfilters[index]?.localProperty == 'Class') && (
858
+ <MenuItem value='checkForNull'> {'لايحتوي على قيمة'} </MenuItem>
859
+ )}
860
+ </Select>
861
+ )}
862
+ />
863
+ </FormControl>
675
864
  </Grid>
676
865
  )}
677
- {(Tfilters[index]?.localProperty === 'Int' ||
678
- Tfilters[index]?.localProperty === 'Double' ||
679
- Tfilters[index]?.localProperty === 'String') && ((Tfilters[index]?.method == 'Orlist' || Tfilters[index]?.method == 'NotOrlist') && (Tfilters[index]?.path !== 'Id' && !Tfilters[index]?.path?.toLowerCase().endsWith(".id"))) &&
680
- Tfilters[index]?.isOrList === true && (
681
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
682
- <Controller
683
- name={`Tfilters.${index}.value`}
684
- control={control}
685
- render={({field}) => (
686
- <Autocomplete
687
- multiple
688
- freeSolo
689
- options={[]}
690
- value={field.value || []}
691
- onChange={(event, newValue) => {
692
- field.onChange(newValue)
693
- }}
694
- renderTags={(tagValue, getTagProps) =>
695
- tagValue.map((option, i) => (
696
- <Chip key={i} variant='outlined' label={option} {...getTagProps({index: i})} />
697
- ))
866
+
867
+ {(
868
+ (Tfilters[index]?.localProperty === "Int" ||
869
+ Tfilters[index]?.localProperty === "Double" ||
870
+ Tfilters[index]?.localProperty === "String") &&
871
+ (Tfilters[index]?.method !== "NotOrlist" &&
872
+ Tfilters[index]?.method !== "Orlist") &&
873
+ Tfilters[index]?.isOrList === false &&
874
+ Tfilters[index]?.method !== "isBetween"
875
+ ) && (
876
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
877
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
878
+ <Controller
879
+ name={`Tfilters.${index}.value`}
880
+ control={control}
881
+ render={({field}) => (
882
+ <TextField
883
+ {...field}
884
+ type={field.value && typeof field.value === 'string' && field.value.includes('{{auth.') ? 'text' : 'text'}
885
+ size="small"
886
+ variant="outlined"
887
+ fullWidth
888
+ label={Tfilters[index]?.friendlyName || 'value'}
889
+ placeholder={Tfilters[index]?.friendlyName || 'value'}
890
+ />
891
+ )}
892
+ />
893
+ <IconButton
894
+ size="small"
895
+ sx={{ml: 1}}
896
+ onClick={() => {
897
+ let authPath = '';
898
+ if (index === 0) authPath = 'user.id';
899
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('shop')) authPath = 'user.contact.shopId';
900
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('contact')) authPath = 'user.contact.id';
901
+
902
+ if (authPath) {
903
+ setValue(`Tfilters.${index}.value`, `{{auth.${authPath}}}`);
904
+ } else {
905
+ setValue(`Tfilters.${index}.value`, `{{auth.user.id}}`);
698
906
  }
699
- renderInput={params => (
700
- <TextField {...params} variant='outlined' size='small' fullWidth
701
- label={Tfilters[index]?.friendlyName || 'value'}
702
- placeholder={Tfilters[index]?.friendlyName || 'value'}
703
- />
704
- )}
705
- />
706
- )}
707
- />
907
+ }}
908
+ title="Bind to Auth Context"
909
+ >
910
+ <CodeBraces fontSize="small"/>
911
+ </IconButton>
912
+ </Box>
708
913
  </Grid>
709
914
  )}
710
915
 
711
- {(Tfilters[index]?.localProperty === 'Bool' || (Tfilters[index]?.localProperty === 'Class' && Tfilters[index]?.method === 'checkForNull')) && (
712
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
713
- <FormControl fullWidth>
714
- <InputLabel>{Tfilters[index]?.friendlyName || 'القيمة'}</InputLabel>
715
- <Select
716
- value={watch(`Tfilters.${index}.value`)}
717
- fullWidth
718
- label={Tfilters[index]?.friendlyName || 'القيمة'}
719
- variant='outlined'
720
- size='small'
721
- onChange={e => {
722
- setValue(`Tfilters.${index}.value`, e.target.value)
723
- }}
724
- >
725
- <MenuItem value='Set'>نعم</MenuItem>
726
- <MenuItem value='NotSet'>كلا</MenuItem>
727
- </Select>
728
- </FormControl>
729
- </Grid>
730
- )}
731
- {Tfilters[index]?.localProperty === 'Enum' && Tfilters[index]?.isOrList === false && (
732
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
733
- <FormControl fullWidth>
734
- <Controller
735
- name={`Tfilters.${index}.value`}
736
- control={control}
737
- render={({field}) => (
738
- <Autocomplete
739
- {...field}
740
- options={Enums}
741
- getOptionLabel={option => option?.name || option}
742
- onChange={(e, value) => {
743
- field.onChange(value)
744
- setValue(`Tfilters.${index}.value`, value || '')
745
- }}
746
- renderInput={params => (
916
+ {(Tfilters[index]?.localProperty === 'Int' || Tfilters[index]?.localProperty === 'Double') &&
917
+ Tfilters[index]?.method === 'isBetween' && (
918
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 6 : 3 }}>
919
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
920
+ <Controller
921
+ name={`Tfilters.${index}.value.fromValue`}
922
+ control={control}
923
+ render={({field}) => (
747
924
  <TextField
748
- {...params}
749
- label={Tfilters[index]?.friendlyName || 'البحث عن'}
750
- placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
925
+ {...field}
926
+ type={field.value && typeof field.value === 'string' && field.value.includes('{{auth.') ? 'text' : 'text'}
751
927
  size='small'
752
928
  variant='outlined'
753
- InputProps={{
754
- ...params.InputProps,
755
- onFocus: () => handleGetEnums(Tfilters[index]?.enumName)
756
- }}
929
+ fullWidth
930
+ label='From'
757
931
  />
758
932
  )}
759
933
  />
760
- )}
761
- />
762
- </FormControl>
763
- </Grid>
764
- )}
765
- {Tfilters[index]?.localProperty === 'Enum' && Tfilters[index]?.isOrList === true && (
766
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
767
- <FormControl fullWidth>
768
- <Controller
769
- name={`Tfilters.${index}.value`}
770
- control={control}
771
- render={({field}) => (
772
- <Autocomplete
773
- {...field}
774
- multiple
775
- options={Enums}
776
- getOptionLabel={option => option?.name || option}
777
- onChange={(e, value) => {
778
- const newValue = Array.isArray(value) ? value : []
779
- field.onChange(newValue)
780
- setValue(`Tfilters.${index}.value`, newValue)
934
+ <IconButton
935
+ size="small"
936
+ sx={{ml: 1}}
937
+ onClick={() => {
938
+ let authPath = '';
939
+ if (index === 0) authPath = 'user.id';
940
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('shop')) authPath = 'user.contact.shopId';
941
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('contact')) authPath = 'user.contact.id';
942
+
943
+ if (authPath) {
944
+ setValue(`Tfilters.${index}.value.fromValue`, `{{auth.${authPath}}}`);
945
+ } else {
946
+ setValue(`Tfilters.${index}.value.fromValue`, `{{auth.user.id}}`);
947
+ }
781
948
  }}
782
- renderTags={(tagValue, getTagProps) =>
783
- tagValue.map((option, index) => (
784
- <Chip key={option?.name || index} label={option?.name} {...getTagProps({index})} />
785
- ))
786
- }
787
- renderInput={params => (
949
+ title="Bind to Auth Context"
950
+ >
951
+ <CodeBraces fontSize="small"/>
952
+ </IconButton>
953
+ </Box>
954
+ </Grid>
955
+ )}
956
+ {(Tfilters[index]?.localProperty === 'Int' || Tfilters[index]?.localProperty === 'Double') &&
957
+ Tfilters[index]?.method === 'isBetween' && (
958
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 6 : 3 }}>
959
+ <Box sx={{display: 'flex', alignItems: 'center'}}>
960
+ <Controller
961
+ name={`Tfilters.${index}.value.toValue`}
962
+ control={control}
963
+ render={({field}) => (
788
964
  <TextField
789
- {...params}
790
- label={Tfilters[index]?.friendlyName || 'البحث عن'}
791
- placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
965
+ {...field}
966
+ type={field.value && typeof field.value === 'string' && field.value.includes('{{auth.') ? 'text' : 'text'}
792
967
  size='small'
793
968
  variant='outlined'
794
- InputProps={{
795
- ...params.InputProps,
796
- onFocus: () => handleGetEnums(Tfilters[index]?.enumName)
797
- }}
969
+ fullWidth
970
+ label='To'
798
971
  />
799
972
  )}
800
- value={Array.isArray(field.value) ? field.value : []}
801
973
  />
802
- )}
803
- />
804
- </FormControl>
805
- </Grid>
806
- )}
807
- {((Tfilters[index]?.localProperty === 'Class')
808
- && Tfilters[index]?.isOrList === false
809
- && Tfilters[index]?.method !== 'checkForNull') && (
810
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
811
- <FormControl fullWidth>
812
- <Controller
813
- name={`Tfilters.${index}.value`}
814
- control={control}
815
- render={({field}) => (
816
- <Autocomplete
817
- {...field}
818
- options={Classes}
819
- getOptionKey={(option) => option?.id}
820
- getOptionLabel={(option) => option?.name ?? ''}
821
- onChange={(e, value) => {
822
- field.onChange(value || '');
823
- setValue(`Tfilters.${index}.value`, value ?? null);
824
- setSearchInputs(prev => ({...prev, [index]: ''}));
825
- }}
826
- inputValue={searchInputs[index] ?? ''}
827
- onInputChange={(e, newInputValue, reason) => {
828
- if (reason === 'input') {
829
- setSearchInputs(prev => ({...prev, [index]: newInputValue}));
830
- setClasses([]);
831
- debouncedSearch(newInputValue, index);
832
- } else if (reason === 'reset') {
833
- const label = field.value?.name ?? '';
834
- setSearchInputs(prev => ({...prev, [index]: label}));
974
+ <IconButton
975
+ size="small"
976
+ sx={{ml: 1}}
977
+ onClick={() => {
978
+ let authPath = '';
979
+ if (index === 0) authPath = 'user.id';
980
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('shop')) authPath = 'user.contact.shopId';
981
+ else if (Tfilters[index]?.friendlyName?.toLowerCase().includes('contact')) authPath = 'user.contact.id';
982
+
983
+ if (authPath) {
984
+ setValue(`Tfilters.${index}.value.toValue`, `{{auth.${authPath}}}`);
985
+ } else {
986
+ setValue(`Tfilters.${index}.value.toValue`, `{{auth.user.id}}`);
835
987
  }
836
988
  }}
837
- renderInput={(params) => (
838
- <TextField
839
- {...params}
840
- label={Tfilters[index]?.friendlyName || 'البحث عن'}
841
- placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
842
- size="small"
843
- variant="outlined"
844
- InputProps={{
845
- ...params.InputProps,
846
- endAdornment: (
847
- <InputAdornment position="end">
848
- <IconButton
849
- sx={{right: 0, position: 'absolute', top: -10}}
850
- onClick={() => {
851
- setSelectedFilter((e) => ({
852
- item: Tfilters[index]?.Tfilter,
853
- index: index,
854
- dto: Tfilters[index]?.dtoClassName,
855
- }));
856
- handleOpenDialogs('CustomFilter');
857
- }}
858
- >
859
- <FilterPlus/>
860
- </IconButton>
861
- </InputAdornment>
862
- ),
989
+ title="Bind to Auth Context"
990
+ >
991
+ <CodeBraces fontSize="small"/>
992
+ </IconButton>
993
+ </Box>
994
+ </Grid>
995
+ )}
996
+ {(Tfilters[index]?.localProperty === 'Int' ||
997
+ Tfilters[index]?.localProperty === 'Double' ||
998
+ Tfilters[index]?.localProperty === 'String') && (Tfilters[index]?.method === 'Orlist' || Tfilters[index]?.method === 'NotOrlist') &&
999
+ Tfilters[index]?.isOrList === true && (
1000
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1001
+ <Controller
1002
+ name={`Tfilters.${index}.value`}
1003
+ control={control}
1004
+ render={({field}) => (
1005
+ <Autocomplete
1006
+ multiple
1007
+ freeSolo
1008
+ options={[]}
1009
+ value={Array.isArray(field.value) ? field.value : (field.value ? [field.value] : [])}
1010
+ onChange={(event, newValue) => {
1011
+ field.onChange(newValue)
1012
+ }}
1013
+ renderTags={(tagValue, getTagProps) =>
1014
+ tagValue.map((option, i) => (
1015
+ <Chip key={i} variant='outlined' label={option} {...getTagProps({index: i})} />
1016
+ ))
1017
+ }
1018
+ renderInput={params => (
1019
+ <TextField {...params} variant='outlined' size='small' fullWidth
1020
+ label={Tfilters[index]?.friendlyName || 'value'}
1021
+ placeholder={Tfilters[index]?.friendlyName || 'value'}
1022
+ />
1023
+ )}
1024
+ />
1025
+ )}
1026
+ />
1027
+ </Grid>
1028
+ )}
863
1029
 
864
- }}
865
- />
866
- )}
867
- />
868
- )}
869
- />
870
- </FormControl>
871
- </Grid>
872
- )}
1030
+ {(Tfilters[index]?.localProperty === 'Bool' || (Tfilters[index]?.localProperty === 'Class' && Tfilters[index]?.method === 'checkForNull')) && (
1031
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1032
+ <FormControl fullWidth>
1033
+ <InputLabel>{Tfilters[index]?.friendlyName || 'القيمة'}</InputLabel>
1034
+ <Select
1035
+ value={watch(`Tfilters.${index}.value`)}
1036
+ fullWidth
1037
+ label={Tfilters[index]?.friendlyName || 'القيمة'}
1038
+ variant='outlined'
1039
+ size='small'
1040
+ onChange={e => {
1041
+ if (e.target.value == '')
1042
+ setValue(`Tfilters.${index}.value`, null)
1043
+ setValue(`Tfilters.${index}.value`, e.target.value)
1044
+ }}
1045
+ >
1046
+ <MenuItem value={''}>الكل</MenuItem>
1047
+ <MenuItem value='Set'>نعم</MenuItem>
1048
+ <MenuItem value='NotSet'>كلا</MenuItem>
1049
+ </Select>
1050
+ </FormControl>
1051
+ </Grid>
1052
+ )}
1053
+ {Tfilters[index]?.localProperty === 'Enum' && Tfilters[index]?.isOrList === false && (
1054
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1055
+ <FormControl fullWidth>
1056
+ <Controller
1057
+ name={`Tfilters.${index}.value`}
1058
+ control={control}
1059
+ render={({field}) => (
1060
+ <Autocomplete
1061
+ {...field}
1062
+ options={Enums}
1063
+ getOptionLabel={option => option?.name || option}
1064
+ onChange={(e, value) => {
1065
+ field.onChange(value)
1066
+ setValue(`Tfilters.${index}.value`, value || '')
1067
+ }}
1068
+ renderInput={params => (
1069
+ <TextField
1070
+ {...params}
1071
+ label={Tfilters[index]?.friendlyName || 'البحث عن'}
1072
+ placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
1073
+ size='small'
1074
+ variant='outlined'
1075
+ InputProps={{
1076
+ ...params.InputProps,
1077
+ onFocus: () => handleGetEnums(Tfilters[index]?.enumName)
1078
+ }}
1079
+ />
1080
+ )}
1081
+ />
1082
+ )}
1083
+ />
1084
+ </FormControl>
1085
+ </Grid>
1086
+ )}
1087
+ {Tfilters[index]?.localProperty === 'Enum' && Tfilters[index]?.isOrList === true && (
1088
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1089
+ <FormControl fullWidth>
1090
+ <Controller
1091
+ name={`Tfilters.${index}.value`}
1092
+ control={control}
1093
+ render={({field}) => (
1094
+ <Autocomplete
1095
+ {...field}
1096
+ multiple
1097
+ options={Enums}
1098
+ getOptionLabel={option => option?.name || option}
1099
+ value={Array.isArray(field.value) ? field.value : (field.value ? [field.value] : [])}
1100
+ onChange={(e, value) => {
1101
+ const newValue = Array.isArray(value) ? value : []
1102
+ field.onChange(newValue)
1103
+ setValue(`Tfilters.${index}.value`, newValue)
1104
+ }}
1105
+ renderTags={(tagValue, getTagProps) =>
1106
+ tagValue.map((option, index) => (
1107
+ <Chip key={option?.name || index} label={option?.name} {...getTagProps({index})} />
1108
+ ))
1109
+ }
1110
+ renderInput={params => (
1111
+ <TextField
1112
+ {...params}
1113
+ label={Tfilters[index]?.friendlyName || 'البحث عن'}
1114
+ placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
1115
+ size='small'
1116
+ variant='outlined'
1117
+ InputProps={{
1118
+ ...params.InputProps,
1119
+ onFocus: () => handleGetEnums(Tfilters[index]?.enumName)
1120
+ }}
1121
+ />
1122
+ )}
1123
+ />
1124
+ )}
1125
+ />
1126
+ </FormControl>
1127
+ </Grid>
1128
+ )}
1129
+ {((Tfilters[index]?.localProperty === 'Class')
1130
+ && Tfilters[index]?.isOrList === false
1131
+ && Tfilters[index]?.method !== 'checkForNull') && (
1132
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1133
+ <FormControl fullWidth>
1134
+ <Controller
1135
+ name={`Tfilters.${index}.value`}
1136
+ control={control}
1137
+ render={({field}) => (
1138
+ <Autocomplete
1139
+ {...field}
1140
+ options={Classes}
1141
+ getOptionKey={(option) => option?.id}
1142
+ getOptionLabel={(option) => option?.name ?? ''}
1143
+ onChange={(e, value) => {
1144
+ field.onChange(value || '');
1145
+ setValue(`Tfilters.${index}.value`, value ?? null);
1146
+ setSearchInputs(prev => ({...prev, [index]: ''}));
1147
+ }}
1148
+ inputValue={searchInputs[index] ?? ''}
1149
+ onInputChange={(e, newInputValue, reason) => {
1150
+ if (reason === 'input') {
1151
+ setSearchInputs(prev => ({...prev, [index]: newInputValue}));
1152
+ setClasses([]);
1153
+ debouncedSearch(newInputValue, index);
1154
+ } else if (reason === 'reset') {
1155
+ const label = field.value?.name ?? '';
1156
+ setSearchInputs(prev => ({...prev, [index]: label}));
1157
+ }
1158
+ }}
1159
+ renderInput={(params) => (
1160
+ <TextField
1161
+ {...params}
1162
+ label={Tfilters[index]?.friendlyName || 'البحث عن'}
1163
+ placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
1164
+ size="small"
1165
+ variant="outlined"
1166
+ InputProps={{
1167
+ ...params.InputProps,
1168
+ endAdornment: (
1169
+ <InputAdornment position="end">
1170
+ <IconButton
1171
+ sx={{right: 0, position: 'absolute', top: -10}}
1172
+ onClick={() => {
1173
+ setSelectedFilter((e) => ({
1174
+ item: Tfilters[index]?.LocalTfilter,
1175
+ index: index,
1176
+ dto: Tfilters[index]?.dtoClassName,
1177
+ }));
1178
+ handleOpenDialogs('CustomFilter');
1179
+ }}
1180
+ >
1181
+ <FilterPlus/>
1182
+ </IconButton>
1183
+ </InputAdornment>
1184
+ ),
873
1185
 
874
- {((Tfilters[index]?.localProperty === 'Class' || ((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id"))) && Tfilters[index]?.isOrList === true && Tfilters[index]?.method !== 'checkForNull') && (
875
- <Grid size={Tfilters[index]?.fixed === true ? 12 : 5}>
876
- <FormControl fullWidth>
877
- <Controller
878
- name={`Tfilters.${index}.value`}
879
- control={control}
880
- render={({field}) => (
881
- <Autocomplete
882
- multiple
883
- {...field}
884
- options={Classes}
885
- disableCloseOnSelect
886
- isOptionEqualToValue={(option, value) => option?.id === value?.id}
887
- getOptionLabel={option => option?.name ?? ''}
888
- value={Array.isArray(field.value) ? field.value : []}
889
- onChange={(e, value) => {
890
- const newValue = Array.isArray(value) ? value : [];
891
- field.onChange(newValue);
892
- setValue(`Tfilters.${index}.value`, newValue);
893
- setSearchInputs(prev => ({...prev, [index]: ''}));
894
- }}
895
- // 👇 Add these
896
- inputValue={searchInputs[index] ?? ''}
897
- onInputChange={(e, newInputValue, reason) => {
898
- if (reason === 'input') {
899
- setSearchInputs(prev => ({...prev, [index]: newInputValue}));
900
- setClasses([])
901
- debouncedSearch(newInputValue, index);
1186
+ }}
1187
+ />
1188
+ )}
1189
+ />
1190
+ )}
1191
+ />
1192
+ </FormControl>
1193
+ </Grid>
1194
+ )}
1195
+
1196
+ {((Tfilters[index]?.localProperty === 'Class' || ((Tfilters[index]?.path === "Id") || Tfilters[index]?.path?.toLowerCase().endsWith(".id"))) && Tfilters[index]?.isOrList === true && Tfilters[index]?.method !== 'checkForNull') && (
1197
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1198
+ <FormControl fullWidth>
1199
+ <Controller
1200
+ name={`Tfilters.${index}.value`}
1201
+ control={control}
1202
+ render={({field}) => (
1203
+ <Autocomplete
1204
+ multiple
1205
+ {...field}
1206
+ options={Classes}
1207
+ disableCloseOnSelect
1208
+ isOptionEqualToValue={(option, value) => {
1209
+ const optId = option?.id ?? option?.value;
1210
+ const valId = value?.id ?? value?.value;
1211
+ return optId === valId;
1212
+ }}
1213
+ getOptionLabel={option => option?.name ?? ''}
1214
+ value={Array.isArray(field.value) ? field.value : []}
1215
+ onChange={(e, value) => {
1216
+ const newValue = Array.isArray(value) ? value : [];
1217
+ field.onChange(newValue);
1218
+ setValue(`Tfilters.${index}.value`, newValue);
1219
+ setSearchInputs(prev => ({...prev, [index]: ''}));
1220
+ }}
1221
+ // 👇 Add these
1222
+ inputValue={searchInputs[index] ?? ''}
1223
+ onInputChange={(e, newInputValue, reason) => {
1224
+ if (reason === 'input') {
1225
+ setSearchInputs(prev => ({...prev, [index]: newInputValue}));
1226
+ setClasses([])
1227
+ debouncedSearch(newInputValue, index);
1228
+ }
1229
+ }}
1230
+ renderTags={(tagValue, getTagProps) =>
1231
+ tagValue.map((option, i) => (
1232
+ <Chip key={option?.id || i} label={option?.name} {...getTagProps({index: i})} />
1233
+ ))
902
1234
  }
903
- }}
904
- renderTags={(tagValue, getTagProps) =>
905
- tagValue.map((option, i) => (
906
- <Chip key={option?.id || i} label={option?.name} {...getTagProps({index: i})} />
907
- ))
1235
+ renderInput={params => (
1236
+ <TextField
1237
+ {...params}
1238
+ label={Tfilters[index]?.friendlyName || 'البحث عن'}
1239
+ placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
1240
+ size="small"
1241
+ variant="outlined"
1242
+ InputProps={{
1243
+ ...params.InputProps,
1244
+ endAdornment: (
1245
+ <InputAdornment position="end">
1246
+ <IconButton
1247
+ sx={{right: 0, position: 'absolute'}}
1248
+ onClick={() => {
1249
+ setSelectedFilter({
1250
+ item: Tfilters[index]?.LocalTfilter,
1251
+ index,
1252
+ dto: Tfilters[index]?.dtoClassName
1253
+ });
1254
+ handleOpenDialogs('CustomFilter');
1255
+ }}
1256
+ >
1257
+ <FilterPlus/>
1258
+ </IconButton>
1259
+ </InputAdornment>
1260
+ )
1261
+ }}
1262
+ />
1263
+ )}
1264
+ />
1265
+ )}
1266
+ />
1267
+ </FormControl>
1268
+ </Grid>
1269
+ )}
1270
+
1271
+ {Tfilters[index]?.localProperty === 'DateTime' && Tfilters[index]?.method === 'isBetween' && (
1272
+ <>
1273
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 6 : 3 }}>
1274
+ <Controller
1275
+ name={`Tfilters.${index}.value.fromValue`}
1276
+ control={control}
1277
+ render={({field}) => {
1278
+ const raw = field.value;
1279
+ let val = null;
1280
+ if (raw) {
1281
+ const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
1282
+ val = d.isValid() ? d : null;
908
1283
  }
909
- renderInput={params => (
910
- <TextField
911
- {...params}
912
- label={Tfilters[index]?.friendlyName || 'البحث عن'}
913
- placeholder={Tfilters[index]?.friendlyName || 'البحث عن'}
914
- size="small"
915
- variant="outlined"
916
- InputProps={{
917
- ...params.InputProps,
918
- endAdornment: (
919
- <InputAdornment position="end">
920
- <IconButton
921
- sx={{right: 0, position: 'absolute'}}
922
- onClick={() => {
923
- setSelectedFilter({
924
- item: Tfilters[index]?.Tfilter,
925
- index,
926
- dto: Tfilters[index]?.dtoClassName
927
- });
928
- handleOpenDialogs('CustomFilter');
929
- }}
930
- >
931
- <FilterPlus/>
932
- </IconButton>
933
- </InputAdornment>
934
- )
935
- }}
936
- />
937
- )}
938
- />
939
- )}
940
- />
941
- </FormControl>
942
- </Grid>
943
- )}
1284
+ return (
1285
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
1286
+ <DatePicker
1287
+ {...field}
1288
+ value={val}
1289
+ onChange={(v) => field.onChange(v ? dayjs(v).startOf('day') : null)}
1290
+ slotProps={{
1291
+ field: {clearable: true},
1292
+ textField: {
1293
+ fullWidth: true,
1294
+ label: (Tfilters[index]?.friendlyName ? `${Tfilters[index]?.friendlyName} - من` : 'من التاريخ'),
1295
+ size: 'small',
1296
+ variant: 'outlined'
1297
+ },
1298
+ }}
1299
+ />
1300
+ </LocalizationProvider>
1301
+ );
1302
+ }}
1303
+ />
1304
+ </Grid>
944
1305
 
945
- {Tfilters[index]?.localProperty === 'DateTime' && Tfilters[index]?.method === 'isBetween' && (
946
- <>
947
- <Grid item size={Tfilters[index]?.fixed === true ? 6 : 3}>
948
- <Controller
949
- name={`Tfilters.${index}.value.fromValue`}
950
- control={control}
951
- render={({field}) => {
952
- const raw = field.value;
953
- let val = null;
954
- if (raw) {
955
- const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
956
- val = d.isValid() ? d : null;
957
- }
958
- return (
959
- <LocalizationProvider dateAdapter={AdapterDayjs}>
960
- <DatePicker
961
- {...field}
962
- value={val}
963
- onChange={(v) => field.onChange(v ? dayjs(v).startOf('day') : null)}
964
- renderInput={(params) => (
965
- <TextField
966
- {...params}
967
- fullWidth
968
- label={(Tfilters[index]?.friendlyName ? `${Tfilters[index]?.friendlyName} - من` : 'من التاريخ')}
969
- size="small"
970
- variant="outlined"
971
- />
972
- )}
973
- />
974
- </LocalizationProvider>
975
- );
976
- }}
977
- />
978
- </Grid>
1306
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 6 : 3 }}>
1307
+ <Controller
1308
+ name={`Tfilters.${index}.value.toValue`}
1309
+ control={control}
1310
+ render={({field}) => {
1311
+ const raw = field.value;
1312
+ let val = null;
1313
+ if (raw) {
1314
+ const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
1315
+ val = d.isValid() ? d : null;
1316
+ }
979
1317
 
980
- <Grid item size={Tfilters[index]?.fixed === true ? 6 : 3}>
981
- <Controller
982
- name={`Tfilters.${index}.value.toValue`}
983
- control={control}
984
- render={({field}) => {
985
- const raw = field.value;
986
- let val = null;
987
- if (raw) {
988
- const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
989
- val = d.isValid() ? d : null;
990
- }
1318
+ return (
1319
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
1320
+ <DatePicker
1321
+ {...field}
1322
+ value={val}
1323
+ onChange={(v) => field.onChange(v ? dayjs(v).endOf('day') : null)}
1324
+ slotProps={{
1325
+ field: {clearable: true},
991
1326
 
992
- return (
993
- <LocalizationProvider dateAdapter={AdapterDayjs}>
994
- <DatePicker
995
- {...field}
996
- value={val}
997
- onChange={(v) => field.onChange(v ? dayjs(v).endOf('day') : null)}
998
- renderInput={(params) => (
999
- <TextField
1000
- {...params}
1001
- fullWidth
1002
- label={(Tfilters[index]?.friendlyName ? `${Tfilters[index]?.friendlyName} - الى` : 'الى التاريخ')}
1003
- size="small"
1004
- variant="outlined"
1005
- />
1006
- )}
1007
- />
1008
- </LocalizationProvider>
1009
- );
1010
- }}
1011
- />
1012
- </Grid>
1013
- </>
1014
- )}
1327
+ textField: {
1328
+ fullWidth: true,
1329
+ label: (Tfilters[index]?.friendlyName ? `${Tfilters[index]?.friendlyName} - الى` : 'الى التاريخ'),
1330
+ size: 'small',
1331
+ variant: 'outlined'
1332
+ },
1333
+ }}
1334
+ />
1335
+ </LocalizationProvider>
1336
+ );
1337
+ }}
1338
+ />
1339
+ </Grid>
1340
+ </>
1341
+ )}
1015
1342
 
1016
- {Tfilters[index]?.localProperty === 'DateTime' && Tfilters[index]?.method !== 'isBetween' && (
1017
- <>
1018
- <Grid item size={Tfilters[index]?.fixed === true ? 12 : 5}>
1019
- <Controller
1020
- name={`Tfilters.${index}.value`}
1021
- control={control}
1022
- render={({field}) => {
1023
- // Normalize to a valid Dayjs or null. Do NOT wrap null/undefined which can re-populate old values.
1024
- const raw = field.value;
1025
- let dateValue = null;
1026
- if (raw) {
1027
- const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
1028
- dateValue = d.isValid() ? d : null;
1029
- }
1343
+ {Tfilters[index]?.localProperty === 'DateTime' && Tfilters[index]?.method !== 'isBetween' && (
1344
+ <>
1345
+ <Grid size={{ xs: Tfilters[index]?.fixed === true ? 12 : 5 }}>
1346
+ <Controller
1347
+ name={`Tfilters.${index}.value`}
1348
+ control={control}
1349
+ render={({field}) => {
1350
+ // Normalize to a valid Dayjs or null. Do NOT wrap null/undefined which can re-populate old values.
1351
+ const raw = field.value;
1352
+ let dateValue = null;
1353
+ if (raw) {
1354
+ const d = dayjs.isDayjs(raw) ? raw : dayjs(raw);
1355
+ dateValue = d.isValid() ? d : null;
1356
+ }
1030
1357
 
1031
- return (
1032
- <LocalizationProvider dateAdapter={AdapterDayjs}>
1033
- <DatePicker
1034
- {...field}
1035
- value={dateValue}
1036
- onChange={(newVal) => {
1037
- // When cleared, MUI passes null. Ensure we store null; if invalid, also null.
1038
- if (!newVal) {
1039
- field.onChange(null);
1040
- } else if (dayjs.isDayjs(newVal)) {
1041
- field.onChange(newVal.isValid() ? newVal : null);
1042
- } else {
1043
- const d = dayjs(newVal);
1044
- field.onChange(d.isValid() ? d : null);
1045
- }
1046
- }}
1047
- renderInput={(params) => (
1048
- <TextField
1049
- {...params}
1050
- fullWidth
1051
- label={(Tfilters[index]?.friendlyName || 'التاريخ')}
1052
- placeholder={(Tfilters[index]?.friendlyName || 'التاريخ')}
1053
- size="small"
1054
- variant="outlined"
1055
- />
1056
- )}
1057
- />
1058
- </LocalizationProvider>
1059
- );
1060
- }}
1061
- />
1062
- </Grid>
1063
- </>
1064
- )}
1065
-
1066
- {/*{Tfilters[index]?.fixed && (*/}
1067
- {/* <Grid item size={12} sx={{mt:'0px',pt:'0px'}}>*/}
1068
- {/* <Typography variant='caption' color='text.secondary'>*/}
1069
- {/* {(Tfilters[index]?.friendlyName || Tfilters[index]?.path || '') + (Tfilters[index]?.method ? ` • ${Tfilters[index]?.method}` : '')}*/}
1070
- {/* </Typography>*/}
1071
- {/* </Grid>*/}
1072
- {/*)}*/}
1073
-
1074
- <Grid item size={1} sx={{display: 'flex', alignItems: 'center', pb: 0}}>
1075
- {!Tfilters[index]?.fixed && (
1076
- <IconButton size='small' sx={{color: 'red'}} onClick={() => remove(index)}>
1077
- <TrashCanOutline fontSize='small'/>
1078
- </IconButton>
1358
+ return (
1359
+ <LocalizationProvider dateAdapter={AdapterDayjs}>
1360
+ <DatePicker
1361
+ {...field}
1362
+ value={dateValue}
1363
+ onChange={(newVal) => {
1364
+ // When cleared, MUI passes null. Ensure we store null; if invalid, also null.
1365
+ if (!newVal) {
1366
+ field.onChange(null);
1367
+ } else if (dayjs.isDayjs(newVal)) {
1368
+ field.onChange(newVal.isValid() ? newVal : null);
1369
+ } else {
1370
+ const d = dayjs(newVal);
1371
+ field.onChange(d.isValid() ? d : null);
1372
+ }
1373
+ }}
1374
+ slotProps={{
1375
+ field: {clearable: true},
1376
+ textField: {
1377
+ fullWidth: true,
1378
+ label: (Tfilters[index]?.friendlyName || 'التاريخ'),
1379
+ placeholder: (Tfilters[index]?.friendlyName || 'التاريخ'),
1380
+ size: 'small',
1381
+ variant: 'outlined',
1382
+ },
1383
+ }}
1384
+ />
1385
+ </LocalizationProvider>
1386
+ );
1387
+ }}
1388
+ />
1389
+ </Grid>
1390
+ </>
1079
1391
  )}
1392
+
1393
+ {/*{Tfilters[index]?.fixed && (*/}
1394
+ {/* <Grid sx={{mt:'0px',pt:'0px'}} size={{ xs: 12 }}>*/}
1395
+ {/* <Typography variant='caption' color='text.secondary'>*/}
1396
+ {/* {(Tfilters[index]?.friendlyName || Tfilters[index]?.path || '') + (Tfilters[index]?.method ? ` • ${Tfilters[index]?.method}` : '')}*/}
1397
+ {/* </Typography>*/}
1398
+ {/* </Grid>*/}
1399
+ {/*)}*/}
1400
+
1401
+ <Grid sx={{display: 'flex', alignItems: 'center', pb: 0}} size={{ xs: 1 }}>
1402
+ {!Tfilters[index]?.fixed && (
1403
+ <IconButton size='small' sx={{color: 'red'}} onClick={() => remove(index)}>
1404
+ <TrashCanOutline fontSize='small'/>
1405
+ </IconButton>
1406
+ )}
1407
+ </Grid>
1080
1408
  </Grid>
1081
- </Grid>
1082
- ))}
1409
+ )
1410
+ })}
1083
1411
 
1084
1412
  <IconButton
1085
1413
  sx={{marginTop: '10px'}}
@@ -1095,6 +1423,41 @@ const CustomFilterDialog = props => {
1095
1423
  <FilterPlus sx={{fontSize: '25px !important'}}/>
1096
1424
  </IconButton>
1097
1425
 
1426
+ {/* Custom Code Editor Section */}
1427
+ <Box sx={{mt: 3, mb: 2}}>
1428
+ <Button
1429
+ startIcon={<CodeBraces/>}
1430
+ variant="outlined"
1431
+ onClick={() => setShowCodeEditor(!showCodeEditor)}
1432
+ fullWidth
1433
+ >
1434
+ {showCodeEditor ? 'Hide' : 'Show'} Custom Filter Code
1435
+ </Button>
1436
+ <Collapse in={showCodeEditor}>
1437
+ <Box sx={{mt: 2, border: '1px solid', borderColor: 'divider', borderRadius: 1}} dir="ltr">
1438
+ <Box sx={{px: 2, py: 1, bgcolor: 'background.default', borderBottom: '1px solid', borderColor: 'divider', display: 'flex', alignItems: 'center', gap: 0.5}}>
1439
+ <Typography variant="subtitle2">Custom Filter Function</Typography>
1440
+ <HelpPopover type='customFilter' />
1441
+ </Box>
1442
+ <MonacoEditor
1443
+ height="300px"
1444
+ defaultLanguage="javascript"
1445
+ theme="vs-dark"
1446
+ value={customCode}
1447
+ onChange={(value) => setCustomCode(value || '')}
1448
+ options={{
1449
+ minimap: {enabled: false},
1450
+ fontSize: 14,
1451
+ lineNumbers: 'on',
1452
+ roundedSelection: false,
1453
+ scrollBeyondLastLine: false,
1454
+ automaticLayout: true,
1455
+ }}
1456
+ />
1457
+ </Box>
1458
+ </Collapse>
1459
+ </Box>
1460
+
1098
1461
  <DialogActions sx={{pb: {xs: 8}, justifyContent: 'center'}}>
1099
1462
  <Button type='submit' variant='contained' sx={{mr: 2}} disabled={IsSubmitting}>
1100
1463
  {IsSubmitting ? (