From 091e125d8048419db11e074934a9fbf6eb142a45 Mon Sep 17 00:00:00 2001 From: Alicia de Dios Fuente <Alicia.DeDiosFuente@unige.ch> Date: Wed, 29 Jan 2020 17:45:06 +0100 Subject: [PATCH] feat: added reports info for JobExecutionReport --- package-lock.json | 15 +- .../aip-detail-edit.routable.html | 2 + .../aip/stores/aip-aip/aip-aip.state.ts | 9 -- .../job-execution-list.container.ts | 14 +- .../job-execution-detail.dialog.ts | 2 +- .../job-execution-form.presentational.html | 105 ++++++++++++ .../job-execution-form.presentational.ts | 78 +++++++++ .../job-detail-edit.routable.html | 55 ++++--- .../job-detail-edit.routable.ts | 46 +++++- .../job-execution-detail.routable.html | 30 ++++ .../job-execution-detail.routable.scss | 7 + .../job-execution-detail.routable.ts | 153 ++++++++++++++++++ .../preservation/job/helper/job.helper.ts | 26 +++ .../job/preservation-job-routing.module.ts | 9 ++ .../job/preservation-job.module.ts | 4 + .../preservation-job-execution.action.ts | 24 ++- .../preservation-job-execution.state.ts | 85 +++++++++- .../job/stores/preservation-job.state.ts | 4 +- src/app/shared/enums/api-action.enum.ts | 2 +- .../shared/enums/api-resource-name.enum.ts | 1 + .../business/job-report-aip-status.enum.ts | 5 + src/app/shared/enums/local-state.enum.ts | 5 +- src/app/shared/enums/routes.enum.ts | 3 + .../job-execution-report-line.model.ts | 10 ++ .../business/job-execution-report.model.ts | 10 ++ .../models/business/job-execution.model.ts | 3 +- src/app/shared/stores/report/report.action.ts | 0 src/app/shared/stores/report/report.state.ts | 0 src/assets/i18n/de.json | 39 ++++- src/assets/i18n/en.json | 34 +++- src/assets/i18n/fr.json | 34 +++- 31 files changed, 752 insertions(+), 62 deletions(-) create mode 100644 src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.html create mode 100644 src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.ts create mode 100644 src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.html create mode 100644 src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.scss create mode 100644 src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.ts create mode 100644 src/app/shared/enums/business/job-report-aip-status.enum.ts create mode 100644 src/app/shared/models/business/job-execution-report-line.model.ts create mode 100644 src/app/shared/models/business/job-execution-report.model.ts create mode 100644 src/app/shared/stores/report/report.action.ts create mode 100644 src/app/shared/stores/report/report.state.ts diff --git a/package-lock.json b/package-lock.json index f857bf8f2..24095876b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1559,7 +1559,7 @@ "@angular/compiler": "^8.1.3", "boxen": "^4.1.0", "colorette": "^1.1.0", - "flat": "git://github.com/lenchvolodymyr/flat.git#ffe77efe8c33bc80ffb2f7a465537610dea4f611", + "flat": "git://github.com/lenchvolodymyr/flat.git#ffe77ef", "gettext-parser": "^4.0.1", "glob": "^7.1.4", "mkdirp": "^0.5.1", @@ -5563,7 +5563,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5928,7 +5929,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5976,6 +5978,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6014,11 +6017,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true + "bundled": true, + "optional": true } } }, diff --git a/src/app/features/preservation/aip/components/routables/aip-detail-edit/aip-detail-edit.routable.html b/src/app/features/preservation/aip/components/routables/aip-detail-edit/aip-detail-edit.routable.html index bf3f0c773..d7fbe9189 100644 --- a/src/app/features/preservation/aip/components/routables/aip-detail-edit/aip-detail-edit.routable.html +++ b/src/app/features/preservation/aip/components/routables/aip-detail-edit/aip-detail-edit.routable.html @@ -1,3 +1,5 @@ +<script src="../../../aip-routing.module.ts"></script> +<script src="../../../../job/preservation-job-routing.module.ts"></script> <dlcm-shared-banner-edit-mode [isEdit]="isEdit"></dlcm-shared-banner-edit-mode> <dlcm-button-toolbar-detail [mode]="'detail'" diff --git a/src/app/features/preservation/aip/stores/aip-aip/aip-aip.state.ts b/src/app/features/preservation/aip/stores/aip-aip/aip-aip.state.ts index 805a812fc..2aeb828b7 100644 --- a/src/app/features/preservation/aip/stores/aip-aip/aip-aip.state.ts +++ b/src/app/features/preservation/aip/stores/aip-aip/aip-aip.state.ts @@ -4,7 +4,6 @@ import {ApiActionEnum} from "@app/shared/enums/api-action.enum"; import {ApiResourceNameEnum} from "@app/shared/enums/api-resource-name.enum"; import {ArchivalStorageResourceApiEnum} from "@app/shared/enums/api.enum"; import {LocalStateEnum} from "@app/shared/enums/local-state.enum"; -import {Navigate} from "@ngxs/router-plugin"; import { Action, Actions, @@ -13,15 +12,8 @@ import { StateContext, Store, } from "@ngxs/store"; -import {AipHelper} from "@preservation/aip/helpers/aip.helper"; import {AipExtended} from "@preservation/aip/models/aip-extended.model"; import {PreservationAipAction} from "@preservation/aip/stores/aip.action"; -import { - AppRoutesEnum, - PreservationPlanningRoutesEnum, - RoutesEnum, - urlSeparator, -} from "@shared/enums/routes.enum"; import {DownloadService} from "@shared/services/download.service"; import { PreservationAipAipAction, @@ -32,7 +24,6 @@ import { PreservationAipAipStatusHistoryStateModel, } from "@preservation/aip/stores/aip-aip/status-history/aip-aip-status-history.state"; import {defaultStatusHistoryInitValue} from "@shared/stores/status-history/status-history.state"; -import {saveAs} from "file-saver"; import { ApiService, CompositionState, diff --git a/src/app/features/preservation/job/components/containers/job-execution-list/job-execution-list.container.ts b/src/app/features/preservation/job/components/containers/job-execution-list/job-execution-list.container.ts index 65484c55c..01414c86e 100644 --- a/src/app/features/preservation/job/components/containers/job-execution-list/job-execution-list.container.ts +++ b/src/app/features/preservation/job/components/containers/job-execution-list/job-execution-list.container.ts @@ -12,6 +12,7 @@ import {PreservationJobAction} from "@app/features/preservation/job/stores/prese import {PreservationJobState} from "@app/features/preservation/job/stores/preservation-job.state"; import {PreservationJob} from "@app/generated-api"; import {SharedAbstractPresentational} from "@app/shared/components/presentationals/shared-abstract/shared-abstract.presentational"; +import {Navigate} from "@ngxs/router-plugin"; import { Actions, ofActionCompleted, @@ -20,8 +21,13 @@ import { import {JobStatusEnum} from "@shared/enums/business/job-status.enum"; import {DataTableComponentEnum} from "@shared/enums/data-table-component.enum"; import {FieldTypeEnum} from "@shared/enums/field-type.enum"; -import {AppRoutesEnum} from "@shared/enums/routes.enum"; import {PollingHelper} from "@shared/helpers/polling.helper"; +import { + AppRoutesEnum, + PreservationPlanningRoutesEnum, + RoutesEnum, + urlSeparator, +} from "@shared/enums/routes.enum"; import {JobExecution} from "@shared/models/business/job-execution.model"; import {DataTableColumns} from "@shared/models/data-table-columns.model"; import {Observable} from "rxjs"; @@ -191,8 +197,8 @@ export class JobExecutionListContainer extends SharedAbstractPresentational impl } showExecutionDetail(jobExecution: JobExecution): void { - const dialogRef = this._dialog.open(JobExecutionDetailDialog, { - data: jobExecution, - }); + const pathExecution = RoutesEnum.preservation + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.job + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.jobDetail + AppRoutesEnum.separator + this._resId + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.preservationPlanningExecution; + const path = [pathExecution, jobExecution.resId]; + this._store.dispatch(new Navigate(path)); } } diff --git a/src/app/features/preservation/job/components/dialogs/job-execution-detail/job-execution-detail.dialog.ts b/src/app/features/preservation/job/components/dialogs/job-execution-detail/job-execution-detail.dialog.ts index 1ce54a18c..95d55ce54 100644 --- a/src/app/features/preservation/job/components/dialogs/job-execution-detail/job-execution-detail.dialog.ts +++ b/src/app/features/preservation/job/components/dialogs/job-execution-detail/job-execution-detail.dialog.ts @@ -91,7 +91,7 @@ export class JobExecutionDetailDialog extends SharedAbstractContainer implements } resume(): void { - this._store.dispatch(new PreservationJobExecutionAction.Resume(this.jobExecution.jobId, this.jobExecution)); + this._store.dispatch(new PreservationJobExecutionAction.Resume(this.jobExecution.jobId, this.jobExecution.resId)); this.subscribe(this._actions$.pipe(ofActionCompleted(PreservationJobExecutionAction.ResumeSuccess)) .pipe( tap(result => { diff --git a/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.html b/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.html new file mode 100644 index 000000000..4fd919a0b --- /dev/null +++ b/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.html @@ -0,0 +1,105 @@ +<form [formGroup]="form" +> + <mat-form-field *ngIf="getFormControl(formDefinition.status) as fd"> + <mat-label>{{'preservation.jobExecution.form.status' | translate}}</mat-label> + <mat-select [formControl]="fd" + [required]="formValidationHelper.hasRequiredField(fd)" + > + <mat-option *ngFor="let executionStatus of listExecutionStatus" + [value]="executionStatus.key" + > + {{executionStatus.value | translate}} + </mat-option> + </mat-select> + </mat-form-field> + + + <mat-form-field [matTooltip]="'preservation.jobExecution.form.statusMessage' | translate" + [matTooltipPosition]="'left'" + aria-label="publication date tooltip" + matTooltipClass="tooltip" + *ngIf="getFormControl(formDefinition.statusMessage) as fd" + > + <input [formControl]="fd" + matInput + [placeholder]="'preservation.jobExecution.statusMessage' | translate" + [required]="formValidationHelper.hasRequiredField(fd)" + > + </mat-form-field> + + <mat-form-field [matTooltip]="'preservation.jobExecution.form.startDate' | translate" + [matTooltipPosition]="'left'" + matTooltipClass="tooltip" + *ngIf="getFormControl(formDefinition.startDate) as fd" + > + <input [formControl]="fd" + matInput + [placeholder]="'preservation.jobExecution.startDate' | translate" + [required]="formValidationHelper.hasRequiredField(fd)" + > + </mat-form-field> + + <mat-form-field [matTooltip]="'preservation.jobExecution.form.endDate' | translate" + [matTooltipPosition]="'left'" + aria-label="publication date tooltip" + matTooltipClass="tooltip" + *ngIf="getFormControl(formDefinition.endDate) as fd" + > + <input [formControl]="fd" + matInput + [placeholder]="'preservation.jobExecution.endDate' | translate" + [required]="formValidationHelper.hasRequiredField(fd)" + > + </mat-form-field> + +<!-- <div class="right-part">--> + +<!-- <mat-form-field [matTooltip]="'preservation.jobExecution.form.total' | translate"--> +<!-- [matTooltipPosition]="'left'"--> +<!-- matTooltipClass="tooltip"--> +<!-- *ngIf="getFormControl(formDefinition.totalItems) as fd"--> +<!-- >--> +<!-- <input [formControl]="fd"--> +<!-- matInput--> +<!-- [placeholder]="'preservation.jobExecution.total' | translate"--> +<!-- [required]="formValidationHelper.hasRequiredField(fd)"--> +<!-- >--> +<!-- </mat-form-field>--> + +<!-- <mat-form-field [matTooltip]="'preservation.jobExecution.form.processed' | translate"--> +<!-- [matTooltipPosition]="'left'"--> +<!-- matTooltipClass="tooltip"--> +<!-- *ngIf="getFormControl(formDefinition.processedItems) as fd"--> +<!-- >--> +<!-- <input [formControl]="fd"--> +<!-- matInput--> +<!-- [placeholder]="'preservation.jobExecution.processed' | translate"--> +<!-- [required]="formValidationHelper.hasRequiredField(fd)"--> +<!-- >--> +<!-- </mat-form-field>--> + +<!-- <mat-form-field [matTooltip]="'preservation.jobExecution.form.ignored' | translate"--> +<!-- [matTooltipPosition]="'left'"--> +<!-- matTooltipClass="tooltip"--> +<!-- *ngIf="getFormControl(formDefinition.ignoredItems) as fd"--> +<!-- >--> +<!-- <input [formControl]="fd"--> +<!-- matInput--> +<!-- [placeholder]="'preservation.jobExecution.ignored' | translate"--> +<!-- [required]="formValidationHelper.hasRequiredField(fd)"--> +<!-- >--> +<!-- </mat-form-field>--> + +<!-- <mat-form-field [matTooltip]="'preservation.jobExecution.form.inError' | translate"--> +<!-- [matTooltipPosition]="'left'"--> +<!-- matTooltipClass="tooltip"--> +<!-- *ngIf="getFormControl(formDefinition.inErrorItems) as fd"--> +<!-- >--> +<!-- <input [formControl]="fd"--> +<!-- matInput--> +<!-- [placeholder]="'preservation.jobExecution.inError' | translate"--> +<!-- [required]="formValidationHelper.hasRequiredField(fd)"--> +<!-- >--> +<!-- </mat-form-field>--> +<!-- </div>--> +</form> diff --git a/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.ts b/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.ts new file mode 100644 index 000000000..10bb49cc0 --- /dev/null +++ b/src/app/features/preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational.ts @@ -0,0 +1,78 @@ +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, +} from "@angular/core"; +import { + FormBuilder, + Validators, +} from "@angular/forms"; +import {JobHelper} from "@preservation/job/helper/job.helper"; +import {SharedAbstractFormPresentational} from "@shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational"; +import {BaseFormDefinition} from "@shared/models/base-form-definition.model"; +import {JobExecution} from "@shared/models/business/job-execution.model"; +import { + KeyValue, + PropertyName, + SolidifyValidator, +} from "solidify-frontend"; + +@Component({ + selector: "dlcm-job-execution-form", + templateUrl: "./job-execution-form.presentational.html", + styleUrls: ["../../../../../../shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational.scss"], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class JobExecutionFormPresentational extends SharedAbstractFormPresentational<JobExecution> { + formDefinition: FormComponentFormDefinition = new FormComponentFormDefinition(); + + listExecutionStatus: KeyValue[] = JobHelper.getExecutionStatus(); + + + constructor(protected readonly _changeDetectorRef: ChangeDetectorRef, + private readonly _fb: FormBuilder) { + super(_changeDetectorRef); + } + + protected bindFormTo(jobExecution: JobExecution): void { + this.form = this._fb.group({ + [this.formDefinition.status]: [jobExecution.status, [Validators.required, SolidifyValidator]], + [this.formDefinition.statusMessage]: [jobExecution.statusMessage, [SolidifyValidator]], + [this.formDefinition.startDate]: [jobExecution.startDate, [Validators.required, SolidifyValidator]], + [this.formDefinition.endDate]: [jobExecution.endDate, [Validators.required, SolidifyValidator]], + [this.formDefinition.totalItems]: [jobExecution.ignoredItems + jobExecution.processedItems + jobExecution.inErrorItems, [Validators.required, SolidifyValidator]], + [this.formDefinition.ignoredItems]: [jobExecution.ignoredItems, [Validators.required, SolidifyValidator]], + [this.formDefinition.processedItems]: [jobExecution.processedItems, [Validators.required, SolidifyValidator]], + [this.formDefinition.inErrorItems]: [jobExecution.inErrorItems, [Validators.required, SolidifyValidator]], + }); + } + + protected initNewForm(): void { + this.form = this._fb.group({ + [this.formDefinition.status]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.statusMessage]: ["", [SolidifyValidator]], + [this.formDefinition.startDate]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.endDate]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.totalItems]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.ignoredItems]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.processedItems]: ["", [Validators.required, SolidifyValidator]], + [this.formDefinition.inErrorItems]: ["", [Validators.required, SolidifyValidator]], + }); + } + + protected treatmentBeforeSubmit(model: JobExecution): JobExecution { + return undefined; + } + +} + +class FormComponentFormDefinition extends BaseFormDefinition { + @PropertyName() status: string; + @PropertyName() statusMessage: string; + @PropertyName() startDate: string; + @PropertyName() endDate: string; + @PropertyName() totalItems: string; + @PropertyName() ignoredItems: string; + @PropertyName() processedItems: string; + @PropertyName() inErrorItems: string; +} diff --git a/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.html b/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.html index 272b4285d..5a87f9fe1 100644 --- a/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.html +++ b/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.html @@ -1,26 +1,33 @@ -<dlcm-button-toolbar-detail [mode]="isEdit ? 'edit' : 'detail'" - [currentModel]="currentObs | async" - (editChange)="edit()" - (deleteChange)="delete()" - (backToDetailChange)="backToDetail()" - (backToListChange)="backToList()" - [listExtraButtons]="listExtraButtons()" -> -</dlcm-button-toolbar-detail> +<router-outlet></router-outlet> -<div class="wrapper" - [dlcmSpinner]="isLoadingWithDependencyObs | async" -> - <dlcm-job-form #formPresentational - *ngIf="isReadyToBeDisplayedObs | async" - [model]="currentObs| async" - [readonly]="!isEdit" - (submitChange)="update($event)" - (dirtyChange)="updateCanDeactivate($event)" - ></dlcm-job-form> -</div> +<ng-template [ngIf]="this.preservationJob"> + <dlcm-shared-button-id [resource]="currentObs | async"></dlcm-shared-button-id> + + <dlcm-button-toolbar-detail [mode]="isEdit ? 'edit' : 'detail'" + [currentModel]="currentObs | async" + (editChange)="edit()" + (deleteChange)="delete()" + (backToDetailChange)="backToDetail()" + (backToListChange)="backToList()" + [listExtraButtons]="listExtraButtons()" + > + </dlcm-button-toolbar-detail> + + <div class="wrapper" + [dlcmSpinner]="isLoadingWithDependencyObs | async" + > + <dlcm-job-form #formPresentational + *ngIf="isReadyToBeDisplayedObs | async" + [model]="currentObs| async" + [readonly]="!isEdit" + (submitChange)="update($event)" + (dirtyChange)="updateCanDeactivate($event)" + ></dlcm-job-form> + </div> + + <dlcm-job-execution-container *ngIf="!isEdit" + #jobExecutionList + > + </dlcm-job-execution-container> +</ng-template> -<dlcm-job-execution-container *ngIf="!isEdit" - #jobExecutionList -> -</dlcm-job-execution-container> diff --git a/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.ts b/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.ts index dfb9124ec..79e8136ab 100644 --- a/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.ts +++ b/src/app/features/preservation/job/components/routables/job-detail-edit/job-detail-edit.routable.ts @@ -1,10 +1,15 @@ import { ChangeDetectorRef, Component, + OnInit, ViewChild, } from "@angular/core"; import {MatDialog} from "@angular/material"; -import {ActivatedRoute} from "@angular/router"; +import { + ActivatedRoute, + Router, + RouterStateSnapshot, +} from "@angular/router"; import {JobExecutionListContainer} from "@app/features/preservation/job/components/containers/job-execution-list/job-execution-list.container"; import { PreservationJobAction, @@ -23,9 +28,18 @@ import { } from "@ngxs/store"; import {SharedAbstractDetailEditCommonRoutable} from "@shared/components/routables/shared-abstract-detail-edit-common/shared-abstract-detail-edit-common.routable"; import {LocalStateEnum} from "@shared/enums/local-state.enum"; +import { + PreservationPlanningRoutesEnum, +} from "@shared/enums/routes.enum"; import {JobRecurrence} from "@shared/models/business/job-recurrence.model"; import {ExtraButtonToolbar} from "@shared/models/extra-button-toolbar.model"; -import {Observable} from "rxjs"; +import {LocalStateModel} from "@shared/models/local-state.model"; +import { + Observable, +} from "rxjs"; +import { + tap, +} from "rxjs/operators"; import {TRANSLATE} from "solidify-frontend"; import JobRecurrenceEnum = JobRecurrence.JobRecurrenceEnum; @@ -34,21 +48,26 @@ import JobRecurrenceEnum = JobRecurrence.JobRecurrenceEnum; templateUrl: "./job-detail-edit.routable.html", styleUrls: ["./job-detail-edit.routable.scss"], }) -export class JobDetailEditRoutable extends SharedAbstractDetailEditCommonRoutable<PreservationJob, PreservationJobStateModel> { +export class JobDetailEditRoutable extends SharedAbstractDetailEditCommonRoutable<PreservationJob, PreservationJobStateModel> implements OnInit{ @Select(PreservationJobState.isLoadingWithDependency) isLoadingWithDependencyObs: Observable<boolean>; @Select(PreservationJobState.isReadyToBeDisplayed) isReadyToBeDisplayedObs: Observable<boolean>; + @Select((state: LocalStateModel) => state.router.state) urlStateObs: Observable<RouterStateSnapshot>; + @ViewChild("jobExecutionList", {static: false}) readonly jobExecutionList: JobExecutionListContainer; readonly KEY_PARAM_NAME: keyof PreservationJob & string = "name"; + preservationJob: boolean | undefined = undefined; get jobRecurrenceEnum(): typeof JobRecurrenceEnum { return JobRecurrenceEnum; } - constructor(protected _store: Store, + constructor( + protected _store: Store, protected _route: ActivatedRoute, + protected _router: Router, protected readonly _actions$: Actions, protected readonly _changeDetector: ChangeDetectorRef, public _dialog: MatDialog) { @@ -58,6 +77,25 @@ export class JobDetailEditRoutable extends SharedAbstractDetailEditCommonRoutabl getSubResourceWithParentId(id: string): void { } + ngOnInit(): void { + super.ngOnInit(); + this.subscribe(this.urlStateObs + .pipe( + tap( urLState => { + if (urLState) { + const url = urLState.url; + console.error(url); + if (url.includes(PreservationPlanningRoutesEnum.preservationPlanningExecution)) { + this.preservationJob = false; + } + else { + this.preservationJob = true; + } + } + }) + )); + } + start(): void { this.subscribe(this._actions$.pipe(ofActionCompleted(PreservationJobAction.StartSuccess)), result => { diff --git a/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.html b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.html new file mode 100644 index 000000000..91b94762b --- /dev/null +++ b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.html @@ -0,0 +1,30 @@ +<dlcm-shared-button-id [resource]="currentObs | async"></dlcm-shared-button-id> + +<dlcm-button-toolbar-detail [mode]="'detail'" + [editAvailable]="false" + [deleteAvailable]="false" + [currentModel]="currentObs | async" + (backToListChange)="backToList()" + [listExtraButtons]="listExtraButtons()" +> +</dlcm-button-toolbar-detail> + +<div class="wrapper" + [dlcmSpinner]="isLoadingObs | async" +> + <dlcm-job-execution-form #formPresentational + *ngIf="isReadyToBeDisplayedObs | async" + [model]="currentObs| async" + [readonly]="true" + ></dlcm-job-execution-form> + + <h1>{{'preservation.jobExecution.report.title' | translate}}</h1> + + <dlcm-shared-data-table [columns]="columns" + [datas]="listReportObs | async" + (selectChange)="showExecutionDetail($event)" + > + </dlcm-shared-data-table> +</div> + + diff --git a/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.scss b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.scss new file mode 100644 index 000000000..6c4bb3918 --- /dev/null +++ b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.scss @@ -0,0 +1,7 @@ +@import "../../../../../../shared/components/routables/shared-abstract-detail-edit-common/shared-abstract-detail-edit-common.routable.scss"; + +:host { + .wrapper { + min-height: 100px; + } +} diff --git a/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.ts b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.ts new file mode 100644 index 000000000..0534c27cc --- /dev/null +++ b/src/app/features/preservation/job/components/routables/job-execution-detail/job-execution-detail.routable.ts @@ -0,0 +1,153 @@ +import { + Component, + OnInit, +} from "@angular/core"; +import {ActivatedRoute} from "@angular/router"; +import {Navigate} from "@ngxs/router-plugin"; +import { + Actions, + ofActionCompleted, + Select, + Store, +} from "@ngxs/store"; +import {PreservationJobExecutionAction} from "@preservation/job/stores/preservation-job-execution/preservation-job-execution.action"; +import {PreservationJobExecutionState} from "@preservation/job/stores/preservation-job-execution/preservation-job-execution.state"; +import {SharedAbstractRoutable} from "@shared/components/routables/shared-abstract/shared-abstract.routable"; +import {JobStatusEnum} from "@shared/enums/business/job-status.enum"; +import {FieldTypeEnum} from "@shared/enums/field-type.enum"; +import { + AppRoutesEnum, + PreservationPlanningRoutesEnum, + RoutesEnum, +} from "@shared/enums/routes.enum"; +import {JobExecutionReport} from "@shared/models/business/job-execution-report.model"; +import {JobExecution} from "@shared/models/business/job-execution.model"; +import {DataTableColumns} from "@shared/models/data-table-columns.model"; +import {ExtraButtonToolbar} from "@shared/models/extra-button-toolbar.model"; +import {LocalStateModel} from "@shared/models/local-state.model"; +import {Observable} from "rxjs"; +import {tap} from "rxjs/operators"; +import { + BaseResource, + CompositionState, + OrderEnum, + TRANSLATE, +} from "solidify-frontend"; + +@Component({ + selector: "dlcm-job-execution-detail-routable", + templateUrl: "./job-execution-detail.routable.html", + styleUrls: ["./job-execution-detail.routable.scss"], +}) +export class JobExecutionDetailRoutable extends SharedAbstractRoutable implements OnInit { + + @Select((state: LocalStateModel) => state.preservation.preservation_job.preservation_job_execution.current) currentObs: Observable<JobExecution>; + @Select(PreservationJobExecutionState.isReadyToBeDisplayed) isReadyToBeDisplayedObs: Observable<boolean>; + @Select(PreservationJobExecutionState.isLoading) isLoadingObs: Observable<boolean>; + @Select(PreservationJobExecutionState.listReport) listReportObs: Observable<JobExecutionReport[]>; + + columns: DataTableColumns<BaseResource & JobExecutionReport>[] = [ + { + field: "executionNumber", + header: TRANSLATE("preservation.jobExecution.report.table.header.executionNumber"), + type: FieldTypeEnum.string, + order: OrderEnum.descending, + isFilterable: false, + isSortable: true, + }, + { + field: "processedItems", + header: TRANSLATE("preservation.jobExecution.report.table.header.processedItems"), + type: FieldTypeEnum.string, + order: OrderEnum.none, + isFilterable: false, + isSortable: false, + }, + { + field: "ignoredItems", + header: TRANSLATE("preservation.jobExecution.report.table.header.ignoredItems"), + type: FieldTypeEnum.string, + order: OrderEnum.none, + isFilterable: false, + isSortable: false, + }, + { + field: "inErrorItems", + header: TRANSLATE("preservation.jobExecution.report.table.header.inErrorItems"), + type: FieldTypeEnum.string, + order: OrderEnum.none, + isFilterable: false, + isSortable: false, + }, + ]; + + private _preservationJobId: string; + private _resId: string; + + constructor(private readonly _store: Store, + private readonly _route: ActivatedRoute, + private readonly _actions$: Actions) { + super(); + this.retrieveCurrentModelWithUrl(); + } + + protected retrieveCurrentModelWithUrl(): void { + this.retrieveResIdFromUrl(); + this._store.dispatch(new PreservationJobExecutionAction.GetById(this._preservationJobId, this._resId)); + } + + protected retrieveResIdFromUrl(): void { + this._resId = this._route.snapshot.paramMap.get(AppRoutesEnum.paramIdExecutionWithoutPrefixParam); + this._preservationJobId = this._route.snapshot.parent.paramMap.get(AppRoutesEnum.paramIdWithoutPrefixParam); + } + + ngOnInit(): void { + super.ngOnInit(); + } + + backToList(): void { + const pathExecution = RoutesEnum.preservation + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.job + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.jobDetail ; + const path = [pathExecution, this._preservationJobId]; + this._store.dispatch(new Navigate(path)); + } + + listExtraButtons(): ExtraButtonToolbar<JobExecution>[] { + return [ + { + color: "primary", + icon: "play_arrow", + labelToTranslate: TRANSLATE("preservation.jobExecution.button.resume"), + callback: () => this.resume(), + displayCondition: (resource) => resource && (resource.status === JobStatusEnum.IN_ERROR), + order: 31, + }, + { + color: "accent", + icon: "refresh", + labelToTranslate: TRANSLATE("preservation.jobExecution.button.refresh"), + callback: () => this.refresh(), + order: 41, + }, + ]; + } + + private resume(): void { + this._store.dispatch(new PreservationJobExecutionAction.Resume(this._preservationJobId, this._resId)); + this.subscribe(this._actions$.pipe(ofActionCompleted(PreservationJobExecutionAction.ResumeSuccess)) + .pipe( + tap(result => { + if (result.result.successful) { + this.refresh(); + } + }), + )); + } + + showExecutionDetail($event: JobExecutionReport): void { + console.error("DIALOG OPEN HERE", $event); + } + + private refresh(): void { + this._store.dispatch(new PreservationJobExecutionAction.GetById(this._preservationJobId, this._resId)); + } +} diff --git a/src/app/features/preservation/job/helper/job.helper.ts b/src/app/features/preservation/job/helper/job.helper.ts index 9a830e941..0b5a5ceef 100644 --- a/src/app/features/preservation/job/helper/job.helper.ts +++ b/src/app/features/preservation/job/helper/job.helper.ts @@ -1,4 +1,5 @@ import {PreservationJob} from "@app/generated-api"; +import {JobStatusEnum} from "@shared/enums/business/job-status.enum"; import { KeyValue, TRANSLATE, @@ -157,4 +158,29 @@ export class JobHelper { }, ]; } + + static getExecutionStatus(): KeyValue[] { + return[ + { + key: JobStatusEnum.IN_PROGRESS, + value: TRANSLATE("preservation.jobExecution.jobStatusEnum.inProgress"), + }, + { + key: JobStatusEnum.COMPLETED, + value: TRANSLATE("preservation.jobExecution.jobStatusEnum.completed"), + }, + { + key: JobStatusEnum.READY, + value: TRANSLATE("preservation.jobExecution.jobStatusEnum.ready"), + }, + { + key: JobStatusEnum.PAUSED, + value: TRANSLATE("preservation.jobExecution.jobStatusEnum.paused"), + }, + { + key: JobStatusEnum.IN_ERROR, + value: TRANSLATE("preservation.jobExecution.jobStatusEnum.inError"), + } + ]; + } } diff --git a/src/app/features/preservation/job/preservation-job-routing.module.ts b/src/app/features/preservation/job/preservation-job-routing.module.ts index 866549ffe..daddb9f90 100644 --- a/src/app/features/preservation/job/preservation-job-routing.module.ts +++ b/src/app/features/preservation/job/preservation-job-routing.module.ts @@ -5,6 +5,7 @@ import {JobDetailEditRoutable} from "@app/features/preservation/job/components/r import {JobListRoutable} from "@app/features/preservation/job/components/routables/job-list/job-list.routable"; import {PreservationJobState} from "@app/features/preservation/job/stores/preservation-job.state"; import {DlcmRoutes} from "@app/shared/models/dlcm-route.model"; +import {JobExecutionDetailRoutable} from "@preservation/job/components/routables/job-execution-detail/job-execution-detail.routable"; import { AppRoutesEnum, PreservationPlanningRoutesEnum, @@ -34,6 +35,13 @@ const routes: DlcmRoutes = [ breadcrumbMemoizedSelector: PreservationJobState.currentTitle, }, children: [ + { + path: PreservationPlanningRoutesEnum.preservationPlanningExecution + AppRoutesEnum.separator + AppRoutesEnum.paramIdExecution, + component: JobExecutionDetailRoutable, + data: { + breadcrumb: TRANSLATE("breadcrumb.preservation.job.execution"), + }, + }, { path: PreservationPlanningRoutesEnum.jobEdit, data: { @@ -43,6 +51,7 @@ const routes: DlcmRoutes = [ }, ], }, + ]; @NgModule({ diff --git a/src/app/features/preservation/job/preservation-job.module.ts b/src/app/features/preservation/job/preservation-job.module.ts index efd8ca744..6a062c3e9 100644 --- a/src/app/features/preservation/job/preservation-job.module.ts +++ b/src/app/features/preservation/job/preservation-job.module.ts @@ -12,11 +12,14 @@ import {PreservationJobState} from "@app/features/preservation/job/stores/preser import {SharedModule} from "@app/shared/shared.module"; import {TranslateModule} from "@ngx-translate/core"; import {NgxsModule} from "@ngxs/store"; +import {JobExecutionFormPresentational} from "@preservation/job/components/presentationals/job-execution-form/job-execution-form.presentational"; +import {JobExecutionDetailRoutable} from "@preservation/job/components/routables/job-execution-detail/job-execution-detail.routable"; const routables = [ JobListRoutable, JobDetailEditRoutable, JobCreateRoutable, + JobExecutionDetailRoutable ]; const containers = [ JobExecutionListContainer, @@ -27,6 +30,7 @@ const dialogs = [ ]; const presentationals = [ JobFormPresentational, + JobExecutionFormPresentational ]; @NgModule({ diff --git a/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.action.ts b/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.action.ts index 3363d90bc..c09c81fa0 100644 --- a/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.action.ts +++ b/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.action.ts @@ -1,8 +1,10 @@ import {LocalStateEnum} from "@shared/enums/local-state.enum"; +import {JobExecutionReport} from "@shared/models/business/job-execution-report.model"; import {JobExecution} from "@shared/models/business/job-execution.model"; import { BaseAction, BaseSubAction, + CollectionTyped, CompositionAction, CompositionNameSpace, QueryParameters, @@ -75,7 +77,7 @@ export namespace PreservationJobExecutionAction { export class Resume extends BaseAction { static readonly type: string = `[${state}] Resume`; - constructor(public parentId: string, public jobExecution: JobExecution) { + constructor(public parentId: string, public jobExecutionId: string) { super(); } } @@ -111,6 +113,26 @@ export namespace PreservationJobExecutionAction { super(); } } + + export class GetListReport extends BaseAction { + static readonly type: string = `[${state}] Get List Reports`; + + constructor(public parentId: string, public jobExecutionId: string) { + super(); + } + } + + export class GetListReportSuccess extends BaseSubAction<GetListReport> { + static readonly type: string = `[${state}] Get List Report Success`; + + constructor(public parentAction: GetListReport, public list: CollectionTyped<JobExecutionReport>) { + super(parentAction); + } + } + + export class GetListReportFail extends BaseSubAction<GetListReport> { + static readonly type: string = `[${state}] Get List Report Fail`; + } } export const preservationJobExecutionActionNameSpace: CompositionNameSpace = PreservationJobExecutionAction; diff --git a/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.state.ts b/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.state.ts index c87b7c742..84b8079fa 100644 --- a/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.state.ts +++ b/src/app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.state.ts @@ -2,6 +2,7 @@ import { PreservationJobExecutionAction, preservationJobExecutionActionNameSpace, } from "@app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.action"; +import {Collection} from "@app/generated-api"; import {LocalStateEnum} from "@app/shared/enums/local-state.enum"; import { Action, @@ -11,10 +12,15 @@ import { StateContext, Store, } from "@ngxs/store"; +import {PreservationJobStateModel} from "@preservation/job/stores/preservation-job.state"; +import {SipDataFileStateModel} from "@preservation/sip/stores/data-file/sip-data-file.state"; import {ApiActionEnum} from "@shared/enums/api-action.enum"; import {ApiResourceNameEnum} from "@shared/enums/api-resource-name.enum"; import {PreservationPlanningResourceApiEnum} from "@shared/enums/api.enum"; +import {JobExecutionReport} from "@shared/models/business/job-execution-report.model"; import {JobExecution} from "@shared/models/business/job-execution.model"; +import {defaultStatusHistoryInitValue} from "@shared/stores/status-history/status-history.state"; +import {SelectorType} from "codelyzer/selectorPropertyBase"; import {Observable} from "rxjs"; import { catchError, @@ -22,23 +28,39 @@ import { } from "rxjs/operators"; import { ApiService, + BaseResourceType, + CollectionTyped, CompositionState, CompositionStateModel, + defaultCompositionStateInitValue, defaultResourceStateInitValue, isNullOrUndefined, NotificationService, + OverrideDefaultAction, + QueryParameters, + ResourceStateModel, SolidifyStateError, + StoreUtil, TRANSLATE, urlSeparator, } from "solidify-frontend"; + +export const defaultJobExecutionInitValue: () => PreservationJobExecutionStateModel = () => +({ + ...defaultResourceStateInitValue(), + listReports: undefined, +}); + export interface PreservationJobExecutionStateModel extends CompositionStateModel<JobExecution> { + listReports: JobExecutionReport[] | undefined; } @State<PreservationJobExecutionStateModel>({ name: LocalStateEnum.preservation_job_execution, defaults: { ...defaultResourceStateInitValue(), + listReports: undefined, }, }) export class PreservationJobExecutionState extends CompositionState<PreservationJobExecutionStateModel, JobExecution> { @@ -69,8 +91,10 @@ export class PreservationJobExecutionState extends CompositionState<Preservation ctx.patchState({ isLoadingCounter: ctx.getState().isLoadingCounter + 1, }); + console.error(action.parentId); + console.error(action); - return this.apiService.post<string>(this._urlResource + urlSeparator + action.parentId + urlSeparator + ApiResourceNameEnum.PRES_JOB_EXECUTION + urlSeparator + action.jobExecution.resId + urlSeparator + ApiActionEnum.RESUME) + return this.apiService.post<string>(this._urlResource + urlSeparator + action.parentId + urlSeparator + ApiResourceNameEnum.PRES_JOB_EXECUTION + urlSeparator + action.jobExecutionId + urlSeparator + ApiActionEnum.RESUME) .pipe( tap(result => { ctx.dispatch(new PreservationJobExecutionAction.ResumeSuccess(action)); @@ -131,4 +155,63 @@ export class PreservationJobExecutionState extends CompositionState<Preservation }); this.notificationService.showError(TRANSLATE("preservation.jobExecution.notification.start.fail"), true); } + + @Selector() + static isReadyToBeDisplayed(state: PreservationJobStateModel): boolean { + return !isNullOrUndefined(state.current); + } + + @Selector() + static isLoading(state: PreservationJobStateModel): boolean { + return StoreUtil.isLoadingState(state); + } + + @Selector() + static listReport(state: PreservationJobExecutionStateModel): JobExecutionReport[] { + return state.listReports; + } + + @OverrideDefaultAction() + @Action(PreservationJobExecutionAction.GetByIdSuccess) + getByIdSuccess(ctx: StateContext<PreservationJobExecutionStateModel>, action: PreservationJobExecutionAction.GetByIdSuccess): void { + ctx.patchState({ + current: action.model, + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + ctx.dispatch(new PreservationJobExecutionAction.GetListReport(action.model.jobId, action.model.resId)); + } + + @Action(PreservationJobExecutionAction.GetListReport) + getListReport(ctx: StateContext<PreservationJobExecutionStateModel>, action: PreservationJobExecutionAction.GetListReport): Observable<CollectionTyped<JobExecutionReport>> { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + }); + + return this.apiService.get<JobExecutionReport>(this._urlResource + urlSeparator + action.parentId + urlSeparator + ApiResourceNameEnum.PRES_JOB_EXECUTION + urlSeparator + action.jobExecutionId + urlSeparator + ApiActionEnum.REPORT, new QueryParameters()) + .pipe( + tap((collection: CollectionTyped<JobExecutionReport>) => { + ctx.dispatch(new PreservationJobExecutionAction.GetListReportSuccess(action, collection)); + }), + catchError(error => { + ctx.dispatch(new PreservationJobExecutionAction.GetListReportFail(action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @Action(PreservationJobExecutionAction.GetListReportSuccess) + getListReportSuccess(ctx: StateContext<PreservationJobExecutionStateModel>, action: PreservationJobExecutionAction.GetListReportSuccess): void { + ctx.patchState({ + listReports: action.list._data, + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + + } + + @Action(PreservationJobExecutionAction.GetListReportFail) + getListReportFail(ctx: StateContext<PreservationJobExecutionStateModel>, action: PreservationJobExecutionAction.GetListReportFail): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } } diff --git a/src/app/features/preservation/job/stores/preservation-job.state.ts b/src/app/features/preservation/job/stores/preservation-job.state.ts index dd2423557..cd745ffc2 100644 --- a/src/app/features/preservation/job/stores/preservation-job.state.ts +++ b/src/app/features/preservation/job/stores/preservation-job.state.ts @@ -1,4 +1,5 @@ import { + defaultJobExecutionInitValue, PreservationJobExecutionState, PreservationJobExecutionStateModel, } from "@app/features/preservation/job/stores/preservation-job-execution/preservation-job-execution.state"; @@ -38,7 +39,6 @@ import { TRANSLATE, urlSeparator, } from "solidify-frontend"; - export interface PreservationJobStateModel extends ResourceStateModel<PreservationJob> { listJobTypes: JobType[] | undefined; listJobRecurrences: JobRecurrence[] | undefined; @@ -51,7 +51,7 @@ export interface PreservationJobStateModel extends ResourceStateModel<Preservati ...defaultResourceStateInitValue(), listJobTypes: undefined, listJobRecurrences: undefined, - preservation_job_execution: {...defaultResourceStateInitValue()}, + preservation_job_execution: {...defaultJobExecutionInitValue()}, }, children: [ PreservationJobExecutionState, diff --git a/src/app/shared/enums/api-action.enum.ts b/src/app/shared/enums/api-action.enum.ts index 9788e9441..c57662f97 100644 --- a/src/app/shared/enums/api-action.enum.ts +++ b/src/app/shared/enums/api-action.enum.ts @@ -83,6 +83,6 @@ export class ApiActionEnum { public static REJECT: string = "reject"; public static ENABLE_REVISION: string = "enable-revision"; public static INIT: string = "initialize"; - public static REPORT: string = "report"; + public static REPORT: string = "reports"; public static VALIDATE: string = "validate"; } diff --git a/src/app/shared/enums/api-resource-name.enum.ts b/src/app/shared/enums/api-resource-name.enum.ts index 77eeaccb1..ef1717b65 100644 --- a/src/app/shared/enums/api-resource-name.enum.ts +++ b/src/app/shared/enums/api-resource-name.enum.ts @@ -30,6 +30,7 @@ export class ApiResourceNameEnum implements ApiResourceNameEnum { public static MONITOR: string = "monitor"; public static PRES_JOB: string = "preservation-jobs"; public static PRES_JOB_EXECUTION: string = "executions"; + public static PRES_JOB_EXECUTION_REPORT: string = "reports"; public static PRES_POLICY: string = "preservation-policies"; public static SUB_POLICY: string = "submission-policies"; public static DISSEMINATION_POLICY: string = "dissemination-policies"; diff --git a/src/app/shared/enums/business/job-report-aip-status.enum.ts b/src/app/shared/enums/business/job-report-aip-status.enum.ts new file mode 100644 index 000000000..838d9ba84 --- /dev/null +++ b/src/app/shared/enums/business/job-report-aip-status.enum.ts @@ -0,0 +1,5 @@ +export enum JobReportAipStatus { + PROCESSED = "PROCESSED", + IGNORED = "IGNORED", + ERROR = "ERROR" +} diff --git a/src/app/shared/enums/local-state.enum.ts b/src/app/shared/enums/local-state.enum.ts index 406ee130e..b9f39f0cb 100644 --- a/src/app/shared/enums/local-state.enum.ts +++ b/src/app/shared/enums/local-state.enum.ts @@ -90,6 +90,9 @@ export enum LocalStateEnum { preservation_monitoring = "preservation_monitoring", preservation_aipStatus = "preservation_aipStatus", preservation_job = "preservation_job", + preservation_job_execution = "preservation_job_execution", + preservation_job_execution_report = "preservation_job_execution_report", + preservation_aip = "preservation_aip", preservation_aip_organizationalUnit = "preservation_aip_organizationalUnit", @@ -97,8 +100,6 @@ export enum LocalStateEnum { preservation_aip_statusHistory = "preservation_aip_statusHistory", preservation_aip_aip_statusHistory = "preservation_aip_aip_statusHistory", - preservation_job_execution = "preservation_job_execution", - preservation_sip = "preservation_sip", preservation_sip_statusHistory = "preservation_sip_statusHistory", preservation_sip_dataFile = "preservation_sip_dataFile", diff --git a/src/app/shared/enums/routes.enum.ts b/src/app/shared/enums/routes.enum.ts index c501aa552..328a9e4a5 100644 --- a/src/app/shared/enums/routes.enum.ts +++ b/src/app/shared/enums/routes.enum.ts @@ -16,6 +16,8 @@ export enum AppRoutesEnum { paramIdOrgUnit = ":idOrgUnit", paramIdWithoutPrefixParam = "id", paramIdOrgUnitWithoutPrefixParam = "idOrgUnit", + paramIdExecution = ":idExecution", + paramIdExecutionWithoutPrefixParam = "idExecution", edit = "edit", } @@ -126,6 +128,7 @@ export enum PreservationPlanningRoutesEnum { preservationPlanningCreate = "create", preservationPlanningDetail = "detail", preservationPlanningEdit = "edit", + preservationPlanningExecution= "execution", monitoring = "monitoring", diff --git a/src/app/shared/models/business/job-execution-report-line.model.ts b/src/app/shared/models/business/job-execution-report-line.model.ts new file mode 100644 index 000000000..18366c34a --- /dev/null +++ b/src/app/shared/models/business/job-execution-report-line.model.ts @@ -0,0 +1,10 @@ +import {JobReportAipStatus} from "@shared/enums/business/job-report-aip-status.enum"; + +export interface JobExecutionReportLine { + seq: number; + reportId: string; + errorMessage?: string; + storageUrl?: string; + changeTime?: Date; + status: JobReportAipStatus; +} diff --git a/src/app/shared/models/business/job-execution-report.model.ts b/src/app/shared/models/business/job-execution-report.model.ts new file mode 100644 index 000000000..703037a6c --- /dev/null +++ b/src/app/shared/models/business/job-execution-report.model.ts @@ -0,0 +1,10 @@ +import {JobExecutionReportLine} from "@shared/models/business/job-execution-report-line.model"; + +export interface JobExecutionReport { + jobExecutionId: string; + executionNumber: number; + listAip?: JobExecutionReportLine[]; + processedItems: number; + ignoredItems: number; + inErrorItems: number; +} diff --git a/src/app/shared/models/business/job-execution.model.ts b/src/app/shared/models/business/job-execution.model.ts index 360eefd78..e65c3bc4a 100644 --- a/src/app/shared/models/business/job-execution.model.ts +++ b/src/app/shared/models/business/job-execution.model.ts @@ -1,6 +1,6 @@ import {ChangeInfo} from "@app/generated-api"; import {JobStatusEnum} from "@shared/enums/business/job-status.enum"; - +import {JobExecutionReport} from "@shared/models/business/job-execution-report.model"; export interface JobExecution { resId: string; jobId?: string; @@ -16,4 +16,5 @@ export interface JobExecution { totalItems?: number; creation?: ChangeInfo; lastUpdate?: ChangeInfo; + executionReports?: JobExecutionReport[]; } diff --git a/src/app/shared/stores/report/report.action.ts b/src/app/shared/stores/report/report.action.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/shared/stores/report/report.state.ts b/src/app/shared/stores/report/report.state.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 25f3b3ed5..3aa3afc9d 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -989,7 +989,8 @@ "job": { "create": "Create", "edit": "Edit", - "root": "Job" + "root": "Job", + "execution": "Execution" }, "monitoring": { "root": "Monitoring" @@ -1952,9 +1953,17 @@ } }, "jobExecution": { + "inError": "Aips in error from last report", + "ignored": "Aips ignore from last report", + "processed": "Aips Processed from last report", + "total": "Aips total from last report", + "startDate": "Start Date", + "endDate": "End Date", + "statusMessage": "Status Message", "button": { "refresh": "Refresh", - "start": "Run" + "start": "Run", + "resume": "Resume" }, "home": { "title": "Job executions : {{name}}" @@ -1984,6 +1993,27 @@ "startDate": "Start date", "status": "Status" } + }, + "form": { + "status": "Status", + "statusMessage": "Status Message", + "startDate": "Start Date", + "endDate": "End Date", + "ignored": "Aips ignored from last report", + "processed": "Aips processed from last report", + "inError": "Aips in error from last report", + "total": "Total Aips considered from last report" + }, + "report": { + "title": "Reports", + "table": { + "header": { + "executionNumber": "Report number", + "processedItems": "Items processed", + "ignoredItems": "Items ignored", + "inErrorItems": "Items in error" + } + } } }, "jobExecutionDetail": { @@ -1997,7 +2027,10 @@ "runNumber": "Run number", "status": "Status", "title": "Job execution detail", - "totalItems": "Total items" + "totalItems": "Total items", + "form": { + "status": "Status" + } }, "jobs": { "home": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 25f3b3ed5..0d5b93124 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -989,7 +989,8 @@ "job": { "create": "Create", "edit": "Edit", - "root": "Job" + "root": "Job", + "execution": "Execution" }, "monitoring": { "root": "Monitoring" @@ -1952,9 +1953,17 @@ } }, "jobExecution": { + "inError": "Aips in error from last report", + "ignored": "Aips ignore from last report", + "processed": "Aips Processed from last report", + "total": "Aips total from last report", + "startDate": "Start Date", + "endDate": "End Date", + "statusMessage": "Status Message", "button": { "refresh": "Refresh", - "start": "Run" + "start": "Run", + "resume": "Resume" }, "home": { "title": "Job executions : {{name}}" @@ -1984,6 +1993,27 @@ "startDate": "Start date", "status": "Status" } + }, + "form": { + "status": "Status", + "statusMessage": "Status Message", + "startDate": "Start Date", + "endDate": "End Date", + "ignored": "Aips ignored from last report", + "processed": "Aips processed from last report", + "inError": "Aips in error from last report", + "total": "Total Aips considered from last report" + }, + "report": { + "title": "Reports", + "table": { + "header": { + "executionNumber": "Report number", + "processedItems": "Items processed", + "ignoredItems": "Items ignored", + "inErrorItems": "Items in error" + } + } } }, "jobExecutionDetail": { diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index a6bdb24be..6a5729817 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -989,7 +989,8 @@ "job": { "create": "Créer", "edit": "Modifier", - "root": "Job" + "root": "Job", + "execution": "Exécution" }, "monitoring": { "root": "Surveillance" @@ -1952,9 +1953,17 @@ } }, "jobExecution": { + "ignored": "Aips ignorés du dernière rapport", + "processed": "Aips traités du dernière rapport", + "inError": "Aips en erreurs du dernière rapport", + "total": "Total Aips du dernière rapport", + "startDate": "Start Date", + "endDate": "End Date", + "statusMessage": "Détail de l'exécution du job", "button": { "refresh": "Rafraichir", - "start": "Lancer" + "start": "Lancer", + "resume": "Resumé" }, "home": { "title": "Exécutions du job : {{name}}" @@ -1984,6 +1993,27 @@ "startDate": "Date de début", "status": "Statut" } + }, + "form": { + "status": "Statut", + "statusMessage": "Détail de l'exécution du job", + "startDate": "Start Date", + "endDate": "End Date", + "ignored": "Aips ignorés du dernière rapport", + "processed": "Aips traités du dernière rapport", + "inError": "Aips en erreurs du dernière rapport", + "total": "Total Aips du dernière rapport" + }, + "report": { + "title": "Rapports", + "table": { + "header": { + "executionNumber": "Numero du rapport", + "processedItems": "Items traités", + "ignoredItems": "Items ignorés", + "inErrorItems": "Items en erreur" + } + } } }, "jobExecutionDetail": { -- GitLab