@gooddata/sdk-ui-dashboard 11.65.0-alpha.9 → 11.65.1
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 +536 -2137
- package/README.md +1 -1
- package/esm/__version.d.ts +1 -1
- package/esm/__version.d.ts.map +1 -1
- package/esm/__version.js +1 -1
- package/esm/index.d.ts +6 -4
- 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 -0
- 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/changeFilterContextSelectionHandler.d.ts.map +1 -1
- package/esm/model/commandHandlers/filterContext/changeFilterContextSelectionHandler.js +9 -3
- 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/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.map +1 -1
- package/esm/model/commandHandlers/parameters/changeParameterValuesHandler.js +7 -3
- 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 +10 -1
- package/esm/model/commands/parameters.d.ts.map +1 -1
- package/esm/model/commands/parameters.js +2 -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/store/config/configSelectors.d.ts +12 -0
- package/esm/model/store/config/configSelectors.d.ts.map +1 -1
- package/esm/model/store/config/configSelectors.js +12 -0
- 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/filterContext/filterContextReducers.d.ts +24 -0
- package/esm/model/store/tabs/filterContext/filterContextReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/filterContext/filterContextReducers.js +75 -0
- package/esm/model/store/tabs/index.d.ts +8 -0
- package/esm/model/store/tabs/index.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts +16 -0
- package/esm/model/store/tabs/parameters/parametersReducers.d.ts.map +1 -1
- package/esm/model/store/tabs/parameters/parametersReducers.js +25 -0
- 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 +18 -0
- 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/presentation/automations/alerting/DefaultAlertingManagementDialog/DefaultAlertingManagementDialogContent.d.ts.map +1 -1
- package/esm/presentation/automations/alerting/DefaultAlertingManagementDialog/DefaultAlertingManagementDialogContent.js +1 -4
- package/esm/presentation/automations/connectors/hooks/useAutomationManagementEditRouting.d.ts.map +1 -1
- package/esm/presentation/automations/connectors/hooks/useAutomationManagementEditRouting.js +2 -6
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailDialog/components/RecipientsSelect/RecipientsSelectRenderer.js +6 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialogContent.d.ts.map +1 -1
- package/esm/presentation/automations/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialogContent.js +2 -5
- 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/automations/shared/utils/automationUtils.d.ts +1 -2
- package/esm/presentation/automations/shared/utils/automationUtils.d.ts.map +1 -1
- package/esm/presentation/automations/shared/utils/automationUtils.js +0 -1
- 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 +0 -10
- 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/DashboardInner.d.ts.map +1 -1
- package/esm/presentation/dashboard/components/DashboardInner.js +13 -9
- package/esm/presentation/dashboard/hooks/useDashboard.d.ts.map +1 -1
- package/esm/presentation/dashboard/hooks/useDashboard.js +3 -2
- 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 +23 -0
- package/esm/presentation/insightEditor/useExploreFilterTransfer.d.ts.map +1 -0
- package/esm/presentation/insightEditor/useExploreFilterTransfer.js +194 -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 +10 -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 +11 -1
- package/esm/presentation/localization/bundles/en-AU.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/en-GB.localization-bundle.d.ts +10 -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 +16 -6
- package/esm/presentation/localization/bundles/en-US.localization-bundle.d.ts +32 -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 +32 -0
- package/esm/presentation/localization/bundles/es-419.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/es-ES.localization-bundle.d.ts +10 -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 +50 -40
- package/esm/presentation/localization/bundles/fi-FI.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/fr-CA.localization-bundle.d.ts +10 -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 +12 -2
- package/esm/presentation/localization/bundles/fr-FR.localization-bundle.d.ts +10 -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 +186 -176
- package/esm/presentation/localization/bundles/id-ID.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/it-IT.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/ja-JP.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/ko-KR.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/nl-NL.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/pl-PL.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/pt-BR.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/pt-PT.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/ru-RU.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/sl-SI.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/th-TH.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/tr-TR.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/uk-UA.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/vi-VN.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/zh-HK.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/zh-Hans.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/localization/bundles/zh-Hant.localization-bundle.d.ts +10 -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 +11 -1
- package/esm/presentation/shareDialog/DefaultShareDialog.d.ts.map +1 -1
- package/esm/presentation/shareDialog/DefaultShareDialog.js +2 -5
- 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/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 +301 -5
- package/package.json +23 -21
- package/styles/css/dashboard.css +40 -1
- 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/insightEditor.css +46 -0
- package/styles/css/insightEditor.css.map +1 -0
- package/styles/css/main.css +86 -1
- package/styles/css/main.css.map +1 -1
- package/styles/scss/dashboard.scss +2 -1
- package/styles/scss/dashboardContentLoader.scss +45 -0
- package/styles/scss/insightEditor.scss +53 -0
- package/styles/scss/main.scss +1 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2022-2026 GoodData Corporation
|
|
3
|
+
import { FormattedMessage } from "react-intl";
|
|
4
|
+
import { INSIGHT_WIDGET_SIZE_INFO_NEW_DEFAULT } from "@gooddata/sdk-ui-ext";
|
|
5
|
+
import { UiIcon } from "@gooddata/sdk-ui-kit";
|
|
6
|
+
import { useWidgetSelection } from "../../model/react/useWidgetSelection.js";
|
|
7
|
+
import { DraggableCreatePanelItem } from "../dragAndDrop/DraggableCreatePanelItem.js";
|
|
8
|
+
const dragItem = {
|
|
9
|
+
type: "insight-placeholder",
|
|
10
|
+
size: {
|
|
11
|
+
gridWidth: INSIGHT_WIDGET_SIZE_INFO_NEW_DEFAULT.width.default,
|
|
12
|
+
gridHeight: INSIGHT_WIDGET_SIZE_INFO_NEW_DEFAULT.height.default,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
function AddInsightPlaceholder() {
|
|
16
|
+
return (_jsxs("div", { className: "add-item-placeholder add-insight-placeholder s-add-insight", children: [_jsx("div", { className: "add-item-placeholder__icon", children: _jsx(UiIcon, { type: "visualization", size: 18, layout: "block" }) }), _jsx(FormattedMessage, { id: "addPanel.insight" })] }));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The item of the edit mode panel that the user drags to the layout to create a new insight in the
|
|
20
|
+
* embedded Analytical Designer.
|
|
21
|
+
*/
|
|
22
|
+
export function InsightEditorCreatePanelItem({ WrapCreatePanelItemWithDragComponent, disabled, }) {
|
|
23
|
+
const { deselectWidgets } = useWidgetSelection();
|
|
24
|
+
return (_jsx(DraggableCreatePanelItem, { Component: AddInsightPlaceholder, WrapCreatePanelItemWithDragComponent: WrapCreatePanelItemWithDragComponent, disabled: disabled, dragItem: dragItem, hideDefaultPreview: false, onDragStart: () => deselectWidgets() }));
|
|
25
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The embedded Analytical Designer on top of the dashboard. It renders only when the dashboard config
|
|
3
|
+
* enables insight editing.
|
|
4
|
+
*/
|
|
5
|
+
export declare function InsightEditorOverlay(): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
//# sourceMappingURL=InsightEditorOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InsightEditorOverlay.d.ts","sourceRoot":"","sources":["../../../src/presentation/insightEditor/InsightEditorOverlay.tsx"],"names":[],"mappings":"AAsCA;;;GAGG;AACH,wBAAgB,oBAAoB,mDAGnC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2020-2026 GoodData Corporation
|
|
3
|
+
import { Suspense, lazy, useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { objRefToString } from "@gooddata/sdk-model";
|
|
6
|
+
import { LoadingMask, Overlay, OverlayController, OverlayControllerProvider, useMediaQuery, } from "@gooddata/sdk-ui-kit";
|
|
7
|
+
import { insightEditorOpened } from "../../model/events/insightEditor.js";
|
|
8
|
+
import { useDashboardDispatch, useDashboardSelector } from "../../model/react/DashboardStoreProvider.js";
|
|
9
|
+
import { useDashboardEventDispatch } from "../../model/react/useDashboardEventDispatch.js";
|
|
10
|
+
import { selectEnableInsightEditing } from "../../model/store/config/configSelectors.js";
|
|
11
|
+
import { uiActions } from "../../model/store/ui/index.js";
|
|
12
|
+
import { selectInsightEditorTarget } from "../../model/store/ui/uiSelectors.js";
|
|
13
|
+
import { isInsightOverlayTopmost } from "./insightEditorEscapeGuard.js";
|
|
14
|
+
import { useInsightEditorSession } from "./useInsightEditorSession.js";
|
|
15
|
+
// Analytical Designer downloads when the editor first opens, not with the dashboard.
|
|
16
|
+
const LazyInsightEditorContent = lazy(() => import("./InsightEditorContent.js").then((module) => ({ default: module.InsightEditorContent })));
|
|
17
|
+
// AD renders the configuration panels of visualizations in a separate React root, so the overlays it
|
|
18
|
+
// opens from there (dropdowns, color pickers) see no OverlayControllerProvider and fall back to the
|
|
19
|
+
// ui-kit default z-index 5001. The editor overlay must not paint above them: its controller base 5000
|
|
20
|
+
// gives it 5001 too, and the config panel popups win by DOM order.
|
|
21
|
+
const overlayController = OverlayController.getInstance(5000);
|
|
22
|
+
/**
|
|
23
|
+
* The embedded Analytical Designer on top of the dashboard. It renders only when the dashboard config
|
|
24
|
+
* enables insight editing.
|
|
25
|
+
*/
|
|
26
|
+
export function InsightEditorOverlay() {
|
|
27
|
+
const isEnabled = useDashboardSelector(selectEnableInsightEditing);
|
|
28
|
+
return isEnabled ? _jsx(InsightEditorOverlayCore, {}) : null;
|
|
29
|
+
}
|
|
30
|
+
function InsightEditorOverlayCore() {
|
|
31
|
+
const dispatch = useDashboardDispatch();
|
|
32
|
+
const target = useDashboardSelector(selectInsightEditorTarget);
|
|
33
|
+
const isMobile = useMediaQuery("mobileDevice");
|
|
34
|
+
// The editor has no mobile layout, so it does not open on a mobile screen. A breakpoint change
|
|
35
|
+
// after the editor opened keeps it open: an unmount would drop the editing session silently.
|
|
36
|
+
const [openedTarget, setOpenedTarget] = useState({ target, isMobile });
|
|
37
|
+
if (openedTarget.target !== target) {
|
|
38
|
+
setOpenedTarget({ target, isMobile });
|
|
39
|
+
}
|
|
40
|
+
const isBlocked = openedTarget.target === target ? openedTarget.isMobile : isMobile;
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (target && isBlocked) {
|
|
43
|
+
dispatch(uiActions.closeInsightEditor());
|
|
44
|
+
}
|
|
45
|
+
}, [dispatch, target, isBlocked]);
|
|
46
|
+
if (!target || isBlocked) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
// Each target gets its own session, so an open of another target never reuses its state.
|
|
50
|
+
return _jsx(InsightEditorModal, { target: target }, getTargetKey(target));
|
|
51
|
+
}
|
|
52
|
+
function getTargetKey(target) {
|
|
53
|
+
return target.type === "widget" || target.type === "insight"
|
|
54
|
+
? `${target.type}:${objRefToString(target.ref)}`
|
|
55
|
+
: target.type;
|
|
56
|
+
}
|
|
57
|
+
function InsightEditorModal({ target }) {
|
|
58
|
+
const eventDispatch = useDashboardEventDispatch();
|
|
59
|
+
const session = useInsightEditorSession(target);
|
|
60
|
+
const closeHandleRef = useRef(null);
|
|
61
|
+
const intl = useIntl();
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
eventDispatch(insightEditorOpened(target));
|
|
64
|
+
}, [eventDispatch, target]);
|
|
65
|
+
// No focus trap: Analytical Designer portals its dropdowns and dialogs to the body, out of the
|
|
66
|
+
// modal. The dialog takes the focus when it mounts, and the focus returns when the editor closes.
|
|
67
|
+
// The render reads the prior focus: the ref callback moves it before any effect runs.
|
|
68
|
+
const [previouslyFocused] = useState(() => document.activeElement);
|
|
69
|
+
const focusDialog = useCallback((dialog) => {
|
|
70
|
+
dialog?.focus({ preventScroll: true });
|
|
71
|
+
}, []);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
return () => {
|
|
74
|
+
if (previouslyFocused instanceof HTMLElement && previouslyFocused.isConnected) {
|
|
75
|
+
previouslyFocused.focus();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}, [previouslyFocused]);
|
|
79
|
+
// Before the AD chunk loads, or when AD fails to start, nothing can confirm the cancellation.
|
|
80
|
+
const requestClose = useCallback(() => {
|
|
81
|
+
if (closeHandleRef.current) {
|
|
82
|
+
closeHandleRef.current.requestClose();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
session.cancel();
|
|
86
|
+
}
|
|
87
|
+
}, [session]);
|
|
88
|
+
// The Overlay closeOnEscape listens on window with no stack awareness. An Escape meant for nested
|
|
89
|
+
// AD UI (a filter dropdown, the save dialog) would cancel the whole editing session. Close only
|
|
90
|
+
// when this overlay is the topmost one, so Escape peels one layer per press.
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const onKeyDown = (e) => {
|
|
93
|
+
if (e.key === "Escape" && isInsightOverlayTopmost()) {
|
|
94
|
+
requestClose();
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
window.addEventListener("keydown", onKeyDown);
|
|
98
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
99
|
+
}, [requestClose]);
|
|
100
|
+
return (_jsx(OverlayControllerProvider, { overlayController: overlayController, children: _jsx(Overlay, { containerClassName: "gd-insight-editor-overlay", className: "gd-edit-insight-modal-overlay", isModal: true,
|
|
101
|
+
// closeOnOutsideClick stops the propagation of the document mousedowns inside the
|
|
102
|
+
// overlay. AD registers its drag-start listener in the capture phase to survive it.
|
|
103
|
+
closeOnOutsideClick: true, closeOnEscape: false, ignoreClicksOnByClass: [".s-sort-direction-arrow", ".dash-content"], onClose: requestClose, shouldCloseOnClick: isNotBodyClick, positionType: "fixed", children: _jsx("div", { ref: focusDialog, tabIndex: -1, className: "gd-edit-insight-overlay-content s-edit-insight-overlay-content overlay-move-left", role: "dialog", "aria-modal": "true", "aria-label": intl.formatMessage({ id: "insightEditor.dialog.label" }), children: _jsx(Suspense, { fallback: _jsx(LoadingMask, { height: "100%" }), children: _jsx(LazyInsightEditorContent, { target: target, session: session, closeHandleRef: closeHandleRef }) }) }) }) }));
|
|
104
|
+
}
|
|
105
|
+
// The menu item that opens the overlay leaves the DOM during the click, so the browser retargets the
|
|
106
|
+
// rest of that click to bare <body>. A click meant to close the overlay lands on a real element (the
|
|
107
|
+
// modal mask or a dashboard node), never on bare <body>.
|
|
108
|
+
function isNotBodyClick(e) {
|
|
109
|
+
return e.target !== document.body;
|
|
110
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type InsightPermissionsById } from "./useInsightEditPermissions.js";
|
|
3
|
+
/**
|
|
4
|
+
* Loads the permissions of the user on the dashboard visualizations once for all widget menus.
|
|
5
|
+
*/
|
|
6
|
+
export declare function InsightEditorPermissionsProvider({ children }: {
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function useInsightEditorPermissions(): InsightPermissionsById | undefined;
|
|
10
|
+
//# sourceMappingURL=InsightEditorPermissionsContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InsightEditorPermissionsContext.d.ts","sourceRoot":"","sources":["../../../src/presentation/insightEditor/InsightEditorPermissionsContext.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,OAAO,CAAC;AAKlE,OAAO,EAAE,KAAK,sBAAsB,EAA6B,MAAM,gCAAgC,CAAC;AAIxG;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,2CAQtF;AAED,wBAAgB,2BAA2B,IAAI,sBAAsB,GAAG,SAAS,CAEhF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2026 GoodData Corporation
|
|
3
|
+
import { createContext, useContext } from "react";
|
|
4
|
+
import { useDashboardSelector } from "../../model/react/DashboardStoreProvider.js";
|
|
5
|
+
import { selectEnableInsightEditing } from "../../model/store/config/configSelectors.js";
|
|
6
|
+
import { useInsightEditPermissions } from "./useInsightEditPermissions.js";
|
|
7
|
+
const InsightEditorPermissionsContext = createContext(undefined);
|
|
8
|
+
/**
|
|
9
|
+
* Loads the permissions of the user on the dashboard visualizations once for all widget menus.
|
|
10
|
+
*/
|
|
11
|
+
export function InsightEditorPermissionsProvider({ children }) {
|
|
12
|
+
const isEnabled = useDashboardSelector(selectEnableInsightEditing);
|
|
13
|
+
const permissions = useInsightEditPermissions(isEnabled);
|
|
14
|
+
return (_jsx(InsightEditorPermissionsContext.Provider, { value: permissions, children: children }));
|
|
15
|
+
}
|
|
16
|
+
export function useInsightEditorPermissions() {
|
|
17
|
+
return useContext(InsightEditorPermissionsContext);
|
|
18
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type IDashboardWidgetProps } from "../widget/widget/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Takes the place of a new insight dropped in the layout. It opens the embedded Analytical Designer
|
|
4
|
+
* to create the insight.
|
|
5
|
+
*/
|
|
6
|
+
export declare function InsightEditorPlaceholder(_props: IDashboardWidgetProps): null;
|
|
7
|
+
//# sourceMappingURL=InsightEditorPlaceholder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InsightEditorPlaceholder.d.ts","sourceRoot":"","sources":["../../../src/presentation/insightEditor/InsightEditorPlaceholder.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAO5E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// (C) 2022-2026 GoodData Corporation
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { useDashboardDispatch } from "../../model/react/DashboardStoreProvider.js";
|
|
4
|
+
import { uiActions } from "../../model/store/ui/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Takes the place of a new insight dropped in the layout. It opens the embedded Analytical Designer
|
|
7
|
+
* to create the insight.
|
|
8
|
+
*/
|
|
9
|
+
export function InsightEditorPlaceholder(_props) {
|
|
10
|
+
const dispatch = useDashboardDispatch();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
dispatch(uiActions.openInsightEditor({ type: "placeholder" }));
|
|
13
|
+
}, [dispatch]);
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type AttributeFilterItem } from "@gooddata/sdk-embedding";
|
|
2
|
+
import { type ICatalogAttribute, type IFilter, type IInsight, type ObjRef } from "@gooddata/sdk-model";
|
|
3
|
+
export declare function getAttributeFilterItems(appliedFilters: IFilter[], insight: IInsight, availableAttributes: ICatalogAttribute[], attributeFilterConfigsDisplayAsLabelMap: Map<string, ObjRef> | undefined, supportsElementUris: boolean): AttributeFilterItem[];
|
|
4
|
+
//# sourceMappingURL=attributeFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attributeFilters.d.ts","sourceRoot":"","sources":["../../../../src/presentation/insightEditor/filterContext/attributeFilters.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,mBAAmB,EAI3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGH,KAAK,iBAAiB,EACtB,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,MAAM,EAWd,MAAM,qBAAqB,CAAC;AAyB7B,wBAAgB,uBAAuB,CACnC,cAAc,EAAE,OAAO,EAAE,EACzB,OAAO,EAAE,QAAQ,EACjB,mBAAmB,EAAE,iBAAiB,EAAE,EACxC,uCAAuC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACxE,mBAAmB,EAAE,OAAO,GAC7B,mBAAmB,EAAE,CAQvB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// (C) 2020-2026 GoodData Corporation
|
|
2
|
+
import { compact } from "lodash-es";
|
|
3
|
+
import { isPositiveAttributeFilter, } from "@gooddata/sdk-embedding";
|
|
4
|
+
import { areObjRefsEqual, filterAttributeElements, filterLocalIdentifier, filterObjRef, insightFilters, isArbitraryAttributeFilter, isAttributeElementsByValue, isAttributeFilter, isMatchAttributeFilter, isNegativeAttributeFilter, } from "@gooddata/sdk-model";
|
|
5
|
+
import { areFiltersWithSameElements, intersectFilters } from "./filterIntersection.js";
|
|
6
|
+
import { toObjIdentifierQualifier } from "./objQualifiers.js";
|
|
7
|
+
function getValidAppliedAttributeFilters(appliedFilters, availableAttributes) {
|
|
8
|
+
return (appliedFilters
|
|
9
|
+
.filter(isAttributeFilter)
|
|
10
|
+
// remove filters not on attributes that are available for the given insight
|
|
11
|
+
// those are considered invalid
|
|
12
|
+
.filter((attrFilter) => {
|
|
13
|
+
const filterDisplayForm = filterObjRef(attrFilter);
|
|
14
|
+
return availableAttributes.some((available) => {
|
|
15
|
+
return available.displayForms.some((displayForm) => areObjRefsEqual(displayForm.ref, filterDisplayForm));
|
|
16
|
+
});
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
export function getAttributeFilterItems(appliedFilters, insight, availableAttributes, attributeFilterConfigsDisplayAsLabelMap, supportsElementUris) {
|
|
20
|
+
return getAttributeFilterItemsFromAppliedFilters(getValidAppliedAttributeFilters(appliedFilters, availableAttributes), insightFilters(insight).filter(isAttributeFilter), availableAttributes, attributeFilterConfigsDisplayAsLabelMap, supportsElementUris);
|
|
21
|
+
}
|
|
22
|
+
function getAttributeFilterItemsFromAppliedFilters(appliedFilters, insightAttrFilters, availableAttributes, attributeFilterConfigsDisplayAsLabelMap, supportsElementUris) {
|
|
23
|
+
const processedFilters = appliedFilters
|
|
24
|
+
// validate and intersect the dashboard filters with the insight filters
|
|
25
|
+
.map((attrFilter) => {
|
|
26
|
+
const filterDisplayForm = filterObjRef(attrFilter);
|
|
27
|
+
const isInverted = isNegativeAttributeFilter(attrFilter);
|
|
28
|
+
const selectedElements = filterAttributeElements(attrFilter);
|
|
29
|
+
const localIdentifier = filterLocalIdentifier(attrFilter);
|
|
30
|
+
if (isArbitraryAttributeFilter(attrFilter)) {
|
|
31
|
+
const { label, values, negativeSelection } = attrFilter.arbitraryAttributeFilter;
|
|
32
|
+
return {
|
|
33
|
+
arbitraryAttributeFilter: {
|
|
34
|
+
displayForm: toObjIdentifierQualifier(label),
|
|
35
|
+
values: values,
|
|
36
|
+
...(negativeSelection === undefined ? {} : { negativeSelection }),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (isMatchAttributeFilter(attrFilter)) {
|
|
41
|
+
const { label, operator, literal, caseSensitive, negativeSelection } = attrFilter.matchAttributeFilter;
|
|
42
|
+
return {
|
|
43
|
+
matchAttributeFilter: {
|
|
44
|
+
displayForm: toObjIdentifierQualifier(label),
|
|
45
|
+
operator,
|
|
46
|
+
literal,
|
|
47
|
+
...(caseSensitive === undefined ? {} : { caseSensitive }),
|
|
48
|
+
...(negativeSelection === undefined ? {} : { negativeSelection }),
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (isAttributeElementsByValue(selectedElements)) {
|
|
53
|
+
// effectively skipping insight-based filters by this
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
const filterDisplayAsLabel = localIdentifier
|
|
57
|
+
? attributeFilterConfigsDisplayAsLabelMap?.get(localIdentifier)
|
|
58
|
+
: undefined;
|
|
59
|
+
// The embedding API types the element lists as strings. The null element passes as it is.
|
|
60
|
+
const elementUris = [...(selectedElements?.uris ?? [])];
|
|
61
|
+
const attrFilterContext = isInverted
|
|
62
|
+
? {
|
|
63
|
+
negativeAttributeFilter: {
|
|
64
|
+
displayForm: filterDisplayForm,
|
|
65
|
+
notIn: elementUris,
|
|
66
|
+
},
|
|
67
|
+
...(filterDisplayAsLabel ? { displayAsLabel: filterDisplayAsLabel } : {}),
|
|
68
|
+
}
|
|
69
|
+
: {
|
|
70
|
+
positiveAttributeFilter: {
|
|
71
|
+
displayForm: filterDisplayForm,
|
|
72
|
+
in: elementUris,
|
|
73
|
+
},
|
|
74
|
+
...(filterDisplayAsLabel ? { displayAsLabel: filterDisplayAsLabel } : {}),
|
|
75
|
+
};
|
|
76
|
+
// Check if the insight contains a filter on the same attribute
|
|
77
|
+
const insightAttrFilter = getInsightAttrFilter(insightAttrFilters, attrFilter, availableAttributes);
|
|
78
|
+
if (insightAttrFilter &&
|
|
79
|
+
!supportsElementUris &&
|
|
80
|
+
!areObjRefsEqual(filterDisplayForm, filterObjRef(insightAttrFilter))) {
|
|
81
|
+
// when the display form is different and the backend does not support element uris, skip it and don't transfer the filter
|
|
82
|
+
// (when uris not supported, we cannot match the elements for filters easily)
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
// If it does, try to merge the two filters so that the resulting elements are the intersection of the two
|
|
86
|
+
// The intersection might not be possible and return undefined in that case
|
|
87
|
+
// Only element-based insight filters can be intersected with the dashboard filter
|
|
88
|
+
return insightAttrFilter &&
|
|
89
|
+
!isArbitraryAttributeFilter(insightAttrFilter) &&
|
|
90
|
+
!isMatchAttributeFilter(insightAttrFilter)
|
|
91
|
+
? getIntersectedAttrFilterContext(insightAttrFilter, attrFilterContext)
|
|
92
|
+
: attrFilterContext;
|
|
93
|
+
});
|
|
94
|
+
return compact(processedFilters);
|
|
95
|
+
}
|
|
96
|
+
function getInsightAttrFilter(insightAttrFilters, attrFilter, availableAttributes) {
|
|
97
|
+
const targetDisplayForm = filterObjRef(attrFilter);
|
|
98
|
+
return insightAttrFilters.find((filterItem) => {
|
|
99
|
+
const filterItemDisplayForm = filterObjRef(filterItem);
|
|
100
|
+
const filterItemAttribute = availableAttributes?.find((availableAttribute) => {
|
|
101
|
+
return availableAttribute.displayForms.some((displayForm) => areObjRefsEqual(displayForm.ref, filterItemDisplayForm));
|
|
102
|
+
});
|
|
103
|
+
return filterItemAttribute?.displayForms.some((displayForm) => areObjRefsEqual(displayForm.ref, targetDisplayForm));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function getIntersectedAttrFilterContext(insightAttrFilter, attrFilterContext) {
|
|
107
|
+
const intersectedAttrFilter = intersectFilters(insightAttrFilter, attrFilterContext);
|
|
108
|
+
const isIntersectedNoop = isPositiveAttributeFilter(intersectedAttrFilter)
|
|
109
|
+
? intersectedAttrFilter.positiveAttributeFilter.in.length === 0
|
|
110
|
+
: false; // strictly speaking, this needs to check whether all the items are selected, however such filter is extremely improbable and not worth the hassle
|
|
111
|
+
if (isIntersectedNoop || areFiltersWithSameElements(insightAttrFilter, intersectedAttrFilter)) {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
return intersectedAttrFilter;
|
|
115
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type DateFilterItem } from "@gooddata/sdk-embedding";
|
|
2
|
+
import { type IDashboardDateFilter, type IFilter, type IInsight, type IWidget } from "@gooddata/sdk-model";
|
|
3
|
+
export declare function getWidgetDateFilterItem(widget: IWidget, dateFilterContextItem: IDashboardDateFilter | undefined): DateFilterItem | undefined;
|
|
4
|
+
export declare function getDateFilterItems(appliedFilters: IFilter[], insight: IInsight): DateFilterItem[];
|
|
5
|
+
//# sourceMappingURL=dateFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dateFilters.d.ts","sourceRoot":"","sources":["../../../../src/presentation/insightEditor/filterContext/dateFilters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EACH,KAAK,oBAAoB,EAEzB,KAAK,OAAO,EACZ,KAAK,QAAQ,EAEb,KAAK,OAAO,EAWf,MAAM,qBAAqB,CAAC;AAwC7B,wBAAgB,uBAAuB,CACnC,MAAM,EAAE,OAAO,EACf,qBAAqB,EAAE,oBAAoB,GAAG,SAAS,GACxD,cAAc,GAAG,SAAS,CAK5B;AAoED,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,QAAQ,GAAG,cAAc,EAAE,CAOjG"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// (C) 2020-2026 GoodData Corporation
|
|
2
|
+
import { absoluteDateFilterValues, areObjRefsEqual, filterObjRef, insightFilters, isAbsoluteDateFilter, isAllTimeDateFilter, isDateFilter, isRelativeDateFilter, relativeDateFilterValues, } from "@gooddata/sdk-model";
|
|
3
|
+
const ALL_TIME_GRANULARITY = "ALL_TIME_GRANULARITY";
|
|
4
|
+
function getDateFilterItem(dataSet, dateFilterContextItem) {
|
|
5
|
+
if (dateFilterContextItem) {
|
|
6
|
+
if (dateFilterContextItem.dateFilter.type === "absolute") {
|
|
7
|
+
return {
|
|
8
|
+
absoluteDateFilter: {
|
|
9
|
+
dataSet,
|
|
10
|
+
from: String(dateFilterContextItem.dateFilter.from),
|
|
11
|
+
to: String(dateFilterContextItem.dateFilter.to),
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const boundedFilter = dateFilterContextItem.dateFilter.boundedFilter;
|
|
17
|
+
return {
|
|
18
|
+
relativeDateFilter: {
|
|
19
|
+
dataSet,
|
|
20
|
+
granularity: dateFilterContextItem.dateFilter.granularity,
|
|
21
|
+
from: Number(dateFilterContextItem.dateFilter.from),
|
|
22
|
+
to: Number(dateFilterContextItem.dateFilter.to),
|
|
23
|
+
...(boundedFilter ? { boundedFilter } : {}),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return {
|
|
30
|
+
relativeDateFilter: {
|
|
31
|
+
dataSet,
|
|
32
|
+
granularity: ALL_TIME_GRANULARITY,
|
|
33
|
+
from: -1,
|
|
34
|
+
to: 1,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function getWidgetDateFilterItem(widget, dateFilterContextItem) {
|
|
40
|
+
if (!widget?.dateDataSet) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return getDateFilterItem(widget.dateDataSet, dateFilterContextItem);
|
|
44
|
+
}
|
|
45
|
+
const sanitizeCorruptedAllTimeFilters = (appliedDateFilter) => {
|
|
46
|
+
if (!isRelativeDateFilter(appliedDateFilter)) {
|
|
47
|
+
return appliedDateFilter;
|
|
48
|
+
}
|
|
49
|
+
// A corrupted all time filter misses its bounds, although the type requires them.
|
|
50
|
+
const { from, to, dataSet } = appliedDateFilter.relativeDateFilter;
|
|
51
|
+
if (from === undefined || to === undefined) {
|
|
52
|
+
const relativeAllTimeDateFilter = {
|
|
53
|
+
relativeDateFilter: {
|
|
54
|
+
dataSet,
|
|
55
|
+
granularity: ALL_TIME_GRANULARITY,
|
|
56
|
+
from: 0,
|
|
57
|
+
to: 0,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
return relativeAllTimeDateFilter;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
return appliedDateFilter;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
function getDateFilterContext(dateFilter) {
|
|
67
|
+
const includeDataSet = true;
|
|
68
|
+
if (isAllTimeDateFilter(dateFilter)) {
|
|
69
|
+
const { dataSet } = relativeDateFilterValues(dateFilter, includeDataSet);
|
|
70
|
+
return {
|
|
71
|
+
relativeDateFilter: {
|
|
72
|
+
dataSet,
|
|
73
|
+
granularity: ALL_TIME_GRANULARITY,
|
|
74
|
+
from: -1,
|
|
75
|
+
to: 1,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
else if (isAbsoluteDateFilter(dateFilter)) {
|
|
80
|
+
const { dataSet, from, to } = absoluteDateFilterValues(dateFilter, includeDataSet);
|
|
81
|
+
return {
|
|
82
|
+
absoluteDateFilter: {
|
|
83
|
+
dataSet,
|
|
84
|
+
from,
|
|
85
|
+
to,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
const { dataSet, from, to, granularity, boundedFilter } = relativeDateFilterValues(dateFilter, includeDataSet);
|
|
91
|
+
return {
|
|
92
|
+
relativeDateFilter: {
|
|
93
|
+
dataSet,
|
|
94
|
+
granularity,
|
|
95
|
+
from,
|
|
96
|
+
to,
|
|
97
|
+
...(boundedFilter ? { boundedFilter } : {}),
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
export function getDateFilterItems(appliedFilters, insight) {
|
|
103
|
+
const sanitizedAppliedDateFilters = appliedFilters
|
|
104
|
+
.filter(isDateFilter)
|
|
105
|
+
.map(sanitizeCorruptedAllTimeFilters);
|
|
106
|
+
const insightDateFilters = insightFilters(insight).filter(isDateFilter);
|
|
107
|
+
return getDateFilterItemsFromAppliedFilters(sanitizedAppliedDateFilters, insightDateFilters);
|
|
108
|
+
}
|
|
109
|
+
function getDateFilterItemsFromAppliedFilters(appliedFilters, insightDateFilters) {
|
|
110
|
+
const uniqueInsightDateFilters = insightDateFilters.filter((insightDateFilter) => {
|
|
111
|
+
return !appliedFilters.some((appliedFilter) => {
|
|
112
|
+
return areObjRefsEqual(filterObjRef(appliedFilter), filterObjRef(insightDateFilter));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
const allDateFilters = [...appliedFilters, ...uniqueInsightDateFilters];
|
|
116
|
+
return allDateFilters.map((dateFilter) => getDateFilterContext(dateFilter));
|
|
117
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type INegativeAttributeFilter as IEmbedNegativeAttributeFilter, type IPositiveAttributeFilter as IEmbedPositiveAttributeFilter } from "@gooddata/sdk-embedding";
|
|
2
|
+
import { type IAttributeFilterWithSelection, type INegativeAttributeFilter, type IPositiveAttributeFilter } from "@gooddata/sdk-model";
|
|
3
|
+
export declare function intersectPositiveWithNegativeAttrFilters(positiveAttrFilter: IPositiveAttributeFilter, negativeAttrFilter: IEmbedNegativeAttributeFilter): IEmbedPositiveAttributeFilter;
|
|
4
|
+
export declare function intersectPositiveWithNegativeAttrFilters2(positiveAttrFilter: IEmbedPositiveAttributeFilter, negativeAttrFilter: INegativeAttributeFilter): IEmbedPositiveAttributeFilter;
|
|
5
|
+
export declare function intersectFilters(insightAttrFilter: IAttributeFilterWithSelection, attrFilterContext: IEmbedPositiveAttributeFilter | IEmbedNegativeAttributeFilter): IEmbedPositiveAttributeFilter | IEmbedNegativeAttributeFilter;
|
|
6
|
+
export declare function areFiltersWithSameElements(insightAttrFilter: IAttributeFilterWithSelection, attrFilterContext: IEmbedPositiveAttributeFilter | IEmbedNegativeAttributeFilter): boolean;
|
|
7
|
+
//# sourceMappingURL=filterIntersection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterIntersection.d.ts","sourceRoot":"","sources":["../../../../src/presentation/insightEditor/filterContext/filterIntersection.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,wBAAwB,IAAI,6BAA6B,EAC9D,KAAK,wBAAwB,IAAI,6BAA6B,EAGjE,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEH,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAUhC,MAAM,qBAAqB,CAAC;AAQ7B,wBAAgB,wCAAwC,CACpD,kBAAkB,EAAE,wBAAwB,EAC5C,kBAAkB,EAAE,6BAA6B,GAClD,6BAA6B,CAiC/B;AAED,wBAAgB,yCAAyC,CACrD,kBAAkB,EAAE,6BAA6B,EACjD,kBAAkB,EAAE,wBAAwB,GAC7C,6BAA6B,CA0B/B;AACD,wBAAgB,gBAAgB,CAC5B,iBAAiB,EAAE,6BAA6B,EAChD,iBAAiB,EAAE,6BAA6B,GAAG,6BAA6B,GACjF,6BAA6B,GAAG,6BAA6B,CA+D/D;AAED,wBAAgB,0BAA0B,CACtC,iBAAiB,EAAE,6BAA6B,EAChD,iBAAiB,EAAE,6BAA6B,GAAG,6BAA6B,GACjF,OAAO,CAsDT"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// (C) 2007-2026 GoodData Corporation
|
|
2
|
+
import { uniq } from "lodash-es";
|
|
3
|
+
import { isNegativeAttributeFilter as isEmbedNegativeAttributeFilter, isPositiveAttributeFilter as isEmbedPositiveAttributeFilter, } from "@gooddata/sdk-embedding";
|
|
4
|
+
import { filterAttributeElements, filterIsEmpty, isAttributeElementsByRef, isAttributeElementsByValue, isNegativeAttributeFilter, isObjRef, isPositiveAttributeFilter, newNegativeAttributeFilter, newPositiveAttributeFilter, } from "@gooddata/sdk-model";
|
|
5
|
+
// The embedding API types the element lists as strings. The null element (an empty value) passes
|
|
6
|
+
// through as it is.
|
|
7
|
+
function elementIds(elements) {
|
|
8
|
+
return (isAttributeElementsByRef(elements) ? elements.uris : elements.values);
|
|
9
|
+
}
|
|
10
|
+
export function intersectPositiveWithNegativeAttrFilters(positiveAttrFilter, negativeAttrFilter) {
|
|
11
|
+
const normalizedPositiveAttrFilter = normalizeEmptyFilterElements(positiveAttrFilter);
|
|
12
|
+
const attributeElements = normalizedPositiveAttrFilter.positiveAttributeFilter.in;
|
|
13
|
+
//NOTE: Currently in dashboard filters we are not support local identifiers, so we can safely assume that
|
|
14
|
+
// that displayForm is ObjRef
|
|
15
|
+
if (!isObjRef(normalizedPositiveAttrFilter.positiveAttributeFilter.displayForm)) {
|
|
16
|
+
throw new Error("Expected positive attribute filter display form to be ObjRef");
|
|
17
|
+
}
|
|
18
|
+
if (!isAttributeElementsByRef(attributeElements)) {
|
|
19
|
+
return {
|
|
20
|
+
positiveAttributeFilter: {
|
|
21
|
+
displayForm: normalizedPositiveAttrFilter.positiveAttributeFilter.displayForm,
|
|
22
|
+
in: elementIds(attributeElements).filter((identifier) => !negativeAttrFilter.negativeAttributeFilter.notIn.includes(identifier)),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
positiveAttributeFilter: {
|
|
28
|
+
displayForm: normalizedPositiveAttrFilter.positiveAttributeFilter.displayForm,
|
|
29
|
+
in: elementIds(attributeElements).filter((uri) => !negativeAttrFilter.negativeAttributeFilter.notIn.includes(uri)),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function intersectPositiveWithNegativeAttrFilters2(positiveAttrFilter, negativeAttrFilter) {
|
|
34
|
+
const normalizedNegativeAttrFilter = normalizeEmptyFilterElements(negativeAttrFilter);
|
|
35
|
+
const attributeElements = normalizedNegativeAttrFilter.negativeAttributeFilter.notIn;
|
|
36
|
+
if (!isAttributeElementsByRef(attributeElements)) {
|
|
37
|
+
return {
|
|
38
|
+
positiveAttributeFilter: {
|
|
39
|
+
displayForm: positiveAttrFilter.positiveAttributeFilter.displayForm,
|
|
40
|
+
in: positiveAttrFilter.positiveAttributeFilter.in.filter((identifier) => !elementIds(attributeElements).includes(identifier)),
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
positiveAttributeFilter: {
|
|
46
|
+
displayForm: positiveAttrFilter.positiveAttributeFilter.displayForm,
|
|
47
|
+
in: positiveAttrFilter.positiveAttributeFilter.in.filter((uri) => !elementIds(attributeElements).includes(uri)),
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function intersectFilters(insightAttrFilter, attrFilterContext) {
|
|
52
|
+
const normalizedInsightAttrFilter = normalizeEmptyFilterElements(insightAttrFilter);
|
|
53
|
+
const attributeElements = filterAttributeElements(normalizedInsightAttrFilter);
|
|
54
|
+
if (!isAttributeElementsByRef(attributeElements)) {
|
|
55
|
+
if (isPositiveAttributeFilter(normalizedInsightAttrFilter)) {
|
|
56
|
+
if (isEmbedPositiveAttributeFilter(attrFilterContext)) {
|
|
57
|
+
return {
|
|
58
|
+
positiveAttributeFilter: {
|
|
59
|
+
displayForm: attrFilterContext.positiveAttributeFilter.displayForm,
|
|
60
|
+
in: attrFilterContext.positiveAttributeFilter.in.filter((identifier) => elementIds(attributeElements).includes(identifier)),
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return intersectPositiveWithNegativeAttrFilters(normalizedInsightAttrFilter, attrFilterContext);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (isEmbedNegativeAttributeFilter(attrFilterContext)) {
|
|
68
|
+
return {
|
|
69
|
+
negativeAttributeFilter: {
|
|
70
|
+
displayForm: attrFilterContext.negativeAttributeFilter.displayForm,
|
|
71
|
+
notIn: uniq(elementIds(attributeElements).concat(attrFilterContext.negativeAttributeFilter.notIn)),
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return intersectPositiveWithNegativeAttrFilters2(attrFilterContext, normalizedInsightAttrFilter);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (isPositiveAttributeFilter(normalizedInsightAttrFilter)) {
|
|
79
|
+
if (isEmbedPositiveAttributeFilter(attrFilterContext)) {
|
|
80
|
+
return {
|
|
81
|
+
positiveAttributeFilter: {
|
|
82
|
+
displayForm: attrFilterContext.positiveAttributeFilter.displayForm,
|
|
83
|
+
in: attrFilterContext.positiveAttributeFilter.in.filter((uri) => elementIds(attributeElements).includes(uri)),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return intersectPositiveWithNegativeAttrFilters(normalizedInsightAttrFilter, attrFilterContext);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
if (isEmbedNegativeAttributeFilter(attrFilterContext)) {
|
|
91
|
+
return {
|
|
92
|
+
negativeAttributeFilter: {
|
|
93
|
+
displayForm: attrFilterContext.negativeAttributeFilter.displayForm,
|
|
94
|
+
notIn: uniq(elementIds(attributeElements).concat(attrFilterContext.negativeAttributeFilter.notIn)),
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return intersectPositiveWithNegativeAttrFilters2(attrFilterContext, normalizedInsightAttrFilter);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export function areFiltersWithSameElements(insightAttrFilter, attrFilterContext) {
|
|
102
|
+
const normalizedInsightAttrFilter = normalizeEmptyFilterElements(insightAttrFilter);
|
|
103
|
+
const attributeElements = filterAttributeElements(normalizedInsightAttrFilter);
|
|
104
|
+
if (!isAttributeElementsByRef(attributeElements)) {
|
|
105
|
+
if (isPositiveAttributeFilter(normalizedInsightAttrFilter) &&
|
|
106
|
+
isEmbedPositiveAttributeFilter(attrFilterContext)) {
|
|
107
|
+
return (elementIds(attributeElements).length ===
|
|
108
|
+
attrFilterContext.positiveAttributeFilter.in.length &&
|
|
109
|
+
elementIds(attributeElements).every((identifier) => attrFilterContext.positiveAttributeFilter.in.includes(identifier)));
|
|
110
|
+
}
|
|
111
|
+
else if (isNegativeAttributeFilter(normalizedInsightAttrFilter) &&
|
|
112
|
+
isEmbedNegativeAttributeFilter(attrFilterContext)) {
|
|
113
|
+
return (elementIds(attributeElements).length ===
|
|
114
|
+
attrFilterContext.negativeAttributeFilter.notIn.length &&
|
|
115
|
+
elementIds(attributeElements).every((identifier) => attrFilterContext.negativeAttributeFilter.notIn.includes(identifier)));
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (isPositiveAttributeFilter(normalizedInsightAttrFilter) &&
|
|
120
|
+
isEmbedPositiveAttributeFilter(attrFilterContext)) {
|
|
121
|
+
return (elementIds(attributeElements).length === attrFilterContext.positiveAttributeFilter.in.length &&
|
|
122
|
+
elementIds(attributeElements).every((uri) => attrFilterContext.positiveAttributeFilter.in.includes(uri)));
|
|
123
|
+
}
|
|
124
|
+
else if (isNegativeAttributeFilter(normalizedInsightAttrFilter) &&
|
|
125
|
+
isEmbedNegativeAttributeFilter(attrFilterContext)) {
|
|
126
|
+
return (elementIds(attributeElements).length === attrFilterContext.negativeAttributeFilter.notIn.length &&
|
|
127
|
+
elementIds(attributeElements).every((uri) => attrFilterContext.negativeAttributeFilter.notIn.includes(uri)));
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Empty attribute filters by value and by uri are same, so we want to sometimes normalize them to uris.
|
|
133
|
+
* If filter is not empty it can't be normalized, so same filter is returned
|
|
134
|
+
* @param filter -
|
|
135
|
+
* @returns empty filter with uri elements or original filter
|
|
136
|
+
*/
|
|
137
|
+
function normalizeEmptyFilterElements(filter) {
|
|
138
|
+
const attributeElements = filterAttributeElements(filter);
|
|
139
|
+
if (filterIsEmpty(filter) && isAttributeElementsByValue(attributeElements)) {
|
|
140
|
+
if (isPositiveAttributeFilter(filter) && isObjRef(filter.positiveAttributeFilter.displayForm)) {
|
|
141
|
+
return newPositiveAttributeFilter(filter.positiveAttributeFilter.displayForm, { uris: [] });
|
|
142
|
+
}
|
|
143
|
+
if (isNegativeAttributeFilter(filter) && isObjRef(filter.negativeAttributeFilter.displayForm)) {
|
|
144
|
+
return newNegativeAttributeFilter(filter.negativeAttributeFilter.displayForm, { uris: [] });
|
|
145
|
+
}
|
|
146
|
+
throw new Error("Invariant: expected positive or negative filter");
|
|
147
|
+
}
|
|
148
|
+
return filter;
|
|
149
|
+
}
|