From 6621d60d09eac498cdac6db768e773f480b53bfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Thu, 25 Jan 2024 16:28:59 +0000 Subject: [PATCH 1/2] chore: project actions table --- .../ProjectActions/ProjectActions.tsx | 7 +- .../ProjectActionsActionsCell.tsx | 44 +++ .../ProjectActionsActorCell.tsx | 22 ++ .../ProjectActionsDeleteDialog.tsx | 31 +++ .../ProjectActionsFiltersCell.tsx | 43 +++ .../ProjectActionsTable.tsx | 256 +++++++++++++++++- .../ProjectActionsTableActionsCell.tsx | 123 +++++++++ .../ProjectActionsTriggerCell.tsx | 49 ++++ .../actions/useActionsApi/useActionsApi.ts | 35 +++ frontend/src/interfaces/action.ts | 1 + 10 files changed, 608 insertions(+), 3 deletions(-) create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsDeleteDialog.tsx create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTableActionsCell.tsx create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActions.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActions.tsx index 651b070895ee..fab97c11e04e 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActions.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActions.tsx @@ -57,7 +57,12 @@ export const ProjectActions = () => { } > - + ); diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx new file mode 100644 index 000000000000..356bea877877 --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx @@ -0,0 +1,44 @@ +import { styled, Typography } from '@mui/material'; +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import { IActionSet } from 'interfaces/action'; +import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; +import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; + +const StyledItem = styled(Typography)(({ theme }) => ({ + fontSize: theme.fontSizes.smallerBody, +})); + +interface IProjectActionsActionsCellProps { + action: IActionSet; + onCreateAction?: () => void; +} + +export const ProjectActionsActionsCell = ({ + action, + onCreateAction, +}: IProjectActionsActionsCellProps) => { + const { actions } = action; + + if (actions.length === 0) { + if (!onCreateAction) return 0 actions; + else return ; + } + + return ( + + + {actions.map(({ id, action, executionParams }) => ( + + {action}: {JSON.stringify(executionParams)} + + ))} + + } + > + {actions.length === 1 ? '1 action' : `${actions.length} tokens`} + + + ); +}; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx new file mode 100644 index 000000000000..d8179715209b --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx @@ -0,0 +1,22 @@ +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import { IActionSet } from 'interfaces/action'; +import { IServiceAccount } from 'interfaces/service-account'; + +interface IProjectActionsActorCellProps { + action: IActionSet; + serviceAccounts: IServiceAccount[]; +} + +export const ProjectActionsActorCell = ({ + action, + serviceAccounts, +}: IProjectActionsActorCellProps) => { + const { sourceId } = action.match; + const actor = serviceAccounts.find(({ id }) => id === sourceId); + + if (!actor) { + return No service account; + } + + return {actor.name}; +}; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsDeleteDialog.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsDeleteDialog.tsx new file mode 100644 index 000000000000..6f870d2ba21d --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsDeleteDialog.tsx @@ -0,0 +1,31 @@ +import { Dialogue } from 'component/common/Dialogue/Dialogue'; +import { IActionSet } from 'interfaces/action'; + +interface IProjectActionsDeleteDialogProps { + action?: IActionSet; + open: boolean; + setOpen: React.Dispatch>; + onConfirm: (action: IActionSet) => void; +} + +export const ProjectActionsDeleteDialog = ({ + action, + open, + setOpen, + onConfirm, +}: IProjectActionsDeleteDialogProps) => ( + onConfirm(action!)} + onClose={() => { + setOpen(false); + }} + > +

+ You are about to delete action: {action?.name} +

