From 56475b56fc10f5aa5ffc54ddee3ea93fcd4f87e0 Mon Sep 17 00:00:00 2001
From: fsdavid <daviti1@mail.com>
Date: Tue, 18 May 2021 15:20:38 +0200
Subject: [PATCH] Adding annotation

---
 common/constants.js                           |  11 +-
 .../annotationList.component.ts               |  53 +++
 .../annotationList/annotationList.style.css   |  12 +
 .../annotationList.template.html              | 100 +++++
 .../annotationMode.component.ts               | 363 ++++++++++++++++++
 .../annotationMode/annotationMode.style.css   |   7 +
 .../annotationMode.template.html              |  26 ++
 .../annotationService.service.ts              | 163 ++++++++
 .../editAnnotation.component.ts               | 249 ++----------
 .../editAnnotation/editAnnotation.style.css   |   7 -
 .../editAnnotation.template.html              |  71 +---
 .../groupAnnotationPolygons.pipe.ts           |  31 ++
 src/atlasComponents/userAnnotations/index.ts  |   3 +-
 src/atlasComponents/userAnnotations/module.ts |  15 +-
 .../userAnnotationsCmp.components.ts          | 204 ----------
 .../userAnnotationsCmp.style.css              |  29 --
 .../userAnnotationsCmp.template.html          | 110 ------
 .../atlasViewer.apiService.service.ts         |  15 +-
 .../state/viewerState.store.helper.ts         |  10 +-
 src/services/state/viewerState.store.ts       |  24 +-
 src/services/state/viewerState/actions.ts     |   9 +-
 src/services/state/viewerState/selectors.ts   |   9 +-
 .../topMenu/topMenuCmp/topMenu.components.ts  |   8 +-
 .../topMenu/topMenuCmp/topMenu.template.html  |  43 +--
 src/viewerModule/module.ts                    |   2 +
 .../viewerCmp/viewerCmp.component.ts          |  22 +-
 .../viewerCmp/viewerCmp.template.html         |  69 +++-
 27 files changed, 963 insertions(+), 702 deletions(-)
 create mode 100644 src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
 create mode 100644 src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
 create mode 100644 src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
 create mode 100644 src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
 create mode 100644 src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
 create mode 100644 src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
 create mode 100644 src/atlasComponents/userAnnotations/annotationService.service.ts
 delete mode 100644 src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.style.css
 create mode 100644 src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts
 delete mode 100644 src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.components.ts
 delete mode 100644 src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.style.css
 delete mode 100644 src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.template.html

diff --git a/common/constants.js b/common/constants.js
index 97fcd1559..0b589f5d8 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -54,7 +54,10 @@
 
     // additional volumes
     TOGGLE_SHOW_LAYER_CONTROL: `Show layer control`,
