2022-02-11 00:08:55 +01:00
|
|
|
import { useContext, useState } from 'react';
|
2021-03-30 15:14:02 +02:00
|
|
|
import { Link, useHistory } from 'react-router-dom';
|
|
|
|
import useMediaQuery from '@material-ui/core/useMediaQuery';
|
2021-11-29 14:29:58 +01:00
|
|
|
import {
|
|
|
|
IconButton,
|
|
|
|
List,
|
|
|
|
ListItem,
|
|
|
|
ListItemAvatar,
|
|
|
|
ListItemText,
|
|
|
|
Tooltip,
|
|
|
|
} from '@material-ui/core';
|
|
|
|
import {
|
|
|
|
Add,
|
|
|
|
Delete,
|
2022-03-04 23:39:41 +01:00
|
|
|
Edit,
|
2021-11-29 14:29:58 +01:00
|
|
|
Extension,
|
|
|
|
Visibility,
|
|
|
|
VisibilityOff,
|
|
|
|
} from '@material-ui/icons';
|
|
|
|
import {
|
|
|
|
CREATE_STRATEGY,
|
|
|
|
DELETE_STRATEGY,
|
|
|
|
UPDATE_STRATEGY,
|
2022-03-28 10:49:59 +02:00
|
|
|
} from 'component/providers/AccessProvider/permissions';
|
2022-03-04 23:39:41 +01:00
|
|
|
import ConditionallyRender from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
|
|
import PageContent from 'component/common/PageContent/PageContent';
|
|
|
|
import HeaderTitle from 'component/common/HeaderTitle';
|
2022-02-11 00:08:55 +01:00
|
|
|
import { useStyles } from './StrategiesList.styles';
|
2022-03-04 23:39:41 +01:00
|
|
|
import AccessContext from 'contexts/AccessContext';
|
|
|
|
import Dialogue from 'component/common/Dialogue';
|
2022-04-01 10:28:15 +02:00
|
|
|
import { ADD_NEW_STRATEGY_ID } from 'utils/testIds';
|
2022-03-04 23:39:41 +01:00
|
|
|
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
|
|
|
|
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
|
2022-03-25 12:34:20 +01:00
|
|
|
import { formatStrategyName } from 'utils/strategyNames';
|
2022-03-09 14:59:24 +01:00
|
|
|
import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies';
|
2022-03-04 23:39:41 +01:00
|
|
|
import useStrategiesApi from 'hooks/api/actions/useStrategiesApi/useStrategiesApi';
|
|
|
|
import useToast from 'hooks/useToast';
|
2022-03-25 12:34:20 +01:00
|
|
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
2022-03-04 23:39:41 +01:00
|
|
|
import { ICustomStrategy } from 'interfaces/strategy';
|
2022-02-11 00:08:55 +01:00
|
|
|
|
|
|
|
interface IDialogueMetaData {
|
|
|
|
show: boolean;
|
|
|
|
title: string;
|
|
|
|
onConfirm: () => void;
|
|
|
|
}
|
2021-03-30 15:14:02 +02:00
|
|
|
|
2022-02-11 00:08:55 +01:00
|
|
|
export const StrategiesList = () => {
|
2021-03-30 15:14:02 +02:00
|
|
|
const history = useHistory();
|
|
|
|
const styles = useStyles();
|
|
|
|
const smallScreen = useMediaQuery('(max-width:700px)');
|
2021-04-20 19:13:31 +02:00
|
|
|
const { hasAccess } = useContext(AccessContext);
|
2022-02-11 00:08:55 +01:00
|
|
|
const [dialogueMetaData, setDialogueMetaData] = useState<IDialogueMetaData>(
|
2022-02-25 10:55:39 +01:00
|
|
|
{
|
|
|
|
show: false,
|
|
|
|
title: '',
|
|
|
|
onConfirm: () => {},
|
|
|
|
}
|
2022-02-11 00:08:55 +01:00
|
|
|
);
|
|
|
|
const { strategies, refetchStrategies } = useStrategies();
|
|
|
|
const { removeStrategy, deprecateStrategy, reactivateStrategy } =
|
|
|
|
useStrategiesApi();
|
|
|
|
const { setToastData, setToastApiError } = useToast();
|
2021-03-30 15:14:02 +02:00
|
|
|
|
|
|
|
const headerButton = () => (
|
|
|
|
<ConditionallyRender
|
2021-04-20 19:13:31 +02:00
|
|
|
condition={hasAccess(CREATE_STRATEGY)}
|
2021-03-30 15:14:02 +02:00
|
|
|
show={
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={smallScreen}
|
|
|
|
show={
|
2021-11-29 14:29:58 +01:00
|
|
|
<PermissionIconButton
|
2022-04-08 13:13:45 +02:00
|
|
|
data-testid={ADD_NEW_STRATEGY_ID}
|
2021-11-29 14:29:58 +01:00
|
|
|
onClick={() => history.push('/strategies/create')}
|
|
|
|
permission={CREATE_STRATEGY}
|
2022-04-21 08:26:49 +02:00
|
|
|
tooltip="New strategy"
|
2021-11-29 14:29:58 +01:00
|
|
|
>
|
|
|
|
<Add />
|
|
|
|
</PermissionIconButton>
|
2021-03-30 15:14:02 +02:00
|
|
|
}
|
|
|
|
elseShow={
|
2021-10-21 13:25:39 +02:00
|
|
|
<PermissionButton
|
2021-04-23 15:21:24 +02:00
|
|
|
onClick={() => history.push('/strategies/create')}
|
|
|
|
color="primary"
|
2021-10-21 13:25:39 +02:00
|
|
|
permission={CREATE_STRATEGY}
|
2022-04-08 13:13:45 +02:00
|
|
|
data-testid={ADD_NEW_STRATEGY_ID}
|
2021-04-23 15:21:24 +02:00
|
|
|
>
|
2022-02-23 00:10:48 +01:00
|
|
|
New strategy
|
2021-10-21 13:25:39 +02:00
|
|
|
</PermissionButton>
|
2021-03-30 15:14:02 +02:00
|
|
|
}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const strategyLink = (name: string, deprecated: boolean) => (
|
|
|
|
<Link to={`/strategies/${name}`}>
|
2022-03-09 14:59:24 +01:00
|
|
|
<strong>{formatStrategyName(name)}</strong>
|
2021-04-23 15:21:24 +02:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={deprecated}
|
|
|
|
show={<small> (Deprecated)</small>}
|
|
|
|
/>
|
2021-03-30 15:14:02 +02:00
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const onReactivateStrategy = (strategy: ICustomStrategy) => {
|
2022-02-11 00:08:55 +01:00
|
|
|
setDialogueMetaData({
|
|
|
|
show: true,
|
|
|
|
title: 'Really reactivate strategy?',
|
|
|
|
onConfirm: async () => {
|
|
|
|
try {
|
|
|
|
await reactivateStrategy(strategy);
|
|
|
|
refetchStrategies();
|
|
|
|
setToastData({
|
|
|
|
type: 'success',
|
|
|
|
title: 'Success',
|
|
|
|
text: 'Strategy reactivated successfully',
|
|
|
|
});
|
2022-02-25 10:55:39 +01:00
|
|
|
} catch (error: unknown) {
|
|
|
|
setToastApiError(formatUnknownError(error));
|
2022-02-11 00:08:55 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const onDeprecateStrategy = (strategy: ICustomStrategy) => {
|
2022-02-11 00:08:55 +01:00
|
|
|
setDialogueMetaData({
|
|
|
|
show: true,
|
|
|
|
title: 'Really deprecate strategy?',
|
|
|
|
onConfirm: async () => {
|
|
|
|
try {
|
|
|
|
await deprecateStrategy(strategy);
|
|
|
|
refetchStrategies();
|
|
|
|
setToastData({
|
|
|
|
type: 'success',
|
|
|
|
title: 'Success',
|
|
|
|
text: 'Strategy deprecated successfully',
|
|
|
|
});
|
2022-02-25 10:55:39 +01:00
|
|
|
} catch (error: unknown) {
|
|
|
|
setToastApiError(formatUnknownError(error));
|
2022-02-11 00:08:55 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const onDeleteStrategy = (strategy: ICustomStrategy) => {
|
2022-02-11 00:08:55 +01:00
|
|
|
setDialogueMetaData({
|
|
|
|
show: true,
|
|
|
|
title: 'Really delete strategy?',
|
|
|
|
onConfirm: async () => {
|
|
|
|
try {
|
|
|
|
await removeStrategy(strategy);
|
|
|
|
refetchStrategies();
|
|
|
|
setToastData({
|
|
|
|
type: 'success',
|
|
|
|
title: 'Success',
|
|
|
|
text: 'Strategy deleted successfully',
|
|
|
|
});
|
2022-02-25 10:55:39 +01:00
|
|
|
} catch (error: unknown) {
|
|
|
|
setToastApiError(formatUnknownError(error));
|
2022-02-11 00:08:55 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const reactivateButton = (strategy: ICustomStrategy) => (
|
2022-04-21 08:26:49 +02:00
|
|
|
<PermissionIconButton
|
|
|
|
onClick={() => onReactivateStrategy(strategy)}
|
|
|
|
permission={UPDATE_STRATEGY}
|
|
|
|
tooltip="Reactivate activation strategy"
|
|
|
|
>
|
|
|
|
<VisibilityOff />
|
|
|
|
</PermissionIconButton>
|
2021-03-30 15:14:02 +02:00
|
|
|
);
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const deprecateButton = (strategy: ICustomStrategy) => (
|
2021-03-30 15:14:02 +02:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={strategy.name === 'default'}
|
|
|
|
show={
|
|
|
|
<Tooltip title="You cannot deprecate the default strategy">
|
|
|
|
<div>
|
|
|
|
<IconButton disabled>
|
2022-03-23 09:12:10 +01:00
|
|
|
<Visibility titleAccess="Deprecate strategy" />
|
2021-03-30 15:14:02 +02:00
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
</Tooltip>
|
|
|
|
}
|
|
|
|
elseShow={
|
2021-10-21 13:25:39 +02:00
|
|
|
<div>
|
|
|
|
<PermissionIconButton
|
2022-02-11 00:08:55 +01:00
|
|
|
onClick={() => onDeprecateStrategy(strategy)}
|
2021-10-21 13:25:39 +02:00
|
|
|
permission={UPDATE_STRATEGY}
|
2022-04-21 08:26:49 +02:00
|
|
|
tooltip="Deprecate strategy"
|
2021-10-21 13:25:39 +02:00
|
|
|
>
|
2022-04-21 08:26:49 +02:00
|
|
|
<Visibility />
|
2021-10-21 13:25:39 +02:00
|
|
|
</PermissionIconButton>
|
|
|
|
</div>
|
2021-03-30 15:14:02 +02:00
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
2022-03-04 23:39:41 +01:00
|
|
|
const editButton = (strategy: ICustomStrategy) => (
|
2021-03-30 15:14:02 +02:00
|
|
|
<ConditionallyRender
|
2022-03-04 23:39:41 +01:00
|
|
|
condition={strategy?.editable}
|
|
|
|
show={
|
|
|
|
<PermissionIconButton
|
|
|
|
onClick={() =>
|
|
|
|
history.push(`/strategies/${strategy?.name}/edit`)
|
|
|
|
}
|
|
|
|
permission={UPDATE_STRATEGY}
|
2022-04-21 08:26:49 +02:00
|
|
|
tooltip="Edit strategy"
|
2022-03-04 23:39:41 +01:00
|
|
|
>
|
2022-04-21 08:26:49 +02:00
|
|
|
<Edit />
|
2022-03-04 23:39:41 +01:00
|
|
|
</PermissionIconButton>
|
|
|
|
}
|
|
|
|
elseShow={
|
|
|
|
<Tooltip title="You cannot delete a built-in strategy">
|
|
|
|
<div>
|
|
|
|
<IconButton disabled>
|
|
|
|
<Edit titleAccess="Edit strategy" />
|
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
</Tooltip>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
|
|
|
const deleteButton = (strategy: ICustomStrategy) => (
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={strategy?.editable}
|
2021-03-30 15:14:02 +02:00
|
|
|
show={
|
2021-11-29 14:29:58 +01:00
|
|
|
<PermissionIconButton
|
2022-02-11 00:08:55 +01:00
|
|
|
onClick={() => onDeleteStrategy(strategy)}
|
2021-11-29 14:29:58 +01:00
|
|
|
permission={DELETE_STRATEGY}
|
2022-04-21 08:26:49 +02:00
|
|
|
tooltip="Delete strategy"
|
2021-11-29 14:29:58 +01:00
|
|
|
>
|
|
|
|
<Delete />
|
|
|
|
</PermissionIconButton>
|
2021-03-30 15:14:02 +02:00
|
|
|
}
|
|
|
|
elseShow={
|
|
|
|
<Tooltip title="You cannot delete a built-in strategy">
|
|
|
|
<div>
|
|
|
|
<IconButton disabled>
|
2022-04-21 08:26:49 +02:00
|
|
|
<Delete titleAccess="Delete strategy" />
|
2021-03-30 15:14:02 +02:00
|
|
|
</IconButton>
|
|
|
|
</div>
|
|
|
|
</Tooltip>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
|
|
|
const strategyList = () =>
|
|
|
|
strategies.map(strategy => (
|
2022-03-04 23:39:41 +01:00
|
|
|
<ListItem key={strategy.name} className={styles.listItem}>
|
2021-03-30 15:14:02 +02:00
|
|
|
<ListItemAvatar>
|
2021-06-29 10:21:54 +02:00
|
|
|
<Extension style={{ color: '#0000008a' }} />
|
2021-03-30 15:14:02 +02:00
|
|
|
</ListItemAvatar>
|
2021-04-23 15:21:24 +02:00
|
|
|
<ListItemText
|
2022-03-04 23:39:41 +01:00
|
|
|
primary={strategyLink(strategy?.name, strategy?.deprecated)}
|
2021-04-23 15:21:24 +02:00
|
|
|
secondary={strategy.description}
|
|
|
|
/>
|
2021-03-30 15:14:02 +02:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={strategy.deprecated}
|
|
|
|
show={reactivateButton(strategy)}
|
|
|
|
elseShow={deprecateButton(strategy)}
|
|
|
|
/>
|
2022-03-04 23:39:41 +01:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={hasAccess(UPDATE_STRATEGY)}
|
|
|
|
show={editButton(strategy)}
|
|
|
|
/>
|
2021-04-23 15:21:24 +02:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={hasAccess(DELETE_STRATEGY)}
|
|
|
|
show={deleteButton(strategy)}
|
|
|
|
/>
|
2021-03-30 15:14:02 +02:00
|
|
|
</ListItem>
|
|
|
|
));
|
|
|
|
|
2021-05-10 13:22:22 +02:00
|
|
|
const onDialogConfirm = () => {
|
|
|
|
dialogueMetaData?.onConfirm();
|
|
|
|
setDialogueMetaData(prev => ({ ...prev, show: false }));
|
|
|
|
};
|
|
|
|
|
2021-03-30 15:14:02 +02:00
|
|
|
return (
|
2021-04-23 15:21:24 +02:00
|
|
|
<PageContent
|
|
|
|
headerContent={
|
|
|
|
<HeaderTitle title="Strategies" actions={headerButton()} />
|
|
|
|
}
|
|
|
|
>
|
2021-05-10 13:22:22 +02:00
|
|
|
<Dialogue
|
|
|
|
open={dialogueMetaData.show}
|
|
|
|
onClick={onDialogConfirm}
|
|
|
|
title={dialogueMetaData?.title}
|
|
|
|
onClose={() =>
|
|
|
|
setDialogueMetaData(prev => ({ ...prev, show: false }))
|
|
|
|
}
|
|
|
|
/>
|
2021-03-30 15:14:02 +02:00
|
|
|
<List>
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={strategies.length > 0}
|
2022-02-11 00:08:55 +01:00
|
|
|
show={<>{strategyList()}</>}
|
2021-03-30 15:14:02 +02:00
|
|
|
elseShow={<ListItem>No strategies found</ListItem>}
|
|
|
|
/>
|
|
|
|
</List>
|
|
|
|
</PageContent>
|
|
|
|
);
|
|
|
|
};
|