Skip to content
This repository has been archived by the owner on Jan 16, 2025. It is now read-only.

Commit

Permalink
Merge pull request #18 from katalon-studio/RA-TES-6185
Browse files Browse the repository at this point in the history
[RA-TES-6185] Add more filter
  • Loading branch information
huynguyen2908 authored Apr 5, 2024
2 parents 0865c92 + a354a36 commit ab9084f
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import DropdownContainer, {
Ref as DropdownContainerRef,
} from 'src/components/DropdownContainer';
import Icons from 'src/components/Icons';
import FilterExtension from 'src/katalon/CustomFilter/FilterExtension';
import { FiltersOutOfScopeCollapsible } from '../FiltersOutOfScopeCollapsible';
import { useFilterControlFactory } from '../useFilterControlFactory';
import { FiltersDropdownContent } from '../FiltersDropdownContent';
Expand Down Expand Up @@ -215,6 +216,7 @@ const FilterControls: FC<FilterControlsProps> = ({
if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS)) {
const nativeFiltersInScope = filtersInScope.map((filter, index) => ({
id: filter.id,
name: filter.name,
element: (
<div
className="filter-item-wrapper"
Expand Down Expand Up @@ -316,6 +318,8 @@ const FilterControls: FC<FilterControlsProps> = ({
}
}, [outlinedFilterId, lastUpdated, popoverRef, overflowedIds]);

const renderFilterExtension = () => <FilterExtension items={items} />;

return (
<>
{portalNodes
Expand All @@ -332,7 +336,9 @@ const FilterControls: FC<FilterControlsProps> = ({
{filterBarOrientation === FilterBarOrientation.VERTICAL &&
renderVerticalContent()}
{filterBarOrientation === FilterBarOrientation.HORIZONTAL &&
renderHorizontalContent()}
renderFilterExtension()}
{/* {filterBarOrientation === FilterBarOrientation.HORIZONTAL &&
renderHorizontalContent()} */}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { logEvent } from 'src/logger/actions';
import { LOG_ACTIONS_CHANGE_DASHBOARD_FILTER } from 'src/logger/LogUtils';
import { FilterBarOrientation, RootState } from 'src/dashboard/types';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
import KatalonHorizontal from 'src/katalon/CustomFilter/KatalonHorizontal';
import { checkIsApplyDisabled } from './utils';
import { FiltersBarProps } from './types';
import {
Expand Down Expand Up @@ -287,7 +288,7 @@ const FilterBar: React.FC<FiltersBarProps> = ({

const filterBarComponent =
orientation === FilterBarOrientation.HORIZONTAL ? (
<Horizontal
<KatalonHorizontal
actions={actions}
canEdit={canEdit}
dashboardId={dashboardId}
Expand Down
150 changes: 150 additions & 0 deletions superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React, { useState, MouseEvent } from 'react';
import { t } from '@superset-ui/core';
import {
Button,
Checkbox,
Grid,
ListSubheader,
Menu,
MenuItem,
Stack,
} from '@mui/material';

Check failure on line 11 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Unable to resolve path to module '@mui/material'

Check failure on line 11 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Unable to resolve path to module '@mui/material'

interface FilterItem {
id: string;
name: string;
element: JSX.Element;
}

interface FilterExtensionProps {
items: FilterItem[];
}

function FilterExtension(props: FilterExtensionProps) {
const { items } = props;

const [addFilter, setAddFilter] = useState<FilterItem[]>([]);

const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

const handleClick = (event: MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};

const handleClose = () => {
setAnchorEl(null);
};

const handleAddOrRemove = (selectedFilter: FilterItem) => {
setAddFilter((prevFilters: FilterItem[]) => {
// Check if the filter is already added
const isFilterExisting = prevFilters.some(
filter => filter.id === selectedFilter.id,
);

if (isFilterExisting) {
// If the filter exists, remove it from the list
return prevFilters.filter(filter => filter.id !== selectedFilter.id);
}
return [...prevFilters, selectedFilter];
});
handleClose();
};

const renderPopperMenu = (invisbleFilter: FilterItem[]) => (
<Menu
elevation={2}
id="list-advance-filter"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
<ListSubheader
sx={{
color: '#797B7F',

Check failure on line 73 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors

Check failure on line 73 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors
fontSize: 14,
fontWeight: 700,
}}
>
{t('all filters').toUpperCase()}
</ListSubheader>
{invisbleFilter.length !== 0 &&
invisbleFilter.map(item => {
const isFilterExisting = addFilter.find(
filterComponent => filterComponent?.id === item?.id,
);
return (
<MenuItem onClick={() => handleAddOrRemove(item)} key={item?.id}>
<Grid
container
direction="row"
justifyContent="center"
alignItems="center"
spacing={1}
>
<Grid item xs={8}>
{item?.name}
</Grid>
<Grid item xs={4}>
<Checkbox color="primary" checked={!!isFilterExisting} />
</Grid>
</Grid>
</MenuItem>
);
})}
</Menu>
);

const renderAddMoreButton = () => {
// Take the list all filters,
// then device them into two parts
const visibleFilter: FilterItem[] = items.slice(0, 2);
const invisbleFilter: FilterItem[] = items.slice(3);

return (
<Stack
sx={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
gap: '3px',
}}
direction="row"
spacing={2}
>
{visibleFilter.length !== 0 &&
visibleFilter.map((item, index) => (
<div key={index}>{item.element}</div>
))}
{addFilter.length !== 0 &&
addFilter.map((item, index) => <div key={index}>{item.element}</div>)}
<Button
sx={{
bgcolor: '#FFFFFF',

Check failure on line 132 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors

Check failure on line 132 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors
color: '#0F1866',

Check failure on line 133 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors

Check failure on line 133 in superset-frontend/src/katalon/CustomFilter/FilterExtension.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

Theme color variables are preferred over rgb(a)/hex/literal colors
textTransform: 'none',
fontSize: 16,
fontWeight: 600,
}}
onClick={handleClick}
>
{t('+ Add more')}
</Button>
{renderPopperMenu(invisbleFilter)}
</Stack>
);
};

return <>{renderAddMoreButton()}</>;
}

export default FilterExtension;
165 changes: 165 additions & 0 deletions superset-frontend/src/katalon/CustomFilter/KatalonHorizontal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React, { useMemo } from 'react';
import {
DataMaskStateWithId,
FeatureFlag,
isFeatureEnabled,
JsonObject,
styled,
t,
} from '@superset-ui/core';
import Icons from 'src/components/Icons';

Check failure on line 10 in superset-frontend/src/katalon/CustomFilter/KatalonHorizontal.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

'superset' should be listed in the project's dependencies. Run 'npm i -S superset' to add it

Check failure on line 10 in superset-frontend/src/katalon/CustomFilter/KatalonHorizontal.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

'superset' should be listed in the project's dependencies. Run 'npm i -S superset' to add it
import Loading from 'src/components/Loading';

Check failure on line 11 in superset-frontend/src/katalon/CustomFilter/KatalonHorizontal.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

'superset' should be listed in the project's dependencies. Run 'npm i -S superset' to add it

Check failure on line 11 in superset-frontend/src/katalon/CustomFilter/KatalonHorizontal.tsx

View workflow job for this annotation

GitHub Actions / frontend-build

'superset' should be listed in the project's dependencies. Run 'npm i -S superset' to add it
import { useSelector } from 'react-redux';
import {
getFilterBarTestId,
useChartsVerboseMaps,
} from 'src/dashboard/components/nativeFilters/FilterBar/utils';
import { HorizontalBarProps } from 'src/dashboard/components/nativeFilters/FilterBar/types';
import { DashboardLayout, RootState } from 'src/dashboard/types';
import { crossFiltersSelector } from 'src/dashboard/components/nativeFilters/FilterBar/CrossFilters/selectors';
import { getUrlParam } from 'src/utils/urlUtils';
import { URL_PARAMS } from 'src/constants';
import FilterConfigurationLink from 'src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink';
import FilterBarSettings from 'src/dashboard/components/nativeFilters/FilterBar/FilterBarSettings';
import FilterControls from 'src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls';

const HorizontalBar = styled.div`
${({ theme }) => `
padding: ${theme.gridUnit * 3}px ${theme.gridUnit * 2}px ${
theme.gridUnit * 3
}px ${theme.gridUnit * 4}px;
background: ${theme.colors.grayscale.light5};
box-shadow: inset 0px -2px 2px -1px ${theme.colors.grayscale.light2};
`}
`;

const HorizontalBarContent = styled.div`
${({ theme }) => `
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: flex-start;
line-height: 0;
.loading {
margin: ${theme.gridUnit * 2}px auto ${theme.gridUnit * 2}px;
padding: 0;
}
`}
`;

const FilterBarEmptyStateContainer = styled.div`
${({ theme }) => `
font-weight: ${theme.typography.weights.bold};
color: ${theme.colors.grayscale.base};
font-size: ${theme.typography.sizes.s}px;
`}
`;

const FiltersLinkContainer = styled.div<{ hasFilters: boolean }>`
${({ theme, hasFilters }) => `
height: 24px;
display: flex;
align-items: center;
padding: 0 ${theme.gridUnit * 4}px 0 ${theme.gridUnit * 4}px;
border-right: ${
hasFilters ? `1px solid ${theme.colors.grayscale.light2}` : 0
};
button {
display: flex;
align-items: center;
> .anticon {
height: 24px;
padding-right: ${theme.gridUnit}px;
}
> .anticon + span, > .anticon {
margin-right: 0;
margin-left: 0;
}
}
`}
`;

const HorizontalFilterBar: React.FC<HorizontalBarProps> = ({
actions,
canEdit,
dashboardId,
dataMaskSelected,
filterValues,
isInitialized,
onSelectionChange,
}) => {
const dataMask = useSelector<RootState, DataMaskStateWithId>(
state => state.dataMask,
);
const chartConfiguration = useSelector<RootState, JsonObject>(
state => state.dashboardInfo.metadata?.chart_configuration,
);
const dashboardLayout = useSelector<RootState, DashboardLayout>(
state => state.dashboardLayout.present,
);
const isCrossFiltersEnabled = isFeatureEnabled(
FeatureFlag.DASHBOARD_CROSS_FILTERS,
);
const verboseMaps = useChartsVerboseMaps();

const selectedCrossFilters = isCrossFiltersEnabled
? crossFiltersSelector({
dataMask,
chartConfiguration,
dashboardLayout,
verboseMaps,
})
: [];
const hasFilters = filterValues.length > 0 || selectedCrossFilters.length > 0;

const actionsElement = useMemo(
() =>
isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) ? actions : null,
[actions],
);

const isKatalonEmbeddedMode = getUrlParam(URL_PARAMS.isKatalonEmbeddedMode);

return (
<HorizontalBar {...getFilterBarTestId()}>
<HorizontalBarContent>
{!isInitialized ? (
<Loading position="inline-centered" />
) : (
<>
{!isKatalonEmbeddedMode && (
<>
<FilterBarSettings />
{canEdit &&
isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && (
<FiltersLinkContainer hasFilters={hasFilters}>
<FilterConfigurationLink
dashboardId={dashboardId}
createNewOnOpen={filterValues.length === 0}
>
<Icons.PlusSmall /> {t('Add/Edit Filters')}
</FilterConfigurationLink>
</FiltersLinkContainer>
)}
</>
)}
{!hasFilters && (
<FilterBarEmptyStateContainer data-test="horizontal-filterbar-empty">
{t('No filters are currently added to this dashboard.')}
</FilterBarEmptyStateContainer>
)}
{hasFilters && (
<FilterControls
dataMaskSelected={dataMaskSelected}
onFilterSelectionChange={onSelectionChange}
/>
)}
{actionsElement}
</>
)}
</HorizontalBarContent>
</HorizontalBar>
);
};
export default React.memo(HorizontalFilterBar);

0 comments on commit ab9084f

Please sign in to comment.