Skip to content

Commit

Permalink
feat(filter-set): adding new filters (#13515)
Browse files Browse the repository at this point in the history
* refactor(native-filters): move data mask to root reducer

* refactor: update rest stuff for dataMask

* refactor: add ownCrrentState to explore

* fix: fix immer reducer

* fix: merge with master

* refactor: support explore dataMask

* refactor: support explore dataMask

* docs: add comment

* refactor: remove json stringify

* fix: fix failed cases

* feat: filter bat buttons start

* fix: fix CR notes

* fix: fix cascade filters

* fix: fix CR notes

* refactor: add clear all

* fix: fix CR notes

* fix: fix CR notes

* fix: fix CR notes

* feat: buttons in filter bar

* lint: update imports

* feat: add tabs for filter sets

* feat: add buttons to filter set

* feat: first phase add filter sets

* fix: undo FF

* fix: fix CR notes

* fix: fix CR notes

* lint: fix lint

* fix: fix filter bar opening

* refactor: continue filter sets
  • Loading branch information
simcha90 authored Mar 9, 2021
1 parent 40fc144 commit 9b8e255
Show file tree
Hide file tree
Showing 11 changed files with 506 additions and 276 deletions.
2 changes: 1 addition & 1 deletion superset-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions superset-frontend/src/common/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export { FormInstance } from 'antd/lib/form';
export { RadioChangeEvent } from 'antd/lib/radio';

export { default as Badge } from './Badge';
export { default as Collapse } from './Collapse';
export { default as Progress } from './ProgressBar';

export const MenuItem = styled(AntdMenu.Item)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
FilterValue,
} from './Styles';
import { Indicator } from './selectors';
import { getFilterValueForDisplay } from '../nativeFilters/FilterBar/FilterSets/utils';

export interface IndicatorProps {
indicator: Indicator;
Expand All @@ -46,18 +47,21 @@ export interface IndicatorProps {
const Indicator = ({
indicator: { column, name, value = [], path },
onClick,
}: IndicatorProps) => (
<Item onClick={() => onClick([...path, `LABEL-${column}`])}>
<Title bold>
<ItemIcon>
<SearchOutlined />
</ItemIcon>
{name}
{value.length ? ': ' : ''}
</Title>
<FilterValue>{value.length ? value.join(', ') : ''}</FilterValue>
</Item>
);
}: IndicatorProps) => {
const resultValue = getFilterValueForDisplay(value);
return (
<Item onClick={() => onClick([...path, `LABEL-${column}`])}>
<Title bold>
<ItemIcon>
<SearchOutlined />
</ItemIcon>
{name}
{resultValue ? ': ' : ''}
</Title>
<FilterValue>{resultValue}</FilterValue>
</Item>
);
};

