1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-02 01:17:58 +02:00
Nuno Góis 2024-03-05 11:33:34 +00:00 committed by GitHub
parent 454f44dec5
commit 86a795e87c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 163 additions and 53 deletions

View File

@ -3,6 +3,13 @@ import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { IActionSet } from 'interfaces/action'; import { IActionSet } from 'interfaces/action';
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; 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 }) => ({ const StyledActionItems = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -34,7 +41,8 @@ export const ProjectActionsActionsCell = ({
} }
return ( return (
<TextCell> <StyledCell>
<ProjectActionsLastEvent action={action} />
<TooltipLink <TooltipLink
tooltip={ tooltip={
<StyledActionItems> <StyledActionItems>
@ -60,6 +68,6 @@ export const ProjectActionsActionsCell = ({
? '1 action' ? '1 action'
: `${actions.length} actions`} : `${actions.length} actions`}
</TooltipLink> </TooltipLink>
</TextCell> </StyledCell>
); );
}; };

View File

@ -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' ? (
<StyledSuccessIcon />
) : actionSetEvent.state === 'failed' ? (
<StyledFailedIcon />
) : (
<CircularProgress size={20} />
);
return (
<StyledTooltipLink
tooltipProps={{
maxWidth: 500,
maxHeight: 600,
}}
tooltip={<ProjectActionsEventsDetails {...actionSetEvent} />}
>
{icon}
</StyledTooltipLink>
);
};

View File

@ -19,5 +19,11 @@ export const ProjectActionsActorCell = ({
return <TextCell>No service account</TextCell>; return <TextCell>No service account</TextCell>;
} }
return <LinkCell to='/admin/service-accounts'>{actor.name}</LinkCell>; return (
<LinkCell
to='/admin/service-accounts'
title={actor.name}
subtitle={actor.username}
/>
);
}; };

View File

