Skip to content

Commit fb1a202

Browse files
Merge b564fa0 into 407e35f
2 parents 407e35f + b564fa0 commit fb1a202

11 files changed

+179
-18
lines changed

src/app/app-config.module.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ describe("AppConfigModule", () =>{
1313
imports: [AppConfigModule],
1414
});
1515
});
16-
16+
1717
it("initializes", () => {
1818
const module = TestBed.inject(AppConfigModule);
1919
expect(module).toBeTruthy();
2020
});
2121

22-
22+
2323
describe("initial environment", () =>{
24-
24+
2525
it("initialized", () => {
2626
expect(environment.loginFormEnabled).toBeTruthy();
2727
expect(environment.oAuth2Endpoints.length).toEqual(0);
@@ -40,6 +40,7 @@ describe("AppConfigModule", () =>{
4040
it ("constructs", () => {
4141
const appConfig: AppConfig = {
4242
lbBaseURL: "lbBaseURL",
43+
fileserverButtonLabel: "Download",
4344
externalAuthEndpoint: "externalAuthEndpoint",
4445
fileserverBaseURL: "fileserverBaseURL",
4546
synapseBaseUrl: "synapseBaseUrl",
@@ -97,10 +98,10 @@ describe("AppConfigModule", () =>{
9798
expect(appConfig.disabledDatasetColumns[0]).toEqual("disabledDatasetColumns");
9899
});
99100
});
100-
101+
101102
describe("OAuth2Endpoint", () => {
102103

103-
104+
104105

105106
it("has initial values", () => {
106107
const endpoint2: OAuth2Endpoint = new OAuth2Endpoint();
@@ -114,7 +115,7 @@ describe("AppConfigModule", () =>{
114115
displayText: "test",
115116
authURL: "foo/bar"
116117
};
117-
118+
118119
expect(endpoint.displayText).toEqual("test");
119120
expect(endpoint.authURL).toEqual("foo/bar");
120121
expect(endpoint.displayImage).toBeUndefined();

src/app/app-config.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class AppConfig {
1919
lbBaseURL = "";
2020
externalAuthEndpoint: string | null = null;
2121
fileserverBaseURL: string | null = null;
22+
fileserverButtonLabel: string | null = null;
2223
synapseBaseUrl: string | null = null;
2324
riotBaseUrl: string | null = null;
2425
jupyterHubUrl: string | null = null;
@@ -69,6 +70,7 @@ export const APP_DI_CONFIG: AppConfig = {
6970
lbBaseURL: environment.lbBaseURL ?? "http://localhost:3000",
7071
externalAuthEndpoint: environment.externalAuthEndpoint ?? null,
7172
fileserverBaseURL: environment.fileserverBaseURL ?? null,
73+
fileserverButtonLabel: environment.fileserverButtonLabel ?? "Download",
7274
synapseBaseUrl: environment.synapseBaseUrl ?? null,
7375
riotBaseUrl: environment.riotBaseUrl ?? null,
7476
jupyterHubUrl: environment.jupyterHubUrl ?? null,
@@ -126,7 +128,7 @@ export const APP_DI_CONFIG: AppConfig = {
126128
landingPage: environment.landingPage ?? null,
127129
editPublishedData: (environment.editPublishedData === undefined) ? true: environment.editPublishedData,
128130
oAuth2Endpoints: environment.oAuth2Endpoints ?? [],
129-
loginFormEnabled: (environment.loginFormEnabled == undefined) ? true: environment.loginFormEnabled
131+
loginFormEnabled: (environment.loginFormEnabled == undefined) ? true: environment.loginFormEnabled,
130132
};
131133

132134
@NgModule({

src/app/datasets/datafiles/datafiles.component.html

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
</div>
2222
</ng-template>
2323

24-
<ng-template [ngIf]="tableData && maxFileSize">
24+
<ng-template [ngIf]="tableData">
2525
<div class="selected" fxLayout="row" fxLayoutAlign="space-evenly end">
2626
<div fxFlex="auto" style="margin-bottom: 0.5em;">
2727
Selected: {{ selectedFileSize | filesize
@@ -58,7 +58,8 @@ <h3>No datafiles linked to this dataset</h3>
5858
[name]="'files[' + i + ']'"
5959
[value]="file"
6060
/>
61-
<button
61+
<ng-template [ngIf]="multipleDownloadAction">
62+
<button
6263
mat-raised-button
6364
class="download-button"
6465
type="submit"
@@ -67,6 +68,8 @@ <h3>No datafiles linked to this dataset</h3>
6768
>
6869
Download All
6970
</button>
71+
</ng-template>
72+
7073
</form>
7174

7275
<form
@@ -84,7 +87,8 @@ <h3>No datafiles linked to this dataset</h3>
8487
[name]="'files[' + i + ']'"
8588
[value]="file"
8689
/>
87-
<button
90+
<ng-template [ngIf]="multipleDownloadAction">
91+
<button
8892
mat-raised-button
8993
class="download-button"
9094
type="submit"
@@ -95,10 +99,35 @@ <h3>No datafiles linked to this dataset</h3>
9599
>
96100
Download Selected
97101
</button>
102+
</ng-template>
98103
</form>
104+
105+
<ng-template [ngIf]="(isLoggedIn$ | async) === false && fileserverBaseURL">
106+
<button
107+
mat-raised-button
108+
class="download-button"
109+
type="submit"
110+
color="accent"
111+
[disabled]="isNoneSelected"
112+
(click)="openDialog()"
113+
>
114+
{{ fileserverButtonLabel}}
115+
</button>
116+
</ng-template>
117+
<ng-template [ngIf]="(isLoggedIn$ | async) && fileserverBaseURL">
118+
<a
119+
mat-raised-button
120+
class="download-button"
121+
color="accent"
122+
[href]="getFileTransferLink()" target="_blank"
123+
>
124+
{{ fileserverButtonLabel}}
125+
</a>
126+
</ng-template>
127+
128+
99129
<div style="clear: both;"></div>
100130
</div>
101-
102131
<app-table
103132
[data]="tableData"
104133
[columns]="tableColumns"

src/app/datasets/datafiles/datafiles.component.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import { PipesModule } from "shared/pipes/pipes.module";
99
import { RouterModule } from "@angular/router";
1010
import { StoreModule } from "@ngrx/store";
1111
import { CheckboxEvent } from "shared/modules/table/table.component";
12-
import { MockUserApi } from "shared/MockStubs";
12+
import { MockMatDialogRef, MockUserApi } from "shared/MockStubs";
1313
import { MatCheckboxChange } from "@angular/material/checkbox";
1414
import { MatIconModule } from "@angular/material/icon";
1515
import { MatButtonModule } from "@angular/material/button";
16+
import { MatDialogModule, MatDialogRef } from "@angular/material/dialog";
1617

1718
describe("DatafilesComponent", () => {
1819
let component: DatafilesComponent;
@@ -29,6 +30,7 @@ describe("DatafilesComponent", () => {
2930
MatTableModule,
3031
PipesModule,
3132
ReactiveFormsModule,
33+
MatDialogModule,
3234
RouterModule,
3335
RouterModule.forRoot([], { relativeLinkResolution: "legacy" }),
3436
StoreModule.forRoot({}),
@@ -37,7 +39,9 @@ describe("DatafilesComponent", () => {
3739
});
3840
TestBed.overrideComponent(DatafilesComponent, {
3941
set: {
40-
providers: [{ provide: UserApi, useClass: MockUserApi }],
42+
providers: [
43+
{ provide: UserApi, useClass: MockUserApi },
44+
{ provide: MatDialogRef, useClass: MockMatDialogRef }]
4145
},
4246
});
4347
TestBed.compileComponents();

src/app/datasets/datafiles/datafiles.component.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { APP_CONFIG, AppConfig } from "app-config.module";
2-
import { Dataset } from "shared/sdk/models";
32
import {
43
Component,
54
OnInit,
@@ -20,10 +19,13 @@ import {
2019
PageChangeEvent,
2120
CheckboxEvent,
2221
} from "shared/modules/table/table.component";
23-
import { selectIsLoading } from "state-management/selectors/user.selectors";
24-
import { Datablock, UserApi } from "shared/sdk";
22+
import { selectIsLoading, selectIsLoggedIn } from "state-management/selectors/user.selectors";
23+
import { Dataset, Job, UserApi } from "shared/sdk";
2524
import { FileSizePipe } from "shared/pipes/filesize.pipe";
2625
import { MatCheckboxChange } from "@angular/material/checkbox";
26+
import { MatDialog } from "@angular/material/dialog";
27+
import { PublicDownloadDialogComponent } from "datasets/public-download-dialog/public-download-dialog.component";
28+
import { submitJobAction } from "state-management/actions/jobs.actions";
2729

2830
export interface File {
2931
path: string;
@@ -46,7 +48,7 @@ export class DatafilesComponent
4648
datablocks$ = this.store.select(selectCurrentOrigDatablocks);
4749
dataset$ = this.store.select(selectCurrentDataset);
4850
loading$ = this.store.select(selectIsLoading);
49-
51+
isLoggedIn$ = this.store.select(selectIsLoggedIn);
5052
tooLargeFile = false;
5153
totalFileSize = 0;
5254
selectedFileSize = 0;
@@ -58,14 +60,18 @@ export class DatafilesComponent
5860

5961
files: Array<any> = [];
6062
sourcefolder = "";
63+
datasetPid = "";
6164

6265
count = 0;
6366
pageSize = 25;
6467
currentPage = 0;
6568

6669
fileDownloadEnabled: boolean = this.appConfig.fileDownloadEnabled;
6770
multipleDownloadEnabled: boolean = this.appConfig.multipleDownloadEnabled;
68-
multipleDownloadAction: string | null = this.appConfig.multipleDownloadAction;
71+
fileserverBaseURL: string | null = this.appConfig.fileserverBaseURL;
72+
fileserverButtonLabel: string | null = this.appConfig.fileserverButtonLabel;
73+
multipleDownloadAction: string | null = this.appConfig
74+
.multipleDownloadAction;
6975
maxFileSize: number | null = this.appConfig.maxDirectDownloadSize;
7076
sftpHost: string | null = this.appConfig.sftpHost;
7177
jwt: any;
@@ -99,6 +105,7 @@ export class DatafilesComponent
99105
private store: Store<Dataset>,
100106
private cdRef: ChangeDetectorRef,
101107
private userApi: UserApi,
108+
private dialog: MatDialog,
102109
@Inject(APP_CONFIG) public appConfig: AppConfig
103110
) {}
104111

@@ -193,6 +200,7 @@ export class DatafilesComponent
193200
this.dataset$.subscribe((dataset) => {
194201
if (dataset) {
195202
this.sourcefolder = dataset.sourceFolder;
203+
this.datasetPid = dataset.pid;
196204
}
197205
})
198206
);
@@ -223,4 +231,29 @@ export class DatafilesComponent
223231
ngOnDestroy() {
224232
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
225233
}
234+
openDialog(): void {
235+
const dialogRef = this.dialog.open(PublicDownloadDialogComponent, {
236+
width: "500px",
237+
data: {email: ""}
238+
});
239+
dialogRef.afterClosed().subscribe((email) => {
240+
if (email) {
241+
this.getSelectedFiles();
242+
const data = {
243+
emailJobInitiator: email,
244+
creationTime: new Date(),
245+
type: "public",
246+
datasetList: [{
247+
pid: this.datasetPid,
248+
files: this.getSelectedFiles()
249+
}]
250+
};
251+
const job = new Job(data);
252+
this.store.dispatch(submitJobAction({ job }));
253+
}
254+
});
255+
}
256+
getFileTransferLink() {
257+
return this.fileserverBaseURL + "&origin_path=" + encodeURIComponent(this.sourcefolder);
258+
}
226259
}

src/app/datasets/datasets.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import { BatchCardModule } from "./batch-card/batch-card.module";
7575
import { JobEffects } from "state-management/effects/jobs.effects";
7676
import { LogbookEffects } from "state-management/effects/logbooks.effects";
7777
import { logbooksReducer } from "state-management/reducers/logbooks.reducer";
78+
import { PublicDownloadDialogComponent } from "./public-download-dialog/public-download-dialog.component";
7879
import { DatasetFileUploaderComponent } from "./dataset-file-uploader/dataset-file-uploader.component";
7980
import { AdminTabComponent } from "./admin-tab/admin-tab.component";
8081

@@ -141,6 +142,7 @@ import { AdminTabComponent } from "./admin-tab/admin-tab.component";
141142
DatasetTableActionsComponent,
142143
DatasetLifecycleComponent,
143144
SampleEditComponent,
145+
PublicDownloadDialogComponent,
144146
ShareDialogComponent,
145147
DatasetFileUploaderComponent,
146148
AdminTabComponent,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<h1 mat-dialog-title>Request to download dataset</h1>
2+
<div mat-dialog-content>
3+
<p>Please enter your email so we can contact you once the dataset is ready to be downloaded.</p>
4+
<mat-form-field wid appearance="fill">
5+
<mat-label>Email</mat-label>
6+
<input matInput [formControl]="emailFormControl" type="email" [(ngModel)] ="data.email">
7+
<mat-error *ngIf="emailFormControl.errors">
8+
{{getErrorMessage()}}
9+
</mat-error>
10+
</mat-form-field>
11+
</div>
12+
<div mat-dialog-actions>
13+
<button mat-button (click)="onCancel()">Cancel</button>
14+
<button mat-button [mat-dialog-close]="data.email" [disabled]="hasError()">Submit</button>
15+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mat-form-field {
2+
width: 100%;
3+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
2+
import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
3+
import { MockMatDialogRef } from "shared/MockStubs";
4+
5+
import { PublicDownloadDialogComponent } from "./public-download-dialog.component";
6+
7+
describe("PublicDownloadDialogComponent", () => {
8+
let component: PublicDownloadDialogComponent;
9+
let fixture: ComponentFixture<PublicDownloadDialogComponent>;
10+
11+
beforeEach(
12+
waitForAsync(() =>{
13+
TestBed.configureTestingModule({
14+
declarations: [ PublicDownloadDialogComponent ],
15+
imports:[
16+
MatDialogModule
17+
]
18+
});
19+
TestBed.overrideComponent(PublicDownloadDialogComponent, {
20+
set: {
21+
providers: [
22+
{ provide: MatDialogRef, useClass: MockMatDialogRef },
23+
{ provide: MAT_DIALOG_DATA, useClass: MockMatDialogRef },],
24+
},
25+
});
26+
TestBed.compileComponents();
27+
})
28+
);
29+
30+
beforeEach(() => {
31+
fixture = TestBed.createComponent(PublicDownloadDialogComponent);
32+
component = fixture.componentInstance;
33+
fixture.detectChanges();
34+
});
35+
36+
it("should create", () => {
37+
expect(component).toBeTruthy();
38+
});
39+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Component, Inject } from "@angular/core";
2+
import { FormControl, Validators } from "@angular/forms";
3+
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
4+
5+
@Component({
6+
selector: "app-public-download-dialog",
7+
templateUrl: "./public-download-dialog.component.html",
8+
styleUrls: ["./public-download-dialog.component.scss"]
9+
})
10+
export class PublicDownloadDialogComponent {
11+
emailFormControl = new FormControl("", [Validators.required, Validators.email]);
12+
constructor(
13+
public dialogRef: MatDialogRef<PublicDownloadDialogComponent>,
14+
@Inject(MAT_DIALOG_DATA) public data: {email: string}
15+
) { }
16+
hasError(): boolean {
17+
return this.emailFormControl.hasError("required") || this.emailFormControl.hasError("email");
18+
}
19+
getErrorMessage():string {
20+
if (this.emailFormControl.hasError("required")) {
21+
return "Email is required";
22+
}
23+
if( this.emailFormControl.hasError("email")) {
24+
return "Please enter valid email address";
25+
}
26+
return "";
27+
}
28+
onCancel(): void {
29+
this.dialogRef.close();
30+
this.emailFormControl.errors;
31+
}
32+
}

0 commit comments

Comments
 (0)