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:
parent
41370be591
commit
b91b7276c5
@ -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),
|
||||||
|
@ -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
|
|
||||||
“
|
|
||||||
{globalFilter}
|
|
||||||
”
|
|
||||||
</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
|
|
||||||
“
|
|
||||||
{globalFilter}
|
|
||||||
”
|
|
||||||
</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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user