From d1a20be77aeb2f7b58c598937199462dd8c85053 Mon Sep 17 00:00:00 2001
From: fsdavid <daviti1@mail.com>
Date: Tue, 1 Jun 2021 03:06:51 +0200
Subject: [PATCH] User annotation fixes

---
 package.json                                  |   1 +
 .../annotationList.component.ts               | 121 ++++----
 .../annotationList/annotationList.style.css   |  10 +
 .../annotationList.template.html              |  81 +++--
 .../annotationMessage.component.ts            |  21 ++
 .../annotationMode.component.ts               | 142 ++++++---
 .../annotationMode/annotationMode.style.css   |   6 -
 .../annotationMode.template.html              |  23 +-
 .../annotationService.service.ts              | 289 ++++++++++++++----
 .../editAnnotation.component.ts               | 118 -------
 .../editAnnotation.template.html              |  60 ----
 .../groupAnnotationPolygons.pipe.ts           |  31 --
 src/atlasComponents/userAnnotations/index.ts  |   1 +
 src/atlasComponents/userAnnotations/module.ts |   9 +-
 .../atlasViewer.apiService.service.ts         |  20 +-
 src/services/state/viewerState.store.ts       |   4 +-
 .../viewerCmp/viewerCmp.component.ts          |   2 +-
 .../viewerCmp/viewerCmp.template.html         |  11 +-
 18 files changed, 502 insertions(+), 448 deletions(-)
 create mode 100644 src/atlasComponents/userAnnotations/annotationMessage/annotationMessage.component.ts
 delete mode 100644 src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
 delete mode 100644 src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
 delete mode 100644 src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts

diff --git a/package.json b/package.json
index 142c217a9..bea7e83f4 100644
--- a/package.json
+++ b/package.json
@@ -82,6 +82,7 @@
     "@types/node": "12.12.39",
     "export-nehuba": "0.0.12",
     "hbp-connectivity-component": "^0.3.18",
