diff --git a/src/atlasViewer/atlasViewer.style.css b/src/atlasViewer/atlasViewer.style.css index 4add13a9b03d29fdfb50d376224d0b2ba1421372..c5024d44227a8cb0e0594637e583f392418efcbb 100644 --- a/src/atlasViewer/atlasViewer.style.css +++ b/src/atlasViewer/atlasViewer.style.css @@ -77,4 +77,10 @@ region-menu .floating-container { max-width: 350px; -} \ No newline at end of file +} + +logo-container +{ + height: 2rem; + opacity: 0.2; +} diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index 690af5b76204a0e9344ee75bb91bdd57a034289d..7bd8564fc1dadbf7ead97cdc4ea0ec18289f2e00 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -105,7 +105,7 @@ <div *ngIf="(media.mediaBreakPoint$ | async) < 3" - class="fixed-bottom muted-7 pe-none mb-8 d-flex justify-content-end m-4"> + class="fixed-bottom pe-none mb-2 d-flex justify-content-center"> <ng-container *ngTemplateOutlet="logoTmpl"> </ng-container> </div> diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index aaa460d345db20ed131767266762207ef448816b..eaa42b6966fcdc552fa7587ef420c15652aea308 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -576,11 +576,6 @@ mat-icon[fontset="far"] max-width: none!important; } -.mb-8 -{ - margin-bottom:4rem!important; -} - .min-h-2 { min-height: 1rem; @@ -611,10 +606,11 @@ body::after { content: ''; position: fixed; - bottom: 1rem; - right: 2rem; + bottom: 3rem; + width: 100%; + text-align: center; font-size: 200%; - color: rgba(128, 128, 128, 0.5); + color: rgba(128, 128, 128, 0.2); pointer-events: none; z-index: 99999; } @@ -699,6 +695,11 @@ kg-dataset-previewer > img margin-right: -1rem!important; } +.mb-6 +{ + margin-bottom: 3rem!important; +} + .mat-card-sm > mat-dialog-container { padding-left: 16px!important; diff --git a/src/ui/viewerSelector/viewerSelector.component.ts b/src/ui/atlasLayerSelector/atlasLayerSelector.component.ts similarity index 56% rename from src/ui/viewerSelector/viewerSelector.component.ts rename to src/ui/atlasLayerSelector/atlasLayerSelector.component.ts index 8cad2c8c6e62a3bb6e79fcc60a959dcf7eb56824..755763b0983caf57928c5c3b4302539728009418 100644 --- a/src/ui/viewerSelector/viewerSelector.component.ts +++ b/src/ui/atlasLayerSelector/atlasLayerSelector.component.ts @@ -1,24 +1,26 @@ -import { Component, ElementRef, OnInit, ViewChild, ViewChildren, QueryList } from "@angular/core"; +import { Component, OnInit, ViewChildren, QueryList } from "@angular/core"; import { select, Store } from "@ngrx/store"; import { safeFilter } from "src/services/stateStore.service"; -import { distinctUntilChanged, map, withLatestFrom, shareReplay } from "rxjs/operators"; -import { Observable, Subscription } from "rxjs"; +import { distinctUntilChanged, map, withLatestFrom, shareReplay, groupBy, mergeMap, toArray, switchMap, scan } from "rxjs/operators"; +import { Observable, Subscription, from, zip, of } from "rxjs"; import { viewerStateGetSelectedAtlas, viewerStateSelectParcellationWithId, viewerStateSelectTemplateWithId } from "src/services/state/viewerState.store.helper"; import { MatMenuTrigger } from "@angular/material/menu"; @Component({ - selector: 'viewer-selector', - templateUrl: './viewerSelector.template.html', - styleUrls: ['./viewerSelector.style.css'], + selector: 'atlas-layer-selector', + templateUrl: './atlasLayerSelector.template.html', + styleUrls: ['./atlasLayerSelector.style.css'], + exportAs: 'atlasLayerSelector' }) -export class ViewerSelectorComponent implements OnInit { +export class AtlasLayerSelector implements OnInit { @ViewChildren(MatMenuTrigger) matMenuTriggers: QueryList<MatMenuTrigger> public atlas: any - public groupedLayers = [] + public nonGroupedLayers$: Observable<any[]> + public groupedLayers$: Observable<any[]> - public selectedTemplateSpaceIndex: number = 0 + public selectedTemplateSpaceId: string public selectedLayers = [] public selectedTemplate$: Observable<any> @@ -26,8 +28,6 @@ export class ViewerSelectorComponent implements OnInit { public selectedAtlas$: Observable<any> private subscriptions: Subscription[] = [] - public layerGroupMenuItems: any[] - public selectorExpanded: boolean = false public selectedTemplatePreviewUrl: string = '' @@ -54,14 +54,44 @@ export class ViewerSelectorComponent implements OnInit { safeFilter('parcellationSelected'), map(state => state.parcellationSelected), ) + + const layersGroupBy$ = this.selectedAtlas$.pipe( + switchMap(selectedAtlas => from((selectedAtlas?.parcellations) || []).pipe( + groupBy((parcellation: any) => parcellation.groupName, p => p), + mergeMap(group => zip( + of(group.key), + group.pipe(toArray())) + ), + scan((acc, curr) => acc.concat([ curr ]), []), + shareReplay(1), + )) + ) + + this.nonGroupedLayers$ = layersGroupBy$.pipe( + map(arr => { + const nonGrouped = arr.find(([ _key ]) => !_key) + return (nonGrouped && nonGrouped[1]) || [] + }) + ) + + this.groupedLayers$ = layersGroupBy$.pipe( + map(arr => arr + .filter(([ key ]) => !!key ) + .map(([key, parcellations]) => ({ + name: key, + previewUrl: parcellations[0].previewUrl, + parcellations + })) + ), + ) } ngOnInit(): void { this.subscriptions.push( this.selectedTemplate$.subscribe(st => { this.selectedTemplatePreviewUrl = st.templateSpaces.find(t => t['@id'] === st['@id']).previewUrl - this.selectedTemplateSpaceIndex = this.atlas && this.atlas.templateSpaces.findIndex(ts => ts['@id'] === st['@id']) - }) + this.selectedTemplateSpaceId = st['@id'] + }), ) this.subscriptions.push( this.selectedParcellation$.subscribe(ps => { @@ -71,15 +101,6 @@ export class ViewerSelectorComponent implements OnInit { this.subscriptions.push( this.selectedAtlas$.subscribe(sa => { if (sa && sa !== 'undefined') this.atlas = sa - - const groupableParcellations = this.atlas?.parcellations.filter(p => p.groupName && p.groupName.length) - - const groupsDict = groupableParcellations.reduce((r, a) => { - r[a.groupName] = r[a.groupName] || [] - r[a.groupName].push(a) - return r - }, {}) - this.groupedLayers = Object.entries(groupsDict) }) ) } @@ -96,16 +117,16 @@ export class ViewerSelectorComponent implements OnInit { ) } - templateIncludesLayer(layer, template) { - return layer.availableIn.map(a => a['@id']).includes(template['@id']) + currentTemplateIncludesLayer(layer) { + return layer.availableIn.map(a => a['@id']).includes(this.selectedTemplateSpaceId) } - templateIncludesGroup(group, template) { - return group[1].every(v => v.availableIn.map(t => t['@id']).includes(template['@id'])) + templateIncludesGroup(group) { + return group.parcellations.some(v => v.availableIn.map(t => t['@id']).includes(this.selectedTemplateSpaceId)) } selectedOneOfTheLayers(layers) { - const includes = layers.map(l=>l['@id']).some(r=> this.selectedLayers.includes(r)) + const includes = layers.map(l=>l['@id']).some(id=> this.selectedLayers.includes(id)) return includes } @@ -113,11 +134,11 @@ export class ViewerSelectorComponent implements OnInit { return this.selectedLayers.includes(id) } - notGroupedParcellations(parcellations) { - return parcellations.filter(p => !p.groupName) - } - collapseExpandedGroup(){ this.matMenuTriggers.forEach(t => t.menuOpen && t.closeMenu()) } + + getTileTmplClickFnAsCtx(fn: (...arg) => void, param: any) { + return () => fn.call(this, param) + } } diff --git a/src/ui/viewerSelector/viewerSelector.style.css b/src/ui/atlasLayerSelector/atlasLayerSelector.style.css similarity index 97% rename from src/ui/viewerSelector/viewerSelector.style.css rename to src/ui/atlasLayerSelector/atlasLayerSelector.style.css index 2533ae94d54cde966344d5ef06602ff859c459a4..6be755e34cf83aefd429f448a32a1beca8bd5845 100644 --- a/src/ui/viewerSelector/viewerSelector.style.css +++ b/src/ui/atlasLayerSelector/atlasLayerSelector.style.css @@ -31,11 +31,6 @@ border: 2px solid #FED363; } -.cursorPointer { - cursor: pointer !important; -} - - .scale-up-bl { -webkit-animation: scale-up-bl .2s cubic-bezier(.39, .575, .565, 1.000) both; animation: scale-up-bl .2s cubic-bezier(.39, .575, .565, 1.000) both; diff --git a/src/ui/atlasLayerSelector/atlasLayerSelector.template.html b/src/ui/atlasLayerSelector/atlasLayerSelector.template.html new file mode 100644 index 0000000000000000000000000000000000000000..b9abcaf436507145bd6322b217d5cf25f8710840 --- /dev/null +++ b/src/ui/atlasLayerSelector/atlasLayerSelector.template.html @@ -0,0 +1,129 @@ +<div> + <div [hidden]="selectorExpanded" + class="muted-7 m-2 selectedLayerBorder cursor-pointer selectedTemplateDefaultContainer" + (click)="selectorExpanded = true"> + <img [src]="selectedTemplatePreviewUrl" draggable="false"/> + </div> + + + <small *ngIf="selectorExpanded" class="position-relative"> + <mat-card class="scale-up-bl"> + <div class="position-absolute cursor-pointer" style="top: 10px; right: 10px;" (click)="selectorExpanded = false"> + <i class="fas fa-times-circle"></i> + </div> + <!-- templates --> + <mat-card-subtitle class="mb-1">Templates</mat-card-subtitle> + + <div class="d-flex flex-wrap w-100"> + <ng-container *ngFor="let template of (selectedAtlas$ | async)?.templateSpaces"> + <ng-container *ngTemplateOutlet="tileTmpl; context: { + tileSrc: template, + selected: selectedTemplateSpaceId === template['@id'], + onClick: getTileTmplClickFnAsCtx(selectTemplateWithName, template) + }"> + + </ng-container> + </ng-container> + </div> + + <!-- atlas layers --> + <mat-card-subtitle class="mb-1 mt-2">Layers</mat-card-subtitle> + + <div class="d-flex flex-wrap w-100"> + <ng-container *ngFor="let layer of (nonGroupedLayers$ | async)"> + <ng-container *ngTemplateOutlet="tileTmpl; context: { + tileSrc: layer, + selected: selectedLayersIncludes(layer['@id']), + onClick: getTileTmplClickFnAsCtx(selectParcellationWithName, layer), + disabled: !currentTemplateIncludesLayer(layer) + }"> + + </ng-container> + </ng-container> + + <ng-container *ngFor="let group of (groupedLayers$ | async)"> + <ng-container *ngTemplateOutlet="tileTmpl; context: { + tileSrc: group, + selected: selectedOneOfTheLayers(group.parcellations), + disabled: !templateIncludesGroup(group), + menuTriggerFor: layerGroupMenu, + menuTriggerData: { layerGroupItems: group.parcellations }, + isDirectory: true + }"> + + </ng-container> + </ng-container> + </div> + </mat-card> + </small> +</div> + +<!-- image tile tmpl --> +<ng-template #tileTmpl + let-tileSrc="tileSrc" + let-selected="selected" + let-onClick="onClick" + let-disabled="disabled" + let-isDirectory="isDirectory" + let-menuTriggerFor="menuTriggerFor" + let-menuTriggerData="menuTriggerData"> + <div *ngIf="menuTriggerFor; else noMatMenuTriggerTmpl" + iav-stop="click" + [matMenuTriggerFor]="menuTriggerFor" + [matMenuTriggerData]="menuTriggerData"> + + <ng-container *ngTemplateOutlet="tileContent"> + + </ng-container> + </div> + + <ng-template #noMatMenuTriggerTmpl> + <ng-container *ngTemplateOutlet="tileContent"> + + </ng-container> + </ng-template> + + <ng-template #tileContent> + <div class="d-flex flex-column justify-content-start w-100 mb-1 mt-1 overflow-hidden cursor-pointer singleLayerImageContainer" + [matTooltip]="tileSrc.name" + matTooltipPosition="above" + (click)="!disabled && onClick && onClick()" + [ngStyle]="{opacity: disabled ? '0.2': '1' }"> + <img [src]="tileSrc.previewUrl" + alt="Preview of this tile" + class="layer-image align-self-center" + [ngClass]="{ 'selectedLayerBorder': selected }" + draggable="false"> + <div *ngIf="isDirectory" class="d-flex flex-row-reverse align-items-end w-100 h-0"> + <i class="fas fa-folder folder-container fa-2x"></i> + </div> + <small class="ml-1 mr-1 mt-2 text-truncate">{{ tileSrc.name }}</small> + </div> + </ng-template> +</ng-template> + +<!-- mat menu for grouped layer --> +<mat-menu + #layerGroupMenu="matMenu" + class="layerGroupMenu" + hasBackdrop="false"> + + <ng-template matMenuContent let-layerGroupItems="layerGroupItems"> + <div iav-stop="click" + class="d-flex flex-column align-items-center" + (iav-outsideClick)="collapseExpandedGroup()"> + <div class="d-flex flex-column justify-content-center w-100 mb-1 mt-1 overflow-hidden cursor-pointer singleLayerImageContainer" + *ngFor="let layer of layerGroupItems; let i = index;" + [matTooltip]="layer.name" + matTooltipPosition="above" + (click)="currentTemplateIncludesLayer(layer) && selectParcellationWithName(layer)" + [ngStyle]="{opacity: currentTemplateIncludesLayer(layer)? '1' : '0.2'}"> + <img class="layer-image align-self-center" + [ngClass]="selectedLayersIncludes(layer['@id'])? 'selectedLayerBorder' : null" + [src]="layer.previewUrl" + draggable="false"/> + <small class="iv-custom-comp text ml-1 mr-1 mt-2 mb-2 text-truncate">{{layer.name}}</small> + </div> + </div> + </ng-template> +</mat-menu> \ No newline at end of file diff --git a/src/ui/atlasLayerWidget/alwContainer/alwContainer.template.html b/src/ui/atlasLayerWidget/alwContainer/alwContainer.template.html index 8492c463219a3aff5f24a4b207d852d64d17700e..8e775ee6faffeee843e7d72cf64b98cfdcb993e9 100644 --- a/src/ui/atlasLayerWidget/alwContainer/alwContainer.template.html +++ b/src/ui/atlasLayerWidget/alwContainer/alwContainer.template.html @@ -72,7 +72,7 @@ </data-browser> </div> -<!-- tab btn selector --> +<!-- tab btn container --> <div class="flex-grow-0 widget-container d-flex pe-none position-relative"> <mat-chip-list class="poi-name-tag" *ngIf="parcellationOfInterest$ | async as poi"> @@ -82,6 +82,13 @@ <span> {{ poi.name }} </span> + <mat-icon *ngFor="let oDataset of poi.originDatasets" + fontSet="fas" + fontIcon="fa-info-circle" + iav-dataset-show-dataset-dialog + [iav-dataset-show-dataset-dialog-kgschema]="oDataset.kgSchema" + [iav-dataset-show-dataset-dialog-kgid]="oDataset.kgId"> + </mat-icon> <mat-icon *ngIf="!poiIsBaseLayer" (click)="removeNonBaseLayer(poi)" @@ -105,6 +112,7 @@ </ng-container> </div> +<!-- icon for layer widget --> <ng-template #btnTmpl let-matBtnDisabled="matBtnDisabled" @@ -112,6 +120,8 @@ let-badge="badge" let-iconClass="iconClass" let-tooltipText="tooltipText"> + <!-- delay event emit needs to be used. otherwise, iav-dynamic-mat-button will replace the clicked btn with a new btn (via ngSwitch directive) + this results in outsideClick being a false positive --> <iav-dynamic-mat-button class="pe-all" [matBadge]="badge" @@ -127,6 +137,7 @@ </iav-dynamic-mat-button> </ng-template> +<!-- close btn for atlas layer widget --> <ng-template #closeBtn> <button mat-icon-button (click)="visibleTab = null"> diff --git a/src/ui/databrowserModule/showDatasetDialog.directive.ts b/src/ui/databrowserModule/showDatasetDialog.directive.ts index 2d8131e0ab4789738f84c2d1c3c3f8265b86b61d..a77b375018a8438c16bc0a68c6975af88badfaf9 100644 --- a/src/ui/databrowserModule/showDatasetDialog.directive.ts +++ b/src/ui/databrowserModule/showDatasetDialog.directive.ts @@ -16,7 +16,7 @@ export class ShowDatasetDialogDirective{ autoFocus: false } - @Input() + @Input('iav-dataset-show-dataset-dialog-kgschema') kgSchema: string = 'minds/core/dataset/v1.0.0' @Input('iav-dataset-show-dataset-dialog-kgid') diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts index 5df6d2da1723febd1a334e18e04ce1f560c7bc6f..8480e5b9c122f5fd25ee2e7d4663fee068bddd61 100644 --- a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts +++ b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts @@ -18,7 +18,7 @@ export { ChangeDetectorRef, } -export class SingleDatasetBase implements OnInit, OnChanges, OnDestroy { +export class SingleDatasetBase implements OnChanges, OnDestroy { public SHOW_DATASET_PREVIEW_ARIA_LABEL = ARIA_LABELS.SHOW_DATASET_PREVIEW public PIN_DATASET_ARIA_LABEL = ARIA_LABELS.PIN_DATASET @@ -89,7 +89,6 @@ export class SingleDatasetBase implements OnInit, OnChanges, OnDestroy { private error: string = null - public fetchingSingleInfoInProgress = false public downloadInProgress = false public dlFromKgHref: string = null @@ -126,11 +125,18 @@ export class SingleDatasetBase implements OnInit, OnChanges, OnDestroy { }) ).subscribe(dataset => { if (!dataset) return - const { name, description, publications, fullId } = dataset + const { kgSchema, kgId } = this + + const { name, description, publications, fullId, kgReference, files } = dataset this.name = name this.description = description this.publications = publications + this.files = files this.fullId = fullId + + this.kgReference = kgReference + + this.dlFromKgHref = this.singleDatasetService.getDownloadZipFromKgHref({ kgSchema, kgId }) this.fetchFlag = false this.cdr.markForCheck() @@ -184,24 +190,6 @@ export class SingleDatasetBase implements OnInit, OnChanges, OnDestroy { while(this.subscriptions.length > 0) this.subscriptions.pop().unsubscribe() } - public ngOnInit() { - const { kgId, kgSchema, dataset } = this - this.dlFromKgHref = this.singleDatasetService.getDownloadZipFromKgHref({ kgSchema, kgId }) - if ( dataset ) { - const { name, description, kgReference, publications, files, preview } = dataset - this.name = name - this.description = description - this.kgReference = kgReference - this.publications = publications - this.files = files - this.preview = preview - - return - } - if (!kgSchema || !kgId) { return } - this.fetchingSingleInfoInProgress = true - } - get downloadEnabled() { return this.kgSchema && this.kgId } diff --git a/src/ui/logoContainer/logoContainer.style.css b/src/ui/logoContainer/logoContainer.style.css index 7c4c04468d1e04b5095f8096bca89a34b0ed3056..d36734ae3983a6fb3d974aef86ed828811f50b61 100644 --- a/src/ui/logoContainer/logoContainer.style.css +++ b/src/ui/logoContainer/logoContainer.style.css @@ -2,13 +2,11 @@ { display:inline-block; background-size: cover; - pointer-events: none; - height:80px; + height: 100%; } [hbpLogoContainer] > img { visibility: hidden; - height:80px; - pointer-events: none; + height: 100%; } diff --git a/src/ui/nehubaContainer/nehubaContainer.style.css b/src/ui/nehubaContainer/nehubaContainer.style.css index a3a28715e6e18ae84d41dba8115525a6c5568bb9..1d1e5373929a2544c09447cf46733a9b8f829a16 100644 --- a/src/ui/nehubaContainer/nehubaContainer.style.css +++ b/src/ui/nehubaContainer/nehubaContainer.style.css @@ -144,8 +144,8 @@ div#scratch-pad .viewer-status-container { position: absolute; - right: 1em; - bottom: 1em; + right: 0; + bottom: 0; } /* if not mobile, then show on hover */ diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index bdaedfe4394a0b9d986616ad624373faff96119c..b50c6c766fe3a1f4f5dd64d5c1acd258de2991d4 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -28,11 +28,11 @@ <div *ngIf="templateSelected$ | async" class="viewer-config-container d-flex align-items-end pe-none"> <!-- Viewer Selector Container--> - <viewer-selector - #viewerSelector + <atlas-layer-selector + #alSelector="atlasLayerSelector" class="pe-all" - (iav-outsideClick)="viewerSelector.selectorExpanded = false"> - </viewer-selector> + (iav-outsideClick)="alSelector.selectorExpanded = false"> + </atlas-layer-selector> <atlas-layer-container class="pe-none overflow-visible" @@ -42,10 +42,11 @@ </div> <!-- StatusCard container--> - <div class="viewer-status-container pe-all"> + <div *ngIf="viewerLoaded" class="viewer-status-container pe-none"> - <div class="muted-7" *ngIf="viewerLoaded"> + <div class="muted-7 mb-6 mr-1"> <ui-status-card + class="pe-all" [selectedTemplateName]="selectedTemplate && selectedTemplate.name" [nehubaViewer]="nehubaViewer"> </ui-status-card> diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts index 419490f6a88b87f78183f3abac756e190ef2cffc..a9e93036bfa1437ca13f0813a7ecb7116b0b40cd 100644 --- a/src/ui/ui.module.ts +++ b/src/ui/ui.module.ts @@ -90,7 +90,7 @@ import { APPEND_SCRIPT_TOKEN, appendScriptFactory } from "src/util/constants"; import { DOCUMENT } from "@angular/common"; import { AtlasDropdownSelector } from './atlasDropdown/atlasDropdown.component' import { AtlasLayerContainer } from "./atlasLayerWidget/alwContainer/alwContainer.component"; -import {ViewerSelectorComponent} from "src/ui/viewerSelector/viewerSelector.component"; +import {AtlasLayerSelector} from "src/ui/atlasLayerSelector/atlasLayerSelector.component"; @NgModule({ imports : [ @@ -127,7 +127,7 @@ import {ViewerSelectorComponent} from "src/ui/viewerSelector/viewerSelector.comp ConfigComponent, SigninBanner, AtlasDropdownSelector, - ViewerSelectorComponent, + AtlasLayerSelector, AtlasDropdownSelector, StatusCardComponent, diff --git a/src/ui/viewerSelector/viewerSelector.template.html b/src/ui/viewerSelector/viewerSelector.template.html deleted file mode 100644 index 44abc80ce190dea10e4d1d26ade2e4d6bf76f2fe..0000000000000000000000000000000000000000 --- a/src/ui/viewerSelector/viewerSelector.template.html +++ /dev/null @@ -1,96 +0,0 @@ -<div> - <div [hidden]="selectorExpanded" - class="muted-7 m-2 selectedLayerBorder cursorPointer selectedTemplateDefaultContainer" - (click)="selectorExpanded = true"> - <img [src]="selectedTemplatePreviewUrl" draggable="false"/> - </div> - - - <small *ngIf="selectorExpanded" class="position-relative"> - <mat-card class="scale-up-bl"> - <div class="position-absolute cursorPointer" style="top: 10px; right: 10px;" (click)="selectorExpanded = false"> - <i class="fas fa-times-circle"></i> - </div> - <mat-card-subtitle class="mb-1">Templates</mat-card-subtitle> - - - <div class="d-flex flex-wrap w-100"> - <div class="d-flex flex-column justify-content-start w-100 mb-1 mt-1 overflow-hidden cursorPointer singleLayerImageContainer" - *ngFor="let template of (selectedAtlas$ | async)?.templateSpaces; let i = index" - [matTooltip]="template.name" - matTooltipPosition="above" - (click)="selectTemplateWithName(template)"> - <img class="layer-image align-self-center" - [ngClass]="selectedTemplateSpaceIndex === i? 'selectedLayerBorder': null " - [src]="template.previewUrl" - draggable="false"/> <!--[ngStyle]="{opacity: hover? '1' : '0.2'}" (mouseenter)="hover = true" (mouseleave)="hover = false"--> - <small class="ml-1 mr-1 mt-2 text-truncate">{{template.name}}</small> - </div> - </div> - - <mat-card-subtitle class="mb-1 mt-2">Layers</mat-card-subtitle> - - - - - <div class="d-flex flex-wrap w-100"> - <div class="d-flex flex-column justify-content-start w-100 mb-1 mt-1 overflow-hidden cursorPointer singleLayerImageContainer" - *ngFor="let layer of notGroupedParcellations((selectedAtlas$ | async)?.parcellations); let i = index;" - [matTooltip]="layer.name" - matTooltipPosition="above" - (click)="templateIncludesLayer(layer, atlas?.templateSpaces[selectedTemplateSpaceIndex]) && selectParcellationWithName(layer)" - [ngStyle]="{opacity: templateIncludesLayer(layer, atlas?.templateSpaces[selectedTemplateSpaceIndex])? '1' : '0.2'}"> - <img class="layer-image align-self-center" - [ngClass]="selectedLayersIncludes(layer['@id'])? 'selectedLayerBorder' : null" - [src]="layer.previewUrl" - draggable="false"/> - <small class="ml-1 mr-1 mt-2 mb-2 text-truncate">{{layer.name}}</small> - </div> - - <div class="d-flex flex-column justify-content-start w-100 mb-1 mt-1 overflow-hidden cursorPointer singleLayerImageContainer" - [matMenuTriggerFor]="layerGroupMenu" - iav-stop="click" - *ngFor="let group of groupedLayers; let i = index;" - [matTooltip]="group[0]" - matTooltipPosition="above" - (click)="layerGroupMenuItems = group[1]" - [ngStyle]="{opacity: templateIncludesGroup(group, atlas?.templateSpaces[selectedTemplateSpaceIndex])? '1' : '0.2'}" - #groupedMenuTrigger="matMenuTrigger"> - <img class="layer-image align-self-center" - [ngClass]="selectedOneOfTheLayers(group[1])? 'selectedLayerBorder' : null" - [src]="group[1][0].previewUrl" - draggable="false"/> - <div class="d-flex flex-row-reverse align-items-end w-100 h-0"> - <i class="fas fa-folder folder-container fa-2x"></i> - </div> - <small class="ml-1 mr-1 mt-2 mb-2 text-truncate">{{group[0]}}</small> - </div> - - <mat-menu - #layerGroupMenu="matMenu" - class="layerGroupMenu" - hasBackdrop="false"> - - <ng-template matMenuContent> - <div iav-stop="click" - class="d-flex flex-column align-items-center" - (iav-outsideClick)="collapseExpandedGroup()"> - <div class="d-flex flex-column justify-content-center w-100 mb-1 mt-1 overflow-hidden cursorPointer singleLayerImageContainer" - *ngFor="let layer of layerGroupMenuItems; let i = index;" - [matTooltip]="layer.name" - matTooltipPosition="above" - (click)="templateIncludesLayer(layer, atlas?.templateSpaces[selectedTemplateSpaceIndex]) && selectParcellationWithName(layer)" - [ngStyle]="{opacity: templateIncludesLayer(layer, atlas?.templateSpaces[selectedTemplateSpaceIndex])? '1' : '0.2'}"> - <img class="layer-image align-self-center" - [ngClass]="selectedLayersIncludes(layer['@id'])? 'selectedLayerBorder' : null" - [src]="layer.previewUrl" - draggable="false"/> - <small class="iv-custom-comp text ml-1 mr-1 mt-2 mb-2 text-truncate">{{layer.name}}</small> - </div> - </div> - </ng-template> - </mat-menu> - </div> - </mat-card> - </small> -</div>