diff --git a/deploy/datasets/index.js b/deploy/datasets/index.js index bb43d6d033e9cba9ce9010212940d912d259d7e2..abb1ef174225f58b62f5e9afdb3c9696589a5f05 100644 --- a/deploy/datasets/index.js +++ b/deploy/datasets/index.js @@ -130,11 +130,13 @@ datasetsRouter.post("/downloadParcellationThemself", (req,res, next) => { - //ToDo: Need to download files dynamicly. Nii folder should remove + + //ToDo: Need to download files dynamically. Nii folder should be removed if (req.body['niiFiles']) { var nii = zip.folder("nifti") + const filepath = process.env.STORAGE_PATH || path.join(__dirname, 'nii') req.body['niiFiles'].forEach(file => { - nii.file(file['file'], fs.readFileSync(path.join(__dirname, 'nii') + '/' + file['file'])) + nii.file(file['file'], fs.readFileSync(path.join(filepath, file['file']))) }) } diff --git a/src/atlasViewer/atlasViewer.component.ts b/src/atlasViewer/atlasViewer.component.ts index 3a758aa9815642fc8bda62dc86e6d671d7227643..f2dac903f512b6be381c220af79f39029407cc6f 100644 --- a/src/atlasViewer/atlasViewer.component.ts +++ b/src/atlasViewer/atlasViewer.component.ts @@ -20,8 +20,6 @@ import { DatabrowserService } from "src/ui/databrowserModule/databrowser.service import { AGREE_COOKIE, AGREE_KG_TOS, SHOW_KG_TOS } from "src/services/state/uiState.store"; import { TabsetComponent } from "ngx-bootstrap/tabs"; import { ToastService } from "src/services/toastService.service"; -import { ZipFileDownloadService } from "src/services/zipFileDownload.service"; -import {forEach} from "@angular/router/src/utils/collection"; /** * TODO @@ -96,11 +94,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { public sidePanelOpen$: Observable<boolean> - handleToast - tPublication - pPublication - downloadingProcess = false - niiFileSize = 0 get toggleMessage(){ return this.constantsService.toggleMessage @@ -117,7 +110,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { private databrowserService: DatabrowserService, private dispatcher$: ActionsSubject, private toastService: ToastService, - private zipFileDownloadService: ZipFileDownloadService, ) { this.ngLayerNames$ = this.store.pipe( select('viewerState'), @@ -238,30 +230,11 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { this.niiFileSize = 0 - if (this.selectedTemplate && this.selectedParcellation) { - if (this.selectedTemplate['properties'] && this.selectedTemplate['properties']['publications']) { - this.tPublication = this.selectedTemplate['properties']['publications'] - } else { - this.tPublication = null - } - if (this.selectedParcellation['properties'] && this.selectedParcellation['properties']['publications']) { - this.pPublication = this.selectedParcellation['properties']['publications'] - } else { - this.pPublication = null - } - if(this.selectedParcellation['properties'] && this.selectedParcellation['properties']['nifty']) { - this.selectedParcellation['properties']['nifty'].forEach(nii => { - this.niiFileSize += nii['size'] - }) - } - - } else { - this.tPublication = null - this.pPublication = null - } - - if (this.tPublication || this.pPublication) { + if ((this.selectedParcellation['properties'] && + (this.selectedParcellation['properties']['publications'] || this.selectedParcellation['properties']['description'])) + || (this.selectedTemplate['properties'] && + (this.selectedTemplate['properties']['publications'] || this.selectedTemplate['properties']['description']))) { if (this.handleToast) { this.handleToast() this.handleToast = null @@ -272,38 +245,6 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { } }) ) - - - } - - downloadPublications() { - this.downloadingProcess = true - - const fileName = this.selectedTemplate.name + ' - ' + this.selectedParcellation.name - let publicationsText = '' - - if (this.tPublication) { - publicationsText += this.selectedTemplate.name + ' Publications:\r\n' - this.tPublication.forEach((tp, i) => { - publicationsText += '\t' + (i+1) + '. ' + tp['citation'] + ' - ' + tp['doi'] + '\r\n' - }); - } - - if (this.pPublication) { - if (this.tPublication) publicationsText += '\r\n\r\n' - publicationsText += this.selectedParcellation.name + ' Publications:\r\n' - this.pPublication.forEach((pp, i) => { - publicationsText += '\t' + (i+1) + '. ' + pp['citation'] + ' - ' + pp['doi'] + '\r\n' - }); - } - - this.zipFileDownloadService.downloadZip( - publicationsText, - fileName, - this.selectedParcellation['properties'] && this.selectedParcellation['properties']['nifty']? this.selectedParcellation['properties']['nifty'] : 0).subscribe(data => { - this.downloadingProcess = false - }) - publicationsText = '' } @@ -557,22 +498,25 @@ export class AtlasViewer implements OnDestroy, OnInit, AfterViewInit { closeMenuWithSwipe(documentToSwipe: ElementRef) { - const swipeDistance = 150; // swipe distance - const swipeLeft$ = fromEvent(documentToSwipe.nativeElement, "touchstart") - .pipe( - switchMap(startEvent => - fromEvent(documentToSwipe.nativeElement, "touchmove") - .pipe( - takeUntil(fromEvent(documentToSwipe.nativeElement, "touchend")) - ,map(event => event['touches'][0].pageX) - ,scan((acc, pageX) => Math.round(startEvent['touches'][0].pageX - pageX), 0) - ,takeLast(1) - ,filter(difference => difference >= swipeDistance) - ))) - // Subscription - swipeLeft$.subscribe(val => { - this.changeMenuState({close: true}) - }) + if (documentToSwipe && documentToSwipe.nativeElement) { + const swipeDistance = 150; // swipe distance + const swipeLeft$ = fromEvent(documentToSwipe.nativeElement, 'touchstart') + .pipe( + switchMap(startEvent => + fromEvent(documentToSwipe.nativeElement, 'touchmove') + .pipe( + takeUntil(fromEvent(documentToSwipe.nativeElement, 'touchend')), + map(event => event['touches'][0].pageX), + scan((acc, pageX) => Math.round(startEvent['touches'][0].pageX - pageX), 0), + takeLast(1), + filter(difference => difference >= swipeDistance) + ))) + this.subscriptions.push( + swipeLeft$.subscribe(() => { + this.changeMenuState({close: true}) + }) + ) + } } } diff --git a/src/atlasViewer/atlasViewer.style.css b/src/atlasViewer/atlasViewer.style.css index 8b7ec26edc1f8eb6f5ac60e7aba51b152d67d074..75604388751f3a6d86c5f39da18550cadd18c118 100644 --- a/src/atlasViewer/atlasViewer.style.css +++ b/src/atlasViewer/atlasViewer.style.css @@ -1,5 +1,3 @@ -/* @import '~@angular/material/prebuilt-themes/indigo-pink.css'; */ - :host, :host > .atlas-container { display:block; @@ -175,45 +173,6 @@ mat-sidenav { box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } -.mpobileMenuTabs { +.mobileMenuTabs { margin: 40px 0 0 5px; -} - -.timerToast { - max-width: 700px; - display: flex; - flex-direction: column; - max-height: 500px; - padding-right: 10px; - overflow-y: auto; -} - -.download-buttons-panel { - align-self: flex-end; -} -.downloadPublications { - margin: 5px; - outline: none; -} - -.textPartInPublications { - text-align: justify; -} - - -.timerToast:hover::-webkit-scrollbar-thumb{ - background: #888; - border-radius: 10px; -} -.timerToast::-webkit-scrollbar { - width: 7px; -} -.timerToast::-webkit-scrollbar-track { - background: transparent; -} -.timerToast::-webkit-scrollbar-thumb { - background: #CCC; -} -.timerToast::-webkit-scrollbar-thumb:hover { - background: #555; } \ No newline at end of file diff --git a/src/atlasViewer/atlasViewer.template.html b/src/atlasViewer/atlasViewer.template.html index 474312047f0dfc309b02a47c0ddab6e4bb95f2b9..045fe85dfe3b204a3a2f70ac37bacf1013a54682 100644 --- a/src/atlasViewer/atlasViewer.template.html +++ b/src/atlasViewer/atlasViewer.template.html @@ -23,7 +23,7 @@ <button mat-button style="height: 0; position: absolute;"></button> <logo-container class="logoContainerMobile"></logo-container> - <tabset #mobileMenuTabs [justified]="true" class="mpobileMenuTabs" > + <tabset #mobileMenuTabs [justified]="true" class="mobileMenuTabs" > <tab heading="Template"> <signin-banner [darktheme] = "darktheme" signinWrapper></signin-banner> <layout-floating-container *ngIf="this.nehubaContainer && this.nehubaContainer.nehubaViewer"> @@ -127,10 +127,10 @@ <ui-nehuba-container (contextmenu)="nehubaClickHandler($event)"> </ui-nehuba-container> - <div *ngIf="!isMobile" bannerWrapper> - <menu-icons iconWrapper *ngIf="selectedTemplate"> + <div *ngIf="!isMobile && selectedTemplate" bannerWrapper> + <menu-icons iconWrapper> </menu-icons> - <signin-banner signinWrapper *ngIf="selectedTemplate"> + <signin-banner signinWrapper> </signin-banner> </div> @@ -260,38 +260,13 @@ </ng-template> <ng-template #publications > - <div *ngIf="tPublication || pPublication" class="timerToast"> -<!-- <button mat-mini-fab color="primary" class="downloadPublications" (click)="downloadPublications()">↓</button>--> - - - - <div *ngIf="tPublication && selectedTemplate['name']"> - <p>{{selectedTemplate['name']}}</p> - <p class="textPartInPublications">{{selectedTemplate['properties']['description']}}</p> - - <p>Publication(s)</p> - <div *ngFor="let tp of tPublication" class="textPartInPublications"> - <a [href]="tp['doi']" target="_blank">{{tp['citation']}}</a> - </div> - <hr *ngIf="pPublication"> - </div> - <div *ngIf="pPublication"> - <p>{{selectedParcellation['name']}}</p> - <p class="textPartInPublications">{{selectedParcellation['properties']['description']}}</p> - - <p>Publication(s)</p> - <div *ngFor="let pp of pPublication" class="textPartInPublications"> - <a [href]="pp['doi']" target="_blank">{{pp['citation']}}</a> - </div> - </div> - - <div class="download-buttons-panel"> - <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications()">Explore <i class="fas fa-external-link-alt"></i></button> - <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications()" [disabled] = "downloadingProcess" > - Download - <span *ngIf="niiFileSize > 0">(.nii {{niiFileSize/10000 | number:'.1-2'}} Mb) </span> - <i class="fas" [ngClass]="!downloadingProcess? 'fa-download' :'fa-spinner fa-pulse'"></i> - </button> - </div> - </div> + <reference-toast-component + [templateName] = "selectedTemplate['name']? selectedTemplate['name'] : null" + [parcellationName] = "selectedParcellation['name']? selectedParcellation['name'] : null" + [templateDescription] = "selectedTemplate['properties'] && selectedTemplate['properties']['description']? selectedTemplate['properties']['description'] : null" + [parcellationDescription] = "selectedParcellation['properties'] && selectedParcellation['properties']['description']? selectedParcellation['properties']['description'] : null" + [templatePublications] = "selectedTemplate['properties'] && selectedTemplate['properties']['publications']? selectedTemplate['properties']['publications']: null" + [parcellationPublications] = "selectedParcellation['properties'] && selectedParcellation['properties']['publications']? selectedParcellation['properties']['publications']: null" + [parcellationNifti] = "selectedParcellation['properties'] && selectedParcellation['properties']['nifti']? selectedParcellation['properties']['nifti'] : null"> + </reference-toast-component> </ng-template> \ No newline at end of file diff --git a/src/components/dropdown/dropdown.component.ts b/src/components/dropdown/dropdown.component.ts index 139e1add801255f3fb651ceaffb2bbd2bad312d2..9141a42190b26bb40b56e8ce9d7bb77b0f8d903f 100644 --- a/src/components/dropdown/dropdown.component.ts +++ b/src/components/dropdown/dropdown.component.ts @@ -26,6 +26,7 @@ export class DropdownComponent{ @Input() darktheme: boolean @Output() itemSelected : EventEmitter<any> = new EventEmitter() + @Output() listItemButtonClicked: EventEmitter<any> = new EventEmitter() @ViewChild('dropdownToggle',{read:ElementRef}) dropdownToggle : ElementRef diff --git a/src/components/dropdown/dropdown.template.html b/src/components/dropdown/dropdown.template.html index b31ed3fc131507c35127bbb1c5da3e5c52328439..b4d7ff326d754c7f8ef8794e9bd4c501dea2fb27 100644 --- a/src/components/dropdown/dropdown.template.html +++ b/src/components/dropdown/dropdown.template.html @@ -25,6 +25,7 @@ [inputArray]="inputArray" [@showState]="openState ? 'show' : 'hide'" [isMobile]="isMobile" - [darktheme]="darktheme"> + [darktheme]="darktheme" + (listItemButtonClicked) = listItemButtonClicked.emit($event)> </radio-list> diff --git a/src/components/radiolist/radiolist.component.ts b/src/components/radiolist/radiolist.component.ts index 109cda7a557234e74fe6d819b826edaf6f6a474b..9db15d19c131f6183dc4789b6a53aa993e889eb5 100644 --- a/src/components/radiolist/radiolist.component.ts +++ b/src/components/radiolist/radiolist.component.ts @@ -1,6 +1,4 @@ import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, OnInit, ViewChild, TemplateRef } from "@angular/core"; -import { ToastService } from "src/services/toastService.service"; -import { ZipFileDownloadService } from "src/services/zipFileDownload.service"; @Component({ selector: 'radio-list', @@ -8,22 +6,6 @@ import { ZipFileDownloadService } from "src/services/zipFileDownload.service"; styleUrls: [ './radiolist.style.css' ], - styles: [ - // ` - // ul > li.selected > .textSpan:before - // { - // content: '\u2022'; - // width : 1em; - // display:inline-block; - // } - // ul > li:not(.selected) > .textSpan:before - // { - // content: ' '; - // width : 1em; - // display:inline-block; - // } - // ` - ], changeDetection: ChangeDetectionStrategy.OnPush }) @@ -48,48 +30,13 @@ export class RadioList{ @Input() isMobile: boolean @Input() darktheme: boolean - @ViewChild('publicationTemplate') publicationTemplate: TemplateRef<any> - - downloadingProcess = false - handleToast - niiFileSize = 0 - - constructor(private toastService: ToastService, - private zipFileDownloadService: ZipFileDownloadService) {} - - showToast(item) { - this.niiFileSize = 0 - if(item['properties']['nifty']) { - item['properties']['nifty'].forEach(nii => { - this.niiFileSize += nii['size'] - }) - } - - if (this.handleToast) { - this.handleToast() - this.handleToast = null - } - this.handleToast = this.toastService.showToast(this.publicationTemplate, { - timeout: 7000 - }) - } - - - downloadPublications(item) { - this.downloadingProcess = true + @Output() listItemButtonClicked = new EventEmitter<string>(); - const filename = item['name'] - let publicationsText = item['name'] + ' Publications:\r\n' - item['properties']['publications'].forEach((p, i) => { - publicationsText += '\t' + (i+1) + '. ' + p['citation'] + ' - ' + p['doi'] + '\r\n' - }); - this.zipFileDownloadService.downloadZip(publicationsText, filename, item['properties']['nifty']? item['properties']['nifty'] : 0).subscribe(data => { - this.downloadingProcess = false - }) - publicationsText = '' + clickListButton(i) { + this.listItemButtonClicked.emit(i) } overflowText(event) { - return (event.offsetWidth < event.scrollWidth); + return (event.offsetWidth < event.scrollWidth) } } \ No newline at end of file diff --git a/src/components/radiolist/radiolist.style.css b/src/components/radiolist/radiolist.style.css index af97671263ad49485ebd06b815d7ddb623430773..752487399d4ae42cc44da90cc2b1868cb8ee8527 100644 --- a/src/components/radiolist/radiolist.style.css +++ b/src/components/radiolist/radiolist.style.css @@ -67,45 +67,7 @@ ul,span.dropdown-item-1 border-radius: 15px; width: 24px; height: 24px; + min-width: 24px; cursor: pointer; text-align: center; -} - -.timerToast { - max-width: 700px; - display: flex; - flex-direction: column; - max-height: 500px; - padding-right: 10px; - overflow-y: auto; -} - -.download-buttons-panel { - align-self: flex-end; -} -.downloadPublications { - margin: 5px; - outline: none; -} - -.textPartInPublications { - text-align: justify; -} - - -.timerToast:hover::-webkit-scrollbar-thumb{ - background: #888; - border-radius: 10px; -} -.timerToast::-webkit-scrollbar { - width: 7px; -} -.timerToast::-webkit-scrollbar-track { - background: transparent; -} -.timerToast::-webkit-scrollbar-thumb { - background: #CCC; -} -.timerToast::-webkit-scrollbar-thumb:hover { - background: #555; } \ No newline at end of file diff --git a/src/components/radiolist/radiolist.template.html b/src/components/radiolist/radiolist.template.html index 617e9801ff206b5f68ddf6a5f3fe11ab932b73b3..c79b2314132ae8e2ba0df65eadd8d3933bd0a736 100644 --- a/src/components/radiolist/radiolist.template.html +++ b/src/components/radiolist/radiolist.template.html @@ -4,48 +4,22 @@ role="menu"> <li - *ngFor="let input of inputArray" + *ngFor="let input of inputArray; let i = index" + class="d-flex justify-content-between" [ngClass]="checkSelected(selectedItem, input) ? 'selected' : 'notselected'" role="menuitem" - (click)="itemSelected.emit({previous: selectedItem, current: input})" - style="display: flex; justify-content: space-between;"> - - - + (click)="itemSelected.emit({previous: selectedItem, current: input})"> + <span class="dropdown-item-1 textSpan" - #DropDownText - [innerHTML] = "listDisplay(input)" - [style.fontWeight] = "checkSelected(selectedItem, input)? 'bold' : ''" - [ngStyle]="input['properties'] && input['properties']['publications'] ? {'width': 'calc(100% - 30px)', 'overflow': 'hidden'} : {}" - [matTooltip]="overflowText(DropDownText)? DropDownText.innerText: ''"> + #DropDownText + [innerHTML] = "listDisplay(input)" + [style.fontWeight] = "checkSelected(selectedItem, input)? 'bold' : ''" + [matTooltip]="overflowText(DropDownText)? DropDownText.innerText: ''"> </span> - <span *ngIf="input['properties'] && input['properties']['publications']" class="infoIcon" (click)="showToast(input);$event.stopPropagation()" - style="align-self: flex-end;"> + <span *ngIf="input['properties'] && (input['properties']['publications'] || input['properties']['description'])" + class="infoIcon align-self-end" (click)="clickListButton(i);$event.stopPropagation()"> i </span> - - -<ng-template #publicationTemplate *ngIf="input['properties'] && input['properties']['publications']"> - <div class="timerToast"> - <p>{{input['name']}}</p> - <p class="textPartInPublications">{{input['properties']['description']}}</p> - <p>Publication(s)</p> - <div *ngFor="let p of input['properties']['publications']" class="textPartInPublications"> - <a [href]="p['doi']" target="_blank">{{p['citation']}}</a> - </div> - <div class="download-buttons-panel"> - <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications(input)">Explore <i class="fas fa-external-link-alt"></i></button> - <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications(input)" [disabled] = "downloadingProcess" > - Download - <span *ngIf="niiFileSize > 0">(.nii {{niiFileSize/10000 | number:'.1-2'}} Mb) </span> - <i class="fas" [ngClass]="!downloadingProcess? 'fa-download' :'fa-spinner fa-pulse'"></i> - </button> - </div> - </div> -</ng-template> - - - </li> </ul> \ No newline at end of file diff --git a/src/res/ext/MNI152.json b/src/res/ext/MNI152.json index 62a682fe726ab25cb83527404869f1bfe224dbac..657e54448a563c3824f615d880f980a6abeac658 100644 --- a/src/res/ext/MNI152.json +++ b/src/res/ext/MNI152.json @@ -13,7 +13,7 @@ "version": "1.0", "description": "not yet", "publications": [], - "nifty": [{"file": "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "44000"}] + "nifti": [{"file": "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "4400000"}] }, "regions": [ { diff --git a/src/res/ext/colin.json b/src/res/ext/colin.json index c90b6b9696c4f0a1d1d718bd793f18b5e96974cb..4e6e3f948e7408a2bad396a3f971f842c2812b67 100644 --- a/src/res/ext/colin.json +++ b/src/res/ext/colin.json @@ -13,7 +13,7 @@ "version": "1.0", "description": "not yet", "publications": [], - "nifty": [{"file": "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "44000"}] + "nifti": [{"file": "jubrain-max-pmap-v22c_space-mnicolin27.nii", "size": "4400000"}] }, "regions": [ { diff --git a/src/services/zipFileDownload.service.ts b/src/services/zipFileDownload.service.ts index f6b9e164faeb25c84d7590d9085fb4edd81de708..68131c4bf6932e0dd8df8691936b3bd0d3563738 100644 --- a/src/services/zipFileDownload.service.ts +++ b/src/services/zipFileDownload.service.ts @@ -23,11 +23,9 @@ export class ZipFileDownloadService { } downloadFile(data, fileName) { - const contentType = 'application/zip'; const b64Data = data - const b64toBlob = (b64Data, contentType='', sliceSize=512) => { const byteCharacters = atob(b64Data); const byteArrays = []; @@ -48,9 +46,7 @@ export class ZipFileDownloadService { return blob; } - const blob = b64toBlob(b64Data, contentType); - // const blob = new Blob([data], { type: 'text/csv' }); const url= window.URL.createObjectURL(blob); const anchor = document.createElement("a"); anchor.download = fileName + '.zip'; diff --git a/src/ui/referenceToast/referenceToast.component.ts b/src/ui/referenceToast/referenceToast.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..9b68e7dcd4d449704f96147a42e4341ef3d1d410 --- /dev/null +++ b/src/ui/referenceToast/referenceToast.component.ts @@ -0,0 +1,91 @@ +import { Component, Input, OnInit } from "@angular/core"; +import { ZipFileDownloadService } from "src/services/zipFileDownload.service"; + +@Component({ + selector : 'reference-toast-component', + templateUrl : './referenceToast.template.html', + styleUrls : [ + `./referenceToast.style.css` + ], +}) +export class ReferenceToastComponent implements OnInit{ + @Input() templateName? : string + @Input() parcellationName? : string + @Input() templateDescription? : string + @Input() parcellationDescription? : string + @Input() templatePublications? : any + @Input() parcellationPublications? : any + @Input() parcellationNifti? : any + + downloadingProcess = false + niiFileSize = 0 + + constructor(private zipFileDownloadService: ZipFileDownloadService) {} + + ngOnInit(): void { + if (this.parcellationNifti) { + this.parcellationNifti.forEach(nii => { + this.niiFileSize += nii['size'] + }) + } + } + + downloadPublications() { + this.downloadingProcess = true + + let fileName = '' + let publicationsText = '' + + if (this.templatePublications || this.templateDescription) { + fileName += this.templateName? this.templateName : 'Template' + + if (this.templateDescription) { + publicationsText += this.templateName + '\r\n' + this.templateDescription.split(" ").forEach((word, index) => { + publicationsText += word + ' ' + if (index && index%15 === 0) publicationsText += '\r\n' + }) + publicationsText += '\r\n' + } + + if (this.templatePublications) { + if (!this.templateDescription) publicationsText += this.templateName + publicationsText += ' Publications:\r\n' + this.templatePublications.forEach((tp, i) => { + publicationsText += '\t' + (i+1) + '. ' + tp['citation'] + ' - ' + tp['doi'] + '\r\n' + }) + } + } + + if (this.parcellationPublications || this.parcellationDescription) { + if (this.templateName) fileName += ' - ' + fileName += this.parcellationName? this.parcellationName : 'Parcellation' + if (this.templateDescription || this.templatePublications) publicationsText += '\r\n\r\n' + + if (this.parcellationDescription) { + publicationsText += this.parcellationName + '\r\n' + this.parcellationDescription.split(" ").forEach((word, index) => { + publicationsText += word + ' ' + if (index && index%15 === 0) publicationsText += '\r\n' + }) + publicationsText += '\r\n' + } + + if (this.parcellationPublications) { + if (!this.parcellationDescription) publicationsText += this.parcellationName + publicationsText += ' Publications:\r\n' + this.parcellationPublications.forEach((pp, i) => { + publicationsText += '\t' + (i+1) + '. ' + pp['citation'] + ' - ' + pp['doi'] + '\r\n' + }) + } + } + + this.zipFileDownloadService.downloadZip( + publicationsText, + fileName, + this.parcellationNifti? this.parcellationNifti : 0).subscribe(data => { + this.downloadingProcess = false + }) + publicationsText = '' + } +} diff --git a/src/ui/referenceToast/referenceToast.style.css b/src/ui/referenceToast/referenceToast.style.css new file mode 100644 index 0000000000000000000000000000000000000000..cf52094f562a63ff2034df2ee50b64240b889c00 --- /dev/null +++ b/src/ui/referenceToast/referenceToast.style.css @@ -0,0 +1,14 @@ +.timerToast { + max-width: 700px; + max-height: 500px; + padding-right: 10px; + overflow-y: auto; +} + +.download-buttons-panel { + align-self: flex-end; +} +.downloadPublications { + margin: 5px; + outline: none; +} \ No newline at end of file diff --git a/src/ui/referenceToast/referenceToast.template.html b/src/ui/referenceToast/referenceToast.template.html new file mode 100644 index 0000000000000000000000000000000000000000..7db995f2b15468c795a0b31d404475a16fa8ee0a --- /dev/null +++ b/src/ui/referenceToast/referenceToast.template.html @@ -0,0 +1,33 @@ +<div class="timerToast d-flex flex-column"> + <div *ngIf="templateDescription"> + <p *ngIf="templateName">{{templateName}}</p> + <p class="text-justify">{{templateDescription}}</p> + </div> + <div *ngIf="templatePublications"> + <p>Publication(s)</p> + <div *ngFor="let tp of templatePublications" class="text-justify"> + <a [href]="tp['doi']" target="_blank">{{tp['citation']}}</a> + </div> + <hr *ngIf="parcellationPublications"> + </div> + <div *ngIf="parcellationDescription"> + <p *ngIf="parcellationName">{{parcellationName}}</p> + <p class="text-justify">{{parcellationDescription}}</p> + </div> + + <div *ngIf="parcellationPublications"> + <p>Publication(s)</p> + <div *ngFor="let pp of parcellationPublications" class="text-justify"> + <a [href]="pp['doi']" target="_blank">{{pp['citation']}}</a> + </div> + </div> + + <div class="align-self-end"> + <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications()">Explore <i class="fas fa-external-link-alt"></i></button> + <button mat-raised-button color="primary" class="downloadPublications" (click)="downloadPublications()" [disabled] = "downloadingProcess" > + Download + <span *ngIf="niiFileSize > 0">(.nii {{niiFileSize/1000000 | number:'.1-2'}} Mb) </span> + <i class="fas" [ngClass]="!downloadingProcess? 'fa-download' :'fa-spinner fa-pulse'"></i> + </button> + </div> +</div> \ No newline at end of file diff --git a/src/ui/signinBanner/signinBanner.components.ts b/src/ui/signinBanner/signinBanner.components.ts index 7285cc0ef16df99267b1dc6746d59cbf074b364d..80fc79fb55464aaabb80b0afdaf40b06e70f46a3 100644 --- a/src/ui/signinBanner/signinBanner.components.ts +++ b/src/ui/signinBanner/signinBanner.components.ts @@ -1,4 +1,4 @@ -import { Component, ChangeDetectionStrategy, OnDestroy, OnInit, Input } from "@angular/core"; +import {Component, ChangeDetectionStrategy, OnDestroy, OnInit, Input, ViewChild, TemplateRef} from "@angular/core"; import { AtlasViewerConstantsServices } from "src/atlasViewer/atlasViewer.constantService.service"; import { AuthService, User } from "src/services/auth.service"; import { Store, select } from "@ngrx/store"; @@ -34,6 +34,12 @@ export class SigninBanner implements OnInit, OnDestroy{ selectedTemplate: any @Input() darktheme: boolean + @ViewChild('publicationTemplate', {read:TemplateRef}) publicationTemplate: TemplateRef<any> + + dismissToastHandler: any + chosenTemplateIndex: number + chosenParcellationIndex: number + constructor( private constantService: AtlasViewerConstantsServices, private authService: AuthService, @@ -174,6 +180,19 @@ export class SigninBanner implements OnInit, OnDestroy{ }) } + showInfoToast($event, toastType) { + this.chosenTemplateIndex = toastType === 'template'? $event : null + this.chosenParcellationIndex = toastType === 'parcellation'? $event : null + + if (this.dismissToastHandler) { + this.dismissToastHandler() + this.dismissToastHandler = null + } + this.dismissToastHandler = this.toastService.showToast(this.publicationTemplate, { + timeout: 7000 + }) + } + get isMobile(){ return this.constantService.mobile } diff --git a/src/ui/signinBanner/signinBanner.template.html b/src/ui/signinBanner/signinBanner.template.html index 59c5d3d4a1f6da3959292788de5ff73e75ebb533..c962b4c2d0a40c2f1168dd4b9e24f34183dd7125 100644 --- a/src/ui/signinBanner/signinBanner.template.html +++ b/src/ui/signinBanner/signinBanner.template.html @@ -10,7 +10,8 @@ [inputArray]="loadedTemplates$ | async | filterNull" [isMobile] = "isMobile" [ngClass]="isMobile ? flexItemIsMobileClass : flexItemIsDesktopClass" - [darktheme] ="darktheme"> + [darktheme] ="darktheme" + (listItemButtonClicked)="showInfoToast($event, 'template')"> </dropdown-component> <ng-container *ngIf="selectedTemplate$ | async as selectedTemplate"> @@ -23,7 +24,8 @@ [inputArray]="selectedTemplate.parcellations" [isMobile] = "isMobile" [ngClass]="isMobile ? flexItemIsMobileClass : flexItemIsDesktopClass" - [darktheme] ="darktheme"> + [darktheme] ="darktheme" + (listItemButtonClicked)="showInfoToast($event, 'parcellation')">> </dropdown-component> <region-hierarchy @@ -76,18 +78,28 @@ </div> </div> +</div> - - <div *ngIf="!selectedTemplate && !isMobile" class="login-button-panel-splash"> - <div - (click)="showSignin()" - class="login-button-splash"> - <button mat-button>Log In</button> - </div> - <div (click)="showHelp()" class="login-button-splash"> - <button mat-button>Help</button> +<ng-template #publicationTemplate> + <div *ngIf="loadedTemplates$ | async as loadedTemplates"> + <div *ngIf="chosenTemplateIndex !== null; else parcellationToast"> + <reference-toast-component *ngIf="loadedTemplates[chosenTemplateIndex]['properties'] && (loadedTemplates[chosenTemplateIndex]['properties']['description'] || loadedTemplates[chosenTemplateIndex]['properties']['publications'])" + [templateName] = "loadedTemplates[chosenTemplateIndex]['name'] ? loadedTemplates[chosenTemplateIndex]['name'] : null" + [templateDescription] = "loadedTemplates[chosenTemplateIndex]['properties']['description']? loadedTemplates[chosenTemplateIndex]['properties']['description'] : null" + [templatePublications] = "loadedTemplates[chosenTemplateIndex]['properties']['publications']? loadedTemplates[chosenTemplateIndex]['properties']['publications']: null"> + </reference-toast-component> </div> + <ng-template #parcellationToast> + <div *ngIf="(selectedTemplate$ | async) as selectedTemplate"> + <div *ngIf="selectedTemplate.parcellations[chosenParcellationIndex]['properties'] && (selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description'] || selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications'])"> + <reference-toast-component + [parcellationName] = "selectedTemplate.parcellations[chosenParcellationIndex]['name']? selectedTemplate.parcellations[chosenParcellationIndex]['name'] : null" + [parcellationDescription] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['description'] : null" + [parcellationPublications] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['publications']: null" + [parcellationNifti] = "selectedTemplate.parcellations[chosenParcellationIndex]['properties']['nifti']? selectedTemplate.parcellations[chosenParcellationIndex]['properties']['nifti'] : null"> + </reference-toast-component> + </div> + </div> + </ng-template> </div> - - -</div> \ No newline at end of file +</ng-template> \ No newline at end of file diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts index 33649a5175c811658c903161efd006fe62004525..868912b551cb0c72e77aac85ebca80204d0abf5d 100644 --- a/src/ui/ui.module.ts +++ b/src/ui/ui.module.ts @@ -46,6 +46,7 @@ import { StatusCardComponent } from "./nehubaContainer/statusCard/statusCard.com import { CookieAgreement } from "./cookieAgreement/cookieAgreement.component"; import { KGToS } from "./kgtos/kgtos.component"; import { AngularMaterialModule } from "./sharedModules/angularMaterial.module"; +import {ReferenceToastComponent} from "src/ui/referenceToast/referenceToast.component"; @NgModule({ @@ -82,6 +83,7 @@ import { AngularMaterialModule } from "./sharedModules/angularMaterial.module"; StatusCardComponent, CookieAgreement, KGToS, + ReferenceToastComponent, /* pipes */ GroupDatasetByRegion, @@ -126,7 +128,8 @@ import { AngularMaterialModule } from "./sharedModules/angularMaterial.module"; CookieAgreement, KGToS, AngularMaterialModule, - StatusCardComponent + StatusCardComponent, + ReferenceToastComponent ] })