@gooddata/sdk-ui-dashboard 11.65.0-alpha.1 → 11.65.0-alpha.11
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/NOTICE +72039 -4
- package/esm/__version.d.ts +1 -1
- package/esm/__version.d.ts.map +1 -1
- package/esm/__version.js +1 -1
- package/esm/assets/type-csv-formatted.svg +1 -1
- package/esm/assets/type-csv-raw.svg +1 -1
- package/esm/index.d.ts +8 -5
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -2
- package/esm/model/commandHandlers/dashboard/common/filterViews.d.ts +36 -3
- package/esm/model/commandHandlers/dashboard/common/filterViews.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/common/filterViews.js +138 -26
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts +15 -4
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/index.js +55 -11
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/preloadAttributeFiltersData.d.ts +6 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/preloadAttributeFiltersData.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/preloadAttributeFiltersData.js +14 -6
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.js +1 -3
- package/esm/model/commandHandlers/dashboard/resetDashboardHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/dashboard/resetDashboardHandler.js +21 -8
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeDisplayFormHandler.js +8 -7
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/changeAttributeFilterSelectionHandler.js +19 -28
- package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/removeAttributeFiltersHandler.js +4 -5
- package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/replaceAttributeFilterItemSelectionHandler.js +14 -15
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts +4 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/attributeFilter/resolveDisplayFormMetadata.js +11 -2
- package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +28 -44
- package/esm/model/commandHandlers/filterContext/common.d.ts +6 -5
- package/esm/model/commandHandlers/filterContext/common.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/common.js +12 -18
- package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/dateFilter/changeDateFilterSelectionHandler.js +30 -36
- package/esm/model/commandHandlers/filterContext/filterViewHandler.d.ts +10 -0
- package/esm/model/commandHandlers/filterContext/filterViewHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/filterViewHandler.js +79 -24
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterConditionHandler.js +11 -17
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/measureValueFilter/changeMeasureValueFilterDimensionalityHandler.js +7 -10
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts +15 -0
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/expandActionsForTabSync.js +88 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts +11 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncRules.js +335 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts +52 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncSaga.js +60 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts +69 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/tabSyncScope.js +2 -0
- package/esm/model/commandHandlers/filterContext/tabSync/writtenTargets.d.ts +17 -0
- package/esm/model/commandHandlers/filterContext/tabSync/writtenTargets.d.ts.map +1 -0
- package/esm/model/commandHandlers/filterContext/tabSync/writtenTargets.js +79 -0
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts +2 -1
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +44 -9
- package/esm/model/commandHandlers/tabs/switchDashboardTabHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/tabs/switchDashboardTabHandler.js +3 -1
- package/esm/model/commands/filters.d.ts +16 -1
- package/esm/model/commands/filters.d.ts.map +1 -1
- package/esm/model/commands/filters.js +2 -1
- package/esm/model/commands/parameters.d.ts +20 -1
- package/esm/model/commands/parameters.d.ts.map +1 -1
- package/esm/model/commands/parameters.js +3 -1
- package/esm/model/events/base.d.ts +1 -1
- package/esm/model/events/base.d.ts.map +1 -1
- package/esm/model/events/index.d.ts +2 -1
- package/esm/model/events/index.d.ts.map +1 -1
- package/esm/model/events/insightEditor.d.ts +128 -0
- package/esm/model/events/insightEditor.d.ts.map +1 -0
- package/esm/model/events/insightEditor.js +74 -0
- package/esm/model/react/useInitializeDashboardStore.d.ts.map +1 -1
- package/esm/model/react/useInitializeDashboardStore.js +4 -9
- package/esm/model/store/config/configReducers.d.ts +4 -8
- package/esm/model/store/config/configReducers.d.ts.map +1 -1
- package/esm/model/store/config/configReducers.js +6 -12
- package/esm/model/store/config/configSelectors.d.ts +24 -0
- package/esm/model/store/config/configSelectors.d.ts.map +1 -1
- package/esm/model/store/config/configSelectors.js +30 -4
- package/esm/model/store/config/index.d.ts +2 -3
- package/esm/model/store/config/index.d.ts.map +1 -1
- package/esm/model/store/filterViews/filterViewsReducers.d.ts +8 -0
- package/esm/model/store/filterViews/filterViewsReducers.d.ts.map +1 -1
- package/esm/model/store/filterViews/filterViewsReducers.js +11 -0
- package/esm/model/store/filterViews/filterViewsReducersSelectors.d.ts +6 -0
- package/esm/model/store/filterViews/filterViewsReducersSelectors.d.ts.map +1 -1
- package/esm/model/store/filterViews/filterViewsReducersSelectors.js +6 -0
- package/esm/model/store/filterViews/filterViewsState.d.ts +6 -0
- package/esm/model/store/filterViews/filterViewsState.d.ts.map +1 -1
- package/esm/model/store/filterViews/index.d.ts +2 -0
- package/esm/model/store/filterViews/index.d.ts.map +1 -1
- package/esm/model/store/meta/metaSelectors.d.ts +7 -0
- package/esm/model/store/meta/metaSelectors.d.ts.map +1 -1
- package/esm/model/store/meta/metaSelectors.js +10 -0
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts +75 -5
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/attributeFilterConfigs/attributeFilterConfigsReducers.js +35 -60
- package/esm/model/store/tabs/dateFilterConfigs/dateFilterConfigsReducers.js +1 -1
- package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts +163 -31
- package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/filterContext/filterContextReducers.js +389 -529
- package/esm/model/store/tabs/filterContext/filterSync.d.ts +35 -13
- package/esm/model/store/tabs/filterContext/filterSync.d.ts.map +1 -1
- package/esm/model/store/tabs/filterContext/filterSync.js +79 -58
- package/esm/model/store/tabs/index.d.ts +18 -12
- package/esm/model/store/tabs/index.d.ts.map +1 -1
- package/esm/model/store/tabs/layout/layoutReducers.d.ts +1 -0
- package/esm/model/store/tabs/layout/layoutReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/measureValueFilterConfigs/measureValueFilterConfigsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts +16 -5
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.js +33 -7
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts +7 -0
- package/esm/model/store/tabs/parameters/parametersSelectors.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersSelectors.js +16 -0
- package/esm/model/store/tabs/tabsReducers.d.ts +8 -4
- package/esm/model/store/tabs/tabsReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/tabsReducers.js +15 -18
- package/esm/model/store/tabs/tabsState.d.ts +0 -10
- package/esm/model/store/tabs/tabsState.d.ts.map +1 -1
- package/esm/model/store/tabs/tabsState.js +0 -20
- package/esm/model/store/ui/index.d.ts +2 -0
- package/esm/model/store/ui/index.d.ts.map +1 -1
- package/esm/model/store/ui/uiReducers.d.ts +6 -0
- package/esm/model/store/ui/uiReducers.d.ts.map +1 -1
- package/esm/model/store/ui/uiReducers.js +8 -0
- package/esm/model/store/ui/uiSelectors.d.ts +7 -0
- package/esm/model/store/ui/uiSelectors.d.ts.map +1 -1
- package/esm/model/store/ui/uiSelectors.js +6 -0
- package/esm/model/store/ui/uiState.d.ts +5 -0
- package/esm/model/store/ui/uiState.d.ts.map +1 -1
- package/esm/model/store/ui/uiState.js +1 -0
- package/esm/model/types/commonTypes.d.ts +38 -22
- package/esm/model/types/commonTypes.d.ts.map +1 -1
- package/esm/model/types/insightEditorTypes.d.ts +43 -0
- package/esm/model/types/insightEditorTypes.d.ts.map +1 -0
- package/esm/model/types/insightEditorTypes.js +2 -0
- package/esm/model/utils/attributeFilterMatching.d.ts +10 -0
- package/esm/model/utils/attributeFilterMatching.d.ts.map +1 -1
- package/esm/model/utils/attributeFilterMatching.js +14 -3
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts +8 -0
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.d.ts.map +1 -1
- package/esm/model/utils/attributeFilterSelectionTypeCompatibility.js +14 -4
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/LiveRegionLastSelectContainer.d.ts +9 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/LiveRegionLastSelectContainer.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/LiveRegionLastSelectContainer.js +12 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelect.js +3 -3
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.js +14 -7
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectionDescription.d.ts +12 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectionDescription.d.ts.map +1 -0
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectionDescription.js +30 -0
- package/esm/presentation/automations/scheduledEmail/utils/users.d.ts +1 -0
- package/esm/presentation/automations/scheduledEmail/utils/users.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/utils/users.js +3 -0
- package/esm/presentation/automations/shared/automationFilters/utils.d.ts +4 -0
- package/esm/presentation/automations/shared/automationFilters/utils.d.ts.map +1 -1
- package/esm/presentation/automations/shared/automationFilters/utils.js +12 -5
- package/esm/presentation/dashboard/DashboardHeader/DashboardHeader.d.ts +1 -1
- package/esm/presentation/dashboard/DashboardHeader/DashboardHeader.d.ts.map +1 -1
- package/esm/presentation/dashboard/DashboardHeader/DashboardHeader.js +2 -11
- package/esm/presentation/dashboard/DashboardSidebar/CreationPanel.d.ts.map +1 -1
- package/esm/presentation/dashboard/DashboardSidebar/CreationPanel.js +10 -1
- package/esm/presentation/dashboard/DefaultDashboardContent/DashboardContentLoader.d.ts +5 -0
- package/esm/presentation/dashboard/DefaultDashboardContent/DashboardContentLoader.d.ts.map +1 -0
- package/esm/presentation/dashboard/DefaultDashboardContent/DashboardContentLoader.js +27 -0
- package/esm/presentation/dashboard/DefaultDashboardContent/DefaultDashboardMainContent.d.ts.map +1 -1
- package/esm/presentation/dashboard/DefaultDashboardContent/DefaultDashboardMainContent.js +7 -2
- package/esm/presentation/dashboard/components/DashboardAiComposingOverlay.d.ts +4 -0
- package/esm/presentation/dashboard/components/DashboardAiComposingOverlay.d.ts.map +1 -0
- package/esm/presentation/dashboard/components/DashboardAiComposingOverlay.js +151 -0
- package/esm/presentation/dashboard/components/DashboardInner.d.ts.map +1 -1
- package/esm/presentation/dashboard/components/DashboardInner.js +17 -14
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts +8 -0
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.d.ts.map +1 -0
- package/esm/presentation/dashboard/components/DashboardInteractionComposing.js +23 -0
- package/esm/presentation/dashboard/components/DashboardInteractionLock.d.ts +8 -0
- package/esm/presentation/dashboard/components/DashboardInteractionLock.d.ts.map +1 -0
- package/esm/presentation/dashboard/components/DashboardInteractionLock.js +29 -0
- package/esm/presentation/dashboard/hooks/useDashboard.d.ts.map +1 -1
- package/esm/presentation/dashboard/hooks/useDashboard.js +3 -2
- package/esm/presentation/dashboard/types.d.ts +5 -0
- package/esm/presentation/dashboard/types.d.ts.map +1 -1
- package/esm/presentation/dragAndDrop/draggableWidget/AddDashboardLayoutWidgetButton.d.ts.map +1 -1
- package/esm/presentation/dragAndDrop/draggableWidget/AddDashboardLayoutWidgetButton.js +2 -4
- package/esm/presentation/dragAndDrop/draggableWidget/AddRichTextWidgetButton.d.ts.map +1 -1
- package/esm/presentation/dragAndDrop/draggableWidget/AddRichTextWidgetButton.js +3 -3
- package/esm/presentation/dragAndDrop/draggableWidget/AddVisualizationSwitcherWidgetButton.d.ts.map +1 -1
- package/esm/presentation/dragAndDrop/draggableWidget/AddVisualizationSwitcherWidgetButton.js +2 -4
- package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AddAttributeFilterPlaceholder.d.ts.map +1 -1
- package/esm/presentation/filterBar/attributeFilter/addAttributeFilter/AddAttributeFilterPlaceholder.js +3 -2
- package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.d.ts.map +1 -1
- package/esm/presentation/filterBar/filterBar/hooks/useResetFiltersButton.js +4 -1
- package/esm/presentation/insightEditor/InsightEditorContent.d.ts +26 -0
- package/esm/presentation/insightEditor/InsightEditorContent.d.ts.map +1 -0
- package/esm/presentation/insightEditor/InsightEditorContent.js +179 -0
- package/esm/presentation/insightEditor/InsightEditorCreatePanelItem.d.ts +7 -0
- package/esm/presentation/insightEditor/InsightEditorCreatePanelItem.d.ts.map +1 -0
- package/esm/presentation/insightEditor/InsightEditorCreatePanelItem.js +25 -0
- package/esm/presentation/insightEditor/InsightEditorOverlay.d.ts +6 -0
- package/esm/presentation/insightEditor/InsightEditorOverlay.d.ts.map +1 -0
- package/esm/presentation/insightEditor/InsightEditorOverlay.js +110 -0
- package/esm/presentation/insightEditor/InsightEditorPermissionsContext.d.ts +10 -0
- package/esm/presentation/insightEditor/InsightEditorPermissionsContext.d.ts.map +1 -0
- package/esm/presentation/insightEditor/InsightEditorPermissionsContext.js +18 -0
- package/esm/presentation/insightEditor/InsightEditorPlaceholder.d.ts +7 -0
- package/esm/presentation/insightEditor/InsightEditorPlaceholder.d.ts.map +1 -0
- package/esm/presentation/insightEditor/InsightEditorPlaceholder.js +15 -0
- package/esm/presentation/insightEditor/filterContext/attributeFilters.d.ts +4 -0
- package/esm/presentation/insightEditor/filterContext/attributeFilters.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/attributeFilters.js +115 -0
- package/esm/presentation/insightEditor/filterContext/dateFilters.d.ts +5 -0
- package/esm/presentation/insightEditor/filterContext/dateFilters.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/dateFilters.js +117 -0
- package/esm/presentation/insightEditor/filterContext/filterIntersection.d.ts +7 -0
- package/esm/presentation/insightEditor/filterContext/filterIntersection.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/filterIntersection.js +149 -0
- package/esm/presentation/insightEditor/filterContext/insightFilterContext.d.ts +26 -0
- package/esm/presentation/insightEditor/filterContext/insightFilterContext.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/insightFilterContext.js +72 -0
- package/esm/presentation/insightEditor/filterContext/measureValueFilters.d.ts +20 -0
- package/esm/presentation/insightEditor/filterContext/measureValueFilters.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/measureValueFilters.js +76 -0
- package/esm/presentation/insightEditor/filterContext/objQualifiers.d.ts +11 -0
- package/esm/presentation/insightEditor/filterContext/objQualifiers.d.ts.map +1 -0
- package/esm/presentation/insightEditor/filterContext/objQualifiers.js +18 -0
- package/esm/presentation/insightEditor/insightEditorEscapeGuard.d.ts +18 -0
- package/esm/presentation/insightEditor/insightEditorEscapeGuard.d.ts.map +1 -0
- package/esm/presentation/insightEditor/insightEditorEscapeGuard.js +24 -0
- package/esm/presentation/insightEditor/insightEditorRoute.d.ts +34 -0
- package/esm/presentation/insightEditor/insightEditorRoute.d.ts.map +1 -0
- package/esm/presentation/insightEditor/insightEditorRoute.js +48 -0
- package/esm/presentation/insightEditor/types.d.ts +7 -0
- package/esm/presentation/insightEditor/types.d.ts.map +1 -0
- package/esm/presentation/insightEditor/types.js +2 -0
- package/esm/presentation/insightEditor/useCanCreateInsightInEditor.d.ts +5 -0
- package/esm/presentation/insightEditor/useCanCreateInsightInEditor.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useCanCreateInsightInEditor.js +14 -0
- package/esm/presentation/insightEditor/useExploreFilterTransfer.d.ts +21 -0
- package/esm/presentation/insightEditor/useExploreFilterTransfer.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useExploreFilterTransfer.js +193 -0
- package/esm/presentation/insightEditor/useInsightEditPermissions.d.ts +17 -0
- package/esm/presentation/insightEditor/useInsightEditPermissions.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useInsightEditPermissions.js +42 -0
- package/esm/presentation/insightEditor/useInsightEditorMenuItems.d.ts +23 -0
- package/esm/presentation/insightEditor/useInsightEditorMenuItems.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useInsightEditorMenuItems.js +126 -0
- package/esm/presentation/insightEditor/useInsightEditorSession.d.ts +19 -0
- package/esm/presentation/insightEditor/useInsightEditorSession.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useInsightEditorSession.js +141 -0
- package/esm/presentation/insightList/InsightList.d.ts.map +1 -1
- package/esm/presentation/insightList/InsightList.js +10 -5
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/de-DE.localization-bundle.js +48 -42
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.js +11 -5
- package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +56 -0
- package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/en-US.localization-bundle.js +56 -0
- package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/es-419.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.js +187 -181
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.js +6 -0
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +6 -0
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts.map +1 -1
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.js +7 -1
- package/esm/presentation/topBar/buttonBar/button/saveAsButton/DefaultSaveAsNewButton.d.ts.map +1 -1
- package/esm/presentation/topBar/buttonBar/button/saveAsButton/DefaultSaveAsNewButton.js +3 -2
- package/esm/presentation/topBar/buttonBar/button/saveButton/DefaultSaveButton.d.ts.map +1 -1
- package/esm/presentation/topBar/buttonBar/button/saveButton/DefaultSaveButton.js +3 -2
- package/esm/presentation/topBar/buttonBar/button/settingButton/DefaultSettingButton.d.ts.map +1 -1
- package/esm/presentation/topBar/buttonBar/button/settingButton/DefaultSettingButton.js +3 -2
- package/esm/presentation/topBar/buttonBar/button/shareButton/DefaultShareButton.d.ts.map +1 -1
- package/esm/presentation/topBar/buttonBar/button/shareButton/DefaultShareButton.js +3 -2
- package/esm/presentation/topBar/title/EditableTitle.d.ts.map +1 -1
- package/esm/presentation/topBar/title/EditableTitle.js +6 -0
- package/esm/presentation/widget/insight/DefaultDashboardInsightComponentSetFactory.d.ts +1 -1
- package/esm/presentation/widget/insight/DefaultDashboardInsightComponentSetFactory.d.ts.map +1 -1
- package/esm/presentation/widget/insight/DefaultDashboardInsightComponentSetFactory.js +13 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.d.ts.map +1 -1
- package/esm/presentation/widget/insightMenu/DefaultDashboardInsightMenu/DashboardInsightMenu/index.js +10 -1
- package/esm/presentation/widget/richText/EditModeDashboardRichText.js +1 -1
- package/esm/presentation/widget/visualizationSwitcher/EditModeDashboardVisualizationSwitcher.js +1 -1
- package/esm/presentation/widget/visualizationSwitcher/configuration/ToolbarTop.js +2 -2
- package/esm/presentation/widget/widget/InsightWidget/useEditableInsightMenu.d.ts.map +1 -1
- package/esm/presentation/widget/widget/InsightWidget/useEditableInsightMenu.js +5 -1
- package/esm/presentation/widget/widget/InsightWidget/useInsightMenu.d.ts.map +1 -1
- package/esm/presentation/widget/widget/InsightWidget/useInsightMenu.js +4 -1
- package/esm/sdk-ui-dashboard.d.ts +596 -69
- package/package.json +23 -21
- package/styles/css/alerting.css +1 -1
- package/styles/css/alerting.css.map +1 -1
- package/styles/css/attributeFilterConfig.css +3 -3
- package/styles/css/automationFilters.css +1 -1
- package/styles/css/configurationPanel.css +2 -2
- package/styles/css/configurationPanel.css.map +1 -1
- package/styles/css/dashboard.css +141 -87
- package/styles/css/dashboard.css.map +1 -1
- package/styles/css/dashboardContentLoader.css +45 -0
- package/styles/css/dashboardContentLoader.css.map +1 -0
- package/styles/css/dashboardNestedLayoutToolbar.css.map +1 -1
- package/styles/css/dashboardNestedLayoutWidget.css +1 -1
- package/styles/css/dashboardSettingsDialog.css +1 -1
- package/styles/css/dragAndDrop.css +0 -8
- package/styles/css/dragAndDrop.css.map +1 -1
- package/styles/css/drillConfigPanel.css +7 -7
- package/styles/css/drillConfigPanel.css.map +1 -1
- package/styles/css/filterBar.css +4 -4
- package/styles/css/filterBar.css.map +1 -1
- package/styles/css/grouped-navigation.css +2 -2
- package/styles/css/grouped-navigation.css.map +1 -1
- package/styles/css/icons.css.map +1 -1
- package/styles/css/insightConfiguration.css +1 -1
- package/styles/css/insightConfiguration.css.map +1 -1
- package/styles/css/insightEditor.css +46 -0
- package/styles/css/insightEditor.css.map +1 -0
- package/styles/css/kpi.css +2 -2
- package/styles/css/kpi.css.map +1 -1
- package/styles/css/kpi_alert_dialog.css +2 -2
- package/styles/css/layout.css +5 -5
- package/styles/css/layout.css.map +1 -1
- package/styles/css/main.css +336 -219
- package/styles/css/main.css.map +1 -1
- package/styles/css/notifications_channels_dialog.css +2 -2
- package/styles/css/notifications_channels_dialog.css.map +1 -1
- package/styles/css/resizing.css.map +1 -1
- package/styles/css/richTextWidget.css.map +1 -1
- package/styles/css/saveAsDialog.css.map +1 -1
- package/styles/css/sidebar.css +35 -10
- package/styles/css/sidebar.css.map +1 -1
- package/styles/css/topBar.css.map +1 -1
- package/styles/css/visualization.css.map +1 -1
- package/styles/css/visualizationSwitcherHeader.css.map +1 -1
- package/styles/css/visualizationSwitcherToolbar.css +1 -1
- package/styles/css/visualizationSwitcherToolbar.css.map +1 -1
- package/styles/css/visualizationSwitcherWidget.css +1 -1
- package/styles/css/visualizationSwitcherWidget.css.map +1 -1
- package/styles/scss/_variables.scss +3 -2
- package/styles/scss/_zIndexes.scss +4 -0
- package/styles/scss/attributeFilterConfig.scss +1 -1
- package/styles/scss/configurationPanel.scss +1 -1
- package/styles/scss/dashboard.scss +104 -96
- package/styles/scss/dashboardContentLoader.scss +45 -0
- package/styles/scss/dragAndDrop.scss +2 -9
- package/styles/scss/drillConfigPanel.scss +3 -3
- package/styles/scss/insightEditor.scss +53 -0
- package/styles/scss/layout.scss +1 -1
- package/styles/scss/main.scss +1 -0
- package/styles/scss/sidebar.scss +47 -12
- package/esm/presentation/dashboard/components/DashboardSkeleton.d.ts +0 -5
- package/esm/presentation/dashboard/components/DashboardSkeleton.d.ts.map +0 -1
- package/esm/presentation/dashboard/components/DashboardSkeleton.js +0 -20
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
// (C) 2021-2026 GoodData Corporation
|
|
2
|
+
import { cloneDeep } from "lodash-es";
|
|
2
3
|
import { invariant } from "ts-invariant";
|
|
3
|
-
import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemLocalIdentifier, dashboardFilterLocalIdentifier,
|
|
4
|
+
import { areObjRefsEqual, attributeElementsIsEmpty, dashboardAttributeFilterItemDisplayForm, dashboardAttributeFilterItemLocalIdentifier, dashboardFilterLocalIdentifier, isAttributeElementsByRef, isDashboardArbitraryAttributeFilter, isDashboardAttributeFilter, isDashboardAttributeFilterItem, isDashboardCommonDateFilter, isDashboardDateFilter, isDashboardDateFilterWithDimension, isDashboardMatchAttributeFilter, isDashboardMeasureValueFilter, isIdentifierRef, newAllTimeDashboardDateFilter, } from "@gooddata/sdk-model";
|
|
5
|
+
import { isDisplayFormMetadataReferencedBy } from "../../../utils/attributeFilterMatching.js";
|
|
4
6
|
import { generateFilterLocalIdentifier, generateMeasureValueFilterLocalIdentifier, } from "../../_infra/generators.js";
|
|
5
|
-
import { getActiveTab, getTabOrActive
|
|
6
|
-
import { filterContextInitialState } from "./filterContextState.js";
|
|
7
|
+
import { getActiveTab, getTabOrActive } from "../tabsState.js";
|
|
8
|
+
import { filterContextInitialState, } from "./filterContextState.js";
|
|
7
9
|
import { applyFilterContext, initializeFilterContext } from "./filterContextUtils.js";
|
|
8
|
-
import {
|
|
10
|
+
import { findOriginalFilter, preserveFilterDependencies } from "./filterSync.js";
|
|
11
|
+
/**
|
|
12
|
+
* Filter context of the tab addressed by `tabLocalIdentifier`, or of the active tab when omitted.
|
|
13
|
+
* Initializes an empty filter context on a tab that has none.
|
|
14
|
+
*/
|
|
15
|
+
function getTabFilterContext(state, tabLocalIdentifier) {
|
|
16
|
+
const tab = getTabOrActive(state, tabLocalIdentifier);
|
|
17
|
+
if (!tab) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
if (!tab.filterContext) {
|
|
21
|
+
tab.filterContext = { ...filterContextInitialState };
|
|
22
|
+
}
|
|
23
|
+
return { tab, filterContext: tab.filterContext };
|
|
24
|
+
}
|
|
25
|
+
function getEditableFilterContext(state, tabLocalIdentifier) {
|
|
26
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
27
|
+
if (!target) {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const definition = target.filterContext.filterContextDefinition;
|
|
31
|
+
invariant(definition, "Attempt to edit uninitialized filter context");
|
|
32
|
+
return { ...target, definition };
|
|
33
|
+
}
|
|
9
34
|
const setFilterContext = (state, action) => {
|
|
10
35
|
const activeTab = getActiveTab(state);
|
|
11
36
|
if (!activeTab) {
|
|
@@ -46,42 +71,34 @@ const updateFilterContextIdentityForTab = (state, action) => {
|
|
|
46
71
|
}
|
|
47
72
|
tab.filterContext.filterContextIdentity = filterContextIdentity;
|
|
48
73
|
};
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
74
|
const removeAttributeFilterDisplayForms = (state, action) => {
|
|
53
|
-
const
|
|
54
|
-
|
|
75
|
+
const { displayForm, tabLocalIdentifier } = action.payload;
|
|
76
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
77
|
+
if (!target) {
|
|
55
78
|
return;
|
|
56
79
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
80
|
+
const { filterContext } = target;
|
|
81
|
+
invariant(filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
82
|
+
// A cross-filtering virtual filter shares its display form with the dashboard filter it duplicates.
|
|
83
|
+
const usedDisplayForms = (filterContext.filterContextDefinition?.filters ?? [])
|
|
84
|
+
.filter(isDashboardAttributeFilterItem)
|
|
85
|
+
.map(dashboardAttributeFilterItemDisplayForm);
|
|
86
|
+
filterContext.attributeFilterDisplayForms = filterContext.attributeFilterDisplayForms.filter((df) => !isDisplayFormMetadataReferencedBy(df, displayForm) ||
|
|
87
|
+
usedDisplayForms.some((used) => isDisplayFormMetadataReferencedBy(df, used)));
|
|
65
88
|
};
|
|
66
89
|
const addAttributeFilterDisplayForm = (state, action) => {
|
|
67
90
|
// Handle both old and new payload formats for backward compatibility
|
|
68
91
|
const displayForm = "displayForm" in action.payload ? action.payload.displayForm : action.payload;
|
|
69
92
|
const tabLocalIdentifier = "tabLocalIdentifier" in action.payload ? action.payload.tabLocalIdentifier : undefined;
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
93
|
+
const target = getTabFilterContext(state, tabLocalIdentifier);
|
|
94
|
+
if (!target) {
|
|
72
95
|
return;
|
|
73
96
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
invariant(targetTab.filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
97
|
+
const { filterContext } = target;
|
|
98
|
+
invariant(filterContext.attributeFilterDisplayForms, "attempting to work with uninitialized state");
|
|
78
99
|
// if there is already a display form with the same ref, replace it
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
targetTab.filterContext.attributeFilterDisplayForms =
|
|
82
|
-
targetTab.filterContext.attributeFilterDisplayForms.filter((df) => !areObjRefsEqual(df, displayForm));
|
|
83
|
-
}
|
|
84
|
-
targetTab.filterContext.attributeFilterDisplayForms.push(displayForm);
|
|
100
|
+
filterContext.attributeFilterDisplayForms = filterContext.attributeFilterDisplayForms.filter((df) => !isDisplayFormMetadataReferencedBy(df, displayForm.ref));
|
|
101
|
+
filterContext.attributeFilterDisplayForms.push(displayForm);
|
|
85
102
|
};
|
|
86
103
|
//
|
|
87
104
|
//
|
|
@@ -92,88 +109,19 @@ const setPreloadedAttributesWithReferences = (state, action) => {
|
|
|
92
109
|
state.attributesWithReferences = action.payload;
|
|
93
110
|
};
|
|
94
111
|
const upsertDateFilter = (state, action) => {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
const source = tabs[0];
|
|
98
|
-
if (!source) {
|
|
112
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
113
|
+
if (!tab) {
|
|
99
114
|
return;
|
|
100
115
|
}
|
|
101
|
-
upsertDateFilterOnTab(
|
|
102
|
-
for (const tab of tabs.slice(1)) {
|
|
103
|
-
const payload = action.payload.restoreTargetOriginal
|
|
104
|
-
? restoredDateFilterPayload(tab, action.payload)
|
|
105
|
-
: action.payload;
|
|
106
|
-
if (!payload) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
upsertDateFilterOnTab(tab, payload, false);
|
|
110
|
-
}
|
|
116
|
+
upsertDateFilterOnTab(tab, action.payload);
|
|
111
117
|
};
|
|
112
|
-
|
|
113
|
-
* Saved date filter for a non-source tab during reset.
|
|
114
|
-
* A common date filter with no saved original is all time, which is stored as the filter's absence.
|
|
115
|
-
* A dimension date filter with no counterpart, or no saved original, is left unchanged.
|
|
116
|
-
*/
|
|
117
|
-
function restoredDateFilterPayload(tab, payload) {
|
|
118
|
-
const applied = findAppliedDateFilter(tab, payload.dataSet);
|
|
119
|
-
if (!applied && payload.dataSet) {
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
const original = findOriginalFilter(tab, applied ?? {
|
|
123
|
-
dateFilter: { type: "relative", granularity: "GDC.time.date" },
|
|
124
|
-
});
|
|
125
|
-
if (isDashboardDateFilter(original)) {
|
|
126
|
-
return toUpsertDateFilterPayload(original, payload);
|
|
127
|
-
}
|
|
128
|
-
if (!payload.dataSet) {
|
|
129
|
-
return { type: "allTime" };
|
|
130
|
-
}
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
function findAppliedDateFilter(tab, dataSet) {
|
|
134
|
-
const filters = tab.filterContext?.filterContextDefinition?.filters;
|
|
135
|
-
if (!filters) {
|
|
136
|
-
return undefined;
|
|
137
|
-
}
|
|
138
|
-
if (dataSet) {
|
|
139
|
-
return filters.find((item) => isDashboardDateFilter(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
140
|
-
}
|
|
141
|
-
return filters.find(isDashboardCommonDateFilter);
|
|
142
|
-
}
|
|
143
|
-
function toUpsertDateFilterPayload(filter, source) {
|
|
144
|
-
const { dataSet, localIdentifier, emptyValueHandling, boundedFilter, type, granularity, from, to } = filter.dateFilter;
|
|
145
|
-
const shared = {
|
|
146
|
-
...(dataSet ? { dataSet } : {}),
|
|
147
|
-
...(localIdentifier ? { localIdentifier } : {}),
|
|
148
|
-
...(emptyValueHandling ? { emptyValueHandling } : {}),
|
|
149
|
-
...(source.isWorkingSelectionChange ? { isWorkingSelectionChange: true } : {}),
|
|
150
|
-
...(source.tabLocalIdentifier ? { tabLocalIdentifier: source.tabLocalIdentifier } : {}),
|
|
151
|
-
};
|
|
152
|
-
if (isAllTimeDashboardDateFilter(filter)) {
|
|
153
|
-
return { type: "allTime", ...shared };
|
|
154
|
-
}
|
|
155
|
-
return {
|
|
156
|
-
type,
|
|
157
|
-
granularity,
|
|
158
|
-
from,
|
|
159
|
-
to,
|
|
160
|
-
...(boundedFilter ? { boundedFilter } : {}),
|
|
161
|
-
...shared,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
118
|
+
function upsertDateFilterOnTab(targetTab, payload) {
|
|
165
119
|
if (!targetTab.filterContext) {
|
|
166
|
-
if (!isSource) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
120
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
170
121
|
}
|
|
171
122
|
const filterContextDefinition = payload.isWorkingSelectionChange
|
|
172
123
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
173
124
|
: targetTab.filterContext.filterContextDefinition;
|
|
174
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
125
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
178
126
|
const dateDataSet = payload.dataSet;
|
|
179
127
|
let existingFilterIndex = -1;
|
|
@@ -183,9 +131,6 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
183
131
|
else {
|
|
184
132
|
existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardCommonDateFilter(item));
|
|
185
133
|
}
|
|
186
|
-
if (!isSource && existingFilterIndex < 0 && dateDataSet) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
134
|
if (payload.isWorkingSelectionChange && payload.type === "allTime") {
|
|
190
135
|
// we need to allways set working filter to distinguish between "not changed" and "all time" filter
|
|
191
136
|
if (existingFilterIndex >= 0) {
|
|
@@ -207,15 +152,9 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
207
152
|
}
|
|
208
153
|
}
|
|
209
154
|
else {
|
|
210
|
-
const existing = filterContextDefinition.filters[existingFilterIndex];
|
|
211
|
-
const preservedLocalIdentifier = isSource
|
|
212
|
-
? payload.localIdentifier
|
|
213
|
-
: isDashboardDateFilter(existing)
|
|
214
|
-
? existing.dateFilter.localIdentifier
|
|
215
|
-
: undefined;
|
|
216
155
|
if (payload.emptyValueHandling) {
|
|
217
156
|
// Preserve all-time common DF when it carries additional config (e.g. emptyValueHandling).
|
|
218
|
-
filterContextDefinition.filters[existingFilterIndex] = newAllTimeDashboardDateFilter(undefined,
|
|
157
|
+
filterContextDefinition.filters[existingFilterIndex] = newAllTimeDashboardDateFilter(undefined, payload.localIdentifier, payload.emptyValueHandling);
|
|
219
158
|
}
|
|
220
159
|
else {
|
|
221
160
|
// if allTime common DF remove the date filter altogether
|
|
@@ -236,7 +175,7 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
236
175
|
dateFilter.dateFilter.granularity = granularity;
|
|
237
176
|
dateFilter.dateFilter.from = from;
|
|
238
177
|
dateFilter.dateFilter.to = to;
|
|
239
|
-
if (localIdentifier
|
|
178
|
+
if (localIdentifier) {
|
|
240
179
|
dateFilter.dateFilter.localIdentifier = localIdentifier;
|
|
241
180
|
}
|
|
242
181
|
if (boundedFilter) {
|
|
@@ -253,7 +192,7 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
253
192
|
}
|
|
254
193
|
}
|
|
255
194
|
}
|
|
256
|
-
else
|
|
195
|
+
else {
|
|
257
196
|
const { type, granularity, from, to, dataSet, localIdentifier, boundedFilter, emptyValueHandling } = payload;
|
|
258
197
|
filterContextDefinition.filters.unshift({
|
|
259
198
|
dateFilter: {
|
|
@@ -270,69 +209,22 @@ function upsertDateFilterOnTab(targetTab, payload, isSource) {
|
|
|
270
209
|
}
|
|
271
210
|
}
|
|
272
211
|
const updateAttributeFilterSelection = (state, action) => {
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
const source = tabs[0];
|
|
276
|
-
if (!source) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
const sourceFilter = findAppliedFilterByLocalId(source, action.payload.filterLocalId);
|
|
280
|
-
updateAttributeFilterSelectionOnTab(source, action.payload, action.payload.filterLocalId, true);
|
|
281
|
-
if (tabs.length === 1 ||
|
|
282
|
-
!sourceFilter ||
|
|
283
|
-
!isDashboardAttributeFilter(sourceFilter) ||
|
|
284
|
-
isCrossFilteringVirtualFilter(source, action.payload.filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
212
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
213
|
+
if (!tab) {
|
|
285
214
|
return;
|
|
286
215
|
}
|
|
287
|
-
|
|
288
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences, {
|
|
289
|
-
allowListToText: false,
|
|
290
|
-
crossFilteringLocalIdsByTab,
|
|
291
|
-
});
|
|
292
|
-
if (!match || !isDashboardAttributeFilter(match)) {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
const targetLocalId = match.attributeFilter.localIdentifier;
|
|
296
|
-
if (!targetLocalId) {
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
const original = action.payload.restoreTargetOriginal ? findOriginalFilter(tab, match) : undefined;
|
|
300
|
-
if (action.payload.restoreTargetOriginal && !isDashboardAttributeFilter(original)) {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
updateAttributeFilterSelectionOnTab(tab, {
|
|
304
|
-
...action.payload,
|
|
305
|
-
filterLocalId: targetLocalId,
|
|
306
|
-
...(isDashboardAttributeFilter(original)
|
|
307
|
-
? {
|
|
308
|
-
elements: original.attributeFilter.attributeElements,
|
|
309
|
-
negativeSelection: original.attributeFilter.negativeSelection,
|
|
310
|
-
}
|
|
311
|
-
: {}),
|
|
312
|
-
enableImmediateAttributeFilterDisplayAsLabelMigration: false,
|
|
313
|
-
isResultOfMigration: false,
|
|
314
|
-
}, targetLocalId, false);
|
|
315
|
-
}
|
|
216
|
+
updateAttributeFilterSelectionOnTab(tab, action.payload);
|
|
316
217
|
};
|
|
317
|
-
function updateAttributeFilterSelectionOnTab(targetTab, payload
|
|
218
|
+
function updateAttributeFilterSelectionOnTab(targetTab, payload) {
|
|
318
219
|
if (!targetTab.filterContext) {
|
|
319
|
-
if (!isSource) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
220
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
323
221
|
}
|
|
324
|
-
const { elements, negativeSelection, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, isSelectionInvalid, } = payload;
|
|
222
|
+
const { filterLocalId, elements, negativeSelection, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, isSelectionInvalid, } = payload;
|
|
325
223
|
const filterContextDefinition = isWorkingSelectionChange
|
|
326
224
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
327
225
|
: targetTab.filterContext.filterContextDefinition;
|
|
328
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
226
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
332
227
|
const existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
333
|
-
if (!isSource && existingFilterIndex < 0) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
228
|
invariant(existingFilterIndex >= 0 || isWorkingSelectionChange, "Attempt to update non-existing filter");
|
|
337
229
|
if (isWorkingSelectionChange && existingFilterIndex >= 0) {
|
|
338
230
|
filterContextDefinition.filters[existingFilterIndex] = {
|
|
@@ -393,60 +285,23 @@ function findAppliedFilterByLocalId(tab, localIdentifier) {
|
|
|
393
285
|
return tab.filterContext?.filterContextDefinition?.filters.find((item) => dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
394
286
|
}
|
|
395
287
|
const replaceAttributeFilterItem = (state, action) => {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
const source = tabs[0];
|
|
399
|
-
if (!source) {
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
const sourceFilter = findAppliedFilterByLocalId(source, action.payload.filterLocalId);
|
|
403
|
-
replaceAttributeFilterItemOnTab(source, action.payload, action.payload.filter, true);
|
|
404
|
-
if (tabs.length === 1 ||
|
|
405
|
-
!sourceFilter ||
|
|
406
|
-
!isDashboardAttributeFilterItem(sourceFilter) ||
|
|
407
|
-
isCrossFilteringVirtualFilter(source, action.payload.filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
288
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
289
|
+
if (!tab) {
|
|
408
290
|
return;
|
|
409
291
|
}
|
|
410
|
-
|
|
411
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences, {
|
|
412
|
-
allowListToText: true,
|
|
413
|
-
crossFilteringLocalIdsByTab,
|
|
414
|
-
});
|
|
415
|
-
if (!match || !isDashboardAttributeFilterItem(match)) {
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
const targetLocalId = dashboardAttributeFilterItemLocalIdentifier(match);
|
|
419
|
-
if (!targetLocalId) {
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
const original = action.payload.restoreTargetOriginal ? findOriginalFilter(tab, match) : undefined;
|
|
423
|
-
if (action.payload.restoreTargetOriginal && !isDashboardAttributeFilterItem(original)) {
|
|
424
|
-
continue;
|
|
425
|
-
}
|
|
426
|
-
const replacement = isDashboardAttributeFilterItem(original) ? original : action.payload.filter;
|
|
427
|
-
replaceAttributeFilterItemOnTab(tab, { ...action.payload, filterLocalId: targetLocalId }, retargetAttributeFilterItem(replacement, targetLocalId), false);
|
|
428
|
-
}
|
|
292
|
+
replaceAttributeFilterItemOnTab(tab, action.payload);
|
|
429
293
|
};
|
|
430
|
-
function replaceAttributeFilterItemOnTab(targetTab, payload
|
|
294
|
+
function replaceAttributeFilterItemOnTab(targetTab, payload) {
|
|
431
295
|
if (!targetTab.filterContext) {
|
|
432
|
-
if (!isSource) {
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
296
|
targetTab.filterContext = { ...filterContextInitialState };
|
|
436
297
|
}
|
|
437
|
-
const { filterLocalId, isWorkingSelectionChange, isSelectionInvalid } = payload;
|
|
298
|
+
const { filterLocalId, filter, isWorkingSelectionChange, isSelectionInvalid } = payload;
|
|
438
299
|
const filterContextDefinition = isWorkingSelectionChange
|
|
439
300
|
? targetTab.filterContext.workingFilterContextDefinition
|
|
440
301
|
: targetTab.filterContext.filterContextDefinition;
|
|
441
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
302
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
445
303
|
const existingFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilterItem(item) &&
|
|
446
304
|
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
447
|
-
if (!isSource && existingFilterIndex < 0) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
305
|
// Preserve parent filter relationships from the existing filter when replacing.
|
|
451
306
|
// The replacement filter typically only carries selection data, not dependency configuration.
|
|
452
307
|
const replacementFilter = existingFilterIndex >= 0
|
|
@@ -480,17 +335,14 @@ function replaceAttributeFilterItemOnTab(targetTab, payload, filter, isSource) {
|
|
|
480
335
|
}
|
|
481
336
|
}
|
|
482
337
|
const addAttributeFilter = (state, action) => {
|
|
483
|
-
const
|
|
484
|
-
if (!
|
|
338
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
339
|
+
if (!target) {
|
|
485
340
|
return;
|
|
486
341
|
}
|
|
487
|
-
if (!activeTab.filterContext) {
|
|
488
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
489
|
-
}
|
|
490
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
491
342
|
const { displayForm, index, initialIsNegativeSelection, initialSelection, parentFilters, selectionMode, localIdentifier, title, } = action.payload;
|
|
343
|
+
const { definition } = target;
|
|
492
344
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
493
|
-
const isDateFilterPresent =
|
|
345
|
+
const isDateFilterPresent = definition.filters.findIndex(isDashboardDateFilter) >= 0;
|
|
494
346
|
const hasSelection = initialSelection && !attributeElementsIsEmpty(initialSelection);
|
|
495
347
|
const isNegative = selectionMode !== "single" && (initialIsNegativeSelection || !hasSelection);
|
|
496
348
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
@@ -500,117 +352,152 @@ const addAttributeFilter = (state, action) => {
|
|
|
500
352
|
attributeElements: initialSelection ?? { uris: [] },
|
|
501
353
|
displayForm,
|
|
502
354
|
negativeSelection: isNegative,
|
|
503
|
-
localIdentifier: localIdentifier
|
|
504
|
-
generateFilterLocalIdentifier(displayForm, Math.max(0, attributeFilterIndex)),
|
|
355
|
+
localIdentifier: resolveAttributeFilterLocalIdentifier(definition, displayForm, attributeFilterIndex, localIdentifier),
|
|
505
356
|
filterElementsBy: parentFilters ? [...parentFilters] : undefined,
|
|
506
357
|
...(selectionMode === undefined ? {} : { selectionMode }),
|
|
507
358
|
title,
|
|
508
359
|
},
|
|
509
360
|
};
|
|
510
361
|
if (index === -1) {
|
|
511
|
-
|
|
362
|
+
definition.filters.push(filter);
|
|
512
363
|
}
|
|
513
364
|
else {
|
|
514
|
-
|
|
365
|
+
definition.filters.splice(attributeFilterIndex, 0, filter);
|
|
515
366
|
}
|
|
516
367
|
};
|
|
517
368
|
const addTextAttributeFilter = (state, action) => {
|
|
518
|
-
const
|
|
519
|
-
if (!
|
|
369
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
370
|
+
if (!target) {
|
|
520
371
|
return;
|
|
521
372
|
}
|
|
522
|
-
if (!activeTab.filterContext) {
|
|
523
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
524
|
-
}
|
|
525
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
526
373
|
const { filter, index } = action.payload;
|
|
374
|
+
const { definition } = target;
|
|
527
375
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
528
|
-
const isDateFilterPresent =
|
|
376
|
+
const isDateFilterPresent = definition.filters.findIndex(isDashboardDateFilter) >= 0;
|
|
529
377
|
const attributeFilterIndex = isDateFilterPresent ? index + 1 : index;
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
378
|
+
const filterWithLocalIdentifier = withAttributeFilterLocalIdentifier(filter, resolveAttributeFilterLocalIdentifier(definition, dashboardAttributeFilterItemDisplayForm(filter), attributeFilterIndex, dashboardAttributeFilterItemLocalIdentifier(filter)));
|
|
379
|
+
if (!filterWithLocalIdentifier) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (index === -1) {
|
|
383
|
+
definition.filters.push(filterWithLocalIdentifier);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
definition.filters.splice(attributeFilterIndex, 0, filterWithLocalIdentifier);
|
|
387
|
+
}
|
|
388
|
+
};
|
|
389
|
+
function withAttributeFilterLocalIdentifier(filter, localIdentifier) {
|
|
390
|
+
if (isDashboardArbitraryAttributeFilter(filter)) {
|
|
391
|
+
return {
|
|
533
392
|
arbitraryAttributeFilter: {
|
|
534
393
|
...filter.arbitraryAttributeFilter,
|
|
535
|
-
localIdentifier
|
|
536
|
-
|
|
394
|
+
localIdentifier,
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
if (isDashboardMatchAttributeFilter(filter)) {
|
|
399
|
+
return {
|
|
400
|
+
matchAttributeFilter: {
|
|
401
|
+
...filter.matchAttributeFilter,
|
|
402
|
+
localIdentifier,
|
|
537
403
|
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Keeps `preferred` unless another filter on the tab already uses it, otherwise generates
|
|
410
|
+
* the first free identifier. A filter mirrored from another tab can collide with a local one.
|
|
411
|
+
*/
|
|
412
|
+
function resolveAttributeFilterLocalIdentifier(definition, displayForm, index, preferred) {
|
|
413
|
+
return resolveFilterLocalIdentifier(definition, (candidateIndex) => generateFilterLocalIdentifier(displayForm, candidateIndex), index, preferred);
|
|
414
|
+
}
|
|
415
|
+
function resolveFilterLocalIdentifier(definition, generate, index, preferred) {
|
|
416
|
+
const used = new Set();
|
|
417
|
+
for (const item of definition.filters) {
|
|
418
|
+
const localIdentifier = dashboardFilterLocalIdentifier(item);
|
|
419
|
+
if (localIdentifier) {
|
|
420
|
+
used.add(localIdentifier);
|
|
538
421
|
}
|
|
539
|
-
: isDashboardMatchAttributeFilter(filter)
|
|
540
|
-
? {
|
|
541
|
-
matchAttributeFilter: {
|
|
542
|
-
...filter.matchAttributeFilter,
|
|
543
|
-
localIdentifier: filter.matchAttributeFilter.localIdentifier ??
|
|
544
|
-
generateFilterLocalIdentifier(filter.matchAttributeFilter.displayForm, generatedLocalIdentifierIndex),
|
|
545
|
-
},
|
|
546
|
-
}
|
|
547
|
-
: filter;
|
|
548
|
-
if (index === -1) {
|
|
549
|
-
activeTab.filterContext.filterContextDefinition.filters.push(filterWithLocalIdentifier);
|
|
550
422
|
}
|
|
551
|
-
|
|
552
|
-
|
|
423
|
+
if (preferred && !used.has(preferred)) {
|
|
424
|
+
return preferred;
|
|
553
425
|
}
|
|
554
|
-
|
|
426
|
+
let candidateIndex = Math.max(0, index);
|
|
427
|
+
let localIdentifier = generate(candidateIndex);
|
|
428
|
+
while (used.has(localIdentifier)) {
|
|
429
|
+
candidateIndex += 1;
|
|
430
|
+
localIdentifier = generate(candidateIndex);
|
|
431
|
+
}
|
|
432
|
+
return localIdentifier;
|
|
433
|
+
}
|
|
555
434
|
const removeAttributeFilter = (state, action) => {
|
|
556
|
-
const
|
|
557
|
-
if (!
|
|
435
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
436
|
+
if (!target) {
|
|
558
437
|
return;
|
|
559
438
|
}
|
|
560
|
-
if (!activeTab.filterContext) {
|
|
561
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
562
|
-
}
|
|
563
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
564
439
|
const { filterLocalId } = action.payload;
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
440
|
+
const { filterContext, definition } = target;
|
|
441
|
+
filterContext.filterContextDefinition = {
|
|
442
|
+
...definition,
|
|
443
|
+
filters: definition.filters.filter((item) => isDashboardDateFilter(item) ||
|
|
444
|
+
!isDashboardAttributeFilterItem(item) ||
|
|
445
|
+
dashboardAttributeFilterItemLocalIdentifier(item) !== filterLocalId),
|
|
571
446
|
};
|
|
447
|
+
removeAttributeFilterParentReferences(filterContext.filterContextDefinition, filterLocalId);
|
|
572
448
|
};
|
|
449
|
+
/**
|
|
450
|
+
* Drops parent references to a removed filter, including children that exist only on this tab.
|
|
451
|
+
*/
|
|
452
|
+
function removeAttributeFilterParentReferences(definition, removedLocalId) {
|
|
453
|
+
for (const item of definition.filters) {
|
|
454
|
+
if (isDashboardAttributeFilter(item) && item.attributeFilter.filterElementsBy) {
|
|
455
|
+
const remaining = item.attributeFilter.filterElementsBy.filter((parent) => parent.filterLocalIdentifier !== removedLocalId);
|
|
456
|
+
if (remaining.length !== item.attributeFilter.filterElementsBy.length) {
|
|
457
|
+
item.attributeFilter.filterElementsBy = remaining;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else if (isDashboardArbitraryAttributeFilter(item) &&
|
|
461
|
+
item.arbitraryAttributeFilter.filterElementsBy) {
|
|
462
|
+
const remaining = item.arbitraryAttributeFilter.filterElementsBy.filter((parent) => parent.filterLocalIdentifier !== removedLocalId);
|
|
463
|
+
if (remaining.length !== item.arbitraryAttributeFilter.filterElementsBy.length) {
|
|
464
|
+
item.arbitraryAttributeFilter.filterElementsBy = remaining;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
573
469
|
const moveAttributeFilter = (state, action) => {
|
|
574
|
-
const
|
|
575
|
-
if (!
|
|
470
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
471
|
+
if (!target) {
|
|
576
472
|
return;
|
|
577
473
|
}
|
|
578
|
-
if (!activeTab.filterContext) {
|
|
579
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
580
|
-
}
|
|
581
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
582
474
|
const { filterLocalId, index } = action.payload;
|
|
583
|
-
const
|
|
475
|
+
const filters = target.definition.filters;
|
|
476
|
+
const currentFilterIndex = filters.findIndex((item) => isDashboardAttributeFilterItem(item) &&
|
|
584
477
|
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
585
478
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing filter");
|
|
586
|
-
const filter =
|
|
587
|
-
|
|
479
|
+
const filter = filters[currentFilterIndex];
|
|
480
|
+
filters.splice(currentFilterIndex, 1);
|
|
588
481
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
589
|
-
const isDateFilterPresent =
|
|
482
|
+
const isDateFilterPresent = filters.findIndex(isDashboardDateFilter) >= 0;
|
|
590
483
|
if (index === -1) {
|
|
591
|
-
|
|
484
|
+
filters.push(filter);
|
|
592
485
|
}
|
|
593
486
|
else {
|
|
594
487
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
595
488
|
const attributeFilterIndex = isDateFilterPresent ? index + 1 : index;
|
|
596
|
-
|
|
489
|
+
filters.splice(attributeFilterIndex, 0, filter);
|
|
597
490
|
}
|
|
598
491
|
};
|
|
599
492
|
const setAttributeFilterParents = (state, action) => {
|
|
600
|
-
const
|
|
601
|
-
if (!
|
|
493
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
494
|
+
if (!target) {
|
|
602
495
|
return;
|
|
603
496
|
}
|
|
604
|
-
if (!activeTab.filterContext) {
|
|
605
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
606
|
-
}
|
|
607
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
608
497
|
const { filterLocalId, parentFilters } = action.payload;
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
invariant(currentFilterIndex >= 0, "Attempt to set parent of a non-existing filter");
|
|
498
|
+
const filter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
499
|
+
invariant(filter, "Attempt to set parent of a non-existing filter");
|
|
612
500
|
// silently ignore when targeting match filter, will have no effect
|
|
613
|
-
const filter = activeTab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
614
501
|
if (isDashboardAttributeFilter(filter)) {
|
|
615
502
|
filter.attributeFilter.filterElementsBy = [...parentFilters];
|
|
616
503
|
}
|
|
@@ -619,19 +506,13 @@ const setAttributeFilterParents = (state, action) => {
|
|
|
619
506
|
}
|
|
620
507
|
};
|
|
621
508
|
const setAttributeFilterDependentDateFilters = (state, action) => {
|
|
622
|
-
const
|
|
623
|
-
if (!
|
|
509
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
510
|
+
if (!target) {
|
|
624
511
|
return;
|
|
625
512
|
}
|
|
626
|
-
if (!activeTab.filterContext) {
|
|
627
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
628
|
-
}
|
|
629
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
630
513
|
const { filterLocalId, dependentDateFilters } = action.payload;
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
invariant(currentFilterIndex >= 0, "Attempt to set dependent date filter of a non-existing filter");
|
|
634
|
-
const filter = activeTab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
514
|
+
const filter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
515
|
+
invariant(filter, "Attempt to set dependent date filter of a non-existing filter");
|
|
635
516
|
if (isDashboardAttributeFilter(filter)) {
|
|
636
517
|
filter.attributeFilter.filterElementsByDate = [...dependentDateFilters];
|
|
637
518
|
}
|
|
@@ -640,64 +521,43 @@ const setAttributeFilterDependentDateFilters = (state, action) => {
|
|
|
640
521
|
}
|
|
641
522
|
// Match filters do not support filterElementsByDate
|
|
642
523
|
};
|
|
524
|
+
function findAttributeFilterItem(definition, localIdentifier) {
|
|
525
|
+
return definition.filters.find((item) => isDashboardAttributeFilterItem(item) &&
|
|
526
|
+
dashboardAttributeFilterItemLocalIdentifier(item) === localIdentifier);
|
|
527
|
+
}
|
|
643
528
|
const clearAttributeFiltersSelection = (state, action) => {
|
|
644
|
-
const { tabLocalIdentifier,
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
if (!source) {
|
|
529
|
+
const { tabLocalIdentifier, filterLocalIds, restoreOriginal } = action.payload;
|
|
530
|
+
const tab = getTabOrActive(state, tabLocalIdentifier);
|
|
531
|
+
if (!tab) {
|
|
648
532
|
return;
|
|
649
533
|
}
|
|
650
|
-
if (!
|
|
651
|
-
|
|
534
|
+
if (!tab.filterContext) {
|
|
535
|
+
tab.filterContext = { ...filterContextInitialState };
|
|
652
536
|
}
|
|
653
|
-
const
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
});
|
|
660
|
-
for (const tab of tabs.slice(1)) {
|
|
661
|
-
for (const { filterLocalId, filter } of sourceFilters) {
|
|
662
|
-
if (!filter ||
|
|
663
|
-
!isDashboardAttributeFilter(filter) ||
|
|
664
|
-
isCrossFilteringVirtualFilter(source, filterLocalId, crossFilteringLocalIdsByTab)) {
|
|
665
|
-
continue;
|
|
666
|
-
}
|
|
667
|
-
const match = findCounterpartFilter(source, filter, tab, state.attributesWithReferences, {
|
|
668
|
-
allowListToText: false,
|
|
669
|
-
crossFilteringLocalIdsByTab,
|
|
670
|
-
});
|
|
671
|
-
if (!match || !isDashboardAttributeFilter(match) || !match.attributeFilter.localIdentifier) {
|
|
672
|
-
continue;
|
|
673
|
-
}
|
|
674
|
-
const targetLocalId = match.attributeFilter.localIdentifier;
|
|
675
|
-
if (action.payload.restoreTargetOriginal) {
|
|
676
|
-
const original = findOriginalFilter(tab, match);
|
|
677
|
-
if (!isDashboardAttributeFilter(original)) {
|
|
678
|
-
continue;
|
|
679
|
-
}
|
|
680
|
-
updateAttributeFilterSelectionOnTab(tab, {
|
|
681
|
-
filterLocalId: targetLocalId,
|
|
682
|
-
elements: original.attributeFilter.attributeElements,
|
|
683
|
-
negativeSelection: original.attributeFilter.negativeSelection,
|
|
684
|
-
}, targetLocalId, false);
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
clearAttributeFilterSelectionOnTab(tab, targetLocalId, false);
|
|
537
|
+
for (const filterLocalId of filterLocalIds) {
|
|
538
|
+
if (restoreOriginal) {
|
|
539
|
+
restoreAttributeFilterSelectionOnTab(tab, filterLocalId);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
clearAttributeFilterSelectionOnTab(tab, filterLocalId);
|
|
688
543
|
}
|
|
689
544
|
}
|
|
690
545
|
};
|
|
691
|
-
function
|
|
692
|
-
const
|
|
693
|
-
|
|
546
|
+
function restoreAttributeFilterSelectionOnTab(tab, filterLocalId) {
|
|
547
|
+
const filter = findAppliedFilterByLocalId(tab, filterLocalId);
|
|
548
|
+
const original = filter ? findOriginalFilter(tab, filter) : undefined;
|
|
549
|
+
if (!isDashboardAttributeFilter(original)) {
|
|
694
550
|
return;
|
|
695
551
|
}
|
|
552
|
+
updateAttributeFilterSelectionOnTab(tab, {
|
|
553
|
+
filterLocalId,
|
|
554
|
+
elements: original.attributeFilter.attributeElements,
|
|
555
|
+
negativeSelection: original.attributeFilter.negativeSelection,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
function clearAttributeFilterSelectionOnTab(tab, filterLocalId) {
|
|
696
559
|
invariant(tab.filterContext?.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
697
560
|
const currentFilterIndex = tab.filterContext.filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
698
|
-
if (!isSource && currentFilterIndex < 0) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
561
|
invariant(currentFilterIndex >= 0, "Attempt to clear selection of a non-existing filter");
|
|
702
562
|
const currentFilter = tab.filterContext.filterContextDefinition.filters[currentFilterIndex];
|
|
703
563
|
currentFilter.attributeFilter.negativeSelection =
|
|
@@ -710,17 +570,15 @@ function clearAttributeFilterSelectionOnTab(tab, filterLocalId, isSource) {
|
|
|
710
570
|
* Changes the display form for the filter given by its local identifier.
|
|
711
571
|
*/
|
|
712
572
|
const changeAttributeDisplayForm = (state, action) => {
|
|
713
|
-
const
|
|
714
|
-
if (!
|
|
573
|
+
const target = getTabFilterContext(state, action.payload.tabLocalIdentifier);
|
|
574
|
+
if (!target) {
|
|
715
575
|
return;
|
|
716
576
|
}
|
|
717
|
-
if (!targetTab.filterContext) {
|
|
718
|
-
targetTab.filterContext = { ...filterContextInitialState };
|
|
719
|
-
}
|
|
720
577
|
const { filterLocalId, displayForm, isWorkingSelectionChange, enableImmediateAttributeFilterDisplayAsLabelMigration, isResultOfMigration, } = action.payload;
|
|
578
|
+
const { filterContext } = target;
|
|
721
579
|
const filterContextDefinition = isWorkingSelectionChange
|
|
722
|
-
?
|
|
723
|
-
:
|
|
580
|
+
? filterContext.workingFilterContextDefinition
|
|
581
|
+
: filterContext.filterContextDefinition;
|
|
724
582
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
725
583
|
const currentFilterIndex = filterContextDefinition.filters.findIndex((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
726
584
|
invariant(currentFilterIndex >= 0 || isWorkingSelectionChange, "Attempt to set parent of a non-existing filter");
|
|
@@ -738,7 +596,7 @@ const changeAttributeDisplayForm = (state, action) => {
|
|
|
738
596
|
currentFilter.attributeFilter.displayForm = { ...displayForm };
|
|
739
597
|
// update original filters to not show "reset filters" button, that will revert filter to wrong state
|
|
740
598
|
if (enableImmediateAttributeFilterDisplayAsLabelMigration && isResultOfMigration) {
|
|
741
|
-
const originalFilter =
|
|
599
|
+
const originalFilter = filterContext.originalFilterContextDefinition?.filters.find((item) => isDashboardAttributeFilter(item) && item.attributeFilter.localIdentifier === filterLocalId);
|
|
742
600
|
if (isDashboardAttributeFilter(originalFilter)) {
|
|
743
601
|
originalFilter.attributeFilter.displayForm = { ...displayForm };
|
|
744
602
|
}
|
|
@@ -751,21 +609,12 @@ const changeAttributeDisplayForm = (state, action) => {
|
|
|
751
609
|
*/
|
|
752
610
|
const changeTextFilterDisplayForm = (state, action) => {
|
|
753
611
|
const targetTab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
754
|
-
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
const { filterLocalId, displayForm } = action.payload;
|
|
758
|
-
const filterContextDefinition = targetTab.filterContext.filterContextDefinition;
|
|
612
|
+
const filterContextDefinition = targetTab?.filterContext?.filterContextDefinition;
|
|
759
613
|
if (!filterContextDefinition?.filters) {
|
|
760
614
|
return;
|
|
761
615
|
}
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
765
|
-
if (currentFilterIndex < 0) {
|
|
766
|
-
return;
|
|
767
|
-
}
|
|
768
|
-
const filter = filterContextDefinition.filters[currentFilterIndex];
|
|
616
|
+
const { filterLocalId, displayForm } = action.payload;
|
|
617
|
+
const filter = findAttributeFilterItem(filterContextDefinition, filterLocalId);
|
|
769
618
|
if (isDashboardArbitraryAttributeFilter(filter)) {
|
|
770
619
|
filter.arbitraryAttributeFilter.displayForm = { ...displayForm };
|
|
771
620
|
}
|
|
@@ -777,17 +626,12 @@ const changeTextFilterDisplayForm = (state, action) => {
|
|
|
777
626
|
* Changes the title for the filter given by its local identifier.
|
|
778
627
|
*/
|
|
779
628
|
const changeAttributeTitle = (state, action) => {
|
|
780
|
-
const
|
|
781
|
-
if (!
|
|
629
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
630
|
+
if (!target) {
|
|
782
631
|
return;
|
|
783
632
|
}
|
|
784
|
-
if (!activeTab.filterContext) {
|
|
785
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
786
|
-
}
|
|
787
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
788
633
|
const { filterLocalId, title } = action.payload;
|
|
789
|
-
const findFilter =
|
|
790
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
634
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
791
635
|
invariant(findFilter, "Attempt to change title of a non-existing filter");
|
|
792
636
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
793
637
|
findFilter.attributeFilter.title = title;
|
|
@@ -803,17 +647,12 @@ const changeAttributeTitle = (state, action) => {
|
|
|
803
647
|
* Changes the selection mode for the filter given by its local identifier.
|
|
804
648
|
*/
|
|
805
649
|
const changeSelectionMode = (state, action) => {
|
|
806
|
-
const
|
|
807
|
-
if (!
|
|
650
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
651
|
+
if (!target) {
|
|
808
652
|
return;
|
|
809
653
|
}
|
|
810
|
-
if (!activeTab.filterContext) {
|
|
811
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
812
|
-
}
|
|
813
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
814
654
|
const { filterLocalId, selectionMode } = action.payload;
|
|
815
|
-
const findFilter =
|
|
816
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
655
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
817
656
|
invariant(findFilter, "Attempt to change selection mode of a non-existing filter");
|
|
818
657
|
// Text filters (arbitrary, match) do not have selectionMode; no-op for them
|
|
819
658
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
@@ -821,15 +660,12 @@ const changeSelectionMode = (state, action) => {
|
|
|
821
660
|
}
|
|
822
661
|
};
|
|
823
662
|
const addDateFilter = (state, action) => {
|
|
824
|
-
const
|
|
825
|
-
if (!
|
|
663
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
664
|
+
if (!target) {
|
|
826
665
|
return;
|
|
827
666
|
}
|
|
828
|
-
if (!activeTab.filterContext) {
|
|
829
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
830
|
-
}
|
|
831
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
832
667
|
const { index, dateDataset } = action.payload;
|
|
668
|
+
const { definition } = target;
|
|
833
669
|
const filter = {
|
|
834
670
|
dateFilter: {
|
|
835
671
|
dataSet: dateDataset,
|
|
@@ -838,73 +674,58 @@ const addDateFilter = (state, action) => {
|
|
|
838
674
|
},
|
|
839
675
|
};
|
|
840
676
|
// Only draggable filters are indexed, if DateFilter is present should be always first item
|
|
841
|
-
const isCommonDateFilterPresent =
|
|
677
|
+
const isCommonDateFilterPresent = definition.filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
842
678
|
if (index === -1) {
|
|
843
|
-
|
|
679
|
+
definition.filters.push(filter);
|
|
844
680
|
}
|
|
845
681
|
else {
|
|
846
682
|
// If CommonDateFilter is present we have to move index by 1 because index of filter is calculated just for AttributeFilers array
|
|
847
683
|
const newFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
848
|
-
|
|
684
|
+
definition.filters.splice(newFilterIndex, 0, filter);
|
|
849
685
|
}
|
|
850
686
|
};
|
|
851
|
-
//
|
|
852
|
-
//
|
|
853
|
-
//
|
|
854
687
|
const addMeasureValueFilter = (state, action) => {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
const activeTab = getTabsToMutate(state)[0];
|
|
858
|
-
if (!activeTab) {
|
|
688
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
689
|
+
if (!target) {
|
|
859
690
|
return;
|
|
860
691
|
}
|
|
861
|
-
if (!activeTab.filterContext) {
|
|
862
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
863
|
-
}
|
|
864
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
865
692
|
const { index, measure, localIdentifier, title } = action.payload;
|
|
693
|
+
const { definition } = target;
|
|
866
694
|
const filter = {
|
|
867
695
|
dashboardMeasureValueFilter: {
|
|
868
696
|
measure,
|
|
869
|
-
localIdentifier:
|
|
697
|
+
localIdentifier: resolveFilterLocalIdentifier(definition, (candidateIndex) => generateMeasureValueFilterLocalIdentifier(measure, candidateIndex), index, localIdentifier),
|
|
870
698
|
title,
|
|
871
699
|
},
|
|
872
700
|
};
|
|
873
|
-
const isCommonDateFilterPresent =
|
|
701
|
+
const isCommonDateFilterPresent = definition.filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
874
702
|
if (index === -1) {
|
|
875
|
-
|
|
703
|
+
definition.filters.push(filter);
|
|
876
704
|
}
|
|
877
705
|
else {
|
|
878
706
|
const newFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
879
|
-
|
|
707
|
+
definition.filters.splice(newFilterIndex, 0, filter);
|
|
880
708
|
}
|
|
881
709
|
};
|
|
882
710
|
const removeMeasureValueFilter = (state, action) => {
|
|
883
|
-
const
|
|
884
|
-
if (!
|
|
711
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
712
|
+
if (!target) {
|
|
885
713
|
return;
|
|
886
714
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
...activeTab.filterContext.filterContextDefinition,
|
|
893
|
-
filters: activeTab.filterContext.filterContextDefinition.filters.filter((item) => !(isDashboardMeasureValueFilter(item) &&
|
|
894
|
-
dashboardFilterLocalIdentifier(item) === action.payload.localIdentifier)),
|
|
715
|
+
const { localIdentifier } = action.payload;
|
|
716
|
+
target.filterContext.filterContextDefinition = {
|
|
717
|
+
...target.definition,
|
|
718
|
+
filters: target.definition.filters.filter((item) => !(isDashboardMeasureValueFilter(item) &&
|
|
719
|
+
dashboardFilterLocalIdentifier(item) === localIdentifier)),
|
|
895
720
|
};
|
|
896
721
|
};
|
|
897
722
|
const moveMeasureValueFilter = (state, action) => {
|
|
898
|
-
const
|
|
899
|
-
if (!
|
|
723
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
724
|
+
if (!target) {
|
|
900
725
|
return;
|
|
901
726
|
}
|
|
902
|
-
if (!activeTab.filterContext) {
|
|
903
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
904
|
-
}
|
|
905
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
906
727
|
const { localIdentifier, index } = action.payload;
|
|
907
|
-
const filters =
|
|
728
|
+
const filters = target.definition.filters;
|
|
908
729
|
const currentFilterIndex = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
909
730
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing measure value filter");
|
|
910
731
|
const filter = filters[currentFilterIndex];
|
|
@@ -919,61 +740,91 @@ const moveMeasureValueFilter = (state, action) => {
|
|
|
919
740
|
}
|
|
920
741
|
};
|
|
921
742
|
const removeDateFilter = (state, action) => {
|
|
922
|
-
const
|
|
923
|
-
if (!
|
|
743
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
744
|
+
if (!target) {
|
|
924
745
|
return;
|
|
925
746
|
}
|
|
926
|
-
if (!activeTab.filterContext) {
|
|
927
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
928
|
-
}
|
|
929
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
930
747
|
const { dataSet } = action.payload;
|
|
931
|
-
const
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
748
|
+
const { filterContext, definition } = target;
|
|
749
|
+
const removed = definition.filters.find((item) => isDashboardDateFilterWithDimension(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
750
|
+
const removedLocalIdentifier = isDashboardDateFilter(removed)
|
|
751
|
+
? removed.dateFilter.localIdentifier
|
|
752
|
+
: undefined;
|
|
753
|
+
filterContext.filterContextDefinition = {
|
|
754
|
+
...definition,
|
|
755
|
+
filters: definition.filters.filter((item) => !isDashboardDateFilter(item) || !areObjRefsEqual(item.dateFilter.dataSet, dataSet)),
|
|
935
756
|
};
|
|
757
|
+
removeDimensionDateFilterDependencies(filterContext.filterContextDefinition, dataSet, removedLocalIdentifier);
|
|
936
758
|
};
|
|
759
|
+
/**
|
|
760
|
+
* Drops attribute-filter dependencies that point at the removed dimension date filter, including
|
|
761
|
+
* filters that exist only on this tab. Matches both the filter local identifier and the legacy
|
|
762
|
+
* dataset-identifier form.
|
|
763
|
+
*/
|
|
764
|
+
function removeDimensionDateFilterDependencies(definition, dataSet, removedLocalIdentifier) {
|
|
765
|
+
const datasetIdentifier = isIdentifierRef(dataSet) ? dataSet.identifier : undefined;
|
|
766
|
+
for (const item of definition.filters) {
|
|
767
|
+
if (isDashboardAttributeFilter(item)) {
|
|
768
|
+
const next = withoutRemovedDateDependency(item.attributeFilter.filterElementsByDate, removedLocalIdentifier, datasetIdentifier);
|
|
769
|
+
if (next !== item.attributeFilter.filterElementsByDate) {
|
|
770
|
+
item.attributeFilter.filterElementsByDate = next;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
else if (isDashboardArbitraryAttributeFilter(item)) {
|
|
774
|
+
const next = withoutRemovedDateDependency(item.arbitraryAttributeFilter.filterElementsByDate, removedLocalIdentifier, datasetIdentifier);
|
|
775
|
+
if (next !== item.arbitraryAttributeFilter.filterElementsByDate) {
|
|
776
|
+
item.arbitraryAttributeFilter.filterElementsByDate = next;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function withoutRemovedDateDependency(dependencies, removedLocalIdentifier, datasetIdentifier) {
|
|
782
|
+
if (!dependencies?.length) {
|
|
783
|
+
return dependencies;
|
|
784
|
+
}
|
|
785
|
+
const remaining = dependencies.filter((dependency) => {
|
|
786
|
+
if (dependency.isCommonDate) {
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
const matchesLocalIdentifier = removedLocalIdentifier !== undefined &&
|
|
790
|
+
dependency.filterLocalIdentifier === removedLocalIdentifier;
|
|
791
|
+
const matchesDatasetIdentifier = datasetIdentifier !== undefined && dependency.filterLocalIdentifier === datasetIdentifier;
|
|
792
|
+
return !matchesLocalIdentifier && !matchesDatasetIdentifier;
|
|
793
|
+
});
|
|
794
|
+
return remaining.length === dependencies.length ? dependencies : remaining;
|
|
795
|
+
}
|
|
937
796
|
const moveDateFilter = (state, action) => {
|
|
938
|
-
const
|
|
939
|
-
if (!
|
|
797
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
798
|
+
if (!target) {
|
|
940
799
|
return;
|
|
941
800
|
}
|
|
942
|
-
if (!activeTab.filterContext) {
|
|
943
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
944
|
-
}
|
|
945
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
946
801
|
const { dataSet, index } = action.payload;
|
|
947
|
-
const
|
|
802
|
+
const filters = target.definition.filters;
|
|
803
|
+
const currentFilterIndex = filters.findIndex((item) => isDashboardDateFilter(item) && areObjRefsEqual(item.dateFilter.dataSet, dataSet));
|
|
948
804
|
invariant(currentFilterIndex >= 0, "Attempt to move non-existing filter");
|
|
949
|
-
const filter =
|
|
950
|
-
|
|
805
|
+
const filter = filters[currentFilterIndex];
|
|
806
|
+
filters.splice(currentFilterIndex, 1);
|
|
951
807
|
// Filters are indexed just for attribute filters, if DateFilter is present should be always first item
|
|
952
|
-
const isCommonDateFilterPresent =
|
|
808
|
+
const isCommonDateFilterPresent = filters.findIndex(isDashboardCommonDateFilter) >= 0;
|
|
953
809
|
if (index === -1) {
|
|
954
|
-
|
|
810
|
+
filters.push(filter);
|
|
955
811
|
}
|
|
956
812
|
else {
|
|
957
813
|
// If DateFilter is present we have to move index by 1 because index of filter is calculated just for DraggableFilters array
|
|
958
814
|
const dateFilterIndex = isCommonDateFilterPresent ? index + 1 : index;
|
|
959
|
-
|
|
815
|
+
filters.splice(dateFilterIndex, 0, filter);
|
|
960
816
|
}
|
|
961
817
|
};
|
|
962
818
|
/**
|
|
963
819
|
* Changes the element limiting items for the filter given by its local identifier.
|
|
964
820
|
*/
|
|
965
821
|
const changeLimitingItems = (state, action) => {
|
|
966
|
-
const
|
|
967
|
-
if (!
|
|
822
|
+
const target = getEditableFilterContext(state, action.payload.tabLocalIdentifier);
|
|
823
|
+
if (!target) {
|
|
968
824
|
return;
|
|
969
825
|
}
|
|
970
|
-
if (!activeTab.filterContext) {
|
|
971
|
-
activeTab.filterContext = { ...filterContextInitialState };
|
|
972
|
-
}
|
|
973
|
-
invariant(activeTab.filterContext.filterContextDefinition, "Attempt to edit uninitialized filter context");
|
|
974
826
|
const { filterLocalId, limitingItems } = action.payload;
|
|
975
|
-
const findFilter =
|
|
976
|
-
dashboardAttributeFilterItemLocalIdentifier(item) === filterLocalId);
|
|
827
|
+
const findFilter = findAttributeFilterItem(target.definition, filterLocalId);
|
|
977
828
|
invariant(findFilter, "Attempt to change limiting items of a non-existing filter");
|
|
978
829
|
if (isDashboardAttributeFilter(findFilter)) {
|
|
979
830
|
findFilter.attributeFilter.validateElementsBy = limitingItems;
|
|
@@ -1012,8 +863,9 @@ export function clearFilterContextWorkingValues(tab) {
|
|
|
1012
863
|
tab.filterContext.workingFilterContextDefinition = { filters: [] };
|
|
1013
864
|
}
|
|
1014
865
|
const resetWorkingFilterSelection = (state) => {
|
|
1015
|
-
|
|
1016
|
-
|
|
866
|
+
const activeTab = getActiveTab(state);
|
|
867
|
+
if (activeTab) {
|
|
868
|
+
clearFilterContextWorkingValues(activeTab);
|
|
1017
869
|
}
|
|
1018
870
|
};
|
|
1019
871
|
//
|
|
@@ -1030,59 +882,24 @@ const setDefaultFilterOverrides = (state, action) => {
|
|
|
1030
882
|
activeTab.filterContext.defaultFilterOverrides = action.payload;
|
|
1031
883
|
};
|
|
1032
884
|
const changeMeasureValueFilterCondition = (state, action) => {
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
const source = tabs[0];
|
|
1036
|
-
if (!source) {
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
const sourceFilter = findAppliedFilterByLocalId(source, localIdentifier);
|
|
1040
|
-
changeMeasureValueFilterConditionOnTab(source, action.payload, localIdentifier, true);
|
|
1041
|
-
if (!sourceFilter || !isDashboardMeasureValueFilter(sourceFilter)) {
|
|
885
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
886
|
+
if (!tab) {
|
|
1042
887
|
return;
|
|
1043
888
|
}
|
|
1044
|
-
|
|
1045
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences);
|
|
1046
|
-
const targetLocalId = match ? dashboardFilterLocalIdentifier(match) : undefined;
|
|
1047
|
-
if (!targetLocalId || !match) {
|
|
1048
|
-
continue;
|
|
1049
|
-
}
|
|
1050
|
-
if (action.payload.restoreTargetOriginal) {
|
|
1051
|
-
const original = findOriginalFilter(tab, match);
|
|
1052
|
-
if (!isDashboardMeasureValueFilter(original)) {
|
|
1053
|
-
continue;
|
|
1054
|
-
}
|
|
1055
|
-
changeMeasureValueFilterConditionOnTab(tab, {
|
|
1056
|
-
...action.payload,
|
|
1057
|
-
localIdentifier: targetLocalId,
|
|
1058
|
-
conditions: original.dashboardMeasureValueFilter.conditions,
|
|
1059
|
-
}, targetLocalId, false);
|
|
1060
|
-
continue;
|
|
1061
|
-
}
|
|
1062
|
-
changeMeasureValueFilterConditionOnTab(tab, action.payload, targetLocalId, false);
|
|
1063
|
-
}
|
|
889
|
+
changeMeasureValueFilterConditionOnTab(tab, action.payload);
|
|
1064
890
|
};
|
|
1065
|
-
function changeMeasureValueFilterConditionOnTab(tab, payload
|
|
891
|
+
function changeMeasureValueFilterConditionOnTab(tab, payload) {
|
|
1066
892
|
if (!tab.filterContext) {
|
|
1067
|
-
if (!isSource) {
|
|
1068
|
-
return;
|
|
1069
|
-
}
|
|
1070
893
|
tab.filterContext = { ...filterContextInitialState };
|
|
1071
894
|
}
|
|
1072
|
-
const { conditions, isWorkingSelectionChange } = payload;
|
|
895
|
+
const { localIdentifier, conditions, isWorkingSelectionChange } = payload;
|
|
1073
896
|
const filterContextDefinition = isWorkingSelectionChange
|
|
1074
897
|
? tab.filterContext?.workingFilterContextDefinition
|
|
1075
898
|
: tab.filterContext?.filterContextDefinition;
|
|
1076
|
-
if (!isSource && !filterContextDefinition?.filters) {
|
|
1077
|
-
return;
|
|
1078
|
-
}
|
|
1079
899
|
invariant(filterContextDefinition?.filters, "Attempt to edit uninitialized filter context");
|
|
1080
900
|
const filters = filterContextDefinition.filters;
|
|
1081
901
|
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
1082
902
|
const hasConditions = !!conditions && conditions.length > 0;
|
|
1083
|
-
if (!isSource && index < 0) {
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
903
|
invariant(index >= 0 || isWorkingSelectionChange, `Attempt to change condition of measure value filter ${localIdentifier} that does not exist`);
|
|
1087
904
|
if (isWorkingSelectionChange && index < 0) {
|
|
1088
905
|
const workingFilter = {
|
|
@@ -1103,48 +920,17 @@ function changeMeasureValueFilterConditionOnTab(tab, payload, localIdentifier, i
|
|
|
1103
920
|
};
|
|
1104
921
|
}
|
|
1105
922
|
const setMeasureValueFilterDimensionality = (state, action) => {
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
const source = tabs[0];
|
|
1109
|
-
if (!source) {
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
const sourceFilter = findAppliedFilterByLocalId(source, localIdentifier);
|
|
1113
|
-
setMeasureValueFilterDimensionalityOnTab(source, action.payload, localIdentifier, true);
|
|
1114
|
-
if (!sourceFilter || !isDashboardMeasureValueFilter(sourceFilter)) {
|
|
923
|
+
const tab = getTabOrActive(state, action.payload.tabLocalIdentifier);
|
|
924
|
+
if (!tab) {
|
|
1115
925
|
return;
|
|
1116
926
|
}
|
|
1117
|
-
|
|
1118
|
-
const match = findCounterpartFilter(source, sourceFilter, tab, state.attributesWithReferences);
|
|
1119
|
-
const targetLocalId = match ? dashboardFilterLocalIdentifier(match) : undefined;
|
|
1120
|
-
if (!targetLocalId || !match) {
|
|
1121
|
-
continue;
|
|
1122
|
-
}
|
|
1123
|
-
if (restoreTargetOriginal) {
|
|
1124
|
-
const original = findOriginalFilter(tab, match);
|
|
1125
|
-
if (!isDashboardMeasureValueFilter(original)) {
|
|
1126
|
-
continue;
|
|
1127
|
-
}
|
|
1128
|
-
setMeasureValueFilterDimensionalityOnTab(tab, {
|
|
1129
|
-
...action.payload,
|
|
1130
|
-
localIdentifier: targetLocalId,
|
|
1131
|
-
dimensionality: original.dashboardMeasureValueFilter.dimensionality,
|
|
1132
|
-
}, targetLocalId, false);
|
|
1133
|
-
continue;
|
|
1134
|
-
}
|
|
1135
|
-
setMeasureValueFilterDimensionalityOnTab(tab, action.payload, targetLocalId, false);
|
|
1136
|
-
}
|
|
927
|
+
setMeasureValueFilterDimensionalityOnTab(tab, action.payload);
|
|
1137
928
|
};
|
|
1138
|
-
function setMeasureValueFilterDimensionalityOnTab(tab, payload
|
|
929
|
+
function setMeasureValueFilterDimensionalityOnTab(tab, payload) {
|
|
930
|
+
const { localIdentifier } = payload;
|
|
1139
931
|
const filters = tab.filterContext?.filterContextDefinition?.filters;
|
|
1140
|
-
if (!isSource && !filters) {
|
|
1141
|
-
return;
|
|
1142
|
-
}
|
|
1143
932
|
invariant(filters, "Attempt to edit uninitialized filter context");
|
|
1144
933
|
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === localIdentifier);
|
|
1145
|
-
if (!isSource && index < 0) {
|
|
1146
|
-
return;
|
|
1147
|
-
}
|
|
1148
934
|
invariant(index >= 0, `Attempt to change dimensionality of measure value filter ${localIdentifier} that does not exist`);
|
|
1149
935
|
const filter = filters[index];
|
|
1150
936
|
const dimensionality = payload.dimensionality && payload.dimensionality.length > 0 ? payload.dimensionality : undefined;
|
|
@@ -1156,23 +942,96 @@ function setMeasureValueFilterDimensionalityOnTab(tab, payload, localIdentifier,
|
|
|
1156
942
|
};
|
|
1157
943
|
}
|
|
1158
944
|
const changeMeasureValueFilterTitle = (state, action) => {
|
|
1159
|
-
const
|
|
1160
|
-
|
|
945
|
+
const { filterLocalId, title, tabLocalIdentifier } = action.payload;
|
|
946
|
+
const targetTab = getTabOrActive(state, tabLocalIdentifier);
|
|
947
|
+
if (!targetTab) {
|
|
1161
948
|
return;
|
|
1162
949
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) &&
|
|
1166
|
-
|
|
1167
|
-
invariant(index >= 0, `Attempt to change title of measure value filter ${action.payload.filterLocalId} that does not exist`);
|
|
950
|
+
const filters = targetTab.filterContext?.filterContextDefinition?.filters;
|
|
951
|
+
invariant(filters, "Attempt to edit uninitialized filter context");
|
|
952
|
+
const index = filters.findIndex((item) => isDashboardMeasureValueFilter(item) && dashboardFilterLocalIdentifier(item) === filterLocalId);
|
|
953
|
+
invariant(index >= 0, `Attempt to change title of measure value filter ${filterLocalId} that does not exist`);
|
|
1168
954
|
const filter = filters[index];
|
|
1169
955
|
filters[index] = {
|
|
1170
956
|
dashboardMeasureValueFilter: {
|
|
1171
957
|
...filter.dashboardMeasureValueFilter,
|
|
1172
|
-
title
|
|
958
|
+
title,
|
|
1173
959
|
},
|
|
1174
960
|
};
|
|
1175
961
|
};
|
|
962
|
+
function isWrittenFilter(filter, written) {
|
|
963
|
+
if (isDashboardDateFilter(filter)) {
|
|
964
|
+
const { dataSet } = filter.dateFilter;
|
|
965
|
+
return dataSet
|
|
966
|
+
? written.dateDataSets.some((writtenDataSet) => areObjRefsEqual(writtenDataSet, dataSet))
|
|
967
|
+
: written.commonDateFilter;
|
|
968
|
+
}
|
|
969
|
+
const localIdentifier = dashboardFilterLocalIdentifier(filter);
|
|
970
|
+
return !!localIdentifier && written.filterLocalIds.includes(localIdentifier);
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Makes the applied values of the written filters their initial values. A default filter view that
|
|
974
|
+
* initializes the shared state is that initial state, so the reset button stays hidden until the user
|
|
975
|
+
* changes it. Filters the view did not write keep their initial values, so a change the user made
|
|
976
|
+
* before stays resettable.
|
|
977
|
+
*/
|
|
978
|
+
const adoptAppliedFiltersAsOriginal = (state, action) => {
|
|
979
|
+
for (const written of action.payload) {
|
|
980
|
+
const tab = getTabOrActive(state, written.tabLocalIdentifier);
|
|
981
|
+
const definition = tab?.filterContext?.filterContextDefinition;
|
|
982
|
+
if (!tab?.filterContext || !definition) {
|
|
983
|
+
continue;
|
|
984
|
+
}
|
|
985
|
+
const originals = tab.filterContext.originalFilterContextDefinition?.filters ?? [];
|
|
986
|
+
const originalOf = new Map();
|
|
987
|
+
const matchedOriginals = new Set();
|
|
988
|
+
const match = (filter, original) => {
|
|
989
|
+
if (original && !matchedOriginals.has(original)) {
|
|
990
|
+
originalOf.set(filter, original);
|
|
991
|
+
matchedOriginals.add(original);
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
// Each initial value belongs to one applied filter. Exact localIdentifier matches go first, so a
|
|
995
|
+
// filter without an initial value, e.g. a cross-filtering one, cannot take the initial value of
|
|
996
|
+
// another filter with the same display form through identity matching.
|
|
997
|
+
for (const filter of definition.filters) {
|
|
998
|
+
const localIdentifier = dashboardFilterLocalIdentifier(filter);
|
|
999
|
+
match(filter, localIdentifier
|
|
1000
|
+
? originals.find((original) => dashboardFilterLocalIdentifier(original) === localIdentifier)
|
|
1001
|
+
: undefined);
|
|
1002
|
+
}
|
|
1003
|
+
for (const filter of definition.filters) {
|
|
1004
|
+
if (!originalOf.has(filter)) {
|
|
1005
|
+
match(filter, findOriginalFilter(tab, filter));
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
// the reset button compares the lists in order, so the applied order is kept; an unwritten filter
|
|
1009
|
+
// without an initial value, e.g. a cross-filtering one, stays out of the initial values
|
|
1010
|
+
const adopted = definition.filters.flatMap((filter) => {
|
|
1011
|
+
if (isWrittenFilter(filter, written)) {
|
|
1012
|
+
return [cloneDeep(filter)];
|
|
1013
|
+
}
|
|
1014
|
+
const original = originalOf.get(filter);
|
|
1015
|
+
return original ? [cloneDeep(original)] : [];
|
|
1016
|
+
});
|
|
1017
|
+
// an unwritten initial value without an applied filter, e.g. a common date filter set to all time
|
|
1018
|
+
for (const original of originals) {
|
|
1019
|
+
if (matchedOriginals.has(original) || isWrittenFilter(original, written)) {
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
if (isDashboardCommonDateFilter(original)) {
|
|
1023
|
+
adopted.unshift(cloneDeep(original));
|
|
1024
|
+
}
|
|
1025
|
+
else {
|
|
1026
|
+
adopted.push(cloneDeep(original));
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
tab.filterContext.originalFilterContextDefinition = {
|
|
1030
|
+
...(tab.filterContext.originalFilterContextDefinition ?? definition),
|
|
1031
|
+
filters: adopted,
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1176
1035
|
//
|
|
1177
1036
|
//
|
|
1178
1037
|
//
|
|
@@ -1209,4 +1068,5 @@ export const filterContextReducers = {
|
|
|
1209
1068
|
changeMeasureValueFilterCondition,
|
|
1210
1069
|
setMeasureValueFilterDimensionality,
|
|
1211
1070
|
changeMeasureValueFilterTitle,
|
|
1071
|
+
adoptAppliedFiltersAsOriginal,
|
|
1212
1072
|
};
|