diff --git a/src/app/app-config.service.spec.ts b/src/app/app-config.service.spec.ts
index 517350b83..e276c8dec 100644
--- a/src/app/app-config.service.spec.ts
+++ b/src/app/app-config.service.spec.ts
@@ -54,6 +54,8 @@ const appConfig: AppConfig = {
searchPublicDataEnabled: true,
searchSamples: true,
sftpHost: "login.esss.dk",
+ sourceFolder: "default",
+ maxFileSizeWarning: "Some files are above the max size",
shareEnabled: true,
shoppingCartEnabled: true,
shoppingCartOnHeader: true,
diff --git a/src/app/app-config.service.ts b/src/app/app-config.service.ts
index 904df35da..acd6e3ea9 100644
--- a/src/app/app-config.service.ts
+++ b/src/app/app-config.service.ts
@@ -82,6 +82,8 @@ export interface AppConfig {
searchPublicDataEnabled: boolean;
searchSamples: boolean;
sftpHost: string | null;
+ sourceFolder?: string;
+ maxFileSizeWarning?: string;
shareEnabled: boolean;
shoppingCartEnabled: boolean;
shoppingCartOnHeader: boolean;
diff --git a/src/app/datasets/dashboard/dashboard.component.ts b/src/app/datasets/dashboard/dashboard.component.ts
index 94b501441..a8f61ac02 100644
--- a/src/app/datasets/dashboard/dashboard.component.ts
+++ b/src/app/datasets/dashboard/dashboard.component.ts
@@ -73,7 +73,6 @@ export class DashboardComponent implements OnInit, OnDestroy {
subscriptions: Subscription[] = [];
appConfig = this.appConfigService.getConfig();
-
currentUser: User = new User();
userGroups: string[] = [];
clearColumnSearch = false;
diff --git a/src/app/datasets/datafiles/datafiles.component.html b/src/app/datasets/datafiles/datafiles.component.html
index 8eb776fa3..001ca7d38 100644
--- a/src/app/datasets/datafiles/datafiles.component.html
+++ b/src/app/datasets/datafiles/datafiles.component.html
@@ -2,16 +2,7 @@
warning
- One or more files are too large to be downloaded directly.
- {{
- sftpHost
- ? "These files are available via sftp host " +
- sftpHost +
- " in directory " +
- sourcefolder +
- "."
- : ""
- }}
+
@@ -54,7 +45,7 @@
No files associated to this dataset
-
+
No files associated to this dataset
-
+
{
let component: DatafilesComponent;
@@ -100,6 +101,7 @@ describe("DatafilesComponent", () => {
provide: DatafilesActionsComponent,
useClass: MockDatafilesActionsComponent,
},
+ { provide: FileSizePipe },
],
},
});
@@ -140,7 +142,7 @@ describe("DatafilesComponent", () => {
},
];
component.tableData = component.files;
- component.sourcefolder = "/test/";
+ component.sourceFolder = "/test/";
fixture.detectChanges();
});
diff --git a/src/app/datasets/datafiles/datafiles.component.ts b/src/app/datasets/datafiles/datafiles.component.ts
index 136e192bd..c643ac84b 100644
--- a/src/app/datasets/datafiles/datafiles.component.ts
+++ b/src/app/datasets/datafiles/datafiles.component.ts
@@ -62,7 +62,6 @@ export class DatafilesComponent
subscriptions: Subscription[] = [];
files: Array = [];
- sourcefolder = "";
datasetPid = "";
actionDataset: ActionDataset;
@@ -76,7 +75,12 @@ export class DatafilesComponent
this.appConfig.fileserverButtonLabel || "Download";
multipleDownloadAction: string | null = this.appConfig.multipleDownloadAction;
maxFileSize: number | null = this.appConfig.maxDirectDownloadSize;
- sftpHost: string | null = this.appConfig.sftpHost;
+ sourceFolder: string =
+ this.appConfig.sourceFolder || "No source folder provided";
+ sftpHost: string = this.appConfig.sftpHost || "No sftp host provided";
+ maxFileSizeWarning: string | null =
+ this.appConfig.maxFileSizeWarning ||
+ `Some files are above the max size ${this.fileSizePipe.transform(this.maxFileSize)}`;
jwt: any;
auth_token: any;
@@ -110,6 +114,7 @@ export class DatafilesComponent
private store: Store,
private cdRef: ChangeDetectorRef,
private dialog: MatDialog,
+ private fileSizePipe: FileSizePipe,
private userApi: UserApi,
) {}
@@ -204,11 +209,40 @@ export class DatafilesComponent
}
}
+ hasFileAboveMaxSizeWarning() {
+ /**
+ * Template for a file size warning message.
+ * Placeholders:
+ * - : Maximum file size allowed (e.g., "10 MB").
+ * - : SFTP host for downloading large files.
+ * - : Directory path on the SFTP host.
+ *
+ * Example usage:
+ * Some files are above . These file can be accessed via sftp host: in directory:
+ */
+
+ const valueMapping = {
+ sftpHost: this.sftpHost,
+ sourceFolder: this.sourceFolder,
+ maxDirectDownloadSize: this.fileSizePipe.transform(this.maxFileSize),
+ };
+
+ let warning = this.maxFileSizeWarning;
+
+ Object.keys(valueMapping).forEach((key) => {
+ warning = warning.replace(
+ "<" + key + ">",
+ `${valueMapping[key]}`,
+ );
+ });
+
+ return warning;
+ }
ngAfterViewInit() {
this.subscriptions.push(
this.dataset$.subscribe((dataset) => {
if (dataset) {
- this.sourcefolder = dataset.sourceFolder;
+ this.sourceFolder = dataset.sourceFolder;
this.datasetPid = dataset.pid;
this.actionDataset = dataset;
}
@@ -287,7 +321,7 @@ export class DatafilesComponent
return (
this.fileserverBaseURL +
"&origin_path=" +
- encodeURIComponent(this.sourcefolder)
+ encodeURIComponent(this.sourceFolder)
);
}
}
diff --git a/src/app/datasets/dataset-detail/dataset-detail.component.html b/src/app/datasets/dataset-detail/dataset-detail.component.html
index db97d4657..d049b4fe8 100644
--- a/src/app/datasets/dataset-detail/dataset-detail.component.html
+++ b/src/app/datasets/dataset-detail/dataset-detail.component.html
@@ -268,13 +268,6 @@
{{ sample.description }}
-
- edit
-
diff --git a/src/app/datasets/dataset-detail/dataset-detail.component.spec.ts b/src/app/datasets/dataset-detail/dataset-detail.component.spec.ts
index e83e5f4fd..96c778a5e 100644
--- a/src/app/datasets/dataset-detail/dataset-detail.component.spec.ts
+++ b/src/app/datasets/dataset-detail/dataset-detail.component.spec.ts
@@ -341,34 +341,6 @@ describe("DatasetDetailComponent", () => {
});
});
- describe("#openSampleEditDialog()", () => {
- it("should open the sample edit dialog and dispatch updatePropertyAction", () => {
- const dispatchSpy = spyOn(store, "dispatch");
- component.dataset = new Dataset();
- component.dataset.ownerGroup = "test";
- component.sample = new Sample();
- const sampleId = "testId";
- component.sample.sampleId = sampleId;
- const pid = "testPid";
- component.dataset.pid = pid;
- const property = { sampleId };
- const dialogOpenSpy = spyOn(component.dialog, "open").and.returnValue({
- afterClosed: () => of({ sample: { sampleId: "testId" } }),
- } as MatDialogRef);
- component.openSampleEditDialog();
-
- expect(dialogOpenSpy).toHaveBeenCalledTimes(1);
- expect(dialogOpenSpy).toHaveBeenCalledWith(SampleEditComponent, {
- width: "1000px",
- data: { ownerGroup: "test", sampleId: "testId" },
- });
- expect(dispatchSpy).toHaveBeenCalledTimes(1);
- expect(dispatchSpy).toHaveBeenCalledWith(
- updatePropertyAction({ pid, property }),
- );
- });
- });
-
describe("#onSaveMetadata()", () => {
it("should dispatch an updatePropertyAction", () => {
const dispatchSpy = spyOn(store, "dispatch");
diff --git a/src/app/datasets/dataset-detail/dataset-detail.component.ts b/src/app/datasets/dataset-detail/dataset-detail.component.ts
index 3de466a4e..c48fb223c 100644
--- a/src/app/datasets/dataset-detail/dataset-detail.component.ts
+++ b/src/app/datasets/dataset-detail/dataset-detail.component.ts
@@ -4,7 +4,7 @@ import { ENTER, COMMA, SPACE } from "@angular/cdk/keycodes";
import { MatChipInputEvent } from "@angular/material/chips";
import { MatDialog } from "@angular/material/dialog";
-import { SampleEditComponent } from "datasets/sample-edit/sample-edit.component";
+// import { SampleEditComponent } from "datasets/sample-edit/sample-edit.component";
import { DialogComponent } from "shared/modules/dialog/dialog.component";
import { combineLatest, fromEvent, Observable, Subscription } from "rxjs";
import { Store } from "@ngrx/store";
@@ -277,29 +277,6 @@ export class DatasetDetailComponent
this.router.navigateByUrl("/samples/" + id);
}
- openSampleEditDialog() {
- if (this.dataset) {
- this.dialog
- .open(SampleEditComponent, {
- width: "1000px",
- data: {
- ownerGroup: this.dataset.ownerGroup,
- sampleId: this.sample?.sampleId,
- },
- })
- .afterClosed()
- .subscribe((res) => {
- if (res && this.dataset) {
- const { sample } = res;
- this.sample = sample;
- const pid = this.dataset.pid;
- const property = { sampleId: sample.sampleId };
- this.store.dispatch(updatePropertyAction({ pid, property }));
- }
- });
- }
- }
-
onSlidePublic(event: MatSlideToggleChange) {
if (this.dataset) {
const pid = this.dataset.pid;
@@ -351,11 +328,7 @@ export class DatasetDetailComponent
}
getImageUrl(encoded: string) {
- const mimeType = this.base64MimeType(encoded);
- if (mimeType === "application/pdf") {
- return "assets/images/pdf-icon.svg";
- }
- return encoded;
+ return this.attachmentService.getImageUrl(encoded);
}
openAttachment(encoded: string) {
diff --git a/src/app/datasets/dataset-table/dataset-table.component.html b/src/app/datasets/dataset-table/dataset-table.component.html
index 99657fe7d..9aa6f3dd9 100644
--- a/src/app/datasets/dataset-table/dataset-table.component.html
+++ b/src/app/datasets/dataset-table/dataset-table.component.html
@@ -208,7 +208,7 @@
diff --git a/src/app/datasets/datasets.module.ts b/src/app/datasets/datasets.module.ts
index ad668eb0a..d20615983 100644
--- a/src/app/datasets/datasets.module.ts
+++ b/src/app/datasets/datasets.module.ts
@@ -89,7 +89,6 @@ import { DatasetsFilterSettingsComponent } from "./datasets-filter/settings/data
import { CdkDrag, CdkDragHandle, CdkDropList } from "@angular/cdk/drag-drop";
import { FiltersModule } from "shared/modules/filters/filters.module";
import { userReducer } from "state-management/reducers/user.reducer";
-import { AttachmentService } from "shared/services/attachment.service";
@NgModule({
imports: [
diff --git a/src/app/shared/modules/file-uploader/file-uploader.component.ts b/src/app/shared/modules/file-uploader/file-uploader.component.ts
index 9970a2b0e..af18cfb49 100644
--- a/src/app/shared/modules/file-uploader/file-uploader.component.ts
+++ b/src/app/shared/modules/file-uploader/file-uploader.component.ts
@@ -109,11 +109,7 @@ export class FileUploaderComponent {
}
getImageUrl(encoded: string) {
- const mimeType = this.base64MimeType(encoded);
- if (mimeType === "application/pdf") {
- return "assets/images/pdf-icon.svg";
- }
- return encoded;
+ return this.attachmentService.getImageUrl(encoded);
}
openAttachment(encoded: string) {
diff --git a/src/app/shared/services/attachment.service.spec.ts b/src/app/shared/services/attachment.service.spec.ts
index 4cb7f76fd..888753ec8 100644
--- a/src/app/shared/services/attachment.service.spec.ts
+++ b/src/app/shared/services/attachment.service.spec.ts
@@ -29,11 +29,25 @@ describe("AttachmentService", () => {
});
it("should return null for non-string input", () => {
- const mimeType = service.base64MimeType(null as any);
+ const mimeType = service.base64MimeType(null);
expect(mimeType).toBeNull();
});
});
+ describe("getImageUrl", () => {
+ it("should return the pdf icon if the file is pdf", () => {
+ const encoded = "data:application/pdf;base64,SGVsbG8sIFdvcmxkIQ==";
+ const imageUrl = service.getImageUrl(encoded);
+ expect(imageUrl).toBe("assets/images/pdf-icon.svg");
+ });
+
+ it("should return the encoded string if the file is not pdf", () => {
+ const encoded = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA";
+ const imageUrl = service.getImageUrl(encoded);
+ expect(imageUrl).toBe(encoded);
+ });
+ });
+
describe("openAttachment", () => {
it("should open a new window with the correct object URL", () => {
const encoded = "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==";
diff --git a/src/app/shared/services/attachment.service.ts b/src/app/shared/services/attachment.service.ts
index 7d4e054a6..9ad1f9ab8 100644
--- a/src/app/shared/services/attachment.service.ts
+++ b/src/app/shared/services/attachment.service.ts
@@ -3,6 +3,10 @@ import { Injectable } from "@angular/core";
@Injectable()
export class AttachmentService {
base64MimeType(encoded: string): string {
+ if (!encoded) {
+ return null;
+ }
+
let result = null;
if (typeof encoded !== "string") {
@@ -17,7 +21,24 @@ export class AttachmentService {
return result;
}
+
+ getImageUrl(encoded: string) {
+ if (!encoded) {
+ return null;
+ }
+
+ const mimeType = this.base64MimeType(encoded);
+ if (mimeType === "application/pdf") {
+ return "assets/images/pdf-icon.svg";
+ }
+ return encoded;
+ }
+
openAttachment(encoded: string) {
+ if (!encoded) {
+ return null;
+ }
+
const mimeType = this.base64MimeType(encoded);
const strippedData = encoded.replace(
new RegExp(`^data:${mimeType};base64,`),
diff --git a/src/app/shared/services/thumbnail.service.spec.ts b/src/app/shared/services/thumbnail.service.spec.ts
index 9a441dfbc..fb187528d 100644
--- a/src/app/shared/services/thumbnail.service.spec.ts
+++ b/src/app/shared/services/thumbnail.service.spec.ts
@@ -5,6 +5,7 @@ import { ThumbnailService } from "./thumbnail.service";
import { selectDatasetsPerPage } from "state-management/selectors/datasets.selectors";
import { MockStore, provideMockStore } from "@ngrx/store/testing";
import { of, throwError } from "rxjs";
+import { AttachmentService } from "./attachment.service";
describe("ThumbnailService", () => {
let service: ThumbnailService;
@@ -27,6 +28,9 @@ describe("ThumbnailService", () => {
provide: AppConfigService,
useValue: { getConfig },
},
+ {
+ provide: AttachmentService,
+ },
provideMockStore({
selectors: [
{
diff --git a/src/app/shared/services/thumbnail.service.ts b/src/app/shared/services/thumbnail.service.ts
index f4879b2bb..7990139de 100644
--- a/src/app/shared/services/thumbnail.service.ts
+++ b/src/app/shared/services/thumbnail.service.ts
@@ -4,6 +4,7 @@ import { distinctUntilChanged, firstValueFrom } from "rxjs";
import { DatasetApi } from "shared/sdk";
import { selectDatasetsPerPage } from "state-management/selectors/datasets.selectors";
import { AppConfigService } from "app-config.service";
+import { AttachmentService } from "./attachment.service";
interface ThumbnailCache {
[pid: string]: {
@@ -25,6 +26,7 @@ export class ThumbnailService {
constructor(
private datasetApi: DatasetApi,
private store: Store,
+ private attachmentService: AttachmentService,
private appConfigService: AppConfigService,
) {
this.store
@@ -60,7 +62,7 @@ export class ThumbnailService {
try {
const encodedPid = encodeURIComponent(pid);
const res = await firstValueFrom(this.datasetApi.thumbnail(encodedPid));
- const thumbnail = res?.thumbnail || null;
+ const thumbnail = this.attachmentService.getImageUrl(res?.thumbnail);
this.thumbnailCache[pid] = {
value: thumbnail,