From fc5add9d042bbbac24b42751cd39b410f516984b Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Tue, 20 Oct 2020 12:11:18 +0200
Subject: [PATCH] bugfix: temporarily disable multiregion selection

---
 docs/releases/v2.3.0.md                       |  8 ++++
 .../atlasViewer.history.service.spec.ts       |  4 +-
 .../atlasViewer.history.service.ts            |  8 +++-
 src/atlasViewer/atlasViewer.urlUtil.spec.ts   | 40 +++++++++++++++++++
 src/atlasViewer/atlasViewer.urlUtil.ts        | 14 +++++--
 .../sharedModules/angularMaterial.module.ts   |  7 +++-
 6 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/docs/releases/v2.3.0.md b/docs/releases/v2.3.0.md
index a0c965335..85b6cf282 100644
--- a/docs/releases/v2.3.0.md
+++ b/docs/releases/v2.3.0.md
@@ -22,3 +22,11 @@
 ## Under the hood stuff
 
 - Updated how dataset retrieval work. It will now query on a region basis
+
+## Breaking changes
+
+- Temporarily disabled multiregion selection
+
+> as a result of the UI overhaul, multi-region selection as it existed before will break the UI in several ways. As a result, it will be disabled temporarily until higher hierarchy region selection can be implemented properly.
+>
+> Any existing URL which points to a multi-region selection state will be shown a message `Selecting multiple regions has been temporarily disabled in v2.3.0`
diff --git a/src/atlasViewer/atlasViewer.history.service.spec.ts b/src/atlasViewer/atlasViewer.history.service.spec.ts
index 3e4bfb146..aec52f695 100644
--- a/src/atlasViewer/atlasViewer.history.service.spec.ts
+++ b/src/atlasViewer/atlasViewer.history.service.spec.ts
@@ -7,6 +7,7 @@ import { Action, Store } from '@ngrx/store'
 import { defaultRootState } from '../services/stateStore.service'
 import { cold } from 'jasmine-marbles'
 import { HttpClientTestingModule } from '@angular/common/http/testing'
+import { AngularMaterialModule } from 'src/ui/sharedModules/angularMaterial.module'
 
 const bigbrainJson = require('!json-loader!src/res/ext/bigbrain.json')
 
