Index: imaps-frontend/src/scripts/base/MapNode.js
===================================================================
--- imaps-frontend/src/scripts/base/MapNode.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,99 +1,0 @@
-import MapShape from "./MapShape.js";
-import Konva from "konva";
-
-export default class MapNode extends MapShape{
-
-    constructor(config, layer, blockSize, snap) {
-        if (new.target === MapNode) {
-            throw new Error("Cannot instantiate abstract class NodeShape directly.");
-        }
-
-        super(config,layer,blockSize,snap);
-        this.connectionLines = [];
-
-        this.connLine = new Konva.Line({
-            stroke: "rgba(245,37,37,0.85)",
-            dash: [2,3],
-            strokeWidth: 2,
-            lineCap: 'round',
-            lineJoin: 'miter',
-            opacity: 0.8
-        });
-        this.connLine.cache();
-
-        this.on("dragmove",() => {
-            this.connectionLines.forEach(lineWrapper => {
-                console.log("other",lineWrapper.otherShape)
-                let updatedPoints = [this.x(),this.y(),lineWrapper.otherShape.x(),lineWrapper.otherShape.y()]
-                lineWrapper.line.points(updatedPoints);
-            })
-        })
-    }
-
-    connect(node,draw = true){
-
-
-        if(!node.info.selectedPins.includes(this.info.name)){
-            console.log("vleze conn 2ds")
-            node.info.selectedPins.push(this.info.name);
-        }
-
-        if(!draw) return
-
-        const line = this.connLine.clone({
-            points: [this.x(),this.y(),node.x(),node.y()]
-        });
-
-        let lineWrapper = {
-            line: line,
-            otherShape: node
-        };
-
-        this.connectionLines.push(lineWrapper);
-
-        let lineWrapperSend = {
-            line: line,
-            otherShape: this
-        };
-
-        node.addLineReference(lineWrapperSend);
-
-        this.layer.add(lineWrapper.line);
-    }
-    
-    
-
-    addLineReference(line){
-        this.connectionLines.push(line);
-    }
-
-    removeLineWrapper(target){
-        this.connectionLines = this.connectionLines.filter(lineWrapper => lineWrapper.otherShape !== target);
-    }
-
-    removeConnection(shape){
-        this.info.selectedPins = this.info.selectedPins.filter(sl => sl !== shape.info.name)
-    }
-
-
-    removeConnectionLine(target){
-        this.connectionLines.forEach(lineWrapper => {
-            if (lineWrapper.otherShape === target){
-                lineWrapper.line.remove();
-                target.removeLineWrapper(this);
-                this.removeLineWrapper(target);
-            }
-        })
-    }
-
-
-    destroy() {
-        super.destroy();
-        this.connectionLines.forEach(lineWrapper => {
-            lineWrapper.line.remove()
-            lineWrapper.otherShape.removeLineWrapper(this);
-        });
-    }
-
-
-}
Index: imaps-frontend/src/scripts/base/MapShape.js
===================================================================
--- imaps-frontend/src/scripts/base/MapShape.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,156 +1,0 @@
-import Konva from "konva";
-
-export default class MapShape extends Konva.Shape {
-    constructor(config, layer, blockSize, snap) {
-        if (new.target === MapShape) {
-            throw new Error("Cannot instantiate abstract class BaseShape directly.");
-        }
-
-        super(config);
-        this.layer = layer;
-        this.blockSize = blockSize;
-        this._type = "";
-        this.snappable = snap;
-        this._info = {};
-        this.eventName = "";
-        this.infoText = null;
-        this.floorNum;
-
-        this.shadowForStrokeEnabled(false);
-        this.on("mouseover", () => (document.body.style.cursor = "pointer"));
-        this.on("mouseout", () => (document.body.style.cursor = "default"));
-        this.on("click", (e) => {
-            if(e.evt.altKey){
-                this.moveToTop();
-                this.getLayer()
-                    .find("Transformer")
-                    .forEach((t) => t.moveToTop());
-            }
-
-        });
-
-        if (snap) {
-            this.on("dragend", this.snapToGrid.bind(this));
-            this.on('dblclick', this.snapToGrid.bind(this));
-        }
-
-        this.on("transform", () => {
-            const scaleX = this.scaleX();
-            const scaleY = this.scaleY();
-            this.strokeWidth(1 / Math.max(scaleX, scaleY));
-        });
-
-
-        this.on('dragmove', () => {
-            if (this.infoText) {
-                this.updateTextPosition();
-            }
-        });
-
-    }
-
-    loadInfo(attrs) {
-        console.log("Abstract function");
-    }
-
-
-    initText() {
-        this.textOffsetX = 0;
-        this.textOffsetY = -30;
-        this.infoText = new Konva.Text({
-            x: this.x() + this.textOffsetX,
-            y: this.y() + this.textOffsetY,
-            text: this._info.name,
-            fontSize: 12,
-            fontFamily: 'Exo',
-            fill: 'white',
-        });
-    }
-
-    updateTextPosition() {
-        if (this.infoText) {
-            this.infoText.x(this.x() + this.textOffsetX);
-            this.infoText.y(this.y() + this.textOffsetY);
-        }
-    }
-
-    displayName(layer) {
-        if (this.infoText) {
-            this.infoText.text(this._info.name);
-            layer.add(this.infoText);
-        }
-    }
-
-
-    destroy() {
-        super.destroy();
-        if (this.infoText !== null) {
-            this.infoText.remove()
-            console.log("cleared text")
-        }
-    }
-
-    setInfo(infoObj){
-        this.info = infoObj;
-    }
-
-    load(){
-        console.log("Abstract function")
-    }
-
-    _sceneFunc(context) {
-        let width = this.width();
-        let height = this.height();
-        context.beginPath();
-        context.rect(0, 0, width, height)
-        context.closePath();
-        context.fillStrokeShape(this);
-    }
-
-    clearText() {
-        if (this.infoText !== null) {
-            this.infoText.remove()
-            console.log("cleared text")
-        }
-
-    }
-
-    updateText(shapeName){
-            this.infoText.text = shapeName;
-            console.log("Updated text to : " + shapeName)
-    }
-
-    snapToGrid() {
-        this.position({
-            x: Math.round(this.x() / this.blockSize) * this.blockSize,
-            y: Math.round(this.y() / this.blockSize) * this.blockSize,
-        });
-
-    }
-
-    saveShapeDetails() {
-        console.log("This shape does not contain information");
-    }
-
-    onPlace(){
-        //this.snapToGrid();
-    }
-
-
-    get info() {
-        return this._info;
-    }
-
-    set info(formData) {
-        this._info = formData;
-    }
-
-    get type() {
-        return this._type;
-    }
-
-    set type(type) {
-        this._type = type
-    }
-
-}
Index: imaps-frontend/src/scripts/base/RenderedMapShape.js
===================================================================
--- imaps-frontend/src/scripts/base/RenderedMapShape.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,89 +1,0 @@
-import Konva from "konva";
-import config from "../net/netconfig.js";
-
-export default class RenderedMapShape extends Konva.Shape {
-  constructor(config) {
-    if (new.target === RenderedMapShape) {
-      throw new Error("Cannot instantiate abstract class RenderedMapShape directly.");
-    }
-
-    super(config);
-
-    this.info = {
-      name: "",
-      description: "",
-      type: "",
-    };
-    this.class = "Rect";
-    this.infoText = null;
-    this.textOffsetX = 0;
-    this.textOffsetY = 0;
-
-    this.eventName = "";
-
-  }
-
-  initText() {
-    const rectWidth = this.width();
-    const rectHeight = this.height();
-
-    this.infoText = new Konva.Text({
-      x: this.x(),
-      y: this.y(),
-      text: this.info.name || "no name",
-      fontSize: 10,
-      fontFamily: "Exo",
-      fill: "black",
-      align: "center",
-      verticalAlign: "middle",
-    });
-
-    this.infoText.offsetX(this.infoText.width() / 2);
-    this.infoText.offsetY(this.infoText.height() / 2);
-
-    this.infoText.x(this.x() + rectWidth / 2);
-    this.infoText.y(this.y() + rectHeight / 2);
-    this.infoText.rotation(this.rotation());
-  }
-
-
-  updateTextPosition() {
-    if (this.infoText) {
-      this.infoText.x(this.x() + this.textOffsetX);
-      this.infoText.y(this.y() + this.textOffsetY);
-    }
-  }
-
-  clearText() {
-    if (this.infoText !== null) {
-      this.infoText.remove()
-      console.log("cleared text")
-    }
-
-  }
-  _sceneFunc(context) {
-
-    let width = this.width();
-    let height = this.height();
-
-    const cornerRadius = this.attrs.cornerRadius;
-
-    context.beginPath();
-
-    if(!cornerRadius){
-      context.rect(0, 0, width, height)
-    } else {
-      Konva.Util.drawRoundedRectPath(context,width,height,cornerRadius)
-    }
-
-    context.closePath();
-    context.fillStrokeShape(this);
-  }
-
-
-  displayName(layer) {
-    if (this.infoText != null) {
-      layer.add(this.infoText);
-    }
-  }
-}
Index: imaps-frontend/src/scripts/main/MapBuilder.js
===================================================================
--- imaps-frontend/src/scripts/main/MapBuilder.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/main/MapBuilder.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -2,625 +2,565 @@
 import Konva from "konva";
 import HttpService from "../net/HttpService.js";
