From 39f7c923a4e2b5d27bbda378e39dc31d1ec542a3 Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Thu, 23 Apr 2020 15:23:45 +0200
Subject: [PATCH] chore: update tight int of pmap

---
 common/constants.js                           |   7 +-
 e2e/src/navigating/originDataset.e2e-spec.js  |  80 +++++
 e2e/src/util.js                               |   8 +
 src/components/components.module.ts           |   3 +
 src/components/vButton/vButton.component.ts   |  18 ++
 src/components/vButton/vButton.style.css      |  28 ++
 src/components/vButton/vButton.template.html  |  14 +
 src/services/state/dataStore.store.ts         |  14 +-
 src/services/state/ngViewerState.store.ts     |  42 +--
 src/theme.scss                                |  30 ++
 .../databrowserModule/databrowser.module.ts   |  51 +++-
 .../databrowser.useEffect.ts                  |  80 ++++-
 .../previewDatasetFile.directive.spec.ts      | 112 ++++++-
 .../previewDatasetFile.directive.ts           |  28 +-
 src/ui/layerbrowser/layerbrowser.component.ts |   6 +-
 .../nehubaContainer.component.ts              |   2 +-
 src/ui/parcellationRegion/region.base.ts      |   4 +
 .../regionMenu/regionMenu.style.css           |  13 +-
 .../regionMenu/regionMenu.template.html       | 277 +++++++++++-------
 .../searchSideNav/searchSideNav.component.ts  |   1 -
 src/util/directives/switch.directive.ts       |  21 ++
 src/util/pipes/addUnitAndJoin.pipe.ts         |  12 +
 src/util/pipes/numbers.pipe.ts                |  12 +
 src/util/util.module.ts                       |  11 +-
 24 files changed, 703 insertions(+), 171 deletions(-)
 create mode 100644 e2e/src/navigating/originDataset.e2e-spec.js
 create mode 100644 src/components/vButton/vButton.component.ts
 create mode 100644 src/components/vButton/vButton.style.css
 create mode 100644 src/components/vButton/vButton.template.html
 create mode 100644 src/util/directives/switch.directive.ts
 create mode 100644 src/util/pipes/addUnitAndJoin.pipe.ts
 create mode 100644 src/util/pipes/numbers.pipe.ts

diff --git a/common/constants.js b/common/constants.js
index 363efa6a8..bfb603d31 100644
--- a/common/constants.js
+++ b/common/constants.js
@@ -6,6 +6,11 @@
     SHARE_BTN: `Share this view`,
     SHARE_COPY_URL_CLIPBOARD: `Copy URL to clipboard`,
     SHARE_CUSTOM_URL: 'Create a custom URL',
-    SHARE_CUSTOM_URL_DIALOG: 'Dialog for creating a custom URL'
+    SHARE_CUSTOM_URL_DIALOG: 'Dialog for creating a custom URL',
+
+    // parcellation region specific
+    SHOW_ORIGIN_DATASET: `Show probabilistic map`,
+    SHOW_CONNECTIVITY_DATA: `Show connectivity data`,
+    SHOW_IN_OTHER_REF_SPACE: `Show in other reference space`,
   }
 })(typeof exports === 'undefined' ? module.exports : exports)
diff --git a/e2e/src/navigating/originDataset.e2e-spec.js b/e2e/src/navigating/originDataset.e2e-spec.js
new file mode 100644
index 000000000..22d774177
--- /dev/null
+++ b/e2e/src/navigating/originDataset.e2e-spec.js
@@ -0,0 +1,80 @@
+const { AtlasPage } = require("../util")
+const { ARIA_LABELS } = require('../../../common/constants')
+const { SHOW_CONNECTIVITY_DATA, SHOW_IN_OTHER_REF_SPACE, SHOW_ORIGIN_DATASET } = ARIA_LABELS
+
+const cssSelector = `[aria-label="${SHOW_ORIGIN_DATASET}"]`
+
+const dict = {
+  'ICBM 2009c Nonlinear Asymmetric': {
+    'JuBrain Cytoarchitectonic Atlas': {
+      tests: [
+        {
+          position: [600, 490],
+          expectedLabelName: 'Area 6ma (preSMA, mesial SFG) - left hemisphere',
+        }
+      ]
+    }
+  }
+}
+
+describe('origin dataset pmap', () => {
+  let iavPage
+
+  beforeAll(async () => {
+    iavPage = new AtlasPage()
+    await iavPage.init()
+  })
+
+  for (const templateName in dict) {
+    for (const parcellationName in dict[templateName]) {
+      describe(`testing template: ${templateName}, parcellation name: ${parcellationName}`, () => {
+
+        const {url, tests} = dict[templateName][parcellationName]
+        beforeAll(async () => {
+          if (url) {
+            await iavPage.goto(url)
+          } else {
+            await iavPage.goto()
+            await iavPage.selectTitleTemplateParcellation(templateName, parcellationName)
+          }
+          
+          const tag = await iavPage.getSideNavTag()
+          await tag.click()
+          await iavPage.wait(5000)
+          await iavPage.waitUntilAllChunksLoaded()
+        })
+
+        for (const test of tests) {
+          it('> original pmap btn exists, and on click, show pmap', async () => {
+
+            const { position, expectedLabelName } = test
+            await iavPage.cursorMoveToAndClick({ position })
+
+            await iavPage.click(cssSelector)
+            await iavPage.wait(5000)
+            await iavPage.waitForAsync()
+
+            const additionalLayerControlIsShown = await iavPage.additionalLayerControlIsVisible()
+            expect(additionalLayerControlIsShown).toEqual(true)
+            
+            const checked = await iavPage.switchIsChecked(cssSelector)
+            expect(checked).toEqual(true)
+          })
+
+          it('> on second click, dismisses the pmap', async () => {
+
+            await iavPage.click(cssSelector)
+            await iavPage.wait(5000)
+            await iavPage.waitForAsync()
+
+            const additionalLayerControlIsShown = await iavPage.additionalLayerControlIsVisible()
+            expect(additionalLayerControlIsShown).toEqual(false)
+            
+            const checked = await iavPage.switchIsChecked(cssSelector)
+            expect(checked).toEqual(false)
+          })
+        }
+      })
+    }
+  }
+})
\ No newline at end of file
diff --git a/e2e/src/util.js b/e2e/src/util.js
index f9a7519ff..2c53dd6e2 100644
--- a/e2e/src/util.js
+++ b/e2e/src/util.js
@@ -92,6 +92,14 @@ class WdBase{
     return result
   }
 
