diff --git a/deploy/datasets/index.js b/deploy/datasets/index.js index c064b0cea583dec5d2c30ba56e10f23bc67d484a..dc98c0bae950722a2d2b7ec7b4c68490d3c94fd0 100644 --- a/deploy/datasets/index.js +++ b/deploy/datasets/index.js @@ -172,9 +172,16 @@ datasetsRouter.get('/kgInfo', checkKgQuery, cacheMaxAge24Hr, async (req, res) => const { kgId } = req.query const { kgSchema } = req.query const { user } = req + + const tokenInRequest = req.headers['authorization'] && req.headers['authorization'].replace(/bearer\s+/i, '') + const reqUser = tokenInRequest && ({ + tokenset: { + access_token: tokenInRequest + } + }) try{ if (kgSchema === 'minds/core/dataset/v1.0.0') { - const stream = await getDatasetFromId({user, kgId, returnAsStream: true}) + const stream = await getDatasetFromId({user: reqUser || user, kgId, returnAsStream: true}) stream.on('error', getHandleErrorFn(req, res)).pipe(res) } else { const data = getExternalSchemaDatasets(kgId, kgSchema) diff --git a/docs/releases/v2.1.0.md b/docs/releases/v2.1.0.md index 28f1c1cb54ed693c6573281033c56a7b776197b7..c0a893dad71e7936282c0b4a619d685c6488a6f0 100644 --- a/docs/releases/v2.1.0.md +++ b/docs/releases/v2.1.0.md @@ -2,7 +2,6 @@ 1 April 2020 -## New features: ## New features - Region search also searches for relatedAreas diff --git a/docs/releases/v2.3.0.md b/docs/releases/v2.3.0.md index 9b0086dd452aeec01a694b3472c83864828590a7..f1c252954124027ddae342d240177e93a357adc8 100644 --- a/docs/releases/v2.3.0.md +++ b/docs/releases/v2.3.0.md @@ -9,3 +9,7 @@ - Updated `README.md` - introduced zoom buttons - major UI overhaul + +# Bugfixes: + +- dataset list view explicitly show loading status diff --git a/src/ui/databrowserModule/kgSingleDatasetService.service.ts b/src/ui/databrowserModule/kgSingleDatasetService.service.ts index cb836d066f31b607877b347927923c330d14347b..985c4f6df17d53aad0c2038357ce1d32cae1a88e 100644 --- a/src/ui/databrowserModule/kgSingleDatasetService.service.ts +++ b/src/ui/databrowserModule/kgSingleDatasetService.service.ts @@ -41,11 +41,7 @@ export class KgSingleDatasetService implements OnDestroy { const searchParam = _url.searchParams searchParam.set('kgSchema', kgSchema) searchParam.set('kgId', kgId) - return fetch(_url.toString()) - .then(res => { - if (res.status >= 400) { throw new Error(res.status.toString()) } - return res.json() - }) + return this.http.get<any>(_url.toString(), { responseType: 'json' }) } public getDownloadZipFromKgHref({ kgSchema = 'minds/core/dataset/v1.0.0', kgId }) { diff --git a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts index b6a897adb54dd26fc3b27515846b0b5843c83df0..7de89407502787381a8c89e7920e045c2fb3b5d8 100644 --- a/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts +++ b/src/ui/databrowserModule/modalityPicker/modalityPicker.component.ts @@ -62,7 +62,7 @@ export class ModalityPicker implements OnChanges { } } -const sortByFn = (a: CountedDataModality, b: CountedDataModality) => (a.name || '0').charCodeAt(0) - (b.name || '0').charCodeAt(0) +const sortByFn = (a: CountedDataModality, b: CountedDataModality) => (a.name || '0').toLowerCase().charCodeAt(0) - (b.name || '0').toLowerCase().charCodeAt(0) @Pipe({ name: 'sortModalityAlphabetically', diff --git a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts index e76e30ae9ce96d2575ea0013be013a9aa4d5900a..e5ee2a4ae915cd12a93a8f89f74e8981ea7c0aaa 100644 --- a/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts +++ b/src/ui/databrowserModule/singleDataset/detailedView/singleDataset.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Optional} from "@angular/core"; +import { ChangeDetectorRef, Component, Inject, Optional} from "@angular/core"; import { DatabrowserService, KgSingleDatasetService, @@ -12,8 +12,7 @@ import { MatSnackBar } from "@angular/material/snack-bar"; templateUrl: './singleDataset.template.html', styleUrls: [ `./singleDataset.style.css`, - ], - changeDetection: ChangeDetectionStrategy.OnPush, + ] }) export class SingleDatasetView extends SingleDatasetBase { diff --git a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html b/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html index ea640ed7aa4553d72cfec9128c28fec947af6ab5..926b4a5d855e64afbcc5df7b3408416b6855e0f5 100644 --- a/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html +++ b/src/ui/databrowserModule/singleDataset/listView/singleDatasetListView.template.html @@ -7,7 +7,7 @@ <!-- title --> <div class="flex-grow-1 name-container d-flex align-items-start"> - <small *ngIf="name else loadingName" class="flex-grow-1 flex-shrink-1"> + <small *ngIf="!fetchFlag else loadingName" class="flex-grow-1 flex-shrink-1"> {{ name }} </small> <ng-template #loadingName> diff --git a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts index 5fdd11b073145a6f530bd1a3688b5c0ca622fe78..5df6d2da1723febd1a334e18e04ce1f560c7bc6f 100644 --- a/src/ui/databrowserModule/singleDataset/singleDataset.base.ts +++ b/src/ui/databrowserModule/singleDataset/singleDataset.base.ts @@ -1,5 +1,5 @@ -import { ChangeDetectorRef, Input, OnInit, TemplateRef, OnChanges } from "@angular/core"; -import { Observable } from "rxjs"; +import { ChangeDetectorRef, Input, OnInit, TemplateRef, OnChanges, OnDestroy } from "@angular/core"; +import { Observable, Subject, Subscription, of, combineLatest } from "rxjs"; import { IDataEntry, IFile, IPublication } from 'src/services/state/dataStore.store' import { HumanReadableFileSizePipe } from "src/util/pipes/humanReadableFileSize.pipe"; import { DatabrowserService } from "../databrowser.service"; @@ -10,6 +10,7 @@ import { getKgSchemaIdFromFullId } from "../util/getKgSchemaIdFromFullId.pipe"; import { MatSnackBar } from "@angular/material/snack-bar"; import { ARIA_LABELS } from 'common/constants' +import { switchMap, catchError, distinctUntilChanged, filter } from "rxjs/operators"; export { DatabrowserService, @@ -17,7 +18,7 @@ export { ChangeDetectorRef, } -export class SingleDatasetBase implements OnInit, OnChanges { +export class SingleDatasetBase implements OnInit, OnChanges, OnDestroy { public SHOW_DATASET_PREVIEW_ARIA_LABEL = ARIA_LABELS.SHOW_DATASET_PREVIEW public PIN_DATASET_ARIA_LABEL = ARIA_LABELS.PIN_DATASET @@ -32,6 +33,7 @@ export class SingleDatasetBase implements OnInit, OnChanges { @Input() public description?: string @Input() public publications?: IPublication[] + public fetchFlag = false private _fullId: string @Input() @@ -42,9 +44,32 @@ export class SingleDatasetBase implements OnInit, OnChanges { get fullId(){ return this._fullId || (this.kgSchema && this.kgId && `${this.kgSchema}/${this.kgId}`) || null } + + private _kgSchema: string = 'minds/core/dataset/v1.0.0' + private kgSchema$: Subject<string> = new Subject() + + @Input() + set kgSchema(val) { + this._kgSchema = val + this.kgSchema$.next(this._kgSchema) + } + + get kgSchema(){ + return this._kgSchema + } - @Input() public kgSchema?: string = 'minds/core/dataset/v1.0.0' - @Input() public kgId?: string + private _kgId: string + private kgId$: Subject<string> = new Subject() + + @Input() + set kgId(val){ + this._kgId = val + this.kgId$.next(this._kgId) + } + + get kgId(){ + return this._kgId + } @Input() public dataset: any = null @Input() public simpleMode: boolean = false @@ -81,6 +106,37 @@ export class SingleDatasetBase implements OnInit, OnChanges { ) { this.favedDataentries$ = this.dbService.favedDataentries$ + this.subscriptions.push( + combineLatest( + this.kgSchema$.pipe( + distinctUntilChanged(), + filter(v => !!v) + ), + this.kgId$.pipe( + distinctUntilChanged(), + filter(v => !!v) + ) + ).pipe( + switchMap(([kgSchema, kgId]) => { + this.fetchFlag = true + this.cdr.markForCheck() + return this.singleDatasetService.getInfoFromKg({ kgSchema, kgId }).pipe( + catchError((err, obs) => of(null)) + ) + }) + ).subscribe(dataset => { + if (!dataset) return + const { name, description, publications, fullId } = dataset + this.name = name + this.description = description + this.publications = publications + this.fullId = fullId + + this.fetchFlag = false + this.cdr.markForCheck() + }) + ) + if (dataset) { const { fullId } = dataset const obj = getKgSchemaIdFromFullId(fullId) @@ -106,25 +162,6 @@ export class SingleDatasetBase implements OnInit, OnChanges { } } - public async fetchDatasetDetail(){ - try { - const { kgId } = this - const { kgSchema } = this - if (!kgId) return - const dataset = await this.singleDatasetService.getInfoFromKg({ kgId, kgSchema }) - - const { name, description, publications, fullId } = dataset - this.name = name - this.description = description - this.publications = publications - this.fullId = fullId - - this.cdr.detectChanges() - } catch (e) { - // catch error - } - } - // TODO this is not perfect logic for singledataset // singledataset.base.ts should be tidied up in general // fullId, kgId, dataset... too many different entries @@ -139,8 +176,12 @@ export class SingleDatasetBase implements OnInit, OnChanges { this.kgId = re[1] } } + } - this.fetchDatasetDetail() + private subscriptions: Subscription[] = [] + + public ngOnDestroy(){ + while(this.subscriptions.length > 0) this.subscriptions.pop().unsubscribe() } public ngOnInit() { @@ -159,32 +200,6 @@ export class SingleDatasetBase implements OnInit, OnChanges { } if (!kgSchema || !kgId) { return } this.fetchingSingleInfoInProgress = true - this.singleDatasetService.getInfoFromKg({ - kgId, - kgSchema, - }) - .then(json => { - /** - * TODO dataset specific - */ - const { files, publications, name, description, kgReference} = json - this.name = name - this.description = description - this.kgReference = kgReference - this.publications = publications - this.files = files - - this.dataset = json - - this.cdr.markForCheck() - }) - .catch(e => { - this.error = e - }) - .finally(() => { - this.fetchingSingleInfoInProgress = false - this.cdr.markForCheck() - }) } get downloadEnabled() { diff --git a/src/util/directives/clickOutside.directive.ts b/src/util/directives/clickOutside.directive.ts index 1a845ee56b1cdeef625305d1fa2ba6a04f2dd8ac..d60184085f92a7726d98116d12d3dbd96db0ff26 100644 --- a/src/util/directives/clickOutside.directive.ts +++ b/src/util/directives/clickOutside.directive.ts @@ -13,7 +13,8 @@ export class ClickOutsideDirective { @HostListener('document:click', ['$event.target']) onMouseClick(targetElement) { const clickedInside = this.elementRef.nativeElement.contains(targetElement) - if (!clickedInside) { + const clickInsideCdkOverlay = document.querySelector('.cdk-overlay-container')?.contains(targetElement) + if (!clickedInside && !clickInsideCdkOverlay) { this.clickOutside.emit() } }