+    "jszip": "^3.6.0",
     "zone.js": "^0.10.2"
   }
 }
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
index fbc8b0d6f..b963c5908 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
@@ -10,61 +10,13 @@ import {Store} from "@ngrx/store";
 })
 export class AnnotationList {
 
-  public editing = -1
-
-  get annotationsToShow() {
-    return this.ans.annotations
-    // .filter(a => this.annotationFilter === 'all' || a.templateName === this.ans.selectedTemplate)
-    // .filter(a => (a.type !== 'polygon' || +a.id.split('_')[1] === 0)
-
-    // let transformed = [...this.ans.annotations]
-    //
-    // for (let i = 0; i<this.ans.annotations.length; i++) {
-    //   if (this.ans.annotations[i].type === 'polygon') {
-    //     const annotationId = this.ans.annotations[i].id.split('_')
-    //     if (!transformed.find(t => t.id === annotationId[0])) {
-    //       const polygonAnnotations = this.ans.annotations.filter(a => a.id.split('_')[0] === annotationId[0]
-    //         && a.id.split('_')[1])
-    //
-    //       const polygonPositions = polygonAnnotations.map((a, i) => {
-    //         return i-1 !== polygonAnnotations.length? {
-    //           position: a.position1,
-    //           lines: [
-    //             {id: a.id, point: 2},
-    //             {id: polygonAnnotations[i+1], point: 1}
-    //           ]
-    //         } : polygonAnnotations[i].position2 !== polygonAnnotations[0].position1? {
-    //           position: a.position2,
-    //           lines: [
-    //             {id: a.id, point: 2}
-    //           ]
-    //         } : null
-    //       })
-    //
-    //       transformed = transformed.filter(a => a.id.split('_')[0] !== annotationId[0])
-    //
-    //       transformed.push({
-    //         id: annotationId[0],
-    //         name: this.ans.annotations[i].name,
-    //         type: 'polygon',
-    //         annotations: polygonAnnotations,
-    //         positions: polygonPositions,
-    //         annotationVisible: this.ans.annotations[i].annotationVisible,
-    //         templateName: this.ans.annotations[i].templateName
-    //       })
-    //     }
-    //   }
-    // }
-    // return transformed
-  }
-
-  public identifyer = (index: number, item: any) => item.id
+  public identifier = (index: number, item: any) => item.id
 
   constructor(private store$: Store<any>, public ans: AnnotationService) {}
 
   toggleAnnotationVisibility(annotation) {
     if (annotation.type === 'polygon') {
-      this.ans.annotations.filter(an => an.id.split('_')[0] === annotation.id.split('_')[0])
+      this.ans.pureAnnotationsForViewer.filter(an => an.id.split('_')[0] === annotation.id.split('_')[0])
         .forEach(a => this.toggleVisibility(a))
     } else {
       this.toggleVisibility(annotation)
@@ -72,21 +24,21 @@ export class AnnotationList {
   }
 
   toggleVisibility(annotation) {
-    const annotationIndex = this.ans.annotations.findIndex(a => a.id === annotation.id)
+    const annotationIndex = this.ans.pureAnnotationsForViewer.findIndex(a => a.id === annotation.id)
 
-    if (this.ans.annotations[annotationIndex].annotationVisible) {
+    if (this.ans.pureAnnotationsForViewer[annotationIndex].annotationVisible) {
       this.ans.removeAnnotationFromViewer(annotation.id)
-      this.ans.annotations[annotationIndex].annotationVisible = false
+      this.ans.pureAnnotationsForViewer[annotationIndex].annotationVisible = false
     } else {
-      this.ans.addAnnotationOnViewer(this.ans.annotations[annotationIndex])
-      this.ans.annotations[annotationIndex].annotationVisible = true
+      this.ans.addAnnotationOnViewer(this.ans.pureAnnotationsForViewer[annotationIndex])
+      this.ans.pureAnnotationsForViewer[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])
+      this.ans.pureAnnotationsForViewer.filter(an => an.id.split('_')[0] === annotation.id.split('_')[0])
         .forEach(a => this.ans.removeAnnotation(a.id))
     } else {
       this.ans.removeAnnotation(annotation.id)
@@ -94,7 +46,6 @@ export class AnnotationList {
   }
 
   navigate(position) {
-    //ToDo change for real position for all templates
     position = position.split(',').map(p => +p * 1e6)
     this.store$.dispatch(
       viewerStateChangeNavigation({
@@ -106,27 +57,61 @@ export class AnnotationList {
     )
   }
 
-  saveAnnotation(annotation) {
-    if (annotation.position1.split(',').length !== 3 || !annotation.position1.split(',').every(e => !!e)
-        || ((annotation.position2
-            && annotation.position2.split(',').length !== 3) || !annotation.position1.split(',').every(e => !!e))) {
-      return
+  saveAnnotation(annotation, singlePolygon = false) {
+    if (annotation.type !== 'polygon' || singlePolygon) {
+      annotation.position1 = annotation.position1.replace(/\s/g, '')
+      annotation.position2 = annotation.position2 && annotation.position2.replace(/\s/g, '')
+      if (annotation.position1.split(',').length !== 3 || !annotation.position1.split(',').every(e => !!e)
+          || ((annotation.position2
+              && annotation.position2.split(',').length !== 3) || !annotation.position1.split(',').every(e => !!e))) {
+        return
+      } else {
+        annotation.position1 = this.ans.mmToVoxel(annotation.position1.split(',')).join()
+        annotation.position2 = annotation.position2 && this.ans.mmToVoxel(annotation.position2.split(',')).join()
+      }
+      this.ans.saveAnnotation(annotation)
+    } else {
+      if (!annotation.name) {
+        annotation.name = this.ans.giveNameByType('polygon')
+      }
+
+      const toUpdateFirstAnnotation = this.ans.pureAnnotationsForViewer.find(a => a.id === `${annotation.id}_0`)
+      toUpdateFirstAnnotation.name = annotation.name
+      toUpdateFirstAnnotation.description = annotation.description
+      this.ans.saveAnnotation(toUpdateFirstAnnotation)
+
+      const toUpdate = this.ans.groupedAnnotations.findIndex(a => a.id === annotation.id)
+      this.ans.groupedAnnotations[toUpdate].name = annotation.name
+      this.ans.groupedAnnotations[toUpdate].description = annotation.description
+      this.ans.refreshAnnotationFilter()
+
     }
-    this.ans.saveAnnotation(annotation)
   }
 
-  savePolygonPosition(position, inputVal) {
+  savePolygonPosition(id, position, inputVal) {
+    inputVal = inputVal.replace(/\s/g, '')
+    if (inputVal.split(',').length !== 3 || !inputVal.split(',').every(e => !!e)) {
+      return
+    } else {
+      inputVal = this.ans.mmToVoxel(inputVal.split(',')).join()
+    }
     position.lines.forEach(l => {
       if (l.point === 2) {
-        const annotation = this.ans.annotations.find(a => a.id === l.id)
+        const annotation = this.ans.pureAnnotationsForViewer.find(a => a.id === l.id)
         annotation.position2 = inputVal
-        this.saveAnnotation(annotation)
+        this.saveAnnotation(annotation, true)
       } else {
-        const annotation = this.ans.annotations.find(a => a.id === l.id)
+        const annotation = this.ans.pureAnnotationsForViewer.find(a => a.id === l.id)
         annotation.position1 = inputVal
-        this.saveAnnotation(annotation)
+        this.saveAnnotation(annotation, true)
       }
     })
   }
 
+  submitInput(e, area) {
+    if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
+      area.blur()
+    }
+  }
+
 }
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css b/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
index 5d6cede95..858e3ab3d 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.style.css
@@ -20,3 +20,13 @@ input:focus, textarea:focus {
   border-bottom: 2px solid;
 }
 
+.annotation-name-input {
+  width: 180px;
+}
+
+:host-context([darktheme="true"]) .hovering-header {
+    background-color: #737373;
+}
+:host-context([darktheme="false"]) .hovering-header {
+    background-color: rgb(245, 245, 245);
+}
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
index 731f821a8..c8fd56c4f 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
@@ -4,25 +4,45 @@
         <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">
+                        aria-label="Import annotation"
+                        matTooltip="Import JSON"
+                        [matMenuTriggerFor]="importMenu">
                     <i class="fas fa-file-import"></i>
                 </button>
+                <input type="file" #importInput (change)="$event.target.files.length && ans.importFile( $event.target.files[0])" hidden/>
+                <input type="file" #importInputSands (change)="$event.target.files.length && ans.importFile($event.target.files[0], true)" hidden/>
+                <mat-menu #importMenu="matMenu">
+                    <button mat-menu-item (click)="importInputSands.click()">
+                        SANDS format
+                    </button>
+                    <button mat-menu-item (click)="importInput.click()">
+                        Siibra explorer format
+                    </button>
+                </mat-menu>
+
                 <button class="mr-1 ml-1" mat-icon-button
-                        disabled
-                        aria-label="Export user annotation"
-                        matTooltip="Export">
+                        aria-label="Export annotation"
+                        matTooltip="Export"
+                        [matMenuTriggerFor]="exportAllMenu">
                     <i class="fas fa-file-export"></i>
                 </button>
+                <mat-menu #exportAllMenu="matMenu">
+                    <button mat-menu-item (click)="ans.exportAnnotations(ans.finalAnnotationList, true)">
+                        SANDS format
+                    </button>
+                    <button mat-menu-item (click)="ans.exportAnnotations(ans.finalAnnotationList)">
+                        Siibra explorer format
+                    </button>
+                </mat-menu>
+
             </div>
             <div class="d-flex flex-column">
                 <small [ngClass]="[ans.annotationFilter !== 'all'? 'inactive-filter' : '']"
-                       class="cursor-pointer" (click)="ans.changeAnnotationFilter('all')">
+                       class="cursor-pointer" (click)="ans.refreshAnnotationFilter('all')">
                     All landmarks
                 </small>
                 <small [ngClass]="[ans.annotationFilter !== 'current'? 'inactive-filter' : '']"
-                       class="cursor-pointer" (click)="ans.changeAnnotationFilter('current')">
+                       class="cursor-pointer" (click)="ans.refreshAnnotationFilter('current')">
                     Current template
                 </small>
             </div>
@@ -32,9 +52,8 @@
 
     <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 #expansion hideToggle *ngFor="let annotation of ans.displayAnnotations; let i = index; trackBy: identifyer">
-            <mat-expansion-panel-header>
+        <mat-expansion-panel #expansion hideToggle *ngFor="let annotation of ans.finalAnnotationList; let i = index; trackBy: identifier">
+            <mat-expansion-panel-header [ngClass]="ans.hoverAnnotation?.id.includes(annotation.id) && 'hovering-header'">
 
                 <mat-panel-title>
                     <small class="cursor-pointer mr-3 ml-1 d-flex align-items-center"
@@ -44,11 +63,14 @@
                         <i class="fas far fa-check-circle" *ngIf="annotation.annotationVisible; else notVisible"></i>
                         <ng-template #notVisible><i class="far fa-circle"></i></ng-template>
                     </small>
-                    <input class="font-italic outline-none color-inherit"
+                    <input #annotationNameRef class="font-italic outline-none color-inherit annotation-name-input"
                            (click)="expansion.expanded? $event.stopPropagation() : null"
                            [(ngModel)]="annotation.name"
+                           (keydown.escape)="$event.stopPropagation(); annotationNameRef.blur();"
+                           (keydown.space)="$event.stopPropagation();"
+                           (keydown.enter)="$event.stopPropagation(); annotationNameRef.blur();"
+                           (keydown)="submitInput($event, annotationNameRef)"
                            (keyup)="this.saveAnnotation(annotation)"/>
-<!--                    <span class="mr-2">{{annotation.name}}</span>-->
                 </mat-panel-title>
 
                 <mat-panel-description class="w-100 d-flex align-items-center justify-content-end"
@@ -66,11 +88,15 @@
 
 
             <div>
-                <small class="mt-2 mb-2">{{annotation.templateName}}</small>
+                <small class="mt-2 mb-2">{{annotation.template.name}}</small>
 
                 <div *ngIf="annotation.type !== 'polygon'" class="w-100 d-flex align-items-center justify-content-between mt-2">
                     <input class="w-100 font-italic outline-none color-inherit"
+                           #position1Ref
                            [(ngModel)]="annotation.position1"
+                           (keyup.escape)="position1Ref.blur(); $event.stopPropagation();"
+                           (keyup.enter)="position1Ref.blur(); $event.stopPropagation();"
+                           (keydown)="submitInput($event, position1Ref)"
                            (keyup)="this.saveAnnotation(annotation)"/>
                     <small class="d-flex align-items-center">mm <i class="fas fa-map-marked-alt mr-2 ml-2 cursor-pointer" (click)="navigate(annotation.position1)"></i></small>
                 </div>
@@ -78,6 +104,10 @@
                 <div *ngIf="annotation.type !== 'polygon' && annotation.position2" class="w-100 d-flex align-items-center justify-content-between mb-2">
                     <input class="w-100 font-italic d-flex align-items-center outline-none color-inherit"
                            [(ngModel)]="annotation.position2"
+                           #position2Ref
+                           (keyup.escape)="position2Ref.blur(); $event.stopPropagation();"
+                           (keyup.enter)="position2Ref.blur(); $event.stopPropagation();"
+                           (keydown)="submitInput($event, position2Ref)"
                            (keyup)="this.saveAnnotation(annotation)"/>
                     <small class="d-flex align-items-center">mm <i class="fas fa-map-marked-alt mr-2 ml-2 cursor-pointer" (click)="navigate(annotation.position2)"></i></small>
                 </div>
@@ -87,7 +117,10 @@
                         <input class="w-100 font-italic d-flex align-items-center outline-none color-inherit"
                                [value]="position?.position"
                                #polygonPositionInput
-                               (keyup)="this.savePolygonPosition(position, polygonPositionInput.value)"/>
+                               (keyup.escape)="polygonPositionInput.blur(); $event.stopPropagation();"
+                               (keyup.enter)="polygonPositionInput.blur(); $event.stopPropagation();"
+                               (keydown)="submitInput($event, polygonPositionInput)"
+                               (keyup)="this.savePolygonPosition(annotation.id, position, polygonPositionInput.value)"/>
                         <small class="d-flex align-items-center">mm <i class="fas fa-map-marked-alt mr-2 ml-2 cursor-pointer" (click)="navigate(position?.position)"></i></small>
                     </div>
                 </div>
@@ -97,10 +130,13 @@
                     <textarea class="w-100 outline-none color-inherit"
                               placeholder="Add description"
                               cdkTextareaAutosize
+                              #descriptionTextAreaRef
                               #autosize="cdkTextareaAutosize"
                               cdkAutosizeMinRows="1"
                               cdkAutosizeMaxRows="5"
                               [(ngModel)]="annotation.description"
+                              (keyup.escape)="descriptionTextAreaRef.blur(); $event.stopPropagation();"
+                              (keydown)="submitInput($event, descriptionTextAreaRef)"
                               (keyup)="this.saveAnnotation(annotation)"></textarea>
                 </div>
 
@@ -108,10 +144,19 @@
 
                 <div class="d-flex align-items-center justify-content-end w-100">
                     <button class="mr-1 ml-1" mat-icon-button
-                            disabled
-                            aria-label="Export single annotation">
+                            aria-label="Export single annotation"
+                            matTooltip="Export"
+                            [matMenuTriggerFor]="exportSingleMenu">
                         <i class="fas fa-file-export"></i>
                     </button>
+                    <mat-menu #exportSingleMenu="matMenu">
+                        <button mat-menu-item (click)="ans.exportAnnotations([annotation], true)">
+                            SANDS format
+                        </button>
+                        <button mat-menu-item (click)="ans.exportAnnotations([annotation])">
+                            Siibra explorer format
+                        </button>
+                    </mat-menu>
                     <button class="mr-1 ml-1" mat-icon-button
                             aria-label="Delete annotation"
                             (click)="removeAnnotation(annotation)">
@@ -119,8 +164,6 @@
                     </button>
                 </div>
 
-                <edit-annotation [annotation]="annotation" *ngIf="editing === i" (finished)="editing = -1">
-                </edit-annotation>
             </div>
 
         </mat-expansion-panel>
diff --git a/src/atlasComponents/userAnnotations/annotationMessage/annotationMessage.component.ts b/src/atlasComponents/userAnnotations/annotationMessage/annotationMessage.component.ts
new file mode 100644
index 000000000..cf1c198e0
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/annotationMessage/annotationMessage.component.ts
@@ -0,0 +1,21 @@
+import {Component} from "@angular/core";
+import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+
+@Component({
+  selector: 'annotation-message',
+  template: `<mat-card class="pe-all position-absolute d-flex align-items-center  annotation-mode-message-panel">
+          <mat-panel-title>Annotation mode</mat-panel-title>
+          <button mat-icon-button
+                  color="warn"
+                  (click)="ans.disable()"
+                  type="button"
+                  class="mb-2 mt-2"
+                  matTooltip="Exit annotation mode">
+              <i class="fas fa-times"></i>
+          </button>
+      </mat-card>`,
+  styles: [`.annotation-mode-message-panel {height: 30px;top: 20px;right: 0;}`]
+})
+export class AnnotationMessage {
+  constructor(public ans: AnnotationService) {}
+}
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
index 6605fb2c1..0803ac641 100644
--- a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.component.ts
@@ -1,16 +1,19 @@
 import {Component, HostListener, Inject, OnDestroy, OnInit, Optional} from "@angular/core";
 import {select, Store} from "@ngrx/store";
 import {ARIA_LABELS, CONST} from "common/constants";
-import {Observable, Subscription} from "rxjs";
+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 {
+  viewerStateGetSelectedAtlas,
   viewerStateNavigationStateSelector,
-  viewerStateSelectedTemplateSelector,
-  viewerStateViewerModeSelector
+  viewerStateSelectedTemplateSelector, viewerStateViewerModeSelector,
 } from "src/services/state/viewerState/selectors";
 import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
+import {NehubaViewerUnit} from "src/viewerModule/nehuba";
+import {NEHUBA_INSTANCE_INJTKN} from "src/viewerModule/nehuba/util";
+import {CLICK_INTERCEPTOR_INJECTOR, ClickInterceptor} from "src/util";
 
 @Component({
   selector: 'annotating-mode',
@@ -26,11 +29,11 @@ export class AnnotationMode implements OnInit, OnDestroy {
     public editingAnnotationId: string
 
     public selecting = 'position1'
-    public mousePos
-    public navState: any
+    public mousePos: any[]
+    public navState: any = {}
 
     private hoverAnnotation$: Observable<{id: string, partIndex: number}>
-    public hoverAnnotation: {id: string, partIndex: number}
+    // public hoverAnnotation: {id: string, partIndex: number}
     private onDestroyCb: Function[] = []
     public subscriptions: Subscription[] = []
 
@@ -38,9 +41,15 @@ export class AnnotationMode implements OnInit, OnDestroy {
       return this.injectedViewer || (window as any).viewer
     }
 
-    get nehubaViewer() {
-      return (window as any).nehubaViewer
+    private _nehubaViewer: NehubaViewerUnit;
+
+    get nehubaViewer(){
+      return this._nehubaViewer
+    }
+    set nehubaViewer(v: NehubaViewerUnit) {
+      this._nehubaViewer = v
     }
+
     get interactiveViewer() {
       return (window as any).interactiveViewer
     }
@@ -49,7 +58,33 @@ export class AnnotationMode implements OnInit, OnDestroy {
         private store$: Store<any>,
         public ans: AnnotationService,
         @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer,
-    ) {}
+        @Optional() @Inject(NEHUBA_INSTANCE_INJTKN) nehubaViewer$: Observable<NehubaViewerUnit>,
+        @Optional() @Inject(CLICK_INTERCEPTOR_INJECTOR) clickInterceptor: ClickInterceptor
+    ) {
+      if (clickInterceptor) {
+        const { register, deregister } = clickInterceptor
+        const onMouseClick = this.onMouseClick.bind(this)
+        register(onMouseClick)
+        this.onDestroyCb.push(() => deregister(onMouseClick))
+      }
+
+      if (nehubaViewer$) {
+        this.subscriptions.push(
+          nehubaViewer$.subscribe(
+            viewer => this.nehubaViewer = viewer
+          )
+        )
+      }
+    }
+
+    onMouseClick(e: any) {
+      let viewerMode: string
+      this.store$.pipe(
+        select(viewerStateViewerModeSelector),
+        take(1)
+      ).subscribe(vm => viewerMode = vm)
+      if (viewerMode === ARIA_LABELS.VIEWER_MODE_ANNOTATING) return false
+    }
 
     ngOnInit(): void {
       // Load annotation layer on init
@@ -79,7 +114,7 @@ export class AnnotationMode implements OnInit, OnDestroy {
       )
 
       this.subscriptions.push(this.hoverAnnotation$.subscribe(ha => {
-        this.hoverAnnotation = ha
+        this.ans.hoverAnnotation = ha
       }))
 
       const mouseDown$ = this.interactiveViewer.viewerHandle.mouseEvent.pipe(
@@ -119,25 +154,24 @@ export class AnnotationMode implements OnInit, OnDestroy {
       let hoveringName: string
       let hoveringPosition1: []
       let hoveringPosition2: []
-      let draggingStartPosition: []
+      let draggingStartPosition: any[]
       let hoveringPolygonAnnotations: any[]
       let dragging = false
       this.subscriptions.push(
         mouseDown$.pipe(
           tap(() => {
-            hovering = this.hoverAnnotation
+            hovering = this.ans.hoverAnnotation
             if (hovering) {
               draggingStartPosition = this.mousePos
-              const hoveringAnnotation = this.ans.annotations.find(a => a.id === this.hoverAnnotation.id)
+              const hoveringAnnotation = this.ans.pureAnnotationsForViewer.find(a => a.id === this.ans.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
+                hoveringType = this.ans.pureAnnotationsForViewer.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])
+                  hoveringPolygonAnnotations = this.ans.pureAnnotationsForViewer.filter(a => a.id.split('_')[0] === hovering.id.split('_')[0])
                 }
-                hoveringType = this.ans.annotations.find(a => a.id === hovering.id)?.type
-                hoveringName = this.ans.annotations.find(a => a.id === hovering.id)?.name
+                hoveringName = this.ans.pureAnnotationsForViewer.find(a => a.id === hovering.id)?.name
               }
             }
           }),
@@ -156,7 +190,12 @@ export class AnnotationMode implements OnInit, OnDestroy {
           if (hovering && this.selecting !== 'position2') {
             dragging = true
             // keep navigation while dragging
-            this.interactiveViewer.viewerHandle.setNavigationLoc(this.navState)
+            // this.interactiveViewer.viewerHandle.setNavigationLoc(this.navState)
+            this.nehubaViewer.setNavigationState({
+              position: this.navState.position,
+              perspectiveOrientation: this.navState.perspectiveOrientation,
+              positionReal: true
+            })
             // make changes to annotations by type
             //  - when line is hovered move full annotation -
             //  - when line point is hovered move only point
@@ -167,7 +206,6 @@ export class AnnotationMode implements OnInit, OnDestroy {
                 this.ans.saveAnnotation({id: hovering.id, position1: this.mousePos.join(), name: hoveringName, type: hoveringType}, false, true)
               } 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(),
@@ -205,46 +243,57 @@ export class AnnotationMode implements OnInit, OnDestroy {
                       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(),
-                      name: hoveringName,
+                      name: pa.name,
+                      description: pa.description,
                       type: pa.type
                     }, false, true)
                   })
                 } else {
                   let samePos1: any[]
                   let samePos2: any[]
+                  const name = hoveringPolygonAnnotations[0].name
+                  const description = hoveringPolygonAnnotations[0].description
                   if (hovering.partIndex === 2) {
                     samePos1 = hoveringPolygonAnnotations.filter(hp => hp.id !== hovering.id && hp.position1 === hoveringPosition2.join())
                     samePos2 = hoveringPolygonAnnotations.filter(hp => hp.id !== hovering.id && hp.position2 === hoveringPosition2.join())
                     this.ans.saveAnnotation({id: hovering.id,
                       position1: hoveringPosition1.join(),
                       position2: this.mousePos.join(),
-                      name: hoveringName,
-                      type: hoveringType}, false, true)
+                      name,
+                      description,
+                      type: hoveringType}, true, false)
                   } else if (hovering.partIndex === 1) {
                     samePos1 = hoveringPolygonAnnotations.filter(hp => hp.id !== hovering.id && hp.position1 === hoveringPosition1.join())
                     samePos2 = hoveringPolygonAnnotations.filter(hp => hp.id !== hovering.id && hp.position2 === hoveringPosition1.join())
                     this.ans.saveAnnotation({id: hovering.id,
                       position1: this.mousePos.join(),
                       position2: hoveringPosition2.join(),
-                      name: hoveringName,
-                      type: hoveringType}, false, true)
+                      name,
+                      description,
+                      type: hoveringType}, true, false)
 
                   }
                   samePos1.forEach(a => {
                     this.ans.saveAnnotation({id: a.id,
                       position1: this.mousePos.join(),
                       position2: a.position2,
-                      name: hoveringName,
-                      type: a.type}, false, true)
+                      name,
+                      description,
+                      type: a.type}, true, false)
                   })
 
                   samePos2.forEach(a => {
                     this.ans.saveAnnotation({id: a.id,
                       position1: a.position1,
                       position2: this.mousePos.join(),
-                      name: hoveringName,
-                      type: a.type}, false, true)
+                      name,
+                      description,
+                      type: a.type}, true, false)
                   })
+
+                  this.ans.addPolygonsToGroupedAnnotations(
+                    this.ans.pureAnnotationsForViewer.filter(a => a.id.split('_')[0] === hovering.id.split('_')[0])
+                  )
                 }
               }
             }
@@ -254,10 +303,9 @@ export class AnnotationMode implements OnInit, OnDestroy {
       )
 
       this.subscriptions.push(
-        this.nehubaViewer.mousePosition.inVoxels
+        this.nehubaViewer.mousePosInVoxel$
           .subscribe(floatArr => {
             this.mousePos = floatArr && floatArr
-
             if (this.selecting === 'position1' && this.mousePos) {
               this.position1 = this.mousePos.join()
             } else if (this.selecting === 'position2' && this.mousePos) {
@@ -315,22 +363,33 @@ export class AnnotationMode implements OnInit, OnDestroy {
         this.store$.pipe(
           select(viewerStateNavigationStateSelector),
         ).subscribe(nav => {
-          this.navState = nav.position
+          this.navState.position = nav.position
+          this.navState.perspectiveOrientation = nav.perspectiveOrientation
         }),
+        this.store$.pipe(
+          select(viewerStateGetSelectedAtlas)
+        ).subscribe(atlas => {
+          this.ans.selectedAtlas = {name: atlas.name, id: atlas['@id']}
+        }),
+
         this.store$.pipe(
           select(viewerStateSelectedTemplateSelector),
           take(1)
         ).subscribe(tmpl => {
-          this.ans.selectedTemplate = tmpl.name
-          this.ans.darkTheme = tmpl.useTheme === 'dark'
+          this.ans.selectedTemplate = {
+            name: tmpl.name,
+            id: tmpl['@id']
+          }
+          this.ans.voxelSize = this.ans.getVoxelFromSpace(tmpl.fullId)
 
           // 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.displayAnnotations = this.ans.annotations.filter(a => a.type !== 'polygon')
-            this.ans.addPolygonsToDisplayAnnotations(this.ans.annotations.filter(a => a.type === 'polygon'))
-            this.ans.annotations.filter(a => a.annotationVisible && a.templateName === this.ans.selectedTemplate)
+            this.ans.pureAnnotationsForViewer = JSON.parse(annotationsString).filter(a => a.atlas.id === this.ans.selectedAtlas.id)
+            this.ans.groupedAnnotations = this.ans.pureAnnotationsForViewer.filter(a => a.type !== 'polygon')
+            this.ans.addPolygonsToGroupedAnnotations(this.ans.pureAnnotationsForViewer.filter(a => a.type === 'polygon'))
+            this.ans.refreshAnnotationFilter()
+            this.ans.pureAnnotationsForViewer.filter(a => a.annotationVisible && a.template.id === this.ans.selectedTemplate.id)
               .forEach(a => {
                 this.ans.addAnnotationOnViewer(a)
               })
@@ -369,20 +428,19 @@ export class AnnotationMode implements OnInit, OnDestroy {
 
     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 (this.ans.annotationTypes[this.selectedType].type === 'remove' && this.ans.hoverAnnotation) {
+        const hoveringAnnotationObj = this.ans.pureAnnotationsForViewer.find(a => a.id === this.ans.hoverAnnotation.id)
         if (hoveringAnnotationObj.type === 'polygon') {
-          const polygonAnnotations = this.ans.annotations.filter(a => a.id.split('_')[0] === hoveringAnnotationObj.id.split('_')[0])
+          const polygonAnnotations = this.ans.pureAnnotationsForViewer.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)
+          this.ans.removeAnnotation(this.ans.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') {
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
index 02e6997f4..89e110ea0 100644
--- a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.style.css
@@ -5,9 +5,3 @@
 .annotation-toolbar-content {
     margin-bottom: 20px;
 }
-.annotation-mode-message-panel {
-    height: 30px;
-    top: 20px;
-    right: 0;
-    background-color: rgba(66,65,65, 0.3);
-}
diff --git a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
index ed046f989..a67bdb554 100644
--- a/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
+++ b/src/atlasComponents/userAnnotations/annotationMode/annotationMode.template.html
@@ -1,9 +1,9 @@
 <div class="pe-all d-flex flex-column justify-content-content annotation-toolbar">
 
-    <div class="d-flex flex-column flex-grow-0 panel-default annotation-toolbar-content"
-         [ngStyle]="{backgroundColor: ans.darkTheme? '#424242' : 'white',
-         color: ans.darkTheme? 'antiquewhite' : '#424242'}">
-        <button *ngFor="let type of ans.annotationTypes; let i = index"
+    <mat-card class="d-flex flex-column flex-grow-0 panel-default annotation-toolbar-content p-0">
+
+        <div *ngFor="let type of ans.annotationTypes; let i = index; let last = last">
+        <button
                 mat-icon-button
                 type="button"
                 (click)="selectAnnotationType(i)"
@@ -12,6 +12,8 @@
                 [color]="selectedType === i? 'primary' : 'secondary'">
             <i [ngClass]="type.class"></i>
         </button>
+            <mat-divider *ngIf="last || type.action !== ans.annotationTypes[i+1].action"></mat-divider>
+        </div>
         <button
                 mat-icon-button
                 (click)="ans.disable()"
@@ -21,16 +23,5 @@
                 color="warn">
             <i class="fas fa-times"></i>
         </button>
-    </div>
-</div>
-
-<div class="pe-all position-absolute d-flex align-items-center p-3 annotation-mode-message-panel">
-    <span>Annotation mode</span>
-    <button mat-icon-button
-            (click)="ans.disable()"
-            type="button"
-            class="mb-2 mt-2"
-            matTooltip="Exit annotation mode">
-        <i class="fas fa-times"></i>
-    </button>
+    </mat-card>
 </div>
diff --git a/src/atlasComponents/userAnnotations/annotationService.service.ts b/src/atlasComponents/userAnnotations/annotationService.service.ts
index 6e361e0b1..7dc46abea 100644
--- a/src/atlasComponents/userAnnotations/annotationService.service.ts
+++ b/src/atlasComponents/userAnnotations/annotationService.service.ts
@@ -1,11 +1,14 @@
-import {ApplicationRef, ChangeDetectorRef, Inject, Injectable, OnDestroy, Optional} from "@angular/core";
-import {CONST} from "common/constants";
+import {Inject, Injectable, OnDestroy, Optional} from "@angular/core";
+import {CONST, ARIA_LABELS} 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 {select, Store} from "@ngrx/store";
 import {VIEWER_INJECTION_TOKEN} from "src/ui/layerbrowser/layerDetail/layerDetail.component";
-import {TemplateCoordinatesTransformation} from "src/services/templateCoordinatesTransformation.service";
+import {CLICK_INTERCEPTOR_INJECTOR, ClickInterceptor} from "src/util";
+import {viewerStateViewerModeSelector} from "src/services/state/viewerState/selectors";
+import {take} from "rxjs/operators";
+import * as JSZip from 'jszip';
 
 const USER_ANNOTATION_LAYER_SPEC = {
   "type": "annotation",
@@ -16,26 +19,34 @@ const USER_ANNOTATION_LAYER_SPEC = {
 }
 
 @Injectable()
-export class AnnotationService implements OnDestroy {
+export class AnnotationService {
+
+    // Annotations to display on viewer
+    public pureAnnotationsForViewer = []
+
+    // Grouped annotations for user
+    public groupedAnnotations = []
+
+    // Filtered annotations with converted voxed to mm
+    public finalAnnotationList = []
 
-    public annotations = []
-    public displayAnnotations = []
     public addedLayer: any
     public ellipsoidMinRadius = 0.5
     public annotationFilter: 'all' | 'current' = 'current'
 
-    public selectedTemplate: string
-    public darkTheme = false
-    public subscriptions: Subscription[] = []
+    public selectedTemplate: {name, id}
+    public voxelSize: any[] = []
+    public selectedAtlas: {name, id}
+    public hoverAnnotation: {id: string, partIndex: number}
 
     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'},
+      {name: 'Cursor', class: 'fas fa-mouse-pointer', type: 'move', action: 'none'},
+      {name: 'Point', class: 'fas fa-circle', type: 'singleCoordinate', action: 'paint'},
+      {name: 'Line', class: 'fas fa-slash', type: 'doubleCoordinate', action: 'paint'},
+      {name: 'Polygon', class: 'fas fa-draw-polygon', type: 'polygon', action: 'paint'},
+      // {name: 'Bounding box', class: 'far fa-square', type: 'doubleCoordinate', action: 'paint'},
+      // {name: 'Ellipsoid', class: 'fas fa-bullseye', type: 'doubleCoordinate', action: 'paint'},
+      {name: 'Remove', class: 'fas fa-trash', type: 'remove', action: 'remove'},
     ]
 
     private get viewer(){
@@ -43,7 +54,8 @@ export class AnnotationService implements OnDestroy {
     }
 
     constructor(private store$: Store<any>,
-                @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer) {}
+                @Optional() @Inject(VIEWER_INJECTION_TOKEN) private injectedViewer
+    ) {}
 
     public disable = () => {
       this.store$.dispatch(viewerStateSetViewerMode({payload: null}))
@@ -71,12 +83,14 @@ export class AnnotationService implements OnDestroy {
     }
 
     saveAnnotation({id = null,
-      position1 = null, //this.position1,
-      position2 = null, //this.position2,
-      type = null, //this.annotationTypes[this.selectedType].name,
-      description = null,
+      position1 = null,
+      position2 = null,
       name = null,
-      templateName = null,
+      description = null,
+      type = null,
+      circular = null,
+      atlas = null,
+      template = null,
     } = {}, store = true, backup = false) {
       let annotation = {
         id: id || getUuid(),
@@ -85,15 +99,17 @@ export class AnnotationService implements OnDestroy {
         name,
         position1,
         position2,
-        templateName: templateName || this.selectedTemplate,
+        circular,
+        template: template || this.selectedTemplate,
+        atlas: this.selectedAtlas,
         type: type.toLowerCase()
       }
 
-      const foundIndex = this.annotations.findIndex(x => x.id === annotation.id)
+      const foundIndex = this.pureAnnotationsForViewer.findIndex(x => x.id === annotation.id)
 
       if (foundIndex >= 0) {
         annotation = {
-          ...this.annotations[foundIndex],
+          ...this.pureAnnotationsForViewer[foundIndex],
           ...annotation
         }
       }
@@ -115,7 +131,7 @@ export class AnnotationService implements OnDestroy {
     public storeBackup() {
       if (this.saveEditList.length) {
         if (this.saveEditList[0].type === 'polygon') {
-          this.addPolygonsToDisplayAnnotations(this.saveEditList)
+          this.addPolygonsToGroupedAnnotations(this.saveEditList)
         }
         this.saveEditList.forEach(a => this.storeAnnotation(a))
         this.saveEditList = []
@@ -123,7 +139,7 @@ export class AnnotationService implements OnDestroy {
     }
 
     giveNameByType(type) {
-      const pointAnnotationNumber = this.annotations
+      const pointAnnotationNumber = this.pureAnnotationsForViewer
         .filter(a => a.name && a.name.startsWith(type) && (+a.name.split(type)[1]))
         .map(a => +a.name.split(type)[1])
 
@@ -134,30 +150,31 @@ export class AnnotationService implements OnDestroy {
 
     storeAnnotation(annotation) {
       // give names by type + number
-      if (!annotation.name) {
+      if (!annotation.name && annotation.type !== 'polygon') {
         annotation.name = this.giveNameByType(annotation.type)
       }
 
-      const foundIndex = this.annotations.findIndex(x => x.id === annotation.id)
+      const foundIndex = this.pureAnnotationsForViewer.findIndex(x => x.id === annotation.id)
 
       if (foundIndex >= 0) {
         annotation = {
-          ...this.annotations[foundIndex],
+          ...this.pureAnnotationsForViewer[foundIndex],
           ...annotation
         }
-        this.annotations[foundIndex] = annotation
+        this.pureAnnotationsForViewer[foundIndex] = annotation
       } else {
-        this.annotations.push(annotation)
+        this.pureAnnotationsForViewer.push(annotation)
       }
 
       if(annotation.type !== 'polygon') {
-        const foundIndex = this.displayAnnotations.findIndex(x => x.id === annotation.id)
+        const foundIndex = this.groupedAnnotations.findIndex(x => x.id === annotation.id)
 
         if (foundIndex >= 0) {
-          this.displayAnnotations[foundIndex] = annotation
+          this.groupedAnnotations[foundIndex] = annotation
         } else {
-          this.displayAnnotations.push(annotation)
+          this.groupedAnnotations.push(annotation)
         }
+        this.refreshAnnotationFilter()
       }
 
       this.storeToLocalStorage()
@@ -167,12 +184,6 @@ export class AnnotationService implements OnDestroy {
       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(',') : ''
 
@@ -199,16 +210,14 @@ export class AnnotationService implements OnDestroy {
 
     removeAnnotation(id) {
       this.removeAnnotationFromViewer(id)
-      this.annotations = this.annotations.filter(a => a.id !== id)
-      this.displayAnnotations = this.annotations.filter(a => a.id !== id)
+      this.pureAnnotationsForViewer = this.pureAnnotationsForViewer.filter(a => a.id !== id)
+      this.groupedAnnotations = this.groupedAnnotations.filter(a => a.id !== id.split('_')[0])
+      this.refreshAnnotationFilter()
       this.storeToLocalStorage()
     }
 
     storeToLocalStorage() {
-      // ToDo temporary solution - because impure pipe stucks
-
-
-      window.localStorage.setItem(CONST.USER_ANNOTATION_STORE_KEY, JSON.stringify(this.annotations))
+      window.localStorage.setItem(CONST.USER_ANNOTATION_STORE_KEY, JSON.stringify(this.pureAnnotationsForViewer))
     }
 
     removeAnnotationFromViewer(id) {
@@ -220,7 +229,7 @@ export class AnnotationService implements OnDestroy {
       }
     }
 
-    addPolygonsToDisplayAnnotations(annotations) {
+    addPolygonsToGroupedAnnotations(annotations) {
       let transformed = [...annotations]
 
       for (let i = 0; i<annotations.length; i++) {
@@ -260,34 +269,196 @@ export class AnnotationService implements OnDestroy {
           transformed.push({
             id: annotationId[0],
             name: annotations[i].name,
+            description: annotations[i].description,
             type: 'polygon',
             annotations: polygonAnnotations,
             positions: polygonPositions,
+            circular: polygonAnnotations[0].position1 === [...polygonAnnotations].pop().position2,
             annotationVisible: annotations[i].annotationVisible,
-            templateName: annotations[i].templateName
+            template: annotations[i].template,
+            atlas: this.selectedAtlas
           })
         }
 
       }
 
       transformed.forEach(tr=> {
-        const foundIndex = this.displayAnnotations.findIndex(x => x.id === tr.id)
+        const foundIndex = this.groupedAnnotations.findIndex(x => x.id === tr.id)
 
         if (foundIndex >= 0) {
-          this.displayAnnotations[foundIndex] = tr
+          this.groupedAnnotations[foundIndex] = tr
         } else {
-          this.displayAnnotations.push(tr)
+          this.groupedAnnotations.push(tr)
         }
+        this.refreshAnnotationFilter()
       })
     }
 
-    changeAnnotationFilter(filter) {
-      this.annotationFilter = filter
-      this.displayAnnotations = this.displayAnnotations
-        .filter(a => this.annotationFilter === 'all' || a.templateName === this.selectedTemplate)
+    refreshAnnotationFilter(filter = null) {
+      if (filter) {this.annotationFilter = filter}
+      this.finalAnnotationList = this.groupedAnnotations
+        // Filter all/current template
+        .filter(a => this.annotationFilter === 'all' || a.template.id === this.selectedTemplate.id)
+        // convert to MM
+        .map(a => {
+          if (a.positions) {
+            a.positions = a.positions.map(p => {
+              return {
+                ...p,
+                position: this.voxelToMM(p.position.split(',')).join()
+              }
+            })
+          } else {
+            a.position1 = this.voxelToMM(a.position1.split(',')).join()
+            a.position2 = a.position2 && this.voxelToMM(a.position2.split(',')).join()
+          }
+
+          a.dimension = 'mm'
+          return a
+        })
+        // clear polygonAnnotations
+        .map(a => {
+          if (a.annotations) {
+            a.annotations = a.annotations.map(an => {
+              return {
+                id: an.id,
+                position1: an.position1,
+                position2: an.position2
+              }
+            })
+          }
+
+          return a
+        })
+    }
+
+    voxelToMM(r): any[] {
+      return r.map((r, i) => parseFloat((+r*this.voxelSize[i]/1e6).toFixed(3)))
+    }
+
+    mmToVoxel(mm): any[] {
+      return mm.map((m, i) => +m*1e6/this.voxelSize[i])
+    }
+
+    getVoxelFromSpace = (spaceId: string) => {
+      return IAV_VOXEL_SIZES_NM[spaceId]
     }
 
-    ngOnDestroy(){
-      this.subscriptions.forEach(s => s.unsubscribe())
+    getSandsObj(position, template) {
+      return {
+        coordinates: {
+          value: position.split(',').map(p => +p),
+          unit: 'mm'
+        },
+        coordinateSpace: {
+          fullName: template.name,
+          versionIdentifier: template.id
+        }
+      }
     }
+
+    exportAnnotations(annotations: any[], sands = false) {
+      const zip = new JSZip()
+      const zipFileName = `annotation - ${annotations[0].atlas.name}.zip`
+
+
+      if (sands) {
+        annotations.forEach(a => {
+          zip.folder(a.name)
+          if (a.positions) {
+            a.positions.forEach(p => {
+              zip.folder(a.name).file(`${p.position}.json`, JSON.stringify(this.getSandsObj(p.position, a.template)))
+            })
+          } else {
+            zip.folder(a.name).file(`${a.position1}.json`, JSON.stringify(this.getSandsObj(a.position1, a.template)))
+            if (a.position2) zip.folder(a.name).file(`${a.position1}.json`, JSON.stringify(this.getSandsObj(a.position2, a.template)))
+          }
+        })
+      } else {
+        annotations.forEach(a => {
+          const fileName = a.name.replace(/[\\/:*?"<>|]/g, "").trim()
+          zip.file(`${fileName}.json`, JSON.stringify(a))
+        })
+      }
+
+
+      zip.file("README.txt",
+        `The annotation has been extracted from the atlas: "${annotations.map(a => a.atlas.name).filter((v, i, a) => a.indexOf(v) === i).join()}" 
+        and template(s): "${annotations.map(a => a.template.name).filter((v, i, a) => a.indexOf(v) === i).join()}"`)
+      zip.generateAsync({
+        type: "base64"
+      }).then(content => {
+        const link = document.createElement('a')
+        link.href = 'data:application/zip;base64,' + content
+        link.download = zipFileName
+        document.body.appendChild(link)
+        link.click()
+        document.body.removeChild(link)
+      })
+    }
+
+
+    importFile(file, sands = false) {
+      const fileReader = new FileReader()
+      fileReader.readAsText(file, "UTF-8")
+      fileReader.onload = () => {
+        const fileData = JSON.parse(fileReader.result.toString())
+
+        if (sands) {
+          if (!fileData.coordinates || !fileData.coordinates.value || fileData.coordinates.value.length !== 3
+              || !fileData.coordinateSpace || !fileData.coordinateSpace.fullName || !fileData.coordinateSpace.versionIdentifier) {
+            return
+          }
+          const position1 = this.mmToVoxel(fileData.coordinates.value).join()
+          this.saveAnnotation({position1,
+            template: {
+              name: fileData.coordinateSpace.fullName,
+              id: fileData.coordinateSpace.versionIdentifier
+            },
+            type: 'point'})
+        } else {
+          const {id, name, description, type,
+            atlas, template, positions, annotations} = fileData
+
+          if (!id || !(fileData.position1 || positions) || !type) {
+            return
+          }
+
+          if (fileData.type !== 'polygon') {
+            const position1 = this.mmToVoxel(fileData.position1.split(',')).join()
+            const position2 = fileData.position2 && this.mmToVoxel(fileData.position2.split(',')).join()
+
+            this.saveAnnotation({position1, position2,
+              name, description, type, atlas, template
+            })
+          } else if (annotations) {
+            annotations.forEach(a => {
+              this.saveAnnotation({
+                id: a.id,
+                name, description,
+                position1: a.position1,
+                position2: a.position2,
+                type: 'polygon'})
+            })
+            this.groupedAnnotations.push(fileData)
+            this.refreshAnnotationFilter()
+          }
+
+        }
+      }
+      fileReader.onerror = (error) => {
+        console.warn(error)
+      }
+    }
+
+}
+
+
+
+export const IAV_VOXEL_SIZES_NM = {
+  'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9': [25000, 25000, 25000],
+  'minds/core/referencespace/v1.0.0/d5717c4a-0fa1-46e6-918c-b8003069ade8': [39062.5, 39062.5, 39062.5],
+  'minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588': [21166.666015625, 20000, 21166.666015625],
+  'minds/core/referencespace/v1.0.0/7f39f7be-445b-47c0-9791-e971c0b6d992': [1000000, 1000000, 1000000,],
+  'minds/core/referencespace/v1.0.0/dafcffc5-4826-4bf1-8ff6-46b8a31ff8e2': [1000000, 1000000, 1000000]
 }
diff --git a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
deleted file mode 100644
index e758630b3..000000000
--- a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.component.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-import {
-  Component,
-  EventEmitter,
-  Input,
-  OnDestroy,
-  OnInit,
-  Output
-} from "@angular/core";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
-import { animate, style, transition, trigger } from "@angular/animations";
-import { Subscription } from "rxjs";
-import {AnnotationService} from "src/atlasComponents/userAnnotations/annotationService.service";
-import {viewerStateChangeNavigation} from "src/services/state/viewerState/actions";
-import {Store} from "@ngrx/store";
-
-@Component({
-  selector: 'edit-annotation',
-  templateUrl: './editAnnotation.template.html',
-  animations: [
-    trigger(
-      'enterAnimation', [
-        transition(':enter', [
-          style({transform: 'translateY(100%)', opacity: 0}),
-          animate('100ms', style({transform: 'translateY(0)', opacity: 1}))
-        ]),
-      ]
-    )
-  ],
-})
-export class EditAnnotationComponent implements OnInit, OnDestroy {
-
-    @Input() annotation: any
-
-    @Output() finished: EventEmitter<any> = new EventEmitter()
-
-    public annotationForm: FormGroup
-
-    public subscriptions: Subscription[] = []
-
-    constructor(
-      private formBuilder: FormBuilder,
-      public ans: AnnotationService,
-      private store$: Store<any>,
-    ) {
-      this.annotationForm = this.formBuilder.group({
-        id: [{value: 'null'}],
-        position1: [{value: ''}],
-        position2: [{value: ''}],
-        name: [{value: ''}, {
-          validators: [Validators.maxLength(200)]
-        }],
-        description: [{value: ''}, {
-          validators: [Validators.maxLength(1000)]
-        }],
-        templateName: [{value: ''}],
-        type: [{value: ''}],
-        annotationVisible: [{value: true}]
-      })
-    }
-
-    ngOnInit() {
-      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)
-    }
-
-
-    submitForm() {
-      if (this.annotationForm.valid) {
-        if (this.annotationForm.controls.position1.value.split(',').length !== 3 ||
-            (this.annotationForm.controls.position2.value
-                && this.annotationForm.controls.position2.value.split(',').length !== 3)) {
-          return
-        }
-        this.ans.saveAnnotation(this.annotationForm.value)
-        this.cancelEditing()
-      }
-    }
-
-    cancelEditing() {
-      this.finished.emit()
-      this.resetForm()
-    }
-
-    resetForm() {
-      this.annotationForm.reset()
-      this.annotationForm.markAsPristine()
-      this.annotationForm.markAsUntouched()
-
-      this.annotationForm.controls.annotationVisible.setValue(true)
-      Object.keys(this.annotationForm.controls).forEach(key => {
-        this.annotationForm.get(key).setErrors(null)
-      })
-    }
-
-    ngOnDestroy() {
-      this.subscriptions.forEach(s => s.unsubscribe())
-    }
-
-    navigate(position) {
-      //ToDo change for real position for all templates
-      position = position.split(',').map(p => +p * 1e6)
-      this.store$.dispatch(
-        viewerStateChangeNavigation({
-          navigation: {
-            position,
-            positionReal: true
-          },
-        })
-      )
-    }
-
-}
diff --git a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html b/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
deleted file mode 100644
index d423d5415..000000000
--- a/src/atlasComponents/userAnnotations/editAnnotation/editAnnotation.template.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<form class="annotation-form d-flex flex-column align-items-center"
-      autocomplete="off"
-      [formGroup]="annotationForm"
-      (keydown.enter)="!annotationForm.invalid? submitForm() : null"
-      (ngSubmit)="submitForm()">
-
-
-    <div class="w-100"
-         [@enterAnimation]>
-        <mat-form-field class="w-100">
-            <mat-label>Name</mat-label>
-            <input name="name"
-                   formControlName="name"
-                   (keyup)="submitForm()"
-                   matInput>
-        </mat-form-field>
-            <div class="d-flex flex-column align-items-center position-relative w-100">
-                <mat-form-field class="w-100 annotation-editing-body">
-                    <mat-label *ngIf="annotation.type !== 'ellipsoid'">Position {{annotation.position2 && ' 1'}} (vox)</mat-label>
-                    <mat-label *ngIf="annotation.type === 'ellipsoid'">Center (vox)</mat-label>
-                    <div>
-                        <input type="text" name="position1"
-                               placeholder="0,0,0mm"
-                               class="pr-4"
-                               formControlName="position1"
-                               (keyup)="submitForm()"
-                               matInput>
-                    </div>
-                </mat-form-field>
-                <small class="position-absolute" style="bottom: 20px; right: 0">mm <i class="fas fa-map-marked-alt mr-2 ml-2 cursor-pointer" (click)="navigate(annotation.position1)"></i></small>
-            </div>
-
-            <div class="d-flex flex-column align-items-center w-100 position-relative" *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,0mm"
-                           formControlName="position2"
-                           (keyup)="submitForm()"
-                           matInput>
-                </mat-form-field>
-                <small class="position-absolute" style="bottom: 20px; right: 0">mm <i class="fas fa-map-marked-alt mr-2 ml-2 cursor-pointer" (click)="navigate(annotation.position2)"></i></small>
-
-            </div>
-
-        <mat-form-field class="w-100 annotation-editing-body">
-            <mat-label>description</mat-label>
-            <textarea [matTextareaAutosize]="true"
-                      [matAutosizeMinRows]="1"
-                      [matAutosizeMaxRows]="5"
-                      name="description"
-                      (keyup)="submitForm()"
-                      formControlName="description" matInput></textarea>
-        </mat-form-field>
-        <div class="w-100 d-flex justify-content-end">
-            <button type="button" (click)="cancelEditing()" mat-button>Cancel</button>
-            <button type="submit" mat-raised-button color="primary">Save</button>
-        </div>
-    </div>
-</form>
diff --git a/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts b/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts
deleted file mode 100644
index 0b85117b8..000000000
--- a/src/atlasComponents/userAnnotations/groupAnnotationPolygons.pipe.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-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 6da0cda7d..d5c0a00d0 100644
--- a/src/atlasComponents/userAnnotations/index.ts
+++ b/src/atlasComponents/userAnnotations/index.ts
@@ -1,3 +1,4 @@
 export { AnnotationMode } from "./annotationMode/annotationMode.component";
 export { AnnotationList } from "./annotationList/annotationList.component";
+export { AnnotationMessage } from "./annotationMessage/annotationMessage.component";
 export { UserAnnotationsModule } from "./module";
diff --git a/src/atlasComponents/userAnnotations/module.ts b/src/atlasComponents/userAnnotations/module.ts
index e54f72cee..c9e2aabec 100644
--- a/src/atlasComponents/userAnnotations/module.ts
+++ b/src/atlasComponents/userAnnotations/module.ts
@@ -3,12 +3,11 @@ import {CommonModule} from "@angular/common";
 import {DatabrowserModule} from "src/atlasComponents/databrowserModule";
 import {AngularMaterialModule} from "src/ui/sharedModules/angularMaterial.module";
 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";
+import {AnnotationMessage} from "src/atlasComponents/userAnnotations/annotationMessage/annotationMessage.component";
 
 @NgModule({
   imports: [
@@ -20,17 +19,17 @@ import {GroupAnnotationPolygons} from "src/atlasComponents/userAnnotations/group
     AngularMaterialModule,
   ],
   declarations: [
-    EditAnnotationComponent,
     AnnotationMode,
     AnnotationList,
-    GroupAnnotationPolygons
+    AnnotationMessage
   ],
   providers: [
     AnnotationService
   ],
   exports: [
     AnnotationMode,
-    AnnotationList
+    AnnotationList,
+    AnnotationMessage
   ]
 })
 
diff --git a/src/atlasViewer/atlasViewer.apiService.service.ts b/src/atlasViewer/atlasViewer.apiService.service.ts
index 0833ddd51..7fd34675d 100644
--- a/src/atlasViewer/atlasViewer.apiService.service.ts
+++ b/src/atlasViewer/atlasViewer.apiService.service.ts
@@ -87,16 +87,7 @@ 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
-
+  private onMouseClick(ev: any) {
     const { rs, spec } = this.getNextUserRegionSelectHandler() || {}
     if (!!rs) {
 
@@ -125,11 +116,10 @@ export class AtlasViewerAPIServices implements OnDestroy{
                 mousePositionReal = floatArr && Array.from(floatArr).map((val: number) => val / 1e6)
               })
           }
-          rs({
+          return rs({
             type: spec.type,
             payload: mousePositionReal
           })
-          return false
         }
 
         /**
@@ -139,11 +129,10 @@ export class AtlasViewerAPIServices implements OnDestroy{
 
           if (!!moSegments && Array.isArray(moSegments) && moSegments.length > 0) {
             this.popUserRegionSelectHandler()
-            rs({
+            return rs({
               type: spec.type,
               payload: moSegments
             })
-            return false
           }
         }
       } else {
@@ -153,8 +142,7 @@ export class AtlasViewerAPIServices implements OnDestroy{
          */
         if (!!moSegments && Array.isArray(moSegments) && moSegments.length > 0) {
           this.popUserRegionSelectHandler()
-          rs(moSegments[0])
-          return false
+          return rs(moSegments[0])
         }
       }
     }
diff --git a/src/services/state/viewerState.store.ts b/src/services/state/viewerState.store.ts
index f28fc4109..ed2422c70 100644
--- a/src/services/state/viewerState.store.ts
+++ b/src/services/state/viewerState.store.ts
@@ -171,7 +171,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Part
       regionsSelected: selectRegions,
     }
   }
-  case SET_VIEWER_MODE: {
+  case viewerStateSetViewerMode.type: {
     return {
       ...prevState,
       viewerMode: action.payload
@@ -266,7 +266,7 @@ 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 SET_VIEWER_MODE = viewerStateSetViewerMode.type
 export const SELECT_LANDMARKS = `SELECT_LANDMARKS`
 export const SELECT_REGIONS = viewerStateSetSelectedRegions.type
 export const DESELECT_LANDMARKS = `DESELECT_LANDMARKS`
diff --git a/src/viewerModule/viewerCmp/viewerCmp.component.ts b/src/viewerModule/viewerCmp/viewerCmp.component.ts
index ffffe0d10..f10fa7340 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.component.ts
+++ b/src/viewerModule/viewerCmp/viewerCmp.component.ts
@@ -136,7 +136,7 @@ export class ViewerCmp implements OnDestroy {
   )
 
   public viewerMode: string
-  public viewerMode$ = this.store$.pipe(
+  public hideUi$ = this.store$.pipe(
     select(viewerStateViewerModeSelector),
     distinctUntilChanged(),
   )
diff --git a/src/viewerModule/viewerCmp/viewerCmp.template.html b/src/viewerModule/viewerCmp/viewerCmp.template.html
index 352b73b71..6fa739408 100644
--- a/src/viewerModule/viewerCmp/viewerCmp.template.html
+++ b/src/viewerModule/viewerCmp/viewerCmp.template.html
@@ -7,16 +7,16 @@
 
 
   <!-- Annotation mode -->
-  <div *ngIf="(viewerMode$ | async) === ARIA_LABELS.VIEWER_MODE_ANNOTATING">
+  <div *ngIf="(hideUi$ | 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">
+      <mat-drawer #drawer [mode]="'push'" [disableClose]="true" 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">
+        <div class="d-flex flex-column flex-nowrap w-100">
 
           <!-- top left -->
           <div class="flex-grow-1 d-flex flex-nowrap mb-2">
@@ -34,10 +34,11 @@
 
       </mat-drawer-content>
     </mat-drawer-container>
+    <annotation-message></annotation-message>
   </div>
   <!-- top drawer -->
   <mat-drawer-container
-    [hidden]="viewerMode$ | async"
+    [hidden]="hideUi$ | async"
     [iav-switch-initstate]="false"
     iav-switch
     #sideNavTopSwitch="iavSwitch"
@@ -221,7 +222,7 @@
     </mat-drawer>
 
     <!-- main-content -->
-    <mat-drawer-content class="visible position-relative" [hidden]="viewerMode$ | async">
+    <mat-drawer-content class="visible position-relative" [hidden]="hideUi$ | async">
 
       <iav-layout-fourcorners [iav-layout-fourcorners-cnr-cntr-ngclass]="{'w-100': true}">
 
-- 
GitLab