diff --git a/landingPages/result/resultLanding.component.html b/landingPages/result/resultLanding.component.html index f43629b5..ee67a757 100644 --- a/landingPages/result/resultLanding.component.html +++ b/landingPages/result/resultLanding.component.html @@ -71,8 +71,7 @@
  • @@ -165,8 +164,7 @@
    diff --git a/utils/dataTransfer/transferData.component.html b/utils/dataTransfer/transferData.component.html index 2a478607..8fd50ef7 100644 --- a/utils/dataTransfer/transferData.component.html +++ b/utils/dataTransfer/transferData.component.html @@ -9,11 +9,11 @@ - +
    -
    +
    In order to send data to a Cloud Storage, you would need to be authenticated, please login via EGI check-in.
    @@ -22,18 +22,18 @@
    -
    +
    You have requested to send the data corresponding to the DOI {{selectedSourceUrl.split(doiPrefix)[1]}} to a cloud storage using the EOSC Data Transfer service
    -
    +
    -

    Available Zenodo DOI URLs:

    -
    Available DOI URLs:

    +
    -
    +
    {{this.downloadElements.length}} files found:
    -
    +
    • {{ element.name}}
    • @@ -43,53 +43,100 @@
    -
    -

    Please select the Destination Storage type:

    -
    - -

    Provide the corresponding storage destination path:

    -
    -
    -

    or browse to - select a folder.

    -
    - +
    + + + + + + + +

    Destination storage type:

    +
    + +

    Destination system (e.g. hostname:8080):

    +
    + + +

    Authentication:

    +
    +
    +
    - -
    - - -

    Comming soon!

    +
    +

    Destination path (e.g. /folder1/folder2):

    +
    + +

    or browse to + select a folder.

    +
    + +
    + + + +

    Comming soon!

    +
    + +
    + + + *I have read and accepted the data protection policy here. +
    + +
    + +
    +
    -
    -
    - - - + + +
    +
    + + + +
    +
    + + + +
    -
    -
    +
    -
    - -
    + + + +
    - + @@ -117,7 +164,8 @@
    • - + @@ -144,7 +192,7 @@ title="Expand/ Collapse"> {{folder.name?folder.name:folder.accessUrl.split(selectedDestination.url)[1]}} + class="uk-width-expand uk-text-truncate uk-margin-small-left">{{folder.name?folder.name:folder.accessUrl.split(destinationUrl)[1]}}
    diff --git a/utils/dataTransfer/transferData.component.ts b/utils/dataTransfer/transferData.component.ts index 699a5bd0..1062e910 100644 --- a/utils/dataTransfer/transferData.component.ts +++ b/utils/dataTransfer/transferData.component.ts @@ -1,12 +1,15 @@ -import {Component, Input, ViewChild} from '@angular/core'; -import {Subscriber} from "rxjs"; +import {ChangeDetectorRef, Component, Input, ViewChild} from '@angular/core'; +import {interval, Subscriber, Subscription} from "rxjs"; import {HttpClient, HttpHeaders} from "@angular/common/http"; import {AbstractControl, ValidatorFn, Validators} from "@angular/forms"; import {Location} from '@angular/common'; import {COOKIE} from "../../login/utils/helper.class"; import {Router} from "@angular/router"; import {properties} from "../../../../environments/environment"; -import {delay, repeat} from "rxjs/operators"; +import {delay, repeat, startWith, switchMap} from "rxjs/operators"; +import {StringUtils} from "../string-utils.class"; +import {HelperFunctions} from "../HelperFunctions.class"; +import {FullScreenModalComponent} from "../modal/full-screen-modal/full-screen-modal.component"; declare var UIkit; @Component({ @@ -33,30 +36,58 @@ declare var UIkit; }) export class EGIDataTransferComponent { subscriptions = []; + statusSub: Subscription[] = []; accessToken = null; @Input() dois; - loginURL = properties.environment == "development"? "http://rudie.di.uoa.gr:8580/openid_connect_login":"https://explore.eosc-portal.eu/egi-login-service/openid_connect_login" + loginURL = properties.eoscDataTransferLoginUrl; sourceUrls = []; selectedSourceUrl = null; + destinationUrl = ""; + destinationAuthUser = ""; + destinationAuthPass = ""; destinationPath = ""; - destinationOptions = properties.eoscDataTransferDestinations; - selectedDestination = null; + destinationOptions = null;//properties.eoscDataTransferDestinations.map(dest => {return {"label": dest.destination, "value": dest}}); + selectedDestination:{ kind: string, destination: string, description: string, authType: 'token' | 'password' | 'keys', + protocol: string, canBrowse: boolean, transferWith: string} = null; folders = {}; files = {}; + requests: number = 0; downloadElements = null; @Input() isOpen = false; - @Input() selectedDestinationId = "dcache"; - @ViewChild('egiTransferModal') egiTransferModal; + // @Input() selectedDestinationId = "dcache"; + @ViewChild('egiTransferModal') egiTransferModal: FullScreenModalComponent; APIURL = properties.eoscDataTransferAPI; - status: "loading" | "success" | "errorParser" | "errorUser" | "errorTransfer" | "init" | "canceled" = "init"; + // status: "loading" | "success" | "errorParser" | "errorUser" | "errorTransfer" | "init" | "canceled" = "init"; + status: "unused" | "staging" | "submitted" | "active" | "succeeded" | "partial" | "failed" | "canceled" | "errorParser" | "errorUser" | "init" = "init"; + + // unused("unused"), + // active("active"), + // succeeded("succeeded"), + // failed("failed"), + // canceled("canceled"); + message; doiPrefix = properties.doiURL; - validators = [Validators.required, this.pathValidator() /*StringUtils.urlValidator()*/]; + pathValidators = [Validators.required, this.pathValidator() /*StringUtils.urlValidator()*/]; + // URLValidators = [Validators.required, StringUtils.urlValidator()]; + URLValidators = [Validators.required]; jobId = null; statusMessage = null; jobStatus; - constructor(private http: HttpClient, private location: Location, private _router: Router) { + privacyAccepted: boolean = false; + + public hostnameRegex = '[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|' + + '[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|' + + '[a-zA-Z0-9]+\.[^\s]{2,}|' + + '[a-zA-Z0-9]+\.[^\s]{2,}' + + constructor(private http: HttpClient, private location: Location, private _router: Router, private cdr: ChangeDetectorRef) { + + } + + ngOnInit() { + this.URLValidators = [Validators.required, Validators.pattern(this.hostnameRegex)]; } ngAfterViewInit() { @@ -71,25 +102,37 @@ export class EGIDataTransferComponent { subscription.unsubscribe(); } }); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); } open(){ this.accessToken = COOKIE.getCookie("EGIAccessToken"); if(this.accessToken) { - if (this.selectedDestinationId) { - for (let option of this.destinationOptions) { - if (this.selectedDestinationId == option.value.id) { - this.selectedDestination = option.value; - } + // if (this.selectedDestinationId) { + // for (let option of this.destinationOptions) { + // if (this.selectedDestinationId == option.value.destination) { + // this.selectedDestination = option.value; + // } + // } + // } else { + // this.selectedDestination = this.destinationOptions[0].value; + // } + + let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); + this.subscriptions.push(this.http.get(this.APIURL + "/storage/types", {headers: headers}).subscribe( + (res: Array) => { + this.destinationOptions = res.map(dest => {return {"label": dest.description, "value": dest}}); + this.selectedDestination = res[0]; } - } else { - this.selectedDestination = this.destinationOptions[0].value; - } + )); + for (let doi of this.dois) { - if (doi.indexOf("zenodo.") != -1) { this.sourceUrls.push(this.doiPrefix + doi); - } } try { this.sourceUrls.sort(function (a, b) { @@ -103,13 +146,15 @@ export class EGIDataTransferComponent { this.parse(); } this.isOpen = true; + this.egiTransferModal.back = true; this.egiTransferModal.cancelButton = false; - this.egiTransferModal.okButton = true; + this.egiTransferModal.okButton = false; this.egiTransferModal.okButtonText = ">> Transfer"; - this.egiTransferModal.alertTitle = "EOSC data transfer service [demo]"; - this.egiTransferModal.stayOpen = true; + this.egiTransferModal.title = "EOSC Data Transfer [demo]"; this.init(); - this.egiTransferModal.open(); + if(typeof document !== 'undefined') { + this.egiTransferModal.open(); + } } close(){ if(this.isOpen) { @@ -125,34 +170,52 @@ export class EGIDataTransferComponent { } init(){ this.destinationPath = ""; - this.selectedDestination = this.destinationOptions[0].value; + // this.selectedDestination = this.destinationOptions[0].value; this.selectedSourceUrl = this.sourceUrls[0]; this.message = null; this.status = "init"; this.jobId = null; - this.statusMessage = null; + // this.statusMessage = null; + this.statusMessage = "primary"; + this.requests = 0; + this.folders = {}; + this.files = {}; + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); } checkin(){ window.location.href = this.loginURL+"?redirect="+ encodeURIComponent(window.location.href + (window.location.href.indexOf("&egiTransfer=t")!=-1?"":"&egiTransfer=t")); } parse(){ - this.status = "loading"; + this.status = "active"; this.message = null; this.downloadElements = []; - this.subscriptions.push(this.http.get(this.APIURL + "/parser?doi=" + encodeURIComponent(this.selectedSourceUrl)).subscribe( + let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); + this.subscriptions.push(this.http.get(this.APIURL + "/parser?doi=" + encodeURIComponent(this.selectedSourceUrl), {headers: headers}).subscribe( res => { + // res['elements'].forEach(element => { + // if(element.downloadUrl && element.name) { + // this.downloadElements.push(element); + // } + // }) this.downloadElements= res['elements'] // console.log(this.downloadElements) - this.status = "init"; + this.status = "init"; }, error => { this.status = "errorParser"; - this.message = "Couldn't get download URLs from zenodo"; - UIkit.notification("Couldn't get download URLs from zenodo", { + this.message = error.error && error.error.id && error.error.id == 'doiNotSupported'?'DOI not supported.':( error.error && error.error.description && error.error.description? (error.error.description+'.'):'Error parsing information.') ; + this.statusMessage = "danger"; + this.cdr.detectChanges(); + HelperFunctions.scrollToId("transferAlert"); + /* UIkit.notification(this.message, { status: 'error', timeout: 3000, pos: 'bottom-right' - }); + });*/ } )); @@ -161,9 +224,11 @@ export class EGIDataTransferComponent { transfer() { // console.log(this.selectedDestination) - this.status = "loading"; + this.status = "active"; + this.message = ""; let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.get(this.APIURL + "/user/info?dest="+this.selectedDestination.id, {headers: headers}).subscribe( + + this.subscriptions.push(this.http.get(this.APIURL + "/user/info?dest="+this.selectedDestination.destination, {headers: headers}).subscribe( res => { // console.log(res) let body = { @@ -177,10 +242,9 @@ export class EGIDataTransferComponent { // console.log(this.selectedDestination) for (let element of this.downloadElements) { - let file = { "sources": [element['downloadUrl']], - "destinations": [this.selectedDestination.url + this.destinationPath + element.name], + "destinations": [(this.selectedDestination.protocol+"://") + this.destinationUrl + this.destinationPath + (this.destinationPath.endsWith("/") ? "" : "/") + ((element.path && element.path != "/") ? element.path : "") + element.name], }; //TODO priority? checksum? filesize? @@ -189,20 +253,28 @@ export class EGIDataTransferComponent { } let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); + if(this.selectedDestination.authType != "token" && this.destinationAuthPass.length > 0 && this.destinationAuthUser.length > 0){ + headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken, + 'Authorization-Storage': btoa(this.destinationAuthUser + ':' + this.destinationAuthPass)}); + } this.subscriptions.push(this.http.post(this.APIURL + "/transfers" ,body, {headers: headers}).subscribe( res => { // console.log(res) - UIkit.notification('Data transfer has began! ', { - status: 'success', - timeout: 6000, - pos: 'bottom-right' - }); + // UIkit.notification('Data transfer has began! ', { + // status: 'success', + // timeout: 6000, + // pos: 'bottom-right' + // }); + this.jobId = res['jobId']; - this.status = "success"; - this.egiTransferModal.okButton = false; + this.getStatus(); + this.status = "active"; + this.statusMessage = "primary"; + + // this.egiTransferModal.okButton = false; this.message = ` -
    Transfer of ` + this.downloadElements.length + ` files to `+this.selectedDestination.label+` has began.`; +
    Transfer of ` + this.downloadElements.length + ` files to `+this.selectedDestination.description+` has began.`; /*this.message += `
      `; @@ -219,27 +291,37 @@ export class EGIDataTransferComponent { this.message += `
    ` - // this.getStatus(true) + + this.cdr.detectChanges(); + HelperFunctions.scrollToId("transferAlert"); + + // this.getStatus(true) }, error => { - this.status = "errorTransfer"; - this.message = "Couldn't transfer files"; - UIkit.notification("Couldn't transfer files", { - status: 'error', - timeout: 6000, - pos: 'bottom-right' - }); + this.status = "failed"; + this.message = "Files could not be transfered."; + this.statusMessage = "danger"; + this.cdr.detectChanges(); + HelperFunctions.scrollToId("transferAlert"); + // UIkit.notification("Couldn't transfer files", { + // status: 'error', + // timeout: 6000, + // pos: 'bottom-right' + // }); } )); }, error => { this.status = "errorUser"; - this.message = "User can't be authenticated!"; - UIkit.notification("User can't be authenticated!", { - status: 'error', - timeout: 6000, - pos: 'bottom-right' - }); + this.message = "User cannot be authenticated."; + this.statusMessage = "danger"; + this.cdr.detectChanges(); + HelperFunctions.scrollToId("transferAlert"); + // UIkit.notification("User can't be authenticated!", { + // status: 'error', + // timeout: 6000, + // pos: 'bottom-right' + // }); } )); @@ -247,50 +329,131 @@ export class EGIDataTransferComponent { getStatus(updateTransferMessage:boolean = false){ if(this.jobId){ - + this.requests = 10; + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); let source = this.http.get(this.APIURL + "/transfer/" +this.jobId , {headers: headers}).pipe(delay(5000)); - this.subscriptions.push(source.pipe(repeat(3)).subscribe( - res => { - this.jobStatus = res; - this.message = ` - -
    Transfer of ` + this.downloadElements.length + ` files to `+this.selectedDestination.label+` has began.`; - /*this.message += `
    -
      - `; - // TODO LATER we can call status for each file and see if the transfer has been complete - for(let element of this.downloadElements){ - // console.log(element) - // this.message += `
    • `+ element.name+ `
    • `; - this.message += `
    • `+ element.name+ `
    • `; - } - this.message += ` -
    -
    -
    `*/ - this.message += ` - -
    `; - console.log(res) - this.statusMessage = res['jobState'] + (res['reason']?(" :" + res['reason']):""); - UIkit.notification('got status! ', { - status: 'success', - timeout: 6000, - pos: 'bottom-right' - }); - + let source2 = interval(5000) // request status every 5 secs + .pipe( + startWith(2000), // first call after 2 secs + switchMap(() => this.http.get(this.APIURL + "/transfer/" +this.jobId , {headers: headers})) + ); + this.statusSub.push(source2.subscribe((res: any) => { + this.requests--; + if(this.status != res.jobState) { + this.status = res.jobState; + this.jobStatus = res; + this.message = ` + +
    Transfer of ` + this.downloadElements.length + ` files to ` + this.selectedDestination.description + ` has began.`; + /*this.message += `
    +
      + `; + // TODO LATER we can call status for each file and see if the transfer has been complete + for(let element of this.downloadElements){ + // console.log(element) + // this.message += `
    • `+ element.name+ `
    • `; + this.message += `
    • `+ element.name+ `
    • `; + } + this.message += ` +
    +
    +
    `*/ + this.message += ` + +
    `; + this.message += "
    Transfer status: "+res.jobState+".
    "; + this.statusMessage = "primary"; + //this.statusMessage = res['jobState'] + (res['reason'] ? (" :" + res['reason']) : ""); + if(this.status == "partial") { + this.message = "At least one of the selected files was successfully transfered."; + this.statusMessage = "success"; + //this.statusSub.unsubscribe(); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + this.requests = 0; + } else if(this.status == "succeeded") { + this.message = "Transfer successfully completed!"; + this.statusMessage = "success"; + //this.statusSub.unsubscribe(); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + this.requests = 0; + // UIkit.notification('Transfer successfully completed! ', { + // status: 'success', + // timeout: 6000, + // pos: 'bottom-right' + // }); + } else if(this.status == "failed") { + this.message = "Transfer failed."; + this.statusMessage = "danger"; + //this.statusSub.unsubscribe(); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + this.requests = 0; + // UIkit.notification('Transfer failed', { + // status: 'danger', + // timeout: 6000, + // pos: 'bottom-right' + // }); + } else if(this.requests <= 0 || (this.status != "active" && this.status != "submitted" && this.status != "staging")) { + this.message = "Transfer status: "+this.status+"."; + this.statusMessage = "warning"; + //this.statusSub.unsubscribe(); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + this.requests = 0; + // UIkit.notification('Transfer completed with status: '+this.status, { + // status: 'warning', + // timeout: 6000, + // pos: 'bottom-right' + // }); + } + } + if(this.requests <= 0) { + this.message = "Transfer status: "+this.status+"."; + this.statusMessage = "warning"; + //this.statusSub.unsubscribe(); + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + } }, error => { - this.status = "errorTransfer"; - this.message = "Couldn't get status "; - UIkit.notification("Couldn't get status", { - status: 'error', - timeout: 6000, - pos: 'bottom-right' - }); + this.status = "failed"; + this.message = "Status of the transfer could not be retrieved."; + this.statusMessage = "danger"; + this.statusSub.forEach(sub => { + if(sub instanceof Subscriber) { + sub.unsubscribe(); + } + }); + this.requests = 0; + // UIkit.notification("Couldn't get status", { + // status: 'error', + // timeout: 6000, + // pos: 'bottom-right' + // }); } )); @@ -303,7 +466,6 @@ export class EGIDataTransferComponent { let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); this.subscriptions.push(this.http.delete(this.APIURL + "/transfer/" +this.jobId , {headers: headers}).subscribe( res => { - console.log(res); this.jobStatus = res; this.statusMessage = res['jobState'] + (res['reason']?(" :" + res['reason']):""); this.jobId = null; @@ -314,7 +476,7 @@ export class EGIDataTransferComponent { } hasBrowse(){ let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.get(this.APIURL + "/storage/info?dest="+this.selectedDestination.id+"&seUrl="+encodeURIComponent(this.selectedDestination.url + this.destinationPath) , {headers: headers}).subscribe( + this.subscriptions.push(this.http.get(this.APIURL + "/storage/info?dest="+this.selectedDestination.destination+"&seUrl="+encodeURIComponent((this.selectedDestination.protocol+'://') + this.destinationUrl + this.destinationPath) , {headers: headers}).subscribe( res => { console.log(res); } @@ -324,7 +486,7 @@ export class EGIDataTransferComponent { getFolder(folderPath){ //TODO is this necessary? let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.get(this.APIURL + "/storage/folder?dest="+this.selectedDestination.id+"&seUrl="+encodeURIComponent(this.selectedDestination.url + folderPath) , {headers: headers}).subscribe( + this.subscriptions.push(this.http.get(this.APIURL + "/storage/folder?dest="+this.selectedDestination.destination+"&seUrl="+encodeURIComponent((this.selectedDestination.protocol + '://') + this.destinationUrl + folderPath) , {headers: headers}).subscribe( res => { this.folders[folderPath]= res; this.folders[folderPath]['isOpen'] = true; @@ -339,7 +501,7 @@ export class EGIDataTransferComponent { } this.getFolder(folderPath); let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.get(this.APIURL + "/storage/folder/list?dest="+this.selectedDestination.id+"&folderUrl="+encodeURIComponent(this.selectedDestination.url + folderPath) , {headers: headers}).subscribe( + this.subscriptions.push(this.http.get(this.APIURL + "/storage/folder/list?dest="+this.selectedDestination.destination+"&folderUrl="+encodeURIComponent((this.selectedDestination.protocol + '://') + this.destinationUrl + folderPath) , {headers: headers}).subscribe( res => { this.files[folderPath]= res['elements']; } @@ -348,8 +510,8 @@ export class EGIDataTransferComponent { } createFolder(){ let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.post(this.APIURL + "/storage/folder?dest="+this.selectedDestination.id+"&seUrl="+ - encodeURIComponent(this.selectedDestination.url + this.destinationPath + "test1/") , {headers: headers}).subscribe( + this.subscriptions.push(this.http.post(this.APIURL + "/storage/folder?dest="+this.selectedDestination.destination+"&seUrl="+ + encodeURIComponent(this.destinationUrl + this.destinationPath + "test1/") , {headers: headers}).subscribe( res => { console.log(res); } @@ -359,7 +521,7 @@ export class EGIDataTransferComponent { deleteFolder(){ let headers = new HttpHeaders({'Authorization': 'Bearer '+this.accessToken}); - this.subscriptions.push(this.http.delete(this.APIURL + "/storage/folder?dest="+this.selectedDestination.id+"&seUrl="+encodeURIComponent(this.selectedDestination.url + this.destinationPath + "test1/") , {headers: headers}).subscribe( + this.subscriptions.push(this.http.delete(this.APIURL + "/storage/folder?dest="+this.selectedDestination.destination+"&seUrl="+encodeURIComponent(this.destinationUrl + this.destinationPath + "test1/") , {headers: headers}).subscribe( res => { console.log(res); } @@ -373,14 +535,23 @@ export class EGIDataTransferComponent { pathValidator(): ValidatorFn { return (control: AbstractControl): { [key: string]: string } | null => { if (!this.validatePath()) { - return {'error': 'Path should start and end with "/" e.g /path/'}; + return {'error': 'Path should start with "/"'}; } return null; } } validatePath():boolean { - let exp1 = /^\/([A-z0-9-_+]+\/)*$/g; + let exp1 = /^\/([A-z0-9-_+]+\/?)*$/g; return (this.destinationPath.length > 0 && this.destinationPath.match(exp1) != null) } + + validateDestinationUrl():boolean { + return (this.destinationUrl.length > 0 && new RegExp(this.hostnameRegex).test(this.destinationUrl)); + } + + // public sourceUrlValidators() { + // this.URLValidators = []; + // this.URLValidators = [Validators.required, Validators.pattern(this.hostnameRegex)]; + // } } diff --git a/utils/dataTransfer/transferData.module.ts b/utils/dataTransfer/transferData.module.ts index d78dd6d2..9267d368 100644 --- a/utils/dataTransfer/transferData.module.ts +++ b/utils/dataTransfer/transferData.module.ts @@ -4,10 +4,11 @@ import {FormsModule} from '@angular/forms'; import {EGIDataTransferComponent} from "./transferData.component"; import {InputModule} from "../../sharedComponents/input/input.module"; import {AlertModalModule} from "../modal/alertModal.module"; +import {FullScreenModalModule} from "../modal/full-screen-modal/full-screen-modal.module"; @NgModule({ imports: [ - CommonModule, FormsModule, InputModule, AlertModalModule + CommonModule, FormsModule, InputModule, AlertModalModule, FullScreenModalModule ], declarations: [ diff --git a/utils/modal/full-screen-modal/full-screen-modal.component.ts b/utils/modal/full-screen-modal/full-screen-modal.component.ts index 750286a0..07c542fb 100644 --- a/utils/modal/full-screen-modal/full-screen-modal.component.ts +++ b/utils/modal/full-screen-modal/full-screen-modal.component.ts @@ -31,12 +31,14 @@ declare var ResizeObserver; class="uk-width-expand uk-padding-small uk-padding-remove-vertical uk-flex uk-flex-center">

    {{title}}

    -
    +
    -
    @@ -58,6 +60,7 @@ export class FullScreenModalComponent implements AfterViewInit, OnDestroy { @Input() classBody: string = 'uk-container-large'; back: boolean = false; title: string; + cancelButton: boolean = true; okButton: boolean = false; okButtonText = 'OK'; @Input() diff --git a/utils/properties/env-properties.ts b/utils/properties/env-properties.ts index 5528da7b..cacc7cb1 100644 --- a/utils/properties/env-properties.ts +++ b/utils/properties/env-properties.ts @@ -143,6 +143,7 @@ export interface EnvProperties { egiNotebookLink?: string; connectPortalUrl?; eoscDataTransferAPI?; + eoscDataTransferLoginUrl?; eoscDataTransferDestinations?; hasMachineCache?: boolean; }