From 0342260c0317502d601a6acd9347ea834186e1e4 Mon Sep 17 00:00:00 2001
From: Xiao Gui <xgui3783@gmail.com>
Date: Wed, 18 Oct 2023 08:54:41 +0200
Subject: [PATCH] feat: add info icon, even if they are hidden

---
 docs/releases/v2.14.0.md                      |   1 +
 src/atlasComponents/sapi/schemaV3.ts          |   2 +
 src/atlasComponents/sapi/translateV3.ts       |   9 +-
 .../sapiViews/core/parcellation/index.ts      |   2 +-
 .../sapiViews/core/parcellation/module.ts     |   6 +-
 .../core/parcellation/parcTmplDoi.pipe.ts     |  13 ++
 .../core/parcellation/parcellationDoi.pipe.ts |  13 --
 .../region/rich/region.rich.template.html     |   2 +-
 .../sapiViews/core/rich/ATPSelector/module.ts |   2 +
 .../pureDumb/pureATPSelector.components.ts    |  68 +++++----
 .../pureDumb/pureATPSelector.template.html    | 144 ++++++++++--------
 11 files changed, 155 insertions(+), 107 deletions(-)
 create mode 100644 src/atlasComponents/sapiViews/core/parcellation/parcTmplDoi.pipe.ts
 delete mode 100644 src/atlasComponents/sapiViews/core/parcellation/parcellationDoi.pipe.ts

diff --git a/docs/releases/v2.14.0.md b/docs/releases/v2.14.0.md
index 0339fb1b0..4c561f6b4 100644
--- a/docs/releases/v2.14.0.md
+++ b/docs/releases/v2.14.0.md
@@ -4,6 +4,7 @@
 
 - added `[p]` and `[n]` as keyboard shortcut to navigate previous/next slice
 - experimental support for other versions of regions
+- show template and parcellation info even if the chip are hidden
 
 ## Behind the scenes
 