+  async switchIsChecked(cssSelector){
+    if (!cssSelector) throw new Error(`switchChecked method requies css selector`)
+    const checked = await this._browser
+      .findElement( By.css(cssSelector) )
+      .getAttribute('aria-checked')
+    return checked === 'true'
+  }
+
   async click(cssSelector){
     if (!cssSelector) throw new Error(`click method needs to define a css selector`)
     await this._browser.findElement( By.css(cssSelector) ).click()
diff --git a/src/components/components.module.ts b/src/components/components.module.ts
index c16f932a5..f6cdb091c 100644
--- a/src/components/components.module.ts
+++ b/src/components/components.module.ts
@@ -31,6 +31,7 @@ import { SleightOfHand } from './sleightOfHand/soh.component';
 import { TimerComponent } from './timer/timer.component';
 import { TreeComponent } from './tree/tree.component';
 import { TreeBaseDirective } from './tree/treeBase.directive';
+import { IAVVerticalButton } from './vButton/vButton.component';
 
 @NgModule({
   imports : [
@@ -56,6 +57,7 @@ import { TreeBaseDirective } from './tree/treeBase.directive';
     SleightOfHand,
     DialogComponent,
     ConfirmDialogComponent,
+    IAVVerticalButton,
 
     /* directive */
     HoverableBlockDirective,
@@ -88,6 +90,7 @@ import { TreeBaseDirective } from './tree/treeBase.directive';
     SleightOfHand,
     DialogComponent,
     ConfirmDialogComponent,
+    IAVVerticalButton,
 
     SearchResultPaginationPipe,
     TreeSearchPipe,
diff --git a/src/components/vButton/vButton.component.ts b/src/components/vButton/vButton.component.ts
new file mode 100644
index 000000000..63eda444b
--- /dev/null
+++ b/src/components/vButton/vButton.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input, ChangeDetectionStrategy } from "@angular/core";
+
+@Component({
+  selector: 'iav-v-button',
+  templateUrl: './vButton.template.html',
+  styleUrls: [
+    './vButton.style.css'
+  ],
+  exportAs: 'iavVButton',
+  changeDetection: ChangeDetectionStrategy.OnPush
+})
+
+export class IAVVerticalButton{
+  @Input() color: 'default' | 'primary' | 'accent' | 'warng' = 'default'
+  get class(){
+    return `d-flex flex-column align-items-center iv-custom-comp ${this.color} h-100`
+  }
+}
\ No newline at end of file
diff --git a/src/components/vButton/vButton.style.css b/src/components/vButton/vButton.style.css
new file mode 100644
index 000000000..d5201cbe5
--- /dev/null
+++ b/src/components/vButton/vButton.style.css
@@ -0,0 +1,28 @@
+:host
+{
+  padding: 1rem 2rem;
+  /* background-color:rgba(128,128,128,0.3) */
+}
+
+:host:hover
+{
+  cursor: pointer;
+}
+
+.icon-container
+{
+  flex-basis: 2.5rem;
+}
+
+.text-container
+{
+  flex-basis: 0;
+  overflow: visible;
+  text-align: center;
+}
+
+.footer-container
+{
+  flex-basis: 0rem;
+  margin-bottom: -1rem;
+}
\ No newline at end of file
diff --git a/src/components/vButton/vButton.template.html b/src/components/vButton/vButton.template.html
new file mode 100644
index 000000000..539d1b897
--- /dev/null
+++ b/src/components/vButton/vButton.template.html
@@ -0,0 +1,14 @@
+<div [class]="class">
+  <div class="icon-container flex-grow-0 flex-shrink-0">
+    <ng-content select="[iav-v-button-icon]">
+    </ng-content>
+  </div>
+  <div class="text-container flex-grow-1 flex-shrink-1">
+    <ng-content select="[iav-v-button-text]">
+    </ng-content>
+  </div>
+  <div class="footer-container flex-grow-0 flex-shrink-0">
+    <ng-content select="[iav-v-button-footer]">
+    </ng-content>
+  </div>
+</div>
\ No newline at end of file
diff --git a/src/services/state/dataStore.store.ts b/src/services/state/dataStore.store.ts
index 5d16c11a6..07782dfec 100644
--- a/src/services/state/dataStore.store.ts
+++ b/src/services/state/dataStore.store.ts
@@ -18,8 +18,6 @@ export interface IStateInterface {
   datasetPreviews: DatasetPreview[]
 }
 
-
-
 export const defaultState = {
   fetchedDataEntries: [],
   favDataEntries: (() => {
@@ -74,6 +72,17 @@ export const getStateStore = ({ state: state = defaultState } = {}) => (prevStat
       })
     }
   }
+  case ACTION_TYPES.CLEAR_PREVIEW_DATASET: {
+    const { payload = {}} = action
+    const { file , dataset } = payload
+    const { fullId } = dataset
+    const { filename } = file
+    return {
+      ...prevState,
+      datasetPreviews: prevState.datasetPreviews
+        .filter(({ datasetId, filename: fName }) => !(datasetId === fullId && fName === filename))
+    }
+  }
   case ACTION_TYPES.CLEAR_PREVIEW_DATASETS: {
     return {
       ...prevState,
@@ -233,6 +242,7 @@ const ACTION_TYPES = {
   UNFAV_DATASET: 'UNFAV_DATASET',
   TOGGLE_FAV_DATASET: 'TOGGLE_FAV_DATASET',
   PREVIEW_DATASET: 'PREVIEW_DATASET',
+  CLEAR_PREVIEW_DATASET: 'CLEAR_PREVIEW_DATASET',
   CLEAR_PREVIEW_DATASETS: 'CLEAR_PREVIEW_DATASETS'
 }
 
diff --git a/src/services/state/ngViewerState.store.ts b/src/services/state/ngViewerState.store.ts
index aaa71a273..652310cec 100644
--- a/src/services/state/ngViewerState.store.ts
+++ b/src/services/state/ngViewerState.store.ts
@@ -6,6 +6,8 @@ import { AtlasViewerConstantsServices } from 'src/atlasViewer/atlasViewer.consta
 import { SNACKBAR_MESSAGE } from './uiState.store';
 import { getNgIds, IavRootStoreInterface, GENERAL_ACTION_TYPES } from '../stateStore.service';
 import { Action, select, Store } from '@ngrx/store'
+import { BACKENDURL } from 'src/util/constants';
+import { HttpClient } from '@angular/common/http';
 
 export const FOUR_PANEL = 'FOUR_PANEL'
 export const V_ONE_THREE = 'V_ONE_THREE'
@@ -78,26 +80,7 @@ export const getStateStore = ({ state = defaultState } = {}) => (prevState: Stat
   case ADD_NG_LAYER:
     return {
       ...prevState,
-
-      /* this configration hides the layer if a non mixable layer already present */
-
-      /* this configuration does not the addition of multiple non mixable layers */
-      // layers : action.layer.mixability === 'nonmixable' && prevState.layers.findIndex(l => l.mixability === 'nonmixable') >= 0
-      //   ? prevState.layers
-      //   : prevState.layers.concat(action.layer)
-
-      /* this configuration allows the addition of multiple non mixables */
-      // layers : prevState.layers.map(l => mapLayer(l, action.layer)).concat(action.layer)
       layers : mixNgLayers(prevState.layers, action.layer),
-
-      // action.layer.constructor === Array
-      //   ? prevState.layers.concat(action.layer)
-      //   : prevState.layers.concat({
-      //     ...action.layer,
-      //     ...( action.layer.mixability === 'nonmixable' && prevState.layers.findIndex(l => l.mixability === 'nonmixable') >= 0
-      //           ? {visible: false}
-      //           : {})
-      //   })
     }
   case REMOVE_NG_LAYERS: {
     const { layers } = action
@@ -198,30 +181,34 @@ export class NgViewerUseEffect implements OnDestroy {
   constructor(
     private actions: Actions,
     private store$: Store<IavRootStoreInterface>,
-    private constantService: AtlasViewerConstantsServices
+    private constantService: AtlasViewerConstantsServices,
+    private http: HttpClient,
   ){
 
     // TODO either split backend user to be more granular, or combine the user config into a single subscription
     this.subscriptions.push(
       this.store$.pipe(
         select('ngViewerState'),
-        distinctUntilChanged(),
         debounceTime(200),
         skip(1),
         // Max frequency save once every second
+
+        // properties to be saved
+        map(({ panelMode, panelOrder }) => {
+          return { panelMode, panelOrder }
+        }),
+        distinctUntilChanged(),
         throttleTime(1000)
-      ).subscribe(({panelMode, panelOrder}) => {
-        fetch(`${this.constantService.backendUrl}user/config`, {
-          method: 'POST',
+      ).subscribe(ngViewerState => {
+        this.http.post(`${BACKENDURL}user/config`, JSON.stringify({ ngViewerState }),  {
           headers: {
             'Content-type': 'application/json'
-          },
-          body: JSON.stringify({ ngViewerState: { panelMode, panelOrder } })
+          }
         })
       })
     )
 
-    this.applySavedUserConfig$ = from(fetch(`${this.constantService.backendUrl}user/config`).then(r => r.json())).pipe(
+    this.applySavedUserConfig$ = this.http.get(`${BACKENDURL}user/config`).pipe(
       catchError((err,caught) => of(null)),
       filter(v => !!v),
       withLatestFrom(this.store$),
@@ -449,6 +436,7 @@ export interface INgLayerInterface {
   name: string
   source: string
   mixability: string // base | mixable | nonmixable
+  annotation?: string //
   visible?: boolean
   shader?: string
   transform?: any
diff --git a/src/theme.scss b/src/theme.scss
index 71c0a7c3d..abd448e9a 100644
--- a/src/theme.scss
+++ b/src/theme.scss
@@ -2,6 +2,34 @@
 
 @include  mat-core();
 
+@mixin custom-cmp($theme) {
+  $primary: map-get($theme, primary);
+  $accent: map-get($theme, accent);
+  $warn: map-get($theme, warn);
+
+  [iv-custom-comp],
+  .iv-custom-comp
+  {
+    &[primary],
+    &.primary
+    {
+      color: mat-color($primary);
+    }
+
+    &[accent],
+    &.accent
+    {
+      color: mat-color($accent);
+    }
+
+    &[warn],
+    &.warn
+    {
+      color: mat-color($warn);
+    }
+  }
+}
+
 $iv-theme-primary: mat-palette($mat-indigo);
 $iv-theme-accent: mat-palette($mat-amber);
 $iv-theme-warn: mat-palette($mat-red);
@@ -9,6 +37,7 @@ $iv-theme-warn: mat-palette($mat-red);
 $iv-theme: mat-light-theme($iv-theme-primary, $iv-theme-accent, $iv-theme-warn);
 
 @include angular-material-theme($iv-theme);
+@include custom-cmp($iv-theme);
 
 $iv-dark-theme-primary: mat-palette($mat-blue);
 $iv-dark-theme-accent:  mat-palette($mat-amber, A200, A100, A400);
@@ -18,6 +47,7 @@ $iv-dark-theme:   mat-dark-theme($iv-dark-theme-primary, $iv-dark-theme-accent,
 [darktheme=true]
 {
   @include angular-material-theme($iv-dark-theme);
+  @include custom-cmp($iv-dark-theme);
 }
 
 .iav-dialog-class
diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts
index 00ced43a6..422d9cb01 100644
--- a/src/ui/databrowserModule/databrowser.module.ts
+++ b/src/ui/databrowserModule/databrowser.module.ts
@@ -1,5 +1,5 @@
 import { CommonModule } from "@angular/common";
-import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA, OnDestroy } from "@angular/core";
 import { FormsModule } from "@angular/forms";
 import { ComponentsModule } from "src/components/components.module";
 import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
@@ -29,21 +29,46 @@ import { DatasetPreviewList, UnavailableTooltip } from "./singleDataset/datasetP
 import { PreviewComponentWrapper } from "./preview/previewComponentWrapper/previewCW.component";
 import { BulkDownloadBtn, TransformDatasetToIdPipe } from "./bulkDownload/bulkDownloadBtn.component";
 import { ShowDatasetDialogDirective, IAV_DATASET_SHOW_DATASET_DIALOG_CMP } from "./showDatasetDialog.directive";
-import { PreviewDatasetFile, IAV_DATASET_PREVIEW_DATASET_FN } from "./singleDataset/datasetPreviews/previewDatasetFile.directive";
-import { Store } from "@ngrx/store";
+import { PreviewDatasetFile, IAV_DATASET_PREVIEW_DATASET_FN, IAV_DATASET_PREVIEW_ACTIVE } from "./singleDataset/datasetPreviews/previewDatasetFile.directive";
+import { Store, select } from "@ngrx/store";
 import { DATASETS_ACTIONS_TYPES } from "src/services/state/dataStore.store";
+import { startWith, map, take, debounceTime } from "rxjs/operators";
+import { Observable } from "rxjs";
 
+const previewDisplayedFactory = (store: Store<any>) => {
+
+  return (file, dataset) => store.pipe(
+    select('dataStore'),
+    select('datasetPreviews'),
+    startWith([]),
+    map(datasetPreviews => {
+      const { fullId } = dataset || {}
+      const { filename } = file
+      return (datasetPreviews as any[]).findIndex(({ datasetId, filename: fName }) =>
+        datasetId === fullId && fName === filename) >= 0
+    })
+  )
+}
 
 // TODO not too sure if this is the correct place for providing the callback token
-const previewEmitFactory = (store) => {
+const previewEmitFactory = (store: Store<any>, previewDisplayed: (file,dataset) => Observable<boolean>) => {
+
   return (file, dataset) => {
-    store.dispatch({
-      type: DATASETS_ACTIONS_TYPES.PREVIEW_DATASET,
-      payload: {
-        file,
-        dataset
-      }
-    })
+    previewDisplayed(file, dataset).pipe(
+      debounceTime(10),
+      take(1),
+    ).subscribe(flag => 
+      
+      store.dispatch({
+        type: flag
+          ? DATASETS_ACTIONS_TYPES.CLEAR_PREVIEW_DATASET
+          : DATASETS_ACTIONS_TYPES.PREVIEW_DATASET,
+        payload: {
+          file,
+          dataset
+        }
+      })
+    )
   }
 }
 
@@ -116,6 +141,10 @@ const previewEmitFactory = (store) => {
     },{
       provide: IAV_DATASET_PREVIEW_DATASET_FN,
       useFactory: previewEmitFactory,
+      deps: [ Store, IAV_DATASET_PREVIEW_ACTIVE ]
+    },{
+      provide: IAV_DATASET_PREVIEW_ACTIVE,
+      useFactory: previewDisplayedFactory,
       deps: [ Store ]
     }
   ],
diff --git a/src/ui/databrowserModule/databrowser.useEffect.ts b/src/ui/databrowserModule/databrowser.useEffect.ts
index b760603e5..c107a7d27 100644
--- a/src/ui/databrowserModule/databrowser.useEffect.ts
+++ b/src/ui/databrowserModule/databrowser.useEffect.ts
@@ -4,7 +4,7 @@ import { select, Store } from "@ngrx/store";
 import { from, merge, Observable, of, Subscription, forkJoin, combineLatest } from "rxjs";
 import { filter, map, scan, switchMap, withLatestFrom, mapTo, shareReplay, startWith, distinctUntilChanged, concatMap } from "rxjs/operators";
 import { LoggingService } from "src/logging";
-import { DATASETS_ACTIONS_TYPES, IDataEntry, ViewerPreviewFile } from "src/services/state/dataStore.store";
+import { DATASETS_ACTIONS_TYPES, IDataEntry, ViewerPreviewFile, DatasetPreview } from "src/services/state/dataStore.store";
 import { IavRootStoreInterface, ADD_NG_LAYER, CHANGE_NAVIGATION } from "src/services/stateStore.service";
 import { LOCAL_STORAGE_CONST, DS_PREVIEW_URL } from "src/util/constants";
 import { KgSingleDatasetService } from "./kgSingleDatasetService.service";
@@ -16,6 +16,9 @@ import { MatDialog } from "@angular/material/dialog";
 import { PreviewComponentWrapper } from "./preview/previewComponentWrapper/previewCW.component";
 import { getKgSchemaIdFromFullId } from "./util/getKgSchemaIdFromFullId.pipe";
 import { HttpClient } from "@angular/common/http";
+import { INgLayerInterface, REMOVE_NG_LAYERS } from "src/services/state/ngViewerState.store";
+
+const DATASET_PREVIEW_ANNOTATION = `DATASET_PREVIEW_ANNOTATION`
 
 @Injectable({
   providedIn: 'root',
@@ -30,6 +33,9 @@ export class DataBrowserUseEffect implements OnDestroy {
   @Effect()
   previewNgLayer$: Observable<any>
 
+  @Effect()
+  removePreviewNgLayers$: Observable<any>
+
   // registerd layers (to be further developed)
   @Effect()
   previewRegisteredVolumes$: Observable<any>
@@ -45,6 +51,8 @@ export class DataBrowserUseEffect implements OnDestroy {
   public previewDatasetFile$: Observable<ViewerPreviewFile>
   private storePreviewDatasetFile$: Observable<{dataset: IDataEntry,file: ViewerPreviewFile}[]>
 
+  private datasetPreviews$: Observable<DatasetPreview[]>
+
   constructor(
     private store$: Store<IavRootStoreInterface>,
     private actions$: Actions<any>,
@@ -55,12 +63,51 @@ export class DataBrowserUseEffect implements OnDestroy {
     private http: HttpClient
   ) {
 
+    const ngViewerStateLayers$ = this.store$.pipe(
+      select('ngViewerState'),
+      select('layers'),
+      startWith([]),
+      shareReplay(1)
+    ) as Observable<INgLayerInterface[]>
+
+    this.datasetPreviews$ = this.store$.pipe(
+      select('dataStore'),
+      select('datasetPreviews'),
+      startWith([]),
+      shareReplay(1),
+    )
+
+    this.removePreviewDataset$ = ngViewerStateLayers$.pipe(
+      map(layers => layers.filter(({ annotation }) => annotation && annotation.indexOf(DATASET_PREVIEW_ANNOTATION) >= 0)),
+      withLatestFrom(this.datasetPreviews$),
+      map(([ ngViewerLayers, datasetPreviews ]) => {
+        return datasetPreviews.filter(({ filename }) => {
+          return ngViewerLayers.findIndex(({ annotation }) => annotation.indexOf(filename) >= 0) < 0
+        })
+      }),
+      filter(arr => arr.length > 0),
+      concatMap(arr => from(arr).pipe(
+        map(item => {
+          const { filename, datasetId } = item
+          return {
+            type: DATASETS_ACTIONS_TYPES.CLEAR_PREVIEW_DATASET,
+            payload: {
+              dataset: {
+                fullId: datasetId
+              },
+              file: {
+                filename
+              }
+            }
+          }
+        })
+      ))
+    )
+
     // TODO this is almost definitely wrong
     // possibily causing https://github.com/HumanBrainProject/interactive-viewer/issues/502
     this.subscriptions.push(
-      this.store$.pipe(
-        select('dataStore'),
-        select('datasetPreviews'),
+      this.datasetPreviews$.pipe(
         filter(datasetPreviews => datasetPreviews.length > 0),
         map((datasetPreviews) => datasetPreviews[datasetPreviews.length - 1]),
         switchMap(({ datasetId, filename }) =>{
@@ -207,16 +254,34 @@ export class DataBrowserUseEffect implements OnDestroy {
       })
     )
 
+    this.removePreviewNgLayers$ = this.datasetPreviews$.pipe(
+      withLatestFrom( ngViewerStateLayers$ ),
+      map(([ datasetPreviews, ngLayers ]) => {
+        const previewingFilesName = datasetPreviews.map(({ filename }) => filename)
+        return ngLayers.filter(({ name, annotation }) =>
+          annotation && annotation.indexOf(DATASET_PREVIEW_ANNOTATION) >= 0
+          && previewingFilesName.indexOf(name) < 0)
+      }),
+      filter(layers => layers.length > 0),
+      map(layers => {
+        return {
+          type: REMOVE_NG_LAYERS,
+          layers
+        }
+      })
+    )
+
     this.previewNgLayer$ = this.previewDatasetFile$.pipe(
       filter(file => 
         determinePreviewFileType(file) === PREVIEW_FILE_TYPES.NIFTI
       ),
-      map(({ url }) => {
+      map(({ url, filename }) => {
         const layer = {
-          name: url,
+          name: filename,
           source : `nifti://${url}`,
           mixability : 'nonmixable',
           shader : GLSL_COLORMAP_JET,
+          annotation: `${DATASET_PREVIEW_ANNOTATION} ${filename}`
         }
         return {
           type: ADD_NG_LAYER,
@@ -357,4 +422,7 @@ export class DataBrowserUseEffect implements OnDestroy {
 
   @Effect()
   public toggleDataset$: Observable<any>
+
+  @Effect()
+  public removePreviewDataset$: Observable<any>
 }
diff --git a/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.spec.ts b/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.spec.ts
index cde8f3681..87c32a9fc 100644
--- a/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.spec.ts
+++ b/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.spec.ts
@@ -3,23 +3,29 @@ import { async, TestBed } from "@angular/core/testing";
 import { By } from "@angular/platform-browser";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { AngularMaterialModule } from "src/ui/sharedModules/angularMaterial.module";
-import { PreviewDatasetFile, IAV_DATASET_PREVIEW_DATASET_FN } from './previewDatasetFile.directive'
+import { PreviewDatasetFile, IAV_DATASET_PREVIEW_DATASET_FN, IAV_DATASET_PREVIEW_ACTIVE } from './previewDatasetFile.directive'
+import { Subject } from "rxjs";
 
 @Component({
   template: ''
 })
 
-class TestCmp{}
+class TestCmp{
+  testmethod(arg) {}
+}
 
 const dummyMatSnackBar = {
   open: jasmine.createSpy('open')
 }
 
 const previewDatasetFnSpy = jasmine.createSpy('previewDatasetFn')
+const mockDatasetActiveObs = new Subject()
+const getDatasetActiveObs = jasmine.createSpy('getDatasetActive').and.returnValue(mockDatasetActiveObs)
 
 describe('ShowDatasetDialogDirective', () => {
+  let testModule
   beforeEach(async(() => {
-    TestBed
+    testModule = TestBed
       .configureTestingModule({
         imports: [
           AngularMaterialModule
@@ -36,7 +42,11 @@ describe('ShowDatasetDialogDirective', () => {
           {
             provide: IAV_DATASET_PREVIEW_DATASET_FN,
             useValue: previewDatasetFnSpy
-          }
+          },
+          // {
+          //   provide: IAV_DATASET_PREVIEW_ACTIVE,
+          //   useValue: getDatasetActiveObs
+          // }
         ]
       })
       
@@ -61,6 +71,100 @@ describe('ShowDatasetDialogDirective', () => {
     expect(directive).not.toBeNull()
   })
 
+  describe('> DI', () => {
+    describe(`> ${IAV_DATASET_PREVIEW_ACTIVE}`, () => {
+
+      afterEach(() => {
+        getDatasetActiveObs.calls.reset()
+      })
+
+      describe('> if not provided', () => {
+        beforeEach(() => {
+          TestBed.overrideComponent(TestCmp, {
+            set: {
+              template: `
+              <div iav-dataset-preview-dataset-file
+                (iav-dataset-preview-active-changed)="testmethod($event)"
+                iav-dataset-preview-dataset-file-filename="banana">
+              </div>
+              `,
+            }
+          }).compileComponents()
+        })
+
+
+        it('> should init directive', () => {
+          const fixture = TestBed.createComponent(TestCmp)
+          fixture.detectChanges()
+          const directive = fixture.debugElement.query( By.directive( PreviewDatasetFile ) )
+          expect(directive).toBeTruthy()
+        })
+
+        it('> should not call getDatasetActiveObs', () => {
+
+          const fixture = TestBed.createComponent(TestCmp)
+          fixture.detectChanges()
+          expect(getDatasetActiveObs).not.toHaveBeenCalled()
+        })
+
+        it('> if not provided, on subject next, should not emit active$', () => {
+          
+          const fixture = TestBed.createComponent(TestCmp)
+          const cmp = fixture.debugElement.componentInstance
+
+          const testmethodSpy = spyOn(cmp, 'testmethod')
+
+          fixture.detectChanges()
+          mockDatasetActiveObs.next(true)
+          fixture.detectChanges()
+
+          expect(testmethodSpy).not.toHaveBeenCalled()
+        })
+      })
+
+      describe('> if provided', () => {
+        beforeEach(() => {
+          TestBed.overrideComponent(TestCmp, {
+            set: {
+              template: `
+              <div iav-dataset-preview-dataset-file
+                (iav-dataset-preview-active-changed)="testmethod($event)"
+                iav-dataset-preview-dataset-file-filename="banana">
+              </div>
+              `,
+              providers: [
+                {
+                  provide: IAV_DATASET_PREVIEW_ACTIVE,
+                  useValue: getDatasetActiveObs
+                }
+              ]
+            }
+          }).compileComponents()
+        })
+
+        it('> should call getDatasetObs', () => {
+          const fixture = TestBed.createComponent(TestCmp)
+          fixture.detectChanges()
+          expect(getDatasetActiveObs).toHaveBeenCalled()
+        })
+
+        it('> on obs.next, should emit active$,', () => {
+
+          const fixture = TestBed.createComponent(TestCmp)
+          const cmp = fixture.debugElement.componentInstance
+
+          const testmethodSpy = spyOn(cmp, 'testmethod')
+
+          fixture.detectChanges()
+          mockDatasetActiveObs.next(true)
+          fixture.detectChanges()
+
+          expect(testmethodSpy).toHaveBeenCalledWith(true)
+        })
+      })
+    })
+  })
+
   it('without providing file or filename, should not call emitFn', () => {
 
     TestBed.overrideComponent(TestCmp, {
diff --git a/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.ts b/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.ts
index 26683fb73..edc8fae81 100644
--- a/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.ts
+++ b/src/ui/databrowserModule/singleDataset/datasetPreviews/previewDatasetFile.directive.ts
@@ -1,15 +1,18 @@
-import { Directive, Input, HostListener, Inject, Output, EventEmitter, Optional } from "@angular/core";
+import { Directive, Input, HostListener, Inject, Output, EventEmitter, Optional, OnChanges } from "@angular/core";
 import { MatSnackBar } from "@angular/material/snack-bar";
 import { ViewerPreviewFile, IDataEntry } from 'src/services/state/dataStore.store'
+import { Observable, Subscription } from "rxjs";
+import { distinctUntilChanged } from "rxjs/operators";
 
 export const IAV_DATASET_PREVIEW_DATASET_FN = 'IAV_DATASET_PREVIEW_DATASET_FN'
+export const IAV_DATASET_PREVIEW_ACTIVE = `IAV_DATASET_PREVIEW_ACTIVE`
 
 @Directive({
   selector: '[iav-dataset-preview-dataset-file]',
   exportAs: 'iavDatasetPreviewDatasetFile'
 })
 
-export class PreviewDatasetFile{
+export class PreviewDatasetFile implements OnChanges{
   @Input('iav-dataset-preview-dataset-file')
   file: ViewerPreviewFile
 
@@ -31,10 +34,29 @@ export class PreviewDatasetFile{
   @Output('iav-dataset-preview-dataset-file-emit')
   emitter: EventEmitter<{file: Partial<ViewerPreviewFile>, dataset: Partial<IDataEntry>}> = new EventEmitter()
 
+  @Output('iav-dataset-preview-active-changed')
+  active$: EventEmitter<boolean> = new EventEmitter()
+
+  public active: boolean = false
+
+  private dataActiveObs: Subscription
   constructor(
     private snackbar: MatSnackBar,
-    @Optional() @Inject(IAV_DATASET_PREVIEW_DATASET_FN) private emitFn: any
+    @Optional() @Inject(IAV_DATASET_PREVIEW_DATASET_FN) private emitFn: any,
+    @Optional() @Inject(IAV_DATASET_PREVIEW_ACTIVE) private getDatasetActiveObs: (file, dataset) => Observable<boolean>
   ){
+    
+  }
+
+  ngOnChanges(){
+    if (this.dataActiveObs) this.dataActiveObs.unsubscribe()
+    
+    if (this.getDatasetActiveObs) this.dataActiveObs = this.getDatasetActiveObs(this.getFile(), this.getDataset()).pipe(
+      distinctUntilChanged()
+    ).subscribe(flag => {
+      this.active = flag
+      this.active$.emit(flag)
+    })
   }
 
   private getFile(): Partial<ViewerPreviewFile>{
diff --git a/src/ui/layerbrowser/layerbrowser.component.ts b/src/ui/layerbrowser/layerbrowser.component.ts
index cc14ee88c..f72381f13 100644
--- a/src/ui/layerbrowser/layerbrowser.component.ts
+++ b/src/ui/layerbrowser/layerbrowser.component.ts
@@ -205,10 +205,8 @@ export class LayerBrowser implements OnInit, OnDestroy {
       return
     }
     this.store.dispatch({
-      type : REMOVE_NG_LAYER,
-      layer : {
-        name : layer.name,
-      },
+      type: REMOVE_NG_LAYER,
+      layer
     })
   }
 
diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts
index 0ddb3de68..94fcdc3f9 100644
--- a/src/ui/nehubaContainer/nehubaContainer.component.ts
+++ b/src/ui/nehubaContainer/nehubaContainer.component.ts
@@ -616,7 +616,7 @@ export class NehubaContainer implements OnInit, OnChanges, OnDestroy {
           type : ADD_NG_LAYER,
           layer : dispatchLayers,
         })
-      }),
+      })
     )
 
     this.subscriptions.push(
diff --git a/src/ui/parcellationRegion/region.base.ts b/src/ui/parcellationRegion/region.base.ts
index cec5a668c..17b84af7f 100644
--- a/src/ui/parcellationRegion/region.base.ts
+++ b/src/ui/parcellationRegion/region.base.ts
@@ -9,6 +9,7 @@ import {
 import { VIEWERSTATE_CONTROLLER_ACTION_TYPES } from "../viewerStateController/viewerState.base";
 import {distinctUntilChanged, shareReplay} from "rxjs/operators";
 import {Observable} from "rxjs";
+import { ARIA_LABELS } from 'common/constants'
 
 export class RegionBase {
 
@@ -149,4 +150,7 @@ export class RegionBase {
     }
   }
 
+  public SHOW_CONNECTIVITY_DATA = ARIA_LABELS.SHOW_CONNECTIVITY_DATA
+  public SHOW_IN_OTHER_REF_SPACE = ARIA_LABELS.SHOW_IN_OTHER_REF_SPACE
+  public SHOW_ORIGIN_DATASET = ARIA_LABELS.SHOW_ORIGIN_DATASET
 }
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.style.css b/src/ui/parcellationRegion/regionMenu/regionMenu.style.css
index c56194bd3..278de0373 100644
--- a/src/ui/parcellationRegion/regionMenu/regionMenu.style.css
+++ b/src/ui/parcellationRegion/regionMenu/regionMenu.style.css
@@ -1,6 +1,11 @@
-.speed-dial
+mat-list.sm mat-list-item
 {
-  right: 0;
-  bottom: 0;
-  height: 0;
+  height:36px;
+  font-size: 90%;
+  cursor: default;
+}
+
+mat-icon
+{
+  transform: scale(0.75);
 }
\ No newline at end of file
diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
index 44d38e797..7ba29a29e 100644
--- a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
+++ b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html
@@ -4,62 +4,6 @@
       <span class="mr-8">
         {{ region.name }}
       </span>
-
-      <!-- only show speed dial if originDatasets exists and are greater than 0 -->
-      <div *ngIf="((region && region.originDatasets) || []).length > 0"
-        class="speed-dial position-absolute d-flex flex-row-reverse align-items-center"
-        (iav-onclick-outside)="fab.close()"
-        #fab="iavFabSpeedDialContainer"
-        iav-fab-speed-dial-scale-origin="right"
-        iav-fab-speed-dial-container>
-
-        <!-- main btn -->
-        <button mat-fab class="ml-3"
-          iav-fab-speed-dial-trigger
-          [color]="fab.isOpen ? 'default' : 'accent'">
-
-          <!-- TODO add test to ensure this does not happen -->
-          <!-- nb pe-none is essential for iav-onclick-outside directive to work properly -->
-          <ng-container *ngIf="fab.isOpen; else closedTmpl">
-            <i class="pe-none fas fa-times"></i>
-          </ng-container>
-          <ng-template #closedTmpl>
-            <i class="pe-none fas fa-ellipsis-v"></i>
-          </ng-template>
-        </button>
-
-        <!-- action btns -->
-        <!-- originDatasets -->
-        <ng-container *ngFor="let originDataset of (region.originDatasets || []); let index = index">
-
-          <!-- preview file -->
-          <button *ngIf="originDataset.kgSchema && originDataset.kgId && originDataset.filename"
-            mat-mini-fab
-            iav-dataset-preview-dataset-file
-            [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
-            [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
-            class="m-1"
-            [iav-fab-speed-dial-child-index]="index * 2"
-            matTooltip="Preview file"
-            iav-fab-speed-dial-child>
-            <i class="far fa-eye"></i>
-          </button>
-
-          <!-- show dataset -->
-          <button *ngIf="originDataset.kgSchema && originDataset.kgId"
-            mat-mini-fab
-            class="m-1"
-            (click)="fab.close()"
-            matTooltip="More detail on dataset"
-            [iav-dataset-show-dataset-dialog-kgid]="originDataset.kgId"
-            iav-dataset-show-dataset-dialog
-            [iav-fab-speed-dial-child-index]="index * 2 + 1"
-            iav-fab-speed-dial-child>
-            <i class="fas fa-info"></i>
-          </button>
-        </ng-container>
-
-      </div>
     </div>
   </mat-card-title>
   <mat-card-subtitle>
@@ -68,61 +12,185 @@
       Brain region
     </span>
   </mat-card-subtitle>
+  
   <mat-card-content>
-    {{ region.description }}
-  </mat-card-content>
-  <div class="d-flex flex-row flex-wrap">
-    <button mat-button
-      (click)="toggleRegionSelected()"
-      [color]="isSelected ? 'primary': 'basic'">
-      <i class="far" [ngClass]="{'fa-check-square': isSelected, 'fa-square': !isSelected}"></i>
-      <span>
-        {{isSelected? 'Deselect' : 'Select'}}
-      </span>
-    </button>
-    <button mat-button (click)="navigateToRegion()">
-      <i class="fas fa-map-marked-alt"></i>
-      <span>
-        Navigate
-      </span>
-    </button>
-    <button *ngIf="hasConnectivity"
-      mat-button
-      [matMenuTriggerFor]="connectivitySourceDatasets"
-      #connectivityMenuButton="matMenuTrigger"
-      iav-captureClickListenerDirective
-      [iav-captureClickListenerDirective-captureDocument]="true"
-      (iav-captureClickListenerDirective-onMousedown)="connectivityMenuButton.closeMenu()">
-      <i class="fab fa-connectdevelop"></i>
-      <span>
-        Connectivity
-      </span>
-      <i class="fas fa-angle-right"></i>
-    </button>
+    <mat-divider></mat-divider>
+    
+    <!-- region actions -->
+    <mat-grid-list cols="2" rowHeight="6rem" gutterSize="0px">
+
+      <mat-grid-tile>
+        <iav-v-button
+          class="h-100 w-100"
+          mat-ripple
+          [color]="isSelected ? 'primary' : 'default'"
+          (click)="toggleRegionSelected()">
+          <i iav-v-button-icon class="far" [ngClass]="{'fa-check-square': isSelected, 'fa-square': !isSelected}"></i>
+          <span iav-v-button-text>{{isSelected ? 'Deselect' : 'Select'}}</span>
+        </iav-v-button>
+      </mat-grid-tile>
 
+      <mat-grid-tile>
+        <iav-v-button
+          class="h-100 w-100"
+          mat-ripple
+          (click)="navigateToRegion()">
+          <i class="fas fa-map-marked-alt" iav-v-button-icon></i>
+          <span iav-v-button-text>Navigate</span>
+        </iav-v-button>
+      </mat-grid-tile>
 
+      <ng-template #safeHarbour>
+        <ng-container *ngFor="let originDataset of (region.originDatasets || [])">
+          <mat-grid-tile class="iv-custom-comp">
+            <iav-v-button
+              iav-dataset-preview-dataset-file
+              [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
+              [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
+              #previewDirective="iavDatasetPreviewDatasetFile"
+              class="h-100 w-100"
+              mat-ripple>
+              <i class="far fa-eye" iav-v-button-icon></i>
+              <span iav-v-button-text [class]="(previewDirective.active | async) ? 'iv-custom-comp primary' : ''">Probability Map {{ previewDirective.active | async }}</span>
+            </iav-v-button>
+          </mat-grid-tile>
+        </ng-container> 
+        
+        <mat-grid-tile>
+          <iav-v-button *ngIf="hasConnectivity"
+            class="h-100 w-100"
+            mat-ripple
+            [matMenuTriggerFor]="connectivitySourceDatasets"
+            #connectivityMenuButton="matMenuTrigger"
+            iav-captureClickListenerDirective
+            [iav-captureClickListenerDirective-captureDocument]="true"
+            (iav-captureClickListenerDirective-onMousedown)="connectivityMenuButton.closeMenu()">
+            <i class="fab fa-connectdevelop" iav-v-button-icon></i>
+            <span iav-v-button-text>Connectivity</span>
+            <i class="fas fa-chevron-down" iav-v-button-footer></i>
+          </iav-v-button>
+        </mat-grid-tile>
 
-    <!-- Menu to navigate between template spaces to explore same region -->
-    <div>
-      <button mat-button
-        aria-label="Show availability in other reference spaces"
-        *ngIf="sameRegionTemplate.length"
-        [matMenuTriggerFor]="additionalActions"
-        #changeTmplTrigger="matMenuTrigger"
-        iav-captureClickListenerDirective
-        [iav-captureClickListenerDirective-captureDocument]="true"
-        (iav-captureClickListenerDirective-onMousedown)="changeTmplTrigger.closeMenu()">
-        <i class="fas fa-brain"></i>
-        <span>
-          Change template
-        </span>
-        <i class="fas fa-angle-right"></i>
-      </button>
+        <mat-grid-tile>
+          <iav-v-button *ngIf="sameRegionTemplate.length"
+            [attr.aria-label]="'Show availability in other reference spaces'"
+            class="h-100 w-100"
+            mat-ripple
+            [matMenuTriggerFor]="additionalActions"
+            #changeTmplTrigger="matMenuTrigger"
+            iav-captureClickListenerDirective
+            [iav-captureClickListenerDirective-captureDocument]="true"
+            (iav-captureClickListenerDirective-onMousedown)="changeTmplTrigger.closeMenu()">
+            <i class="fas fa-brain" iav-v-button-icon></i>
+            <span iav-v-button-text>Change template</span>
+            <i class="fas fa-chevron-down" iav-v-button-footer></i>
+          </iav-v-button>
+        </mat-grid-tile> 
+      </ng-template>
+    </mat-grid-list>
+
+
+    <!-- region desc -->
+    <ng-container *ngIf="region?.description?.length > 0">
+      <mat-divider></mat-divider>
+      <div>
+        {{ region.description }}
     </div>
+    </ng-container>
 
-  </div>
-</mat-card>
+    <mat-divider></mat-divider>
+
+    <mat-list class="sm">
+
+      <!-- position -->
+      <mat-list-item *ngIf="region?.position" (click)="navigateToRegion()" mat-ripple>
+        <mat-icon scaled-down fontSet="fas" fontIcon="fa-map-marked-alt" mat-list-icon></mat-icon>
+        <div mat-line>
+          {{ region.position | nmToMm | addUnitAndJoin : 'mm' }}
+        </div>
+      </mat-list-item>
+
+      <!-- originData -->
+      <mat-list-item *ngFor="let originDataset of (region.originDatasets || [])"
+        iav-dataset-preview-dataset-file
+        [iav-dataset-preview-dataset-file-kgid]="originDataset.kgId"
+        [iav-dataset-preview-dataset-file-filename]="originDataset.filename"
+        #previewDirective="iavDatasetPreviewDatasetFile"
+        iv-custom-comp
+        [attr.primary]="previewDirective.active || null"
+        role="switch"
+        [attr.aria-checked]="previewDirective.active"
+        [attr.aria-label]="SHOW_ORIGIN_DATASET"
+        mat-ripple>
+        <mat-icon fontSet="fas" fontIcon="fa-eye" mat-list-icon></mat-icon>
+        <div mat-line>
+          Preview probability map
+        </div>
+      </mat-list-item>
 
+      <!-- connectivity -->
+      <div iav-switch #connectivitySwitch="iavSwitch">
+
+        <mat-list-item mat-ripple
+          (click)="connectivitySwitch.toggle()"
+          [attr.aria-label]="SHOW_CONNECTIVITY_DATA">
+          <mat-icon fontSet="fab" fontIcon="fa-connectdevelop" mat-list-icon></mat-icon >
+          <div mat-line>
+            <span>
+              Connectivity
+            </span>
+            <span class="muted">
+             ({{ 1 }})
+            </span>
+          </div>
+          <mat-icon fontSet="fas" [fontIcon]="connectivitySwitch.switchState ? 'fa-chevron-up' : 'fa-chevron-down'"></mat-icon>
+        </mat-list-item>
+  
+        <!-- connectivity -->
+        <mat-list-item *ngIf="connectivitySwitch.switchState" mat-ripple (click)="showConnectivity(region.name)">
+          <mat-icon fontSet="fas" fontIcon="fa-none" mat-list-icon></mat-icon>
+          <div mat-line>1000 Brain Study - DTI connectivity</div>
+        </mat-list-item>
+
+      </div>
+
+      <!-- change template -->
+      <div iav-switch #changeTmplSwitch="iavSwitch">
+
+        <mat-list-item *ngIf="sameRegionTemplate.length"
+          mat-ripple
+          [attr.aria-label]="SHOW_IN_OTHER_REF_SPACE"
+          (click)="changeTmplSwitch && changeTmplSwitch.toggle()">
+          <mat-icon fontSet="fas" fontIcon="fa-brain" mat-list-icon></mat-icon>
+          <div mat-line>
+            <span>
+              Explore in other templates
+            </span>
+            <span class="muted">
+              ({{ sameRegionTemplate.length }})
+            </span>
+          </div>
+          <mat-icon fontSet="fas" [fontIcon]="changeTmplSwitch.switchState ? 'fa-chevron-up' : 'fa-chevron-down'"></mat-icon>
+        </mat-list-item>
+
+        <!-- change template items -->
+        <div *ngIf="changeTmplSwitch.switchState"
+          aria-label="Availability in other reference spaces">
+          <mat-list-item *ngFor="let sameRegion of sameRegionTemplate; let i = index"
+            (click)="changeView(i)"
+            mat-ripple>
+            <mat-icon fontSet="fas" fontIcon="fa-none" mat-list-icon></mat-icon>
+            <div mat-line>
+              <span class="overflow-x-hidden text-truncate"> {{ sameRegion.template.name }} </span>
+              <span *ngIf="sameRegion.hemisphere"> - {{ sameRegion.hemisphere }}</span>
+            </div>
+          </mat-list-item>
+        </div>
+      
+      </div>
+    </mat-list>
+  </mat-card-content>
+</mat-card>
 
 <!-- ToDo make dynamic with AVAILABLE CONNECTIVITY DATASETS data - get info from atlas viewer core -->
 <mat-menu
@@ -138,7 +206,6 @@
 
 
 <mat-menu
-  [aria-label]="'Availability in other reference spaces'"
   #additionalActions="matMenu"
   xPosition="before"
   hasBackdrop="false">
diff --git a/src/ui/searchSideNav/searchSideNav.component.ts b/src/ui/searchSideNav/searchSideNav.component.ts
index f514928bd..a0647a652 100644
--- a/src/ui/searchSideNav/searchSideNav.component.ts
+++ b/src/ui/searchSideNav/searchSideNav.component.ts
@@ -10,7 +10,6 @@ import {
   EXPAND_SIDE_PANEL_CURRENT_VIEW,
 } from "src/services/state/uiState.store";
 import { IavRootStoreInterface, SELECT_REGIONS } from "src/services/stateStore.service";
-import { LayerBrowser } from "../layerbrowser/layerbrowser.component";
 import { trackRegionBy } from '../viewerStateController/regionHierachy/regionHierarchy.component'
 import { MatDialog, MatDialogRef } from "@angular/material/dialog";
 import { MatSnackBar } from "@angular/material/snack-bar";
diff --git a/src/util/directives/switch.directive.ts b/src/util/directives/switch.directive.ts
new file mode 100644
index 000000000..cbdbe4dfc
--- /dev/null
+++ b/src/util/directives/switch.directive.ts
@@ -0,0 +1,21 @@
+import { Directive, Input } from "@angular/core";
+
+@Directive({
+  selector: '[iav-switch]',
+  exportAs: 'iavSwitch'
+})
+export class SwitchDirective{
+  @Input() switchState: boolean = false
+  
+  toggle(){
+    this.switchState = !this.switchState
+  }
+
+  close(){
+    this.switchState = false
+  }
+
+  open(){
+    this.switchState = true
+  }
+}
\ No newline at end of file
diff --git a/src/util/pipes/addUnitAndJoin.pipe.ts b/src/util/pipes/addUnitAndJoin.pipe.ts
new file mode 100644
index 000000000..000e245da
--- /dev/null
+++ b/src/util/pipes/addUnitAndJoin.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from "@angular/core";
+
+@Pipe({
+  name: 'addUnitAndJoin',
+  pure: true
+})
+
+export class AddUnitAndJoin implements PipeTransform{
+  public transform(arr: (string | number)[], unit: string, separator: string = ', '): string {
+    return arr.map(v => `${v}${unit}`).join(separator)
+  }
+}
\ No newline at end of file
diff --git a/src/util/pipes/numbers.pipe.ts b/src/util/pipes/numbers.pipe.ts
new file mode 100644
index 000000000..0390ea90d
--- /dev/null
+++ b/src/util/pipes/numbers.pipe.ts
@@ -0,0 +1,12 @@
+import { Pipe, PipeTransform } from "@angular/core";
+
+@Pipe({
+  name: 'nmToMm',
+  pure: true
+})
+
+export class NmToMm implements PipeTransform{
+  public transform(nums: number[], decimal: number = 2): number[] {
+    return nums.map(num => (num / 1e6).toFixed(decimal)).map(Number)
+  }
+}
\ No newline at end of file
diff --git a/src/util/util.module.ts b/src/util/util.module.ts
index 0675aa46c..47d094f5f 100644
--- a/src/util/util.module.ts
+++ b/src/util/util.module.ts
@@ -8,6 +8,9 @@ import { FilterNullPipe } from "./pipes/filterNull.pipe";
 import { IncludesPipe } from "./pipes/includes.pipe";
 import { SafeResourcePipe } from "./pipes/safeResource.pipe";
 import { CaptureClickListenerDirective } from "./directives/captureClickListener.directive";
+import { AddUnitAndJoin } from "./pipes/addUnitAndJoin.pipe";
+import { NmToMm } from "./pipes/numbers.pipe";
+import { SwitchDirective } from "./directives/switch.directive";
 
 @NgModule({
   declarations: [
@@ -22,6 +25,9 @@ import { CaptureClickListenerDirective } from "./directives/captureClickListener
     IncludesPipe,
     SafeResourcePipe,
     CaptureClickListenerDirective,
+    AddUnitAndJoin,
+    NmToMm,
+    SwitchDirective,
   ],
   exports: [
     FilterNullPipe,
@@ -35,8 +41,9 @@ import { CaptureClickListenerDirective } from "./directives/captureClickListener
     IncludesPipe,
     SafeResourcePipe,
     CaptureClickListenerDirective,
-  ],
-  providers: [
+    AddUnitAndJoin,
+    NmToMm,
+    SwitchDirective,
   ]
 })
 
-- 
GitLab