From 86a795e87c688513701a0b77cbced3f9b79adbb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Tue, 5 Mar 2024 11:33:34 +0000 Subject: [PATCH] chore: new actions table UI (#6435) https://linear.app/unleash/issue/2-1995/ui-feature-rename-adapt-the-actions-ui https://linear.app/unleash/issue/2-1988/nice-to-have-last-action-status-on-the-action-sets-table Brings the project actions table UI up to par with the new designs, implementing some features that were discussed with UX. ![image](https://github.com/Unleash/unleash/assets/14320932/1a8ef47d-ab33-4284-9650-4c2481dd16dc) ![image](https://github.com/Unleash/unleash/assets/14320932/c19f6691-67a5-4abc-a546-837e25cad388) ![image](https://github.com/Unleash/unleash/assets/14320932/61e3f221-ae93-4d87-98f1-db2782285d2e) --- .../ProjectActionsActionsCell.tsx | 12 +++- .../ProjectActionsLastEvent.tsx | 59 +++++++++++++++++++ .../ProjectActionsActorCell.tsx | 8 ++- .../ProjectActionsEventsDetails.tsx | 8 ++- .../ProjectActionsEventsDetailsAction.tsx | 1 + ...tionsEventsDetailsSourceSignalEndpoint.tsx | 8 ++- .../ProjectActionsFiltersCell.tsx | 43 ++++++++++---- .../useProjectActionsForm.ts | 4 ++ .../ProjectActionsModal.tsx | 3 + ...rCell.tsx => ProjectActionsSourceCell.tsx} | 58 +++++++++--------- .../ProjectActionsTable.tsx | 11 ++-- frontend/src/interfaces/action.ts | 1 + 12 files changed, 163 insertions(+), 53 deletions(-) rename frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/{ => ProjectActionsActionsCell}/ProjectActionsActionsCell.tsx (88%) create mode 100644 frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsLastEvent.tsx rename frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/{ProjectActionsTriggerCell.tsx => ProjectActionsSourceCell.tsx} (53%) diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsActionsCell.tsx similarity index 88% rename from frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx rename to frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsActionsCell.tsx index 4a3b1b3bca2..29b13bd0bc5 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsActionsCell.tsx @@ -3,6 +3,13 @@ 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'; +import { ProjectActionsLastEvent } from './ProjectActionsLastEvent'; + +const StyledCell = styled('div')(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing(1), +})); const StyledActionItems = styled('div')(({ theme }) => ({ display: 'flex', @@ -34,7 +41,8 @@ export const ProjectActionsActionsCell = ({ } return ( - + + @@ -60,6 +68,6 @@ export const ProjectActionsActionsCell = ({ ? '1 action' : `${actions.length} actions`} - + ); }; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsLastEvent.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsLastEvent.tsx new file mode 100644 index 00000000000..7e0ad18a8ff --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActionsCell/ProjectActionsLastEvent.tsx @@ -0,0 +1,59 @@ +import { IActionSet } from 'interfaces/action'; +import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; +import { useActionEvents } from 'hooks/api/getters/useActionEvents/useActionEvents'; +import { ProjectActionsEventsDetails } from '../ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetails'; +import { CircularProgress, styled } from '@mui/material'; +import { CheckCircle, Error as ErrorIcon } from '@mui/icons-material'; + +const StyledTooltipLink = styled(TooltipLink)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', +})); + +export const StyledSuccessIcon = styled(CheckCircle)(({ theme }) => ({ + color: theme.palette.success.main, +})); + +export const StyledFailedIcon = styled(ErrorIcon)(({ theme }) => ({ + color: theme.palette.error.main, +})); + +interface IProjectActionsLastEventProps { + action: IActionSet; +} + +export const ProjectActionsLastEvent = ({ + action, +}: IProjectActionsLastEventProps) => { + const { id, project } = action; + const { actionEvents } = useActionEvents(id, project, 1, { + refreshInterval: 5000, + }); + + if (actionEvents.length === 0) { + return null; + } + + const actionSetEvent = actionEvents[0]; + + const icon = + actionSetEvent.state === 'success' ? ( + + ) : actionSetEvent.state === 'failed' ? ( + + ) : ( + + ); + + return ( + } + > + {icon} + + ); +}; 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 d3427841112..44c5aa993e8 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsActorCell.tsx @@ -19,5 +19,11 @@ export const ProjectActionsActorCell = ({ return No service account; } - return {actor.name}; + return ( + + ); }; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetails.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetails.tsx index 0e858148cec..0bca4b1651c 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetails.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetails.tsx @@ -10,6 +10,10 @@ const StyledDetails = styled('div')(({ theme }) => ({ padding: theme.spacing(2), })); +const StyledAlert = styled(Alert)({ + fontSize: 'inherit', +}); + export const ProjectActionsEventsDetails = ({ state, actionSet: { actions }, @@ -24,9 +28,9 @@ export const ProjectActionsEventsDetails = ({ return ( - + {stateText} - + {actions.map((action, i) => ( ({ const StyledAlert = styled(Alert)(({ theme }) => ({ marginTop: theme.spacing(2), + fontSize: 'inherit', })); const StyledDivider = styled(Divider)(({ theme }) => ({ diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetailsSource/ProjectActionsEventsDetailsSourceSignalEndpoint.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetailsSource/ProjectActionsEventsDetailsSourceSignalEndpoint.tsx index 4ecc08610e3..d0bb910748a 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetailsSource/ProjectActionsEventsDetailsSourceSignalEndpoint.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsEventsModal/ProjectActionsEventsDetails/ProjectActionsEventsDetailsSource/ProjectActionsEventsDetailsSourceSignalEndpoint.tsx @@ -24,6 +24,10 @@ const StyledAccordion = styled(Accordion)(({ theme }) => ({ }, })); +const StyledAccordionSummary = styled(AccordionSummary)({ + lineHeight: '1.5rem', +}); + const StyledLink = styled(Link)(({ theme }) => ({ marginLeft: theme.spacing(1), })); @@ -47,7 +51,7 @@ export const ProjectActionsEventsDetailsSourceSignalEndpoint = ({ return ( - @@ -58,7 +62,7 @@ export const ProjectActionsEventsDetailsSourceSignalEndpoint = ({ {signalEndpointName} - + ({ fontSize: theme.fontSizes.smallerBody, @@ -24,6 +25,9 @@ export const ProjectActionsFiltersCell = ({ return ( {filters.map( @@ -36,18 +40,33 @@ export const ProjectActionsFiltersCell = ({ value, values, }, - ]) => ( - - {parameter}{' '} - {inverted ? 'NOT' : ''} {operator}{' '} - {caseInsensitive - ? '(case insensitive)' - : ''}{' '} - - {values ? values.join(', ') : value} - - - ), + ]) => { + const operatorDescription: string = + formatOperatorDescription(operator); + + const operatorText = inverted ? ( + <> + is not{' '} + {operatorDescription.substring(2)} + + ) : ( + operatorDescription + ); + + return ( + + {parameter}{' '} + {operatorText} + {caseInsensitive + ? ' (case insensitive)' + : ''} + {': '} + + {values ? values.join(', ') : value} + + + ); + }, )} } diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/useProjectActionsForm.ts b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/useProjectActionsForm.ts index 93bcc186c49..6b0a75ac307 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/useProjectActionsForm.ts +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsForm/useProjectActionsForm.ts @@ -41,6 +41,7 @@ export const useProjectActionsForm = (action?: IActionSet) => { const [enabled, setEnabled] = useState(false); const [name, setName] = useState(''); + const [description, setDescription] = useState(''); const [sourceId, setSourceId] = useState(0); const [filters, setFilters] = useState([]); const [actorId, setActorId] = useState(0); @@ -49,6 +50,7 @@ export const useProjectActionsForm = (action?: IActionSet) => { const reloadForm = () => { setEnabled(action?.enabled ?? true); setName(action?.name || ''); + setDescription(action?.description || ''); setSourceId(action?.match?.sourceId ?? 0); setFilters( Object.entries(action?.match?.payload ?? {}).map( @@ -171,6 +173,8 @@ export const useProjectActionsForm = (action?: IActionSet) => { setEnabled, name, setName, + description, + setDescription, sourceId, setSourceId, filters, diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsModal.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsModal.tsx index 2c653cf86e5..0222b37aa7e 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsModal.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsModal/ProjectActionsModal.tsx @@ -69,6 +69,8 @@ export const ProjectActionsModal = ({ setEnabled, name, setName, + description, + setDescription, sourceId, setSourceId, filters, @@ -94,6 +96,7 @@ export const ProjectActionsModal = ({ const payload: ActionSetPayload = { enabled, name, + description, match: { source: 'signal-endpoint', sourceId, diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsSourceCell.tsx similarity index 53% rename from frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx rename to frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsSourceCell.tsx index 6a54cd1c776..87884c9f2e2 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTriggerCell.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsSourceCell.tsx @@ -31,43 +31,43 @@ const StyledLink = styled(Link)<{ }, })); -interface IProjectActionsTriggerCellProps { +interface IProjectActionsSourceCellProps { action: IActionSet; signalEndpoints: ISignalEndpoint[]; } -export const ProjectActionsTriggerCell = ({ +export const ProjectActionsSourceCell = ({ action, signalEndpoints, -}: IProjectActionsTriggerCellProps) => { +}: IProjectActionsSourceCellProps) => { const { sourceId, source } = action.match; - const trigger = signalEndpoints.find(({ id }) => id === sourceId); - if (!trigger) { - return No trigger; - } + if (source === 'signal-endpoint') { + const signalEndpoint = signalEndpoints.find( + ({ id }) => id === sourceId, + ); - const sourceIcon = - source === 'signal-endpoint' ? ( - - - - - - ) : null; + if (signalEndpoint) { + return ( + + + + + + + + + {signalEndpoint.name} + + + + ); + } + } - return ( - - - {sourceIcon} - - {trigger.name} - - - - ); + return No source; }; 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 b6effb2e940..8572b31b2d4 100644 --- a/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectActions/ProjectActionsTable/ProjectActionsTable.tsx @@ -13,10 +13,10 @@ 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 { ProjectActionsSourceCell } from './ProjectActionsSourceCell'; import { ProjectActionsFiltersCell } from './ProjectActionsFiltersCell'; import { ProjectActionsActorCell } from './ProjectActionsActorCell'; -import { ProjectActionsActionsCell } from './ProjectActionsActionsCell'; +import { ProjectActionsActionsCell } from './ProjectActionsActionsCell/ProjectActionsActionsCell'; import { ProjectActionsTableActionsCell } from './ProjectActionsTableActionsCell'; import { ProjectActionsModal } from './ProjectActionsModal/ProjectActionsModal'; import { ProjectActionsDeleteDialog } from './ProjectActionsDeleteDialog'; @@ -96,6 +96,7 @@ export const ProjectActionsTable = ({ }: { row: { original: IActionSet } }) => ( { setSelectedAction(action); setModalOpen(true); @@ -104,12 +105,12 @@ export const ProjectActionsTable = ({ ), }, { - id: 'trigger', - Header: 'Trigger', + id: 'source', + Header: 'Source', Cell: ({ row: { original: action }, }: { row: { original: IActionSet } }) => ( - diff --git a/frontend/src/interfaces/action.ts b/frontend/src/interfaces/action.ts index d6614be6399..b7be6709462 100644 --- a/frontend/src/interfaces/action.ts +++ b/frontend/src/interfaces/action.ts @@ -9,6 +9,7 @@ export interface IActionSet { id: number; enabled: boolean; name: string; + description: string; project: string; actorId: number; match: IMatch;