From 8cbedefbf63a5877ca69b7f35537ab6a12618f29 Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Thu, 17 Jun 2021 14:14:14 +0200
Subject: [PATCH] feat: add edit line component

---
 common/constants.js                           |   4 +-
 .../annotationList.component.ts               |  30 ++---
 .../annotationList.template.html              |  16 ---
 .../singleAnnotationUnit.component.ts         |  17 +--
 .../userAnnotations/tools/line.ts             |   5 +-
 .../tools/line/line.component.ts              | 117 ++++++++++++++++++
 .../userAnnotations/tools/line/line.style.css |   0
 .../tools/line/line.template.html             | 103 +++++++++++++++
 .../userAnnotations/tools/module.ts           |   3 +
 .../tools/point/point.component.ts            |  12 +-
 .../tools/point/point.template.html           |   4 +-
 .../tools/poly/poly.component.ts              |  12 +-
 .../tools/poly/poly.template.html             |   4 +-
 .../userAnnotations/tools/service.ts          |   6 +-
 .../userAnnotations/tools/type.ts             |   4 -
 src/res/css/extra_styles.css                  |   5 +
 16 files changed, 269 insertions(+), 73 deletions(-)
 create mode 100644 src/atlasComponents/userAnnotations/tools/line/line.component.ts
 create mode 100644 src/atlasComponents/userAnnotations/tools/line/line.style.css
 create mode 100644 src/atlasComponents/userAnnotations/tools/line/line.template.html

diff --git a/common/constants.js b/common/constants.js
index d9d3e6c4f..5a7066902 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -64,10 +64,10 @@
     USER_ANNOTATION_LIST: 'user annotations footer',
     USER_ANNOTATION_IMPORT: 'user annotations import',
     USER_ANNOTATION_EXPORT: 'user annotations export',
-    USER_ANNOTATION_EXPORT_SINGLE: 'user annotations export single',
+    USER_ANNOTATION_EXPORT_SINGLE: 'Export annotation',
     USER_ANNOTATION_HIDE: 'user annotations hide',
     USER_ANNOTATION_DELETE: 'user annotations delete',
-    GOTO_ANNOTATION_ROI: 'Navigate to annotation location of interest.'
+    GOTO_ANNOTATION_ROI: 'Navigate to annotation location of interest'
 
   }
 
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
index 141c36903..0dccb5411 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.component.ts
@@ -4,34 +4,34 @@ import {viewerStateChangeNavigation} from "src/services/state/viewerState/action
 import {Store} from "@ngrx/store";
 import {ARIA_LABELS} from "common/constants";
 import { ModularUserAnnotationToolService } from "../tools/service";
