diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageEntity.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageEntity.kt index 286961ab3..6b8fd8e10 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageEntity.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageEntity.kt @@ -1,8 +1,5 @@ package fr.gouv.cacem.monitorenv.domain.entities.vigilanceArea -import kotlinx.serialization.Serializable - -@Serializable data class ImageEntity( val id: Int? = null, val vigilanceAreaId: Int? = null, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageInputEntity.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/ImageDataInput.kt similarity index 65% rename from backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageInputEntity.kt rename to backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/ImageDataInput.kt index 56d93c998..238a0d205 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/domain/entities/vigilanceArea/ImageInputEntity.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/ImageDataInput.kt @@ -1,9 +1,9 @@ -package fr.gouv.cacem.monitorenv.domain.entities.vigilanceArea +package fr.gouv.cacem.monitorenv.infrastructure.api.adapters.bff.inputs.vigilanceArea import kotlinx.serialization.Serializable @Serializable -data class ImageInputEntity( +data class ImageDataInput( val id: Int? = null, val vigilanceAreaId: Int? = null, val name: String, diff --git a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/VigilanceAreaDataInput.kt b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/VigilanceAreaDataInput.kt index 152477c28..630951c4c 100644 --- a/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/VigilanceAreaDataInput.kt +++ b/backend/src/main/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/adapters/bff/inputs/vigilanceArea/VigilanceAreaDataInput.kt @@ -18,7 +18,7 @@ data class VigilanceAreaDataInput( val geom: MultiPolygon? = null, val isArchived: Boolean, val isDraft: Boolean, - val images: List? = listOf(), + val images: List? = listOf(), val links: List? = null, val linkedAMPs: List? = listOf(), val linkedRegulatoryAreas: List? = listOf(), @@ -44,8 +44,9 @@ data class VigilanceAreaDataInput( isArchived = this.isArchived, isDeleted = false, isDraft = this.isDraft, - images = this.images?.map { image -> - return@map ImageEntity( + images = + this.images?.map { image -> + ImageEntity( id = image.id, vigilanceAreaId = image.vigilanceAreaId, name = image.name, diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/GetVigilanceAreaByIdUTests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/GetVigilanceAreaByIdUTests.kt index 487576934..27dcd165d 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/GetVigilanceAreaByIdUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/GetVigilanceAreaByIdUTests.kt @@ -14,7 +14,7 @@ class GetVigilanceAreaByIdUTests { @Test fun `execute should return vigilance area entity`() { val vigilanceAreaId = 3 - val expectedEntity = VigilanceAreaFixture.aArchivedVigilanceAreaEntity() + val expectedEntity = VigilanceAreaFixture.anArchivedVigilanceAreaEntity() given(vigilanceAreaRepository.findById(vigilanceAreaId)).willReturn(expectedEntity) diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/fixtures/VigilanceAreaFixture.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/fixtures/VigilanceAreaFixture.kt index 18cbb38f6..60fc31477 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/fixtures/VigilanceAreaFixture.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/domain/use_cases/vigilanceArea/fixtures/VigilanceAreaFixture.kt @@ -83,7 +83,7 @@ class VigilanceAreaFixture { ) } - fun aArchivedVigilanceAreaEntity(): VigilanceAreaEntity { + fun anArchivedVigilanceAreaEntity(): VigilanceAreaEntity { return VigilanceAreaEntity( id = 3, comments = "Basic area comments", diff --git a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/v1/VigilanceAreasITests.kt b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/v1/VigilanceAreasITests.kt index 8aa10ae16..0c5eee5be 100644 --- a/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/v1/VigilanceAreasITests.kt +++ b/backend/src/test/kotlin/fr/gouv/cacem/monitorenv/infrastructure/api/endpoints/bff/v1/VigilanceAreasITests.kt @@ -8,6 +8,7 @@ import fr.gouv.cacem.monitorenv.domain.use_cases.vigilanceArea.CreateOrUpdateVig import fr.gouv.cacem.monitorenv.domain.use_cases.vigilanceArea.DeleteVigilanceArea import fr.gouv.cacem.monitorenv.domain.use_cases.vigilanceArea.GetVigilanceAreaById import fr.gouv.cacem.monitorenv.domain.use_cases.vigilanceArea.GetVigilanceAreas +import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.bff.inputs.vigilanceArea.ImageDataInput import fr.gouv.cacem.monitorenv.infrastructure.api.adapters.bff.inputs.vigilanceArea.VigilanceAreaDataInput import org.hamcrest.Matchers.equalTo import org.junit.jupiter.api.Test @@ -228,13 +229,13 @@ class VigilanceAreasITests { endDatePeriod = ZonedDateTime.parse("2024-08-08T23:59:59Z"), geom = polygon, images = listOf( - ImageInputEntity( + ImageDataInput( name = "image1.jpg", content = "AQID", mimeType = "image/jpeg", size = 1024, ), - ImageInputEntity( + ImageDataInput( name = "image2.png", content = "BAUG", mimeType = "image/png", diff --git a/frontend/src/features/InterestPoint/components/InterestPointMapButton.tsx b/frontend/src/features/InterestPoint/components/InterestPointMapButton.tsx index 1750e69d5..ea20f3f39 100644 --- a/frontend/src/features/InterestPoint/components/InterestPointMapButton.tsx +++ b/frontend/src/features/InterestPoint/components/InterestPointMapButton.tsx @@ -41,7 +41,7 @@ export function InterestPointMapButton() { close() }, [dispatch, close]) - useEscapeKey(cancel) + useEscapeKey({ onEscape: cancel }) const toggleInterestPointMenu = useCallback(() => { if (!isOpen) { diff --git a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/ImageViewer.tsx b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/ImageViewer.tsx index 9f7cea433..e9a0a990b 100644 --- a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/ImageViewer.tsx +++ b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/ImageViewer.tsx @@ -1,5 +1,6 @@ +import { useEscapeKey } from '@hooks/useEscapeKey' import { Accent, Icon, IconButton, THEME } from '@mtes-mct/monitor-ui' -import { useCallback, useEffect, useState } from 'react' +import { useCallback, useState } from 'react' import styled from 'styled-components' interface ImageViewerProps { @@ -22,34 +23,15 @@ export function ImageViewer({ currentIndex, images, onClose }: ImageViewerProps) [images.length, localCurrentIndex] ) - const handleKeyDown = useCallback( - (event: any) => { - if (event.key === 'Escape') { - onClose() - } - - if (event.key === 'ArrowLeft') { - changeImage(-1) - } - - if (event.key === 'ArrowRight') { - changeImage(1) - } - }, - [onClose, changeImage] - ) - - useEffect(() => { - document.addEventListener('keydown', handleKeyDown) - - return () => { - document.removeEventListener('keydown', handleKeyDown) - } - }, [handleKeyDown]) + useEscapeKey({ + onArrowLeft: () => changeImage(-1), + onArrowRight: () => changeImage(1), + onEscape: () => onClose() + }) return ( <> - + naturalHeight ? VigilanceArea.Orientation.LANDSCAPE @@ -177,19 +178,20 @@ export function PhotoUploaderWithRef(_, ref) { {imagesList && imagesList.map((image, index) => ( - - openImageViewer(index)} - src={image?.image} - width={ - image?.orientation === VigilanceArea.Orientation.LANDSCAPE - ? IMAGES_WIDTH_LANDSCAPE - : IMAGES_WIDTH_PORTRAIT - } - /> + // eslint-disable-next-line react/no-array-index-key + + openImageViewer(index)} type="button"> + {`${values.name}-${image.name}`} + img { + object-fit: cover; + } ` + +const StyledImageButton = styled.button` + cursor: zoom-in; + background: none; + border: none; + padding: 0px; +` + const StyledButton = styled(Button)` background-color: ${p => p.theme.color.white}; bottom: 4px; @@ -228,16 +247,10 @@ const StyledButton = styled(Button)` margin-right: 0px !important; } ` + const Text = styled.p<{ $hasError: boolean }>` color: ${p => (p.$hasError ? p.theme.color.maximumRed : p.theme.color.slateGray)}; font-style: italic; margin-bottom: 4px; margin-top: 4px; ` - -const PreviewImagesContainer = styled.div` - position: relative; - > img { - cursor: zoom-in; - } -` diff --git a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/VigilanceAreaPanel.tsx b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/VigilanceAreaPanel.tsx index 0c4d6ac88..79da169ae 100644 --- a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/VigilanceAreaPanel.tsx +++ b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/VigilanceAreaPanel.tsx @@ -16,7 +16,7 @@ import { AMPList } from './AddAMPs/AMPList' import { RegulatoryAreas } from './AddRegulatoryAreas/RegulatoryAreas' import { ImageViewer } from './ImageViewer' import { PublishedSchema } from './Schema' -import { DeleteButton, FooterContainer, FooterRightButtons } from './style' +import { DeleteButton, FooterContainer, FooterRightButtons, StyledImageButton } from './style' import { getImages } from './utils' const EMPTY_VALUE = '--' @@ -184,19 +184,19 @@ export function VigilanceAreaPanel({ vigilanceArea }: { vigilanceArea: Vigilance {imagesList.length > 0 && ( {imagesList.map((image, index) => ( - openImageViewer(index)} - src={image?.image} - width={ - image?.orientation === VigilanceArea.Orientation.LANDSCAPE - ? IMAGES_WIDTH_LANDSCAPE - : IMAGES_WIDTH_PORTRAIT - } - /> + // eslint-disable-next-line react/no-array-index-key + openImageViewer(index)} type="button"> + {`${values.name}-${image.name}`} + ))} )} @@ -285,7 +285,7 @@ const ImageContainer = styled.div` padding: 16px; border-bottom: 1px solid ${p => p.theme.color.lightGray}; > img { - cursor: zoom-in; + object-fit: cover; } ` diff --git a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/style.ts b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/style.ts index c93812bb5..01bb87b5b 100644 --- a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/style.ts +++ b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/style.ts @@ -53,3 +53,9 @@ export const ValidateButton = styled(Button)` border: 1px ${p => p.theme.color.mediumSeaGreen} solid; } ` +export const StyledImageButton = styled.button` + cursor: zoom-in; + background: none; + border: none; + padding: 0px; +` diff --git a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/utils.ts b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/utils.ts index a79db74d6..53d9c3574 100644 --- a/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/utils.ts +++ b/frontend/src/features/VigilanceArea/components/VigilanceAreaForm/utils.ts @@ -38,6 +38,7 @@ export async function getImages(images: VigilanceArea.ImagePropsForApi[]) { return { image: base64Image, + name: image.name, orientation: naturalWidth > naturalHeight ? VigilanceArea.Orientation.LANDSCAPE : VigilanceArea.Orientation.PORTRAIT } diff --git a/frontend/src/features/VigilanceArea/types.ts b/frontend/src/features/VigilanceArea/types.ts index b34fb51eb..f3bf36269 100644 --- a/frontend/src/features/VigilanceArea/types.ts +++ b/frontend/src/features/VigilanceArea/types.ts @@ -93,6 +93,7 @@ export namespace VigilanceArea { export type ImageForFrontProps = { id?: string image: string + name: string orientation: Orientation } diff --git a/frontend/src/features/map/tools/measurements/MeasurementMapButton.tsx b/frontend/src/features/map/tools/measurements/MeasurementMapButton.tsx index 0c8731308..e9b9b614b 100644 --- a/frontend/src/features/map/tools/measurements/MeasurementMapButton.tsx +++ b/frontend/src/features/map/tools/measurements/MeasurementMapButton.tsx @@ -30,9 +30,11 @@ export function MeasurementMapButton() { dispatch(globalActions.setIsMapToolVisible(undefined)) }) - useEscapeKey(() => { - dispatch(setMeasurementTypeToAdd(undefined)) - dispatch(globalActions.setIsMapToolVisible(undefined)) + useEscapeKey({ + onEscape: () => { + dispatch(setMeasurementTypeToAdd(undefined)) + dispatch(globalActions.setIsMapToolVisible(undefined)) + } }) useEffect(() => { diff --git a/frontend/src/hooks/useEscapeKey.ts b/frontend/src/hooks/useEscapeKey.ts index 10393528a..760a739d0 100644 --- a/frontend/src/hooks/useEscapeKey.ts +++ b/frontend/src/hooks/useEscapeKey.ts @@ -1,17 +1,30 @@ import { useEffect } from 'react' -export const useEscapeKey = (onEscape?: () => void) => { +type UseEscapeKeyProps = { + onArrowLeft?: () => void + onArrowRight?: () => void + onEscape?: () => void +} +export const useEscapeKey = ({ onArrowLeft, onArrowRight, onEscape }: UseEscapeKeyProps) => { useEffect(() => { - const escapeFromKeyboard = event => { + const handleKeyDown = event => { if (event.key === 'Escape' && onEscape) { onEscape() } + + if (event.key === 'ArrowLeft' && onArrowLeft) { + onArrowLeft() + } + + if (event.key === 'ArrowRight' && onArrowRight) { + onArrowRight() + } } - document.addEventListener('keydown', escapeFromKeyboard, false) + document.addEventListener('keydown', handleKeyDown, false) return () => { - document.removeEventListener('keydown', escapeFromKeyboard, false) + document.removeEventListener('keydown', handleKeyDown, false) } - }, [onEscape]) + }, [onEscape, onArrowLeft, onArrowRight]) }