Skip to content

Commit

Permalink
Frontend - timeline - show previous status for status
Browse files Browse the repository at this point in the history
  • Loading branch information
lwih committed Mar 1, 2024
1 parent 52ac504 commit 6202eae
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 74 deletions.
109 changes: 69 additions & 40 deletions frontend/src/pam/mission/timeline/item/timeline-item-status.test.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,88 @@
import { render, screen } from '../../../../test-utils.tsx'
import { Action } from "@sentry/react/types/types";
import {
ActionTypeEnum,
MissionSourceEnum
ActionTypeEnum,
MissionSourceEnum
} from "../../../../types/env-mission-types.ts";
import {
ActionStatusType,
ActionStatus as ActionStatusBaseType,
ActionStatusReason
ActionStatusType,
ActionStatus as ActionStatusBaseType,
ActionStatusReason
} from "../../../../types/action-types.ts";
import ActionStatus from "./timeline-item-status.tsx";


const actionMock = {
id: '1',
missionId: 1,
type: ActionTypeEnum.CONTROL,
source: MissionSourceEnum.RAPPORTNAV,
status: ActionStatusType.DOCKED,
startDateTimeUtc: '2022-01-01T00:00:00Z',
endDateTimeUtc: '2022-01-01T01:00:00Z',
summaryTags: undefined,
controlsToComplete: undefined,
data: {
id: '1',
missionId: 1,
type: ActionTypeEnum.CONTROL,
source: MissionSourceEnum.RAPPORTNAV,
status: ActionStatusType.DOCKED,
startDateTimeUtc: '2022-01-01T00:00:00Z',
endDateTimeUtc: '2022-01-01T01:00:00Z',
summaryTags: undefined,
controlsToComplete: undefined,
data: {
startDateTimeUtc: '2022-01-01T00:00:00Z',
endDateTimeUtc: '2022-01-01T01:00:00Z',
status: ActionStatusType.UNAVAILABLE,
reason: ActionStatusReason.TECHNICAL,
observations: 'obs'
} as any as ActionStatusBaseType
}
const previousActionMock = {
id: '1',
missionId: 1,
type: ActionTypeEnum.CONTROL,
source: MissionSourceEnum.RAPPORTNAV,
status: ActionStatusType.UNAVAILABLE,
reason: ActionStatusReason.TECHNICAL,
observations: 'obs'
} as any as ActionStatusBaseType
startDateTimeUtc: '2022-01-01T00:00:00Z',
endDateTimeUtc: '2022-01-01T01:00:00Z',
summaryTags: undefined,
controlsToComplete: undefined,
data: {
startDateTimeUtc: '2022-01-01T00:00:00Z',
endDateTimeUtc: '2022-01-01T01:00:00Z',
status: ActionStatusType.UNAVAILABLE,
reason: ActionStatusReason.TECHNICAL,
observations: 'obs'
} as any as ActionStatusBaseType
}

