Skip to content
Snippets Groups Projects

feat(layer-text): add transform interaction for layer text and delete functionality

All threads resolved!
@@ -9,19 +9,23 @@ import { JSX, useState } from 'react';
import { LayersDrawerImageItem } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component';
import { LayersDrawerTextItem } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component';
import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component';
import { removeLayerImage, updateLayerImageObject } from '@/redux/layers/layers.thunks';
import { layerDeleteImage, layerUpdateImage } from '@/redux/layers/layers.slice';
import {
removeLayerImage,
removeLayerText,
updateLayerImageObject,
} from '@/redux/layers/layers.thunks';
import { layerDeleteImage, layerDeleteText, layerUpdateImage } from '@/redux/layers/layers.slice';
import removeElementFromLayer from '@/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer';
import { showToast } from '@/utils/showToast';
import { SerializedError } from '@reduxjs/toolkit';
import { LayerImage } from '@/types/models';
import { LayerImage, LayerText } from '@/types/models';
import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
import { useMapInstance } from '@/utils/context/mapInstanceContext';
import { mapModelIdSelector } from '@/redux/map/map.selectors';
import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph';
import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement';
import { useSetBounds } from '@/utils/map/useSetBounds';
import { mapEditToolsLayerImageObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
import { usePointToProjection } from '@/utils/map/usePointToProjection';
import { Coordinate } from 'ol/coordinate';
import { openLayerImageObjectEditFactoryModal } from '@/redux/modal/modal.slice';
@@ -32,6 +36,19 @@ interface LayersDrawerObjectsListProps {
isLayerActive: boolean;
}
const removeObjectConfig = {
image: {
question: 'Are you sure you want to remove the image?',
successMessage: 'The layer image has been successfully removed',
errorMessage: 'An error occurred while removing the layer text',
},
text: {
question: 'Are you sure you want to remove the text?',
successMessage: 'The layer text has been successfully removed',
errorMessage: 'An error occurred while removing the layer text',
},
};
export const LayersDrawerObjectsList = ({
layerId,
isLayerVisible,
@@ -41,57 +58,81 @@ export const LayersDrawerObjectsList = ({
const highestZIndex = useAppSelector(highestZIndexSelector);
const lowestZIndex = useAppSelector(lowestZIndexSelector);
const layer = useAppSelector(state => layerByIdSelector(state, layerId));
const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerImageObjectSelector);
const [isImageRemoveModalOpen, setIsImageRemoveModalOpen] = useState(false);
const [layerImageToRemove, setLayerImageToRemove] = useState<LayerImage | null>(null);
const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector);
const [removeModalState, setRemoveModalState] = useState<undefined | 'text' | 'image'>(undefined);
const [layerObjectToRemove, setLayerObjectToRemove] = useState<LayerImage | LayerText | null>(
null,
);
const dispatch = useAppDispatch();
const setBounds = useSetBounds();
const pointToProjection = usePointToProjection();
const { mapInstance } = useMapInstance();
const removeImage = (layerImage: LayerImage): void => {
setLayerImageToRemove(layerImage);
setIsImageRemoveModalOpen(true);
const removeObject = (layerObject: LayerImage | LayerText): void => {
setLayerObjectToRemove(layerObject);
if ('glyph' in layerObject) {
setRemoveModalState('image');
} else {
setRemoveModalState('text');
}
};
const rejectImageRemove = (): void => {
setIsImageRemoveModalOpen(false);
const rejectRemove = (): void => {
setRemoveModalState(undefined);
};
const confirmImageRemove = async (): Promise<void> => {
if (!layerImageToRemove) {
const confirmRemove = async (): Promise<void> => {
if (!layerObjectToRemove || !removeModalState) {
return;
}
try {
await dispatch(
removeLayerImage({
modelId: currentModelId,
layerId: layerImageToRemove.layer,
imageId: layerImageToRemove.id,
}),
).unwrap();
dispatch(
layerDeleteImage({
modelId: currentModelId,
layerId: layerImageToRemove.layer,
imageId: layerImageToRemove.id,
}),
);
if (removeModalState === 'text') {
await dispatch(
removeLayerText({
modelId: currentModelId,
layerId: layerObjectToRemove.layer,
textId: layerObjectToRemove.id,
}),
).unwrap();
dispatch(
layerDeleteText({
modelId: currentModelId,
layerId: layerObjectToRemove.layer,
textId: layerObjectToRemove.id,
}),
);
} else {
await dispatch(
removeLayerImage({
modelId: currentModelId,
layerId: layerObjectToRemove.layer,
imageId: layerObjectToRemove.id,
}),
).unwrap();
dispatch(
layerDeleteImage({
modelId: currentModelId,
layerId: layerObjectToRemove.layer,
imageId: layerObjectToRemove.id,
}),
);
}
removeElementFromLayer({
mapInstance,
layerId: layerImageToRemove.layer,
featureId: layerImageToRemove.id,
layerId: layerObjectToRemove.layer,
featureId: layerObjectToRemove.id,
});
showToast({
type: 'success',
message: 'The layer image has been successfully removed',
message: removeObjectConfig[removeModalState].successMessage,
});
setIsImageRemoveModalOpen(false);
setRemoveModalState(undefined);
} catch (error) {
const typedError = error as SerializedError;
showToast({
type: 'error',
message: typedError.message || 'An error occurred while removing the layer image',
message: typedError.message || removeObjectConfig[removeModalState].errorMessage,
});
}
};
@@ -120,7 +161,7 @@ export const LayersDrawerObjectsList = ({
}),
);
dispatch(mapEditToolsSetLayerObject(newLayerImage));
updateGlyph(mapInstance, newLayerImage.layer, newLayerImage);
updateElement(mapInstance, newLayerImage.layer, newLayerImage);
}
};
@@ -132,12 +173,12 @@ export const LayersDrawerObjectsList = ({
await updateImageZIndex({ zIndex: lowestZIndex - 1, layerImage });
};
const centerObject = (layerImage: LayerImage): void => {
if (mapEditToolsLayerImageObject && mapEditToolsLayerImageObject.id === layerImage.id) {
const point1 = pointToProjection({ x: layerImage.x, y: layerImage.y });
const centerObject = (layerObject: LayerImage | LayerText): void => {
if (mapEditToolsLayerImageObject && mapEditToolsLayerImageObject.id === layerObject.id) {
const point1 = pointToProjection({ x: layerObject.x, y: layerObject.y });
const point2 = pointToProjection({
x: layerImage.x + layerImage.width,
y: layerImage.y + layerImage.height,
x: layerObject.x + layerObject.width,
y: layerObject.y + layerObject.height,
});
setBounds([point1, point2] as Coordinate[]);
}
@@ -154,13 +195,27 @@ export const LayersDrawerObjectsList = ({
return (
<div className={`${isLayerVisible ? 'opacity-100' : 'opacity-40'} flex flex-col gap-1 ps-3`}>
<QuestionModal
isOpen={isImageRemoveModalOpen}
onClose={rejectImageRemove}
onConfirm={confirmImageRemove}
question="Are you sure you want to remove the image?"
isOpen={Boolean(removeModalState)}
onClose={rejectRemove}
onConfirm={confirmRemove}
question={
removeModalState
? removeObjectConfig[removeModalState]?.question
: 'Are you sure you want to remove the object'
}
/>
{Object.values(layer.texts).map(layerText => (
<LayersDrawerTextItem layerText={layerText} key={layerText.id} />
<LayersDrawerTextItem
layerText={layerText}
key={layerText.id}
bringToFront={() => {}}
bringToBack={() => {}}
removeObject={() => removeObject(layerText)}
centerObject={() => centerObject(layerText)}
editObject={() => {}}
isLayerVisible={isLayerVisible}
isLayerActive={isLayerActive}
/>
))}
{Object.values(layer.images).map(layerImage => (
<LayersDrawerImageItem
@@ -168,7 +223,7 @@ export const LayersDrawerObjectsList = ({
key={layerImage.id}
bringToFront={() => bringImageToFront(layerImage)}
bringToBack={() => bringImageToBack(layerImage)}
removeObject={() => removeImage(layerImage)}
removeObject={() => removeObject(layerImage)}
centerObject={() => centerObject(layerImage)}
editObject={() => editImage()}
isLayerVisible={isLayerVisible}
Loading