Index: imaps-frontend/src/scripts/base/MapNode.js
===================================================================
--- imaps-frontend/src/scripts/base/MapNode.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/src/scripts/base/MapNode.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,99 @@
+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 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/src/scripts/base/MapShape.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,153 @@
+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.");
+        }
+
+        console.log(config.x,"FFF");
+        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: '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);
+        }
+    }
+
+
+    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");
+    }
+
+
+    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 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
+++ imaps-frontend/src/scripts/base/RenderedMapShape.js	(revision 0c6b92add4cfaedcb91bcd37b45849f142f7d152)
@@ -0,0 +1,89 @@
+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);
+    }
+  }
+}