-import { EXPORT_FORMAT_INJ_TOKEN, TExportFormats } from "../tools/type";
+import { TExportFormats } from "../tools/type";
+import { ComponentStore } from "src/viewerModule/componentStore";
 
 
 @Component({
   selector: 'annotation-list',
   templateUrl: './annotationList.template.html',
   styleUrls: ['./annotationList.style.css'],
-  providers: [{
-    provide: EXPORT_FORMAT_INJ_TOKEN,
-    useFactory: (svc: ModularUserAnnotationToolService) => svc.exportFormat$,
-    deps: [
-      ModularUserAnnotationToolService
-    ]
-  }]
+  providers: [
+    ComponentStore,
+  ]
 })
 export class AnnotationList {
 
   public ARIA_LABELS = ARIA_LABELS
   public identifier = (index: number, item: any) => item.id
 
-  public availableFormat: TExportFormats[] = ['json', 'sands', 'string']
-  public exportFromat$ = this.annotSvc.exportFormat$
-  public selectExportFormat(format: TExportFormats) {
-    this.exportFromat$.next(format)
-  }
-
   public managedAnnotations$ = this.annotSvc.managedAnnotations$
-  constructor(private store$: Store<any>, public ans: AnnotationService, private annotSvc: ModularUserAnnotationToolService) {}
+  constructor(
+    private store$: Store<any>,
+    public ans: AnnotationService,
+    private annotSvc: ModularUserAnnotationToolService,
+    cStore: ComponentStore<{ useFormat: TExportFormats }>,
+  ) {
+    cStore.setState({
+      useFormat: 'json'
+    })
+  }
 
   toggleAnnotationVisibility(annotation) {
     if (annotation.type === 'polygon') {
diff --git a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
index 5433e233e..2b06e3ade 100644
--- a/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
+++ b/src/atlasComponents/userAnnotations/annotationList/annotationList.template.html
@@ -37,22 +37,6 @@
 
         </div>
 
-        <!-- select export format -->
-        <button mat-icon-button [matMenuTriggerFor]="exportFormatMenu">
-            <i class="fas fa-code"></i>
-        </button>
-
-        <mat-menu #exportFormatMenu="matMenu">
-            <button *ngFor="let format of availableFormat"
-                mat-menu-item
-                (click)="selectExportFormat(format)">
-                <span class="iv-custom-comp text"
-                    [ngClass]="{'primary': (exportFromat$ | async) === format}">
-                    {{ format }}
-                </span>
-            </button>
-        </mat-menu>
-
         <div class="d-flex flex-column">
             <small [ngClass]="[ans.annotationFilter !== 'all'? 'text-muted' : '']"
                    class="cursor-pointer" (click)="ans.refreshFinalAnnotationList('all')">
diff --git a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
index 26124e538..299e8ccf5 100644
--- a/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
+++ b/src/atlasComponents/userAnnotations/singleAnnotationUnit/singleAnnotationUnit.component.ts
@@ -1,9 +1,9 @@
 import { AfterViewInit, Component, ComponentFactoryResolver, Inject, Injector, Input, OnDestroy, Optional, Pipe, PipeTransform, ViewChild, ViewContainerRef } from "@angular/core";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../tools/type";
+import { IAnnotationGeometry, UDPATE_ANNOTATION_TOKEN } from "../tools/type";
 import { Point } from '../tools/point'
 import { Polygon } from '../tools/poly'
 import { FormControl, FormGroup } from "@angular/forms";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 import { select, Store } from "@ngrx/store";
 import { viewerStateFetchedAtlasesSelector } from "src/services/state/viewerState/selectors";
 import { ModularUserAnnotationToolService } from "../tools/service";
@@ -60,7 +60,7 @@ export class SingleAnnotationUnit implements OnDestroy, AfterViewInit{
     private snackbar: MatSnackBar,
     private svc: ModularUserAnnotationToolService,
     private cfr: ComponentFactoryResolver,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) private useFormat$: Observable<TExportFormats>,
+    private injector: Injector,
   ){
     this.subs.push(
       store.pipe(
@@ -82,18 +82,19 @@ export class SingleAnnotationUnit implements OnDestroy, AfterViewInit{
     if (this.managedAnnotation && this.editAnnotationVCR) {
       const editCmp = this.svc.getEditAnnotationCmp(this.managedAnnotation)
       if (!editCmp) {
-        this.snackbar.open(`Update component not found!`)
+        this.snackbar.open(`Update component not found!`, 'Dismiss', {
+          duration: 3000
+        })
         throw new Error(`Edit component not found!`)
       }
       const cf = this.cfr.resolveComponentFactory(editCmp)
+      
       const injector = Injector.create({
         providers: [{
           provide: UDPATE_ANNOTATION_TOKEN,
           useValue: this.managedAnnotation
-        }, {
-          provide: EXPORT_FORMAT_INJ_TOKEN,
-          useValue: this.useFormat$
-        }]
+        }],
+        parent: this.injector
       })
       this.editAnnotationVCR.createComponent(cf, null, injector)
     }
diff --git a/src/atlasComponents/userAnnotations/tools/line.ts b/src/atlasComponents/userAnnotations/tools/line.ts
index 6f6c6b309..923604f28 100644
--- a/src/atlasComponents/userAnnotations/tools/line.ts
+++ b/src/atlasComponents/userAnnotations/tools/line.ts
@@ -39,6 +39,7 @@ export class Line extends IAnnotationGeometry{
       : new Point({
           id: `${this.id}_${getUuid()}`,
           "@type": 'siibra-ex/annotatoin/point',
+          space: this.space,
           ...p
         })
     if (!this.points[0]) this.points[0] = point
@@ -127,11 +128,13 @@ export class Line extends IAnnotationGeometry{
   }
 }
 
+export const LINE_ICON_CLASS = 'fas fa-slash'
+
 export class ToolLine extends AbsToolClass implements IAnnotationTools, OnDestroy {
   static PREVIEW_ID='tool_line_preview'
   public name = 'Line'
   public toolType: TToolType = 'drawing'
-  public iconClass = 'fas fa-slash'
+  public iconClass = LINE_ICON_CLASS
 
   private selectedLine: Line
   
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.component.ts b/src/atlasComponents/userAnnotations/tools/line/line.component.ts
new file mode 100644
index 000000000..b30984ff3
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/tools/line/line.component.ts
@@ -0,0 +1,117 @@
+import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild } from "@angular/core";
+import { MatSnackBar } from "@angular/material/snack-bar";
+import { Store } from "@ngrx/store";
+import { Subscription } from "rxjs";
+import { Line, LINE_ICON_CLASS } from "../line";
+import { ToolCmpBase } from "../toolCmp.base";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { Clipboard } from "@angular/cdk/clipboard";
+import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
+import { Point } from "../point";
+import { ARIA_LABELS } from 'common/constants'
+import { ComponentStore } from "src/viewerModule/componentStore";
+
+@Component({
+  selector: 'line-update-cmp',
+  templateUrl: './line.template.html',
+  styleUrls: [
+    './line.style.css'
+  ]
+})
+
+export class LineUpdateCmp extends ToolCmpBase implements OnDestroy{
+  @Input('update-annotation')
+  public updateAnnotation: Line
+
+  public showMoreFlag = false
+
+  public ARIA_LABELS = ARIA_LABELS
+
+  public annotationLabel = 'Line'
+  public LINE_ICON_CLASS = LINE_ICON_CLASS
+
+  @ViewChild('copyTarget', { read: ElementRef, static: false })
+  copyTarget: ElementRef
+
+  public useFormat: TExportFormats = 'json'
+  private sub: Subscription[] = []
+
+  constructor(
+    private store: Store<any>,
+    snackbar: MatSnackBar,
+    clipboard: Clipboard,
+    private cStore: ComponentStore<{ useFormat: TExportFormats }>,
+    @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
+  ){
+    super(clipboard, snackbar)
+    if (this.cStore) {
+      this.sub.push(
+        this.cStore.select(store => store.useFormat).subscribe((val: TExportFormats) => {
+          this.useFormat = val
+        })
+      )
+    }
+
+    if (updateAnnotation) {
+      if (updateAnnotation instanceof Line) {
+        this.updateAnnotation = updateAnnotation
+      }
+    }
+  }
+
+  public viableFormats: TExportFormats[] = ['json', 'sands']
+
+  setFormat(format: TExportFormats){
+    if (this.cStore) {
+      this.cStore.setState({
+        useFormat: format
+      })
+    }
+  }
+
+  ngOnDestroy(){
+    while (this.sub.length > 0) this.sub.pop().unsubscribe()
+  }
+
+  get copyValue(){
+    return this.copyTarget && this.copyTarget.nativeElement.value
+  }
+
+  gotoRoi(roi?:IAnnotationGeometry){
+    if (!this.updateAnnotation && !roi) {
+      throw new Error(`updateAnnotation undefined`)
+    }
+    if (this.updateAnnotation.points.length < 1) {
+      this.snackbar.open('No points added to polygon yet.', 'Dismiss', {
+        duration: 3000
+      })
+      return
+    }
+    const { x, y, z } = this.updateAnnotation.points[0]
+    
+    this.store.dispatch(
+      viewerStateChangeNavigation({
+        navigation: {
+          position: [x, y, z],
+          positionReal: true,
+          animation: {}
+        }
+      })
+    )
+  }
+
+  gotoPoint(point:Point){
+    if (!point) throw new Error(`Point is not defined.`)
+    const { x, y, z } = point
+
+    this.store.dispatch(
+      viewerStateChangeNavigation({
+        navigation: {
+          position: [x, y, z],
+          positionReal: true,
+          animation: {}
+        }
+      })
+    )
+  }
+}
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.style.css b/src/atlasComponents/userAnnotations/tools/line/line.style.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/atlasComponents/userAnnotations/tools/line/line.template.html b/src/atlasComponents/userAnnotations/tools/line/line.template.html
new file mode 100644
index 000000000..0a851d9d0
--- /dev/null
+++ b/src/atlasComponents/userAnnotations/tools/line/line.template.html
@@ -0,0 +1,103 @@
+<!-- actions -->
+<div class="d-flex">
+
+  <!-- show more -->
+  <button mat-icon-button (click)="showMoreFlag = !showMoreFlag">
+    <i [ngClass]="showMoreFlag ? 'r-90' :  ''"
+      class="t-a-ease-200 transform-origin-center fas fa-chevron-right">
+    </i>
+  </button>
+
+  <!-- spacer -->
+  <div class="flex-grow-1"></div>
+
+  <!-- go to -->
+  <button mat-icon-button
+    [attr.aria-label]="ARIA_LABELS.GOTO_ANNOTATION_ROI"
+    [matTooltip]="ARIA_LABELS.GOTO_ANNOTATION_ROI"
+    (click)="gotoRoi()">
+    <i class="fas fa-map-marked-alt"></i>
+  </button>
+
+  <!-- export -->
+  <button mat-icon-button
+    [attr.aria-label]="ARIA_LABELS.USER_ANNOTATION_EXPORT_SINGLE"
+    [matTooltip]="ARIA_LABELS.USER_ANNOTATION_EXPORT_SINGLE"
+    [matMenuTriggerFor]="exportMenu">
+    <i class="fas fa-file-export"></i>
+  </button>
+</div>
+
+<mat-menu #exportMenu="matMenu" xPosition="before">
+  <div class="iv-custom-comp card text"
+    iav-stop="click">
+
+    <div class="d-flex">
+      <button *ngFor="let format of viableFormats"
+        (click)="setFormat(format)"
+        mat-flat-button
+        [color]="useFormat === format ? 'primary' : ''">
+        {{ format }}
+      </button>
+    </div>
+
+    <div class="iv-custom-comp text">
+      <mat-form-field>
+        <mat-label>
+          {{ useFormat }}
+        </mat-label>
+        <textarea
+          disabled="true"
+          matInput
+          #exportTarget>{{ updateAnnotation.updateSignal$ | async | toFormattedStringPipe : updateAnnotation : useFormat }}</textarea>
+
+        <button mat-icon-button
+          matSuffix
+          iav-stop="click"
+          aria-label="Copy to clipboard"
+          matTooltip="Copy to clipboard."
+          (click)="copyToClipboard(exportTarget.value)"
+          color="basic">
+          <i class="fas fa-copy"></i>
+        </button>
+      </mat-form-field>
+    </div>
+  </div>
+</mat-menu>
+
+<!-- detail pane -->
+<ng-template [ngIf]="showMoreFlag">
+  
+  <h2 class="mat-h4">
+    Points connecting the line
+  </h2>
+  
+  <!-- points detail -->
+  <mat-tab-group animationDuration="0ms">
+  
+    <!-- summary -->
+    <mat-tab label="Summary">
+      <div class="m-2">
+        <mat-chip-list>
+          <mat-chip *ngFor="let point of (updateAnnotation?.points || []) ; let i = index"
+            (click)="gotoPoint(point)">
+            {{ i }}
+          </mat-chip>
+        </mat-chip-list>
+      </div>
+    </mat-tab>
+  
+    <!-- detail -->
+    <mat-tab label="Detail">
+      <ng-template matTabContent>
+        <point-update-cmp
+          *ngFor="let point of (updateAnnotation?.points || []) ; let i = index"
+          class="pl-4"
+          [annotation-label]="'Point ' + ( i + 1 )"
+          [update-annotation]="point">
+        </point-update-cmp>
+      </ng-template>
+    </mat-tab>
+  </mat-tab-group>
+  
+</ng-template>
\ No newline at end of file
diff --git a/src/atlasComponents/userAnnotations/tools/module.ts b/src/atlasComponents/userAnnotations/tools/module.ts
index d68658dbe..3576af312 100644
--- a/src/atlasComponents/userAnnotations/tools/module.ts
+++ b/src/atlasComponents/userAnnotations/tools/module.ts
@@ -3,6 +3,7 @@ import { NgModule } from "@angular/core";
 import { Subject } from "rxjs";
 import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
 import { UtilModule } from "src/util";
+import { LineUpdateCmp } from "./line/line.component";
 import { PointUpdateCmp } from "./point/point.component";
 import { PolyUpdateCmp } from "./poly/poly.component";
 import { ModularUserAnnotationToolService } from "./service";
@@ -16,11 +17,13 @@ import { ANNOTATION_EVENT_INJ_TOKEN } from "./type";
     UtilModule,
   ],
   declarations: [
+    LineUpdateCmp,
     PolyUpdateCmp,
     PointUpdateCmp,
     ToFormattedStringPipe,
   ],
   exports: [
+    LineUpdateCmp,
     PolyUpdateCmp,
     PointUpdateCmp,
   ],
diff --git a/src/atlasComponents/userAnnotations/tools/point/point.component.ts b/src/atlasComponents/userAnnotations/tools/point/point.component.ts
index 869a2c497..9e08437b5 100644
--- a/src/atlasComponents/userAnnotations/tools/point/point.component.ts
+++ b/src/atlasComponents/userAnnotations/tools/point/point.component.ts
@@ -1,12 +1,12 @@
 import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild } from "@angular/core";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { Point, POINT_ICON_CLASS } from "../point";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
 import { Clipboard } from "@angular/cdk/clipboard";
 import { ToolCmpBase } from "../toolCmp.base";
 import { Store } from "@ngrx/store";
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 
 @Component({
   selector: 'point-update-cmp',
@@ -39,18 +39,10 @@ export class PointUpdateCmp extends ToolCmpBase implements OnDestroy{
     private store: Store<any>,
     snackbar: MatSnackBar,
     clipboard: Clipboard,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) useFormat$: Observable<TExportFormats>,
     @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
   ){
     super(clipboard, snackbar)
     
-    if (useFormat$) {
-      this.sub.push(
-        useFormat$.subscribe(val => {
-          this.useFormat = val
-        })
-      )
-    }
     if (updateAnnotation) {
       if (updateAnnotation instanceof Point) {
         this.updateAnnotation = updateAnnotation
diff --git a/src/atlasComponents/userAnnotations/tools/point/point.template.html b/src/atlasComponents/userAnnotations/tools/point/point.template.html
index 2fd1334d2..c5fdf7805 100644
--- a/src/atlasComponents/userAnnotations/tools/point/point.template.html
+++ b/src/atlasComponents/userAnnotations/tools/point/point.template.html
@@ -6,7 +6,7 @@
     <i [class]="POINT_ICON_CLASS"></i>
   </button>
 
-  <form class="flex-grow-1 flex-shrink-1">
+  <div class="flex-grow-1 flex-shrink-1">
     <mat-form-field class="w-100">
       <mat-label>
         {{ annotationLabel }}
@@ -28,5 +28,5 @@
         <i class="fas fa-copy"></i>
       </button>
     </mat-form-field>
-  </form>
+  </div>
 </div>
diff --git a/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts b/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
index e6c734730..3621c2d25 100644
--- a/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
+++ b/src/atlasComponents/userAnnotations/tools/poly/poly.component.ts
@@ -2,11 +2,11 @@ import { Component, ElementRef, Inject, Input, OnDestroy, Optional, ViewChild }
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { Polygon, POLY_ICON_CLASS } from "../poly";
 import { ToolCmpBase } from "../toolCmp.base";
-import { EXPORT_FORMAT_INJ_TOKEN, IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
+import { IAnnotationGeometry, TExportFormats, UDPATE_ANNOTATION_TOKEN } from "../type";
 import { Clipboard } from "@angular/cdk/clipboard";
 import { viewerStateChangeNavigation } from "src/services/state/viewerState/actions";
 import { Store } from "@ngrx/store";
-import { Observable, Subscription } from "rxjs";
+import { Subscription } from "rxjs";
 
 @Component({
   selector: 'poly-update-cmp',
@@ -33,17 +33,9 @@ export class PolyUpdateCmp extends ToolCmpBase implements OnDestroy{
     private store: Store<any>,
     snackbar: MatSnackBar,
     clipboard: Clipboard,
-    @Optional() @Inject(EXPORT_FORMAT_INJ_TOKEN) useFormat$: Observable<TExportFormats>,
     @Optional() @Inject(UDPATE_ANNOTATION_TOKEN) updateAnnotation: IAnnotationGeometry,
   ){
     super(clipboard, snackbar)
-    if (useFormat$) {
-      this.sub.push(
-        useFormat$.subscribe(val => {
-          this.useFormat = val
-        })
-      )
-    }
 
     if (updateAnnotation) {
       if (updateAnnotation instanceof Polygon) {
diff --git a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
index a26ca35b9..52dab491e 100644
--- a/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
+++ b/src/atlasComponents/userAnnotations/tools/poly/poly.template.html
@@ -6,7 +6,7 @@
     <i [class]="POLY_ICON_CLASS"></i>
   </button>
 
-  <form class="flex-grow-1 flex-shrink-1">
+  <div class="flex-grow-1 flex-shrink-1">
     <mat-form-field class="w-100">
       <mat-label>
         {{ annotationLabel }}
@@ -26,7 +26,7 @@
         <i class="fas fa-copy"></i>
       </button>
     </mat-form-field>
-  </form>
+  </div>
 </div>
 
 <point-update-cmp
diff --git a/src/atlasComponents/userAnnotations/tools/service.ts b/src/atlasComponents/userAnnotations/tools/service.ts
index 8697311dc..2cc09e7e4 100644
--- a/src/atlasComponents/userAnnotations/tools/service.ts
+++ b/src/atlasComponents/userAnnotations/tools/service.ts
@@ -14,6 +14,7 @@ import {Line, ToolLine} from "src/atlasComponents/userAnnotations/tools/line";
 import { PolyUpdateCmp } from './poly/poly.component'
 import { Point, ToolPoint } from "./point";
 import { PointUpdateCmp } from "./point/point.component";
+import { LineUpdateCmp } from "./line/line.component";
 
 const IAV_VOXEL_SIZES_NM = {
   'minds/core/referencespace/v1.0.0/265d32a0-3d84-40a5-926f-bf89f68212b9': [25000, 25000, 25000],
@@ -182,8 +183,6 @@ export class ModularUserAnnotationToolService implements OnDestroy{
     }
   }
 
-  public exportFormat$ = new BehaviorSubject<TExportFormats>('string')
-
   constructor(
     store: Store<any>,
     @Inject(INJ_ANNOT_TARGET) annotTarget$: Observable<HTMLElement>,
@@ -199,7 +198,8 @@ export class ModularUserAnnotationToolService implements OnDestroy{
 
     this.registerTool({
       toolCls: ToolLine,
-      target: Line
+      target: Line,
+      editCmp: LineUpdateCmp,
     })
 
     this.registerTool({
diff --git a/src/atlasComponents/userAnnotations/tools/type.ts b/src/atlasComponents/userAnnotations/tools/type.ts
index 0323f6f8f..0a0b1bebc 100644
--- a/src/atlasComponents/userAnnotations/tools/type.ts
+++ b/src/atlasComponents/userAnnotations/tools/type.ts
@@ -326,7 +326,3 @@ export interface ClassInterface<T> {
 }
 
 export type TExportFormats = 'sands' | 'json' | 'string'
-
-export const EXPORT_FORMAT_INJ_TOKEN = new InjectionToken<
-  Observable<TExportFormats>
->('EXPORT_FORMAT_INJ_TOKEN')
diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css
index a295e3f09..e98f09941 100644
--- a/src/res/css/extra_styles.css
+++ b/src/res/css/extra_styles.css
@@ -370,6 +370,11 @@ markdown-dom p
   pointer-events: all;
 }
 
+.t-a-ease-200
+{
+  transition: all ease 200ms;
+}
+
 .t-a-ease-500
 {
   transition: all ease 500ms;
-- 
GitLab