const props = (action: Action = actionMock, onClick = vi.fn()) => ({
action,
onClick
const props = (action: Action = actionMock, previousAction = null, onClick = vi.fn()) => ({
action,
previousActionWithSameType: previousAction,
onClick
})
describe('ActionStatus', () => {
test('should render', () => {
render(<ActionStatus {...props()} />);
expect(screen.getByText('Indisponibilité - début - Technique')).toBeInTheDocument();
});
test('should render observations', () => {
render(<ActionStatus {...props()} />);
expect(screen.getByText('- obs')).toBeInTheDocument();
});
test('should not render the reason when none', () => {
const mock = {...actionMock, data: {...actionMock.data, reason: undefined}}
render(<ActionStatus {...props(mock)} />);
expect(screen.queryByText('Indisponibilité - début - Technique')).toBeNull();
expect(screen.queryByText('Technique')).toBeNull();
});
test('should not render observations when none', () => {
const mock = {...actionMock, data: {...actionMock.data, observations: undefined}}
render(<ActionStatus {...props(mock)} />);
expect(screen.queryByText('- obs')).toBeNull();
});
test('should render', () => {
render(<ActionStatus {...props()} />);
expect(screen.getByText('Indisponibilité - début - Technique')).toBeInTheDocument();
});
test('should render observations', () => {
render(<ActionStatus {...props()} />);
expect(screen.getByText('- obs')).toBeInTheDocument();
});
test('should not render the reason when none', () => {
const mock = {...actionMock, data: {...actionMock.data, reason: undefined}}
render(<ActionStatus {...props(mock)} />);
expect(screen.queryByText('Indisponibilité - début - Technique')).toBeNull();
expect(screen.queryByText('Technique')).toBeNull();
});
test('should not render observations when none', () => {
const mock = {...actionMock, data: {...actionMock.data, observations: undefined}}
render(<ActionStatus {...props(mock)} />);
expect(screen.queryByText('- obs')).toBeNull();
});
test('should not render the previous status when not available', () => {
const mock = {...actionMock, data: {...actionMock.data, observations: undefined}}
render(<ActionStatus {...props(mock, null)} />);
expect(screen.queryByText('Indisponibilité - Technique - fin')).toBeNull();
});
test('should render the previous status when available', () => {
const mock = {...actionMock, data: {...actionMock.data, observations: undefined}}
render(<ActionStatus {...props(mock, previousActionMock)} />);
expect(screen.queryByText('Indisponibilité - Technique - fin')).toBeInTheDocument();
});

});
69 changes: 42 additions & 27 deletions frontend/src/pam/mission/timeline/item/timeline-item-status.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,59 @@
import React from 'react'
import React, { FC } from 'react'
import { Icon, THEME } from '@mtes-mct/monitor-ui'
import { Stack } from 'rsuite'
import { Action, ActionStatus as NavActionStatus } from '../../../../types/action-types'

Check warning on line 4 in frontend/src/pam/mission/timeline/item/timeline-item-status.tsx

View workflow job for this annotation

GitHub Actions / build-and-test-frontend

'Action' is defined but never used

Check warning on line 4 in frontend/src/pam/mission/timeline/item/timeline-item-status.tsx

View workflow job for this annotation

GitHub Actions / build-and-test-frontend

'Action' is defined but never used

Check warning on line 4 in frontend/src/pam/mission/timeline/item/timeline-item-status.tsx

View workflow job for this annotation

GitHub Actions / Frontend

'Action' is defined but never used
import { StatusColorTag } from '../../status/status-selection-dropdown'
import { mapStatusToText, statusReasonToHumanString } from '../../status/utils'
import Text from '../../../../ui/text'
import { useParams } from 'react-router-dom'
import { TimelineItemWrapper } from "./timeline-item.tsx";
import { MissionTimelineItemProps, TimelineItemWrapper } from "./timeline-item.tsx";

const ActionStatus: React.FC<{ action: Action; onClick: any }> = ({action, onClick}) => {
const ActionStatus: FC<MissionTimelineItemProps> = ({action, previousActionWithSameType, onClick}) => {
const {actionId} = useParams()
const isSelected = action.id === actionId
const actionData = action.data as unknown as NavActionStatus
const prevActionData = previousActionWithSameType?.data as unknown as NavActionStatus
return (
<TimelineItemWrapper onClick={onClick} borderWhenSelected={false}>
<Stack alignItems="center" spacing="0.5rem" style={{width: '100%'}}>
<Stack.Item>
<StatusColorTag status={actionData?.status}/>
</Stack.Item>
<Stack.Item style={{maxWidth: 'calc(100% - 3rem)'}}>
<Text
as="h3"
weight="normal"
color={isSelected ? THEME.color.charcoal : THEME.color.slateGray}
decoration={isSelected ? 'underline' : 'normal'}
style={{
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
<b>{`${mapStatusToText(actionData?.status)} - début${
!!actionData?.reason ? ' - ' + statusReasonToHumanString(actionData?.reason) : ''
}`}</b>
{!!actionData?.observations ? ' - ' + actionData?.observations : ''}
</Text>
</Stack.Item>
<Stack.Item>
<Icon.EditUnbordered size={20} color={THEME.color.slateGray}/>
<Stack direction={"column"} spacing={'0.2rem'} style={{padding: '0.2rem 0'}}>
<Stack.Item alignSelf={"flex-start"}>
<Stack alignItems="center" spacing="0.5rem" style={{width: '100%'}}>
<Stack.Item>
<StatusColorTag status={actionData?.status}/>
</Stack.Item>
<Stack.Item style={{maxWidth: 'calc(100% - 3rem)'}}>
<Text
as="h3"
weight="normal"
color={isSelected ? THEME.color.charcoal : THEME.color.slateGray}
decoration={isSelected ? 'underline' : 'normal'}
style={{
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
}}
>
<b>{`${mapStatusToText(actionData?.status)} - début${
!!actionData?.reason ? ' - ' + statusReasonToHumanString(actionData?.reason) : ''
}`}</b>
{!!actionData?.observations ? ' - ' + actionData?.observations : ''}
</Text>
</Stack.Item>
<Stack.Item>
<Icon.EditUnbordered size={20} color={THEME.color.slateGray}/>
</Stack.Item>
</Stack>
</Stack.Item>
{
!!prevActionData && (
<Stack.Item alignSelf={"flex-start"}>
<Text as={"h3"} color={THEME.color.slateGray} fontStyle={"italic"}>
{`${mapStatusToText(prevActionData?.status)} ${prevActionData?.reason ? `- ${statusReasonToHumanString(prevActionData?.reason)} ` : ''}- fin`}
</Text>
</Stack.Item>
)
}

</Stack>
</TimelineItemWrapper>
)
Expand Down
11 changes: 4 additions & 7 deletions frontend/src/pam/mission/timeline/item/timeline-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ActionNote from "./timeline-item-note.tsx";

export interface MissionTimelineItemProps {
action: Action
previousActionWithSameType?: Action
onClick: (action: Action) => void
}

Expand Down Expand Up @@ -64,19 +65,15 @@ const getActionComponent = (action: Action) => {
return null
}

const MissionTimelineItem: React.FC<MissionTimelineItemProps> = ({
action,
onClick
// componentMap = ActionComponentMap
}) => {
const Component = getActionComponent(action)
const MissionTimelineItem: React.FC<MissionTimelineItemProps> = (props: MissionTimelineItemProps) => {
const Component = getActionComponent(props.action)
// const Component = componentMap[action.actionType]

if (!Component) {
return null
}

return <Component action={action as any} onClick={onClick}/>
return <Component {...props}/>
}

export default MissionTimelineItem
7 changes: 7 additions & 0 deletions frontend/src/pam/mission/timeline/timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getColorForStatus } from '../status/utils'
import { ActionTypeEnum } from '../../../types/env-mission-types'
import { groupByDay } from '../utils'
import useGetMissionTimeline from "./use-mission-timeline.tsx";
import { find } from "lodash";

interface MissionTimelineProps {
missionId?: string
Expand Down Expand Up @@ -111,6 +112,12 @@ const MissionTimeline: React.FC<MissionTimelineProps> = ({missionId, onSelectAct
actionType={action.type as any}
>
<MissionTimelineItem action={action}
previousActionWithSameType={
find(
mission.actions,
{type: action.type},
mission.actions.findIndex(item => item === action) + 1
)}
onClick={() => onSelectAction(action)}/>
</MissionTimelineItemContainer>
</Stack.Item>
Expand Down

0 comments on commit 6202eae

Please sign in to comment.