+
+); diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx new file mode 100644 index 000000000000..b135fd530944 --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx @@ -0,0 +1,43 @@ +import { styled, Typography } from '@mui/material'; +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import { IActionSet } from 'interfaces/action'; +import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; + +const StyledItem = styled(Typography)(({ theme }) => ({ + fontSize: theme.fontSizes.smallerBody, +})); + +interface IProjectActionsFiltersCellProps { + action: IActionSet; +} + +export const ProjectActionsFiltersCell = ({ + action, +}: IProjectActionsFiltersCellProps) => { + const { payload } = action.match; + const filters = Object.keys(payload); + + if (filters.length === 0) { + return 0 filters; + } + + return ( + + + {filters.map((filter) => ( + + {filter} = {payload[filter]} + + ))} + + } + > + {filters.length === 1 + ? '1 filter' + : `${filters.length} filters`} + + + ); +}; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx index bfc6d5dc99ae..21db0edc5cd7 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx @@ -1,3 +1,255 @@ -export const ProjectActionsTable = () => { - return TODO; +import { useMemo, useState } from 'react'; +import { TablePlaceholder, VirtualizedTable } from 'component/common/Table'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; +import useToast from 'hooks/useToast'; +import { formatUnknownError } from 'utils/formatUnknownError'; +import { useMediaQuery } from '@mui/material'; +import { useFlexLayout, useSortBy, useTable } from 'react-table'; +import { sortTypes } from 'utils/sortTypes'; +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import { DateCell } from 'component/common/Table/cells/DateCell/DateCell'; +import theme from 'themes/theme'; +import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns'; +import { useActions } from 'hooks/api/getters/useActions/useActions'; +import { useActionsApi } from 'hooks/api/actions/useActionsApi/useActionsApi'; +import { IActionSet } from 'interfaces/action'; +import { ToggleCell } from 'component/common/Table/cells/ToggleCell/ToggleCell'; +import { ProjectActionsTriggerCell } from './ProjectActionsTriggerCell'; +import { ProjectActionsFiltersCell } from './ProjectActionsFiltersCell'; +import { ProjectActionsActorCell } from './ProjectActionsActorCell'; +import { ProjectActionsActionsCell } from './ProjectActionsActionsCell'; +import { ProjectActionsTableActionsCell } from './ProjectActionsTableActionsCell'; +// import { ProjectActionsModal } from '../ProjectActionsModal/ProjectActionsModal'; +import { ProjectActionsDeleteDialog } from './ProjectActionsDeleteDialog'; +import { useServiceAccounts } from 'hooks/api/getters/useServiceAccounts/useServiceAccounts'; +import { useIncomingWebhooks } from 'hooks/api/getters/useIncomingWebhooks/useIncomingWebhooks'; + +interface IProjectActionsTableProps { + modalOpen: boolean; + setModalOpen: React.Dispatch>; + selectedAction?: IActionSet; + setSelectedAction: React.Dispatch< + React.SetStateAction + >; +} + +export const ProjectActionsTable = ({ + modalOpen, + setModalOpen, + selectedAction, + setSelectedAction, +}: IProjectActionsTableProps) => { + const { setToastData, setToastApiError } = useToast(); + + const { actions, refetch } = useActions(); + const { toggleActionSet, removeActionSet } = useActionsApi(); + + const { incomingWebhooks } = useIncomingWebhooks(); + const { serviceAccounts } = useServiceAccounts(); + + const [deleteOpen, setDeleteOpen] = useState(false); + + const onToggleAction = async (action: IActionSet, enabled: boolean) => { + try { + await toggleActionSet(action.id, enabled); + setToastData({ + title: `"${action.name}" has been ${ + enabled ? 'enabled' : 'disabled' + }`, + type: 'success', + }); + refetch(); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }; + + const onDeleteConfirm = async (action: IActionSet) => { + try { + await removeActionSet(action.id); + setToastData({ + title: `"${action.name}" has been deleted`, + type: 'success', + }); + refetch(); + setDeleteOpen(false); + } catch (error: unknown) { + setToastApiError(formatUnknownError(error)); + } + }; + + const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); + + const columns = useMemo( + () => [ + { + Header: 'Name', + accessor: 'name', + }, + { + id: 'trigger', + Header: 'Trigger', + Cell: ({ + row: { original: action }, + }: { row: { original: IActionSet } }) => ( + + ), + }, + { + id: 'filters', + Header: 'Filters', + Cell: ({ + row: { original: action }, + }: { + row: { original: IActionSet }; + }) => , + maxWidth: 120, + }, + { + id: 'actor', + Header: 'Service account', + Cell: ({ + row: { original: action }, + }: { + row: { original: IActionSet }; + }) => ( + + ), + maxWidth: 120, + }, + { + id: 'actions', + Header: 'Actions', + Cell: ({ + row: { original: action }, + }: { + row: { original: IActionSet }; + }) => ( + { + setSelectedAction(action); + setModalOpen(true); + }} + /> + ), + maxWidth: 120, + }, + { + Header: 'Created', + accessor: 'createdAt', + Cell: DateCell, + width: 120, + maxWidth: 120, + }, + { + Header: 'Enabled', + accessor: 'enabled', + Cell: ({ + row: { original: action }, + }: { row: { original: IActionSet } }) => ( + + onToggleAction(action, enabled) + } + /> + ), + sortType: 'boolean', + width: 90, + maxWidth: 90, + }, + { + id: 'table-actions', + Header: '', + align: 'center', + Cell: ({ + row: { original: action }, + }: { row: { original: IActionSet } }) => ( + { + setSelectedAction(action); + setModalOpen(true); + }} + onDelete={() => { + setSelectedAction(action); + setDeleteOpen(true); + }} + /> + ), + width: 90, + disableSortBy: true, + }, + ], + [], + ); + + const [initialState] = useState({ + sortBy: [{ id: 'createdAt', desc: true }], + }); + + const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable( + { + columns: columns as any, + data: actions, + initialState, + sortTypes, + autoResetHiddenColumns: false, + autoResetSortBy: false, + disableSortRemove: true, + disableMultiSort: true, + defaultColumn: { + Cell: TextCell, + }, + }, + useSortBy, + useFlexLayout, + ); + + useConditionallyHiddenColumns( + [ + { + condition: isSmallScreen, + columns: ['createdAt'], + }, + ], + setHiddenColumns, + columns, + ); + + return ( + <> + + + No actions available. Get started by adding one. + + } + /> + {/* */} + + + ); }; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTableActionsCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTableActionsCell.tsx new file mode 100644 index 000000000000..94113cad497e --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTableActionsCell.tsx @@ -0,0 +1,123 @@ +import { useState } from 'react'; +import { + Box, + IconButton, + ListItemIcon, + ListItemText, + MenuItem, + MenuList, + Popover, + Tooltip, + Typography, + styled, +} from '@mui/material'; +import MoreVertIcon from '@mui/icons-material/MoreVert'; +import { Delete, Edit } from '@mui/icons-material'; +import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC'; +import { ADMIN } from 'component/providers/AccessProvider/permissions'; +import { defaultBorderRadius } from 'themes/themeStyles'; + +const StyledBoxCell = styled(Box)({ + display: 'flex', + justifyContent: 'center', +}); + +interface IProjectActionsTableActionsCellProps { + actionId: number; + onEdit: (event: React.SyntheticEvent) => void; + onDelete: (event: React.SyntheticEvent) => void; +} + +export const ProjectActionsTableActionsCell = ({ + actionId, + onEdit, + onDelete, +}: IProjectActionsTableActionsCellProps) => { + const [anchorEl, setAnchorEl] = useState(null); + + const open = Boolean(anchorEl); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleClose = () => { + setAnchorEl(null); + }; + + const id = `action-${actionId}-actions`; + const menuId = `${id}-menu`; + + return ( + + + + + + + ({ + borderRadius: `${theme.shape.borderRadius}px`, + padding: theme.spacing(1, 1.5), + }), + }} + > + + + {({ hasAccess }) => ( + + + + + + + Edit + + + + )} + + + {({ hasAccess }) => ( + + + + + + + Remove + + + + )} + + + + + ); +}; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx new file mode 100644 index 000000000000..ce8533f1a63c --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx @@ -0,0 +1,49 @@ +import { Avatar, styled } from '@mui/material'; +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import { IActionSet } from 'interfaces/action'; +import { IIncomingWebhook } from 'interfaces/incomingWebhook'; +import webhooksIcon from 'assets/icons/webhooks.svg'; +import { Link as RouterLink } from 'react-router-dom'; +import { StyledLink } from 'component/common/Table/cells/LinkCell/LinkCell.styles'; + +const StyledIcon = styled(Avatar)(({ theme }) => ({ + marginRight: theme.spacing(2), + borderRadius: theme.shape.borderRadius, + overflow: 'hidden', + width: theme.spacing(4), + height: theme.spacing(4), +})); + +interface IProjectActionsTriggerCellProps { + action: IActionSet; + incomingWebhooks: IIncomingWebhook[]; +} + +export const ProjectActionsTriggerCell = ({ + action, + incomingWebhooks, +}: IProjectActionsTriggerCellProps) => { + const { sourceId } = action.match; + const trigger = incomingWebhooks.find(({ id }) => id === sourceId); + + if (!trigger) { + return No trigger; + } + + return ( + + + + {trigger.name} + + + ); +}; diff --git a/frontend/src/hooks/api/actions/useActionsApi/useActionsApi.ts b/frontend/src/hooks/api/actions/useActionsApi/useActionsApi.ts index 54032411d33d..18cad8fc0966 100644 --- a/frontend/src/hooks/api/actions/useActionsApi/useActionsApi.ts +++ b/frontend/src/hooks/api/actions/useActionsApi/useActionsApi.ts @@ -52,6 +52,40 @@ export const useActionsApi = () => { await makeRequest(req.caller, req.id); }; + const enableActionSet = async (actionSetId: number) => { + const requestId = 'enableActionSet'; + const req = createRequest( + `${ENDPOINT}/${actionSetId}/on`, + { + method: 'POST', + }, + requestId, + ); + + await makeRequest(req.caller, req.id); + }; + + const disableActionSet = async (actionSetId: number) => { + const requestId = 'disableActionSet'; + const req = createRequest( + `${ENDPOINT}/${actionSetId}/off`, + { + method: 'POST', + }, + requestId, + ); + + await makeRequest(req.caller, req.id); + }; + + const toggleActionSet = async (actionSetId: number, enabled: boolean) => { + if (enabled) { + await enableActionSet(actionSetId); + } else { + await disableActionSet(actionSetId); + } + }; + const removeActionSet = async (actionSetId: number) => { const requestId = 'removeActionSet'; const req = createRequest( @@ -67,6 +101,7 @@ export const useActionsApi = () => { addActionSet, updateActionSet, removeActionSet, + toggleActionSet, errors, loading, }; diff --git a/frontend/src/interfaces/action.ts b/frontend/src/interfaces/action.ts index e9a8073e4024..d521c81f06ba 100644 --- a/frontend/src/interfaces/action.ts +++ b/frontend/src/interfaces/action.ts @@ -1,5 +1,6 @@ export interface IActionSet { id: number; + enabled: boolean; name: string; project: string; actorId: number; From ddebd1813ebb53c7684f9e30f2e0fcbdd6771399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Thu, 25 Jan 2024 17:48:03 +0000 Subject: [PATCH 2/2] chore: implement table with remaining cells --- .../ProjectActionsActionsCell.tsx | 36 ++++++++++--- .../ProjectActionsActorCell.tsx | 7 +-- .../ProjectActionsFiltersCell.tsx | 8 +-- .../ProjectActionsTable.tsx | 32 ++++++------ .../ProjectActionsTriggerCell.tsx | 51 ++++++++++++------- 5 files changed, 85 insertions(+), 49 deletions(-) diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx index 356bea877877..b10bbce1036c 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx @@ -1,13 +1,22 @@ -import { styled, Typography } from '@mui/material'; +import { styled } from '@mui/material'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { IActionSet } from 'interfaces/action'; import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; -const StyledItem = styled(Typography)(({ theme }) => ({ +const StyledActionItems = styled('div')(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(1), fontSize: theme.fontSizes.smallerBody, })); +const StyledParameterList = styled('ul')(({ theme }) => ({ + listStyle: 'none', + paddingLeft: theme.spacing(1), + margin: 0, +})); + interface IProjectActionsActionsCellProps { action: IActionSet; onCreateAction?: () => void; @@ -28,16 +37,27 @@ export const ProjectActionsActionsCell = ({ + {actions.map(({ id, action, executionParams }) => ( - - {action}: {JSON.stringify(executionParams)} - +
+ {action} + + {Object.entries(executionParams).map( + ([param, value]) => ( +
  • + {param}: {value} +
  • + ), + )} +
    +
    ))} - +
    } > - {actions.length === 1 ? '1 action' : `${actions.length} tokens`} + {actions.length === 1 + ? '1 action' + : `${actions.length} actions`}
    ); diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx index d8179715209b..d3427841112a 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx @@ -1,3 +1,4 @@ +import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { IActionSet } from 'interfaces/action'; import { IServiceAccount } from 'interfaces/service-account'; @@ -11,12 +12,12 @@ export const ProjectActionsActorCell = ({ action, serviceAccounts, }: IProjectActionsActorCellProps) => { - const { sourceId } = action.match; - const actor = serviceAccounts.find(({ id }) => id === sourceId); + const { actorId } = action; + const actor = serviceAccounts.find(({ id }) => id === actorId); if (!actor) { return No service account; } - return {actor.name}; + return {actor.name}; }; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx index b135fd530944..41d8c69628a7 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsFiltersCell.tsx @@ -15,7 +15,7 @@ export const ProjectActionsFiltersCell = ({ action, }: IProjectActionsFiltersCellProps) => { const { payload } = action.match; - const filters = Object.keys(payload); + const filters = Object.entries(payload); if (filters.length === 0) { return 0 filters; @@ -26,9 +26,9 @@ export const ProjectActionsFiltersCell = ({ - {filters.map((filter) => ( - - {filter} = {payload[filter]} + {filters.map(([parameter, value]) => ( + + {parameter}: {value} ))} diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx index 21db0edc5cd7..9f0208a1e80e 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx @@ -7,7 +7,6 @@ import { useMediaQuery } from '@mui/material'; import { useFlexLayout, useSortBy, useTable } from 'react-table'; import { sortTypes } from 'utils/sortTypes'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; -import { DateCell } from 'component/common/Table/cells/DateCell/DateCell'; import theme from 'themes/theme'; import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns'; import { useActions } from 'hooks/api/getters/useActions/useActions'; @@ -78,13 +77,15 @@ export const ProjectActionsTable = ({ } }; - const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); + const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm')); + const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg')); const columns = useMemo( () => [ { Header: 'Name', accessor: 'name', + minWidth: 60, }, { id: 'trigger', @@ -106,7 +107,7 @@ export const ProjectActionsTable = ({ }: { row: { original: IActionSet }; }) => , - maxWidth: 120, + maxWidth: 90, }, { id: 'actor', @@ -121,7 +122,7 @@ export const ProjectActionsTable = ({ serviceAccounts={serviceAccounts} /> ), - maxWidth: 120, + minWidth: 160, }, { id: 'actions', @@ -139,14 +140,7 @@ export const ProjectActionsTable = ({ }} /> ), - maxWidth: 120, - }, - { - Header: 'Created', - accessor: 'createdAt', - Cell: DateCell, - width: 120, - maxWidth: 120, + maxWidth: 130, }, { Header: 'Enabled', @@ -184,15 +178,15 @@ export const ProjectActionsTable = ({ }} /> ), - width: 90, + width: 50, disableSortBy: true, }, ], - [], + [actions, incomingWebhooks, serviceAccounts], ); const [initialState] = useState({ - sortBy: [{ id: 'createdAt', desc: true }], + sortBy: [{ id: 'name', desc: true }], }); const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable( @@ -216,8 +210,12 @@ export const ProjectActionsTable = ({ useConditionallyHiddenColumns( [ { - condition: isSmallScreen, - columns: ['createdAt'], + condition: isMediumScreen, + columns: ['actor', 'enabled'], + }, + { + condition: isExtraSmallScreen, + columns: ['filters', 'actions'], }, ], setHiddenColumns, diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx index ce8533f1a63c..02b3db621220 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx @@ -1,17 +1,32 @@ -import { Avatar, styled } from '@mui/material'; +import { Avatar, Box, Link, styled } from '@mui/material'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { IActionSet } from 'interfaces/action'; import { IIncomingWebhook } from 'interfaces/incomingWebhook'; import webhooksIcon from 'assets/icons/webhooks.svg'; import { Link as RouterLink } from 'react-router-dom'; -import { StyledLink } from 'component/common/Table/cells/LinkCell/LinkCell.styles'; +import { ComponentType } from 'react'; +import { wrapperStyles } from 'component/common/Table/cells/LinkCell/LinkCell.styles'; + +const StyledCell = styled(Box)({ + display: 'flex', + alignItems: 'center', +}); const StyledIcon = styled(Avatar)(({ theme }) => ({ - marginRight: theme.spacing(2), borderRadius: theme.shape.borderRadius, overflow: 'hidden', - width: theme.spacing(4), - height: theme.spacing(4), + width: theme.spacing(3), + height: theme.spacing(3), +})); + +const StyledLink = styled(Link)<{ + component?: ComponentType; + to?: string; +}>(({ theme }) => ({ + ...wrapperStyles(theme), + '&:hover, &:focus': { + textDecoration: 'underline', + }, })); interface IProjectActionsTriggerCellProps { @@ -32,18 +47,20 @@ export const ProjectActionsTriggerCell = ({ return ( - - - {trigger.name} - + + + + {trigger.name} + + ); };