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.
- package/README.md +211 -0
- package/next.config.js +19 -48
- package/package.json +39 -85
- package/src/context/BuilderContext.jsx +134 -6
- package/src/context/SystemContext.js +2 -2
- package/src/hooks/useGlobalStore.js +36 -0
- package/src/hooks/useTimerEngine.js +54 -0
- package/src/lib/index.js +11 -3
- package/src/lib/layouts/BlankLayout.jsx +13 -0
- package/src/lib/providers/RoboByteFrontBuilderProvider.jsx +59 -1
- package/src/lib/themes/builderTheme.js +41 -0
- package/src/pages/_app.js +32 -134
- package/src/pages/api/ai.js +87 -0
- package/src/pages/builders/report/index.js +1 -0
- package/src/pages/builders/report/list/index.js +1 -0
- package/src/pages/builders/report/viewer/index.js +1 -0
- package/src/pages/index.js +88 -37
- package/src/pages/printBuilder/index.jsx +263 -0
- package/src/pages/printBuilder/layouts/index.jsx +298 -0
- package/src/pages/reportModule/reportBuilder/index.js +723 -563
- package/src/pages/reportModule/reportBuilder/reportViewer/index.js +137 -71
- package/src/pages/reportModule/reportBuilder/reports/index.js +51 -13
- package/src/pages/reportModule/reportBuilder/reportsPermissions/index.js +126 -0
- package/src/pages/viewBuilder/index.jsx +117 -32
- package/src/pages/viewBuilder/views/index.js +3 -3
- package/src/pages/viewer/[id]/index.js +2 -1
- package/src/services/DeleteService.js +31 -60
- package/src/services/Endpoints/PrintLayoutEndpoints.js +42 -0
- package/src/services/Endpoints.js +2 -0
- package/src/services/GetService.js +33 -54
- package/src/services/PatchService.js +38 -65
- package/src/services/PostService.js +37 -63
- package/src/services/UpdateService.js +39 -65
- package/src/services/builderHelper/actionExecutor.js +141 -25
- package/src/services/builderHelper/builderHelper.js +92 -0
- package/src/services/builderHelper/colorSchema.js +95 -0
- package/src/services/builderHelper/iconResolver.js +50 -0
- package/src/services/builderHelper/jsExecutor.js +212 -46
- package/src/services/builderHelper/nodeFactory.js +32 -15
- package/src/services/builderHelper/numberFormat.js +123 -0
- package/src/services/builderHelper/resolveProps.js +73 -4
- package/src/services/builderHelper/thresholdEngine.js +77 -0
- package/src/services/builderHelper/tree.js +31 -0
- package/src/services/components/agGridAutoComplete.js +5 -9
- package/src/services/config.js +9 -1
- package/src/services/globalStore.js +80 -0
- package/src/services/helper/multiSelectEditor.js +5 -9
- package/src/services/helper/multiSelectEditorByBuilder.js +241 -0
- package/src/services/helper/reportSessionHelper.js +83 -0
- package/src/services/reportData/fetchReportData.js +69 -28
- package/src/services/routerRef.js +35 -0
- package/src/views/ConfirmDialog.js +2 -2
- package/src/views/builder/JSEditor.js +105 -107
- package/src/views/builder/inspector/Inspector.jsx +6 -9
- package/src/views/builder/inspector/Tabs/ComponentActionsTab.jsx +7 -13
- package/src/views/builder/inspector/Tabs/MainTab.jsx +143 -25
- package/src/views/builder/inspector/Tabs/RulesTab.jsx +9 -24
- package/src/views/builder/inspector/Tabs/StyleTab.jsx +9 -24
- package/src/views/builder/inspector/definitions/autocomplete/main.js +4 -6
- package/src/views/builder/inspector/definitions/banner/actions.js +7 -0
- package/src/views/builder/inspector/definitions/banner/main.js +22 -0
- package/src/views/builder/inspector/definitions/banner/rules.js +1 -0
- package/src/views/builder/inspector/definitions/banner/style.js +1 -0
- package/src/views/builder/inspector/definitions/breadcrumb/main.js +43 -6
- package/src/views/builder/inspector/definitions/button/main.js +11 -12
- package/src/views/builder/inspector/definitions/button/style.js +18 -30
- package/src/views/builder/inspector/definitions/checkbox/actions.js +3 -1
- package/src/views/builder/inspector/definitions/checkbox/main.js +4 -6
- package/src/views/builder/inspector/definitions/common/main.js +13 -2
- package/src/views/builder/inspector/definitions/dataGrid/main.js +23 -0
- package/src/views/builder/inspector/definitions/dataTableViewer/main.js +46 -0
- package/src/views/builder/inspector/definitions/datepicker/actions.js +3 -1
- package/src/views/builder/inspector/definitions/datepicker/main.js +6 -14
- package/src/views/builder/inspector/definitions/dialog/main.js +36 -0
- package/src/views/builder/inspector/definitions/dropdown/main.js +5 -8
- package/src/views/builder/inspector/definitions/excelUpload/actions.js +23 -0
- package/src/views/builder/inspector/definitions/excelUpload/main.js +17 -0
- package/src/views/builder/inspector/definitions/excelUpload/rules.js +1 -0
- package/src/views/builder/inspector/definitions/excelUpload/style.js +45 -0
- package/src/views/builder/inspector/definitions/header/main.js +10 -1
- package/src/views/builder/inspector/definitions/index.js +106 -19
- package/src/views/builder/inspector/definitions/input/actions.js +4 -1
- package/src/views/builder/inspector/definitions/input/main.js +20 -11
- package/src/views/builder/inspector/definitions/kpi/avatarGroup.js +22 -0
- package/src/views/builder/inspector/definitions/kpi/badge.js +17 -0
- package/src/views/builder/inspector/definitions/kpi/bulletChart.js +47 -0
- package/src/views/builder/inspector/definitions/kpi/chart.js +55 -0
- package/src/views/builder/inspector/definitions/kpi/colorScale.js +60 -0
- package/src/views/builder/inspector/definitions/kpi/comparisonBars.js +41 -0
- package/src/views/builder/inspector/definitions/kpi/countdown.js +46 -0
- package/src/views/builder/inspector/definitions/kpi/donut.js +51 -0
- package/src/views/builder/inspector/definitions/kpi/funnel.js +25 -0
- package/src/views/builder/inspector/definitions/kpi/gauge.js +39 -0
- package/src/views/builder/inspector/definitions/kpi/heatmapGrid.js +96 -0
- package/src/views/builder/inspector/definitions/kpi/iconBox.js +20 -0
- package/src/views/builder/inspector/definitions/kpi/metric.js +45 -0
- package/src/views/builder/inspector/definitions/kpi/rating.js +27 -0
- package/src/views/builder/inspector/definitions/kpi/statusDot.js +18 -0
- package/src/views/builder/inspector/definitions/kpi/stepStage.js +65 -0
- package/src/views/builder/inspector/definitions/kpi/tagList.js +32 -0
- package/src/views/builder/inspector/definitions/kpi/timeline.js +80 -0
- package/src/views/builder/inspector/definitions/kpi/trend.js +20 -0
- package/src/views/builder/inspector/definitions/label/main.js +10 -1
- package/src/views/builder/inspector/definitions/layout/main.js +27 -3
- package/src/views/builder/inspector/definitions/number/main.js +6 -14
- package/src/views/builder/inspector/definitions/pageNumber/main.js +21 -0
- package/src/views/builder/inspector/definitions/popover/main.js +71 -0
- package/src/views/builder/inspector/definitions/radio/main.js +5 -8
- package/src/views/builder/inspector/definitions/repeater/main.js +31 -0
- package/src/views/builder/inspector/definitions/reportViewer/main.js +15 -1
- package/src/views/builder/inspector/definitions/richtext/main.js +5 -8
- package/src/views/builder/inspector/definitions/signature/main.js +4 -1
- package/src/views/builder/inspector/definitions/tag/main.js +5 -8
- package/src/views/builder/inspector/definitions/textarea/actions.js +4 -1
- package/src/views/builder/inspector/definitions/textarea/main.js +5 -7
- package/src/views/builder/inspector/definitions/time/main.js +5 -8
- package/src/views/builder/inspector/definitions/toggle/main.js +5 -19
- package/src/views/builder/inspector/definitions/treeView/main.js +61 -0
- package/src/views/builder/inspector/definitions/viewRenderer/main.js +53 -0
- package/src/views/builder/inspector/definitions/wizard/main.js +68 -0
- package/src/views/builder/inspector/definitions/wizard-step/main.js +25 -0
- package/src/views/builder/inspector/fields/ActionsConfigEditor.jsx +426 -0
- package/src/views/builder/inspector/fields/ColorSchemaField.jsx +140 -0
- package/src/views/builder/inspector/fields/ColumnFunctionEditor.jsx +238 -0
- package/src/views/builder/inspector/fields/ColumnMappingEditor.jsx +105 -0
- package/src/views/builder/inspector/fields/ColumnsConfigEditor.jsx +506 -0
- package/src/views/builder/inspector/fields/DonutRingsEditorField.jsx +337 -0
- package/src/views/builder/inspector/fields/ExtraColsEditor.jsx +618 -0
- package/src/views/builder/inspector/fields/FunctionHelpPopover.jsx +295 -0
- package/src/views/builder/inspector/fields/IconEditor.jsx +64 -0
- package/src/views/builder/inspector/fields/KpiActionField.jsx +223 -0
- package/src/views/builder/inspector/fields/MarkersEditorField.jsx +173 -0
- package/src/views/builder/inspector/fields/SelectEditor.jsx +9 -5
- package/src/views/builder/inspector/fields/SeriesEditorField.jsx +363 -0
- package/src/views/builder/inspector/fields/TableColumnsEditor.jsx +104 -0
- package/src/views/builder/inspector/fields/ThresholdsEditor.jsx +247 -0
- package/src/views/builder/inspector/fields/ValueFunctionsRefPanel.jsx +217 -0
- package/src/views/builder/inspector/fields/columnEditorShared.jsx +217 -0
- package/src/views/builder/sidebar/Sidebar.jsx +4 -2
- package/src/views/builder/sidebar/SidebarTabs.jsx +28 -17
- package/src/views/builder/sidebar/tabs/ActionsTab.jsx +7 -3
- package/src/views/builder/sidebar/tabs/AiTab/AiPreviewDialog.jsx +193 -0
- package/src/views/builder/sidebar/tabs/AiTab/aiProvider.js +49 -0
- package/src/views/builder/sidebar/tabs/AiTab/index.jsx +409 -0
- package/src/views/builder/sidebar/tabs/AiTab/schemaTransformer.js +102 -0
- package/src/views/builder/sidebar/tabs/AiTab/schemaValidator.js +64 -0
- package/src/views/builder/sidebar/tabs/AiTab/systemPrompt.js +1151 -0
- package/src/views/builder/sidebar/tabs/Components/ComponentsTab.jsx +31 -31
- package/src/views/builder/sidebar/tabs/Components/componentCatalog.js +43 -21
- package/src/views/builder/sidebar/tabs/Components/printComponentCatalog.js +81 -0
- package/src/views/builder/sidebar/tabs/TimersTab.jsx +338 -0
- package/src/views/builder/sidebar/tabs/TreeTab.jsx +13 -4
- package/src/views/builder/sidebar/tabs/ViewTab.jsx +1 -1
- package/src/views/builder/viewer/AdornedLabel.jsx +82 -0
- package/src/views/builder/viewer/ComponentRenderer.jsx +98 -24
- package/src/views/builder/viewer/DialogsZone.jsx +259 -0
- package/src/views/builder/viewer/FieldLabel.jsx +106 -0
- package/src/views/builder/viewer/PrintDialog.jsx +481 -0
- package/src/views/builder/viewer/ProductionViewer.jsx +80 -5
- package/src/views/builder/viewer/Viewer.jsx +106 -8
- package/src/views/builder/viewer/ViewerComponentWrapper.jsx +61 -4
- package/src/views/builder/viewer/ViewerToolbar.jsx +273 -59
- package/src/views/builder/viewer/renderers/AutoCompleteRenderer.jsx +26 -22
- package/src/views/builder/viewer/renderers/AvatarGroupRenderer.jsx +112 -0
- package/src/views/builder/viewer/renderers/BadgeRenderer.jsx +79 -0
- package/src/views/builder/viewer/renderers/BannerRenderer.jsx +62 -0
- package/src/views/builder/viewer/renderers/BreadcrumbRenderer.jsx +203 -15
- package/src/views/builder/viewer/renderers/BulletChartRenderer.jsx +147 -0
- package/src/views/builder/viewer/renderers/ButtonRenderer.jsx +98 -39
- package/src/views/builder/viewer/renderers/CardRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/ChartRenderer.jsx +388 -0
- package/src/views/builder/viewer/renderers/CheckboxRenderer.jsx +17 -9
- package/src/views/builder/viewer/renderers/ColorScaleRenderer.jsx +300 -0
- package/src/views/builder/viewer/renderers/ComparisonBarsRenderer.jsx +133 -0
- package/src/views/builder/viewer/renderers/ContainerRenderer.jsx +3 -1
- package/src/views/builder/viewer/renderers/CountdownRenderer.jsx +249 -0
- package/src/views/builder/viewer/renderers/DataGridRenderer.jsx +380 -0
- package/src/views/builder/viewer/renderers/DataTableViewerRenderer.jsx +240 -0
- package/src/views/builder/viewer/renderers/DatePickerRenderer.jsx +25 -24
- package/src/views/builder/viewer/renderers/DialogRenderer.jsx +327 -0
- package/src/views/builder/viewer/renderers/DividerRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/DonutRenderer.jsx +294 -0
- package/src/views/builder/viewer/renderers/DropdownRenderer.jsx +36 -44
- package/src/views/builder/viewer/renderers/ExcelUploadRenderer.jsx +639 -0
- package/src/views/builder/viewer/renderers/FunnelRenderer.jsx +93 -0
- package/src/views/builder/viewer/renderers/GaugeRenderer.jsx +159 -0
- package/src/views/builder/viewer/renderers/HeaderRenderer.jsx +31 -9
- package/src/views/builder/viewer/renderers/HeatmapGridRenderer.jsx +432 -0
- package/src/views/builder/viewer/renderers/IconBoxRenderer.jsx +59 -0
- package/src/views/builder/viewer/renderers/ImageRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/InputRenderer.jsx +75 -18
- package/src/views/builder/viewer/renderers/LabelRenderer.jsx +35 -9
- package/src/views/builder/viewer/renderers/LayoutCellRenderer.jsx +102 -40
- package/src/views/builder/viewer/renderers/LayoutContextMenu.jsx +8 -8
- package/src/views/builder/viewer/renderers/LayoutRenderer.jsx +48 -6
- package/src/views/builder/viewer/renderers/LinkRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/MenuRenderer.jsx +2 -2
- package/src/views/builder/viewer/renderers/MetricRenderer.jsx +80 -0
- package/src/views/builder/viewer/renderers/NumberFormatRenderer.jsx +21 -30
- package/src/views/builder/viewer/renderers/PageNumberRenderer.jsx +76 -0
- package/src/views/builder/viewer/renderers/PopoverRenderer.jsx +350 -0
- package/src/views/builder/viewer/renderers/ProgressCircleRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/ProgressLineRenderer.jsx +1 -1
- package/src/views/builder/viewer/renderers/RadioGroupRenderer.jsx +28 -39
- package/src/views/builder/viewer/renderers/RatingRenderer.jsx +80 -0
- package/src/views/builder/viewer/renderers/RepeaterRenderer.jsx +297 -38
- package/src/views/builder/viewer/renderers/ReportViewerRenderer.jsx +219 -5
- package/src/views/builder/viewer/renderers/RichTextRenderer.jsx +60 -66
- package/src/views/builder/viewer/renderers/RowActionsCell.jsx +308 -0
- package/src/views/builder/viewer/renderers/SignatureRenderer.jsx +33 -62
- package/src/views/builder/viewer/renderers/StatusDotRenderer.jsx +75 -0
- package/src/views/builder/viewer/renderers/StepStageRenderer.jsx +348 -0
- package/src/views/builder/viewer/renderers/TagListRenderer.jsx +115 -0
- package/src/views/builder/viewer/renderers/TagPickerRenderer.jsx +31 -45
- package/src/views/builder/viewer/renderers/TextAreaRenderer.jsx +25 -18
- package/src/views/builder/viewer/renderers/TextRenderer.jsx +7 -1
- package/src/views/builder/viewer/renderers/TimePickerRenderer.jsx +25 -24
- package/src/views/builder/viewer/renderers/TimelineRenderer.jsx +525 -0
- package/src/views/builder/viewer/renderers/ToggleRenderer.jsx +21 -27
- package/src/views/builder/viewer/renderers/TreeViewRenderer.jsx +832 -0
- package/src/views/builder/viewer/renderers/TrendRenderer.jsx +66 -0
- package/src/views/builder/viewer/renderers/ViewRendererRenderer.jsx +315 -0
- package/src/views/builder/viewer/renderers/WizardRenderer.jsx +380 -64
- package/src/views/builder/viewer/renderers/WizardStepRenderer.jsx +21 -12
- package/src/views/builder/viewer/renderers/dataGridComponents.jsx +824 -0
- package/src/views/customFilter/CustomFilterDialog.js +1023 -660
- package/src/views/customFilter/FixedFilterDialog.js +649 -0
- package/src/views/customFilter/SearchFilterDialog.js +248 -0
- package/src/views/genericTable/BuilderExpressionParams.js +3 -3
- package/src/views/genericTable/ColumnConfiguratorDialog.js +771 -0
- package/src/views/genericTable/FixedFilterDialog.js +3 -2
- package/src/views/genericTable/FormattingSettingsDialog.js +551 -0
- package/src/views/genericTable/ReportSettingsDialog.js +151 -0
- package/src/views/genericTable/SGrid.js +1061 -247
- package/src/views/genericTable/SearchFilterDialog.js +3 -2
- package/src/views/genericTable/TAGGrid.js +83 -69
- package/src/views/genericTable/cellEditors/autocompleteEditor.js +5 -9
- package/src/views/genericTable/convertStringFunctions.js +336 -0
- package/src/views/genericTable/statusBar/rowCountStatusBar.js +3 -1
- package/src/views/genericTable/updateRefHelpers.js +424 -0
- package/src/views/printBuilder/PrintBuilderViewer.jsx +607 -0
- package/src/views/printBuilder/PrintPreviewCanvas.jsx +157 -0
- package/src/views/rolePermissions/UpdateReportPermissionDialog.js +316 -0
- package/src/@core/components/auth/AclGuard.js +0 -55
- package/src/@core/components/auth/AuthGuard.js +0 -40
- package/src/@core/components/auth/GuestGuard.js +0 -30
- package/src/@core/components/custom-inputs/Horizontal.jsx +0 -143
- package/src/@core/components/custom-inputs/Image.jsx +0 -78
- package/src/@core/components/custom-inputs/Vertical.jsx +0 -113
- package/src/@core/components/customizer/index.jsx +0 -470
- package/src/@core/components/customizer/styles.module.css +0 -169
- package/src/@core/components/mui/Avatar.jsx +0 -41
- package/src/@core/components/mui/Badge.jsx +0 -20
- package/src/@core/components/mui/IconButton.jsx +0 -74
- package/src/@core/components/mui/TabList.jsx +0 -60
- package/src/@core/components/option-menu/index.jsx +0 -137
- package/src/@core/components/scroll-to-top/index.jsx +0 -43
- package/src/@core/components/spinner/index.js +0 -26
- package/src/@core/components/window-wrapper/index.js +0 -27
- package/src/@core/contexts/settingsContext.jsx +0 -98
- package/src/@core/hooks/useBgColor.js +0 -63
- package/src/@core/hooks/useImageVariant.js +0 -27
- package/src/@core/hooks/useLayoutInit.js +0 -37
- package/src/@core/hooks/useObjectCookie.js +0 -18
- package/src/@core/hooks/useSettings.jsx +0 -15
- package/src/@core/layouts/BlankLayout.js +0 -37
- package/src/@core/layouts/BlankLayoutWithAppBar.js +0 -51
- package/src/@core/layouts/HorizontalLayout.jsx +0 -151
- package/src/@core/layouts/Layout.js +0 -39
- package/src/@core/layouts/VerticalLayout.jsx +0 -124
- package/src/@core/layouts/components/blank-layout-with-appBar/index.js +0 -115
- package/src/@core/layouts/components/horizontal/app-bar-content/index.js +0 -67
- package/src/@core/layouts/components/horizontal/navigation/HorizontalNavGroup.js +0 -352
- package/src/@core/layouts/components/horizontal/navigation/HorizontalNavItems.js +0 -21
- package/src/@core/layouts/components/horizontal/navigation/HorizontalNavLink.js +0 -195
- package/src/@core/layouts/components/horizontal/navigation/index.js +0 -31
- package/src/@core/layouts/components/shared-components/LanguageDropdown.js +0 -96
- package/src/@core/layouts/components/shared-components/ModeToggler.js +0 -32
- package/src/@core/layouts/components/shared-components/NotificationDropdown.js +0 -226
- package/src/@core/layouts/components/shared-components/UserDropdown.js +0 -177
- package/src/@core/layouts/components/shared-components/footer/FooterContent.js +0 -46
- package/src/@core/layouts/components/shared-components/footer/index.js +0 -61
- package/src/@core/layouts/components/vertical/appBar/index.js +0 -74
- package/src/@core/layouts/components/vertical/navigation/Drawer.js +0 -122
- package/src/@core/layouts/components/vertical/navigation/VerticalNavGroup.js +0 -435
- package/src/@core/layouts/components/vertical/navigation/VerticalNavHeader.js +0 -180
- package/src/@core/layouts/components/vertical/navigation/VerticalNavItems.js +0 -26
- package/src/@core/layouts/components/vertical/navigation/VerticalNavLink.js +0 -258
- package/src/@core/layouts/components/vertical/navigation/VerticalNavSectionTitle.js +0 -102
- package/src/@core/layouts/components/vertical/navigation/index.js +0 -169
- package/src/@core/layouts/utils.js +0 -69
- package/src/@core/styles/Table.module.css +0 -93
- package/src/@core/styles/horizontal/menuItemStyles.js +0 -100
- package/src/@core/styles/horizontal/menuRootStyles.js +0 -19
- package/src/@core/styles/libs/fullcalendar/index.js +0 -461
- package/src/@core/styles/libs/keen-slider/index.js +0 -111
- package/src/@core/styles/libs/react-apexcharts/index.js +0 -107
- package/src/@core/styles/libs/react-cleave/index.js +0 -33
- package/src/@core/styles/libs/react-credit-cards/index.js +0 -11
- package/src/@core/styles/libs/react-datepicker/index.js +0 -388
- package/src/@core/styles/libs/react-draft-wysiwyg/index.js +0 -144
- package/src/@core/styles/libs/react-dropzone/index.js +0 -76
- package/src/@core/styles/libs/react-hot-toast/index.js +0 -37
- package/src/@core/styles/libs/recharts/index.js +0 -47
- package/src/@core/styles/stepper.js +0 -103
- package/src/@core/styles/vertical/menuItemStyles.js +0 -138
- package/src/@core/styles/vertical/menuSectionStyles.js +0 -54
- package/src/@core/styles/vertical/navigationCustomStyles.js +0 -62
- package/src/@core/svg/ContentCompact.jsx +0 -17
- package/src/@core/svg/ContentWide.jsx +0 -17
- package/src/@core/svg/DirectionLtr.jsx +0 -93
- package/src/@core/svg/DirectionRtl.jsx +0 -93
- package/src/@core/svg/LayoutCollapsed.jsx +0 -59
- package/src/@core/svg/LayoutHorizontal.jsx +0 -42
- package/src/@core/svg/LayoutVertical.jsx +0 -59
- package/src/@core/svg/Logo.jsx +0 -76
- package/src/@core/svg/SkinBordered.jsx +0 -54
- package/src/@core/svg/SkinDefault.jsx +0 -59
- package/src/@core/tailwind/plugin.js +0 -78
- package/src/@core/theme/ThemeComponent.js +0 -63
- package/src/@core/theme/ThemeOptions.js +0 -71
- package/src/@core/theme/breakpoints/index.js +0 -11
- package/src/@core/theme/colorSchemes.js +0 -326
- package/src/@core/theme/customShadows.js +0 -11
- package/src/@core/theme/globalStyles.js +0 -81
- package/src/@core/theme/index.js +0 -42
- package/src/@core/theme/overrides/accordion.js +0 -51
- package/src/@core/theme/overrides/accordion.jsx +0 -85
- package/src/@core/theme/overrides/alerts.js +0 -110
- package/src/@core/theme/overrides/alerts.jsx +0 -180
- package/src/@core/theme/overrides/autocomplete.js +0 -14
- package/src/@core/theme/overrides/autocomplete.jsx +0 -68
- package/src/@core/theme/overrides/avatar.js +0 -38
- package/src/@core/theme/overrides/avatars.js +0 -27
- package/src/@core/theme/overrides/backdrop.js +0 -22
- package/src/@core/theme/overrides/badges.js +0 -16
- package/src/@core/theme/overrides/breadcrumbs.js +0 -11
- package/src/@core/theme/overrides/button-group.js +0 -84
- package/src/@core/theme/overrides/button.js +0 -93
- package/src/@core/theme/overrides/buttonGroup.js +0 -9
- package/src/@core/theme/overrides/card.js +0 -83
- package/src/@core/theme/overrides/checkbox.jsx +0 -95
- package/src/@core/theme/overrides/chip.js +0 -72
- package/src/@core/theme/overrides/dataGrid.js +0 -114
- package/src/@core/theme/overrides/dateTimePicker.js +0 -65
- package/src/@core/theme/overrides/dialog.js +0 -120
- package/src/@core/theme/overrides/divider.js +0 -13
- package/src/@core/theme/overrides/drawer.js +0 -20
- package/src/@core/theme/overrides/fab.js +0 -13
- package/src/@core/theme/overrides/form-control-label.js +0 -19
- package/src/@core/theme/overrides/icon-button.js +0 -145
- package/src/@core/theme/overrides/index.js +0 -103
- package/src/@core/theme/overrides/input.js +0 -72
- package/src/@core/theme/overrides/link.js +0 -9
- package/src/@core/theme/overrides/list.js +0 -44
- package/src/@core/theme/overrides/menu.js +0 -25
- package/src/@core/theme/overrides/pagination.js +0 -41
- package/src/@core/theme/overrides/paper.js +0 -9
- package/src/@core/theme/overrides/popover.js +0 -16
- package/src/@core/theme/overrides/progress.js +0 -38
- package/src/@core/theme/overrides/radio.jsx +0 -80
- package/src/@core/theme/overrides/rating.js +0 -16
- package/src/@core/theme/overrides/rating.jsx +0 -32
- package/src/@core/theme/overrides/select.js +0 -19
- package/src/@core/theme/overrides/select.jsx +0 -52
- package/src/@core/theme/overrides/slider.js +0 -97
- package/src/@core/theme/overrides/snackbar.js +0 -19
- package/src/@core/theme/overrides/switch.js +0 -73
- package/src/@core/theme/overrides/switches.js +0 -25
- package/src/@core/theme/overrides/table-pagination.js +0 -39
- package/src/@core/theme/overrides/table.js +0 -81
- package/src/@core/theme/overrides/tabs.js +0 -30
- package/src/@core/theme/overrides/timeline.js +0 -80
- package/src/@core/theme/overrides/toggle-button.js +0 -33
- package/src/@core/theme/overrides/toggleButton.js +0 -16
- package/src/@core/theme/overrides/tooltip.js +0 -21
- package/src/@core/theme/overrides/typography.js +0 -13
- package/src/@core/theme/palette/index.js +0 -107
- package/src/@core/theme/shadows/index.js +0 -61
- package/src/@core/theme/shadows.js +0 -12
- package/src/@core/theme/spacing/index.js +0 -3
- package/src/@core/theme/spacing.js +0 -5
- package/src/@core/theme/typography/index.js +0 -65
- package/src/@core/theme/typography.js +0 -84
- package/src/@core/utils/create-emotion-cache.js +0 -5
- package/src/@core/utils/hex-to-rgba.js +0 -11
- package/src/@core/utils/serverHelpers.js +0 -45
- package/src/@menu/components/RouterLink.jsx +0 -18
- package/src/@menu/components/horizontal-menu/HorizontalNav.jsx +0 -88
- package/src/@menu/components/horizontal-menu/Menu.jsx +0 -83
- package/src/@menu/components/horizontal-menu/MenuButton.jsx +0 -100
- package/src/@menu/components/horizontal-menu/MenuItem.jsx +0 -183
- package/src/@menu/components/horizontal-menu/SubMenu.jsx +0 -418
- package/src/@menu/components/horizontal-menu/SubMenuContent.jsx +0 -41
- package/src/@menu/components/horizontal-menu/VerticalNavInHorizontal.jsx +0 -20
- package/src/@menu/components/vertical-menu/Menu.jsx +0 -161
- package/src/@menu/components/vertical-menu/MenuButton.jsx +0 -95
- package/src/@menu/components/vertical-menu/MenuItem.jsx +0 -180
- package/src/@menu/components/vertical-menu/MenuSection.jsx +0 -124
- package/src/@menu/components/vertical-menu/NavCollapseIcons.jsx +0 -70
- package/src/@menu/components/vertical-menu/NavHeader.jsx +0 -39
- package/src/@menu/components/vertical-menu/SubMenu.jsx +0 -420
- package/src/@menu/components/vertical-menu/SubMenuContent.jsx +0 -101
- package/src/@menu/components/vertical-menu/VerticalNav.jsx +0 -216
- package/src/@menu/contexts/horizontalNavContext.jsx +0 -29
- package/src/@menu/contexts/verticalNavContext.jsx +0 -65
- package/src/@menu/defaultConfigs.js +0 -12
- package/src/@menu/hooks/useHorizontalMenu.jsx +0 -19
- package/src/@menu/hooks/useHorizontalNav.jsx +0 -19
- package/src/@menu/hooks/useMediaQuery.jsx +0 -29
- package/src/@menu/hooks/useVerticalMenu.jsx +0 -19
- package/src/@menu/hooks/useVerticalNav.jsx +0 -19
- package/src/@menu/horizontal-menu/index.jsx +0 -8
- package/src/@menu/styles/StyledBackdrop.jsx +0 -15
- package/src/@menu/styles/StyledMenuIcon.jsx +0 -12
- package/src/@menu/styles/StyledMenuLabel.jsx +0 -16
- package/src/@menu/styles/StyledMenuPrefix.jsx +0 -10
- package/src/@menu/styles/StyledMenuSectionLabel.jsx +0 -21
- package/src/@menu/styles/StyledMenuSuffix.jsx +0 -10
- package/src/@menu/styles/StyledSubMenuContent.jsx +0 -43
- package/src/@menu/styles/horizontal/StyledHorizontalMenu.jsx +0 -13
- package/src/@menu/styles/horizontal/StyledHorizontalMenuItem.jsx +0 -26
- package/src/@menu/styles/horizontal/StyledHorizontalNav.jsx +0 -11
- package/src/@menu/styles/horizontal/StyledHorizontalNavExpandIcon.jsx +0 -33
- package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContent.jsx +0 -18
- package/src/@menu/styles/horizontal/StyledHorizontalSubMenuContentWrapper.jsx +0 -10
- package/src/@menu/styles/horizontal/horizontalUl.module.css +0 -15
- package/src/@menu/styles/styles.module.css +0 -5
- package/src/@menu/styles/vertical/StyledVerticalMenu.jsx +0 -16
- package/src/@menu/styles/vertical/StyledVerticalMenuItem.jsx +0 -28
- package/src/@menu/styles/vertical/StyledVerticalMenuSection.jsx +0 -23
- package/src/@menu/styles/vertical/StyledVerticalNav.jsx +0 -67
- package/src/@menu/styles/vertical/StyledVerticalNavBgColorContainer.jsx +0 -15
- package/src/@menu/styles/vertical/StyledVerticalNavContainer.jsx +0 -23
- package/src/@menu/styles/vertical/StyledVerticalNavExpandIcon.jsx +0 -25
- package/src/@menu/styles/vertical/verticalNavBgImage.module.css +0 -10
- package/src/@menu/svg/ChevronRight.jsx +0 -9
- package/src/@menu/svg/Close.jsx +0 -12
- package/src/@menu/svg/RadioCircle.jsx +0 -12
- package/src/@menu/svg/RadioCircleMarked.jsx +0 -13
- package/src/@menu/utils/menuClasses.js +0 -44
- package/src/@menu/utils/menuUtils.jsx +0 -145
- package/src/@menu/vertical-menu/index.jsx +0 -11
- package/src/configs/acl.js +0 -115
- package/src/configs/auth.js +0 -5
- package/src/configs/aws-exports.js +0 -30
- package/src/configs/firebase.js +0 -25
- package/src/configs/i18n.js +0 -34
- package/src/configs/primaryColorConfig.js +0 -35
- package/src/configs/themeConfig.js +0 -44
- package/src/layouts/UserLayout.js +0 -94
- package/src/layouts/UserThemeOptions.js +0 -191
- package/src/layouts/components/Direction.js +0 -30
- package/src/layouts/components/HtmlTooltip.js +0 -15
- package/src/layouts/components/Translations.js +0 -11
- package/src/layouts/components/UserDropdown.js +0 -217
- package/src/layouts/components/UserIcon.js +0 -40
- package/src/layouts/components/acl/Can.js +0 -6
- package/src/layouts/components/acl/CanViewNavGroup.js +0 -36
- package/src/layouts/components/acl/CanViewNavLink.js +0 -17
- package/src/layouts/components/acl/CanViewNavSectionTitle.js +0 -17
- package/src/layouts/components/horizontal/AppBarContent.js +0 -39
- package/src/layouts/components/horizontal/ServerSideNavItems.js +0 -44
- package/src/layouts/components/mui/StepperComps.js +0 -55
- package/src/layouts/components/vertical/AppBarContent.js +0 -35
- package/src/layouts/components/vertical/ServerSideNavItems.js +0 -44
- package/src/libs/ApexCharts.jsx +0 -5
- package/src/libs/ReactPlayer.jsx +0 -5
- package/src/libs/Recharts.jsx +0 -4
- package/src/libs/auth.js +0 -124
- package/src/libs/styles/AppFullCalendar.js +0 -505
- package/src/libs/styles/AppKeenSlider.js +0 -116
- package/src/libs/styles/AppReactApexCharts.jsx +0 -110
- package/src/libs/styles/AppReactDatepicker.jsx +0 -470
- package/src/libs/styles/AppReactDropzone.js +0 -76
- package/src/libs/styles/AppReactToastify.jsx +0 -108
- package/src/libs/styles/AppRecharts.js +0 -55
- package/src/libs/styles/inputOtp.module.css +0 -39
- package/src/libs/styles/tiptapEditor.css +0 -72
- package/src/navigation/horizontal/index.js +0 -246
- package/src/navigation/vertical/index.js +0 -253
- package/src/pages/401.js +0 -70
- package/src/pages/404.js +0 -67
- package/src/pages/500.js +0 -68
- package/src/pages/[slug].js +0 -115
- package/src/pages/_document.js +0 -72
- package/src/pages/api/navigation/regenerate-registry.js +0 -116
- package/src/pages/api/navigation/save.js +0 -218
- package/src/pages/authModule/acl/index.js +0 -48
- package/src/pages/authModule/forgot-password/index.js +0 -228
- package/src/pages/authModule/permissions/rolePermissions/[id]/rolePermissionsUser/index.js +0 -392
- package/src/pages/authModule/permissions/rolePermissions/index.js +0 -343
- package/src/pages/authModule/permissions/systemPermissions/index.js +0 -354
- package/src/pages/authModule/privacy/index.js +0 -721
- package/src/pages/authModule/users/index.js +0 -210
- package/src/pages/login/index.js +0 -328
- package/src/pages/mainHome/index.js +0 -181
- package/src/views/builder/inspector/definitions/cell/main.js +0 -4
- package/src/views/builder/inspector/definitions/column/main.js +0 -9
- package/src/views/builder/inspector/definitions/column-group/main.js +0 -18
- package/src/views/builder/inspector/definitions/header-cell/main.js +0 -5
- package/src/views/builder/inspector/definitions/table/main.js +0 -9
- package/src/views/builder/viewer/renderers/CellRenderer.jsx +0 -71
- package/src/views/builder/viewer/renderers/ColumnGroupRenderer.jsx +0 -96
- package/src/views/builder/viewer/renderers/ColumnRenderer.jsx +0 -71
- package/src/views/builder/viewer/renderers/HeaderCellRenderer.jsx +0 -78
- package/src/views/builder/viewer/renderers/TabRenderer.jsx +0 -82
- package/src/views/builder/viewer/renderers/TableRenderer.jsx +0 -92
- package/src/views/pages/auth/FooterIllustrationsV2.js +0 -40
- package/src/views/pages/misc/FooterIllustrations.js +0 -47
- package/src/views/pages/misc/muiTable/CustomPagination.js +0 -34
- package/src/views/pages/users/UserManageDialog.js +0 -283
- package/src/views/pages/users/UserViewPage.js +0 -199
- package/src/views/users/AddUserNameDialog.js +0 -162
- package/src/views/users/ContactManage.js +0 -449
- package/src/views/users/ResetPasswordDialog.js +0 -242
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import BlankLayout from
|
|
1
|
+
import BlankLayout from "../../../lib/layouts/BlankLayout";
|
|
2
2
|
import {
|
|
3
3
|
Autocomplete,
|
|
4
4
|
Box,
|
|
@@ -16,68 +16,73 @@ import {
|
|
|
16
16
|
Link,
|
|
17
17
|
Chip,
|
|
18
18
|
Button,
|
|
19
|
+
DialogActions,
|
|
20
|
+
MenuItem,
|
|
21
|
+
Select,
|
|
22
|
+
InputLabel,
|
|
23
|
+
FormControl,
|
|
24
|
+
DialogContent,
|
|
25
|
+
DialogTitle,
|
|
19
26
|
Dialog,
|
|
20
27
|
Tooltip,
|
|
21
|
-
Accordion,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
} from '@mui/material'
|
|
26
|
-
import { useEffect, useRef, useState } from 'react'
|
|
27
|
-
import { Endpoints, Services } from 'services/Endpoints'
|
|
28
|
+
Checkbox, Accordion, AccordionSummary, AccordionDetails, FormControlLabel,
|
|
29
|
+
} from '@mui/material';
|
|
30
|
+
import {useEffect, useRef, useState} from "react";
|
|
31
|
+
import {Endpoints, Services} from "services/Endpoints";
|
|
28
32
|
import {
|
|
29
33
|
AddBox,
|
|
34
|
+
ArrowBackOutlined,
|
|
30
35
|
ArrowForwardSharp,
|
|
31
36
|
AssessmentOutlined,
|
|
32
|
-
|
|
33
|
-
FilterAlt,
|
|
37
|
+
BackupOutlined,
|
|
38
|
+
Expand, FilterAlt, FilterBAndW, FilterVintageOutlined,
|
|
39
|
+
KeyboardReturnOutlined,
|
|
34
40
|
PreviewOutlined,
|
|
35
41
|
SaveAsOutlined,
|
|
36
|
-
SaveOutlined,
|
|
37
|
-
Search,
|
|
38
|
-
Visibility,
|
|
39
|
-
VisibilityOff,
|
|
40
|
-
Image as ImageIcon,
|
|
42
|
+
SaveOutlined, Search, Visibility, VisibilityOff, Image as ImageIcon,
|
|
41
43
|
CloudDownloadOutlined,
|
|
42
|
-
CloudUploadOutlined
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
import
|
|
47
|
-
import {
|
|
48
|
-
import
|
|
49
|
-
import
|
|
50
|
-
import
|
|
51
|
-
import
|
|
52
|
-
import
|
|
53
|
-
import
|
|
54
|
-
import
|
|
55
|
-
import
|
|
56
|
-
import
|
|
57
|
-
import
|
|
58
|
-
import
|
|
59
|
-
import
|
|
60
|
-
|
|
61
|
-
import
|
|
62
|
-
import
|
|
63
|
-
import
|
|
64
|
-
import
|
|
44
|
+
CloudUploadOutlined,
|
|
45
|
+
CheckCircleOutlined,
|
|
46
|
+
DeleteOutlined
|
|
47
|
+
} from "@mui/icons-material";
|
|
48
|
+
import dayjs from 'dayjs';
|
|
49
|
+
import {BackspaceOutline, Filter, PencilOutline} from "mdi-material-ui";
|
|
50
|
+
import SGrid from "views/genericTable/SGrid";
|
|
51
|
+
import {Controller, useForm} from "react-hook-form";
|
|
52
|
+
import ComputedTextEditor from "views/genericTable/RegexTextEditor";
|
|
53
|
+
import ExpressionEditor from "views/genericTable/RegexTextEditor";
|
|
54
|
+
import BuilderExpressionParams from "views/genericTable/BuilderExpressionParams";
|
|
55
|
+
import handleChange from "services/helper/handleChange";
|
|
56
|
+
import DynamicValueList from "views/genericTable/BuilderExpressionParams";
|
|
57
|
+
import SqlEditor from "views/genericTable/QueryEditor";
|
|
58
|
+
import Switch from "@mui/material/Switch";
|
|
59
|
+
import {EditorState} from "draft-js";
|
|
60
|
+
import PermissionsSubjects from "src/configs/Permissions/PermissionsSubjects.json";
|
|
61
|
+
import ReportBuilderSaveForm from "views/genericTable/ReportBuilderSaveDialog";
|
|
62
|
+
import {useRouter} from "next/router";
|
|
63
|
+
import CustomFilterDialog from "views/customFilter/CustomFilterDialog";
|
|
64
|
+
import FixedFilterDialog from "views/customFilter/FixedFilterDialog";
|
|
65
|
+
import RoutingSettingDialog from "views/genericTable/RoutingSettingDialog";
|
|
66
|
+
import FormattingSettingsDialog from "views/genericTable/FormattingSettingsDialog";
|
|
67
|
+
import ColumnConfiguratorDialog from "views/genericTable/ColumnConfiguratorDialog";
|
|
68
|
+
import ReportSettingsDialog from "views/genericTable/ReportSettingsDialog";
|
|
69
|
+
import {DragDropContext, Droppable, Draggable} from 'react-beautiful-dnd';
|
|
65
70
|
|
|
66
71
|
const ReportBuilder = () => {
|
|
67
|
-
const [models, setModels] = useState([])
|
|
68
|
-
const [modelFields, setModelFields] = useState([])
|
|
69
|
-
const [searchQuery, setSearchQuery] = useState('')
|
|
70
|
-
const [selectedCollection, setSelectedCollection] = useState()
|
|
71
|
-
const [editingHeaderPath, setEditingHeaderPath] = useState(null)
|
|
72
|
-
const [isLoading, setIsLoading] = useState(false)
|
|
72
|
+
const [models, setModels] = useState([]);
|
|
73
|
+
const [modelFields, setModelFields] = useState([]);
|
|
74
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
75
|
+
const [selectedCollection, setSelectedCollection] = useState();
|
|
76
|
+
const [editingHeaderPath, setEditingHeaderPath] = useState(null);
|
|
77
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
73
78
|
const router = useRouter()
|
|
74
|
-
const {
|
|
79
|
+
const {id} = router.query
|
|
75
80
|
const [builderMetadata, setBuilderMetadata] = useState({
|
|
76
81
|
id: 0,
|
|
77
82
|
name: '',
|
|
78
83
|
description: '',
|
|
79
|
-
isNew: true
|
|
80
|
-
})
|
|
84
|
+
isNew: true,
|
|
85
|
+
});
|
|
81
86
|
const [builderModel, setBuilderModel] = useState({
|
|
82
87
|
reportSource: null,
|
|
83
88
|
selectedFields: [],
|
|
@@ -85,14 +90,17 @@ const ReportBuilder = () => {
|
|
|
85
90
|
isRaw: false,
|
|
86
91
|
filter: {
|
|
87
92
|
Tfilter: [],
|
|
88
|
-
LocalTfilter: []
|
|
93
|
+
LocalTfilter: [],
|
|
89
94
|
},
|
|
90
95
|
searchFilter: [],
|
|
91
96
|
rawSql: '',
|
|
92
|
-
routingSettings: []
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
routingSettings: [],
|
|
98
|
+
settings: {
|
|
99
|
+
rowUniqueId: []
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const [breadcrumbs, setBreadcrumbs] = useState([]);
|
|
103
|
+
const [isPreview, setIsPreview] = useState(false);
|
|
96
104
|
const [openDialogs, setOpenDialogs] = useState({
|
|
97
105
|
expression: false,
|
|
98
106
|
params: false,
|
|
@@ -100,12 +108,19 @@ const ReportBuilder = () => {
|
|
|
100
108
|
filter: false,
|
|
101
109
|
searchFilter: false,
|
|
102
110
|
routing: false,
|
|
103
|
-
fixedFilter: false
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
fixedFilter: false,
|
|
112
|
+
formatting: false,
|
|
113
|
+
columnConfig: false,
|
|
114
|
+
settings: false
|
|
115
|
+
});
|
|
116
|
+
const [selectedRow, setSelectedRow] = useState(null);
|
|
117
|
+
const [columnConfigResult, setColumnConfigResult] = useState(null);
|
|
106
118
|
|
|
107
119
|
// File input ref for uploading builder model JSON
|
|
108
|
-
const fileInputRef = useRef(null)
|
|
120
|
+
const fileInputRef = useRef(null);
|
|
121
|
+
|
|
122
|
+
// UpdateRef for tracking field changes in the grid (array structure)
|
|
123
|
+
const updateRef = useRef([]);
|
|
109
124
|
|
|
110
125
|
// Download current builderModel as JSON file
|
|
111
126
|
const handleDownloadModel = () => {
|
|
@@ -113,121 +128,122 @@ const ReportBuilder = () => {
|
|
|
113
128
|
const replacer = (key, value) => {
|
|
114
129
|
// Convert Dayjs instances to Date so JSON.stringify uses ISO via toJSON
|
|
115
130
|
if (value && typeof value === 'object') {
|
|
116
|
-
if (dayjs.isDayjs(value)) return value.toDate()
|
|
117
|
-
if (value instanceof Date) return value // keep as Date
|
|
131
|
+
if (dayjs.isDayjs(value)) return value.toDate();
|
|
132
|
+
if (value instanceof Date) return value; // keep as Date
|
|
118
133
|
}
|
|
119
|
-
return value
|
|
120
|
-
}
|
|
121
|
-
const json = JSON.stringify(builderModel, replacer, 2)
|
|
122
|
-
const blob = new Blob([json], {
|
|
123
|
-
const url = URL.createObjectURL(blob)
|
|
124
|
-
const a = document.createElement('a')
|
|
125
|
-
const ts = new Date().toISOString().replace(/[:.]/g, '-')
|
|
126
|
-
a.href = url
|
|
127
|
-
a.download = `builderModel-${ts}.json
|
|
128
|
-
document.body.appendChild(a)
|
|
129
|
-
a.click()
|
|
130
|
-
document.body.removeChild(a)
|
|
131
|
-
URL.revokeObjectURL(url)
|
|
134
|
+
return value;
|
|
135
|
+
};
|
|
136
|
+
const json = JSON.stringify(builderModel, replacer, 2);
|
|
137
|
+
const blob = new Blob([json], {type: 'application/json'});
|
|
138
|
+
const url = URL.createObjectURL(blob);
|
|
139
|
+
const a = document.createElement('a');
|
|
140
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-');
|
|
141
|
+
a.href = url;
|
|
142
|
+
a.download = `builderModel-${ts}.json`;
|
|
143
|
+
document.body.appendChild(a);
|
|
144
|
+
a.click();
|
|
145
|
+
document.body.removeChild(a);
|
|
146
|
+
URL.revokeObjectURL(url);
|
|
132
147
|
} catch (err) {
|
|
133
|
-
console.error('Failed to download builder model:', err)
|
|
148
|
+
console.error('Failed to download builder model:', err);
|
|
134
149
|
}
|
|
135
|
-
}
|
|
150
|
+
};
|
|
136
151
|
|
|
137
152
|
// Trigger hidden file input
|
|
138
153
|
const handleUploadClick = () => {
|
|
139
154
|
try {
|
|
140
|
-
fileInputRef.current?.click()
|
|
155
|
+
fileInputRef.current?.click();
|
|
141
156
|
} catch (e) {
|
|
142
|
-
console.error(e)
|
|
157
|
+
console.error(e);
|
|
143
158
|
}
|
|
144
|
-
}
|
|
159
|
+
};
|
|
145
160
|
|
|
146
161
|
// Handle JSON file selection and load into builderModel
|
|
147
|
-
const handleFileChange = e => {
|
|
148
|
-
const file = e?.target?.files?.[0]
|
|
149
|
-
if (!file) return
|
|
150
|
-
const reader = new FileReader()
|
|
162
|
+
const handleFileChange = (e) => {
|
|
163
|
+
const file = e?.target?.files?.[0];
|
|
164
|
+
if (!file) return;
|
|
165
|
+
const reader = new FileReader();
|
|
151
166
|
reader.onload = () => {
|
|
152
167
|
try {
|
|
153
|
-
const text = reader.result || ''
|
|
154
|
-
const obj = JSON.parse(text)
|
|
168
|
+
const text = reader.result || '';
|
|
169
|
+
const obj = JSON.parse(text);
|
|
155
170
|
// Basic validation: ensure it's an object
|
|
156
171
|
if (obj && typeof obj === 'object') {
|
|
157
|
-
setBuilderModel(obj)
|
|
172
|
+
setBuilderModel(obj);
|
|
158
173
|
} else {
|
|
159
|
-
console.error('Uploaded file is not a valid builder model object')
|
|
174
|
+
console.error('Uploaded file is not a valid builder model object');
|
|
160
175
|
}
|
|
161
176
|
} catch (err) {
|
|
162
|
-
console.error('Failed to parse uploaded JSON:', err)
|
|
177
|
+
console.error('Failed to parse uploaded JSON:', err);
|
|
163
178
|
} finally {
|
|
164
|
-
if (e?.target) e.target.value = ''
|
|
179
|
+
if (e?.target) e.target.value = '';
|
|
165
180
|
}
|
|
166
|
-
}
|
|
167
|
-
reader.readAsText(file)
|
|
168
|
-
}
|
|
181
|
+
};
|
|
182
|
+
reader.readAsText(file);
|
|
183
|
+
};
|
|
169
184
|
|
|
170
|
-
const {
|
|
185
|
+
const {control, handleSubmit, reset} = useForm({
|
|
171
186
|
defaultValues: {
|
|
172
187
|
name: '',
|
|
173
188
|
type: '',
|
|
174
|
-
expression: ''
|
|
175
|
-
}
|
|
176
|
-
})
|
|
189
|
+
expression: '',
|
|
190
|
+
},
|
|
191
|
+
});
|
|
177
192
|
|
|
178
193
|
const handleToggleDialogs = dialog => {
|
|
179
194
|
handleChange(setOpenDialogs, dialog, !openDialogs[dialog])
|
|
180
195
|
}
|
|
181
196
|
|
|
182
|
-
const isInSearchFilter = fullPath
|
|
197
|
+
const isInSearchFilter = (fullPath) =>
|
|
198
|
+
(builderModel.searchFilter ?? []).some(f => f.fullPath === fullPath);
|
|
183
199
|
|
|
184
|
-
const toggleSearchFilterByFullPath = payload => {
|
|
200
|
+
const toggleSearchFilterByFullPath = (payload) => {
|
|
185
201
|
setBuilderModel(prev => {
|
|
186
|
-
const exists = (prev.searchFilter ?? []).some(f => f.fullPath === payload.fullPath)
|
|
202
|
+
const exists = (prev.searchFilter ?? []).some(f => f.fullPath === payload.fullPath);
|
|
187
203
|
const updated = exists
|
|
188
204
|
? prev.searchFilter.filter(f => f.fullPath !== payload.fullPath)
|
|
189
|
-
: [...(prev.searchFilter ?? []), payload]
|
|
205
|
+
: [...(prev.searchFilter ?? []), payload];
|
|
190
206
|
|
|
191
207
|
return {
|
|
192
208
|
...prev,
|
|
193
209
|
searchFilter: updated
|
|
194
|
-
}
|
|
195
|
-
})
|
|
196
|
-
}
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
};
|
|
197
213
|
|
|
198
214
|
const handleGetModels = async () => {
|
|
199
215
|
try {
|
|
200
|
-
setIsLoading(true)
|
|
201
|
-
const response = await Services.PostService(Endpoints.ReportBuilder.Post.GetModels, false, {})
|
|
216
|
+
setIsLoading(true);
|
|
217
|
+
const response = await Services.PostService(Endpoints.ReportBuilder.Post.GetModels, false, {});
|
|
202
218
|
if (response) {
|
|
203
|
-
setModels(response)
|
|
219
|
+
setModels(response);
|
|
204
220
|
}
|
|
205
221
|
} catch (error) {
|
|
206
|
-
console.error(error)
|
|
222
|
+
console.error(error);
|
|
207
223
|
} finally {
|
|
208
|
-
setIsLoading(false)
|
|
224
|
+
setIsLoading(false);
|
|
209
225
|
}
|
|
210
|
-
}
|
|
226
|
+
};
|
|
211
227
|
|
|
212
228
|
const handleGetFields = async (modelFullName, friendlyName = null, propertyType, isPrevious) => {
|
|
213
229
|
try {
|
|
214
|
-
setIsLoading(true)
|
|
230
|
+
setIsLoading(true);
|
|
215
231
|
const response = await Services.PostService(
|
|
216
232
|
Endpoints.ReportBuilder.Post.GetModelFields,
|
|
217
233
|
false,
|
|
218
234
|
{},
|
|
219
|
-
{
|
|
220
|
-
)
|
|
235
|
+
{modelFullName}
|
|
236
|
+
);
|
|
221
237
|
if (response) {
|
|
222
|
-
setModelFields(response.data)
|
|
223
|
-
const modelObject = models.find(m => m.fullName === modelFullName)
|
|
238
|
+
setModelFields(response.data);
|
|
239
|
+
const modelObject = models.find(m => m.fullName === modelFullName);
|
|
224
240
|
|
|
225
|
-
console.log(modelObject)
|
|
241
|
+
console.log(modelObject);
|
|
226
242
|
setBreadcrumbs(prev => {
|
|
227
|
-
const exists = prev.find(b => b.fullName === modelFullName)
|
|
243
|
+
const exists = prev.find(b => b.fullName === modelFullName);
|
|
228
244
|
if (exists && isPrevious) {
|
|
229
|
-
const index = prev.findIndex(b => b.fullName === modelFullName)
|
|
230
|
-
return prev.slice(0, index + 1)
|
|
245
|
+
const index = prev.findIndex(b => b.fullName === modelFullName);
|
|
246
|
+
return prev.slice(0, index + 1);
|
|
231
247
|
}
|
|
232
248
|
console.log(prev)
|
|
233
249
|
return [
|
|
@@ -235,69 +251,73 @@ const ReportBuilder = () => {
|
|
|
235
251
|
{
|
|
236
252
|
fullName: modelFullName,
|
|
237
253
|
friendlyName: friendlyName ?? modelObject?.friendlyName ?? modelFullName,
|
|
238
|
-
propertyType: propertyType ?? modelObject?.propertyType ?? null
|
|
239
|
-
}
|
|
240
|
-
]
|
|
241
|
-
})
|
|
254
|
+
propertyType: propertyType ?? modelObject?.propertyType ?? null,
|
|
255
|
+
},
|
|
256
|
+
];
|
|
257
|
+
});
|
|
242
258
|
}
|
|
243
259
|
} catch (error) {
|
|
244
|
-
console.error(error)
|
|
260
|
+
console.error(error);
|
|
245
261
|
} finally {
|
|
246
|
-
setIsLoading(false)
|
|
262
|
+
setIsLoading(false);
|
|
247
263
|
}
|
|
248
|
-
}
|
|
264
|
+
};
|
|
249
265
|
|
|
250
266
|
// 1) Trim a full field‐path for *leaf* fields:
|
|
251
|
-
|
|
252
|
-
|
|
267
|
+
// • always drop the root segment
|
|
268
|
+
// • if there are any collections, drop everything up through the *last* collection
|
|
253
269
|
const getLeafTrimmedPath = (fullPath, collectionBreadcrumbs) => {
|
|
254
|
-
const parts = fullPath.split('.')
|
|
255
|
-
const afterRoot = parts.slice(1)
|
|
270
|
+
const parts = fullPath.split('.');
|
|
271
|
+
const afterRoot = parts.slice(1);
|
|
256
272
|
if (!collectionBreadcrumbs.length) {
|
|
257
|
-
return afterRoot.join('.')
|
|
273
|
+
return afterRoot.join('.');
|
|
258
274
|
}
|
|
259
|
-
const lastColl = collectionBreadcrumbs[collectionBreadcrumbs.length - 1].friendlyName
|
|
260
|
-
const idx = afterRoot.lastIndexOf(lastColl)
|
|
261
|
-
return idx >= 0
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
275
|
+
const lastColl = collectionBreadcrumbs[collectionBreadcrumbs.length - 1].friendlyName;
|
|
276
|
+
const idx = afterRoot.lastIndexOf(lastColl);
|
|
277
|
+
return idx >= 0
|
|
278
|
+
? afterRoot.slice(idx + 1).join('.')
|
|
279
|
+
: afterRoot.join('.');
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
// 2) Trim a *collection* node’s path:
|
|
283
|
+
// • drop the root segment
|
|
284
|
+
// • then drop *exactly* the first collection (if present), keep everything else
|
|
267
285
|
const getCollectionTrimmedPath = (fullCollectionPath, collectionBreadcrumbs) => {
|
|
268
|
-
const parts = fullCollectionPath.split('.')
|
|
269
|
-
const afterRoot = parts.slice(1)
|
|
286
|
+
const parts = fullCollectionPath.split('.');
|
|
287
|
+
const afterRoot = parts.slice(1);
|
|
270
288
|
if (!collectionBreadcrumbs.length) {
|
|
271
|
-
return afterRoot.join('.')
|
|
289
|
+
return afterRoot.join('.');
|
|
272
290
|
}
|
|
273
|
-
const firstColl = collectionBreadcrumbs[0].friendlyName
|
|
291
|
+
const firstColl = collectionBreadcrumbs[0].friendlyName;
|
|
274
292
|
// if the very first segment after root is our first collection, drop it
|
|
275
293
|
if (afterRoot[0] === firstColl) {
|
|
276
|
-
const rest = afterRoot.slice(1)
|
|
294
|
+
const rest = afterRoot.slice(1);
|
|
277
295
|
// if that was the only segment, fall back to the collection name
|
|
278
|
-
return rest.length ? rest.join('.') : firstColl
|
|
296
|
+
return rest.length ? rest.join('.') : firstColl;
|
|
279
297
|
}
|
|
280
|
-
return afterRoot.join('.')
|
|
281
|
-
}
|
|
298
|
+
return afterRoot.join('.');
|
|
299
|
+
};
|
|
282
300
|
|
|
283
|
-
const handleAddStaticField = field => {
|
|
301
|
+
const handleAddStaticField = (field) => {
|
|
284
302
|
console.log(builderModel.selectedFields)
|
|
285
303
|
// build fullPath & identify collection crumbs
|
|
286
|
-
const fullPathParts = [
|
|
287
|
-
|
|
304
|
+
const fullPathParts = [
|
|
305
|
+
...breadcrumbs.map(b => b.friendlyName),
|
|
306
|
+
field.friendlyName
|
|
307
|
+
];
|
|
308
|
+
const fullPath = fullPathParts.join('.');
|
|
288
309
|
const collectionBreadcrumbs = breadcrumbs
|
|
289
310
|
.map((b, i) => ({
|
|
290
311
|
...b,
|
|
291
|
-
fullPath: breadcrumbs
|
|
292
|
-
.slice(0, i + 1)
|
|
312
|
+
fullPath: breadcrumbs.slice(0, i + 1)
|
|
293
313
|
.map(x => x.friendlyName)
|
|
294
314
|
.join('.')
|
|
295
315
|
}))
|
|
296
|
-
.filter(b => b.propertyType === 'Collection')
|
|
316
|
+
.filter(b => b.propertyType === 'Collection');
|
|
297
317
|
|
|
298
318
|
// compute leaf path & header
|
|
299
|
-
const trimmedPath = getLeafTrimmedPath(fullPath, collectionBreadcrumbs)
|
|
300
|
-
const headerName = trimmedPath.replace(/\./g, '_')
|
|
319
|
+
const trimmedPath = getLeafTrimmedPath(fullPath, collectionBreadcrumbs);
|
|
320
|
+
const headerName = trimmedPath.replace(/\./g, '_');
|
|
301
321
|
console.log(field)
|
|
302
322
|
const newLeafField = {
|
|
303
323
|
fullPath: fullPath,
|
|
@@ -309,19 +329,21 @@ const ReportBuilder = () => {
|
|
|
309
329
|
propertyType: field.propertyType,
|
|
310
330
|
enumName: field.enumName,
|
|
311
331
|
hidden: false,
|
|
312
|
-
image: false
|
|
313
|
-
}
|
|
332
|
+
image: false,
|
|
333
|
+
};
|
|
314
334
|
|
|
315
335
|
setBuilderModel(prev => {
|
|
316
|
-
const clone = [...prev.selectedFields]
|
|
336
|
+
const clone = [...prev.selectedFields];
|
|
317
337
|
|
|
318
338
|
const insertIntoCollectionsOnly = (nodes, crumbs, depth = 0) => {
|
|
319
|
-
const crumb = crumbs[depth]
|
|
320
|
-
const collFull = crumb.fullPath
|
|
321
|
-
const collTrimmed = getCollectionTrimmedPath(collFull, crumbs)
|
|
322
|
-
const collHeader = collTrimmed.replace(/\./g, '_')
|
|
323
|
-
|
|
324
|
-
let node = nodes.find(n =>
|
|
339
|
+
const crumb = crumbs[depth];
|
|
340
|
+
const collFull = crumb.fullPath;
|
|
341
|
+
const collTrimmed = getCollectionTrimmedPath(collFull, crumbs);
|
|
342
|
+
const collHeader = collTrimmed.replace(/\./g, '_');
|
|
343
|
+
|
|
344
|
+
let node = nodes.find(n =>
|
|
345
|
+
n.propertyType === 'Collection' && n.path === collTrimmed
|
|
346
|
+
);
|
|
325
347
|
if (!node) {
|
|
326
348
|
node = {
|
|
327
349
|
fullPath: fullPath,
|
|
@@ -329,33 +351,34 @@ const ReportBuilder = () => {
|
|
|
329
351
|
headerName: collHeader,
|
|
330
352
|
propertyType: 'Collection',
|
|
331
353
|
children: []
|
|
332
|
-
}
|
|
333
|
-
nodes.push(node)
|
|
354
|
+
};
|
|
355
|
+
nodes.push(node);
|
|
334
356
|
}
|
|
335
357
|
|
|
336
|
-
const isLast = depth === crumbs.length - 1
|
|
358
|
+
const isLast = depth === crumbs.length - 1;
|
|
337
359
|
if (isLast) {
|
|
338
360
|
if (!node.children.some(f => f.path === trimmedPath)) {
|
|
339
|
-
node.children.push(newLeafField)
|
|
361
|
+
node.children.push(newLeafField);
|
|
340
362
|
}
|
|
341
363
|
} else {
|
|
342
|
-
insertIntoCollectionsOnly(node.children, crumbs, depth + 1)
|
|
364
|
+
insertIntoCollectionsOnly(node.children, crumbs, depth + 1);
|
|
343
365
|
}
|
|
344
|
-
}
|
|
366
|
+
};
|
|
345
367
|
|
|
346
368
|
if (!collectionBreadcrumbs.length) {
|
|
347
369
|
// no collections ⇒ flat insert
|
|
348
370
|
if (!clone.some(f => f.path === trimmedPath)) {
|
|
349
|
-
return {
|
|
371
|
+
return {...prev, selectedFields: [...clone, newLeafField]};
|
|
350
372
|
}
|
|
351
|
-
return prev
|
|
373
|
+
return prev;
|
|
352
374
|
}
|
|
353
375
|
|
|
354
376
|
// otherwise build the nested collection node(s)
|
|
355
|
-
insertIntoCollectionsOnly(clone, collectionBreadcrumbs)
|
|
356
|
-
return {
|
|
357
|
-
})
|
|
358
|
-
}
|
|
377
|
+
insertIntoCollectionsOnly(clone, collectionBreadcrumbs);
|
|
378
|
+
return {...prev, selectedFields: clone};
|
|
379
|
+
});
|
|
380
|
+
};
|
|
381
|
+
|
|
359
382
|
|
|
360
383
|
// (1) Helper: insert a node into the right collection, by `collectionPath`
|
|
361
384
|
function insertIntoCollection(nodes, collectionPath, newField) {
|
|
@@ -366,19 +389,19 @@ const ReportBuilder = () => {
|
|
|
366
389
|
return {
|
|
367
390
|
...node,
|
|
368
391
|
children: [...(node.children || []), newField]
|
|
369
|
-
}
|
|
392
|
+
};
|
|
370
393
|
}
|
|
371
394
|
// otherwise recurse
|
|
372
395
|
return {
|
|
373
396
|
...node,
|
|
374
397
|
children: insertIntoCollection(node.children || [], collectionPath, newField)
|
|
375
|
-
}
|
|
398
|
+
};
|
|
376
399
|
}
|
|
377
|
-
return node
|
|
378
|
-
})
|
|
400
|
+
return node;
|
|
401
|
+
});
|
|
379
402
|
}
|
|
380
403
|
|
|
381
|
-
|
|
404
|
+
// (2) Add computed field — either top‐level or inside the selectedCollection
|
|
382
405
|
const handleAddComputedField = (expression, headerName, propertyType, title) => {
|
|
383
406
|
const newField = {
|
|
384
407
|
path: headerName,
|
|
@@ -388,221 +411,230 @@ const ReportBuilder = () => {
|
|
|
388
411
|
expression,
|
|
389
412
|
title,
|
|
390
413
|
hidden: false,
|
|
391
|
-
image: false
|
|
392
|
-
}
|
|
414
|
+
image: false,
|
|
415
|
+
};
|
|
393
416
|
|
|
394
417
|
setBuilderModel(prev => {
|
|
395
|
-
const {
|
|
418
|
+
const {selectedFields} = prev;
|
|
396
419
|
// if no collection selected, append at root
|
|
397
420
|
if (!selectedCollection) {
|
|
398
421
|
return {
|
|
399
422
|
...prev,
|
|
400
423
|
selectedFields: [...selectedFields, newField]
|
|
401
|
-
}
|
|
424
|
+
};
|
|
402
425
|
}
|
|
403
426
|
// otherwise insert under the chosen collection
|
|
404
|
-
const updated = insertIntoCollection(
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
427
|
+
const updated = insertIntoCollection(
|
|
428
|
+
selectedFields,
|
|
429
|
+
selectedCollection.path,
|
|
430
|
+
newField
|
|
431
|
+
);
|
|
432
|
+
return {...prev, selectedFields: updated};
|
|
433
|
+
});
|
|
434
|
+
setSelectedCollection(null);
|
|
435
|
+
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// (3) Update computed field — likewise drill into the right spot
|
|
439
|
+
const handleUpdateComputedField = (
|
|
440
|
+
oldHeaderName,
|
|
441
|
+
expression,
|
|
442
|
+
headerName,
|
|
443
|
+
propertyType,
|
|
444
|
+
title
|
|
445
|
+
) => {
|
|
412
446
|
setBuilderModel(prev => {
|
|
413
447
|
const updateNode = node => {
|
|
414
448
|
if (node.type === 'computed' && node.headerName === oldHeaderName) {
|
|
415
|
-
return {
|
|
449
|
+
return {...node, headerName, expression, propertyType, title, path: headerName};
|
|
416
450
|
}
|
|
417
451
|
if (node.propertyType === 'Collection') {
|
|
418
452
|
return {
|
|
419
453
|
...node,
|
|
420
454
|
children: (node.children || []).map(updateNode)
|
|
421
|
-
}
|
|
455
|
+
};
|
|
422
456
|
}
|
|
423
|
-
return node
|
|
424
|
-
}
|
|
457
|
+
return node;
|
|
458
|
+
};
|
|
425
459
|
|
|
426
460
|
return {
|
|
427
461
|
...prev,
|
|
428
462
|
selectedFields: prev.selectedFields.map(updateNode)
|
|
429
|
-
}
|
|
430
|
-
})
|
|
431
|
-
setSelectedCollection(null)
|
|
432
|
-
|
|
463
|
+
};
|
|
464
|
+
});
|
|
465
|
+
setSelectedCollection(null);
|
|
466
|
+
|
|
467
|
+
};
|
|
468
|
+
|
|
433
469
|
|
|
434
470
|
function removeFieldByPath(fields, pathToRemove) {
|
|
435
471
|
return fields.reduce((acc, f) => {
|
|
436
472
|
if (f.propertyType === 'Collection') {
|
|
437
473
|
// first, recurse into its children
|
|
438
|
-
const filteredChildren = removeFieldByPath(f.children || [], pathToRemove)
|
|
474
|
+
const filteredChildren = removeFieldByPath(f.children || [], pathToRemove);
|
|
439
475
|
// only keep this collection if it still has children
|
|
440
476
|
if (filteredChildren.length > 0) {
|
|
441
|
-
acc.push({
|
|
477
|
+
acc.push({...f, children: filteredChildren});
|
|
442
478
|
}
|
|
443
479
|
} else {
|
|
444
480
|
// leaf field: only keep it if paths don't match
|
|
445
481
|
if (f.path !== pathToRemove) {
|
|
446
|
-
acc.push(f)
|
|
482
|
+
acc.push(f);
|
|
447
483
|
}
|
|
448
484
|
}
|
|
449
|
-
return acc
|
|
450
|
-
}, [])
|
|
485
|
+
return acc;
|
|
486
|
+
}, []);
|
|
451
487
|
}
|
|
452
488
|
|
|
453
489
|
function handleFilterChange(field, value) {
|
|
454
|
-
console.log(field, value)
|
|
490
|
+
console.log(field, value);
|
|
455
491
|
setBuilderModel(prev => ({
|
|
456
492
|
...prev,
|
|
457
493
|
filter: {
|
|
458
494
|
...prev.filter,
|
|
459
|
-
[field]: value
|
|
460
|
-
}
|
|
461
|
-
}))
|
|
495
|
+
[field]: value, // <-- computed key on the nested object
|
|
496
|
+
},
|
|
497
|
+
}));
|
|
462
498
|
}
|
|
463
499
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (
|
|
468
|
-
|
|
500
|
+
|
|
501
|
+
const handleDragEnd = (result) => {
|
|
502
|
+
const {source, destination} = result || {};
|
|
503
|
+
if (!destination) return;
|
|
504
|
+
if (source.droppableId !== destination.droppableId) return;
|
|
505
|
+
const droppableId = source.droppableId;
|
|
469
506
|
|
|
470
507
|
setBuilderModel(prev => {
|
|
471
508
|
const reorderLeaves = (arr, from, to) => {
|
|
472
|
-
const leaves = arr.filter(n => !n.children)
|
|
473
|
-
const collections = arr.filter(n => n.children)
|
|
474
|
-
if (from < 0 || to < 0 || from >= leaves.length || to >= leaves.length) return arr
|
|
475
|
-
const leafMap = Object.fromEntries(leaves.map(n => [n.path, n]))
|
|
476
|
-
const order = leaves.map(n => n.path)
|
|
477
|
-
const [moved] = order.splice(from, 1)
|
|
478
|
-
order.splice(to, 0, moved)
|
|
479
|
-
const orderQueue = order.slice()
|
|
509
|
+
const leaves = arr.filter(n => !n.children);
|
|
510
|
+
const collections = arr.filter(n => n.children);
|
|
511
|
+
if (from < 0 || to < 0 || from >= leaves.length || to >= leaves.length) return arr;
|
|
512
|
+
const leafMap = Object.fromEntries(leaves.map(n => [n.path, n]));
|
|
513
|
+
const order = leaves.map(n => n.path);
|
|
514
|
+
const [moved] = order.splice(from, 1);
|
|
515
|
+
order.splice(to, 0, moved);
|
|
516
|
+
const orderQueue = order.slice();
|
|
480
517
|
// rebuild original array: keep collections in place, leaves in new order
|
|
481
518
|
return arr.map(node => {
|
|
482
|
-
if (node.children) return node
|
|
483
|
-
const nextPath = orderQueue.shift()
|
|
484
|
-
return leafMap[nextPath] || node
|
|
485
|
-
})
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
const updateCollections = nodes =>
|
|
489
|
-
|
|
490
|
-
if (n.
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
return { ...n, children: newChildren }
|
|
494
|
-
}
|
|
495
|
-
return { ...n, children: updateCollections(n.children || []) }
|
|
519
|
+
if (node.children) return node;
|
|
520
|
+
const nextPath = orderQueue.shift();
|
|
521
|
+
return leafMap[nextPath] || node;
|
|
522
|
+
});
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
const updateCollections = (nodes) => nodes.map(n => {
|
|
526
|
+
if (n.propertyType === 'Collection') {
|
|
527
|
+
if (n.path === droppableId) {
|
|
528
|
+
const newChildren = reorderLeaves(n.children || [], source.index, destination.index);
|
|
529
|
+
return {...n, children: newChildren};
|
|
496
530
|
}
|
|
497
|
-
return n
|
|
498
|
-
}
|
|
531
|
+
return {...n, children: updateCollections(n.children || [])};
|
|
532
|
+
}
|
|
533
|
+
return n;
|
|
534
|
+
});
|
|
499
535
|
|
|
500
536
|
if (droppableId === 'root') {
|
|
501
|
-
return {
|
|
537
|
+
return {...prev, selectedFields: reorderLeaves(prev.selectedFields, source.index, destination.index)};
|
|
502
538
|
} else {
|
|
503
|
-
return {
|
|
539
|
+
return {...prev, selectedFields: updateCollections(prev.selectedFields)};
|
|
504
540
|
}
|
|
505
|
-
})
|
|
506
|
-
}
|
|
541
|
+
});
|
|
542
|
+
};
|
|
507
543
|
|
|
508
544
|
const renderSelectedFields = (nodes, level = 0, droppableId = 'root') => {
|
|
509
545
|
// Count leaf-only index for Draggable indices
|
|
510
|
-
let leafIndexCounter = 0
|
|
546
|
+
let leafIndexCounter = 0;
|
|
511
547
|
return (
|
|
512
548
|
<Droppable droppableId={droppableId}>
|
|
513
|
-
{provided => (
|
|
514
|
-
<List dense disablePadding sx={{
|
|
515
|
-
{nodes.map(item =>
|
|
549
|
+
{(provided) => (
|
|
550
|
+
<List dense disablePadding sx={{pl: level * 2}} ref={provided.innerRef} {...provided.droppableProps}>
|
|
551
|
+
{nodes.map((item) => (
|
|
516
552
|
item.children ? (
|
|
517
|
-
<Accordion key={item.headerName} disableGutters sx={{
|
|
518
|
-
<AccordionSummary expandIcon={<Expand
|
|
553
|
+
<Accordion key={item.headerName} disableGutters sx={{mb: 1}}>
|
|
554
|
+
<AccordionSummary expandIcon={<Expand/>}>
|
|
519
555
|
<Box
|
|
520
556
|
sx={{
|
|
521
557
|
display: 'flex',
|
|
522
558
|
alignItems: 'center',
|
|
523
559
|
justifyContent: 'space-between',
|
|
524
|
-
width: '100%'
|
|
560
|
+
width: '100%',
|
|
525
561
|
}}
|
|
526
562
|
>
|
|
527
|
-
<Typography variant=
|
|
563
|
+
<Typography variant="subtitle2" fontWeight="bold">
|
|
528
564
|
{item.headerName ?? item.path}
|
|
529
565
|
</Typography>
|
|
530
566
|
<IconButton
|
|
531
|
-
size=
|
|
532
|
-
onClick={e => {
|
|
533
|
-
e.stopPropagation()
|
|
534
|
-
setSelectedCollection(item)
|
|
535
|
-
setSelectedRow(null)
|
|
536
|
-
setOpenDialogs(prev => ({
|
|
567
|
+
size="small"
|
|
568
|
+
onClick={(e) => {
|
|
569
|
+
e.stopPropagation();
|
|
570
|
+
setSelectedCollection(item);
|
|
571
|
+
setSelectedRow(null);
|
|
572
|
+
setOpenDialogs(prev => ({...prev, expression: true}));
|
|
537
573
|
}}
|
|
538
|
-
title=
|
|
574
|
+
title="Add computed field to this collection"
|
|
539
575
|
>
|
|
540
|
-
<AddBox fontSize=
|
|
576
|
+
<AddBox fontSize="small"/>
|
|
541
577
|
</IconButton>
|
|
542
578
|
</Box>
|
|
543
579
|
</AccordionSummary>
|
|
544
|
-
<AccordionDetails>
|
|
580
|
+
<AccordionDetails>
|
|
581
|
+
{renderSelectedFields(item.children, level + 1, item.path)}
|
|
582
|
+
</AccordionDetails>
|
|
545
583
|
</Accordion>
|
|
546
584
|
) : (
|
|
547
|
-
<Draggable
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
index={leafIndexCounter++}
|
|
551
|
-
>
|
|
552
|
-
{providedDrag => (
|
|
585
|
+
<Draggable key={`${droppableId}::${item.path}`} draggableId={`${droppableId}::${item.path}`}
|
|
586
|
+
index={leafIndexCounter++}>
|
|
587
|
+
{(providedDrag) => (
|
|
553
588
|
<ListItem
|
|
554
|
-
ref={providedDrag.innerRef}
|
|
555
|
-
|
|
556
|
-
{...providedDrag.dragHandleProps}
|
|
557
|
-
divider
|
|
558
|
-
>
|
|
589
|
+
ref={providedDrag.innerRef} {...providedDrag.draggableProps} {...providedDrag.dragHandleProps}
|
|
590
|
+
divider>
|
|
559
591
|
<ListItemText
|
|
560
592
|
primary={
|
|
561
593
|
editingHeaderPath === item.path ? (
|
|
562
594
|
<TextField
|
|
563
|
-
size=
|
|
595
|
+
size="small"
|
|
564
596
|
autoFocus
|
|
565
|
-
variant=
|
|
597
|
+
variant="standard"
|
|
566
598
|
value={item.title}
|
|
567
|
-
onChange={e => {
|
|
568
|
-
const newHeaderName = e.target.value
|
|
599
|
+
onChange={(e) => {
|
|
600
|
+
const newHeaderName = e.target.value;
|
|
569
601
|
|
|
570
602
|
setBuilderModel(prev => {
|
|
571
|
-
const updateNode = node => {
|
|
603
|
+
const updateNode = (node) => {
|
|
572
604
|
if (node.path === item.path && !node.children) {
|
|
573
|
-
return {
|
|
605
|
+
return {...node, title: newHeaderName};
|
|
574
606
|
}
|
|
575
607
|
if (node.propertyType === 'Collection') {
|
|
576
|
-
return {
|
|
608
|
+
return {...node, children: (node.children || []).map(updateNode)};
|
|
577
609
|
}
|
|
578
|
-
return node
|
|
579
|
-
}
|
|
610
|
+
return node;
|
|
611
|
+
};
|
|
580
612
|
|
|
581
613
|
return {
|
|
582
614
|
...prev,
|
|
583
615
|
selectedFields: prev.selectedFields.map(updateNode)
|
|
584
|
-
}
|
|
585
|
-
})
|
|
616
|
+
};
|
|
617
|
+
});
|
|
586
618
|
}}
|
|
587
619
|
onBlur={() => setEditingHeaderPath(null)}
|
|
588
|
-
onKeyDown={e => {
|
|
620
|
+
onKeyDown={(e) => {
|
|
589
621
|
if (e.key === 'Enter' || e.key === 'Escape') {
|
|
590
|
-
setEditingHeaderPath(null)
|
|
622
|
+
setEditingHeaderPath(null);
|
|
591
623
|
}
|
|
592
624
|
}}
|
|
593
625
|
inputProps={{
|
|
594
626
|
style: {
|
|
595
627
|
fontWeight: 'bold',
|
|
596
|
-
fontSize: '0.875rem'
|
|
628
|
+
fontSize: '0.875rem',
|
|
597
629
|
}
|
|
598
630
|
}}
|
|
599
631
|
/>
|
|
600
632
|
) : (
|
|
601
633
|
<Typography
|
|
602
|
-
variant=
|
|
603
|
-
fontWeight=
|
|
634
|
+
variant="subtitle2"
|
|
635
|
+
fontWeight="bold"
|
|
604
636
|
onDoubleClick={() => setEditingHeaderPath(item.path)}
|
|
605
|
-
sx={{
|
|
637
|
+
sx={{cursor: 'pointer'}}
|
|
606
638
|
>
|
|
607
639
|
{item.title ?? item.headerName}
|
|
608
640
|
</Typography>
|
|
@@ -610,153 +642,175 @@ const ReportBuilder = () => {
|
|
|
610
642
|
}
|
|
611
643
|
secondary={item.path}
|
|
612
644
|
/>
|
|
613
|
-
<Box sx={{
|
|
645
|
+
<Box sx={{display: 'flex', gap: 1}}>
|
|
614
646
|
{item.type === 'computed' && (
|
|
615
647
|
<IconButton
|
|
616
|
-
size=
|
|
648
|
+
size="small"
|
|
617
649
|
onClick={() => {
|
|
618
|
-
setSelectedRow(item)
|
|
619
|
-
setOpenDialogs(prev => ({
|
|
650
|
+
setSelectedRow(item);
|
|
651
|
+
setOpenDialogs(prev => ({...prev, expression: true}));
|
|
620
652
|
}}
|
|
621
|
-
title=
|
|
653
|
+
title="Edit computed field"
|
|
622
654
|
>
|
|
623
|
-
<PencilOutline fontSize=
|
|
655
|
+
<PencilOutline fontSize="small"/>
|
|
624
656
|
</IconButton>
|
|
625
657
|
)}
|
|
626
658
|
|
|
627
|
-
{(item?.field?.propertyType === 'String' ||
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
'
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
)}
|
|
659
|
+
{((item?.field?.propertyType === 'String' || item?.field?.propertyType === 'Int' || item?.field?.propertyType === 'Guid') && item?.type === 'static') && (
|
|
660
|
+
<IconButton
|
|
661
|
+
size="small"
|
|
662
|
+
onClick={() => {
|
|
663
|
+
console.log(item, level)
|
|
664
|
+
toggleSearchFilterByFullPath({
|
|
665
|
+
fullPath: item.fullPath,
|
|
666
|
+
path: item.path || item.headerName || item.fullPath,
|
|
667
|
+
propertyType: item.propertyType,
|
|
668
|
+
isWithinCollection: level !== 0
|
|
669
|
+
});
|
|
670
|
+
}}
|
|
671
|
+
title={
|
|
672
|
+
isInSearchFilter(item.fullPath)
|
|
673
|
+
? 'Remove from search filter'
|
|
674
|
+
: 'Add to search filter'
|
|
675
|
+
}
|
|
676
|
+
sx={{
|
|
677
|
+
color: isInSearchFilter(item.fullPath) ? 'primary.main' : 'text.secondary',
|
|
678
|
+
'&:hover': {
|
|
679
|
+
backgroundColor: 'transparent',
|
|
680
|
+
color: isInSearchFilter(item.fullPath) ? 'primary.main' : 'info.main',
|
|
681
|
+
},
|
|
682
|
+
}}
|
|
683
|
+
>
|
|
684
|
+
<Search fontSize="small"/>
|
|
685
|
+
</IconButton>
|
|
686
|
+
)}
|
|
656
687
|
<IconButton
|
|
657
|
-
size=
|
|
688
|
+
size="small"
|
|
658
689
|
onClick={() => {
|
|
659
690
|
setBuilderModel(prev => {
|
|
660
|
-
const toggleHidden = node => {
|
|
691
|
+
const toggleHidden = (node) => {
|
|
661
692
|
if (node.propertyType === 'Collection') {
|
|
662
693
|
return {
|
|
663
694
|
...node,
|
|
664
695
|
children: (node.children || []).map(toggleHidden)
|
|
665
|
-
}
|
|
696
|
+
};
|
|
666
697
|
}
|
|
667
698
|
if (node.path === item.path) {
|
|
668
|
-
return {
|
|
699
|
+
return {...node, hidden: !node.hidden};
|
|
669
700
|
}
|
|
670
|
-
return node
|
|
671
|
-
}
|
|
701
|
+
return node;
|
|
702
|
+
};
|
|
672
703
|
return {
|
|
673
704
|
...prev,
|
|
674
705
|
selectedFields: prev.selectedFields.map(toggleHidden)
|
|
675
|
-
}
|
|
676
|
-
})
|
|
706
|
+
};
|
|
707
|
+
});
|
|
677
708
|
}}
|
|
678
|
-
title={item.hidden ?
|
|
709
|
+
title={item.hidden ? "Show column" : "Hide column"}
|
|
679
710
|
sx={{
|
|
680
711
|
color: item.hidden ? 'warning.main' : 'text.secondary',
|
|
681
712
|
'&:hover': {
|
|
682
713
|
backgroundColor: 'transparent',
|
|
683
|
-
color: item.hidden ? 'warning.main' : 'info.main'
|
|
684
|
-
}
|
|
714
|
+
color: item.hidden ? 'warning.main' : 'info.main',
|
|
715
|
+
},
|
|
685
716
|
}}
|
|
686
717
|
>
|
|
687
|
-
{item.hidden ? <VisibilityOff fontSize=
|
|
718
|
+
{item.hidden ? <VisibilityOff fontSize="small"/> : <Visibility fontSize="small"/>}
|
|
688
719
|
</IconButton>
|
|
689
720
|
<IconButton
|
|
690
|
-
size=
|
|
721
|
+
size="small"
|
|
691
722
|
onClick={() => {
|
|
692
723
|
setBuilderModel(prev => {
|
|
693
|
-
const toggleImage = node => {
|
|
724
|
+
const toggleImage = (node) => {
|
|
694
725
|
if (node.propertyType === 'Collection') {
|
|
695
|
-
return {
|
|
726
|
+
return {...node, children: (node.children || []).map(toggleImage)};
|
|
696
727
|
}
|
|
697
728
|
if (node.path === item.path) {
|
|
698
|
-
return {
|
|
729
|
+
return {...node, image: !node.image};
|
|
699
730
|
}
|
|
700
|
-
return node
|
|
701
|
-
}
|
|
731
|
+
return node;
|
|
732
|
+
};
|
|
702
733
|
return {
|
|
703
734
|
...prev,
|
|
704
735
|
selectedFields: prev.selectedFields.map(toggleImage)
|
|
705
|
-
}
|
|
706
|
-
})
|
|
736
|
+
};
|
|
737
|
+
});
|
|
707
738
|
}}
|
|
708
|
-
title={item.image ?
|
|
739
|
+
title={item.image ? "Unset image" : "Render as image"}
|
|
709
740
|
sx={{
|
|
710
741
|
color: item.image ? 'success.main' : 'text.secondary',
|
|
711
742
|
'&:hover': {
|
|
712
743
|
backgroundColor: 'transparent',
|
|
713
|
-
color: item.image ? 'success.main' : 'info.main'
|
|
714
|
-
}
|
|
744
|
+
color: item.image ? 'success.main' : 'info.main',
|
|
745
|
+
},
|
|
746
|
+
}}
|
|
747
|
+
>
|
|
748
|
+
<ImageIcon fontSize="small"/>
|
|
749
|
+
</IconButton>
|
|
750
|
+
<IconButton
|
|
751
|
+
size="small"
|
|
752
|
+
onClick={() => {
|
|
753
|
+
setSelectedRow(item);
|
|
754
|
+
setOpenDialogs(prev => ({...prev, formatting: true}));
|
|
755
|
+
}}
|
|
756
|
+
title="Formatting Settings"
|
|
757
|
+
sx={{
|
|
758
|
+
color: item.formatting ? 'primary.main' : 'text.secondary',
|
|
759
|
+
'&:hover': {
|
|
760
|
+
backgroundColor: 'transparent',
|
|
761
|
+
color: item.formatting ? 'primary.main' : 'info.main',
|
|
762
|
+
},
|
|
715
763
|
}}
|
|
716
764
|
>
|
|
717
|
-
<
|
|
765
|
+
<FilterVintageOutlined fontSize="small"/>
|
|
718
766
|
</IconButton>
|
|
719
767
|
<IconButton
|
|
720
|
-
size=
|
|
768
|
+
size="small"
|
|
721
769
|
onClick={() =>
|
|
722
770
|
setBuilderModel(prev => ({
|
|
723
771
|
...prev,
|
|
724
772
|
selectedFields: removeFieldByPath(prev.selectedFields, item.path)
|
|
725
773
|
}))
|
|
726
774
|
}
|
|
727
|
-
title=
|
|
775
|
+
title="Remove field"
|
|
728
776
|
>
|
|
729
|
-
<
|
|
777
|
+
<DeleteOutlined fontSize="small"/>
|
|
730
778
|
</IconButton>
|
|
731
779
|
</Box>
|
|
732
780
|
</ListItem>
|
|
733
781
|
)}
|
|
734
782
|
</Draggable>
|
|
735
783
|
)
|
|
736
|
-
)}
|
|
784
|
+
))}
|
|
737
785
|
{provided.placeholder}
|
|
738
786
|
</List>
|
|
739
787
|
)}
|
|
740
788
|
</Droppable>
|
|
741
|
-
)
|
|
742
|
-
}
|
|
789
|
+
);
|
|
790
|
+
};
|
|
743
791
|
|
|
744
792
|
const isFullPathSelected = (nodes, targetFullPath) => {
|
|
745
793
|
for (const node of nodes) {
|
|
746
|
-
if (node.fullPath === targetFullPath) return true
|
|
794
|
+
if (node.fullPath === targetFullPath) return true;
|
|
747
795
|
if (node.children && isFullPathSelected(node.children, targetFullPath)) {
|
|
748
|
-
return true
|
|
796
|
+
return true;
|
|
749
797
|
}
|
|
750
798
|
}
|
|
751
|
-
return false
|
|
752
|
-
}
|
|
799
|
+
return false;
|
|
800
|
+
};
|
|
753
801
|
|
|
754
|
-
|
|
802
|
+
|
|
803
|
+
const handleGetReport = async (id) => {
|
|
755
804
|
try {
|
|
756
|
-
setIsLoading(true)
|
|
757
|
-
const response = await Services.PostService(
|
|
805
|
+
setIsLoading(true);
|
|
806
|
+
const response = await Services.PostService(
|
|
807
|
+
Endpoints.ReportBuilder.Post.GetReportDetails,
|
|
808
|
+
false,
|
|
809
|
+
{},
|
|
810
|
+
{id: id}
|
|
811
|
+
)
|
|
758
812
|
if (response) {
|
|
759
|
-
setBuilderModel(JSON.parse(response.data.value))
|
|
813
|
+
setBuilderModel(JSON.parse(response.data.value));
|
|
760
814
|
setBuilderMetadata({
|
|
761
815
|
id: response.data.id,
|
|
762
816
|
name: response.data.name,
|
|
@@ -769,22 +823,24 @@ const ReportBuilder = () => {
|
|
|
769
823
|
} catch (error) {
|
|
770
824
|
console.error(error)
|
|
771
825
|
} finally {
|
|
772
|
-
setIsLoading(false)
|
|
826
|
+
setIsLoading(false);
|
|
773
827
|
}
|
|
774
828
|
}
|
|
775
829
|
|
|
776
830
|
|
|
777
831
|
useEffect(() => {
|
|
778
|
-
handleGetModels()
|
|
779
|
-
}, [])
|
|
832
|
+
handleGetModels();
|
|
833
|
+
}, []);
|
|
780
834
|
useEffect(() => {
|
|
781
835
|
if (id != null) {
|
|
782
|
-
|
|
836
|
+
|
|
837
|
+
handleGetReport(id);
|
|
783
838
|
}
|
|
784
|
-
}, [id])
|
|
839
|
+
}, [id]);
|
|
840
|
+
|
|
785
841
|
|
|
786
842
|
return (
|
|
787
|
-
<div dir=
|
|
843
|
+
<div dir="ltr" style={{direction: 'ltr', textAlign: 'left', width: '100%', height: '100%'}}>
|
|
788
844
|
<style>
|
|
789
845
|
{`
|
|
790
846
|
.MuiListItemText-primary,
|
|
@@ -796,8 +852,8 @@ const ReportBuilder = () => {
|
|
|
796
852
|
`}
|
|
797
853
|
</style>
|
|
798
854
|
|
|
799
|
-
<CssBaseline
|
|
800
|
-
<Box sx={{
|
|
855
|
+
<CssBaseline/>
|
|
856
|
+
<Box sx={{display: 'flex', height: '100vh', overflow: 'hidden'}}>
|
|
801
857
|
<Paper
|
|
802
858
|
elevation={3}
|
|
803
859
|
sx={{
|
|
@@ -807,84 +863,86 @@ const ReportBuilder = () => {
|
|
|
807
863
|
borderRight: '1px solid #eee',
|
|
808
864
|
borderRadius: '0px',
|
|
809
865
|
p: 2,
|
|
810
|
-
bgcolor: 'white'
|
|
866
|
+
bgcolor: 'white',
|
|
811
867
|
}}
|
|
812
868
|
>
|
|
813
|
-
<Box display=
|
|
814
|
-
<Box display=
|
|
815
|
-
<Typography variant=
|
|
816
|
-
|
|
869
|
+
<Box display="flex" alignItems="center" gap={1} justifyContent="space-between">
|
|
870
|
+
<Box display="flex" alignItems="center" gap={1}>
|
|
871
|
+
<Typography variant="h6">
|
|
872
|
+
Report Configuration
|
|
873
|
+
</Typography>
|
|
874
|
+
<Chip variant={'filled'} label="Beta" color="warning" size="small"/>
|
|
817
875
|
</Box>
|
|
818
876
|
<Box>
|
|
819
|
-
<IconButton
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
>
|
|
828
|
-
<SaveAsOutlined color={'primary'} />
|
|
877
|
+
<IconButton onClick={() => {
|
|
878
|
+
setBuilderMetadata(preValue => ({
|
|
879
|
+
...preValue,
|
|
880
|
+
isNew: (id == null),
|
|
881
|
+
}))
|
|
882
|
+
handleToggleDialogs('save')
|
|
883
|
+
}}>
|
|
884
|
+
<SaveAsOutlined color={'primary'}/>
|
|
829
885
|
</IconButton>
|
|
830
|
-
{builderMetadata.id !== 0 && (
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
)}
|
|
843
|
-
|
|
844
|
-
<IconButton
|
|
845
|
-
onClick={() => {
|
|
846
|
-
router.push('/reportModule/reportBuilder/reports')
|
|
847
|
-
}}
|
|
848
|
-
>
|
|
849
|
-
<AssessmentOutlined color={'primary'} />
|
|
886
|
+
{builderMetadata.id !== 0 && <IconButton onClick={() => {
|
|
887
|
+
setBuilderMetadata(preValue => ({
|
|
888
|
+
...preValue,
|
|
889
|
+
isNew: false,
|
|
890
|
+
}))
|
|
891
|
+
handleToggleDialogs('save')
|
|
892
|
+
}}><SaveOutlined color={'primary'}/></IconButton>}
|
|
893
|
+
|
|
894
|
+
<IconButton onClick={() => {
|
|
895
|
+
router.push('/builders/report/list')
|
|
896
|
+
}}>
|
|
897
|
+
<AssessmentOutlined color={'primary'}/>
|
|
850
898
|
</IconButton>
|
|
851
899
|
</Box>
|
|
900
|
+
|
|
852
901
|
</Box>
|
|
853
902
|
<Autocomplete
|
|
854
|
-
size=
|
|
903
|
+
size="small"
|
|
855
904
|
value={builderModel.reportSource}
|
|
856
905
|
options={models}
|
|
857
906
|
getOptionLabel={option => option.tableName || ''}
|
|
858
907
|
onChange={(e, value) => {
|
|
859
908
|
if (value) {
|
|
860
|
-
setBuilderModel(preValue => ({
|
|
861
|
-
setBreadcrumbs([])
|
|
862
|
-
handleGetFields(value.fullName, value.friendlyName, value.propertyType)
|
|
909
|
+
setBuilderModel(preValue => ({...preValue, reportSource: value}))
|
|
910
|
+
setBreadcrumbs([]);
|
|
911
|
+
handleGetFields(value.fullName, value.friendlyName, value.propertyType);
|
|
863
912
|
}
|
|
864
913
|
}}
|
|
865
914
|
renderOption={(props, option) => (
|
|
866
|
-
<Box sx={{
|
|
915
|
+
<Box sx={{direction: 'rtl'}} component="li" {...props}>
|
|
867
916
|
<Box>
|
|
868
|
-
<Typography sx={{
|
|
869
|
-
|
|
917
|
+
<Typography sx={{color: 'primary.dark'}}>
|
|
918
|
+
{option.tableName}
|
|
919
|
+
</Typography>
|
|
920
|
+
<Typography variant="body2" color="text.secondary">
|
|
870
921
|
{option.friendlyName}
|
|
871
922
|
</Typography>
|
|
872
923
|
</Box>
|
|
873
924
|
</Box>
|
|
874
925
|
)}
|
|
875
|
-
renderInput={params =>
|
|
876
|
-
|
|
926
|
+
renderInput={(params) => (
|
|
927
|
+
<TextField
|
|
928
|
+
{...params}
|
|
929
|
+
variant="outlined"
|
|
930
|
+
label="Select Source Model"
|
|
931
|
+
fullWidth
|
|
932
|
+
/>
|
|
933
|
+
)}
|
|
934
|
+
sx={{mb: 2, mt: 2}}
|
|
877
935
|
/>
|
|
878
936
|
|
|
879
937
|
{breadcrumbs.length > 0 && (
|
|
880
|
-
<Breadcrumbs separator=
|
|
938
|
+
<Breadcrumbs separator="›" sx={{mb: 2}} aria-label="breadcrumb">
|
|
881
939
|
{breadcrumbs.map((crumb, i) => (
|
|
882
940
|
<Link
|
|
883
941
|
key={crumb.fullName}
|
|
884
|
-
underline=
|
|
942
|
+
underline="hover"
|
|
885
943
|
color={i === breadcrumbs.length - 1 ? 'primary.main' : 'inherit'}
|
|
886
944
|
onClick={() => handleGetFields(crumb.fullName, crumb.friendlyName, crumb.propertyType, true)}
|
|
887
|
-
sx={{
|
|
945
|
+
sx={{cursor: 'pointer', fontSize: '0.875rem'}}
|
|
888
946
|
>
|
|
889
947
|
{crumb.friendlyName}
|
|
890
948
|
</Link>
|
|
@@ -892,45 +950,51 @@ const ReportBuilder = () => {
|
|
|
892
950
|
</Breadcrumbs>
|
|
893
951
|
)}
|
|
894
952
|
|
|
895
|
-
<Box sx={{
|
|
896
|
-
<Typography variant=
|
|
953
|
+
<Box sx={{display: 'flex', flexDirection: 'column', gap: 1, mb: 2}}>
|
|
954
|
+
<Typography variant="subtitle1" gutterBottom>
|
|
897
955
|
Available Fields
|
|
898
956
|
</Typography>
|
|
899
957
|
<TextField
|
|
900
|
-
variant=
|
|
901
|
-
size=
|
|
902
|
-
placeholder=
|
|
958
|
+
variant="outlined"
|
|
959
|
+
size="small"
|
|
960
|
+
placeholder="Search fields..."
|
|
903
961
|
fullWidth
|
|
904
962
|
value={searchQuery}
|
|
905
|
-
onChange={e => setSearchQuery(e.target.value)}
|
|
963
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
906
964
|
/>
|
|
907
965
|
</Box>
|
|
908
966
|
|
|
909
|
-
<Box sx={{
|
|
967
|
+
<Box sx={{flexGrow: 1, overflowY: 'auto'}}>
|
|
910
968
|
<List dense disablePadding>
|
|
911
969
|
{modelFields
|
|
912
|
-
.filter(
|
|
913
|
-
field
|
|
914
|
-
|
|
915
|
-
field.path?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
970
|
+
.filter(field =>
|
|
971
|
+
field.friendlyName?.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
972
|
+
field.path?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
916
973
|
)
|
|
917
974
|
.map((field, index) => {
|
|
975
|
+
|
|
918
976
|
// Now check against your selectedFields by their stored 'path'
|
|
919
|
-
const fullPath = [
|
|
977
|
+
const fullPath = [
|
|
978
|
+
...breadcrumbs.map(b => b.friendlyName),
|
|
979
|
+
field.friendlyName
|
|
980
|
+
].join('.');
|
|
920
981
|
|
|
921
982
|
// now check *that*:
|
|
922
|
-
const isSelected = isFullPathSelected(
|
|
983
|
+
const isSelected = isFullPathSelected(
|
|
984
|
+
builderModel.selectedFields,
|
|
985
|
+
fullPath
|
|
986
|
+
);
|
|
923
987
|
return (
|
|
924
988
|
<ListItem key={index} divider>
|
|
925
989
|
<ListItemText
|
|
926
990
|
primary={
|
|
927
|
-
<Box sx={{
|
|
991
|
+
<Box sx={{display: 'flex', alignItems: 'center', gap: 1}}>
|
|
928
992
|
{field.friendlyName}
|
|
929
993
|
{isSelected && (
|
|
930
|
-
<
|
|
931
|
-
fontSize=
|
|
932
|
-
color=
|
|
933
|
-
titleAccess=
|
|
994
|
+
<CheckCircleOutlined
|
|
995
|
+
fontSize="small"
|
|
996
|
+
color="success"
|
|
997
|
+
titleAccess="Field already selected"
|
|
934
998
|
/>
|
|
935
999
|
)}
|
|
936
1000
|
</Box>
|
|
@@ -940,7 +1004,7 @@ const ReportBuilder = () => {
|
|
|
940
1004
|
sx: {
|
|
941
1005
|
textAlign: 'left',
|
|
942
1006
|
direction: 'ltr',
|
|
943
|
-
display: 'block'
|
|
1007
|
+
display: 'block',
|
|
944
1008
|
}
|
|
945
1009
|
}}
|
|
946
1010
|
secondaryTypographyProps={{
|
|
@@ -949,7 +1013,7 @@ const ReportBuilder = () => {
|
|
|
949
1013
|
color: 'red',
|
|
950
1014
|
textAlign: 'left',
|
|
951
1015
|
direction: 'ltr',
|
|
952
|
-
display: 'block'
|
|
1016
|
+
display: 'block',
|
|
953
1017
|
}
|
|
954
1018
|
}}
|
|
955
1019
|
/>
|
|
@@ -960,12 +1024,12 @@ const ReportBuilder = () => {
|
|
|
960
1024
|
alignItems: 'center',
|
|
961
1025
|
gap: 1,
|
|
962
1026
|
ml: 1,
|
|
963
|
-
direction: 'ltr'
|
|
1027
|
+
direction: 'ltr',
|
|
964
1028
|
}}
|
|
965
1029
|
>
|
|
966
1030
|
{(field.propertyType === 'Class' || field.propertyType === 'Collection') && (
|
|
967
1031
|
<IconButton
|
|
968
|
-
size=
|
|
1032
|
+
size="small"
|
|
969
1033
|
onClick={() => {
|
|
970
1034
|
handleGetFields(field.modelClassName, field.friendlyName, field.propertyType)
|
|
971
1035
|
setSearchQuery('')
|
|
@@ -974,90 +1038,98 @@ const ReportBuilder = () => {
|
|
|
974
1038
|
color: 'text.secondary',
|
|
975
1039
|
'&:hover': {
|
|
976
1040
|
backgroundColor: 'transparent',
|
|
977
|
-
color: 'success.main'
|
|
978
|
-
}
|
|
1041
|
+
color: 'success.main',
|
|
1042
|
+
},
|
|
979
1043
|
}}
|
|
980
|
-
title=
|
|
1044
|
+
title="Navigate into nested fields"
|
|
981
1045
|
>
|
|
982
|
-
<ArrowForwardSharp fontSize=
|
|
1046
|
+
<ArrowForwardSharp fontSize="inherit"/>
|
|
983
1047
|
</IconButton>
|
|
984
1048
|
)}
|
|
985
1049
|
|
|
1050
|
+
|
|
986
1051
|
{field.propertyType !== 'Class' && field.propertyType !== 'Collection' && (
|
|
987
1052
|
<IconButton
|
|
988
1053
|
onClick={() => {
|
|
989
1054
|
handleAddStaticField(field)
|
|
990
1055
|
}}
|
|
991
|
-
size=
|
|
1056
|
+
size="small"
|
|
992
1057
|
sx={{
|
|
993
1058
|
color: 'text.secondary',
|
|
994
1059
|
'&:hover': {
|
|
995
1060
|
backgroundColor: 'transparent',
|
|
996
|
-
color: 'primary.main'
|
|
997
|
-
}
|
|
1061
|
+
color: 'primary.main',
|
|
1062
|
+
},
|
|
998
1063
|
}}
|
|
999
|
-
title=
|
|
1064
|
+
title="Add field to report"
|
|
1000
1065
|
>
|
|
1001
|
-
<AddBox fontSize=
|
|
1066
|
+
<AddBox fontSize="inherit"/>
|
|
1002
1067
|
</IconButton>
|
|
1003
1068
|
)}
|
|
1069
|
+
|
|
1004
1070
|
</Box>
|
|
1005
1071
|
</ListItem>
|
|
1006
|
-
)
|
|
1072
|
+
);
|
|
1007
1073
|
})}
|
|
1008
1074
|
</List>
|
|
1075
|
+
|
|
1009
1076
|
</Box>
|
|
1010
1077
|
|
|
1011
1078
|
{isLoading && (
|
|
1012
|
-
<Box sx={{
|
|
1013
|
-
<CircularProgress size={24}
|
|
1079
|
+
<Box sx={{display: 'flex', justifyContent: 'center', mt: 2}}>
|
|
1080
|
+
<CircularProgress size={24}/>
|
|
1014
1081
|
</Box>
|
|
1015
1082
|
)}
|
|
1016
1083
|
</Paper>
|
|
1017
1084
|
|
|
1018
|
-
<Box sx={{
|
|
1085
|
+
<Box sx={{flexGrow: 1, p: 3, overflowY: 'auto'}}>
|
|
1086
|
+
|
|
1019
1087
|
<Grid container spacing={2}>
|
|
1020
|
-
<Box sx={{
|
|
1021
|
-
<Box sx={{
|
|
1088
|
+
<Box sx={{flexGrow: 1, p: 3, overflowY: 'auto'}}>
|
|
1089
|
+
<Box sx={{mb: 3}}>
|
|
1022
1090
|
{/* Top row: Title (left) and Preview icon (right) */}
|
|
1023
1091
|
<Box
|
|
1024
1092
|
sx={{
|
|
1025
1093
|
display: 'flex',
|
|
1026
1094
|
justifyContent: 'space-between',
|
|
1027
1095
|
alignItems: 'center',
|
|
1028
|
-
mb: 2
|
|
1096
|
+
mb: 2,
|
|
1029
1097
|
}}
|
|
1030
1098
|
>
|
|
1031
|
-
<Box sx={{
|
|
1032
|
-
<Typography variant=
|
|
1099
|
+
<Box sx={{display: 'flex', alignItems: 'center', gap: 2}}>
|
|
1100
|
+
<Typography variant="h5" sx={{fontWeight: 600}}>
|
|
1033
1101
|
Builder
|
|
1034
1102
|
</Typography>
|
|
1035
1103
|
|
|
1036
1104
|
<FormControlLabel
|
|
1037
1105
|
control={
|
|
1038
1106
|
<Switch
|
|
1039
|
-
size=
|
|
1107
|
+
size="small"
|
|
1040
1108
|
checked={builderModel.isRaw}
|
|
1041
|
-
onChange={() =>
|
|
1042
|
-
|
|
1109
|
+
onChange={() =>
|
|
1110
|
+
setBuilderModel(prev => ({...prev, isRaw: !prev.isRaw}))
|
|
1111
|
+
}
|
|
1112
|
+
color="primary"
|
|
1043
1113
|
/>
|
|
1044
1114
|
}
|
|
1045
|
-
label=
|
|
1115
|
+
label="Raw"
|
|
1046
1116
|
/>
|
|
1047
1117
|
</Box>
|
|
1048
|
-
<Box sx={{
|
|
1118
|
+
<Box sx={{display: 'flex', alignItems: 'center', gap: 2}}>
|
|
1049
1119
|
<Tooltip title={'تصفية رئيسية'}>
|
|
1120
|
+
|
|
1050
1121
|
<IconButton
|
|
1051
1122
|
sx={{
|
|
1052
1123
|
color: isPreview ? 'primary.main' : 'text.secondary',
|
|
1053
1124
|
'&:hover': {
|
|
1054
1125
|
backgroundColor: 'transparent',
|
|
1055
|
-
color: 'primary.main'
|
|
1056
|
-
}
|
|
1126
|
+
color: 'primary.main',
|
|
1127
|
+
},
|
|
1057
1128
|
}}
|
|
1058
|
-
onClick={() => handleToggleDialogs('filter')
|
|
1129
|
+
onClick={() => handleToggleDialogs('filter')
|
|
1130
|
+
}
|
|
1059
1131
|
>
|
|
1060
|
-
<FilterAlt
|
|
1132
|
+
<FilterAlt/>
|
|
1061
1133
|
</IconButton>
|
|
1062
1134
|
</Tooltip>
|
|
1063
1135
|
<IconButton
|
|
@@ -1065,14 +1137,15 @@ const ReportBuilder = () => {
|
|
|
1065
1137
|
color: isPreview ? 'primary.main' : 'text.secondary',
|
|
1066
1138
|
'&:hover': {
|
|
1067
1139
|
backgroundColor: 'transparent',
|
|
1068
|
-
color: 'primary.main'
|
|
1069
|
-
}
|
|
1140
|
+
color: 'primary.main',
|
|
1141
|
+
},
|
|
1070
1142
|
}}
|
|
1071
1143
|
onClick={() => setIsPreview(prev => !prev)}
|
|
1072
1144
|
>
|
|
1073
|
-
<PreviewOutlined
|
|
1145
|
+
<PreviewOutlined/>
|
|
1074
1146
|
</IconButton>
|
|
1075
1147
|
</Box>
|
|
1148
|
+
|
|
1076
1149
|
</Box>
|
|
1077
1150
|
|
|
1078
1151
|
{/* Actions row: Just the Add Computed Field button aligned right */}
|
|
@@ -1085,22 +1158,22 @@ const ReportBuilder = () => {
|
|
|
1085
1158
|
borderRadius: '8px',
|
|
1086
1159
|
display: 'flex',
|
|
1087
1160
|
justifyContent: 'space-between',
|
|
1088
|
-
backgroundColor: 'background.paper'
|
|
1161
|
+
backgroundColor: 'background.paper',
|
|
1089
1162
|
}}
|
|
1090
1163
|
>
|
|
1091
1164
|
<Button
|
|
1092
|
-
variant=
|
|
1093
|
-
color=
|
|
1165
|
+
variant="outlined"
|
|
1166
|
+
color="primary"
|
|
1094
1167
|
onClick={() => {
|
|
1095
|
-
console.log(breadcrumbs)
|
|
1168
|
+
console.log(breadcrumbs);
|
|
1096
1169
|
handleToggleDialogs('expression')
|
|
1097
1170
|
}}
|
|
1098
1171
|
>
|
|
1099
1172
|
Add Computed Field
|
|
1100
1173
|
</Button>
|
|
1101
1174
|
<Button
|
|
1102
|
-
variant=
|
|
1103
|
-
color=
|
|
1175
|
+
variant="outlined"
|
|
1176
|
+
color="primary"
|
|
1104
1177
|
onClick={() => {
|
|
1105
1178
|
setSelectedRow(null) // reset edit
|
|
1106
1179
|
handleToggleDialogs('routing')
|
|
@@ -1109,38 +1182,56 @@ const ReportBuilder = () => {
|
|
|
1109
1182
|
Add Routing
|
|
1110
1183
|
</Button>
|
|
1111
1184
|
<Button
|
|
1112
|
-
variant=
|
|
1113
|
-
color=
|
|
1185
|
+
variant="outlined"
|
|
1186
|
+
color="primary"
|
|
1114
1187
|
onClick={() => {
|
|
1115
|
-
console.log(breadcrumbs)
|
|
1188
|
+
console.log(breadcrumbs);
|
|
1116
1189
|
handleToggleDialogs('params')
|
|
1117
1190
|
}}
|
|
1118
1191
|
>
|
|
1119
1192
|
Global Parameters
|
|
1120
1193
|
</Button>
|
|
1121
|
-
<Button
|
|
1194
|
+
<Button
|
|
1195
|
+
variant="outlined"
|
|
1196
|
+
color="secondary"
|
|
1197
|
+
onClick={() => handleToggleDialogs('fixedFilter')}
|
|
1198
|
+
>
|
|
1122
1199
|
Fixed Filter
|
|
1123
1200
|
</Button>
|
|
1201
|
+
<Button
|
|
1202
|
+
variant="outlined"
|
|
1203
|
+
color="info"
|
|
1204
|
+
onClick={() => handleToggleDialogs('columnConfig')}
|
|
1205
|
+
>
|
|
1206
|
+
Column Configurator
|
|
1207
|
+
</Button>
|
|
1208
|
+
<Button
|
|
1209
|
+
variant="outlined"
|
|
1210
|
+
color="warning"
|
|
1211
|
+
onClick={() => handleToggleDialogs('settings')}
|
|
1212
|
+
>
|
|
1213
|
+
Report Settings
|
|
1214
|
+
</Button>
|
|
1124
1215
|
{/* Hidden input for uploading builder model */}
|
|
1125
1216
|
<input
|
|
1126
|
-
type=
|
|
1127
|
-
accept=
|
|
1217
|
+
type="file"
|
|
1218
|
+
accept="application/json,.json"
|
|
1128
1219
|
ref={fileInputRef}
|
|
1129
|
-
style={{
|
|
1220
|
+
style={{display: 'none'}}
|
|
1130
1221
|
onChange={handleFileChange}
|
|
1131
1222
|
/>
|
|
1132
1223
|
<Button
|
|
1133
|
-
variant=
|
|
1134
|
-
color=
|
|
1135
|
-
startIcon={<CloudDownloadOutlined
|
|
1224
|
+
variant="outlined"
|
|
1225
|
+
color="secondary"
|
|
1226
|
+
startIcon={<CloudDownloadOutlined/>}
|
|
1136
1227
|
onClick={handleDownloadModel}
|
|
1137
1228
|
>
|
|
1138
1229
|
Download Model
|
|
1139
1230
|
</Button>
|
|
1140
1231
|
<Button
|
|
1141
|
-
variant=
|
|
1142
|
-
color=
|
|
1143
|
-
startIcon={<CloudUploadOutlined
|
|
1232
|
+
variant="outlined"
|
|
1233
|
+
color="secondary"
|
|
1234
|
+
startIcon={<CloudUploadOutlined/>}
|
|
1144
1235
|
onClick={handleUploadClick}
|
|
1145
1236
|
>
|
|
1146
1237
|
Upload Model
|
|
@@ -1148,35 +1239,31 @@ const ReportBuilder = () => {
|
|
|
1148
1239
|
</Box>
|
|
1149
1240
|
</Box>
|
|
1150
1241
|
|
|
1151
|
-
{!isPreview ?
|
|
1152
|
-
builderModel
|
|
1153
|
-
<Box>
|
|
1154
|
-
<SqlEditor builderModel={builderModel} setBuilderModel={setBuilderModel} />
|
|
1155
|
-
</Box>
|
|
1156
|
-
) : (
|
|
1157
|
-
<Box>
|
|
1158
|
-
<DragDropContext onDragEnd={handleDragEnd}>
|
|
1159
|
-
{renderSelectedFields(builderModel.selectedFields)}
|
|
1160
|
-
</DragDropContext>
|
|
1161
|
-
</Box>
|
|
1162
|
-
)
|
|
1163
|
-
) : (
|
|
1242
|
+
{!isPreview ? builderModel.isRaw ?
|
|
1243
|
+
<Box><SqlEditor builderModel={builderModel} setBuilderModel={setBuilderModel}/></Box> :
|
|
1164
1244
|
<Box>
|
|
1165
|
-
<
|
|
1166
|
-
|
|
1167
|
-
|
|
1245
|
+
<DragDropContext onDragEnd={handleDragEnd}>
|
|
1246
|
+
{renderSelectedFields(builderModel.selectedFields)}
|
|
1247
|
+
</DragDropContext>
|
|
1248
|
+
</Box> : <Box>
|
|
1249
|
+
<SGrid
|
|
1250
|
+
builderModel={builderModel}
|
|
1251
|
+
filter={builderModel.filter}
|
|
1252
|
+
extraCols={columnConfigResult?.extraCols ?? []}
|
|
1253
|
+
columnsConfig={columnConfigResult?.columnsConfig ?? []}
|
|
1254
|
+
updateRef={updateRef}
|
|
1255
|
+
/>
|
|
1256
|
+
</Box>}
|
|
1168
1257
|
</Box>
|
|
1169
1258
|
</Grid>
|
|
1170
|
-
{!isPreview &&
|
|
1171
|
-
<Box
|
|
1172
|
-
|
|
1173
|
-
>
|
|
1174
|
-
<Typography variant='h6' gutterBottom>
|
|
1259
|
+
{!isPreview &&
|
|
1260
|
+
<Box sx={{mt: 4, backgroundColor: '#fff', borderRadius: '12px', p: '10px', border: '1px solid lightgrey'}}>
|
|
1261
|
+
<Typography variant="h6" gutterBottom>
|
|
1175
1262
|
Routing Settings
|
|
1176
1263
|
</Typography>
|
|
1177
1264
|
|
|
1178
1265
|
{builderModel.routingSettings?.length === 0 && (
|
|
1179
|
-
<Typography variant=
|
|
1266
|
+
<Typography variant="body2" color="text.secondary">
|
|
1180
1267
|
No routing settings defined yet.
|
|
1181
1268
|
</Typography>
|
|
1182
1269
|
)}
|
|
@@ -1189,37 +1276,37 @@ const ReportBuilder = () => {
|
|
|
1189
1276
|
display: 'flex',
|
|
1190
1277
|
alignItems: 'center',
|
|
1191
1278
|
justifyContent: 'space-between',
|
|
1192
|
-
width: '100%'
|
|
1279
|
+
width: '100%',
|
|
1193
1280
|
}}
|
|
1194
1281
|
>
|
|
1195
1282
|
{/* Left side: routing info */}
|
|
1196
1283
|
<Box>
|
|
1197
|
-
<Typography variant=
|
|
1198
|
-
{route.fieldName} → {route.pattern}
|
|
1284
|
+
<Typography variant="body1">
|
|
1285
|
+
{route.name ? `${route.name} (${route.fieldName})` : route.fieldName} → {route.type === 'Filter' ? `Page: ${route.pageId}` : route.pattern}
|
|
1199
1286
|
</Typography>
|
|
1200
|
-
<Typography variant=
|
|
1201
|
-
Params: {route.params.join(', ')}
|
|
1287
|
+
<Typography variant="body2" color="text.secondary">
|
|
1288
|
+
Params: {(route.params || []).join(', ')}
|
|
1202
1289
|
</Typography>
|
|
1203
1290
|
</Box>
|
|
1204
1291
|
|
|
1205
1292
|
{/* Right side: action buttons */}
|
|
1206
|
-
<Box sx={{
|
|
1293
|
+
<Box sx={{display: 'flex', gap: 1}}>
|
|
1207
1294
|
<Button
|
|
1208
|
-
size=
|
|
1295
|
+
size="small"
|
|
1209
1296
|
onClick={() => {
|
|
1210
|
-
setSelectedRow({
|
|
1297
|
+
setSelectedRow({...route, index: idx})
|
|
1211
1298
|
handleToggleDialogs('routing')
|
|
1212
1299
|
}}
|
|
1213
1300
|
>
|
|
1214
1301
|
Update
|
|
1215
1302
|
</Button>
|
|
1216
1303
|
<Button
|
|
1217
|
-
size=
|
|
1218
|
-
color=
|
|
1304
|
+
size="small"
|
|
1305
|
+
color="error"
|
|
1219
1306
|
onClick={() =>
|
|
1220
|
-
setBuilderModel(prev => ({
|
|
1307
|
+
setBuilderModel((prev) => ({
|
|
1221
1308
|
...prev,
|
|
1222
|
-
routingSettings: prev.routingSettings.filter((_, i) => i !== idx)
|
|
1309
|
+
routingSettings: prev.routingSettings.filter((_, i) => i !== idx),
|
|
1223
1310
|
}))
|
|
1224
1311
|
}
|
|
1225
1312
|
>
|
|
@@ -1230,9 +1317,40 @@ const ReportBuilder = () => {
|
|
|
1230
1317
|
</ListItem>
|
|
1231
1318
|
))}
|
|
1232
1319
|
</List>
|
|
1233
|
-
|
|
1234
|
-
|
|
1320
|
+
|
|
1321
|
+
</Box>}
|
|
1322
|
+
|
|
1323
|
+
{!isPreview && columnConfigResult &&
|
|
1324
|
+
<Box sx={{mt: 4, backgroundColor: '#fff', borderRadius: '12px', p: '10px', border: '1px solid lightgrey'}}>
|
|
1325
|
+
<Box sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2}}>
|
|
1326
|
+
<Typography variant="h6">
|
|
1327
|
+
Column Configurator Result (Testing)
|
|
1328
|
+
</Typography>
|
|
1329
|
+
<Button
|
|
1330
|
+
size="small"
|
|
1331
|
+
color="error"
|
|
1332
|
+
onClick={() => setColumnConfigResult(null)}
|
|
1333
|
+
>
|
|
1334
|
+
Clear
|
|
1335
|
+
</Button>
|
|
1336
|
+
</Box>
|
|
1337
|
+
<Box
|
|
1338
|
+
component="pre"
|
|
1339
|
+
sx={{
|
|
1340
|
+
p: 2,
|
|
1341
|
+
bgcolor: 'grey.900',
|
|
1342
|
+
color: 'grey.100',
|
|
1343
|
+
borderRadius: 1,
|
|
1344
|
+
overflow: 'auto',
|
|
1345
|
+
maxHeight: 400,
|
|
1346
|
+
fontSize: '0.875rem'
|
|
1347
|
+
}}
|
|
1348
|
+
>
|
|
1349
|
+
{JSON.stringify(columnConfigResult, null, 2)}
|
|
1350
|
+
</Box>
|
|
1351
|
+
</Box>}
|
|
1235
1352
|
</Box>
|
|
1353
|
+
|
|
1236
1354
|
</Box>
|
|
1237
1355
|
|
|
1238
1356
|
<Dialog
|
|
@@ -1240,46 +1358,35 @@ const ReportBuilder = () => {
|
|
|
1240
1358
|
onClose={() => {
|
|
1241
1359
|
handleToggleDialogs('expression')
|
|
1242
1360
|
setSelectedRow(null)
|
|
1243
|
-
setSelectedCollection(null)
|
|
1244
|
-
}}
|
|
1245
|
-
maxWidth='lg'
|
|
1246
|
-
fullWidth
|
|
1247
|
-
>
|
|
1361
|
+
setSelectedCollection(null);
|
|
1362
|
+
}} maxWidth="lg" fullWidth>
|
|
1248
1363
|
<ExpressionEditor
|
|
1249
1364
|
oldValue={selectedRow}
|
|
1250
1365
|
addComputedField={handleAddComputedField}
|
|
1251
1366
|
handleUpdateComputedField={handleUpdateComputedField}
|
|
1252
1367
|
selectionParams={builderModel.selectionParams}
|
|
1253
|
-
setSelectionParams={params =>
|
|
1368
|
+
setSelectionParams={(params) =>
|
|
1369
|
+
setBuilderModel(prev => ({...prev, selectionParams: params}))
|
|
1370
|
+
}
|
|
1254
1371
|
/>
|
|
1255
1372
|
</Dialog>
|
|
1256
|
-
<Dialog
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
setSelectedRow(null)
|
|
1261
|
-
}}
|
|
1262
|
-
maxWidth='lg'
|
|
1263
|
-
fullWidth
|
|
1264
|
-
>
|
|
1373
|
+
<Dialog open={openDialogs.params} onClose={() => {
|
|
1374
|
+
handleToggleDialogs('params')
|
|
1375
|
+
setSelectedRow(null)
|
|
1376
|
+
}} maxWidth="lg" fullWidth>
|
|
1265
1377
|
<DynamicValueList
|
|
1266
1378
|
items={builderModel.selectionParams}
|
|
1267
1379
|
onChange={newParams => {
|
|
1268
1380
|
setBuilderModel(prev => ({
|
|
1269
1381
|
...prev,
|
|
1270
1382
|
selectionParams: newParams
|
|
1271
|
-
}))
|
|
1383
|
+
}));
|
|
1272
1384
|
}}
|
|
1273
1385
|
/>
|
|
1274
1386
|
</Dialog>
|
|
1275
|
-
<Dialog
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
handleToggleDialogs('save')
|
|
1279
|
-
}}
|
|
1280
|
-
maxWidth='lg'
|
|
1281
|
-
fullWidth
|
|
1282
|
-
>
|
|
1387
|
+
<Dialog open={openDialogs.save} onClose={() => {
|
|
1388
|
+
handleToggleDialogs('save')
|
|
1389
|
+
}} maxWidth="lg" fullWidth>
|
|
1283
1390
|
<ReportBuilderSaveForm
|
|
1284
1391
|
builderMetadata={builderMetadata}
|
|
1285
1392
|
setBuilderMetadata={setBuilderMetadata}
|
|
@@ -1296,15 +1403,18 @@ const ReportBuilder = () => {
|
|
|
1296
1403
|
scroll='body'
|
|
1297
1404
|
// onClose={() => handleToggleDialogs('CustomFilter')}
|
|
1298
1405
|
>
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1406
|
+
{openDialogs.filter && builderModel.reportSource && (
|
|
1407
|
+
<CustomFilterDialog
|
|
1408
|
+
handleToggleDialogs={handleToggleDialogs}
|
|
1409
|
+
Filter={builderModel.filter?.LocalTfilter || []}
|
|
1410
|
+
customFilterCode={builderModel.filter?.customFilterCode}
|
|
1411
|
+
handleFilterChange={handleFilterChange}
|
|
1412
|
+
className={builderModel?.reportSource?.fullName}
|
|
1413
|
+
LocalFilter={false}
|
|
1414
|
+
selectTFilter={[]}
|
|
1415
|
+
// selectParamsMeta={builderModel.selectionParams}
|
|
1416
|
+
/>
|
|
1417
|
+
)}
|
|
1308
1418
|
</Dialog>
|
|
1309
1419
|
<Dialog
|
|
1310
1420
|
fullWidth
|
|
@@ -1316,7 +1426,7 @@ const ReportBuilder = () => {
|
|
|
1316
1426
|
<FixedFilterDialog
|
|
1317
1427
|
className={builderModel?.reportSource?.fullName}
|
|
1318
1428
|
value={builderModel?.filter?.fixedTFilter || []}
|
|
1319
|
-
onSave={list => {
|
|
1429
|
+
onSave={(list) => {
|
|
1320
1430
|
setBuilderModel(prev => ({
|
|
1321
1431
|
...prev,
|
|
1322
1432
|
filter: {
|
|
@@ -1328,11 +1438,16 @@ const ReportBuilder = () => {
|
|
|
1328
1438
|
onClose={() => handleToggleDialogs('fixedFilter')}
|
|
1329
1439
|
/>
|
|
1330
1440
|
</Dialog>
|
|
1331
|
-
<Dialog
|
|
1441
|
+
<Dialog
|
|
1442
|
+
open={openDialogs.routing}
|
|
1443
|
+
onClose={() => handleToggleDialogs('routing')}
|
|
1444
|
+
maxWidth="sm"
|
|
1445
|
+
fullWidth
|
|
1446
|
+
>
|
|
1332
1447
|
<RoutingSettingDialog
|
|
1333
|
-
value={selectedRow || {
|
|
1334
|
-
onChange={newValue => {
|
|
1335
|
-
setBuilderModel(prev => {
|
|
1448
|
+
value={selectedRow || {fieldName: '', pattern: '', params: []}}
|
|
1449
|
+
onChange={(newValue) => {
|
|
1450
|
+
setBuilderModel((prev) => {
|
|
1336
1451
|
const clone = [...(prev.routingSettings || [])]
|
|
1337
1452
|
if (selectedRow?.index != null) {
|
|
1338
1453
|
// Update existing
|
|
@@ -1341,21 +1456,66 @@ const ReportBuilder = () => {
|
|
|
1341
1456
|
// Add new
|
|
1342
1457
|
clone.push(newValue)
|
|
1343
1458
|
}
|
|
1344
|
-
return {
|
|
1459
|
+
return {...prev, routingSettings: clone}
|
|
1345
1460
|
})
|
|
1346
1461
|
}}
|
|
1347
1462
|
onClose={() => handleToggleDialogs('routing')}
|
|
1348
1463
|
/>
|
|
1349
1464
|
</Dialog>
|
|
1465
|
+
<FormattingSettingsDialog
|
|
1466
|
+
open={openDialogs.formatting}
|
|
1467
|
+
onClose={() => setOpenDialogs(prev => ({...prev, formatting: false}))}
|
|
1468
|
+
field={selectedRow ? {
|
|
1469
|
+
...selectedRow,
|
|
1470
|
+
parentFields: builderModel.selectedFields.filter(f => f.path !== selectedRow.path && !f.children)
|
|
1471
|
+
} : null}
|
|
1472
|
+
onSave={(formatting) => {
|
|
1473
|
+
setBuilderModel(prev => {
|
|
1474
|
+
const updateNode = (node) => {
|
|
1475
|
+
if (node.propertyType === 'Collection') {
|
|
1476
|
+
return {...node, children: (node.children || []).map(updateNode)};
|
|
1477
|
+
}
|
|
1478
|
+
if (node.path === selectedRow.path) {
|
|
1479
|
+
return {...node, formatting};
|
|
1480
|
+
}
|
|
1481
|
+
return node;
|
|
1482
|
+
};
|
|
1483
|
+
return {
|
|
1484
|
+
...prev,
|
|
1485
|
+
selectedFields: prev.selectedFields.map(updateNode)
|
|
1486
|
+
};
|
|
1487
|
+
});
|
|
1488
|
+
}}
|
|
1489
|
+
/>
|
|
1490
|
+
<ColumnConfiguratorDialog
|
|
1491
|
+
open={openDialogs.columnConfig}
|
|
1492
|
+
onClose={() => handleToggleDialogs('columnConfig')}
|
|
1493
|
+
onResult={(result) => {
|
|
1494
|
+
console.log('Column Configuration Result:', result);
|
|
1495
|
+
setColumnConfigResult(result);
|
|
1496
|
+
handleToggleDialogs('columnConfig');
|
|
1497
|
+
}}
|
|
1498
|
+
/>
|
|
1499
|
+
<ReportSettingsDialog
|
|
1500
|
+
open={openDialogs.settings}
|
|
1501
|
+
onClose={() => handleToggleDialogs('settings')}
|
|
1502
|
+
settings={builderModel.settings}
|
|
1503
|
+
onSave={(newSettings) => {
|
|
1504
|
+
setBuilderModel(prev => ({
|
|
1505
|
+
...prev,
|
|
1506
|
+
settings: newSettings
|
|
1507
|
+
}));
|
|
1508
|
+
}}
|
|
1509
|
+
/>
|
|
1350
1510
|
</div>
|
|
1351
1511
|
)
|
|
1352
|
-
}
|
|
1512
|
+
};
|
|
1353
1513
|
|
|
1354
1514
|
ReportBuilder.acl = {
|
|
1355
1515
|
action: 'view',
|
|
1356
|
-
subject: PermissionsSubjects.
|
|
1357
|
-
}
|
|
1516
|
+
subject: PermissionsSubjects.ReportBuilder
|
|
1517
|
+
};
|
|
1358
1518
|
|
|
1359
|
-
ReportBuilder.getLayout = page => <BlankLayout>{page}</BlankLayout
|
|
1519
|
+
ReportBuilder.getLayout = (page) => <BlankLayout>{page}</BlankLayout>;
|
|
1360
1520
|
|
|
1361
|
-
export default ReportBuilder
|
|
1521
|
+
export default ReportBuilder;
|