-import {zoomStage} from "../util/zoomStage.js";
-import {addEventHandling} from "../util/addEventHandling.js";
-import MapNode from "../base/MapNode.js";
-import {json} from "react-router-dom";
-import log from "eslint-plugin-react/lib/util/log.js";
-import ShapeRegistry from "../util/ShapeRegistry.js";
-import shapeRegistry from "../util/ShapeRegistry.js";
-import triggerMapSave from "../util/triggerMapSave.js";
+import { zoomStage } from "../util/zoomStage.js";
 
 export class MapBuilder {
-    constructor(containerId,floorNum,mapName) {
-        this.container = document.getElementById(containerId);
-        this.stage = new Konva.Stage({
-            container: containerId,
-            width: this.container.clientWidth,
-            height: this.container.clientHeight,
+  constructor(containerId) {
+    this.container = document.getElementById(containerId);
+    this.stage = new Konva.Stage({
+      container: containerId,
+      width: this.container.clientWidth,
+      height: this.container.clientHeight,
+    });
+
+    // TODO AKO DRAGNIT NEKOJ OD POCETOK NA STAGE POZICIIVE KE SA ZEZNAT
+    // TODO jwt vo cookie
+    // TODO placed shape i mouseMoveHandler da ne callback ( da ne vrakjat funkcija)
+
+    this.gridLayer = new Konva.Layer();
+    this.mainLayer = new Konva.Layer();
+    this.dragLayer = new Konva.Layer();
+    this.infoPinLayer = new Konva.Layer();
+    this.textLayer = new Konva.Layer();
+    this.gridLayer.listening(false);
+
+    this.originalWidth = this.container.clientWidth;
+    this.originalHeight = this.container.clientHeight;
+
+    this.shapes = [];
+    this.blockSize = 10;
+    this.efficientDrawingMode = false;
+    this.roomTypes = [];
+
+    this.gridLine = new Konva.Line({
+      points: [],
+      stroke: "grey",
+      strokeWidth: 1,
+      opacity: 0.3,
+    });
+
+    this.gridLine.cache();
+
+    this.mainTransformer = new Konva.Transformer({
+      centeredScaling: false,
+      rotationSnaps: [0, 90, 180, 270],
+      anchorSize: 5,
+      padding: 2,
+      anchorFill: "#ef7539",
+      borderStroke: "black",
+      anchorStroke: "black",
+      cornerRadius: 20,
+      anchorCornerRadius: 10,
+      anchorDragBoundFunc: this.transformerSnapFunc(),
+    });
+
+    this.selectionRectangle = new Konva.Rect({
+      fill: "rgba(200,0,255,0.5)",
+      visible: false,
+      listening: false,
+      zIndex: 100,
+    });
+
+    this.x1 = 0;
+    this.y1 = 0;
+    this.x2 = 0;
+    this.y2 = 0;
+
+    this.selecting = false;
+
+    this.initialize();
+  }
+
+  initialize() {
+    this.drawGrid();
+    this.mainLayer.add(this.mainTransformer);
+    this.mainLayer.add(this.selectionRectangle);
+    this.stage.add(this.gridLayer);
+    this.stage.add(this.dragLayer);
+    this.stage.add(this.mainLayer);
+    this.stage.add(this.infoPinLayer);
+    this.stage.add(this.textLayer);
+    this.setupEventListeners();
+  }
+
+  setupEventListeners() {
+    document.getElementById("shapeOptions").addEventListener("click", this.selectShape.bind(this));
+    document.getElementById("render-button").addEventListener("click", this.render.bind(this));
+    window.addEventListener("keydown", this.handleExitSelection.bind(this));
+    window.addEventListener("keydown", this.handleDelete.bind(this));
+    window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
+    window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
+    window.addEventListener("resize", this.handleResize.bind(this));
+    this.stage.on("mousedown touchstart", this.handleMouseDown.bind(this));
+    this.stage.on("mousemove touchmove", this.handleMouseMove.bind(this));
+    this.stage.on("mouseup touchend", this.handleMouseUp.bind(this));
+    this.stage.on("click tap", this.handleStageClick.bind(this));
+    this.stage.on("contextmenu", this.placeInfoPin.bind(this));
+    this.stage.on("dragmove", this.dragStage.bind(this));
+    this.stage.on("wheel", this.zoom.bind(this));
+  }
+
+  detachKeyPressEventListeners() {
+    window.removeEventListener("keydown", this.handleExitSelection.bind(this));
+    window.removeEventListener("keydown", this.handleDelete.bind(this));
+    window.removeEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
+    window.removeEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
+  }
+  attachKeyPressEventListeners() {
+    window.addEventListener("keydown", this.handleExitSelection.bind(this));
+    window.addEventListener("keydown", this.handleDelete.bind(this));
+    window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
+    window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
+  }
+
+  dragStage(e) {
+    if (!e.evt.shiftKey) return;
+    this.drawGrid();
+  }
+
+  transformerSnapFunc() {
+    return (oldPos, newPos) => {
+      const snapDistance = 8;
+
+      if (this.mainTransformer.getActiveAnchor() === "rotater") {
+        return newPos;
+      }
+
+      const distance = Math.sqrt(Math.pow(newPos.x - oldPos.x, 2) + Math.pow(newPos.y - oldPos.y, 2));
+
+      if (distance > snapDistance) {
+        return newPos;
+      }
+
+      const nextX = Math.round(newPos.x / this.blockSize) * this.blockSize;
+      const diffX = Math.abs(newPos.x - nextX);
+
+      const nextY = Math.round(newPos.y / this.blockSize) * this.blockSize;
+      const diffY = Math.abs(newPos.y - nextY);
+
+      const snapToX = diffX < snapDistance;
+      const snapToY = diffY < snapDistance;
+
+      if (snapToX && !snapToY) {
+        return {
+          x: nextX,
+          y: oldPos.y,
+        };
+      } else if (!snapToX && snapToY) {
+        return {
+          x: oldPos.x,
+          y: nextY,
+        };
+      } else if (snapToX && snapToY) {
+        return {
+          x: nextX,
+          y: nextY,
+        };
+      }
+
+      return newPos;
+    };
+  }
+
+  handleResize() {
+    this.stage.width(this.container.offsetWidth);
+    this.stage.height(this.container.offsetHeight);
+    this.drawGrid();
+  }
+
+  zoom(e) {
+   zoomStage(e,this.stage);
+   this.drawGrid();
+  }
+
+  drawGrid() {
+    this.gridLayer.destroyChildren();
+
+    let width = this.stage.width();
+    let height = this.stage.height();
+
+    //presmetka od globalen koordinaten sistem vo lokalen na canvasot
+    let transform = this.stage.getAbsoluteTransform().copy().invert();
+    let topLeft = transform.point({
+      x: 0,
+      y: 0,
+    });
+
+    let bottomRight = transform.point({
+      x: width,
+      y: height,
+    });
+
+    let startX = Math.floor(topLeft.x / this.blockSize) * this.blockSize;
+    let startY = Math.floor(topLeft.y / this.blockSize) * this.blockSize;
+
+    let endX = Math.ceil(bottomRight.x / this.blockSize) * this.blockSize;
+    let endY = Math.ceil(bottomRight.y / this.blockSize) * this.blockSize;
+
+    for (let x = startX; x <= endX; x += this.blockSize) {
+      let line = this.gridLine.clone({
+        points: [x + 0.5, topLeft.y - this.blockSize, x + 0.5, bottomRight.y + this.blockSize],
+      });
+
+      line.transformsEnabled("position");
+      line.perfectDrawEnabled(false);
+      line.shadowForStrokeEnabled(false);
+
+      this.gridLayer.add(line);
+    }
+
+    for (let y = startY; y <= endY; y += this.blockSize) {
+      let line = this.gridLine.clone({
+        points: [topLeft.x - this.blockSize, y + 0.5, bottomRight.x + this.blockSize, y + 0.5],
+      });
+
+      line.perfectDrawEnabled(false);
+      line.shadowForStrokeEnabled(false);
+      line.transformsEnabled("position");
+      this.gridLayer.add(line);
+    }
+
+    this.mainLayer.moveToTop();
+    this.infoPinLayer.moveToTop();
+
+    this.gridLayer.batchDraw();
+  }
+
+  placeInfoPin(e) {
+    e.evt.preventDefault();
+    let mousePos = this.stage.getRelativePointerPosition();
+    let infoPin = Factory.createShape("InfoPin", mousePos, this.blockSize, this.mainLayer, 0,1,1,true);
+    this.addModalHandling(infoPin);
+    this.shapes.push(infoPin);
+    this.mainLayer.add(infoPin)
+    infoPin.displayName(this.textLayer);
+    console.log(infoPin.name());
+  }
+
+  toggleEfficientDrawingMode(e) {
+    if (e.key === "e" || e.key === "E") {
+      this.efficientDrawingMode = !this.efficientDrawingMode;
+      console.log("EFFICIENT DRAWING MODE is: ", this.efficientDrawingMode);
+
+      if (!this.efficientDrawingMode) {
+        this.stopDrawing();
+      }
+    }
+  }
+
+  placeShape() {
+    const mousePos = this.stage.getRelativePointerPosition();
+    const placedObj = Factory.createShape(
+      this.hoverObj.type,
+      mousePos,
+      this.blockSize,
+      this.mainLayer,
+      this.hoverObj.rotation(),
+        1,
+        1,
+        true
+    );
+
+    if (!placedObj) return;
+
+    this.mainLayer.add(placedObj);
+    this.shapes.push(placedObj);
+    this.addModalHandling(placedObj);
+    this.mainLayer.draw();
+    placedObj.displayName(this.textLayer);
+    placedObj.snapToGrid();
+
+    if (!this.efficientDrawingMode) {
+      this.stopDrawing();
+    }
+  }
+
+  stopDrawing() {
+    this.mainTransformer.nodes([]);
+    this.hoverObj.remove();
+    this.dragLayer.removeChildren();
+    this.stage.off("mousemove", this.boundMouseMoveHandler);
+    this.stage.off("click", this.boundPlaceShapeHandler);
+  }
+
+  mouseMoveHandler() {
+    const mousePos = this.stage.getRelativePointerPosition();
+    this.hoverObj.position({ x: mousePos.x, y: mousePos.y });
+    this.hoverObj.visible(true);
+  }
+
+  startDrawing(shapeType) {
+    let pos = { x: 0, y: 0 };
+    this.hoverObj = Factory.createShape(shapeType, pos, this.blockSize, this.dragLayer, 0);
+
+    this.hoverObj.visible(false);
+    this.dragLayer.add(this.hoverObj);
+    this.dragLayer.moveToTop();
+    this.boundMouseMoveHandler = this.mouseMoveHandler.bind(this);
+    this.boundPlaceShapeHandler = this.placeShape.bind(this);
+
+    this.stage.on("mousemove", this.boundMouseMoveHandler);
+    this.stage.on("click", this.boundPlaceShapeHandler);
+  }
+
+  selectShape(e) {
+    if (e.target.tagName === "LI") {
+      const shapeType = e.target.getAttribute("data-info");
+      this.startDrawing(shapeType);
+      this.mainTransformer.nodes([]);
+    }
+  }
+
+  addModalHandling(shape) {
+    shape.on("dblclick", () => {
+      const eventName = shape.modalEventName;
+      if (eventName) {
+        const data = {
+          room: shape,
+          map: this,
+        };
+        const event = new CustomEvent(eventName, { detail: data });
+        window.dispatchEvent(event);
+      }
+    });
+  }
+
+  rotateShapesBy90Deg(e) {
+    if (e.key === "r" || e.key === "R") {
+      if (this.hoverObj) {
+        this.hoverObj.rotate(90);
+      }
+      this.mainTransformer.nodes().forEach((node) => {
+        node.rotate(90);
+      });
+    }
+  }
+
+  handleDelete(e) {
+    if (e.key === "Delete") {
+      this.mainTransformer.nodes().forEach((node) => {
+        node.remove();
+        this.shapes.splice(this.shapes.indexOf(node), 1);
+      });
+      this.mainTransformer.nodes([]);
+      this.mainLayer.batchDraw();
+    }
+  }
+
+  handleExitSelection(e) {
+    if (e.key === "Escape") {
+      this.mainTransformer.nodes([]);
+      this.stopDrawing();
+    }
+  }
+
+  handleMouseDown(e) {
+    this.stage.draggable(e.evt.shiftKey);
+
+    if (e.target !== this.stage) {
+      return;
+    }
+
+    e.evt.preventDefault();
+    this.x1 = this.stage.getRelativePointerPosition().x;
+    this.y1 = this.stage.getRelativePointerPosition().y;
+    this.x2 = this.stage.getRelativePointerPosition().x;
+    this.y2 = this.stage.getRelativePointerPosition().y;
+
+    this.selectionRectangle.width(0);
+    this.selectionRectangle.height(0);
+    this.selecting = true;
+  }
+
+  handleMouseMove(e) {
+    if (!this.selecting) {
+      return;
+    }
+    e.evt.preventDefault();
+    this.x2 = this.stage.getRelativePointerPosition().x;
+    this.y2 = this.stage.getRelativePointerPosition().y;
+
+    this.selectionRectangle.setAttrs({
+      visible: true,
+      x: Math.min(this.x1, this.x2),
+      y: Math.min(this.y1, this.y2),
+      width: Math.abs(this.x2 - this.x1),
+      height: Math.abs(this.y2 - this.y1),
+    });
+  }
+
+  handleMouseUp(e) {
+    this.selecting = false;
+    this.stage.draggable(false);
+
+    if (!this.selectionRectangle.visible()) {
+      return;
+    }
+
+    e.evt.preventDefault();
+    this.selectionRectangle.visible(false);
+    const shapes = this.stage.find(".mapObj");
+    const box = this.selectionRectangle.getClientRect();
+    const selected = shapes.filter((shape) => Konva.Util.haveIntersection(box, shape.getClientRect()));
+    this.mainTransformer.nodes(selected);
+    console.log(this.mainTransformer.nodes());
+  }
+
+  saveShapeDetails() {
+    this.shapes.forEach((room) => {
+      room.saveShapeDetails();
+      console.log(room.info);
+    });
+  }
+
+  async render() {
+    this.saveShapeDetails();
+    const httpService = new HttpService("http://localhost:8080/api/protected", true);
+    try {
+      const response = await httpService.post("/render", this.shapes);
+      console.log(response);
+    } catch (err) {
+      console.log("ERROR --> Could not render map --->", err);
+    }
+  }
+
+  async saveMap(mapName) {
+    this.saveShapeDetails();
+    const httpService = new HttpService("http://localhost:8080/api/protected/maps", true);
+    try {
+      const response = await httpService.put(`/save?mapName=${mapName}`, this.shapes);
+      console.log(response, "resp in builder");
+    } catch (err) {
+      console.log("ERROR --> Could not Save map --->", err);
+    }
+  }
+
+  handleStageClick(e) {
+    if (this.selectionRectangle.visible()) {
+      return;
+    }
+
+    if (e.target === this.stage) {
+      this.mainTransformer.nodes([]);
+      return;
+    }
+
+    if (!e.target.hasName("mapObj")) {
+      return;
+    }
+
+    const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
+    const isSelected = this.mainTransformer.nodes().indexOf(e.target) >= 0;
+
+    if (!metaPressed && !isSelected) {
+      this.mainTransformer.nodes([e.target]);
+      console.log("Sel 1");
+    } else if (metaPressed && isSelected) {
+      const nodes = this.mainTransformer.nodes().slice();
+      nodes.splice(nodes.indexOf(e.target), 1);
+      this.mainTransformer.nodes(nodes);
+    } else if (metaPressed && !isSelected) {
+      const nodes = this.mainTransformer.nodes().concat([e.target]);
+      this.mainTransformer.nodes(nodes);
+    }
+  }
+
+  addRoomType(roomType) {
+    this.roomTypes.push(roomType);
+  }
+
+  getRoomTypes() {
+    return this.roomTypes;
+  }
+
+  getRooms() {
+    return this.getShapeInfoByType("Room");
+  }
+
+  getPins() {
+    return this.getShapeInfoByType("InfoPin");
+  }
+
+  getEntrances() {
+    return this.getShapeInfoByType("Entrance");
+  }
+
+  getConnections() {
+    const pins = this.getShapeInfoByType("InfoPin");
+    const entrances = this.getShapeInfoByType("Entrance");
+    return [...pins, ...entrances];
+  }
+
+  getShapeInfoByType(type) {
+    return this.shapes.filter((shape) => shape.className === type).map((shape) => shape.info);
+  }
+
+  updateConnections() {
+    console.log("Update");
+
+    this.shapes.forEach((shape) => {
+      if (shape.className === "InfoPin" || shape.className === "Entrance") {
+        shape.info.selectedPins.forEach((connectedShapeName) => {
+          const connectedShape = this.shapes.find((s) => s.info.name === connectedShapeName);
+          if (
+            connectedShape &&
+            (connectedShape.className === "InfoPin" || connectedShape.className === "Entrance")
+          ) {
+            if (!connectedShape.info.selectedPins.includes(shape.info.name)) {
+              connectedShape.info.selectedPins.push(shape.info.name);
+            }
+          }
         });
-
-        // TODO AKO DRAGNIT NEKOJ OD POCETOK NA STAGE POZICIIVE KE SA ZEZNAT
-        // TODO placed shape i mouseMoveHandler da ne callback ( da ne vrakjat funkcija)
-        // TODO text na top layer sekogas
-
-        this._floorNum = floorNum;
-        this.mapName = mapName;
-
-        this.gridLayer = new Konva.Layer();
-        this.mainLayer = new Konva.Layer();
-        this.dragLayer = new Konva.Layer();
-        this.infoPinLayer = new Konva.Layer();
-        this.prioLayer = new Konva.Layer();
-        this.textLayer = new Konva.Layer();
-        this.gridLayer.listening(false);
-
-        this.isDrawEventBound = false;
-
-
-        this.othStairs = [];
-
-        this.blockSize = 10;
-        this.efficientDrawingMode = false;
-        this.roomTypes = [];
-
-        this.gridLine = new Konva.Line({
-            points: [],
-            stroke: "grey",
-            strokeWidth: 1,
-            opacity: 0.3,
-        });
-
-        this.gridLine.cache();
-
-        this.mainTransformer = new Konva.Transformer({
-            centeredScaling: false,
-            rotationSnaps: [0, 90, 180, 270],
-            anchorSize: 5,
-            padding: 2,
-            anchorFill: "#f6031f",
-            borderStroke: "black",
-            anchorStroke: "black",
-            cornerRadius: 20,
-            anchorCornerRadius: 10,
-            anchorDragBoundFunc: this.transformerSnapFunc(),
-        });
-
-        this.selectionRectangle = new Konva.Rect({
-            fill: "rgba(56,194,245,0.5)",
-            visible: false,
-            listening: false,
-            zIndex: 100,
-        });
-
-        this.x1 = 0;
-        this.y1 = 0;
-        this.x2 = 0;
-        this.y2 = 0;
-
-        this.selecting = false;
-
-        this.initialize();
-    }
-
-    initialize() {
-        this.drawGrid();
-        this.mainLayer.add(this.mainTransformer);
-        this.mainLayer.add(this.selectionRectangle);
-        this.stage.add(this.gridLayer);
-        this.stage.add(this.dragLayer);
-        this.stage.add(this.mainLayer);
-        this.stage.add(this.infoPinLayer);
-        this.stage.add(this.textLayer);
-        this.setupEventListeners();
-    }
-
-    setupEventListeners() {
-        document.getElementById("shapeOptions").addEventListener("click", this.selectShape.bind(this));
-        // window.addEventListener("keydown", this.handleExitSelection.bind(this));
-        // window.addEventListener("keydown", this.handleDelete.bind(this));
-        // window.addEventListener("keydown", this.rotateShapesBy90Deg.bind(this));
-        // window.addEventListener("keydown", this.toggleEfficientDrawingMode.bind(this));
-        window.addEventListener("resize", this.handleResize.bind(this));
-
-        this.boundEscapeEventListener = this.handleExitSelection.bind(this);
-        this.boundDeleteEventListener = this.handleDelete.bind(this);
-        this.boundRotateShapeEventListener = this.rotateShapesBy90Deg.bind(this)
-        this.boundEfficientDrawingModeEventListener = this.toggleEfficientDrawingMode.bind(this);
-
-        this.attachKeyPressEventListeners();
-
-        this.stage.on("mousedown touchstart", this.handleMouseDown.bind(this));
-        this.stage.on("mousemove touchmove", this.handleMouseMove.bind(this));
-        this.stage.on("mouseup touchend", this.handleMouseUp.bind(this));
-        this.stage.on("click tap", this.handleStageClick.bind(this));
-        this.stage.on("contextmenu", this.placeInfoPin.bind(this));
-        this.stage.on("dragmove", this.dragStage.bind(this));
-        this.stage.on("wheel", this.zoom.bind(this));
-    }
-
-    detachKeyPressEventListeners() {
-        console.log("DETACH")
-        window.removeEventListener("keydown", this.boundEscapeEventListener);
-        window.removeEventListener("keydown", this.boundDeleteEventListener);
-        window.removeEventListener("keydown", this.boundRotateShapeEventListener);
-        window.removeEventListener("keydown", this.boundEfficientDrawingModeEventListener);
-    }
-
-    attachKeyPressEventListeners() {
-        console.log("ATTACH")
-        window.addEventListener("keydown", this.boundEscapeEventListener);
-        window.addEventListener("keydown", this.boundDeleteEventListener);
-        window.addEventListener("keydown", this.boundRotateShapeEventListener);
-        window.addEventListener("keydown", this.boundEfficientDrawingModeEventListener);
-    }
-
-    dragStage(e) {
-        if (!e.evt.shiftKey) return;
-        this.drawGrid();
-    }
-
-    transformerSnapFunc() {
-        return (oldPos, newPos) => {
-            const snapDistance = 8;
-
-            if (this.mainTransformer.getActiveAnchor() === "rotater") {
-                return newPos;
-            }
-
-            const distance = Math.sqrt(Math.pow(newPos.x - oldPos.x, 2) + Math.pow(newPos.y - oldPos.y, 2));
-
-            if (distance > snapDistance) {
-                return newPos;
-            }
-
-            const nextX = Math.round(newPos.x / this.blockSize) * this.blockSize;
-            const diffX = Math.abs(newPos.x - nextX);
-
-            const nextY = Math.round(newPos.y / this.blockSize) * this.blockSize;
-            const diffY = Math.abs(newPos.y - nextY);
-
-            const snapToX = diffX < snapDistance;
-            const snapToY = diffY < snapDistance;
-
-            if (snapToX && !snapToY) {
-                return {
-                    x: nextX,
-                    y: oldPos.y,
-                };
-            } else if (!snapToX && snapToY) {
-                return {
-                    x: oldPos.x,
-                    y: nextY,
-                };
-            } else if (snapToX && snapToY) {
-                return {
-                    x: nextX,
-                    y: nextY,
-                };
-            }
-
-            return newPos;
-        };
-    }
-
-    handleResize() {
-        this.stage.width(this.container.offsetWidth);
-        this.stage.height(this.container.offsetHeight);
-        this.drawGrid();
-    }
-
-    zoom(e) {
-        zoomStage(e, this.stage, true);
-        this.drawGrid();
-    }
-
-    get floorNum(){
-        return this._floorNum;
-    }
-
-    set floorNum(val){
-        this._floorNum = val;
-    }
-
-    drawGrid() {
-        this.gridLayer.destroyChildren();
-
-        let width = this.stage.width();
-        let height = this.stage.height();
-
-        //presmetka od globalen koordinaten sistem vo lokalen na canvasot
-        let transform = this.stage.getAbsoluteTransform().copy().invert();
-        let topLeft = transform.point({
-            x: 0,
-            y: 0,
-        });
-
-        let bottomRight = transform.point({
-            x: width,
-            y: height,
-        });
-
-        let startX = Math.floor(topLeft.x / this.blockSize) * this.blockSize;
-        let startY = Math.floor(topLeft.y / this.blockSize) * this.blockSize;
-
-        let endX = Math.ceil(bottomRight.x / this.blockSize) * this.blockSize;
-        let endY = Math.ceil(bottomRight.y / this.blockSize) * this.blockSize;
-
-        for (let x = startX; x <= endX; x += this.blockSize) {
-            let line = this.gridLine.clone({
-                points: [x + 0.5, topLeft.y - this.blockSize, x + 0.5, bottomRight.y + this.blockSize],
-            });
-
-            line.transformsEnabled("position");
-            line.perfectDrawEnabled(false);
-            line.shadowForStrokeEnabled(false);
-
-            this.gridLayer.add(line);
-        }
-
-        for (let y = startY; y <= endY; y += this.blockSize) {
-            let line = this.gridLine.clone({
-                points: [topLeft.x - this.blockSize, y + 0.5, bottomRight.x + this.blockSize, y + 0.5],
-            });
-
-            line.perfectDrawEnabled(false);
-            line.shadowForStrokeEnabled(false);
-            line.transformsEnabled("position");
-            this.gridLayer.add(line);
-        }
-
-        this.mainLayer.moveToTop();
-        this.infoPinLayer.moveToTop();
-
-        this.gridLayer.batchDraw();
-    }
-
-    placeInfoPin(e) {
-        e.evt.preventDefault();
-        let mousePos = this.stage.getRelativePointerPosition();
-        const attrs = {
-            type: "InfoPin",
-            position: mousePos,
-            blockSize: this.blockSize,
-            layer: this.mainLayer,
-            rotation: 0,
-            scaleX: 1,
-            scaleY: 1,
-            increment: true,
-            floorNum: this.floorNum
-        };
-        let infoPin = Factory.createShape("InfoPin", attrs);
-        addEventHandling(infoPin, this, "dblclick");
-        ShapeRegistry.add(infoPin)
-        this.mainLayer.add(infoPin);
-        infoPin.displayName(this.textLayer);
-        triggerMapSave()
-
-        console.log(infoPin.name());
-    }
-
-    toggleEfficientDrawingMode(e) {
-        if (e.key === "e" || e.key === "E") {
-            this.efficientDrawingMode = !this.efficientDrawingMode;
-            console.log("EFFICIENT DRAWING MODE is: ", this.efficientDrawingMode);
-
-            if (!this.efficientDrawingMode) {
-                this.stopDrawing();
-            }
-        }
-    }
-
-    placeShape() {
-        const mousePos = this.stage.getRelativePointerPosition();
-        const attrs = {
-            position: mousePos,
-            width: this.blockSize,
-            height: this.blockSize,
-            layer: this.mainLayer,
-            rotation: this.hoverObj.rotation(),
-            scaleX: 1,
-            scaleY: 1,
-            increment: true,
-            snap: true,
-            fromLoad: false,
-            blockSize: this.blockSize,
-            floorNum: this.floorNum
-        };
-
-        const placedObj = Factory.createShape(this.hoverObj.type, attrs);
-
-        if (!placedObj) return;
-
-        console.info("ATTRS FNUM",attrs.floorNum)
-
-        this.mainLayer.add(placedObj);
-        ShapeRegistry.add(placedObj);
-        addEventHandling(placedObj, this, "dblclick");
-        this.mainLayer.draw();
-        // site ovie func da se vo edna funkcija vo shape.
-
-        placedObj.displayName(this.textLayer);
-        placedObj.snapToGrid();
-        placedObj.onPlace();
-
-        triggerMapSave();
-
-        if (!this.efficientDrawingMode) {
-            this.stopDrawing();
-        }
-        this.mainTransformer.nodes([])
-    }
-
-    stopDrawing() {
-        if(this.isDrawEventBound){
-            this.mainTransformer.nodes([]);
-            if (this.hoverObj != null) this.hoverObj.remove();
-            this.dragLayer.removeChildren();
-            this.stage.off("mousemove", this.boundMouseMoveHandler);
-            this.stage.off("click", this.boundPlaceShapeHandler);
-            this.isDrawEventBound = false;
-        }
-
-    }
-
-    mouseMoveHandler() {
-        const mousePos = this.stage.getRelativePointerPosition();
-        this.hoverObj.position({x: mousePos.x, y: mousePos.y});
-        this.hoverObj.visible(true);
-    }
-
-    startDrawing(shapeType) {
-        const attrs = {
-            position: {x: 0, y: 0},
-            width: this.blockSize,
-            height: this.blockSize,
-            layer: this.mainLayer,
-            rotation: 0,
-            scaleX: 1,
-            scaleY: 1,
-            increment: false,
-            snap: true,
-            fromLoad: false,
-            blockSize: this.blockSize
-        };
-        this.hoverObj = Factory.createShape(shapeType, attrs);
-
-        console.log("HOVBER OBK:", this.hoverObj)
-
-        this.hoverObj.visible(false);
-        this.dragLayer.add(this.hoverObj);
-        this.dragLayer.moveToTop();
-
-
-        this.boundMouseMoveHandler = this.mouseMoveHandler.bind(this);
-        this.boundPlaceShapeHandler = this.placeShape.bind(this);
-        this.isDrawEventBound = true;
-
-        this.stage.on("mousemove", this.boundMouseMoveHandler);
-        this.stage.on("click", this.boundPlaceShapeHandler);
-    }
-
-    selectShape(e) {
-        if (e.target.tagName === "LI") {
-          this.stopDrawing()
-            const shapeType = e.target.getAttribute("data-info");
-            this.startDrawing(shapeType);
-            this.mainTransformer.nodes([])
-        }
-    }
-
-    rotateShapesBy90Deg(e) {
-        if (e.key === "r" || e.key === "R") {
-            if (this.hoverObj) {
-                this.hoverObj.rotate(90);
-            }
-            this.mainTransformer.nodes().forEach((node) => {
-                node.rotate(90);
-            });
-        }
-    }
-
-    handleDelete(e) {
-        if (e.key === "Delete") {
-            this.mainTransformer.nodes().forEach((node) => {
-                node.remove();
-                node.destroy();
-                ShapeRegistry.delete(node);
-                triggerMapSave();
-            });
-            this.mainTransformer.nodes([]);
-            this.mainLayer.batchDraw();
-        }
-    }
-
-    handleExitSelection(e) {
-        if (e.key === "Escape") {
-            this.mainTransformer.nodes([]);
-            this.stopDrawing();
-        }
-    }
-
-    handleMouseDown(e) {
-        this.stage.draggable(e.evt.shiftKey);
-
-        if (e.target !== this.stage) {
-            return;
-        }
-
-        e.evt.preventDefault();
-        this.x1 = this.stage.getRelativePointerPosition().x;
-        this.y1 = this.stage.getRelativePointerPosition().y;
-        this.x2 = this.stage.getRelativePointerPosition().x;
-        this.y2 = this.stage.getRelativePointerPosition().y;
-
-        this.selectionRectangle.width(0);
-        this.selectionRectangle.height(0);
-        this.selecting = true;
-    }
-
-    handleMouseMove(e) {
-        if (!this.selecting) {
-            return;
-        }
-        e.evt.preventDefault();
-        this.x2 = this.stage.getRelativePointerPosition().x;
-        this.y2 = this.stage.getRelativePointerPosition().y;
-
-        this.selectionRectangle.setAttrs({
-            visible: true,
-            x: Math.min(this.x1, this.x2),
-            y: Math.min(this.y1, this.y2),
-            width: Math.abs(this.x2 - this.x1),
-            height: Math.abs(this.y2 - this.y1),
-        });
-    }
-
-    handleMouseUp(e) {
-        this.selecting = false;
-        this.stage.draggable(false);
-
-        if (!this.selectionRectangle.visible()) {
-            return;
-        }
-
-        e.evt.preventDefault();
-        this.selectionRectangle.visible(false);
-        const shapes = this.stage.find(".mapObj");
-        const box = this.selectionRectangle.getClientRect();
-        const selected = shapes.filter((shape) => Konva.Util.haveIntersection(box, shape.getClientRect()));
-        this.mainTransformer.nodes(selected);
-        console.log(this.mainTransformer.nodes());
-    }
-
-    saveShapeDetails() {
-        ShapeRegistry.saveDetails();
-        console.log("thisflornum",this.floorNum)
-        return  {
-            shapes: ShapeRegistry.getShapes(this.floorNum),
-            roomTypes: JSON.stringify(this.roomTypes),
-            mapName: this.mapName,
-            floorNum: this.floorNum
-        }
-    }
-
-
-
-    handleStageClick(e) {
-        if (this.selectionRectangle.visible()) {
-            console.log("STAGECLICK1")
-            return;
-        }
-
-        if (e.target === this.stage) {
-            console.log("STAGECLICK2")
-            this.mainTransformer.nodes([]);
-            return;
-        }
-
-        if (!e.target.hasName("mapObj")) {
-            console.log("STAGECLICK3")
-            return;
-        }
-
-        const metaPressed = e.evt.shiftKey || e.evt.ctrlKey || e.evt.metaKey;
-        const isSelected = this.mainTransformer.nodes().indexOf(e.target) >= 0;
-
-
-        if (!metaPressed && !isSelected) {
-            this.mainTransformer.nodes([e.target]);
-            console.log("Sel 1");
-        } else if (metaPressed && isSelected) {
-            const nodes = this.mainTransformer.nodes().slice();
-            nodes.splice(nodes.indexOf(e.target), 1);
-            this.mainTransformer.nodes(nodes);
-        } else if (metaPressed && !isSelected) {
-            const nodes = this.mainTransformer.nodes().concat([e.target]);
-            this.mainTransformer.nodes(nodes);
-        }
-    }
-
-    addRoomType(type) {
-        this.roomTypes.push(type);
-    }
-
-    removeRoomType(targetType) {
-        this.roomTypes = this.roomTypes.filter(type => type !== targetType);
-    }
-
-
-    drawConnection(node1Name, node2Name) {
-
-        ShapeRegistry.drawConnection(node1Name,node2Name);
-    }
-
-    removeConnection(from, to) {
-        ShapeRegistry.removeConnection(from,to);
-    }
-
-    updateRoomNames() {
-        this.textLayer.removeChildren();
-        ShapeRegistry.getShapes(this.floorNum).forEach((shape) => {
-            shape.displayName(this.textLayer);
-        });
-
-    }
-
-
-    clearMap() {
-        this.mainLayer.removeChildren();
-        this.hoverObj = null;
-    }
-
-
-    // ova  klasa i map display da nasledbat od glavna klasa
-
-    loadNewFloor(floor) {
-
-        this._floorNum = floor?.num;
-        let data = floor?.mapData;
-
-        if (data == null || data === "") return;
-
-        this.deserializeMap(data);
-        shapeRegistry.getShapes(this.floorNum).forEach((shape) => {
-            this.mainLayer.add(shape);
-        });
-
-
-    }
-
-    //nov
-    deserializeMap(data) {
-        console.log("DESERIALIZING: ", data);
-        ShapeRegistry.clear(this.floorNum);
-
-        if (data != null) {
-            const dsrData = JSON.parse(data);
-            //load shapes
-            dsrData.forEach((shape) => {
-                const attrs = {
-                    position: {x: shape.attrs.x, y: shape.attrs.y},
-                    width: shape.attrs.width,
-                    height: shape.attrs.height,
-                    layer: this.mainLayer,
-                    blockSize: this.blockSize,
-                    rotation: shape.attrs.rotation,
-                    scaleX: shape.attrs.scaleX,
-                    scaleY: shape.attrs.scaleY,
-                    increment: false,
-                    snap: true,
-                    fromLoad: true,
-                    floorNum: this.floorNum
-                };
-
-                const loadedShape = Factory.createShape(shape.className, attrs);
-                loadedShape.loadInfo(shape.attrs);
-                ShapeRegistry.add(loadedShape);
-                // na destroy trebit events da sa trgnat
-                addEventHandling(loadedShape, this, "dblclick");
-            });
-            let nodes = ShapeRegistry.getShapes(this.floorNum).filter((shape) => shape.className === "InfoPin" || shape.className === "Entrance" || shape.className === "Stairs");
-            nodes.forEach((pin) => {
-                let connectedPins = pin.info.selectedPins;
-                if (connectedPins) {
-                    connectedPins.forEach((slPin) => {
-                        console.log("CONN node1: " + pin + "conn node2: " + slPin)
-                        this.drawConnection(pin.info.name, slPin);
-                    });
-                }
-            });
-        }
-
-        this.mainTransformer.nodes([]);
-        this.mainLayer.add(this.mainTransformer);
-        this.mainLayer.add(this.selectionRectangle);
-
-        ShapeRegistry.getShapes(this.floorNum).forEach((shape) => {
-            shape.displayName(this.textLayer);
-            if(shape.className === "Entrance"){
-                shape.setHighlight();
-            }
-        });
-    }
-
+      }
+    });
+  }
+
+  removeConnection(from, to) {
+    this.shapes
+      .filter((s) => s.info.name === from || s.info.name === to)
+      .forEach((s) => {
+        s.info.selectedPins = s.info.selectedPins.filter((pin) => pin !== from && pin !== to);
+      });
+    console.log("Remove");
+  }
+
+  updateRoomNames() {
+    this.textLayer.removeChildren();
+    this.shapes.forEach((shape) => {
+      shape.displayName(this.textLayer);
+    });
+    this.textLayer.children.forEach((child) => console.log(child));
+  }
+
+  clearMap() {
+    this.mainLayer.removeChildren();
+    this.shapes = [];
+    this.hoverObj = null;
+  }
+
+  deserializeMap(data) {
+    console.log("DESERIALIZING: ", data);
+    this.clearMap();
+    let dsrData = JSON.parse(data);
+    dsrData.forEach((child) => {
+      const shape = JSON.parse(child);
+      const loadedShape = Factory.createShape(
+        shape.className,
+        { x: shape.attrs.x, y: shape.attrs.y },
+        this.blockSize,
+        this.mainLayer,
+        shape.attrs.rotation,
+          shape.attrs.scaleX,
+          shape.attrs.scaleY
+      );
+      loadedShape.loadInfo(shape.attrs);
+      this.shapes.push(loadedShape);
+      this.addModalHandling(loadedShape);
+      this.mainLayer.add(loadedShape);
+    });
+    this.mainTransformer.nodes([]);
+    this.mainLayer.add(this.mainTransformer);
+    this.mainLayer.add(this.selectionRectangle);
+
+    this.shapes.forEach((shape) => shape.displayName(this.textLayer));
+  }
 }
Index: imaps-frontend/src/scripts/main/MapDisplay.js
===================================================================
--- imaps-frontend/src/scripts/main/MapDisplay.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/main/MapDisplay.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -3,314 +3,121 @@
 import HttpService from "../net/HttpService.js";
 import {zoomStage} from "../util/zoomStage.js";
-import {addEventHandling} from "../util/addEventHandling.js";
-import ShapeRegistry from "../util/ShapeRegistry.js";
-import triggerNavigate from "../util/triggerNavigate.js";
-import config from "../net/netconfig.js";
-import {dispatchCustomEvent} from "../util/dispatchCustomEvent.js";
-import { jsPDF } from "jspdf";
+export class MapDisplay {
+  constructor(containerId) {
+    this.container = document.getElementById(containerId);
+    this.containerId = containerId;
+    this.stage = new Konva.Stage({
+      container: containerId,
+      width: window.innerWidth,
+      height: window.innerHeight,
+      draggable: true,
+    });
+
+    this.shapes = [];
+    this.loaded = false;
+    this.mainLayer = new Konva.Layer();
+    this.routeLayer = new Konva.Layer();
+    this.textLayer = new Konva.Layer();
+    this.stage.add(this.mainLayer);
+    this.stage.add(this.routeLayer);
+    this.stage.add(this.textLayer);
+    this.route = new Konva.Line();
+
+    this.stage.on("resize", () => {
+      this.stage.width = window.innerWidth;
+      this.stage.height = window.innerHeight;
+    });
+
+    this.stage.on("wheel",(e) => {
+        zoomStage(e,this.stage);
+    })
+
+   
+  }
+
+  deserializeMap(data) {
+    data.forEach((child) => {
+        const shape = JSON.parse(child);
+        if (shape.className !== "InfoPin") {
+            const renderedShape = Factory.createRenderedShape(
+                shape.className,
+                shape.attrs
+            );
+            this.shapes.push(renderedShape);
+      }
+    });
+  }
+
+  displayRoomNames(){
+    console.log("VLEZE")
+    this.shapes.forEach(shape => {
+      shape.displayName(this.textLayer);
+    })
+
+    this.textLayer.children.forEach(child => console.log(child,"DECAAA"));
+  }
+
+  async loadMap() {
+    const httpService = new HttpService();
+    const mapData = await httpService.get("/public/mapData");
+    console.log("DESERIALIZED --->",mapData);
+    this.deserializeMap(mapData);
+    this.shapes.forEach((shape) => {
+      this.mainLayer.add(shape);
+    });
+    this.displayRoomNames();
+  }
+
+  drawRoute(path) {
+    this.routeLayer.removeChildren();
+    console.log("====PATH====");
+    path.forEach((point) => console.log(point.x, point.y));
+
+    const pointsArray = path.flatMap((point) => [point.x, point.y]);
+
+    console.log(pointsArray, "POINTS");
+
+    let buff = [];
+    let count = 0;
+    let index = 0;
+
+    const drawNextSegment = () => {
+        if (index >= pointsArray.length) return;
+
+        buff.push(pointsArray[index]);
+        count++;
+
+        if (count % 4 === 0) {
+            const line = new Konva.Arrow({
+                points: buff,
+                stroke: "#e91332",
+                strokeWidth: 2.5,
+                dash: [5, 4],
+                lineCap: 'round',
+                lineJoin: 'round',
+                pointerLength: 7,
+                pointerWidth: 7,
+                fill:'red',
+            });
+
+            this.routeLayer.add(line);
+            this.routeLayer.draw(); 
+
+            console.log(buff, "BUFFER");
+            buff = []; 
+            index -= 2; 
+        }
+
+        index++;
+
+        setTimeout(drawNextSegment, 25); 
+    };
+
+    drawNextSegment(); 
+}
 
 
-export class MapDisplay {
-    constructor(containerId, floorNum) {
-        this.container = document.getElementById(containerId);
-        this.containerId = containerId;
-        this.stage = new Konva.Stage({
-            container: containerId,
-            width: window.innerWidth,
-            height: window.innerHeight,
-            draggable: true,
-        });
-
-        this.selectedRoom = {
-            id: 1,
-            name: "223",
-            type: "Laboratory",
-            image:
-                "data:image/jpeg;base64,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",
-            description: "223 is a laboratory with a capacity of 40 people",
-        };
-        this.toggleSearch = false;
-
-        this.shapes = [];
-        this.roomTypes = [];
-        this.loaded = false;
-        this.mainLayer = new Konva.Layer();
-        this.routeLayer = new Konva.Layer();
-        this.textLayer = new Konva.Layer();
-        this.stage.add(this.mainLayer);
-        this.stage.add(this.routeLayer);
-        this.stage.add(this.textLayer);
-
-
-        this.cachedCanvases = [];
-
-        this.floorNum = floorNum;
-
-        this.navArrow = new Konva.Arrow({
-            stroke: "#bb0000",
-            strokeWidth: 3,
-            dash: [12, 7],
-            lineCap: "round",
-            tension: 10,
-            pointerLength: 2,
-            pointerWidth: 3,
-        });
-
-        this.navArrow.cache();
-
-        this.stage.on("resize", () => {
-            this.stage.width = window.innerWidth;
-            this.stage.height = window.innerHeight;
-        });
-
-        this.stage.on("wheel", (e) => {
-            zoomStage(e, this.stage);
-        });
-    }
-
-    clearMap() {
-        this.mainLayer.removeChildren();
-        this.shapes.forEach(shape => shape.clearText())
-        this.shapes = [];
-    }
-
-    deserializeMap(data) {
-        this.clearMap();
-
-        let dsrData = JSON.parse(data);
-        dsrData.forEach((shape) => {
-            if (shape.className !== "InfoPin") {
-                console.log("SHAPE ATTRS CREATE: " + JSON.stringify(shape.attrs));
-                const renderedShape = Factory.createRenderedShape(shape.className, shape.attrs);
-                addEventHandling(renderedShape, this, "click");
-                this.shapes.push(renderedShape);
-                console.log(renderedShape)
-            }
-        });
-    }
-
-    displayRoomNames() {
-        this.shapes.forEach((shape) => {
-            shape.displayName(this.textLayer);
-        });
-
-    }
-
-    loadMapN(floorData) {
-        if (floorData == null || floorData === "") return;
-
-        this.deserializeMap(floorData);
-        this.shapes.forEach((shape) => {
-            this.mainLayer.add(shape);
-        });
-        this.displayRoomNames();
-        this.initializeRoomTypes();
-
-    }
-
-    clearRoute() {
-        this.routeLayer.removeChildren();
-    }
-
-
-
-    drawRouteNEW(nodes, offset = 0) {
-
-        this.clearRoute();
-        console.log("====PATH====");
-        nodes.forEach((node) => console.log("NODE", node));
-
-        let idx = offset;
-        let buff = [nodes[idx].coordinates.x, nodes[idx].coordinates.y];
-
-        ++idx;
-
-        console.log("INIT BUFFER", buff);
-        console.log("INIT IDX", idx);
-
-        const drawNextSegment = () => {
-
-            if (idx >= nodes.length){
-                console.log("FLOOR NUM DISPLAY: " + this.floorNum)
-                let stageInfo = {stage:this.stage.clone(),floor:this.floorNum};
-                this.cachedCanvases.push(stageInfo);
-                dispatchCustomEvent("navend",this.downloadURI)
-                return;
-            }
-
-            const currentNode = nodes[idx - 1];
-            const nextNode = nodes[idx];
-
-            if (nextNode.floorNumber !== currentNode.floorNumber) {
-                let stageInfo = {stage:this.stage.clone(),floor:this.floorNum};
-                this.cachedCanvases.push(stageInfo);
-                triggerNavigate(nodes, idx, nextNode.floorNumber, nextNode);
-                return;
-            }
-
-            const startX = currentNode.coordinates.x;
-            const startY = currentNode.coordinates.y;
-            const endX = nextNode.coordinates.x;
-            const endY = nextNode.coordinates.y;
-
-            const numSegments = 10;
-
-            const deltaX = (endX - startX) / numSegments;
-            const deltaY = (endY - startY) / numSegments;
-
-            const drawSegment = (i) => {
-                const segmentX = startX + deltaX * i;
-                const segmentY = startY + deltaY * i;
-
-                buff.push(segmentX, segmentY);
-
-                let line = this.navArrow.clone({ points: [...buff] });
-                this.routeLayer.add(line);
-                this.routeLayer.draw();
-
-                buff = [segmentX, segmentY];
-            };
-
-            let segmentIdx = 1;
-            const interval = setInterval(() => {
-                drawSegment(segmentIdx);
-                segmentIdx++;
-
-                if (segmentIdx > numSegments) {
-                    clearInterval(interval);
-                    idx++;
-                    setTimeout(drawNextSegment, 60);
-                }
-            }, 30);
-        };
-
-        drawNextSegment();
-    }
-
-    initializeRoomTypes() {
-        this.roomTypes = this.shapes
-            .filter((shape) => shape.class === "Room" && shape.info.type !== "")
-            .map((shape) => shape.info.type);
-    }
-
-    getShapeByType(type) {
-        return this.shapes.filter((shape) => shape.class === type)
-    }
-
-    //ova e loso ne trebit vaka
-    highlightShape(roomName) {
-        let foundShape = this.shapes.filter((shape) => shape.info.name === roomName)[0];
-        foundShape.highlight();
-    }
-
-     downloadURI(uri, name) {
-        let link = document.createElement('a');
-        link.download = name;
-        link.href = uri;
-        document.body.appendChild(link);
-        link.click();
-        document.body.removeChild(link);
-    }
-
-
-    getRouteImages(mapDetails = { mapName: "mapName", from: "from", to: "to" }) {
-
-        const pdf = new jsPDF("p", "mm", "a4");
-        const pageWidth = pdf.internal.pageSize.getWidth();
-        const pageHeight = pdf.internal.pageSize.getHeight();
-        const margin = 10;
-        let yOffset = margin;
-
-        const imagesData = [];
-
-        let minWidth = 800;
-
-        this.cachedCanvases.forEach((canvas, index) => {
-            console.log("CANVASL " + JSON.stringify(canvas.stage))
-            let dsrStage = Konva.Node.create(canvas.stage, document.createElement("div"));
-
-            let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
-
-            dsrStage.getLayers().forEach(layer => {
-                layer.getChildren().forEach(shape => {
-                    const shapeX = shape.x();
-                    const shapeY = shape.y();
-                    const width = shape.width() * shape.scaleX();
-                    const height = shape.height() * shape.scaleY();
-
-                    minX = Math.min(minX, shapeX - shape.offsetX() * shape.scaleX());
-                    minY = Math.min(minY, shapeY - shape.offsetY() * shape.scaleY());
-                    maxX = Math.max(maxX, shapeX + width - shape.offsetX() * shape.scaleX());
-                    maxY = Math.max(maxY, shapeY + height - shape.offsetY() * shape.scaleY());
-                });
-            });
-
-            let padding = 50;
-
-            const virtualWidth = maxX - minX + padding;
-            const virtualHeight = maxY - minY + padding;
-
-            const scaleDownFactor = Math.min(pageWidth / virtualWidth, pageHeight / virtualHeight);
-
-            dsrStage.size({ width: virtualWidth, height: virtualHeight });
-            dsrStage.position({ x: -minX, y: -minY });
-            dsrStage.batchDraw();
-
-            let canvasImageURI = dsrStage.toDataURL({
-                pixelRatio: 1
-            });
-
-            imagesData.push(canvasImageURI);
-            console.log(`Generated Image ${index + 1}`);
-        });
-
-
-
-        imagesData.forEach((imageURI, index) => {
-            const text = `Floor: ${this.cachedCanvases[index].floor}`;
-            pdf.text(text, margin, yOffset + 5);
-
-            const img = new Image();
-            img.src = imageURI;
-
-            const maxWidth = pageWidth - 2 * margin;
-            const maxHeight = pageHeight - 2 * margin;
-            let imgWidth = maxWidth;
-            let imgHeight = maxHeight / 2
-
-            if (imgHeight > maxHeight) {
-                imgHeight = maxHeight;
-                imgWidth = (pageWidth * maxHeight) / pageHeight;
-            }
-
-            if (yOffset + imgHeight > pageHeight - margin) {
-                pdf.addPage();
-                yOffset = margin;
-            }
-
-            pdf.addImage(imageURI, "PNG", margin, yOffset, imgWidth, imgHeight);
-            yOffset += imgHeight + 10;
-        });
-
-        pdf.save(`${mapDetails.mapName}-${mapDetails.from}-->${mapDetails.to}.route.pdf`);
-    }
-
-
-
-setFilter(filter) {
-        let rooms = this.getShapeByType("Room")
-        if (filter === "All") {
-            rooms.forEach((shape) => {
-                shape.unHighlight()
-            })
-        } else {
-            rooms.filter((shape) => shape.info.type === filter).forEach((shape) => {
-                shape.highlight()
-            })
-            rooms.filter((shape) => shape.info.type !== filter).forEach((shape) => {
-                shape.unHighlight()
-            })
-        }
-
-    }
+  search() {
+    console.log("VLEZE VO SEARCH");
+  }
 }
Index: imaps-frontend/src/scripts/net/HttpService.js
===================================================================
--- imaps-frontend/src/scripts/net/HttpService.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/net/HttpService.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -3,7 +3,7 @@
 
 class HttpService {
-    constructor(auth = false) {
+    constructor(URL = config.apiBaseUrl, auth = false) {
+      this.baseURL = URL;
       this.auth = auth;
-      this.responseType = 'json';
     }
 
@@ -11,14 +11,4 @@
         this.auth = true;
     }
-    setResponseType(type){
-        if(type === 'text'){
-            this.responseType = 'text';
-        } else if (type === 'json'){
-            this.responseType = 'json'
-        } else {
-            console.error('unsupported response type in http service')
-        }
-    }
-
 
     async request(method, endpoint, data = null) {
@@ -43,5 +33,5 @@
       }
   
-      const response = await fetch(`${endpoint}`, options);
+      const response = await fetch(`${this.baseURL}${endpoint}`, options);
       
       if (!response.ok) {
@@ -64,12 +54,6 @@
 
       console.log("HTTPSERVICE: RESPONSE:",response);
-
-      if(this.responseType === 'json'){
-          return response.json();
-      } else if (this.responseType === 'text'){
-          return response.text()
-      } else{
-          console.error('bad resp type')
-      }
+  
+      return response.json();
     }
   
Index: imaps-frontend/src/scripts/net/netconfig.js
===================================================================
--- imaps-frontend/src/scripts/net/netconfig.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/net/netconfig.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,66 +1,14 @@
-export const API_BASE_URL = "http://localhost:8080/api";
-export const API_PROTECTED = `${API_BASE_URL}/protected`
-export const API_PUBLIC = `${API_BASE_URL}/public`
-export const API_AUTH = `${API_BASE_URL}/auth`
-
 
 const config = {
-    my_maps: {
-        display: `${API_PROTECTED}/my-maps`,
-        save: `${API_PROTECTED}/my-maps/save`,
-        add: `${API_PROTECTED}/my-maps/create`,
-        load: `${API_PROTECTED}/my-maps/load`,
-        delete: `${API_PROTECTED}/my-maps/delete`,
-        publish: `${API_PROTECTED}/publish/add`,
-        publish_get: `${API_PROTECTED}/publish/get`,
-        edit_map_info: `${API_PROTECTED}/my-maps/edit`,
-    },
-    room_types: {
-        display: (auth) => {
-            return auth ? `${API_PROTECTED}/room-types` : `${API_PUBLIC}/room-types`
-        },
-        add: `${API_PROTECTED}/room-types/add`,
+    apiBaseUrl: "http://localhost:8080/api",
 
-    },
-    floors: {
-        add: `${API_PROTECTED}/floors/add`,
-        load: `${API_PROTECTED}/my-maps/load`,
-        delete: `${API_PROTECTED}/floors/delete`,
-    },
-    view_maps: {
-        display: `${API_PUBLIC}/maps`,
-        load: (auth) => {
-            return auth ? `${API_PROTECTED}/load-map` : `${API_PUBLIC}/load-map`
-        },
-        navigate: `${API_PUBLIC}/navigate`,
-        add_favourite: `${API_PROTECTED}/favourites/add`,
-        add_report: `${API_PROTECTED}/reports/create`,
-    },
-    favourites: {
-        display: `${API_PROTECTED}/favourites`,
-        add: `${API_PROTECTED}/favourites/add`,
-        delete: `${API_PROTECTED}/favourites/delete`,
-    },
-    auth:{
-        login: `${API_AUTH}/login`,
-        register: `${API_AUTH}/register`,
-        verify: `${API_AUTH}/verify`,
-        oauth: {
-            github: {
-                state: `${API_BASE_URL}/oauth/state`,
-                redirectUri : `${API_BASE_URL}/oauth/callback`
-            }
-        }
-
-    },
-    admin:{
-        display: `${API_BASE_URL}/admin`,
-        load_pr: `${API_BASE_URL}/admin/load-pr`,
-        approve_pr: `${API_BASE_URL}/admin/pr/approve`,
-        deny_pr: `${API_BASE_URL}/admin/pr/deny`,
-        load_reports: `${API_BASE_URL}/admin/load-reports`
+    endpoints: {
+        login: "/auth/login",
+        register: "/auth/register",
+        verify: "/auth/verify",
+        render: "/protected/render",
+        publicMapData: "/public/mapData"
     }
 };
 
-
 export default config;
Index: imaps-frontend/src/scripts/rendered_shapes/RenderedEntrance.js
===================================================================
--- imaps-frontend/src/scripts/rendered_shapes/RenderedEntrance.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/rendered_shapes/RenderedEntrance.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,44 +1,37 @@
-import RenderedMapShape from "../base/RenderedMapShape.js";
-import {_registerNode} from "konva/lib/Global";
-import RenderedRoom from "./RenderedRoom.js";
+import RenderedMapShape from "./RenderedMapShape.js";
 
-export default class RenderedEntrance extends RenderedMapShape {
-  constructor(attrs, scaleX, scaleY) {
-    super({
-      x: attrs.x,
-      y: attrs.y,
-      width: attrs.width,
-      height: attrs.height,
-      fill: "#7fef83",
-      stroke: "black",
-      strokeWidth: 1,
-      draggable: false,
-      rotation: attrs.rotation,
-      cornerRadius: 3,
-      zIndex: 0,
-    });
+export default class RenderedEntrance extends RenderedMapShape{
+    constructor(attrs,scaleX,scaleY){
+        super({
+            x: attrs.x,
+            y: attrs.y,
+            width: attrs.width * scaleX,
+            height: attrs.height * scaleY,
+            fill: '#1c3cff',
+            stroke: 'black',
+            strokeWidth: 1,
+            draggable: false,
+            rotation: attrs.rotation,
+            cornerRadius:3,
+            zIndex: 0
+        });
 
-    this.info.name = attrs.obj_name;
-    this.info.description = attrs.description;
-    this.info.isMainEntrance = attrs.is_main_entrance;
+        this.info.name = attrs.obj_name;
+        this.info.description = attrs.description;
+        
+    
+        this.on("mouseenter",() => {
+        console.log("HOVER ROOM IN", this.x());
+        console.log(this.info.name,"NAME");
+        this.stroke('purple');
+        })
+        this.on("mouseleave", () => {
+            console.log("HOVER ROOM OUT");
+            this.opacity(1);
+            this.stroke('black')
 
-    this.floorNum = attrs.floor_num
+        })
 
-    this.class = "Entrance";
-
-    console.log("ATTRS VIEW:  " + attrs)
-
-    this.on("mouseenter", () => {
-      this.stroke("purple");
-    });
-    this.on("mouseleave", () => {
-      this.opacity(1);
-      this.stroke("black");
-    });
-
-    //this.initText();
-  }
+        this.initText()
+    }
 }
-
-RenderedEntrance.prototype.className = "RenderedEntrance";
-_registerNode(RenderedEntrance);
Index: imaps-frontend/src/scripts/rendered_shapes/RenderedMapShape.js
===================================================================
--- imaps-frontend/src/scripts/rendered_shapes/RenderedMapShape.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
+++ imaps-frontend/src/scripts/rendered_shapes/RenderedMapShape.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -0,0 +1,45 @@
+import Konva from "konva";
+
+export default class RenderedMapShape extends Konva.Rect{
+    constructor(config){
+        if (new.target === RenderedMapShape) {
+            throw new Error("Cannot instantiate abstract class RenderedMapShape directly.");
+          }
+
+          super(config);
+
+          this.info = {
+            name: "",
+            description: "",
+          }
+          this.infoText = null;
+          this.textOffsetX = 0;
+          this.textOffsetY = 0;
+    }
+
+    initText() {
+      this.infoText = new Konva.Text({
+        x: this.x() + this.textOffsetX,
+        y: this.y() + this.textOffsetY,
+        text: this.info.name || "no name",
+        fontSize: 12,
+        fontFamily: 'Verdana',
+        fill: 'black',
+      });
+    }
+  
+    updateTextPosition() {
+      if(this.infoText){
+        this.infoText.x(this.x() + this.textOffsetX);
+        this.infoText.y(this.y() + this.textOffsetY);
+      }
+    }
+  
+    displayName(layer) {
+        if(this.infoText != null){
+            layer.add(this.infoText);
+        }
+
+    }
+    
+}
Index: imaps-frontend/src/scripts/rendered_shapes/RenderedRoom.js
===================================================================
--- imaps-frontend/src/scripts/rendered_shapes/RenderedRoom.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/rendered_shapes/RenderedRoom.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,62 +1,41 @@
-import RenderedMapShape from "../base/RenderedMapShape.js";
-import {_registerNode} from "konva/lib/Global";
+import RenderedMapShape from "./RenderedMapShape.js";
 
-export default class RenderedRoom extends RenderedMapShape {
-  constructor(attrs, scaleX, scaleY) {
-    super({
-      x: attrs.x,
-      y: attrs.y,
-      width: attrs.width,
-      height: attrs.height,
-      fill: "#A2D9FF",
-      stroke: "black",
-      strokeWidth: 1,
-      draggable: false,
-      rotation: attrs.rotation,
-      cornerRadius: 3
-    });
+export default class RenderedRoom extends RenderedMapShape{
+    constructor(attrs,scaleX,scaleY){
+        super({
+            x: attrs.x,
+            y: attrs.y,
+            width: attrs.width * scaleX,
+            height: attrs.height * scaleY,
+            fill: 'white',
+            stroke: 'black',
+            strokeWidth: 1,
+            draggable: false,
+            rotation: attrs.rotation,
+            cornerRadius:3,
+            zIndex: 0
+        });
 
-    console.info("FNUM RENDER:",attrs.floor_num)
+        this.info.name = attrs.obj_name;
+        this.info.description = attrs.description;
 
-    this.floorNum = attrs.floor_num
+        this.textOffsetX = -50
+        
+    
+        this.on("mouseenter",() => {
+        console.log("HOVER ROOM IN", this.x());
+        console.log(this.info.name,"NAME");
+        this.opacity(0.7);
+        this.fill("pink");
+        })
+        this.on("mouseleave", () => {
+            console.log("HOVER ROOM OUT");
+            this.opacity(1);
+            this.fill("white");
+        })
 
-    this.info.name = attrs.obj_name;
-    this.info.type = attrs.room_type;
-    this.info.description = attrs.description;
-    this.class = "Room";
-    this.textOffsetX = -50;
+        this.initText()
+    }
 
-    this.eventName = "openRoomInfoPanel"
-
-    this.on("mouseenter", () => {
-      console.log(this.info.name, "NAME");
-      this.fill("#65c3f8");
-    });
-    this.on("mouseleave", () => {
-      this.fill("#A2D9FF");
-    });
-
-
-
-    // searched(){
-    //   this.fill("#b92d39")
-    // }
-    // unsearched(){
-    //   this.fill("#A2D9FF");
-    // }
-
-    // console.log("ATTRS: " + attrs);
-
-    this.initText();
-  }
-  highlight(){
-    this.fill("rgba(29,238,78,0.49)");
-    this.strokeWidth(2)
-  }
-  unHighlight(){
-    this.fill("#A2D9FF");
-    this.strokeWidth(1);
-  }
+   
 }
-RenderedRoom.prototype.className = "RenderedRoom";
-_registerNode(RenderedRoom);
Index: imaps-frontend/src/scripts/rendered_shapes/RenderedStairs.js
===================================================================
--- imaps-frontend/src/scripts/rendered_shapes/RenderedStairs.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,43 +1,0 @@
-import RenderedMapShape from "../base/RenderedMapShape.js";
-import Stairs from "../shapes/Stairs.js";
-import {_registerNode} from "konva/lib/Global";
-import Konva from "konva";
-export default class RenderedStairs extends RenderedMapShape{
-    constructor(attrs,scaleX,scaleY) {
-        super({
-            x: attrs.x,
-            y: attrs.y,
-            width: attrs.width ,
-            height: attrs.height,
-            fill: "rgb(199,190,133)",
-            stroke: "rgb(16,15,15)",
-            strokeWidth: 1,
-            name: "mapObj",
-            rotation: attrs.rotation,
-        });
-
-
-        this.floorNum = attrs.floor_num;
-        this.info.name = attrs.obj_name;
-        //this.initText()
-    }
-
-
-
-
-    _sceneFunc(context, shape) {
-        const { width, height} = this.attrs;
-
-        let steps = 5;
-        let offset = 10;
-        context.beginPath()
-        for(let i = 0; i < steps; i++){
-            context.rect((-offset) * i,(offset * 0.6) * i,width * 0.86,height/2)
-            context.fillStrokeShape(shape);
-        }
-        context.closePath()
-    }
-}
-
-RenderedStairs.prototype.className = "RenderedStairs";
-_registerNode(RenderedStairs);
Index: imaps-frontend/src/scripts/rendered_shapes/RenderedWall.js
===================================================================
--- imaps-frontend/src/scripts/rendered_shapes/RenderedWall.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/rendered_shapes/RenderedWall.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,4 +1,3 @@
-import RenderedMapShape from "../base/RenderedMapShape.js";
-import {_registerNode} from "konva/lib/Global";
+import RenderedMapShape from "./RenderedMapShape.js";
 
 export default class RenderedWall extends RenderedMapShape{
@@ -7,7 +6,7 @@
             x: attrs.x,
             y: attrs.y,
-            width: attrs.width,
-            height: attrs.height,
-            fill: '#4B4B4B',
+            width: attrs.width * scaleX,
+            height: attrs.height * scaleY,
+            fill: 'grey',
             stroke: 'black',
             strokeWidth: 1,
@@ -19,5 +18,2 @@
     }
 }
-
-RenderedWall.prototype.className = "RenderedWall";
-_registerNode(RenderedWall);
Index: imaps-frontend/src/scripts/shapes/Entrance.js
===================================================================
--- imaps-frontend/src/scripts/shapes/Entrance.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/shapes/Entrance.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,109 +1,58 @@
-import {_registerNode} from "konva/lib/Global";
-import MapNode from "../base/MapNode.js";
-import {node} from "prop-types";
-import ShapeRegistry from "../util/ShapeRegistry.js";
-import ShapeQuery from "../util/ShapeQuery.js";
 import Konva from "konva";
+import MapShape from "./MapShape";
+import { _registerNode } from "konva/lib/Global";
+export default class Entrance extends MapShape {
+  constructor(mousePos, blockSize, layer, rotation, snap,id,scaleX = 1, scaleY = 1) {
+    super(
+      {
+        x: mousePos.x,
+        y: mousePos.y,
+        width: blockSize * scaleX,
+        height: blockSize * 2 * scaleY,
+        fill: "#0051ff",
+        stroke: "grey",
+        strokeWidth: 1,
+        opacity: 0.7,
+        name: "mapObj",
+        draggable: true,
+        rotation: rotation,
+        zIndex: 1,
+      },
+      layer,
+      blockSize,
+      snap
+    );
+    this.type = "Entrance";
+    this.modalEventName = "openEntranceModalEvent";
 
-export default class Entrance extends MapNode {
+    this.id = id;
 
-    constructor(attrs, id) {
+    this._info = {
+      name: `Entrance ${id}`,
+      connectedRoom: "",
+      description: "",
+      isMainEntrance: false,
+      selectedPin: "",
+      selectedPins: [],
+    };
 
-        if (!attrs.fromLoad) {
-            attrs.height *= 2;
-        }
-        super(
-            {
-                x: attrs.position.x,
-                y: attrs.position.y,
-                width: attrs.width * attrs.scaleX,
-                height: attrs.height * attrs.scaleY,
-                fill: "rgb(126,238,167)",
-                stroke: "#252627",
-                strokeWidth: 1,
-                opacity: 0.9,
-                name: "mapObj",
-                draggable: true,
-                rotation: attrs.rotation,
-                zIndex: 1,
-            },
-            attrs.layer,
-            attrs.blockSize,
-            attrs.snap
-        );
-        this.type = "Entrance";
-        this.eventName = "openEntranceModalEvent";
-        this.floorNum = attrs.floorNum
+    this.initText();
+  }
 
-        this.id = id;
+  loadInfo(attrs) {
+    this.info.name = attrs.obj_name;
+    this.info.connectedRoom = attrs.connected_room;
+    this.info.description = attrs.description;
+    this.info.isMainEntrance = attrs.is_main_entrance;
+    this.info.selectedPins = attrs.connected_pins;
+  }
 
-        this._info = {
-            name: `Entrance${id} [${this.floorNum}F]`,
-            connectedRoom: "",
-            description: "",
-            isMainEntrance: false,
-            selectedPin: "",
-            selectedPins: [],
-        };
-
-        this.initText();
-        this.moveToTop();
-
-        console.log("room CONNECT: " + attrs.connected_room,this.info.connectedRoom + "CON")
-        console.log("entrance: " + this.info.name)
-    }
-
-    loadInfo(attrs) {
-        this.info.name = attrs.obj_name ?? `Entrance${this.id} [${this.floorNum}F]`;
-        this.info.connectedRoom = attrs.connected_room ?? ``;
-        this.info.description = attrs.description ?? ``;
-        this.info.isMainEntrance = attrs.is_main_entrance ?? false;
-        this.info.selectedPins = attrs.connected_pins ?? [];
-    }
-
-
-    saveShapeDetails() {
-        console.info("fnum entrance",this.attrs.floorNum)
-        this.setAttr("connected_pins", this.info.selectedPins);
-        this.setAttr("obj_name", this.info.name);
-        this.setAttr("description", this.info.description);
-        this.setAttr("is_main_entrance", this.info.isMainEntrance);
-        this.setAttr("connected_room", this.info.connectedRoom);
-        this.setAttr("floor_num",this.floorNum);
-    }
-
-    connect(node, draw = true) {
-        if(this.floorNum !== node.floorNum) return;
-
-        super.connect(node)
-    }
-
-    setInfo(infoObj) {
-        this.info = infoObj;
-        this.setHighlight();
-    }
-
-    setHighlight(){
-        console.log("info room: " + this.info.connectedRoom)
-        if(this.info.connectedRoom == null || this.info.connectedRoom === "" ){
-            console.log("vleze if")
-            this.strokeWidth(2);
-            this.stroke("#8a000d")
-        }else{
-            this.strokeWidth(1)
-            this.stroke("black")
-        }
-    }
-
-    onPlace() {
-        ShapeQuery
-            .findAllByTypeAndFloor(this.floorNum,"Room")
-            .forEach(room => {
-                if(Konva.Util.haveIntersection(room.getClientRect(),this.getClientRect())){
-                    this.info.connectedRoom = room.info.name;
-                }
-            })
-        this.setHighlight()
-    }
+  saveShapeDetails() {
+    this.setAttr("connected_pins", this.info.selectedPins);
+    this.setAttr("obj_name", this.info.name);
+    this.setAttr("description", this.info.description);
+    this.setAttr("is_main_entrance", this.info.isMainEntrance);
+    this.setAttr("connected_room", this.info.connectedRoom);
+  }
 }
 
Index: imaps-frontend/src/scripts/shapes/InfoPin.js
===================================================================
--- imaps-frontend/src/scripts/shapes/InfoPin.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/shapes/InfoPin.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,35 +1,32 @@
-
+import Konva from "konva";
+import MapShape from "./MapShape";
+import Factory from "../util/Factory";
 import { _registerNode } from "konva/lib/Global";
-import MapNode from "../base/MapNode.js";
-import {node} from "prop-types";
-import draw from "../../pages/Draw/Draw.jsx";
-export default class InfoPin extends MapNode {
-  constructor(attrs,id) {
-    attrs.snap = false;
+export default class InfoPin extends MapShape {
+  constructor(mousePos, blockSize, layer, snappable,id) {
     super(
       {
-        x: attrs.position.x,
-        y: attrs.position.y,
-        radiusX: attrs.blockSize * 0.5,
-        radiusY: attrs.blockSize * 0.7,
-        tailHeight: attrs.blockSize * 1.2,
-        fill: "#f60000",
+        x: mousePos.x,
+        y: mousePos.y,
+        radiusX: blockSize * 0.5,
+        radiusY: blockSize * 0.7,
+        tailHeight: blockSize * 1.2,
+        fill: "#d70113",
         stroke: "#1b1b1b",
-        strokeWidth: 1,
+        strokeWidth: 0.2,
         draggable: true,
         name: "mapObj",
       },
-      attrs.layer,
-      attrs.blockSize,
-      attrs.snap
+      layer,
+      blockSize,
+      snappable
     );
 
     this.id = id;
-    this.eventName = "openPinModalEvent";
-    this.floorNum = attrs.floorNum;
 
+    this.modalEventName = "openPinModalEvent";
     this.type = "InfoPin";
     this._info = {
-      name: `Pin${id} [${this.floorNum}F]`,
+      name: `Pin ${id}`,
       selectedPins: [],
       description: "",
@@ -37,15 +34,14 @@
 
     this.on("mouseover", () => {
-      this.fill("#FFD700");
+      this.fill("yellow");
     });
     this.on("mouseout", () => {
-      this.fill("#f60000");
+      this.fill("red");
     });
-
 
     this.initText();
   }
   _sceneFunc(context, shape) {
-    const { radiusX, radiusY, tailHeight } = this.attrs; // attrs od konva
+    const { radiusX, radiusY, tailHeight } = this.attrs;
 
     context.beginPath();
@@ -63,10 +59,8 @@
   }
 
-
   loadInfo(attrs) {
     this.info.name = attrs.obj_name;
     this.info.selectedPins = attrs.connected_pins;
     this.info.description = attrs.description;
-    this.floorNum = attrs.floor_num
   }
 
@@ -75,11 +69,5 @@
     this.setAttr("connected_pins", this.info.selectedPins);
     this.setAttr("description", this.info.description);
-    this.setAttr("floor_num",this.floorNum)
     console.log(this.info, "vnatre vo info");
-  }
-
-  connect(node, draw = true) {
-    if(this.floorNum !== node.floorNum) return;
-    super.connect(node)
   }
 }
Index: imaps-frontend/src/scripts/shapes/MapShape.js
===================================================================
--- imaps-frontend/src/scripts/shapes/MapShape.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
+++ imaps-frontend/src/scripts/shapes/MapShape.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -0,0 +1,123 @@
+import Konva from "konva";
+
+export default class MapShape extends Konva.Shape {
+    constructor(config, layer, blockSize, snap) {
+        if (new.target === MapShape) {
+            throw new Error("Cannot instantiate abstract class BaseShape directly.");
+        }
+        super(config);
+        this.layer = layer;
+        this.blockSize = blockSize;
+        this._type = "";
+        this.snappable = snap;
+        this._info = {};
+        this.modalEventName = "";
+        this.infoText = null;
+
+        this.shadowForStrokeEnabled(false);
+        this.on("mouseover", () => (document.body.style.cursor = "pointer"));
+        this.on("mouseout", () => (document.body.style.cursor = "default"));
+        // this.on("dblclick", (e) => {
+        //   this.moveToTop();
+        //   this.getLayer()
+        //     .find("Transformer")
+        //     .forEach((t) => t.moveToTop());
+        // });
+
+        if (snap) {
+            this.on("dragend", this.snapToGrid.bind(this));
+            this.on('dblclick', this.snapToGrid.bind(this))
+        }
+
+        this.on("transform", () => {
+            const scaleX = this.scaleX();
+            const scaleY = this.scaleY();
+            this.strokeWidth(1 / Math.max(scaleX, scaleY));
+        });
+
+        this.on('dragend', () => {
+            if (this.infoText) {
+                this.updateTextPosition();
+            }
+        });
+
+    }
+
+    loadInfo(attrs) {
+        console.log("Abstract function");
+    }
+
+
+    initText() {
+        this.textOffsetX = 0;
+        this.textOffsetY = -30;
+        this.infoText = new Konva.Text({
+            x: this.x() + this.textOffsetX,
+            y: this.y() + this.textOffsetY,
+            text: this._info.name,
+            fontSize: 12,
+            fontFamily: 'Verdana',
+            fill: 'white',
+        });
+    }
+
+    updateTextPosition() {
+        if (this.infoText) {
+            this.infoText.x(this.x() + this.textOffsetX);
+            this.infoText.y(this.y() + this.textOffsetY);
+        }
+    }
+
+    displayName(layer) {
+        if (this.infoText) {
+            this.infoText.text(this._info.name);
+            layer.add(this.infoText);
+        }
+    }
+
+    _sceneFunc(context) {
+        let width = this.width();
+        let height = this.height();
+        context.beginPath();
+        context.rect(0, 0, width, height)
+        context.closePath();
+        context.fillStrokeShape(this);
+    }
+
+    clearText() {
+        if (this.infoText !== null) {
+            this.infoText.remove()
+            console.log("cleared text")
+        }
+
+    }
+
+    snapToGrid() {
+        this.position({
+            x: Math.round(this.x() / this.blockSize) * this.blockSize,
+            y: Math.round(this.y() / this.blockSize) * this.blockSize,
+        });
+    }
+
+    saveShapeDetails() {
+        console.log("This shape does not contain information");
+    }
+
+
+    get info() {
+        return this._info;
+    }
+
+    set info(formData) {
+        this._info = formData;
+    }
+
+    get type() {
+        return this._type;
+    }
+
+    set type(type) {
+        this._type = type
+    }
+
+}
Index: imaps-frontend/src/scripts/shapes/Room.js
===================================================================
--- imaps-frontend/src/scripts/shapes/Room.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/shapes/Room.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,36 +1,27 @@
 import Konva from "konva";
-import MapShape from "../base/MapShape.js";
+import MapShape from "./MapShape";
 import { _registerNode } from "konva/lib/Global";
 export default class Room extends MapShape {
-  constructor(attrs,id){
-
-      if(!attrs.fromLoad){
-          attrs.width *= 12;
-          attrs.height *= 8;
-      }
-
-      console.log(attrs.position,"hehe")
+  constructor(mousePos, blockSize, layer, rotation, snap, id, scaleX = 1, scaleY = 1){
     super(
       {
-        x: attrs.position.x,
-        y: attrs.position.y,
-        width: attrs.width * attrs.scaleX,
-        height: attrs.height * attrs.scaleY,
-        fill: "rgb(86,168,253)",
+        x: mousePos.x,
+        y: mousePos.y,
+        width: blockSize * 8 * scaleX,
+        height: blockSize * 4 * scaleY,
+        fill: "#DDE0F8",
         stroke: "grey",
         strokeWidth: 1,
         name: "mapObj",
-        rotation: attrs.rotation,
+        rotation: rotation,
         draggable: true,
       },
-        attrs.layer,
-        attrs.blockSize,
-        attrs.snap
+      layer,
+      blockSize,
+      snap
     );
 
-      this.floorNum = attrs.floorNum;
-
     this._info = {
-      name: `Room${id} [${this.floorNum}F]`,
+      name: `Room ${id}`,
       type: "",
       description: "",
@@ -38,5 +29,5 @@
 
     this.type = "Room";
-    this.eventName = "openRoomModalEvent";
+    this.modalEventName = "openRoomModalEvent";
     this.id = id;
 
@@ -48,5 +39,4 @@
     this.info.type = attrs.room_type;
     this.info.description = attrs.description;
-    this.floorNum = attrs.floor_num;
   }
 
@@ -55,5 +45,4 @@
     this.setAttr("room_type", this.info.type);
     this.setAttr("description", this.info.description);
-    this.setAttr("floor_num",this.floorNum);
   }
 }
Index: imaps-frontend/src/scripts/shapes/Stairs.js
===================================================================
--- imaps-frontend/src/scripts/shapes/Stairs.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/shapes/Stairs.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,78 +1,4 @@
 import Konva from "konva";
-import MapNode from "../base/MapNode.js";
-import {_registerNode} from "konva/lib/Global.js";
-import Room from "./Room.js";
-export default class Stairs extends MapNode{
-    constructor(attrs,id) {
+import { MapShape } from "./MapShape";
 
-        if(!attrs.fromLoad){
-            attrs.width *= 4;
-        }
-
-        super({
-                x: attrs.position.x,
-                y: attrs.position.y,
-                width: attrs.width * attrs.scaleX,
-                height: attrs.height * attrs.scaleY,
-                fill: "rgb(225,213,124)",
-                stroke: "rgb(16,15,15)",
-                strokeWidth: 1,
-                name: "mapObj",
-                rotation: attrs.rotation,
-                draggable: true
-            },
-            attrs.layer,
-            attrs.blockSize,
-            attrs.snap
-        );
-
-        this.floorNum = attrs.floorNum;
-
-        this.type = "Stairs"
-        this._info = {
-            name: `Stairs${id} [${this.floorNum}F]`,
-            description: "",
-            selectedPins: []
-        };
-
-        this.id = id;
-        this.eventName = "openStairsModalEvent";
-        this.initText();
-    }
-
-
-    _sceneFunc(context, shape) {
-        const { width, height} = this.attrs;
-
-        let steps = 5;
-        context.beginPath()
-        for(let i = 0; i < steps; i++){
-            context.rect((-this.blockSize) * i,(this.blockSize * 0.6) * i,width * 0.86,height/2)
-            context.fillStrokeShape(shape);
-        }
-        context.closePath()
-    }
-
-    loadInfo(attrs) {
-        this.info.name = attrs.obj_name;
-        this.info.description = attrs.description;
-        this.info.selectedPins = attrs.connected_pins;
-        this.floorNum = attrs.floor_num;
-    }
-
-    saveShapeDetails() {
-        this.setAttr("connected_pins", this.info.selectedPins);
-        this.setAttr("obj_name", this.info.name);
-        this.setAttr("description", this.info.description);
-        this.setAttr("floor_num",this.floorNum)
-    }
-    connect(node,draw = true) {
-        let canDraw = this.floorNum === node.floorNum;
-        super.connect(node,canDraw);
-    }
-
-}
-
-Stairs.prototype.className = "Stairs";
-_registerNode(Stairs);
 //TODO
Index: imaps-frontend/src/scripts/shapes/Wall.js
===================================================================
--- imaps-frontend/src/scripts/shapes/Wall.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/shapes/Wall.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,43 +1,29 @@
 import Konva from "konva";
-import MapShape from "../base/MapShape.js";
+import MapShape from "./MapShape";
 import { _registerNode } from 'konva/lib/Global';
 export default class Wall extends MapShape {
-    constructor(attrs){
-        if(!attrs.fromLoad){
-            attrs.height *= 8;
-        }
-
-
+    constructor(mousePos, blockSize, layer, rotation,snap, draggable = true,scaleX = 1, scaleY = 1){
       super(
         {
-          x: attrs.position.x,
-          y: attrs.position.y,
-          width: attrs.width * attrs.scaleX,
-          height: attrs.height * attrs.scaleY,
-          fill: "#d3d3d3",
+          x: mousePos.x,
+          y: mousePos.y,
+          width: blockSize * scaleX,
+          height: blockSize * 8 * scaleY,
+          fill: "#DDE0F8",
           stroke: "grey",
           strokeWidth: 1,
           name: "mapObj",
-          draggable: true,
-          rotation: attrs.rotation,
+          draggable: draggable,
+          rotation: rotation,
           zIndex: 0,
         },
-        attrs.layer,
-        attrs.blockSize,
-        attrs.snap,
+        layer,
+        blockSize,
+        snap,
       );
+  
       this.type = "Wall";
-
-        this.floorNum = attrs.floorNum;
     }
-
-    loadInfo(attrs) {
-        this.floorNum = attrs.floor_num;
-    }
-
-    saveShapeDetails() {
-        this.setAttr("floor_num",this.floorNum)
-    }
-}
+  }
 
   Wall.prototype.className = 'Wall'
Index: imaps-frontend/src/scripts/util/Factory.js
===================================================================
--- imaps-frontend/src/scripts/util/Factory.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/util/Factory.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -6,35 +6,24 @@
 import RenderedEntrance from "../rendered_shapes/RenderedEntrance";
 import RenderedWall from "../rendered_shapes/RenderedWall.js";
-import Stairs from "../shapes/Stairs.js";
-import RenderedStairs from "../rendered_shapes/RenderedStairs.js";
-import {updateShapeCount, getShapeCount} from "./ShapeCount.js";
 export default class Factory {
-  // BUG KO KE NAPRES REFRESH SA RESETVAT COUNTS!
 
-  static createShape(shapeType,attrs) {
-    console.log(attrs,"attrs in factory")
-    console.log("position in factory: " + attrs.position.x)
+  static infoPinCount = 0;
+  static wallCount = 0;
+  static entranceCount = 0;
+  static roomCount = 0;
 
-    let scaleX = (attrs.scaleX ? parseFloat(attrs.scaleX) : 1);
-    let scaleY =  (attrs.scaleY ? parseFloat(attrs.scaleY) : 1);
-
-    attrs.scaleX = scaleX;
-    attrs.scaleY = scaleY;
-
+  static createShape(shapeType, position, blockSize, layer, rotation,scaleX = 1, scaleY = 1, increment = false) {
     switch (shapeType) {
       case "Entrance":
-        if(attrs.increment) updateShapeCount("entrance")
-        return new Entrance(attrs,getShapeCount("entrance"));
+        if(increment) this.entranceCount++;
+        return new Entrance(position, blockSize, layer, rotation,true,this.entranceCount,scaleX,scaleY);
       case "Room":
-        if(attrs.increment) updateShapeCount("room");
-        return new Room(attrs,getShapeCount("room"));
-       case "Wall":
-         return new Wall(attrs);
-       case "InfoPin":
-        if(attrs.increment) updateShapeCount("infoPin")
-          return new InfoPin(attrs,getShapeCount("infoPin"));
-      case "Stairs":
-        if(attrs.increment) updateShapeCount("stairs")
-        return new Stairs(attrs,getShapeCount("stairs"))
+        if(increment) this.roomCount++;
+        return new Room(position, blockSize, layer, rotation,true, this.roomCount,scaleX,scaleY);
+      case "Wall":
+        return new Wall(position, blockSize, layer, rotation,true,scaleX,scaleY);
+      case "InfoPin":
+        if(increment) this.infoPinCount++;
+        return new InfoPin(position, blockSize, layer, false,this.infoPinCount);
       default:
         throw new Error("Invalid shape type: " + shapeType);
@@ -45,10 +34,4 @@
     let scaleX = (attrs.scaleX ? parseFloat(attrs.scaleX) : 1);
     let scaleY =  (attrs.scaleY ? parseFloat(attrs.scaleY) : 1);
-
-    attrs.width *= scaleX;
-    attrs.height *= scaleY
-
-    console.log("SCALEX " + scaleX)
-    console.log("SCALEY " + scaleY)
     switch (shapeType) {
       case "Entrance":
@@ -58,6 +41,4 @@
       case "Wall":
         return new RenderedWall(attrs,scaleX,scaleY);
-      case "Stairs":
-        return new RenderedStairs(attrs,scaleX,scaleY)
       default:
         throw new Error("Invalid shape type." + shapeType);
Index: imaps-frontend/src/scripts/util/ShapeCount.js
===================================================================
--- imaps-frontend/src/scripts/util/ShapeCount.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,18 +1,0 @@
-const shapeCount = {
-    infoPin: 0,
-    wall: 0,
-    entrance: 0,
-    room: 0,
-    stairs: 0
-};
-
-const updateShapeCount = (key) => {
-    shapeCount[key]++;
-}
-const getShapeCount = (key) => {
-    return shapeCount[key];
-}
-
-export {updateShapeCount, getShapeCount};
-
-// todo za da sa incrementvit i posle restart na browwser, trebit vo baza nova tabela za broenje
Index: imaps-frontend/src/scripts/util/ShapeQuery.js
===================================================================
--- imaps-frontend/src/scripts/util/ShapeQuery.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,19 +1,0 @@
-import MapNode from "../base/MapNode.js";
-import ShapeRegistry from "./ShapeRegistry.js";
-
-export default class ShapeQuery{
-    static findAllByType(...types) {
-        return ShapeRegistry.getShapes().filter(shape => types.includes(shape.className));
-    }
-
-    static findNodeByName(shapes, name){
-        return shapes.filter(shape => shape instanceof MapNode && shape.info.name === name)[0];
-    }
-    static findAllByTypeAndFloor(floor,...types){
-        return ShapeRegistry.getShapes().filter(shape => types.includes(shape.className) && shape.floorNum === floor);
-    }
-
-    static getAllNodes(floor = null){
-        return ShapeRegistry.getShapes(floor).filter(shape => shape instanceof MapNode);
-    }
-}
Index: imaps-frontend/src/scripts/util/ShapeRegistry.js
===================================================================
--- imaps-frontend/src/scripts/util/ShapeRegistry.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,165 +1,0 @@
-import MapNode from "../base/MapNode.js";
-import ShapeQuery from "./ShapeQuery.js";
-// TODO abstraktna klasa ova da stanit i za da napram za view registry, za da mozis search na floors globalno
-
-class ShapeRegistry {
-    constructor() {
-        if (!ShapeRegistry.instance) {
-            this.store = {
-                floors: {} // key brojka 0: shappes arr
-            };
-            ShapeRegistry.instance = this;
-        }
-
-        return ShapeRegistry.instance;
-    }
-
-    /**
-     * @description Get all the shapes from a floor if floorNumber is specified.
-     * @description If floorNumber is not specified, returns all the shapes from every floor.
-     * @param floorNumber
-     * @returns {[{}]} [shapes]
-     */
-    getShapes(floorNumber = null) {
-        if (!this.store.floors[floorNumber]) {
-            this.store.floors[floorNumber] = [];
-        }
-
-        if (floorNumber != null) {
-            return this.store.floors[floorNumber];
-        } else {
-            return Object.values(this.store.floors).flat();
-        }
-
-
-    }
-
-    /**
-     * Adds a shape to a floor that corresponds the shape's internally stored floor number.
-     * @param shape
-     */
-    add(shape) {
-        console.log("floor: " + shape.floorNum)
-        if (!this.store.floors[shape.floorNum]) {
-            this.store.floors[shape.floorNum] = [];
-        }
-        this.store.floors[shape.floorNum].push(shape);
-    }
-
-    /**
-     * Deletes a shape from the floor corresponds the shape's internally stored floor number
-     * @param shape
-     */
-    delete(shape) {
-        const floorShapes = this.store.floors[shape.floorNum];
-        if (floorShapes) {
-            const index = floorShapes.indexOf(shape);
-            if (index !== -1) {
-                floorShapes.splice(index, 1);
-            }
-        }
-    }
-
-    /**
-     * @param floorNumber Clears all shapes from the specified floor
-     */
-    clear(floorNumber = null) {
-
-        if(floorNumber != null){
-            const floor = this.store.floors[floorNumber];
-            if (Array.isArray(floor)) {
-                floor.forEach(shape => shape.destroy());
-                this.store.floors[floorNumber] = [];
-            }
-        } else {
-           Object.keys(this.store.floors).forEach(floorNumber => {
-               const floor = this.store.floors[floorNumber];
-               if (Array.isArray(floor)) {
-                   floor.forEach(shape => shape.destroy());
-                   this.store.floors[floorNumber] = [];
-               }
-           })
-        }
-
-
-
-    }
-
-    // ova mozit optimizacija da ne pret na site spratoj update celo vreme, samo ko ke povrzvis stairs da pret na site
-    updateConnections() {
-        Object.values(this.store.floors).forEach(floorShapes => {
-            floorShapes.forEach(shape => {
-                if (shape.className === "InfoPin" || shape.className === "Entrance" || shape.className === "Stairs") {
-                    shape.info.selectedPins.forEach((connectedShapeName) => {
-                        const connectedShape = floorShapes.find(s => s.info.name === connectedShapeName);
-                        if (
-                            connectedShape &&
-                            (connectedShape.className === "InfoPin" || connectedShape.className === "Entrance" || connectedShape.className === "Stairs")
-                        ) {
-                            if (!connectedShape.info.selectedPins.includes(shape.info.name)) {
-                                connectedShape.info.selectedPins.push(shape.info.name);
-                            }
-                        }
-                    });
-                }
-            });
-        });
-    }
-
-    drawConnection(node1Name, node2Name) {
-        const node1 = Object.values(this.store.floors).flat()
-            .find(shape => shape instanceof MapNode && shape.info.name === node1Name);
-        const node2 = Object.values(this.store.floors).flat()
-            .find(shape => shape instanceof MapNode && shape.info.name === node2Name);
-
-        console.log("NODE1: " + JSON.stringify(node1))
-        console.log("NODE2: " + JSON.stringify(node2));
-
-        if (node1 && node2) {
-            node1.connect(node2);
-            console.log("N1",node1.info.selectedPins,"N2",node2.info.selectedPins)
-        } else {
-            console.error("Cant find node1 or node 2.","Node1: " + node1,"Node2: " + node2);
-        }
-    }
-
-
-    removeConnection(from, to) {
-        let shapes = Object.values(this.store.floors).flat();
-
-        let node1 = ShapeQuery.findNodeByName(shapes, from);
-        let node2 = ShapeQuery.findNodeByName(shapes, to);
-
-        if(node1.floorNum === node2.floorNum)
-            node1.removeConnectionLine(node2);
-
-        //node1.removeConnection(node2);
-
-        Object.values(this.store.floors).flat().filter(s => s.info.name === from || s.info.name === to)
-            .forEach(s => {
-                if(s.info.name  === from){
-                    s.info.selectedPins = s.info.selectedPins.filter(pin =>  pin !== to);
-                } else {
-                    s.info.selectedPins = s.info.selectedPins.filter(pin =>  pin !== from);
-                }
-
-            });
-        console.log("Remove");
-    }
-
-    saveDetails() {
-        Object.values(this.store.floors).flat().forEach(shape => {
-            shape.saveShapeDetails();
-            console.log(shape.info);
-        });
-    }
-}
-
-/**
- * A singleton instance that holds all the shapes for all the floors in the map builder.
- * Every operation of adding, removing or updating drawn shapes should reference this instance.
- */
-const instance = new ShapeRegistry();
-Object.freeze(instance);
-
-export default instance;
Index: imaps-frontend/src/scripts/util/addEventHandling.js
===================================================================
--- imaps-frontend/src/scripts/util/addEventHandling.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,13 +1,0 @@
-export const addEventHandling = (shape, map, action) => {
-    shape.on(action, () => {
-        const eventName = shape.eventName;
-        if (eventName) {
-            const data = {
-                room: shape,
-                map: map,
-            };
-            const event = new CustomEvent(eventName, { detail: data });
-            window.dispatchEvent(event);
-        }
-    });
-}
Index: imaps-frontend/src/scripts/util/dispatchCustomEvent.js
===================================================================
--- imaps-frontend/src/scripts/util/dispatchCustomEvent.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,6 +1,0 @@
-export const dispatchCustomEvent = (eventName,data) => {
-    let event = new CustomEvent(eventName,{
-        detail : data
-    })
-    window.dispatchEvent(event)
-}
Index: imaps-frontend/src/scripts/util/parseMapData.js
===================================================================
--- imaps-frontend/src/scripts/util/parseMapData.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,28 +1,0 @@
-import Factory from "./Factory.js";
-import shapeRegistry from "./ShapeRegistry.js";
-
-export default function parseMapData(data, predicate, rendered) {
-    if (data == null || data === "") return [];
-    const dsrData = JSON.parse(data);
-
-    console.log("VLEZE use")
-
-    let result = [];
-
-    dsrData.filter(predicate)
-        .forEach(s => {
-            console.log(s.attrs, "Sattrs pls")
-            s.attrs.position = {x: s.attrs.x, y: s.attrs.y}
-            const shape = rendered ? Factory.createRenderedShape(s.className, s.attrs) : Factory.createShape(s.className, s.attrs);
-
-            if (!rendered) {
-                shape.loadInfo(s.attrs);
-                shapeRegistry.add(shape)
-            }
-
-            result.push(shape)
-
-        })
-
-    return result;
-}
Index: imaps-frontend/src/scripts/util/queryShapes.js
===================================================================
--- imaps-frontend/src/scripts/util/queryShapes.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,8 +1,0 @@
-export const queryShapeInfo = (map,type) => {
-    return map.shapes.filter(shape => shape.className === type).map(shape => shape.info);
-}
-
-export const queryRenderedShapes = (map,type) => {
-
-}
-
Index: imaps-frontend/src/scripts/util/triggerMapSave.js
===================================================================
--- imaps-frontend/src/scripts/util/triggerMapSave.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,21 +1,0 @@
-let canSave = true;
-const mapSaveEvent = new CustomEvent("mapsave",{});
-const setCanSave = (value) => {
-    canSave = value;
-}
-/**
- * Triggers a save event for the floor you are currently on with a debounce time of 3s;
- * @example triggerMapSave() - will save the floor once, and after 3s again.
- */
-const triggerMapSave = () => {
-    if(!canSave) return;
-
-    window.dispatchEvent(mapSaveEvent)
-    setCanSave(false);
-    setTimeout(() => {
-        setCanSave(true);
-        window.dispatchEvent(mapSaveEvent)
-    },2000)
-}
-
-export default triggerMapSave;
Index: imaps-frontend/src/scripts/util/triggerNavigate.js
===================================================================
--- imaps-frontend/src/scripts/util/triggerNavigate.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,14 +1,0 @@
-const triggerNavigate = (nodes,idx,changeFloorTo,shape) => {
-    const event = new CustomEvent("navigate",{
-        detail: {
-            nodes: nodes,
-            offset: idx,
-            changeFloorTo: changeFloorTo,
-            shape:shape
-        }
-    })
-
-    window.dispatchEvent(event);
-}
-
-export default triggerNavigate;
Index: imaps-frontend/src/scripts/util/verifyToken.js
===================================================================
--- imaps-frontend/src/scripts/util/verifyToken.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ 	(revision )
@@ -1,23 +1,0 @@
-import HttpService from "../net/HttpService.js";
-import config from "../net/netconfig.js";
-
-export const verifyToken = async (setIsAuthenticated,setUsername,setLoading) => {
-    const token = localStorage.getItem("token");
-    const httpService = new HttpService();
-
-    try {
-        const response = await httpService.get(`${config.auth.verify}?token=${token}`);
-        if (response.username) {
-            setIsAuthenticated(true);
-            setUsername(response.username)
-            console.log("/verify resp: ",response.username);
-        } else {
-            setIsAuthenticated(false);
-            setLoading(false);
-        }
-    } catch (error) {
-        setIsAuthenticated(false);
-    } finally {
-        setLoading(false);
-    }
-}
Index: imaps-frontend/src/scripts/util/zoomStage.js
===================================================================
--- imaps-frontend/src/scripts/util/zoomStage.js	(revision 79a03170cdde4e801d12257ee86723774970427b)
+++ imaps-frontend/src/scripts/util/zoomStage.js	(revision d56544918790c0c3bc50f2f0a98c99f3d2988ccf)
@@ -1,4 +1,4 @@
-export const zoomStage = (e,stage,shift=false) => {
-    if (shift && !e.evt.shiftKey) return;
+export const zoomStage = (e,stage) => {
+    if (!e.evt.shiftKey) return;
 
     e.evt.preventDefault();