export interface DetailsPanelProps {
appliedIndicators: Indicator[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ import { useImmer } from 'use-immer';
import { getInitialMask } from 'src/dataMask/reducer';
import { areObjectsEqual } from 'src/reduxUtils';
import FilterConfigurationLink from './FilterConfigurationLink';
import { useFilterConfiguration } from '../state';
import { Filter } from '../types';
import { buildCascadeFiltersTree, mapParentFiltersToChildren } from './utils';
import CascadePopover from './CascadePopover';
import FilterSets from './FilterSets';
import FilterSets from './FilterSets/FilterSets';
import { useFilters, useFilterSets } from './state';

const barWidth = `250px`;

Expand Down Expand Up @@ -128,14 +128,6 @@ const TitleArea = styled.h4`
& > span {
flex-grow: 1;
}
& :not(:first-child) {
margin-left: ${({ theme }) => theme.gridUnit}px;
&:hover {
cursor: pointer;
}
}
`;

const StyledTabs = styled(Tabs)`
Expand All @@ -153,6 +145,9 @@ const StyledTabs = styled(Tabs)`
const ActionButtons = styled.div`
display: grid;
flex-direction: row;
justify-content: center;
align-items: center;
grid-gap: 10px;
grid-template-columns: 1fr 1fr;
${({ theme }) =>
`padding: 0 ${theme.gridUnit * 2}px ${theme.gridUnit * 2}px`};
Expand All @@ -164,6 +159,9 @@ const ActionButtons = styled.div`

const FilterControls = styled.div`
padding: 0 ${({ theme }) => theme.gridUnit * 4}px;
&:hover {
cursor: pointer;
}
`;

interface FiltersBarProps {
Expand All @@ -183,48 +181,67 @@ const FilterBar: React.FC<FiltersBarProps> = ({
setLastAppliedFilterData,
] = useImmer<DataMaskUnit>({});
const dispatch = useDispatch();
const filterSets = useFilterSets();
const filterSetsArray = Object.values(filterSets);
const filters = useFilters();
const filtersArray = Object.values(filters);
const dataMaskState = useSelector<any, DataMaskUnitWithId>(
state => state.dataMask.nativeFilters ?? {},
);
const filterConfigs = useFilterConfiguration();
const canEdit = useSelector<any, boolean>(
({ dashboardInfo }) => dashboardInfo.dash_edit_perm,
);
const [visiblePopoverId, setVisiblePopoverId] = useState<string | null>(null);
const [isInitialized, setIsInitialized] = useState<boolean>(false);

const handleApply = () => {
const filterIds = Object.keys(filterData);
filterIds.forEach(filterId => {
if (filterData[filterId]) {
dispatch(
updateDataMask(filterId, {
nativeFilters: filterData[filterId],
}),
);
}
});
setLastAppliedFilterData(() => filterData);
};

useEffect(() => {
if (isInitialized) {
return;
}
const areFiltersInitialized = filterConfigs.every(
filterConfig =>
filterConfig.defaultValue ===
const areFiltersInitialized = filtersArray.every(filterConfig =>
areObjectsEqual(
filterConfig.defaultValue,
filterData[filterConfig.id]?.currentState?.value,
),
);
if (areFiltersInitialized) {
handleApply();
setIsInitialized(true);
}
}, [filterConfigs, filterData, isInitialized]);
}, [filtersArray, filterData, isInitialized]);

useEffect(() => {
if (filterConfigs.length === 0 && filtersOpen) {
if (filtersArray.length === 0 && filtersOpen) {
toggleFiltersBar(false);
}
}, [filterConfigs]);
}, [filtersArray.length]);

const cascadeChildren = useMemo(
() => mapParentFiltersToChildren(filterConfigs),
[filterConfigs],
() => mapParentFiltersToChildren(filtersArray),
[filtersArray],
);

const cascadeFilters = useMemo(() => {
const filtersWithValue = filterConfigs.map(filter => ({
const filtersWithValue = filtersArray.map(filter => ({
...filter,
currentValue: filterData[filter.id]?.currentState?.value,
}));
return buildCascadeFiltersTree(filtersWithValue);
}, [filterConfigs, filterData]);
}, [filtersArray, filterData]);

const handleFilterSelectionChange = (
filter: Pick<Filter, 'id'> & Partial<Filter>,
Expand All @@ -243,35 +260,15 @@ const FilterBar: React.FC<FiltersBarProps> = ({
});
};

const handleApply = () => {
const filterIds = Object.keys(filterData);
filterIds.forEach(filterId => {
if (filterData[filterId]) {
dispatch(
updateDataMask(filterId, {
nativeFilters: filterData[filterId],
}),
);
}
});
setLastAppliedFilterData(() => filterData);
};

useEffect(() => {
if (isInitialized) {
handleApply();
}
}, [isInitialized]);

const handleClearAll = () => {
filterConfigs.forEach(filter => {
filtersArray.forEach(filter => {
setFilterData(draft => {
draft[filter.id] = getInitialMask(filter.id);
});
});
};

const isClearAllDisabled = !Object.values(dataMaskState).every(
const isClearAllDisabled = Object.values(dataMaskState).every(
filter =>
filterData[filter.id]?.currentState?.value === null ||
(!filterData[filter.id] && filter.currentState?.value === null),
Expand All @@ -295,6 +292,9 @@ const FilterBar: React.FC<FiltersBarProps> = ({
</FilterControls>
);

const isApplyDisabled =
!isInitialized || areObjectsEqual(filterData, lastAppliedFilterData);

return (
<BarWrapper data-test="filter-bar" className={cx({ open: filtersOpen })}>
<CollapsedBar
Expand All @@ -309,7 +309,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
<span>{t('Filters')}</span>
{canEdit && (
<FilterConfigurationLink
createNewOnOpen={filterConfigs.length === 0}
createNewOnOpen={filtersArray.length === 0}
>
<Icon name="edit" data-test="create-filter" />
</FilterConfigurationLink>
Expand All @@ -318,7 +318,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
</TitleArea>
<ActionButtons>
<Button
disabled={!isClearAllDisabled}
disabled={isClearAllDisabled}
buttonStyle="tertiary"
buttonSize="small"
onClick={handleClearAll}
Expand All @@ -327,10 +327,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
{t('Clear all')}
</Button>
<Button
disabled={
!isInitialized ||
areObjectsEqual(filterData, lastAppliedFilterData)
}
disabled={isApplyDisabled}
buttonStyle="primary"
htmlType="submit"
buttonSize="small"
Expand All @@ -347,13 +344,17 @@ const FilterBar: React.FC<FiltersBarProps> = ({
onChange={() => {}}
>
<Tabs.TabPane
tab={t(`All Filters (${filterConfigs.length})`)}
tab={t(`All Filters (${filtersArray.length})`)}
key="allFilters"
>
{getFilterControls()}
</Tabs.TabPane>
<Tabs.TabPane tab={t('Filter Sets')} key="filterSets">
<Tabs.TabPane
tab={t(`Filter Sets (${filterSetsArray.length})`)}
key="filterSets"
>
<FilterSets
disabled={!isApplyDisabled}
dataMaskState={dataMaskState}
onFilterSelectionChange={handleFilterSelectionChange}
/>
Expand Down
Loading

0 comments on commit 9b8e255

Please sign in to comment.