From f5581ac6077236d1fecfae3a7d06ba2e4024ee1e Mon Sep 17 00:00:00 2001 From: Loup Theron Date: Thu, 12 Oct 2023 17:56:00 +0200 Subject: [PATCH] Add warning message when control unit is engaged --- .../mission/create_mission.spec.ts | 9 ++++ frontend/package-lock.json | 54 +++++++++++++++++-- frontend/package.json | 4 +- frontend/src/api/missionsAPI.ts | 13 +++++ .../MissionForm/ControlUnitSelector.tsx | 13 ++++- .../missions/MissionForm/ControlUnitsForm.tsx | 15 +++++- 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts b/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts index ec27afde9..e91de3afb 100644 --- a/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts @@ -149,4 +149,13 @@ context('Mission', () => { // Then cy.get('*[data-cy="delete-mission"]').should('be.disabled') }) + + it('A warning should be displayed When a control unit is already engaged in a mission ', () => { + // Given + cy.wait(200) + cy.get('*[data-cy="edit-mission-43"]').click({ force: true }) + cy.intercept('PUT', `/bff/v1/missions/43`).as('updateMission') + + cy.get('body').contains('Cette unité est actuellement sélectionnée dans une autre mission en cours.') + }) }) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 4b1a18b4d..f040b981d 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,7 +9,9 @@ "version": "0.1.0", "license": "AGPL-3.0", "dependencies": { - "@mtes-mct/monitor-ui": "10.1.1", + "@dnd-kit/core": "^4.0.3", + "@dnd-kit/modifiers": "^4.0.0", + "@mtes-mct/monitor-ui": "10.4.0", "@reduxjs/toolkit": "1.9.5", "@rsuite/responsive-nav": "5.0.1", "@sentry/browser": "7.73.0", @@ -2367,6 +2369,50 @@ "node": ">=10.0.0" } }, + "node_modules/@dnd-kit/accessibility": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/core": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.0.0", + "@dnd-kit/utilities": "^3.0.1", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@dnd-kit/modifiers": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.0.0", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^4.0.0" + } + }, + "node_modules/@dnd-kit/utilities": { + "version": "3.2.0", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/@emotion/is-prop-valid": { "version": "1.2.0", "license": "MIT", @@ -5053,9 +5099,9 @@ } }, "node_modules/@mtes-mct/monitor-ui": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-10.1.1.tgz", - "integrity": "sha512-9guDaraFHXQyUJRMEkkm+ML5wD4bdPv7qnbubj7fLmaK/4GPmOMVy6ArqzPxfFOIAw+UO06X5Wr7iY6/bkrrcw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-10.4.0.tgz", + "integrity": "sha512-JOT6aCOVwA3cPGVKaaGxP3qgx8gLRUmSSPDImmqCCsz0JtvLpG08j5nmoy+EahYhgQ2RpVfZApNFH06DI2rFSw==", "dependencies": { "@babel/runtime": "7.22.15", "@tanstack/react-table": "8.9.7", diff --git a/frontend/package.json b/frontend/package.json index 2d9d6af20..332910551 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,7 +31,9 @@ "test:unit:watch": "npm run test:unit -- --watch" }, "dependencies": { - "@mtes-mct/monitor-ui": "10.1.1", + "@dnd-kit/core": "^4.0.3", + "@dnd-kit/modifiers": "^4.0.0", + "@mtes-mct/monitor-ui": "10.4.0", "@reduxjs/toolkit": "1.9.5", "@rsuite/responsive-nav": "5.0.1", "@sentry/browser": "7.73.0", diff --git a/frontend/src/api/missionsAPI.ts b/frontend/src/api/missionsAPI.ts index 72eb46e58..b542872d1 100644 --- a/frontend/src/api/missionsAPI.ts +++ b/frontend/src/api/missionsAPI.ts @@ -1,5 +1,8 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' +import { monitorenvPublicApi } from './api' +import { ControlUnit } from '../domain/entities/controlUnit' + import type { Mission } from '../domain/entities/missions' type MissionsResponse = Mission[] @@ -83,6 +86,14 @@ export const missionsAPI = createApi({ tagTypes: ['Missions'] }) +export const publicMissionsAPI = monitorenvPublicApi.injectEndpoints({ + endpoints: builder => ({ + getEngagedControlUnits: builder.query({ + query: () => `/v1/missions/engaged_control_units` + }) + }) +}) + export const { useCreateMissionMutation, useDeleteMissionMutation, @@ -90,3 +101,5 @@ export const { useGetMissionsQuery, useUpdateMissionMutation } = missionsAPI + +export const { useGetEngagedControlUnitsQuery } = publicMissionsAPI diff --git a/frontend/src/features/missions/MissionForm/ControlUnitSelector.tsx b/frontend/src/features/missions/MissionForm/ControlUnitSelector.tsx index f40bd8e89..b6e66b75e 100644 --- a/frontend/src/features/missions/MissionForm/ControlUnitSelector.tsx +++ b/frontend/src/features/missions/MissionForm/ControlUnitSelector.tsx @@ -1,5 +1,5 @@ /* eslint-disable react/jsx-props-no-spreading */ -import { FieldError, FormikTextInput } from '@mtes-mct/monitor-ui' +import { FormikTextInput, FieldError, Message, Level } from '@mtes-mct/monitor-ui' import { useField } from 'formik' import _ from 'lodash' import { type MutableRefObject, useMemo, useRef } from 'react' @@ -13,7 +13,7 @@ import { ReactComponent as DeleteSVG } from '../../../uiMonitor/icons/Delete.svg import type { ControlUnit } from '../../../domain/entities/controlUnit' -export function ControlUnitSelector({ controlUnitIndex, controlUnitPath, removeControlUnit, ...props }) { +export function ControlUnitSelector({ controlUnitIndex, controlUnitPath, isEngaged, removeControlUnit, ...props }) { const [administrationField, administrationMeta, administrationHelpers] = useField( `controlUnits.${controlUnitIndex}.administration` ) @@ -138,6 +138,11 @@ export function ControlUnitSelector({ controlUnitIndex, controlUnitPath, removeC /> {unitNameMeta.error && {unitNameMeta.error}} + {isEngaged && ( + + Cette unité est actuellement sélectionnée dans une autre mission en cours. + + )} @@ -169,6 +174,10 @@ export function ControlUnitSelector({ controlUnitIndex, controlUnitPath, removeC ) } +const StyledMessage = styled(Message)` + margin-top: 8px; +` + const RessourceUnitWrapper = styled.div` margin-bottom: 14px; display: flex; diff --git a/frontend/src/features/missions/MissionForm/ControlUnitsForm.tsx b/frontend/src/features/missions/MissionForm/ControlUnitsForm.tsx index 24f9b3743..490afdc80 100644 --- a/frontend/src/features/missions/MissionForm/ControlUnitsForm.tsx +++ b/frontend/src/features/missions/MissionForm/ControlUnitsForm.tsx @@ -1,9 +1,21 @@ import { Accent, Button, Icon, Size } from '@mtes-mct/monitor-ui' +import { useMemo } from 'react' import { ControlUnitSelector } from './ControlUnitSelector' +import { useGetEngagedControlUnitsQuery } from '../../../api/missionsAPI' import { controlUnitFactory } from '../Missions.helpers' export function ControlUnitsForm({ form, push, remove }) { + const { data: engagedControlUnitsData } = useGetEngagedControlUnitsQuery(undefined) + + const engagedControlUnits = useMemo(() => { + if (!engagedControlUnitsData) { + return [] + } + + return engagedControlUnitsData + }, [engagedControlUnitsData]) + const handleAddControlUnit = () => { push(controlUnitFactory()) } @@ -16,12 +28,13 @@ export function ControlUnitsForm({ form, push, remove }) {
{form?.values.controlUnits?.length > 0 && ( <> - {form.values.controlUnits.map((_, index) => ( + {form.values.controlUnits.map(({ id }, index) => ( engaged.id === id)} removeControlUnit={handleRemoveControlUnit(index)} /> ))}