From 4a9d3eb1e717fcb78bd61cc59f53219b6b77b5b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Mon, 17 Feb 2025 12:16:14 +0100
Subject: [PATCH 1/8] feat(layer-text): add transform interaction for layer
 text and delete functionality

---
 ...eObjectEditFactoryModal.component.test.tsx |  38 ++-
 ...rImageObjectEditFactoryModal.component.tsx |  21 +-
 .../LayerDrawerTextItem.component.tsx         |  70 +++-
 .../LayersDrawer/LayersDrawer.component.tsx   |   4 +-
 .../LayersDrawerImageItem.component.tsx       |   4 +-
 .../LayersDrawerObjectsList.component.tsx     | 147 +++++---
 .../Map/MapViewer/MapViewer.component.tsx     |   8 +-
 .../useOlMapAdditionalLayers.ts               |  34 +-
 .../utils/shapes/elements/Glyph/Glyph.ts      |  10 +-
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |  56 ++--
 .../Glyph => layer/elements}/LayerImage.ts    |  33 +-
 .../elements/LayerText.test.ts}               |  28 +-
 .../utils/shapes/layer/elements/LayerText.ts  | 315 ++++++++++++++++++
 ...est.ts => getTransformInteraction.test.ts} |   6 +-
 ...eraction.ts => getTransformInteraction.ts} |  40 +--
 .../utils/updateElement.ts}                   |  12 +-
 .../Map/MapViewer/utils/shapes/text/Text.ts   | 145 --------
 .../utils/shapes/text/getTextCoords.ts        |   9 +-
 .../utils/websocket/processLayerImage.ts      |   4 +-
 .../utils/websocket/processLayerText.ts       |  33 +-
 src/models/layerTextSchema.ts                 |   4 +-
 src/redux/apiPath.ts                          |   4 +
 src/redux/layers/layers.reducers.ts           |  32 ++
 src/redux/layers/layers.slice.ts              |   6 +
 src/redux/layers/layers.thunks.ts             |  86 ++++-
 src/redux/mapEditTools/mapEditTools.mock.ts   |   2 +-
 .../mapEditTools/mapEditTools.reducers.ts     |   6 +-
 .../mapEditTools/mapEditTools.selectors.ts    |   4 +-
 src/redux/mapEditTools/mapEditTools.types.ts  |   4 +-
 29 files changed, 818 insertions(+), 347 deletions(-)
 rename src/components/Map/MapViewer/utils/shapes/{elements/Glyph => layer/elements}/LayerImage.ts (54%)
 rename src/components/Map/MapViewer/utils/shapes/{text/Text.test.ts => layer/elements/LayerText.test.ts} (75%)
 create mode 100644 src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts
 rename src/components/Map/MapViewer/utils/shapes/layer/interaction/{getTransformImageInteraction.test.ts => getTransformInteraction.test.ts} (85%)
 rename src/components/Map/MapViewer/utils/shapes/layer/interaction/{getTransformImageInteraction.ts => getTransformInteraction.ts} (76%)
 rename src/components/Map/MapViewer/utils/shapes/{elements/Glyph/updateGlyph.ts => layer/utils/updateElement.ts} (60%)
 delete mode 100644 src/components/Map/MapViewer/utils/shapes/text/Text.ts

diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
index 0c0973f2..29a26c8b 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
@@ -81,7 +81,13 @@ const renderComponent = (
 
 describe('LayerImageObjectEditFactoryModal - component', () => {
   it('should render LayerImageObjectEditFactoryModal component with initial state', () => {
-    renderComponent();
+    renderComponent({
+      activeAction: null,
+      layerObject: {
+        ...layerImageFixture,
+        glyph: null,
+      },
+    });
 
     expect(screen.getByText(/Glyph:/i)).toBeInTheDocument();
     expect(screen.getByText(/File:/i)).toBeInTheDocument();
@@ -90,7 +96,13 @@ describe('LayerImageObjectEditFactoryModal - component', () => {
   });
 
   it('should display a list of glyphs in the dropdown', async () => {
-    renderComponent();
+    renderComponent({
+      activeAction: null,
+      layerObject: {
+        ...layerImageFixture,
+        glyph: null,
+      },
+    });
 
     const dropdown = screen.getByTestId('autocomplete');
     if (!dropdown.firstChild) {
@@ -102,7 +114,13 @@ describe('LayerImageObjectEditFactoryModal - component', () => {
   });
 
   it('should update the selected glyph on dropdown change', async () => {
-    renderComponent();
+    renderComponent({
+      activeAction: null,
+      layerObject: {
+        ...layerImageFixture,
+        glyph: null,
+      },
+    });
 
     const dropdown = screen.getByTestId('autocomplete');
     if (!dropdown.firstChild) {
@@ -142,13 +160,13 @@ describe('LayerImageObjectEditFactoryModal - component', () => {
     };
     const getGlyphDataMock = jest.fn(() => glyphData);
     jest.spyOn(layerObjectFeature, 'get').mockImplementation(key => {
-      if (key === 'update') return (): void => {};
-      if (key === 'getGlyphData') return getGlyphDataMock;
+      if (key === 'updateElement') return (): void => {};
+      if (key === 'getObjectData') return getGlyphDataMock;
       return undefined;
     });
     renderComponent({
       activeAction: MAP_EDIT_ACTIONS.TRANSFORM_IMAGE,
-      layerImageObject: glyphData,
+      layerObject: glyphData,
     });
 
     const submitButton = screen.getByText(/Submit/i);
@@ -164,7 +182,13 @@ describe('LayerImageObjectEditFactoryModal - component', () => {
   });
 
   it('should display "No Image" when there is no image file', () => {
-    const { store } = renderComponent();
+    const { store } = renderComponent({
+      activeAction: null,
+      layerObject: {
+        ...layerImageFixture,
+        glyph: null,
+      },
+    });
 
     store.dispatch({
       type: 'glyphs/clearGlyphData',
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
index e4dfcdd0..dc280845 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
@@ -2,7 +2,7 @@
 import React, { useState } from 'react';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 
-import { mapEditToolsLayerImageObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
 import { LayerImageObjectForm } from '@/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectForm.component';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { addGlyph } from '@/redux/glyphs/glyphs.thunks';
@@ -13,24 +13,25 @@ import { showToast } from '@/utils/showToast';
 import { closeModal } from '@/redux/modal/modal.slice';
 import { SerializedError } from '@reduxjs/toolkit';
 import { useMapInstance } from '@/utils/context/mapInstanceContext';
-import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph';
+import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement';
 import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
 
 export const LayerImageObjectEditFactoryModal: React.FC = () => {
-  const layerImageObject = useAppSelector(mapEditToolsLayerImageObjectSelector);
+  const layerObject = useAppSelector(mapEditToolsLayerObjectSelector);
   const { mapInstance } = useMapInstance();
 
+  if (!layerObject || !('glyph' in layerObject)) {
+    throw new Error('Invalid layer image object');
+  }
   const currentModelId = useAppSelector(currentModelIdSelector);
   const dispatch = useAppDispatch();
 
-  const [selectedGlyph, setSelectedGlyph] = useState<number | null>(
-    layerImageObject?.glyph || null,
-  );
+  const [selectedGlyph, setSelectedGlyph] = useState<number | null>(layerObject?.glyph || null);
   const [file, setFile] = useState<File | null>(null);
   const [isSending, setIsSending] = useState<boolean>(false);
 
   const handleSubmit = async (): Promise<void> => {
-    if (!layerImageObject) {
+    if (!layerObject) {
       return;
     }
     setIsSending(true);
@@ -47,8 +48,8 @@ export const LayerImageObjectEditFactoryModal: React.FC = () => {
       const layerImage = await dispatch(
         updateLayerImageObject({
           modelId: currentModelId,
-          layerId: layerImageObject.layer,
-          ...layerImageObject,
+          layerId: layerObject.layer,
+          ...layerObject,
           glyph: glyphId,
         }),
       ).unwrap();
@@ -57,7 +58,7 @@ export const LayerImageObjectEditFactoryModal: React.FC = () => {
           layerUpdateImage({ modelId: currentModelId, layerId: layerImage.layer, layerImage }),
         );
         dispatch(mapEditToolsSetLayerObject(layerImage));
-        updateGlyph(mapInstance, layerImage.layer, layerImage);
+        updateElement(mapInstance, layerImage.layer, layerImage);
       }
       showToast({
         type: 'success',
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
index 12a7959c..6f57c762 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
@@ -1,18 +1,80 @@
-import { JSX } from 'react';
+import React, { JSX, useMemo } from 'react';
 import { LayerText } from '@/types/models';
 import { Icon } from '@/shared/Icon';
+import { LayersDrawerObjectActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
+import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
 
 interface LayersDrawerTextItemProps {
   layerText: LayerText;
+  bringToFront: () => void;
+  bringToBack: () => void;
+  removeObject: () => void;
+  centerObject: () => void;
+  editObject: () => void;
+  isLayerVisible: boolean;
+  isLayerActive: boolean;
 }
 
 export const LayersDrawerTextItem = ({
   layerText,
+  bringToFront,
+  bringToBack,
+  removeObject,
+  centerObject,
+  editObject,
+  isLayerVisible,
+  isLayerActive,
 }: LayersDrawerTextItemProps): JSX.Element | null => {
+  const dispatch = useAppDispatch();
+  const activeLayerObject = useAppSelector(mapEditToolsLayerObjectSelector);
+  const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
+
+  const showActions = useMemo(() => {
+    return activeLayerObject?.id === layerText.id;
+  }, [activeLayerObject?.id, layerText.id]);
+
+  const canSelectItem = useMemo(() => {
+    return isLayerVisible && isLayerActive && hasPrivilegeToWriteProject;
+  }, [isLayerVisible, isLayerActive, hasPrivilegeToWriteProject]);
+
+  const selectItem = useMemo(() => {
+    return (): void => {
+      if (canSelectItem) {
+        dispatch(mapEditToolsSetLayerObject(layerText));
+      }
+    };
+  }, [canSelectItem, dispatch, layerText]);
+
+  const handleKeyPress = (): void => {};
+
   return (
-    <div className="flex min-h-[24px]  gap-2">
-      <Icon name="text" className="shrink-0" />
-      <span className="truncate">{layerText.notes}</span>
+    <div
+      className="flex min-h-[24px] items-center justify-between gap-2"
+      id={`layer-text-item-${layerText.id}`}
+    >
+      <div
+        className={`flex gap-2 ${canSelectItem ? 'cursor-pointer' : 'cursor-default'}`}
+        onClick={selectItem}
+        tabIndex={0}
+        onKeyDown={handleKeyPress}
+        role="button"
+      >
+        <Icon name="text" className="shrink-0" />
+        <span className="truncate">{layerText.notes}</span>
+      </div>
+      {showActions && (
+        <LayersDrawerObjectActions
+          bringToFront={bringToFront}
+          bringToBack={bringToBack}
+          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 df941aca..12bef081 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
@@ -8,14 +8,14 @@ import { JSX, useEffect, useRef } from 'react';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
 import { LayersDrawerLayer } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component';
-import { mapEditToolsLayerImageObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
 
 export const LayersDrawer = (): JSX.Element => {
   const layersForCurrentModel = useAppSelector(layersForCurrentModelSelector);
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
   const dispatch = useAppDispatch();
   const layersDrawerRef = useRef<HTMLDivElement>(null);
-  const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerImageObjectSelector);
+  const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector);
 
   const addNewLayer = (): void => {
     dispatch(openLayerFactoryModal());
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
index d2884a5b..0622f141 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
@@ -4,7 +4,7 @@ import { Icon } from '@/shared/Icon';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { glyphFileNameByIdSelector } from '@/redux/glyphs/glyphs.selectors';
 import { LayersDrawerObjectActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component';
-import { mapEditToolsLayerImageObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
 import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
@@ -31,7 +31,7 @@ export const LayersDrawerImageItem = ({
   isLayerActive,
 }: LayersDrawerImageItemProps): JSX.Element | null => {
   const dispatch = useAppDispatch();
-  const activeLayerImage = useAppSelector(mapEditToolsLayerImageObjectSelector);
+  const activeLayerImage = useAppSelector(mapEditToolsLayerObjectSelector);
   const fileName = useAppSelector(state => glyphFileNameByIdSelector(state, layerImage.glyph));
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
 
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index fca7a858..fa98e051 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -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}
diff --git a/src/components/Map/MapViewer/MapViewer.component.tsx b/src/components/Map/MapViewer/MapViewer.component.tsx
index 0307cf08..faf874c1 100644
--- a/src/components/Map/MapViewer/MapViewer.component.tsx
+++ b/src/components/Map/MapViewer/MapViewer.component.tsx
@@ -1,13 +1,17 @@
 import 'ol/ol.css';
 import { twMerge } from 'tailwind-merge';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
-import { isMapEditToolsActiveSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import {
+  isMapEditToolsActiveSelector,
+  mapEditToolsLayerObjectSelector,
+} from '@/redux/mapEditTools/mapEditTools.selectors';
 import { useOlMap } from './utils/useOlMap';
 import { MAP_VIEWER_ROLE } from './MapViewer.constants';
 
 export const MapViewer = (): JSX.Element => {
   const { mapRef } = useOlMap();
   const isMapEditToolsActive = useAppSelector(isMapEditToolsActiveSelector);
+  const layerObject = useAppSelector(mapEditToolsLayerObjectSelector);
 
   return (
     <div
@@ -15,7 +19,7 @@ export const MapViewer = (): JSX.Element => {
       role={MAP_VIEWER_ROLE}
       className={twMerge(
         'absolute left-[88px] top-[104px] h-[calc(100%-104px)] w-[calc(100%-88px)] bg-white',
-        isMapEditToolsActive ? 'bg-[#e4e2de]' : 'bg-white',
+        isMapEditToolsActive || layerObject ? 'bg-[#e4e2de]' : 'bg-white',
       )}
     />
   );
diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
index 162d345c..5e378293 100644
--- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
+++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
@@ -16,7 +16,7 @@ import {
 } from '@/redux/layers/layers.selectors';
 import { usePointToProjection } from '@/utils/map/usePointToProjection';
 import { MapInstance } from '@/types/map';
-import { Geometry, LineString, MultiPolygon, Point } from 'ol/geom';
+import { Geometry, LineString, MultiPolygon } from 'ol/geom';
 import Polygon from 'ol/geom/Polygon';
 import Layer from '@/components/Map/MapViewer/utils/shapes/layer/Layer';
 import { arrowTypesSelector, lineTypesSelector } from '@/redux/shapes/shapes.selectors';
@@ -25,7 +25,7 @@ import { mapDataSizeSelector } from '@/redux/map/map.selectors';
 import { LayerState } from '@/redux/layers/layers.types';
 import {
   mapEditToolsActiveActionSelector,
-  mapEditToolsLayerImageObjectSelector,
+  mapEditToolsLayerObjectSelector,
 } from '@/redux/mapEditTools/mapEditTools.selectors';
 import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants';
 import getDrawBoundingBoxInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getDrawBoundingBoxInteraction';
@@ -38,7 +38,7 @@ import {
   mapEditToolsSetActiveAction,
   mapEditToolsSetLayerObject,
 } from '@/redux/mapEditTools/mapEditTools.slice';
-import getTransformImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction';
+import getTransformInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction';
 import { useWebSocketEntityUpdatesContext } from '@/utils/websocket-entity-updates/webSocketEntityUpdatesProvider';
 import processMessage from '@/components/Map/MapViewer/utils/websocket/processMessage';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
@@ -46,9 +46,7 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 export const useOlMapAdditionalLayers = (
   mapInstance: MapInstance,
 ): Array<
-  VectorLayer<
-    VectorSource<Feature<Point> | Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>>
-  >
+  VectorLayer<VectorSource<Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>>>
 > => {
   const activeAction = useAppSelector(mapEditToolsActiveActionSelector);
   const dispatch = useAppDispatch();
@@ -61,7 +59,7 @@ export const useOlMapAdditionalLayers = (
   const activeLayers = useAppSelector(layersActiveLayersSelector);
   const drawLayer = useAppSelector(layersDrawLayerSelector);
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
-  const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerImageObjectSelector);
+  const mapEditToolsLayerObject = useAppSelector(mapEditToolsLayerObjectSelector);
 
   const [layersState, setLayersState] = useState<Array<LayerState>>([]);
   const [layersLoadingState, setLayersLoadingState] = useState(false);
@@ -157,21 +155,23 @@ export const useOlMapAdditionalLayers = (
     if (!dispatch || !currentModelId || !activeLayers.length) {
       return null;
     }
-    const imagesFeatures: Array<Feature<Geometry>> = [];
+    const features: Array<Feature<Geometry>> = [];
     const activeVectorLayers = vectorLayers.filter(layer => activeLayers.includes(layer.get('id')));
     activeVectorLayers.forEach(vectorLayer => {
-      imagesFeatures.push(...vectorLayer.get('imagesFeatures'));
+      features.push(...vectorLayer.get('imagesFeatures'));
+      features.push(...vectorLayer.get('textsFeatures'));
     });
-    const imagesFeaturesCollection = new Collection(imagesFeatures);
-    return getTransformImageInteraction(
+    const featuresCollection = new Collection(features);
+    return getTransformInteraction(
       dispatch,
       mapSize,
       currentModelId,
-      imagesFeaturesCollection,
+      featuresCollection,
       restrictionExtent,
     );
   }, [dispatch, mapSize, currentModelId, restrictionExtent, activeLayers, vectorLayers]);
   const transformRef = useRef(transformInteraction);
+
   useEffect(() => {
     transformRef.current = transformInteraction;
   }, [transformInteraction]);
@@ -202,13 +202,13 @@ export const useOlMapAdditionalLayers = (
     }
     const transformFeatures = transformRef.current.getFeatures();
     if (
-      mapEditToolsLayerImageObject &&
+      mapEditToolsLayerObject &&
       (!transformFeatures.getLength() ||
-        transformFeatures.item(0).getId() !== mapEditToolsLayerImageObject.id)
+        transformFeatures.item(0).getId() !== mapEditToolsLayerObject.id)
     ) {
       const layer = vectorLayers.find(vectorLayer => {
         const layerId = vectorLayer.get('id');
-        return layerId === mapEditToolsLayerImageObject.layer;
+        return layerId === mapEditToolsLayerObject.layer;
       });
       if (!layer) {
         return;
@@ -217,13 +217,13 @@ export const useOlMapAdditionalLayers = (
       if (!source) {
         return;
       }
-      const feature = source.getFeatureById(mapEditToolsLayerImageObject.id);
+      const feature = source.getFeatureById(mapEditToolsLayerObject.id);
       if (!feature) {
         return;
       }
       transformRef.current.setSelection(new Collection<Feature>([feature]));
     }
-  }, [mapEditToolsLayerImageObject, vectorLayers]);
+  }, [mapEditToolsLayerObject, vectorLayers]);
 
   useEffect(() => {
     const activeVectorLayers = vectorLayers.filter(layer => {
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 0dca36a1..342cdfac 100644
--- a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts
+++ b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts
@@ -17,7 +17,6 @@ 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 getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent';
 
 export type GlyphProps = {
   elementId: number;
@@ -154,7 +153,7 @@ export default class Glyph {
 
     this.feature.set('setCoordinates', this.setCoordinates.bind(this));
     this.feature.set('refreshPolygon', this.refreshPolygon.bind(this));
-    this.feature.set('update', this.update.bind(this));
+    this.feature.set('updateElement', this.updateElement.bind(this));
     this.feature.setId(this.elementId);
     this.feature.setStyle(this.getStyle.bind(this));
 
@@ -186,7 +185,7 @@ export default class Glyph {
     this.feature.changed();
   }
 
-  private update(imageObject: LayerImage): void {
+  protected updateElement(imageObject: LayerImage): void {
     this.elementId = imageObject.id;
     this.x = imageObject.x;
     this.y = imageObject.y;
@@ -219,11 +218,6 @@ export default class Glyph {
     const geometry = this.polygonStyle.getGeometry();
     if (geometry && geometry instanceof Polygon) {
       geometry.setCoordinates(coords);
-      const boundingBox = getBoundingBoxFromExtent(geometry.getExtent(), this.mapSize);
-      this.x = boundingBox.x;
-      this.y = boundingBox.y;
-      this.width = boundingBox.width;
-      this.height = boundingBox.height;
     }
   }
 
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
index 2149e63b..7f697a72 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
@@ -4,12 +4,12 @@ import {
   LayerLine,
   LayerOval,
   LayerRect,
-  LayerText,
+  LayerText as LayerTextModel,
 } from '@/types/models';
 import { MapInstance } from '@/types/map';
 import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
 import { Feature } from 'ol';
-import { LineString, MultiPolygon, Point } from 'ol/geom';
+import { LineString, MultiPolygon } from 'ol/geom';
 import Polygon from 'ol/geom/Polygon';
 import VectorSource from 'ol/source/Vector';
 import VectorLayer from 'ol/layer/Vector';
@@ -30,11 +30,11 @@ import getArrowFeature from '@/components/Map/MapViewer/utils/shapes/elements/ge
 import getRotation from '@/components/Map/MapViewer/utils/shapes/coords/getRotation';
 import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle';
 import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords';
-import Text from '@/components/Map/MapViewer/utils/shapes/text/Text';
-import LayerImage from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/LayerImage';
+import LayerText from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerText';
+import LayerImage from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage';
 
 export interface LayerProps {
-  texts: { [key: string]: LayerText };
+  texts: { [key: string]: LayerTextModel };
   rects: Array<LayerRect>;
   ovals: Array<LayerOval>;
   lines: Array<LayerLine>;
@@ -51,7 +51,7 @@ export interface LayerProps {
 export default class Layer {
   layerId: number;
 
-  texts: { [key: string]: LayerText };
+  texts: { [key: string]: LayerTextModel };
 
   rects: Array<LayerRect>;
 
@@ -71,12 +71,10 @@ export default class Layer {
 
   mapSize: MapSize;
 
-  vectorSource: VectorSource<
-    Feature<Point> | Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>
-  >;
+  vectorSource: VectorSource<Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>>;
 
   vectorLayer: VectorLayer<
-    VectorSource<Feature<Point> | Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>>
+    VectorSource<Feature<Polygon> | Feature<LineString> | Feature<MultiPolygon>>
   >;
 
   constructor({
@@ -107,7 +105,9 @@ export default class Layer {
     this.mapSize = mapSize;
     this.layerId = layerId;
 
-    this.vectorSource.addFeatures(this.getTextsFeatures());
+    const textsFeatures = this.getTextsFeatures();
+    this.vectorSource.addFeatures(textsFeatures);
+
     this.vectorSource.addFeatures(this.getRectsFeatures());
     this.vectorSource.addFeatures(this.getOvalsFeatures());
     const imagesFeatures = this.getImagesFeatures();
@@ -127,53 +127,39 @@ export default class Layer {
 
     this.vectorLayer.set('id', layerId);
     this.vectorLayer.set('imagesFeatures', imagesFeatures);
+    this.vectorLayer.set('textsFeatures', textsFeatures);
     this.vectorLayer.set('drawImage', this.drawImage.bind(this));
     this.vectorLayer.set('drawText', this.drawText.bind(this));
   }
 
-  private getTextsFeatures = (): Array<Feature<Point>> => {
-    const textObjects = Object.values(this.texts).map(text => {
-      return new Text({
-        x: text.x,
-        y: text.y,
-        zIndex: text.z,
-        width: text.width,
-        height: text.height,
-        layer: text.layer,
-        fontColor: text.color,
-        borderColor: text.borderColor,
-        fontSize: text.fontSize,
-        text: text.notes,
-        verticalAlign: text.verticalAlign as VerticalAlign,
-        horizontalAlign: text.horizontalAlign as HorizontalAlign,
-        pointToProjection: this.pointToProjection,
-        mapInstance: this.mapInstance,
-      });
-    });
-    return textObjects.map(text => text.feature);
+  private getTextsFeatures = (): Array<Feature<Polygon>> => {
+    return Object.values(this.texts).map(text => this.getTextFeature(text));
   };
 
-  private drawText(text: LayerText): void {
+  private drawText(text: LayerTextModel): void {
     const textFeature = this.getTextFeature(text);
     this.vectorSource.addFeature(textFeature);
   }
 
-  private getTextFeature(text: LayerText): Feature<Point> {
-    const textObject = new Text({
+  private getTextFeature(text: LayerTextModel): Feature<Polygon> {
+    const textObject = new LayerText({
+      elementId: text.id,
       x: text.x,
       y: text.y,
       zIndex: text.z,
       width: text.width,
       height: text.height,
       layer: text.layer,
-      fontColor: text.color,
+      color: text.color,
       borderColor: text.borderColor,
+      backgroundColor: text.backgroundColor,
       fontSize: text.fontSize,
       text: text.notes,
       verticalAlign: text.verticalAlign as VerticalAlign,
       horizontalAlign: text.horizontalAlign as HorizontalAlign,
       pointToProjection: this.pointToProjection,
       mapInstance: this.mapInstance,
+      mapSize: this.mapSize,
     });
     return textObject.feature;
   }
diff --git a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/LayerImage.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage.ts
similarity index 54%
rename from src/components/Map/MapViewer/utils/shapes/elements/Glyph/LayerImage.ts
rename to src/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage.ts
index ff893bdf..b7d306bb 100644
--- a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/LayerImage.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage.ts
@@ -3,6 +3,11 @@ import { MapInstance } from '@/types/map';
 import { MapSize } from '@/redux/map/map.types';
 import { LayerImage as LayerImageModel } from '@/types/models';
 import Glyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph';
+import { store } from '@/redux/store';
+import { updateLayerImageObject } from '@/redux/layers/layers.thunks';
+import { layerUpdateImage } from '@/redux/layers/layers.slice';
+import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
+import { BoundingBox } from '@/components/Map/MapViewer/MapViewer.types';
 
 export type LayerImageProps = {
   elementId: number;
@@ -47,11 +52,35 @@ export default class LayerImage extends Glyph {
       mapSize,
     });
     this.layer = layer;
-    this.feature.set('getGlyphData', this.getGlyphData.bind(this));
+    this.feature.set('getObjectData', this.getData.bind(this));
+    this.feature.set('save', this.save.bind(this));
     this.feature.set('layer', layer);
   }
 
-  private getGlyphData(): LayerImageModel {
+  private async save({
+    modelId,
+    boundingBox,
+  }: {
+    modelId: number;
+    boundingBox: BoundingBox;
+  }): Promise<void> {
+    const { dispatch } = store;
+    const layerImage = await dispatch(
+      updateLayerImageObject({
+        modelId,
+        layerId: this.layer,
+        ...this.getData(),
+        ...boundingBox,
+      }),
+    ).unwrap();
+    if (layerImage) {
+      dispatch(layerUpdateImage({ modelId, layerId: layerImage.layer, layerImage }));
+      dispatch(mapEditToolsSetLayerObject(layerImage));
+      this.updateElement(layerImage);
+    }
+  }
+
+  private getData(): LayerImageModel {
     return {
       id: this.elementId,
       x: this.x,
diff --git a/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.test.ts
similarity index 75%
rename from src/components/Map/MapViewer/utils/shapes/text/Text.test.ts
rename to src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.test.ts
index 2f2e145d..7db76f34 100644
--- a/src/components/Map/MapViewer/utils/shapes/text/Text.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.test.ts
@@ -3,17 +3,20 @@ import { Map } from 'ol';
 import { Style } from 'ol/style';
 import View from 'ol/View';
 import { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants';
-import Text, { TextProps } from '@/components/Map/MapViewer/utils/shapes/text/Text';
+import LayerText, {
+  LayerTextProps,
+} from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerText';
 import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle';
 import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex';
 import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords';
+import { DEFAULT_TILE_SIZE } from '@/constants/map';
 
-jest.mock('./getTextCoords');
-jest.mock('./getTextStyle');
-jest.mock('../style/rgbToHex');
+jest.mock('../../text/getTextCoords');
+jest.mock('../../text/getTextStyle');
+jest.mock('../../style/rgbToHex');
 
 describe('Text', () => {
-  let props: TextProps;
+  let props: LayerTextProps;
 
   beforeEach(() => {
     const dummyElement = document.createElement('div');
@@ -26,6 +29,7 @@ describe('Text', () => {
       }),
     });
     props = {
+      elementId: 1,
       x: 0,
       y: 0,
       width: 100,
@@ -34,12 +38,20 @@ describe('Text', () => {
       layer: 1,
       text: 'Test',
       fontSize: 12,
-      fontColor: BLACK_COLOR,
+      color: BLACK_COLOR,
       borderColor: BLACK_COLOR,
+      backgroundColor: BLACK_COLOR,
       verticalAlign: 'MIDDLE',
       horizontalAlign: 'CENTER',
       pointToProjection: jest.fn(({ x, y }) => [x, y]),
       mapInstance,
+      mapSize: {
+        minZoom: 1,
+        maxZoom: 9,
+        width: 0,
+        height: 0,
+        tileSize: DEFAULT_TILE_SIZE,
+      },
     };
 
     (getTextStyle as jest.Mock).mockReturnValue(new Style());
@@ -48,7 +60,7 @@ describe('Text', () => {
   });
 
   it('should apply correct styles to the feature', () => {
-    const text = new Text(props);
+    const text = new LayerText(props);
     const { feature } = text;
 
     const style = feature.getStyleFunction()?.call(text, feature, 1);
@@ -61,7 +73,7 @@ describe('Text', () => {
   });
 
   it('should hide text when the scaled font size is too small', () => {
-    const text = new Text(props);
+    const text = new LayerText(props);
     const { feature } = text;
 
     const style = feature.getStyleFunction()?.call(text, feature, 20);
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts
new file mode 100644
index 00000000..133034cf
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts
@@ -0,0 +1,315 @@
+/* eslint-disable no-magic-numbers */
+import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
+import Style from 'ol/style/Style';
+import { Point } from 'ol/geom';
+import { Feature } from 'ol';
+import { FeatureLike } from 'ol/Feature';
+import { MapInstance } from '@/types/map';
+import { LayerText as LayerTextModel, Color } from '@/types/models';
+import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewer.constants';
+import {
+  BoundingBox,
+  HorizontalAlign,
+  VerticalAlign,
+} from '@/components/Map/MapViewer/MapViewer.types';
+import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords';
+import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle';
+import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex';
+import Polygon from 'ol/geom/Polygon';
+import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke';
+import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle';
+import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle';
+import { Stroke } from 'ol/style';
+import { MapSize } from '@/redux/map/map.types';
+import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent';
+import { Coordinate } from 'ol/coordinate';
+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';
+
+export interface LayerTextProps {
+  elementId: number;
+  x: number;
+  y: number;
+  width: number;
+  height: number;
+  layer: number;
+  zIndex: number;
+  text: string;
+  fontSize: number;
+  color: Color;
+  borderColor: Color;
+  backgroundColor: Color;
+  verticalAlign: VerticalAlign;
+  horizontalAlign: HorizontalAlign;
+  pointToProjection: UsePointToProjectionResult;
+  mapInstance: MapInstance;
+  mapSize: MapSize;
+}
+
+export default class LayerText {
+  elementId: number;
+
+  x: number;
+
+  y: number;
+
+  zIndex: number;
+
+  width: number;
+
+  height: number;
+
+  layer: number;
+
+  text: string;
+
+  verticalAlign: VerticalAlign;
+
+  horizontalAlign: HorizontalAlign;
+
+  backgroundColor: Color;
+
+  borderColor: Color;
+
+  color: Color;
+
+  fontSize: number;
+
+  style: Style;
+
+  polygonStyle: Style;
+
+  polygon: Polygon = new Polygon([]);
+
+  strokeStyle: Stroke;
+
+  point: Point;
+
+  feature: Feature<Polygon>;
+
+  mapSize: MapSize;
+
+  pointToProjection: UsePointToProjectionResult;
+
+  constructor({
+    elementId,
+    x,
+    y,
+    width,
+    height,
+    layer,
+    zIndex,
+    text,
+    fontSize,
+    color,
+    borderColor,
+    backgroundColor,
+    verticalAlign,
+    horizontalAlign,
+    pointToProjection,
+    mapInstance,
+    mapSize,
+  }: LayerTextProps) {
+    this.text = text;
+    this.fontSize = fontSize;
+    this.elementId = elementId;
+    this.x = x;
+    this.y = y;
+    this.zIndex = zIndex;
+    this.width = width;
+    this.height = height;
+    this.layer = layer;
+    this.text = text;
+    this.verticalAlign = verticalAlign;
+    this.horizontalAlign = horizontalAlign;
+    this.backgroundColor = backgroundColor;
+    this.borderColor = borderColor;
+    this.color = color;
+    this.mapSize = mapSize;
+    this.pointToProjection = pointToProjection;
+
+    const textCoords = getTextCoords({
+      x,
+      y,
+      height,
+      width,
+      fontSize,
+      verticalAlign,
+      horizontalAlign,
+      pointToProjection,
+    });
+    this.drawPolygon();
+    this.strokeStyle = getStroke({
+      color: rgbToHex(borderColor),
+      width: 1,
+    });
+    this.polygonStyle = getStyle({
+      geometry: this.polygon,
+      borderColor,
+      fillColor: { rgb: 0, alpha: 0 },
+      lineWidth: 1,
+      zIndex,
+    });
+
+    const textStyle = getTextStyle({
+      text,
+      fontSize,
+      color: rgbToHex(color),
+      zIndex,
+      horizontalAlign,
+    });
+    this.point = new Point(textCoords);
+    this.style = textStyle;
+    this.style.setGeometry(this.point);
+
+    this.feature = new Feature({
+      geometry: this.polygon,
+      getScale: (resolution: number): number => {
+        const maxZoom = mapInstance?.getView().get('originalMaxZoom');
+        if (maxZoom) {
+          const minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom);
+          if (minResolution) {
+            return Math.round((minResolution / resolution) * 100) / 100;
+          }
+        }
+        return 1;
+      },
+      layer,
+    });
+    this.feature.setId(this.elementId);
+    this.feature.set('getObjectData', this.getData.bind(this));
+    this.feature.set('setCoordinates', this.setCoordinates.bind(this));
+    this.feature.set('refreshPolygon', this.refreshPolygon.bind(this));
+    this.feature.set('save', this.save.bind(this));
+    this.feature.set('updateElement', this.updateElement.bind(this));
+    this.feature.setStyle(this.getStyle.bind(this));
+  }
+
+  private getData(): LayerTextModel {
+    return {
+      id: this.elementId,
+      x: this.x,
+      y: this.y,
+      z: this.zIndex,
+      width: this.width,
+      height: this.height,
+      layer: this.layer,
+      fontSize: this.fontSize,
+      notes: this.text,
+      verticalAlign: this.verticalAlign,
+      horizontalAlign: this.horizontalAlign,
+      backgroundColor: this.backgroundColor,
+      borderColor: this.borderColor,
+      color: this.color,
+    };
+  }
+
+  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 layerText = await dispatch(
+      updateLayerText({
+        modelId,
+        layerId: this.layer,
+        ...this.getData(),
+        ...boundingBox,
+      }),
+    ).unwrap();
+    if (layerText) {
+      dispatch(layerUpdateText({ modelId, layerId: layerText.layer, layerText }));
+      dispatch(mapEditToolsSetLayerObject(layerText));
+      this.updateElement(layerText);
+    }
+  }
+
+  private refreshPolygon(): void {
+    this.drawPolygon();
+    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 updateElement(layerText: LayerTextModel): void {
+    this.elementId = layerText.id;
+    this.x = layerText.x;
+    this.y = layerText.y;
+    this.zIndex = layerText.z;
+    this.width = layerText.width;
+    this.height = layerText.height;
+    this.text = layerText.notes;
+    this.fontSize = layerText.fontSize;
+    this.color = layerText.color;
+    this.borderColor = layerText.borderColor;
+    this.verticalAlign = layerText.verticalAlign;
+    this.horizontalAlign = layerText.horizontalAlign;
+
+    this.refreshPolygon();
+    this.refreshZIndex();
+    this.feature.changed();
+  }
+
+  private setCoordinates(coords: Coordinate[][]): void {
+    const geometry = this.polygonStyle.getGeometry();
+    if (geometry && geometry instanceof Polygon) {
+      geometry.setCoordinates(coords);
+    }
+  }
+
+  protected getStyle(feature: FeatureLike, resolution: number): Style | Array<Style> | void {
+    const getScale = feature.get('getScale');
+    let scale = 1;
+    if (getScale instanceof Function) {
+      scale = getScale(resolution);
+    }
+    const geometry = feature.getGeometry();
+    if (geometry && geometry instanceof Polygon) {
+      const polygonExtent = geometry.getExtent();
+      if (polygonExtent) {
+        const boundingBox = getBoundingBoxFromExtent(polygonExtent, this.mapSize);
+        const textCoords = getTextCoords({
+          x: boundingBox.x,
+          y: boundingBox.y,
+          height: boundingBox.height,
+          width: boundingBox.width,
+          fontSize: this.fontSize,
+          verticalAlign: this.verticalAlign,
+          horizontalAlign: this.horizontalAlign,
+          pointToProjection: this.pointToProjection,
+        });
+        this.point.setCoordinates(textCoords);
+      }
+    }
+    if (scale < TEXT_CUTOFF_SCALE) {
+      return undefined;
+    }
+    return [
+      getScaledElementStyle(this.polygonStyle, this.strokeStyle, scale),
+      getScaledElementStyle(this.style, undefined, scale),
+    ];
+  }
+}
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.test.ts
similarity index 85%
rename from src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.test.ts
rename to src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.test.ts
index c2f77a29..1cb1fec9 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.test.ts
@@ -10,13 +10,13 @@ import { DEFAULT_TILE_SIZE } from '@/constants/map';
 import { Collection, Feature } from 'ol';
 import Transform from 'ol-ext/interaction/Transform';
 import { Geometry } from 'ol/geom';
-import getTransformImageInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction';
+import getTransformInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction';
 
 jest.mock('../../../../../../../utils/map/latLngToPoint', () => ({
   latLngToPoint: jest.fn(latLng => ({ x: latLng[0], y: latLng[1] })),
 }));
 
-describe('getTransformImageInteraction', () => {
+describe('getTransformInteraction', () => {
   let store = {} as ToolkitStoreWithSingleSlice<ModalState>;
   let modelIdMock: number;
   let featuresCollectionMock: Collection<Feature<Geometry>>;
@@ -39,7 +39,7 @@ describe('getTransformImageInteraction', () => {
   });
 
   it('returns a Transform interaction', () => {
-    const transformInteraction = getTransformImageInteraction(
+    const transformInteraction = getTransformInteraction(
       store.dispatch,
       mapSize,
       modelIdMock,
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.ts b/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.ts
similarity index 76%
rename from src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.ts
rename to src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.ts
index 3a1435fd..c1c8565c 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformImageInteraction.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/interaction/getTransformInteraction.ts
@@ -5,15 +5,13 @@ import Transform from 'ol-ext/interaction/Transform';
 import { Geometry } from 'ol/geom';
 import { Collection, Feature } from 'ol';
 import BaseEvent from 'ol/events/Event';
-import { updateLayerImageObject } from '@/redux/layers/layers.thunks';
-import { layerUpdateImage } from '@/redux/layers/layers.slice';
 import getBoundingBoxFromExtent from '@/components/Map/MapViewer/utils/shapes/coords/getBoundingBoxFromExtent';
 import { MapSize } from '@/redux/map/map.types';
 import { Extent } from 'ol/extent';
 import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
 import { openDrawer } from '@/redux/drawer/drawer.slice';
 
-export default function getTransformImageInteraction(
+export default function getTransformInteraction(
   dispatch: AppDispatch,
   mapSize: MapSize,
   modelId: number,
@@ -86,6 +84,11 @@ export default function getTransformImageInteraction(
       newGeometry.scale(1, -1);
       feature.setGeometry(newGeometry);
       transform.setSelection(new Collection([feature]));
+      return;
+    }
+    const setCoordinates = feature.get('setCoordinates');
+    if (geometry instanceof Polygon && setCoordinates instanceof Function) {
+      setCoordinates(geometry.getCoordinates());
     }
   });
 
@@ -96,10 +99,10 @@ export default function getTransformImageInteraction(
       dispatch(mapEditToolsSetLayerObject(null));
       return;
     }
-    const getGlyphData = features.item(0).get('getGlyphData');
-    if (getGlyphData && getGlyphData instanceof Function) {
-      const glyphData = getGlyphData();
-      dispatch(mapEditToolsSetLayerObject(glyphData));
+    const getObjectData = features.item(0).get('getObjectData');
+    if (getObjectData && getObjectData instanceof Function) {
+      const objectData = getObjectData();
+      dispatch(mapEditToolsSetLayerObject(objectData));
       dispatch(openDrawer('layers'));
     }
   });
@@ -107,30 +110,13 @@ export default function getTransformImageInteraction(
   transform.on(['scaleend', 'translateend'], async (event: BaseEvent | Event): Promise<void> => {
     const transformEvent = event as unknown as { feature: Feature };
     const { feature } = transformEvent;
-    const setCoordinates = feature.get('setCoordinates');
-    const getGlyphData = feature.get('getGlyphData');
     const refreshPolygon = feature.get('refreshPolygon');
+    const save = feature.get('save');
     const geometry = feature.getGeometry();
-    if (geometry && getGlyphData instanceof Function) {
-      const glyphData = getGlyphData();
+    if (geometry && save instanceof Function) {
       try {
         const boundingBox = getBoundingBoxFromExtent(geometry.getExtent(), mapSize);
-        const layerImage = await dispatch(
-          updateLayerImageObject({
-            modelId,
-            layerId: glyphData.layer,
-            ...glyphData,
-            ...boundingBox,
-          }),
-        ).unwrap();
-        if (layerImage) {
-          dispatch(layerUpdateImage({ modelId, layerId: layerImage.layer, layerImage }));
-          dispatch(mapEditToolsSetLayerObject(layerImage));
-        }
-        if (geometry instanceof Polygon && setCoordinates instanceof Function) {
-          setCoordinates(geometry.getCoordinates());
-          geometry.changed();
-        }
+        save({ modelId, boundingBox });
       } catch {
         if (refreshPolygon instanceof Function) {
           refreshPolygon();
diff --git a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph.ts b/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts
similarity index 60%
rename from src/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph.ts
rename to src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts
index 05418973..88f50d44 100644
--- a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/utils/updateElement.ts
@@ -1,20 +1,20 @@
 import VectorSource from 'ol/source/Vector';
-import { LayerImage } from '@/types/models';
+import { LayerImage, LayerText } from '@/types/models';
 import { MapInstance } from '@/types/map';
 
-export default function updateGlyph(
+export default function updateElement(
   mapInstance: MapInstance,
   layerId: number,
-  layerImage: LayerImage,
+  layerObject: LayerImage | LayerText,
 ): void {
   mapInstance?.getAllLayers().forEach(layer => {
     if (layer.get('id') === layerId) {
       const source = layer.getSource();
       if (source instanceof VectorSource) {
-        const feature = source.getFeatureById(layerImage.id);
-        const update = feature?.get('update');
+        const feature = source.getFeatureById(layerObject.id);
+        const update = feature?.get('updateElement');
         if (update && update instanceof Function) {
-          update(layerImage);
+          update(layerObject);
           feature.changed();
         }
       }
diff --git a/src/components/Map/MapViewer/utils/shapes/text/Text.ts b/src/components/Map/MapViewer/utils/shapes/text/Text.ts
deleted file mode 100644
index c1bc5799..00000000
--- a/src/components/Map/MapViewer/utils/shapes/text/Text.ts
+++ /dev/null
@@ -1,145 +0,0 @@
-/* eslint-disable no-magic-numbers */
-import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
-import Style from 'ol/style/Style';
-import { Point } from 'ol/geom';
-import { Feature } from 'ol';
-import { FeatureLike } from 'ol/Feature';
-import { MapInstance } from '@/types/map';
-import { Color } from '@/types/models';
-import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewer.constants';
-import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types';
-import getTextCoords from '@/components/Map/MapViewer/utils/shapes/text/getTextCoords';
-import getTextStyle from '@/components/Map/MapViewer/utils/shapes/text/getTextStyle';
-import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex';
-import Polygon from 'ol/geom/Polygon';
-import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke';
-import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle';
-import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle';
-import { Stroke } from 'ol/style';
-
-export interface TextProps {
-  x: number;
-  y: number;
-  width: number;
-  height: number;
-  layer: number;
-  zIndex: number;
-  text: string;
-  fontSize: number;
-  fontColor: Color;
-  borderColor: Color;
-  verticalAlign: VerticalAlign;
-  horizontalAlign: HorizontalAlign;
-  pointToProjection: UsePointToProjectionResult;
-  mapInstance: MapInstance;
-}
-
-export default class Text {
-  text: string;
-
-  fontSize: number;
-
-  style: Style;
-
-  polygonStyle: Style;
-
-  strokeStyle: Stroke;
-
-  point: Point;
-
-  feature: Feature<Point>;
-
-  constructor({
-    x,
-    y,
-    width,
-    height,
-    layer,
-    zIndex,
-    text,
-    fontSize,
-    fontColor,
-    borderColor,
-    verticalAlign,
-    horizontalAlign,
-    pointToProjection,
-    mapInstance,
-  }: TextProps) {
-    this.text = text;
-    this.fontSize = fontSize;
-
-    const textCoords = getTextCoords({
-      x,
-      y,
-      height,
-      width,
-      fontSize,
-      verticalAlign,
-      horizontalAlign,
-      pointToProjection,
-    });
-    const borderPolygon = 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 }),
-      ],
-    ]);
-    this.strokeStyle = getStroke({
-      color: rgbToHex(borderColor),
-      width: 1,
-    });
-    this.polygonStyle = getStyle({
-      geometry: borderPolygon,
-      borderColor,
-      fillColor: { rgb: 0, alpha: 0 },
-      lineWidth: 1,
-      zIndex,
-    });
-
-    const textStyle = getTextStyle({
-      text,
-      fontSize,
-      color: rgbToHex(fontColor),
-      zIndex,
-      horizontalAlign,
-    });
-    this.point = new Point(textCoords);
-    this.style = textStyle;
-    this.style.setGeometry(this.point);
-
-    this.feature = new Feature({
-      geometry: this.point,
-      getScale: (resolution: number): number => {
-        const maxZoom = mapInstance?.getView().get('originalMaxZoom');
-        if (maxZoom) {
-          const minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom);
-          if (minResolution) {
-            return Math.round((minResolution / resolution) * 100) / 100;
-          }
-        }
-        return 1;
-      },
-      layer,
-    });
-
-    this.feature.setStyle(this.getStyle.bind(this));
-  }
-
-  protected getStyle(feature: FeatureLike, resolution: number): Style | Array<Style> | void {
-    const getScale = feature.get('getScale');
-    let scale = 1;
-    if (getScale instanceof Function) {
-      scale = getScale(resolution);
-    }
-    if (scale < TEXT_CUTOFF_SCALE) {
-      return undefined;
-    }
-    return [
-      getScaledElementStyle(this.polygonStyle, this.strokeStyle, scale),
-      getScaledElementStyle(this.style, undefined, scale),
-    ];
-  }
-}
diff --git a/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts
index e3224fc9..26acfb6b 100644
--- a/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts
+++ b/src/components/Map/MapViewer/utils/shapes/text/getTextCoords.ts
@@ -12,6 +12,7 @@ export default function getTextCoords({
   verticalAlign,
   horizontalAlign,
   pointToProjection,
+  useProjection = true,
 }: {
   x: number;
   y: number;
@@ -20,7 +21,8 @@ export default function getTextCoords({
   fontSize: number;
   verticalAlign: VerticalAlign;
   horizontalAlign: HorizontalAlign;
-  pointToProjection: UsePointToProjectionResult;
+  pointToProjection?: UsePointToProjectionResult;
+  useProjection?: boolean;
 }): Coordinate {
   const minX = x;
   const maxX = x + width;
@@ -41,5 +43,8 @@ export default function getTextCoords({
     textX = maxX;
   }
 
-  return pointToProjection({ x: textX, y: textY });
+  if (useProjection && pointToProjection) {
+    return pointToProjection({ x: textX, y: textY });
+  }
+  return [textX, textY];
 }
diff --git a/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts b/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts
index 84018d80..6fd6ec3a 100644
--- a/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts
+++ b/src/components/Map/MapViewer/utils/websocket/processLayerImage.ts
@@ -2,7 +2,7 @@ import { WebSocketEntityUpdateInterface } from '@/utils/websocket-entity-updates
 import { store } from '@/redux/store';
 import { ENTITY_OPERATION_TYPES } from '@/utils/websocket-entity-updates/webSocketEntityUpdates.constants';
 import { getLayerImage } from '@/redux/layers/layers.thunks';
-import updateGlyph from '@/components/Map/MapViewer/utils/shapes/elements/Glyph/updateGlyph';
+import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement';
 import { MapInstance } from '@/types/map';
 import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer';
 import { layerDeleteImage } from '@/redux/layers/layers.slice';
@@ -38,7 +38,7 @@ export default async function processLayerImage({
         drawFunctionKey: 'drawImage',
       });
     } else {
-      updateGlyph(mapInstance, data.layerId, resultImage);
+      updateElement(mapInstance, data.layerId, resultImage);
     }
   } else if (data.type === ENTITY_OPERATION_TYPES.ENTITY_DELETED) {
     dispatch(
diff --git a/src/components/Map/MapViewer/utils/websocket/processLayerText.ts b/src/components/Map/MapViewer/utils/websocket/processLayerText.ts
index f31697c4..e1740c97 100644
--- a/src/components/Map/MapViewer/utils/websocket/processLayerText.ts
+++ b/src/components/Map/MapViewer/utils/websocket/processLayerText.ts
@@ -4,6 +4,9 @@ import { ENTITY_OPERATION_TYPES } from '@/utils/websocket-entity-updates/webSock
 import { getLayerText } from '@/redux/layers/layers.thunks';
 import { MapInstance } from '@/types/map';
 import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer';
+import { layerDeleteText } from '@/redux/layers/layers.slice';
+import removeElementFromLayer from '@/components/Map/MapViewer/utils/shapes/elements/removeElementFromLayer';
+import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement';
 
 export default async function processLayerText({
   data,
@@ -13,7 +16,10 @@ export default async function processLayerText({
   mapInstance: MapInstance;
 }): Promise<void> {
   const { dispatch } = store;
-  if (data.type === ENTITY_OPERATION_TYPES.ENTITY_CREATED) {
+  if (
+    data.type === ENTITY_OPERATION_TYPES.ENTITY_CREATED ||
+    data.type === ENTITY_OPERATION_TYPES.ENTITY_UPDATED
+  ) {
     const resultText = await dispatch(
       getLayerText({
         modelId: data.mapId,
@@ -24,11 +30,24 @@ export default async function processLayerText({
     if (!resultText) {
       return;
     }
-    drawElementOnLayer({
-      mapInstance,
-      activeLayer: data.layerId,
-      object: resultText,
-      drawFunctionKey: 'drawText',
-    });
+    if (data.type === ENTITY_OPERATION_TYPES.ENTITY_CREATED) {
+      drawElementOnLayer({
+        mapInstance,
+        activeLayer: data.layerId,
+        object: resultText,
+        drawFunctionKey: 'drawText',
+      });
+    } else {
+      updateElement(mapInstance, data.layerId, resultText);
+    }
+  } else if (data.type === ENTITY_OPERATION_TYPES.ENTITY_DELETED) {
+    dispatch(
+      layerDeleteText({
+        modelId: data.mapId,
+        layerId: data.layerId,
+        textId: data.entityId,
+      }),
+    );
+    removeElementFromLayer({ mapInstance, layerId: data.layerId, featureId: data.entityId });
   }
 }
diff --git a/src/models/layerTextSchema.ts b/src/models/layerTextSchema.ts
index 0ec90665..a575b139 100644
--- a/src/models/layerTextSchema.ts
+++ b/src/models/layerTextSchema.ts
@@ -11,8 +11,8 @@ export const layerTextSchema = z.object({
   layer: z.number(),
   fontSize: z.number(),
   notes: z.string(),
-  verticalAlign: z.string(),
-  horizontalAlign: z.string(),
+  verticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']),
+  horizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']),
   backgroundColor: colorSchema,
   borderColor: colorSchema,
   color: colorSchema,
diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts
index 9eb33c02..18186d6f 100644
--- a/src/redux/apiPath.ts
+++ b/src/redux/apiPath.ts
@@ -64,6 +64,10 @@ export const apiPath = {
     `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}`,
+  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 =>
+    `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/${textId}`,
   getLayer: (modelId: number, layerId: number): string =>
     `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}`,
   getGlyphImage: (glyphId: number): string =>
diff --git a/src/redux/layers/layers.reducers.ts b/src/redux/layers/layers.reducers.ts
index 0213d714..238a3441 100644
--- a/src/redux/layers/layers.reducers.ts
+++ b/src/redux/layers/layers.reducers.ts
@@ -198,3 +198,35 @@ export const layerAddTextReducer = (
   }
   layer.texts[layerText.id] = layerText;
 };
+
+export const layerUpdateTextReducer = (
+  state: LayersState,
+  action: PayloadAction<{ modelId: number; layerId: number; layerText: LayerText }>,
+): void => {
+  const { modelId, layerId, layerText } = action.payload;
+  const { data } = state[modelId];
+  if (!data) {
+    return;
+  }
+  const layer = data.layers.find(layerState => layerState.details.id === layerId);
+  if (!layer) {
+    return;
+  }
+  layer.texts[layerText.id] = layerText;
+};
+
+export const layerDeleteTextReducer = (
+  state: LayersState,
+  action: PayloadAction<{ modelId: number; layerId: number; textId: number }>,
+): void => {
+  const { modelId, layerId, textId } = action.payload;
+  const { data } = state[modelId];
+  if (!data) {
+    return;
+  }
+  const layer = data.layers.find(layerState => layerState.details.id === layerId);
+  if (!layer) {
+    return;
+  }
+  delete layer.texts[textId];
+};
diff --git a/src/redux/layers/layers.slice.ts b/src/redux/layers/layers.slice.ts
index dcd20ceb..871012fc 100644
--- a/src/redux/layers/layers.slice.ts
+++ b/src/redux/layers/layers.slice.ts
@@ -12,6 +12,8 @@ import {
   setDrawLayerReducer,
   setLayerToInactiveReducer,
   setLayerToActiveReducer,
+  layerDeleteTextReducer,
+  layerUpdateTextReducer,
 } from '@/redux/layers/layers.reducers';
 
 export const layersSlice = createSlice({
@@ -25,6 +27,8 @@ export const layersSlice = createSlice({
     layerUpdateImage: layerUpdateImageReducer,
     layerDeleteImage: layerDeleteImageReducer,
     layerAddText: layerAddTextReducer,
+    layerUpdateText: layerUpdateTextReducer,
+    layerDeleteText: layerDeleteTextReducer,
     setDrawLayer: setDrawLayerReducer,
   },
   extraReducers: builder => {
@@ -42,6 +46,8 @@ export const {
   layerUpdateImage,
   layerDeleteImage,
   layerAddText,
+  layerUpdateText,
+  layerDeleteText,
   setDrawLayer,
 } = layersSlice.actions;
 
diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts
index 847d84d2..66035fd8 100644
--- a/src/redux/layers/layers.thunks.ts
+++ b/src/redux/layers/layers.thunks.ts
@@ -1,7 +1,7 @@
 /* eslint-disable no-magic-numbers */
 import { z as zod } from 'zod';
 import { apiPath } from '@/redux/apiPath';
-import { Layer, LayerImage, Layers, LayerText } from '@/types/models';
+import { Color, Layer, LayerImage, Layers, LayerText } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { ThunkConfig } from '@/types/store';
@@ -22,7 +22,11 @@ import { layerLineSchema } from '@/models/layerLineSchema';
 import { layerImageSchema } from '@/models/layerImageSchema';
 import arrayToKeyValue from '@/utils/array/arrayToKeyValue';
 import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types';
-import { BoundingBox } from '@/components/Map/MapViewer/MapViewer.types';
+import {
+  BoundingBox,
+  HorizontalAlign,
+  VerticalAlign,
+} from '@/components/Map/MapViewer/MapViewer.types';
 
 export const getLayer = createAsyncThunk<
   Layer | null,
@@ -307,3 +311,81 @@ export const getLayerText = createAsyncThunk<
     return Promise.reject(getError({ error }));
   }
 });
+
+export const removeLayerText = createAsyncThunk<
+  null,
+  { modelId: number; layerId: number; textId: number },
+  ThunkConfig
+>('layers/removeLayerText', async ({ modelId, layerId, textId }) => {
+  try {
+    await axiosInstanceNewAPI.delete<void>(apiPath.removeLayerText(modelId, layerId, textId));
+    return null;
+  } catch (error) {
+    return Promise.reject(getError({ error }));
+  }
+});
+
+export const updateLayerText = createAsyncThunk<
+  LayerText | null,
+  {
+    modelId: number;
+    layerId: number;
+    id: number;
+    x: number;
+    y: number;
+    z: number;
+    width: number;
+    height: number;
+    fontSize: number;
+    notes: string;
+    verticalAlign: VerticalAlign;
+    horizontalAlign: HorizontalAlign;
+    color: Color;
+    borderColor: Color;
+  },
+  ThunkConfig
+>(
+  'layers/updateLayerText',
+  async ({
+    modelId,
+    layerId,
+    id,
+    x,
+    y,
+    z,
+    width,
+    height,
+    fontSize,
+    notes,
+    verticalAlign,
+    horizontalAlign,
+    color,
+    borderColor,
+  }) => {
+    try {
+      const { data } = await axiosInstanceNewAPI.put<LayerText>(
+        apiPath.updateLayerText(modelId, layerId, id),
+        {
+          x,
+          y,
+          z,
+          width,
+          height,
+          fontSize,
+          notes,
+          verticalAlign,
+          horizontalAlign,
+          color,
+          borderColor,
+        },
+      );
+      const isDataValid = validateDataUsingZodSchema(data, layerTextSchema);
+      if (isDataValid) {
+        return data;
+      }
+      return null;
+    } catch (error) {
+      return Promise.reject(getError({ error }));
+    }
+  },
+);
diff --git a/src/redux/mapEditTools/mapEditTools.mock.ts b/src/redux/mapEditTools/mapEditTools.mock.ts
index d6fe529c..fbbacec7 100644
--- a/src/redux/mapEditTools/mapEditTools.mock.ts
+++ b/src/redux/mapEditTools/mapEditTools.mock.ts
@@ -2,5 +2,5 @@ import { MapEditToolsState } from '@/redux/mapEditTools/mapEditTools.types';
 
 export const MAP_EDIT_TOOLS_STATE_INITIAL_MOCK: MapEditToolsState = {
   activeAction: null,
-  layerImageObject: null,
+  layerObject: null,
 };
diff --git a/src/redux/mapEditTools/mapEditTools.reducers.ts b/src/redux/mapEditTools/mapEditTools.reducers.ts
index da3f5f7f..d45e719f 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 } from '@/types/models';
+import { LayerImage, LayerText } from '@/types/models';
 
 export const mapEditToolsSetActiveActionReducer = (
   state: MapEditToolsState,
@@ -13,7 +13,7 @@ export const mapEditToolsSetActiveActionReducer = (
 
 export const mapEditToolsSetLayerObjectReducer = (
   state: MapEditToolsState,
-  action: PayloadAction<LayerImage | null>,
+  action: PayloadAction<LayerImage | LayerText | null>,
 ): void => {
-  state.layerImageObject = action.payload;
+  state.layerObject = action.payload;
 };
diff --git a/src/redux/mapEditTools/mapEditTools.selectors.ts b/src/redux/mapEditTools/mapEditTools.selectors.ts
index 2b29bd35..d3ea7d12 100644
--- a/src/redux/mapEditTools/mapEditTools.selectors.ts
+++ b/src/redux/mapEditTools/mapEditTools.selectors.ts
@@ -9,9 +9,9 @@ export const mapEditToolsActiveActionSelector = createSelector(
   state => state.activeAction,
 );
 
-export const mapEditToolsLayerImageObjectSelector = createSelector(
+export const mapEditToolsLayerObjectSelector = createSelector(
   mapEditToolsSelector,
-  state => state.layerImageObject,
+  state => state.layerObject,
 );
 
 export const isMapEditToolsActiveSelector = createSelector(mapEditToolsSelector, state =>
diff --git a/src/redux/mapEditTools/mapEditTools.types.ts b/src/redux/mapEditTools/mapEditTools.types.ts
index e141e6b8..4c216c40 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 } from '@/types/models';
+import { LayerImage, LayerText } from '@/types/models';
 
 export type MapEditToolsState = {
   activeAction: keyof typeof MAP_EDIT_ACTIONS | null;
-  layerImageObject: LayerImage | null;
+  layerObject: LayerImage | LayerText | null;
 };
-- 
GitLab


From 09dff5302aad6a606bc317acb391aa0a7b2cc0bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Mon, 17 Feb 2025 13:08:07 +0100
Subject: [PATCH 2/8] feat(layer-text): Add editing text notes, font size,
 color alignment etc.

---
 ...rImageObjectEditFactoryModal.component.tsx |   2 +-
 .../LayerTextEditFactoryModal.component.tsx   | 109 ++++++++++++++++++
 .../LayerTextFactory.constants.ts             |  12 +-
 .../LayerTextFactory.types.ts                 |   5 +-
 .../LayerTextForm.component.tsx               |   4 +-
 .../FunctionalArea/Modal/Modal.component.tsx  |   6 +
 .../ModalLayout/ModalLayout.component.tsx     |   3 +-
 .../LayersDrawerObjectsList.component.tsx     |  59 +++++++++-
 .../Map/MapViewer/MapViewer.types.ts          |   2 +-
 .../utils/shapes/elements/Glyph/Glyph.ts      |  52 +++++----
 .../utils/shapes/layer/elements/LayerText.ts  |  56 ++++-----
 src/models/bioEntitySchema.ts                 |   2 +-
 src/models/layerTextSchema.ts                 |   2 +-
 src/models/modelElementModificationSchema.ts  |   2 +-
 src/models/modelElementSchema.ts              |   2 +-
 src/redux/modal/modal.reducers.ts             |   6 +
 src/redux/modal/modal.slice.ts                |   3 +
 src/types/modal.ts                            |   3 +-
 18 files changed, 257 insertions(+), 73 deletions(-)
 create mode 100644 src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx

diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
index dc280845..b90d5b25 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.tsx
@@ -69,7 +69,7 @@ export const LayerImageObjectEditFactoryModal: React.FC = () => {
       const typedError = error as SerializedError;
       showToast({
         type: 'error',
-        message: typedError.message || 'An error occurred while adding a new image',
+        message: typedError.message || 'An error occurred while editing the layer image',
       });
     } finally {
       setIsSending(false);
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx
new file mode 100644
index 00000000..c73e9d93
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component.tsx
@@ -0,0 +1,109 @@
+/* eslint-disable no-magic-numbers */
+import React, { useState } from 'react';
+import './LayerTextFactoryModal.styles.css';
+import { LayerTextForm } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component';
+import { LoadingIndicator } from '@/shared/LoadingIndicator';
+import { Button } from '@/shared/Button';
+import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types';
+import { Color } from '@/types/models';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { currentModelIdSelector } from '@/redux/models/models.selectors';
+import { showToast } from '@/utils/showToast';
+import { closeModal } from '@/redux/modal/modal.slice';
+import { SerializedError } from '@reduxjs/toolkit';
+import { updateLayerText } from '@/redux/layers/layers.thunks';
+import { layerUpdateText } from '@/redux/layers/layers.slice';
+import { useMapInstance } from '@/utils/context/mapInstanceContext';
+import { mapEditToolsSetLayerObject } from '@/redux/mapEditTools/mapEditTools.slice';
+import { mapEditToolsLayerObjectSelector } from '@/redux/mapEditTools/mapEditTools.selectors';
+import updateElement from '@/components/Map/MapViewer/utils/shapes/layer/utils/updateElement';
+
+export const LayerTextEditFactoryModal: React.FC = () => {
+  const layerObject = useAppSelector(mapEditToolsLayerObjectSelector);
+  const currentModelId = useAppSelector(currentModelIdSelector);
+  const dispatch = useAppDispatch();
+  const { mapInstance } = useMapInstance();
+
+  if (!layerObject || !('notes' in layerObject)) {
+    throw new Error('Invalid layer text object');
+  }
+
+  const [isSending, setIsSending] = useState<boolean>(false);
+  const [data, setData] = useState<LayerTextFactoryForm>({
+    notes: layerObject.notes,
+    fontSize: layerObject.fontSize,
+    horizontalAlign: layerObject.horizontalAlign,
+    verticalAlign: layerObject.verticalAlign,
+    color: layerObject.color,
+    borderColor: layerObject.borderColor,
+  });
+
+  const handleSubmit = async (): Promise<void> => {
+    if (!layerObject) {
+      return;
+    }
+    try {
+      const layerText = await dispatch(
+        updateLayerText({
+          modelId: currentModelId,
+          layerId: layerObject.layer,
+          id: layerObject.id,
+          x: layerObject.x,
+          y: layerObject.y,
+          z: layerObject.z,
+          width: layerObject.width,
+          height: layerObject.height,
+          notes: data.notes,
+          fontSize: data.fontSize,
+          horizontalAlign: data.horizontalAlign,
+          verticalAlign: data.verticalAlign,
+          color: data.color,
+          borderColor: data.borderColor,
+        }),
+      ).unwrap();
+
+      if (layerText) {
+        dispatch(layerUpdateText({ modelId: currentModelId, layerId: layerText.layer, layerText }));
+        dispatch(mapEditToolsSetLayerObject(layerText));
+        updateElement(mapInstance, layerText.layer, layerText);
+      }
+      showToast({
+        type: 'success',
+        message: 'The text 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 layer text',
+      });
+    } finally {
+      setIsSending(false);
+    }
+  };
+
+  const changeValues = (value: string | number | Color, key: string): void => {
+    setData(prevData => ({ ...prevData, [key]: value }));
+  };
+
+  return (
+    <div className="relative w-[900px] border border-t-[#E1E0E6] bg-white p-[24px]">
+      {isSending && (
+        <div className="c-layer-text-factory-modal-loader">
+          <LoadingIndicator width={44} height={44} />
+        </div>
+      )}
+      <LayerTextForm onChange={changeValues} data={data} />
+      <hr className="py-2" />
+      <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/LayerTextFactoryModal/LayerTextFactory.constants.ts b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.constants.ts
index feddd690..cbee5e1c 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.constants.ts
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.constants.ts
@@ -1,21 +1,21 @@
 /* eslint-disable no-magic-numbers */
 
+import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types';
+
 export const TEXT_FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 60, 72, 96];
 
 export const TEXT_HORIZONTAL_ALIGNMENTS = [
   { id: 'LEFT', name: 'left' },
   { id: 'RIGHT', name: 'right' },
   { id: 'CENTER', name: 'center' },
-  { id: 'END', name: 'end' },
-  { id: 'START', name: 'start' },
-];
+] as const;
 
 export const TEXT_VERTICAL_ALIGNMENTS = [
   { id: 'TOP', name: 'top' },
   { id: 'MIDDLE', name: 'middle' },
   { id: 'BOTTOM', name: 'bottom' },
-];
+] as const;
 
 export const DEFAULT_TEXT_FONT_SIZE = 12;
-export const DEFAULT_HORIZONTAL_ALIGNMENT = TEXT_HORIZONTAL_ALIGNMENTS[0].id;
-export const DEFAULT_VERTICAL_ALIGNMENT = TEXT_VERTICAL_ALIGNMENTS[0].id;
+export const DEFAULT_HORIZONTAL_ALIGNMENT: HorizontalAlign = TEXT_HORIZONTAL_ALIGNMENTS[0].id;
+export const DEFAULT_VERTICAL_ALIGNMENT: VerticalAlign = TEXT_VERTICAL_ALIGNMENTS[0].id;
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types.ts b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types.ts
index bb47feaa..231eb942 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types.ts
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactory.types.ts
@@ -1,10 +1,11 @@
 import { Color } from '@/types/models';
+import { HorizontalAlign, VerticalAlign } from '@/components/Map/MapViewer/MapViewer.types';
 
 export type LayerTextFactoryForm = {
   notes: string;
   fontSize: number;
-  horizontalAlign: string;
-  verticalAlign: string;
+  horizontalAlign: HorizontalAlign;
+  verticalAlign: VerticalAlign;
   color: Color;
   borderColor: Color;
 };
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx
index 22bcde3c..2dac649b 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextForm.component.tsx
@@ -41,7 +41,7 @@ export const LayerTextForm = ({ data, onChange }: LayerTextFormProps): React.JSX
         <div>
           <span>Horizontal alignment:</span>
           <Select
-            options={TEXT_HORIZONTAL_ALIGNMENTS}
+            options={[...TEXT_HORIZONTAL_ALIGNMENTS]}
             selectedId={data.horizontalAlign}
             testId="horizontal-alignment-select"
             onChange={value => onChange(value, 'horizontalAlign')}
@@ -50,7 +50,7 @@ export const LayerTextForm = ({ data, onChange }: LayerTextFormProps): React.JSX
         <div>
           <span>Vertical alignment:</span>
           <Select
-            options={TEXT_VERTICAL_ALIGNMENTS}
+            options={[...TEXT_VERTICAL_ALIGNMENTS]}
             selectedId={data.verticalAlign}
             testId="vertical-alignment-select"
             onChange={value => onChange(value, 'verticalAlign')}
diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx
index 6cc342ee..bbd8c7d5 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -10,6 +10,7 @@ import {
   LayerImageObjectFactoryModal,
 } from '@/components/FunctionalArea/Modal/LayerImageObjectModal';
 import { LayerTextFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component';
+import { LayerTextEditFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component';
 import { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
 import { ErrorReportModal } from './ErrorReportModal';
@@ -105,6 +106,11 @@ export const Modal = (): React.ReactNode => {
           <LayerTextFactoryModal />
         </ModalLayout>
       )}
+      {isOpen && modalName === 'layer-text-edit-factory' && (
+        <ModalLayout>
+          <LayerTextEditFactoryModal />
+        </ModalLayout>
+      )}
     </>
   );
 };
diff --git a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
index 59d85797..e9fd515a 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-text-factory' && 'h-auto w-[900px]',
+            ['layer-text-factory', 'layer-text-edit-factory'].includes(modalName) &&
+              'h-auto w-[900px]',
             ['layer-image-object-factory', 'layer-image-object-edit-factory'].includes(modalName) &&
               'h-auto w-[800px]',
             ['edit-overlay', 'logged-in-menu'].includes(modalName) && 'h-auto w-[432px]',
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index fa98e051..70a6acf5 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -13,8 +13,14 @@ import {
   removeLayerImage,
   removeLayerText,
   updateLayerImageObject,
+  updateLayerText,
 } from '@/redux/layers/layers.thunks';
-import { layerDeleteImage, layerDeleteText, layerUpdateImage } from '@/redux/layers/layers.slice';
+import {
+  layerDeleteImage,
+  layerDeleteText,
+  layerUpdateImage,
+  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';
@@ -28,7 +34,10 @@ import { useSetBounds } from '@/utils/map/useSetBounds';
 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';
+import {
+  openLayerImageObjectEditFactoryModal,
+  openLayerTextEditFactoryModal,
+} from '@/redux/modal/modal.slice';
 
 interface LayersDrawerObjectsListProps {
   layerId: number;
@@ -173,6 +182,42 @@ export const LayersDrawerObjectsList = ({
     await updateImageZIndex({ zIndex: lowestZIndex - 1, layerImage });
   };
 
+  const updateTextZIndex = async ({
+    zIndex,
+    layerText,
+  }: {
+    zIndex: number;
+    layerText: LayerText;
+  }): Promise<void> => {
+    const newLayerText = await dispatch(
+      updateLayerText({
+        modelId: currentModelId,
+        layerId: layerText.layer,
+        ...layerText,
+        z: zIndex,
+      }),
+    ).unwrap();
+    if (newLayerText) {
+      dispatch(
+        layerUpdateText({
+          modelId: currentModelId,
+          layerId: newLayerText.layer,
+          layerText: newLayerText,
+        }),
+      );
+      dispatch(mapEditToolsSetLayerObject(newLayerText));
+      updateElement(mapInstance, newLayerText.layer, newLayerText);
+    }
+  };
+
+  const bringTextToFront = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: highestZIndex + 1, layerText });
+  };
+
+  const bringTextToBack = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: lowestZIndex - 1, layerText });
+  };
+
   const centerObject = (layerObject: LayerImage | LayerText): void => {
     if (mapEditToolsLayerImageObject && mapEditToolsLayerImageObject.id === layerObject.id) {
       const point1 = pointToProjection({ x: layerObject.x, y: layerObject.y });
@@ -188,6 +233,10 @@ export const LayersDrawerObjectsList = ({
     dispatch(openLayerImageObjectEditFactoryModal());
   };
 
+  const editText = (): void => {
+    dispatch(openLayerTextEditFactoryModal());
+  };
+
   if (!layer) {
     return null;
   }
@@ -208,11 +257,11 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerTextItem
           layerText={layerText}
           key={layerText.id}
-          bringToFront={() => {}}
-          bringToBack={() => {}}
+          bringToFront={() => bringTextToFront(layerText)}
+          bringToBack={() => bringTextToBack(layerText)}
           removeObject={() => removeObject(layerText)}
           centerObject={() => centerObject(layerText)}
-          editObject={() => {}}
+          editObject={() => editText()}
           isLayerVisible={isLayerVisible}
           isLayerActive={isLayerActive}
         />
diff --git a/src/components/Map/MapViewer/MapViewer.types.ts b/src/components/Map/MapViewer/MapViewer.types.ts
index f10c9070..4204320f 100644
--- a/src/components/Map/MapViewer/MapViewer.types.ts
+++ b/src/components/Map/MapViewer/MapViewer.types.ts
@@ -8,7 +8,7 @@ export type MapConfig = {
 };
 
 export type VerticalAlign = 'TOP' | 'MIDDLE' | 'BOTTOM';
-export type HorizontalAlign = 'LEFT' | 'RIGHT' | 'CENTER' | 'END' | 'START';
+export type HorizontalAlign = 'LEFT' | 'RIGHT' | 'CENTER';
 
 export type OverlayBioEntityGroupedElementsType = {
   [id: string]: Array<OverlayBioEntityRender & { amount: number }>;
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 342cdfac..57b36875 100644
--- a/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts
+++ b/src/components/Map/MapViewer/utils/shapes/elements/Glyph/Glyph.ts
@@ -34,13 +34,13 @@ export type GlyphProps = {
 export default class Glyph {
   feature: Feature<Polygon>;
 
-  style: Style = new Style({});
+  style: Style = new Style();
 
-  noGlyphStyle: Style;
+  noGlyphStyle: Style = new Style();
 
   imageScale: number = 1;
 
-  polygonStyle: Style;
+  polygonStyle: Style = new Style();
 
   polygon: Polygon = new Polygon([]);
 
@@ -113,26 +113,7 @@ export default class Glyph {
 
     this.drawPolygon();
 
-    this.polygonStyle = getStyle({
-      geometry: this.polygon,
-      zIndex: this.zIndex,
-      borderColor: { ...WHITE_COLOR, alpha: 0 },
-      fillColor: { ...WHITE_COLOR, alpha: 0 },
-    });
-
-    this.noGlyphStyle = getStyle({
-      geometry: this.polygon,
-      zIndex: this.zIndex,
-      fillColor: '#E7E7E7',
-    });
-    this.noGlyphStyle.setText(
-      new Text({
-        text: 'No image',
-        font: '12pt Arial',
-        fill: getFill({ color: '#000' }),
-        overflow: true,
-      }),
-    );
+    this.setStyles();
 
     this.feature = new Feature({
       geometry: this.polygon,
@@ -172,6 +153,29 @@ export default class Glyph {
     ]);
   }
 
+  private setStyles(): void {
+    this.polygonStyle = getStyle({
+      geometry: this.polygon,
+      zIndex: this.zIndex,
+      borderColor: { ...WHITE_COLOR, alpha: 0 },
+      fillColor: { ...WHITE_COLOR, alpha: 0 },
+    });
+
+    this.noGlyphStyle = getStyle({
+      geometry: this.polygon,
+      zIndex: this.zIndex,
+      fillColor: '#E7E7E7',
+    });
+    this.noGlyphStyle.setText(
+      new Text({
+        text: 'No image',
+        font: '12pt Arial',
+        fill: getFill({ color: '#000' }),
+        overflow: true,
+      }),
+    );
+  }
+
   private refreshPolygon(): void {
     this.drawPolygon();
     this.polygonStyle.setGeometry(this.polygon);
@@ -195,7 +199,7 @@ export default class Glyph {
     this.glyphId = imageObject.glyph;
 
     this.refreshPolygon();
-    this.refreshZIndex();
+    this.setStyles();
     this.drawImage();
     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 133034cf..26565345 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerText.ts
@@ -5,7 +5,7 @@ import { Point } from 'ol/geom';
 import { Feature } from 'ol';
 import { FeatureLike } from 'ol/Feature';
 import { MapInstance } from '@/types/map';
-import { LayerText as LayerTextModel, Color } from '@/types/models';
+import { Color, LayerText as LayerTextModel } from '@/types/models';
 import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewer.constants';
 import {
   BoundingBox,
@@ -77,13 +77,13 @@ export default class LayerText {
 
   fontSize: number;
 
-  style: Style;
+  style: Style = new Style();
 
-  polygonStyle: Style;
+  polygonStyle: Style = new Style();
 
   polygon: Polygon = new Polygon([]);
 
-  strokeStyle: Stroke;
+  strokeStyle: Stroke = new Stroke();
 
   point: Point;
 
@@ -140,29 +140,11 @@ export default class LayerText {
       horizontalAlign,
       pointToProjection,
     });
+    this.point = new Point(textCoords);
+
     this.drawPolygon();
-    this.strokeStyle = getStroke({
-      color: rgbToHex(borderColor),
-      width: 1,
-    });
-    this.polygonStyle = getStyle({
-      geometry: this.polygon,
-      borderColor,
-      fillColor: { rgb: 0, alpha: 0 },
-      lineWidth: 1,
-      zIndex,
-    });
 
-    const textStyle = getTextStyle({
-      text,
-      fontSize,
-      color: rgbToHex(color),
-      zIndex,
-      horizontalAlign,
-    });
-    this.point = new Point(textCoords);
-    this.style = textStyle;
-    this.style.setGeometry(this.point);
+    this.setStyles();
 
     this.feature = new Feature({
       geometry: this.polygon,
@@ -254,6 +236,28 @@ export default class LayerText {
     this.feature.changed();
   }
 
+  private setStyles(): void {
+    this.strokeStyle = getStroke({
+      color: rgbToHex(this.borderColor),
+      width: 1,
+    });
+    this.polygonStyle = getStyle({
+      geometry: this.polygon,
+      borderColor: this.borderColor,
+      fillColor: { rgb: 0, alpha: 0 },
+      lineWidth: 1,
+      zIndex: this.zIndex,
+    });
+    this.style = getTextStyle({
+      text: this.text,
+      fontSize: this.fontSize,
+      color: rgbToHex(this.color),
+      zIndex: this.zIndex,
+      horizontalAlign: this.horizontalAlign,
+    });
+    this.style.setGeometry(this.point);
+  }
+
   private updateElement(layerText: LayerTextModel): void {
     this.elementId = layerText.id;
     this.x = layerText.x;
@@ -269,7 +273,7 @@ export default class LayerText {
     this.horizontalAlign = layerText.horizontalAlign;
 
     this.refreshPolygon();
-    this.refreshZIndex();
+    this.setStyles();
     this.feature.changed();
   }
 
diff --git a/src/models/bioEntitySchema.ts b/src/models/bioEntitySchema.ts
index ec78db95..5c754989 100644
--- a/src/models/bioEntitySchema.ts
+++ b/src/models/bioEntitySchema.ts
@@ -26,7 +26,7 @@ export const bioEntitySchema = z.object({
   nameWidth: z.number(),
   nameHeight: z.number(),
   nameVerticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']),
-  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']),
+  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER']),
   width: z
     .number()
     .optional()
diff --git a/src/models/layerTextSchema.ts b/src/models/layerTextSchema.ts
index a575b139..d0460100 100644
--- a/src/models/layerTextSchema.ts
+++ b/src/models/layerTextSchema.ts
@@ -12,7 +12,7 @@ export const layerTextSchema = z.object({
   fontSize: z.number(),
   notes: z.string(),
   verticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']),
-  horizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']),
+  horizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER']),
   backgroundColor: colorSchema,
   borderColor: colorSchema,
   color: colorSchema,
diff --git a/src/models/modelElementModificationSchema.ts b/src/models/modelElementModificationSchema.ts
index 3d7f318e..d69ce89a 100644
--- a/src/models/modelElementModificationSchema.ts
+++ b/src/models/modelElementModificationSchema.ts
@@ -15,7 +15,7 @@ export const modelElementModificationSchema = z.object({
   nameWidth: z.number(),
   nameHeight: z.number(),
   nameVerticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']),
-  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']),
+  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER']),
   species: z.number(),
   borderColor: colorSchema,
   fillColor: colorSchema,
diff --git a/src/models/modelElementSchema.ts b/src/models/modelElementSchema.ts
index 86b82f67..32eae25e 100644
--- a/src/models/modelElementSchema.ts
+++ b/src/models/modelElementSchema.ts
@@ -36,7 +36,7 @@ export const modelElementSchema = z.object({
   nameWidth: z.number(),
   nameHeight: z.number(),
   nameVerticalAlign: z.enum(['TOP', 'MIDDLE', 'BOTTOM']),
-  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER', 'END', 'START']),
+  nameHorizontalAlign: z.enum(['LEFT', 'RIGHT', 'CENTER']),
   synonyms: z.array(z.string()),
   formerSymbols: z.array(z.string()),
   activity: z.boolean().optional(),
diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts
index 1b903069..923d2858 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -165,3 +165,9 @@ export const openLayerTextFactoryModalReducer = (
   state.modalTitle = 'Add text';
   state.isOpen = true;
 };
+
+export const openLayerTextEditFactoryModalReducer = (state: ModalState): void => {
+  state.isOpen = true;
+  state.modalName = 'layer-text-edit-factory';
+  state.modalTitle = 'Edit text';
+};
diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts
index bf01d86a..ed74baec 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -20,6 +20,7 @@ import {
   openLayerImageObjectFactoryModalReducer,
   openLayerImageObjectEditFactoryModalReducer,
   openLayerTextFactoryModalReducer,
+  openLayerTextEditFactoryModalReducer,
 } from './modal.reducers';
 
 const modalSlice = createSlice({
@@ -45,6 +46,7 @@ const modalSlice = createSlice({
     openLayerImageObjectFactoryModal: openLayerImageObjectFactoryModalReducer,
     openLayerImageObjectEditFactoryModal: openLayerImageObjectEditFactoryModalReducer,
     openLayerTextFactoryModal: openLayerTextFactoryModalReducer,
+    openLayerTextEditFactoryModal: openLayerTextEditFactoryModalReducer,
   },
 });
 
@@ -68,6 +70,7 @@ export const {
   openLayerImageObjectFactoryModal,
   openLayerImageObjectEditFactoryModal,
   openLayerTextFactoryModal,
+  openLayerTextEditFactoryModal,
 } = modalSlice.actions;
 
 export default modalSlice.reducer;
diff --git a/src/types/modal.ts b/src/types/modal.ts
index 8b02e86a..579c8137 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -15,4 +15,5 @@ export type ModalName =
   | 'layer-factory'
   | 'layer-image-object-factory'
   | 'layer-image-object-edit-factory'
-  | 'layer-text-factory';
+  | 'layer-text-factory'
+  | 'layer-text-edit-factory';
-- 
GitLab


From 7f8d0b665cbd00568e46ba57597c5d22ab28192b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 10:10:19 +0100
Subject: [PATCH 3/8] feat(layers): add layers zIndex editing

---
 .../LayerFactoryModal.component.tsx           |   4 +
 ...LayerImageObjectFactoryModal.component.tsx |   9 +-
 .../LayerTextFactoryModal.component.tsx       |   9 +-
 .../LayerDrawerTextItem.component.tsx         |  12 +-
 .../LayersDrawer/LayersDrawer.component.tsx   |  46 ++++--
 .../LayersDrawerImageItem.component.tsx       |  12 +-
 .../LayersDrawerLayer.component.tsx           | 107 +++++++++++---
 .../LayersDrawerLayerActions.component.tsx    |  39 +++++
 .../LayersDrawerObjectActions.component.tsx   |  20 +--
 .../LayersDrawerObjectsList.component.tsx     |  32 ++--
 .../useOlMapAdditionalLayers.ts               |   1 +
 .../commentsLayer/useOlMapCommentsLayer.ts    |   1 +
 .../config/mapCardLayer/useOlMapCardLayer.ts  |   1 +
 .../config/pinsLayer/useOlMapPinsLayer.ts     |   1 +
 .../processLayer/useOlMapProcessLayer.ts      |   1 +
 .../reactionsLayer/useOlMapReactionsLayer.ts  |   1 +
 .../utils/shapes/layer/Layer.test.ts          |   1 +
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |   3 +
 src/models/layerSchema.ts                     |   1 +
 src/redux/layers/layers.reducers.test.ts      |   4 +-
 src/redux/layers/layers.selectors.ts          | 139 +++++++++++++-----
 src/redux/layers/layers.thunks.test.ts        |  18 ++-
 src/redux/layers/layers.thunks.ts             |  28 ++--
 src/redux/layers/layers.types.ts              |   2 +
 src/shared/Icon/Icon.component.tsx            |  12 +-
 src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx |  12 +-
 src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx   |  12 +-
 src/shared/Icon/Icons/LayerArrowDownIcon.tsx  |  18 +++
 src/shared/Icon/Icons/LayerArrowUpIcon.tsx    |  18 +++
 .../{BringBackIcon.tsx => MoveBackIcon.tsx}   |   6 +-
 .../{BringFrontIcon.tsx => MoveFrontIcon.tsx} |   6 +-
 .../IconButton/IconButton.component.tsx       |   8 +-
 src/types/iconTypes.ts                        |   6 +-
 33 files changed, 430 insertions(+), 160 deletions(-)
 create mode 100644 src/shared/Icon/Icons/LayerArrowDownIcon.tsx
 create mode 100644 src/shared/Icon/Icons/LayerArrowUpIcon.tsx
 rename src/shared/Icon/Icons/{BringBackIcon.tsx => MoveBackIcon.tsx} (78%)
 rename src/shared/Icon/Icons/{BringFrontIcon.tsx => MoveFrontIcon.tsx} (77%)

diff --git a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
index 8d925951..b806d2b6 100644
--- a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
@@ -19,11 +19,13 @@ import { SerializedError } from '@reduxjs/toolkit';
 import { layerFactoryStateSelector } from '@/redux/modal/modal.selector';
 import './LayerFactoryModal.styles.css';
 import { LoadingIndicator } from '@/shared/LoadingIndicator';
+import { maxLayerZIndexAboveDiagramSelector } from '@/redux/layers/layers.selectors';
 
 export const LayerFactoryModal: React.FC = () => {
   const dispatch = useAppDispatch();
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerFactoryState = useAppSelector(layerFactoryStateSelector);
+  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
   const [loaded, setLoaded] = useState<boolean>(false);
 
   const [data, setData] = useState<LayerStoreInterface>({
@@ -31,6 +33,7 @@ export const LayerFactoryModal: React.FC = () => {
     visible: false,
     locked: false,
     modelId: currentModelId,
+    zIndex: maxLayerZIndexAboveDiagram,
   });
 
   const fetchData = useMemo(() => {
@@ -42,6 +45,7 @@ export const LayerFactoryModal: React.FC = () => {
           visible: layer.visible,
           locked: layer.locked,
           modelId: currentModelId,
+          zIndex: layer.z,
         });
       }
       setLoaded(true);
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
index 1efb7d88..4d1513e9 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
@@ -4,7 +4,10 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerImageObjectFactoryStateSelector } from '@/redux/modal/modal.selector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
-import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
+import {
+  layersDrawLayerSelector,
+  maxObjectZIndexForLayerSelector,
+} from '@/redux/layers/layers.selectors';
 import { addLayerImageObject } from '@/redux/layers/layers.thunks';
 import { addGlyph } from '@/redux/glyphs/glyphs.thunks';
 import { SerializedError } from '@reduxjs/toolkit';
@@ -22,7 +25,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
   const drawLayer = useAppSelector(layersDrawLayerSelector);
   const layerImageObjectFactoryState = useAppSelector(layerImageObjectFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const highestZIndex = useAppSelector(highestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
   const { mapInstance } = useMapInstance();
 
   const [selectedGlyph, setSelectedGlyph] = useState<number | null>(null);
@@ -49,7 +52,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
           layerId: drawLayer,
           x: layerImageObjectFactoryState.x,
           y: layerImageObjectFactoryState.y,
-          z: highestZIndex + 1,
+          z: maxZIndex + 1,
           width: layerImageObjectFactoryState.width,
           height: layerImageObjectFactoryState.height,
           glyph: glyphId,
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
index e1ccf612..bfb80aff 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
@@ -13,7 +13,10 @@ import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTex
 import { Color } from '@/types/models';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerTextFactoryStateSelector } from '@/redux/modal/modal.selector';
-import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
+import {
+  layersDrawLayerSelector,
+  maxObjectZIndexForLayerSelector,
+} from '@/redux/layers/layers.selectors';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { showToast } from '@/utils/showToast';
@@ -31,7 +34,7 @@ export const LayerTextFactoryModal: React.FC = () => {
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerTextFactoryState = useAppSelector(layerTextFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const highestZIndex = useAppSelector(highestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
   const { mapInstance } = useMapInstance();
 
   const [isSending, setIsSending] = useState<boolean>(false);
@@ -55,7 +58,7 @@ export const LayerTextFactoryModal: React.FC = () => {
           layerId: drawLayer,
           boundingBox: layerTextFactoryState,
           textData: data,
-          z: highestZIndex + 1,
+          z: maxZIndex + 1,
         }),
       ).unwrap();
       if (!textData) {
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
index 6f57c762..a9c3d3b3 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
@@ -10,8 +10,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerTextItemProps {
   layerText: LayerText;
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -21,8 +21,8 @@ interface LayersDrawerTextItemProps {
 
 export const LayersDrawerTextItem = ({
   layerText,
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -68,8 +68,8 @@ export const LayersDrawerTextItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          bringToFront={bringToFront}
-          bringToBack={bringToBack}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
index 12bef081..33c259f3 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
@@ -4,7 +4,7 @@ import { DrawerHeading } from '@/shared/DrawerHeading';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { layersForCurrentModelSelector } from '@/redux/layers/layers.selectors';
 import { Button } from '@/shared/Button';
-import { JSX, useEffect, useRef } from 'react';
+import { JSX, useEffect, useMemo, useRef } from 'react';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
 import { LayersDrawerLayer } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component';
@@ -21,6 +21,19 @@ export const LayersDrawer = (): JSX.Element => {
     dispatch(openLayerFactoryModal());
   };
 
+  const sortedLayers = useMemo(() => {
+    return [...layersForCurrentModel].sort((layerA, layerB) => layerB.details.z - layerA.details.z);
+  }, [layersForCurrentModel]);
+
+  const negativeZLayers = useMemo(
+    () => sortedLayers.filter(layer => layer.details.z < 0),
+    [sortedLayers],
+  );
+  const positiveZLayers = useMemo(
+    () => sortedLayers.filter(layer => layer.details.z >= 0),
+    [sortedLayers],
+  );
+
   useEffect(() => {
     if (!mapEditToolsLayerImageObject || !layersDrawerRef.current) {
       return;
@@ -61,20 +74,33 @@ export const LayersDrawer = (): JSX.Element => {
         ref={layersDrawerRef}
       >
         {hasPrivilegeToWriteProject && (
-          <div className="flex justify-start pt-2">
+          <div className="flex justify-start py-2">
             <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}>
               Add layer
             </Button>
           </div>
         )}
-        <div className="flex flex-col gap-4">
-          {layersForCurrentModel.map(layer => (
-            <LayersDrawerLayer
-              key={layer.details.id}
-              layerId={layer.details.id}
-              layerName={layer.details.name}
-            />
-          ))}
+        <div className="flex flex-col gap-2">
+          {Boolean(positiveZLayers.length) && (
+            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
+              Layers above the diagram
+            </span>
+          )}
+          <div className="flex flex-col gap-5">
+            {positiveZLayers.map(layer => (
+              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
+            ))}
+          </div>
+          {Boolean(negativeZLayers.length) && (
+            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
+              Layers below the diagram
+            </span>
+          )}
+          <div className="flex flex-col gap-5">
+            {negativeZLayers.map(layer => (
+              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
+            ))}
+          </div>
         </div>
       </div>
     </div>
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
index 0622f141..e160b807 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
@@ -11,8 +11,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerImageItemProps {
   layerImage: LayerImage;
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -22,8 +22,8 @@ interface LayersDrawerImageItemProps {
 
 export const LayersDrawerImageItem = ({
   layerImage,
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -72,8 +72,8 @@ export const LayersDrawerImageItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          bringToFront={bringToFront}
-          bringToBack={bringToBack}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
index 49b8536f..8b0f9b01 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
@@ -1,14 +1,19 @@
+/* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import {
   layersActiveLayersSelector,
   layersVisibilityForCurrentModelSelector,
+  maxLayerZIndexAboveDiagramSelector,
+  maxLayerZIndexBelowDiagramSelector,
+  minLayerZIndexAboveDiagramSelector,
+  minLayerZIndexBelowDiagramSelector,
 } from '@/redux/layers/layers.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component';
 import { useState, JSX, useMemo } from 'react';
-import { getLayersForModel, removeLayer } from '@/redux/layers/layers.thunks';
+import { getLayersForModel, removeLayer, updateLayer } from '@/redux/layers/layers.thunks';
 import { showToast } from '@/utils/showToast';
 import { SerializedError } from '@reduxjs/toolkit';
 import { LayersDrawerLayerActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component';
@@ -21,38 +26,42 @@ import {
 import { LayersDrawerObjectsList } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component';
 import { mapEditToolsSetActiveAction } from '@/redux/mapEditTools/mapEditTools.slice';
 import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants';
+import { Layer } from '@/types/models';
 
 interface LayersDrawerLayerProps {
-  layerId: number;
-  layerName: string;
+  layerDetails: Layer;
 }
 
-export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps): JSX.Element => {
+export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX.Element => {
   const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector);
   const activeLayers = useAppSelector(layersActiveLayersSelector);
   const currentModelId = useAppSelector(currentModelIdSelector);
+  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
+  const maxLayerZIndexBelowDiagram = useAppSelector(maxLayerZIndexBelowDiagramSelector);
+  const minLayerZIndexAboveDiagram = useAppSelector(minLayerZIndexAboveDiagramSelector);
+  const minLayerZIndexBelowDiagram = useAppSelector(minLayerZIndexBelowDiagramSelector);
   const dispatch = useAppDispatch();
   const [isModalOpen, setIsModalOpen] = useState(false);
 
   const isLayerVisible = useMemo(() => {
-    return layersVisibilityForCurrentModel[layerId];
-  }, [layerId, layersVisibilityForCurrentModel]);
+    return layersVisibilityForCurrentModel[layerDetails.id];
+  }, [layerDetails.id, layersVisibilityForCurrentModel]);
 
   const isLayerActive = useMemo(() => {
-    return activeLayers.includes(layerId);
-  }, [activeLayers, layerId]);
+    return activeLayers.includes(layerDetails.id);
+  }, [activeLayers, layerDetails.id]);
 
   const editLayer = (): void => {
-    dispatch(openLayerFactoryModal(layerId));
+    dispatch(openLayerFactoryModal(layerDetails.id));
   };
 
   const addImage = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.DRAW_IMAGE));
   };
 
   const addText = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.ADD_TEXT));
   };
 
@@ -61,11 +70,11 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
   };
 
   const confirmRemove = async (): Promise<void> => {
-    if (!layerId) {
+    if (!layerDetails.id) {
       return;
     }
     try {
-      await dispatch(removeLayer({ modelId: currentModelId, layerId })).unwrap();
+      await dispatch(removeLayer({ modelId: currentModelId, layerId: layerDetails.id })).unwrap();
       showToast({
         type: 'success',
         message: 'The layer has been successfully removed',
@@ -87,12 +96,61 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
 
   const toggleActiveLayer = (value: boolean): void => {
     if (value) {
-      dispatch(setLayerToActive({ modelId: currentModelId, layerId }));
+      dispatch(setLayerToActive({ modelId: currentModelId, layerId: layerDetails.id }));
     } else {
-      dispatch(setLayerToInactive({ modelId: currentModelId, layerId }));
+      dispatch(setLayerToInactive({ modelId: currentModelId, layerId: layerDetails.id }));
     }
   };
 
+  const updateLayerZIndex = async (zIndex: number): Promise<void> => {
+    try {
+      dispatch(
+        updateLayer({
+          name: layerDetails.name,
+          visible: layerDetails.visible,
+          locked: layerDetails.locked,
+          modelId: currentModelId,
+          layerId: layerDetails.id,
+          zIndex,
+        }),
+      );
+    } catch (error) {
+      const typedError = error as SerializedError;
+      showToast({
+        type: 'error',
+        message: typedError.message || 'An error occurred while updating the layer',
+      });
+    }
+  };
+
+  const moveToFront = (): void => {
+    if (layerDetails.z > 0) {
+      updateLayerZIndex(maxLayerZIndexAboveDiagram);
+    } else if (layerDetails.z < 0) {
+      const zIndex = Math.min(maxLayerZIndexBelowDiagram, -1);
+      updateLayerZIndex(zIndex);
+    }
+  };
+
+  const moveToBack = (): void => {
+    if (layerDetails.z > 0) {
+      const zIndex = Math.max(minLayerZIndexAboveDiagram, 1);
+      updateLayerZIndex(zIndex);
+    } else if (layerDetails.z < 0) {
+      updateLayerZIndex(minLayerZIndexBelowDiagram);
+    }
+  };
+
+  const moveAboveDiagram = (): void => {
+    const zIndex = Math.max(minLayerZIndexAboveDiagram - 1, 1);
+    updateLayerZIndex(zIndex);
+  };
+
+  const moveBelowDiagram = (): void => {
+    const zIndex = Math.min(minLayerZIndexBelowDiagram + 1, -1);
+    updateLayerZIndex(zIndex);
+  };
+
   return (
     <div>
       <QuestionModal
@@ -101,9 +159,13 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
         onConfirm={confirmRemove}
         question="Are you sure you want to remove the layer?"
       />
-      <div className="flex items-center justify-between py-3">
-        <span className={`font-semibold ${isLayerVisible ? 'opacity-100' : 'opacity-40'}`}>
-          {layerName}
+      <div className="flex items-center justify-between pb-3">
+        <span
+          className={`font-semibold ${
+            isLayerVisible ? 'opacity-100' : 'opacity-40'
+          } min-w-0 flex-1 truncate `}
+        >
+          {layerDetails.name}
         </span>
         <LayersDrawerLayerActions
           toggleVisibility={() =>
@@ -111,7 +173,7 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
               setLayerVisibility({
                 modelId: currentModelId,
                 visible: !isLayerVisible,
-                layerId,
+                layerId: layerDetails.id,
               }),
             )
           }
@@ -120,12 +182,17 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
           removeLayer={onRemoveLayer}
           addImage={addImage}
           addText={addText}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
+          moveAboveDiagram={moveAboveDiagram}
+          moveBelowDiagram={moveBelowDiagram}
+          zIndex={layerDetails.z}
           isVisible={isLayerVisible}
           isActive={isLayerActive}
         />
       </div>
       <LayersDrawerObjectsList
-        layerId={layerId}
+        layerId={layerDetails.id}
         isLayerVisible={isLayerVisible}
         isLayerActive={isLayerActive}
       />
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
index 18627b13..81435100 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable no-magic-numbers */
 import { IconButton } from '@/shared/IconButton';
 import { JSX } from 'react';
 import { LayerDrawerLayerContextMenu } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component';
@@ -9,10 +10,15 @@ type LayersDrawerLayerActionsProps = {
   removeLayer: () => void;
   isVisible: boolean;
   isActive: boolean;
+  zIndex: number;
   toggleVisibility: () => void;
   toggleActiveLayer: (value: boolean) => void;
   addImage: () => void;
   addText: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
+  moveAboveDiagram: () => void;
+  moveBelowDiagram: () => void;
 };
 
 export const LayersDrawerLayerActions = ({
@@ -20,10 +26,15 @@ export const LayersDrawerLayerActions = ({
   removeLayer,
   isVisible,
   isActive,
+  zIndex,
   toggleVisibility,
   toggleActiveLayer,
   addImage,
   addText,
+  moveToFront,
+  moveToBack,
+  moveAboveDiagram,
+  moveBelowDiagram,
 }: LayersDrawerLayerActionsProps): JSX.Element => {
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
 
@@ -43,6 +54,34 @@ export const LayersDrawerLayerActions = ({
             className="h-auto w-auto bg-transparent p-0"
             onClick={() => toggleActiveLayer(!isActive)}
           />
+          <IconButton
+            title="Move to front"
+            icon="move-front"
+            className="h-auto w-auto bg-transparent p-0"
+            onClick={moveToFront}
+          />
+          <IconButton
+            title="Move to back"
+            icon="move-back"
+            className="h-auto w-auto bg-transparent p-0"
+            onClick={moveToBack}
+          />
+          {zIndex < 0 && (
+            <IconButton
+              title="Move above the diagram"
+              icon="layer-arrow-up"
+              className="h-auto w-auto bg-transparent p-0"
+              onClick={moveAboveDiagram}
+            />
+          )}
+          {zIndex > 0 && (
+            <IconButton
+              title="Move below the diagram"
+              icon="layer-arrow-down"
+              className="h-auto w-auto bg-transparent p-0"
+              onClick={moveBelowDiagram}
+            />
+          )}
           <LayerDrawerLayerContextMenu
             removeLayer={removeLayer}
             editLayer={editLayer}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
index 4cf6871e..a97189ea 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
@@ -2,16 +2,16 @@ import { JSX } from 'react';
 import { IconButton } from '@/shared/IconButton';
 
 interface LayersDrawerObjectActionsProps {
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
 }
 
 export const LayersDrawerObjectActions = ({
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -31,16 +31,16 @@ export const LayersDrawerObjectActions = ({
         onClick={editObject}
       />
       <IconButton
-        icon="bring-front"
+        icon="move-front"
         className="h-auto w-auto bg-transparent p-0"
-        title="Bring to front"
-        onClick={bringToFront}
+        title="Move to front"
+        onClick={moveToFront}
       />
       <IconButton
-        icon="bring-back"
+        icon="move-back"
         className="h-auto w-auto bg-transparent p-0"
-        title="Bring to back"
-        onClick={bringToBack}
+        title="Move to back"
+        onClick={moveToBack}
       />
       <IconButton
         icon="trash"
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index 70a6acf5..9ec19fe4 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -1,9 +1,9 @@
 /* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import {
-  highestZIndexSelector,
   layerByIdSelector,
-  lowestZIndexSelector,
+  maxObjectZIndexForLayerSelector,
+  minObjectZIndexForLayerSelector,
 } from '@/redux/layers/layers.selectors';
 import { JSX, useState } from 'react';
 import { LayersDrawerImageItem } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component';
@@ -64,8 +64,8 @@ export const LayersDrawerObjectsList = ({
   isLayerActive,
 }: LayersDrawerObjectsListProps): JSX.Element | null => {
   const currentModelId = useAppSelector(mapModelIdSelector);
-  const highestZIndex = useAppSelector(highestZIndexSelector);
-  const lowestZIndex = useAppSelector(lowestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, layerId));
+  const minZIndex = useAppSelector(state => minObjectZIndexForLayerSelector(state, layerId));
   const layer = useAppSelector(state => layerByIdSelector(state, layerId));
   const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector);
   const [removeModalState, setRemoveModalState] = useState<undefined | 'text' | 'image'>(undefined);
@@ -174,12 +174,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const bringImageToFront = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: highestZIndex + 1, layerImage });
+  const moveImageToFront = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: maxZIndex + 1, layerImage });
   };
 
-  const bringImageToBack = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: lowestZIndex - 1, layerImage });
+  const moveImageToBack = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: minZIndex - 1, layerImage });
   };
 
   const updateTextZIndex = async ({
@@ -210,12 +210,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const bringTextToFront = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: highestZIndex + 1, layerText });
+  const moveTextToFront = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: maxZIndex + 1, layerText });
   };
 
-  const bringTextToBack = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: lowestZIndex - 1, layerText });
+  const moveTextToBack = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: minZIndex - 1, layerText });
   };
 
   const centerObject = (layerObject: LayerImage | LayerText): void => {
@@ -257,8 +257,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerTextItem
           layerText={layerText}
           key={layerText.id}
-          bringToFront={() => bringTextToFront(layerText)}
-          bringToBack={() => bringTextToBack(layerText)}
+          moveToFront={() => moveTextToFront(layerText)}
+          moveToBack={() => moveTextToBack(layerText)}
           removeObject={() => removeObject(layerText)}
           centerObject={() => centerObject(layerText)}
           editObject={() => editText()}
@@ -270,8 +270,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerImageItem
           layerImage={layerImage}
           key={layerImage.id}
-          bringToFront={() => bringImageToFront(layerImage)}
-          bringToBack={() => bringImageToBack(layerImage)}
+          moveToFront={() => moveImageToFront(layerImage)}
+          moveToBack={() => moveImageToBack(layerImage)}
           removeObject={() => removeObject(layerImage)}
           centerObject={() => centerObject(layerImage)}
           editObject={() => editImage()}
diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
index 5e378293..6d41944f 100644
--- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
+++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
@@ -125,6 +125,7 @@ export const useOlMapAdditionalLayers = (
   const vectorLayers = useMemo(() => {
     return layersState.map(layer => {
       const additionalLayer = new Layer({
+        zIndex: layer.details.z,
         texts: layer.texts,
         rects: layer.rects,
         ovals: layer.ovals,
diff --git a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
index 7ac3b73b..a3640020 100644
--- a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
@@ -36,6 +36,7 @@ export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geomet
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.COMMENTS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
index 69cec807..db3dbad4 100644
--- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
@@ -38,6 +38,7 @@ export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: -Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({
diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
index f7b6001c..4cd5a32b 100644
--- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
@@ -77,6 +77,7 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.PINS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
index 2811ec30..98cb6e1e 100644
--- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
@@ -274,6 +274,7 @@ export const useOlMapProcessLayer = ({
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: 0,
       source: vectorSource,
       updateWhileAnimating: true,
       updateWhileInteracting: true,
diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
index bfb2668e..df526271 100644
--- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
@@ -63,6 +63,7 @@ export const useOlMapReactionsLayer = (): VectorLayer<VectorSource<Feature<Geome
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({ color: LINE_COLOR }),
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
index 7b8bb971..10349c6d 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
@@ -133,6 +133,7 @@ describe('Layer', () => {
       pointToProjection: jest.fn(point => [point.x, point.y]),
       mapInstance,
       mapSize,
+      zIndex: 1,
       lineTypes: {},
       arrowTypes: {},
     };
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
index 7f697a72..14d5f8b5 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
@@ -34,6 +34,7 @@ import LayerText from '@/components/Map/MapViewer/utils/shapes/layer/elements/La
 import LayerImage from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage';
 
 export interface LayerProps {
+  zIndex: number;
   texts: { [key: string]: LayerTextModel };
   rects: Array<LayerRect>;
   ovals: Array<LayerOval>;
@@ -78,6 +79,7 @@ export default class Layer {
   >;
 
   constructor({
+    zIndex,
     texts,
     rects,
     ovals,
@@ -118,6 +120,7 @@ export default class Layer {
     this.vectorSource.addFeatures(arrowsFeatures);
 
     this.vectorLayer = new VectorLayer({
+      zIndex,
       source: this.vectorSource,
       visible,
       updateWhileAnimating: true,
diff --git a/src/models/layerSchema.ts b/src/models/layerSchema.ts
index 380146a7..11fcd88d 100644
--- a/src/models/layerSchema.ts
+++ b/src/models/layerSchema.ts
@@ -5,4 +5,5 @@ export const layerSchema = z.object({
   name: z.string(),
   visible: z.boolean(),
   locked: z.boolean(),
+  z: z.number(),
 });
diff --git a/src/redux/layers/layers.reducers.test.ts b/src/redux/layers/layers.reducers.test.ts
index 7bcb10ba..d93fb4f8 100644
--- a/src/redux/layers/layers.reducers.test.ts
+++ b/src/redux/layers/layers.reducers.test.ts
@@ -92,7 +92,7 @@ describe('layers reducer', () => {
 
     const { type } = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
-    expect(type).toBe('vectorMap/getLayers/fulfilled');
+    expect(type).toBe('layers/getLayers/fulfilled');
     expect(loading).toEqual('succeeded');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual({
@@ -120,7 +120,7 @@ describe('layers reducer', () => {
     const action = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
 
-    expect(action.type).toBe('vectorMap/getLayers/rejected');
+    expect(action.type).toBe('layers/getLayers/rejected');
     expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch layers: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
diff --git a/src/redux/layers/layers.selectors.ts b/src/redux/layers/layers.selectors.ts
index 8f016c8a..8123fa00 100644
--- a/src/redux/layers/layers.selectors.ts
+++ b/src/redux/layers/layers.selectors.ts
@@ -2,6 +2,7 @@
 import { createSelector } from '@reduxjs/toolkit';
 import { rootSelector } from '@/redux/root/root.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
+import { LayerState } from '@/redux/layers/layers.types';
 
 export const layersSelector = createSelector(rootSelector, state => state.layers);
 
@@ -18,7 +19,7 @@ export const layersActiveLayersSelector = createSelector(
 
 export const layersDrawLayerSelector = createSelector(
   layersStateForCurrentModelSelector,
-  state => state?.data?.drawLayer,
+  state => state?.data?.drawLayer || null,
 );
 
 export const layerByIdSelector = createSelector(
@@ -41,40 +42,112 @@ export const layersForCurrentModelSelector = createSelector(
   state => state?.data?.layers || [],
 );
 
-export const highestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
-  if (!layers || layers.length === 0) return 0;
-
-  const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-    items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
-
-  return layers.reduce((maxZ, layer) => {
-    const textsMaxZ = getMaxZFromItems(Object.values(layer.texts));
-    const rectsMaxZ = getMaxZFromItems(layer.rects);
-    const ovalsMaxZ = getMaxZFromItems(layer.ovals);
-    const linesMaxZ = getMaxZFromItems(layer.lines);
-    const imagesMaxZ = getMaxZFromItems(Object.values(layer.images));
-
-    const layerMaxZ = Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
-
-    return Math.max(maxZ, layerMaxZ);
-  }, 0);
-});
+export const maxLayerZIndexAboveDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return 1000;
+    }
+    let maxZIndex = -Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z > 0 && layer.details.z > maxZIndex) {
+        maxZIndex = layer.details.z;
+      }
+    });
+    return maxZIndex;
+  },
+);
 
-export const lowestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
-  if (!layers || layers.length === 0) return 0;
+export const maxLayerZIndexBelowDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return -1000;
+    }
+    let maxZIndex = -Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z < 0 && layer.details.z > maxZIndex) {
+        maxZIndex = layer.details.z;
+      }
+    });
+    return maxZIndex;
+  },
+);
 
-  const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-    items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
+export const minLayerZIndexAboveDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return 1000;
+    }
+    let minZIndex = Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z > 0 && layer.details.z < minZIndex) {
+        minZIndex = layer.details.z;
+      }
+    });
+    return minZIndex;
+  },
+);
 
-  return layers.reduce((minZ, layer) => {
-    const textsMinZ = getMinZFromItems(Object.values(layer.texts));
-    const rectsMinZ = getMinZFromItems(layer.rects);
-    const ovalsMinZ = getMinZFromItems(layer.ovals);
-    const linesMinZ = getMinZFromItems(layer.lines);
-    const imagesMinZ = getMinZFromItems(Object.values(layer.images));
+export const minLayerZIndexBelowDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return -1000;
+    }
+    let minZIndex = Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z < 0 && layer.details.z < minZIndex) {
+        minZIndex = layer.details.z;
+      }
+    });
+    return minZIndex;
+  },
+);
 
-    const layerMinZ = Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
+export const maxObjectZIndexForLayerSelector = createSelector(
+  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
+  (layers, layerId) => {
+    if (!layers || layers.length === 0 || !layerId) {
+      return 0;
+    }
+    const foundLayer = layers.find(layer => layer.details.id === layerId);
+    if (!foundLayer) {
+      return 0;
+    }
+    const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+      items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
+
+    const textsMaxZ = getMaxZFromItems(Object.values(foundLayer.texts));
+    const rectsMaxZ = getMaxZFromItems(foundLayer.rects);
+    const ovalsMaxZ = getMaxZFromItems(foundLayer.ovals);
+    const linesMaxZ = getMaxZFromItems(foundLayer.lines);
+    const imagesMaxZ = getMaxZFromItems(Object.values(foundLayer.images));
+
+    return Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
+  },
+);
 
-    return Math.min(minZ, layerMinZ);
-  }, 0);
-});
+export const minObjectZIndexForLayerSelector = createSelector(
+  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
+  (layers, layerId) => {
+    if (!layers || layers.length === 0 || !layerId) {
+      return 0;
+    }
+    const foundLayer = layers.find(layer => layer.details.id === layerId);
+    if (!foundLayer) {
+      return 0;
+    }
+    const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+      items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
+
+    const textsMinZ = getMinZFromItems(Object.values(foundLayer.texts));
+    const rectsMinZ = getMinZFromItems(foundLayer.rects);
+    const ovalsMinZ = getMinZFromItems(foundLayer.ovals);
+    const linesMinZ = getMinZFromItems(foundLayer.lines);
+    const imagesMinZ = getMinZFromItems(Object.values(foundLayer.images));
+
+    return Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
+  },
+);
diff --git a/src/redux/layers/layers.thunks.test.ts b/src/redux/layers/layers.thunks.test.ts
index 77e10bdb..09028272 100644
--- a/src/redux/layers/layers.thunks.test.ts
+++ b/src/redux/layers/layers.thunks.test.ts
@@ -111,7 +111,13 @@ describe('layers thunks', () => {
       mockedAxiosClient.onPost(apiPath.storeLayer(1)).reply(HttpStatusCode.Created, layerFixture);
 
       const { payload } = await store.dispatch(
-        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
+        addLayerForModel({
+          name: 'New Layer',
+          visible: true,
+          locked: false,
+          modelId: 1,
+          zIndex: 1,
+        }),
       );
       expect(payload).toEqual(layerFixture);
     });
@@ -122,7 +128,13 @@ describe('layers thunks', () => {
         .reply(HttpStatusCode.Created, { invalid: 'data' });
 
       const { payload } = await store.dispatch(
-        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
+        addLayerForModel({
+          name: 'New Layer',
+          visible: true,
+          locked: false,
+          modelId: 1,
+          zIndex: 1,
+        }),
       );
       expect(payload).toBeNull();
     });
@@ -139,6 +151,7 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
+          zIndex: 1,
         }),
       );
       expect(payload).toEqual(layerFixture);
@@ -156,6 +169,7 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
+          zIndex: 1,
         }),
       );
       expect(payload).toBeNull();
diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts
index 66035fd8..bda72fce 100644
--- a/src/redux/layers/layers.thunks.ts
+++ b/src/redux/layers/layers.thunks.ts
@@ -32,7 +32,7 @@ export const getLayer = createAsyncThunk<
   Layer | null,
   { modelId: number; layerId: number },
   ThunkConfig
->('vectorMap/getLayer', async ({ modelId, layerId }) => {
+>('layers/getLayer', async ({ modelId, layerId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layer>(apiPath.getLayer(modelId, layerId));
 
@@ -48,7 +48,7 @@ export const getLayersForModel = createAsyncThunk<
   LayersVisibilitiesState | undefined,
   number,
   ThunkConfig
->('vectorMap/getLayers', async (modelId: number) => {
+>('layers/getLayers', async (modelId: number) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layers>(apiPath.getLayers(modelId));
     const isDataValid = validateDataUsingZodSchema(data, pageableSchema(layerSchema));
@@ -103,13 +103,14 @@ export const getLayersForModel = createAsyncThunk<
 });
 
 export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterface, ThunkConfig>(
-  'vectorMap/addLayer',
-  async ({ name, visible, locked, modelId }) => {
+  'layers/addLayer',
+  async ({ name, visible, locked, modelId, zIndex }) => {
     try {
       const { data } = await axiosInstanceNewAPI.post<Layer>(apiPath.storeLayer(modelId), {
         name,
         visible,
         locked,
+        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -122,13 +123,14 @@ export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterfa
 );
 
 export const updateLayer = createAsyncThunk<Layer | null, LayerUpdateInterface, ThunkConfig>(
-  'vectorMap/updateLayer',
-  async ({ name, visible, locked, modelId, layerId }) => {
+  'layers/updateLayer',
+  async ({ name, visible, locked, modelId, layerId, zIndex }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<Layer>(apiPath.updateLayer(modelId, layerId), {
         name,
         visible,
         locked,
+        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -144,7 +146,7 @@ export const removeLayer = createAsyncThunk<
   null,
   { modelId: number; layerId: number },
   ThunkConfig
->('vectorMap/removeLayer', async ({ modelId, layerId }) => {
+>('layers/removeLayer', async ({ modelId, layerId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(apiPath.removeLayer(modelId, layerId));
     return null;
@@ -161,7 +163,7 @@ export const getLayerImage = createAsyncThunk<
     imageId: number;
   },
   ThunkConfig
->('vectorMap/getLayerImage', async ({ modelId, layerId, imageId }) => {
+>('layers/getLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerImage>(
       apiPath.getLayerImageObject(modelId, layerId, imageId),
@@ -187,7 +189,7 @@ export const addLayerImageObject = createAsyncThunk<
     glyph: number | null;
   },
   ThunkConfig
->('vectorMap/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
+>('layers/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerImage>(
       apiPath.addLayerImageObject(modelId, layerId),
@@ -223,7 +225,7 @@ export const updateLayerImageObject = createAsyncThunk<
   },
   ThunkConfig
 >(
-  'vectorMap/updateLayerImageObject',
+  'layers/updateLayerImageObject',
   async ({ modelId, layerId, id, x, y, z, width, height, glyph }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<LayerImage>(
@@ -252,7 +254,7 @@ export const removeLayerImage = createAsyncThunk<
   null,
   { modelId: number; layerId: number; imageId: number },
   ThunkConfig
->('vectorMap/removeLayerImage', async ({ modelId, layerId, imageId }) => {
+>('layers/removeLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(
       apiPath.removeLayerImageObject(modelId, layerId, imageId),
@@ -273,7 +275,7 @@ export const addLayerText = createAsyncThunk<
     textData: LayerTextFactoryForm;
   },
   ThunkConfig
->('vectorMap/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
+>('layers/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerText>(
       apiPath.addLayerText(modelId, layerId),
@@ -299,7 +301,7 @@ export const getLayerText = createAsyncThunk<
     textId: number;
   },
   ThunkConfig
->('vectorMap/getLayerText', async ({ modelId, layerId, textId }) => {
+>('layers/getLayerText', async ({ modelId, layerId, textId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerText>(
       apiPath.getLayerText(modelId, layerId, textId),
diff --git a/src/redux/layers/layers.types.ts b/src/redux/layers/layers.types.ts
index 60e42717..05b4636e 100644
--- a/src/redux/layers/layers.types.ts
+++ b/src/redux/layers/layers.types.ts
@@ -6,6 +6,7 @@ export interface LayerStoreInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
+  zIndex: number;
 }
 
 export interface LayerUpdateInterface {
@@ -14,6 +15,7 @@ export interface LayerUpdateInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
+  zIndex: number;
 }
 
 export type LayerState = {
diff --git a/src/shared/Icon/Icon.component.tsx b/src/shared/Icon/Icon.component.tsx
index 5745b6ec..aed961c3 100644
--- a/src/shared/Icon/Icon.component.tsx
+++ b/src/shared/Icon/Icon.component.tsx
@@ -31,8 +31,10 @@ import { PadlockOpenIcon } from '@/shared/Icon/Icons/PadlockOpenIcon';
 import { PadlockLockedIcon } from '@/shared/Icon/Icons/PadlockLockedIcon';
 import { CrossedEyeIcon } from '@/shared/Icon/Icons/CrossedEyeIcon';
 import { CenterIcon } from '@/shared/Icon/Icons/CenterIcon';
-import { BringFrontIcon } from '@/shared/Icon/Icons/BringFrontIcon';
-import { BringBackIcon } from '@/shared/Icon/Icons/BringBackIcon';
+import { MoveFrontIcon } from '@/shared/Icon/Icons/MoveFrontIcon';
+import { MoveBackIcon } from '@/shared/Icon/Icons/MoveBackIcon';
+import { LayerArrowUpIcon } from '@/shared/Icon/Icons/LayerArrowUpIcon';
+import { LayerArrowDownIcon } from '@/shared/Icon/Icons/LayerArrowDownIcon';
 import { LocationIcon } from './Icons/LocationIcon';
 import { MaginfierZoomInIcon } from './Icons/MagnifierZoomIn';
 import { MaginfierZoomOutIcon } from './Icons/MagnifierZoomOut';
@@ -87,8 +89,10 @@ const icons: Record<IconTypes, IconComponentType> = {
   'padlock-open': PadlockOpenIcon,
   'padlock-locked': PadlockLockedIcon,
   center: CenterIcon,
-  'bring-front': BringFrontIcon,
-  'bring-back': BringBackIcon,
+  'move-front': MoveFrontIcon,
+  'move-back': MoveBackIcon,
+  'layer-arrow-up': LayerArrowUpIcon,
+  'layer-arrow-down': LayerArrowDownIcon,
 } as const;
 
 export const Icon = ({ name, className = '', ...rest }: IconProps): JSX.Element => {
diff --git a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
index d7ab4e38..cf5ce5f7 100644
--- a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
@@ -13,26 +13,16 @@ export const ArrowDoubleDownIcon = ({ className }: ArrowDoubleDownIconProps): JS
   >
     <path
       d="M8 8L8 18M8 18L5 15M8 18L11 15"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 8L16 18M16 18L13 15M16 18L19 15"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line
-      x1="4"
-      y1="6"
-      x2="20"
-      y2="6"
-      stroke="currentColor"
-      strokeWidth="1.5"
-      strokeLinecap="round"
-    />
+    <line x1="4" y1="6" x2="20" y2="6" strokeWidth="1.5" strokeLinecap="round" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
index ed51a602..861773cd 100644
--- a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
@@ -13,26 +13,16 @@ export const ArrowDoubleUpIcon = ({ className }: ArrowDoubleUpIconProps): JSX.El
   >
     <path
       d="M8 16L8 6M8 6L5 9M8 6L11 9"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 16L16 6M16 6L13 9M16 6L19 9"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line
-      x1="4"
-      y1="18"
-      x2="20"
-      y2="18"
-      stroke="currentColor"
-      strokeWidth="1.5"
-      strokeLinecap="round"
-    />
+    <line x1="4" y1="18" x2="20" y2="18" strokeWidth="1.5" strokeLinecap="round" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/LayerArrowDownIcon.tsx b/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
new file mode 100644
index 00000000..71223a31
--- /dev/null
+++ b/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
@@ -0,0 +1,18 @@
+interface LayerArrowDownIconProps {
+  className?: string;
+}
+
+export const LayerArrowDownIcon = ({ className }: LayerArrowDownIconProps): JSX.Element => (
+  <svg
+    width="20"
+    height="20"
+    viewBox="2 3 20 17"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+    className={className}
+  >
+    <path d="M12 21L7 16H10V10H14V16H17L12 21Z" />
+    <rect x="4" y="3" width="16" height="2" />
+    <rect x="4" y="7" width="16" height="2" />
+  </svg>
+);
diff --git a/src/shared/Icon/Icons/LayerArrowUpIcon.tsx b/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
new file mode 100644
index 00000000..bbcf233f
--- /dev/null
+++ b/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
@@ -0,0 +1,18 @@
+interface LayerArrowUpIconProps {
+  className?: string;
+}
+
+export const LayerArrowUpIcon = ({ className }: LayerArrowUpIconProps): JSX.Element => (
+  <svg
+    width="20"
+    height="20"
+    viewBox="2 3 20 19"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+    className={className}
+  >
+    <path d="M12 3L7 8H10V14H14V8H17L12 3Z" />
+    <rect x="4" y="16" width="16" height="2" />
+    <rect x="4" y="20" width="16" height="2" />
+  </svg>
+);
diff --git a/src/shared/Icon/Icons/BringBackIcon.tsx b/src/shared/Icon/Icons/MoveBackIcon.tsx
similarity index 78%
rename from src/shared/Icon/Icons/BringBackIcon.tsx
rename to src/shared/Icon/Icons/MoveBackIcon.tsx
index d086ac9b..734bd201 100644
--- a/src/shared/Icon/Icons/BringBackIcon.tsx
+++ b/src/shared/Icon/Icons/MoveBackIcon.tsx
@@ -1,8 +1,8 @@
-interface BringBackIconProps {
+interface MoveBackIconProps {
   className?: string;
 }
 
-export const BringBackIcon = ({ className }: BringBackIconProps): JSX.Element => (
+export const MoveBackIcon = ({ className }: MoveBackIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -23,6 +23,6 @@ export const BringBackIcon = ({ className }: BringBackIconProps): JSX.Element =>
       stroke="white"
       fill="none"
     />
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/BringFrontIcon.tsx b/src/shared/Icon/Icons/MoveFrontIcon.tsx
similarity index 77%
rename from src/shared/Icon/Icons/BringFrontIcon.tsx
rename to src/shared/Icon/Icons/MoveFrontIcon.tsx
index e5aa5017..037f5cb3 100644
--- a/src/shared/Icon/Icons/BringFrontIcon.tsx
+++ b/src/shared/Icon/Icons/MoveFrontIcon.tsx
@@ -1,8 +1,8 @@
-interface BringFrontIconProps {
+interface MoveFrontIconProps {
   className?: string;
 }
 
-export const BringFrontIcon = ({ className }: BringFrontIconProps): JSX.Element => (
+export const MoveFrontIcon = ({ className }: MoveFrontIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -11,7 +11,7 @@ export const BringFrontIcon = ({ className }: BringFrontIconProps): JSX.Element
     fill="none"
     className={className}
   >
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
     <rect
       x="30"
       y="30"
diff --git a/src/shared/IconButton/IconButton.component.tsx b/src/shared/IconButton/IconButton.component.tsx
index 1330e460..e71c6211 100644
--- a/src/shared/IconButton/IconButton.component.tsx
+++ b/src/shared/IconButton/IconButton.component.tsx
@@ -29,8 +29,8 @@ export const IconButton = ({
 
   const isStrokeIcon = [
     'plugin',
-    'bring-back',
-    'bring-front',
+    'move-back',
+    'move-front',
     'center',
     'eye',
     'crossed-eye',
@@ -38,6 +38,8 @@ export const IconButton = ({
     'padlock-locked',
     'layers',
     'edit',
+    'arrow-double-up',
+    'arrow-double-down',
   ].includes(icon);
 
   return (
@@ -57,6 +59,8 @@ export const IconButton = ({
           isStrokeIcon
             ? 'stroke-font-400 group-hover:stroke-primary-500 group-active:stroke-primary-500'
             : 'fill-font-400 group-hover:fill-primary-500 group-active:fill-primary-500',
+          ['move-back', 'move-front'].includes(icon) &&
+            'fill-font-400 stroke-font-400 group-hover:fill-primary-500 group-hover:stroke-primary-500 group-active:fill-primary-500 group-active:stroke-primary-500',
           isActive && getActiveFillOrStrokeColor(icon),
           classNameIcon,
         )}
diff --git a/src/types/iconTypes.ts b/src/types/iconTypes.ts
index 0d74dd78..0083a622 100644
--- a/src/types/iconTypes.ts
+++ b/src/types/iconTypes.ts
@@ -38,7 +38,9 @@ export type IconTypes =
   | 'padlock-open'
   | 'padlock-locked'
   | 'center'
-  | 'bring-front'
-  | 'bring-back';
+  | 'move-front'
+  | 'move-back'
+  | 'layer-arrow-up'
+  | 'layer-arrow-down';
 
 export type IconComponentType = ({ className }: { className: string }) => JSX.Element;
-- 
GitLab


From f6e504ece2951e59900cec58b70bec18b21b4bde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 10:19:22 +0100
Subject: [PATCH 4/8] Revert "feat(layers): add layers zIndex editing"

This reverts commit 7f8d0b665cbd00568e46ba57597c5d22ab28192b.
---
 .../LayerFactoryModal.component.tsx           |   4 -
 ...LayerImageObjectFactoryModal.component.tsx |   9 +-
 .../LayerTextFactoryModal.component.tsx       |   9 +-
 .../LayerDrawerTextItem.component.tsx         |  12 +-
 .../LayersDrawer/LayersDrawer.component.tsx   |  46 ++----
 .../LayersDrawerImageItem.component.tsx       |  12 +-
 .../LayersDrawerLayer.component.tsx           | 107 +++-----------
 .../LayersDrawerLayerActions.component.tsx    |  39 -----
 .../LayersDrawerObjectActions.component.tsx   |  20 +--
 .../LayersDrawerObjectsList.component.tsx     |  32 ++--
 .../useOlMapAdditionalLayers.ts               |   1 -
 .../commentsLayer/useOlMapCommentsLayer.ts    |   1 -
 .../config/mapCardLayer/useOlMapCardLayer.ts  |   1 -
 .../config/pinsLayer/useOlMapPinsLayer.ts     |   1 -
 .../processLayer/useOlMapProcessLayer.ts      |   1 -
 .../reactionsLayer/useOlMapReactionsLayer.ts  |   1 -
 .../utils/shapes/layer/Layer.test.ts          |   1 -
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |   3 -
 src/models/layerSchema.ts                     |   1 -
 src/redux/layers/layers.reducers.test.ts      |   4 +-
 src/redux/layers/layers.selectors.ts          | 139 +++++-------------
 src/redux/layers/layers.thunks.test.ts        |  18 +--
 src/redux/layers/layers.thunks.ts             |  28 ++--
 src/redux/layers/layers.types.ts              |   2 -
 src/shared/Icon/Icon.component.tsx            |  12 +-
 src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx |  12 +-
 src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx   |  12 +-
 .../{MoveBackIcon.tsx => BringBackIcon.tsx}   |   6 +-
 .../{MoveFrontIcon.tsx => BringFrontIcon.tsx} |   6 +-
 src/shared/Icon/Icons/LayerArrowDownIcon.tsx  |  18 ---
 src/shared/Icon/Icons/LayerArrowUpIcon.tsx    |  18 ---
 .../IconButton/IconButton.component.tsx       |   8 +-
 src/types/iconTypes.ts                        |   6 +-
 33 files changed, 160 insertions(+), 430 deletions(-)
 rename src/shared/Icon/Icons/{MoveBackIcon.tsx => BringBackIcon.tsx} (78%)
 rename src/shared/Icon/Icons/{MoveFrontIcon.tsx => BringFrontIcon.tsx} (77%)
 delete mode 100644 src/shared/Icon/Icons/LayerArrowDownIcon.tsx
 delete mode 100644 src/shared/Icon/Icons/LayerArrowUpIcon.tsx

diff --git a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
index b806d2b6..8d925951 100644
--- a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
@@ -19,13 +19,11 @@ import { SerializedError } from '@reduxjs/toolkit';
 import { layerFactoryStateSelector } from '@/redux/modal/modal.selector';
 import './LayerFactoryModal.styles.css';
 import { LoadingIndicator } from '@/shared/LoadingIndicator';
-import { maxLayerZIndexAboveDiagramSelector } from '@/redux/layers/layers.selectors';
 
 export const LayerFactoryModal: React.FC = () => {
   const dispatch = useAppDispatch();
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerFactoryState = useAppSelector(layerFactoryStateSelector);
-  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
   const [loaded, setLoaded] = useState<boolean>(false);
 
   const [data, setData] = useState<LayerStoreInterface>({
@@ -33,7 +31,6 @@ export const LayerFactoryModal: React.FC = () => {
     visible: false,
     locked: false,
     modelId: currentModelId,
-    zIndex: maxLayerZIndexAboveDiagram,
   });
 
   const fetchData = useMemo(() => {
@@ -45,7 +42,6 @@ export const LayerFactoryModal: React.FC = () => {
           visible: layer.visible,
           locked: layer.locked,
           modelId: currentModelId,
-          zIndex: layer.z,
         });
       }
       setLoaded(true);
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
index 4d1513e9..1efb7d88 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
@@ -4,10 +4,7 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerImageObjectFactoryStateSelector } from '@/redux/modal/modal.selector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
-import {
-  layersDrawLayerSelector,
-  maxObjectZIndexForLayerSelector,
-} from '@/redux/layers/layers.selectors';
+import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
 import { addLayerImageObject } from '@/redux/layers/layers.thunks';
 import { addGlyph } from '@/redux/glyphs/glyphs.thunks';
 import { SerializedError } from '@reduxjs/toolkit';
@@ -25,7 +22,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
   const drawLayer = useAppSelector(layersDrawLayerSelector);
   const layerImageObjectFactoryState = useAppSelector(layerImageObjectFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
+  const highestZIndex = useAppSelector(highestZIndexSelector);
   const { mapInstance } = useMapInstance();
 
   const [selectedGlyph, setSelectedGlyph] = useState<number | null>(null);
@@ -52,7 +49,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
           layerId: drawLayer,
           x: layerImageObjectFactoryState.x,
           y: layerImageObjectFactoryState.y,
-          z: maxZIndex + 1,
+          z: highestZIndex + 1,
           width: layerImageObjectFactoryState.width,
           height: layerImageObjectFactoryState.height,
           glyph: glyphId,
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
index bfb80aff..e1ccf612 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
@@ -13,10 +13,7 @@ import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTex
 import { Color } from '@/types/models';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerTextFactoryStateSelector } from '@/redux/modal/modal.selector';
-import {
-  layersDrawLayerSelector,
-  maxObjectZIndexForLayerSelector,
-} from '@/redux/layers/layers.selectors';
+import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { showToast } from '@/utils/showToast';
@@ -34,7 +31,7 @@ export const LayerTextFactoryModal: React.FC = () => {
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerTextFactoryState = useAppSelector(layerTextFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
+  const highestZIndex = useAppSelector(highestZIndexSelector);
   const { mapInstance } = useMapInstance();
 
   const [isSending, setIsSending] = useState<boolean>(false);
@@ -58,7 +55,7 @@ export const LayerTextFactoryModal: React.FC = () => {
           layerId: drawLayer,
           boundingBox: layerTextFactoryState,
           textData: data,
-          z: maxZIndex + 1,
+          z: highestZIndex + 1,
         }),
       ).unwrap();
       if (!textData) {
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
index a9c3d3b3..6f57c762 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
@@ -10,8 +10,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerTextItemProps {
   layerText: LayerText;
-  moveToFront: () => void;
-  moveToBack: () => void;
+  bringToFront: () => void;
+  bringToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -21,8 +21,8 @@ interface LayersDrawerTextItemProps {
 
 export const LayersDrawerTextItem = ({
   layerText,
-  moveToFront,
-  moveToBack,
+  bringToFront,
+  bringToBack,
   removeObject,
   centerObject,
   editObject,
@@ -68,8 +68,8 @@ export const LayersDrawerTextItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          moveToFront={moveToFront}
-          moveToBack={moveToBack}
+          bringToFront={bringToFront}
+          bringToBack={bringToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
index 33c259f3..12bef081 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
@@ -4,7 +4,7 @@ import { DrawerHeading } from '@/shared/DrawerHeading';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { layersForCurrentModelSelector } from '@/redux/layers/layers.selectors';
 import { Button } from '@/shared/Button';
-import { JSX, useEffect, useMemo, useRef } from 'react';
+import { JSX, useEffect, useRef } from 'react';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
 import { LayersDrawerLayer } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component';
@@ -21,19 +21,6 @@ export const LayersDrawer = (): JSX.Element => {
     dispatch(openLayerFactoryModal());
   };
 
-  const sortedLayers = useMemo(() => {
-    return [...layersForCurrentModel].sort((layerA, layerB) => layerB.details.z - layerA.details.z);
-  }, [layersForCurrentModel]);
-
-  const negativeZLayers = useMemo(
-    () => sortedLayers.filter(layer => layer.details.z < 0),
-    [sortedLayers],
-  );
-  const positiveZLayers = useMemo(
-    () => sortedLayers.filter(layer => layer.details.z >= 0),
-    [sortedLayers],
-  );
-
   useEffect(() => {
     if (!mapEditToolsLayerImageObject || !layersDrawerRef.current) {
       return;
@@ -74,33 +61,20 @@ export const LayersDrawer = (): JSX.Element => {
         ref={layersDrawerRef}
       >
         {hasPrivilegeToWriteProject && (
-          <div className="flex justify-start py-2">
+          <div className="flex justify-start pt-2">
             <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}>
               Add layer
             </Button>
           </div>
         )}
-        <div className="flex flex-col gap-2">
-          {Boolean(positiveZLayers.length) && (
-            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
-              Layers above the diagram
-            </span>
-          )}
-          <div className="flex flex-col gap-5">
-            {positiveZLayers.map(layer => (
-              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
-            ))}
-          </div>
-          {Boolean(negativeZLayers.length) && (
-            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
-              Layers below the diagram
-            </span>
-          )}
-          <div className="flex flex-col gap-5">
-            {negativeZLayers.map(layer => (
-              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
-            ))}
-          </div>
+        <div className="flex flex-col gap-4">
+          {layersForCurrentModel.map(layer => (
+            <LayersDrawerLayer
+              key={layer.details.id}
+              layerId={layer.details.id}
+              layerName={layer.details.name}
+            />
+          ))}
         </div>
       </div>
     </div>
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
index e160b807..0622f141 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
@@ -11,8 +11,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerImageItemProps {
   layerImage: LayerImage;
-  moveToFront: () => void;
-  moveToBack: () => void;
+  bringToFront: () => void;
+  bringToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -22,8 +22,8 @@ interface LayersDrawerImageItemProps {
 
 export const LayersDrawerImageItem = ({
   layerImage,
-  moveToFront,
-  moveToBack,
+  bringToFront,
+  bringToBack,
   removeObject,
   centerObject,
   editObject,
@@ -72,8 +72,8 @@ export const LayersDrawerImageItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          moveToFront={moveToFront}
-          moveToBack={moveToBack}
+          bringToFront={bringToFront}
+          bringToBack={bringToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
index 8b0f9b01..49b8536f 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
@@ -1,19 +1,14 @@
-/* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import {
   layersActiveLayersSelector,
   layersVisibilityForCurrentModelSelector,
-  maxLayerZIndexAboveDiagramSelector,
-  maxLayerZIndexBelowDiagramSelector,
-  minLayerZIndexAboveDiagramSelector,
-  minLayerZIndexBelowDiagramSelector,
 } from '@/redux/layers/layers.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component';
 import { useState, JSX, useMemo } from 'react';
-import { getLayersForModel, removeLayer, updateLayer } from '@/redux/layers/layers.thunks';
+import { getLayersForModel, removeLayer } from '@/redux/layers/layers.thunks';
 import { showToast } from '@/utils/showToast';
 import { SerializedError } from '@reduxjs/toolkit';
 import { LayersDrawerLayerActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component';
@@ -26,42 +21,38 @@ import {
 import { LayersDrawerObjectsList } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component';
 import { mapEditToolsSetActiveAction } from '@/redux/mapEditTools/mapEditTools.slice';
 import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants';
-import { Layer } from '@/types/models';
 
 interface LayersDrawerLayerProps {
-  layerDetails: Layer;
+  layerId: number;
+  layerName: string;
 }
 
-export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX.Element => {
+export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps): JSX.Element => {
   const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector);
   const activeLayers = useAppSelector(layersActiveLayersSelector);
   const currentModelId = useAppSelector(currentModelIdSelector);
-  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
-  const maxLayerZIndexBelowDiagram = useAppSelector(maxLayerZIndexBelowDiagramSelector);
-  const minLayerZIndexAboveDiagram = useAppSelector(minLayerZIndexAboveDiagramSelector);
-  const minLayerZIndexBelowDiagram = useAppSelector(minLayerZIndexBelowDiagramSelector);
   const dispatch = useAppDispatch();
   const [isModalOpen, setIsModalOpen] = useState(false);
 
   const isLayerVisible = useMemo(() => {
-    return layersVisibilityForCurrentModel[layerDetails.id];
-  }, [layerDetails.id, layersVisibilityForCurrentModel]);
+    return layersVisibilityForCurrentModel[layerId];
+  }, [layerId, layersVisibilityForCurrentModel]);
 
   const isLayerActive = useMemo(() => {
-    return activeLayers.includes(layerDetails.id);
-  }, [activeLayers, layerDetails.id]);
+    return activeLayers.includes(layerId);
+  }, [activeLayers, layerId]);
 
   const editLayer = (): void => {
-    dispatch(openLayerFactoryModal(layerDetails.id));
+    dispatch(openLayerFactoryModal(layerId));
   };
 
   const addImage = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.DRAW_IMAGE));
   };
 
   const addText = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.ADD_TEXT));
   };
 
@@ -70,11 +61,11 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
   };
 
   const confirmRemove = async (): Promise<void> => {
-    if (!layerDetails.id) {
+    if (!layerId) {
       return;
     }
     try {
-      await dispatch(removeLayer({ modelId: currentModelId, layerId: layerDetails.id })).unwrap();
+      await dispatch(removeLayer({ modelId: currentModelId, layerId })).unwrap();
       showToast({
         type: 'success',
         message: 'The layer has been successfully removed',
@@ -96,61 +87,12 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
 
   const toggleActiveLayer = (value: boolean): void => {
     if (value) {
-      dispatch(setLayerToActive({ modelId: currentModelId, layerId: layerDetails.id }));
+      dispatch(setLayerToActive({ modelId: currentModelId, layerId }));
     } else {
-      dispatch(setLayerToInactive({ modelId: currentModelId, layerId: layerDetails.id }));
+      dispatch(setLayerToInactive({ modelId: currentModelId, layerId }));
     }
   };
 
-  const updateLayerZIndex = async (zIndex: number): Promise<void> => {
-    try {
-      dispatch(
-        updateLayer({
-          name: layerDetails.name,
-          visible: layerDetails.visible,
-          locked: layerDetails.locked,
-          modelId: currentModelId,
-          layerId: layerDetails.id,
-          zIndex,
-        }),
-      );
-    } catch (error) {
-      const typedError = error as SerializedError;
-      showToast({
-        type: 'error',
-        message: typedError.message || 'An error occurred while updating the layer',
-      });
-    }
-  };
-
-  const moveToFront = (): void => {
-    if (layerDetails.z > 0) {
-      updateLayerZIndex(maxLayerZIndexAboveDiagram);
-    } else if (layerDetails.z < 0) {
-      const zIndex = Math.min(maxLayerZIndexBelowDiagram, -1);
-      updateLayerZIndex(zIndex);
-    }
-  };
-
-  const moveToBack = (): void => {
-    if (layerDetails.z > 0) {
-      const zIndex = Math.max(minLayerZIndexAboveDiagram, 1);
-      updateLayerZIndex(zIndex);
-    } else if (layerDetails.z < 0) {
-      updateLayerZIndex(minLayerZIndexBelowDiagram);
-    }
-  };
-
-  const moveAboveDiagram = (): void => {
-    const zIndex = Math.max(minLayerZIndexAboveDiagram - 1, 1);
-    updateLayerZIndex(zIndex);
-  };
-
-  const moveBelowDiagram = (): void => {
-    const zIndex = Math.min(minLayerZIndexBelowDiagram + 1, -1);
-    updateLayerZIndex(zIndex);
-  };
-
   return (
     <div>
       <QuestionModal
@@ -159,13 +101,9 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
         onConfirm={confirmRemove}
         question="Are you sure you want to remove the layer?"
       />
-      <div className="flex items-center justify-between pb-3">
-        <span
-          className={`font-semibold ${
-            isLayerVisible ? 'opacity-100' : 'opacity-40'
-          } min-w-0 flex-1 truncate `}
-        >
-          {layerDetails.name}
+      <div className="flex items-center justify-between py-3">
+        <span className={`font-semibold ${isLayerVisible ? 'opacity-100' : 'opacity-40'}`}>
+          {layerName}
         </span>
         <LayersDrawerLayerActions
           toggleVisibility={() =>
@@ -173,7 +111,7 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
               setLayerVisibility({
                 modelId: currentModelId,
                 visible: !isLayerVisible,
-                layerId: layerDetails.id,
+                layerId,
               }),
             )
           }
@@ -182,17 +120,12 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
           removeLayer={onRemoveLayer}
           addImage={addImage}
           addText={addText}
-          moveToFront={moveToFront}
-          moveToBack={moveToBack}
-          moveAboveDiagram={moveAboveDiagram}
-          moveBelowDiagram={moveBelowDiagram}
-          zIndex={layerDetails.z}
           isVisible={isLayerVisible}
           isActive={isLayerActive}
         />
       </div>
       <LayersDrawerObjectsList
-        layerId={layerDetails.id}
+        layerId={layerId}
         isLayerVisible={isLayerVisible}
         isLayerActive={isLayerActive}
       />
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
index 81435100..18627b13 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable no-magic-numbers */
 import { IconButton } from '@/shared/IconButton';
 import { JSX } from 'react';
 import { LayerDrawerLayerContextMenu } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component';
@@ -10,15 +9,10 @@ type LayersDrawerLayerActionsProps = {
   removeLayer: () => void;
   isVisible: boolean;
   isActive: boolean;
-  zIndex: number;
   toggleVisibility: () => void;
   toggleActiveLayer: (value: boolean) => void;
   addImage: () => void;
   addText: () => void;
-  moveToFront: () => void;
-  moveToBack: () => void;
-  moveAboveDiagram: () => void;
-  moveBelowDiagram: () => void;
 };
 
 export const LayersDrawerLayerActions = ({
@@ -26,15 +20,10 @@ export const LayersDrawerLayerActions = ({
   removeLayer,
   isVisible,
   isActive,
-  zIndex,
   toggleVisibility,
   toggleActiveLayer,
   addImage,
   addText,
-  moveToFront,
-  moveToBack,
-  moveAboveDiagram,
-  moveBelowDiagram,
 }: LayersDrawerLayerActionsProps): JSX.Element => {
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
 
@@ -54,34 +43,6 @@ export const LayersDrawerLayerActions = ({
             className="h-auto w-auto bg-transparent p-0"
             onClick={() => toggleActiveLayer(!isActive)}
           />
-          <IconButton
-            title="Move to front"
-            icon="move-front"
-            className="h-auto w-auto bg-transparent p-0"
-            onClick={moveToFront}
-          />
-          <IconButton
-            title="Move to back"
-            icon="move-back"
-            className="h-auto w-auto bg-transparent p-0"
-            onClick={moveToBack}
-          />
-          {zIndex < 0 && (
-            <IconButton
-              title="Move above the diagram"
-              icon="layer-arrow-up"
-              className="h-auto w-auto bg-transparent p-0"
-              onClick={moveAboveDiagram}
-            />
-          )}
-          {zIndex > 0 && (
-            <IconButton
-              title="Move below the diagram"
-              icon="layer-arrow-down"
-              className="h-auto w-auto bg-transparent p-0"
-              onClick={moveBelowDiagram}
-            />
-          )}
           <LayerDrawerLayerContextMenu
             removeLayer={removeLayer}
             editLayer={editLayer}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
index a97189ea..4cf6871e 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
@@ -2,16 +2,16 @@ import { JSX } from 'react';
 import { IconButton } from '@/shared/IconButton';
 
 interface LayersDrawerObjectActionsProps {
-  moveToFront: () => void;
-  moveToBack: () => void;
+  bringToFront: () => void;
+  bringToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
 }
 
 export const LayersDrawerObjectActions = ({
-  moveToFront,
-  moveToBack,
+  bringToFront,
+  bringToBack,
   removeObject,
   centerObject,
   editObject,
@@ -31,16 +31,16 @@ export const LayersDrawerObjectActions = ({
         onClick={editObject}
       />
       <IconButton
-        icon="move-front"
+        icon="bring-front"
         className="h-auto w-auto bg-transparent p-0"
-        title="Move to front"
-        onClick={moveToFront}
+        title="Bring to front"
+        onClick={bringToFront}
       />
       <IconButton
-        icon="move-back"
+        icon="bring-back"
         className="h-auto w-auto bg-transparent p-0"
-        title="Move to back"
-        onClick={moveToBack}
+        title="Bring to back"
+        onClick={bringToBack}
       />
       <IconButton
         icon="trash"
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index 9ec19fe4..70a6acf5 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -1,9 +1,9 @@
 /* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import {
+  highestZIndexSelector,
   layerByIdSelector,
-  maxObjectZIndexForLayerSelector,
-  minObjectZIndexForLayerSelector,
+  lowestZIndexSelector,
 } from '@/redux/layers/layers.selectors';
 import { JSX, useState } from 'react';
 import { LayersDrawerImageItem } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component';
@@ -64,8 +64,8 @@ export const LayersDrawerObjectsList = ({
   isLayerActive,
 }: LayersDrawerObjectsListProps): JSX.Element | null => {
   const currentModelId = useAppSelector(mapModelIdSelector);
-  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, layerId));
-  const minZIndex = useAppSelector(state => minObjectZIndexForLayerSelector(state, layerId));
+  const highestZIndex = useAppSelector(highestZIndexSelector);
+  const lowestZIndex = useAppSelector(lowestZIndexSelector);
   const layer = useAppSelector(state => layerByIdSelector(state, layerId));
   const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector);
   const [removeModalState, setRemoveModalState] = useState<undefined | 'text' | 'image'>(undefined);
@@ -174,12 +174,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const moveImageToFront = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: maxZIndex + 1, layerImage });
+  const bringImageToFront = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: highestZIndex + 1, layerImage });
   };
 
-  const moveImageToBack = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: minZIndex - 1, layerImage });
+  const bringImageToBack = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: lowestZIndex - 1, layerImage });
   };
 
   const updateTextZIndex = async ({
@@ -210,12 +210,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const moveTextToFront = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: maxZIndex + 1, layerText });
+  const bringTextToFront = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: highestZIndex + 1, layerText });
   };
 
-  const moveTextToBack = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: minZIndex - 1, layerText });
+  const bringTextToBack = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: lowestZIndex - 1, layerText });
   };
 
   const centerObject = (layerObject: LayerImage | LayerText): void => {
@@ -257,8 +257,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerTextItem
           layerText={layerText}
           key={layerText.id}
-          moveToFront={() => moveTextToFront(layerText)}
-          moveToBack={() => moveTextToBack(layerText)}
+          bringToFront={() => bringTextToFront(layerText)}
+          bringToBack={() => bringTextToBack(layerText)}
           removeObject={() => removeObject(layerText)}
           centerObject={() => centerObject(layerText)}
           editObject={() => editText()}
@@ -270,8 +270,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerImageItem
           layerImage={layerImage}
           key={layerImage.id}
-          moveToFront={() => moveImageToFront(layerImage)}
-          moveToBack={() => moveImageToBack(layerImage)}
+          bringToFront={() => bringImageToFront(layerImage)}
+          bringToBack={() => bringImageToBack(layerImage)}
           removeObject={() => removeObject(layerImage)}
           centerObject={() => centerObject(layerImage)}
           editObject={() => editImage()}
diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
index 6d41944f..5e378293 100644
--- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
+++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
@@ -125,7 +125,6 @@ export const useOlMapAdditionalLayers = (
   const vectorLayers = useMemo(() => {
     return layersState.map(layer => {
       const additionalLayer = new Layer({
-        zIndex: layer.details.z,
         texts: layer.texts,
         rects: layer.rects,
         ovals: layer.ovals,
diff --git a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
index a3640020..7ac3b73b 100644
--- a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
@@ -36,7 +36,6 @@ export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geomet
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
-      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.COMMENTS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
index db3dbad4..69cec807 100644
--- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
@@ -38,7 +38,6 @@ export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
-      zIndex: -Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({
diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
index 4cd5a32b..f7b6001c 100644
--- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
@@ -77,7 +77,6 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
-      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.PINS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
index 98cb6e1e..2811ec30 100644
--- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
@@ -274,7 +274,6 @@ export const useOlMapProcessLayer = ({
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
-      zIndex: 0,
       source: vectorSource,
       updateWhileAnimating: true,
       updateWhileInteracting: true,
diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
index df526271..bfb2668e 100644
--- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
@@ -63,7 +63,6 @@ export const useOlMapReactionsLayer = (): VectorLayer<VectorSource<Feature<Geome
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
-      zIndex: Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({ color: LINE_COLOR }),
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
index 10349c6d..7b8bb971 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
@@ -133,7 +133,6 @@ describe('Layer', () => {
       pointToProjection: jest.fn(point => [point.x, point.y]),
       mapInstance,
       mapSize,
-      zIndex: 1,
       lineTypes: {},
       arrowTypes: {},
     };
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
index 14d5f8b5..7f697a72 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
@@ -34,7 +34,6 @@ import LayerText from '@/components/Map/MapViewer/utils/shapes/layer/elements/La
 import LayerImage from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage';
 
 export interface LayerProps {
-  zIndex: number;
   texts: { [key: string]: LayerTextModel };
   rects: Array<LayerRect>;
   ovals: Array<LayerOval>;
@@ -79,7 +78,6 @@ export default class Layer {
   >;
 
   constructor({
-    zIndex,
     texts,
     rects,
     ovals,
@@ -120,7 +118,6 @@ export default class Layer {
     this.vectorSource.addFeatures(arrowsFeatures);
 
     this.vectorLayer = new VectorLayer({
-      zIndex,
       source: this.vectorSource,
       visible,
       updateWhileAnimating: true,
diff --git a/src/models/layerSchema.ts b/src/models/layerSchema.ts
index 11fcd88d..380146a7 100644
--- a/src/models/layerSchema.ts
+++ b/src/models/layerSchema.ts
@@ -5,5 +5,4 @@ export const layerSchema = z.object({
   name: z.string(),
   visible: z.boolean(),
   locked: z.boolean(),
-  z: z.number(),
 });
diff --git a/src/redux/layers/layers.reducers.test.ts b/src/redux/layers/layers.reducers.test.ts
index d93fb4f8..7bcb10ba 100644
--- a/src/redux/layers/layers.reducers.test.ts
+++ b/src/redux/layers/layers.reducers.test.ts
@@ -92,7 +92,7 @@ describe('layers reducer', () => {
 
     const { type } = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
-    expect(type).toBe('layers/getLayers/fulfilled');
+    expect(type).toBe('vectorMap/getLayers/fulfilled');
     expect(loading).toEqual('succeeded');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual({
@@ -120,7 +120,7 @@ describe('layers reducer', () => {
     const action = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
 
-    expect(action.type).toBe('layers/getLayers/rejected');
+    expect(action.type).toBe('vectorMap/getLayers/rejected');
     expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch layers: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
diff --git a/src/redux/layers/layers.selectors.ts b/src/redux/layers/layers.selectors.ts
index 8123fa00..8f016c8a 100644
--- a/src/redux/layers/layers.selectors.ts
+++ b/src/redux/layers/layers.selectors.ts
@@ -2,7 +2,6 @@
 import { createSelector } from '@reduxjs/toolkit';
 import { rootSelector } from '@/redux/root/root.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
-import { LayerState } from '@/redux/layers/layers.types';
 
 export const layersSelector = createSelector(rootSelector, state => state.layers);
 
@@ -19,7 +18,7 @@ export const layersActiveLayersSelector = createSelector(
 
 export const layersDrawLayerSelector = createSelector(
   layersStateForCurrentModelSelector,
-  state => state?.data?.drawLayer || null,
+  state => state?.data?.drawLayer,
 );
 
 export const layerByIdSelector = createSelector(
@@ -42,112 +41,40 @@ export const layersForCurrentModelSelector = createSelector(
   state => state?.data?.layers || [],
 );
 
-export const maxLayerZIndexAboveDiagramSelector = createSelector(
-  layersForCurrentModelSelector,
-  layers => {
-    if (!layers || layers.length === 0) {
-      return 1000;
-    }
-    let maxZIndex = -Infinity;
-    layers.forEach((layer: LayerState) => {
-      if (layer.details.z > 0 && layer.details.z > maxZIndex) {
-        maxZIndex = layer.details.z;
-      }
-    });
-    return maxZIndex;
-  },
-);
+export const highestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
+  if (!layers || layers.length === 0) return 0;
 
-export const maxLayerZIndexBelowDiagramSelector = createSelector(
-  layersForCurrentModelSelector,
-  layers => {
-    if (!layers || layers.length === 0) {
-      return -1000;
-    }
-    let maxZIndex = -Infinity;
-    layers.forEach((layer: LayerState) => {
-      if (layer.details.z < 0 && layer.details.z > maxZIndex) {
-        maxZIndex = layer.details.z;
-      }
-    });
-    return maxZIndex;
-  },
-);
+  const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+    items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
 
-export const minLayerZIndexAboveDiagramSelector = createSelector(
-  layersForCurrentModelSelector,
-  layers => {
-    if (!layers || layers.length === 0) {
-      return 1000;
-    }
-    let minZIndex = Infinity;
-    layers.forEach((layer: LayerState) => {
-      if (layer.details.z > 0 && layer.details.z < minZIndex) {
-        minZIndex = layer.details.z;
-      }
-    });
-    return minZIndex;
-  },
-);
+  return layers.reduce((maxZ, layer) => {
+    const textsMaxZ = getMaxZFromItems(Object.values(layer.texts));
+    const rectsMaxZ = getMaxZFromItems(layer.rects);
+    const ovalsMaxZ = getMaxZFromItems(layer.ovals);
+    const linesMaxZ = getMaxZFromItems(layer.lines);
+    const imagesMaxZ = getMaxZFromItems(Object.values(layer.images));
 
-export const minLayerZIndexBelowDiagramSelector = createSelector(
-  layersForCurrentModelSelector,
-  layers => {
-    if (!layers || layers.length === 0) {
-      return -1000;
-    }
-    let minZIndex = Infinity;
-    layers.forEach((layer: LayerState) => {
-      if (layer.details.z < 0 && layer.details.z < minZIndex) {
-        minZIndex = layer.details.z;
-      }
-    });
-    return minZIndex;
-  },
-);
+    const layerMaxZ = Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
 
-export const maxObjectZIndexForLayerSelector = createSelector(
-  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
-  (layers, layerId) => {
-    if (!layers || layers.length === 0 || !layerId) {
-      return 0;
-    }
-    const foundLayer = layers.find(layer => layer.details.id === layerId);
-    if (!foundLayer) {
-      return 0;
-    }
-    const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-      items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
-
-    const textsMaxZ = getMaxZFromItems(Object.values(foundLayer.texts));
-    const rectsMaxZ = getMaxZFromItems(foundLayer.rects);
-    const ovalsMaxZ = getMaxZFromItems(foundLayer.ovals);
-    const linesMaxZ = getMaxZFromItems(foundLayer.lines);
-    const imagesMaxZ = getMaxZFromItems(Object.values(foundLayer.images));
-
-    return Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
-  },
-);
+    return Math.max(maxZ, layerMaxZ);
+  }, 0);
+});
 
-export const minObjectZIndexForLayerSelector = createSelector(
-  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
-  (layers, layerId) => {
-    if (!layers || layers.length === 0 || !layerId) {
-      return 0;
-    }
-    const foundLayer = layers.find(layer => layer.details.id === layerId);
-    if (!foundLayer) {
-      return 0;
-    }
-    const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-      items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
-
-    const textsMinZ = getMinZFromItems(Object.values(foundLayer.texts));
-    const rectsMinZ = getMinZFromItems(foundLayer.rects);
-    const ovalsMinZ = getMinZFromItems(foundLayer.ovals);
-    const linesMinZ = getMinZFromItems(foundLayer.lines);
-    const imagesMinZ = getMinZFromItems(Object.values(foundLayer.images));
-
-    return Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
-  },
-);
+export const lowestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
+  if (!layers || layers.length === 0) return 0;
+
+  const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+    items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
+
+  return layers.reduce((minZ, layer) => {
+    const textsMinZ = getMinZFromItems(Object.values(layer.texts));
+    const rectsMinZ = getMinZFromItems(layer.rects);
+    const ovalsMinZ = getMinZFromItems(layer.ovals);
+    const linesMinZ = getMinZFromItems(layer.lines);
+    const imagesMinZ = getMinZFromItems(Object.values(layer.images));
+
+    const layerMinZ = Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
+
+    return Math.min(minZ, layerMinZ);
+  }, 0);
+});
diff --git a/src/redux/layers/layers.thunks.test.ts b/src/redux/layers/layers.thunks.test.ts
index 09028272..77e10bdb 100644
--- a/src/redux/layers/layers.thunks.test.ts
+++ b/src/redux/layers/layers.thunks.test.ts
@@ -111,13 +111,7 @@ describe('layers thunks', () => {
       mockedAxiosClient.onPost(apiPath.storeLayer(1)).reply(HttpStatusCode.Created, layerFixture);
 
       const { payload } = await store.dispatch(
-        addLayerForModel({
-          name: 'New Layer',
-          visible: true,
-          locked: false,
-          modelId: 1,
-          zIndex: 1,
-        }),
+        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
       );
       expect(payload).toEqual(layerFixture);
     });
@@ -128,13 +122,7 @@ describe('layers thunks', () => {
         .reply(HttpStatusCode.Created, { invalid: 'data' });
 
       const { payload } = await store.dispatch(
-        addLayerForModel({
-          name: 'New Layer',
-          visible: true,
-          locked: false,
-          modelId: 1,
-          zIndex: 1,
-        }),
+        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
       );
       expect(payload).toBeNull();
     });
@@ -151,7 +139,6 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
-          zIndex: 1,
         }),
       );
       expect(payload).toEqual(layerFixture);
@@ -169,7 +156,6 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
-          zIndex: 1,
         }),
       );
       expect(payload).toBeNull();
diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts
index bda72fce..66035fd8 100644
--- a/src/redux/layers/layers.thunks.ts
+++ b/src/redux/layers/layers.thunks.ts
@@ -32,7 +32,7 @@ export const getLayer = createAsyncThunk<
   Layer | null,
   { modelId: number; layerId: number },
   ThunkConfig
->('layers/getLayer', async ({ modelId, layerId }) => {
+>('vectorMap/getLayer', async ({ modelId, layerId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layer>(apiPath.getLayer(modelId, layerId));
 
@@ -48,7 +48,7 @@ export const getLayersForModel = createAsyncThunk<
   LayersVisibilitiesState | undefined,
   number,
   ThunkConfig
->('layers/getLayers', async (modelId: number) => {
+>('vectorMap/getLayers', async (modelId: number) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layers>(apiPath.getLayers(modelId));
     const isDataValid = validateDataUsingZodSchema(data, pageableSchema(layerSchema));
@@ -103,14 +103,13 @@ export const getLayersForModel = createAsyncThunk<
 });
 
 export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterface, ThunkConfig>(
-  'layers/addLayer',
-  async ({ name, visible, locked, modelId, zIndex }) => {
+  'vectorMap/addLayer',
+  async ({ name, visible, locked, modelId }) => {
     try {
       const { data } = await axiosInstanceNewAPI.post<Layer>(apiPath.storeLayer(modelId), {
         name,
         visible,
         locked,
-        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -123,14 +122,13 @@ export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterfa
 );
 
 export const updateLayer = createAsyncThunk<Layer | null, LayerUpdateInterface, ThunkConfig>(
-  'layers/updateLayer',
-  async ({ name, visible, locked, modelId, layerId, zIndex }) => {
+  'vectorMap/updateLayer',
+  async ({ name, visible, locked, modelId, layerId }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<Layer>(apiPath.updateLayer(modelId, layerId), {
         name,
         visible,
         locked,
-        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -146,7 +144,7 @@ export const removeLayer = createAsyncThunk<
   null,
   { modelId: number; layerId: number },
   ThunkConfig
->('layers/removeLayer', async ({ modelId, layerId }) => {
+>('vectorMap/removeLayer', async ({ modelId, layerId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(apiPath.removeLayer(modelId, layerId));
     return null;
@@ -163,7 +161,7 @@ export const getLayerImage = createAsyncThunk<
     imageId: number;
   },
   ThunkConfig
->('layers/getLayerImage', async ({ modelId, layerId, imageId }) => {
+>('vectorMap/getLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerImage>(
       apiPath.getLayerImageObject(modelId, layerId, imageId),
@@ -189,7 +187,7 @@ export const addLayerImageObject = createAsyncThunk<
     glyph: number | null;
   },
   ThunkConfig
->('layers/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
+>('vectorMap/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerImage>(
       apiPath.addLayerImageObject(modelId, layerId),
@@ -225,7 +223,7 @@ export const updateLayerImageObject = createAsyncThunk<
   },
   ThunkConfig
 >(
-  'layers/updateLayerImageObject',
+  'vectorMap/updateLayerImageObject',
   async ({ modelId, layerId, id, x, y, z, width, height, glyph }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<LayerImage>(
@@ -254,7 +252,7 @@ export const removeLayerImage = createAsyncThunk<
   null,
   { modelId: number; layerId: number; imageId: number },
   ThunkConfig
->('layers/removeLayerImage', async ({ modelId, layerId, imageId }) => {
+>('vectorMap/removeLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(
       apiPath.removeLayerImageObject(modelId, layerId, imageId),
@@ -275,7 +273,7 @@ export const addLayerText = createAsyncThunk<
     textData: LayerTextFactoryForm;
   },
   ThunkConfig
->('layers/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
+>('vectorMap/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerText>(
       apiPath.addLayerText(modelId, layerId),
@@ -301,7 +299,7 @@ export const getLayerText = createAsyncThunk<
     textId: number;
   },
   ThunkConfig
->('layers/getLayerText', async ({ modelId, layerId, textId }) => {
+>('vectorMap/getLayerText', async ({ modelId, layerId, textId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerText>(
       apiPath.getLayerText(modelId, layerId, textId),
diff --git a/src/redux/layers/layers.types.ts b/src/redux/layers/layers.types.ts
index 05b4636e..60e42717 100644
--- a/src/redux/layers/layers.types.ts
+++ b/src/redux/layers/layers.types.ts
@@ -6,7 +6,6 @@ export interface LayerStoreInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
-  zIndex: number;
 }
 
 export interface LayerUpdateInterface {
@@ -15,7 +14,6 @@ export interface LayerUpdateInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
-  zIndex: number;
 }
 
 export type LayerState = {
diff --git a/src/shared/Icon/Icon.component.tsx b/src/shared/Icon/Icon.component.tsx
index aed961c3..5745b6ec 100644
--- a/src/shared/Icon/Icon.component.tsx
+++ b/src/shared/Icon/Icon.component.tsx
@@ -31,10 +31,8 @@ import { PadlockOpenIcon } from '@/shared/Icon/Icons/PadlockOpenIcon';
 import { PadlockLockedIcon } from '@/shared/Icon/Icons/PadlockLockedIcon';
 import { CrossedEyeIcon } from '@/shared/Icon/Icons/CrossedEyeIcon';
 import { CenterIcon } from '@/shared/Icon/Icons/CenterIcon';
-import { MoveFrontIcon } from '@/shared/Icon/Icons/MoveFrontIcon';
-import { MoveBackIcon } from '@/shared/Icon/Icons/MoveBackIcon';
-import { LayerArrowUpIcon } from '@/shared/Icon/Icons/LayerArrowUpIcon';
-import { LayerArrowDownIcon } from '@/shared/Icon/Icons/LayerArrowDownIcon';
+import { BringFrontIcon } from '@/shared/Icon/Icons/BringFrontIcon';
+import { BringBackIcon } from '@/shared/Icon/Icons/BringBackIcon';
 import { LocationIcon } from './Icons/LocationIcon';
 import { MaginfierZoomInIcon } from './Icons/MagnifierZoomIn';
 import { MaginfierZoomOutIcon } from './Icons/MagnifierZoomOut';
@@ -89,10 +87,8 @@ const icons: Record<IconTypes, IconComponentType> = {
   'padlock-open': PadlockOpenIcon,
   'padlock-locked': PadlockLockedIcon,
   center: CenterIcon,
-  'move-front': MoveFrontIcon,
-  'move-back': MoveBackIcon,
-  'layer-arrow-up': LayerArrowUpIcon,
-  'layer-arrow-down': LayerArrowDownIcon,
+  'bring-front': BringFrontIcon,
+  'bring-back': BringBackIcon,
 } as const;
 
 export const Icon = ({ name, className = '', ...rest }: IconProps): JSX.Element => {
diff --git a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
index cf5ce5f7..d7ab4e38 100644
--- a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
@@ -13,16 +13,26 @@ export const ArrowDoubleDownIcon = ({ className }: ArrowDoubleDownIconProps): JS
   >
     <path
       d="M8 8L8 18M8 18L5 15M8 18L11 15"
+      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 8L16 18M16 18L13 15M16 18L19 15"
+      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line x1="4" y1="6" x2="20" y2="6" strokeWidth="1.5" strokeLinecap="round" />
+    <line
+      x1="4"
+      y1="6"
+      x2="20"
+      y2="6"
+      stroke="currentColor"
+      strokeWidth="1.5"
+      strokeLinecap="round"
+    />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
index 861773cd..ed51a602 100644
--- a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
@@ -13,16 +13,26 @@ export const ArrowDoubleUpIcon = ({ className }: ArrowDoubleUpIconProps): JSX.El
   >
     <path
       d="M8 16L8 6M8 6L5 9M8 6L11 9"
+      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 16L16 6M16 6L13 9M16 6L19 9"
+      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line x1="4" y1="18" x2="20" y2="18" strokeWidth="1.5" strokeLinecap="round" />
+    <line
+      x1="4"
+      y1="18"
+      x2="20"
+      y2="18"
+      stroke="currentColor"
+      strokeWidth="1.5"
+      strokeLinecap="round"
+    />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/MoveBackIcon.tsx b/src/shared/Icon/Icons/BringBackIcon.tsx
similarity index 78%
rename from src/shared/Icon/Icons/MoveBackIcon.tsx
rename to src/shared/Icon/Icons/BringBackIcon.tsx
index 734bd201..d086ac9b 100644
--- a/src/shared/Icon/Icons/MoveBackIcon.tsx
+++ b/src/shared/Icon/Icons/BringBackIcon.tsx
@@ -1,8 +1,8 @@
-interface MoveBackIconProps {
+interface BringBackIconProps {
   className?: string;
 }
 
-export const MoveBackIcon = ({ className }: MoveBackIconProps): JSX.Element => (
+export const BringBackIcon = ({ className }: BringBackIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -23,6 +23,6 @@ export const MoveBackIcon = ({ className }: MoveBackIconProps): JSX.Element => (
       stroke="white"
       fill="none"
     />
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/MoveFrontIcon.tsx b/src/shared/Icon/Icons/BringFrontIcon.tsx
similarity index 77%
rename from src/shared/Icon/Icons/MoveFrontIcon.tsx
rename to src/shared/Icon/Icons/BringFrontIcon.tsx
index 037f5cb3..e5aa5017 100644
--- a/src/shared/Icon/Icons/MoveFrontIcon.tsx
+++ b/src/shared/Icon/Icons/BringFrontIcon.tsx
@@ -1,8 +1,8 @@
-interface MoveFrontIconProps {
+interface BringFrontIconProps {
   className?: string;
 }
 
-export const MoveFrontIcon = ({ className }: MoveFrontIconProps): JSX.Element => (
+export const BringFrontIcon = ({ className }: BringFrontIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -11,7 +11,7 @@ export const MoveFrontIcon = ({ className }: MoveFrontIconProps): JSX.Element =>
     fill="none"
     className={className}
   >
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
     <rect
       x="30"
       y="30"
diff --git a/src/shared/Icon/Icons/LayerArrowDownIcon.tsx b/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
deleted file mode 100644
index 71223a31..00000000
--- a/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-interface LayerArrowDownIconProps {
-  className?: string;
-}
-
-export const LayerArrowDownIcon = ({ className }: LayerArrowDownIconProps): JSX.Element => (
-  <svg
-    width="20"
-    height="20"
-    viewBox="2 3 20 17"
-    fill="none"
-    xmlns="http://www.w3.org/2000/svg"
-    className={className}
-  >
-    <path d="M12 21L7 16H10V10H14V16H17L12 21Z" />
-    <rect x="4" y="3" width="16" height="2" />
-    <rect x="4" y="7" width="16" height="2" />
-  </svg>
-);
diff --git a/src/shared/Icon/Icons/LayerArrowUpIcon.tsx b/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
deleted file mode 100644
index bbcf233f..00000000
--- a/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-interface LayerArrowUpIconProps {
-  className?: string;
-}
-
-export const LayerArrowUpIcon = ({ className }: LayerArrowUpIconProps): JSX.Element => (
-  <svg
-    width="20"
-    height="20"
-    viewBox="2 3 20 19"
-    fill="none"
-    xmlns="http://www.w3.org/2000/svg"
-    className={className}
-  >
-    <path d="M12 3L7 8H10V14H14V8H17L12 3Z" />
-    <rect x="4" y="16" width="16" height="2" />
-    <rect x="4" y="20" width="16" height="2" />
-  </svg>
-);
diff --git a/src/shared/IconButton/IconButton.component.tsx b/src/shared/IconButton/IconButton.component.tsx
index e71c6211..1330e460 100644
--- a/src/shared/IconButton/IconButton.component.tsx
+++ b/src/shared/IconButton/IconButton.component.tsx
@@ -29,8 +29,8 @@ export const IconButton = ({
 
   const isStrokeIcon = [
     'plugin',
-    'move-back',
-    'move-front',
+    'bring-back',
+    'bring-front',
     'center',
     'eye',
     'crossed-eye',
@@ -38,8 +38,6 @@ export const IconButton = ({
     'padlock-locked',
     'layers',
     'edit',
-    'arrow-double-up',
-    'arrow-double-down',
   ].includes(icon);
 
   return (
@@ -59,8 +57,6 @@ export const IconButton = ({
           isStrokeIcon
             ? 'stroke-font-400 group-hover:stroke-primary-500 group-active:stroke-primary-500'
             : 'fill-font-400 group-hover:fill-primary-500 group-active:fill-primary-500',
-          ['move-back', 'move-front'].includes(icon) &&
-            'fill-font-400 stroke-font-400 group-hover:fill-primary-500 group-hover:stroke-primary-500 group-active:fill-primary-500 group-active:stroke-primary-500',
           isActive && getActiveFillOrStrokeColor(icon),
           classNameIcon,
         )}
diff --git a/src/types/iconTypes.ts b/src/types/iconTypes.ts
index 0083a622..0d74dd78 100644
--- a/src/types/iconTypes.ts
+++ b/src/types/iconTypes.ts
@@ -38,9 +38,7 @@ export type IconTypes =
   | 'padlock-open'
   | 'padlock-locked'
   | 'center'
-  | 'move-front'
-  | 'move-back'
-  | 'layer-arrow-up'
-  | 'layer-arrow-down';
+  | 'bring-front'
+  | 'bring-back';
 
 export type IconComponentType = ({ className }: { className: string }) => JSX.Element;
-- 
GitLab


From 9a22256d5716408896071fe7f94a3eb95ca86932 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 10:24:21 +0100
Subject: [PATCH 5/8] feat(layers): add layers zIndex editing

-- 
GitLab


From 3b5fd23cd01eca739523f29616d79577817a2bd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 10:27:03 +0100
Subject: [PATCH 6/8] Revert "Revert "feat(layers): add layers zIndex editing""

This reverts commit f6e504ece2951e59900cec58b70bec18b21b4bde.
---
 .../LayerFactoryModal.component.tsx           |   4 +
 ...LayerImageObjectFactoryModal.component.tsx |   9 +-
 .../LayerTextFactoryModal.component.tsx       |   9 +-
 .../LayerDrawerTextItem.component.tsx         |  12 +-
 .../LayersDrawer/LayersDrawer.component.tsx   |  46 ++++--
 .../LayersDrawerImageItem.component.tsx       |  12 +-
 .../LayersDrawerLayer.component.tsx           | 107 +++++++++++---
 .../LayersDrawerLayerActions.component.tsx    |  39 +++++
 .../LayersDrawerObjectActions.component.tsx   |  20 +--
 .../LayersDrawerObjectsList.component.tsx     |  32 ++--
 .../useOlMapAdditionalLayers.ts               |   1 +
 .../commentsLayer/useOlMapCommentsLayer.ts    |   1 +
 .../config/mapCardLayer/useOlMapCardLayer.ts  |   1 +
 .../config/pinsLayer/useOlMapPinsLayer.ts     |   1 +
 .../processLayer/useOlMapProcessLayer.ts      |   1 +
 .../reactionsLayer/useOlMapReactionsLayer.ts  |   1 +
 .../utils/shapes/layer/Layer.test.ts          |   1 +
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |   3 +
 src/models/layerSchema.ts                     |   1 +
 src/redux/layers/layers.reducers.test.ts      |   4 +-
 src/redux/layers/layers.selectors.ts          | 139 +++++++++++++-----
 src/redux/layers/layers.thunks.test.ts        |  18 ++-
 src/redux/layers/layers.thunks.ts             |  28 ++--
 src/redux/layers/layers.types.ts              |   2 +
 src/shared/Icon/Icon.component.tsx            |  12 +-
 src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx |  12 +-
 src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx   |  12 +-
 src/shared/Icon/Icons/LayerArrowDownIcon.tsx  |  18 +++
 src/shared/Icon/Icons/LayerArrowUpIcon.tsx    |  18 +++
 .../{BringBackIcon.tsx => MoveBackIcon.tsx}   |   6 +-
 .../{BringFrontIcon.tsx => MoveFrontIcon.tsx} |   6 +-
 .../IconButton/IconButton.component.tsx       |   8 +-
 src/types/iconTypes.ts                        |   6 +-
 33 files changed, 430 insertions(+), 160 deletions(-)
 create mode 100644 src/shared/Icon/Icons/LayerArrowDownIcon.tsx
 create mode 100644 src/shared/Icon/Icons/LayerArrowUpIcon.tsx
 rename src/shared/Icon/Icons/{BringBackIcon.tsx => MoveBackIcon.tsx} (78%)
 rename src/shared/Icon/Icons/{BringFrontIcon.tsx => MoveFrontIcon.tsx} (77%)

diff --git a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
index 8d925951..b806d2b6 100644
--- a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
@@ -19,11 +19,13 @@ import { SerializedError } from '@reduxjs/toolkit';
 import { layerFactoryStateSelector } from '@/redux/modal/modal.selector';
 import './LayerFactoryModal.styles.css';
 import { LoadingIndicator } from '@/shared/LoadingIndicator';
+import { maxLayerZIndexAboveDiagramSelector } from '@/redux/layers/layers.selectors';
 
 export const LayerFactoryModal: React.FC = () => {
   const dispatch = useAppDispatch();
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerFactoryState = useAppSelector(layerFactoryStateSelector);
+  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
   const [loaded, setLoaded] = useState<boolean>(false);
 
   const [data, setData] = useState<LayerStoreInterface>({
@@ -31,6 +33,7 @@ export const LayerFactoryModal: React.FC = () => {
     visible: false,
     locked: false,
     modelId: currentModelId,
+    zIndex: maxLayerZIndexAboveDiagram,
   });
 
   const fetchData = useMemo(() => {
@@ -42,6 +45,7 @@ export const LayerFactoryModal: React.FC = () => {
           visible: layer.visible,
           locked: layer.locked,
           modelId: currentModelId,
+          zIndex: layer.z,
         });
       }
       setLoaded(true);
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
index 1efb7d88..4d1513e9 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.tsx
@@ -4,7 +4,10 @@ import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerImageObjectFactoryStateSelector } from '@/redux/modal/modal.selector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
-import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
+import {
+  layersDrawLayerSelector,
+  maxObjectZIndexForLayerSelector,
+} from '@/redux/layers/layers.selectors';
 import { addLayerImageObject } from '@/redux/layers/layers.thunks';
 import { addGlyph } from '@/redux/glyphs/glyphs.thunks';
 import { SerializedError } from '@reduxjs/toolkit';
@@ -22,7 +25,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
   const drawLayer = useAppSelector(layersDrawLayerSelector);
   const layerImageObjectFactoryState = useAppSelector(layerImageObjectFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const highestZIndex = useAppSelector(highestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
   const { mapInstance } = useMapInstance();
 
   const [selectedGlyph, setSelectedGlyph] = useState<number | null>(null);
@@ -49,7 +52,7 @@ export const LayerImageObjectFactoryModal: React.FC = () => {
           layerId: drawLayer,
           x: layerImageObjectFactoryState.x,
           y: layerImageObjectFactoryState.y,
-          z: highestZIndex + 1,
+          z: maxZIndex + 1,
           width: layerImageObjectFactoryState.width,
           height: layerImageObjectFactoryState.height,
           glyph: glyphId,
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
index e1ccf612..bfb80aff 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.tsx
@@ -13,7 +13,10 @@ import { LayerTextFactoryForm } from '@/components/FunctionalArea/Modal/LayerTex
 import { Color } from '@/types/models';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { layerTextFactoryStateSelector } from '@/redux/modal/modal.selector';
-import { highestZIndexSelector, layersDrawLayerSelector } from '@/redux/layers/layers.selectors';
+import {
+  layersDrawLayerSelector,
+  maxObjectZIndexForLayerSelector,
+} from '@/redux/layers/layers.selectors';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { showToast } from '@/utils/showToast';
@@ -31,7 +34,7 @@ export const LayerTextFactoryModal: React.FC = () => {
   const currentModelId = useAppSelector(currentModelIdSelector);
   const layerTextFactoryState = useAppSelector(layerTextFactoryStateSelector);
   const dispatch = useAppDispatch();
-  const highestZIndex = useAppSelector(highestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
   const { mapInstance } = useMapInstance();
 
   const [isSending, setIsSending] = useState<boolean>(false);
@@ -55,7 +58,7 @@ export const LayerTextFactoryModal: React.FC = () => {
           layerId: drawLayer,
           boundingBox: layerTextFactoryState,
           textData: data,
-          z: highestZIndex + 1,
+          z: maxZIndex + 1,
         }),
       ).unwrap();
       if (!textData) {
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
index 6f57c762..a9c3d3b3 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerTextItem.component.tsx
@@ -10,8 +10,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerTextItemProps {
   layerText: LayerText;
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -21,8 +21,8 @@ interface LayersDrawerTextItemProps {
 
 export const LayersDrawerTextItem = ({
   layerText,
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -68,8 +68,8 @@ export const LayersDrawerTextItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          bringToFront={bringToFront}
-          bringToBack={bringToBack}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
index 12bef081..33c259f3 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawer.component.tsx
@@ -4,7 +4,7 @@ import { DrawerHeading } from '@/shared/DrawerHeading';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { layersForCurrentModelSelector } from '@/redux/layers/layers.selectors';
 import { Button } from '@/shared/Button';
-import { JSX, useEffect, useRef } from 'react';
+import { JSX, useEffect, useMemo, useRef } from 'react';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors';
 import { LayersDrawerLayer } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component';
@@ -21,6 +21,19 @@ export const LayersDrawer = (): JSX.Element => {
     dispatch(openLayerFactoryModal());
   };
 
+  const sortedLayers = useMemo(() => {
+    return [...layersForCurrentModel].sort((layerA, layerB) => layerB.details.z - layerA.details.z);
+  }, [layersForCurrentModel]);
+
+  const negativeZLayers = useMemo(
+    () => sortedLayers.filter(layer => layer.details.z < 0),
+    [sortedLayers],
+  );
+  const positiveZLayers = useMemo(
+    () => sortedLayers.filter(layer => layer.details.z >= 0),
+    [sortedLayers],
+  );
+
   useEffect(() => {
     if (!mapEditToolsLayerImageObject || !layersDrawerRef.current) {
       return;
@@ -61,20 +74,33 @@ export const LayersDrawer = (): JSX.Element => {
         ref={layersDrawerRef}
       >
         {hasPrivilegeToWriteProject && (
-          <div className="flex justify-start pt-2">
+          <div className="flex justify-start py-2">
             <Button icon="plus" isIcon isFrontIcon onClick={addNewLayer}>
               Add layer
             </Button>
           </div>
         )}
-        <div className="flex flex-col gap-4">
-          {layersForCurrentModel.map(layer => (
-            <LayersDrawerLayer
-              key={layer.details.id}
-              layerId={layer.details.id}
-              layerName={layer.details.name}
-            />
-          ))}
+        <div className="flex flex-col gap-2">
+          {Boolean(positiveZLayers.length) && (
+            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
+              Layers above the diagram
+            </span>
+          )}
+          <div className="flex flex-col gap-5">
+            {positiveZLayers.map(layer => (
+              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
+            ))}
+          </div>
+          {Boolean(negativeZLayers.length) && (
+            <span className="border-b-2 border-dashed border-b-gray-400 text-center text-lg font-semibold">
+              Layers below the diagram
+            </span>
+          )}
+          <div className="flex flex-col gap-5">
+            {negativeZLayers.map(layer => (
+              <LayersDrawerLayer key={layer.details.id} layerDetails={layer.details} />
+            ))}
+          </div>
         </div>
       </div>
     </div>
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
index 0622f141..e160b807 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component.tsx
@@ -11,8 +11,8 @@ import { hasPrivilegeToWriteProjectSelector } from '@/redux/user/user.selectors'
 
 interface LayersDrawerImageItemProps {
   layerImage: LayerImage;
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
@@ -22,8 +22,8 @@ interface LayersDrawerImageItemProps {
 
 export const LayersDrawerImageItem = ({
   layerImage,
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -72,8 +72,8 @@ export const LayersDrawerImageItem = ({
       </div>
       {showActions && (
         <LayersDrawerObjectActions
-          bringToFront={bringToFront}
-          bringToBack={bringToBack}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
           removeObject={removeObject}
           centerObject={centerObject}
           editObject={editObject}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
index 49b8536f..8b0f9b01 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
@@ -1,14 +1,19 @@
+/* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import {
   layersActiveLayersSelector,
   layersVisibilityForCurrentModelSelector,
+  maxLayerZIndexAboveDiagramSelector,
+  maxLayerZIndexBelowDiagramSelector,
+  minLayerZIndexAboveDiagramSelector,
+  minLayerZIndexBelowDiagramSelector,
 } from '@/redux/layers/layers.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
 import { openLayerFactoryModal } from '@/redux/modal/modal.slice';
 import QuestionModal from '@/components/FunctionalArea/Modal/QuestionModal/QustionModal.component';
 import { useState, JSX, useMemo } from 'react';
-import { getLayersForModel, removeLayer } from '@/redux/layers/layers.thunks';
+import { getLayersForModel, removeLayer, updateLayer } from '@/redux/layers/layers.thunks';
 import { showToast } from '@/utils/showToast';
 import { SerializedError } from '@reduxjs/toolkit';
 import { LayersDrawerLayerActions } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component';
@@ -21,38 +26,42 @@ import {
 import { LayersDrawerObjectsList } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component';
 import { mapEditToolsSetActiveAction } from '@/redux/mapEditTools/mapEditTools.slice';
 import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants';
+import { Layer } from '@/types/models';
 
 interface LayersDrawerLayerProps {
-  layerId: number;
-  layerName: string;
+  layerDetails: Layer;
 }
 
-export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps): JSX.Element => {
+export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX.Element => {
   const layersVisibilityForCurrentModel = useAppSelector(layersVisibilityForCurrentModelSelector);
   const activeLayers = useAppSelector(layersActiveLayersSelector);
   const currentModelId = useAppSelector(currentModelIdSelector);
+  const maxLayerZIndexAboveDiagram = useAppSelector(maxLayerZIndexAboveDiagramSelector);
+  const maxLayerZIndexBelowDiagram = useAppSelector(maxLayerZIndexBelowDiagramSelector);
+  const minLayerZIndexAboveDiagram = useAppSelector(minLayerZIndexAboveDiagramSelector);
+  const minLayerZIndexBelowDiagram = useAppSelector(minLayerZIndexBelowDiagramSelector);
   const dispatch = useAppDispatch();
   const [isModalOpen, setIsModalOpen] = useState(false);
 
   const isLayerVisible = useMemo(() => {
-    return layersVisibilityForCurrentModel[layerId];
-  }, [layerId, layersVisibilityForCurrentModel]);
+    return layersVisibilityForCurrentModel[layerDetails.id];
+  }, [layerDetails.id, layersVisibilityForCurrentModel]);
 
   const isLayerActive = useMemo(() => {
-    return activeLayers.includes(layerId);
-  }, [activeLayers, layerId]);
+    return activeLayers.includes(layerDetails.id);
+  }, [activeLayers, layerDetails.id]);
 
   const editLayer = (): void => {
-    dispatch(openLayerFactoryModal(layerId));
+    dispatch(openLayerFactoryModal(layerDetails.id));
   };
 
   const addImage = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.DRAW_IMAGE));
   };
 
   const addText = (): void => {
-    dispatch(setDrawLayer({ modelId: currentModelId, layerId }));
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.ADD_TEXT));
   };
 
@@ -61,11 +70,11 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
   };
 
   const confirmRemove = async (): Promise<void> => {
-    if (!layerId) {
+    if (!layerDetails.id) {
       return;
     }
     try {
-      await dispatch(removeLayer({ modelId: currentModelId, layerId })).unwrap();
+      await dispatch(removeLayer({ modelId: currentModelId, layerId: layerDetails.id })).unwrap();
       showToast({
         type: 'success',
         message: 'The layer has been successfully removed',
@@ -87,12 +96,61 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
 
   const toggleActiveLayer = (value: boolean): void => {
     if (value) {
-      dispatch(setLayerToActive({ modelId: currentModelId, layerId }));
+      dispatch(setLayerToActive({ modelId: currentModelId, layerId: layerDetails.id }));
     } else {
-      dispatch(setLayerToInactive({ modelId: currentModelId, layerId }));
+      dispatch(setLayerToInactive({ modelId: currentModelId, layerId: layerDetails.id }));
     }
   };
 
+  const updateLayerZIndex = async (zIndex: number): Promise<void> => {
+    try {
+      dispatch(
+        updateLayer({
+          name: layerDetails.name,
+          visible: layerDetails.visible,
+          locked: layerDetails.locked,
+          modelId: currentModelId,
+          layerId: layerDetails.id,
+          zIndex,
+        }),
+      );
+    } catch (error) {
+      const typedError = error as SerializedError;
+      showToast({
+        type: 'error',
+        message: typedError.message || 'An error occurred while updating the layer',
+      });
+    }
+  };
+
+  const moveToFront = (): void => {
+    if (layerDetails.z > 0) {
+      updateLayerZIndex(maxLayerZIndexAboveDiagram);
+    } else if (layerDetails.z < 0) {
+      const zIndex = Math.min(maxLayerZIndexBelowDiagram, -1);
+      updateLayerZIndex(zIndex);
+    }
+  };
+
+  const moveToBack = (): void => {
+    if (layerDetails.z > 0) {
+      const zIndex = Math.max(minLayerZIndexAboveDiagram, 1);
+      updateLayerZIndex(zIndex);
+    } else if (layerDetails.z < 0) {
+      updateLayerZIndex(minLayerZIndexBelowDiagram);
+    }
+  };
+
+  const moveAboveDiagram = (): void => {
+    const zIndex = Math.max(minLayerZIndexAboveDiagram - 1, 1);
+    updateLayerZIndex(zIndex);
+  };
+
+  const moveBelowDiagram = (): void => {
+    const zIndex = Math.min(minLayerZIndexBelowDiagram + 1, -1);
+    updateLayerZIndex(zIndex);
+  };
+
   return (
     <div>
       <QuestionModal
@@ -101,9 +159,13 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
         onConfirm={confirmRemove}
         question="Are you sure you want to remove the layer?"
       />
-      <div className="flex items-center justify-between py-3">
-        <span className={`font-semibold ${isLayerVisible ? 'opacity-100' : 'opacity-40'}`}>
-          {layerName}
+      <div className="flex items-center justify-between pb-3">
+        <span
+          className={`font-semibold ${
+            isLayerVisible ? 'opacity-100' : 'opacity-40'
+          } min-w-0 flex-1 truncate `}
+        >
+          {layerDetails.name}
         </span>
         <LayersDrawerLayerActions
           toggleVisibility={() =>
@@ -111,7 +173,7 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
               setLayerVisibility({
                 modelId: currentModelId,
                 visible: !isLayerVisible,
-                layerId,
+                layerId: layerDetails.id,
               }),
             )
           }
@@ -120,12 +182,17 @@ export const LayersDrawerLayer = ({ layerId, layerName }: LayersDrawerLayerProps
           removeLayer={onRemoveLayer}
           addImage={addImage}
           addText={addText}
+          moveToFront={moveToFront}
+          moveToBack={moveToBack}
+          moveAboveDiagram={moveAboveDiagram}
+          moveBelowDiagram={moveBelowDiagram}
+          zIndex={layerDetails.z}
           isVisible={isLayerVisible}
           isActive={isLayerActive}
         />
       </div>
       <LayersDrawerObjectsList
-        layerId={layerId}
+        layerId={layerDetails.id}
         isLayerVisible={isLayerVisible}
         isLayerActive={isLayerActive}
       />
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
index 18627b13..81435100 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable no-magic-numbers */
 import { IconButton } from '@/shared/IconButton';
 import { JSX } from 'react';
 import { LayerDrawerLayerContextMenu } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component';
@@ -9,10 +10,15 @@ type LayersDrawerLayerActionsProps = {
   removeLayer: () => void;
   isVisible: boolean;
   isActive: boolean;
+  zIndex: number;
   toggleVisibility: () => void;
   toggleActiveLayer: (value: boolean) => void;
   addImage: () => void;
   addText: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
+  moveAboveDiagram: () => void;
+  moveBelowDiagram: () => void;
 };
 
 export const LayersDrawerLayerActions = ({
@@ -20,10 +26,15 @@ export const LayersDrawerLayerActions = ({
   removeLayer,
   isVisible,
   isActive,
+  zIndex,
   toggleVisibility,
   toggleActiveLayer,
   addImage,
   addText,
+  moveToFront,
+  moveToBack,
+  moveAboveDiagram,
+  moveBelowDiagram,
 }: LayersDrawerLayerActionsProps): JSX.Element => {
   const hasPrivilegeToWriteProject = useAppSelector(hasPrivilegeToWriteProjectSelector);
 
@@ -43,6 +54,34 @@ export const LayersDrawerLayerActions = ({
             className="h-auto w-auto bg-transparent p-0"
             onClick={() => toggleActiveLayer(!isActive)}
           />
+          <IconButton
+            title="Move to front"
+            icon="move-front"
+            className="h-auto w-auto bg-transparent p-0"
+            onClick={moveToFront}
+          />
+          <IconButton
+            title="Move to back"
+            icon="move-back"
+            className="h-auto w-auto bg-transparent p-0"
+            onClick={moveToBack}
+          />
+          {zIndex < 0 && (
+            <IconButton
+              title="Move above the diagram"
+              icon="layer-arrow-up"
+              className="h-auto w-auto bg-transparent p-0"
+              onClick={moveAboveDiagram}
+            />
+          )}
+          {zIndex > 0 && (
+            <IconButton
+              title="Move below the diagram"
+              icon="layer-arrow-down"
+              className="h-auto w-auto bg-transparent p-0"
+              onClick={moveBelowDiagram}
+            />
+          )}
           <LayerDrawerLayerContextMenu
             removeLayer={removeLayer}
             editLayer={editLayer}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
index 4cf6871e..a97189ea 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectActions.component.tsx
@@ -2,16 +2,16 @@ import { JSX } from 'react';
 import { IconButton } from '@/shared/IconButton';
 
 interface LayersDrawerObjectActionsProps {
-  bringToFront: () => void;
-  bringToBack: () => void;
+  moveToFront: () => void;
+  moveToBack: () => void;
   removeObject: () => void;
   centerObject: () => void;
   editObject: () => void;
 }
 
 export const LayersDrawerObjectActions = ({
-  bringToFront,
-  bringToBack,
+  moveToFront,
+  moveToBack,
   removeObject,
   centerObject,
   editObject,
@@ -31,16 +31,16 @@ export const LayersDrawerObjectActions = ({
         onClick={editObject}
       />
       <IconButton
-        icon="bring-front"
+        icon="move-front"
         className="h-auto w-auto bg-transparent p-0"
-        title="Bring to front"
-        onClick={bringToFront}
+        title="Move to front"
+        onClick={moveToFront}
       />
       <IconButton
-        icon="bring-back"
+        icon="move-back"
         className="h-auto w-auto bg-transparent p-0"
-        title="Bring to back"
-        onClick={bringToBack}
+        title="Move to back"
+        onClick={moveToBack}
       />
       <IconButton
         icon="trash"
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index 70a6acf5..9ec19fe4 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -1,9 +1,9 @@
 /* eslint-disable no-magic-numbers */
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
 import {
-  highestZIndexSelector,
   layerByIdSelector,
-  lowestZIndexSelector,
+  maxObjectZIndexForLayerSelector,
+  minObjectZIndexForLayerSelector,
 } from '@/redux/layers/layers.selectors';
 import { JSX, useState } from 'react';
 import { LayersDrawerImageItem } from '@/components/Map/Drawer/LayersDrawer/LayersDrawerImageItem.component';
@@ -64,8 +64,8 @@ export const LayersDrawerObjectsList = ({
   isLayerActive,
 }: LayersDrawerObjectsListProps): JSX.Element | null => {
   const currentModelId = useAppSelector(mapModelIdSelector);
-  const highestZIndex = useAppSelector(highestZIndexSelector);
-  const lowestZIndex = useAppSelector(lowestZIndexSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, layerId));
+  const minZIndex = useAppSelector(state => minObjectZIndexForLayerSelector(state, layerId));
   const layer = useAppSelector(state => layerByIdSelector(state, layerId));
   const mapEditToolsLayerImageObject = useAppSelector(mapEditToolsLayerObjectSelector);
   const [removeModalState, setRemoveModalState] = useState<undefined | 'text' | 'image'>(undefined);
@@ -174,12 +174,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const bringImageToFront = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: highestZIndex + 1, layerImage });
+  const moveImageToFront = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: maxZIndex + 1, layerImage });
   };
 
-  const bringImageToBack = async (layerImage: LayerImage): Promise<void> => {
-    await updateImageZIndex({ zIndex: lowestZIndex - 1, layerImage });
+  const moveImageToBack = async (layerImage: LayerImage): Promise<void> => {
+    await updateImageZIndex({ zIndex: minZIndex - 1, layerImage });
   };
 
   const updateTextZIndex = async ({
@@ -210,12 +210,12 @@ export const LayersDrawerObjectsList = ({
     }
   };
 
-  const bringTextToFront = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: highestZIndex + 1, layerText });
+  const moveTextToFront = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: maxZIndex + 1, layerText });
   };
 
-  const bringTextToBack = async (layerText: LayerText): Promise<void> => {
-    await updateTextZIndex({ zIndex: lowestZIndex - 1, layerText });
+  const moveTextToBack = async (layerText: LayerText): Promise<void> => {
+    await updateTextZIndex({ zIndex: minZIndex - 1, layerText });
   };
 
   const centerObject = (layerObject: LayerImage | LayerText): void => {
@@ -257,8 +257,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerTextItem
           layerText={layerText}
           key={layerText.id}
-          bringToFront={() => bringTextToFront(layerText)}
-          bringToBack={() => bringTextToBack(layerText)}
+          moveToFront={() => moveTextToFront(layerText)}
+          moveToBack={() => moveTextToBack(layerText)}
           removeObject={() => removeObject(layerText)}
           centerObject={() => centerObject(layerText)}
           editObject={() => editText()}
@@ -270,8 +270,8 @@ export const LayersDrawerObjectsList = ({
         <LayersDrawerImageItem
           layerImage={layerImage}
           key={layerImage.id}
-          bringToFront={() => bringImageToFront(layerImage)}
-          bringToBack={() => bringImageToBack(layerImage)}
+          moveToFront={() => moveImageToFront(layerImage)}
+          moveToBack={() => moveImageToBack(layerImage)}
           removeObject={() => removeObject(layerImage)}
           centerObject={() => centerObject(layerImage)}
           editObject={() => editImage()}
diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
index 5e378293..6d41944f 100644
--- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
+++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
@@ -125,6 +125,7 @@ export const useOlMapAdditionalLayers = (
   const vectorLayers = useMemo(() => {
     return layersState.map(layer => {
       const additionalLayer = new Layer({
+        zIndex: layer.details.z,
         texts: layer.texts,
         rects: layer.rects,
         ovals: layer.ovals,
diff --git a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
index 7ac3b73b..a3640020 100644
--- a/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/commentsLayer/useOlMapCommentsLayer.ts
@@ -36,6 +36,7 @@ export const useOlMapCommentsLayer = (): VectorLayer<VectorSource<Feature<Geomet
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.COMMENTS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
index 69cec807..db3dbad4 100644
--- a/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/mapCardLayer/useOlMapCardLayer.ts
@@ -38,6 +38,7 @@ export const useOlMapCardLayer = (): VectorLayer<VectorSource<Feature<Polygon>>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: -Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({
diff --git a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
index f7b6001c..4cd5a32b 100644
--- a/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/pinsLayer/useOlMapPinsLayer.ts
@@ -77,6 +77,7 @@ export const useOlMapPinsLayer = (): VectorLayer<VectorSource<Feature<Geometry>>
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
     });
     vectorLayer.set('type', LAYER_TYPE.PINS_LAYER);
diff --git a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
index 2811ec30..98cb6e1e 100644
--- a/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/processLayer/useOlMapProcessLayer.ts
@@ -274,6 +274,7 @@ export const useOlMapProcessLayer = ({
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: 0,
       source: vectorSource,
       updateWhileAnimating: true,
       updateWhileInteracting: true,
diff --git a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
index bfb2668e..df526271 100644
--- a/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
+++ b/src/components/Map/MapViewer/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
@@ -63,6 +63,7 @@ export const useOlMapReactionsLayer = (): VectorLayer<VectorSource<Feature<Geome
 
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
+      zIndex: Infinity,
       source: vectorSource,
       style: new Style({
         fill: new Fill({ color: LINE_COLOR }),
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
index 7b8bb971..10349c6d 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
@@ -133,6 +133,7 @@ describe('Layer', () => {
       pointToProjection: jest.fn(point => [point.x, point.y]),
       mapInstance,
       mapSize,
+      zIndex: 1,
       lineTypes: {},
       arrowTypes: {},
     };
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
index 7f697a72..14d5f8b5 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
@@ -34,6 +34,7 @@ import LayerText from '@/components/Map/MapViewer/utils/shapes/layer/elements/La
 import LayerImage from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage';
 
 export interface LayerProps {
+  zIndex: number;
   texts: { [key: string]: LayerTextModel };
   rects: Array<LayerRect>;
   ovals: Array<LayerOval>;
@@ -78,6 +79,7 @@ export default class Layer {
   >;
 
   constructor({
+    zIndex,
     texts,
     rects,
     ovals,
@@ -118,6 +120,7 @@ export default class Layer {
     this.vectorSource.addFeatures(arrowsFeatures);
 
     this.vectorLayer = new VectorLayer({
+      zIndex,
       source: this.vectorSource,
       visible,
       updateWhileAnimating: true,
diff --git a/src/models/layerSchema.ts b/src/models/layerSchema.ts
index 380146a7..11fcd88d 100644
--- a/src/models/layerSchema.ts
+++ b/src/models/layerSchema.ts
@@ -5,4 +5,5 @@ export const layerSchema = z.object({
   name: z.string(),
   visible: z.boolean(),
   locked: z.boolean(),
+  z: z.number(),
 });
diff --git a/src/redux/layers/layers.reducers.test.ts b/src/redux/layers/layers.reducers.test.ts
index 7bcb10ba..d93fb4f8 100644
--- a/src/redux/layers/layers.reducers.test.ts
+++ b/src/redux/layers/layers.reducers.test.ts
@@ -92,7 +92,7 @@ describe('layers reducer', () => {
 
     const { type } = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
-    expect(type).toBe('vectorMap/getLayers/fulfilled');
+    expect(type).toBe('layers/getLayers/fulfilled');
     expect(loading).toEqual('succeeded');
     expect(error).toEqual({ message: '', name: '' });
     expect(data).toEqual({
@@ -120,7 +120,7 @@ describe('layers reducer', () => {
     const action = await store.dispatch(getLayersForModel(1));
     const { data, loading, error } = store.getState().layers[1];
 
-    expect(action.type).toBe('vectorMap/getLayers/rejected');
+    expect(action.type).toBe('layers/getLayers/rejected');
     expect(() => unwrapResult(action)).toThrow(
       "Failed to fetch layers: The page you're looking for doesn't exist. Please verify the URL and try again.",
     );
diff --git a/src/redux/layers/layers.selectors.ts b/src/redux/layers/layers.selectors.ts
index 8f016c8a..8123fa00 100644
--- a/src/redux/layers/layers.selectors.ts
+++ b/src/redux/layers/layers.selectors.ts
@@ -2,6 +2,7 @@
 import { createSelector } from '@reduxjs/toolkit';
 import { rootSelector } from '@/redux/root/root.selectors';
 import { currentModelIdSelector } from '@/redux/models/models.selectors';
+import { LayerState } from '@/redux/layers/layers.types';
 
 export const layersSelector = createSelector(rootSelector, state => state.layers);
 
@@ -18,7 +19,7 @@ export const layersActiveLayersSelector = createSelector(
 
 export const layersDrawLayerSelector = createSelector(
   layersStateForCurrentModelSelector,
-  state => state?.data?.drawLayer,
+  state => state?.data?.drawLayer || null,
 );
 
 export const layerByIdSelector = createSelector(
@@ -41,40 +42,112 @@ export const layersForCurrentModelSelector = createSelector(
   state => state?.data?.layers || [],
 );
 
-export const highestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
-  if (!layers || layers.length === 0) return 0;
-
-  const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-    items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
-
-  return layers.reduce((maxZ, layer) => {
-    const textsMaxZ = getMaxZFromItems(Object.values(layer.texts));
-    const rectsMaxZ = getMaxZFromItems(layer.rects);
-    const ovalsMaxZ = getMaxZFromItems(layer.ovals);
-    const linesMaxZ = getMaxZFromItems(layer.lines);
-    const imagesMaxZ = getMaxZFromItems(Object.values(layer.images));
-
-    const layerMaxZ = Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
-
-    return Math.max(maxZ, layerMaxZ);
-  }, 0);
-});
+export const maxLayerZIndexAboveDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return 1000;
+    }
+    let maxZIndex = -Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z > 0 && layer.details.z > maxZIndex) {
+        maxZIndex = layer.details.z;
+      }
+    });
+    return maxZIndex;
+  },
+);
 
-export const lowestZIndexSelector = createSelector(layersForCurrentModelSelector, layers => {
-  if (!layers || layers.length === 0) return 0;
+export const maxLayerZIndexBelowDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return -1000;
+    }
+    let maxZIndex = -Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z < 0 && layer.details.z > maxZIndex) {
+        maxZIndex = layer.details.z;
+      }
+    });
+    return maxZIndex;
+  },
+);
 
-  const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
-    items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
+export const minLayerZIndexAboveDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return 1000;
+    }
+    let minZIndex = Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z > 0 && layer.details.z < minZIndex) {
+        minZIndex = layer.details.z;
+      }
+    });
+    return minZIndex;
+  },
+);
 
-  return layers.reduce((minZ, layer) => {
-    const textsMinZ = getMinZFromItems(Object.values(layer.texts));
-    const rectsMinZ = getMinZFromItems(layer.rects);
-    const ovalsMinZ = getMinZFromItems(layer.ovals);
-    const linesMinZ = getMinZFromItems(layer.lines);
-    const imagesMinZ = getMinZFromItems(Object.values(layer.images));
+export const minLayerZIndexBelowDiagramSelector = createSelector(
+  layersForCurrentModelSelector,
+  layers => {
+    if (!layers || layers.length === 0) {
+      return -1000;
+    }
+    let minZIndex = Infinity;
+    layers.forEach((layer: LayerState) => {
+      if (layer.details.z < 0 && layer.details.z < minZIndex) {
+        minZIndex = layer.details.z;
+      }
+    });
+    return minZIndex;
+  },
+);
 
-    const layerMinZ = Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
+export const maxObjectZIndexForLayerSelector = createSelector(
+  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
+  (layers, layerId) => {
+    if (!layers || layers.length === 0 || !layerId) {
+      return 0;
+    }
+    const foundLayer = layers.find(layer => layer.details.id === layerId);
+    if (!foundLayer) {
+      return 0;
+    }
+    const getMaxZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+      items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
+
+    const textsMaxZ = getMaxZFromItems(Object.values(foundLayer.texts));
+    const rectsMaxZ = getMaxZFromItems(foundLayer.rects);
+    const ovalsMaxZ = getMaxZFromItems(foundLayer.ovals);
+    const linesMaxZ = getMaxZFromItems(foundLayer.lines);
+    const imagesMaxZ = getMaxZFromItems(Object.values(foundLayer.images));
+
+    return Math.max(textsMaxZ, rectsMaxZ, ovalsMaxZ, linesMaxZ, imagesMaxZ);
+  },
+);
 
-    return Math.min(minZ, layerMinZ);
-  }, 0);
-});
+export const minObjectZIndexForLayerSelector = createSelector(
+  [layersForCurrentModelSelector, (_state, layerId: number | null): number | null => layerId],
+  (layers, layerId) => {
+    if (!layers || layers.length === 0 || !layerId) {
+      return 0;
+    }
+    const foundLayer = layers.find(layer => layer.details.id === layerId);
+    if (!foundLayer) {
+      return 0;
+    }
+    const getMinZFromItems = <T extends { z?: number }>(items: T[] = []): number =>
+      items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
+
+    const textsMinZ = getMinZFromItems(Object.values(foundLayer.texts));
+    const rectsMinZ = getMinZFromItems(foundLayer.rects);
+    const ovalsMinZ = getMinZFromItems(foundLayer.ovals);
+    const linesMinZ = getMinZFromItems(foundLayer.lines);
+    const imagesMinZ = getMinZFromItems(Object.values(foundLayer.images));
+
+    return Math.min(textsMinZ, rectsMinZ, ovalsMinZ, linesMinZ, imagesMinZ);
+  },
+);
diff --git a/src/redux/layers/layers.thunks.test.ts b/src/redux/layers/layers.thunks.test.ts
index 77e10bdb..09028272 100644
--- a/src/redux/layers/layers.thunks.test.ts
+++ b/src/redux/layers/layers.thunks.test.ts
@@ -111,7 +111,13 @@ describe('layers thunks', () => {
       mockedAxiosClient.onPost(apiPath.storeLayer(1)).reply(HttpStatusCode.Created, layerFixture);
 
       const { payload } = await store.dispatch(
-        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
+        addLayerForModel({
+          name: 'New Layer',
+          visible: true,
+          locked: false,
+          modelId: 1,
+          zIndex: 1,
+        }),
       );
       expect(payload).toEqual(layerFixture);
     });
@@ -122,7 +128,13 @@ describe('layers thunks', () => {
         .reply(HttpStatusCode.Created, { invalid: 'data' });
 
       const { payload } = await store.dispatch(
-        addLayerForModel({ name: 'New Layer', visible: true, locked: false, modelId: 1 }),
+        addLayerForModel({
+          name: 'New Layer',
+          visible: true,
+          locked: false,
+          modelId: 1,
+          zIndex: 1,
+        }),
       );
       expect(payload).toBeNull();
     });
@@ -139,6 +151,7 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
+          zIndex: 1,
         }),
       );
       expect(payload).toEqual(layerFixture);
@@ -156,6 +169,7 @@ describe('layers thunks', () => {
           locked: true,
           modelId: 1,
           layerId: 2,
+          zIndex: 1,
         }),
       );
       expect(payload).toBeNull();
diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts
index 66035fd8..bda72fce 100644
--- a/src/redux/layers/layers.thunks.ts
+++ b/src/redux/layers/layers.thunks.ts
@@ -32,7 +32,7 @@ export const getLayer = createAsyncThunk<
   Layer | null,
   { modelId: number; layerId: number },
   ThunkConfig
->('vectorMap/getLayer', async ({ modelId, layerId }) => {
+>('layers/getLayer', async ({ modelId, layerId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layer>(apiPath.getLayer(modelId, layerId));
 
@@ -48,7 +48,7 @@ export const getLayersForModel = createAsyncThunk<
   LayersVisibilitiesState | undefined,
   number,
   ThunkConfig
->('vectorMap/getLayers', async (modelId: number) => {
+>('layers/getLayers', async (modelId: number) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<Layers>(apiPath.getLayers(modelId));
     const isDataValid = validateDataUsingZodSchema(data, pageableSchema(layerSchema));
@@ -103,13 +103,14 @@ export const getLayersForModel = createAsyncThunk<
 });
 
 export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterface, ThunkConfig>(
-  'vectorMap/addLayer',
-  async ({ name, visible, locked, modelId }) => {
+  'layers/addLayer',
+  async ({ name, visible, locked, modelId, zIndex }) => {
     try {
       const { data } = await axiosInstanceNewAPI.post<Layer>(apiPath.storeLayer(modelId), {
         name,
         visible,
         locked,
+        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -122,13 +123,14 @@ export const addLayerForModel = createAsyncThunk<Layer | null, LayerStoreInterfa
 );
 
 export const updateLayer = createAsyncThunk<Layer | null, LayerUpdateInterface, ThunkConfig>(
-  'vectorMap/updateLayer',
-  async ({ name, visible, locked, modelId, layerId }) => {
+  'layers/updateLayer',
+  async ({ name, visible, locked, modelId, layerId, zIndex }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<Layer>(apiPath.updateLayer(modelId, layerId), {
         name,
         visible,
         locked,
+        z: zIndex,
       });
 
       const isDataValid = validateDataUsingZodSchema(data, layerSchema);
@@ -144,7 +146,7 @@ export const removeLayer = createAsyncThunk<
   null,
   { modelId: number; layerId: number },
   ThunkConfig
->('vectorMap/removeLayer', async ({ modelId, layerId }) => {
+>('layers/removeLayer', async ({ modelId, layerId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(apiPath.removeLayer(modelId, layerId));
     return null;
@@ -161,7 +163,7 @@ export const getLayerImage = createAsyncThunk<
     imageId: number;
   },
   ThunkConfig
->('vectorMap/getLayerImage', async ({ modelId, layerId, imageId }) => {
+>('layers/getLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerImage>(
       apiPath.getLayerImageObject(modelId, layerId, imageId),
@@ -187,7 +189,7 @@ export const addLayerImageObject = createAsyncThunk<
     glyph: number | null;
   },
   ThunkConfig
->('vectorMap/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
+>('layers/addLayerImageObject', async ({ modelId, layerId, x, y, z, width, height, glyph }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerImage>(
       apiPath.addLayerImageObject(modelId, layerId),
@@ -223,7 +225,7 @@ export const updateLayerImageObject = createAsyncThunk<
   },
   ThunkConfig
 >(
-  'vectorMap/updateLayerImageObject',
+  'layers/updateLayerImageObject',
   async ({ modelId, layerId, id, x, y, z, width, height, glyph }) => {
     try {
       const { data } = await axiosInstanceNewAPI.put<LayerImage>(
@@ -252,7 +254,7 @@ export const removeLayerImage = createAsyncThunk<
   null,
   { modelId: number; layerId: number; imageId: number },
   ThunkConfig
->('vectorMap/removeLayerImage', async ({ modelId, layerId, imageId }) => {
+>('layers/removeLayerImage', async ({ modelId, layerId, imageId }) => {
   try {
     await axiosInstanceNewAPI.delete<void>(
       apiPath.removeLayerImageObject(modelId, layerId, imageId),
@@ -273,7 +275,7 @@ export const addLayerText = createAsyncThunk<
     textData: LayerTextFactoryForm;
   },
   ThunkConfig
->('vectorMap/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
+>('layers/addLayerText', async ({ modelId, layerId, z, boundingBox, textData }) => {
   try {
     const { data } = await axiosInstanceNewAPI.post<LayerText>(
       apiPath.addLayerText(modelId, layerId),
@@ -299,7 +301,7 @@ export const getLayerText = createAsyncThunk<
     textId: number;
   },
   ThunkConfig
->('vectorMap/getLayerText', async ({ modelId, layerId, textId }) => {
+>('layers/getLayerText', async ({ modelId, layerId, textId }) => {
   try {
     const { data } = await axiosInstanceNewAPI.get<LayerText>(
       apiPath.getLayerText(modelId, layerId, textId),
diff --git a/src/redux/layers/layers.types.ts b/src/redux/layers/layers.types.ts
index 60e42717..05b4636e 100644
--- a/src/redux/layers/layers.types.ts
+++ b/src/redux/layers/layers.types.ts
@@ -6,6 +6,7 @@ export interface LayerStoreInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
+  zIndex: number;
 }
 
 export interface LayerUpdateInterface {
@@ -14,6 +15,7 @@ export interface LayerUpdateInterface {
   visible: boolean;
   locked: boolean;
   modelId: number;
+  zIndex: number;
 }
 
 export type LayerState = {
diff --git a/src/shared/Icon/Icon.component.tsx b/src/shared/Icon/Icon.component.tsx
index 5745b6ec..aed961c3 100644
--- a/src/shared/Icon/Icon.component.tsx
+++ b/src/shared/Icon/Icon.component.tsx
@@ -31,8 +31,10 @@ import { PadlockOpenIcon } from '@/shared/Icon/Icons/PadlockOpenIcon';
 import { PadlockLockedIcon } from '@/shared/Icon/Icons/PadlockLockedIcon';
 import { CrossedEyeIcon } from '@/shared/Icon/Icons/CrossedEyeIcon';
 import { CenterIcon } from '@/shared/Icon/Icons/CenterIcon';
-import { BringFrontIcon } from '@/shared/Icon/Icons/BringFrontIcon';
-import { BringBackIcon } from '@/shared/Icon/Icons/BringBackIcon';
+import { MoveFrontIcon } from '@/shared/Icon/Icons/MoveFrontIcon';
+import { MoveBackIcon } from '@/shared/Icon/Icons/MoveBackIcon';
+import { LayerArrowUpIcon } from '@/shared/Icon/Icons/LayerArrowUpIcon';
+import { LayerArrowDownIcon } from '@/shared/Icon/Icons/LayerArrowDownIcon';
 import { LocationIcon } from './Icons/LocationIcon';
 import { MaginfierZoomInIcon } from './Icons/MagnifierZoomIn';
 import { MaginfierZoomOutIcon } from './Icons/MagnifierZoomOut';
@@ -87,8 +89,10 @@ const icons: Record<IconTypes, IconComponentType> = {
   'padlock-open': PadlockOpenIcon,
   'padlock-locked': PadlockLockedIcon,
   center: CenterIcon,
-  'bring-front': BringFrontIcon,
-  'bring-back': BringBackIcon,
+  'move-front': MoveFrontIcon,
+  'move-back': MoveBackIcon,
+  'layer-arrow-up': LayerArrowUpIcon,
+  'layer-arrow-down': LayerArrowDownIcon,
 } as const;
 
 export const Icon = ({ name, className = '', ...rest }: IconProps): JSX.Element => {
diff --git a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
index d7ab4e38..cf5ce5f7 100644
--- a/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleDownIcon.tsx
@@ -13,26 +13,16 @@ export const ArrowDoubleDownIcon = ({ className }: ArrowDoubleDownIconProps): JS
   >
     <path
       d="M8 8L8 18M8 18L5 15M8 18L11 15"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 8L16 18M16 18L13 15M16 18L19 15"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line
-      x1="4"
-      y1="6"
-      x2="20"
-      y2="6"
-      stroke="currentColor"
-      strokeWidth="1.5"
-      strokeLinecap="round"
-    />
+    <line x1="4" y1="6" x2="20" y2="6" strokeWidth="1.5" strokeLinecap="round" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
index ed51a602..861773cd 100644
--- a/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
+++ b/src/shared/Icon/Icons/ArrowDoubleUpIcon.tsx
@@ -13,26 +13,16 @@ export const ArrowDoubleUpIcon = ({ className }: ArrowDoubleUpIconProps): JSX.El
   >
     <path
       d="M8 16L8 6M8 6L5 9M8 6L11 9"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
     <path
       d="M16 16L16 6M16 6L13 9M16 6L19 9"
-      stroke="currentColor"
       strokeWidth="1.5"
       strokeLinecap="round"
       strokeLinejoin="round"
     />
-    <line
-      x1="4"
-      y1="18"
-      x2="20"
-      y2="18"
-      stroke="currentColor"
-      strokeWidth="1.5"
-      strokeLinecap="round"
-    />
+    <line x1="4" y1="18" x2="20" y2="18" strokeWidth="1.5" strokeLinecap="round" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/LayerArrowDownIcon.tsx b/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
new file mode 100644
index 00000000..71223a31
--- /dev/null
+++ b/src/shared/Icon/Icons/LayerArrowDownIcon.tsx
@@ -0,0 +1,18 @@
+interface LayerArrowDownIconProps {
+  className?: string;
+}
+
+export const LayerArrowDownIcon = ({ className }: LayerArrowDownIconProps): JSX.Element => (
+  <svg
+    width="20"
+    height="20"
+    viewBox="2 3 20 17"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+    className={className}
+  >
+    <path d="M12 21L7 16H10V10H14V16H17L12 21Z" />
+    <rect x="4" y="3" width="16" height="2" />
+    <rect x="4" y="7" width="16" height="2" />
+  </svg>
+);
diff --git a/src/shared/Icon/Icons/LayerArrowUpIcon.tsx b/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
new file mode 100644
index 00000000..bbcf233f
--- /dev/null
+++ b/src/shared/Icon/Icons/LayerArrowUpIcon.tsx
@@ -0,0 +1,18 @@
+interface LayerArrowUpIconProps {
+  className?: string;
+}
+
+export const LayerArrowUpIcon = ({ className }: LayerArrowUpIconProps): JSX.Element => (
+  <svg
+    width="20"
+    height="20"
+    viewBox="2 3 20 19"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+    className={className}
+  >
+    <path d="M12 3L7 8H10V14H14V8H17L12 3Z" />
+    <rect x="4" y="16" width="16" height="2" />
+    <rect x="4" y="20" width="16" height="2" />
+  </svg>
+);
diff --git a/src/shared/Icon/Icons/BringBackIcon.tsx b/src/shared/Icon/Icons/MoveBackIcon.tsx
similarity index 78%
rename from src/shared/Icon/Icons/BringBackIcon.tsx
rename to src/shared/Icon/Icons/MoveBackIcon.tsx
index d086ac9b..734bd201 100644
--- a/src/shared/Icon/Icons/BringBackIcon.tsx
+++ b/src/shared/Icon/Icons/MoveBackIcon.tsx
@@ -1,8 +1,8 @@
-interface BringBackIconProps {
+interface MoveBackIconProps {
   className?: string;
 }
 
-export const BringBackIcon = ({ className }: BringBackIconProps): JSX.Element => (
+export const MoveBackIcon = ({ className }: MoveBackIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -23,6 +23,6 @@ export const BringBackIcon = ({ className }: BringBackIconProps): JSX.Element =>
       stroke="white"
       fill="none"
     />
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
   </svg>
 );
diff --git a/src/shared/Icon/Icons/BringFrontIcon.tsx b/src/shared/Icon/Icons/MoveFrontIcon.tsx
similarity index 77%
rename from src/shared/Icon/Icons/BringFrontIcon.tsx
rename to src/shared/Icon/Icons/MoveFrontIcon.tsx
index e5aa5017..037f5cb3 100644
--- a/src/shared/Icon/Icons/BringFrontIcon.tsx
+++ b/src/shared/Icon/Icons/MoveFrontIcon.tsx
@@ -1,8 +1,8 @@
-interface BringFrontIconProps {
+interface MoveFrontIconProps {
   className?: string;
 }
 
-export const BringFrontIcon = ({ className }: BringFrontIconProps): JSX.Element => (
+export const MoveFrontIcon = ({ className }: MoveFrontIconProps): JSX.Element => (
   <svg
     width="20"
     height="20"
@@ -11,7 +11,7 @@ export const BringFrontIcon = ({ className }: BringFrontIconProps): JSX.Element
     fill="none"
     className={className}
   >
-    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" fill="black" />
+    <rect x="4" y="4" width="64" height="64" rx="10" ry="10" strokeWidth="8" />
     <rect
       x="30"
       y="30"
diff --git a/src/shared/IconButton/IconButton.component.tsx b/src/shared/IconButton/IconButton.component.tsx
index 1330e460..e71c6211 100644
--- a/src/shared/IconButton/IconButton.component.tsx
+++ b/src/shared/IconButton/IconButton.component.tsx
@@ -29,8 +29,8 @@ export const IconButton = ({
 
   const isStrokeIcon = [
     'plugin',
-    'bring-back',
-    'bring-front',
+    'move-back',
+    'move-front',
     'center',
     'eye',
     'crossed-eye',
@@ -38,6 +38,8 @@ export const IconButton = ({
     'padlock-locked',
     'layers',
     'edit',
+    'arrow-double-up',
+    'arrow-double-down',
   ].includes(icon);
 
   return (
@@ -57,6 +59,8 @@ export const IconButton = ({
           isStrokeIcon
             ? 'stroke-font-400 group-hover:stroke-primary-500 group-active:stroke-primary-500'
             : 'fill-font-400 group-hover:fill-primary-500 group-active:fill-primary-500',
+          ['move-back', 'move-front'].includes(icon) &&
+            'fill-font-400 stroke-font-400 group-hover:fill-primary-500 group-hover:stroke-primary-500 group-active:fill-primary-500 group-active:stroke-primary-500',
           isActive && getActiveFillOrStrokeColor(icon),
           classNameIcon,
         )}
diff --git a/src/types/iconTypes.ts b/src/types/iconTypes.ts
index 0d74dd78..0083a622 100644
--- a/src/types/iconTypes.ts
+++ b/src/types/iconTypes.ts
@@ -38,7 +38,9 @@ export type IconTypes =
   | 'padlock-open'
   | 'padlock-locked'
   | 'center'
-  | 'bring-front'
-  | 'bring-back';
+  | 'move-front'
+  | 'move-back'
+  | 'layer-arrow-up'
+  | 'layer-arrow-down';
 
 export type IconComponentType = ({ className }: { className: string }) => JSX.Element;
-- 
GitLab


From 4772a0a546256b02df1898bc102dad8fb90af90d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 13:15:02 +0100
Subject: [PATCH 7/8] feat(layer-rects): implement adding rectangles

---
 .../EditOverlayModal.component.test.tsx       |   7 +
 .../hooks/useEditOverlay.test.ts              |   5 +
 ...eObjectEditFactoryModal.component.test.tsx |   1 +
 ...ImageObjectFactoryModal.component.test.tsx |   1 +
 .../LayerRectFactory.types.ts                 |   6 +
 .../LayerRectFactoryModal.component.test.tsx  | 102 ++++++++++
 .../LayerRectFactoryModal.component.tsx       | 108 ++++++++++
 .../LayerRectFactoryModal.styles.css          |  12 ++
 .../LayerRectForm.component.tsx               |  31 +++
 .../LayerTextFactoryModal.component.test.tsx  |   1 +
 .../FunctionalArea/Modal/Modal.component.tsx  |   6 +
 .../ModalLayout/ModalLayout.component.tsx     |  12 +-
 .../LayerDrawerLayerContextMenu.component.tsx |   6 +
 .../LayerDrawerRectItem.component.tsx         |  23 +++
 .../LayersDrawerLayer.component.tsx           |   6 +
 .../LayersDrawerLayerActions.component.tsx    |   3 +
 ...sDrawerLayerContextMenuItems.component.tsx |  15 +-
 .../LayersDrawerObjectsList.component.tsx     |   4 +
 .../useOlMapAdditionalLayers.ts               |  31 +++
 .../utils/shapes/layer/Layer.test.ts          |   9 +-
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |  68 ++++---
 .../utils/shapes/layer/elements/LayerRect.ts  | 189 ++++++++++++++++++
 .../shapes/layer/utils/drawElementOnLayer.ts  |   4 +-
 src/models/fixtures/layerRectFixture.ts       |   9 +
 src/models/fixtures/layerRectsFixture.ts      |   2 +-
 src/models/layerRectSchema.ts                 |   3 +-
 src/redux/apiPath.ts                          |   2 +
 src/redux/layers/layers.reducers.test.ts      |   6 +-
 src/redux/layers/layers.reducers.ts           |  18 +-
 src/redux/layers/layers.selectors.ts          |   4 +-
 src/redux/layers/layers.slice.ts              |   3 +
 src/redux/layers/layers.thunks.test.ts        |   2 +-
 src/redux/layers/layers.thunks.ts             |  35 +++-
 src/redux/layers/layers.types.ts              |   2 +-
 .../mapEditTools/mapEditTools.constants.ts    |   1 +
 src/redux/modal/modal.constants.ts            |   1 +
 src/redux/modal/modal.mock.ts                 |   1 +
 src/redux/modal/modal.reducers.ts             |  10 +
 src/redux/modal/modal.selector.ts             |   5 +
 src/redux/modal/modal.slice.ts                |   3 +
 src/redux/modal/modal.types.ts                |   3 +
 src/shared/Icon/Icon.component.tsx            |   2 +
 src/shared/Icon/Icons/RectangleIcon.tsx       |  16 ++
 src/types/iconTypes.ts                        |   3 +-
 src/types/modal.ts                            |   3 +-
 src/utils/convert/hexToRgbIntAlpha.test.ts    |   4 +-
 src/utils/convert/hexToRgbIntAlpha.ts         |   7 +-
 47 files changed, 728 insertions(+), 67 deletions(-)
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types.ts
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.styles.css
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectForm.component.tsx
 create mode 100644 src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx
 create mode 100644 src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts
 create mode 100644 src/models/fixtures/layerRectFixture.ts
 create mode 100644 src/shared/Icon/Icons/RectangleIcon.tsx

diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
index cd91fa65..12f95047 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/EditOverlayModal.component.test.tsx
@@ -52,6 +52,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -73,6 +74,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -107,6 +109,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -146,6 +149,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -186,6 +190,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -234,6 +239,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
       overlays: OVERLAYS_INITIAL_STATE_MOCK,
     });
@@ -266,6 +272,7 @@ describe('EditOverlayModal - component', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
diff --git a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
index a086bb3e..3ab251bf 100644
--- a/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
+++ b/src/components/FunctionalArea/Modal/EditOverlayModal/hooks/useEditOverlay.test.ts
@@ -28,6 +28,7 @@ describe('useEditOverlay', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -68,6 +69,7 @@ describe('useEditOverlay', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -111,6 +113,7 @@ describe('useEditOverlay', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -150,6 +153,7 @@ describe('useEditOverlay', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
@@ -190,6 +194,7 @@ describe('useEditOverlay', () => {
         layerFactoryState: { id: undefined },
         layerImageObjectFactoryState: undefined,
         layerTextFactoryState: undefined,
+        layerRectFactoryState: undefined,
       },
     });
 
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
index 29a26c8b..a6adc865 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
@@ -63,6 +63,7 @@ const renderComponent = (
         height: 1,
       },
       layerTextFactoryState: undefined,
+      layerRectFactoryState: undefined,
     },
     models: {
       ...MODELS_DATA_MOCK_WITH_MAIN_MAP,
diff --git a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx
index 0d0de1fe..18e2172b 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx
@@ -57,6 +57,7 @@ const renderComponent = (): { store: StoreType } => {
         height: 1,
       },
       layerTextFactoryState: undefined,
+      layerRectFactoryState: undefined,
     },
     models: {
       ...MODELS_DATA_MOCK_WITH_MAIN_MAP,
diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types.ts b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types.ts
new file mode 100644
index 00000000..bd0218dc
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types.ts
@@ -0,0 +1,6 @@
+import { Color } from '@/types/models';
+
+export type LayerRectFactoryForm = {
+  fillColor: Color;
+  borderColor: Color;
+};
diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx
new file mode 100644
index 00000000..d6dae5a2
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx
@@ -0,0 +1,102 @@
+/* eslint-disable no-magic-numbers */
+import { render, screen, fireEvent } from '@testing-library/react';
+import { act } from 'react-dom/test-utils';
+import { StoreType } from '@/redux/store';
+import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
+import { INITIAL_STORE_STATE_MOCK } from '@/redux/root/root.fixtures';
+import { GLYPHS_STATE_INITIAL_MOCK } from '@/redux/glyphs/glyphs.mock';
+import { apiPath } from '@/redux/apiPath';
+import { HttpStatusCode } from 'axios';
+import { mockNetworkNewAPIResponse } from '@/utils/mockNetworkResponse';
+import {
+  LAYER_STATE_DEFAULT_DATA,
+  LAYERS_STATE_INITIAL_LAYER_MOCK,
+} from '@/redux/layers/layers.mock';
+import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock';
+import { overlayFixture } from '@/models/fixtures/overlaysFixture';
+import { showToast } from '@/utils/showToast';
+import { layerRectFixture } from '@/models/fixtures/layerRectFixture';
+import { LayerRectFactoryModal } from './LayerRectFactoryModal.component';
+
+const mockedAxiosNewClient = mockNetworkNewAPIResponse();
+
+const glyph = { id: 1, file: 23, filename: 'Glyph1.png' };
+
+jest.mock('../../../../utils/showToast');
+
+const renderComponent = (): { store: StoreType } => {
+  const { Wrapper, store } = getReduxWrapperWithStore({
+    ...INITIAL_STORE_STATE_MOCK,
+    glyphs: {
+      ...GLYPHS_STATE_INITIAL_MOCK,
+      data: [glyph],
+    },
+    layers: {
+      0: {
+        ...LAYERS_STATE_INITIAL_LAYER_MOCK,
+        data: {
+          ...LAYER_STATE_DEFAULT_DATA,
+          activeLayers: [1],
+          drawLayer: 1,
+        },
+      },
+    },
+    modal: {
+      isOpen: true,
+      modalTitle: overlayFixture.name,
+      modalName: 'layer-rect-factory',
+      editOverlayState: overlayFixture,
+      molArtState: {},
+      overviewImagesState: {},
+      errorReportState: {},
+      layerFactoryState: { id: undefined },
+      layerImageObjectFactoryState: undefined,
+      layerRectFactoryState: {
+        x: 1,
+        y: 1,
+        width: 1,
+        height: 1,
+      },
+      layerTextFactoryState: undefined,
+    },
+    models: {
+      ...MODELS_DATA_MOCK_WITH_MAIN_MAP,
+    },
+  });
+
+  return {
+    store,
+    ...render(
+      <Wrapper>
+        <LayerRectFactoryModal />
+      </Wrapper>,
+    ),
+  };
+};
+
+describe('LayerRectFactoryModal - component', () => {
+  it('should render LayerRectFactoryModal component with initial state', () => {
+    renderComponent();
+
+    expect(screen.getByText('Fill color:')).toBeInTheDocument();
+    expect(screen.getByText('Border color:')).toBeInTheDocument();
+  });
+
+  it('should handle form submission correctly', async () => {
+    mockedAxiosNewClient
+      .onPost(apiPath.addLayerRect(0, 1))
+      .reply(HttpStatusCode.Ok, layerRectFixture);
+    renderComponent();
+
+    const submitButton = screen.getByText(/Submit/i);
+
+    await act(async () => {
+      fireEvent.click(submitButton);
+    });
+
+    expect(showToast).toHaveBeenCalledWith({
+      message: 'A new rect 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
new file mode 100644
index 00000000..c374bfc5
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.tsx
@@ -0,0 +1,108 @@
+/* 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 { BLACK_COLOR } from '@/components/Map/MapViewer/MapViewer.constants';
+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 {
+  layersDrawLayerSelector,
+  maxObjectZIndexForLayerSelector,
+} from '@/redux/layers/layers.selectors';
+import { currentModelIdSelector } from '@/redux/models/models.selectors';
+import { Color } from '@/types/models';
+import { layerRectFactoryStateSelector } from '@/redux/modal/modal.selector';
+import { addLayerRect } from '@/redux/layers/layers.thunks';
+import { showToast } from '@/utils/showToast';
+import { layerAddRect } from '@/redux/layers/layers.slice';
+import drawElementOnLayer from '@/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer';
+import { closeModal } from '@/redux/modal/modal.slice';
+import { mapEditToolsSetActiveAction } from '@/redux/mapEditTools/mapEditTools.slice';
+import { SerializedError } from '@reduxjs/toolkit';
+import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
+import { useMapInstance } from '@/utils/context/mapInstanceContext';
+
+export const LayerRectFactoryModal: React.FC = () => {
+  const drawLayer = useAppSelector(layersDrawLayerSelector);
+  const currentModelId = useAppSelector(currentModelIdSelector);
+  const layerRectFactoryState = useAppSelector(layerRectFactoryStateSelector);
+  const maxZIndex = useAppSelector(state => maxObjectZIndexForLayerSelector(state, drawLayer));
+  const dispatch = useAppDispatch();
+  const { mapInstance } = useMapInstance();
+
+  const [isSending, setIsSending] = useState<boolean>(false);
+  const [data, setData] = useState<LayerRectFactoryForm>({
+    fillColor: BLACK_COLOR,
+    borderColor: BLACK_COLOR,
+  });
+
+  const handleSubmit = async (): Promise<void> => {
+    if (!layerRectFactoryState || !drawLayer) {
+      return;
+    }
+    try {
+      const layerRect = await dispatch(
+        addLayerRect({
+          modelId: currentModelId,
+          layerId: drawLayer,
+          boundingBox: layerRectFactoryState,
+          rectData: data,
+          z: maxZIndex + 1,
+        }),
+      ).unwrap();
+      if (!layerRect) {
+        showToast({
+          type: 'error',
+          message: 'Error while adding the rect',
+        });
+        return;
+      }
+      dispatch(layerAddRect({ modelId: currentModelId, layerId: drawLayer, layerRect }));
+      drawElementOnLayer({
+        mapInstance,
+        activeLayer: drawLayer,
+        object: layerRect,
+        drawFunctionKey: 'drawRect',
+      });
+      showToast({
+        type: 'success',
+        message: 'A new rect has been successfully added',
+      });
+      dispatch(closeModal());
+      dispatch(mapEditToolsSetActiveAction(null));
+    } catch (error) {
+      const typedError = error as SerializedError;
+      showToast({
+        type: 'error',
+        message: typedError.message || 'An error occurred while adding a new rect',
+      });
+    } 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.styles.css b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.styles.css
new file mode 100644
index 00000000..4e585a0e
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.styles.css
@@ -0,0 +1,12 @@
+.c-layer-rect-factory-modal-loader {
+  width: 100%;
+  height: 100%;
+  margin-left: -24px;
+  margin-top: -24px;
+  background: #f9f9f980;
+  z-index: 1;
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
diff --git a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectForm.component.tsx b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectForm.component.tsx
new file mode 100644
index 00000000..2bc34fb0
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectForm.component.tsx
@@ -0,0 +1,31 @@
+/* eslint-disable no-magic-numbers */
+import { ColorTilePicker } from '@/shared/ColorPicker/ColorTilePicker.component';
+import hexToRgbIntAlpha from '@/utils/convert/hexToRgbIntAlpha';
+import { Color } from '@/types/models';
+import { LayerRectFactoryForm } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types';
+
+type LayerRectFormProps = {
+  data: LayerRectFactoryForm;
+  onChange: (value: number | string | Color, key: string) => void;
+};
+
+export const LayerRectForm = ({ data, onChange }: LayerRectFormProps): React.JSX.Element => {
+  return (
+    <div className="grid grid-cols-2 gap-4">
+      <div>
+        <span>Fill color:</span>
+        <ColorTilePicker
+          initialColor={data.fillColor}
+          colorChange={color => onChange(hexToRgbIntAlpha(color), 'fillColor')}
+        />
+      </div>
+      <div>
+        <span>Border color:</span>
+        <ColorTilePicker
+          initialColor={data.borderColor}
+          colorChange={color => onChange(hexToRgbIntAlpha(color), 'borderColor')}
+        />
+      </div>
+    </div>
+  );
+};
diff --git a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx
index c739fb38..71f607e3 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx
@@ -56,6 +56,7 @@ const renderComponent = (): { store: StoreType } => {
       errorReportState: {},
       layerFactoryState: { id: undefined },
       layerImageObjectFactoryState: undefined,
+      layerRectFactoryState: undefined,
       layerTextFactoryState: {
         x: 1,
         y: 1,
diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx
index bbd8c7d5..c64517dc 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -11,6 +11,7 @@ import {
 } from '@/components/FunctionalArea/Modal/LayerImageObjectModal';
 import { LayerTextFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component';
 import { LayerTextEditFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextEditFactoryModal.component';
+import { LayerRectFactoryModal } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component';
 import { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
 import { ErrorReportModal } from './ErrorReportModal';
@@ -111,6 +112,11 @@ export const Modal = (): React.ReactNode => {
           <LayerTextEditFactoryModal />
         </ModalLayout>
       )}
+      {isOpen && modalName === 'layer-rect-factory' && (
+        <ModalLayout>
+          <LayerRectFactoryModal />
+        </ModalLayout>
+      )}
     </>
   );
 };
diff --git a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
index e9fd515a..357f7cf1 100644
--- a/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
+++ b/src/components/FunctionalArea/Modal/ModalLayout/ModalLayout.component.tsx
@@ -23,10 +23,10 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => {
       className={twMerge('absolute left-0 top-0 z-20 h-full w-full bg-cetacean-blue/[.48]')}
       role={MODAL_ROLE}
     >
-      <div className="flex h-full w-full items-center justify-center">
+      <div className="relative flex h-full w-full items-center justify-center">
         <div
           className={twMerge(
-            'flex h-5/6 w-10/12	flex-col	overflow-hidden rounded-lg',
+            'flex h-5/6 w-10/12 flex-col	overflow-hidden rounded-lg',
             modalName === 'login' && 'h-auto w-[400px]',
             modalName === 'access-denied' && 'h-auto w-[400px]',
             modalName === 'select-project' && 'h-auto w-[400px]',
@@ -34,6 +34,7 @@ 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-text-factory', 'layer-text-edit-factory'].includes(modalName) &&
               'h-auto w-[900px]',
             ['layer-image-object-factory', 'layer-image-object-edit-factory'].includes(modalName) &&
@@ -41,7 +42,12 @@ export const ModalLayout = ({ children }: ModalLayoutProps): JSX.Element => {
             ['edit-overlay', 'logged-in-menu'].includes(modalName) && 'h-auto w-[432px]',
           )}
         >
-          <div className="flex items-center justify-between bg-white p-[24px] text-xl">
+          <div
+            className={twMerge(
+              'flex items-center justify-between bg-white p-[24px] text-xl',
+              modalName === 'layer-rect-factory' && 'rounded-t-lg',
+            )}
+          >
             {(modalName === 'error-report' || modalName === 'access-denied') && (
               <div className="font-bold text-red-500">
                 <Icon name="info" className={twMerge('mr-4 fill-red-500')} />
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component.tsx
index 4906b2bd..10d57012 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerLayerContextMenu.component.tsx
@@ -7,6 +7,7 @@ type LayerDrawerLayerContextMenuProps = {
   editLayer: () => void;
   addImage: () => void;
   addText: () => void;
+  addRect: () => void;
 };
 
 export const LayerDrawerLayerContextMenu = ({
@@ -14,6 +15,7 @@ export const LayerDrawerLayerContextMenu = ({
   editLayer,
   addImage,
   addText,
+  addRect,
 }: LayerDrawerLayerContextMenuProps): JSX.Element => {
   const [menuVisible, setMenuVisible] = useState(false);
   const menuRef = useRef<HTMLUListElement>(null);
@@ -66,6 +68,10 @@ export const LayerDrawerLayerContextMenu = ({
             setMenuVisible(false);
             addText();
           }}
+          addRect={() => {
+            setMenuVisible(false);
+            addRect();
+          }}
         />
       )}
     </div>
diff --git a/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx
new file mode 100644
index 00000000..a8f0e9bc
--- /dev/null
+++ b/src/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component.tsx
@@ -0,0 +1,23 @@
+import React, { JSX } from 'react';
+import { LayerRect } from '@/types/models';
+import { Icon } from '@/shared/Icon';
+
+interface LayersDrawerRectItemProps {
+  layerRect: LayerRect;
+}
+
+export const LayersDrawerRectItem = ({
+  layerRect,
+}: LayersDrawerRectItemProps): JSX.Element | null => {
+  return (
+    <div
+      className="flex min-h-[24px] items-center justify-between gap-2"
+      id={`layer-rect-item-${layerRect.id}`}
+    >
+      <div className="flex gap-2">
+        <Icon name="rectangle" className="shrink-0" />
+        <span className="truncate">rectangle - {layerRect.id}</span>
+      </div>
+    </div>
+  );
+};
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
index 8b0f9b01..03aa4417 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayer.component.tsx
@@ -65,6 +65,11 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
     dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.ADD_TEXT));
   };
 
+  const addRect = (): void => {
+    dispatch(setDrawLayer({ modelId: currentModelId, layerId: layerDetails.id }));
+    dispatch(mapEditToolsSetActiveAction(MAP_EDIT_ACTIONS.ADD_RECT));
+  };
+
   const rejectRemove = (): void => {
     setIsModalOpen(false);
   };
@@ -182,6 +187,7 @@ export const LayersDrawerLayer = ({ layerDetails }: LayersDrawerLayerProps): JSX
           removeLayer={onRemoveLayer}
           addImage={addImage}
           addText={addText}
+          addRect={addRect}
           moveToFront={moveToFront}
           moveToBack={moveToBack}
           moveAboveDiagram={moveAboveDiagram}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
index 81435100..dd015fd6 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerActions.component.tsx
@@ -15,6 +15,7 @@ type LayersDrawerLayerActionsProps = {
   toggleActiveLayer: (value: boolean) => void;
   addImage: () => void;
   addText: () => void;
+  addRect: () => void;
   moveToFront: () => void;
   moveToBack: () => void;
   moveAboveDiagram: () => void;
@@ -31,6 +32,7 @@ export const LayersDrawerLayerActions = ({
   toggleActiveLayer,
   addImage,
   addText,
+  addRect,
   moveToFront,
   moveToBack,
   moveAboveDiagram,
@@ -87,6 +89,7 @@ export const LayersDrawerLayerActions = ({
             editLayer={editLayer}
             addImage={addImage}
             addText={addText}
+            addRect={addRect}
           />
         </>
       )}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerContextMenuItems.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerContextMenuItems.component.tsx
index 1017e9c8..c01f2eb7 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerContextMenuItems.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerLayerContextMenuItems.component.tsx
@@ -6,6 +6,7 @@ type LayerDrawerLayerContextMenuProps = {
   editLayer: () => void;
   addImage: () => void;
   addText: () => void;
+  addRect: () => void;
 };
 
 export const LayerDrawerLayerContextMenuItems = forwardRef<
@@ -13,7 +14,7 @@ export const LayerDrawerLayerContextMenuItems = forwardRef<
   LayerDrawerLayerContextMenuProps
 >(
   (
-    { removeLayer, editLayer, addImage, addText }: LayerDrawerLayerContextMenuProps,
+    { removeLayer, editLayer, addImage, addText, addRect }: LayerDrawerLayerContextMenuProps,
     ref,
   ): JSX.Element => {
     const handleKeyPress = (): void => {};
@@ -21,7 +22,7 @@ export const LayerDrawerLayerContextMenuItems = forwardRef<
     return (
       <ul
         ref={ref}
-        className="absolute right-[24px] top-[-14px] z-[1] mt-2 w-[11rem] rounded border bg-white p-2 shadow-md"
+        className="absolute right-[24px] top-[-14px] z-[1] mt-2 w-[12rem] rounded border bg-white p-2 shadow-md"
       >
         <li
           className="flex min-h-[24px] cursor-pointer gap-3 px-4 py-1 hover:bg-gray-200"
@@ -43,6 +44,16 @@ export const LayerDrawerLayerContextMenuItems = forwardRef<
           <Icon name="text" />
           <span>Add text</span>
         </li>
+        <li
+          className="flex min-h-[24px] cursor-pointer gap-3 px-4 py-1 hover:bg-gray-200"
+          tabIndex={0}
+          onClick={addRect}
+          onKeyDown={handleKeyPress}
+          role="menuitem"
+        >
+          <Icon name="rectangle" />
+          <span>Add rectangle</span>
+        </li>
         <li
           className="flex min-h-[24px] cursor-pointer gap-3 px-4 py-1 hover:bg-gray-200"
           tabIndex={0}
diff --git a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
index 9ec19fe4..330c7bbe 100644
--- a/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
+++ b/src/components/Map/Drawer/LayersDrawer/LayersDrawerObjectsList.component.tsx
@@ -38,6 +38,7 @@ import {
   openLayerImageObjectEditFactoryModal,
   openLayerTextEditFactoryModal,
 } from '@/redux/modal/modal.slice';
+import { LayersDrawerRectItem } from '@/components/Map/Drawer/LayersDrawer/LayerDrawerRectItem.component';
 
 interface LayersDrawerObjectsListProps {
   layerId: number;
@@ -279,6 +280,9 @@ export const LayersDrawerObjectsList = ({
           isLayerActive={isLayerActive}
         />
       ))}
+      {Object.values(layer.rects).map(layerRect => (
+        <LayersDrawerRectItem layerRect={layerRect} key={layerRect.id} />
+      ))}
     </div>
   );
 };
diff --git a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
index 6d41944f..fe1497fe 100644
--- a/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
+++ b/src/components/Map/MapViewer/utils/config/additionalLayers/useOlMapAdditionalLayers.ts
@@ -31,6 +31,7 @@ import { MAP_EDIT_ACTIONS } from '@/redux/mapEditTools/mapEditTools.constants';
 import getDrawBoundingBoxInteraction from '@/components/Map/MapViewer/utils/shapes/layer/interaction/getDrawBoundingBoxInteraction';
 import {
   openLayerImageObjectFactoryModal,
+  openLayerRectFactoryModal,
   openLayerTextFactoryModal,
 } from '@/redux/modal/modal.slice';
 import { Extent } from 'ol/extent';
@@ -113,6 +114,18 @@ export const useOlMapAdditionalLayers = (
     );
   }, [mapSize, dispatch, restrictionExtent]);
 
+  const drawRectInteraction = useMemo(() => {
+    if (!mapSize || !dispatch) {
+      return null;
+    }
+    return getDrawBoundingBoxInteraction(
+      mapSize,
+      dispatch,
+      restrictionExtent,
+      openLayerRectFactoryModal,
+    );
+  }, [mapSize, dispatch, restrictionExtent]);
+
   useEffect(() => {
     if (!currentModelId) {
       return;
@@ -320,5 +333,23 @@ export const useOlMapAdditionalLayers = (
     hasPrivilegeToWriteProject,
   ]);
 
+  useEffect(() => {
+    if (!drawRectInteraction || !hasPrivilegeToWriteProject) {
+      return;
+    }
+    mapInstance?.removeInteraction(drawRectInteraction);
+    if (!drawLayer || activeAction !== MAP_EDIT_ACTIONS.ADD_RECT) {
+      return;
+    }
+    mapInstance?.addInteraction(drawRectInteraction);
+  }, [
+    activeAction,
+    drawLayer,
+    currentModelId,
+    drawRectInteraction,
+    mapInstance,
+    hasPrivilegeToWriteProject,
+  ]);
+
   return vectorLayers;
 };
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
index 10349c6d..17e9a679 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.test.ts
@@ -55,21 +55,20 @@ describe('Layer', () => {
           color: BLACK_COLOR,
         },
       },
-      rects: [
-        {
+      rects: {
+        1: {
           id: 1,
           x: 10,
           y: 10,
           z: 3,
           width: 100,
           height: 100,
-          size: 12312,
-          elementId: '341',
+          layer: 1,
           lineWidth: 2,
           borderColor: BLACK_COLOR,
           fillColor: WHITE_COLOR,
         },
-      ],
+      },
       ovals: [
         {
           id: 1,
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
index 14d5f8b5..93456a0d 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/Layer.ts
@@ -3,7 +3,7 @@ import {
   LayerImage as LayerImageModel,
   LayerLine,
   LayerOval,
-  LayerRect,
+  LayerRect as LayerRectModel,
   LayerText as LayerTextModel,
 } from '@/types/models';
 import { MapInstance } from '@/types/map';
@@ -32,11 +32,12 @@ import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle';
 import getEllipseCoords from '@/components/Map/MapViewer/utils/shapes/coords/getEllipseCoords';
 import LayerText from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerText';
 import LayerImage from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerImage';
+import LayerRect from '@/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect';
 
 export interface LayerProps {
   zIndex: number;
   texts: { [key: string]: LayerTextModel };
-  rects: Array<LayerRect>;
+  rects: { [key: string]: LayerRectModel };
   ovals: Array<LayerOval>;
   lines: Array<LayerLine>;
   images: { [key: string]: LayerImageModel };
@@ -54,7 +55,7 @@ export default class Layer {
 
   texts: { [key: string]: LayerTextModel };
 
-  rects: Array<LayerRect>;
+  rects: { [key: string]: LayerRectModel };
 
   ovals: Array<LayerOval>;
 
@@ -133,17 +134,13 @@ export default class Layer {
     this.vectorLayer.set('textsFeatures', textsFeatures);
     this.vectorLayer.set('drawImage', this.drawImage.bind(this));
     this.vectorLayer.set('drawText', this.drawText.bind(this));
+    this.vectorLayer.set('drawRect', this.drawRect.bind(this));
   }
 
   private getTextsFeatures = (): Array<Feature<Polygon>> => {
     return Object.values(this.texts).map(text => this.getTextFeature(text));
   };
 
-  private drawText(text: LayerTextModel): void {
-    const textFeature = this.getTextFeature(text);
-    this.vectorSource.addFeature(textFeature);
-  }
-
   private getTextFeature(text: LayerTextModel): Feature<Polygon> {
     const textObject = new LayerText({
       elementId: text.id,
@@ -167,34 +164,41 @@ export default class Layer {
     return textObject.feature;
   }
 
+  private drawText(text: LayerTextModel): void {
+    const textFeature = this.getTextFeature(text);
+    this.vectorSource.addFeature(textFeature);
+  }
+
   private getRectsFeatures = (): Array<Feature<Polygon>> => {
-    return this.rects.map(rect => {
-      const polygon = new Polygon([
-        [
-          this.pointToProjection({ x: rect.x, y: rect.y }),
-          this.pointToProjection({ x: rect.x + rect.width, y: rect.y }),
-          this.pointToProjection({ x: rect.x + rect.width, y: rect.y + rect.height }),
-          this.pointToProjection({ x: rect.x, y: rect.y + rect.height }),
-        ],
-      ]);
-      const polygonStyle = getStyle({
-        geometry: polygon,
-        borderColor: rect.borderColor,
-        fillColor: rect.fillColor,
-        lineWidth: rect.lineWidth,
-        zIndex: rect.z,
-      });
-      const rectFeature = new Feature<Polygon>({
-        geometry: polygon,
-        style: polygonStyle,
-        lineWidth: rect.lineWidth,
-        elementType: LAYER_ELEMENT_TYPES.RECT,
-      });
-      rectFeature.setStyle(this.getStyle.bind(this));
-      return rectFeature;
+    return Object.values(this.rects).map(rect => {
+      return this.getRectFeature(rect);
+    });
+  };
+
+  private getRectFeature = (rect: LayerRectModel): Feature<Polygon> => {
+    const rectObject = new LayerRect({
+      elementId: rect.id,
+      x: rect.x,
+      y: rect.y,
+      width: rect.width,
+      height: rect.height,
+      layer: rect.layer,
+      zIndex: rect.z,
+      fillColor: rect.fillColor,
+      borderColor: rect.borderColor,
+      lineWidth: rect.lineWidth,
+      pointToProjection: this.pointToProjection,
+      mapInstance: this.mapInstance,
+      mapSize: this.mapSize,
     });
+    return rectObject.feature;
   };
 
+  private drawRect(rect: LayerRectModel): void {
+    const rectFeature = this.getRectFeature(rect);
+    this.vectorSource.addFeature(rectFeature);
+  }
+
   private getOvalsFeatures = (): Array<Feature<Polygon>> => {
     return this.ovals.map(oval => {
       const coords = getEllipseCoords({
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts
new file mode 100644
index 00000000..844ec355
--- /dev/null
+++ b/src/components/Map/MapViewer/utils/shapes/layer/elements/LayerRect.ts
@@ -0,0 +1,189 @@
+/* eslint-disable no-magic-numbers */
+import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
+import Style from 'ol/style/Style';
+import { Feature } from 'ol';
+import { FeatureLike } from 'ol/Feature';
+import { MapInstance } from '@/types/map';
+import { Color, LayerRect as LayerRectModel } from '@/types/models';
+import { rgbToHex } from '@/components/Map/MapViewer/utils/shapes/style/rgbToHex';
+import Polygon from 'ol/geom/Polygon';
+import getStroke from '@/components/Map/MapViewer/utils/shapes/style/getStroke';
+import getStyle from '@/components/Map/MapViewer/utils/shapes/style/getStyle';
+import getScaledElementStyle from '@/components/Map/MapViewer/utils/shapes/style/getScaledElementStyle';
+import { Stroke } from 'ol/style';
+import { MapSize } from '@/redux/map/map.types';
+import { Coordinate } from 'ol/coordinate';
+
+export interface LayerRectProps {
+  elementId: number;
+  x: number;
+  y: number;
+  width: number;
+  height: number;
+  layer: number;
+  zIndex: number;
+  fillColor: Color;
+  borderColor: Color;
+  lineWidth: number;
+  pointToProjection: UsePointToProjectionResult;
+  mapInstance: MapInstance;
+  mapSize: MapSize;
+}
+
+export default class LayerRect {
+  elementId: number;
+
+  x: number;
+
+  y: number;
+
+  width: number;
+
+  height: number;
+
+  layer: number;
+
+  zIndex: number;
+
+  fillColor: Color;
+
+  borderColor: Color;
+
+  lineWidth: number;
+
+  style: Style = new Style();
+
+  polygon: Polygon = new Polygon([]);
+
+  strokeStyle: Stroke = new Stroke();
+
+  feature: Feature<Polygon>;
+
+  mapSize: MapSize;
+
+  pointToProjection: UsePointToProjectionResult;
+
+  minResolution: number;
+
+  constructor({
+    elementId,
+    x,
+    y,
+    width,
+    height,
+    layer,
+    zIndex,
+    fillColor,
+    borderColor,
+    lineWidth,
+    pointToProjection,
+    mapInstance,
+    mapSize,
+  }: LayerRectProps) {
+    this.elementId = elementId;
+    this.x = x;
+    this.y = y;
+    this.width = width;
+    this.height = height;
+    this.layer = layer;
+    this.zIndex = zIndex;
+    this.fillColor = fillColor;
+    this.borderColor = borderColor;
+    this.lineWidth = lineWidth;
+    this.pointToProjection = pointToProjection;
+    this.mapSize = mapSize;
+
+    const maxZoom = mapInstance?.getView().get('originalMaxZoom');
+    this.minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom) || 1;
+
+    this.drawPolygon();
+
+    this.setStyles();
+
+    this.feature = new Feature({
+      geometry: this.polygon,
+      layer,
+    });
+    this.feature.setId(this.elementId);
+    this.feature.set('getObjectData', this.getData.bind(this));
+    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.setStyle(this.getStyle.bind(this));
+  }
+
+  private getData(): LayerRectModel {
+    return {
+      id: this.elementId,
+      x: this.x,
+      y: this.y,
+      z: this.zIndex,
+      width: this.width,
+      height: this.height,
+      layer: this.layer,
+      fillColor: this.fillColor,
+      borderColor: this.borderColor,
+      lineWidth: this.lineWidth,
+    };
+  }
+
+  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 refreshPolygon(): void {
+    this.drawPolygon();
+    this.feature.setGeometry(this.polygon);
+    this.feature.changed();
+  }
+
+  private setStyles(): void {
+    this.strokeStyle = getStroke({
+      color: rgbToHex(this.borderColor),
+      width: this.lineWidth,
+    });
+    this.style = getStyle({
+      geometry: this.polygon,
+      borderColor: this.borderColor,
+      fillColor: this.fillColor,
+      lineWidth: this.lineWidth,
+      zIndex: this.zIndex,
+    });
+    this.style.setGeometry(this.polygon);
+  }
+
+  private updateElement(layerRect: LayerRectModel): void {
+    this.elementId = layerRect.id;
+    this.x = layerRect.x;
+    this.y = layerRect.y;
+    this.width = layerRect.width;
+    this.height = layerRect.height;
+    this.zIndex = layerRect.z;
+    this.fillColor = layerRect.fillColor;
+    this.borderColor = layerRect.borderColor;
+
+    this.refreshPolygon();
+    this.setStyles();
+    this.feature.changed();
+  }
+
+  private setCoordinates(coords: Coordinate[][]): void {
+    const geometry = this.style.getGeometry();
+    if (geometry && geometry instanceof Polygon) {
+      geometry.setCoordinates(coords);
+    }
+  }
+
+  protected getStyle(feature: FeatureLike, resolution: number): Style | Array<Style> | void {
+    const scale = this.minResolution / resolution;
+    return getScaledElementStyle(this.style, this.strokeStyle, scale);
+  }
+}
diff --git a/src/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer.ts b/src/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer.ts
index e80c3fec..7c6338f0 100644
--- a/src/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer.ts
+++ b/src/components/Map/MapViewer/utils/shapes/layer/utils/drawElementOnLayer.ts
@@ -1,4 +1,4 @@
-import { LayerImage, LayerText } from '@/types/models';
+import { LayerImage, LayerRect, LayerText } from '@/types/models';
 import { MapInstance } from '@/types/map';
 
 export default function drawElementOnLayer({
@@ -9,7 +9,7 @@ export default function drawElementOnLayer({
 }: {
   mapInstance: MapInstance;
   activeLayer: number;
-  object: LayerImage | LayerText;
+  object: LayerImage | LayerText | LayerRect;
   drawFunctionKey: string;
 }): void {
   mapInstance?.getAllLayers().forEach(layer => {
diff --git a/src/models/fixtures/layerRectFixture.ts b/src/models/fixtures/layerRectFixture.ts
new file mode 100644
index 00000000..ff5b27d9
--- /dev/null
+++ b/src/models/fixtures/layerRectFixture.ts
@@ -0,0 +1,9 @@
+import { ZOD_SEED } from '@/constants';
+// eslint-disable-next-line import/no-extraneous-dependencies
+import { createFixture } from 'zod-fixture';
+import { layerRectSchema } from '@/models/layerRectSchema';
+
+export const layerRectFixture = createFixture(layerRectSchema, {
+  seed: ZOD_SEED,
+  array: { min: 1, max: 1 },
+});
diff --git a/src/models/fixtures/layerRectsFixture.ts b/src/models/fixtures/layerRectsFixture.ts
index 98469f8b..080cad3b 100644
--- a/src/models/fixtures/layerRectsFixture.ts
+++ b/src/models/fixtures/layerRectsFixture.ts
@@ -6,5 +6,5 @@ import { layerRectSchema } from '@/models/layerRectSchema';
 
 export const layerRectsFixture = createFixture(pageableSchema(layerRectSchema), {
   seed: ZOD_SEED,
-  array: { min: 3, max: 3 },
+  array: { min: 1, max: 1 },
 });
diff --git a/src/models/layerRectSchema.ts b/src/models/layerRectSchema.ts
index 440c96d4..4a299641 100644
--- a/src/models/layerRectSchema.ts
+++ b/src/models/layerRectSchema.ts
@@ -8,9 +8,8 @@ export const layerRectSchema = z.object({
   z: z.number(),
   width: z.number(),
   height: z.number(),
+  layer: z.number(),
   lineWidth: z.number(),
-  size: z.number(),
   fillColor: colorSchema,
   borderColor: colorSchema,
-  elementId: z.string(),
 });
diff --git a/src/redux/apiPath.ts b/src/redux/apiPath.ts
index 18186d6f..d52b7f27 100644
--- a/src/redux/apiPath.ts
+++ b/src/redux/apiPath.ts
@@ -41,6 +41,8 @@ export const apiPath = {
     `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/texts/`,
   getLayerRects: (modelId: number, layerId: number): string =>
     `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/rects/`,
+  addLayerRect: (modelId: number, layerId: number): string =>
+    `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/rects/`,
   getLayerOvals: (modelId: number, layerId: number): string =>
     `projects/${PROJECT_ID}/maps/${modelId}/layers/${layerId}/ovals/`,
   getLayerLines: (modelId: number, layerId: number): string =>
diff --git a/src/redux/layers/layers.reducers.test.ts b/src/redux/layers/layers.reducers.test.ts
index d93fb4f8..04b20859 100644
--- a/src/redux/layers/layers.reducers.test.ts
+++ b/src/redux/layers/layers.reducers.test.ts
@@ -46,7 +46,7 @@ const layersState: LayersState = {
         {
           details: layerFixture,
           texts: {},
-          rects: [],
+          rects: {},
           ovals: [],
           lines: [],
           images: {},
@@ -102,7 +102,7 @@ describe('layers reducer', () => {
         {
           details: layersFixture.content[0],
           texts: { [layerTextsFixture.content[0].id]: layerTextsFixture.content[0] },
-          rects: layerRectsFixture.content,
+          rects: { [layerRectsFixture.content[0].id]: layerRectsFixture.content[0] },
           ovals: layerOvalsFixture.content,
           lines: layerLinesFixture.content,
           images: { [layerImagesFixture.content[0].id]: layerImagesFixture.content[0] },
@@ -168,7 +168,7 @@ describe('layers reducer', () => {
           {
             details: layersFixture.content[0],
             texts: { [layerTextsFixture.content[0].id]: layerTextsFixture.content[0] },
-            rects: layerRectsFixture.content,
+            rects: { [layerRectsFixture.content[0].id]: layerRectsFixture.content[0] },
             ovals: layerOvalsFixture.content,
             lines: layerLinesFixture.content,
             images: { [layerImagesFixture.content[0].id]: layerImagesFixture.content[0] },
diff --git a/src/redux/layers/layers.reducers.ts b/src/redux/layers/layers.reducers.ts
index 238a3441..9d1a42d6 100644
--- a/src/redux/layers/layers.reducers.ts
+++ b/src/redux/layers/layers.reducers.ts
@@ -7,7 +7,7 @@ import {
   LAYERS_STATE_INITIAL_LAYER_MOCK,
 } from '@/redux/layers/layers.mock';
 import { DEFAULT_ERROR } from '@/constants/errors';
-import { LayerImage, LayerText } from '@/types/models';
+import { LayerImage, LayerRect, LayerText } from '@/types/models';
 
 export const getLayersForModelReducer = (builder: ActionReducerMapBuilder<LayersState>): void => {
   builder.addCase(getLayersForModel.pending, (state, action) => {
@@ -230,3 +230,19 @@ export const layerDeleteTextReducer = (
   }
   delete layer.texts[textId];
 };
+
+export const layerAddRectReducer = (
+  state: LayersState,
+  action: PayloadAction<{ modelId: number; layerId: number; layerRect: LayerRect }>,
+): void => {
+  const { modelId, layerId, layerRect } = action.payload;
+  const { data } = state[modelId];
+  if (!data) {
+    return;
+  }
+  const layer = data.layers.find(layerState => layerState.details.id === layerId);
+  if (!layer) {
+    return;
+  }
+  layer.rects[layerRect.id] = layerRect;
+};
diff --git a/src/redux/layers/layers.selectors.ts b/src/redux/layers/layers.selectors.ts
index 8123fa00..65493d94 100644
--- a/src/redux/layers/layers.selectors.ts
+++ b/src/redux/layers/layers.selectors.ts
@@ -120,7 +120,7 @@ export const maxObjectZIndexForLayerSelector = createSelector(
       items.length > 0 ? Math.max(...items.map(item => item.z || 0)) : 0;
 
     const textsMaxZ = getMaxZFromItems(Object.values(foundLayer.texts));
-    const rectsMaxZ = getMaxZFromItems(foundLayer.rects);
+    const rectsMaxZ = getMaxZFromItems(Object.values(foundLayer.rects));
     const ovalsMaxZ = getMaxZFromItems(foundLayer.ovals);
     const linesMaxZ = getMaxZFromItems(foundLayer.lines);
     const imagesMaxZ = getMaxZFromItems(Object.values(foundLayer.images));
@@ -143,7 +143,7 @@ export const minObjectZIndexForLayerSelector = createSelector(
       items.length > 0 ? Math.min(...items.map(item => item.z || 0)) : 0;
 
     const textsMinZ = getMinZFromItems(Object.values(foundLayer.texts));
-    const rectsMinZ = getMinZFromItems(foundLayer.rects);
+    const rectsMinZ = getMinZFromItems(Object.values(foundLayer.rects));
     const ovalsMinZ = getMinZFromItems(foundLayer.ovals);
     const linesMinZ = getMinZFromItems(foundLayer.lines);
     const imagesMinZ = getMinZFromItems(Object.values(foundLayer.images));
diff --git a/src/redux/layers/layers.slice.ts b/src/redux/layers/layers.slice.ts
index 871012fc..c66fa629 100644
--- a/src/redux/layers/layers.slice.ts
+++ b/src/redux/layers/layers.slice.ts
@@ -14,6 +14,7 @@ import {
   setLayerToActiveReducer,
   layerDeleteTextReducer,
   layerUpdateTextReducer,
+  layerAddRectReducer,
 } from '@/redux/layers/layers.reducers';
 
 export const layersSlice = createSlice({
@@ -29,6 +30,7 @@ export const layersSlice = createSlice({
     layerAddText: layerAddTextReducer,
     layerUpdateText: layerUpdateTextReducer,
     layerDeleteText: layerDeleteTextReducer,
+    layerAddRect: layerAddRectReducer,
     setDrawLayer: setDrawLayerReducer,
   },
   extraReducers: builder => {
@@ -48,6 +50,7 @@ export const {
   layerAddText,
   layerUpdateText,
   layerDeleteText,
+  layerAddRect,
   setDrawLayer,
 } = layersSlice.actions;
 
diff --git a/src/redux/layers/layers.thunks.test.ts b/src/redux/layers/layers.thunks.test.ts
index 09028272..2feb78e4 100644
--- a/src/redux/layers/layers.thunks.test.ts
+++ b/src/redux/layers/layers.thunks.test.ts
@@ -68,7 +68,7 @@ describe('layers thunks', () => {
           {
             details: layersFixture.content[0],
             texts: { [layerTextsFixture.content[0].id]: layerTextsFixture.content[0] },
-            rects: layerRectsFixture.content,
+            rects: { [layerRectsFixture.content[0].id]: layerRectsFixture.content[0] },
             ovals: layerOvalsFixture.content,
             lines: layerLinesFixture.content,
             images: { [layerImagesFixture.content[0].id]: layerImagesFixture.content[0] },
diff --git a/src/redux/layers/layers.thunks.ts b/src/redux/layers/layers.thunks.ts
index bda72fce..0db4a364 100644
--- a/src/redux/layers/layers.thunks.ts
+++ b/src/redux/layers/layers.thunks.ts
@@ -1,7 +1,7 @@
 /* eslint-disable no-magic-numbers */
 import { z as zod } from 'zod';
 import { apiPath } from '@/redux/apiPath';
-import { Color, Layer, LayerImage, Layers, LayerText } from '@/types/models';
+import { Color, Layer, LayerImage, LayerRect, Layers, LayerText } from '@/types/models';
 import { validateDataUsingZodSchema } from '@/utils/validateDataUsingZodSchema';
 import { createAsyncThunk } from '@reduxjs/toolkit';
 import { ThunkConfig } from '@/types/store';
@@ -27,6 +27,7 @@ import {
   HorizontalAlign,
   VerticalAlign,
 } from '@/components/Map/MapViewer/MapViewer.types';
+import { LayerRectFactoryForm } from '@/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactory.types';
 
 export const getLayer = createAsyncThunk<
   Layer | null,
@@ -68,7 +69,7 @@ export const getLayersForModel = createAsyncThunk<
         return {
           details: layer,
           texts: arrayToKeyValue(textsResponse.data.content as Array<LayerText>, 'id'),
-          rects: rectsResponse.data.content,
+          rects: arrayToKeyValue(rectsResponse.data.content as Array<LayerRect>, 'id'),
           ovals: ovalsResponse.data.content,
           lines: linesResponse.data.content,
           images: arrayToKeyValue(imagesResponse.data.content as Array<LayerImage>, 'id'),
@@ -78,7 +79,7 @@ export const getLayersForModel = createAsyncThunk<
     layers = layers.filter(layer => {
       return (
         zod.array(layerTextSchema).safeParse(Object.values(layer.texts)).success &&
-        zod.array(layerRectSchema).safeParse(layer.rects).success &&
+        zod.array(layerRectSchema).safeParse(Object.values(layer.rects)).success &&
         zod.array(layerOvalSchema).safeParse(layer.ovals).success &&
         zod.array(layerLineSchema).safeParse(layer.lines).success &&
         zod.array(layerImageSchema).safeParse(Object.values(layer.images)).success
@@ -391,3 +392,31 @@ export const updateLayerText = createAsyncThunk<
     }
   },
 );
+
+export const addLayerRect = createAsyncThunk<
+  LayerRect | null,
+  {
+    modelId: number;
+    layerId: number;
+    z: number;
+    boundingBox: BoundingBox;
+    rectData: LayerRectFactoryForm;
+  },
+  ThunkConfig
+>('layers/addLayerRect', async ({ modelId, layerId, z, boundingBox, rectData }) => {
+  try {
+    const { data } = await axiosInstanceNewAPI.post<LayerRect>(
+      apiPath.addLayerRect(modelId, layerId),
+      {
+        ...boundingBox,
+        ...rectData,
+        z,
+      },
+    );
+    const isDataValid = validateDataUsingZodSchema(data, layerRectSchema);
+
+    return isDataValid ? data : null;
+  } catch (error) {
+    return Promise.reject(getError({ error }));
+  }
+});
diff --git a/src/redux/layers/layers.types.ts b/src/redux/layers/layers.types.ts
index 05b4636e..26547939 100644
--- a/src/redux/layers/layers.types.ts
+++ b/src/redux/layers/layers.types.ts
@@ -21,7 +21,7 @@ export interface LayerUpdateInterface {
 export type LayerState = {
   details: Layer;
   texts: { [key: string]: LayerText };
-  rects: LayerRect[];
+  rects: { [key: string]: LayerRect };
   ovals: LayerOval[];
   lines: LayerLine[];
   images: { [key: string]: LayerImage };
diff --git a/src/redux/mapEditTools/mapEditTools.constants.ts b/src/redux/mapEditTools/mapEditTools.constants.ts
index c3b9c826..2a0a9512 100644
--- a/src/redux/mapEditTools/mapEditTools.constants.ts
+++ b/src/redux/mapEditTools/mapEditTools.constants.ts
@@ -1,5 +1,6 @@
 export const MAP_EDIT_ACTIONS = {
   DRAW_IMAGE: 'DRAW_IMAGE',
   ADD_TEXT: 'ADD_TEXT',
+  ADD_RECT: 'ADD_RECT',
   TRANSFORM_IMAGE: 'TRANSFORM_IMAGE',
 } as const;
diff --git a/src/redux/modal/modal.constants.ts b/src/redux/modal/modal.constants.ts
index f858a91b..6d83ad0b 100644
--- a/src/redux/modal/modal.constants.ts
+++ b/src/redux/modal/modal.constants.ts
@@ -16,4 +16,5 @@ export const MODAL_INITIAL_STATE: ModalState = {
   layerFactoryState: { id: undefined },
   layerImageObjectFactoryState: undefined,
   layerTextFactoryState: undefined,
+  layerRectFactoryState: undefined,
 };
diff --git a/src/redux/modal/modal.mock.ts b/src/redux/modal/modal.mock.ts
index 85f6e5bd..9f4076e2 100644
--- a/src/redux/modal/modal.mock.ts
+++ b/src/redux/modal/modal.mock.ts
@@ -16,4 +16,5 @@ export const MODAL_INITIAL_STATE_MOCK: ModalState = {
   layerFactoryState: { id: undefined },
   layerImageObjectFactoryState: undefined,
   layerTextFactoryState: undefined,
+  layerRectFactoryState: undefined,
 };
diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts
index 923d2858..e95b3e1b 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -171,3 +171,13 @@ export const openLayerTextEditFactoryModalReducer = (state: ModalState): void =>
   state.modalName = 'layer-text-edit-factory';
   state.modalTitle = 'Edit text';
 };
+
+export const openLayerRectFactoryModalReducer = (
+  state: ModalState,
+  action: PayloadAction<BoundingBox>,
+): void => {
+  state.layerRectFactoryState = action.payload;
+  state.modalName = 'layer-rect-factory';
+  state.modalTitle = 'Add rectangle';
+  state.isOpen = true;
+};
diff --git a/src/redux/modal/modal.selector.ts b/src/redux/modal/modal.selector.ts
index 4f5c8fb0..35b4fdbe 100644
--- a/src/redux/modal/modal.selector.ts
+++ b/src/redux/modal/modal.selector.ts
@@ -40,3 +40,8 @@ export const layerTextFactoryStateSelector = createSelector(
   modalSelector,
   modal => modal.layerTextFactoryState,
 );
+
+export const layerRectFactoryStateSelector = createSelector(
+  modalSelector,
+  modal => modal.layerRectFactoryState,
+);
diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts
index ed74baec..7d6d21e2 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -21,6 +21,7 @@ import {
   openLayerImageObjectEditFactoryModalReducer,
   openLayerTextFactoryModalReducer,
   openLayerTextEditFactoryModalReducer,
+  openLayerRectFactoryModalReducer,
 } from './modal.reducers';
 
 const modalSlice = createSlice({
@@ -47,6 +48,7 @@ const modalSlice = createSlice({
     openLayerImageObjectEditFactoryModal: openLayerImageObjectEditFactoryModalReducer,
     openLayerTextFactoryModal: openLayerTextFactoryModalReducer,
     openLayerTextEditFactoryModal: openLayerTextEditFactoryModalReducer,
+    openLayerRectFactoryModal: openLayerRectFactoryModalReducer,
   },
 });
 
@@ -71,6 +73,7 @@ export const {
   openLayerImageObjectEditFactoryModal,
   openLayerTextFactoryModal,
   openLayerTextEditFactoryModal,
+  openLayerRectFactoryModal,
 } = modalSlice.actions;
 
 export default modalSlice.reducer;
diff --git a/src/redux/modal/modal.types.ts b/src/redux/modal/modal.types.ts
index 20f7a998..57ff24ee 100644
--- a/src/redux/modal/modal.types.ts
+++ b/src/redux/modal/modal.types.ts
@@ -26,6 +26,8 @@ export type LayerImageObjectFactoryState = BoundingBox | undefined;
 
 export type LayerTextFactoryState = BoundingBox | undefined;
 
+export type LayerRectFactoryState = BoundingBox | undefined;
+
 export interface ModalState {
   isOpen: boolean;
   modalName: ModalName;
@@ -37,6 +39,7 @@ export interface ModalState {
   layerFactoryState: LayerFactoryState;
   layerImageObjectFactoryState: LayerImageObjectFactoryState;
   layerTextFactoryState: LayerTextFactoryState;
+  layerRectFactoryState: LayerRectFactoryState;
 }
 
 export type OpenEditOverlayModalPayload = MapOverlay;
diff --git a/src/shared/Icon/Icon.component.tsx b/src/shared/Icon/Icon.component.tsx
index aed961c3..298b2c3b 100644
--- a/src/shared/Icon/Icon.component.tsx
+++ b/src/shared/Icon/Icon.component.tsx
@@ -35,6 +35,7 @@ import { MoveFrontIcon } from '@/shared/Icon/Icons/MoveFrontIcon';
 import { MoveBackIcon } from '@/shared/Icon/Icons/MoveBackIcon';
 import { LayerArrowUpIcon } from '@/shared/Icon/Icons/LayerArrowUpIcon';
 import { LayerArrowDownIcon } from '@/shared/Icon/Icons/LayerArrowDownIcon';
+import { RectangleIcon } from '@/shared/Icon/Icons/RectangleIcon';
 import { LocationIcon } from './Icons/LocationIcon';
 import { MaginfierZoomInIcon } from './Icons/MagnifierZoomIn';
 import { MaginfierZoomOutIcon } from './Icons/MagnifierZoomOut';
@@ -93,6 +94,7 @@ const icons: Record<IconTypes, IconComponentType> = {
   'move-back': MoveBackIcon,
   'layer-arrow-up': LayerArrowUpIcon,
   'layer-arrow-down': LayerArrowDownIcon,
+  rectangle: RectangleIcon,
 } as const;
 
 export const Icon = ({ name, className = '', ...rest }: IconProps): JSX.Element => {
diff --git a/src/shared/Icon/Icons/RectangleIcon.tsx b/src/shared/Icon/Icons/RectangleIcon.tsx
new file mode 100644
index 00000000..522b1cc7
--- /dev/null
+++ b/src/shared/Icon/Icons/RectangleIcon.tsx
@@ -0,0 +1,16 @@
+interface RectangleIconProps {
+  className?: string;
+}
+
+export const RectangleIcon = ({ className }: RectangleIconProps): JSX.Element => (
+  <svg
+    width="20"
+    height="20"
+    viewBox="0 0 100 100"
+    fill="none"
+    className={className}
+    xmlns="http://www.w3.org/2000/svg"
+  >
+    <rect x="4" y="21" width="92" height="58" stroke="black" fill="none" strokeWidth="2" />
+  </svg>
+);
diff --git a/src/types/iconTypes.ts b/src/types/iconTypes.ts
index 0083a622..c648c34a 100644
--- a/src/types/iconTypes.ts
+++ b/src/types/iconTypes.ts
@@ -41,6 +41,7 @@ export type IconTypes =
   | 'move-front'
   | 'move-back'
   | 'layer-arrow-up'
-  | 'layer-arrow-down';
+  | 'layer-arrow-down'
+  | 'rectangle';
 
 export type IconComponentType = ({ className }: { className: string }) => JSX.Element;
diff --git a/src/types/modal.ts b/src/types/modal.ts
index 579c8137..eba75e3e 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -16,4 +16,5 @@ export type ModalName =
   | 'layer-image-object-factory'
   | 'layer-image-object-edit-factory'
   | 'layer-text-factory'
-  | 'layer-text-edit-factory';
+  | 'layer-text-edit-factory'
+  | 'layer-rect-factory';
diff --git a/src/utils/convert/hexToRgbIntAlpha.test.ts b/src/utils/convert/hexToRgbIntAlpha.test.ts
index cce777c8..eabaf373 100644
--- a/src/utils/convert/hexToRgbIntAlpha.test.ts
+++ b/src/utils/convert/hexToRgbIntAlpha.test.ts
@@ -3,12 +3,12 @@ import hexToRgbIntAlpha from './hexToRgbIntAlpha';
 describe('hexToRgbIntAlpha', () => {
   it('should convert a valid 6-character HEX color to RGB integer and alpha', () => {
     const result = hexToRgbIntAlpha('#ff5733');
-    expect(result).toEqual({ rgb: 16734003, alpha: 1 });
+    expect(result).toEqual({ rgb: 16734003, alpha: 255 });
   });
 
   it('should convert a valid 8-character HEX color to RGB integer and alpha', () => {
     const result = hexToRgbIntAlpha('#ff5733cc');
-    expect(result).toEqual({ rgb: 16734003, alpha: 0.8 });
+    expect(result).toEqual({ rgb: 16734003, alpha: 204 });
   });
 
   it('should throw an error for an invalid HEX color length', () => {
diff --git a/src/utils/convert/hexToRgbIntAlpha.ts b/src/utils/convert/hexToRgbIntAlpha.ts
index fb2ce4a4..a363ca25 100644
--- a/src/utils/convert/hexToRgbIntAlpha.ts
+++ b/src/utils/convert/hexToRgbIntAlpha.ts
@@ -12,14 +12,11 @@ export default function hexToRgbIntAlpha(hex: string): Color {
   const g = parseInt(sanitizedHex.slice(2, 4), 16);
   const b = parseInt(sanitizedHex.slice(4, 6), 16);
 
-  let a = 255;
+  let alpha = 255;
   if (sanitizedHex.length === 8) {
-    a = parseInt(sanitizedHex.slice(6, 8), 16);
+    alpha = parseInt(sanitizedHex.slice(6, 8), 16);
   }
 
-  const alpha = a / 255;
-
   const rgb = r * 65536 + g * 256 + b;
-
   return { rgb, alpha };
 }
-- 
GitLab


From 486b0ec407ab1af117baf91a5cc50bfb7ca71de2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Tue, 18 Feb 2025 14:32:59 +0100
Subject: [PATCH 8/8] feat(layers-rect): implement layer rectangle editing

---
 .../LayerFactoryModal.component.tsx           |   4 +-
 ...eObjectEditFactoryModal.component.test.tsx |   2 +-
 ...rImageObjectEditFactoryModal.component.tsx |   2 +-
 ...ImageObjectFactoryModal.component.test.tsx |   2 +-
 ...LayerImageObjectFactoryModal.component.tsx |   4 +-
 .../LayerRectEditFactoryModal.component.tsx   | 107 ++++++++++++++++++
 .../LayerRectFactoryModal.component.test.tsx  |   2 +-
 .../LayerRectFactoryModal.component.tsx       |   6 +-
 .../LayerTextEditFactoryModal.component.tsx   |   2 +-
 .../LayerTextFactoryModal.component.test.tsx  |   2 +-
 .../LayerTextFactoryModal.component.tsx       |   6 +-
 .../FunctionalArea/Modal/Modal.component.tsx  |   6 +
 .../ModalLayout/ModalLayout.component.tsx     |   6 +-
 .../LayerDrawerRectItem.component.tsx         |  61 +++++++++-
 .../LayersDrawer/LayersDrawer.component.tsx   |  13 ++-
 .../LayersDrawerLayer.component.tsx           |   2 +-
 .../LayersDrawerObjectsList.component.tsx     |  65 ++++++++++-
 .../useOlMapAdditionalLayers.ts               |   1 +
 .../utils/shapes/elements/Glyph/Glyph.ts      |  29 ++---
 .../shapes/elements/getBoundingBoxPolygon.ts  |  26 +++++
 .../Map/MapViewer/utils/shapes/layer/Layer.ts |   8 +-
 .../utils/shapes/layer/elements/LayerRect.ts  |  54 +++++++--
 .../utils/shapes/layer/elements/LayerText.ts  |  35 +++---
 .../utils/shapes/layer/utils/updateElement.ts |   4 +-
 src/redux/apiPath.ts                          |   6 +-
 src/redux/layers/layers.reducers.ts           |  15 ++-
 src/redux/layers/layers.slice.ts              |   3 +
 src/redux/layers/layers.thunks.ts             |  42 +++++++
 src/redux/layers/utils/setLayerRect.ts        |  18 +++
 .../mapEditTools/mapEditTools.reducers.ts     |   4 +-
 src/redux/mapEditTools/mapEditTools.types.ts  |   4 +-
 src/redux/modal/modal.reducers.ts             |   6 +
 src/redux/modal/modal.slice.ts                |   3 +
 src/types/modal.ts                            |   3 +-
 34 files changed, 463 insertions(+), 90 deletions(-)
 create mode 100644 src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectEditFactoryModal.component.tsx
 create mode 100644 src/components/Map/MapViewer/utils/shapes/elements/getBoundingBoxPolygon.ts
 create mode 100644 src/redux/layers/utils/setLayerRect.ts

diff --git a/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx b/src/components/FunctionalArea/Modal/LayerFactoryModal/LayerFactoryModal.component.tsx
index b806d2b6..31c052b8 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 a6adc865..5233b3f6 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectEditFactoryModal.component.test.tsx
@@ -177,7 +177,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 b90d5b25..276b8e51 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 18e2172b..53f1af3d 100644
--- a/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerImageObjectModal/LayerImageObjectFactoryModal.component.test.tsx
@@ -127,7 +127,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 4d1513e9..ec495659 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 00000000..4ff05d12
--- /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 d6dae5a2..cfaed463 100644
--- a/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerRectFactoryModal/LayerRectFactoryModal.component.test.tsx
@@ -95,7 +95,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 c374bfc5..cbdfb230 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 c73e9d93..d80231bd 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 71f607e3..fa095c9a 100644
--- a/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx
+++ b/src/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component.test.tsx
@@ -140,7 +140,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 bfb80aff..b1446156 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 c64517dc..81de8ecb 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -12,6 +12,7 @@ import {
 import { LayerTextFactoryModal } from '@/components/FunctionalArea/Modal/LayerTextFactoryModal/LayerTextFactoryModal.component';
 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 { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
 import { ErrorReportModal } from './ErrorReportModal';
@@ -117,6 +118,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 357f7cf1..6bca9546 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 a8f0e9bc..c36031e5 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 33c259f3..1e85c51d 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 03aa4417..d937ed6e 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 330c7bbe..bd6c7cdd 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 fe1497fe..0ca5564b 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 57b36875..edad8cde 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 00000000..375cee53
--- /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 93456a0d..851bb3ea 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 844ec355..e86cfc44 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 26565345..41662941 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 88f50d44..4318381d 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 d52b7f27..df31fe9e 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 9d1a42d6..74b83a3d 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 c66fa629..0760126a 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 0db4a364..4d351082 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 00000000..a0b9abbb
--- /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 d45e719f..b8519608 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 4c216c40..b9a012c8 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 e95b3e1b..d020354d 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -181,3 +181,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 7d6d21e2..cb3398e3 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -22,6 +22,7 @@ import {
   openLayerTextFactoryModalReducer,
   openLayerTextEditFactoryModalReducer,
   openLayerRectFactoryModalReducer,
+  openLayerRectEditFactoryModalReducer,
 } from './modal.reducers';
 
 const modalSlice = createSlice({
@@ -49,6 +50,7 @@ const modalSlice = createSlice({
     openLayerTextFactoryModal: openLayerTextFactoryModalReducer,
     openLayerTextEditFactoryModal: openLayerTextEditFactoryModalReducer,
     openLayerRectFactoryModal: openLayerRectFactoryModalReducer,
+    openLayerRectEditFactoryModal: openLayerRectEditFactoryModalReducer,
   },
 });
 
@@ -74,6 +76,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 eba75e3e..d7360077 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -17,4 +17,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';
-- 
GitLab