This is an automated email from the ASF dual-hosted git repository.

villebro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new d509b15  feat(filter-set): Update existing filter set (#13545)
d509b15 is described below

commit d509b157fd238fff28f0ddfc74802987609658c5
Author: simcha90 <[email protected]>
AuthorDate: Wed Mar 10 15:43:24 2021 +0200

    feat(filter-set): Update existing filter set (#13545)
    
    * 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
    
    * refactor: continue filter sets
    
    * fix: fix CR notes
    
    * refactor: header
    
    * fix: fix CR notes
    
    * fix: fix CR notes
    
    * refactor: continue filter sets
    
    * lint: fix lint
    
    * refactor: continue filter sets
    
    * fix: fix filter bar opening
    
    * refactor: continue filter sets
    
    * refactor: continue filter sets
    
    * refactor: continue filter sets
    
    * feat: filters sets history
    
    * feat: filters sets history
    
    * fix: filter set name
    
    * refactor: fix expand filters case
    
    * fix: fix CR notes
    
    * refactor: filter sets
    
    * refactor: filter sets
    
    * refactor: filter sets
    
    * refactor: filter sets
    
    * refactor: update sets
    
    * feat: edit filter set
    
    * refactor: add warning icon
    
    * fix: fix CR notes
    
    * Update 
superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
    
    Co-authored-by: Ville Brofeldt <[email protected]>
    
    * fix: fix CR notes
    
    Co-authored-by: Ville Brofeldt <[email protected]>
---
 superset-frontend/src/components/Button/index.tsx  |   1 +
 .../src/dashboard/actions/nativeFilters.ts         |   5 +-
 .../nativeFilters/FilterBar/FilterBar.tsx          |  14 +-
 .../FilterBar/FilterSets/EditSection.tsx           | 150 +++++++++++++++++++++
 .../FilterBar/FilterSets/FilterSetUnit.tsx         |  11 +-
 .../FilterBar/FilterSets/FilterSets.tsx            |  49 ++++---
 .../FilterBar/FilterSets/FiltersHeader.tsx         |   8 +-
 .../nativeFilters/FilterBar/FilterSets/Footer.tsx  |  10 +-
 .../nativeFilters/FilterBar/FilterSets/utils.ts    |  34 +++++
 9 files changed, 241 insertions(+), 41 deletions(-)

diff --git a/superset-frontend/src/components/Button/index.tsx 
b/superset-frontend/src/components/Button/index.tsx
index 168f176..347c6b8 100644
--- a/superset-frontend/src/components/Button/index.tsx
+++ b/superset-frontend/src/components/Button/index.tsx
@@ -30,6 +30,7 @@ export interface ButtonProps {
   id?: string;
   className?: string;
   tooltip?: string;
+  ghost?: boolean;
   placement?:
     | 'bottom'
     | 'left'
diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts 
b/superset-frontend/src/dashboard/actions/nativeFilters.ts
index 8a18d52..2e1c7e7 100644
--- a/superset-frontend/src/dashboard/actions/nativeFilters.ts
+++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts
@@ -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 });
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.tsx
index b5f05e4..03779ab 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.tsx
@@ -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`;
 
@@ -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,
@@ -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}
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
new file mode 100644
index 0000000..5994e6c
--- /dev/null
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx
@@ -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>
+      <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;
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
index ee9ea25..6a83a8b 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSetUnit.tsx
@@ -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';
@@ -46,9 +46,10 @@ type FilterSetUnitProps = {
   isApplied?: boolean;
   filterSet?: FilterSet;
   filterSetName?: string;
-  dataMaskApplied: DataMaskUnitWithId;
+  dataMaskApplied?: DataMaskUnit;
   setFilterSetName?: (name: string) => void;
   onDelete?: HandlerFunction;
+  onEdit?: HandlerFunction;
 };
 
 const FilterSetUnit: FC<FilterSetUnitProps> = ({
@@ -56,6 +57,7 @@ const FilterSetUnit: FC<FilterSetUnitProps> = ({
   editMode,
   setFilterSetName,
   onDelete,
+  onEdit,
   filterSetName,
   dataMaskApplied,
   filterSet,
@@ -63,7 +65,10 @@ const FilterSetUnit: FC<FilterSetUnitProps> = ({
 }) => {
   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 (
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.tsx
index 608c2e7..47c99fd 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.tsx
@@ -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';
@@ -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>,
@@ -78,6 +78,7 @@ const DEFAULT_FILTER_SET_NAME = t('New filter set');
 
 const FilterSets: React.FC<FilterSetsProps> = ({
   dataMaskSelected,
+  onEditFilterSet,
   disabled,
   onFilterSelectionChange,
 }) => {
@@ -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;
@@ -141,6 +133,11 @@ const FilterSets: React.FC<FilterSetsProps> = ({
     );
   };
 
+  const handleEdit = (id: string) => {
+    takeFilterSet(id);
+    onEditFilterSet(id);
+  };
+
   const handleDeleteFilterSets = () => {
     dispatch(
       setFilterSetsConfiguration(
@@ -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>
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
index 8982a21..eb43eb9 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx
@@ -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';
@@ -54,7 +54,7 @@ const StyledCollapse = styled(Collapse)`
 
 type FiltersHeaderProps = {
   filters: Filter[];
-  dataMask: DataMaskUnitWithId;
+  dataMask?: DataMaskUnit;
   expanded: boolean;
 };
 
@@ -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>
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/Footer.tsx
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/Footer.tsx
index 5e53ed8..60fbef4 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/Footer.tsx
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/Footer.tsx
@@ -20,6 +20,7 @@ import { t, styled } from '@superset-ui/core';
 import React, { FC } from 'react';
 import Button from 'src/components/Button';
 import { Tooltip } from 'src/common/components/Tooltip';
+import { APPLY_FILTERS_HINT } from './utils';
 
 type FooterProps = {
   isApplyDisabled: boolean;
@@ -32,14 +33,13 @@ type FooterProps = {
 
 const ActionButton = styled.div<{ disabled: boolean }>`
   display: flex;
-  padding: 1px;
   & button {
     ${({ disabled }) => `pointer-events: ${disabled ? 'none' : 'all'}`};
     flex: 1;
   }
 `;
 
-const ActionButtons = styled.div`
+export const ActionButtons = styled.div`
   display: grid;
   flex-direction: row;
   justify-content: center;
@@ -48,8 +48,6 @@ const ActionButtons = styled.div`
   grid-template-columns: 1fr 1fr;
 `;
 
-const APPLY_FILTERS = t('Please apply filter changes');
-
 const Footer: FC<FooterProps> = ({
   onCancel,
   editMode,
@@ -73,7 +71,7 @@ const Footer: FC<FooterProps> = ({
           placement="bottom"
           title={
             (isApplyDisabled && t('Please filter set name')) ||
-            (disabled && APPLY_FILTERS)
+            (disabled && APPLY_FILTERS_HINT)
           }
         >
           <ActionButton disabled={disabled}>
@@ -91,7 +89,7 @@ const Footer: FC<FooterProps> = ({
         </Tooltip>
       </ActionButtons>
     ) : (
-      <Tooltip placement="bottom" title={disabled && APPLY_FILTERS}>
+      <Tooltip placement="bottom" title={disabled && APPLY_FILTERS_HINT}>
         <ActionButton disabled={disabled}>
           <Button
             disabled={disabled}
diff --git 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils.ts
 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils.ts
index 8f5cce5..e7a87ad 100644
--- 
a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils.ts
+++ 
b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils.ts
@@ -19,9 +19,14 @@
 
 import shortid from 'shortid';
 import { t } from '@superset-ui/core';
+import { areObjectsEqual } from 'src/reduxUtils';
+import { DataMaskUnit } from 'src/dataMask/types';
+import { FilterSet } from 'src/dashboard/reducers/types';
 
 export const generateFiltersSetId = () => `FILTERS_SET-${shortid.generate()}`;
 
+export const APPLY_FILTERS_HINT = t('Please apply filter changes');
+
 export const getFilterValueForDisplay = (
   value?: string[] | null | string | number | object,
 ): string => {
@@ -39,3 +44,32 @@ export const getFilterValueForDisplay = (
   }
   return t('Unknown value');
 };
+
+export const findExistingFilterSet = ({
+  filterSetFilterValues,
+  dataMaskApplied,
+  dataMaskSelected,
+}: {
+  filterSetFilterValues: FilterSet[];
+  dataMaskApplied: DataMaskUnit;
+  dataMaskSelected: DataMaskUnit;
+}) =>
+  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;
+  });

Reply via email to