diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index c4a3b31eed146a5d2a5421bcdae087bf7ea52464..50b135a328207030803278026f2ea2f09fce1278 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -126,6 +126,17 @@ </button> + <mat-card *ngIf="!sideNavDrawer.opened" + (click)="sideNavDrawer.open()" + mat-ripple + class="pe-all mt-4 muted translate-x-4-n"> + <mat-card-content> + <viewer-state-mini> + </viewer-state-mini> + </mat-card-content> + <mat-card-footer></mat-card-footer> + </mat-card> + <!-- TODO clean up menu icon --> </div> </mat-drawer-container> diff --git a/src/res/css/extra_styles.css b/src/res/css/extra_styles.css index 69953526d87cad5723faeca41d3768a72fa4588e..29e8a1512e127ab5fe69f6684cc6f98adb7e1a2d 100644 --- a/src/res/css/extra_styles.css +++ b/src/res/css/extra_styles.css @@ -553,6 +553,11 @@ cdk-virtual-scroll-viewport > .cdk-virtual-scroll-content-wrapper transform: translateX(3em); } +.translate-x-4-n +{ + transform: translateX(-2em); +} + .translate-x-6-n { transform: translateX(-3em); diff --git a/src/ui/databrowserModule/databrowser/databrowser.component.ts b/src/ui/databrowserModule/databrowser/databrowser.component.ts index 1971b7aeba38d2c5096d3b04865eb5d7737349b6..368a12762c5e888cf0b0752447610ccdd96c601a 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.component.ts +++ b/src/ui/databrowserModule/databrowser/databrowser.component.ts @@ -3,7 +3,6 @@ import { DataEntry } from "src/services/stateStore.service"; import { Subscription, merge, Observable } from "rxjs"; import { DatabrowserService, CountedDataModality } from "../databrowser.service"; import { ModalityPicker } from "../modalityPicker/modalityPicker.component"; -import { MatDialog, MatExpansionPanel } from "@angular/material"; import { KgSingleDatasetService } from "../kgSingleDatasetService.service"; import { scan, shareReplay } from "rxjs/operators"; import { ViewerPreviewFile } from "src/services/state/dataStore.store"; @@ -22,8 +21,6 @@ const scanFn: (acc: any[], curr: any) => any[] = (acc, curr) => [curr, ...acc] export class DataBrowser implements OnChanges, OnDestroy,OnInit{ - @ViewChild('selectedRegionExpansionPanel') selectedRegionExpansionPanel: MatExpansionPanel - @Input() public regions: any[] = [] @@ -38,12 +35,6 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ public dataentries: DataEntry[] = [] - /** - * TODO deprecated - */ - public currentPage: number = 0 - public hitsPerPage: number = 5 - public fetchingFlag: boolean = false public fetchError: boolean = false /** @@ -75,7 +66,6 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ constructor( private dbService: DatabrowserService, private cdr:ChangeDetectorRef, - private dialog: MatDialog, private singleDatasetSservice: KgSingleDatasetService ){ this.favDataentries$ = this.dbService.favedDataentries$ @@ -87,8 +77,6 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ ngOnChanges(changes){ - if (this.regions.length === 0) this.selectedRegionExpansionPanel && (this.selectedRegionExpansionPanel.expanded = false) - this.regions = this.regions.map(r => { /** * TODO to be replaced with properly region UUIDs from KG @@ -127,6 +115,7 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ .finally(() => { this.fetchingFlag = false this.dataentriesUpdated.emit(this.dataentries) + this.resetFilters() this.cdr.markForCheck() }) @@ -142,7 +131,6 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ // this.dbService.selectedRegions$, this.dbService.fetchDataObservable$ ).subscribe(() => { - this.resetCurrentPage() /** * Only reset modality picker * resetting all creates infinite loop @@ -171,14 +159,12 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ } }) this.visibleCountedDataM = [] - this.resetCurrentPage() } handleModalityFilterEvent(modalityFilter:CountedDataModality[]){ this.countedDataM = modalityFilter this.visibleCountedDataM = modalityFilter.filter(dm => dm.visible) this.cdr.markForCheck() - this.resetCurrentPage() } retryFetchData(event: MouseEvent){ @@ -206,14 +192,6 @@ export class DataBrowser implements OnChanges, OnDestroy,OnInit{ this.filePreviewName = datasetName } - /** - * when filter changes, it is necessary to set current page to 0, - * or one may overflow and see no dataset - */ - resetCurrentPage(){ - this.currentPage = 0 - } - resetFilters(event?:MouseEvent){ this.clearAll() } diff --git a/src/ui/databrowserModule/databrowser/databrowser.template.html b/src/ui/databrowserModule/databrowser/databrowser.template.html index 6b3eb1e38bba9056c2370fdb5fa0cb38eb8277f3..e8e62e687e0d75f710bfde3a40c89f3d090ffeff 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.template.html +++ b/src/ui/databrowserModule/databrowser/databrowser.template.html @@ -117,30 +117,6 @@ <ng-template #modalitySelector> <mat-accordion class="flex-grow-0 flex-shrink-0"> - <!-- currently selected regions --> - <mat-expansion-panel - *ngIf="regions && regions.length > 1" - #selectedRegionExpansionPanel - hideToggle> - <mat-expansion-panel-header> - <mat-panel-title> - Regions selected - </mat-panel-title> - - <mat-panel-description class="d-flex flex-row justify-content-end align-items-center"> - <small class="text-muted mr-2"> - {{ regions && regions.length }} - </small> - <i class="fas fa-brain"></i> - </mat-panel-description> - </mat-expansion-panel-header> - - <div class="h-10em"> - <currently-selected-regions class="h-100 d-block"> - </currently-selected-regions> - </div> - </mat-expansion-panel> - <!-- Filters --> <mat-expansion-panel hideToggle> diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts index 1e0a4501cebadc4a5e2d452e6ac0885cf7983bc7..6bcbf5830c9b45a0fb409a14b64ed05654930e58 100644 --- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts +++ b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts @@ -23,7 +23,6 @@ const scanFn : (acc: LayerLabelIndex[], curr: LayerLabelIndex) => LayerLabelInde const { layer } = curr const { name } = layer const foundIndex = acc.findIndex(({ layer }) => layer.name === name) - debugger if (foundIndex < 0) return acc.concat(curr) else return acc.map((item, idx) => idx === foundIndex ? { diff --git a/src/ui/searchSideNav/searchSideNav.component.ts b/src/ui/searchSideNav/searchSideNav.component.ts index d1629dbd82eafe0b2a3100927f9a4b9b1a4cb0bc..61a5b169e355295b9941a8802a39a10fdf1f73a5 100644 --- a/src/ui/searchSideNav/searchSideNav.component.ts +++ b/src/ui/searchSideNav/searchSideNav.component.ts @@ -5,6 +5,7 @@ import { LayerBrowser } from "../layerbrowser/layerbrowser.component"; import { Observable, Subscription } from "rxjs"; import { Store, select } from "@ngrx/store"; import { map, startWith, scan, filter, mapTo } from "rxjs/operators"; +import { VIEWERSTATE_ACTION_TYPES } from "../viewerStateController/viewerState.base"; @Component({ selector: 'search-side-nav', @@ -28,9 +29,9 @@ export class SearchSideNav implements OnInit, OnDestroy { constructor( private dialog: MatDialog, - store$: Store<any> + private store$: Store<any> ){ - this.autoOpenSideNav$ = store$.pipe( + this.autoOpenSideNav$ = this.store$.pipe( select('viewerState'), select('regionsSelected'), map(arr => arr.length), @@ -74,4 +75,11 @@ export class SearchSideNav implements OnInit, OnDestroy { disableClose: true }) } + + removeRegion(region: any){ + this.store$.dispatch({ + type: VIEWERSTATE_ACTION_TYPES.SINGLE_CLICK_ON_REGIONHIERARCHY, + payload: { region } + }) + } } \ No newline at end of file diff --git a/src/ui/searchSideNav/searchSideNav.template.html b/src/ui/searchSideNav/searchSideNav.template.html index 7a24467e0032549f794d24b2c760dff7bce8aec5..5d2e5d647f94b712291860d4fe906c68c81acd96 100644 --- a/src/ui/searchSideNav/searchSideNav.template.html +++ b/src/ui/searchSideNav/searchSideNav.template.html @@ -30,20 +30,64 @@ [parcellation]="viewerStateController.parcellationSelected$ | async" [regions]="viewerStateController.regionsSelected$ | async" (dataentriesUpdated)="availableDatasets = $event.length"> - <!-- content prepend --> <ng-container *ngIf="viewerStateController.regionsSelected$ | async as regionsSelected" card-content="prepend"> - <mat-card-content> - <div class="d-flex flex-row align-items-center flex-nowrap"> - <i *ngIf="regionsSelected.length === 1" - class="fas fa-brain font-2x mr-2"> - </i> + <mat-card-content [ngClass]="{'h-10em': regionsSelected.length > 1}"> - <span class="font-weight-bold"> - {{ regionsSelected.length === 0 ? 'In the current view' : regionsSelected.length === 1 ? regionsSelected[0].name : 'Multi-region selection' }} - </span> - </div> + <!-- show when no region is selected --> + <ng-template [ngIf]="regionsSelected.length === 0" [ngIfElse]="showBrainRegions"> + <div class="d-flex flex-row align-items-center flex-nowrap"> + <span class="font-weight-bold"> + In the current view + </span> + </div> + </ng-template> + + <!-- show when regions are selected --> + <ng-template #showBrainRegions> + + <!-- single region --> + <ng-template [ngIf]="regionsSelected.length === 1" [ngIfElse]="multiRegionTemplate"> + + <!-- selected brain region --> + <div class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> + <i class="fas fa-brain font-2x mr-2"></i> + + <span class="font-weight-bold"> + {{ regionsSelected[0].name }} + </span> + + <button (click)="removeRegion(regionsSelected[0])" mat-icon-button> + <i class="fas fa-trash"></i> + </button> + </div> + </ng-template> + + <!-- multi region --> + <ng-template #multiRegionTemplate> + <cdk-virtual-scroll-viewport class="h-100" autosize> + <div *cdkVirtualFor="let region of regionsSelected; let index = index"> + <!-- divider if index !== 0 --> + <mat-divider *ngIf="index !== 0"></mat-divider> + + <!-- selected brain region --> + <div class="pt-2 pb-2 d-flex flex-row align-items-center flex-nowrap"> + <i class="fas fa-brain font-2x mr-2"></i> + + <span class="font-weight-bold"> + {{ region.name }} + </span> + + <button (click)="removeRegion(region)" mat-icon-button> + <i class="fas fa-trash"></i> + </button> + </div> + </div> + </cdk-virtual-scroll-viewport> + </ng-template> + + </ng-template> </mat-card-content> </ng-container> diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts index cfe46add16f17edf5e3d3e73da4d3270758e3768..817b0a2eaaf2686fa325341f7024ad75e08d4e7d 100644 --- a/src/ui/ui.module.ts +++ b/src/ui/ui.module.ts @@ -51,7 +51,10 @@ import { ScrollingModule } from "@angular/cdk/scrolling" import { HttpClientModule } from "@angular/common/http"; import { GetFilenamePipe } from "src/util/pipes/getFilename.pipe"; import { GetFileExtension } from "src/util/pipes/getFileExt.pipe"; -import { ViewerStateController } from "./viewerStateController/viewerState.component"; + +import { ViewerStateController } from 'src/ui/viewerStateController/viewerStateCFull/viewerState.component' +import { ViewerStateMini } from 'src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component' + import { BinSavedRegionsSelectionPipe, SavedRegionsSelectionBtnDisabledPipe } from "./viewerStateController/viewerState.pipes"; import { PluginBtnFabColorPipe } from "src/util/pipes/pluginBtnFabColor.pipe"; import { KgSearchBtnColorPipe } from "src/util/pipes/kgSearchBtnColor.pipe"; @@ -102,6 +105,7 @@ import { SearchSideNav } from "./searchSideNav/searchSideNav.component"; SinglePanel, CurrentLayout, ViewerStateController, + ViewerStateMini, MaximmisePanelButton, SearchSideNav, @@ -165,6 +169,7 @@ import { SearchSideNav } from "./searchSideNav/searchSideNav.component"; StatusCardComponent, ElementOutClickDirective, SearchSideNav, + ViewerStateMini, ] }) diff --git a/src/ui/viewerStateController/currentlySelectedRegions/currentlySelectedRegions.component.ts b/src/ui/viewerStateController/currentlySelectedRegions/currentlySelectedRegions.component.ts index ca1231d800e48dac2ddce1f50d9ebee5ddaa5390..812b734b2ad558a0c51354321f304bba0773ea02 100644 --- a/src/ui/viewerStateController/currentlySelectedRegions/currentlySelectedRegions.component.ts +++ b/src/ui/viewerStateController/currentlySelectedRegions/currentlySelectedRegions.component.ts @@ -3,7 +3,7 @@ import { Store, select } from "@ngrx/store"; import { Observable } from "rxjs"; import { distinctUntilChanged, startWith } from "rxjs/operators"; import { DESELECT_REGIONS } from "src/services/state/viewerState.store"; -import { VIEWERSTATE_ACTION_TYPES } from "../viewerState.component"; +import { VIEWERSTATE_ACTION_TYPES } from "../viewerState.base"; @Component({ selector: 'currently-selected-regions', diff --git a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts b/src/ui/viewerStateController/regionSearch/regionSearch.component.ts index 40ae397d474e0f0cce1edc3f24cbe3da7b721e50..35b70d8177cb2d451e32a8c193b118df78afdc6f 100644 --- a/src/ui/viewerStateController/regionSearch/regionSearch.component.ts +++ b/src/ui/viewerStateController/regionSearch/regionSearch.component.ts @@ -6,7 +6,7 @@ import { getMultiNgIdsRegionsLabelIndexMap, generateLabelIndexId } from "src/ser import { FormControl } from "@angular/forms"; import { MatAutocompleteSelectedEvent, MatDialog } from "@angular/material"; import { ADD_TO_REGIONS_SELECTION_WITH_IDS, SELECT_REGIONS } from "src/services/state/viewerState.store"; -import { VIEWERSTATE_ACTION_TYPES } from "../viewerState.component"; +import { VIEWERSTATE_ACTION_TYPES } from "../viewerState.base"; const filterRegionBasedOnText = searchTerm => region => region.name.toLowerCase().includes(searchTerm.toLowerCase()) diff --git a/src/ui/viewerStateController/viewerState.component.ts b/src/ui/viewerStateController/viewerState.base.ts similarity index 95% rename from src/ui/viewerStateController/viewerState.component.ts rename to src/ui/viewerStateController/viewerState.base.ts index b83181f7a969698aa84f3d4d8a59d5f78d503707..4eacc8515f9121bdc397e85c0af42a076dc9f047 100644 --- a/src/ui/viewerStateController/viewerState.component.ts +++ b/src/ui/viewerStateController/viewerState.base.ts @@ -1,4 +1,4 @@ -import { Component, ViewChild, TemplateRef, OnInit } from "@angular/core"; +import { ViewChild, TemplateRef, OnInit } from "@angular/core"; import { Store, select } from "@ngrx/store"; import { Observable, Subscription } from "rxjs"; import { distinctUntilChanged, shareReplay, filter } from "rxjs/operators"; @@ -8,19 +8,12 @@ import { MatSelectChange, MatBottomSheet, MatBottomSheetRef } from "@angular/mat import { DialogService } from "src/services/dialogService.service"; import { RegionSelection } from "src/services/state/userConfigState.store"; + const compareWith = (o, n) => !o || !n - ? false - : o.name === n.name - -@Component({ - selector: 'viewer-state-controller', - templateUrl: './viewerState.template.html', - styleUrls: [ - './viewerState.style.css' - ] -}) - -export class ViewerStateController implements OnInit{ +? false +: o.name === n.name + +export class ViewerStateBase implements OnInit{ @ViewChild('savedRegionBottomSheetTemplate', {read:TemplateRef}) savedRegionBottomSheetTemplate: TemplateRef<any> diff --git a/src/ui/viewerStateController/viewerState.useEffect.ts b/src/ui/viewerStateController/viewerState.useEffect.ts index 70ab954ca1b0a817d6b6e3402dfe45dd7f211bff..9b1a4b2ce7d2cafe99c6d1c7428c194f79cd0091 100644 --- a/src/ui/viewerStateController/viewerState.useEffect.ts +++ b/src/ui/viewerStateController/viewerState.useEffect.ts @@ -4,7 +4,7 @@ import { Actions, ofType, Effect } from "@ngrx/effects"; import { Store, select, Action } from "@ngrx/store"; import { ToastService } from "src/services/toastService.service"; import { shareReplay, distinctUntilChanged, map, withLatestFrom, filter } from "rxjs/operators"; -import { VIEWERSTATE_ACTION_TYPES } from "./viewerState.component"; +import { VIEWERSTATE_ACTION_TYPES } from "./viewerState.base"; import { CHANGE_NAVIGATION, SELECT_REGIONS, NEWVIEWER, GENERAL_ACTION_TYPES, SELECT_PARCELLATION, isDefined } from "src/services/stateStore.service"; import { regionFlattener } from "src/util/regionFlattener"; diff --git a/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts b/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..b97ae9e5cf8e52b1dc111e0821303314b73792bf --- /dev/null +++ b/src/ui/viewerStateController/viewerStateCFull/viewerState.component.ts @@ -0,0 +1,32 @@ +import { Component } from "@angular/core"; +import { Store } from "@ngrx/store"; +import { ToastService } from "src/services/toastService.service"; +import { MatBottomSheet } from "@angular/material"; +import { DialogService } from "src/services/dialogService.service"; + +import { ViewerStateBase } from '../viewerState.base' + +const compareWith = (o, n) => !o || !n + ? false + : o.name === n.name + +@Component({ + selector: 'viewer-state-controller', + templateUrl: './viewerState.template.html', + styleUrls: [ + './viewerState.style.css' + ] +}) + +export class ViewerStateController extends ViewerStateBase{ + + constructor( + store$: Store<any>, + toastService: ToastService, + dialogService: DialogService, + bottomSheet: MatBottomSheet + ){ + super(store$,toastService,dialogService,bottomSheet) + } + +} diff --git a/src/ui/viewerStateController/viewerState.style.css b/src/ui/viewerStateController/viewerStateCFull/viewerState.style.css similarity index 100% rename from src/ui/viewerStateController/viewerState.style.css rename to src/ui/viewerStateController/viewerStateCFull/viewerState.style.css diff --git a/src/ui/viewerStateController/viewerState.template.html b/src/ui/viewerStateController/viewerStateCFull/viewerState.template.html similarity index 100% rename from src/ui/viewerStateController/viewerState.template.html rename to src/ui/viewerStateController/viewerStateCFull/viewerState.template.html diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..11e8f0120be7a892533b184d565ac81b09460dfb --- /dev/null +++ b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.component.ts @@ -0,0 +1,28 @@ +import { Component } from "@angular/core"; +import { Store } from "@ngrx/store"; +import { ToastService } from "src/services/toastService.service"; +import { MatBottomSheet } from "@angular/material"; +import { DialogService } from "src/services/dialogService.service"; + +import { ViewerStateBase } from '../viewerState.base' + +@Component({ + selector: 'viewer-state-mini', + templateUrl: './viewerStateMini.template.html', + styleUrls: [ + './viewerStateMini.style.css' + ] +}) + +export class ViewerStateMini extends ViewerStateBase{ + + constructor( + store$: Store<any>, + toastService: ToastService, + dialogService: DialogService, + bottomSheet: MatBottomSheet + ){ + super(store$,toastService,dialogService,bottomSheet) + } + +} diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.style.css b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.style.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html new file mode 100644 index 0000000000000000000000000000000000000000..8dda9dbdcc13e04538bb93fb6ca640262e22d96c --- /dev/null +++ b/src/ui/viewerStateController/viewerStateCMini/viewerStateMini.template.html @@ -0,0 +1,7 @@ +<span *ngIf="templateSelected$ | async as templateSelected"> + {{ templateSelected.name }} +</span> +<br> +<span *ngIf="parcellationSelected$ | async as parcellationSelected"> + {{ parcellationSelected.name }} +</span> \ No newline at end of file