import { useState, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { IconButton, Tooltip, Box } from '@mui/material'; import { Delete, Edit, Extension, Visibility, VisibilityOff, } from '@mui/icons-material'; import { DELETE_STRATEGY, UPDATE_STRATEGY, } 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 { PageContent } from 'component/common/PageContent/PageContent'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { Dialogue } from 'component/common/Dialogue/Dialogue'; import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; import { formatStrategyName } from 'utils/strategyNames'; import { useStrategies } from 'hooks/api/getters/useStrategies/useStrategies'; import useStrategiesApi from 'hooks/api/actions/useStrategiesApi/useStrategiesApi'; import useToast from 'hooks/useToast'; import { formatUnknownError } from 'utils/formatUnknownError'; 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 { show: boolean; title: string; onConfirm: () => void; } export const StrategiesList = () => { const navigate = useNavigate(); const [dialogueMetaData, setDialogueMetaData] = useState( { show: false, title: '', onConfirm: () => {}, } ); const { strategies, refetchStrategies, loading } = useStrategies(); const { removeStrategy, deprecateStrategy, reactivateStrategy } = useStrategiesApi(); const { setToastData, setToastApiError } = useToast(); const data = useMemo(() => { if (loading) { return Array(5).fill({ name: 'Context name', description: 'Context description when loading', }); } return strategies.map( ({ name, description, editable, deprecated }) => ({ name, description, editable, deprecated, }) ); }, [strategies, loading]); const columns = useMemo( () => [ { id: 'Icon', Cell: () => ( ), }, { Header: 'Name', accessor: 'name', width: '90%', Cell: ({ row: { original: { name, description, deprecated, editable }, }, }: any) => { const subTitleText = deprecated ? `${description} (deprecated)` : description; return ( } /> ); }, sortType: 'alphanumeric', }, { Header: 'Actions', id: 'Actions', align: 'center', Cell: ({ row: { original } }: any) => ( {editButton(original)} {deleteButton(original)} ), width: 150, disableSortBy: true, }, { accessor: 'description', disableSortBy: true, }, { accessor: 'sortOrder', sortType: 'number', }, ], [] ); const initialState = useMemo( () => ({ sortBy: [{ id: 'name', desc: false }], hiddenColumns: ['description', 'sortOrder'], }), [] ); 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) => { setDialogueMetaData({ show: true, title: 'Really reactivate strategy?', onConfirm: async () => { try { await reactivateStrategy(strategy); refetchStrategies(); setToastData({ type: 'success', title: 'Success', text: 'Strategy reactivated successfully', }); } catch (error: unknown) { setToastApiError(formatUnknownError(error)); } }, }); }; const onDeprecateStrategy = (strategy: IStrategy) => { setDialogueMetaData({ show: true, title: 'Really deprecate strategy?', onConfirm: async () => { try { await deprecateStrategy(strategy); refetchStrategies(); setToastData({ type: 'success', title: 'Success', text: 'Strategy deprecated successfully', }); } catch (error: unknown) { setToastApiError(formatUnknownError(error)); } }, }); }; const onDeleteStrategy = (strategy: IStrategy) => { setDialogueMetaData({ show: true, title: 'Really delete strategy?', onConfirm: async () => { try { await removeStrategy(strategy); refetchStrategies(); setToastData({ type: 'success', title: 'Success', text: 'Strategy deleted successfully', }); } catch (error: unknown) { setToastApiError(formatUnknownError(error)); } }, }); }; const reactivateButton = (strategy: IStrategy) => ( onReactivateStrategy(strategy)} permission={UPDATE_STRATEGY} tooltipProps={{ title: 'Reactivate activation strategy' }} > ); const deprecateButton = (strategy: IStrategy) => (
} elseShow={
onDeprecateStrategy(strategy)} permission={UPDATE_STRATEGY} tooltipProps={{ title: 'Deprecate strategy' }} >
} /> ); const editButton = (strategy: IStrategy) => ( navigate(`/strategies/${strategy?.name}/edit`) } permission={UPDATE_STRATEGY} tooltipProps={{ title: 'Edit strategy' }} > } elseShow={
} /> ); const deleteButton = (strategy: IStrategy) => ( onDeleteStrategy(strategy)} permission={DELETE_STRATEGY} tooltipProps={{ title: 'Delete strategy' }} > } elseShow={
} /> ); const onDialogConfirm = () => { dialogueMetaData?.onConfirm(); setDialogueMetaData((prev: IDialogueMetaData) => ({ ...prev, show: false, })); }; return ( } /> } > {rows.map(row => { prepareRow(row); return ( {row.cells.map(cell => ( {cell.render('Cell')} ))} ); })}
0} show={ No strategies found matching “ {globalFilter} ” } elseShow={ No strategies available. Get started by adding one. } /> } /> setDialogueMetaData((prev: IDialogueMetaData) => ({ ...prev, show: false, })) } />
); };