-    ADDITIONAL_VOLUME_CONTROL: 'Additional volumes control'
+    ADDITIONAL_VOLUME_CONTROL: 'Additional volumes control',
+
+    //Viewer mode
+    VIEWER_MODE_ANNOTATING: 'annotating'
   }
 
   exports.IDS = {
@@ -78,6 +81,12 @@
     RECEPTOR_FP_CAPTION: `The receptor densities are visualized as fingerprints (fp), which provide the mean density and standard deviation for each of the analyzed receptor types, averaged across samples.`,
     RECEPTOR_PR_CAPTION: `For a single tissue sample, an exemplary density distribution for a single receptor from the pial surface to the border between layer VI and the white matter.`,
     RECEPTOR_AR_CAPTION: `An exemplary density distribution of a single receptor for one laminar cross-section in a single tissue sample.`,
+
+    // Annotatins
+
+    // Annotations
+    USER_ANNOTATION_LAYER_NAME: 'user_annotations',
+    USER_ANNOTATION_STORE_KEY: `user_landmarks_demo_1`
   }
 
   exports.QUICKTOUR_DESC ={
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
new file mode 100644
index 000000000..3184287ef
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
@@ -0,0 +1,53 @@
+import {Component} from "@angular/core";
+import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+
+@Component({
+  selector: 'annotation-list',
+  templateUrl: './annotationList.template.html',
+  styleUrls: ['./annotationList.style.css']
+})
+export class AnnotationList {
+
+  public annotationFilter: 'all' | 'current' = 'all'
+  public editing = -1
+
+  get annotationsToShow() {
+    return this.ans.annotations
+      .filter(a => (a.type !== 'polygon' || +a.id.split('_')[1] === 0)
+        && (this.annotationFilter === 'all' || a.templateName === this.ans.selectedTemplate))
+  }
+
+  constructor(public ans: AnnotationService) {}
+
+  toggleAnnotationVisibility(annotation) {
+    if (annotation.type === 'polygon') {
+      this.ans.annotations.filter(an => an.id.split('_')[0] === annotation.id.split('_')[0])
+        .forEach(a => this.toggleVisibility(a))
+    } else {
+      this.toggleVisibility(annotation)
+    }
+  }
+
+  toggleVisibility(annotation) {
+    const annotationIndex = this.ans.annotations.findIndex(a => a.id === annotation.id)
+
+    if (this.ans.annotations[annotationIndex].annotationVisible) {
+      this.ans.removeAnnotationFromViewer(annotation.id)
+      this.ans.annotations[annotationIndex].annotationVisible = false
+    } else {
+      this.ans.addAnnotationOnViewer(this.ans.annotations[annotationIndex])
+      this.ans.annotations[annotationIndex].annotationVisible = true
+    }
+    this.ans.storeToLocalStorage()
+  }
+
+  removeAnnotation(annotation) {
+    if (annotation.type === 'polygon') {
+      this.ans.annotations.filter(an => an.id.split('_')[0] === annotation.id.split('_')[0])
+        .forEach(a => this.ans.removeAnnotation(a.id))
+    } else {
+      this.ans.removeAnnotation(annotation.id)
+    }
+  }
+
+}
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css b/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
new file mode 100644
index 000000000..b405d8a9e
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
@@ -0,0 +1,12 @@
+.annotation-content {
+    max-width: 500px;
+    min-width: 300px;
+}
+
+.inactive-filter {
+    color: #bababa;
+}
+
+.selecting-height {
+    max-height: 100px;
+}
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
new file mode 100644
index 000000000..39677b3ed
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
@@ -0,0 +1,100 @@
+<div aria-label="user annotations viewer" class="annotation-content w-100">
+
+    <div aria-label="user annotations header" class="overflow-hidden mt-3 mr-2 ml-2">
+        <div arial-label="user annotations footer" class="d-flex justify-content-between">
+            <div>
+                <button class="mr-1 ml-1" mat-icon-button
+                        disabled
+                        aria-label="Import user annotation"
+                        matTooltip="Import">
+                    <i class="fas fa-file-import"></i>
+                </button>
+                <button class="mr-1 ml-1" mat-icon-button
+                        disabled
+                        aria-label="Export user annotation"
+                        matTooltip="Export">
+                    <i class="fas fa-file-export"></i>
+                </button>
+            </div>
+            <div class="d-flex flex-column">
+                <small [ngClass]="[annotationFilter !== 'all'? 'inactive-filter' : '']"
+                       class="cursor-pointer" (click)="annotationFilter = 'all'">
+                    All landmarks
+                </small>
+                <small [ngClass]="[annotationFilter !== 'current'? 'inactive-filter' : '']"
+                       class="cursor-pointer" (click)="annotationFilter = 'current'">
+                    Current template
+                </small>
+            </div>
+        </div>
+    </div>
+    <mat-divider class="mt-2 mb-2"></mat-divider>
+
+
+    <mat-accordion aria-label="user annotations list"
+                 class="h-100 d-flex flex-column overflow-auto">
+<!--        <mat-expansion-panel hideToggle *ngFor="let annotation of ans.annotations | groupAnnotationPolygons; let i = index;">-->
+        <mat-expansion-panel hideToggle *ngFor="let annotation of annotationsToShow; let i = index;">
+            <mat-expansion-panel-header>
+
+                <mat-panel-title>
+                    <div class="d-flex flex-column align-items-center m-0">
+                        <small class="font-italic">{{annotation.position1}}</small>
+                        <small class="font-italic" *ngIf="annotation.position2"> {{annotation.position2}}</small>
+                    </div>
+                </mat-panel-title>
+
+                <mat-panel-description class="w-100 d-flex align-items-center justify-content-end"
+                                       [matTooltip]="annotation.type">
+                    <span class="mr-2">{{annotation.name}}</span>
+                    <small><i [ngClass]="annotation.type === 'line'? 'fas fa-slash'
+                        : annotation.type === 'bounding box'? 'far fa-square'
+                        : annotation.type === 'ellipsoid'? 'fas fa-bullseye'
+                        : annotation.type === 'polygonParent' || annotation.type === 'polygon'? 'fas fa-draw-polygon'
+                         : 'fas fa-circle'"></i></small>
+                </mat-panel-description>
+
+
+
+            </mat-expansion-panel-header>
+
+
+            <div>
+                <div *ngIf="annotation.description">{{annotation.description}}</div>
+
+                <small>{{annotation.templateName}}</small>
+
+                <div class="d-flex align-items-center justify-content-center w-100">
+                    <button class="mr-1 ml-1" mat-icon-button
+                            aria-label="Hide annotation"
+                            [matTooltip]="annotation.annotationVisible? 'Hide' : 'Show'"
+                            (click)="toggleAnnotationVisibility(annotation)">
+                        <i class="fas far fa-check-circle" *ngIf="annotation.annotationVisible; else notVisible"></i>
+                        <ng-template #notVisible><i class="far fa-circle"></i></ng-template>
+                    </button>
+                    <button class="mr-1 ml-1" mat-icon-button
+                            disabled
+                            aria-label="Export single annotation">
+                        <i class="fas fa-file-export"></i>
+                    </button>
+                    <button class="mr-1 ml-1" mat-icon-button
+                            (click)="editing = i"
+                            aria-label="Edit annotation">
+                        <i class="fas fa-edit"></i>
+                    </button>
+                    <button class="mr-1 ml-1" mat-icon-button
+                            aria-label="Delete annotation"
+                            (click)="removeAnnotation(annotation)">
+                        <i class="fas fa-trash"></i>
+                    </button>
+                </div>
+
+                <edit-annotation [annotation]="annotation" *ngIf="editing === i" (finished)="editing = -1">
+                </edit-annotation>
+            </div>
+
+        </mat-expansion-panel>
+
+    </mat-accordion>
+
+</div>
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
new file mode 100644
index 000000000..c2368a8d4
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
@@ -0,0 +1,363 @@
+import {Component, HostListener, Inject, OnDestroy, OnInit, Optional} from "@angular/core";
+import {select, Store} from "@ngrx/store";
+import {CONST} from "common/constants";
+import {Observable, Subscription} from "rxjs";
+import {getUuid} from "src/util/fn";
+import {VIEWER_INJECTION_TOKEN} from "src/ui/layerbrowser/layerDetail/layerDetail.component";
+import {buffer, debounceTime, distinctUntilChanged, filter, map, switchMapTo, take, takeUntil, tap} from "rxjs/operators";
+import {viewerStateNavigationStateSelector, viewerStateSelectedTemplateSelector} from "src/services/state/viewerState/selectors";
+import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+
+@Component({
+  selector: 'annotating-mode',
+  templateUrl: './annotationMode.template.html',
+  styleUrls: ['./annotationMode.style.css']
+})
+export class AnnotationMode implements OnInit, OnDestroy {
+
+    public selectedType = 0
+
+    public position1: string
+    public position2: string
+    public editingAnnotationId: string
+
+    public selecting = 'position1'
+    public mousePos
+    public navState: any
+
+    private hoverAnnotation$: Observable<{id: string, partIndex: number}>
+    public hoverAnnotation: {id: string, partIndex: number}
+    private onDestroyCb: Function[] = []
+    public subscriptions: Subscription[] = []
+
+    //ToDo remove
+    public dark = true
+
+    private get viewer(){
+      return this.injectedViewer || (window as any).viewer
+    }
+
+    get nehubaViewer() {
+      return (window as any).nehubaViewer
+    }
+    get interactiveViewer() {
+      return (window as any).interactiveViewer
+    }
+
+    constructor(
+        private store$: Store<any>,
+        public ans: AnnotationService,
+        @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer,
+    ) {}
+
+    ngOnInit(): void {
+      // Load annotation layer on init
+      this.ans.loadAnnotationLayer()
+
+      this.hoverAnnotation$ = new Observable<{id: string, partIndex: number}>(obs => {
+        const mouseState = this.viewer.mouseState
+        const cb: () => void = mouseState.changed.add(() => {
+          if (mouseState.active && mouseState.pickedAnnotationLayer === this.ans.addedLayer.layer.annotationLayerState.value) {
+            obs.next({
+              id: mouseState.pickedAnnotationId,
+              partIndex: mouseState.pickedOffset
+            })
+          } else {
+            obs.next(null)
+          }
+        })
+        this.onDestroyCb.push(() => {
+          cb()
+          obs.complete()
+        })
+      }).pipe(
+        distinctUntilChanged((o, n) => {
+          if (o === n) return true
+          return `${o?.id || ''}${o?.partIndex || ''}` === `${n?.id || ''}${n?.partIndex || ''}`
+        })
+      )
+
+      this.subscriptions.push(this.hoverAnnotation$.subscribe(ha => {
+        this.hoverAnnotation = ha
+      }))
+
+      const mouseDown$ = this.interactiveViewer.viewerHandle.mouseEvent.pipe(
+        filter((e: any) => e.eventName === 'mousedown')
+      )
+      const mouseUp$ = this.interactiveViewer.viewerHandle.mouseEvent.pipe(
+        filter((e: any) => e.eventName === 'mouseup')
+      )
+      const mouseMove$ = this.interactiveViewer.viewerHandle.mouseEvent.pipe(
+        filter((e: any) => e.eventName === 'mousemove')
+      )
+
+      // Trigger mouse click on viewer (avoid dragging)
+      this.subscriptions.push(
+        mouseDown$.pipe(
+          switchMapTo(
+            mouseUp$.pipe(
+              takeUntil(mouseMove$),
+            ),
+          ),
+        ).subscribe(event => {
+          setTimeout(() => {
+            this.mouseClick()
+          })
+        })
+      )
+
+      // Dragging - edit hovering annotations while dragging
+      let hovering
+      let hoveringType
+      let hoveringPosition1
+      let hoveringPosition2
+      let draggingStartPosition
+      let hoveringPolygonAnnotations
+      this.subscriptions.push(
+        mouseDown$.pipe(
+          tap(() => {
+            hovering = this.hoverAnnotation
+            if (hovering) {
+              draggingStartPosition = this.mousePos
+              const hoveringAnnotation = this.ans.annotations.find(a => a.id === this.hoverAnnotation.id)
+              if (hoveringAnnotation) {
+                hoveringPosition1 = hoveringAnnotation.position1.split(',')
+                hoveringPosition2 = hoveringAnnotation.position2 ? hoveringAnnotation.position2.split(',') : null
+                hoveringType = this.ans.annotations.find(a => a.id === hovering.id)?.type
+                if (hoveringAnnotation.type === 'polygon') {
+                  hoveringPolygonAnnotations = this.ans.annotations.filter(a => a.id.split('_')[0] === hovering.id.split('_')[0])
+                }
+                hoveringType = this.ans.annotations.find(a => a.id === hovering.id)?.type
+              }
+            }
+          }),
+          switchMapTo(
+            mouseMove$.pipe(
+              takeUntil(mouseUp$),
+            ),
+          ),
+        ).subscribe(event => {
+          if (hovering && this.selecting !== 'position2') {
+            // keep navigation while dragging
+            this.interactiveViewer.viewerHandle.setNavigationLoc(this.navState, false)
+            // make changes to annotations by type
+            //  - when line is hovered move full annotation -
+            //  - when line point is hovered move only point
+            if (this.mousePos) {
+              const dragRange = this.mousePos.map((mp, i) => mp - +draggingStartPosition[i])
+
+              if (hoveringType === 'point') {
+                this.ans.saveAnnotation({id: hovering.id, position1: this.mousePos.join(), type: hoveringType})
+              } else if (hoveringType === 'line') {
+                if (hovering.partIndex === 0) {
+
+                  this.ans.saveAnnotation({id: hovering.id,
+                    position1: hoveringPosition1.map((hp, i) => +hp + dragRange[i]).join(),
+                    position2: hoveringPosition2.map((hp, i) => +hp + dragRange[i]).join(),
+                    type: hoveringType})
+                } else if (hovering.partIndex === 1) {
+                  this.ans.saveAnnotation({id: hovering.id,
+                    position1: this.mousePos.join(),
+                    position2: hoveringPosition2.join(),
+                    type: hoveringType})
+                } else if (hovering.partIndex === 2) {
+                  this.ans.saveAnnotation({id: hovering.id,
+                    position1: hoveringPosition1.join(),
+                    position2: this.mousePos.join(),
+                    type: hoveringType})
+                }
+              } else if (hoveringType === 'bounding box') {
+                this.ans.saveAnnotation({id: hovering.id,
+                  position1: hoveringPosition1.map((hp, i) => +hp + dragRange[i]).join(),
+                  position2: hoveringPosition2.map((hp, i) => +hp + dragRange[i]).join(),
+                  type: hoveringType})
+              } else if (hoveringType === 'ellipsoid') {
+                this.ans.saveAnnotation({id: hovering.id,
+                  position1: hoveringPosition1.map((hp, i) => +hp + dragRange[i]).join(),
+                  position2: hoveringPosition2.join(),
+                  type: hoveringType})
+              } else if (hoveringType === 'polygon') {
+                if (hovering.partIndex === 0) {
+                  hoveringPolygonAnnotations.forEach(pa => {
+                    this.ans.saveAnnotation({
+                      id: pa.id,
+                      position1: pa.position1.split(',').map((hp, i) => +hp + dragRange[i]).join(),
+                      position2: pa.position2.split(',').map((hp, i) => +hp + dragRange[i]).join(),
+                      type: pa.type
+                    })
+                  })
+                } else if (hovering.partIndex === 2) {
+                  this.ans.saveAnnotation({id: hovering.id,
+                    position1: hoveringPosition1.join(),
+                    position2: this.mousePos.join(),
+                    type: hoveringType})
+
+                  const hoveringPolygonNum = +hovering.id.split('_')[1]
+                  const nextPolygon = hoveringPolygonAnnotations.find(hpa => +hpa.id.split('_')[1] === hoveringPolygonNum + 1)
+                  if (nextPolygon) {
+                    this.ans.saveAnnotation({id: nextPolygon.id,
+                      position1: this.mousePos.join(),
+                      position2: nextPolygon.position2,
+                      type: nextPolygon.type})
+                  }
+
+                } else if (hovering.partIndex === 1) {
+                  this.ans.saveAnnotation({id: hovering.id,
+                    position1: this.mousePos.join(),
+                    position2: hoveringPosition2.join(),
+                    type: hoveringType})
+
+                  const hoveringPolygonNum = +hovering.id.split('_')[1]
+                  const prevPolygon = hoveringPolygonAnnotations.find(hpa => +hpa.id.split('_')[1] === hoveringPolygonNum - 1) || null
+                  if (prevPolygon) {
+                    this.ans.saveAnnotation({id: prevPolygon.id,
+                      position1: prevPolygon.position1,
+                      position2: this.mousePos.join(),
+                      type: prevPolygon.type})
+                  }
+                }
+              }
+            }
+          }
+
+        })
+      )
+
+      this.subscriptions.push(
+        this.nehubaViewer.mousePosition.inVoxels
+          .subscribe(floatArr => {
+            this.mousePos = floatArr && floatArr
+
+            if (this.selecting === 'position1' && this.mousePos) {
+              this.position1 = this.mousePos.join()
+            } else if (this.selecting === 'position2' && this.mousePos) {
+              if (this.ans.annotationTypes[this.selectedType].name === 'Ellipsoid') {
+                this.position2 = [
+                  this.ans.getRadii(this.position1.split(',').map(n => +n), this.mousePos),
+                ].join()
+              } else {
+                this.position2 = this.mousePos.join()
+              }
+
+              if (this.position1
+                            && (this.ans.annotationTypes[this.selectedType].type === 'doubleCoordinate'
+                                || this.ans.annotationTypes[this.selectedType].type === 'polygon')
+                            && this.position2) {
+                if (!this.editingAnnotationId) {
+                  this.editingAnnotationId = getUuid()
+                  if (this.ans.annotationTypes[this.selectedType].type === 'polygon') {
+                    this.editingAnnotationId += '_0'
+                  }
+                }
+                this.ans.saveAnnotation({id: this.editingAnnotationId, position1: this.position1,
+                  position2: this.position2,
+                  type: this.ans.annotationTypes[this.selectedType].name})
+              }
+            }
+          }),
+
+        // Double click - end creating polygon
+        mouseUp$.pipe(
+          buffer(mouseUp$.pipe(debounceTime(250))),
+          map((list: any) => list.length),
+          filter(x => x === 2)
+        ).subscribe(() => {
+
+          if (this.ans.annotationTypes[this.selectedType].type === 'polygon') {
+            this.ans.removeAnnotation(this.editingAnnotationId)
+            const splitEditingAnnotationId = this.editingAnnotationId.split('_')
+            const prevAnnotation = this.ans.annotations.find(a => a.id === `${splitEditingAnnotationId[0]}_${+splitEditingAnnotationId[1] - 1}`)
+            if (prevAnnotation.id) this.ans.removeAnnotation(prevAnnotation.id)
+            this.editingAnnotationId = null
+            this.selecting = 'position1'
+          }
+        }),
+
+        this.store$.pipe(
+          select(viewerStateNavigationStateSelector),
+        ).subscribe(nav => {
+          this.navState = nav.position.map(np => np/1e6)
+        }),
+        this.store$.pipe(
+          select(viewerStateSelectedTemplateSelector),
+          take(1)
+        ).subscribe(tmpl => {
+          this.ans.selectedTemplate = tmpl.name
+          this.dark = tmpl.useTheme === 'dark'
+
+          // Set get annotations from the local storage and add them to the viewer
+          if (window.localStorage.getItem(CONST.USER_ANNOTATION_STORE_KEY) && window.localStorage.getItem(CONST.USER_ANNOTATION_STORE_KEY).length) {
+            const annotationsString = window.localStorage.getItem(CONST.USER_ANNOTATION_STORE_KEY)
+            this.ans.annotations = JSON.parse(annotationsString)
+            this.ans.annotations.filter(a => a.annotationVisible && a.templateName === this.ans.selectedTemplate).forEach(a => this.ans.addAnnotationOnViewer(a))
+          }
+        })
+      )
+
+    }
+
+    ngOnDestroy(): void {
+      while (this.onDestroyCb.length > 0) this.onDestroyCb.pop()()
+      this.subscriptions.forEach(s => s.unsubscribe())
+      if (this.ans.addedLayer) {
+        this.viewer.layerManager.removeManagedLayer(this.ans.addedLayer)
+      }
+    }
+
+    @HostListener('document:keydown.escape', ['$event']) onKeydownHandler(event: KeyboardEvent) {
+      if (this.selecting === 'position2' && this.mousePos) {
+        this.ans.removeAnnotation(this.editingAnnotationId)
+        this.editingAnnotationId = null
+        this.selecting = 'position1'
+      }
+    }
+
+    mouseClick() {
+      // Remove annotation
+      if (this.ans.annotationTypes[this.selectedType].type === 'remove' && this.hoverAnnotation) {
+        const hoveringAnnotationObj = this.ans.annotations.find(a => a.id === this.hoverAnnotation.id)
+        if (hoveringAnnotationObj.type === 'polygon') {
+          const polygonAnnotations = this.ans.annotations.filter(a => a.id.split('_')[0] === hoveringAnnotationObj.id.split('_')[0])
+          polygonAnnotations.forEach(pa => this.ans.removeAnnotation(pa.id))
+        } else {
+          this.ans.removeAnnotation(this.hoverAnnotation.id)
+        }
+      }
+      // save annotation by selected annotation type
+      if (this.selecting === 'position1' && this.position1) {
+        if (this.ans.annotationTypes[this.selectedType].type === 'singleCoordinate') {
+          this.ans.saveAnnotation({position1: this.position1,
+            position2: this.position2,
+            type: this.ans.annotationTypes[this.selectedType].name})
+        } else if (this.ans.annotationTypes[this.selectedType].type === 'doubleCoordinate'
+                        || this.ans.annotationTypes[this.selectedType].type === 'polygon') {
+          this.selecting = 'position2'
+        }
+
+      } else if (this.selecting === 'position2' && this.position2 && this.mousePos) {
+        this.ans.saveAnnotation({id: this.editingAnnotationId,
+          position1: this.position1,
+          position2: this.position2,
+          type: this.ans.annotationTypes[this.selectedType].name})
+        if (this.ans.annotationTypes[this.selectedType].type === 'polygon') {
+          this.position1 = this.position2
+          const splitEditingAnnotationId = this.editingAnnotationId.split('_')
+          this.editingAnnotationId = splitEditingAnnotationId[0] + '_' + (+splitEditingAnnotationId[1]+1)
+        } else {
+          this.editingAnnotationId = null
+          this.selecting = 'position1'
+        }
+
+      }
+    }
+
+    public selectAnnotationType = (typeIndex) => {
+      this.selectedType = typeIndex
+      this.editingAnnotationId = null
+      this.mousePos = null
+      this.position2 = null
+      this.position1 = null
+      this.selecting = 'position1'
+    }
+
+}
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
new file mode 100644
index 000000000..2ff0c0d71
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
@@ -0,0 +1,7 @@
+.annotation-toolbar {
+    z-index: 100;
+    width: 40px;
+}
+.annotation-toolbar div {
+
+}
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
new file mode 100644
index 000000000..022ae8cb0
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
@@ -0,0 +1,26 @@
+<div class="pe-all d-flex flex-column justify-content-content annotation-toolbar">
+
+    <div class="d-flex flex-column flex-grow-0 panel-default"
+         [ngStyle]="{backgroundColor: dark? '#424242' : 'white',
+         color: dark? 'antiquewhite' : '#424242'}"
+         style="margin-bottom: 20px;">
+        <button *ngFor="let type of ans.annotationTypes; let i = index"
+                mat-icon-button
+                type="button"
+                (click)="selectAnnotationType(i)"
+                class="mb-2 mt-2"
+                [matTooltip]="type.name"
+                [color]="selectedType === i? 'primary' : 'secondary'">
+            <i [ngClass]="type.class"></i>
+        </button>
+        <button
+                mat-icon-button
+                (click)="ans.disable()"
+                type="button"
+                class="mb-2 mt-2"
+                matTooltip="Disable annotating"
+                color="warn">
+            <i class="fas fa-times"></i>
+        </button>
+    </div>
+</div>
diff --git a/src/atlasComponents/userAnnotations/annotationService.service.ts b/src/atlasComponents/userAnnotations/annotationService.service.ts
new file mode 100644
index 000000000..517f723b6
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationService.service.ts
@@ -0,0 +1,163 @@
+import {ApplicationRef, ChangeDetectorRef, Inject, Injectable, OnDestroy, Optional} from "@angular/core";
+import {CONST} from "common/constants";
+import {viewerStateSetViewerMode} from "src/services/state/viewerState/actions";
+import {Subscription} from "rxjs";
+import {getUuid} from "src/util/fn";
+import {Store} from "@ngrx/store";
+import {VIEWER_INJECTION_TOKEN} from "src/ui/layerbrowser/layerDetail/layerDetail.component";
+import {TemplateCoordinatesTransformation} from "src/services/templateCoordinatesTransformation.service";
+
+const USER_ANNOTATION_LAYER_SPEC = {
+  "type": "annotation",
+  "tool": "annotateBoundingBox",
+  "name": CONST.USER_ANNOTATION_LAYER_NAME,
+  "annotationColor": "#ffee00",
+  "annotations": [],
+}
+
+@Injectable()
+export class AnnotationService implements OnDestroy {
+
+    public annotations = []
+    public addedLayer: any
+    public ellipsoidMinRadius = 0.5
+
+    public selectedTemplate: string
+    public subscriptions: Subscription[] = []
+
+    public annotationTypes = [
+      {name: 'Cursor', class: 'fas fa-mouse-pointer', type: 'move'},
+      {name: 'Point', class: 'fas fa-circle', type: 'singleCoordinate'},
+      {name: 'Line', class: 'fas fa-slash', type: 'doubleCoordinate'},
+      {name: 'Polygon', class: 'fas fa-draw-polygon', type: 'polygon'},
+      {name: 'Bounding box', class: 'far fa-square', type: 'doubleCoordinate'},
+      {name: 'Ellipsoid', class: 'fas fa-bullseye', type: 'doubleCoordinate'},
+      {name: 'Remove', class: 'fas fa-trash', type: 'remove'},
+    ]
+
+    private get viewer(){
+      return this.injectedViewer || (window as any).viewer
+    }
+
+    constructor(private store$: Store<any>,
+                @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer) {}
+
+    public disable = () => {
+      this.store$.dispatch(viewerStateSetViewerMode({payload: null}))
+    }
+
+    public loadAnnotationLayer() {
+      if (!this.viewer) {
+        throw new Error(`viewer is not initialised`)
+      }
+
+      const layer = this.viewer.layerSpecification.getLayer(
+        CONST.USER_ANNOTATION_LAYER_NAME,
+        USER_ANNOTATION_LAYER_SPEC
+      )
+
+      this.addedLayer = this.viewer.layerManager.addManagedLayer(layer)
+
+
+    }
+
+    getRadii(a, b) {
+      const returnArray = [Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]), Math.abs(b[2] - a[2])]
+        .map(n => n === 0? this.ellipsoidMinRadius : n)
+      return returnArray
+    }
+
+    saveAnnotation({id = null,
+      position1 = null, //this.position1,
+      position2 = null, //this.position2,
+      type = null, //this.annotationTypes[this.selectedType].name,
+      description = null,
+      name = null,
+      templateName = null,
+    } = {}) {
+      let annotation = {
+        id: id || getUuid(),
+        annotationVisible: true,
+        description,
+        name,
+        position1,
+        position2,
+        templateName: templateName || this.selectedTemplate,
+        type: type.toLowerCase()
+      }
+
+      const foundIndex = this.annotations.findIndex(x => x.id === annotation.id)
+
+      if (foundIndex >= 0) {
+        annotation = {
+          ...this.annotations[foundIndex],
+          ...annotation
+        }
+        this.annotations[foundIndex] = annotation
+      } else {
+        this.annotations.push(annotation)
+      }
+      this.addAnnotationOnViewer(annotation)
+      this.storeToLocalStorage()
+    }
+
+    addAnnotationOnViewer(annotation) {
+      const annotationLayer = this.viewer.layerManager.getLayerByName(CONST.USER_ANNOTATION_LAYER_NAME).layer
+      const annotations = annotationLayer.localAnnotations.toJSON()
+
+      // ToDo Still some error with the logic
+      // const position1Voxel = this.annotationForm.controls.position1.value.split(',')
+      //   .map((r, i) => r/this.voxelSize[i])
+      // const position2Voxel = this.annotationForm.controls.position2.value.split(',')
+      //   .map((r, i) => r/this.voxelSize[i])
+
+      const position1Voxel = annotation.position1.split(',')
+      const position2Voxel = annotation.position2? annotation.position2.split(',') : ''
+
+      annotations.push({
+        description: annotation.description? annotation.description : '',
+        id: annotation.id,
+        point: annotation.type === 'point'? annotation.position1.split(',') : null,
+        pointA: annotation.type === 'line' || annotation.type === 'bounding box' || annotation.type === 'polygon'?
+          position1Voxel : null,
+        pointB: annotation.type === 'line' || annotation.type === 'bounding box' || annotation.type === 'polygon'?
+          position2Voxel : null,
+        center: annotation.type === 'ellipsoid'?
+          position1Voxel : null,
+        radii: annotation.type === 'ellipsoid'?
+          position2Voxel : null,
+        type: annotation.type === 'bounding box'?  'axis_aligned_bounding_box'
+          : annotation.type === 'polygon'? 'line'
+            : annotation.type.toUpperCase()
+      })
+
+      annotationLayer.localAnnotations.restoreState(annotations)
+    }
+
+
+    removeAnnotation(id) {
+      this.removeAnnotationFromViewer(id)
+      this.annotations = this.annotations.filter(a => a.id !== id)
+      this.storeToLocalStorage()
+    }
+
+    storeToLocalStorage() {
+      // ToDo temporary solution - because impure pipe stucks
+
+
+      window.localStorage.setItem(CONST.USER_ANNOTATION_STORE_KEY, JSON.stringify(this.annotations))
+    }
+
+    removeAnnotationFromViewer(id) {
+      const annotationLayer = this.viewer.layerManager.getLayerByName(CONST.USER_ANNOTATION_LAYER_NAME)?.layer
+      if (annotationLayer) {
+        let annotations = annotationLayer.localAnnotations.toJSON()
+        annotations = annotations.filter(a => a.id !== id)
+        annotationLayer.localAnnotations.restoreState(annotations)
+      }
+    }
+
+    ngOnDestroy(){
+      this.subscriptions.forEach(s => s.unsubscribe())
+    }
+}
diff --git a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
index f797b1e85..981b3ee90 100644
--- a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
+++ b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
@@ -1,276 +1,81 @@
 import {
-  AfterViewInit,
-  ChangeDetectorRef,
   Component,
   EventEmitter,
-  Inject,
   Input,
   OnDestroy,
   OnInit,
-  Optional,
   Output
 } from "@angular/core";
 import { FormBuilder, FormGroup, Validators } from "@angular/forms";
 import { animate, style, transition, trigger } from "@angular/animations";