@ -10,6 +10,10 @@ const StyledDetails = styled('div')(({ theme }) => ({
padding: theme.spacing(2), padding: theme.spacing(2),
})); }));
const StyledAlert = styled(Alert)({
fontSize: 'inherit',
});
export const ProjectActionsEventsDetails = ({ export const ProjectActionsEventsDetails = ({
state, state,
actionSet: { actions }, actionSet: { actions },
@ -24,9 +28,9 @@ export const ProjectActionsEventsDetails = ({
return ( return (
<StyledDetails> <StyledDetails>
<Alert severity={state === 'failed' ? 'error' : 'success'}> <StyledAlert severity={state === 'failed' ? 'error' : 'success'}>
{stateText} {stateText}
</Alert> </StyledAlert>
<ProjectActionsEventsDetailsSource signal={signal} /> <ProjectActionsEventsDetailsSource signal={signal} />
{actions.map((action, i) => ( {actions.map((action, i) => (
<ProjectActionsEventsDetailsAction <ProjectActionsEventsDetailsAction

View File

@ -44,6 +44,7 @@ export const StyledFailedIcon = styled(ErrorOutline)(({ theme }) => ({
const StyledAlert = styled(Alert)(({ theme }) => ({ const StyledAlert = styled(Alert)(({ theme }) => ({
marginTop: theme.spacing(2), marginTop: theme.spacing(2),
fontSize: 'inherit',
})); }));
const StyledDivider = styled(Divider)(({ theme }) => ({ const StyledDivider = styled(Divider)(({ theme }) => ({

View File

@ -24,6 +24,10 @@ const StyledAccordion = styled(Accordion)(({ theme }) => ({
}, },
})); }));
const StyledAccordionSummary = styled(AccordionSummary)({
lineHeight: '1.5rem',
});
const StyledLink = styled(Link)(({ theme }) => ({ const StyledLink = styled(Link)(({ theme }) => ({
marginLeft: theme.spacing(1), marginLeft: theme.spacing(1),
})); }));
@ -47,7 +51,7 @@ export const ProjectActionsEventsDetailsSourceSignalEndpoint = ({
return ( return (
<StyledAccordion> <StyledAccordion>
<AccordionSummary <StyledAccordionSummary
expandIcon={ expandIcon={
<IconButton> <IconButton>
<ExpandMore titleAccess='Toggle' /> <ExpandMore titleAccess='Toggle' />
@ -58,7 +62,7 @@ export const ProjectActionsEventsDetailsSourceSignalEndpoint = ({
<StyledLink to='/integrations/signals'> <StyledLink to='/integrations/signals'>
{signalEndpointName} {signalEndpointName}
</StyledLink> </StyledLink>
</AccordionSummary> </StyledAccordionSummary>
<AccordionDetails> <AccordionDetails>
<Suspense fallback={null}> <Suspense fallback={null}>
<LazyReactJSONEditor <LazyReactJSONEditor

View File

@ -2,6 +2,7 @@ import { styled, Typography } from '@mui/material';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { IActionSet } from 'interfaces/action'; import { IActionSet } from 'interfaces/action';
import { TooltipLink } from 'component/common/TooltipLink/TooltipLink'; import { TooltipLink } from 'component/common/TooltipLink/TooltipLink';
import { formatOperatorDescription } from 'component/common/NewConstraintAccordion/ConstraintOperator/formatOperatorDescription';
const StyledItem = styled(Typography)(({ theme }) => ({ const StyledItem = styled(Typography)(({ theme }) => ({
fontSize: theme.fontSizes.smallerBody, fontSize: theme.fontSizes.smallerBody,
@ -24,6 +25,9 @@ export const ProjectActionsFiltersCell = ({
return ( return (
<TextCell> <TextCell>
<TooltipLink <TooltipLink
tooltipProps={{
maxWidth: 500,
}}
tooltip={ tooltip={
<> <>
{filters.map( {filters.map(
@ -36,18 +40,33 @@ export const ProjectActionsFiltersCell = ({
value, value,
values, values,
}, },
]) => ( ]) => {
<StyledItem key={parameter}> const operatorDescription: string =
<strong>{parameter}</strong>{' '} formatOperatorDescription(operator);
{inverted ? 'NOT' : ''} {operator}{' '}
{caseInsensitive const operatorText = inverted ? (
? '(case insensitive)' <>
: ''}{' '} is <u>not</u>{' '}
<strong> {operatorDescription.substring(2)}
{values ? values.join(', ') : value} </>
</strong> ) : (
</StyledItem> operatorDescription
), );
return (
<StyledItem key={parameter}>
<strong>{parameter}</strong>{' '}
{operatorText}
{caseInsensitive
? ' (case insensitive)'
: ''}
{': '}
<strong>
{values ? values.join(', ') : value}
</strong>
</StyledItem>
);
},
)} )}
</> </>
} }

View File

@ -41,6 +41,7 @@ export const useProjectActionsForm = (action?: IActionSet) => {
const [enabled, setEnabled] = useState(false); const [enabled, setEnabled] = useState(false);
const [name, setName] = useState(''); const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [sourceId, setSourceId] = useState<number>(0); const [sourceId, setSourceId] = useState<number>(0);
const [filters, setFilters] = useState<ActionsFilterState[]>([]); const [filters, setFilters] = useState<ActionsFilterState[]>([]);
const [actorId, setActorId] = useState<number>(0); const [actorId, setActorId] = useState<number>(0);
@ -49,6 +50,7 @@ export const useProjectActionsForm = (action?: IActionSet) => {
const reloadForm = () => { const reloadForm = () => {
setEnabled(action?.enabled ?? true); setEnabled(action?.enabled ?? true);
setName(action?.name || ''); setName(action?.name || '');
setDescription(action?.description || '');
setSourceId(action?.match?.sourceId ?? 0); setSourceId(action?.match?.sourceId ?? 0);
setFilters( setFilters(
Object.entries(action?.match?.payload ?? {}).map( Object.entries(action?.match?.payload ?? {}).map(
@ -171,6 +173,8 @@ export const useProjectActionsForm = (action?: IActionSet) => {
setEnabled, setEnabled,
name, name,
setName, setName,
description,
setDescription,
sourceId, sourceId,
setSourceId, setSourceId,
filters, filters,

View File

@ -69,6 +69,8 @@ export const ProjectActionsModal = ({
setEnabled, setEnabled,
name, name,
setName, setName,
description,
setDescription,
sourceId, sourceId,
setSourceId, setSourceId,
filters, filters,
@ -94,6 +96,7 @@ export const ProjectActionsModal = ({
const payload: ActionSetPayload = { const payload: ActionSetPayload = {
enabled, enabled,
name, name,
description,
match: { match: {
source: 'signal-endpoint', source: 'signal-endpoint',
sourceId, sourceId,

View File

@ -31,43 +31,43 @@ const StyledLink = styled(Link)<{
}, },
})); }));
interface IProjectActionsTriggerCellProps { interface IProjectActionsSourceCellProps {
action: IActionSet; action: IActionSet;
signalEndpoints: ISignalEndpoint[]; signalEndpoints: ISignalEndpoint[];
} }
export const ProjectActionsTriggerCell = ({ export const ProjectActionsSourceCell = ({
action, action,
signalEndpoints, signalEndpoints,
}: IProjectActionsTriggerCellProps) => { }: IProjectActionsSourceCellProps) => {
const { sourceId, source } = action.match; const { sourceId, source } = action.match;
const trigger = signalEndpoints.find(({ id }) => id === sourceId);
if (!trigger) { if (source === 'signal-endpoint') {
return <TextCell>No trigger</TextCell>; const signalEndpoint = signalEndpoints.find(
({ id }) => id === sourceId,
);
if (signalEndpoint) {
return (
<TextCell>
<StyledCell>
<HtmlTooltip title='Signal endpoint' arrow>
<StyledIcon alt='Signal endpoint' variant='rounded'>
<SignalsIcon />
</StyledIcon>
</HtmlTooltip>
<StyledLink
component={RouterLink}
to='/integrations/signals'
underline='hover'
>
{signalEndpoint.name}
</StyledLink>
</StyledCell>
</TextCell>
);
}
} }
const sourceIcon = return <TextCell>No source</TextCell>;
source === 'signal-endpoint' ? (
<HtmlTooltip title='Signal endpoint' arrow>
<StyledIcon alt='Signal endpoint' variant='rounded'>
<SignalsIcon />
</StyledIcon>
</HtmlTooltip>
) : null;
return (
<TextCell>
<StyledCell>
{sourceIcon}
<StyledLink
component={RouterLink}
to='/integrations/signals'
underline='hover'
>
{trigger.name}
</StyledLink>
</StyledCell>
</TextCell>
);
}; };

View File

@ -13,10 +13,10 @@ import { useActions } from 'hooks/api/getters/useActions/useActions';
import { useActionsApi } from 'hooks/api/actions/useActionsApi/useActionsApi'; import { useActionsApi } from 'hooks/api/actions/useActionsApi/useActionsApi';
import { IActionSet } from 'interfaces/action'; import { IActionSet } from 'interfaces/action';
import { ToggleCell } from 'component/common/Table/cells/ToggleCell/ToggleCell'; import { ToggleCell } from 'component/common/Table/cells/ToggleCell/ToggleCell';
import { ProjectActionsTriggerCell } from './ProjectActionsTriggerCell'; import { ProjectActionsSourceCell } from './ProjectActionsSourceCell';
import { ProjectActionsFiltersCell } from './ProjectActionsFiltersCell'; import { ProjectActionsFiltersCell } from './ProjectActionsFiltersCell';
import { ProjectActionsActorCell } from './ProjectActionsActorCell'; import { ProjectActionsActorCell } from './ProjectActionsActorCell';
import { ProjectActionsActionsCell } from './ProjectActionsActionsCell'; import { ProjectActionsActionsCell } from './ProjectActionsActionsCell/ProjectActionsActionsCell';
import { ProjectActionsTableActionsCell } from './ProjectActionsTableActionsCell'; import { ProjectActionsTableActionsCell } from './ProjectActionsTableActionsCell';
import { ProjectActionsModal } from './ProjectActionsModal/ProjectActionsModal'; import { ProjectActionsModal } from './ProjectActionsModal/ProjectActionsModal';
import { ProjectActionsDeleteDialog } from './ProjectActionsDeleteDialog'; import { ProjectActionsDeleteDialog } from './ProjectActionsDeleteDialog';
@ -96,6 +96,7 @@ export const ProjectActionsTable = ({
}: { row: { original: IActionSet } }) => ( }: { row: { original: IActionSet } }) => (
<LinkCell <LinkCell
title={action.name} title={action.name}
subtitle={action.description}
onClick={() => { onClick={() => {
setSelectedAction(action); setSelectedAction(action);
setModalOpen(true); setModalOpen(true);
@ -104,12 +105,12 @@ export const ProjectActionsTable = ({
), ),
}, },
{ {
id: 'trigger', id: 'source',
Header: 'Trigger', Header: 'Source',
Cell: ({ Cell: ({
row: { original: action }, row: { original: action },
}: { row: { original: IActionSet } }) => ( }: { row: { original: IActionSet } }) => (
<ProjectActionsTriggerCell <ProjectActionsSourceCell
action={action} action={action}
signalEndpoints={signalEndpoints} signalEndpoints={signalEndpoints}
/> />

View File

@ -9,6 +9,7 @@ export interface IActionSet {
id: number; id: number;
enabled: boolean; enabled: boolean;
name: string; name: string;
description: string;
project: string; project: string;
actorId: number; actorId: number;
match: IMatch; match: IMatch;