diff --git a/src/atlasComponents/sapi/schemaV3.ts b/src/atlasComponents/sapi/schemaV3.ts
index 53b4c245c..2e26c5065 100644
--- a/src/atlasComponents/sapi/schemaV3.ts
+++ b/src/atlasComponents/sapi/schemaV3.ts
@@ -550,6 +550,8 @@ export interface components {
        * @description Term or code used to identify the version of something.
        */
       versionIdentifier: string
+      /** Datasets */
+      datasets?: (components["schemas"]["EbrainsDatasetModel"])[]
     }
     /**
      * CoordinatePointModel 
diff --git a/src/atlasComponents/sapi/translateV3.ts b/src/atlasComponents/sapi/translateV3.ts
index 6d08f2199..3f9de1ba5 100644
--- a/src/atlasComponents/sapi/translateV3.ts
+++ b/src/atlasComponents/sapi/translateV3.ts
@@ -166,14 +166,19 @@ class TranslateV3 {
     return this.#templateMap.get(template.id)
   }
   async translateTemplate(template:PathReturn<"/spaces/{space_id}">): Promise<SxplrTemplate> {
+    
+    const ds = await Promise.all((template.datasets || []).map(ds => this.translateDs(ds)))
+    const { ...rest } = ds[0] || {}
 
     this.#templateMap.set(template["@id"], template)
-    const tmpl = {
+    const tmpl: SxplrTemplate = {
       id: template["@id"],
       name: template.fullName,
       shortName: template.shortName,
-      type: "SxplrTemplate" as const
+      type: "SxplrTemplate" as const,
+      ...rest
     }
+    
     this.#sxplrTmplMap.set(tmpl.id, tmpl)
     return tmpl
   }
diff --git a/src/atlasComponents/sapiViews/core/parcellation/index.ts b/src/atlasComponents/sapiViews/core/parcellation/index.ts
index 78616fb9b..74925f1e2 100644
--- a/src/atlasComponents/sapiViews/core/parcellation/index.ts
+++ b/src/atlasComponents/sapiViews/core/parcellation/index.ts
@@ -2,5 +2,5 @@ export { SapiViewsCoreParcellationModule } from "./module"
 export { FilterGroupedParcellationPipe } from "./filterGroupedParcellations.pipe"
 export { FilterUnsupportedParcPipe } from "./filterUnsupportedParc.pipe"
 export { GroupedParcellation } from "./groupedParcellation"
-export { ParcellationDoiPipe } from "./parcellationDoi.pipe"
+export { ParcTmplDoiPipe } from "./parcTmplDoi.pipe"
 export { ParcellationGroupSelectedPipe } from "./parcellationGroupSelected.pipe"
diff --git a/src/atlasComponents/sapiViews/core/parcellation/module.ts b/src/atlasComponents/sapiViews/core/parcellation/module.ts
index 9fb7e0066..5ed46747d 100644
--- a/src/atlasComponents/sapiViews/core/parcellation/module.ts
+++ b/src/atlasComponents/sapiViews/core/parcellation/module.ts
@@ -8,7 +8,7 @@ import { UtilModule } from "src/util";
 import { SapiViewsUtilModule } from "../../util";
 import { FilterGroupedParcellationPipe } from "./filterGroupedParcellations.pipe";
 import { FilterUnsupportedParcPipe } from "./filterUnsupportedParc.pipe";
-import { ParcellationDoiPipe } from "./parcellationDoi.pipe";
+import { ParcTmplDoiPipe } from "./parcTmplDoi.pipe";
 import { ParcellationVisibilityService } from "./parcellationVis.service";
 import { ParcellationGroupSelectedPipe } from "./parcellationGroupSelected.pipe";
 import { IsGroupedParcellation } from "./isGroupedParcellation.pipe";
@@ -31,7 +31,7 @@ import { ParcellationVisEffect } from "./parcellationVis.effect";
   declarations: [
     FilterGroupedParcellationPipe,
     FilterUnsupportedParcPipe,
-    ParcellationDoiPipe,
+    ParcTmplDoiPipe,
     ParcellationGroupSelectedPipe,
     IsGroupedParcellation,
   ],
@@ -39,7 +39,7 @@ import { ParcellationVisEffect } from "./parcellationVis.effect";
     FilterGroupedParcellationPipe,
     FilterUnsupportedParcPipe,
     ParcellationGroupSelectedPipe,
-    ParcellationDoiPipe,
+    ParcTmplDoiPipe,
     IsGroupedParcellation,
   ],
   providers: [
diff --git a/src/atlasComponents/sapiViews/core/parcellation/parcTmplDoi.pipe.ts b/src/atlasComponents/sapiViews/core/parcellation/parcTmplDoi.pipe.ts
new file mode 100644
index 000000000..a2306403f
--- /dev/null
+++ b/src/atlasComponents/sapiViews/core/parcellation/parcTmplDoi.pipe.ts
@@ -0,0 +1,13 @@
+import { Pipe, PipeTransform } from "@angular/core";
+import { SxplrParcellation, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes";
+
+@Pipe({
+  name: 'parcTmplDoiPipe',
+  pure: true
+})
+
+export class ParcTmplDoiPipe implements PipeTransform {
+  public transform(_parc: SxplrParcellation|SxplrTemplate): string[] {
+    return (_parc.link || []).map(v => v.href)
+  }
+}
diff --git a/src/atlasComponents/sapiViews/core/parcellation/parcellationDoi.pipe.ts b/src/atlasComponents/sapiViews/core/parcellation/parcellationDoi.pipe.ts
deleted file mode 100644
index dad016dc1..000000000
--- a/src/atlasComponents/sapiViews/core/parcellation/parcellationDoi.pipe.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Pipe, PipeTransform } from "@angular/core";
-import { SxplrParcellation } from "src/atlasComponents/sapi/sxplrTypes";
-
-@Pipe({
-  name: 'parcellationDoiPipe',
-  pure: true
-})
-
-export class ParcellationDoiPipe implements PipeTransform {
-  public transform(_parc: SxplrParcellation): string[] {
-    return (_parc.link || []).map(v => v.href)
-  }
-}
diff --git a/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.template.html b/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.template.html
index b48e7804e..0f5e72501 100644
--- a/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.template.html
+++ b/src/atlasComponents/sapiViews/core/region/region/rich/region.rich.template.html
@@ -43,7 +43,7 @@
           [sxplr-dialog-data]="{
             title: parcellation.name,
             descMd: parcellation.desc,
-            actions: parcellation | parcellationDoiPipe
+            actions: parcellation | parcTmplDoiPipe
           }">
           <mat-icon mat-list-icon fontSet="fas" fontIcon="fa-brain"></mat-icon>
           <div mat-line class="overview-content">{{ parcellation.name }}</div>
diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/module.ts b/src/atlasComponents/sapiViews/core/rich/ATPSelector/module.ts
index acd1fbb94..c0269e9f1 100644
--- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/module.ts
+++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/module.ts
@@ -13,6 +13,7 @@ import { WrapperATPSelector } from "./wrapper/wrapper.component";
 import { SAPIModule } from "src/atlasComponents/sapi/module";
 import { MatTooltipModule } from "@angular/material/tooltip";
 import { QuickTourModule } from "src/ui/quickTour";
+import { ExperimentalModule } from "src/experimental/experimental.module";
 
 @NgModule({
   imports: [
@@ -28,6 +29,7 @@ import { QuickTourModule } from "src/ui/quickTour";
     SAPIModule,
     SapiViewsCoreParcellationModule,
     QuickTourModule,
+    ExperimentalModule,
   ],
   declarations: [
     PureATPSelector,
diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts
index a11e3301d..2a169d93a 100644
--- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts
+++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.components.ts
@@ -1,4 +1,4 @@
-import { AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, Output, QueryList, SimpleChanges, ViewChildren } from "@angular/core";
+import { AfterViewInit, ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, OnDestroy, Output, QueryList, ViewChildren } from "@angular/core";
 import { BehaviorSubject, Subscription, combineLatest, concat, merge, of } from "rxjs";
 import { map, switchMap } from "rxjs/operators";
 import { SxplrAtlas, SxplrParcellation, SxplrTemplate } from "src/atlasComponents/sapi/sxplrTypes";
@@ -43,28 +43,35 @@ const pipe = new FilterGroupedParcellationPipe()
   changeDetection: ChangeDetectionStrategy.OnPush,
 })
 
-export class PureATPSelector implements OnChanges, AfterViewInit, OnDestroy{
+export class PureATPSelector implements AfterViewInit, OnDestroy{
 
   #subscriptions: Subscription[] = []
 
   @Input('sxplr-pure-atp-selector-color-palette')
   colorPalette: string[] = darkThemePalette
 
+  #selectedATP$ = new BehaviorSubject<ATP>(null)
   @Input(`sxplr-pure-atp-selector-selected-atp`)
-  public selectedATP: ATP
+  set selectedATP(val: ATP){
+    this.#selectedATP$.next(val)
+  }
 
   public selectedIds: string[] = []
 
   @Input(`sxplr-pure-atp-selector-atlases`)
   public allAtlases: SxplrAtlas[] = []
 
+  #availableTemplates$ = new BehaviorSubject<SxplrTemplate[]>([])
   @Input(`sxplr-pure-atp-selector-templates`)
-  public availableTemplates: SxplrTemplate[] = []
+  set availableTemplates(val: SxplrTemplate[]){
+    this.#availableTemplates$.next(val)
+  }
 
+  #parcellations$ = new BehaviorSubject<SxplrParcellation[]>([])
   @Input(`sxplr-pure-atp-selector-parcellations`)
-  public parcellations: SxplrParcellation[] = []
-
-  public parcAndGroup: (GroupedParcellation|SxplrParcellation)[] = []
+  set parcellations(val: SxplrParcellation[]){
+    this.#parcellations$.next(val)
+  }
 
   @Input('sxplr-pure-atp-selector-is-busy')
   public isBusy: boolean = false
@@ -93,27 +100,34 @@ export class PureATPSelector implements OnChanges, AfterViewInit, OnDestroy{
     this.selectLeafEmitter.emit(atp)
   }
 
-  ngOnChanges(changes: SimpleChanges): void {
-    if (changes.selectedATP) {
-      if (!changes.selectedATP.currentValue) {
-        this.selectedIds = []
-      } else {
-        const { atlas, parcellation, template } = changes.selectedATP.currentValue as ATP
-        this.selectedIds = [atlas?.id, parcellation?.id, template?.id].filter(v => !!v)
+  view$ = combineLatest([
+    this.#selectedATP$,
+    this.#parcellations$,
+    this.#availableTemplates$,
+  ]).pipe(
+    map(([{ atlas, parcellation, template }, parcellations, availableTemplates]) => {
+      const parcAndGroup = [
+        ...pipe.transform(parcellations || [], true),
+        ...pipe.transform(parcellations || [], false),
+      ]
+      const selectedIds = [atlas?.id, parcellation?.id, template?.id].filter(v => !!v)
+
+      const hideParcChip = parcAndGroup.length <= 1
+      const hideTmplChip = availableTemplates?.length <= 1
+      
+      return {
+        atlas,
+        parcellation,
+        template,
+        parcAndGroup,
+        parcellations,
+        selectedIds,
+        hideParcChip,
+        hideTmplChip,
+        availableTemplates: availableTemplates || [],
       }
-    }
-
-    if (changes.parcellations) {
-      if (!changes.parcellations.currentValue) {
-        this.parcAndGroup = []
-      } else {
-        this.parcAndGroup = [
-          ...pipe.transform(changes.parcellations.currentValue, true),
-          ...pipe.transform(changes.parcellations.currentValue, false),
-        ]
-      }
-    }
-  }
+    })
+  )
 
   ngAfterViewInit(): void {
     this.#subscriptions.push(
diff --git a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html
index 9aaf8f964..d1a85f1b6 100644
--- a/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html
+++ b/src/atlasComponents/sapiViews/core/rich/ATPSelector/pureDumb/pureATPSelector.template.html
@@ -1,8 +1,36 @@
-<ng-template [ngIf]="selectedATP" let-ATP>
+<ng-template [ngIf]="view$ | async" let-view>
+  
+  <!-- fallback for parcellation info icon -->
+  <ng-template [ngIf]="view.hideParcChip">
+    <button mat-icon-button
+      sxplr-dialog
+      [sxplr-dialog-size]="null"
+      [sxplr-dialog-data]="{
+        title: view.parcellation.name,
+        descMd: view.parcellation.desc,
+        actions: view.parcellation | parcTmplDoiPipe
+      }">
+      <i class="fas fa-info"></i>
+    </button>
+  </ng-template>
+
+  <!-- fallback for space info icon -->
+  <ng-template  [ngIf]="view.hideTmplChip">
+    <button mat-icon-button
+      sxplr-dialog
+      [sxplr-dialog-size]="null"
+      [sxplr-dialog-data]="{
+        title: view.template.name,
+        descMd: view.template.desc,
+        actions: view.template | parcTmplDoiPipe
+      }">
+      <i class="fas fa-info"></i>
+    </button>
+  </ng-template>
 
   <!-- parcellation smart chip -->
-  <sxplr-smart-chip *ngIf="ATP.parcellation && parcAndGroup && parcAndGroup.length > 1"
-    [items]="parcAndGroup || []"
+  <sxplr-smart-chip *ngIf="!view.hideParcChip"
+    [items]="view.parcAndGroup || []"
     [color]="colorPalette[2]"
     [getChildren]="getChildren"
     (itemClicked)="selectLeaf({ parcellation: $event })"
@@ -15,7 +43,7 @@
       </span>
 
       <span class="sxplr-ml-1 text-muted">
-        ({{ parcellations.length }})
+        ({{ view.parcellations.length }})
       </span>
     </ng-template>
 
@@ -27,9 +55,9 @@
         sxplr-dialog
         [sxplr-dialog-size]="null"
         [sxplr-dialog-data]="{
-          title: ATP.parcellation.name,
-          descMd: ATP.parcellation.desc,
-          actions: ATP.parcellation | parcellationDoiPipe
+          title: view.parcellation.name,
+          descMd: view.parcellation.desc,
+          actions: view.parcellation | parcTmplDoiPipe
         }">
         <i class="fas fa-info"></i>
       </button>
@@ -42,7 +70,7 @@
 
     <ng-template sxplrSmartChipContent>
       <span class="chip-text">
-        {{ ATP.parcellation.shortName }}
+        {{ view.parcellation.shortName }}
       </span>
 
     </ng-template>
@@ -51,7 +79,7 @@
       <ng-container *ngTemplateOutlet="optionTmpl; context: {
         $implicit: parc,
         suffixText: (parc | isGroupedParcellation) && '(' + parc.parcellations.length  + ')' ,
-        overridePrefixIconTmpl: (parc | parcellationGroupSelected : ATP.parcellation)
+        overridePrefixIconTmpl: (parc | parcellationGroupSelected : view.parcellation)
           ? halfSelectedTmpl
           : null
       }">
@@ -60,8 +88,8 @@
   </sxplr-smart-chip>
 
   <!-- space smart chip -->
-  <sxplr-smart-chip *ngIf="ATP.template && availableTemplates && availableTemplates.length > 1"
-    [items]="availableTemplates || []"
+  <sxplr-smart-chip *ngIf="!view.hideTmplChip"
+    [items]="view.availableTemplates || []"
     [color]="colorPalette[1]"
     (itemClicked)="selectLeaf({ template: $event })"
     [elevation]="4"
@@ -73,14 +101,14 @@
       </span>
 
       <span class="sxplr-ml-1 text-muted">
-        ({{ availableTemplates.length }})
+        ({{ view.availableTemplates.length }})
       </span>
     </ng-template>
 
 
     <ng-template sxplrSmartChipContent>
       <span class="chip-text">
-        {{ ATP.template.shortName }}
+        {{ view.template.shortName }}
       </span>
     </ng-template>
     <ng-template sxplrSmartChipMenu let-space>
@@ -89,7 +117,7 @@
   </sxplr-smart-chip>
 
   <!-- atlas smart chip -->
-  <sxplr-smart-chip *ngIf="ATP.atlas"
+  <sxplr-smart-chip *ngIf="view.atlas"
     [items]="allAtlases"
     [color]="colorPalette[0]"
     (itemClicked)="selectLeaf({ atlas: $event})"
@@ -112,13 +140,54 @@
     
     <ng-template sxplrSmartChipContent>
       <span class="chip-text">
-        {{ ATP.atlas.name }}
+        {{ view.atlas.name }}
       </span>
     </ng-template>
     <ng-template sxplrSmartChipMenu let-atlas>
       <ng-container *ngTemplateOutlet="optionTmpl; context: { $implicit: atlas }"></ng-container>
     </ng-template>
   </sxplr-smart-chip>
+  
+  <!-- option template -->
+  <ng-template
+    #optionTmpl
+    let-item
+    let-overridePrefixIconTmpl="overridePrefixIconTmpl"
+    let-overrideSuffixIcon="overrideSuffixIcon"
+    let-suffixText="suffixText">
+
+    <!-- prefix -->
+    <ng-template [ngIf]="overridePrefixIconTmpl" [ngIfElse]="defaultPrefix">
+      <ng-template [ngTemplateOutlet]="overridePrefixIconTmpl"></ng-template>
+    </ng-template>
+    <ng-template #defaultPrefix>
+      <ng-template [ngIf]="view.selectedIds" let-selectedIds>
+        <mat-icon
+          fontSet="fas"
+          [fontIcon]="selectedIds.includes(item.id) ? 'fa-circle' : 'fa-none'"
+          >
+        </mat-icon>
+      </ng-template>
+    </ng-template>
+
+    <!-- button body -->
+    <span *ngIf="item" class="full-sized-button"
+      [matTooltip]="item.version?.name || item.name || item.fullName"
+      [matTooltipPosition]="'above'">
+      {{ item.version?.name || item.shortName || item.name || item.fullName }}
+      <ng-template [ngIf]="suffixText">
+        <span class="text-muted">
+          {{ suffixText }}
+        </span>
+      </ng-template>
+    </span>
+
+    <!-- suffix -->
+    <ng-template [ngIf]="overrideSuffixIcon">
+      <i [class]="overrideSuffixIcon"></i>
+    </ng-template>
+  </ng-template>
+
 </ng-template>
 
 <!-- half selected -->
@@ -126,48 +195,3 @@
 <ng-template #halfSelectedTmpl>
   <mat-icon fontSet="far" fontIcon="fa-circle"></mat-icon>
 </ng-template>
-
-<!-- option template -->
-<ng-template
-  #optionTmpl
-  let-item
-  let-overridePrefixIconTmpl="overridePrefixIconTmpl"
-  let-overrideSuffixIcon="overrideSuffixIcon"
-  let-suffixText="suffixText">
-
-  <!-- prefix -->
-  <ng-template [ngIf]="overridePrefixIconTmpl" [ngIfElse]="defaultPrefix">
-    <ng-template [ngTemplateOutlet]="overridePrefixIconTmpl"></ng-template>
-  </ng-template>
-  <ng-template #defaultPrefix>
-    <ng-template [ngIf]="selectedIds" let-selectedIds>
-      <mat-icon
-        fontSet="fas"
-        [fontIcon]="selectedIds.includes(item.id) ? 'fa-circle' : 'fa-none'"
-        >
-      </mat-icon>
-    </ng-template>
-  </ng-template>
-
-  <!-- button body -->
-  <span *ngIf="item" class="full-sized-button"
-    [matTooltip]="item.version?.name || item.name || item.fullName"
-    [matTooltipPosition]="'above'">
-    {{ item.version?.name || item.shortName || item.name || item.fullName }}
-    <ng-template [ngIf]="suffixText">
-      <span class="text-muted">
-        {{ suffixText }}
-      </span>
-    </ng-template>
-  </span>
-
-  <!-- suffix -->
-  <ng-template [ngIf]="overrideSuffixIcon">
-    <i [class]="overrideSuffixIcon"></i>
-  </ng-template>
-</ng-template>
-
-
-<ng-template #isBusyTmpl>
-
-</ng-template>
\ No newline at end of file
-- 
GitLab