-
Xiao Gui authored
feat: added button to navigate to point assignment UI
200ebe9d
viewerCmp.template.html 38.11 KiB
<div iav-media-query class="position-absolute w-100 h-100" #media="iavMediaQuery">
<ng-container *ngTemplateOutlet="viewerTmpl">
</ng-container>
<div class="floating-ui">
<div *ngIf="(media.mediaBreakPoint$ | async) < 2"
class="fixed-bottom sxplr-pe-none sxplr-mb-10 d-flex justify-content-center">
<logo-container></logo-container>
</div>
<div *ngIf="(media.mediaBreakPoint$ | async) < 2" floatingMouseContextualContainerDirective>
<div class="h-0"
iav-mouse-hover
#iavMouseHoverContextualBlock="iavMouseHover">
</div>
<mat-list dense class="contextual-block">
<mat-list-item *ngFor="let cvtOutput of iavMouseHoverContextualBlock.currentOnHoverObs$ | async | mouseoverCvt"
class="h-auto">
<mat-icon
[fontSet]="cvtOutput.icon.fontSet"
[fontIcon]="cvtOutput.icon.fontIcon"
mat-list-icon>
</mat-icon>
<div matLine>{{ cvtOutput.text }}</div>
</mat-list-item>
</mat-list>
<!-- TODO Potentially implementing plugin contextual info -->
</div>
</div>
</div>
<!-- <sxplr-overlay-ui></sxplr-overlay-ui> -->
<!-- master draw container -->
<ng-template [ngIf]="view$ | async" let-view>
<mat-drawer-container
*ngIf="viewerLoaded"
iav-switch
[iav-switch-state]="!(view.onlyShowMiniTray)"
#showFullSidenavSwitch="iavSwitch"
class="position-absolute w-100 h-100 mat-drawer-content-overflow-visible invisible"
[hasBackdrop]="false">
<!-- master drawer -->
<mat-drawer
mode="side"
#drawer="matDrawer"
[opened]="!(view.onlyShowMiniTray)"
[@openClose]="showFullSidenavSwitch && (showFullSidenavSwitch.switchState$ | async) ? 'open' : 'closed'"
(@openClose.start)="$event.toState === 'open' && drawer.open()"
(@openClose.done)="$event.toState === 'closed' && drawer.close()"
[autoFocus]="false"
[disableClose]="true"
class="sxplr-custom-cmp darker-bg sxplr-p-0 pe-all col-10 col-sm-10 col-md-5 col-lg-4 col-xl-3 col-xxl-2 z-index-10">
<!-- entry template -->
<ng-template [ngIf]="view.viewerMode" let-mode [ngIfElse]="regularTmpl">
<ng-template [ngTemplateOutlet]="alternateModeDrawerTmpl"
[ngTemplateOutletContext]="{
mode: mode
}"></ng-template>
</ng-template>
<!-- regular mode -->
<ng-template #regularTmpl>
<ng-template
[ngTemplateOutlet]="regularModeDrawerTmpl"
[ngTemplateOutletContext]="{
drawer: drawer,
showFullSidenavSwitch: showFullSidenavSwitch
}">
</ng-template>
</ng-template>
</mat-drawer>
<!-- master content -->
<mat-drawer-content class="visible sxplr-pe-none position-relative">
<iav-layout-fourcorners>
<!-- top left -->
<div iavLayoutFourCornersTopLeft class="ws-no-wrap align-items-start d-inline-flex">
<!-- special mode -->
<ng-template [ngIf]="view.viewerMode" let-mode [ngIfElse]="defaultTopLeftTmpl">
<ng-template [ngTemplateOutlet]="specialModeTopLeftTmpl"
[ngTemplateOutletContext]="{
mode: mode,
toggleMatDrawer: drawer.toggle.bind(drawer)
}">
</ng-template>
</ng-template>
<!-- default mode top left tmpl -->
<ng-template #defaultTopLeftTmpl>
<ng-template [ngTemplateOutlet]="defaultMainContentTopLeft"
[ngTemplateOutletContext]="{
isOpen: drawer.opened,
drawer: drawer,
showFullSidenavSwitch: showFullSidenavSwitch
}">
</ng-template>
</ng-template>
</div>
<!-- top right -->
<div iavLayoutFourCornersTopRight class="ws-no-wrap">
<!-- exit special mode -->
<ng-template [ngIf]="view.viewerMode" let-mode [ngIfElse]="defaultTopRightTmpl">
<ng-template [ngTemplateOutlet]="specialTopRightTmpl"
[ngTemplateOutletContext]="{
mode: mode
}">
</ng-template>
</ng-template>
<!-- default mode top right tmpl -->
<ng-template #defaultTopRightTmpl>
<ng-template [ngTemplateOutlet]="minDefaultMainContentTopRight">
</ng-template>
</ng-template>
</div>
<!-- bottom left -->
<div iavLayoutFourCornersBottomLeft class="ws-no-wrap d-inline-flex w-100vw sxplr-pe-none align-items-center mb-4">
<!-- special bottom left -->
<ng-template [ngIf]="view.viewerMode" let-mode [ngIfElse]="localBottomLeftTmpl"></ng-template>
<!-- default mode bottom left tmpl -->
<ng-template #localBottomLeftTmpl>
<!-- not the most elegant, but it's a hard problem to solve -->
<!-- on the one hand, showFullSidenavSwitch can be of two states -->
<!-- and drawer.opened can be of two states -->
<ng-template [ngTemplateOutlet]="bottomLeftTmpl"
[ngTemplateOutletContext]="{
showFullSideNav: (showFullSidenavSwitch.switchState$ | async)
? drawer.open.bind(drawer)
: showFullSidenavSwitch.open.bind(showFullSidenavSwitch)
}">
</ng-template>
</ng-template>
</div>
<!-- buttom right -->
<div iavLayoutFourCornersBottomRight>
<div class="leap-control-wrapper">
<div leap-control-view-ref></div>
</div>
</div>
</iav-layout-fourcorners>
</mat-drawer-content>
</mat-drawer-container>
</ng-template>
<!-- alternate mode drawer tmpl -->
<ng-template #alternateModeDrawerTmpl let-mode="mode">
<ng-container [ngSwitch]="mode">
<annotation-list *ngSwitchCase="ARIA_LABELS.VIEWER_MODE_ANNOTATING">
</annotation-list>
<key-frame-controller *ngSwitchCase="ARIA_LABELS.VIEWER_MODE_KEYFRAME">
</key-frame-controller>
<span *ngSwitchDefault>View mode {{ mode }} does not have side nav registered.</span>
</ng-container>
</ng-template>
<!-- regular mode drawer tmpl -->
<ng-template #regularModeDrawerTmpl
let-drawer="drawer"
let-showFullSidenavSwitch="showFullSidenavSwitch">
<!-- selectedFeature || selectedRegion -->
<ng-template [ngIf]="view$ | async" let-view>
<!-- if selected feature is not null, show selected feature -->
<ng-template [ngIf]="view.selectedFeature">
<ng-template
[ngTemplateOutlet]="selectedFeatureTmpl"
[ngTemplateOutletContext]="{
feature: view.selectedFeature
}">
</ng-template>
</ng-template>
<!-- if selected point is not null, show selected point -->
<ng-template [ngIf]="view.selectedPoint">
<ng-template
[ngTemplateOutlet]="selectedPointTmpl"
[ngTemplateOutletContext]="{
view: view
}">
</ng-template>
</ng-template>
<!-- if selected feature and selected point are both null, show default (selected region) -->
<!-- ngIf and ngtemplateoutlet is required when ngIf changes too quickly, it seems -->
<ng-template [ngIf]="!view.selectedFeature && !view.selectedPoint">
<ng-template
[ngTemplateOutlet]="sidenavRegionTmpl"
[ngTemplateOutletContext]="{
view: view,
showFullSidenavSwitch: showFullSidenavSwitch
}">
</ng-template>
</ng-template>
</ng-template>
</ng-template>
<!-- minimal default drawer content -->
<ng-template #minSearchTray
let-showFullSidenav="showFullSidenav"
let-drawer="drawer">
<div class="mt-2 d-inline-block vw-col-10 vw-col-sm-10 vw-col-md-5 vw-col-lg-4 vw-col-xl-3 vw-col-xxl-2"
iav-switch
[iav-switch-state]="true"
#minTrayVisSwitch="iavSwitch"
[ngClass]="{
'vw-col-10-nm vw-col-sm-10-nm vw-col-md-5-nm vw-col-lg-4-nm vw-col-xl-3-nm vw-col-xxl-2-nm': !(minTrayVisSwitch.switchState$ | async),
'transition-margin-left': !drawer.opened
}">
<!-- collapsed side bar view -->
<div class="h-0 w-100 region-text-search-autocomplete-position">
<ng-container *ngTemplateOutlet="autocompleteTmpl; context: { showTour: true }">
</ng-container>
<ng-template [ngIf]="view$ | async" let-view>
<!-- if no selected regions, show spatial search -->
<div *ngIf="(view.selectedRegions || []).length === 0" class="sxplr-p-1 w-100">
<ng-template
[ngTemplateOutlet]="spatialFeatureListTmpl"
[ngTemplateOutletContext]="{
view: view
}">
</ng-template>
</div>
</ng-template>
</div>
<!-- such a gross implementation -->
<!-- TODO fix this -->
<ng-template [ngIf]="view$ | async" let-view>
<div class="min-tray-explr-btn"
sxplr-sapiviews-core-region
[sxplr-sapiviews-core-region-atlas]="selectedAtlas$ | async"
[sxplr-sapiviews-core-region-template]="view.selectedTemplate"
[sxplr-sapiviews-core-region-parcellation]="view.selectedParcellation"
[sxplr-sapiviews-core-region-region]="view.selectedRegions.length === 1 ? view.selectedRegions[0] : null"
[sxplr-sapiviews-core-region-detail-flag]="true"
#sapiRegion="sapiViewsCoreRegion">
<!-- TODO use sapiViews/core/region/base and fix the rest -->
<button mat-raised-button
*ngIf="!(view$ | async | getProperty : 'onlyShowMiniTray')"
[attr.aria-label]="ARIA_LABELS.EXPAND"
(click)="showFullSidenav()"
class="sxplr-mt-9 sxplr-pe-all w-100"
[ngClass]="{
'darktheme': sapiRegion.regionDarkmode,
'lighttheme': !sapiRegion.regionDarkmode
}"
[style.backgroundColor]="sapiRegion.regionRgbString">
<span class="text sxplr-custom-cmp">
Explore
</span>
</button>
</div>
</ng-template>
</div>
<!-- tab to minimize mini tray -->
<div class="tab-toggle-container">
<div [ngClass]="(minTrayVisSwitch.switchState$ | async) ? '' : 'd-none'">
<ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{
fontIcon: 'fas fa-chevron-left',
matColor: null,
click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch)
}">
</ng-template>
</div>
<div [ngClass]="(minTrayVisSwitch.switchState$ | async) ? 'd-none' : ''">
<ng-template [ngIf]="voiFeatureEntryCmp && (voiFeatureEntryCmp.totals$ | async)"
[ngIfElse]="noBadgeTmpl"
let-totals>
<ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{
fontIcon: 'fas fa-search',
matColor: 'primary',
click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch),
badge: totals
}">
</ng-template>
</ng-template>
<ng-template #noBadgeTmpl>
<ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl" [ngTemplateOutletContext]="{
fontIcon: 'fas fa-search',
matColor: 'primary',
click: minTrayVisSwitch.toggle.bind(minTrayVisSwitch)
}">
</ng-template>
</ng-template>
</div>
</div>
</ng-template>
<!-- top left -->
<!-- default top left -->
<ng-template #defaultMainContentTopLeft
let-isOpen="isOpen"
let-drawer="drawer"
let-showFullSidenavSwitch="showFullSidenavSwitch">
<!-- min search tray -->
<ng-template [ngIf]="!(showFullSidenavSwitch.switchState$ | async)">
<ng-template
[ngTemplateOutlet]="minSearchTray"
[ngTemplateOutletContext]="{
showFullSidenav: showFullSidenavSwitch.open.bind(showFullSidenavSwitch),
drawer: drawer
}">
</ng-template>
</ng-template>
<!-- pullable tab top left corner -->
<ng-template [ngIf]="view$ | async" let-view>
<div *ngIf="showFullSidenavSwitch.switchState$ | async"
class="v-align-top pe-all tab-toggle-container d-inline-block"
(click)="drawer.toggle()"
quick-tour
[quick-tour-description]="quickTourRegionSearch.description"
[quick-tour-order]="quickTourRegionSearch.order">
<ng-container *ngTemplateOutlet="tabTmpl; context: {
isOpen: isOpen,
view: view
}">
</ng-container>
</div>
</ng-template>
<!-- status panel for (for nehuba viewer) -->
<iav-cmp-viewer-nehuba-status *ngIf="(useViewer$ | async) === 'nehuba'"
class="pe-all mt-2 muted-7 d-inline-block v-align-top">
</iav-cmp-viewer-nehuba-status>
<button
mat-icon-button
sxplr-share-view
*ngIf="(useViewer$ | async) === 'threeSurfer'"
class="pe-all mt-2 muted-7 d-inline-block v-align-top">
<i class="fas fa-share-square"></i>
</button>
</ng-template>
<!-- special mode top left -->
<ng-template #specialModeTopLeftTmpl
let-mode="mode"
let-toggleMatDrawer="toggleMatDrawer">
<div class="tab-toggle-container">
<ng-container [ngSwitch]="mode">
<!-- annotating top left -->
<ng-template [ngSwitchCase]="ARIA_LABELS.VIEWER_MODE_ANNOTATING">
<ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
matColor: 'primary',
fontIcon: 'fa-list',
tooltip: 'Annotation list',
click: toggleMatDrawer,
badge: toolPanel?.annBadges$ | async
}">
</ng-container>
<annotating-tools-panel class="z-index-10 d-block"
#toolPanel="annoToolsPanel">
</annotating-tools-panel>
</ng-template>
<ng-template [ngSwitchCase]="ARIA_LABELS.VIEWER_MODE_KEYFRAME">
<ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
matColor: 'primary',
fontIcon: 'fa-play',
tooltip: 'Annotation list',
click: toggleMatDrawer
}">
</ng-container>
</ng-template>
</ng-container>
</div>
</ng-template>
<!-- top right -->
<!-- default top right -->
<ng-template #minDefaultMainContentTopRight>
<!-- signin banner at top right corner -->
<top-menu-cmp class="mt-3 mr-2 d-inline-block"
[ismobile]="(media.mediaBreakPoint$ | async) > 3"
[viewerLoaded]="viewerLoaded">
</top-menu-cmp>
</ng-template>
<!-- special mode top right -->
<ng-template #specialTopRightTmpl let-mode="mode">
<mat-card class="mat-card-sm pe-all m-4">
<span>
{{ mode }}
</span>
<button mat-icon-button
color="warn"
(click)="exitSpecialViewMode()">
<i class="fas fa-times"></i>
</button>
</mat-card>
</ng-template>
<!-- bottom left -->
<ng-template #bottomLeftTmpl let-showFullSideNav="showFullSideNav">
<ng-template [ngIf]="view$ | async" let-view>
<!-- scroll container -->
<div class="sxplr-d-inline-flex
sxplr-flex-wrap-nowrap
sxplr-mxw-100vw
sxplr-pe-all
sxplr-of-x-auto
sxplr-of-y-hidden
sxplr-align-items-stretch">
<sxplr-bottom-menu (onRegionClick)="showFullSideNav()"></sxplr-bottom-menu>
</div>
</ng-template>
</ng-template>
<!-- viewer tmpl -->
<ng-template #viewerTmpl>
<div class="position-absolute w-100 h-100 z-index-1"
ctx-menu-host
[ctx-menu-host-tmpl]="viewerCtxMenuTmpl">
<ng-container [ngSwitch]="useViewer$ | async">
<!-- nehuba viewer -->
<iav-cmp-viewer-nehuba-glue class="d-block w-100 h-100 position-absolute left-0 tosxplr-p-0"
*ngSwitchCase="'nehuba'"
(viewerEvent)="handleViewerEvent($event)"
#iavCmpViewerNehubaGlue="iavCmpViewerNehubaGlue">
</iav-cmp-viewer-nehuba-glue>
<!-- three surfer (free surfer viewer) -->
<tmp-threesurfer-lifecycle class="d-block w-100 h-100 position-absolute left-0 tosxplr-p-0"
*ngSwitchCase="'threeSurfer'"
(viewerEvent)="handleViewerEvent($event)">
</tmp-threesurfer-lifecycle>
<!-- if not supported, show not supported message -->
<div *ngSwitchCase="'notsupported'">Template not supported by any of the viewers</div>
<!-- by default, show splash screen -->
<div class="sxplr-h-100" *ngSwitchDefault>
<ng-template [ngIf]="(selectedAtlas$ | async)" [ngIfElse]="splashScreenTmpl">
<div class="center-a-div">
<div class="loading-atlas-text-container">
<spinner-cmp class="fs-200"></spinner-cmp>
<span>
Loading
{{ (selectedAtlas$ | async).name }}
</span>
</div>
</div>
</ng-template>
<ng-template #splashScreenTmpl>
<ui-splashscreen class="position-absolute left-0 tosxplr-p-0">
</ui-splashscreen>
</ng-template>
</div>
</ng-container>
</div>
</ng-template>
<!-- region-hierarchy-tmpl -->
<ng-template #regionHierarchyTmpl>
<ng-template [ngIf]="view$ | async" let-view>
<div class="sxplr-d-flex sxplr-flex-column sxplr-h-100">
<sxplr-sapiviews-core-rich-regionshierarchy
class="sxplr-w-100 sxplr-flex-var"
[sxplr-sapiviews-core-rich-regionshierarchy-regions]="allAvailableRegions$ | async"
[sxplr-sapiviews-core-rich-regionshierarchy-label-mapped-region-names]="view.labelMappedRegionNames"
[sxplr-sapiviews-core-rich-regionshierarchy-accent-regions]="view.selectedRegions"
(sxplr-sapiviews-core-rich-regionshierarchy-region-select)="selectRoi($event)"
(sxplr-sapiviews-core-rich-regionshierarchy-region-toggle)="toggleRoi($event)"
>
</sxplr-sapiviews-core-rich-regionshierarchy>
<mat-dialog-actions align="center" class="sxplr-flex-static">
<button mat-button mat-dialog-close>Close</button>
</mat-dialog-actions>
</div>
</ng-template>
</ng-template>
<!-- auto complete search box -->
<ng-template #autocompleteTmpl let-showTour="showTour">
<ng-template [ngIf]="view$ | async" let-view>
<div class="sxplr-custom-cmp bg card ml-2 mr-2 mat-elevation-z8 pe-all auto-complete-container">
<sxplr-sapiviews-core-rich-regionlistsearch
[sxplr-sapiviews-core-rich-regionlistsearch-regions]="allAvailableRegions$ | async"
[sxplr-sapiviews-core-rich-regionlistsearch-mapped-region-names]="view.labelMappedRegionNames"
[sxplr-sapiviews-core-rich-regionlistsearch-current-search]="view.selectedRegions.length === 1 ? view.selectedRegions[0].name : null"
(sxplr-sapiviews-core-rich-regionlistsearch-region-select)="selectRoi($event)"
(sxplr-sapiviews-core-rich-regionlistsearch-region-toggle)="toggleRoi($event)">
<ng-template regionTemplate let-region>
<div class="sxplr-d-flex">
<button
mat-icon-button
class="sxplr-mt-a sxplr-mb-a">
<i [ngClass]="(view.selectedRegions | includes : region) ? 'fa-circle' : 'fa-none'" class="fas"></i>
</button>
<sxplr-sapiviews-core-region-region-list-item
[sxplr-sapiviews-core-region-region]="region">
</sxplr-sapiviews-core-region-region-list-item>
</div>
</ng-template>
<button mat-icon-button
search-input-suffix
*ngIf="view.selectedRegions.length > 0"
(click)="clearRoi()">
<i class="fas fa-times"></i>
</button>
</sxplr-sapiviews-core-rich-regionlistsearch>
<button mat-icon-button
color="primary"
[sxplr-dialog]="regionHierarchyTmpl"
sxplr-dialog-size="xl">
<i class="fas fa-sitemap"></i>
</button>
<div class="w-100 h-100 position-absolute sxplr-pe-none" *ngIf="showTour">
</div>
</div>
</ng-template>
</ng-template>
<!-- template for rendering tab -->
<ng-template #tabTmpl
let-isOpen="isOpen"
let-iavAdditionallayers="iavAdditionallayers"
let-click="click"
let-badge="badge"
let-view="view">
<!-- if mat drawer is open -->
<ng-template [ngIf]="isOpen" [ngIfElse]="tabTmpl_closedTmpl">
<ng-template [ngTemplateOutlet]="tabTmpl_defaultTmpl"
[ngTemplateOutletContext]="{
matColor: 'basic',
fontIcon: 'fa-chevron-left',
click: click,
badge: badge
}">
</ng-template>
</ng-template>
<!-- if matdrawer is closed -->
<ng-template #tabTmpl_closedTmpl>
<!-- if additional layers are being shown -->
<ng-template [ngIf]="iavAdditionallayers?.length > 0" [ngIfElse]="tabTmpl_noAdditionalLayers">
<ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
matColor: 'accent',
fontIcon: 'fa-database',
tooltip: 'Explore dataset preview',
click: click
}">
</ng-container>
</ng-template>
<!-- if additional layers not not being shown -->
<ng-template #tabTmpl_noAdditionalLayers>
<!-- if region selected === 1 -->
<ng-template [ngIf]="view.regionSelected?.length === 1" [ngIfElse]="tabTmpl_nothingSelected">
<div sxplr-sapiviews-core-region
[sxplr-sapiviews-core-region-detail-flag]="true"
[sxplr-sapiviews-core-region-atlas]="selectedAtlas$ | async"
[sxplr-sapiviews-core-region-template]="view.selectedTemplate"
[sxplr-sapiviews-core-region-parcellation]="view.selectedParcellation"
[sxplr-sapiviews-core-region-region]="view.regionSelected[0]"
#tabTmpl_iavRegion="sapiViewsCoreRegion">
</div>
<!-- TODO fix with sapiView/core/region directive -->
<ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
matColor: 'accent',
customColor: tabTmpl_iavRegion.regionRgbString,
customColorDarkmode: tabTmpl_iavRegion.regionDarkmode,
fontIcon: 'fa-brain',
tooltip: 'Explore ' + view.regionSelected[0].name,
click: click
}">
</ng-container>
</ng-template>
<!-- nothing is selected -->
<ng-template #tabTmpl_nothingSelected>
<ng-container *ngTemplateOutlet="tabTmpl_defaultTmpl; context: {
matColor: 'primary',
fontIcon: 'fa-sitemap',
tooltip: 'Explore regions',
click: click,
badge: badge
}">
</ng-container>
</ng-template>
</ng-template>
</ng-template>
</ng-template>
<ng-template #tabTmpl_defaultTmpl
let-matColor="matColor"
let-fontIcon="fontIcon"
let-customColor="customColor"
let-customColorDarkmode="customColorDarkmode"
let-tooltip="tooltip"
let-badge="badge"
let-badgeColor="badgeColor"
let-click="click">
<!-- (click)="sideNavMasterSwitch.toggle()" -->
<button mat-raised-button
[attr.aria-label]="ARIA_LABELS.TOGGLE_SIDE_PANEL"
[matTooltip]="tooltip"
class="pe-all tab-toggle"
[ngClass]="{
'darktheme': customColorDarkmode === true,
'lighttheme': customColorDarkmode === false
}"
(click)="click && click()"
[style.backgroundColor]="customColor"
[color]="(!customColor && matColor) ? matColor : null"
[matBadge]="badge"
[matBadgeColor]="badgeColor || 'warn'">
<span [ngClass]="{'sxplr-custom-cmp text': !!customColor}">
<i class="fas" [ngClass]="fontIcon || 'fa-question'"></i>
</span>
</button>
</ng-template>
<!-- region sidenav tmpl -->
<ng-template #sidenavRegionTmpl
let-showFullSidenavSwitch="showFullSidenavSwitch"
let-view="view">
<!-- region search autocomplete -->
<!-- [@openCloseAnchor]="sideNavFullLeftSwitch.switchState ? 'open' : 'closed'" -->
<div class="h-0 w-100 region-text-search-autocomplete-position">
<ng-container *ngTemplateOutlet="autocompleteTmpl">
</ng-container>
</div>
<div class="flex-shrink-1 flex-grow-1 d-flex flex-column sxplr-h-100"
[ngClass]="{'region-populated': (view.selectedRegions || []).length > 0 }">
<!-- region detail -->
<!-- single-region-wrapper -->
<ng-template [ngIf]="view.selectedRegions.length === 1" [ngIfElse]="multiRegionWrapperTmpl">
<!-- a series of bugs result in requiring this hacky -->
<!-- see https://github.com/HumanBrainProject/interactive-viewer/issues/698 -->
<ng-template [ngIf]="regionDirective.fetchInProgress$ | async">
<spinner-cmp class="sxplr-mt-10 fs-200"></spinner-cmp>
</ng-template>
<sxplr-sapiviews-core-region-region-rich
[sxplr-sapiviews-core-region-atlas]="selectedAtlas$ | async"
[sxplr-sapiviews-core-region-template]="view.selectedTemplate"
[sxplr-sapiviews-core-region-parcellation]="view.selectedParcellation"
[sxplr-sapiviews-core-region-region]="view.selectedRegions[0]"
(sxplr-sapiviews-core-region-region-rich-feature-clicked)="showDataset($event)"
(sxplr-sapiviews-core-region-navigate-to)="navigateTo($event)"
#regionDirective="sapiViewsCoreRegionRich"
>
<div class="sapi-container" header></div>
</sxplr-sapiviews-core-region-region-rich>
</ng-template>
<!-- multi region wrapper -->
<ng-template #multiRegionWrapperTmpl>
<ng-container *ngTemplateOutlet="multiRegionTmpl; context: {
regions: view.selectedRegions
}">
</ng-container>
<!-- This is a wrapper for multiregion consisting of {{ selectedRegions.length }} regions -->
</ng-template>
<!-- place holder if length === 0 -->
<ng-container *ngIf="view.selectedRegions.length === 0">
no region selected
</ng-container>
<div class="spacer">
</div>
</div>
<!-- collapse btn -->
<ng-template [ngTemplateOutlet]="collapseBtn"
[ngTemplateOutletContext]="{
collapse: showFullSidenavSwitch.close.bind(showFullSidenavSwitch)
}">
</ng-template>
</ng-template>
<!-- expansion tmpl -->
<ng-template #ngMatAccordionTmpl
let-title="title"
let-desc="desc"
let-iconClass="iconClass"
let-iconTooltip="iconTooltip"
let-iavNgIf="iavNgIf"
let-content="content">
</ng-template>
<!-- multi region tmpl -->
<ng-template #multiRegionTmpl let-regions="regions">
<ng-template [ngIf]="regions.length > 0" [ngIfElse]="regionPlaceholderTmpl">
<sxplr-side-panel>
<div class="sapi-container" header></div>
<div title>
Multiple regions selected
</div>
<!-- other regions detail accordion -->
<mat-accordion class="bs-border-box ml-15px-n mr-15px-n mt-2">
<!-- Multi regions include -->
<mat-expansion-panel
[attr.data-opened]="expansionPanel.expanded"
[attr.data-mat-expansion-title]="'Brain regions'"
hideToggle
#expansionPanel="matExpansionPanel">
<mat-expansion-panel-header>
<!-- title -->
<mat-panel-title>
Selected regions
</mat-panel-title>
<!-- desc + icon -->
<mat-panel-description class="d-flex align-items-center justify-content-end">
<span class="mr-3">{{ regions.length }}</span>
<span class="accordion-icon d-inline-flex justify-content-center">
<i class="fas fa-brain"></i>
</span>
</mat-panel-description>
</mat-expansion-panel-header>
<!-- content -->
<ng-template matExpansionPanelContent>
<mat-chip-list class="wrapped-chips">
<mat-chip *ngFor="let region of regions">
<span>
{{ region.name }}
</span>
<button mat-icon-button
(click)="toggleRoi(region)"
iav-stop="mousedown click">
<i class="fas fa-times"></i>
</button>
</mat-chip>
</mat-chip-list>
</ng-template>
</mat-expansion-panel>
</mat-accordion>
</sxplr-side-panel>
</ng-template>
</ng-template>
<!-- collapse btn -->
<ng-template #collapseBtn let-collapse="collapse">
<div class="h-0 w-100 collapse-position d-flex flex-column justify-content-end align-items-center">
<button mat-raised-button class="mat-elevation-z8"
[attr.aria-label]="ARIA_LABELS.COLLAPSE"
(click)="collapse()"
color="basic">
<i class="fas fa-chevron-up"></i>
<span>
collapse
</span>
</button>
</div>
</ng-template>
<!-- region tmpl placeholder -->
<ng-template #regionPlaceholderTmpl>
<div class="placeholder-region-detail bs-border-box ml-15px-n mr-15px-n mat-elevation-z4">
<span class="text-muted">
Select a region by clicking on the viewer or search from above
</span>
</div>
</ng-template>
<!-- context menu template -->
<ng-template #viewerCtxMenuTmpl let-tmplRefs="tmplRefs">
<mat-card class="sxplr-p-0 d-flex flex-column"
[iav-key-listener]="[{type: 'keydown', target: 'document', capture: true, key: 'Esc'}]"
(iav-key-event)="disposeCtxMenu()"
(iav-outsideClick)="disposeCtxMenu()">
<mat-card-content *ngFor="let tmplRef of tmplRefs"
class="m-0"
[ngStyle]="{order: tmplRef.order || 0}">
<mat-divider></mat-divider>
<!-- template provided -->
<ng-template [ngIf]="tmplRef.tmpl"
[ngIfElse]="fallbackTmpl"
[ngTemplateOutlet]="tmplRef.tmpl"
[ngTemplateOutletContext]="{$implicit: tmplRef.data}">
</ng-template>
<!-- template not provided -->
<ng-template #fallbackTmpl>
{{ tmplRef.data.message || 'test' }}
</ng-template>
<mat-divider></mat-divider>
</mat-card-content>
</mat-card>
</ng-template>
<ng-template #lastViewedPointTmpl let-data>
<div class="text-muted sxplr-m-2">
Last selected spatial object
</div>
<button mat-button class="sxplr-list-like-button"
(click)="selectPoint(data, data.template)">
<div class="sxplr-list-like-button-icon">
<i class="fas fa-history"></i>
</div>
<div class="sxplr-list-like-button-body">
<ng-template [ngIf]="data?.point">
<span class="sxplr-list-like-button-body-line">
{{ data.point | nmToMm | numbers | addUnitAndJoin : '' }} (mm)
</span>
<span class="sxplr-list-like-button-body-line text-muted">
Point
</span>
</ng-template>
<ng-template [ngIf]="data.face && data.vertices">
<span class="sxplr-list-like-button-body-line">
Face Index: {{ data.face }}, Vertices Index: {{ data.vertices | addUnitAndJoin : '' }}
</span>
<span class="sxplr-list-like-button-body-line text-muted">
Mesh Face
</span>
</ng-template>
<span class="sxplr-list-like-button-body-line text-muted">
<span>
{{ data.template.name }}
</span>
<ng-template [ngIf]="templateSelected$ | async" let-templateSelected>
<ng-template [ngIf]="templateSelected.id !== data.template.id">
<mat-icon fontSet="fas" fontIcon="fa-exclamation-triangle"
color="warn"
matTooltip="Different template spaces detected.">
</mat-icon>
</ng-template>
</ng-template>
</span>
</div>
<!-- {{ data.point | json }} -->
</button>
</ng-template>
<!-- viewer status ctx menu -->
<ng-template #viewerStatusCtxMenu let-data>
<ng-template [ngIf]="data.context" let-context>
<!-- ref space & position -->
<ng-container [ngSwitch]="context.viewerType">
<!-- volumetric i.e. nehuba -->
<ng-container *ngSwitchCase="'nehuba'">
<button mat-button class="sxplr-list-like-button"
(click)="selectPoint({ point: context.payload.mouse.real }, data.metadata.template)">
<div class="sxplr-list-like-button-icon">
<i class="fas fa-map"></i>
</div>
<div class="sxplr-list-like-button-body">
<span class="sxplr-list-like-button-body-line">
{{ context.payload.mouse.real | nmToMm | numbers | addUnitAndJoin : '' }} (mm)
</span>
<span class="sxplr-list-like-button-body-line text-muted">
Point
</span>
<span class="sxplr-list-like-button-body-line text-muted">
{{ data.metadata.template.name }}
</span>
</div>
</button>
</ng-container>
<ng-container *ngSwitchCase="'threeSurfer'">
<ng-template [ngIf]="context.payload?.faceIndex" let-faceIndex>
<ng-template [ngIf]="context.payload?.vertexIndices" let-vertexIndices>
<button mat-button class="sxplr-list-like-button"
(click)="selectPoint({ face: faceIndex, vertices: vertexIndices }, data.metadata.template)"
disabled>
<div class="sxplr-list-like-button-icon">
<i class="fas fa-map"></i>
</div>
<div class="sxplr-list-like-button-body">
<span class="sxplr-list-like-button-body-line">
Face Index: {{ faceIndex }}, Vertices Index: {{ vertexIndices | addUnitAndJoin : '' }}
</span>
<span class="sxplr-list-like-button-body-line text-muted">
Mesh Face
</span>
<span class="sxplr-list-like-button-body-line text-muted">
{{ data.metadata.template.name }}
</span>
<i class="sxplr-list-like-button-body-line text-muted">
(Not selectable at the moment)
</i>
</div>
</button>
</ng-template>
</ng-template>
</ng-container>
<ng-container *ngSwitchDefault>
DEFAULT
</ng-container>
</ng-container>
</ng-template>
</ng-template>
<!-- viewer state hover ctx menu -->
<ng-template #viewerStatusRegionCtxMenu let-data>
<!-- hovered ROIs -->
<ng-template ngFor [ngForOf]="data.metadata.hoveredRegions"
let-region
let-first="first">
<mat-divider class="top-0" *ngIf="!first"></mat-divider>
<button mat-button
(click)="$event.ctrlKey ? toggleRoi(region) : selectRoi(region)"
class="sxplr-list-like-button">
<div class="sxplr-list-like-button-icon">
<i class="fas fa-brain"></i>
</div>
<div class="sxplr-list-like-button-body">
<span class="sxplr-list-like-button-body-line">
{{ region.name }}
</span>
<span class="sxplr-list-like-button-body-line text-muted">
Brain region
</span>
</div>
</button>
</ng-template>
</ng-template>
<!-- general feature tmpl -->
<ng-template let-feature="feature" #selectedFeatureTmpl>
<!-- TODO differentiate between features (spatial, regional etc) -->
<sxplr-feature-view class="sxplr-z-2 mat-elevation-z2"
[feature]="feature">
<div header>
<!-- back btn -->
<button mat-button
(click)="clearSelectedFeature()"
[attr.aria-label]="ARIA_LABELS.CLOSE"
class="sxplr-mb-2"
>
<i class="fas fa-chevron-left"></i>
<span class="ml-1">
Back
</span>
</button>
</div>
</sxplr-feature-view>
</ng-template>
<!-- general point tmpl -->
<ng-template let-view="view" #selectedPointTmpl>
<sxplr-side-panel>
<div class="sxplr-custom-cmp lighttheme" header>
<!-- back btn -->
<button mat-button
(click)="clearPoint()"
[attr.aria-label]="ARIA_LABELS.CLOSE"
class="sxplr-mb-2"
>
<i class="fas fa-chevron-left"></i>
<span class="ml-1">
Back
</span>
</button>
</div>
<div title>
{{ view.spatialObjectTitle }}
</div>
<div subtitle>
{{ view.spatialObjectSubtitle }}
</div>
</sxplr-side-panel>
<sxplr-point-assignment
[point]="view.selectedPoint"
[template]="view.selectedTemplate"
[parcellation]="view.selectedParcellation"
(clickOnRegion)="$event.event.ctrlKey ? toggleRoi($event.target) : selectRoi($event.target)">
</sxplr-point-assignment>
</ng-template>
<!-- spatial search tmpls -->
<ng-template #spatialFeatureListTmpl let-view="view">
<mat-card class="sxplr-pe-all"
[ngClass]="{
'sxplr-d-none': !(voiSwitch.switchState$ | async) || (voiFeatureEntryCmp.totals$ | async) === 0
}">
<mat-card-header>
<mat-card-title>
Anchored to current view
</mat-card-title>
<mat-card-subtitle>
<div *ngIf="view.selectedTemplate">
{{ view.selectedTemplate.name }}
</div>
<ng-template [ngIf]="bbox.bbox$ | async | getProperty : 'bbox'" let-bbox>
<div>
from {{ bbox[0] | numbers | addUnitAndJoin : '' }}
</div>
<div>
to {{ bbox[1] | numbers | addUnitAndJoin : '' }}
</div>
</ng-template>
</mat-card-subtitle>
</mat-card-header>
<div class="loadingText">
<ng-template [ngIf]="voiFeatureEntryCmp.busy$ | async">
<spinner-cmp class="sxplr-d-inline-block"></spinner-cmp>
<span>
Loading Wireframes ...
</span>
</ng-template>
</div>
</mat-card>
<sxplr-feature-entry
[ngClass]="(voiSwitch.switchState$ | async) ? 'sxplr-d-block' : 'sxplr-d-none'"
class="sxplr-pe-all mat-elevation-z8"
[template]="view.selectedTemplate"
[bbox]="bbox.bbox$ | async | getProperty : 'bbox'"
[attr.data-feature-length]="((voiFeatureEntryCmp.features$ | async) || []).length"
#voiFeatureEntryCmp="featureEntryCmp">
</sxplr-feature-entry>
<mat-card [ngClass]="{
'sxplr-d-none': (voiFeatureEntryCmp.totals$ | async) > 0
}">
No spatial features found.
</mat-card>
<button mat-raised-button
[ngClass]="{
'sxplr-d-none': (voiFeatureEntryCmp.totals$ | async) === 0
}"
class="sxplr-pe-all sxplr-w-100"
iav-switch
[iav-switch-state]="false"
#voiSwitch="iavSwitch"
(iav-switch-event)="$event && pullAllVoi()"
(click)="voiSwitch.toggle()">
<ng-template [ngIf]="voiSwitch.switchState$ | async" [ngIfElse]="chevronCollapseTmpl">
<i class="fas fa-chevron-up"></i>
<span>
Collapse
</span>
</ng-template>
<ng-template #chevronCollapseTmpl>
<i class="fas fa-chevron-down"></i>
<span>
Explore {{ voiFeatureEntryCmp.totals$ | async }} spatial features
</span>
</ng-template>
</button>
<!-- TODO voiBbox directive is used to draw outlines for VOI
this has been temporarily disabled, since datasource is paginated
and how bounding boxes are drawn needs to be reconsidered -->
<div
*ngIf="voiSwitch.switchState$| async"
voiBbox
[features]="voiFeatureEntryCmp.features$ | async">
</div>
</ng-template>
<div
sxplr-sapiviews-core-space-boundingbox
(sxplr-sapiviews-core-space-boundingbox-changed)="pullAllVoi()"
[sxplr-sapiviews-core-space-boundingbox-atlas]="selectedAtlas$ | async"
[sxplr-sapiviews-core-space-boundingbox-space]="templateSelected$ | async"
[sxplr-sapiviews-core-space-boundingbox-spec]="viewerCtx$ | async | nehubaVCtxToBbox"
#bbox="sxplrSapiViewsCoreSpaceBoundingBox">
</div>