You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by di...@apache.org on 2023/02/02 16:04:39 UTC
[superset] 01/01: Initial implementation
This is an automated email from the ASF dual-hosted git repository.
diegopucci pushed a commit to branch feat/cross-filters-sidebar
in repository https://gitbox.apache.org/repos/asf/superset.git
commit 6f8418b9922f32fecff039e146e81c0e83ba8265
Author: geido <di...@gmail.com>
AuthorDate: Thu Feb 2 17:04:17 2023 +0100
Initial implementation
---
.../DetailsPanel/DetailsPanel.test.tsx | 2 +-
.../components/FiltersBadge/DetailsPanel/index.tsx | 2 +-
.../FilterIndicator/FilterIndicator.test.tsx | 2 +-
.../FiltersBadge/FilterIndicator/index.tsx | 2 +-
.../dashboard/components/FiltersBadge/index.tsx | 2 +-
.../FilterBar/FilterBarCrossFilters/Vertical.tsx | 155 +++++++++++++++++
.../FilterBar/FilterBarCrossFilters/index.tsx | 72 ++++++++
.../nativeFilters/FilterBar/Vertical.tsx | 188 ++++++++++++---------
.../{FiltersBadge => nativeFilters}/selectors.ts | 146 +++++++++-------
9 files changed, 426 insertions(+), 145 deletions(-)
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx
index 8d2b121ff6..3c3e25ee56 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/DetailsPanel.test.tsx
@@ -19,7 +19,7 @@
import userEvent from '@testing-library/user-event';
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
-import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors';
+import { Indicator } from 'src/dashboard/components/nativeFilters/selectors';
import DetailsPanel from '.';
const createProps = () => ({
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/index.tsx
index 3531ab1be9..022dab7968 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/index.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/DetailsPanel/index.tsx
@@ -29,7 +29,7 @@ import {
Reset,
Title,
} from 'src/dashboard/components/FiltersBadge/Styles';
-import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors';
+import { Indicator } from 'src/dashboard/components/nativeFilters/selectors';
import FilterIndicator from 'src/dashboard/components/FiltersBadge/FilterIndicator';
import { RootState } from 'src/dashboard/types';
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx
index fdded804b8..de49516a64 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/FilterIndicator.test.tsx
@@ -19,7 +19,7 @@
import userEvent from '@testing-library/user-event';
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
-import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors';
+import { Indicator } from 'src/dashboard/components/nativeFilters/selectors';
import FilterIndicator from '.';
const createProps = () => ({
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx
index e7675a3ef0..2954474e64 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/FilterIndicator/index.tsx
@@ -28,7 +28,7 @@ import {
ItemIcon,
Title,
} from 'src/dashboard/components/FiltersBadge/Styles';
-import { Indicator } from 'src/dashboard/components/FiltersBadge/selectors';
+import { Indicator } from 'src/dashboard/components/nativeFilters/selectors';
export interface IndicatorProps {
indicator: Indicator;
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
index fd21d07fc2..0532822530 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
+++ b/superset-frontend/src/dashboard/components/FiltersBadge/index.tsx
@@ -31,7 +31,7 @@ import {
IndicatorStatus,
selectIndicatorsForChart,
selectNativeIndicatorsForChart,
-} from './selectors';
+} from '../nativeFilters/selectors';
import {
ChartsState,
DashboardInfo,
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/Vertical.tsx
new file mode 100644
index 0000000000..484404580a
--- /dev/null
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/Vertical.tsx
@@ -0,0 +1,155 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback } from 'react';
+import Collapse from 'src/components/Collapse';
+import { styled, t, css } from '@superset-ui/core';
+import { Indicator } from 'src/dashboard/components/nativeFilters/selectors';
+import Icons from 'src/components/Icons';
+import { useDispatch } from 'react-redux';
+import { setFocusedNativeFilter } from 'src/dashboard/actions/nativeFilters';
+import { Tag } from 'src/components';
+
+const StyledCollapse = styled(Collapse)`
+ ${({ theme }) => `
+ .ant-collapse-item > .ant-collapse-header {
+ padding-bottom: 0;
+ }
+ .ant-collapse-item > .ant-collapse-header > .ant-collapse-arrow {
+ font-size: ${theme.typography.sizes.xs}px;
+ padding-top: ${theme.gridUnit * 3.5}px;
+ }
+ .ant-collapse-item > .ant-collapse-content > .ant-collapse-content-box {
+ padding-top: 0;
+ }
+ `}
+`;
+
+const StyledCrossFilter = styled.div`
+ ${({ theme }) => `
+ margin-top: ${theme.gridUnit * 4}px;
+ `}
+`;
+
+const StyledCrossFiltersTitle = styled.span`
+ font-size: ${({ theme }) => `${theme.typography.sizes.s}px;`};
+`;
+
+const StyledCrossFilterTitle = styled.div`
+ ${({ theme }) => `
+ display: flex;
+ font-size: ${theme.typography.sizes.s}px;
+ color: ${theme.colors.grayscale.base};
+ vertical-align: middle;
+ cursor: pointer;
+ align-items: center;
+ `}
+`;
+const StyledIconSearch = styled(Icons.SearchOutlined)`
+ ${({ theme }) => `
+ color: ${theme.colors.grayscale.light1};
+ margin-left: ${theme.gridUnit * 2}px;
+ &:hover {
+ color: ${theme.colors.grayscale.base};
+ }
+ `}
+`;
+
+const StyledCrossFilterTag = styled(Tag)`
+ ${({ theme }) => `
+ margin-top: ${theme.gridUnit * 2}px;
+ `}
+`;
+
+const ellipsisCss = css`
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: inline-block;
+ vertical-align: middle;
+`;
+
+const StyledCrossFilterValue = styled('b')`
+ ${({ theme }) => `
+ max-width: ${theme.gridUnit * 30}px;
+ ${ellipsisCss}
+ `}
+`;
+
+const StyledCrossFilterColumn = styled('span')`
+ ${({ theme }) => `
+ max-width: ${theme.gridUnit * 20}px;
+ ${ellipsisCss}
+ `}
+`;
+
+const FilterBarCrossFiltersVertical = (props: {
+ crossFilters: Indicator[];
+}) => {
+ const { crossFilters } = props;
+ const dispatch = useDispatch();
+ const onHighlightFilterSource = useCallback(
+ (path?: string[]) => {
+ if (path) {
+ dispatch(setFocusedNativeFilter(path[0]));
+ }
+ },
+ [dispatch],
+ );
+
+ const crossFiltersIndicators = crossFilters.map(filter => (
+ <StyledCrossFilter>
+ <StyledCrossFilterTitle
+ key={filter.name}
+ onClick={() => onHighlightFilterSource(filter.path)}
+ role="button"
+ tabIndex={0}
+ >
+ {filter.name} <StyledIconSearch iconSize="xs" />
+ </StyledCrossFilterTitle>
+ {(filter.column || filter.value) && (
+ <StyledCrossFilterTag closable>
+ <StyledCrossFilterColumn>{filter.column} </StyledCrossFilterColumn>
+ <StyledCrossFilterValue>{filter.value}</StyledCrossFilterValue>
+ </StyledCrossFilterTag>
+ )}
+ </StyledCrossFilter>
+ ));
+
+ return (
+ <StyledCollapse
+ ghost
+ defaultActiveKey="crossFilters"
+ expandIconPosition="right"
+ >
+ <Collapse.Panel
+ key="crossFilters"
+ header={
+ <StyledCrossFiltersTitle>
+ {t('Cross-filters')}
+ </StyledCrossFiltersTitle>
+ }
+ >
+ {crossFiltersIndicators}
+ </Collapse.Panel>
+ </StyledCollapse>
+ );
+};
+
+export default FilterBarCrossFiltersVertical;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/index.tsx
new file mode 100644
index 0000000000..8fc639aad8
--- /dev/null
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBarCrossFilters/index.tsx
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from 'react';
+import {
+ FilterBarOrientation,
+ DashboardInfo,
+ DashboardLayout,
+ RootState,
+} from 'src/dashboard/types';
+import { DataMaskStateWithId } from '@superset-ui/core';
+import {
+ selectChartCrossFilters,
+ Indicator,
+} from 'src/dashboard/components/nativeFilters/selectors';
+import { useSelector } from 'react-redux';
+import FilterBarCrossFiltersVertical from './Vertical';
+
+const FilterBarCrossFilters = (props: {
+ orientation: FilterBarOrientation;
+}) => {
+ const { orientation } = props;
+ const dataMask = useSelector<RootState, DataMaskStateWithId>(
+ state => state.dataMask,
+ );
+ const dashboardInfo = useSelector<RootState, DashboardInfo>(
+ state => state.dashboardInfo,
+ );
+ const dashboardLayout = useSelector<RootState, DashboardLayout>(
+ state => state.dashboardLayout.present,
+ );
+ const chartConfiguration = dashboardInfo.metadata?.chart_configuration;
+ const chartsIds = Object.keys(chartConfiguration);
+ let selectedCrossFilters: Indicator[] = [];
+
+ chartsIds.forEach(id => {
+ const chartId = Number(id);
+ const crossFilters = selectChartCrossFilters(
+ dataMask,
+ chartId,
+ dashboardLayout,
+ chartConfiguration,
+ );
+ selectedCrossFilters = [...selectedCrossFilters, ...crossFilters];
+ });
+
+ if (!selectedCrossFilters.length) return null;
+
+ return orientation === FilterBarOrientation.VERTICAL ? (
+ <FilterBarCrossFiltersVertical crossFilters={selectedCrossFilters} />
+ ) : (
+ <span>Horizontal</span>
+ );
+};
+
+export default FilterBarCrossFilters;
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
index 2a6b717836..168994db0c 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx
@@ -34,6 +34,7 @@ import { AntdTabs } from 'src/components';
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
import Loading from 'src/components/Loading';
import { EmptyStateSmall } from 'src/components/EmptyState';
+import { FilterBarOrientation } from 'src/dashboard/types';
import { getFilterBarTestId } from './utils';
import { TabIds, VerticalBarProps } from './types';
import FilterSets from './FilterSets';
@@ -41,6 +42,7 @@ import { useFilterSets } from './state';
import EditSection from './FilterSets/EditSection';
import Header from './Header';
import FilterControls from './FilterControls/FilterControls';
+import FilterBarCrossFilters from './FilterBarCrossFilters';
const BarWrapper = styled.div<{ width: number }>`
width: ${({ theme }) => theme.gridUnit * 8}px;
@@ -191,6 +193,101 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
const numberOfFilters = nativeFilterValues.length;
+ const filterControls = useMemo(
+ () =>
+ filterValues.length === 0 ? (
+ <FilterBarEmptyStateContainer>
+ <EmptyStateSmall
+ title={t('No filters are currently added')}
+ image="filter.svg"
+ description={
+ canEdit &&
+ t('Click the button above to add a filter to the dashboard')
+ }
+ />
+ </FilterBarEmptyStateContainer>
+ ) : (
+ <FilterControlsWrapper>
+ <FilterControls
+ dataMaskSelected={dataMaskSelected}
+ focusedFilterId={focusedFilterId}
+ onFilterSelectionChange={onSelectionChange}
+ />
+ </FilterControlsWrapper>
+ ),
+ [
+ canEdit,
+ dataMaskSelected,
+ filterValues.length,
+ focusedFilterId,
+ onSelectionChange,
+ ],
+ );
+
+ const filterSetsTabs = useMemo(
+ () => (
+ <StyledTabs
+ centered
+ onChange={setTab as HandlerFunction}
+ defaultActiveKey={TabIds.AllFilters}
+ activeKey={editFilterSetId ? TabIds.AllFilters : undefined}
+ >
+ <AntdTabs.TabPane
+ tab={t('All filters (%(filterCount)d)', {
+ filterCount: numberOfFilters,
+ })}
+ key={TabIds.AllFilters}
+ css={tabPaneStyle}
+ >
+ {editFilterSetId && (
+ <EditSection
+ dataMaskSelected={dataMaskSelected}
+ disabled={!isDisabled}
+ onCancel={() => setEditFilterSetId(null)}
+ filterSetId={editFilterSetId}
+ />
+ )}
+ {filterControls}
+ </AntdTabs.TabPane>
+ <AntdTabs.TabPane
+ disabled={!!editFilterSetId}
+ tab={t('Filter sets (%(filterSetCount)d)', {
+ filterSetCount: filterSetFilterValues.length,
+ })}
+ key={TabIds.FilterSets}
+ css={tabPaneStyle}
+ >
+ <FilterSets
+ onEditFilterSet={setEditFilterSetId}
+ disabled={!isDisabled}
+ dataMaskSelected={dataMaskSelected}
+ tab={tab}
+ onFilterSelectionChange={onSelectionChange}
+ />
+ </AntdTabs.TabPane>
+ </StyledTabs>
+ ),
+ [
+ dataMaskSelected,
+ editFilterSetId,
+ filterControls,
+ filterSetFilterValues.length,
+ isDisabled,
+ numberOfFilters,
+ onSelectionChange,
+ tab,
+ tabPaneStyle,
+ ],
+ );
+
+ const crossFilters = useMemo(
+ () =>
+ isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS) ? (
+ <FilterBarCrossFilters orientation={FilterBarOrientation.VERTICAL} />
+ ) : null,
+ [],
+ );
+
return (
<FilterBarScrollContext.Provider value={isScrolling}>
<BarWrapper
@@ -220,91 +317,16 @@ const VerticalFilterBar: React.FC<VerticalBarProps> = ({
<Loading />
</div>
) : isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS_SET) ? (
- <StyledTabs
- centered
- onChange={setTab as HandlerFunction}
- defaultActiveKey={TabIds.AllFilters}
- activeKey={editFilterSetId ? TabIds.AllFilters : undefined}
- >
- <AntdTabs.TabPane
- tab={t('All filters (%(filterCount)d)', {
- filterCount: numberOfFilters,
- })}
- key={TabIds.AllFilters}
- css={tabPaneStyle}
- >
- {editFilterSetId && (
- <EditSection
- dataMaskSelected={dataMaskSelected}
- disabled={!isDisabled}
- onCancel={() => setEditFilterSetId(null)}
- filterSetId={editFilterSetId}
- />
- )}
- {filterValues.length === 0 ? (
- <FilterBarEmptyStateContainer>
- <EmptyStateSmall
- title={t('No filters are currently added')}
- image="filter.svg"
- description={
- canEdit &&
- t(
- 'Click the button above to add a filter to the dashboard',
- )
- }
- />
- </FilterBarEmptyStateContainer>
- ) : (
- <FilterControlsWrapper>
- <FilterControls
- dataMaskSelected={dataMaskSelected}
- focusedFilterId={focusedFilterId}
- onFilterSelectionChange={onSelectionChange}
- />
- </FilterControlsWrapper>
- )}
- </AntdTabs.TabPane>
- <AntdTabs.TabPane
- disabled={!!editFilterSetId}
- tab={t('Filter sets (%(filterSetCount)d)', {
- filterSetCount: filterSetFilterValues.length,
- })}
- key={TabIds.FilterSets}
- css={tabPaneStyle}
- >
- <FilterSets
- onEditFilterSet={setEditFilterSetId}
- disabled={!isDisabled}
- dataMaskSelected={dataMaskSelected}
- tab={tab}
- onFilterSelectionChange={onSelectionChange}
- />
- </AntdTabs.TabPane>
- </StyledTabs>
+ <>
+ {crossFilters}
+ {filterSetsTabs}
+ </>
) : (
<div css={tabPaneStyle} onScroll={onScroll}>
- {filterValues.length === 0 ? (
- <FilterBarEmptyStateContainer>
- <EmptyStateSmall
- title={t('No filters are currently added')}
- image="filter.svg"
- description={
- canEdit &&
- t(
- 'Click the button above to add a filter to the dashboard',
- )
- }
- />
- </FilterBarEmptyStateContainer>
- ) : (
- <FilterControlsWrapper>
- <FilterControls
- dataMaskSelected={dataMaskSelected}
- focusedFilterId={focusedFilterId}
- onFilterSelectionChange={onSelectionChange}
- />
- </FilterControlsWrapper>
- )}
+ <>
+ {crossFilters}
+ {filterControls}
+ </>
</div>
)}
{actions}
diff --git a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts
similarity index 85%
rename from superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
rename to superset-frontend/src/dashboard/components/nativeFilters/selectors.ts
index c0916b9960..d84b755a11 100644
--- a/superset-frontend/src/dashboard/components/FiltersBadge/selectors.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/selectors.ts
@@ -60,7 +60,7 @@ type Filter = {
};
const extractLabel = (filter?: FilterState): string | null => {
- if (filter?.label) {
+ if (filter?.label && !filter?.label?.includes(undefined)) {
return filter.label;
}
if (filter?.value) {
@@ -214,9 +214,84 @@ export const selectIndicatorsForChart = (
return indicators;
};
+const getStatus = ({
+ label,
+ column,
+ type = DataMaskType.NativeFilters,
+ rejectedColumns,
+ appliedColumns,
+}: {
+ label: string | null;
+ column?: string;
+ type?: DataMaskType;
+ rejectedColumns?: Set<string>;
+ appliedColumns?: Set<string>;
+}): IndicatorStatus => {
+ // a filter is only considered unset if it's value is null
+ const hasValue = label !== null;
+ if (type === DataMaskType.CrossFilters && hasValue) {
+ return IndicatorStatus.CrossFilterApplied;
+ }
+ if (!column && hasValue) {
+ // Filter without datasource
+ return IndicatorStatus.Applied;
+ }
+ if (column && rejectedColumns?.has(column))
+ return IndicatorStatus.Incompatible;
+ if (column && appliedColumns?.has(column) && hasValue) {
+ return IndicatorStatus.Applied;
+ }
+ return IndicatorStatus.Unset;
+};
+
+const defaultChartConfig = {};
+export const selectChartCrossFilters = (
+ dataMask: DataMaskStateWithId,
+ chartId: number,
+ dashboardLayout: Layout,
+ chartConfiguration: ChartConfiguration = defaultChartConfig,
+): Indicator[] => {
+ let crossFilterIndicators: any = [];
+ if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
+ const dashboardLayoutValues = Object.values(dashboardLayout);
+ crossFilterIndicators = Object.values(chartConfiguration)
+ .filter(chartConfig =>
+ chartConfig.crossFilters?.chartsInScope?.includes(chartId),
+ )
+ .map(chartConfig => {
+ const filterState = dataMask[chartConfig.id]?.filterState;
+ const extraFormData = dataMask[chartConfig.id]?.extraFormData;
+ const label = extractLabel(filterState);
+ const filtersState = filterState?.filters;
+ const column =
+ extraFormData?.filters?.[0]?.col ||
+ (filtersState && Object.keys(filtersState)[0]);
+
+ const dashboardLayoutItem = dashboardLayoutValues.find(
+ layoutItem => layoutItem?.meta?.chartId === chartConfig.id,
+ );
+ return {
+ column,
+ name: dashboardLayoutItem?.meta?.sliceName as string,
+ path: [
+ ...(dashboardLayoutItem?.parents ?? []),
+ dashboardLayoutItem?.id,
+ ],
+ status: getStatus({
+ label,
+ type: DataMaskType.CrossFilters,
+ }),
+ value: label,
+ };
+ })
+ .filter(filter => filter.status === IndicatorStatus.CrossFilterApplied);
+ }
+
+ return crossFilterIndicators;
+};
+
const cachedNativeIndicatorsForChart = {};
const cachedNativeFilterDataForChart: any = {};
-const defaultChartConfig = {};
export const selectNativeIndicatorsForChart = (
nativeFilters: Filters,
dataMask: DataMaskStateWithId,
@@ -240,31 +315,6 @@ export const selectNativeIndicatorsForChart = (
) {
return cachedNativeIndicatorsForChart[chartId];
}
- const getStatus = ({
- label,
- column,
- type = DataMaskType.NativeFilters,
- }: {
- label: string | null;
- column?: string;
- type?: DataMaskType;
- }): IndicatorStatus => {
- // a filter is only considered unset if it's value is null
- const hasValue = label !== null;
- if (type === DataMaskType.CrossFilters && hasValue) {
- return IndicatorStatus.CrossFilterApplied;
- }
- if (!column && hasValue) {
- // Filter without datasource
- return IndicatorStatus.Applied;
- }
- if (column && rejectedColumns.has(column))
- return IndicatorStatus.Incompatible;
- if (column && appliedColumns.has(column) && hasValue) {
- return IndicatorStatus.Applied;
- }
- return IndicatorStatus.Unset;
- };
let nativeFilterIndicators: any = [];
if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS)) {
@@ -284,7 +334,12 @@ export const selectNativeIndicatorsForChart = (
column,
name: nativeFilter.name,
path: [nativeFilter.id],
- status: getStatus({ label, column }),
+ status: getStatus({
+ label,
+ column,
+ rejectedColumns,
+ appliedColumns,
+ }),
value: label,
};
});
@@ -292,35 +347,12 @@ export const selectNativeIndicatorsForChart = (
let crossFilterIndicators: any = [];
if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) {
- const dashboardLayoutValues = Object.values(dashboardLayout);
- crossFilterIndicators = Object.values(chartConfiguration)
- .filter(chartConfig =>
- chartConfig.crossFilters?.chartsInScope?.includes(chartId),
- )
- .map(chartConfig => {
- const filterState = dataMask[chartConfig.id]?.filterState;
- const label = extractLabel(filterState);
- const filtersState = filterState?.filters;
- const column = filtersState && Object.keys(filtersState)[0];
-
- const dashboardLayoutItem = dashboardLayoutValues.find(
- layoutItem => layoutItem?.meta?.chartId === chartConfig.id,
- );
- return {
- column,
- name: dashboardLayoutItem?.meta?.sliceName as string,
- path: [
- ...(dashboardLayoutItem?.parents ?? []),
- dashboardLayoutItem?.id,
- ],
- status: getStatus({
- label,
- type: DataMaskType.CrossFilters,
- }),
- value: label,
- };
- })
- .filter(filter => filter.status === IndicatorStatus.CrossFilterApplied);
+ crossFilterIndicators = selectChartCrossFilters(
+ dataMask,
+ chartId,
+ dashboardLayout,
+ chartConfiguration,
+ );
}
const indicators = crossFilterIndicators.concat(nativeFilterIndicators);
cachedNativeIndicatorsForChart[chartId] = indicators;