mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
Feat/new strategies table (#1012)
* fix: add flex to toolbarcontainer * feat: add initial new table * feat: add styled badge * feat: remove dead code * fix: remove useContext import * fix: update context buttons to icon buttons * feat: add loading * fix: remove unused imports * Update src/component/strategies/StrategiesList/PredefinedBadge/PredefinedBadge.tsx Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> * fix: update spacing to use theme * fix: update loading * fix: update type Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
This commit is contained in:
parent
9463c8df90
commit
7ba9d2a577
@ -72,6 +72,7 @@ const calculateTrialDaysRemaining = (
|
|||||||
: undefined;
|
: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO - Cleanup to use theme instead of colors
|
||||||
const StyledBar = styled('aside')(({ theme }) => ({
|
const StyledBar = styled('aside')(({ theme }) => ({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
@ -92,6 +93,7 @@ const StyledButton = styled(Button)(({ theme }) => ({
|
|||||||
marginLeft: theme.spacing(2),
|
marginLeft: theme.spacing(2),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// TODO - Cleanup to use theme instead of colors
|
||||||
const StyledInfoIcon = styled(Info)(({ theme }) => ({
|
const StyledInfoIcon = styled(Info)(({ theme }) => ({
|
||||||
color: colors.blue[500],
|
color: colors.blue[500],
|
||||||
}));
|
}));
|
||||||
|
@ -19,6 +19,7 @@ interface IPermissionIconButtonProps {
|
|||||||
type?: 'button';
|
type?: 'button';
|
||||||
edge?: IconButtonProps['edge'];
|
edge?: IconButtonProps['edge'];
|
||||||
tooltipProps?: Omit<ITooltipResolverProps, 'children'>;
|
tooltipProps?: Omit<ITooltipResolverProps, 'children'>;
|
||||||
|
size?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IButtonProps extends IPermissionIconButtonProps {
|
interface IButtonProps extends IPermissionIconButtonProps {
|
||||||
|
@ -28,7 +28,6 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
display: '-webkit-box',
|
display: '-webkit-box',
|
||||||
WebkitBoxOrient: 'vertical',
|
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
color: theme.palette.text.secondary,
|
color: theme.palette.text.secondary,
|
||||||
|
@ -13,7 +13,12 @@ interface ILinkCellProps {
|
|||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkCell: FC<ILinkCellProps> = ({ title, to, subtitle }) => {
|
export const LinkCell: FC<ILinkCellProps> = ({
|
||||||
|
title,
|
||||||
|
to,
|
||||||
|
subtitle,
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
const search = useSearchHighlightContext();
|
const search = useSearchHighlightContext();
|
||||||
|
|
||||||
@ -28,6 +33,7 @@ export const LinkCell: FC<ILinkCellProps> = ({ title, to, subtitle }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Highlighter search={search}>{title}</Highlighter>
|
<Highlighter search={search}>{title}</Highlighter>
|
||||||
|
{children}
|
||||||
</span>
|
</span>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(subtitle)}
|
condition={Boolean(subtitle)}
|
||||||
|
@ -5,40 +5,37 @@ import { Add } from '@mui/icons-material';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
import { CREATE_CONTEXT_FIELD } from 'component/providers/AccessProvider/permissions';
|
import { CREATE_CONTEXT_FIELD } from 'component/providers/AccessProvider/permissions';
|
||||||
|
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
||||||
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
|
|
||||||
interface IAddContextButtonProps {}
|
interface IAddContextButtonProps {}
|
||||||
|
|
||||||
export const AddContextButton: VFC<IAddContextButtonProps> = () => {
|
export const AddContextButton: VFC<IAddContextButtonProps> = () => {
|
||||||
const smallScreen = useMediaQuery('(max-width:700px)');
|
const smallScreen = useMediaQuery('(max-width:700px)');
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(CREATE_CONTEXT_FIELD)}
|
condition={smallScreen}
|
||||||
show={
|
show={
|
||||||
<ConditionallyRender
|
<PermissionIconButton
|
||||||
condition={smallScreen}
|
permission={CREATE_CONTEXT_FIELD}
|
||||||
show={
|
onClick={() => navigate('/context/create')}
|
||||||
<Tooltip title="Add context type" arrow>
|
size="large"
|
||||||
<IconButton
|
tooltipProps={{ title: 'Add context type' }}
|
||||||
onClick={() => navigate('/context/create')}
|
>
|
||||||
size="large"
|
<Add />
|
||||||
>
|
</PermissionIconButton>
|
||||||
<Add />
|
}
|
||||||
</IconButton>
|
elseShow={
|
||||||
</Tooltip>
|
<PermissionButton
|
||||||
}
|
onClick={() => navigate('/context/create')}
|
||||||
elseShow={
|
permission={CREATE_CONTEXT_FIELD}
|
||||||
<Button
|
color="primary"
|
||||||
onClick={() => navigate('/context/create')}
|
variant="contained"
|
||||||
color="primary"
|
>
|
||||||
variant="contained"
|
New context field
|
||||||
>
|
</PermissionButton>
|
||||||
New context field
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -21,6 +21,7 @@ export const ContextActionsCell: VFC<IContextActionsCellProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
|
data-loading
|
||||||
sx={{
|
sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
px: 2,
|
px: 2,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useContext, useMemo, useState, VFC } from 'react';
|
import { useMemo, useState, VFC } from 'react';
|
||||||
import { useGlobalFilter, useSortBy, useTable } from 'react-table';
|
import { useGlobalFilter, useSortBy, useTable } from 'react-table';
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
@ -12,9 +12,7 @@ import {
|
|||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { UPDATE_CONTEXT_FIELD } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import { Dialogue as ConfirmDialogue } from 'component/common/Dialogue/Dialogue';
|
import { Dialogue as ConfirmDialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import useContextsApi from 'hooks/api/actions/useContextsApi/useContextsApi';
|
import useContextsApi from 'hooks/api/actions/useContextsApi/useContextsApi';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
@ -28,12 +26,12 @@ import { Adjust } from '@mui/icons-material';
|
|||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
|
|
||||||
const ContextList: VFC = () => {
|
const ContextList: VFC = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const [showDelDialogue, setShowDelDialogue] = useState(false);
|
const [showDelDialogue, setShowDelDialogue] = useState(false);
|
||||||
const [name, setName] = useState<string>();
|
const [name, setName] = useState<string>();
|
||||||
const { context, refetchUnleashContext, loading } = useUnleashContext();
|
const { context, refetchUnleashContext, loading } = useUnleashContext();
|
||||||
const { removeContext } = useContextsApi();
|
const { removeContext } = useContextsApi();
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return Array(5).fill({
|
return Array(5).fill({
|
||||||
@ -57,6 +55,7 @@ const ContextList: VFC = () => {
|
|||||||
id: 'Icon',
|
id: 'Icon',
|
||||||
Cell: () => (
|
Cell: () => (
|
||||||
<Box
|
<Box
|
||||||
|
data-loading
|
||||||
sx={{
|
sx={{
|
||||||
pl: 2,
|
pl: 2,
|
||||||
pr: 1,
|
pr: 1,
|
||||||
@ -79,12 +78,8 @@ const ContextList: VFC = () => {
|
|||||||
}: any) => (
|
}: any) => (
|
||||||
<LinkCell
|
<LinkCell
|
||||||
title={name}
|
title={name}
|
||||||
to={
|
|
||||||
hasAccess(UPDATE_CONTEXT_FIELD)
|
|
||||||
? `/context/edit/${name}`
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
subtitle={description}
|
subtitle={description}
|
||||||
|
data-loading
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
sortType: 'alphanumeric',
|
sortType: 'alphanumeric',
|
||||||
@ -118,7 +113,7 @@ const ContextList: VFC = () => {
|
|||||||
sortType: 'number',
|
sortType: 'number',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[hasAccess]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const initialState = useMemo(
|
const initialState = useMemo(
|
||||||
@ -172,6 +167,7 @@ const ContextList: VFC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent
|
<PageContent
|
||||||
|
isLoading={loading}
|
||||||
header={
|
header={
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title="Context fields"
|
title="Context fields"
|
||||||
|
@ -17,6 +17,7 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
},
|
},
|
||||||
toolbarContainer: {
|
toolbarContainer: {
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
display: 'flex',
|
||||||
},
|
},
|
||||||
innerContainer: {
|
innerContainer: {
|
||||||
padding: '1rem 2rem',
|
padding: '1rem 2rem',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { FeatureToggleListContainer } from 'component/feature/FeatureToggleList/FeatureToggleListContainer';
|
import { FeatureToggleListContainer } from 'component/feature/FeatureToggleList/FeatureToggleListContainer';
|
||||||
import { StrategyView } from 'component/strategies/StrategyView/StrategyView';
|
import { StrategyView } from 'component/strategies/StrategyView/StrategyView';
|
||||||
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
||||||
|
|
||||||
import { ArchiveListContainer } from 'component/archive/ArchiveListContainer';
|
import { ArchiveListContainer } from 'component/archive/ArchiveListContainer';
|
||||||
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
||||||
import { AddonList } from 'component/addons/AddonList/AddonList';
|
import { AddonList } from 'component/addons/AddonList/AddonList';
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
|
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
||||||
|
import { useMediaQuery } from '@mui/material';
|
||||||
|
import { CREATE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
||||||
|
import { ADD_NEW_STRATEGY_ID } from 'utils/testIds';
|
||||||
|
import { Add } from '@mui/icons-material';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const AddStrategyButton = () => {
|
||||||
|
const smallScreen = useMediaQuery('(max-width:700px)');
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={smallScreen}
|
||||||
|
show={
|
||||||
|
<PermissionIconButton
|
||||||
|
data-testid={ADD_NEW_STRATEGY_ID}
|
||||||
|
onClick={() => navigate('/strategies/create')}
|
||||||
|
permission={CREATE_STRATEGY}
|
||||||
|
size="large"
|
||||||
|
tooltipProps={{ title: 'New strategy' }}
|
||||||
|
>
|
||||||
|
<Add />
|
||||||
|
</PermissionIconButton>
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<PermissionButton
|
||||||
|
onClick={() => navigate('/strategies/create')}
|
||||||
|
color="primary"
|
||||||
|
permission={CREATE_STRATEGY}
|
||||||
|
data-testid={ADD_NEW_STRATEGY_ID}
|
||||||
|
>
|
||||||
|
New strategy
|
||||||
|
</PermissionButton>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,15 @@
|
|||||||
|
import { styled } from '@mui/material';
|
||||||
|
|
||||||
|
export const PredefinedBadge = () => {
|
||||||
|
return <StyledBadge>Predefined</StyledBadge>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledBadge = styled('div')(({ theme }) => ({
|
||||||
|
padding: theme.spacing(0.3, 1.25),
|
||||||
|
backgroundColor: theme.palette.predefinedBadgeColor,
|
||||||
|
textDecoration: 'none',
|
||||||
|
color: theme.palette.text.primary,
|
||||||
|
display: 'inline-block',
|
||||||
|
borderRadius: theme.shape.borderRadius,
|
||||||
|
marginLeft: theme.spacing(1.5),
|
||||||
|
}));
|
@ -1,14 +0,0 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
|
||||||
listItem: {
|
|
||||||
padding: '0',
|
|
||||||
['& a']: {
|
|
||||||
textDecoration: 'none',
|
|
||||||
color: 'inherit',
|
|
||||||
},
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: theme.palette.grey[200],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
@ -1,28 +0,0 @@
|
|||||||
import { MemoryRouter } from 'react-router-dom';
|
|
||||||
import { StrategiesList } from './StrategiesList';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
|
||||||
import UIProvider from 'component/providers/UIProvider/UIProvider';
|
|
||||||
import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider';
|
|
||||||
import { ThemeProvider } from 'themes/ThemeProvider';
|
|
||||||
import { AccessProviderMock } from 'component/providers/AccessProvider/AccessProviderMock';
|
|
||||||
|
|
||||||
test('renders correctly', () => {
|
|
||||||
const tree = renderer.create(
|
|
||||||
<MemoryRouter>
|
|
||||||
<ThemeProvider>
|
|
||||||
<AnnouncerProvider>
|
|
||||||
<UIProvider>
|
|
||||||
<AccessProviderMock
|
|
||||||
permissions={[{ permission: ADMIN }]}
|
|
||||||
>
|
|
||||||
<StrategiesList />
|
|
||||||
</AccessProviderMock>
|
|
||||||
</UIProvider>
|
|
||||||
</AnnouncerProvider>
|
|
||||||
</ThemeProvider>
|
|
||||||
</MemoryRouter>
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
@ -1,16 +1,7 @@
|
|||||||
import { useContext, useState } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import { IconButton, Tooltip, Box } from '@mui/material';
|
||||||
import {
|
import {
|
||||||
IconButton,
|
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
ListItemAvatar,
|
|
||||||
ListItemText,
|
|
||||||
Tooltip,
|
|
||||||
} from '@mui/material';
|
|
||||||
import {
|
|
||||||
Add,
|
|
||||||
Delete,
|
Delete,
|
||||||
Edit,
|
Edit,
|
||||||
Extension,
|
Extension,
|
||||||
@ -18,26 +9,35 @@ import {
|
|||||||
VisibilityOff,
|
VisibilityOff,
|
||||||
} from '@mui/icons-material';
|
} from '@mui/icons-material';
|
||||||
import {
|
import {
|
||||||
CREATE_STRATEGY,
|
|
||||||
DELETE_STRATEGY,
|
DELETE_STRATEGY,
|
||||||
UPDATE_STRATEGY,
|
UPDATE_STRATEGY,
|
||||||
} from 'component/providers/AccessProvider/permissions';
|
} from 'component/providers/AccessProvider/permissions';
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
SortableTableHeader,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
TablePlaceholder,
|
||||||
|
TableSearch,
|
||||||
|
} from 'component/common/Table';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { useStyles } from './StrategiesList.styles';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
|
||||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
import { ADD_NEW_STRATEGY_ID } from 'utils/testIds';
|
|
||||||
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
||||||
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
|
||||||
import { formatStrategyName } from 'utils/strategyNames';
|
import { formatStrategyName } from 'utils/strategyNames';
|
||||||
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
|
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
|
||||||
import useStrategiesApi from 'hooks/api/actions/useStrategiesApi/useStrategiesApi';
|
import useStrategiesApi from 'hooks/api/actions/useStrategiesApi/useStrategiesApi';
|
||||||
import useToast from 'hooks/useToast';
|
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 { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
|
import { useTable, useGlobalFilter, useSortBy } from 'react-table';
|
||||||
|
import { AddStrategyButton } from './AddStrategyButton/AddStrategyButton';
|
||||||
|
import { PredefinedBadge } from './PredefinedBadge/PredefinedBadge';
|
||||||
interface IDialogueMetaData {
|
interface IDialogueMetaData {
|
||||||
show: boolean;
|
show: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
@ -46,9 +46,6 @@ interface IDialogueMetaData {
|
|||||||
|
|
||||||
export const StrategiesList = () => {
|
export const StrategiesList = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { classes: styles } = useStyles();
|
|
||||||
const smallScreen = useMediaQuery('(max-width:700px)');
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
|
||||||
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
||||||
{
|
{
|
||||||
show: false,
|
show: false,
|
||||||
@ -56,50 +53,137 @@ export const StrategiesList = () => {
|
|||||||
onConfirm: () => {},
|
onConfirm: () => {},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const { strategies, refetchStrategies } = useStrategies();
|
|
||||||
|
const { strategies, refetchStrategies, loading } = useStrategies();
|
||||||
const { removeStrategy, deprecateStrategy, reactivateStrategy } =
|
const { removeStrategy, deprecateStrategy, reactivateStrategy } =
|
||||||
useStrategiesApi();
|
useStrategiesApi();
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
const headerButton = () => (
|
const data = useMemo(() => {
|
||||||
<ConditionallyRender
|
if (loading) {
|
||||||
condition={hasAccess(CREATE_STRATEGY)}
|
return Array(5).fill({
|
||||||
show={
|
name: 'Context name',
|
||||||
<ConditionallyRender
|
description: 'Context description when loading',
|
||||||
condition={smallScreen}
|
});
|
||||||
show={
|
}
|
||||||
<PermissionIconButton
|
|
||||||
data-testid={ADD_NEW_STRATEGY_ID}
|
return strategies.map(
|
||||||
onClick={() => navigate('/strategies/create')}
|
({ name, description, editable, deprecated }) => ({
|
||||||
permission={CREATE_STRATEGY}
|
name,
|
||||||
tooltipProps={{ title: 'New strategy' }}
|
description,
|
||||||
|
editable,
|
||||||
|
deprecated,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}, [strategies, loading]);
|
||||||
|
|
||||||
|
const columns = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
id: 'Icon',
|
||||||
|
Cell: () => (
|
||||||
|
<Box
|
||||||
|
data-loading
|
||||||
|
sx={{
|
||||||
|
pl: 2,
|
||||||
|
pr: 1,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Extension color="disabled" />
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Header: 'Name',
|
||||||
|
accessor: 'name',
|
||||||
|
width: '90%',
|
||||||
|
Cell: ({
|
||||||
|
row: {
|
||||||
|
original: { name, description, deprecated, editable },
|
||||||
|
},
|
||||||
|
}: any) => {
|
||||||
|
const subTitleText = deprecated
|
||||||
|
? `${description} (deprecated)`
|
||||||
|
: description;
|
||||||
|
return (
|
||||||
|
<LinkCell
|
||||||
|
data-loading
|
||||||
|
title={formatStrategyName(name)}
|
||||||
|
subtitle={subTitleText}
|
||||||
|
to={`/strategies/${name}`}
|
||||||
>
|
>
|
||||||
<Add />
|
<ConditionallyRender
|
||||||
</PermissionIconButton>
|
condition={!editable}
|
||||||
}
|
show={() => <PredefinedBadge />}
|
||||||
elseShow={
|
/>
|
||||||
<PermissionButton
|
</LinkCell>
|
||||||
onClick={() => navigate('/strategies/create')}
|
);
|
||||||
color="primary"
|
},
|
||||||
permission={CREATE_STRATEGY}
|
sortType: 'alphanumeric',
|
||||||
data-testid={ADD_NEW_STRATEGY_ID}
|
},
|
||||||
>
|
{
|
||||||
New strategy
|
Header: 'Actions',
|
||||||
</PermissionButton>
|
id: 'Actions',
|
||||||
}
|
align: 'center',
|
||||||
/>
|
Cell: ({ row: { original } }: any) => (
|
||||||
}
|
<Box
|
||||||
/>
|
sx={{ display: 'flex', justifyContent: 'flex-end' }}
|
||||||
|
data-loading
|
||||||
|
>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={original.deprecated}
|
||||||
|
show={reactivateButton(original)}
|
||||||
|
elseShow={deprecateButton(original)}
|
||||||
|
/>
|
||||||
|
{editButton(original)}
|
||||||
|
{deleteButton(original)}
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
width: 150,
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: 'description',
|
||||||
|
disableSortBy: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessor: 'sortOrder',
|
||||||
|
sortType: 'number',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const strategyLink = (name: string, deprecated: boolean) => (
|
const initialState = useMemo(
|
||||||
<Link to={`/strategies/${name}`}>
|
() => ({
|
||||||
<strong>{formatStrategyName(name)}</strong>
|
sortBy: [{ id: 'name', desc: false }],
|
||||||
<ConditionallyRender
|
hiddenColumns: ['description', 'sortOrder'],
|
||||||
condition={deprecated}
|
}),
|
||||||
show={<small> (Deprecated)</small>}
|
[]
|
||||||
/>
|
);
|
||||||
</Link>
|
|
||||||
|
const {
|
||||||
|
getTableProps,
|
||||||
|
getTableBodyProps,
|
||||||
|
headerGroups,
|
||||||
|
rows,
|
||||||
|
prepareRow,
|
||||||
|
state: { globalFilter },
|
||||||
|
setGlobalFilter,
|
||||||
|
} = useTable(
|
||||||
|
{
|
||||||
|
columns: columns as any[], // TODO: fix after `react-table` v8 update
|
||||||
|
data,
|
||||||
|
initialState,
|
||||||
|
sortTypes,
|
||||||
|
autoResetGlobalFilter: false,
|
||||||
|
autoResetSortBy: false,
|
||||||
|
disableSortRemove: true,
|
||||||
|
},
|
||||||
|
useGlobalFilter,
|
||||||
|
useSortBy
|
||||||
);
|
);
|
||||||
|
|
||||||
const onReactivateStrategy = (strategy: IStrategy) => {
|
const onReactivateStrategy = (strategy: IStrategy) => {
|
||||||
@ -176,10 +260,7 @@ export const StrategiesList = () => {
|
|||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={strategy.name === 'default'}
|
condition={strategy.name === 'default'}
|
||||||
show={
|
show={
|
||||||
<Tooltip
|
<Tooltip title="You cannot deprecate the default strategy">
|
||||||
title="You cannot deprecate the default strategy"
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<IconButton disabled size="large">
|
<IconButton disabled size="large">
|
||||||
<Visibility titleAccess="Deprecate strategy" />
|
<Visibility titleAccess="Deprecate strategy" />
|
||||||
@ -216,7 +297,7 @@ export const StrategiesList = () => {
|
|||||||
</PermissionIconButton>
|
</PermissionIconButton>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<Tooltip title="You cannot delete a built-in strategy" arrow>
|
<Tooltip title="You cannot edit a built-in strategy" arrow>
|
||||||
<div>
|
<div>
|
||||||
<IconButton disabled size="large">
|
<IconButton disabled size="large">
|
||||||
<Edit titleAccess="Edit strategy" />
|
<Edit titleAccess="Edit strategy" />
|
||||||
@ -251,56 +332,85 @@ export const StrategiesList = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
const strategyList = () =>
|
|
||||||
strategies.map(strategy => (
|
|
||||||
<ListItem key={strategy.name} className={styles.listItem}>
|
|
||||||
<ListItemAvatar>
|
|
||||||
<Extension color="disabled" />
|
|
||||||
</ListItemAvatar>
|
|
||||||
<ListItemText
|
|
||||||
primary={strategyLink(strategy?.name, strategy?.deprecated)}
|
|
||||||
secondary={strategy.description}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={strategy.deprecated}
|
|
||||||
show={reactivateButton(strategy)}
|
|
||||||
elseShow={deprecateButton(strategy)}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={hasAccess(UPDATE_STRATEGY)}
|
|
||||||
show={editButton(strategy)}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={hasAccess(DELETE_STRATEGY)}
|
|
||||||
show={deleteButton(strategy)}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
));
|
|
||||||
|
|
||||||
const onDialogConfirm = () => {
|
const onDialogConfirm = () => {
|
||||||
dialogueMetaData?.onConfirm();
|
dialogueMetaData?.onConfirm();
|
||||||
setDialogueMetaData(prev => ({ ...prev, show: false }));
|
setDialogueMetaData((prev: IDialogueMetaData) => ({
|
||||||
|
...prev,
|
||||||
|
show: false,
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContent
|
<PageContent
|
||||||
header={<PageHeader title="Strategies" actions={headerButton()} />}
|
isLoading={loading}
|
||||||
|
header={
|
||||||
|
<PageHeader
|
||||||
|
title="Strategies"
|
||||||
|
actions={
|
||||||
|
<>
|
||||||
|
<TableSearch
|
||||||
|
initialValue={globalFilter}
|
||||||
|
onChange={setGlobalFilter}
|
||||||
|
/>
|
||||||
|
<PageHeader.Divider />
|
||||||
|
<AddStrategyButton />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
|
<SearchHighlightProvider value={globalFilter}>
|
||||||
|
<Table {...getTableProps()}>
|
||||||
|
<SortableTableHeader headerGroups={headerGroups} />
|
||||||
|
<TableBody {...getTableBodyProps()}>
|
||||||
|
{rows.map(row => {
|
||||||
|
prepareRow(row);
|
||||||
|
return (
|
||||||
|
<TableRow hover {...row.getRowProps()}>
|
||||||
|
{row.cells.map(cell => (
|
||||||
|
<TableCell {...cell.getCellProps()}>
|
||||||
|
{cell.render('Cell')}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</SearchHighlightProvider>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={rows.length === 0}
|
||||||
|
show={
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={globalFilter?.length > 0}
|
||||||
|
show={
|
||||||
|
<TablePlaceholder>
|
||||||
|
No strategies found matching “
|
||||||
|
{globalFilter}
|
||||||
|
”
|
||||||
|
</TablePlaceholder>
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<TablePlaceholder>
|
||||||
|
No strategies available. Get started by adding
|
||||||
|
one.
|
||||||
|
</TablePlaceholder>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Dialogue
|
<Dialogue
|
||||||
open={dialogueMetaData.show}
|
open={dialogueMetaData.show}
|
||||||
onClick={onDialogConfirm}
|
onClick={onDialogConfirm}
|
||||||
title={dialogueMetaData?.title}
|
title={dialogueMetaData?.title}
|
||||||
onClose={() =>
|
onClose={() =>
|
||||||
setDialogueMetaData(prev => ({ ...prev, show: false }))
|
setDialogueMetaData((prev: IDialogueMetaData) => ({
|
||||||
|
...prev,
|
||||||
|
show: false,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<List>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={strategies.length > 0}
|
|
||||||
show={<>{strategyList()}</>}
|
|
||||||
elseShow={<ListItem>No strategies found</ListItem>}
|
|
||||||
/>
|
|
||||||
</List>
|
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,270 +0,0 @@
|
|||||||
// Vitest Snapshot v1
|
|
||||||
|
|
||||||
exports[`renders correctly 1`] = `
|
|
||||||
[
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 tss-15wj2kz-container mui-177gdp-MuiPaper-root"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tss-1ywhhai-headerContainer"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tss-1ylehva-headerContainer"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tss-1uxyh7x-topContainer"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tss-sd6bs4-header"
|
|
||||||
data-loading={true}
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
className="MuiTypography-root MuiTypography-h1 tss-7lbvh4-headerTitle mui-ylrecv-MuiTypography-root"
|
|
||||||
>
|
|
||||||
Strategies
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="tss-u5t8ea-headerActions"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
id="useId-0"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
aria-describedby="useId-0"
|
|
||||||
className="MuiButton-root MuiButton-contained MuiButton-containedPrimary MuiButton-sizeMedium MuiButton-containedSizeMedium MuiButtonBase-root mui-1aw3qf3-MuiButtonBase-root-MuiButton-root"
|
|
||||||
data-testid="ADD_NEW_STRATEGY_ID"
|
|
||||||
disabled={false}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onContextMenu={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={0}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
New strategy
|
|
||||||
<span
|
|
||||||
className="MuiButton-endIcon MuiButton-iconSizeMedium mui-9tj150-MuiButton-endIcon"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="MuiTouchRipple-root mui-8je8zh-MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="tss-54jt3w-bodyContainer"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="MuiList-root MuiList-padding mui-h4y409-MuiList-root"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="MuiListItem-root MuiListItem-gutters MuiListItem-padding tss-ynyzms-listItem mui-vlytkl-MuiListItem-root"
|
|
||||||
disabled={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="MuiListItemAvatar-root mui-1e9lk82-MuiListItemAvatar-root"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root MuiSvgIcon-colorDisabled MuiSvgIcon-fontSizeMedium mui-1db085k-MuiSvgIcon-root"
|
|
||||||
data-testid="ExtensionIcon"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="MuiListItemText-root MuiListItemText-multiline mui-konndc-MuiListItemText-root"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="MuiTypography-root MuiTypography-body1 MuiListItemText-primary mui-1k7ov6f-MuiTypography-root"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/strategies/flexibleRollout"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<strong>
|
|
||||||
Gradual rollout
|
|
||||||
</strong>
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<p
|
|
||||||
className="MuiTypography-root MuiTypography-body2 MuiListItemText-secondary mui-of6c4k-MuiTypography-root"
|
|
||||||
>
|
|
||||||
Roll out to a percentage of your userbase, and ensure that the experience is the same for the user on each visit.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
aria-label="Deprecate strategy"
|
|
||||||
aria-labelledby={null}
|
|
||||||
className=""
|
|
||||||
data-mui-internal-clone-element={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="MuiButtonBase-root MuiIconButton-root MuiIconButton-sizeLarge mui-mf1cb5-MuiButtonBase-root-MuiIconButton-root"
|
|
||||||
disabled={false}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onClick={[Function]}
|
|
||||||
onContextMenu={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={0}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden={true}
|
|
||||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium mui-i4bv87-MuiSvgIcon-root"
|
|
||||||
data-testid="VisibilityIcon"
|
|
||||||
focusable="false"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span
|
|
||||||
className="MuiTouchRipple-root mui-8je8zh-MuiTouchRipple-root"
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="You cannot delete a built-in strategy"
|
|
||||||
aria-labelledby={null}
|
|
||||||
className=""
|
|
||||||
data-mui-internal-clone-element={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="MuiButtonBase-root Mui-disabled MuiIconButton-root Mui-disabled MuiIconButton-sizeLarge mui-mf1cb5-MuiButtonBase-root-MuiIconButton-root"
|
|
||||||
disabled={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onContextMenu={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={-1}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium mui-i4bv87-MuiSvgIcon-root"
|
|
||||||
data-testid="EditIcon"
|
|
||||||
focusable="false"
|
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"
|
|
||||||
/>
|
|
||||||
<title>
|
|
||||||
Edit strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
aria-label="You cannot delete a built-in strategy"
|
|
||||||
aria-labelledby={null}
|
|
||||||
className=""
|
|
||||||
data-mui-internal-clone-element={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseOver={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
className="MuiButtonBase-root Mui-disabled MuiIconButton-root Mui-disabled MuiIconButton-sizeLarge mui-mf1cb5-MuiButtonBase-root-MuiIconButton-root"
|
|
||||||
disabled={true}
|
|
||||||
onBlur={[Function]}
|
|
||||||
onContextMenu={[Function]}
|
|
||||||
onDragLeave={[Function]}
|
|
||||||
onFocus={[Function]}
|
|
||||||
onKeyDown={[Function]}
|
|
||||||
onKeyUp={[Function]}
|
|
||||||
onMouseDown={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
onMouseUp={[Function]}
|
|
||||||
onTouchEnd={[Function]}
|
|
||||||
onTouchMove={[Function]}
|
|
||||||
onTouchStart={[Function]}
|
|
||||||
tabIndex={-1}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium mui-i4bv87-MuiSvgIcon-root"
|
|
||||||
data-testid="DeleteIcon"
|
|
||||||
focusable="false"
|
|
||||||
role="img"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"
|
|
||||||
/>
|
|
||||||
<title>
|
|
||||||
Delete strategy
|
|
||||||
</title>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>,
|
|
||||||
<div
|
|
||||||
aria-atomic={true}
|
|
||||||
aria-live="polite"
|
|
||||||
className="tss-i8rqz1-container"
|
|
||||||
data-testid="ANNOUNCER_ELEMENT_TEST_ID"
|
|
||||||
role="status"
|
|
||||||
>
|
|
||||||
Navigated to Strategies
|
|
||||||
</div>,
|
|
||||||
]
|
|
||||||
`;
|
|
@ -81,6 +81,7 @@ export default createTheme({
|
|||||||
highlight: '#FFEACC',
|
highlight: '#FFEACC',
|
||||||
sidebarContainer: 'rgba(32,32,33, 0.2)',
|
sidebarContainer: 'rgba(32,32,33, 0.2)',
|
||||||
grey: colors.grey,
|
grey: colors.grey,
|
||||||
|
predefinedBadgeColor: colors.green[100],
|
||||||
text: {
|
text: {
|
||||||
primary: colors.grey[900],
|
primary: colors.grey[900],
|
||||||
secondary: colors.grey[800],
|
secondary: colors.grey[800],
|
||||||
|
@ -49,6 +49,11 @@ declare module '@mui/material/styles' {
|
|||||||
abandoned: string;
|
abandoned: string;
|
||||||
};
|
};
|
||||||
dividerAlternative: string;
|
dividerAlternative: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color for predefined badge
|
||||||
|
*/
|
||||||
|
predefinedBadgeColor: string;
|
||||||
/**
|
/**
|
||||||
* For table header hover effect.
|
* For table header hover effect.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user