diff --git a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx index b806d2b6a77e07a288e39d87c591d5f8ebb1ad43..31c052b83813e4d001fae67e986100dbeef97947 100644 --- a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx @@ -75,13 +75,13 @@ export const LayerFactoryModal: React.FC = () => { await dispatch(updateLayer(payload)).unwrap(); showToast({ type: 'success', - message: 'The layer has been successfully updated', + message: 'The layer has been successfully updated.', }); } else { await dispatch(addLayerForModel(data)).unwrap(); showToast({ type: 'success', - message: 'A new layer has been successfully added', + message: 'A new layer has been successfully added.', }); } dispatch(closeModal()); diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx index 6031faa826b4c6d1f58d868f843351dc7eefc38c..4272ddd85964b5e7617b783e422c500329816022 100644 --- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx @@ -179,7 +179,7 @@ describe('LayerImageObjectEditFactoryModal - component', () => { }); expect(showToast).toHaveBeenCalledWith({ - message: 'The image has been successfully updated', + message: 'The image has been successfully updated.', type: 'success', }); }); diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx index b90d5b25c63abe417b39806b1528bdf17d171c4f..276b8e512396c9bbb49f1c2b8fa2811504208146 100644 --- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx @@ -62,7 +62,7 @@ export const LayerImageObjectEditFactoryModal: React.FC = () => { } showToast({ type: 'success', - message: 'The image has been successfully updated', + message: 'The image has been successfully updated.', }); dispatch(closeModal()); } catch (error) { diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx index 140065e5b7ebb6b7b7fb35d310940d47b62f453c..da0929edf4449584d4fc7787226fa2ec307fdbd6 100644 --- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx @@ -129,7 +129,7 @@ describe('LayerImageObjectFactoryModal - component', () => { }); expect(showToast).toHaveBeenCalledWith({ - message: 'A new image has been successfully added', + message: 'A new image has been successfully added.', type: 'success', }); }); diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx index 4d1513e92c02b78669ff3783d3637b87632dd943..ec4956590401f9c2a9a44423367e4c49d51ae2ef 100644 --- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx @@ -61,7 +61,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => { if (!imageData) { showToast({ type: 'error', - message: 'Error while adding the image', + message: 'An error occurred while adding a new image.', }); return; } @@ -76,7 +76,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => { }); showToast({ type: 'success', - message: 'A new image has been successfully added', + message: 'A new image has been successfully added.', }); dispatch(closeModal()); dispatch(mapEditToolsSetActiveAction(null)); diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectEditFactoryModal.component.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4ff05d12f62bb49dbc911c538b0ef23b42905361 --- /dev/null +++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectEditFactoryModal.component.tsx @@ -0,0 +1,107 @@ +/* eslint-disable no-magic-numbers */ +import React, { useState } from 'react'; +import './LayerRectFactoryModal.styles.css'; +import { LoadingIndicator } from '@/shared/LoadingIndicator'; +import { Button } from '@/shared/Button'; +import { LayerRectForm } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectForm.component'; +import { LayerRectFactoryForm } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { currentModelIdSelector } from '@/redux/models/models.selectors'; +import { Color } from '@/types/models'; +import { updateLayerRect } from '@/redux/layers/layers.thunks'; +import { showToast } from '@/utils/showToast'; +import { layerUpdateRect } from '@/redux/layers/layers.slice'; +import { closeModal } from '@/redux/modal/modal.slice'; +import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; +import { SerializedError } from '@reduxjs/toolkit'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { useMapInstance } from '@/utils/context/mapInstanceContext'; +import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors'; +import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement'; + +export const LayerRectEditFactoryModal: React.FC = () => { + const layerObject = useAppSelector(mapEditToolsLayerObjectSelector); + const currentModelId = useAppSelector(currentModelIdSelector); + const dispatch = useAppDispatch(); + const { mapInstance } = useMapInstance(); + + if (!layerObject || !('fillColor' in layerObject && 'borderColor' in layerObject)) { + throw new Error('Invalid layer rectangle object'); + } + + const [isSending, setIsSending] = useState<boolean>(false); + const [data, setData] = useState<LayerRectFactoryForm>({ + fillColor: layerObject.fillColor, + borderColor: layerObject.borderColor, + }); + + const handleSubmit = async (): Promise<void> => { + if (!layerObject) { + return; + } + try { + const layerRect = await dispatch( + updateLayerRect({ + modelId: currentModelId, + layerId: layerObject.layer, + id: layerObject.id, + x: layerObject.x, + y: layerObject.y, + z: layerObject.z, + width: layerObject.width, + height: layerObject.height, + fillColor: data.fillColor, + borderColor: data.borderColor, + }), + ).unwrap(); + + if (!layerRect) { + showToast({ + type: 'error', + message: 'An error occurred while editing the rectangle.', + }); + return; + } + + dispatch(layerUpdateRect({ modelId: currentModelId, layerId: layerRect.layer, layerRect })); + dispatch(mapEditToolsSetLayerObject(layerRect)); + updateElement(mapInstance, layerRect.layer, layerRect); + showToast({ + type: 'success', + message: 'The rectangle has been successfully updated.', + }); + dispatch(closeModal()); + } catch (error) { + const typedError = error as SerializedError; + showToast({ + type: 'error', + message: typedError.message || 'An error occurred while editing the rectangle.', + }); + } finally { + setIsSending(false); + } + }; + + const changeValues = (value: string | number | Color, key: string): void => { + setData(prevData => ({ ...prevData, [key]: value })); + }; + + return ( + <div className="relative flex w-[400px] flex-col gap-4 rounded-b-lg border border-t-[#E1E0E6] bg-white p-[24px]"> + {isSending && ( + <div className="c-layer-rect-factory-modal-loader"> + <LoadingIndicator width={44} height={44} /> + </div> + )} + <LayerRectForm onChange={changeValues} data={data} /> + <hr /> + <Button + type="button" + onClick={handleSubmit} + className="justify-center self-end justify-self-end text-base font-medium" + > + Submit + </Button> + </div> + ); +}; diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx index 43964f7c0e16f1cbe64a6f7399654b9adba86c6b..8d5de75a7f6f92b3dd4b94c732bca1e30fdcc084 100644 --- a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx @@ -97,7 +97,7 @@ describe('LayerRectFactoryModal - component', () => { }); expect(showToast).toHaveBeenCalledWith({ - message: 'A new rect has been successfully added', + message: 'A new rectangle has been successfully added.', type: 'success', }); }); diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx index c374bfc52075844d7c276f64844e935ad3ba8e22..cbdfb2306342a41844b9f877ce9d6173727227c1 100644 --- a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx @@ -55,7 +55,7 @@ export const LayerRectFactoryModal: React.FC = () => { if (!layerRect) { showToast({ type: 'error', - message: 'Error while adding the rect', + message: 'An error occurred while adding a new rectangle.', }); return; } @@ -68,7 +68,7 @@ export const LayerRectFactoryModal: React.FC = () => { }); showToast({ type: 'success', - message: 'A new rect has been successfully added', + message: 'A new rectangle has been successfully added.', }); dispatch(closeModal()); dispatch(mapEditToolsSetActiveAction(null)); @@ -76,7 +76,7 @@ export const LayerRectFactoryModal: React.FC = () => { const typedError = error as SerializedError; showToast({ type: 'error', - message: typedError.message || 'An error occurred while adding a new rect', + message: typedError.message || 'An error occurred while adding a new rectangle.', }); } finally { setIsSending(false); diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx index c73e9d93dc774cded10b1266c8022985df43eade..d80231bd014e0eed40fa1340482d373c28734f0e 100644 --- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx @@ -70,7 +70,7 @@ export const LayerTextEditFactoryModal: React.FC = () => { } showToast({ type: 'success', - message: 'The text has been successfully updated', + message: 'The text has been successfully updated.', }); dispatch(closeModal()); } catch (error) { diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx index 6824d6b1e07895e5982e4d0ae91bf30169f8e908..1b03cb0411dd7992ad63be458af6bfb7db05fe1e 100644 --- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx +++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx @@ -142,7 +142,7 @@ describe('LayerTextFactoryModal - component', () => { }); expect(showToast).toHaveBeenCalledWith({ - message: 'A new text has been successfully added', + message: 'A new text has been successfully added.', type: 'success', }); }); diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx index bfb80aff2c7686feb3ab0d443034ec81ed396027..b144615676f4973389f98abcb986f752540866e6 100644 --- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx +++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx @@ -64,7 +64,7 @@ export const LayerTextFactoryModal: React.FC = () => { if (!textData) { showToast({ type: 'error', - message: 'Error while adding the text', + message: 'An error occurred while adding a new text.', }); return; } @@ -77,7 +77,7 @@ export const LayerTextFactoryModal: React.FC = () => { }); showToast({ type: 'success', - message: 'A new text has been successfully added', + message: 'A new text has been successfully added.', }); dispatch(closeModal()); dispatch(mapEditToolsSetActiveAction(null)); @@ -85,7 +85,7 @@ export const LayerTextFactoryModal: React.FC = () => { const typedError = error as SerializedError; showToast({ type: 'error', - message: typedError.message || 'An error occurred while adding a new text', + message: typedError.message || 'An error occurred while adding a new text.', }); } finally { setIsSending(false); diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx index 97fc435d83f56ff7004ce3b198bd578a92ff096a..c0432b8bce5a572c7229b5d0c735aaa8bbe61a2d 100644 --- a/src/components/FunctionalArea/Modal/Modal.component.tsx +++ b/src/components/FunctionalArea/Modal/Modal.component.tsx @@ -10,9 +10,10 @@ import { LayerImageObjectFactoryModal, } from '@/components/FunctionalArea/Modal/LayerImageObjectModal'; import { LayerTextFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component'; -import { EditOverlayGroupModal } from '@/components/FunctionalArea/Modal/EditOverlayGroupModal'; import { LayerTextEditFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component'; import { LayerRectFactoryModal } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component'; +import { LayerRectEditFactoryModal } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectEditFactoryModal.component'; +import { EditOverlayGroupModal } from '@/components/FunctionalArea/Modal/EditOverlayGroupModal'; import { EditOverlayModal } from './EditOverlayModal'; import { LoginModal } from './LoginModal'; import { ErrorReportModal } from './ErrorReportModal'; @@ -123,6 +124,11 @@ export const Modal = (): React.ReactNode => { <LayerRectFactoryModal /> </ModalLayout> )} + {isOpen && modalName === 'layer-rect-edit-factory' && ( + <ModalLayout> + <LayerRectEditFactoryModal /> + </ModalLayout> + )} </> ); }; diff --git a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx index 357f7cf106ca465543a04c50204a34e9d9eaa486..6bca954667af15e3cc647f406305f0e1676ca7cd 100644 --- a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx +++ b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx @@ -34,7 +34,8 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => { modalName === 'add-comment' && 'h-auto w-[400px]', modalName === 'error-report' && 'h-auto w-[800px]', modalName === 'layer-factory' && 'h-auto w-[400px]', - modalName === 'layer-rect-factory' && 'relative h-auto w-[400px] overflow-visible', + ['layer-rect-factory', 'layer-rect-edit-factory'].includes(modalName) && + 'relative h-auto w-[400px] overflow-visible', ['layer-text-factory', 'layer-text-edit-factory'].includes(modalName) && 'h-auto w-[900px]', ['layer-image-object-factory', 'layer-image-object-edit-factory'].includes(modalName) && @@ -45,7 +46,8 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => { <div className={twMerge( 'flex items-center justify-between bg-white p-[24px] text-xl', - modalName === 'layer-rect-factory' && 'rounded-t-lg', + ['layer-rect-factory', 'layer-rect-edit-factory'].includes(modalName) && + 'rounded-t-lg', )} > {(modalName === 'error-report' || modalName === 'access-denied') && ( diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx index a8f0e9bc536a770602aa634b6075092b08f3af45..c36031e5fbaed61ed236e7ed8f4d6f6f1422c549 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx @@ -1,23 +1,80 @@ -import React, { JSX } from 'react'; +import React, { JSX, useMemo } from 'react'; import { LayerRect } from '@/types/models'; import { Icon } from '@/shared/Icon'; +import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; +import { useAppSelector } from '@/redux/hooks/useAppSelector'; +import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors'; +import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'; +import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; +import { LayersDrawerObjectActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component'; interface LayersDrawerRectItemProps { layerRect: LayerRect; + moveToFront: () => void; + moveToBack: () => void; + removeObject: () => void; + centerObject: () => void; + editObject: () => void; + isLayerVisible: boolean; + isLayerActive: boolean; } export const LayersDrawerRectItem = ({ layerRect, + moveToFront, + moveToBack, + removeObject, + centerObject, + editObject, + isLayerVisible, + isLayerActive, }: LayersDrawerRectItemProps): JSX.Element | null => { + const dispatch = useAppDispatch(); + const activeLayerImage = useAppSelector(mapEditToolsLayerObjectSelector); + const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector); + + const showActions = useMemo(() => { + return activeLayerImage?.id === layerRect.id; + }, [activeLayerImage?.id, layerRect.id]); + + const canSelectItem = useMemo(() => { + return isLayerVisible && isLayerActive && hasPrivilegeToWriteProject; + }, [isLayerVisible, isLayerActive, hasPrivilegeToWriteProject]); + + const selectItem = useMemo(() => { + return (): void => { + if (canSelectItem) { + dispatch(mapEditToolsSetLayerObject(layerRect)); + } + }; + }, [canSelectItem, dispatch, layerRect]); + + const handleKeyPress = (): void => {}; + return ( <div className="flex min-h-[24px] items-center justify-between gap-2" id={`layer-rect-item-${layerRect.id}`} > - <div className="flex gap-2"> + <div + className={`flex gap-2 ${canSelectItem ? 'cursor-pointer' : 'cursor-default'}`} + onClick={selectItem} + tabIndex={0} + onKeyDown={handleKeyPress} + role="button" + > <Icon name="rectangle" className="shrink-0" /> <span className="truncate">rectangle - {layerRect.id}</span> </div> + {showActions && ( + <LayersDrawerObjectActions + moveToFront={moveToFront} + moveToBack={moveToBack} + removeObject={removeObject} + centerObject={centerObject} + editObject={editObject} + /> + )} </div> ); }; diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx index 33c259f3e0793659100d2a3145e177557bbcfc21..1e85c51d71c30cfc9411cbdac4ed14e5f1ae38a1 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx @@ -15,7 +15,7 @@ export const LayersDrawer = (): JSX.Element => { const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector); const dispatch = useAppDispatch(); const layersDrawerRef = useRef<HTMLDivElement>(null); - const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector); + const mapEditToolsLayerObject = useAppSelector(mapEditToolsLayerObjectSelector); const addNewLayer = (): void => { dispatch(openLayerFactoryModal()); @@ -35,12 +35,13 @@ export const LayersDrawer = (): JSX.Element => { ); useEffect(() => { - if (!mapEditToolsLayerImageObject || !layersDrawerRef.current) { + if (!mapEditToolsLayerObject || !layersDrawerRef.current) { return; } - const layerObjectElement = document.getElementById( - `layer-image-item-${mapEditToolsLayerImageObject.id}`, - ); + const layerObjectElement = + document.getElementById(`layer-image-item-${mapEditToolsLayerObject.id}`) || + document.getElementById(`layer-text-item-${mapEditToolsLayerObject.id}`) || + document.getElementById(`layer-rect-item-${mapEditToolsLayerObject.id}`); if (!layerObjectElement) { return; } @@ -64,7 +65,7 @@ export const LayersDrawer = (): JSX.Element => { behavior: 'smooth', }); } - }, [mapEditToolsLayerImageObject]); + }, [mapEditToolsLayerObject]); return ( <div data-testid="layers-drawer" className="h-full max-h-full"> diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx index e5681cbbfc0a09ca7b0037ad713007ee49856857..d074dd0c33600b97654515ff29c47a5a62dc9896 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx @@ -82,7 +82,7 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX await dispatch(removeLayer({ modelId: currentModelId, layerId: layerDetails.id })).unwrap(); showToast({ type: 'success', - message: 'The layer has been successfully removed', + message: 'The layer has been successfully removed.', }); setIsModalOpen(false); dispatch(getLayersForModel(currentModelId)); diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx index cc706ac3a7931622293fff0ddb55dd1f807a548e..a0b3544be2585ec34aa58f3e5b4e985915edeccd 100644 --- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx +++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx @@ -13,18 +13,20 @@ import { removeLayerImage, removeLayerText, updateLayerImageObject, + updateLayerRect, updateLayerText, } from '@/redux/layers/layers.thunks'; import { layerDeleteImage, layerDeleteText, layerUpdateImage, + layerUpdateRect, layerUpdateText, } 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, LayerText } from '@/types/models'; +import { LayerImage, LayerRect, LayerText } from '@/types/models'; import { useAppDispatch } from '@/redux/hooks/useAppDispatch'; import { useMapInstance } from '@/utils/context/mapInstanceContext'; import { mapModelIdSelector } from '@/redux/map/map.selectors'; @@ -36,6 +38,7 @@ import { usePointToProjection } from '@/utils/map/usePointToProjection'; import { Coordinate } from 'ol/coordinate'; import { openLayerImageObjectEditFactoryModal, + openLayerRectEditFactoryModal, openLayerTextEditFactoryModal, } from '@/redux/modal/modal.slice'; import { LayersDrawerRectItem } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component'; @@ -219,7 +222,49 @@ export const LayersDrawerObjectsList = ({ await updateTextZIndex({ zIndex: minZIndex - 1, layerText }); }; - const centerObject = (layerObject: LayerImage | LayerText): void => { + const updateRectZIndex = async ({ + zIndex, + layerRect, + }: { + zIndex: number; + layerRect: LayerRect; + }): Promise<void> => { + const newLayerRect = await dispatch( + updateLayerRect({ + modelId: currentModelId, + layerId: layerRect.layer, + id: layerRect.id, + x: layerRect.x, + y: layerRect.y, + z: zIndex, + width: layerRect.width, + height: layerRect.height, + fillColor: layerRect.fillColor, + borderColor: layerRect.borderColor, + }), + ).unwrap(); + if (newLayerRect) { + dispatch( + layerUpdateRect({ + modelId: currentModelId, + layerId: newLayerRect.layer, + layerRect: newLayerRect, + }), + ); + dispatch(mapEditToolsSetLayerObject(newLayerRect)); + updateElement(mapInstance, newLayerRect.layer, newLayerRect); + } + }; + + const moveRectToFront = async (layerRect: LayerRect): Promise<void> => { + await updateRectZIndex({ zIndex: maxZIndex + 1, layerRect }); + }; + + const moveRectToBack = async (layerRect: LayerRect): Promise<void> => { + await updateRectZIndex({ zIndex: minZIndex - 1, layerRect }); + }; + + const centerObject = (layerObject: LayerImage | LayerText | LayerRect): void => { if (mapEditToolsLayerImageObject && mapEditToolsLayerImageObject.id === layerObject.id) { const point1 = pointToProjection({ x: layerObject.x, y: layerObject.y }); const point2 = pointToProjection({ @@ -238,6 +283,10 @@ export const LayersDrawerObjectsList = ({ dispatch(openLayerTextEditFactoryModal()); }; + const editRect = (): void => { + dispatch(openLayerRectEditFactoryModal()); + }; + if (!layer) { return null; } @@ -281,7 +330,17 @@ export const LayersDrawerObjectsList = ({ /> ))} {Object.values(layer.rects).map(layerRect => ( - <LayersDrawerRectItem layerRect={layerRect} key={layerRect.id} /> + <LayersDrawerRectItem + layerRect={layerRect} + key={layerRect.id} + moveToFront={() => moveRectToFront(layerRect)} + moveToBack={() => moveRectToBack(layerRect)} + removeObject={() => {}} + centerObject={() => centerObject(layerRect)} + editObject={() => editRect()} + isLayerVisible={isLayerVisible} + isLayerActive={isLayerActive} + /> ))} </div> ); diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts index fe1497fe0eceafabbdeacc69a9278463165c1e23..0ca5564bb149b37801a7ecfe34cfaece2573689c 100644 --- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts +++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts @@ -173,6 +173,7 @@ export const useOlMapAdditionalLayers = ( const activeVectorLayers = vectorLayers.filter(layer => activeLayers.includes(layer.get('id'))); activeVectorLayers.forEach(vectorLayer => { features.push(...vectorLayer.get('imagesFeatures')); + features.push(...vectorLayer.get('rectsFeatures')); features.push(...vectorLayer.get('textsFeatures')); }); const featuresCollection = new Collection(features); diff --git a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts index 57b36875f90944a0d631f3595d1062f69692df8f..edad8cde3d3190d13c2bcf64fd0f5b0b729d12b7 100644 --- a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts +++ b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts @@ -17,6 +17,7 @@ import { LayerImage } from '@/types/models'; import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle'; import getFill from '@/components/Map/MapViewer/utils/shapes/style/getFill'; import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle'; +import getBoundingBoxPolygon from '@/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon'; export type GlyphProps = { elementId: number; @@ -111,7 +112,13 @@ export default class Glyph { this.minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom) || 1; this.pixelRatio = this.widthOnMap / this.minResolution / this.width; - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.setStyles(); @@ -141,18 +148,6 @@ export default class Glyph { this.drawImage(); } - private drawPolygon(): void { - this.polygon = new Polygon([ - [ - this.pointToProjection({ x: this.x, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y }), - ], - ]); - } - private setStyles(): void { this.polygonStyle = getStyle({ geometry: this.polygon, @@ -177,7 +172,13 @@ export default class Glyph { } private refreshPolygon(): void { - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.polygonStyle.setGeometry(this.polygon); this.feature.setGeometry(this.polygon); } diff --git a/src/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon.ts b/src/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon.ts new file mode 100644 index 0000000000000000000000000000000000000000..375cee537c982dad5e488eb62f311ddfbab4fbce --- /dev/null +++ b/src/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon.ts @@ -0,0 +1,26 @@ +import Polygon from 'ol/geom/Polygon'; +import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; + +export default function getBoundingBoxPolygon({ + x, + y, + width, + height, + pointToProjection, +}: { + x: number; + y: number; + width: number; + height: number; + pointToProjection: UsePointToProjectionResult; +}): Polygon { + return new Polygon([ + [ + pointToProjection({ x, y }), + pointToProjection({ x: x + width, y }), + pointToProjection({ x: x + width, y: y + height }), + pointToProjection({ x, y: y + height }), + pointToProjection({ x, y }), + ], + ]); +} diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts index 93456a0dfb64d0b3e345d06c6e4e74e37fe412ad..851bb3ea4bbd6df282f6826b6fca35bd4404311b 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts @@ -111,11 +111,14 @@ export default class Layer { const textsFeatures = this.getTextsFeatures(); this.vectorSource.addFeatures(textsFeatures); - this.vectorSource.addFeatures(this.getRectsFeatures()); - this.vectorSource.addFeatures(this.getOvalsFeatures()); + const rectsFeatures = this.getRectsFeatures(); + this.vectorSource.addFeatures(rectsFeatures); + const imagesFeatures = this.getImagesFeatures(); this.vectorSource.addFeatures(imagesFeatures); + this.vectorSource.addFeatures(this.getOvalsFeatures()); + const { linesFeatures, arrowsFeatures } = this.getLinesFeatures(); this.vectorSource.addFeatures(linesFeatures); this.vectorSource.addFeatures(arrowsFeatures); @@ -132,6 +135,7 @@ export default class Layer { this.vectorLayer.set('id', layerId); this.vectorLayer.set('imagesFeatures', imagesFeatures); this.vectorLayer.set('textsFeatures', textsFeatures); + this.vectorLayer.set('rectsFeatures', rectsFeatures); this.vectorLayer.set('drawImage', this.drawImage.bind(this)); this.vectorLayer.set('drawText', this.drawText.bind(this)); this.vectorLayer.set('drawRect', this.drawRect.bind(this)); diff --git a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts index 844ec35549d58c92988dfe649a60fbe59d0d3b5d..e86cfc442a335ad08208d270b985e516953031e2 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts @@ -13,6 +13,12 @@ import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style import { Stroke } from 'ol/style'; import { MapSize } from '@/redux/map/map.types'; import { Coordinate } from 'ol/coordinate'; +import { BoundingBox } from '@/components/Map/MapViewer/MapViewer.types'; +import { store } from '@/redux/store'; +import { updateLayerRect } from '@/redux/layers/layers.thunks'; +import { layerUpdateRect } from '@/redux/layers/layers.slice'; +import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; +import getBoundingBoxPolygon from '@/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon'; export interface LayerRectProps { elementId: number; @@ -96,7 +102,13 @@ export default class LayerRect { const maxZoom = mapInstance?.getView().get('originalMaxZoom'); this.minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom) || 1; - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.setStyles(); @@ -109,6 +121,7 @@ export default class LayerRect { this.feature.set('setCoordinates', this.setCoordinates.bind(this)); this.feature.set('refreshPolygon', this.refreshPolygon.bind(this)); this.feature.set('updateElement', this.updateElement.bind(this)); + this.feature.set('save', this.save.bind(this)); this.feature.setStyle(this.getStyle.bind(this)); } @@ -127,20 +140,37 @@ export default class LayerRect { }; } - private drawPolygon(): void { - this.polygon = new Polygon([ - [ - this.pointToProjection({ x: this.x, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y }), - ], - ]); + private async save({ + modelId, + boundingBox, + }: { + modelId: number; + boundingBox: BoundingBox; + }): Promise<void> { + const { dispatch } = store; + const layerRect = await dispatch( + updateLayerRect({ + modelId, + layerId: this.layer, + ...this.getData(), + ...boundingBox, + }), + ).unwrap(); + if (layerRect) { + dispatch(layerUpdateRect({ modelId, layerId: layerRect.layer, layerRect })); + dispatch(mapEditToolsSetLayerObject(layerRect)); + this.updateElement(layerRect); + } } private refreshPolygon(): void { - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.feature.setGeometry(this.polygon); this.feature.changed(); } diff --git a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts index 265653458e53f62c69da46a9d9d9cef2463090e7..41662941aa751c9470a216be0987f7db566cd385 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts @@ -27,6 +27,7 @@ import { store } from '@/redux/store'; import { updateLayerText } from '@/redux/layers/layers.thunks'; import { layerUpdateText } from '@/redux/layers/layers.slice'; import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice'; +import getBoundingBoxPolygon from '@/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon'; export interface LayerTextProps { elementId: number; @@ -142,7 +143,13 @@ export default class LayerText { }); this.point = new Point(textCoords); - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.setStyles(); @@ -188,18 +195,6 @@ export default class LayerText { }; } - private drawPolygon(): void { - this.polygon = new Polygon([ - [ - this.pointToProjection({ x: this.x, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y }), - this.pointToProjection({ x: this.x + this.width, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y + this.height }), - this.pointToProjection({ x: this.x, y: this.y }), - ], - ]); - } - private async save({ modelId, boundingBox, @@ -224,18 +219,18 @@ export default class LayerText { } private refreshPolygon(): void { - this.drawPolygon(); + this.polygon = getBoundingBoxPolygon({ + x: this.x, + y: this.y, + width: this.width, + height: this.height, + pointToProjection: this.pointToProjection, + }); this.polygonStyle.setGeometry(this.polygon); this.feature.setGeometry(this.polygon); this.feature.changed(); } - private refreshZIndex(): void { - this.polygonStyle.setZIndex(this.zIndex); - this.style.setZIndex(this.zIndex); - this.feature.changed(); - } - private setStyles(): void { this.strokeStyle = getStroke({ color: rgbToHex(this.borderColor), diff --git a/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts b/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts index 88f50d44622b43bebd15476b09d4543ee634143e..4318381d22c3629031630fb53363ed1783fa8900 100644 --- a/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts +++ b/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts @@ -1,11 +1,11 @@ import VectorSource from 'ol/source/Vector'; -import { LayerImage, LayerText } from '@/types/models'; +import { LayerImage, LayerRect, LayerText } from '@/types/models'; import { MapInstance } from '@/types/map'; export default function updateElement( mapInstance: MapInstance, layerId: number, - layerObject: LayerImage | LayerText, + layerObject: LayerImage | LayerText | LayerRect, ): void { mapInstance?.getAllLayers().forEach(layer => { if (layer.get('id') === layerId) { diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts index deabbaacbb76a47e2bb1b61044e3a82191d11ca7..a74faffc9a5a4a3c138286776004a9894da62a59 100644 --- a/src/redux/apiPath.ts +++ b/src/redux/apiPath.ts @@ -43,6 +43,8 @@ export const apiPath = { `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/rects/`, addLayerRect: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/rects/`, + updateLayerRect: (modelId: number, layerId: number, rectId: number | string): string => + `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/rects/${rectId}`, getLayerOvals: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/ovals/`, getLayerLines: (modelId: number, layerId: number): string => @@ -64,8 +66,8 @@ export const apiPath = { `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/images/${imageId}`, addLayerText: (modelId: number, layerId: number): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/`, - getLayerText: (modelId: number, layerId: number, imageId: number | string): string => - `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/${imageId}`, + getLayerText: (modelId: number, layerId: number, textId: number | string): string => + `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/${textId}`, updateLayerText: (modelId: number, layerId: number, textId: number | string): string => `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/${textId}`, removeLayerText: (modelId: number, layerId: number, textId: number | string): string => diff --git a/src/redux/layers/layers.reducers.ts b/src/redux/layers/layers.reducers.ts index 9d1a42d6da1ab8f9ad8258cf214c4112bd351579..74b83a3d44a34e868d9dfa9ad5531336fb5af75f 100644 --- a/src/redux/layers/layers.reducers.ts +++ b/src/redux/layers/layers.reducers.ts @@ -8,6 +8,7 @@ import { } from '@/redux/layers/layers.mock'; import { DEFAULT_ERROR } from '@/constants/errors'; import { LayerImage, LayerRect, LayerText } from '@/types/models'; +import setLayerRect from '@/redux/layers/utils/setLayerRect'; export const getLayersForModelReducer = (builder: ActionReducerMapBuilder<LayersState>): void => { builder.addCase(getLayersForModel.pending, (state, action) => { @@ -240,9 +241,17 @@ export const layerAddRectReducer = ( if (!data) { return; } - const layer = data.layers.find(layerState => layerState.details.id === layerId); - if (!layer) { + setLayerRect({ layerId, layers: data.layers, layerRect }); +}; + +export const layerUpdateRectReducer = ( + state: LayersState, + action: PayloadAction<{ modelId: number; layerId: number; layerRect: LayerRect }>, +): void => { + const { modelId, layerId, layerRect } = action.payload; + const { data } = state[modelId]; + if (!data) { return; } - layer.rects[layerRect.id] = layerRect; + setLayerRect({ layerId, layers: data.layers, layerRect }); }; diff --git a/src/redux/layers/layers.slice.ts b/src/redux/layers/layers.slice.ts index c66fa62906797a52aa27251795425fdff00e3437..0760126a9b3aa051f816f0763d03aa7eed0ff77b 100644 --- a/src/redux/layers/layers.slice.ts +++ b/src/redux/layers/layers.slice.ts @@ -15,6 +15,7 @@ import { layerDeleteTextReducer, layerUpdateTextReducer, layerAddRectReducer, + layerUpdateRectReducer, } from '@/redux/layers/layers.reducers'; export const layersSlice = createSlice({ @@ -31,6 +32,7 @@ export const layersSlice = createSlice({ layerUpdateText: layerUpdateTextReducer, layerDeleteText: layerDeleteTextReducer, layerAddRect: layerAddRectReducer, + layerUpdateRect: layerUpdateRectReducer, setDrawLayer: setDrawLayerReducer, }, extraReducers: builder => { @@ -51,6 +53,7 @@ export const { layerUpdateText, layerDeleteText, layerAddRect, + layerUpdateRect, setDrawLayer, } = layersSlice.actions; diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts index 0db4a364ae9bd37b776dddae0e0fd96420d08a59..4d351082f5e87cba3cfee7402200dfd972950c8a 100644 --- a/src/redux/layers/layers.thunks.ts +++ b/src/redux/layers/layers.thunks.ts @@ -420,3 +420,45 @@ export const addLayerRect = createAsyncThunk< return Promise.reject(getError({ error })); } }); + +export const updateLayerRect = createAsyncThunk< + LayerRect | null, + { + modelId: number; + layerId: number; + id: number; + x: number; + y: number; + z: number; + width: number; + height: number; + fillColor: Color; + borderColor: Color; + }, + ThunkConfig +>( + 'layers/updateLayerRect', + async ({ modelId, layerId, id, x, y, z, width, height, fillColor, borderColor }) => { + try { + const { data } = await axiosInstanceNewAPI.put<LayerRect>( + apiPath.updateLayerRect(modelId, layerId, id), + { + x, + y, + z, + width, + height, + fillColor, + borderColor, + }, + ); + const isDataValid = validateDataUsingZodSchema(data, layerRectSchema); + if (isDataValid) { + return data; + } + return null; + } catch (error) { + return Promise.reject(getError({ error })); + } + }, +); diff --git a/src/redux/layers/utils/setLayerRect.ts b/src/redux/layers/utils/setLayerRect.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0b9abbb82224c4a950f30c787bfd69c6fe515b3 --- /dev/null +++ b/src/redux/layers/utils/setLayerRect.ts @@ -0,0 +1,18 @@ +import { LayerRect } from '@/types/models'; +import { LayerState } from '@/redux/layers/layers.types'; + +export default function setLayerRect({ + layerId, + layers, + layerRect, +}: { + layerId: number; + layers: LayerState[]; + layerRect: LayerRect; +}): void { + const layer = layers.find(layerState => layerState.details.id === layerId); + if (!layer) { + return; + } + layer.rects[layerRect.id] = layerRect; +} diff --git a/src/redux/mapEditTools/mapEditTools.reducers.ts b/src/redux/mapEditTools/mapEditTools.reducers.ts index d45e719f8a892cd828dc650ae0d03ea9dfb808e7..b85196087f6c2cee0a425aae5a2ce4202c7eeb25 100644 --- a/src/redux/mapEditTools/mapEditTools.reducers.ts +++ b/src/redux/mapEditTools/mapEditTools.reducers.ts @@ -2,7 +2,7 @@ import { PayloadAction } from '@reduxjs/toolkit'; import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants'; import { MapEditToolsState } from '@/redux/mapEditTools/mapEditTools.types'; -import { LayerImage, LayerText } from '@/types/models'; +import { LayerImage, LayerRect, LayerText } from '@/types/models'; export const mapEditToolsSetActiveActionReducer = ( state: MapEditToolsState, @@ -13,7 +13,7 @@ export const mapEditToolsSetActiveActionReducer = ( export const mapEditToolsSetLayerObjectReducer = ( state: MapEditToolsState, - action: PayloadAction<LayerImage | LayerText | null>, + action: PayloadAction<LayerImage | LayerText | LayerRect | null>, ): void => { state.layerObject = action.payload; }; diff --git a/src/redux/mapEditTools/mapEditTools.types.ts b/src/redux/mapEditTools/mapEditTools.types.ts index 4c216c406c2b890a4fbc6fe97701928f0f751828..b9a012c8cd3937d19c247cc2379225bc16fcc28b 100644 --- a/src/redux/mapEditTools/mapEditTools.types.ts +++ b/src/redux/mapEditTools/mapEditTools.types.ts @@ -1,7 +1,7 @@ import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants'; -import { LayerImage, LayerText } from '@/types/models'; +import { LayerImage, LayerRect, LayerText } from '@/types/models'; export type MapEditToolsState = { activeAction: keyof typeof MAP_EDIT_ACTIONS | null; - layerObject: LayerImage | LayerText | null; + layerObject: LayerImage | LayerText | LayerRect | null; }; diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts index 979ebce7eb505487f2cf41e953319fc516dfa918..dd54049e9c686790a583c3c587e38b99d0672a0b 100644 --- a/src/redux/modal/modal.reducers.ts +++ b/src/redux/modal/modal.reducers.ts @@ -195,3 +195,9 @@ export const openLayerRectFactoryModalReducer = ( state.modalTitle = 'Add rectangle'; state.isOpen = true; }; + +export const openLayerRectEditFactoryModalReducer = (state: ModalState): void => { + state.isOpen = true; + state.modalName = 'layer-rect-edit-factory'; + state.modalTitle = 'Edit rectangle'; +}; diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts index 803d68c0b738023af3c824b8fd8348a80e981e33..c18561e3ea013cbb6c5fc31052e3f2140960057f 100644 --- a/src/redux/modal/modal.slice.ts +++ b/src/redux/modal/modal.slice.ts @@ -22,6 +22,7 @@ import { openLayerTextFactoryModalReducer, openLayerTextEditFactoryModalReducer, openLayerRectFactoryModalReducer, + openLayerRectEditFactoryModalReducer, openEditOverlayGroupModalReducer, } from './modal.reducers'; @@ -51,6 +52,7 @@ const modalSlice = createSlice({ openLayerTextFactoryModal: openLayerTextFactoryModalReducer, openLayerTextEditFactoryModal: openLayerTextEditFactoryModalReducer, openLayerRectFactoryModal: openLayerRectFactoryModalReducer, + openLayerRectEditFactoryModal: openLayerRectEditFactoryModalReducer, }, }); @@ -77,6 +79,7 @@ export const { openLayerTextFactoryModal, openLayerTextEditFactoryModal, openLayerRectFactoryModal, + openLayerRectEditFactoryModal, } = modalSlice.actions; export default modalSlice.reducer; diff --git a/src/types/modal.ts b/src/types/modal.ts index 69d8b0f4e375ac433594219d1031dd4eec1f4e23..9dc83061a0849ce22843e9f16af957c8b6c50980 100644 --- a/src/types/modal.ts +++ b/src/types/modal.ts @@ -18,4 +18,5 @@ export type ModalName = | 'layer-image-object-edit-factory' | 'layer-text-factory' | 'layer-text-edit-factory' - | 'layer-rect-factory'; + | 'layer-rect-factory' + | 'layer-rect-edit-factory';