Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(filter-set): Update existing filter set #13545

Merged
merged 73 commits into from
Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
2731518
refactor(native-filters): move data mask to root reducer
simcha90 Mar 3, 2021
de6a332
Merge branch 'master' of github.com:apache/superset into filtersState…
simcha90 Mar 3, 2021
6652d19
refactor: update rest stuff for dataMask
simcha90 Mar 3, 2021
266a0a3
refactor: add ownCrrentState to explore
simcha90 Mar 3, 2021
5344dd4
fix: fix immer reducer
simcha90 Mar 4, 2021
2b4bd8f
Merge branch 'master' of github.com:apache/superset into filtersState…
simcha90 Mar 4, 2021
dabfd24
fix: merge with master
simcha90 Mar 4, 2021
802823c
refactor: support explore dataMask
simcha90 Mar 4, 2021
8aed240
refactor: support explore dataMask
simcha90 Mar 4, 2021
a0fa114
docs: add comment
simcha90 Mar 4, 2021
eaec7ef
refactor: remove json stringify
simcha90 Mar 4, 2021
cba3467
fix: fix failed cases
simcha90 Mar 4, 2021
04d6398
feat: filter bat buttons start
simcha90 Mar 4, 2021
af9e35a
fix: fix CR notes
simcha90 Mar 4, 2021
64fb87d
fix: fix cascade filters
simcha90 Mar 4, 2021
57c954f
fix: fix CR notes
simcha90 Mar 4, 2021
bd9b767
Merge branch 'filtersState_to_data_mask' of github.com:simchaNielsen/…
simcha90 Mar 4, 2021
bff44d1
refactor: add clear all
simcha90 Mar 7, 2021
09b594a
fix: fix CR notes
simcha90 Mar 7, 2021
c522391
Merge branch 'master' of github.com:apache/superset into filtersState…
simcha90 Mar 7, 2021
1bf1552
Merge branch 'filtersState_to_data_mask' of github.com:simchaNielsen/…
simcha90 Mar 7, 2021
0527067
fix: fix CR notes
simcha90 Mar 7, 2021
9abe26e
Merge branch 'filtersState_to_data_mask' of github.com:simchaNielsen/…
simcha90 Mar 7, 2021
2d12c37
fix: fix CR notes
simcha90 Mar 7, 2021
84d8cbd
Merge branch 'filtersState_to_data_mask' of github.com:simchaNielsen/…
simcha90 Mar 7, 2021
a9202b1
feat: buttons in filter bar
simcha90 Mar 7, 2021
9ae46b9
Merge branch 'master' of github.com:apache/superset into filter_bar_a…
simcha90 Mar 7, 2021
cdcae95
lint: update imports
simcha90 Mar 7, 2021
6c91054
feat: add tabs for filter sets
simcha90 Mar 7, 2021
844adaa
Merge branch 'master' of github.com:apache/superset into filter-set_tabs
simcha90 Mar 7, 2021
93e5d97
Merge branch 'master' of github.com:apache/superset into filter-set_tabs
simcha90 Mar 7, 2021
04259c2
feat: add buttons to filter set
simcha90 Mar 7, 2021
c053836
Merge branch 'master' of github.com:apache/superset into filter_set_d…
simcha90 Mar 7, 2021
26a0f28
feat: first phase add filter sets
simcha90 Mar 8, 2021
60b1374
fix: undo FF
simcha90 Mar 8, 2021
7985f5d
refactor: continue filter sets
simcha90 Mar 8, 2021
6671c1d
Merge branch 'master' of github.com:apache/superset into filter_set_d…
simcha90 Mar 8, 2021
3af62be
fix: fix CR notes
simcha90 Mar 8, 2021
d7e6b23
Merge branch 'filter_set_design' of github.com:simchaNielsen/incubato…
simcha90 Mar 8, 2021
038e5cc
refactor: header
simcha90 Mar 8, 2021
c7a9849
fix: fix CR notes
simcha90 Mar 8, 2021
d47a1ea
fix: fix CR notes
simcha90 Mar 8, 2021
02800d9
Merge branch 'filter_set_design' of github.com:simchaNielsen/incubato…
simcha90 Mar 8, 2021
4182f51
refactor: continue filter sets
simcha90 Mar 8, 2021
68e32d8
lint: fix lint
simcha90 Mar 8, 2021
f0904de
Merge branch 'filter_set_design' of github.com:simchaNielsen/incubato…
simcha90 Mar 8, 2021
eb8e9b9
refactor: continue filter sets
simcha90 Mar 9, 2021
bdbd0f9
fix: fix filter bar opening
simcha90 Mar 9, 2021
18d39bb
Merge branch 'filter_set_design' of github.com:simchaNielsen/incubato…
simcha90 Mar 9, 2021
33adb45
refactor: continue filter sets
simcha90 Mar 9, 2021
cc82b6a
Merge branch 'master' of github.com:apache/superset into filter_set_d…
simcha90 Mar 9, 2021
8bd69ed
Merge branch 'filter_set_design' of github.com:simchaNielsen/incubato…
simcha90 Mar 9, 2021
376386b
refactor: continue filter sets
simcha90 Mar 9, 2021
db7eccb
refactor: continue filter sets
simcha90 Mar 9, 2021
5d6d39e
Merge branch 'master' of github.com:apache/superset into filter_set_d…
simcha90 Mar 9, 2021
33e182d
feat: filters sets history
simcha90 Mar 9, 2021
5fa0e07
feat: filters sets history
simcha90 Mar 9, 2021
7539f03
fix: filter set name
simcha90 Mar 9, 2021
d887995
refactor: fix expand filters case
simcha90 Mar 9, 2021
a6884a2
Merge branch 'master' of github.com:apache/superset into filter_set_d…
simcha90 Mar 9, 2021
01439b6
fix: fix CR notes
simcha90 Mar 9, 2021
c075d9a
refactor: filter sets
simcha90 Mar 9, 2021
52a66aa
refactor: filter sets
simcha90 Mar 10, 2021
0ee5881
Merge branch 'filter_set_design_2' of github.com:simchaNielsen/incuba…
simcha90 Mar 10, 2021
27c0ca1
refactor: filter sets
simcha90 Mar 10, 2021
34b26b6
refactor: filter sets
simcha90 Mar 10, 2021
a21a394
refactor: update sets
simcha90 Mar 10, 2021
041fe8b
Merge branch 'master' of github.com:apache/superset into filter_set_u…
simcha90 Mar 10, 2021
24dcd16
feat: edit filter set
simcha90 Mar 10, 2021
d8e1bd9
refactor: add warning icon
simcha90 Mar 10, 2021
e558783
fix: fix CR notes
simcha90 Mar 10, 2021
accd1f2
Update superset-frontend/src/dashboard/components/nativeFilters/Filte…
simcha90 Mar 10, 2021
5b3803a
fix: fix CR notes
simcha90 Mar 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions superset-frontend/src/components/Button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface ButtonProps {
id?: string;
className?: string;
tooltip?: string;
ghost?: boolean;
placement?:
| 'bottom'
| 'left'
Expand Down
5 changes: 3 additions & 2 deletions superset-frontend/src/dashboard/actions/nativeFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,15 @@ export const setFilterSetsConfiguration = (
filter_sets_configuration: filterSetsConfig,
}),
});
const newMetadata = JSON.parse(response.result.json_metadata);
dispatch(
dashboardInfoChanged({
metadata: JSON.parse(response.result.json_metadata),
metadata: newMetadata,
}),
);
dispatch({
type: SET_FILTER_SETS_CONFIG_COMPLETE,
filterSetsConfig,
filterSetsConfig: newMetadata?.filter_sets_configuration,
});
} catch (err) {
dispatch({ type: SET_FILTER_SETS_CONFIG_FAIL, filterSetsConfig });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { buildCascadeFiltersTree, mapParentFiltersToChildren } from './utils';
import CascadePopover from './CascadePopover';
import FilterSets from './FilterSets/FilterSets';
import { useDataMask, useFilters, useFilterSets } from './state';
import EditSection from './FilterSets/EditSection';

const barWidth = `250px`;

Expand Down Expand Up @@ -173,6 +174,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({
toggleFiltersBar,
directPathToChild,
}) => {
const [editFilterSetId, setEditFilterSetId] = useState<string | null>(null);
const [dataMaskSelected, setDataMaskSelected] = useImmer<DataMaskUnit>({});
const [
lastAppliedFilterData,
Expand Down Expand Up @@ -337,19 +339,29 @@ const FilterBar: React.FC<FiltersBarProps> = ({
<StyledTabs
centered
defaultActiveKey="allFilters"
onChange={() => {}}
activeKey={editFilterSetId ? 'allFilters' : undefined}
>
<Tabs.TabPane
tab={t(`All Filters (${filterValues.length})`)}
key="allFilters"
>
{editFilterSetId && (
<EditSection
dataMaskSelected={dataMaskSelected}
disabled={!isApplyDisabled}
onCancel={() => setEditFilterSetId(null)}
filterSetId={editFilterSetId}
/>
)}
{getFilterControls()}
</Tabs.TabPane>
<Tabs.TabPane
disabled={!!editFilterSetId}
tab={t(`Filter Sets (${filterSetFilterValues.length})`)}
key="filterSets"
>
<FilterSets
onEditFilterSet={setEditFilterSetId}
disabled={!isApplyDisabled}
dataMaskSelected={dataMaskSelected}
onFilterSelectionChange={handleFilterSelectionChange}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* 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, { FC, useMemo } from 'react';
import { HandlerFunction, styled, t } from '@superset-ui/core';
import { Typography, Tooltip } from 'src/common/components';
import { useDispatch } from 'react-redux';
import Button from 'src/components/Button';
import { setFilterSetsConfiguration } from 'src/dashboard/actions/nativeFilters';
import { DataMaskUnit } from 'src/dataMask/types';
import { WarningOutlined } from '@ant-design/icons';
import { ActionButtons } from './Footer';
import { useDataMask, useFilterSets } from '../state';
import { APPLY_FILTERS_HINT, findExistingFilterSet } from './utils';

const Wrapper = styled.div`
display: grid;
grid-template-columns: 1fr;
align-items: flex-start;
justify-content: flex-start;
grid-gap: ${({ theme }) => theme.gridUnit}px;
background: ${({ theme }) => theme.colors.primary.light4};
padding: ${({ theme }) => theme.gridUnit * 2}px;
`;

const Title = styled(Typography.Text)`
color: ${({ theme }) => theme.colors.primary.dark2};
`;

const Warning = styled(Typography.Text)`
font-size: ${({ theme }) => theme.typography.sizes.s}px;
& .anticon {
padding: ${({ theme }) => theme.gridUnit}px;
}
`;

const ActionButton = styled.div<{ disabled?: boolean }>`
display: flex;
& button {
${({ disabled }) => `pointer-events: ${disabled ? 'none' : 'all'}`};
flex: 1;
}
`;

type EditSectionProps = {
filterSetId: string;
dataMaskSelected: DataMaskUnit;
onCancel: HandlerFunction;
disabled: boolean;
};

const EditSection: FC<EditSectionProps> = ({
filterSetId,
onCancel,
dataMaskSelected,
disabled,
}) => {
const dataMaskApplied = useDataMask();
const dispatch = useDispatch();
const filterSets = useFilterSets();
const filterSetFilterValues = Object.values(filterSets);
const handleSave = () => {
dispatch(
setFilterSetsConfiguration(
filterSetFilterValues.map(filterSet => {
const newFilterSet = {
...filterSet,
dataMask: { nativeFilters: { ...dataMaskApplied } },
};
return filterSetId === filterSet.id ? newFilterSet : filterSet;
}),
),
);
onCancel();
};

const foundFilterSet = useMemo(
() =>
findExistingFilterSet({
dataMaskApplied,
dataMaskSelected,
filterSetFilterValues,
}),
[dataMaskApplied, dataMaskSelected, filterSetFilterValues],
);

const isDuplicateFilterSet =
foundFilterSet && foundFilterSet.id !== filterSetId;

return (
<Wrapper>
<Title strong>{t('Editing filter set:')}</Title>
<Title>{filterSets[filterSetId].name}</Title>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this isn't yet in the design, I think it would be a good idea to make the title editable when in edit mode

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may be in next PR, here it will cause refactor some code and move to other files

<ActionButtons>
<Button
ghost
buttonStyle="tertiary"
buttonSize="small"
onClick={onCancel}
data-test="filter-set-edit-cancel"
>
{t('Cancel')}
</Button>
<Tooltip
placement="top"
title={
(isDuplicateFilterSet && t('Filter set already exists')) ||
(disabled && APPLY_FILTERS_HINT)
}
>
<ActionButton disabled={disabled || isDuplicateFilterSet}>
<Button
disabled={disabled || isDuplicateFilterSet}
buttonStyle="primary"
htmlType="submit"
buttonSize="small"
onClick={handleSave}
data-test="filter-set-edit-save"
>
{t('Save')}
</Button>
</ActionButton>
</Tooltip>
</ActionButtons>
{isDuplicateFilterSet && (
<Warning mark>
<WarningOutlined />
{t('This filter set is identical to: "%s"', foundFilterSet?.name)}
</Warning>
)}
</Wrapper>
);
};

export default EditSection;
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import { Typography, Dropdown, Menu } from 'src/common/components';
import React, { FC } from 'react';
import { FilterSet } from 'src/dashboard/reducers/types';
import { DataMaskUnitWithId } from 'src/dataMask/types';
import { DataMaskUnit } from 'src/dataMask/types';
import { CheckOutlined, EllipsisOutlined } from '@ant-design/icons';
import { HandlerFunction, styled, supersetTheme, t } from '@superset-ui/core';
import FiltersHeader from './FiltersHeader';
Expand All @@ -46,24 +46,29 @@ type FilterSetUnitProps = {
isApplied?: boolean;
filterSet?: FilterSet;
filterSetName?: string;
dataMaskApplied: DataMaskUnitWithId;
dataMaskApplied?: DataMaskUnit;
setFilterSetName?: (name: string) => void;
onDelete?: HandlerFunction;
onEdit?: HandlerFunction;
};

const FilterSetUnit: FC<FilterSetUnitProps> = ({
filters,
editMode,
setFilterSetName,
onDelete,
onEdit,
filterSetName,
dataMaskApplied,
filterSet,
isApplied,
}) => {
const menu = (
<Menu>
<Menu.Item onClick={onDelete}>{t('Delete')}</Menu.Item>
<Menu.Item onClick={onEdit}>{t('Edit')}</Menu.Item>
<Menu.Item onClick={onDelete} danger>
{t('Delete')}
</Menu.Item>
</Menu>
);
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ import { HandlerFunction, styled, t } from '@superset-ui/core';
import { useDispatch } from 'react-redux';
import { DataMaskState, DataMaskUnit, MaskWithId } from 'src/dataMask/types';
import { setFilterSetsConfiguration } from 'src/dashboard/actions/nativeFilters';
import { areObjectsEqual } from 'src/reduxUtils';
import { FilterSet } from 'src/dashboard/reducers/types';
import { generateFiltersSetId } from './utils';
import { findExistingFilterSet, generateFiltersSetId } from './utils';
import { Filter } from '../../types';
import { useFilters, useDataMask, useFilterSets } from '../state';
import Footer from './Footer';
Expand Down Expand Up @@ -68,6 +67,7 @@ const FilterSetUnitWrapper = styled.div<{
type FilterSetsProps = {
disabled: boolean;
dataMaskSelected: DataMaskUnit;
onEditFilterSet: (id: string) => void;
onFilterSelectionChange: (
filter: Pick<Filter, 'id'> & Partial<Filter>,
dataMask: Partial<DataMaskState>,
Expand All @@ -78,6 +78,7 @@ const DEFAULT_FILTER_SET_NAME = t('New filter set');

const FilterSets: React.FC<FilterSetsProps> = ({
dataMaskSelected,
onEditFilterSet,
disabled,
onFilterSelectionChange,
}) => {
Expand All @@ -93,34 +94,25 @@ const FilterSets: React.FC<FilterSetsProps> = ({
>(null);

useEffect(() => {
const foundFilterSet = filterSetFilterValues.find(({ dataMask }) => {
if (dataMask?.nativeFilters) {
return Object.values(dataMask?.nativeFilters).every(
filterFromFilterSet => {
let currentValueFromFiltersTab =
dataMaskApplied[filterFromFilterSet.id]?.currentState ?? {};
if (dataMaskSelected[filterFromFilterSet.id]) {
currentValueFromFiltersTab =
dataMaskSelected[filterFromFilterSet.id]?.currentState;
}
return areObjectsEqual(
filterFromFilterSet.currentState ?? {},
currentValueFromFiltersTab,
);
},
);
}
return false;
const foundFilterSet = findExistingFilterSet({
dataMaskApplied,
dataMaskSelected,
filterSetFilterValues,
});
setSelectedFiltersSetId(foundFilterSet?.id ?? null);
}, [dataMaskApplied, dataMaskSelected, filterSetFilterValues]);

const takeFilterSet = (target: HTMLElement, id: string) => {
const takeFilterSet = (id: string, target?: HTMLElement) => {
const ignoreSelector = 'ant-collapse-header';
if (
target.classList.contains(ignoreSelector) ||
target.parentElement?.classList.contains(ignoreSelector) ||
target.parentElement?.parentElement?.classList.contains(ignoreSelector)
target?.classList.contains(ignoreSelector) ||
target?.parentElement?.classList.contains(ignoreSelector) ||
target?.parentElement?.parentElement?.classList.contains(
ignoreSelector,
) ||
target?.parentElement?.parentElement?.parentElement?.classList.contains(
ignoreSelector,
)
) {
// We don't want select filter set when user expand filters
return;
Expand All @@ -141,6 +133,11 @@ const FilterSets: React.FC<FilterSetsProps> = ({
);
};

const handleEdit = (id: string) => {
takeFilterSet(id);
onEditFilterSet(id);
};

const handleDeleteFilterSets = () => {
dispatch(
setFilterSetsConfiguration(
Expand Down Expand Up @@ -198,14 +195,14 @@ const FilterSets: React.FC<FilterSetsProps> = ({
<FilterSetUnitWrapper
selected={filterSet.id === selectedFiltersSetId}
onClick={(e: MouseEvent<HTMLElement>) =>
takeFilterSet(e.target as HTMLElement, filterSet.id)
takeFilterSet(filterSet.id, e.target as HTMLElement)
}
>
<FilterSetUnit
isApplied={filterSet.id === selectedFiltersSetId && !disabled}
onDelete={handleDeleteFilterSets}
onEdit={() => handleEdit(filterSet.id)}
filters={filters}
dataMaskApplied={dataMaskApplied}
filterSet={filterSet}
/>
</FilterSetUnitWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import React, { FC } from 'react';
import { styled, t } from '@superset-ui/core';
import { Collapse, Typography } from 'src/common/components';
import { DataMaskUnitWithId } from 'src/dataMask/types';
import { DataMaskUnit } from 'src/dataMask/types';
import { CaretDownOutlined } from '@ant-design/icons';
import { getFilterValueForDisplay } from './utils';
import { Filter } from '../../types';
Expand Down Expand Up @@ -54,7 +54,7 @@ const StyledCollapse = styled(Collapse)`

type FiltersHeaderProps = {
filters: Filter[];
dataMask: DataMaskUnitWithId;
dataMask?: DataMaskUnit;
expanded: boolean;
};

Expand Down Expand Up @@ -84,7 +84,9 @@ const FiltersHeader: FC<FiltersHeaderProps> = ({
<div>
<Typography.Text strong>{name}:&nbsp;</Typography.Text>
<Typography.Text>
{getFilterValueForDisplay(dataMask[id]?.currentState?.value) || (
{getFilterValueForDisplay(
dataMask?.[id]?.currentState?.value,
) || (
<Typography.Text type="secondary">{t('None')}</Typography.Text>
)}
</Typography.Text>
Expand Down
Loading