@@ -16,7 +17,8 @@ describe('atlasviewer.history.service.ts', () => {
   beforeEach(() => {
     TestBed.configureTestingModule({
       imports: [
-        HttpClientTestingModule
+        HttpClientTestingModule,
+        AngularMaterialModule,
       ],
       providers: [
         AtlasViewerHistoryUseEffect,
diff --git a/src/atlasViewer/atlasViewer.history.service.ts b/src/atlasViewer/atlasViewer.history.service.ts
index c58aa5a5f..59fe3cd5a 100644
--- a/src/atlasViewer/atlasViewer.history.service.ts
+++ b/src/atlasViewer/atlasViewer.history.service.ts
@@ -8,6 +8,7 @@ import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.consta
 import { cvtSearchParamToState, cvtStateToSearchParam } from "./atlasViewer.urlUtil";
 import { viewerStateHelperStoreName } from '../services/state/viewerState.store.helper'
 import { PureContantService } from "src/util";
+import { MatSnackBar } from "@angular/material/snack-bar";
 const getSearchParamStringFromState = state => {
   try {
     return cvtStateToSearchParam(state).toString()
@@ -58,7 +59,9 @@ export class AtlasViewerHistoryUseEffect implements OnDestroy {
           }
         } else {
           // if non empty search param
-          const newState = cvtSearchParamToState(search, storeState)
+          const newState = cvtSearchParamToState(search, storeState, error => {
+            this.snackbar.open(`${error.message}`, 'Dismiss')
+          })
           return {
             type: GENERAL_ACTION_TYPES.APPLY_STATE,
             state: newState,
@@ -127,7 +130,8 @@ export class AtlasViewerHistoryUseEffect implements OnDestroy {
     private store$: Store<IavRootStoreInterface>,
     private actions$: Actions,
     private constantService: AtlasViewerConstantsServices,
-    private pureConstantSErvice: PureContantService
+    private pureConstantSErvice: PureContantService,
+    private snackbar: MatSnackBar
   ) {
 
     this.setNewSearchString$.subscribe(newSearchString => {
diff --git a/src/atlasViewer/atlasViewer.urlUtil.spec.ts b/src/atlasViewer/atlasViewer.urlUtil.spec.ts
index 01787b3b1..50746735a 100644
--- a/src/atlasViewer/atlasViewer.urlUtil.spec.ts
+++ b/src/atlasViewer/atlasViewer.urlUtil.spec.ts
@@ -31,6 +31,46 @@ const fetchedTemplateRootState = {
 describe('atlasViewer.urlService.service.ts', () => {
   describe('cvtSearchParamToState', () => {
 
+    /**
+     * for 2.3.0 onwards
+     * multi region selection has been temporarily disabled.
+     * search param parse needs to return emtpy array when encountered
+     */
+    it('> filters out multi region selection an returns an empty array', () => {
+      const searchString = `?templateSelected=Waxholm+Space+rat+brain+MRI%2FDTI&parcellationSelected=Waxholm+Space+rat+brain+atlas+v2&cRegionsSelected=%7B%22v2%22%3A%2213.a.b.19.6.c.q.x.1.1L.Y.1K.r.s.y.z._.1G.-.Z.18.v.f.g.1J.1C.k.14.15.7.1E.1F.10.11.12.1D.1S.A.1V.1W.1X.1Y.1Z.1a.1i.1j.1k.1m.1n.1o.1p.U.V.W.3.1I.e.d.1T.1H.m.h.n.1U.o.t.2.17.p.w.4.5.1A.1B.u.l.j.16%22%7D&cNavigation=0.0.0.-W000..2-8Bnd.2_tvb9._yymE._tYzz..1Sjt..9Hnn%7E.Lqll%7E.Vcf..9fo`
+      const searchparam = new URLSearchParams(searchString)
+      const regionObj = JSON.parse(searchparam.get('cRegionsSelected'))
+      const totalRegions = []
+      for (const key in regionObj) {
+        for (const el of regionObj[key].split('.')) {
+          totalRegions.push(el)
+        }
+      }
+      expect(totalRegions.length).toBeGreaterThan(1)
+
+      const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState)
+      expect(newState?.viewerState?.regionsSelected).toEqual([])
+    })
+    
+    /**
+     * leaves single region selection intact
+     */
+    it('> leaves single region selection intact', () => {
+      const searchString = '?templateSelected=Waxholm+Space+rat+brain+MRI%2FDTI&parcellationSelected=Waxholm+Space+rat+brain+atlas+v2&cRegionsSelected=%7B"v2"%3A"1S"%7D&cNavigation=0.0.0.-W000..2-8Bnd.2_tvb9._yymE._tYzz..1Sjt..9Hnn~.Lqll~.Vcf..9fo'
+      const searchparam = new URLSearchParams(searchString)
+      const regionObj = JSON.parse(searchparam.get('cRegionsSelected'))
+      const totalRegions = []
+      for (const key in regionObj) {
+        for (const el of regionObj[key].split('.')) {
+          totalRegions.push(el)
+        }
+      }
+      expect(totalRegions.length).toEqual(1)
+
+      const newState = cvtSearchParamToState(searchparam, fetchedTemplateRootState)
+      expect(newState?.viewerState?.regionsSelected?.length).toEqual(1)
+    })
+
     it('> convert empty search param to empty state', () => {
       const searchparam = new URLSearchParams()
       expect(() => cvtSearchParamToState(searchparam, defaultRootState)).toThrow()
diff --git a/src/atlasViewer/atlasViewer.urlUtil.ts b/src/atlasViewer/atlasViewer.urlUtil.ts
index 59640205e..85ef716d8 100644
--- a/src/atlasViewer/atlasViewer.urlUtil.ts
+++ b/src/atlasViewer/atlasViewer.urlUtil.ts
@@ -13,7 +13,9 @@ export const PARSING_SEARCHPARAM_ERROR = {
 const PARSING_SEARCHPARAM_WARNING = {
   UNKNOWN_PARCELLATION: 'UNKNOWN_PARCELLATION',
   DECODE_CIPHER_ERROR: 'DECODE_CIPHER_ERROR',
-  ID_ERROR: 'ID_ERROR'
+  ID_ERROR: 'ID_ERROR',
+
+  DEPRECATION_ERROR: `DEPRECATION_ERROR`
 }
 
 export const CVT_STATE_TO_SEARCHPARAM_ERROR = {
@@ -90,7 +92,7 @@ export const cvtStateToSearchParam = (state: any): URLSearchParams => {
 }
 
 const { TEMPLATE_NOT_FOUND, TEMPALTE_NOT_SET, PARCELLATION_NOT_UPDATED } = PARSING_SEARCHPARAM_ERROR
-const { UNKNOWN_PARCELLATION, DECODE_CIPHER_ERROR, ID_ERROR } = PARSING_SEARCHPARAM_WARNING
+const { UNKNOWN_PARCELLATION, DECODE_CIPHER_ERROR, ID_ERROR, DEPRECATION_ERROR } = PARSING_SEARCHPARAM_WARNING
 
 const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchParams, state: IavRootStoreInterface, cb?: (arg: any) => void) => {
 
@@ -193,7 +195,13 @@ const parseSearchParamForTemplateParcellationRegion = (searchparams: URLSearchPa
   return {
     templateSelected,
     parcellationSelected,
-    regionsSelected
+    regionsSelected: (() => {
+      if (regionsSelected.length > 1) {
+        cb({ type: DEPRECATION_ERROR,  message: `Selecting multiple regions has been temporarily disabled in v2.3.0` })
+        return []
+      }
+      return regionsSelected
+    })()
   }
 }
 
diff --git a/src/ui/sharedModules/angularMaterial.module.ts b/src/ui/sharedModules/angularMaterial.module.ts
index d5384113b..9bed0ad4b 100644
--- a/src/ui/sharedModules/angularMaterial.module.ts
+++ b/src/ui/sharedModules/angularMaterial.module.ts
@@ -1,6 +1,6 @@
 import {MAT_DIALOG_DEFAULT_OPTIONS, MatDialogConfig, MatDialogModule} from "@angular/material/dialog";
 import {MatButtonModule} from "@angular/material/button";
-import {MatSnackBarModule} from "@angular/material/snack-bar";
+import {MatSnackBarModule, MAT_SNACK_BAR_DEFAULT_OPTIONS} from "@angular/material/snack-bar";
 import {MatCardModule} from "@angular/material/card";
 import {MatCheckboxModule} from "@angular/material/checkbox";
 import {MatTabsModule} from "@angular/material/tabs";
@@ -96,6 +96,11 @@ const defaultDialogOption: MatDialogConfig = new MatDialogConfig()
       ...defaultDialogOption,
       panelClass: 'iav-dialog-class',
     },
+  },{
+    provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
+    useValue: {
+      duration: 2500
+    }
   }],
 })
 export class AngularMaterialModule { }
-- 
GitLab