diff --git a/Makefile b/Makefile index dd03523c4d..c804c47fcd 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ lint-back: run-back-for-puppeteer: run-stubbed-apis docker compose up -d --quiet-pull --wait db docker compose -f ./frontend/puppeteer/docker-compose.dev.yml up -d - cd backend && ./gradlew bootRun --args='--spring.profiles.active=puppeteer --spring.config.additional-location=$(INFRA_FOLDER)' + cd backend && MONITORENV_URL=http://localhost:8882 ./gradlew bootRun --args='--spring.profiles.active=local --spring.config.additional-location=$(INFRA_FOLDER)' run-front-for-puppeteer: cd ./frontend && npm run dev-puppeteer diff --git a/frontend/.env.example b/frontend/.env.example index 600e94ce7b..a54a7e9f4b 100644 --- a/frontend/.env.example +++ b/frontend/.env.example @@ -1,6 +1,5 @@ FRONTEND_GEOSERVER_LOCAL_URL= FRONTEND_GEOSERVER_REMOTE_URL= -FRONTEND_IS_DEV_ENV= FRONTEND_MAPBOX_KEY= FRONTEND_MONITORENV_URL= FRONTEND_OIDC_AUTHORITY= diff --git a/frontend/cypress/docker-compose.yml b/frontend/cypress/docker-compose.yml index 9d9d48421c..553d6735ab 100644 --- a/frontend/cypress/docker-compose.yml +++ b/frontend/cypress/docker-compose.yml @@ -36,7 +36,6 @@ services: - MONITORFISH_API_PROTECTED_API_KEY=APIKEY - FRONTEND_GEOSERVER_LOCAL_URL=http://0.0.0.0:8081 - FRONTEND_GEOSERVER_REMOTE_URL=http://0.0.0.0:8081 - - FRONTEND_IS_DEV_ENV=true - FRONTEND_MAPBOX_KEY=pk.eyJ1IjoibW9uaXRvcmZpc2giLCJhIjoiY2tsdHJ6dHhhMGZ0eDJ2bjhtZmJlOHJmZiJ9.bdi1cO-cUcZKXdkEkqAoZQ - FRONTEND_MONITORENV_URL=http://0.0.0.0:8081 - FRONTEND_OIDC_AUTHORITY=https://authentification.recette.din.developpement-durable.gouv.fr/authSAML/oidc/monitorfish diff --git a/frontend/package.json b/frontend/package.json index 71157488cf..63f50cf670 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,7 +15,7 @@ "build:local": "ENV_PROFILE=local npm run build", "cypress:open": "cypress open --browser firefox --config-file ./config/cypress.config.ts --e2e", "dev": "dotenv -e ../infra/configurations/frontend/.env.local vite --port 3000", - "dev-puppeteer": "dotenv -e ../infra/configurations/frontend/.env.puppeteer vite --port 3000", + "dev-puppeteer": "dotenv -e ../infra/configurations/frontend/.env.local -v FRONTEND_MONITORENV_URL=//localhost:8882 vite --port 3000", "bundle-sw": "esbuild src/workers/serviceWorker.ts --bundle --outfile=public/service-worker.js", "prepare": "cd .. && ./frontend/node_modules/.bin/husky install ./frontend/config/husky", "start": "vite preview --port 3000", diff --git a/frontend/puppeteer/docker-compose.yml b/frontend/puppeteer/docker-compose.yml index 602afb20c1..dcdacbd762 100644 --- a/frontend/puppeteer/docker-compose.yml +++ b/frontend/puppeteer/docker-compose.yml @@ -52,7 +52,6 @@ services: - MONITORFISH_API_PROTECTED_API_KEY=APIKEY - FRONTEND_GEOSERVER_LOCAL_URL=http://0.0.0.0:8081 - FRONTEND_GEOSERVER_REMOTE_URL=http://0.0.0.0:8081 - - FRONTEND_IS_DEV_ENV=true - FRONTEND_MAPBOX_KEY=pk.eyJ1IjoibW9uaXRvcmZpc2giLCJhIjoiY2tsdHJ6dHhhMGZ0eDJ2bjhtZmJlOHJmZiJ9.bdi1cO-cUcZKXdkEkqAoZQ - FRONTEND_MONITORENV_URL=http://0.0.0.0:8882 - FRONTEND_OIDC_AUTHORITY=https://authentification.recette.din.developpement-durable.gouv.fr/authSAML/oidc/monitorfish diff --git a/frontend/puppeteer/e2e/utils.ts b/frontend/puppeteer/e2e/utils.ts index 9a521887a8..37e938a006 100644 --- a/frontend/puppeteer/e2e/utils.ts +++ b/frontend/puppeteer/e2e/utils.ts @@ -1,6 +1,7 @@ import assert from 'assert' +import { Page, Browser } from 'puppeteer' -export function listenToConsole(page, index) { +export function listenToConsole(page: Page, index: number) { page .on('console', message => { const messageType = message.type().substr(0, 3).toUpperCase() @@ -23,32 +24,38 @@ export function listenToConsole(page, index) { }) } -export async function assertContains(page, selector, text) { +export async function assertContains(page: Page, selector: string, text: string) { + // TODO Remove ts-ignore when TS version is 4.9.3: + // @ts-ignore: https://github.com/puppeteer/puppeteer/issues/9369 const nodes = await page.$$eval(selector, elements => elements.map(element => element.textContent)) const node = nodes.find(content => content.includes(text)) assert.ok(node, `${selector} of value ${text} not found in array ${nodes}.`) } -export async function getTextContent(page, selector) { +export async function getTextContent(page: Page, selector: string) { const element = await page.waitForSelector(selector) - return element.evaluate(el => el.textContent) + return element && element.evaluate(el => el.textContent) } -export async function getInputContent(page, selector) { +export async function getInputContent(page: Page, selector: string) { const element = await page.waitForSelector(selector) - return element.evaluate(el => el.value) + // From Puppeteer doc: + // If you are using TypeScript, you may have to provide an explicit type to the first argument of the pageFunction. + // By default it is typed as Element[], but you may need to provide a more specific sub-type + // @ts-ignore + return element && element.evaluate((el: HTMLInputElement) => el.value) } -export async function getFirstTab(browser) { +export async function getFirstTab(browser: Browser) { const [firstTab] = await browser.pages() return firstTab } -export function wait(ms) { +export function wait(ms: number) { /* eslint-disable no-promise-executor-return */ return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/frontend/src/domain/entities/mission/index.ts b/frontend/src/domain/entities/mission/index.ts index cdd09d109c..65462d8005 100644 --- a/frontend/src/domain/entities/mission/index.ts +++ b/frontend/src/domain/entities/mission/index.ts @@ -103,7 +103,7 @@ export const getMissionFeatureZone = (mission: Mission.Mission | MissionMainForm } export const getMissionActionFeature = ( - action: MissionAction.MissionAction | (MissionActionFormValues & { missionId: number }) + action: MissionAction.MissionAction | MissionActionFormValues ): Feature | undefined => { if (!action.longitude || !action.latitude) { return undefined diff --git a/frontend/src/features/SideWindow/MissionForm/ActionList/Item.tsx b/frontend/src/features/SideWindow/MissionForm/ActionList/Item.tsx index 48bf73b71f..85cdfdc562 100644 --- a/frontend/src/features/SideWindow/MissionForm/ActionList/Item.tsx +++ b/frontend/src/features/SideWindow/MissionForm/ActionList/Item.tsx @@ -25,25 +25,25 @@ import type { Promisable } from 'type-fest' export type ItemProps = { isSelected: boolean + missionAction: MissionActionFormValues onDuplicate: () => Promisable onRemove: () => Promisable onSelect: () => Promisable - values: MissionActionFormValues } -export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: ItemProps) { +export function Item({ isSelected, missionAction, onDuplicate, onRemove, onSelect }: ItemProps) { const draft = useMainAppSelector(state => state.mission.draft) const natinfsAsOptions = useGetNatinfsAsOptions() const isControlAction = - values.actionType === MissionAction.MissionActionType.AIR_CONTROL || - values.actionType === MissionAction.MissionActionType.LAND_CONTROL || - values.actionType === MissionAction.MissionActionType.SEA_CONTROL + missionAction.actionType === MissionAction.MissionActionType.AIR_CONTROL || + missionAction.actionType === MissionAction.MissionActionType.LAND_CONTROL || + missionAction.actionType === MissionAction.MissionActionType.SEA_CONTROL const [actionLabel, ActionIcon] = useMemo(() => { - const vesselName = values.vesselName === UNKNOWN_VESSEL.vesselName ? 'INCONNU' : values.vesselName + const vesselName = missionAction.vesselName === UNKNOWN_VESSEL.vesselName ? 'INCONNU' : missionAction.vesselName - switch (values.actionType) { + switch (missionAction.actionType) { case MissionAction.MissionActionType.AIR_CONTROL: return [getActionTitle('Contrôle aérien', vesselName, '- Navire inconnu'), Icon.Plane] @@ -51,7 +51,9 @@ export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: It return [ getActionTitle( 'Surveillance aérienne', - values.numberOfVesselsFlownOver ? `${values.numberOfVesselsFlownOver} pistes survolées` : undefined, + missionAction.numberOfVesselsFlownOver + ? `${missionAction.numberOfVesselsFlownOver} pistes survolées` + : undefined, 'à renseigner' ), Icon.Observation @@ -61,7 +63,7 @@ export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: It return [getActionTitle('Contrôle à la débarque', vesselName, '- Navire inconnu'), Icon.Anchor] case MissionAction.MissionActionType.OBSERVATION: - return [getActionTitle('', values.otherComments, 'Note libre à renseigner'), Icon.Note] + return [getActionTitle('', missionAction.otherComments, 'Note libre à renseigner'), Icon.Note] case MissionAction.MissionActionType.SEA_CONTROL: return [getActionTitle('Contrôle en mer', vesselName, '- Navire inconnu'), Icon.FleetSegment] @@ -69,14 +71,14 @@ export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: It default: throw new FrontendError('`initialValues.actionType` does not match the enum') } - }, [values]) + }, [missionAction]) const infractionTags = useMemo(() => { - const allInfractions = getMissionActionInfractionsFromMissionActionFormValues(values, true) + const allInfractions = getMissionActionInfractionsFromMissionActionFormValues(missionAction, true) if (!allInfractions.length) { return [] } - const nonPendingInfractions = getMissionActionInfractionsFromMissionActionFormValues(values) + const nonPendingInfractions = getMissionActionInfractionsFromMissionActionFormValues(missionAction) const pendingInfractions = allInfractions.filter( ({ infractionType }) => infractionType === MissionAction.InfractionType.PENDING ) @@ -107,28 +109,28 @@ export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: It ) return [...infractionsRecapTags, infractionsTag] - }, [values, natinfsAsOptions]) + }, [missionAction, natinfsAsOptions]) const redTags = useMemo( () => [ - ...(values.hasSomeGearsSeized ? ['Appréhension engin'] : []), - ...(values.hasSomeSpeciesSeized ? ['Appréhension espèce'] : []), - ...(values.seizureAndDiversion ? ['Appréhension navire'] : []) + ...(missionAction.hasSomeGearsSeized ? ['Appréhension engin'] : []), + ...(missionAction.hasSomeSpeciesSeized ? ['Appréhension espèce'] : []), + ...(missionAction.seizureAndDiversion ? ['Appréhension navire'] : []) ].map(label => ( {label} )), - [values] + [missionAction] ) const startDateAsDayjs = useMemo( - () => values.actionDatetimeUtc && getLocalizedDayjs(values.actionDatetimeUtc), - [values] + () => missionAction.actionDatetimeUtc && getLocalizedDayjs(missionAction.actionDatetimeUtc), + [missionAction] ) - const isOpen = isControlAction && draft?.mainFormValues && !draft?.mainFormValues.isClosed && !values.closedBy + const isOpen = isControlAction && draft?.mainFormValues && !draft?.mainFormValues.isClosed && !missionAction.closedBy return ( <> @@ -144,7 +146,7 @@ export function Item({ isSelected, onDuplicate, onRemove, onSelect, values }: It - {!values.isValid && ( + {!missionAction.isValid && ( Veuillez compléter les champs manquants dans cette action de contrôle. )} diff --git a/frontend/src/features/SideWindow/MissionForm/ActionList/index.tsx b/frontend/src/features/SideWindow/MissionForm/ActionList/index.tsx index b5a9995ffd..d3eb56957d 100644 --- a/frontend/src/features/SideWindow/MissionForm/ActionList/index.tsx +++ b/frontend/src/features/SideWindow/MissionForm/ActionList/index.tsx @@ -74,10 +74,10 @@ export function ActionList({ // eslint-disable-next-line react/no-array-index-key key={index} isSelected={index === currentIndex} + missionAction={action} onDuplicate={() => onDuplicate(index)} onRemove={() => onRemove(index)} onSelect={() => onSelect(index)} - values={action} /> ))} diff --git a/frontend/src/features/SideWindow/MissionForm/MainForm/FormikSyncMissionFields.tsx b/frontend/src/features/SideWindow/MissionForm/MainForm/FormikSyncMissionFields.tsx index cd560d8b6e..2781b567ff 100644 --- a/frontend/src/features/SideWindow/MissionForm/MainForm/FormikSyncMissionFields.tsx +++ b/frontend/src/features/SideWindow/MissionForm/MainForm/FormikSyncMissionFields.tsx @@ -3,7 +3,8 @@ import { useFormikContext } from 'formik' import { omit } from 'lodash' import { useDeepCompareEffect } from '../../../../hooks/useDeepCompareEffect' -import { useListenMissionEventUpdatesById } from '../hooks/useListenMissionEventUpdatesById' +import { logInDev } from '../../../../utils/logInDev' +import { useListenToMissionEventUpdatesById } from '../hooks/useListenToMissionEventUpdatesById' import { MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM } from '../sse' import type { MissionMainFormValues } from '../types' @@ -16,34 +17,33 @@ type FormikSyncMissionFormProps = { */ export function FormikSyncMissionFields({ missionId }: FormikSyncMissionFormProps) { const { setFieldValue, values } = useFormikContext() - const receivedMission = useListenMissionEventUpdatesById(missionId) + const missionEvent = useListenToMissionEventUpdatesById(missionId) useDeepCompareEffect( () => { - if (!receivedMission) { + if (!missionEvent) { return } ;(async () => { const receivedDiff = diff( omit(values, MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM), - omit(receivedMission, MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM) + omit(missionEvent, MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM) ) /** * We iterate and use `setFieldValue` on each diff key to avoid a global re-render of the component */ Object.keys(receivedDiff).forEach(key => { - // eslint-disable-next-line no-console - console.log(`SSE: setting form key "${key}" to ${JSON.stringify(receivedMission[key])}`) - setFieldValue(key, receivedMission[key]) + logInDev(`SSE: setting form key "${key}" to ${JSON.stringify(missionEvent[key])}`) + setFieldValue(key, missionEvent[key]) }) })() }, // We don't want to trigger infinite re-renders since `setFieldValue` changes after each rendering // eslint-disable-next-line react-hooks/exhaustive-deps - [receivedMission] + [missionEvent] ) return <> diff --git a/frontend/src/features/SideWindow/MissionForm/MainForm/index.tsx b/frontend/src/features/SideWindow/MissionForm/MainForm/index.tsx index 88d4dd2fa8..5cc22e77bd 100644 --- a/frontend/src/features/SideWindow/MissionForm/MainForm/index.tsx +++ b/frontend/src/features/SideWindow/MissionForm/MainForm/index.tsx @@ -19,7 +19,7 @@ import { FormikMultiControlUnitPicker } from './FormikMultiControlUnitPicker' import { FormikSyncMissionFields } from './FormikSyncMissionFields' import { MainFormLiveSchema } from './schemas' import { BOOLEAN_AS_OPTIONS } from '../../../../constants' -import { useListenMissionEventUpdatesById } from '../hooks/useListenMissionEventUpdatesById' +import { useListenToMissionEventUpdatesById } from '../hooks/useListenToMissionEventUpdatesById' import { FormBody, FormBodyInnerWrapper } from '../shared/FormBody' import { FormHead } from '../shared/FormHead' @@ -32,7 +32,7 @@ type MainFormProps = { onChange: (nextValues: MissionMainFormValues) => Promisable } function UnmemoizedMainForm({ initialValues, missionId, onChange }: MainFormProps) { - const receivedMission = useListenMissionEventUpdatesById(missionId) + const missionEvent = useListenToMissionEventUpdatesById(missionId) function validateBeforeOnChange(validateForm) { return async nextValues => { @@ -46,7 +46,7 @@ function UnmemoizedMainForm({ initialValues, missionId, onChange }: MainFormProp // Prevent re-sending the form when receiving an update const nextValuesWithoutIsValid = omit(nextValues, ['isValid']) - if (isEqual(receivedMission, nextValuesWithoutIsValid)) { + if (isEqual(missionEvent, nextValuesWithoutIsValid)) { return } diff --git a/frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdatesById.ts b/frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdatesById.ts deleted file mode 100644 index 11d6911285..0000000000 --- a/frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdatesById.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { useContext, useMemo } from 'react' - -import { MissionEventContext } from '../../../../context/MissionEventContext' -import { usePreviousNotNull } from '../../../../hooks/usePreviousNotNull' - -import type { Mission } from '../../../../domain/entities/mission/types' - -export function useListenMissionEventUpdatesById(missionId: number | string | undefined) { - const missionEvent = useContext(MissionEventContext) - - const mission = useMemo(() => { - // @ts-ignore: `missionId` is verified with `Number.isInteger(missionId)` - if (!Number.isInteger(missionId) || missionEvent?.id !== missionId) { - return undefined - } - - return missionEvent as Mission.Mission - }, [missionEvent, missionId]) - - const previousMission = usePreviousNotNull(mission) - - return mission || previousMission -} diff --git a/frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdates.ts b/frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdates.ts similarity index 90% rename from frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdates.ts rename to frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdates.ts index b206c00ba2..c38f98a936 100644 --- a/frontend/src/features/SideWindow/MissionForm/hooks/useListenMissionEventUpdates.ts +++ b/frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdates.ts @@ -3,12 +3,13 @@ import { useEffect, useRef, useState } from 'react' import { MONITORENV_API_URL } from '../../../../api/api' import { Mission } from '../../../../domain/entities/mission/types' import { useMainAppSelector } from '../../../../hooks/useMainAppSelector' +import { logInDev } from '../../../../utils/logInDev' import { missionEventListener } from '../sse' const MISSION_UPDATES_URL = `${MONITORENV_API_URL}/api/v1/missions/sse` const MISSION_UPDATE_EVENT = `MISSION_UPDATE` -export function useListenMissionEventUpdates() { +export function useListenToMissionEventUpdates() { const isListeningToEvents = useMainAppSelector(state => state.mission.isListeningToEvents) const eventSourceRef = useRef() const [missionEvent, setMissionEvent] = useState() @@ -18,8 +19,7 @@ export function useListenMissionEventUpdates() { eventSourceRef.current = new EventSource(MISSION_UPDATES_URL) eventSourceRef.current?.addEventListener('open', () => { - // eslint-disable-next-line no-console - console.log(`SSE: Connected to missions endpoint.`) + logInDev(`SSE: Connected to missions endpoint.`) }) return () => { diff --git a/frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdatesById.ts b/frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdatesById.ts new file mode 100644 index 0000000000..e51339c01b --- /dev/null +++ b/frontend/src/features/SideWindow/MissionForm/hooks/useListenToMissionEventUpdatesById.ts @@ -0,0 +1,21 @@ +import { useContext, useMemo, useRef } from 'react' + +import { MissionEventContext } from '../../../../context/MissionEventContext' +import { Mission } from '../../../../domain/entities/mission/types' + +export function useListenToMissionEventUpdatesById(missionId: number | string | undefined) { + const missionEvent = useContext(MissionEventContext) + const previousMission = useRef() + + const mission = useMemo(() => { + if (!Number.isInteger(missionId) || !missionEvent || missionEvent.id !== missionId) { + return previousMission.current + } + + previousMission.current = missionEvent + + return missionEvent + }, [missionEvent, missionId]) + + return mission || previousMission.current +} diff --git a/frontend/src/features/SideWindow/MissionForm/index.tsx b/frontend/src/features/SideWindow/MissionForm/index.tsx index cbf810d7ba..12ad4d7bdd 100644 --- a/frontend/src/features/SideWindow/MissionForm/index.tsx +++ b/frontend/src/features/SideWindow/MissionForm/index.tsx @@ -17,7 +17,7 @@ import { useUpdateMissionMutation } from './apis' import { AUTO_SAVE_ENABLED } from './constants' -import { useListenMissionEventUpdatesById } from './hooks/useListenMissionEventUpdatesById' +import { useListenToMissionEventUpdatesById } from './hooks/useListenToMissionEventUpdatesById' import { useUpdateFreezedActionFormValues } from './hooks/useUpdateFreezedActionFormValues' import { MainForm } from './MainForm' import { AutoSaveTag } from './shared/AutoSaveTag' @@ -83,7 +83,7 @@ export function MissionForm() { const [deleteMissionAction, { isLoading: isDeletingMissionAction }] = useDeleteMissionActionMutation() const [updateMission, { isLoading: isUpdatingMission }] = useUpdateMissionMutation() const [updateMissionAction, { isLoading: isUpdatingMissionAction }] = useUpdateMissionActionMutation() - const missionEvent = useListenMissionEventUpdatesById(missionId) + const missionEvent = useListenToMissionEventUpdatesById(missionId) const isSaving = isCreatingMission || diff --git a/frontend/src/features/SideWindow/MissionForm/sse.ts b/frontend/src/features/SideWindow/MissionForm/sse.ts index 77635065c6..dacd2dcdb9 100644 --- a/frontend/src/features/SideWindow/MissionForm/sse.ts +++ b/frontend/src/features/SideWindow/MissionForm/sse.ts @@ -1,3 +1,5 @@ +import { logInDev } from '../../../utils/logInDev' + import type { Mission } from '../../../domain/entities/mission/types' export const MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM = [ @@ -14,12 +16,10 @@ export const MISSION_EVENT_UNSYNCHRONIZED_PROPERTIES_IN_FORM = [ export const missionEventListener = (callback: (mission: Mission.Mission) => void) => (event: MessageEvent) => { const mission = JSON.parse(event.data) as Mission.Mission - // eslint-disable-next-line no-console - console.log(`SSE: received a mission update.`) + logInDev(`SSE: received a mission update.`) if (import.meta.env.FRONTEND_MISSION_FORM_AUTO_UPDATE_ENABLED === 'false') { - // eslint-disable-next-line no-console - console.log( + logInDev( 'Skipping automatic update of mission form. ' + "Set 'FRONTEND_MISSION_FORM_AUTO_UPDATE_ENABLED=true' feature flag to activate this feature." ) diff --git a/frontend/src/features/SideWindow/MissionForm/types.ts b/frontend/src/features/SideWindow/MissionForm/types.ts index 383bbb6e40..1b585d0d8d 100644 --- a/frontend/src/features/SideWindow/MissionForm/types.ts +++ b/frontend/src/features/SideWindow/MissionForm/types.ts @@ -4,7 +4,7 @@ import type { MissionAction } from '../../../domain/types/missionAction' import type { PartialExcept } from '../../../types' export type MissionActionFormValues = PartialExcept< - Omit, + MissionAction.MissionActionData, 'actionType' | 'actionDatetimeUtc' > & { isValid: boolean diff --git a/frontend/src/features/SideWindow/index.tsx b/frontend/src/features/SideWindow/index.tsx index 6aeccae8c8..a9f98d8df9 100644 --- a/frontend/src/features/SideWindow/index.tsx +++ b/frontend/src/features/SideWindow/index.tsx @@ -16,7 +16,7 @@ import { Alert } from './Alert' import { BeaconMalfunctionBoard } from './BeaconMalfunctionBoard' import { Menu } from './Menu' import { MissionForm } from './MissionForm' -import { useListenMissionEventUpdates } from './MissionForm/hooks/useListenMissionEventUpdates' +import { useListenToMissionEventUpdates } from './MissionForm/hooks/useListenToMissionEventUpdates' import { MissionList } from './MissionList' import { MissionEventContext } from '../../context/MissionEventContext' import { SideWindowMenuKey } from '../../domain/entities/sideWindow/constants' @@ -46,7 +46,7 @@ export function SideWindow({ isFromURL }: SideWindowProps) { ) const editedReportingInSideWindow = useMainAppSelector(state => state.reporting.editedReportingInSideWindow) const selectedPath = useMainAppSelector(state => state.sideWindow.selectedPath) - const missionEvent = useListenMissionEventUpdates() + const missionEvent = useListenToMissionEventUpdates() const [isFirstRender, setIsFirstRender] = useState(true) const [isOverlayed, setIsOverlayed] = useState(false) diff --git a/frontend/src/hooks/usePreviousNotNull.ts b/frontend/src/hooks/usePreviousNotNull.ts deleted file mode 100644 index 17b6596ee1..0000000000 --- a/frontend/src/hooks/usePreviousNotNull.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useEffect, useRef } from 'react' - -export function usePreviousNotNull(value: T): T | undefined { - const ref = useRef() - - useEffect(() => { - if (value) { - ref.current = value - } - }, [value]) // Only re-run if value changes - - return ref.current -} diff --git a/frontend/src/utils/logInDev.ts b/frontend/src/utils/logInDev.ts new file mode 100644 index 0000000000..104a630006 --- /dev/null +++ b/frontend/src/utils/logInDev.ts @@ -0,0 +1,10 @@ +/** + * Log to console only in DEV + * @param text + */ +export function logInDev(text) { + if (import.meta.env.DEV) { + // eslint-disable-next-line no-console + console.log(text) + } +} diff --git a/infra/configurations/application-puppeteer.properties b/infra/configurations/application-puppeteer.properties deleted file mode 100644 index ad5737b6d8..0000000000 --- a/infra/configurations/application-puppeteer.properties +++ /dev/null @@ -1,30 +0,0 @@ -###################### -# Application settings -monitorfish.server.root=http://localhost:8880 -monitorfish.server.port=8880 -monitorfish.flyway.locations=classpath:/db/migration,classpath:/db/testdata -monitorfish.ajp.port=8000 -monitorfish.database.missionsActionsChunkSize=100 -host.ip=localhost:8880 -# Using local MonitorEnv instance: -monitorenv.url=http://localhost:8882 -spring.main.lazy-initialization=true -monitorfish.sentry.enabled=false -sentry.dsn= - -monitorfish.oidc.enabled=false -monitorfish.oidc.issuer-uri=https://authentification.recette.din.developpement-durable.gouv.fr/authSAML/oidc/monitorfish -monitorfish.oidc.userinfo-endpoint=/api/user - -monitorfish.api.protected.paths=/bff/*,/light/v1/vessels/* -# Super-user paths of type /** are not supported -monitorfish.api.protected.super-user-paths=/bff/v1/beacon_malfunctions,/bff/v1/missions,/bff/v1/operational_alerts,/bff/v1/reportings,/bff/v1/vessels/risk_factors -monitorfish.api.protected.public-paths=/api/v1/authorization/management/*,/api/v1/beacon_malfunctions/*,/api/v1/mission_actions/* -monitorfish.api.protected.api-key=DUMMY-API-KEY - -################### -# Database settings - -# Database used by the application (problem with upper case) -env.db.url=jdbc:postgresql://localhost:5432/monitorfishdb?user=postgres&password=postgres -env.db.driver-class-name=org.postgresql.Driver diff --git a/infra/configurations/frontend/.env.local b/infra/configurations/frontend/.env.local index 5b4a4661a0..595f1a98fa 100644 --- a/infra/configurations/frontend/.env.local +++ b/infra/configurations/frontend/.env.local @@ -1,6 +1,5 @@ FRONTEND_GEOSERVER_LOCAL_URL=//localhost:8081 FRONTEND_GEOSERVER_REMOTE_URL=//localhost:8081 -FRONTEND_IS_DEV_ENV=true FRONTEND_MAPBOX_KEY=pk.eyJ1IjoibW9uaXRvcmZpc2giLCJhIjoiY2tsdHJ6dHhhMGZ0eDJ2bjhtZmJlOHJmZiJ9.bdi1cO-cUcZKXdkEkqAoZQ FRONTEND_MONITORENV_URL=//localhost:8081 FRONTEND_OIDC_AUTHORITY=https://authentification.recette.din.developpement-durable.gouv.fr/authSAML/oidc/monitorfish diff --git a/infra/configurations/frontend/.env.puppeteer b/infra/configurations/frontend/.env.puppeteer deleted file mode 100644 index 3fbf2e4659..0000000000 --- a/infra/configurations/frontend/.env.puppeteer +++ /dev/null @@ -1,16 +0,0 @@ -FRONTEND_GEOSERVER_LOCAL_URL=//localhost:8081 -FRONTEND_GEOSERVER_REMOTE_URL=//localhost:8081 -FRONTEND_IS_DEV_ENV=true -FRONTEND_MAPBOX_KEY=pk.eyJ1IjoibW9uaXRvcmZpc2giLCJhIjoiY2tsdHJ6dHhhMGZ0eDJ2bjhtZmJlOHJmZiJ9.bdi1cO-cUcZKXdkEkqAoZQ -FRONTEND_MONITORENV_URL=//localhost:8882 -FRONTEND_OIDC_AUTHORITY=https://authentification.recette.din.developpement-durable.gouv.fr/authSAML/oidc/monitorfish -FRONTEND_OIDC_CLIENT_ID=monitorfish -FRONTEND_OIDC_ENABLED=false -FRONTEND_OIDC_REDIRECT_URI=https://monitorfish.din.developpement-durable.gouv.fr -FRONTEND_SENTRY_DSN=https://a5f3272efa794bb9ada2ffea90f2fec5@sentry.incubateur.net/8 -FRONTEND_SHOM_KEY=rg8ele7cft4ujkwjspsmtwas -FRONTEND_MISSION_FORM_AUTO_SAVE_ENABLED=true -FRONTEND_MISSION_FORM_AUTO_UPDATE_ENABLED=true -# We need to use a VITE_ env var to replace the HTML index file -# see: https://vitejs.dev/guide/env-and-mode.html#html-env-replacement -VITE_SMALL_CHAT_SNIPPET=