Skip to content

Commit

Permalink
[Layers] Add the option of displaying only the layer stroke or the fi…
Browse files Browse the repository at this point in the history
…lled layer
  • Loading branch information
claire2212 committed Dec 10, 2024
1 parent 0eb1457 commit de78ef8
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 75 deletions.
9 changes: 5 additions & 4 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"test:unit:watch": "npm run test:unit -- --watch"
},
"dependencies": {
"@mtes-mct/monitor-ui": "24.10.2",
"@mtes-mct/monitor-ui": "24.11.0",
"@react-pdf/renderer": "4.1.5",
"@reduxjs/toolkit": "2.4.0",
"@sentry/browser": "8.41.0",
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/domain/shared_slices/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import type { Coordinate } from 'ol/coordinate'
import type { Extent } from 'ol/extent'

type LayerType = {
id: number | undefined
id: number
isFilled: boolean
type: RegulatoryOrAMPOrViglanceAreaLayerType
}

type MapSliceStateType = {
coordinatesFormat: CoordinatesFormat
currentMapExtentTracker?: number[]
distanceUnit: DistanceUnit
excludedLayers?: LayerType[]
excludedLayers?: Omit<LayerType, 'isFilled'>[]
fitToExtent?: Extent
isAreaSelected: boolean
isolatedLayer: LayerType | undefined
Expand Down Expand Up @@ -85,7 +86,7 @@ const mapSlice = createSlice({
},
setIsolateMode(
state,
action: PayloadAction<{ excludedLayers: LayerType[]; isolatedLayer: LayerType | undefined }>
action: PayloadAction<{ excludedLayers: Omit<LayerType, 'isFilled'>[]; isolatedLayer: LayerType | undefined }>
) {
state.isolatedLayer = action.payload.isolatedLayer
state.excludedLayers = action.payload.excludedLayers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Fill, Stroke, Style } from 'ol/style'
import { Layers } from '../../../../domain/entities/layers/constants'
import { getColorWithAlpha, stringToColorInGroup } from '../../../../utils/utils'

const getStyle = (color: string, isSelected: boolean | undefined, isLayerFilled: boolean = false) =>
const getStyle = (color: string, isSelected: boolean | undefined, isLayerFilled: boolean = true) =>
new Style({
fill: new Fill({
color: isLayerFilled ? 'transparent' : getColorWithAlpha(color, 0.5)
color: isLayerFilled ? getColorWithAlpha(color, 0.5) : 'transparent'
}),
stroke: new Stroke({
color: getColorWithAlpha(THEME.color.rufous, 1),
Expand Down Expand Up @@ -35,11 +35,11 @@ export const getVigilanceAreaLayerStyle = feature => {
return getStyle(colorWithAlpha, feature.get('isSelected'))
}

export const getIsolatedVigilanceAreaLayerStyle = (feature, excludeLayerIds) => {
export const getIsolatedVigilanceAreaLayerStyle = (feature, excludeLayerIds, isFilled) => {
const isArchived = feature.get('isArchived')

const colorWithAlpha = getVigilanceAreaColorWithAlpha(feature.get('name'), feature.get('comments'), isArchived)
const isLayerFilled = excludeLayerIds.includes(feature.get('id'))
const isLayerFilled = !excludeLayerIds.includes(feature.get('id'))

return getStyle(colorWithAlpha, feature.get('isSelected'), isLayerFilled)
return getStyle(colorWithAlpha, feature.get('isSelected'), isLayerFilled && isFilled)
}
123 changes: 80 additions & 43 deletions frontend/src/features/layersSelector/overlays/OverlayContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export function OverlayContent({ items }: OverlayContentProps) {
const dispatch = useAppDispatch()

const isolatedLayer = useAppSelector(state => state.map.isolatedLayer)
const excludedLayers = useAppSelector(state => state.map.excludedLayers)

const { layerId, layerType } = useAppSelector(state => getDisplayedMetadataLayerIdAndType(state))
const selectedVigilanceAreaId = useAppSelector(state => state.vigilanceArea.selectedVigilanceAreaId)
Expand Down Expand Up @@ -117,7 +118,7 @@ export function OverlayContent({ items }: OverlayContentProps) {
dispatch(vigilanceAreaActions.addAmpIdsToVigilanceArea([id]))
}

const isolateLayer = (e, id, type) => {
const isolateLayer = (e, id: number, type: RegulatoryOrAMPOrViglanceAreaLayerType) => {
e.stopPropagation()

if (isolatedLayer?.id === id) {
Expand All @@ -128,11 +129,30 @@ export function OverlayContent({ items }: OverlayContentProps) {

const layerToIsolate = {
id,
isFilled: true,
type
}
const excludedLayers =
const newExcludedLayers =
items?.map(item => ({ id: item.properties.id, type: item.layerType })).filter(item => item.id !== id) ?? []
dispatch(mapActions.setIsolateMode({ excludedLayers, isolatedLayer: layerToIsolate }))
dispatch(mapActions.setIsolateMode({ excludedLayers: newExcludedLayers, isolatedLayer: layerToIsolate }))
}

const updateFillingMode = e => {
e.stopPropagation()

if (!isolatedLayer) {
return
}

dispatch(
mapActions.setIsolateMode({
excludedLayers: excludedLayers ?? [],
isolatedLayer: {
...isolatedLayer,
isFilled: !isolatedLayer.isFilled
}
})
)
}

return (
Expand Down Expand Up @@ -207,37 +227,51 @@ export function OverlayContent({ items }: OverlayContentProps) {
{getTitle(name) && (
<Name $isDisabled={isDisabled} title={getTitle(name)}>{` / ${getTitle(name)}`}</Name>
)}
{items.length > 1 && isVigilanceArea && (
<StyledTooltip Icon={Icon.Calendar}>{vigilanceAreaPeriod}</StyledTooltip>
)}
{items.length > 1 && (
<StyledIconButton
accent={Accent.TERTIARY}
color={isolatedLayer?.id === id ? THEME.color.blueGray : THEME.color.charcoal}
Icon={Icon.FocusZones}
onClick={e => isolateLayer(e, id, item.layerType)}
/>
)}
{isLinkingRegulatoryToVigilanceArea && isRegulatory && (
<IconButton
accent={Accent.TERTIARY}
disabled={regulatoryAreasToAdd.includes(id)}
Icon={Icon.Plus}
onClick={e => addRegulatoryToVigilanceArea(e, id)}
size={Size.SMALL}
title={`Ajouter la zone réglementaire ${name}`}
/>
)}
{isLinkingAmpToVigilanceArea && isAMP && (
<IconButton
accent={Accent.TERTIARY}
disabled={ampToAdd.includes(id)}
Icon={Icon.Plus}
onClick={e => addAMPToVigilanceArea(e, id)}
size={Size.SMALL}
title={`Ajouter l'AMP ${name}`}
/>
)}
<ButtonContainer>
{items.length > 1 && isVigilanceArea && <Tooltip Icon={Icon.Calendar}>{vigilanceAreaPeriod}</Tooltip>}
{items.length > 1 && (
<>
{isolatedLayer?.id === id && (
<StyledIconButton
accent={Accent.TERTIARY}
color={
isolatedLayer?.id === id && isolatedLayer?.isFilled
? THEME.color.charcoal
: THEME.color.blueGray
}
Icon={Icon.Stroke}
onClick={updateFillingMode}
/>
)}
<StyledIconButton
accent={Accent.TERTIARY}
color={isolatedLayer?.id === id ? THEME.color.blueGray : THEME.color.charcoal}
Icon={Icon.FocusZones}
onClick={e => isolateLayer(e, id, item.layerType)}
/>
</>
)}
{isLinkingRegulatoryToVigilanceArea && isRegulatory && (
<IconButton
accent={Accent.TERTIARY}
disabled={regulatoryAreasToAdd.includes(id)}
Icon={Icon.Plus}
onClick={e => addRegulatoryToVigilanceArea(e, id)}
size={Size.SMALL}
title={`Ajouter la zone réglementaire ${name}`}
/>
)}
{isLinkingAmpToVigilanceArea && isAMP && (
<IconButton
accent={Accent.TERTIARY}
disabled={ampToAdd.includes(id)}
Icon={Icon.Plus}
onClick={e => addAMPToVigilanceArea(e, id)}
size={Size.SMALL}
title={`Ajouter l'AMP ${name}`}
/>
)}
</ButtonContainer>
</Wrapper>
{items.length === 1 && isVigilanceArea && <Period>{vigilanceAreaPeriod}</Period>}
</LayerItem>
Expand Down Expand Up @@ -288,21 +322,24 @@ const Wrapper = styled.div`
display: flex;
align-items: center;
`

const ButtonContainer = styled.div`
display: flex;
gap: 12px;
line-height: 0;
margin-left: auto;
`
const Period = styled.span`
color: ${p => p.theme.color.slateGray};
font-size: 13px;
padding-left: 24px;
`

const StyledTooltip = styled(Tooltip)`
display: flex;
margin-left: auto;
`

const StyledIconButton = styled(IconButton)`
> svg {
height: 18px;
width: 18px;
padding: 0;
> span {
> svg {
height: 18px;
width: 18px;
}
}
`
10 changes: 5 additions & 5 deletions frontend/src/features/map/layers/AMP/AMPLayers.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Fill, Stroke, Style } from 'ol/style'
import { Layers } from '../../../../domain/entities/layers/constants'
import { getColorWithAlpha, stringToColorInGroup } from '../../../../utils/utils'

const getStyle = (color: string, metadataIsShowed: boolean | undefined, isLayerFilled: boolean = false) =>
const getStyle = (color: string, metadataIsShowed: boolean | undefined, isLayerFilled: boolean = true) =>
new Style({
fill: new Fill({
color: isLayerFilled ? 'transparent' : getColorWithAlpha(color, 0.7)
color: isLayerFilled ? getColorWithAlpha(color, 0.7) : 'transparent'
}),
stroke: new Stroke({
color: getColorWithAlpha(THEME.color.darkGoldenrod, 1),
Expand All @@ -31,9 +31,9 @@ export const getAMPLayerStyle = feature => {
return style
}

export const getIsolateAMPLayerStyle = (feature, excludeLayerIds) => {
export const getIsolateAMPLayerStyle = (feature, excludeLayerIds: number[], isFilled: boolean) => {
const colorWithAlpha = getAMPColorWithAlpha(feature.get('designation'), feature.get('name'))
const isLayerFilled = excludeLayerIds.includes(feature.get('id'))
const isLayerFilled = !excludeLayerIds.includes(feature.get('id'))

return getStyle(colorWithAlpha, feature.get('metadataIsShowed'), isLayerFilled)
return getStyle(colorWithAlpha, feature.get('metadataIsShowed'), isLayerFilled && isFilled)
}
20 changes: 11 additions & 9 deletions frontend/src/features/map/layers/IsolationLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ export function IsolationLayer({ map }: BaseMapChildrenProps) {
let regulatoryFeatures: Feature[] = []
if (regulatoryLayers?.entities) {
const isolatedLayerTypeIsRegulatory = (isolatedLayer?.type.search('REGULATORY') ?? -1) > -1
const regulatoryExcludedLayers = excludedLayers
?.filter(layer => layer.type.search('REGULATORY') > -1)
.map(layer => layer.id)
const regulatoryExcludedLayers =
excludedLayers?.filter(layer => layer.type.search('REGULATORY') > -1).map(layer => layer.id) ?? []

let featuresToDisplay = regulatoryExcludedLayers ?? []
if (isolatedLayerTypeIsRegulatory && isolatedLayer?.id) {
Expand All @@ -58,9 +57,11 @@ export function IsolationLayer({ map }: BaseMapChildrenProps) {
const layer = regulatorylayer ? regulatoryLayers.entities[regulatorylayer] : undefined
if (layer) {
const feature = getRegulatoryFeature({ code: Layers.REGULATORY_ENV.code, layer })
const featureIsFilled =
isolatedLayerTypeIsRegulatory && isolatedLayer?.id === regulatorylayer && isolatedLayer?.isFilled

if (feature) {
feature.setStyle(getIsolateRegulatoryLayerStyle(feature, regulatoryExcludedLayers))
feature.setStyle(getIsolateRegulatoryLayerStyle(feature, regulatoryExcludedLayers, featureIsFilled))
feats.push(feature)
}
}
Expand All @@ -77,9 +78,8 @@ export function IsolationLayer({ map }: BaseMapChildrenProps) {

if (ampLayers?.entities) {
const isolatedLayerTypeIsAmp = (isolatedLayer?.type.search('AMP') ?? -1) > -1
const ampExcludedLayers = excludedLayers
?.filter(layer => (layer.type.search('AMP') ?? -1) > -1)
.map(layer => layer.id)
const ampExcludedLayers =
excludedLayers?.filter(layer => (layer.type.search('AMP') ?? -1) > -1).map(layer => layer.id) ?? []
let featuresToDisplay = ampExcludedLayers ?? []
if (isolatedLayerTypeIsAmp && isolatedLayer?.id) {
featuresToDisplay = [...featuresToDisplay, isolatedLayer.id]
Expand All @@ -90,9 +90,10 @@ export function IsolationLayer({ map }: BaseMapChildrenProps) {

if (layer && layer.geom) {
const feature = getAMPFeature({ code: Layers.AMP_PREVIEW.code, layer })
const featureIsFilled = isolatedLayerTypeIsAmp && isolatedLayer?.id === id && isolatedLayer?.isFilled

if (feature) {
feature.setStyle(getIsolateAMPLayerStyle(feature, ampExcludedLayers))
feature.setStyle(getIsolateAMPLayerStyle(feature, ampExcludedLayers, featureIsFilled))
amplayers.push(feature)
}
}
Expand Down Expand Up @@ -121,8 +122,9 @@ export function IsolationLayer({ map }: BaseMapChildrenProps) {
const layer = id ? vigilanceAreas?.entities[id] : undefined
if (layer && layer.geom) {
const feature = getVigilanceAreaZoneFeature(layer, Layers.VIGILANCE_AREA.code)
const featureIsFilled = isolatedLayerIsVigilanceArea && isolatedLayer?.id === id && isolatedLayer?.isFilled
if (feature) {
feature.setStyle(getIsolatedVigilanceAreaLayerStyle(feature, vigilanceAreasExcludedLayers))
feature.setStyle(getIsolatedVigilanceAreaLayerStyle(feature, vigilanceAreasExcludedLayers, featureIsFilled))
vigilanceAreasLayers.push(feature)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ export const getRegulatoryLayerStyle = feature => {
return getStyle(colorWithAlpha, feature.get('metadataIsShowed'))
}

const getStyle = (color, metadataIsShowed, isLayerFilled = false) =>
const getStyle = (color, metadataIsShowed, isLayerFilled = true) =>
new Style({
fill: new Fill({
color: isLayerFilled ? 'transparent' : color
color: isLayerFilled ? color : 'transparent'
}),
stroke: new Stroke({
color: getColorWithAlpha(THEME.color.charcoal, 0.7),
Expand All @@ -202,9 +202,9 @@ export const getRegulatoryEnvColorWithAlpha = (
return getColorWithAlpha(stringToColorInGroup(`${type}`, `${name}`), 0.6)
}

export const getIsolateRegulatoryLayerStyle = (feature, excludeLayerIds) => {
export const getIsolateRegulatoryLayerStyle = (feature, excludeLayerIds: number[], isFilled: boolean) => {
const colorWithAlpha = getRegulatoryEnvColorWithAlpha(feature.get('thematique'), feature.get('entity_name'))
const isLayerFilled = excludeLayerIds.includes(feature.get('id'))
const isLayerFilled = !excludeLayerIds.includes(feature.get('id'))

return getStyle(colorWithAlpha, feature.get('metadataIsShowed'), isLayerFilled)
return getStyle(colorWithAlpha, feature.get('metadataIsShowed'), isLayerFilled && isFilled)
}

0 comments on commit de78ef8

Please sign in to comment.