1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-04 00:18:01 +01:00

feat: split strategies table into two with new design (#3969)

This commit is contained in:
Jaanus Sellin 2023-06-14 09:10:04 +03:00 committed by GitHub
parent 41370be591
commit b91b7276c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 109 deletions

View File

@ -3,6 +3,7 @@ import { FC } from 'react';
const Paragraph: FC = ({ children }) => ( const Paragraph: FC = ({ children }) => (
<Typography <Typography
component={'span'}
variant="body2" variant="body2"
sx={theme => ({ sx={theme => ({
marginBottom: theme.spacing(2), marginBottom: theme.spacing(2),

View File

@ -22,17 +22,15 @@ import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError'; import { formatUnknownError } from 'utils/formatUnknownError';
import { IStrategy } from 'interfaces/strategy'; import { IStrategy } from 'interfaces/strategy';
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
import { sortTypes } from 'utils/sortTypes'; import { sortTypes } from 'utils/sortTypes';
import { useTable, useGlobalFilter, useSortBy } from 'react-table'; import { useTable, useSortBy } from 'react-table';
import { AddStrategyButton } from './AddStrategyButton/AddStrategyButton';
import { StrategySwitch } from './StrategySwitch/StrategySwitch'; import { StrategySwitch } from './StrategySwitch/StrategySwitch';
import { StrategyEditButton } from './StrategyEditButton/StrategyEditButton'; import { StrategyEditButton } from './StrategyEditButton/StrategyEditButton';
import { StrategyDeleteButton } from './StrategyDeleteButton/StrategyDeleteButton'; import { StrategyDeleteButton } from './StrategyDeleteButton/StrategyDeleteButton';
import { Search } from 'component/common/Search/Search';
import { Badge } from 'component/common/Badge/Badge'; import { Badge } from 'component/common/Badge/Badge';
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import { CustomStrategyInfo } from '../CustomStrategyInfo/CustomStrategyInfo'; import { CustomStrategyInfo } from '../CustomStrategyInfo/CustomStrategyInfo';
import { AddStrategyButton } from './AddStrategyButton/AddStrategyButton';
interface IDialogueMetaData { interface IDialogueMetaData {
show: boolean; show: boolean;
@ -40,17 +38,28 @@ interface IDialogueMetaData {
onConfirm: () => void; onConfirm: () => void;
} }
const StyledBox = styled(Box)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2),
}));
const StyledBadge = styled(Badge)(({ theme }) => ({ const StyledBadge = styled(Badge)(({ theme }) => ({
marginLeft: theme.spacing(1), marginLeft: theme.spacing(1),
display: 'inline-block', display: 'inline-block',
})); }));
const StyledTypography = styled(Typography)(({ theme }) => ({
display: 'flex',
fontSize: theme.fontSizes.mainHeader,
}));
const Subtitle: FC<{ const Subtitle: FC<{
title: string; title: string;
description: string; description: string;
link: string; link: string;
}> = ({ title, description, link }) => ( }> = ({ title, description, link }) => (
<Typography component="h2" variant="subtitle1" sx={{ display: 'flex' }}> <StyledTypography>
{title} {title}
<HelpIcon <HelpIcon
htmlTooltip htmlTooltip
@ -69,17 +78,7 @@ const Subtitle: FC<{
</> </>
} }
/> />
</Typography> </StyledTypography>
);
const PredefinedStrategyTitle = () => (
<Box sx={theme => ({ marginBottom: theme.spacing(1.5) })}>
<Subtitle
title="Predefined strategies"
description="Activation strategies let you enable a feature only for a specified audience. Different strategies use different parameters. Predefined strategies are bundled with Unleash."
link="https://docs.getunleash.io/reference/activation-strategies"
/>
</Box>
); );
const CustomStrategyTitle: FC = () => ( const CustomStrategyTitle: FC = () => (
@ -101,6 +100,16 @@ const CustomStrategyTitle: FC = () => (
</Box> </Box>
); );
const PredefinedStrategyTitle = () => (
<Box>
<Subtitle
title="Predefined strategies"
description="Activation strategies let you enable a feature only for a specified audience. Different strategies use different parameters. Predefined strategies are bundled with Unleash."
link="https://docs.getunleash.io/reference/activation-strategies"
/>
</Box>
);
export const StrategiesList = () => { export const StrategiesList = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>( const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
@ -240,7 +249,6 @@ export const StrategiesList = () => {
<Extension color="disabled" /> <Extension color="disabled" />
</Box> </Box>
), ),
disableGlobalFilter: true,
}, },
{ {
id: 'Name', id: 'Name',
@ -304,7 +312,6 @@ export const StrategiesList = () => {
), ),
width: 150, width: 150,
minWidth: 120, minWidth: 120,
disableGlobalFilter: true,
disableSortBy: true, disableSortBy: true,
}, },
{ {
@ -313,7 +320,6 @@ export const StrategiesList = () => {
}, },
{ {
accessor: 'sortOrder', accessor: 'sortOrder',
disableGlobalFilter: true,
sortType: 'number', sortType: 'number',
}, },
], ],
@ -328,27 +334,18 @@ export const StrategiesList = () => {
[] []
); );
const { const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } =
getTableProps, useTable(
getTableBodyProps, {
headerGroups, columns: columns as any[], // TODO: fix after `react-table` v8 update
rows, data: data.predefined,
prepareRow, initialState,
state: { globalFilter }, sortTypes,
setGlobalFilter, autoResetSortBy: false,
} = useTable( disableSortRemove: true,
{ },
columns: columns as any[], // TODO: fix after `react-table` v8 update useSortBy
data: data.predefined, );
initialState,
sortTypes,
autoResetGlobalFilter: false,
autoResetSortBy: false,
disableSortRemove: true,
},
useGlobalFilter,
useSortBy
);
const { const {
getTableProps: customGetTableProps, getTableProps: customGetTableProps,
@ -356,18 +353,15 @@ export const StrategiesList = () => {
headerGroups: customHeaderGroups, headerGroups: customHeaderGroups,
rows: customRows, rows: customRows,
prepareRow: customPrepareRow, prepareRow: customPrepareRow,
setGlobalFilter: customSetGlobalFilter,
} = useTable( } = useTable(
{ {
columns: columns as any[], // TODO: fix after `react-table` v8 update columns: columns as any[], // TODO: fix after `react-table` v8 update
data: data.custom, data: data.custom,
initialState, initialState,
sortTypes, sortTypes,
autoResetGlobalFilter: false,
autoResetSortBy: false, autoResetSortBy: false,
disableSortRemove: true, disableSortRemove: true,
}, },
useGlobalFilter,
useSortBy useSortBy
); );
@ -379,29 +373,17 @@ export const StrategiesList = () => {
})); }));
}; };
let strategyTypeCount = rows.length;
return ( return (
<PageContent <StyledBox>
isLoading={loading} <PageContent
header={ isLoading={loading}
<PageHeader header={
title={`Strategy types (${strategyTypeCount})`} <PageHeader>
actions={ <PredefinedStrategyTitle />
<Search </PageHeader>
initialValue={globalFilter} }
onChange={(...props) => { >
setGlobalFilter(...props); <Box>
customSetGlobalFilter(...props);
}}
/>
}
/>
}
>
<SearchHighlightProvider value={globalFilter}>
<Box sx={theme => ({ paddingBottom: theme.spacing(4) })}>
<PredefinedStrategyTitle />
<Table {...getTableProps()}> <Table {...getTableProps()}>
<SortableTableHeader headerGroups={headerGroups} /> <SortableTableHeader headerGroups={headerGroups} />
<TableBody {...getTableBodyProps()}> <TableBody {...getTableBodyProps()}>
@ -422,27 +404,34 @@ export const StrategiesList = () => {
<ConditionallyRender <ConditionallyRender
condition={rows.length === 0} condition={rows.length === 0}
show={ show={
<ConditionallyRender <TablePlaceholder>
condition={globalFilter?.length > 0} No strategies available.
show={ </TablePlaceholder>
<TablePlaceholder>
No predefined strategies found matching
&ldquo;
{globalFilter}
&rdquo;
</TablePlaceholder>
}
elseShow={
<TablePlaceholder>
No strategies available.
</TablePlaceholder>
}
/>
} }
/> />
</Box> </Box>
<Dialogue
open={dialogueMetaData.show}
onClick={onDialogConfirm}
title={dialogueMetaData?.title}
onClose={() =>
setDialogueMetaData((prev: IDialogueMetaData) => ({
...prev,
show: false,
}))
}
/>
</PageContent>
<PageContent
isLoading={loading}
header={
<PageHeader>
<CustomStrategyTitle />
</PageHeader>
}
>
<Box> <Box>
<CustomStrategyTitle />
<Table {...customGetTableProps()}> <Table {...customGetTableProps()}>
<SortableTableHeader <SortableTableHeader
headerGroups={customHeaderGroups} headerGroups={customHeaderGroups}
@ -464,35 +453,22 @@ export const StrategiesList = () => {
</Table> </Table>
<ConditionallyRender <ConditionallyRender
condition={customRows.length === 0} condition={customRows.length === 0}
show={ show={<CustomStrategyInfo />}
<ConditionallyRender
condition={globalFilter?.length > 0}
show={
<TablePlaceholder>
No custom strategies found matching
&ldquo;
{globalFilter}
&rdquo;
</TablePlaceholder>
}
elseShow={<CustomStrategyInfo />}
/>
}
/> />
</Box> </Box>
</SearchHighlightProvider>
<Dialogue <Dialogue
open={dialogueMetaData.show} open={dialogueMetaData.show}
onClick={onDialogConfirm} onClick={onDialogConfirm}
title={dialogueMetaData?.title} title={dialogueMetaData?.title}
onClose={() => onClose={() =>
setDialogueMetaData((prev: IDialogueMetaData) => ({ setDialogueMetaData((prev: IDialogueMetaData) => ({
...prev, ...prev,
show: false, show: false,
})) }))
} }
/> />
</PageContent> </PageContent>
</StyledBox>
); );
}; };