diff --git a/package.json b/package.json index 4a0407ded877b8aa0235470225e0c2d7ca3e9908..8faee773bfed71ce30d91632abd1f7be4f2eceb1 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "@ngrx/store": "^9.1.1", "@types/node": "12.12.39", "export-nehuba": "0.0.2", - "hbp-connectivity-component": "^0.1.0", + "hbp-connectivity-component": "^0.3.3", "zone.js": "^0.10.2" } } diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index 2274445cc2a7888affbc3f84f472b1c70eca8790..77eb5642a313267cfb3ed3584a255b8956d559b7 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -649,11 +649,6 @@ body::after flex-grow: 3!important; } -.flex-grow-5 -{ - flex-grow: 5!important; -} - .layerBrowserContainer { margin:-1em!important; @@ -751,3 +746,8 @@ kg-dataset-previewer > img width: 100%; } +mat-list.sm mat-list-item +{ + height:2rem!important; + font-size: 0.8rem!important; +} diff --git a/src/ui/connectivityBrowser/connectivityBrowser.component.ts b/src/ui/connectivityBrowser/connectivityBrowser.component.ts index b8794b5cac7177f29398a92871e4283424618fc4..1b8d45857f19bdfeed417f2390d160357a56ca3f 100644 --- a/src/ui/connectivityBrowser/connectivityBrowser.component.ts +++ b/src/ui/connectivityBrowser/connectivityBrowser.component.ts @@ -29,7 +29,6 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A private connectivityRegion$: Observable<any> private templateSelected$: Observable<any> private selectedParcellation$: Observable<any> - public selectedRegions$: Observable<any[]> private subscriptions: Subscription[] = [] public expandMenuIndex = -1 @@ -44,7 +43,8 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A maxHeight: '500px' } - @ViewChild('connectivityComponent', {read: ElementRef, static: true}) public connectivityComponentElement: ElementRef + @ViewChild('connectivityComponent', {read: ElementRef}) public connectivityComponentElement: ElementRef<HTMLHbpConnectivityMatrixRowElement> + @Output() public closeConnectivity: EventEmitter<boolean> = new EventEmitter() @Output() public connectedAreaCount: EventEmitter<number> = new EventEmitter() @@ -63,15 +63,10 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A this.connectivityRegion$ = this.store$.pipe( select('viewerState'), safeFilter('connectivityRegion'), - map(state => state.connectivityRegion) + map(state => state.connectivityRegion), + distinctUntilChanged() ) - this.selectedRegions$ = this.store$.pipe( - select('viewerState'), - filter(state => isDefined(state) && isDefined(state.regionsSelected)), - map(state => state.regionsSelected), - distinctUntilChanged(), - ) this.templateSelected$ = this.store$.pipe( select('viewerState'), select('templateSelected'), @@ -80,7 +75,7 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A } public ngAfterContentChecked(): void { - this.componentHeight = this.connectivityComponentElement.nativeElement.clientHeight + this.componentHeight = this.connectivityComponentElement?.nativeElement.clientHeight } public ngAfterViewInit(): void { @@ -100,6 +95,13 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A }), this.connectivityRegion$.subscribe(cr => { if (cr && cr.length) { + if (this.region !== cr && this.defaultColorMap) { + this.setDefaultMap() + this.store$.dispatch({ + type: SET_CONNECTIVITY_VISIBLE, + payload: false, + }) + } this.region = cr this.changeDetectionRef.detectChanges() } @@ -109,7 +111,7 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A this.closeConnectivityView() })) this.subscriptions.push( - fromEvent(this.connectivityComponentElement.nativeElement, 'connectivityDataReceived', { capture: true }) + fromEvent(this.connectivityComponentElement?.nativeElement, 'connectivityDataReceived', { capture: true }) .subscribe((e: CustomEvent) => { this.connectedAreas = e.detail this.connectedAreaCount.emit(this.connectedAreas.length) @@ -118,15 +120,25 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A } else { this.defaultColorMap = new Map(getWindow().interactiveViewer.viewerHandle.getLayersSegmentColourMap()) } }), - fromEvent(this.connectivityComponentElement.nativeElement, 'collapsedMenuChanged', { capture: true }) + fromEvent(this.connectivityComponentElement?.nativeElement, 'collapsedMenuChanged', { capture: true }) .subscribe((e: CustomEvent) => { this.expandMenuIndex = e.detail }), - fromEvent(this.connectivityComponentElement.nativeElement, 'datasetDataReceived', { capture: true }) + fromEvent(this.connectivityComponentElement?.nativeElement, 'datasetDataReceived', { capture: true }) .subscribe((e: CustomEvent) => { this.datasetList = e.detail this.selectedDataset = this.datasetList[0] }), + fromEvent(this.connectivityComponentElement?.nativeElement, 'customToolEvent', { capture: true }) + .subscribe((e: CustomEvent) => { + if (e.detail.name === 'export csv') { + // ToDo Fix in future to use component + const a = document.querySelector('hbp-connectivity-matrix-row') + a.downloadCSV() + } else if (e.detail.name === 'Apply colors to viewer') { + this.defaultColorMap && this.toggleConnectivityOnViewer( {checked: this.showConnectivityToggle? false : true}) + } + }), ) } @@ -151,6 +163,11 @@ export class ConnectivityBrowserComponent implements AfterViewInit, OnDestroy, A public ngOnDestroy(): void { this.subscriptions.forEach(s => s.unsubscribe()) + this.defaultColorMap && this.setDefaultMap() + this.store$.dispatch({ + type: SET_CONNECTIVITY_VISIBLE, + payload: false, + }) } navigateToRegion(region) { diff --git a/src/ui/connectivityBrowser/connectivityBrowser.template.html b/src/ui/connectivityBrowser/connectivityBrowser.template.html index 597ccb9a34aa1e8c36d7cb3c99aabf3b097c9794..9f626cf3207340f3a1622d5d36fa75fd43f30c08 100644 --- a/src/ui/connectivityBrowser/connectivityBrowser.template.html +++ b/src/ui/connectivityBrowser/connectivityBrowser.template.html @@ -11,10 +11,10 @@ show-toolbar="false" show-description="false" show-dataset-name="false" - custom-dataset-selector="true"> - <div slot="header" class="w-100 d-flex justify-content-between mt-3"> - <mat-slide-toggle (change)="this.defaultColorMap && toggleConnectivityOnViewer($event)">Show connectivity on viewer</mat-slide-toggle> - </div> + custom-dataset-selector="true" + tools_showlog="true" + [tools_custom]='[{"name": "Apply colors to viewer", "type": "checkbox", "checked": showConnectivityToggle}, {"name": "export csv", "type": "button"}]' + hide-export-view="true"> <div slot="dataset"> <div *ngIf="datasetList.length && selectedDataset" class=" flex-grow-0 flex-shrink-0 d-flex flex-row flex-nowrap"> diff --git a/src/ui/nehubaContainer/nehubaContainer.style.css b/src/ui/nehubaContainer/nehubaContainer.style.css index e4db541a0072a4b05c0af33d171b268d7eb48d23..ef857d221260faa750454650437f1aff23993a1d 100644 --- a/src/ui/nehubaContainer/nehubaContainer.style.css +++ b/src/ui/nehubaContainer/nehubaContainer.style.css @@ -181,6 +181,10 @@ div#scratch-pad text-align: right; } +.accordion-icon +{ + width:1.5rem; +} .tab-toggle-container { margin-top: 1.5rem; diff --git a/src/ui/nehubaContainer/nehubaContainer.template.html b/src/ui/nehubaContainer/nehubaContainer.template.html index aff06dee64595cc16c52c45addf3260b67e3714f..a888f42b0264f6e4e8301cee3e0f0fae6391d549 100644 --- a/src/ui/nehubaContainer/nehubaContainer.template.html +++ b/src/ui/nehubaContainer/nehubaContainer.template.html @@ -200,93 +200,6 @@ </ng-template> <!-- single region template --> -<ng-template #singleRegionTmpl let-region="region"> - <ng-template #regionDetailTmpl> - <div class="placeholder-region-detail side-nav-cover mat-elevation-z4"> - <span class="text-muted"> - Select a region by clicking on the viewer or search from above - </span> - </div> - </ng-template> - - <!-- region detail --> - <ng-container *ngIf="region; else regionDetailTmpl"> - <region-menu - [region]="region" - class="side-nav-cover mat-elevation-z4"> - </region-menu> - </ng-container> - - <!-- regional features --> - <mat-card class="mt-3 overflow-hidden mat-elevation-z4 side-nav-cover feature-card d-flex flex-column"> - <mat-card-subtitle class="flex-grow-0 flex-shrink-0 font-weight-bold"> - Regional features - </mat-card-subtitle> - - <mat-card-content class="flex-grow-1 flex-shrink-1 w-100 feature-card overflow-hidden"> - <ng-container *ngIf="region; else regionalFeaturesPlaceholderTmpl"> - <data-browser - [template]="templateSelected$ | async" - [parcellation]="selectedParcellation" - [regions]="[region]"> - </data-browser> - </ng-container> - - <!-- place holder regional features --> - <ng-template #regionalFeaturesPlaceholderTmpl> - - <span *ngIf="selectedParcellation"> - Regional features available in {{ selectedParcellation.name }} - </span> - - <div class="d-inline-flex w-100 modality-card-container"> - <mat-card class="flex-grow-0 flex-shrink-0 modality-card m-2" *ngFor="let dataM of dataBrowser.countedDataM"> - <mat-card-content> - <span> - {{ dataM.name }} - </span> - <small class="text-muted"> - ({{ dataM.occurance }}) - </small> - </mat-card-content> - </mat-card> - </div> - - <data-browser - class="invisible" - [template]="templateSelected$ | async" - [parcellation]="selectedParcellation" - #dataBrowser="dataBrowser"> - </data-browser> - </ng-template> - </mat-card-content> - - </mat-card> - - <mat-card *ngIf="selectedParcellation - && selectedParcellation.hasAdditionalViewMode - && selectedParcellation.hasAdditionalViewMode.includes('connectivity') - && selectedRegions?.length" - class="mt-3 side-nav-cover d-flex flex-column"> - <mat-card-subtitle class="flex-grow-0 flex-shrink-0"> - Connectivity - </mat-card-subtitle> - - <mat-card-content class="flex-grow-1 flex-shrink-1 w-100"> - <!-- add connectivity component --> - <ng-container *ngIf="region; else cnctvtyPlaceholderTmpl"> - <connectivity-browser class="pe-all flex-grow-5 flex-shrink-1"> - </connectivity-browser> - </ng-container> - - <ng-template #cnctvtyPlaceholderTmpl> - CONNECTIVITY PLACEHOLDER - </ng-template> - </mat-card-content> - </mat-card> - -</ng-template> - <div id="scratch-pad"> </div> @@ -315,6 +228,143 @@ </div> </ng-template> +<ng-template #singleRegionTmpl let-region="region"> + <ng-template #regionDetailTmpl> + <div class="placeholder-region-detail side-nav-cover mat-elevation-z4"> + <span class="text-muted"> + Select a region by clicking on the viewer or search from above + </span> + </div> + </ng-template> + + <!-- region detail --> + <ng-container *ngIf="region; else regionDetailTmpl"> + <region-menu + [showRegionInOtherTmpl]="false" + [region]="region" + class="side-nav-cover mat-elevation-z4"> + </region-menu> + </ng-container> + + + <mat-accordion *ngIf="region" + class="side-nav-cover mt-2" + iav-region + [region]="region" + #iavRegion="iavRegion"> + + <!-- expansion tmpl --> + <ng-template #ngMatAccordionTmpl + let-title="title" + let-desc="desc" + let-iconClass="iconClass" + let-iavNgIf="iavNgIf" + let-content="content"> + <mat-expansion-panel class="mt-1 mb-1" + hideToggle + *ngIf="iavNgIf"> + + <mat-expansion-panel-header> + + <!-- title --> + <mat-panel-title> + {{ title }} + </mat-panel-title> + + <!-- desc + icon --> + <mat-panel-description class="d-flex align-items-center justify-content-end"> + <span class="mr-3">{{ desc }}</span> + <span class="accordion-icon d-inline-flex justify-content-center"> + <i [class]="iconClass"></i> + </span> + </mat-panel-description> + + </mat-expansion-panel-header> + + <!-- content --> + <ng-template matExpansionPanelContent> + <ng-container *ngTemplateOutlet="content"> + </ng-container> + </ng-template> + </mat-expansion-panel> + </ng-template> + + <!-- Explore in other template --> + <ng-container *ngIf="iavRegion.regionInOtherTemplates$ | async as regionInOtherTemplates"> + + <ng-template #exploreInOtherTmpl> + <mat-list class="action-list sm cursor-default"> + <mat-list-item *ngFor="let sameRegion of regionInOtherTemplates" + (click)="iavRegion.changeView(sameRegion)" + [matTooltip]="sameRegion.template.name + (sameRegion.hemisphere ? (' - ' + sameRegion.hemisphere) : '')" + mat-ripple> + {{ sameRegion.template.name + (sameRegion.hemisphere ? (' - ' + sameRegion.hemisphere) : '') }} + </mat-list-item> + </mat-list> + </ng-template> + + <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: { + title: 'Explore in other templates', + desc: regionInOtherTemplates.length, + iconClass: 'fas fa-brain', + iavNgIf: regionInOtherTemplates.length, + content: exploreInOtherTmpl + }"> + + + </ng-container> + </ng-container> + + <!-- regional features--> + <ng-template #regionalFeaturesTmpl> + <data-browser [template]="templateSelected$ | async" + [parcellation]="selectedParcellation" + [regions]="[region]"> + </data-browser> + </ng-template> + + <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: { + title: 'Regional features', + desc: 123, + iconClass: 'fas fa-database', + iavNgIf: true, + content: regionalFeaturesTmpl + }"> + </ng-container> + + <!-- Connectivity --> + <ng-template #connectivityContentTmpl> + <mat-card-content class="flex-grow-1 flex-shrink-1 w-100"> + <connectivity-browser class="pe-all flex-shrink-1"> + </connectivity-browser> + </mat-card-content> + </ng-template> + + <ng-container *ngTemplateOutlet="ngMatAccordionTmpl; context: { + title: 'Connectivity', + desc: connectedCounterDir.value, + iconClass: 'fas fa-braille', + iavNgIf: selectedParcellation + && selectedParcellation.hasAdditionalViewMode + && selectedParcellation.hasAdditionalViewMode.includes('connectivity'), + content: connectivityContentTmpl + }"> + </ng-container> + + </mat-accordion> + <div class="w-0 h-0" + iav-counter + #connectedCounterDir="iavCounter"> + + <hbp-connectivity-matrix-row [region]="region.name" + (connectivityDataReceived)="connectedCounterDir.value = $event.detail.length" + class="invisible d-block h-0 w-0" + loadurl="https://connectivityquery-connectivity.apps-dev.hbp.eu/connectivity" + dataset-url="https://connectivityquery-connectivity.apps-dev.hbp.eu/studies"> + </hbp-connectivity-matrix-row> + </div> +</ng-template> + <!-- overlay templates --> <!-- perspective view tmpl --> diff --git a/src/ui/parcellationRegion/region.base.ts b/src/ui/parcellationRegion/region.base.ts index 5cd0adbee794dbf5f60e7e08e21bb3750df472a4..6f4eac0d406e244bb75342346d3a0ba272fb3d41 100644 --- a/src/ui/parcellationRegion/region.base.ts +++ b/src/ui/parcellationRegion/region.base.ts @@ -12,11 +12,10 @@ export class RegionBase { public rgbString: string public rgbDarkmode: boolean - private _region: any + @Input() + showRegionInOtherTmpl: boolean = true - get region(){ - return this._region - } + private _region: any @Input() set region(val) { @@ -28,6 +27,10 @@ export class RegionBase { const [h, s, l] = rgbToHsl(...this._region.rgb) this.rgbDarkmode = l < 0.4 } + + get region(){ + return this._region + } private region$: BehaviorSubject<any> = new BehaviorSubject(null) diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts b/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts index eda0f43eb94b303370a15b4f0bf4b87b35733544..0a89295f665f26c06964abf73159e57df948bcc1 100644 --- a/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts +++ b/src/ui/parcellationRegion/regionMenu/regionMenu.component.spec.ts @@ -119,6 +119,23 @@ describe('> regionMenu.component.ts', () => { expect(toggleBtn).toBeTruthy() }) + it('> if showRegionInOtherTmpl is set to false, toggle btn will not be shown', () => { + + const mockStore = TestBed.inject(MockStore) + mockStore.overrideSelector( + regionInOtherTemplateSelector, + nohemisphereHrms + ) + + const fixture = TestBed.createComponent(RegionMenuComponent) + fixture.componentInstance.region = mr1 + fixture.componentInstance.showRegionInOtherTmpl = false + fixture.detectChanges() + + const toggleBtn = fixture.debugElement.query( By.css(`[aria-label="${ARIA_LABELS.SHOW_IN_OTHER_REF_SPACE}"]`) ) + expect(toggleBtn).toBeFalsy() + }) + it('> even if toggleBtn exists, list should be hidden by default', () => { const mockStore = TestBed.inject(MockStore) diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.style.css b/src/ui/parcellationRegion/regionMenu/regionMenu.style.css index 79e6b14b0cb65fff2a7a375c3e7ac827c825f699..7cccfc149869e1d1b181e3b5413606eee87807d6 100644 --- a/src/ui/parcellationRegion/regionMenu/regionMenu.style.css +++ b/src/ui/parcellationRegion/regionMenu/regionMenu.style.css @@ -1,10 +1,3 @@ -mat-list.sm mat-list-item -{ - height:36px; - font-size: 90%; - cursor: default; -} - mat-icon { transform: scale(0.75); diff --git a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html index ba865d1c594d25fa17a255fdd80046f31c761f02..f5c9a6a49e74ab04b0f2238da39c7d45e72a9d82 100644 --- a/src/ui/parcellationRegion/regionMenu/regionMenu.template.html +++ b/src/ui/parcellationRegion/regionMenu/regionMenu.template.html @@ -57,7 +57,7 @@ <mat-divider></mat-divider> - <mat-list class="action-list sm"> + <mat-list class="action-list sm cursor-default"> <!-- connectivity --> <div *ngIf="hasConnectivity" iav-switch #connectivitySwitch="iavSwitch"> @@ -86,7 +86,9 @@ </div> <!-- change template --> - <ng-container *ngTemplateOutlet="regionInOtherTemplatesTmpl; context: { regionInOtherTemplates: regionInOtherTemplates$ | async }"> + <ng-container *ngIf="showRegionInOtherTmpl"> + <ng-container *ngTemplateOutlet="regionInOtherTemplatesTmpl; context: { regionInOtherTemplates: regionInOtherTemplates$ | async }"> + </ng-container> </ng-container> </mat-list> diff --git a/src/util/directives/counter.directive.ts b/src/util/directives/counter.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..d66f71877e4f13631a4ad6b4db194aa540106de2 --- /dev/null +++ b/src/util/directives/counter.directive.ts @@ -0,0 +1,10 @@ +import { Directive } from "@angular/core"; + +@Directive({ + selector: '[iav-counter]', + exportAs: 'iavCounter' +}) + +export class CounterDirective{ + public value: number = 0 +} \ No newline at end of file diff --git a/src/util/util.module.ts b/src/util/util.module.ts index 74bea90caf7c10bd18596c596344e03b4f94a490..4c8bf1ce5bc6b597e1bc9229c02f48df74c6d949 100644 --- a/src/util/util.module.ts +++ b/src/util/util.module.ts @@ -15,6 +15,7 @@ import { MediaQueryDirective } from './directives/mediaQuery.directive' import { LayoutModule } from "@angular/cdk/layout"; import { MapToPropertyPipe } from "./pipes/mapToProperty.pipe"; import {ClickOutsideDirective} from "src/util/directives/clickOutside.directive"; +import { CounterDirective } from "./directives/counter.directive"; @NgModule({ imports:[ @@ -34,7 +35,8 @@ import {ClickOutsideDirective} from "src/util/directives/clickOutside.directive" SwitchDirective, MediaQueryDirective, MapToPropertyPipe, - ClickOutsideDirective + ClickOutsideDirective, + CounterDirective ], exports: [ FilterNullPipe, @@ -50,7 +52,8 @@ import {ClickOutsideDirective} from "src/util/directives/clickOutside.directive" SwitchDirective, MediaQueryDirective, MapToPropertyPipe, - ClickOutsideDirective + ClickOutsideDirective, + CounterDirective ] })