-import { Observable, Subscription } from "rxjs";
-import { filter } from "rxjs/operators";
-import { select, Store } from "@ngrx/store";
-import { viewerStateSelectedTemplateSelector } from "src/services/state/viewerState/selectors";
-import { NEHUBA_INSTANCE_INJTKN  } from "src/viewerModule/nehuba/util";
+import { Subscription } from "rxjs";
+import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
 
 @Component({
   selector: 'edit-annotation',
   templateUrl: './editAnnotation.template.html',
-  styleUrls: ['./editAnnotation.style.css'],
   animations: [
-    // doesn't do anything?
     trigger(
       'enterAnimation', [
         transition(':enter', [
           style({transform: 'translateY(100%)', opacity: 0}),
           animate('100ms', style({transform: 'translateY(0)', opacity: 1}))
         ]),
-        // transition(':leave', [
-        //   style({transform: 'translateY(0)', opacity: 1}),
-        //   animate('100ms', style({transform: 'translateY(100%)', opacity: 0}))
-        // ])
       ]
     )
   ],
 })
 export class EditAnnotationComponent implements OnInit, OnDestroy {
 
-    @Input() editingAnnotation: any
-    @Input() showOnFocus = false
-    @Input() cursorOut = false
+    @Input() annotation: any
 
-    @Output() saveAnnotation: EventEmitter<any> = new EventEmitter()
-    @Output() selectingOutput: EventEmitter<any> = new EventEmitter()
-    @Output() editingMode: EventEmitter<any> = new EventEmitter()
+    @Output() finished: EventEmitter<any> = new EventEmitter()
 
-    public selecting: string
-    public position1Selected = false
-    public position2Selected = false
-
-    public showFull = false
     public annotationForm: FormGroup
-    public loading = false
-    public mousePos
-
-    public selectedTemplate: string
-    public ellipsoidMinRadius = 0.2
-
-    // public voxelSize
 
     public subscriptions: Subscription[] = []
 
-    public annotationTypes = [{name: 'Point', class: 'fas fa-circle'},
-      {name: 'Line', class: 'fas fa-slash', twoCoordinates: true},
-      {name: 'Bounding box', class: 'far fa-square', twoCoordinates: true},
-      {name: 'Ellipsoid', class: 'fas fa-bullseye', twoCoordinates: true}]
-    public selectedType: any
-
-    get nehubaViewer() {
-      return (window as any).nehubaViewer
-    }
-    get interactiveViewer() {
-      return (window as any).interactiveViewer
-    }
-
-    private get viewer(){
-      return (window as any).viewer
-    }
-
     constructor(
       private formBuilder: FormBuilder,
-      private changeDetectionRef: ChangeDetectorRef,
-      private store: Store<any>,
+      public ans: AnnotationService
     ) {
       this.annotationForm = this.formBuilder.group({
-        id: [{value: null, disabled: true}],
-        position1: [{value: '', disabled: this.loading}],
-        position2: [{value: '', disabled: this.loading}],
-        name: [{value: '', disabled: this.loading}, {
+        id: [{value: 'null'}],
+        position1: [{value: ''}],
+        position2: [{value: ''}],
+        name: [{value: ''}, {
           validators: [Validators.maxLength(200)]
         }],
-        description: [{value: '', disabled: this.loading}, {
+        description: [{value: ''}, {
           validators: [Validators.maxLength(1000)]
         }],
         templateName: [{value: ''}],
-        type: [{value: 'point'}],
-        annotationVisible: [true]
+        type: [{value: ''}],
+        annotationVisible: [{value: true}]
       })
     }
 
     ngOnInit() {
-      this.selectType(this.annotationTypes[0])
-
-      this.subscriptions.push(
-        this.nehubaViewer.mousePosition.inVoxels
-          .subscribe(floatArr => {
-            // this.mousePos = floatArr && Array.from(floatArr).map((val: number) => val / 1e6)
-            this.mousePos = floatArr && floatArr
-
-            if (this.selecting === 'position1' && this.mousePos) {
-              this.annotationForm.controls.position1.setValue(this.mousePos.join())
-            } else if (this.selecting === 'position2' && this.mousePos) {
-              if (this.annotationForm.controls.type.value === 'ellipsoid') {
-                this.annotationForm.controls.position2.setValue([
-                  this.getRadii(this.annotationForm.controls.position1.value.split(',').map(n => +n), this.mousePos),
-                ].join())
-              } else {
-                this.annotationForm.controls.position2.setValue(this.mousePos.join())
-              }
-
-              if (this.annotationForm.controls.position1.value
-                  && this.selectedType.twoCoordinates
-                  && this.annotationForm.controls.position2.value) {
-                this.setAnnotation()
-              }
-            }
-          }),
-
-        this.interactiveViewer.viewerHandle.mouseEvent.pipe(
-          filter((e: any) => e.eventName === 'click')
-        ).subscribe(() => {
-          if (this.selecting === 'position1' && this.annotationForm.controls.position1.value) {
-            this.selectPosition1()
-            if (this.selectedType.twoCoordinates) {
-              this.changeSelectingPoint('position2')
-            } else {
-              this.changeSelectingPoint('')
-            }
-            this.changeDetectionRef.detectChanges()
-          } else if (this.selecting === 'position2' && this.mousePos) {
-            this.selectPosition2()
-          }
-        }),
-        this.store.pipe(
-          select(viewerStateSelectedTemplateSelector)
-        ).subscribe(tmpl => {
-          this.annotationForm.controls.templateName.setValue(tmpl.name)
-          this.selectedTemplate = tmpl.name
-        })
-      )
-
-      // this.voxelSize = this.nehubaViewer.config.dataset.initialNgState.navigation.pose.position.voxelSize
-    }
-
-    changeSelectingPoint(selecting) {
-      this.selecting = selecting
-      this.selectingOutput.emit(selecting)
-    }
-
-    selectPosition1() {
-      this.position1Selected = true
-      if (!this.selectedType.twoCoordinates) {
-        this.changeSelectingPoint('')
-        this.setAnnotation()
-      }
-
-    }
-
-    selectPosition2() {
-      this.position2Selected = true
-      this.changeSelectingPoint('')
-      this.changeDetectionRef.detectChanges()
-
-      if (this.position1Selected) {
-        this.changeSelectingPoint('')
-        this.setAnnotation()
-      }
+      this.annotationForm.controls.id.setValue(this.annotation.id)
+      this.annotationForm.controls.position1.setValue(this.annotation.position1)
+      this.annotationForm.controls.position2.setValue(this.annotation.position2)
+      this.annotationForm.controls.name.setValue(this.annotation.name)
+      this.annotationForm.controls.description.setValue(this.annotation.description)
+      this.annotationForm.controls.templateName.setValue(this.annotation.templateName)
+      this.annotationForm.controls.type.setValue(this.annotation.type)
+      this.annotationForm.controls.annotationVisible.setValue(this.annotation.annotationVisible)
     }
 
-    position1CursorOut() {
-      if (this.annotationForm.controls.position1.value && !this.cursorOut) {
-        this.selectPosition1()
-      }
-    }
-    position2CursorOut() {
-      if (this.annotationForm.controls.position2.value && !this.cursorOut) {
-        this.selectPosition2()
-      }
-    }
-
-    selectType(type) {
-      this.selectedType = type
-      this.annotationForm.controls.type.setValue(type.name.toLowerCase())
-      this.annotationForm.controls.position1.setValue('')
-      this.annotationForm.controls.position2.setValue('')
-      if (!this.showOnFocus || this.showFull) this.changeSelectingPoint('position1')
-      this.position1Selected = false
-      this.position2Selected = false
-    }
-
-    focusInName() {
-      if (this.showOnFocus) {
-        if (!this.showFull) {
-          this.changeSelectingPoint('position1')
-        }
-        this.showFull = true
-        this.editingMode.emit(this.showFull)
-      }
-    }
-
-    setAnnotation() {
-      const annotationLayer = this.viewer.layerManager.getLayerByName('user_annotations').layer
-      const annotations = annotationLayer.localAnnotations.toJSON()
-
-      // ToDo Still some error with the logic
-      // const position1Voxel = this.annotationForm.controls.position1.value.split(',')
-      //   .map((r, i) => r/this.voxelSize[i])
-      // const position2Voxel = this.annotationForm.controls.position2.value.split(',')
-      //   .map((r, i) => r/this.voxelSize[i])
-
-      const position1Voxel = this.annotationForm.controls.position1.value.split(',')
-      const position2Voxel = this.annotationForm.controls.position2.value.split(',')
-
-      annotations.push({
-        description: this.annotationForm.controls.description.value? this.annotationForm.controls.description.value : '',
-        id: 'adding',
-        point: this.annotationForm.controls.type.value === 'point'? this.annotationForm.controls.position1.value.split(',') : null,
-        pointA: this.annotationForm.controls.type.value === 'line' || this.annotationForm.controls.type.value === 'bounding box'?
-          position1Voxel : null,
-        pointB: this.annotationForm.controls.type.value === 'line' || this.annotationForm.controls.type.value === 'bounding box'?
-          position2Voxel : null,
-        center: this.annotationForm.controls.type.value === 'ellipsoid'?
-          position1Voxel : null,
-        radii: this.annotationForm.controls.type.value === 'ellipsoid'?
-          position2Voxel : null,
-        type: this.annotationForm.controls.type.value !== 'bounding box'?
-          this.annotationForm.controls.type.value.toUpperCase() : 'axis_aligned_bounding_box'
-      })
-
-      annotationLayer.localAnnotations.restoreState(annotations)
-    }
-
-    getRadii(a, b) {
-      const returnArray = [Math.abs(b[0] - a[0]), Math.abs(b[1] - a[1]), Math.abs(b[2] - a[2])]
-        .map(n => n === 0? this.ellipsoidMinRadius : n)
-      return returnArray
-    }
-
-    removeLoadingAnnotation() {
-      const annotationLayer = this.viewer.layerManager.getLayerByName('user_annotations')?.layer
-      if (annotationLayer) {
-        const annotations = annotationLayer.localAnnotations.toJSON()
-        annotationLayer.localAnnotations.restoreState(annotations.filter(a => a.id !== 'adding'))
-      }
-    }
 
     submitForm() {
       if (this.annotationForm.valid) {
-        // this.annotationForm.controls.annotationVisible.setValue('true')
-        this.saveAnnotation.emit(this.annotationForm.value)
+        this.ans.saveAnnotation(this.annotationForm.value)
         this.cancelEditing()
       }
     }
 
     cancelEditing() {
-      if (this.showOnFocus) {
-        this.showFull = false
-        this.editingMode.emit(this.showFull)
-      }
+      this.finished.emit()
       this.resetForm()
     }
 
@@ -279,17 +84,7 @@ export class EditAnnotationComponent implements OnInit, OnDestroy {
       this.annotationForm.markAsPristine()
       this.annotationForm.markAsUntouched()
 
-      // Set form defaults
       this.annotationForm.controls.annotationVisible.setValue(true)
-      this.annotationForm.controls.templateName.setValue(this.selectedTemplate)
-      this.annotationForm.controls.templateName.setValue(this.selectedTemplate)
-
-      this.position1Selected = false
-      this.position1Selected = false
-      this.selectType(this.annotationTypes[0])
-      this.removeLoadingAnnotation()
-      this.changeSelectingPoint('')
-
       Object.keys(this.annotationForm.controls).forEach(key => {
         this.annotationForm.get(key).setErrors(null)
       })
diff --git a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.style.css b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.style.css
deleted file mode 100644
index fa79116ce..000000000
--- a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.style.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.selectedType {
-
-}
-
-.short-input {
-    max-width: 200px;
-}
diff --git a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
index 515ffb62c..a52351f57 100644
--- a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
+++ b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
@@ -4,70 +4,39 @@
       (keydown.enter)="!annotationForm.invalid? submitForm() : null"
       (ngSubmit)="submitForm()">
 
-    <mat-form-field *ngIf="!(showFull && cursorOut && selecting)"
-            [ngClass]="!showOnFocus || showFull? 'w-100' : 'short-input'">
-        <mat-label>{{!showOnFocus || showFull ? 'name' : '+ Annotate'}}</mat-label>
-        <input (focusin)="focusInName()"
-               name="name"
-               formControlName="name"
-               matInput>
-    </mat-form-field>
 
-    <div *ngIf="!showOnFocus || showFull"
-         class="w-100"
+    <div class="w-100"
          [@enterAnimation]>
-
-        <div class="w-100 d-flex justify-content-center">
-            <div class="d-flex flex-column align-items-center">
-                <small *ngIf="!(showFull && cursorOut && selecting)">Annotation type</small>
-                <div>
-                    <button *ngFor="let type of annotationTypes"
-                            mat-icon-button
-                            type="button"
-                            [matTooltip]="type.name"
-                            [color]="type.name === selectedType.name? 'primary' : null"
-                            (click)="selectType(type)">
-                        <i [ngClass]="type.class"></i>
-                    </button>
-                </div>
-            </div>
-        </div>
-
+        <mat-form-field class="w-100">
+            <mat-label>Name</mat-label>
+            <input name="name"
+                   formControlName="name"
+                   matInput>
+        </mat-form-field>
         <div class="d-flex w-100">
             <div class="d-flex flex-column align-items-center w-100">
-                <mat-form-field class="w-100 annotation-editing-body"
-                    [ngStyle]="{border: cursorOut && selecting === 'position1'? '2px solid' : null}">
-                    <mat-label *ngIf="selectedType.name !== 'Ellipsoid'">position {{selectedType.twoCoordinates && ' 1'}}</mat-label>
-                    <mat-label *ngIf="selectedType.name === 'Ellipsoid'">center (vox)</mat-label>
+                <mat-form-field class="w-100 annotation-editing-body">
+                    <mat-label *ngIf="annotation.type !== 'ellipsoid'">Position {{annotation.position2 && ' 1'}}</mat-label>
+                    <mat-label *ngIf="annotation.type === 'ellipsoid'">Center (vox)</mat-label>
                     <div>
-                    <input type="text" name="position1"
-                           placeholder="0,0,0"
-                           class="pr-4"
-                           formControlName="position1" matInput
-                           (focusin)="position1Selected = false; changeSelectingPoint('position1')"
-                           (focusout)="position1CursorOut()">
-                        <i *ngIf="selecting === 'position1'" class="fas fa-crosshairs" style="margin-left: -20px;"></i>
-                        <i *ngIf="position1Selected && !(cursorOut && selecting === 'position1')" class="fas fa-check-circle" style="margin-left: -20px;"></i>
+                        <input type="text" name="position1"
+                               placeholder="0,0,0"
+                               class="pr-4"
+                               formControlName="position1"
+                               matInput>
                     </div>
                 </mat-form-field>
-                <small *ngIf="cursorOut && selecting === 'position1'" style="margin-top: -20px;">selecting</small>
             </div>
 
-            <div class="d-flex flex-column align-items-center w-100" *ngIf="selectedType.twoCoordinates">
-                <mat-form-field class="w-100 annotation-editing-body"
-                                [ngStyle]="{border: cursorOut && selecting === 'position2'? '2px solid' : null}">
-                    <mat-label *ngIf="selectedType.name !== 'Ellipsoid'">position 2 (vox)</mat-label>
-                    <mat-label *ngIf="selectedType.name === 'Ellipsoid'">radii</mat-label>
+            <div class="d-flex flex-column align-items-center w-100" *ngIf="annotation.position2">
+                <mat-form-field class="w-100 annotation-editing-body">
+                    <mat-label *ngIf="annotation.type !== 'ellipsoid'">Position 2 (vox)</mat-label>
+                    <mat-label *ngIf="annotation.type === 'ellipsoid'">Radii</mat-label>
                     <input type="text" name="position2"
                            class="pr-4"
                            placeholder="0,0,0"
-                           formControlName="position2" matInput
-                           (focusin)="position2Selected = false; changeSelectingPoint('position2')"
-                           (focusout)="position2CursorOut()">
-                    <i *ngIf="selecting === 'position2'" class="fas fa-crosshairs" style="margin-left: -20px;"></i>
-                    <i *ngIf="position2Selected && !(cursorOut && selecting === 'position2')" class="fas fa-check-circle" style="margin-left: -20px;"></i>
+                           formControlName="position2" matInput>
                 </mat-form-field>
-                <small *ngIf="cursorOut && selecting === 'position2'" style="margin-top: -20px;">selecting</small>
             </div>
         </div>
 
diff --git a/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts b/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts
new file mode 100644
index 000000000..0b85117b8
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts
@@ -0,0 +1,31 @@
+import {Pipe, PipeTransform} from "@angular/core";
+
+@Pipe({ name: 'groupAnnotationPolygons'})
+export class GroupAnnotationPolygons implements PipeTransform {
+
+  transform(annotations: any[]) {
+
+    // let transformed = [...annotations]
+
+    // for (let i = 0; i<annotations.length; i++) {
+    //   if (annotations[i].type === 'polygon') {
+    //     const annotationId = annotations[i].id.split('_')
+    //     if (!transformed.find(t => t.id === annotationId[0])) {
+    //       const polygonAnnotations = annotations.filter(a => a.id.split('_')[0] === annotationId[0])
+    //
+    //       transformed = transformed.filter(a => a.id.split('_')[0] !== annotationId[0])
+    //
+    //       transformed.push({
+    //         id: annotationId[0],
+    //         type: 'polygonParent',
+    //         annotations: polygonAnnotations,
+    //         templateName: annotations[i].templateName
+    //       })
+    //     }
+    //   }
+    // }
+    // return transformed
+
+    return annotations.filter(a => a.type !== 'polygon' || +a.id.split('_')[1] === 0)
+  }
+}
diff --git a/src/atlasComponents/userAnnotations/index.ts b/src/atlasComponents/userAnnotations/index.ts
index 8e75162e0..6da0cda7d 100644
--- a/src/atlasComponents/userAnnotations/index.ts
+++ b/src/atlasComponents/userAnnotations/index.ts
@@ -1,2 +1,3 @@
-export { UserAnnotationsComponent } from "./userAnnotationsCmp/userAnnotationsCmp.components";
+export { AnnotationMode } from "./annotationMode/annotationMode.component";
+export { AnnotationList } from "./annotationList/annotationList.component";
 export { UserAnnotationsModule } from "./module";
diff --git a/src/atlasComponents/userAnnotations/module.ts b/src/atlasComponents/userAnnotations/module.ts
index 942cab632..e54f72cee 100644
--- a/src/atlasComponents/userAnnotations/module.ts
+++ b/src/atlasComponents/userAnnotations/module.ts
@@ -2,10 +2,13 @@ import {NgModule} from "@angular/core";
 import {CommonModule} from "@angular/common";
 import {DatabrowserModule} from "src/atlasComponents/databrowserModule";
 import {AngularMaterialModule} from "src/ui/sharedModules/angularMaterial.module";
-import {UserAnnotationsComponent} from "src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.components";
 import {FormsModule, ReactiveFormsModule} from "@angular/forms";
 import {EditAnnotationComponent} from "src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component";
 import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
+import {AnnotationMode} from "src/atlasComponents/userAnnotations/annotationMode/annotationMode.component";
+import {AnnotationList} from "src/atlasComponents/userAnnotations/annotationList/annotationList.component";
+import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+import {GroupAnnotationPolygons} from "src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe";
 
 @NgModule({
   imports: [
@@ -17,11 +20,17 @@ import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
     AngularMaterialModule,
   ],
   declarations: [
-    UserAnnotationsComponent,
     EditAnnotationComponent,
+    AnnotationMode,
+    AnnotationList,
+    GroupAnnotationPolygons
+  ],
+  providers: [
+    AnnotationService
   ],
   exports: [
-    UserAnnotationsComponent,
+    AnnotationMode,
+    AnnotationList
   ]
 })
 
diff --git a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.components.ts b/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.components.ts
deleted file mode 100644
index 9e19c5f2d..000000000
--- a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.components.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-import { Component, EventEmitter, OnDestroy, OnInit, Output} from "@angular/core";
-import { Observable, Subscription } from "rxjs";
-import { distinctUntilChanged } from "rxjs/operators";
-import { getUuid } from 'src/util/fn'
-
-const USER_ANNOTATION_LAYER_NAME = 'USER_ANNOTATION_LAYER_NAME'
-const USER_ANNOTATION_LAYER_SPEC = {
-  "type": "annotation",
-  "tool": "annotateBoundingBox",
-  "name": USER_ANNOTATION_LAYER_NAME,
-  "annotationColor": "#ffee00",
-  "annotations": [],
-}
-const USER_ANNOTATION_STORE_KEY = `user_landmarks_demo_1`
-
-@Component({
-  selector: 'user-annotations',
-  templateUrl: './userAnnotationsCmp.template.html',
-  styleUrls: ['./userAnnotationsCmp.style.css']
-})
-export class UserAnnotationsComponent implements OnInit, OnDestroy {
-
-  public landmarkFilter: 'all' | 'current' = 'all'
-  public cursorOut = false
-  public selecting: string
-  public editingMode = false
-  public minimized = false
-
-  public hovering = -1
-  public expanded = -1
-
-  public annotations = []
-  private hoverAnnotation$: Observable<{id: string, partIndex: number}>
-
-  @Output() close: EventEmitter<any> = new EventEmitter()
-
-  private subscription: Subscription[] = []
-  private onDestroyCb: (() => void )[] = []
-
-  private get viewer(){
-    return (window as any).viewer
-  }
-
-  ngOnDestroy(): void {
-    while(this.onDestroyCb.length) this.onDestroyCb.pop()()
-    while(this.subscription.length) this.subscription.pop().unsubscribe()
-
-    if (!this.viewer) {
-      throw new Error(`this.viewer is undefined`)
-    }
-    const annotationLayer = this.viewer.layerManager.getLayerByName(USER_ANNOTATION_LAYER_NAME)
-    if (annotationLayer) {
-      this.viewer.layerManager.removeManagedLayer(annotationLayer)
-    }
-  }
-
-  ngOnInit(): void {
-    this.loadAnnotationLayer()
-
-    if (window.localStorage.getItem(USER_ANNOTATION_STORE_KEY) && window.localStorage.getItem(USER_ANNOTATION_STORE_KEY).length) {
-      const annotationsString = window.localStorage.getItem(USER_ANNOTATION_STORE_KEY)
-      this.annotations = JSON.parse(annotationsString)
-      this.annotations.filter(a => a.annotationVisible).forEach(a => this.addAnnotationOnViewer(a))
-    }
-  }
-
-  public loadAnnotationLayer() {
-    if (!this.viewer) {
-      throw new Error(`viewer is not initialised`)
-    }
-
-    const layer = this.viewer.layerSpecification.getLayer(
-      USER_ANNOTATION_LAYER_NAME,
-      USER_ANNOTATION_LAYER_SPEC
-    )
-
-    const addedLayer = this.viewer.layerManager.addManagedLayer(layer)
-    
-    this.hoverAnnotation$ = new Observable<{id: string, partIndex: number}>(obs => {
-      const mouseState = this.viewer.mouseState
-      const cb: () => void = mouseState.changed.add(() => {
-        if (mouseState.active && mouseState.pickedAnnotationLayer === addedLayer.layer.annotationLayerState.value) {
-          obs.next({
-            id: mouseState.pickedAnnotationId,
-            partIndex: mouseState.pickedOffset
-          })
-        } else {
-          obs.next(null)
-        }
-      })
-      this.onDestroyCb.push(() => {
-        cb()
-        obs.complete()
-      })
-    }).pipe(
-      distinctUntilChanged((o, n) => {
-        if (o === n) return true
-        return `${o?.id || ''}${o?.partIndex || ''}` === `${n?.id || ''}${n?.partIndex || ''}`
-      })
-    )
-  }
-
-  saveAnnotation(annotation) {
-    if (!annotation.id) {
-      annotation.id = getUuid()
-    }
-
-    const foundIndex = this.annotations.findIndex(x => x.id === annotation.id)
-    if (foundIndex >= 0) {
-      this.annotations[foundIndex] = annotation
-    } else {
-      this.annotations.push(annotation)
-    }
-
-    if (annotation.annotationVisible) {
-      this.addAnnotationOnViewer(annotation)
-    }
-    this.storeToLocalStorage()
-  }
-
-  addAnnotationOnViewer(annotation) {
-    const annotationLayer = this.viewer.layerManager.getLayerByName(USER_ANNOTATION_LAYER_NAME).layer
-    const annotations = annotationLayer.localAnnotations.toJSON()
-
-    // ToDo Still some error with the logic
-    // const position1Voxel = this.annotationForm.controls.position1.value.split(',')
-    //   .map((r, i) => r/this.voxelSize[i])
-    // const position2Voxel = this.annotationForm.controls.position2.value.split(',')
-    //   .map((r, i) => r/this.voxelSize[i])
-
-    const position1Voxel = annotation.position1.split(',')
-    const position2Voxel = annotation.position2.split(',')
-
-    annotations.push({
-      description: annotation.description? annotation.description : '',
-      id: annotation.id,
-      point: annotation.type === 'point'? annotation.position1.split(',') : null,
-      pointA: annotation.type === 'line' || annotation.type === 'bounding box'?
-        position1Voxel : null,
-      pointB: annotation.type === 'line' || annotation.type === 'bounding box'?
-        position2Voxel : null,
-      center: annotation.type === 'ellipsoid'?
-        position1Voxel : null,
-      radii: annotation.type === 'ellipsoid'?
-        position2Voxel : null,
-      type: annotation.type !== 'bounding box'?
-        annotation.type.toUpperCase() : 'axis_aligned_bounding_box'
-    })
-
-    annotationLayer.localAnnotations.restoreState(annotations)
-  }
-
-  toggleAnnotationView(i) {
-    if (this.expanded === i) {
-      this.expanded = -1
-    } else {
-      this.expanded = i
-    }
-  }
-
-  toggleAnnotationVisibility(id) {
-    const annotationIndex = this.annotations.findIndex(a => a.id === id)
-
-    if (this.annotations[annotationIndex].annotationVisible) {
-      this.removeAnnotationFromViewer(id)
-      this.annotations[annotationIndex].annotationVisible = false
-    } else {
-      this.addAnnotationOnViewer(this.annotations[annotationIndex])
-      this.annotations[annotationIndex].annotationVisible = true
-    }
-    this.storeToLocalStorage()
-  }
-
-  removeAnnotation(id) {
-    this.removeAnnotationFromViewer(id)
-    this.annotations = this.annotations.filter(a => a.id !== id)
-    this.expanded = -1
-    this.storeToLocalStorage()
-  }
-
-  storeToLocalStorage() {
-    window.localStorage.setItem(USER_ANNOTATION_STORE_KEY, JSON.stringify(this.annotations))
-  }
-
-  removeAnnotationFromViewer(id) {
-    const annotationLayer = this.viewer.layerManager.getLayerByName(USER_ANNOTATION_LAYER_NAME)?.layer
-    if (annotationLayer) {
-      let annotations = annotationLayer.localAnnotations.toJSON()
-      annotations = annotations.filter(a => a.id !== id)
-      annotationLayer.localAnnotations.restoreState(annotations)
-    }
-  }
-
-  // navigate(coord) {
-  //   this.store.dispatch(
-  //     viewerStateChangeNavigation({
-  //       navigation: {
-  //         position: coord,
-  //         animation: {},
-  //       }
-  //     })
-  //   )
-  // }
-}
diff --git a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.style.css b/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.style.css
deleted file mode 100644
index ed1848825..000000000
--- a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.style.css
+++ /dev/null
@@ -1,29 +0,0 @@
-.annotation-content {
-    max-width: 500px;
-}
-
-.inactive-filter {
-    color: #bababa;
-}
-
-.selecting-height {
-    max-height: 100px;
-}
-
-.annotation-list {
-    max-height: 400px;
-}
-
-.minimize-icon {
-    position: absolute;
-    top: 10px;
-    right: 10px;
-}
-
-.minimized {
-    max-height: 30px;
-}
-
-.minimize-row {
-    min-height: 30px;
-}
diff --git a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.template.html b/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.template.html
deleted file mode 100644
index 8a79dfdd8..000000000
--- a/src/atlasComponents/userAnnotations/userAnnotationsCmp/userAnnotationsCmp.template.html
+++ /dev/null
@@ -1,110 +0,0 @@
-<div class="w-100 d-flex justify-content-center position-relative overflow-hidden"
-     (mouseleave)="cursorOut = true" (mouseenter)="cursorOut=false"
-     [ngClass]="selecting && cursorOut? 'selecting-height' : minimized? 'minimized' : ''">
-    <div class="minimize-icon" *ngIf="!editingMode">
-        <i *ngIf="minimized" class="fas fa-plus cursor-pointer" (click)="minimized=false"></i>
-        <i *ngIf="!minimized" class="fas fa-minus cursor-pointer" (click)="minimized=true"></i>
-        <i class="ml-3 fas fa-times cursor-pointer" (click)="close.emit()"></i>
-    </div>
-    <div aria-label="user annotations viewer" class="annotation-content w-100">
-        <div class="minimize-row d-flex align-items-center" *ngIf="minimized" (click)="minimized=false">
-            {{this.annotations.length}} - Annotations
-        </div>
-
-        <div aria-label="user annotations header" class="overflow-hidden">
-            <edit-annotation [cursorOut]="cursorOut"
-                             [showOnFocus]="true"
-                             (saveAnnotation)="saveAnnotation($event)"
-                             (editingMode)="editingMode = $event"
-                             (selectingOutput)="this.selecting = $event"></edit-annotation>
-        </div>
-
-        <div *ngIf="!editingMode"
-             aria-label="user annotations list"
-             class="annotation-list d-flex flex-column overflow-auto mb-2">
-            <div *ngFor="let annotation of annotations; let i = index;"
-                      [ngClass]="expanded === i? 'mat-elevation-z6' : hovering === i? 'mat-elevation-z8' : 'mat-elevation-z2'"
-                      (mouseenter)="hovering = i"
-                      (mouseleave)="hovering = -1"
-                 class="p-2 pr-4 pl-4 m-2">
-                <div class="d-flex align-items-center justify-content-between"
-                     (click)="toggleAnnotationView(i)">
-                    <div class="d-flex align-items-center">
-                        <small class="mr-4"><i [ngClass]="annotation.type === 'line'? 'fas fa-slash'
-                        : annotation.type === 'bounding box'? 'far fa-square'
-                        : annotation.type === 'ellipsoid'? 'fas fa-bullseye' : 'fas fa-circle'"></i></small>
-                        <div>
-                            <div *ngIf="annotation.name">{{annotation.name}}</div>
-                            <div matCardSubtitle class="m-0" *ngIf="annotation.templateName">{{annotation.templateName}}</div>
-                            <div matCardSubtitle class="d-flex align-items-center m-0">
-                                <small class="font-italic">{{annotation.position1}}</small>
-                                <small class="font-italic" *ngIf="annotation.position2"> • {{annotation.position2}}</small>
-                            </div>
-                        </div>
-                    </div>
-                    <div>
-                        <button class="mr-1 ml-1" mat-icon-button
-                                aria-label="Toggle annotation view">
-                            <i class="fas" [ngClass]="expanded === i? 'fa-arrow-up' : 'fa-arrow-down'"></i>
-                        </button>
-                    </div>
-                </div>
-                <div *ngIf="expanded === i">
-                    <div *ngIf="annotation.description">{{annotation.description}}</div>
-                    <div class="d-flex align-items-center justify-content-center w-100">
-                        <button class="mr-1 ml-1" mat-icon-button
-                                aria-label="Hide annotation"
-                                [matTooltip]="annotation.annotationVisible? 'Hide' : 'Show'"
-                                (click)="toggleAnnotationVisibility(annotation.id)">
-                            <i class="far fa-circle" *ngIf="!annotation.annotationVisible"></i>
-                            <i class="fas far fa-check-circle" *ngIf="annotation.annotationVisible"></i>
-                        </button>
-                        <button class="mr-1 ml-1" mat-icon-button
-                                disabled
-                                aria-label="Export single annotation">
-                            <i class="fas fa-file-export"></i>
-                        </button>
-                        <button class="mr-1 ml-1" mat-icon-button
-                                disabled
-                                aria-label="Edit annotation">
-                            <i class="fas fa-edit"></i>
-                        </button>
-                        <button class="mr-1 ml-1" mat-icon-button
-                                aria-label="Delete annotation"
-                                (click)="removeAnnotation(annotation.id)">
-                            <i class="fas fa-trash"></i>
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </div>
-
-        <mat-divider class="mt-2 mb-2"></mat-divider>
-        <div arial-label="user annotations footer" class="d-flex justify-content-between">
-            <div>
-                <button class="mr-1 ml-1" mat-icon-button
-                        disabled
-                        aria-label="Import user annotation"
-                        matTooltip="Import">
-                    <i class="fas fa-file-import"></i>
-                </button>
-                <button class="mr-1 ml-1" mat-icon-button
-                        disabled
-                        aria-label="Export user annotation"
-                        matTooltip="Export">
-                    <i class="fas fa-file-export"></i>
-                </button>
-            </div>
-            <div class="d-flex flex-column">
-                <small [ngClass]="[landmarkFilter !== 'all'? 'inactive-filter' : '']"
-                       class="cursor-pointer" (click)="landmarkFilter = 'all'">
-                    All landmarks
-                </small>
-                <small [ngClass]="[landmarkFilter !== 'current'? 'inactive-filter' : '']"
-                       class="cursor-pointer" (click)="landmarkFilter = 'current'">
-                    Current template
-                </small>
-            </div>
-        </div>
-    </div>
-</div>
diff --git a/src/atlasViewer/atlasViewer.apiService.service.ts b/src/atlasViewer/atlasViewer.apiService.service.ts
index e7253b284..0833ddd51 100644
--- a/src/atlasViewer/atlasViewer.apiService.service.ts
+++ b/src/atlasViewer/atlasViewer.apiService.service.ts
@@ -6,7 +6,10 @@ import { Observable, Subject, Subscription, from, race, of, } from "rxjs";
 import { distinctUntilChanged, map, filter, startWith, switchMap, catchError, mapTo, take } from "rxjs/operators";
 import { DialogService } from "src/services/dialogService.service";
 import { uiStateMouseOverSegmentsSelector } from "src/services/state/uiState/selectors";
-import { viewerStateFetchedTemplatesSelector } from "src/services/state/viewerState/selectors";
+import {
+  viewerStateFetchedTemplatesSelector,
+  viewerStateViewerModeSelector
+} from "src/services/state/viewerState/selectors";
 import {
   getLabelIndexMap,
   getMultiNgIdsRegionsLabelIndexMap,
@@ -17,6 +20,7 @@ import { ClickInterceptor, CLICK_INTERCEPTOR_INJECTOR } from "src/util";
 import { FRAGMENT_EMIT_RED } from "src/viewerModule/nehuba/nehubaViewer/nehubaViewer.component";
 import { IPluginManifest, PluginServices } from "src/plugin";
 import { ILoadMesh } from 'src/messaging/types'
+import {ARIA_LABELS} from "common/constants";
 
 declare let window
 
@@ -84,6 +88,15 @@ export class AtlasViewerAPIServices implements OnDestroy{
   private s: Subscription[] = []
 
   private onMouseClick(ev: any): boolean{
+
+    // If annotation mode is on, avoid region selection
+    let viewerMode
+    this.store.pipe(
+      select(viewerStateViewerModeSelector),
+      take(1)
+    ).subscribe(vm => viewerMode = vm)
+    if (viewerMode === ARIA_LABELS.VIEWER_MODE_ANNOTATING) return false
+
     const { rs, spec } = this.getNextUserRegionSelectHandler() || {}
     if (!!rs) {
 
diff --git a/src/services/state/viewerState.store.helper.ts b/src/services/state/viewerState.store.helper.ts
index c636776f3..bf5f69fb8 100644
--- a/src/services/state/viewerState.store.helper.ts
+++ b/src/services/state/viewerState.store.helper.ts
@@ -22,6 +22,7 @@ import {
   viewerStateToggleLayer,
   viewerStateToggleRegionSelect,
   viewerStateSelectRegionWithIdDeprecated,
+  viewerStateSetViewerMode,
   viewerStateDblClickOnViewer,
   viewerStateAddUserLandmarks,
   viewreStateRemoveUserLandmarks,
@@ -46,6 +47,7 @@ export {
   viewerStateToggleLayer,
   viewerStateToggleRegionSelect,
   viewerStateSelectRegionWithIdDeprecated,
+  viewerStateSetViewerMode,
   viewerStateDblClickOnViewer,
   viewerStateAddUserLandmarks,
   viewreStateRemoveUserLandmarks,
@@ -143,7 +145,7 @@ export class ViewerStateHelperEffect{
     private store$: Store<any>,
     private actions$: Actions
   ){
-    
+
   }
 }
 
@@ -180,7 +182,7 @@ export function isNewerThan(arr: IHasVersion[], srcObj: IHasId, compObj: IHasId)
     while (currPreviousId) {
       it += 1
       if (it>100) throw new Error(`iteration excced 100, did you include a loop?`)
-      
+
       const curr = arr.find(v => v['@version']['@this'] === currPreviousId)
       if (!curr) throw new Error(`GenNewerVersions error, version id ${currPreviousId} not found`)
       currPreviousId = curr['@version'][ flag ? '@next' : '@previous' ]
@@ -196,8 +198,8 @@ export function isNewerThan(arr: IHasVersion[], srcObj: IHasId, compObj: IHasId)
   for (const obj of GenNewerVersions(false)) {
     if (obj['@version']['@this'] === compObj['@id']) {
       return true
-    } 
+    }
   }
-  
+
   throw new Error(`isNewerThan error, neither srcObj nor compObj exist in array`)
 }
diff --git a/src/services/state/viewerState.store.ts b/src/services/state/viewerState.store.ts
index ef175c5b6..f28fc4109 100644
--- a/src/services/state/viewerState.store.ts
+++ b/src/services/state/viewerState.store.ts
@@ -10,7 +10,7 @@ import { LoggingService } from 'src/logging';
 import { IavRootStoreInterface } from '../stateStore.service';
 import { GENERAL_ACTION_TYPES } from '../stateStore.service'
 import { CLOSE_SIDE_PANEL } from './uiState.store';
-import { 
+import {
   viewerStateSetSelectedRegions,
   viewerStateSetConnectivityRegion,
   viewerStateSelectParcellation,
@@ -24,7 +24,12 @@ import {
   viewerStateNewViewer
 } from './viewerState.store.helper';
 import { cvtNehubaConfigToNavigationObj } from 'src/state';
-import { actionSelectLandmarks, viewerStateChangeNavigation, viewerStateNehubaLayerchanged } from './viewerState/actions';
+import {
+  viewerStateChangeNavigation,
+  viewerStateNehubaLayerchanged,
+  viewerStateSetViewerMode,
+  actionSelectLandmarks
+} from './viewerState/actions';
 import { serialiseParcellationRegion } from "common/util"
 
 export interface StateInterface {
@@ -34,6 +39,8 @@ export interface StateInterface {
   parcellationSelected: any | null
   regionsSelected: any[]
 
+  viewerMode: string
+
   landmarksSelected: any[]
   userLandmarks: IUserLandmark[]
 
@@ -75,6 +82,7 @@ export const defaultState: StateInterface = {
   fetchedTemplates : [],
   loadedNgLayers: [],
   regionsSelected: [],
+  viewerMode: null,
   userLandmarks: [],
   dedicatedView: null,
   navigation: null,
@@ -163,6 +171,12 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part
       regionsSelected: selectRegions,
     }
   }
+  case SET_VIEWER_MODE: {
+    return {
+      ...prevState,
+      viewerMode: action.payload
+    }
+  }
   case DESELECT_LANDMARKS : {
     return {
       ...prevState,
@@ -223,7 +237,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part
     return {
       ...prevState,
       overwrittenColorMap: action.payload || '',
-    }  
+    }
   default :
     return prevState
   }
@@ -250,6 +264,10 @@ export const CHANGE_NAVIGATION = viewerStateChangeNavigation.type
 
 export const SELECT_PARCELLATION = viewerStateSelectParcellation.type
 
+export const DESELECT_REGIONS = `DESELECT_REGIONS`
+export const SELECT_REGIONS_WITH_ID = viewerStateSelectRegionWithIdDeprecated.type
+export const SET_VIEWER_MODE = viewerStateSetViewerMode.type
+export const SELECT_LANDMARKS = `SELECT_LANDMARKS`
 export const SELECT_REGIONS = viewerStateSetSelectedRegions.type
 export const DESELECT_LANDMARKS = `DESELECT_LANDMARKS`
 export const USER_LANDMARKS = `USER_LANDMARKS`
diff --git a/src/services/state/viewerState/actions.ts b/src/services/state/viewerState/actions.ts
index 7ef58b79f..74d44f9b8 100644
--- a/src/services/state/viewerState/actions.ts
+++ b/src/services/state/viewerState/actions.ts
@@ -3,7 +3,7 @@ import { IRegion } from './constants'
 
 export const viewerStateNewViewer = createAction(
   `[viewerState] newViewer`,
-  props<{ 
+  props<{
     selectTemplate: any
     selectParcellation: any
     navigation?: any
@@ -67,7 +67,7 @@ export const viewerStateSelectParcellation = createAction(
 )
 
 export const viewerStateSelectTemplateWithName = createAction(
-  `[viewerState] selectTemplateWithName`, 
+  `[viewerState] selectTemplateWithName`,
   props<{ payload: { name: string } }>()
 )
 
@@ -91,6 +91,11 @@ export const viewerStateSelectRegionWithIdDeprecated = createAction(
   props<{ selectRegionIds: string[] }>()
 )
 
+export const viewerStateSetViewerMode = createAction(
+  `[viewerState] setViewerMode`,
+  props<{payload: string}>()
+)
+
 export const viewerStateDblClickOnViewer = createAction(
   `[viewerState] dblClickOnViewer`,
   props<{ payload: { segments: any, landmark: any, userLandmark: any } }>()
diff --git a/src/services/state/viewerState/selectors.ts b/src/services/state/viewerState/selectors.ts
index 3e13df34b..cb0ac92e8 100644
--- a/src/services/state/viewerState/selectors.ts
+++ b/src/services/state/viewerState/selectors.ts
@@ -18,7 +18,7 @@ const flattenFetchedTemplatesIntoParcellationsReducer = (acc, curr) => {
       useTheme: curr['useTheme']
     }
   })
-  
+
   return acc.concat( parcelations )
 }
 
@@ -91,6 +91,11 @@ export const viewerStateSelectorNavigation = createSelector(
   viewerState => viewerState['navigation']
 )
 
+export const viewerStateViewerModeSelector = createSelector(
+  state => state['viewerState'],
+  viewerState => viewerState['viewerMode']
+)
+
 export const viewerStateGetOverlayingAdditionalParcellations = createSelector(
   state => state[viewerStateHelperStoreName],
   state => state['viewerState'],
@@ -205,7 +210,7 @@ export const viewerStateSelectedTemplateFullInfoSelector = createSelector(
         darktheme: (fullTemplateInfo || {}).useTheme === 'dark'
       }
     })
-  } 
+  }
 )
 
 export const viewerStateContextedSelectedRegionsSelector = createSelector(
diff --git a/src/ui/topMenu/topMenuCmp/topMenu.components.ts b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
index a15328676..46ca24930 100644
--- a/src/ui/topMenu/topMenuCmp/topMenu.components.ts
+++ b/src/ui/topMenu/topMenuCmp/topMenu.components.ts
@@ -11,7 +11,8 @@ import { AuthService } from "src/auth";
 import { IavRootStoreInterface, IDataEntry } from "src/services/stateStore.service";
 import { MatDialog, MatDialogConfig, MatDialogRef } from "@angular/material/dialog";
 import { MatBottomSheet } from "@angular/material/bottom-sheet";
-import { CONST, QUICKTOUR_DESC } from 'common/constants'
+import { CONST, ARIA_LABELS, QUICKTOUR_DESC } from 'common/constants'
+import {viewerStateSetViewerMode} from "src/services/state/viewerState/actions";
 import { IQuickTourData } from "src/ui/quickTour/constrants";
 
 @Component({
@@ -50,6 +51,7 @@ export class TopMenuCmp {
 
   public pluginTooltipText: string = `Plugins and Tools`
   public screenshotTooltipText: string = 'Take screenshot'
+  public annotateTooltipText: string = 'Start annotating'
 
   public quickTourData: IQuickTourData = {
     description: QUICKTOUR_DESC.TOP_MENU,
@@ -90,6 +92,10 @@ export class TopMenuCmp {
     }
   }
 
+  setAnnotatingMode() {
+    this.store$.dispatch(viewerStateSetViewerMode({payload: ARIA_LABELS.VIEWER_MODE_ANNOTATING,}))
+  }
+
   private keyListenerConfigBase = {
     type: 'keydown',
     stop: true,
diff --git a/src/ui/topMenu/topMenuCmp/topMenu.template.html b/src/ui/topMenu/topMenuCmp/topMenu.template.html
index aec870d1a..773d7e82b 100644
--- a/src/ui/topMenu/topMenuCmp/topMenu.template.html
+++ b/src/ui/topMenu/topMenuCmp/topMenu.template.html
@@ -26,12 +26,6 @@
       </ng-container>
     </div>
 
-    <!-- user annotations -->
-    <div iav-fab-speed-dial-child>
-      <ng-container *ngTemplateOutlet="userAnnotationsBtnTmpl">
-      </ng-container>
-    </div>
-
     <!-- help one pager -->
     <div iav-fab-speed-dial-child>
       <ng-container *ngTemplateOutlet="helpBtnTmpl">
@@ -66,10 +60,6 @@
     <ng-container *ngTemplateOutlet="pinnedDatasetBtnTmpl">
     </ng-container>
 
-    <!-- user annotations -->
-    <ng-container *ngTemplateOutlet="userAnnotationsBtnTmpl">
-    </ng-container>
-
     <!-- help one pager -->
     <ng-container *ngTemplateOutlet="helpBtnTmpl">
     </ng-container>
@@ -133,22 +123,6 @@
   </div>
 </ng-template>
 
-<!-- User annotations btn -->
-<ng-template #userAnnotationsBtnTmpl>
-  <div class="btnWrapper"
-    (click)="bottomSheet.open(userAnnotations, {hasBackdrop: false, disableClose: true})"
-    matTooltip="My annotations">
-    <iav-dynamic-mat-button
-      [attr.pinned-datasets-length]="(favDataEntries$ | async)?.length"
-      [iav-dynamic-mat-button-style]="matBtnStyle"
-      [iav-dynamic-mat-button-color]="matBtnColor"
-      iav-dynamic-mat-button-aria-label="Annotations">
-
-      <i class="fas fa-pencil-ruler"></i>
-    </iav-dynamic-mat-button>
-  </div>
-</ng-template>
-
 <ng-template #helpBtnTmpl>
 
   <div class="btnWrapper"
@@ -177,6 +151,16 @@
       Screenshot
     </span>
   </button>
+  <button mat-menu-item
+    [disabled]="!viewerLoaded"
+    (click)="setAnnotatingMode()"
+    [matTooltip]="annotateTooltipText">
+    <mat-icon fontSet="fas" fontIcon="fa-pencil-ruler">
+    </mat-icon>
+    <span>
+      Annotate
+    </span>
+  </button>
   <plugin-banner></plugin-banner>
 </mat-menu>
 
@@ -286,10 +270,3 @@
     </mat-list-item>
   </mat-list>
 </ng-template>
-
-
-
-<ng-template #userAnnotations>
-  <user-annotations (close)="bottomSheet.dismiss()" style="max-width: 600px">
-  </user-annotations>
-</ng-template>
diff --git a/src/viewerModule/module.ts b/src/viewerModule/module.ts
index d31ef339f..beaaff406 100644
--- a/src/viewerModule/module.ts
+++ b/src/viewerModule/module.ts
@@ -19,6 +19,7 @@ import { NehubaModule } from "./nehuba";
 import { ThreeSurferModule } from "./threeSurfer";
 import { RegionAccordionTooltipTextPipe } from "./util/regionAccordionTooltipText.pipe";
 import { ViewerCmp } from "./viewerCmp/viewerCmp.component";
+import {UserAnnotationsModule} from "src/atlasComponents/userAnnotations";
 import {QuickTourModule} from "src/ui/quickTour/module";
 
 @NgModule({
@@ -38,6 +39,7 @@ import {QuickTourModule} from "src/ui/quickTour/module";
     AtlasCmptConnModule,
     ComponentsModule,
     BSFeatureModule,
+    UserAnnotationsModule,
     QuickTourModule,
     ContextMenuModule,
   ],
diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts
index aa6d2af84..ffffe0d10 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.component.ts
+++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts
@@ -3,7 +3,15 @@ import { select, Store } from "@ngrx/store";
 import { combineLatest, Observable, Subject, Subscription } from "rxjs";
 import { distinctUntilChanged, filter, map, startWith } from "rxjs/operators";
 import { viewerStateHelperSelectParcellationWithId, viewerStateRemoveAdditionalLayer, viewerStateSetSelectedRegions } from "src/services/state/viewerState/actions";
-import { viewerStateContextedSelectedRegionsSelector, viewerStateGetOverlayingAdditionalParcellations, viewerStateParcVersionSelector, viewerStateSelectedParcellationSelector,  viewerStateSelectedTemplateSelector, viewerStateStandAloneVolumes } from "src/services/state/viewerState/selectors"
+import {
+  viewerStateContextedSelectedRegionsSelector,
+  viewerStateGetOverlayingAdditionalParcellations,
+  viewerStateParcVersionSelector,
+  viewerStateSelectedParcellationSelector,
+  viewerStateSelectedTemplateSelector,
+  viewerStateStandAloneVolumes,
+  viewerStateViewerModeSelector
+} from "src/services/state/viewerState/selectors"
 import { CONST, ARIA_LABELS, QUICKTOUR_DESC } from 'common/constants'
 import { ngViewerActionClearView } from "src/services/state/ngViewerState/actions";
 import { ngViewerSelectorClearViewEntries } from "src/services/state/ngViewerState/selectors";
@@ -87,7 +95,7 @@ export class ViewerCmp implements OnDestroy {
   @ViewChild('sideNavFullLeftSwitch', { static: true })
   private sidenavLeftSwitch: SwitchDirective
 
-  
+
   public quickTourRegionSearch: IQuickTourData = {
     order: 7,
     description: QUICKTOUR_DESC.REGION_SEARCH,
@@ -127,6 +135,12 @@ export class ViewerCmp implements OnDestroy {
     map(v => v.length > 0)
   )
 
+  public viewerMode: string
+  public viewerMode$ = this.store$.pipe(
+    select(viewerStateViewerModeSelector),
+    distinctUntilChanged(),
+  )
+
   public useViewer$: Observable<TSupportedViewers | 'notsupported'> = combineLatest([
     this.templateSelected$,
     this.isStandaloneVolumes$,
@@ -233,7 +247,7 @@ export class ViewerCmp implements OnDestroy {
   ngAfterViewInit(){
     const cb = (context: TContextArg<'nehuba' | 'threeSurfer'>) => {
       let hoveredRegions = []
-      
+
       if (context.viewerType === 'nehuba') {
         hoveredRegions = (context as TContextArg<'nehuba'>).payload.nehuba.reduce(
           (acc, curr) => acc.concat(
@@ -256,7 +270,7 @@ export class ViewerCmp implements OnDestroy {
       if (context.viewerType === 'threeSurfer') {
         hoveredRegions = (context as TContextArg<'threeSurfer'>).payload._mouseoverRegion
       }
-      
+
       return {
         tmpl: this.viewerStatusCtxMenu,
         data: {
diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html
index 22b8b3f22..352b73b71 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.template.html
+++ b/src/viewerModule/viewerCmp/viewerCmp.template.html
@@ -5,8 +5,39 @@
 
 <layout-floating-container [zIndex]="10">
 
+
+  <!-- Annotation mode -->
+  <div *ngIf="(viewerMode$ | async) === ARIA_LABELS.VIEWER_MODE_ANNOTATING">
+
+    <mat-drawer-container class="mat-drawer-content-overflow-visible w-100 h-100 position-absolute invisible"
+                          [hasBackdrop]="false">
+      <mat-drawer #drawer [mode]="'push'" class="pe-all">
+        <annotation-list></annotation-list>
+      </mat-drawer>
+      <mat-drawer-content class="visible position-relative pe-none">
+        <!-- pullable tab top right corner -->
+        <div iavLayoutFourCornersTopLeft class="d-flex flex-column flex-nowrap w-100">
+
+          <!-- top left -->
+          <div class="flex-grow-1 d-flex flex-nowrap mb-2">
+            <div (click)="drawer.toggle()" class="tab-toggle-container">
+              <ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
+              matColor: 'primary',
+              fontIcon: 'fa-list',
+              tooltip: 'Annotation list'}">
+              </ng-container>
+            </div>
+          </div>
+          <annotating-mode #annotationMode>
+          </annotating-mode>
+        </div>
+
+      </mat-drawer-content>
+    </mat-drawer-container>
+  </div>
   <!-- top drawer -->
   <mat-drawer-container
+    [hidden]="viewerMode$ | async"
     [iav-switch-initstate]="false"
     iav-switch
     #sideNavTopSwitch="iavSwitch"
@@ -190,7 +221,7 @@
     </mat-drawer>
 
     <!-- main-content -->
-    <mat-drawer-content class="visible position-relative">
+    <mat-drawer-content class="visible position-relative" [hidden]="viewerMode$ | async">
 
       <iav-layout-fourcorners [iav-layout-fourcorners-cnr-cntr-ngclass]="{'w-100': true}">
 
@@ -599,33 +630,33 @@
     </ng-template>
   </ng-template>
 
-  <ng-template #tabTmpl_defaultTmpl
-    let-matColor="matColor"
-    let-fontIcon="fontIcon"
-    let-customColor="customColor"
-    let-customColorDarkmode="customColorDarkmode"
-    let-tooltip="tooltip">
-    <!-- (click)="sideNavMasterSwitch.toggle()" -->
-    <button mat-raised-button
-      [attr.aria-label]="ARIA_LABELS.TOGGLE_SIDE_PANEL"
-      [matTooltip]="tooltip"
-      class="pe-all tab-toggle"
-      [ngClass]="{
+
+</ng-template>
+<ng-template #tabTmpl_defaultTmpl
+             let-matColor="matColor"
+             let-fontIcon="fontIcon"
+             let-customColor="customColor"
+             let-customColorDarkmode="customColorDarkmode"
+             let-tooltip="tooltip">
+  <!-- (click)="sideNavMasterSwitch.toggle()" -->
+  <button mat-raised-button
+          [attr.aria-label]="ARIA_LABELS.TOGGLE_SIDE_PANEL"
+          [matTooltip]="tooltip"
+          class="pe-all tab-toggle"
+          [ngClass]="{
         'darktheme': customColorDarkmode === true,
         'lighttheme': customColorDarkmode === false
       }"
-      [style.backgroundColor]="customColor"
+          [style.backgroundColor]="customColor"
 
-      [color]="(!customColor && matColor) ? matColor : null">
+          [color]="(!customColor && matColor) ? matColor : null">
 
       <span [ngClass]="{'iv-custom-comp  text': !!customColor}">
         <i class="fas" [ngClass]="fontIcon || 'fa-question'"></i>
       </span>
-    </button>
-  </ng-template>
+  </button>
 </ng-template>
 
-
 <!-- region sidenav tmpl -->
 <ng-template #sidenavRegionTmpl>
 
@@ -1078,7 +1109,7 @@
     <!-- hovered ROIs -->
     <ng-template [ngIf]="data.metadata.hoveredRegions.length > 0">
       <mat-divider></mat-divider>
-      
+
       <mat-list-item *ngFor="let hoveredR of data.metadata.hoveredRegions">
         <span mat-line>
           {{ hoveredR.displayName || hoveredR.name }}
-- 
GitLab