Skip to content
Snippets Groups Projects
Unverified Commit e1a3bc31 authored by xgui3783's avatar xgui3783 Committed by GitHub
Browse files

Merge pull request #531 from HumanBrainProject/bugfix_downloadPreview

Restore download of dataset preview
parents 3199fab2 c50471fe
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
TOGGLE_EXPLORE_PANEL: `Toggle explore panel`, TOGGLE_EXPLORE_PANEL: `Toggle explore panel`,
MODALITY_FILTER: `Toggle dataset modality filter`, MODALITY_FILTER: `Toggle dataset modality filter`,
LIST_OF_DATASETS: `List of datasets`, LIST_OF_DATASETS: `List of datasets`,
DOWNLOAD_PREVIEW: `Download`,
DOWNLOAD_PREVIEW_CSV: `Download CSV`,
// overlay specific // overlay specific
CONTEXT_MENU: `Viewer context menu`, CONTEXT_MENU: `Viewer context menu`,
......
...@@ -6,4 +6,5 @@ Please note that the keyboard shortcuts may alter the behaviour irreversibly. ...@@ -6,4 +6,5 @@ Please note that the keyboard shortcuts may alter the behaviour irreversibly.
|---|---| |---|---|
|[0-9]|Toggle layer visibility| |[0-9]|Toggle layer visibility|
|[h] [?]|Show help| |[h] [?]|Show help|
|[o]|Toggle orthographic/perspective _3d view_ | |[o]|Toggle orthographic/perspective _3d view_ |
\ No newline at end of file |[a]|Toggle axis visibility |
...@@ -4,3 +4,4 @@ ...@@ -4,3 +4,4 @@
- Fixed PMap color map reset colormap (#523) - Fixed PMap color map reset colormap (#523)
- Modal filters are now sorted alphabetically (#524) - Modal filters are now sorted alphabetically (#524)
- Restored ability to download csv and image from dataset preview (#522)
const { AtlasPage } = require('../util') const { AtlasPage } = require('../util')
const { ARIA_LABELS } = require('../../../common/constants') const { ARIA_LABELS } = require('../../../common/constants')
const { TOGGLE_EXPLORE_PANEL, MODALITY_FILTER } = ARIA_LABELS const { TOGGLE_EXPLORE_PANEL, MODALITY_FILTER, DOWNLOAD_PREVIEW, DOWNLOAD_PREVIEW_CSV } = ARIA_LABELS
const templates = [ const templates = [
'MNI Colin 27', 'MNI Colin 27',
...@@ -103,6 +103,14 @@ describe('> receptor dataset previews', () => { ...@@ -103,6 +103,14 @@ describe('> receptor dataset previews', () => {
await iavPage.waitFor(true, true) await iavPage.waitFor(true, true)
const modalHasCanvas = await iavPage.modalHasChild('canvas') const modalHasCanvas = await iavPage.modalHasChild('canvas')
expect(modalHasCanvas).toEqual(true) expect(modalHasCanvas).toEqual(true)
await iavPage.wait(500)
const modalHasDownloadBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW}"]`)
const modalHasDownloadCSVBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW_CSV}"]`)
expect(modalHasDownloadBtn).toEqual(true)
expect(modalHasDownloadCSVBtn).toEqual(true)
}) })
it('> can display profile', async () => { it('> can display profile', async () => {
...@@ -113,6 +121,14 @@ describe('> receptor dataset previews', () => { ...@@ -113,6 +121,14 @@ describe('> receptor dataset previews', () => {
await iavPage.waitFor(true, true) await iavPage.waitFor(true, true)
const modalHasCanvas = await iavPage.modalHasChild('canvas') const modalHasCanvas = await iavPage.modalHasChild('canvas')
expect(modalHasCanvas).toEqual(true) expect(modalHasCanvas).toEqual(true)
await iavPage.wait(500)
const modalHasDownloadBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW}"]`)
const modalHasDownloadCSVBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW_CSV}"]`)
expect(modalHasDownloadBtn).toEqual(true)
expect(modalHasDownloadCSVBtn).toEqual(true)
}) })
}) })
it('> can display image', async () => { it('> can display image', async () => {
...@@ -122,6 +138,14 @@ describe('> receptor dataset previews', () => { ...@@ -122,6 +138,14 @@ describe('> receptor dataset previews', () => {
await iavPage.waitFor(true, true) await iavPage.waitFor(true, true)
const modalHasImage = await iavPage.modalHasChild('div[data-img-src]') const modalHasImage = await iavPage.modalHasChild('div[data-img-src]')
expect(modalHasImage).toEqual(true) expect(modalHasImage).toEqual(true)
await iavPage.wait(500)
const modalHasDownloadBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW}"]`)
const modalHasDownloadCSVBtn = await iavPage.modalHasChild(`[aria-label="${DOWNLOAD_PREVIEW_CSV}"]`)
expect(modalHasDownloadBtn).toEqual(true)
expect(modalHasDownloadCSVBtn).toEqual(false)
}) })
}) })
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<link rel="stylesheet" href="theme.css"> <link rel="stylesheet" href="theme.css">
<link rel="stylesheet" href="version.css"> <link rel="stylesheet" href="version.css">
<script src="https://unpkg.com/kg-dataset-previewer@0.0.17/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer> <script src="https://unpkg.com/kg-dataset-previewer@0.0.18/dist/kg-dataset-previewer/kg-dataset-previewer.js" defer>
</script> </script>
<title>Interactive Atlas Viewer</title> <title>Interactive Atlas Viewer</title>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"originDatasets": [ "originDatasets": [
{ {
"kgSchema": "minds/core/dataset/v1.0.0", "kgSchema": "minds/core/dataset/v1.0.0",
"kgId": "e32f9053-38c9-4911-b868-845c56828f4d" "kgId": "d07f9305-1e75-4548-a348-b155fb323d31"
} }
], ],
"nehubaConfigURL": "nehubaConfig/bigbrainNehubaConfig", "nehubaConfigURL": "nehubaConfig/bigbrainNehubaConfig",
......
...@@ -172,7 +172,7 @@ export class DataBrowserUseEffect implements OnDestroy { ...@@ -172,7 +172,7 @@ export class DataBrowserUseEffect implements OnDestroy {
return forkJoin( return forkJoin(
from(this.kgSingleDatasetService.getInfoFromKg({ kgSchema: re[0], kgId: re[1] })), from(this.kgSingleDatasetService.getInfoFromKg({ kgSchema: re[0], kgId: re[1] })),
this.http.get(`${DS_PREVIEW_URL}/${re[1]}/${filename}`) this.http.get(`${DS_PREVIEW_URL}/${re[1]}/${encodeURIComponent(filename)}`)
).pipe( ).pipe(
map(([ dataset, file ]) => { map(([ dataset, file ]) => {
return { return {
......
...@@ -35,15 +35,6 @@ export class KgSingleDatasetService implements OnDestroy { ...@@ -35,15 +35,6 @@ 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(`${BACKENDURL.replace(/\/$/, '')}/datasets/hasPreview`)
const searchParam = _url.searchParams
searchParam.set('datasetName', name)
return this.http.get(_url.toString())
}
public getInfoFromKg({ kgId, kgSchema = 'minds/core/dataset/v1.0.0' }: Partial<KgQueryInterface>) { public getInfoFromKg({ kgId, kgSchema = 'minds/core/dataset/v1.0.0' }: Partial<KgQueryInterface>) {
const _url = new URL(`${BACKENDURL.replace(/\/$/, '')}/datasets/kgInfo`) const _url = new URL(`${BACKENDURL.replace(/\/$/, '')}/datasets/kgInfo`)
const searchParam = _url.searchParams const searchParam = _url.searchParams
......
import { Component, Input, Inject } from "@angular/core"; import { Component, Input, Inject, ViewChild, ElementRef } from "@angular/core";
import { MAT_DIALOG_DATA } from "@angular/material/dialog"; import { MAT_DIALOG_DATA } from "@angular/material/dialog";
import { AtlasViewerConstantsServices } from "../../singleDataset/singleDataset.base"; import { AtlasViewerConstantsServices } from "../../singleDataset/singleDataset.base";
import { Observable } from "rxjs"; import { Observable, fromEvent, Subscription, from, of, throwError } from "rxjs";
import { switchMapTo, catchError, take, concatMap, map, retryWhen, delay } from "rxjs/operators";
import { DomSanitizer, SafeResourceUrl } from "@angular/platform-browser";
import { ARIA_LABELS } from 'common/constants'
const {
DOWNLOAD_PREVIEW,
DOWNLOAD_PREVIEW_CSV
} = ARIA_LABELS
const fromPromiseRetry = ({ retries = 10, timeout = 100 } = {}) => {
const retryCounter = 0
return (fn: () => Promise<any>) => new Observable(obs => {
fn()
.then(val => obs.next(val))
.catch(e => obs.error(e))
.finally(() => obs.complete())
}).pipe(
retryWhen(err => {
if (retryCounter >= retries) return throwError(err)
return err.pipe(
delay(timeout)
)
})
)
}
@Component({ @Component({
templateUrl: './previewCW.template.html', templateUrl: './previewCW.template.html',
...@@ -12,6 +38,14 @@ import { Observable } from "rxjs"; ...@@ -12,6 +38,14 @@ import { Observable } from "rxjs";
export class PreviewComponentWrapper{ export class PreviewComponentWrapper{
public DOWNLOAD_PREVIEW_ARIA_LABEL = DOWNLOAD_PREVIEW
public DOWNLOAD_PREVIEW_CSV_ARIA_LABEL = DOWNLOAD_PREVIEW_CSV
private subscriptions: Subscription[] = []
@ViewChild('dataPreviewerStencilCmp', { read: ElementRef, static: true })
private dataPreviewerStencilCmp: ElementRef<any>
public darktheme$: Observable<boolean> public darktheme$: Observable<boolean>
@Input() @Input()
...@@ -28,7 +62,8 @@ export class PreviewComponentWrapper{ ...@@ -28,7 +62,8 @@ export class PreviewComponentWrapper{
constructor( constructor(
@Inject(MAT_DIALOG_DATA) data: any, @Inject(MAT_DIALOG_DATA) data: any,
private constantService: AtlasViewerConstantsServices private constantService: AtlasViewerConstantsServices,
private sanitizer: DomSanitizer
){ ){
this.darktheme$ = this.constantService.darktheme$ this.darktheme$ = this.constantService.darktheme$
...@@ -40,4 +75,43 @@ export class PreviewComponentWrapper{ ...@@ -40,4 +75,43 @@ export class PreviewComponentWrapper{
this.datasetName = datasetName this.datasetName = datasetName
} }
} }
public downloadHref: SafeResourceUrl
public downloadCsvHref: SafeResourceUrl
ngAfterViewInit(){
this.dataPreviewerStencilCmp.nativeElement.getDownloadPreviewHref()
const hydrateHrefSubscription = fromEvent(this.dataPreviewerStencilCmp.nativeElement, 'renderEvent').pipe(
switchMapTo(
fromPromiseRetry()(() => this.dataPreviewerStencilCmp.nativeElement.getDownloadPreviewHref()).pipe(
concatMap((downloadHref: string) => {
return from(this.dataPreviewerStencilCmp.nativeElement.getDownloadCsvHref()).pipe(
catchError(err => of(null)),
map(csvHref => {
return {
downloadHref,
csvHref
}
})
)
})
)
),
take(1)
).subscribe(({ downloadHref, csvHref }) => {
if (csvHref) this.downloadCsvHref = this.sanitizer.bypassSecurityTrustResourceUrl(csvHref)
this.downloadHref = this.sanitizer.bypassSecurityTrustResourceUrl(downloadHref)
})
this.subscriptions.push(
hydrateHrefSubscription
)
}
ngOnDestroy(){
while(this.subscriptions.length > 0) {
this.subscriptions.pop().unsubscribe()
}
}
} }
\ No newline at end of file
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
</div> </div>
<!-- main content --> <!-- main content -->
<div class="flex-grow-1 flex-shrink-1"> <div class="flex-grow-1 flex-shrink-1 w-0 d-flex align-items-center">
<span class="d-block"> <span class="text-truncate">
{{ filename }} {{ filename }}
</span> </span>
<small class="text-muted d-block"> <small class="text-muted d-block">
...@@ -34,6 +34,29 @@ ...@@ -34,6 +34,29 @@
[darkmode]="darktheme$ | async" [darkmode]="darktheme$ | async"
[filename]="filename" [filename]="filename"
[kgId]="kgId" [kgId]="kgId"
[backendUrl]="backendUrl"> [backendUrl]="backendUrl"
#dataPreviewerStencilCmp>
</kg-dataset-previewer> </kg-dataset-previewer>
<div class="flex-shrink-0 flex-grow-0 d-inline-flex">
<a *ngIf="downloadHref"
[attr.href]="downloadHref"
[attr.download]="filename"
[attr.aria-label]="DOWNLOAD_PREVIEW_ARIA_LABEL"
target="_blank"
mat-icon-button
color="primary">
<i class="fas fa-download"></i>
</a>
<a *ngIf="downloadCsvHref"
[attr.href]="downloadCsvHref"
[attr.download]="filename"
[attr.aria-label]="DOWNLOAD_PREVIEW_CSV_ARIA_LABEL"
target="_blank"
mat-icon-button
color="primary">
<i class="fas fa-file-csv"></i>
</a>
</div>
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment