diff --git a/backend/src/main/resources/db/testdata/V666.5__insert_dummy_missions.sql b/backend/src/main/resources/db/testdata/V666.5__insert_dummy_missions.sql index 7454cbcc4..f72fbdd19 100644 --- a/backend/src/main/resources/db/testdata/V666.5__insert_dummy_missions.sql +++ b/backend/src/main/resources/db/testdata/V666.5__insert_dummy_missions.sql @@ -101,7 +101,6 @@ VALUES ( 40, 10003), ( 41, 10002), ( 42, 10003), - ( 43, 10018), ( 44, 10003), ( 45, 10014), ( 46, 10018), @@ -118,7 +117,8 @@ VALUES ( 34, 10016, 'M. Capitaine Flame'), ( 34, 10017, 'Popeye 06789012345'), ( 47, 10002, 'A Team - Gimme your number'), - ( 25, 10002, 'Full contact'); + ( 25, 10002, 'Full contact'), + ( 43, 10018, 'Full contact'); INSERT INTO missions_control_resources (mission_id, control_resource_id) diff --git a/frontend/cypress/e2e/side_window/mission/close_mission_validation.spec.ts b/frontend/cypress/e2e/side_window/mission/close_mission_validation.spec.ts index d11e40546..1727c7940 100644 --- a/frontend/cypress/e2e/side_window/mission/close_mission_validation.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/close_mission_validation.spec.ts @@ -7,7 +7,7 @@ context('Mission', () => { it('A new mission with control and surveillance can be closed with all required values', () => { // Given cy.get('*[data-cy="add-mission"]').click() - cy.clickButton(' Enregistrer et clôturer') + cy.clickButton('Enregistrer et clôturer') cy.wait(100) cy.get('*[data-cy="mission-errors"]').should('exist') @@ -24,6 +24,7 @@ context('Mission', () => { cy.fill('Type de mission', ['Air']) cy.get('*[data-cy="add-control-unit"]').click() cy.get('.rs-picker-search-bar-input').type('Cross{enter}') + cy.fill("Contact de l'unité 1", 'contact').scrollIntoView() cy.fill('Ouvert par', 'PCF').scrollIntoView() cy.fill('Clôturé par', 'PCF').scrollIntoView() @@ -32,7 +33,7 @@ context('Mission', () => { // we add a control cy.clickButton('Ajouter') cy.clickButton('Ajouter des contrôles') - cy.clickButton(' Enregistrer et clôturer') + cy.clickButton('Enregistrer et clôturer') cy.wait(100) cy.get('*[data-cy="mission-errors"]').should('exist') @@ -80,6 +81,8 @@ context('Mission', () => { // delete theme to test error cy.fill('Thématique de surveillance', '') + cy.clickButton('Enregistrer et clôturer') + cy.wait(100) cy.get('*[data-cy="mission-errors"]').should('exist') cy.fill('Thématique de surveillance', 'Rejets illicites') 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 4a9dde27c..4d3f7f3d4 100644 --- a/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/create_mission.spec.ts @@ -7,7 +7,6 @@ context('Mission', () => { it('A mission should be created', () => { // Given cy.intercept('GET', '/bff/v1/missions*').as('getMissions') - cy.wait('@getMissions') cy.wait(400) cy.get('*[data-cy="Missions-numberOfDisplayedMissions"]').then($el => { const numberOfMissions = parseInt($el.text(), 10) @@ -44,7 +43,7 @@ context('Mission', () => { cy.get('[name="openBy"]').scrollIntoView().type('PCF') cy.intercept('PUT', '/bff/v1/missions').as('createMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@createMission').then(({ request, response }) => { @@ -72,7 +71,6 @@ context('Mission', () => { it('A mission should be deleted', () => { // Given cy.intercept('GET', '/bff/v1/missions*').as('getMissions') - cy.wait('@getMissions') cy.wait(400) cy.get('*[data-cy="Missions-numberOfDisplayedMissions"]').then($el => { const numberOfMissions = parseInt($el.text(), 10) @@ -111,7 +109,7 @@ context('Mission', () => { cy.get('*[data-cy="reopen-mission"]').click() cy.get('*[data-cy="control-unit-contact"]').type('Contact 012345') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ response }) => { @@ -125,14 +123,15 @@ context('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.intercept('PUT', '/bff/v1/missions/43').as('updateMission') + cy.fill("Contact de l'unité 1", '') + cy.wait(300) cy.clickButton('Enregistrer et clôturer') - // Then cy.wait('@updateMission').then(({ request, response }) => { expect(response && response.statusCode).equal(200) - expect(request.body.controlUnits[0].contact).equal(null) + expect(request.body.controlUnits[0].contact).equal(undefined) }) cy.get('*[data-cy="SideWindowHeader-title"]').contains('Missions et contrôles') }) diff --git a/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts b/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts index 247e7219d..82071478d 100644 --- a/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/mission_actions.spec.ts @@ -20,7 +20,7 @@ context('Mission actions', () => { cy.get('*[data-cy="duplicate-infraction"]').eq(1).should('be.disabled') cy.intercept('PUT', `/bff/v1/missions/34`).as('updateMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ request, response }) => { @@ -70,7 +70,7 @@ context('Mission actions', () => { cy.get('*[data-cy="envaction-add-theme"]').should('not.exist') cy.intercept('PUT', `/bff/v1/missions/34`).as('updateMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ request, response }) => { @@ -100,7 +100,7 @@ context('Mission actions', () => { }) cy.intercept('PUT', `/bff/v1/missions/34`).as('updateMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ request, response }) => { @@ -138,7 +138,7 @@ context('Mission actions', () => { cy.get('*[data-cy="envaction-protected-species-selector"]').should('have.length', 0) cy.intercept('PUT', `/bff/v1/missions/34`).as('updateMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ response }) => { diff --git a/frontend/cypress/e2e/side_window/mission/mission_dates_validation.spec.ts b/frontend/cypress/e2e/side_window/mission/mission_dates_validation.spec.ts index 9da3bb198..bcc18038a 100644 --- a/frontend/cypress/e2e/side_window/mission/mission_dates_validation.spec.ts +++ b/frontend/cypress/e2e/side_window/mission/mission_dates_validation.spec.ts @@ -223,7 +223,7 @@ context('Mission dates', () => { cy.fill('Equipement de sécurité et respect des normes', false) cy.intercept('PUT', `/bff/v1/missions/41`).as('updateMission') - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') // Then cy.wait('@updateMission').then(({ request, response }) => { @@ -249,6 +249,6 @@ context('Mission dates', () => { cy.fill('Respect du code de la navigation sur le plan d’eau', true) cy.fill('Gens de mer', true) cy.fill('Equipement de sécurité et respect des normes', true) - cy.get('form').submit() + cy.clickButton('Enregistrer et quitter') }) }) diff --git a/frontend/src/features/map/tools/measurements/CustomCircleRange.tsx b/frontend/src/features/map/tools/measurements/CustomCircleRange.tsx index 3467ab0ed..33bb6aa16 100644 --- a/frontend/src/features/map/tools/measurements/CustomCircleRange.tsx +++ b/frontend/src/features/map/tools/measurements/CustomCircleRange.tsx @@ -88,8 +88,12 @@ export function CustomCircleRange() { ) const addCustomCircleRange = useCallback( - (nextCoordinates, nextCircleRadius) => { - dispatch( + async (nextCoordinates, nextCircleRadius) => { + if (!nextCoordinates?.length || !nextCircleRadius?.length) { + return + } + + await dispatch( setCircleMeasurementToAdd({ circleCoordinatesToAdd: nextCoordinates, circleRadiusToAdd: nextCircleRadius @@ -100,6 +104,7 @@ export function CustomCircleRange() { const extent = transformExtent(boundingExtent([formattedCoordinates]), WSG84_PROJECTION, OPENLAYERS_PROJECTION) dispatch(setFitToExtent(extent)) dispatch(setMeasurementTypeToAdd(undefined)) + dispatch(resetCircleMeasurementInDrawing()) }, [dispatch] ) @@ -131,6 +136,7 @@ export function CustomCircleRange() {
addCustomCircleRange(circleCoordinates, circleRadius)} > OK diff --git a/frontend/src/features/missions/MissionForm/MissionForm.tsx b/frontend/src/features/missions/MissionForm/MissionForm.tsx index 53b54653e..361a46edd 100644 --- a/frontend/src/features/missions/MissionForm/MissionForm.tsx +++ b/frontend/src/features/missions/MissionForm/MissionForm.tsx @@ -25,11 +25,10 @@ import { useAppSelector } from '../../../hooks/useAppSelector' import { sideWindowActions } from '../../SideWindow/slice' import { missionFactory } from '../Missions.helpers' -export function MissionForm({ id, isAlreadyClosed, isNewMission, selectedMission, setShouldValidateOnChange }) { +export function MissionForm({ id, isNewMission, selectedMission, setShouldValidateOnChange }) { const dispatch = useAppDispatch() const { sideWindow } = useAppSelector(state => state) - const { dirty, handleSubmit, setFieldValue, setValues, validateForm, values } = - useFormikContext>() + const { dirty, setFieldValue, setValues, validateForm, values } = useFormikContext>() useSyncFormValuesWithRedux() useUpdateSurveillance() @@ -75,17 +74,12 @@ export function MissionForm({ id, isAlreadyClosed, isNewMission, selectedMission dispatch(sideWindowActions.setCurrentPath(generatePath(sideWindowPaths.MISSIONS))) } - const submitMission = async () => { + const submitMission = () => { setShouldValidateOnChange(false) - // If the mission is not already closed (from the API), we want the `isClosed` field to be set to false. - // if the user has already tried to close the mission and the `isClosed` field is set to true. - if (!isAlreadyClosed) { - await setFieldValue('isClosed', false) - } - validateForm().then(errors => { + validateForm({ ...values, isClosed: false }).then(errors => { if (_.isEmpty(errors)) { - handleSubmit() + dispatch(saveMission({ ...values, isClosed: true })) return } @@ -93,27 +87,27 @@ export function MissionForm({ id, isAlreadyClosed, isNewMission, selectedMission }) } - const closeMission = async () => { - await setFieldValue('isClosed', true) - validateForm().then(errors => { + const closeMission = () => { + validateForm({ ...values, isClosed: true }).then(errors => { if (_.isEmpty(errors)) { - handleSubmit() - } else { - setShouldValidateOnChange(true) + dispatch(saveMission({ ...values, isClosed: true })) + + return } + setShouldValidateOnChange(true) }) } const reopenMission = () => { validateForm({ ...values, isClosed: false }).then(errors => { if (_.isEmpty(errors)) { + setFieldValue('isClosed', false) if (dirty) { return setIsReopenModalOpen(true) } return validateReopenMission() } - setFieldValue('isClosed', true) return setShouldValidateOnChange(true) }) diff --git a/frontend/src/features/missions/MissionForm/formikUseCases/updateActionThemes.ts b/frontend/src/features/missions/MissionForm/formikUseCases/updateActionThemes.ts index 4dd6d0171..8e0da4a88 100644 --- a/frontend/src/features/missions/MissionForm/formikUseCases/updateActionThemes.ts +++ b/frontend/src/features/missions/MissionForm/formikUseCases/updateActionThemes.ts @@ -16,8 +16,11 @@ export const updateTheme = export const updateSubThemes = (setFieldValue: (field: string, value: any) => void) => (value: string, actionIndex: number, themeIndex: number) => { const subThemesPath = `envActions[${actionIndex}].themes.${themeIndex}.subThemes` - + const protectedSpeciesPath = `envActions[${actionIndex}].themes.${themeIndex}.protectedSpecies` setFieldValue(subThemesPath, value) + if (!value || value?.length === 0) { + setFieldValue(protectedSpeciesPath, value) + } } export const updateProtectedSpecies = (setFieldValue: (field: string, value: any) => void) => (value: string, actionIndex: number, themeIndex: number) => { diff --git a/frontend/src/features/missions/MissionForm/index.tsx b/frontend/src/features/missions/MissionForm/index.tsx index fb5824f4a..f177aa68a 100644 --- a/frontend/src/features/missions/MissionForm/index.tsx +++ b/frontend/src/features/missions/MissionForm/index.tsx @@ -1,13 +1,12 @@ import { skipToken } from '@reduxjs/toolkit/dist/query' import { Formik } from 'formik' +import { noop } from 'lodash' import { useMemo, useState } from 'react' import styled from 'styled-components' import { MissionForm } from './MissionForm' import { MissionSchema } from './Schemas' import { useGetMissionQuery } from '../../../api/missionsAPI' -import { saveMission } from '../../../domain/use_cases/missions/saveMission' -import { useAppDispatch } from '../../../hooks/useAppDispatch' import { useAppSelector } from '../../../hooks/useAppSelector' import { FormikForm } from '../../../uiMonitor/CustomFormikFields/FormikForm' import { getIdTyped } from '../../../utils/getIdTyped' @@ -20,7 +19,6 @@ export function Mission() { multiMissions: { selectedMissions }, sideWindow } = useAppSelector(state => state) - const dispatch = useAppDispatch() const [shouldValidateOnChange, setShouldValidateOnChange] = useState(false) const routeParams = getMissionPageRoute(sideWindow.currentPath) @@ -44,10 +42,6 @@ export function Mission() { return missionFactory(missionToEdit) }, [idTyped, missionIsNewMission, missionToEdit]) - const handleSubmitForm = values => { - dispatch(saveMission(values)) - } - if (isLoading) { return
Chargement en cours
} @@ -58,7 +52,7 @@ export function Mission() { key={idTyped} enableReinitialize initialValues={missionFormikValues} - onSubmit={handleSubmitForm} + onSubmit={noop} validateOnBlur={false} validateOnChange={shouldValidateOnChange} validateOnMount={false} @@ -67,7 +61,6 @@ export function Mission() { { - const totalInfractions = infractions.length || 0 + const totalInfractions = infractions?.length || 0 const ras = (actionNumberOfControls || 0) - totalInfractions const infractionsWithReport = infractions?.filter(inf => inf.infractionType === InfractionTypeEnum.WITH_REPORT)?.length || 0