From bec56e6f298f398c779f5d2d982aa0f8026ab87a Mon Sep 17 00:00:00 2001 From: Xiao Gui <xgui3783@gmail.com> Date: Tue, 28 Jan 2020 15:34:18 +0100 Subject: [PATCH] feat: use web component for preview of data --- common/util.js | 2 +- src/res/ext/MNI152.json | 1 + src/res/ext/bigbrain.json | 1 + src/res/ext/colin.json | 1 + src/services/state/dataStore.store.ts | 4 ++ .../databrowserModule/databrowser.module.ts | 5 ++ .../databrowser/databrowser.component.ts | 2 +- .../kgSingleDatasetService.service.ts | 1 + .../datasetPreviewList.component.ts | 57 +++++++++++++++++++ .../datasetPreviewList.template.html | 53 +++++++++++++++++ .../detailedView/singleDataset.template.html | 38 ++----------- .../singleDatasetListView.template.html | 38 ++----------- .../singleDataset/singleDataset.base.ts | 24 +------- ...reviewFileDisabledByReferenceSpace.pipe.ts | 20 +++++++ .../searchSideNav/searchSideNav.component.ts | 4 +- 15 files changed, 161 insertions(+), 90 deletions(-) create mode 100644 src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts create mode 100644 src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html create mode 100644 src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts diff --git a/common/util.js b/common/util.js index 871481b91..330e538fe 100644 --- a/common/util.js +++ b/common/util.js @@ -2,7 +2,7 @@ exports.getIdFromFullId = fullId => { if (!fullId) return null if (typeof fullId === 'string') { - const re = /\/([a-z]{1,}\/[a-z]{1,}\/[a-z]{1,}\/v[0-9.]{1,}\/[0-9a-z-]{1,}$)/.exec(fullId) + const re = /([a-z]{1,}\/[a-z]{1,}\/[a-z]{1,}\/v[0-9.]{1,}\/[0-9a-z-]{1,}$)/.exec(fullId) if (re) return re[1] return null } else { diff --git a/src/res/ext/MNI152.json b/src/res/ext/MNI152.json index cc88e19c2..679909551 100644 --- a/src/res/ext/MNI152.json +++ b/src/res/ext/MNI152.json @@ -1,5 +1,6 @@ { "name": "MNI 152 ICBM 2009c Nonlinear Asymmetric", + "fullId": "minds/core/referencespace/v1.0.0/dafcffc5-4826-4bf1-8ff6-46b8a31ff8e2", "type": "template", "species": "Human", "useTheme": "dark", diff --git a/src/res/ext/bigbrain.json b/src/res/ext/bigbrain.json index abff253c1..7ac96b805 100644 --- a/src/res/ext/bigbrain.json +++ b/src/res/ext/bigbrain.json @@ -1,5 +1,6 @@ { "name": "Big Brain (Histology)", + "fullId": "minds/core/referencespace/v1.0.0/a1655b99-82f1-420f-a3c2-fe80fd4c8588", "type": "template", "species": "Human", "useTheme": "light", diff --git a/src/res/ext/colin.json b/src/res/ext/colin.json index c9a3d1963..d80629a3b 100644 --- a/src/res/ext/colin.json +++ b/src/res/ext/colin.json @@ -1,5 +1,6 @@ { "name": "MNI Colin 27", + "fullId": "minds/core/referencespace/v1.0.0/7f39f7be-445b-47c0-9791-e971c0b6d992", "type": "template", "species": "Human", "useTheme": "dark", diff --git a/src/services/state/dataStore.store.ts b/src/services/state/dataStore.store.ts index 2944d975e..0a328aec4 100644 --- a/src/services/state/dataStore.store.ts +++ b/src/services/state/dataStore.store.ts @@ -187,6 +187,10 @@ export interface ViewerPreviewFile { name: string filename: string mimetype: string + referenceSpaces: { + name: string, + fullId: string + }[] url?: string data?: any position?: any diff --git a/src/ui/databrowserModule/databrowser.module.ts b/src/ui/databrowserModule/databrowser.module.ts index e40a2a24c..0bd7944d6 100644 --- a/src/ui/databrowserModule/databrowser.module.ts +++ b/src/ui/databrowserModule/databrowser.module.ts @@ -26,6 +26,8 @@ import { SingleDatasetListView } from "./singleDataset/listView/singleDatasetLis import { AppendFilerModalityPipe } from "./util/appendFilterModality.pipe"; import { GetKgSchemaIdFromFullIdPipe } from "./util/getKgSchemaIdFromFullId.pipe"; import { ResetCounterModalityPipe } from "./util/resetCounterModality.pipe"; +import { PreviewFileVisibleInSelectedReferenceTemplatePipe } from "./util/previewFileDisabledByReferenceSpace.pipe"; +import { DatasetPreviewList, UnavailableTooltip } from "./singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component"; @NgModule({ imports: [ @@ -43,6 +45,7 @@ import { ResetCounterModalityPipe } from "./util/resetCounterModality.pipe"; ModalityPicker, SingleDatasetView, SingleDatasetListView, + DatasetPreviewList, /** * pipes @@ -60,6 +63,8 @@ import { ResetCounterModalityPipe } from "./util/resetCounterModality.pipe"; PreviewFileTypePipe, AppendFilerModalityPipe, ResetCounterModalityPipe, + PreviewFileVisibleInSelectedReferenceTemplatePipe, + UnavailableTooltip, ], exports: [ DataBrowser, diff --git a/src/ui/databrowserModule/databrowser/databrowser.component.ts b/src/ui/databrowserModule/databrowser/databrowser.component.ts index 3ae4430da..e8705a558 100644 --- a/src/ui/databrowserModule/databrowser/databrowser.component.ts +++ b/src/ui/databrowserModule/databrowser/databrowser.component.ts @@ -67,7 +67,7 @@ export class DataBrowser implements OnChanges, OnDestroy, OnInit { this.favDataentries$ = this.dbService.favedDataentries$ const structuredData = window.document.querySelector('script[type="application/ld+json"]') - if (structuredData) console.log(JSON.parse(structuredData.textContent)) + } public ngOnChanges() { diff --git a/src/ui/databrowserModule/kgSingleDatasetService.service.ts b/src/ui/databrowserModule/kgSingleDatasetService.service.ts index 931f3efeb..9544ef15f 100644 --- a/src/ui/databrowserModule/kgSingleDatasetService.service.ts +++ b/src/ui/databrowserModule/kgSingleDatasetService.service.ts @@ -39,6 +39,7 @@ export class KgSingleDatasetService implements OnDestroy { } } + // TODO deprecate, in favour of web component public datasetHasPreview({ name }: { name: string } = { name: null }) { if (!name) { throw new Error('kgSingleDatasetService#datasetHashPreview name must be defined') } const _url = new URL(`datasets/hasPreview`, this.constantService.backendUrl ) diff --git a/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts b/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts new file mode 100644 index 000000000..a12aba9be --- /dev/null +++ b/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.component.ts @@ -0,0 +1,57 @@ +import { Component, Input, ChangeDetectorRef, Output, EventEmitter, Pipe, PipeTransform } from "@angular/core"; +import { ViewerPreviewFile } from "src/services/state/dataStore.store"; +import { Store, select } from "@ngrx/store"; +import { IavRootStoreInterface } from "src/services/stateStore.service"; +import { Observable } from "rxjs"; + +@Component({ + selector: 'dataset-preview-list', + templateUrl: './datasetPreviewList.template.html' +}) + +export class DatasetPreviewList{ + + @Output() public previewingFile: EventEmitter<ViewerPreviewFile> = new EventEmitter() + + public datasetPreviewList: any[] = [] + public loadingDatasetPreviewList: boolean = false + public selectedTemplateSpace$: Observable<any> + + constructor( + private cdr: ChangeDetectorRef, + store$: Store<IavRootStoreInterface> + ){ + this.selectedTemplateSpace$ = store$.pipe( + select('viewerState'), + select('templateSelected') + ) + } + + @Input() + kgId: string + + handleKgDsPrvUpdated(event: CustomEvent){ + const { detail } = event + const { datasetFiles, loadingFlag } = detail + + this.loadingDatasetPreviewList = loadingFlag + this.datasetPreviewList = datasetFiles + + this.cdr.markForCheck() + } + public handlePreviewFile(file: ViewerPreviewFile) { + + this.previewingFile.emit(file) + } +} + +@Pipe({ + name: 'unavailableTooltip' +}) + +export class UnavailableTooltip implements PipeTransform{ + public transform(file:ViewerPreviewFile):string{ + if (file.referenceSpaces.length === 0) return `This preview is not available to be viewed in any reference space.` + else return `This preview is available in the following reference space: ${file.referenceSpaces.map(({ name }) => name).join(', ')}` + } +} \ No newline at end of file diff --git a/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html b/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html new file mode 100644 index 000000000..a92572cd7 --- /dev/null +++ b/src/ui/databrowserModule/singleDataset/datasetPreviews/datasetPreviewsList/datasetPreviewList.template.html @@ -0,0 +1,53 @@ +<kg-dataset-list + (kgDsPrvUpdated)="handleKgDsPrvUpdated($event)" + class="d-none" + [kgId]="kgId"> + +</kg-dataset-list> + +<div *ngIf="loadingDatasetPreviewList; else datasetList" class="spinnerAnimationCircle"></div> + +<ng-template #datasetList> + + <mat-nav-list> + <h3 mat-subheader>Available Preview Files</h3> + + <ng-container *ngFor="let file of datasetPreviewList"> + + <!-- preview available --> + <ng-template [ngIf]="(selectedTemplateSpace$ | async | previewFileVisibleInSelectedReferenceTemplatePipe : file)" [ngIfElse]="notAvailalbePreview" > + <mat-list-item (click)=" handlePreviewFile(file)"> + <mat-icon + [fontSet]="(file | previewFileIconPipe).fontSet" + [fontIcon]="(file | previewFileIconPipe).fontIcon" + matListIcon> + </mat-icon> + <h4 mat-line>{{ file.name }}</h4> + <p mat-line>mimetype: {{ file.mimetype }}</p> + </mat-list-item> + </ng-template> + + <!-- preview not available in this reference space --> + <ng-template #notAvailalbePreview> + <mat-list-item + [matTooltip]="file | unavailableTooltip" + [matTooltipDisabled]="selectedTemplateSpace$ | async | previewFileVisibleInSelectedReferenceTemplatePipe : file" + [ngClass]="{'text-muted': !(selectedTemplateSpace$ | async | previewFileVisibleInSelectedReferenceTemplatePipe : file)}"> + <mat-icon + [fontSet]="(file | previewFileIconPipe).fontSet" + [fontIcon]="(file | previewFileIconPipe).fontIcon" + matListIcon> + </mat-icon> + <h4 mat-line>{{ file.name }}</h4> + <p mat-line>mimetype: {{ file.mimetype }}</p> + </mat-list-item> + </ng-template> + + </ng-container> + <small *ngIf="datasetPreviewList.length === 0" + class="text-muted"> + There are no preview files in this parcellation/template space. + </small> + + </mat-nav-list> +</ng-template> diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html index 5a9d75185..5871fdd9f 100644 --- a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html +++ b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.template.html @@ -140,37 +140,9 @@ <mat-card-footer></mat-card-footer> <ng-template #previewFilesListTemplate> - <kg-dataset-list - (kgDsPrvUpdated)="handleKgDsPrvUpdated($event)" - class="d-none" - [kgId]="kgId"> - - </kg-dataset-list> - - <div *ngIf="loadingDatasetPreviewList; else datasetList" class="spinnerAnimationCircle"></div> - - <ng-template #datasetList> - - <mat-nav-list> - <h3 mat-subheader>Available Preview Files</h3> - <mat-list-item - *ngFor="let file of datasetPreviewList" - (click)="handlePreviewFile(file)"> - <mat-icon - [fontSet]="(file | previewFileIconPipe).fontSet" - [fontIcon]="(file | previewFileIconPipe).fontIcon" - matListIcon> - </mat-icon> - <h4 mat-line>{{ file.name }}</h4> - <p mat-line>mimetype: {{ file.mimetype }}</p> - </mat-list-item> - - <small *ngIf="datasetPreviewList.length === 0" - class="text-muted"> - There are no preview files in this parcellation/template space. - </small> - - </mat-nav-list> - </ng-template> - + <dataset-preview-list + [kgId]="kgId" + (previewingFile)="handlePreviewFile($event)"> + + </dataset-preview-list> </ng-template> diff --git a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html b/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html index cee6aeed4..ac442f660 100644 --- a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html +++ b/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html @@ -102,39 +102,11 @@ </mat-menu> <ng-template #previewFilesListTemplate> - <kg-dataset-list - (kgDsPrvUpdated)="handleKgDsPrvUpdated($event)" - class="d-none" - [kgId]="kgId"> - - </kg-dataset-list> - - <div *ngIf="loadingDatasetPreviewList; else datasetList" class="spinnerAnimationCircle"></div> - - <ng-template #datasetList> - - <mat-nav-list> - <h3 mat-subheader>Available Preview Files</h3> - <mat-list-item - *ngFor="let file of datasetPreviewList" - (click)="handlePreviewFile(file)"> - <mat-icon - [fontSet]="(file | previewFileIconPipe).fontSet" - [fontIcon]="(file | previewFileIconPipe).fontIcon" - matListIcon> - </mat-icon> - <h4 mat-line>{{ file.name }}</h4> - <p mat-line>mimetype: {{ file.mimetype }}</p> - </mat-list-item> - - <small *ngIf="datasetPreviewList.length === 0" - class="text-muted"> - There are no preview files in this parcellation/template space. - </small> - - </mat-nav-list> - </ng-template> - + <dataset-preview-list + [kgId]="kgId" + (previewingFile)="handlePreviewFile($event)"> + + </dataset-preview-list> </ng-template> <ng-template #fullIcons> diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts index 41ee25581..510232f24 100644 --- a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts +++ b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts @@ -15,7 +15,6 @@ export { export class SingleDatasetBase implements OnInit { - @ViewChild('kg-dataset-list') kgDatasetList: any @Input() public ripple: boolean = false /** @@ -32,8 +31,6 @@ export class SingleDatasetBase implements OnInit { @Input() public dataset: any = null @Input() public simpleMode: boolean = false - @Output() public previewingFile: EventEmitter<ViewerPreviewFile> = new EventEmitter() - public preview: boolean = false private humanReadableFileSizePipe: HumanReadableFileSizePipe = new HumanReadableFileSizePipe() @@ -43,10 +40,6 @@ export class SingleDatasetBase implements OnInit { public kgReference: string[] = [] public files: IFile[] = [] private methods: string[] = [] - /** - * sic! - */ - private parcellationRegion: Array<{ name: string }> private error: string = null @@ -55,6 +48,8 @@ export class SingleDatasetBase implements OnInit { public dlFromKgHref: string = null + public selectedTemplateSpace$: Observable<any> + public favedDataentries$: Observable<IDataEntry[]> constructor( private dbService: DatabrowserService, @@ -64,6 +59,7 @@ export class SingleDatasetBase implements OnInit { dataset?: any, ) { + this.favedDataentries$ = this.dbService.favedDataentries$ if (dataset) { this.dataset = dataset @@ -156,20 +152,6 @@ export class SingleDatasetBase implements OnInit { } public handlePreviewFile(file: ViewerPreviewFile) { - this.previewingFile.emit(file) this.singleDatasetService.previewFile(file, this.dataset) } - - public datasetPreviewList: any[] = [] - public loadingDatasetPreviewList: boolean = false - - handleKgDsPrvUpdated(event: CustomEvent){ - const { detail } = event - const { datasetFiles, loadingFlag } = detail - - this.loadingDatasetPreviewList = loadingFlag - this.datasetPreviewList = datasetFiles - - this.cdr.markForCheck() - } } diff --git a/src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts b/src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts new file mode 100644 index 000000000..0c72d3998 --- /dev/null +++ b/src/ui/databrowserModule/util/previewFileDisabledByReferenceSpace.pipe.ts @@ -0,0 +1,20 @@ +import { Pipe, PipeTransform } from "@angular/core"; +import { ViewerPreviewFile } from "src/services/state/dataStore.store"; +import { getIdFromFullId } from "common/util" + +@Pipe({ + name: 'previewFileVisibleInSelectedReferenceTemplatePipe' +}) + +export class PreviewFileVisibleInSelectedReferenceTemplatePipe implements PipeTransform{ + public transform(selectedReferenceSpace: any, file: ViewerPreviewFile):boolean{ + const { referenceSpaces = [] } = file + if (referenceSpaces.some(({ name, fullId }) => name === '*' && fullId === '*')) return true + const { fullId } = selectedReferenceSpace + if (!fullId) return false + return referenceSpaces.some(({ fullId: rsFullId }) => { + const compare = getIdFromFullId(rsFullId) === getIdFromFullId(fullId) + return compare + }) + } +} \ No newline at end of file diff --git a/src/ui/searchSideNav/searchSideNav.component.ts b/src/ui/searchSideNav/searchSideNav.component.ts index 3e256b85e..46b4bfff9 100644 --- a/src/ui/searchSideNav/searchSideNav.component.ts +++ b/src/ui/searchSideNav/searchSideNav.component.ts @@ -13,6 +13,7 @@ import { import { IavRootStoreInterface, SELECT_REGIONS } from "src/services/stateStore.service"; import { LayerBrowser } from "../layerbrowser/layerbrowser.component"; import { trackRegionBy } from '../viewerStateController/regionHierachy/regionHierarchy.component' +import { determinePreviewFileType, PREVIEW_FILE_TYPES } from "../databrowserModule/preview/previewFileIcon.pipe"; @Component({ selector: 'search-side-nav', @@ -74,7 +75,8 @@ export class SearchSideNav implements OnDestroy { select('dataStore'), select('datasetPreviews'), filter(datasetPreviews => datasetPreviews.length > 0), - map((datasetPreviews) => datasetPreviews[datasetPreviews.length - 1]) + map((datasetPreviews) => datasetPreviews[datasetPreviews.length - 1]), + filter(({ file }) => determinePreviewFileType(file) !== PREVIEW_FILE_TYPES.NIFTI) ).subscribe(({ dataset, file }) => { const { fullId } = dataset -- GitLab