Skip to content

Commit a0823b3

Browse files
despadamnitrosxJunjiequanMatthMigMatthieu Migné
authored
RELEASE 04-06-2025 (#1882)
## Description Short description of the pull request ## Motivation Background on use case, changes needed ## Fixes: Please provide a list of the fixes implemented in this PR * Items added ## Changes: Please provide a list of the changes implemented by this PR * changes made ## Tests included - [ ] Included for each change/fix? - [ ] Passing? (Merge will not be approved unless this is checked) ## Documentation - [ ] swagger documentation updated \[required\] - [ ] official documentation updated \[nice-to-have\] ### official documentation info If you have updated the official documentation, please provide PR # and URL of the pages where the updates are included ## Backend version - [ ] Does it require a specific version of the backend - which version of the backend is required: ## Summary by Sourcery Upgrade core integrations and enhance UI tables, dataset detail, datafiles actions, and jobs workflows while standardizing authentication flows and updating documentation and tests. New Features: - Add JSON-download support in DatafilesActionComponent with payload substitution, file download flow, and error snackbar - Switch SampleDashboard to dynamic-mat-table with persistent user table settings, server-side pagination, sorting, and row events Enhancements: - Extend DatasetDetailDynamicComponent with instrument name resolution, internal link handling, and scientific metadata extraction methods - Migrate jobs module to use v3 API endpoints and update related actions, selectors, reducers, and effects - Standardize returnUrl query parameter naming and handling across login, auth callback, and header components Build: - Bump @scicatproject/scicat-sdk-ts-angular to ^4.17.1 and update OpenAPI generator scripts to v7.13.0 Documentation: - Add comprehensive markdown documentation for Datafiles Actions configuration Tests: - Add extensive unit tests for DatasetDetailDynamicComponent methods - Update SampleDashboard and jobs tests to accommodate dynamic-mat-table events and v3 API changes Chores: - Refactor SampleEffects to only trigger on fetchSamplesAction and adjust metadata keys query logic - Clean up backward-compatibility comments and obsolete code in admin tab and archiving service --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Max Novelli <[email protected]> Co-authored-by: Jay <[email protected]> Co-authored-by: MatthMig <[email protected]> Co-authored-by: Matthieu Migné <[email protected]> Co-authored-by: Martin <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Garrett Birkel <[email protected]>
1 parent 309650a commit a0823b3

File tree

45 files changed

+1645
-744
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1645
-744
lines changed

cypress/e2e/proposals/proposals-general.cy.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,9 +443,7 @@ describe("Proposals general", () => {
443443
.find("input[type=checkbox]")
444444
.uncheck();
445445

446-
cy.get('[role="menu"] .column-config-apply .done-setting')
447-
.contains("done")
448-
.click();
446+
cy.contains(".column-config-apply button.done-setting", "done").click();
449447

450448
cy.get("dynamic-mat-table table-menu button").click();
451449
cy.get('[role="menu"] button').contains("Save table setting").click();
@@ -454,6 +452,8 @@ describe("Proposals general", () => {
454452

455453
cy.get("dynamic-mat-table mat-header-row.header").should("exist");
456454

455+
cy.finishedLoading();
456+
457457
cy.get("dynamic-mat-table mat-header-row.header").should(
458458
"not.contain",
459459
"First Name",

package-lock.json

Lines changed: 459 additions & 382 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"@ngrx/store": "^19.1.0",
3838
"@ngx-translate/core": "^16.0.4",
3939
"@ngxmc/datetime-picker": "^19.3.1",
40-
"@scicatproject/scicat-sdk-ts-angular": "^4.16.0",
40+
"@scicatproject/scicat-sdk-ts-angular": "^4.17.1",
4141
"autolinker": "^4.0.0",
4242
"deep-equal": "^2.0.5",
4343
"exceljs": "^4.3.0",

scripts/generate-nestjs-sdk.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ docker run \
1919
--rm \
2020
--add-host host.docker.internal:host-gateway \
2121
-v "`pwd`:/local" \
22-
openapitools/openapi-generator-cli:v7.12.0 generate \
22+
openapitools/openapi-generator-cli:v7.13.0 generate \
2323
-i http://host.docker.internal:3000/explorer-json \
2424
-g typescript-angular \
2525
-o local/@scicatproject/scicat-sdk-ts-angular \

scripts/generate-nestjs-sdk.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if (isWindows()) {
3333
* This should not be a risk as after the generation we can get a feedback immediately if something is broken here when we run and test the frontend.
3434
*/
3535
const generationOutput = execSync(
36-
`docker run --rm --add-host host.docker.internal:host-gateway -v "${getCurrentDirectory()}:/local" openapitools/openapi-generator-cli:v7.9.0 generate -i http://host.docker.internal:3000/explorer-json -g typescript-angular -o local/@scicatproject/scicat-sdk-ts-angular --additional-properties=ngVersion=19.0.0,npmName=@scicatproject/scicat-sdk-ts-angular,supportsES6=true,npmVersion=10.8.2,withInterfaces=true,paramNaming=original,modelPropertyNaming=original,enumPropertyNaming=original --skip-validate-spec`,
36+
`docker run --rm --add-host host.docker.internal:host-gateway -v "${getCurrentDirectory()}:/local" openapitools/openapi-generator-cli:v7.13.0 generate -i http://host.docker.internal:3000/explorer-json -g typescript-angular -o local/@scicatproject/scicat-sdk-ts-angular --additional-properties=ngVersion=19.0.0,npmName=@scicatproject/scicat-sdk-ts-angular,supportsES6=true,withInterfaces=true,paramNaming=original,modelPropertyNaming=original,enumPropertyNaming=original --skip-validate-spec`,
3737
{ encoding: "utf-8" },
3838
);
3939
console.log(generationOutput);

src/app/_layout/app-header/app-header.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ export class AppHeaderComponent implements OnInit {
4747

4848
login(): void {
4949
if (this.config.skipSciCatLoginPageEnabled) {
50-
const returnURL = encodeURIComponent(this.router.url);
50+
const returnUrl = encodeURIComponent(this.router.url);
5151
for (const endpoint of this.oAuth2Endpoints) {
52-
this.document.location.href = `${this.config.lbBaseURL}/${endpoint.authURL}?returnURL=${returnURL}`;
52+
this.document.location.href = `${this.config.lbBaseURL}/${endpoint.authURL}?returnUrl=${returnUrl}`;
5353
}
5454
} else {
5555
this.router.navigateByUrl("/login");

src/app/datasets/admin-tab/admin-tab.component.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FileObject } from "datasets/dataset-details-dashboard/dataset-details-d
44
import { Subscription } from "rxjs";
55
import { take } from "rxjs/operators";
66
import {
7-
CreateJobDto,
7+
CreateJobDtoV3,
88
OutputDatasetObsoleteDto,
99
} from "@scicatproject/scicat-sdk-ts-angular";
1010
import { submitJobAction } from "state-management/actions/jobs.actions";
@@ -48,12 +48,6 @@ export class AdminTabComponent implements OnInit, OnDestroy {
4848
.pipe(take(1))
4949
.subscribe((user) => {
5050
if (user && this.dataset) {
51-
const job: CreateJobDto = {
52-
ownerUser: user.email,
53-
type: "reset",
54-
jobParams: {},
55-
};
56-
job.jobParams["username"] = user.username;
5751
const fileObj: FileObject = {
5852
pid: "",
5953
files: [],
@@ -66,7 +60,14 @@ export class AdminTabComponent implements OnInit, OnDestroy {
6660
});
6761
}
6862
fileObj.files = fileList;
69-
// job.datasetList = [fileObj]; // TODO: job release back-ward compatibility issue
63+
const job: CreateJobDtoV3 = {
64+
emailJobInitiator: user.email,
65+
type: "reset",
66+
datasetList: [fileObj],
67+
jobParams: {},
68+
jobStatusMessage: "jobCreated",
69+
};
70+
job.jobParams["username"] = user.username;
7071
this.store.dispatch(submitJobAction({ job }));
7172
}
7273
});

src/app/datasets/archiving.service.spec.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import {
1010
import { JobsState } from "state-management/state/jobs.store";
1111
import { ArchivingService } from "./archiving.service";
1212
import { createMock, mockDataset } from "shared/MockStubs";
13-
import { ReturnedUserDto } from "@scicatproject/scicat-sdk-ts-angular";
13+
import {
14+
ReturnedUserDto,
15+
CreateJobDtoV3,
16+
} from "@scicatproject/scicat-sdk-ts-angular";
1417

1518
describe("ArchivingService", () => {
1619
let service: ArchivingService;
@@ -70,7 +73,7 @@ describe("ArchivingService", () => {
7073
destinationPath,
7174
);
7275

73-
// expect(job).toBeInstanceOf(Job);
76+
expect(job).toBeDefined();
7477
expect(job["emailJobInitiator"]).toEqual("[email protected]");
7578
expect(job["jobParams"]["username"]).toEqual("testName");
7679
expect(job["datasetList"]).toEqual(datasetList);
@@ -103,8 +106,8 @@ describe("ArchivingService", () => {
103106
files: [],
104107
}));
105108
const archive = true;
106-
// TODO: job release back-ward compatibility issue
107-
const job = createMock<any>({
109+
110+
const job = createMock<CreateJobDtoV3>({
108111
jobParams: { username: user.username },
109112
emailJobInitiator: user.email,
110113
datasetList,

src/app/datasets/datafiles-actions/datafiles-action.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import { ActionDataset } from "./datafiles-action.interfaces";
1919
import { UsersService } from "@scicatproject/scicat-sdk-ts-angular";
2020
import { AuthService } from "shared/services/auth/auth.service";
21+
import { MatSnackBarModule } from "@angular/material/snack-bar";
2122

2223
describe("1000: DatafilesActionComponent", () => {
2324
let component: DatafilesActionComponent;
@@ -157,6 +158,7 @@ describe("1000: DatafilesActionComponent", () => {
157158
PipesModule,
158159
ReactiveFormsModule,
159160
MatDialogModule,
161+
MatSnackBarModule,
160162
RouterModule,
161163
RouterModule.forRoot([]),
162164
StoreModule.forRoot({}),

src/app/datasets/datafiles-actions/datafiles-action.component.ts

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { UsersService } from "@scicatproject/scicat-sdk-ts-angular";
1010
import { ActionConfig, ActionDataset } from "./datafiles-action.interfaces";
1111
import { DataFiles_File } from "datasets/datafiles/datafiles.interfaces";
1212
import { AuthService } from "shared/services/auth/auth.service";
13+
import { v4 } from "uuid";
14+
import { MatSnackBar } from "@angular/material/snack-bar";
1315

1416
@Component({
1517
selector: "datafiles-action",
@@ -36,6 +38,7 @@ export class DatafilesActionComponent implements OnInit, OnChanges {
3638
constructor(
3739
private usersService: UsersService,
3840
private authService: AuthService,
41+
private snackBar: MatSnackBar,
3942
) {
4043
this.usersService.usersControllerGetUserJWTV3().subscribe((jwt) => {
4144
this.jwt = jwt.jwt;
@@ -118,6 +121,8 @@ export class DatafilesActionComponent implements OnInit, OnChanges {
118121
perform_action() {
119122
const action_type = this.actionConfig.type || "form";
120123
switch (action_type) {
124+
case "json-download":
125+
return this.type_json_download();
121126
case "form":
122127
default:
123128
return this.type_form();
@@ -166,21 +171,81 @@ export class DatafilesActionComponent implements OnInit, OnChanges {
166171
return true;
167172
}
168173

169-
/*
170-
* future development
171-
*
172-
type_fetch() {
173-
const data = new URLSearchParams();
174-
for (const pair of new FormData(formElement)) {
175-
data.append(pair[0], pair[1]);
174+
type_json_download() {
175+
let payload = "";
176+
if (this.actionConfig.payload) {
177+
payload = this.actionConfig.payload
178+
.replace(/{{ auth_token }}/, `Bearer ${this.authService.getToken().id}`)
179+
.replace(/{{ jwt }}/, this.jwt)
180+
.replace(/{{ datasetPid }}/, this.actionDataset.pid)
181+
.replace(/{{ sourceFolder }}/, this.actionDataset.sourceFolder)
182+
.replace(
183+
/{{ filesPath }}/,
184+
JSON.stringify(
185+
this.files
186+
.filter(
187+
(item) =>
188+
this.actionConfig.files === "all" ||
189+
(this.actionConfig.files === "selected" && item.selected),
190+
)
191+
.map((item) => item.path),
192+
),
193+
);
194+
} else {
195+
const data = {
196+
auth_token: `Bearer ${this.authService.getToken().id}`,
197+
jwt: this.jwt,
198+
dataset: this.actionDataset.pid,
199+
directory: this.actionDataset.sourceFolder,
200+
files: this.files
201+
.filter(
202+
(item) =>
203+
this.actionConfig.files === "all" ||
204+
(this.actionConfig.files === "selected" && item.selected),
205+
)
206+
.map((item) => item.path),
207+
};
208+
payload = JSON.stringify(data);
176209
}
177210

178-
fetch(url, {
179-
method: 'post',
180-
body: data,
211+
const filename = this.actionConfig.filename.replace(/{{ uuid }}/, v4());
212+
213+
fetch(this.actionConfig.url, {
214+
method: this.actionConfig.method || "POST",
215+
headers: {
216+
"Content-Type": "application/json",
217+
},
218+
body: payload,
181219
})
182-
.then(…);
183-
}
220+
.then((response) => {
221+
if (response.ok) {
222+
return response.blob();
223+
} else {
224+
// http error
225+
return Promise.reject(
226+
new Error(`HTTP Error code: ${response.status}`),
227+
);
228+
}
229+
})
230+
.then((blob) => URL.createObjectURL(blob))
231+
.then((url) => {
232+
const a = document.createElement("a");
233+
a.href = url;
234+
a.download = filename;
235+
a.click();
236+
URL.revokeObjectURL(url);
237+
})
238+
.catch((error) => {
239+
console.log("Datafile action error : ", error);
240+
this.snackBar.open(
241+
"There has been an error performing the action",
242+
"Close",
243+
{
244+
duration: 2000,
245+
},
246+
);
247+
});
248+
249+
return true;
184250
}
185-
*/
186251
}

0 commit comments

Comments
 (0)