Skip to content
Snippets Groups Projects
Commit 62ad7fb6 authored by Florent Poittevin's avatar Florent Poittevin
Browse files

feat: 865 Manage DIP

parent a8b25f2a
No related branches found
No related tags found
No related merge requests found
Showing
with 1242 additions and 1 deletion
...@@ -296,7 +296,7 @@ ...@@ -296,7 +296,7 @@
type="submit" type="submit"
[disabled]="!form.valid || !form.dirty" [disabled]="!form.valid || !form.dirty"
> >
{{'deposit.submit' | translate }} {{'deposit.submit' | translate}}
</button> </button>
</div> </div>
</form> </form>
<form [formGroup]="form"
class="form-two-columns"
(ngSubmit)="onSubmit()"
>
<div class="two-columns-wrapper">
<div class="left-part">
<dlcm-shared-searchable-single-select *ngIf="getFormControl(formDefinition.organizationalUnitId) as fd"
solidifyValidation
[resourceNameSpace]="sharedOrgUnitActionNameSpace"
[state]="sharedOrgUnitState"
[formControl]="fd"
[required]="formValidationHelper.hasRequiredField(fd)"
[labelKey]="'name'"
[valueKey]="'resId'"
[placeholder]="'deposit.organizationUnit' | translate"
(valueChange)="orgUnitSelectionChange($event)"
[readonly]="true"
>
</dlcm-shared-searchable-single-select>
<mat-form-field *ngIf="getFormControl(formDefinition.resId) as fd">
<input [formControl]="fd"
[placeholder]="'preservation.dip.form.resId' | translate"
matInput
>
</mat-form-field>
<mat-form-field *ngIf="getFormControl(formDefinition.name) as fd">
<input [formControl]="fd"
[placeholder]="'preservation.dip.form.name' | translate"
matInput
>
</mat-form-field>
<mat-form-field *ngIf="getFormControl(formDefinition.description) as fd">
<input [formControl]="fd"
[placeholder]="'preservation.dip.form.description' | translate"
matInput
>
</mat-form-field>
<mat-form-field *ngIf="getFormControl(formDefinition.status) as fd">
<mat-label>{{'preservation.dip.form.status' | translate }}</mat-label>
<mat-select [formControl]="fd"
>
<mat-option *ngFor="let packageStatus of packageStatusEnumValues"
[value]="packageStatus.key"
>
{{packageStatus.value | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class="right-part">
<mat-form-field *ngIf="getFormControl(formDefinition.access) as fd">
<mat-label>{{'preservation.dip.form.access' | translate }}</mat-label>
<mat-select [formControl]="fd"
>
<mat-option *ngFor="let accessLevel of accessEnumValues"
[value]="accessLevel.key"
>
{{accessLevel.value | translate}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="getFormControl(formDefinition.complianceLevel) as fd">
<input [formControl]="fd"
[value]="model.info.complianceLevel | translate"
[placeholder]="'preservation.dip.form.complianceLevel' | translate"
matInput
>
</mat-form-field>
<ng-container *ngIf="readonly && model.aipIds && model.aipIds.length > 0 && model.info?.status === packageStatusEnum.COMPLETED">
<div *ngFor="let aip of model.aipIds"
class="link"
>
<mat-label class="disabled">{{'preservation.dip.form.aip' | translate}} : {{aip}}</mat-label>
<a *ngFor="let storagion of listStoragions"
[href]="getAipPath(aip, storagion.index)"
>
{{'app.aip.storage' | translate:{number: storagion.index} }}
</a>
</div>
</ng-container>
</div>
</div>
<div class="submit-button">
<button *ngIf="!readonly"
mat-flat-button
color="primary"
type="submit"
[disabled]="!form.valid || !form.dirty"
>
{{'preservation.dip.form.submit' | translate }}
</button>
</div>
</form>
@import "../sass/abstracts/mixins";
@import "../sass/abstracts/variables";
@import "../../src/app/shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational.scss";
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Input,
OnInit,
Output,
} from "@angular/core";
import {
FormBuilder,
Validators,
} from "@angular/forms";
import {MatDialog} from "@angular/material/dialog";
import {Dip} from "@app/generated-api";
import {SharedAbstractFormPresentational} from "@app/shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational";
import {BaseFormDefinition} from "@app/shared/models/base-form-definition.model";
import {environment} from "@environments/environment";
import {DipExtended} from "@preservation/dip/models/dip-extended.model";
import {AccessLevelEnumHelper} from "@shared/enums/business/access-level-enum.helper";
import {
PackageStatusEnum,
PackageStatusEnumHelper,
} from "@shared/enums/business/package-status.enum";
import {
AppRoutesEnum,
PreservationPlanningRoutesEnum,
} from "@shared/enums/routes.enum";
import {Storage} from "@shared/models/storage.model";
import {BreakpointService} from "@shared/services/breakpoint.service";
import {sharedOrgUnitActionNameSpace} from "@shared/stores/organizational-unit/shared-organizational-unit.action";
import {SharedOrganizationalUnitState} from "@shared/stores/organizational-unit/shared-organizational-unit.state";
import {
BehaviorSubject,
Observable,
} from "rxjs";
import {
KeyValue,
ObservableUtil,
PropertyName,
ResourceNameSpace,
SolidifyValidator,
urlSeparator,
} from "solidify-frontend";
@Component({
selector: "dlcm-dip-form",
templateUrl: "./dip-form.presentational.html",
styleUrls: ["./dip-form.presentational.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DipFormPresentational extends SharedAbstractFormPresentational<Dip> implements OnInit {
formDefinition: FormComponentFormDefinition = new FormComponentFormDefinition();
accessEnumValues: KeyValue[] = AccessLevelEnumHelper.getListKeyValue();
packageStatusEnumValues: KeyValue[] = PackageStatusEnumHelper.getListKeyValue();
sharedOrgUnitActionNameSpace: ResourceNameSpace = sharedOrgUnitActionNameSpace;
sharedOrgUnitState: typeof SharedOrganizationalUnitState = SharedOrganizationalUnitState;
@Input()
isReady: boolean = false;
listStoragions: Storage[] = environment.storagionUrls;
get packageStatusEnum(): typeof PackageStatusEnum {
return PackageStatusEnum;
}
private readonly _orgUnitValueBS: BehaviorSubject<string | undefined> = new BehaviorSubject<string | undefined>(undefined);
@Output("orgUnitChange")
readonly orgUnitValueObs: Observable<string | undefined> = ObservableUtil.asObservable(this._orgUnitValueBS);
constructor(protected readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _fb: FormBuilder,
private readonly dialog: MatDialog,
public readonly breakpointService: BreakpointService) {
super(_changeDetectorRef);
}
ngOnInit(): void {
super.ngOnInit();
}
protected initNewForm(): void {
}
protected bindFormTo(dip: DipExtended): void {
this.form = this._fb.group({
[this.formDefinition.organizationalUnitId]: [dip.info.organizationalUnitId, [SolidifyValidator]],
[this.formDefinition.resId]: [dip.resId, [SolidifyValidator]],
[this.formDefinition.name]: [dip.info.name, [Validators.required, SolidifyValidator]],
[this.formDefinition.description]: [dip.info.description, [SolidifyValidator]],
[this.formDefinition.status]: [dip.info.status, [SolidifyValidator]],
[this.formDefinition.access]: [dip.info.access, [SolidifyValidator]],
[this.formDefinition.complianceLevel]: [dip.info.complianceLevel, [SolidifyValidator]],
});
this.isValidWhenDisable = this.form.valid;
}
protected treatmentBeforeSubmit(dip: DipExtended): DipExtended {
const dipToSubmit: DipExtended = {
info: {
name: this.form.get(this.formDefinition.name).value,
description: this.form.get(this.formDefinition.description).value,
},
};
return dipToSubmit;
}
// @Override
protected disableSpecificField(): void {
this.form.get(this.formDefinition.resId).disable();
this.form.get(this.formDefinition.status).disable();
this.form.get(this.formDefinition.access).disable();
this.form.get(this.formDefinition.complianceLevel).disable();
}
getAipPath(aipId: string, storagionIndex: number): string {
return "#" + urlSeparator + AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.aip + urlSeparator + storagionIndex + urlSeparator + PreservationPlanningRoutesEnum.aipDetail + urlSeparator + aipId;
}
}
class FormComponentFormDefinition extends BaseFormDefinition {
@PropertyName() organizationalUnitId: string;
@PropertyName() resId: string;
@PropertyName() name: string;
@PropertyName() description: string;
@PropertyName() status: string;
@PropertyName() access: string;
@PropertyName() complianceLevel: string;
@PropertyName() aip: string;
}
<div>
<dlcm-shared-button-status-history class="history"
(showHistory)="showHistory()"
></dlcm-shared-button-status-history>
<dlcm-button-toolbar-detail [mode]="isEdit ? 'edit' : 'detail'"
[currentModel]="currentObs | async"
[deleteAvailable]="false"
[listExtraButtons]="listExtraButtons"
(editChange)="edit()"
(deleteChange)="delete()"
(backToDetailChange)="backToDetail()"
(backToListChange)="backToList()"
>
</dlcm-button-toolbar-detail>
</div>
<mat-tab-group #matTabGroup
mat-align-tabs="center"
animationDuration="0ms"
[selectedIndex]="tabSelected"
(selectedIndexChange)="navigate($event)"
>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon class="tab-header-icon">assignment</mat-icon>
<span class="tab-header-label">{{'preservation.dip.tab.details' | translate}}</span>
</ng-template>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<mat-icon class="tab-header-icon">insert_drive_file</mat-icon>
<span class="tab-header-label">{{'preservation.dip.tab.datafiles' | translate}}</span>
</ng-template>
</mat-tab>
</mat-tab-group>
<div class="tab-content">
<router-outlet></router-outlet>
</div>
@import "../sass/abstracts/variables";
@import "../sass/abstracts/mixins";
@import "./../../../../../../shared/components/routables/shared-abstract-detail-edit-common/shared-abstract-detail-edit-common.routable";
$height-alert: 30px;
:host {
$padding-top: $height-alert + 10px;
padding-top: $padding-top;
@include respond-to-breakpoint("xs") {
$padding-top: $height-alert + 10px + 20px;
padding-top: $padding-top;
}
.tab-header-icon {
}
.tab-header-label {
padding-left: 10px;
@include respond-to-breakpoint("xs") {
display: none;
}
}
}
import {
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
ViewChild,
} from "@angular/core";
import {MatDialog} from "@angular/material";
import {MatTabGroup} from "@angular/material/tabs";
import {
ActivatedRoute,
NavigationCancel,
NavigationEnd,
Router,
} from "@angular/router";
import {DipStateModel} from "@app/features/preservation/dip/stores/dip.state";
import {Dip} from "@app/generated-api";
import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
import {Navigate} from "@ngxs/router-plugin";
import {
Actions,
Store,
} from "@ngxs/store";
import {DipFormPresentational} from "@preservation/dip/components/presentationals/dip-form/dip-form.presentational";
import {DipTabEnum} from "@preservation/dip/enums/dip-tab.enum";
import {DipHelper} from "@preservation/dip/helpers/dip.helper";
import {
PreservationDipAction,
preservationDipActionNameSpace,
} from "@preservation/dip/stores/dip.action";
import {PreservationDipStatusHistoryAction} from "@preservation/dip/stores/status-history/dip-status-history.action";
import {DipStatusHistoryState} from "@preservation/dip/stores/status-history/dip-status-history.state";
import {SharedHistoryDialog} from "@shared/components/dialogs/shared-history/shared-history.dialog";
import {SharedAbstractDetailEditRoutable} from "@shared/components/routables/shared-abstract-detail-edit/shared-abstract-detail-edit.routable";
import {PackageStatusEnum} from "@shared/enums/business/package-status.enum";
import {
DepositRoutesEnum,
RoutesEnum,
} from "@shared/enums/routes.enum";
import {ExtraButtonToolbar} from "@shared/models/extra-button-toolbar.model";
import {StatusHistoryDialog} from "@shared/models/status-history-dialog.model";
import {StatusHistory} from "@shared/models/status-history.model";
import {SecurityService} from "@shared/services/security.service";
import {Observable} from "rxjs";
import {tap} from "rxjs/internal/operators/tap";
import {
distinctUntilChanged,
filter,
} from "rxjs/operators";
import {
isNullOrUndefined,
MemoizedUtil,
QueryParameters,
TRANSLATE,
} from "solidify-frontend";
@Component({
selector: "dlcm-dip-detail-edit-routable",
templateUrl: "./dip-detail-edit.routable.html",
styleUrls: ["./dip-detail-edit.routable.scss"],
})
export class DipDetailEditRoutable extends SharedAbstractDetailEditRoutable<Dip, DipStateModel> implements OnInit, OnDestroy {
historyObs: Observable<StatusHistory[]> = MemoizedUtil.select(this._store, DipStatusHistoryState, state => state.history);
isLoadingObs: Observable<boolean> = MemoizedUtil.isLoading(this._store, DipStatusHistoryState);
queryParametersObs: Observable<QueryParameters> = MemoizedUtil.select(this._store, DipStatusHistoryState, state => state.queryParameters);
@ViewChild("formPresentational", {static: false})
readonly formPresentational: DipFormPresentational;
@ViewChild("matTabGroup", {static: false})
readonly matTabGroup: MatTabGroup;
message: string;
tabSelected: DipTabEnum;
get packageStatusEnum(): typeof PackageStatusEnum {
return PackageStatusEnum;
}
readonly KEY_PARAM_NAME: keyof Dip & string = undefined;
constructor(protected readonly _store: Store,
protected readonly _route: ActivatedRoute,
protected readonly _actions$: Actions,
protected readonly _changeDetector: ChangeDetectorRef,
protected readonly _dialog: MatDialog,
protected readonly _router: Router,
private readonly _securityService: SecurityService) {
super(_store, _route, _actions$, _changeDetector, _dialog, LocalStateEnum.preservation_dip, preservationDipActionNameSpace, LocalStateEnum.preservation);
}
ngOnInit(): void {
super.ngOnInit();
this.retrieveCurrentModelWithUrl();
this._computeCurrentTab();
this.subscribe(this._router.events
.pipe(
filter(event => event instanceof NavigationCancel || event instanceof NavigationEnd),
distinctUntilChanged(),
tap(event => {
this._computeCurrentTab();
this.matTabGroup.selectedIndex = this.tabSelected;
}),
),
);
}
ngOnDestroy(): void {
super.ngOnDestroy();
this.cleanState();
}
private _computeCurrentTab(): void {
const tabRouteSelected = DipHelper.getTabRouteSelected(this._route);
this.tabSelected = DipHelper.getTabSelectedIndexWithRoute(tabRouteSelected);
}
getSubResourceWithParentId(id: string): void {
}
showHistory(): void {
const dialogRef = this._dialog.open(SharedHistoryDialog, {
width: "800px",
data: {
parentId: null,
resourceResId: this._resId,
name: this._state,
statusHistory: this.historyObs,
isLoading: this.isLoadingObs,
queryParametersObs: this.queryParametersObs,
state: PreservationDipStatusHistoryAction,
} as StatusHistoryDialog,
});
}
listExtraButtons: ExtraButtonToolbar<Dip>[] = [
{
color: "accent",
icon: "file_download",
displayCondition: current => !this.isEdit && !isNullOrUndefined(current) && !isNullOrUndefined(current.info) && current.info.status === PackageStatusEnum.COMPLETED,
callback: () => this.download(),
labelToTranslate: TRANSLATE("preservation.dip.button.download"),
},
{
color: "primary",
icon: "play_circle_filled",
displayCondition: current => !this.isEdit && !isNullOrUndefined(current) && !isNullOrUndefined(current.info) && current.info.status === PackageStatusEnum.IN_ERROR,
callback: () => this.resume(),
labelToTranslate: TRANSLATE("preservation.dip.button.resume"),
},
];
// @Override
edit(): void {
const tabRouteSelected = DipHelper.getTabRouteSelected(this._route);
this._store.dispatch(new Navigate([RoutesEnum.preservationDipDetail, this._resId, tabRouteSelected, DepositRoutesEnum.edit]));
}
navigate(tabSelected: DipTabEnum): void {
const tabRouteSelected = DipHelper.getTabRouteSelectedWithTabIndex(tabSelected);
const path = [RoutesEnum.preservationDipDetail, this._resId, tabRouteSelected];
this._store.dispatch(new Navigate(path));
}
download(): void {
this._store.dispatch(new PreservationDipAction.Download(this._resId));
}
resume(): void {
this._store.dispatch(new PreservationDipAction.Resume(this._resId));
}
}
<div>
<div class="tab-content">
<div class="file-uploaded">
<h1>{{'deposit.file.title.filesOfDeposit' | translate}}</h1>
<div class="file-uploaded-header">
<button mat-icon-button
mat-button
(click)="refresh()"
[matTooltip]="'deposit.file.tree.refresh' | translate"
[matTooltipPosition]="'left'"
[class.spinning]="isLoadingDataFileObs | async"
[disabled]="isLoadingDataFileObs | async"
>
<fa-icon icon="sync-alt"></fa-icon>
</button>
</div>
<div class="file-viewer">
<div class="file-list-wrapper"
[dlcmSpinner]="isLoadingDataFileObs | async"
>
<dlcm-shared-data-table *ngIf="columns"
[columns]="columns"
[actions]="actions"
[isLoading]="isLoadingDataFileObs | async"
[datas]="listDataFileObs | async"
[queryParameters]="queryParametersObs | async"
(queryParametersChange)="onQueryParametersEvent($event)"
(selectChange)="showDetail($event)"
>
</dlcm-shared-data-table>
</div>
<ng-template #noFile>
<label>{{'deposit.file.tree.noFile' | translate}}</label>
</ng-template>
</div>
</div>
</div>
</div>
@import "../sass/abstracts/variables";
@import "../sass/abstracts/mixins";
@import "../../../../../../shared/components/routables/shared-abstract-detail-edit/shared-abstract-detail-edit.routable";
:host {
padding: 0;
.tab-content {
.file-uploaded {
.file-uploaded-header {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
min-height: 35px;
fa-icon {
font-size: 20px;
}
button {
transition-property: transform;
transition-duration: 1s;
position: absolute;
top: -10px;
right: 10px;
&.spinning {
animation-name: rotate;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
}
}
}
}
}
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
OnInit,
ViewChild,
} from "@angular/core";
import {MatDialog} from "@angular/material";
import {ActivatedRoute} from "@angular/router";
import {DipStateModel} from "@app/features/preservation/dip/stores/dip.state";
import {Dip} from "@app/generated-api";
import {environment} from "@environments/environment";
import {
Actions,
Store,
} from "@ngxs/store";
import {DipFormPresentational} from "@preservation/dip/components/presentationals/dip-form/dip-form.presentational";
import {DipDataFile} from "@preservation/dip/models/dip-data-file.model";
import {PreservationDipDataFileAction} from "@preservation/dip/stores/data-file/dip-data-file.action";
import {DipDataFileState} from "@preservation/dip/stores/data-file/dip-data-file.state";
import {PreservationDipDataFileStatusHistoryAction} from "@preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action";
import {DipDataFileStatusHistoryState} from "@preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state";
import {preservationDipActionNameSpace} from "@preservation/dip/stores/dip.action";
import {
SharedFileDetailDialog,
SharedFileDetailDialogData,
} from "@shared/components/dialogs/shared-file-detail/shared-file-detail.dialog";
import {SharedAbstractDetailEditRoutable} from "@shared/components/routables/shared-abstract-detail-edit/shared-abstract-detail-edit.routable";
import {ComplianceLevelEnum} from "@shared/enums/business/compliance-level.enum";
import {DataFileStatusEnum} from "@shared/enums/business/data-file-status.enum";
import {DataTableComponentEnum} from "@shared/enums/data-table-component.enum";
import {FieldTypeEnum} from "@shared/enums/field-type.enum";
import {LocalStateEnum} from "@shared/enums/local-state.enum";
import {AppRoutesEnum} from "@shared/enums/routes.enum";
import {DataTableActions} from "@shared/models/data-table-actions.model";
import {DataTableColumns} from "@shared/models/data-table-columns.model";
import {StatusHistory} from "@shared/models/status-history.model";
import {Observable} from "rxjs";
import {
CompositionState,
isNullOrUndefined,
MemoizedUtil,
OrderEnum,
QueryParameters,
TRANSLATE,
} from "solidify-frontend";
@Component({
selector: "dlcm-dip-file-routable",
templateUrl: "./dip-file.routable.html",
styleUrls: ["./dip-file.routable.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DipFileRoutable extends SharedAbstractDetailEditRoutable<Dip, DipStateModel> implements OnInit {
isLoadingDataFileObs: Observable<boolean> = MemoizedUtil.isLoading(this._store, DipDataFileState);
listDataFileObs: Observable<DipDataFile[]> = CompositionState.list(this._store, DipDataFileState);
queryParametersObs: Observable<QueryParameters> = CompositionState.queryParameters(this._store, DipDataFileState);
isLoadingHistoryObs: Observable<boolean> = MemoizedUtil.isLoading(this._store, DipDataFileStatusHistoryState);
dataFileHistoryObs: Observable<StatusHistory[]> = MemoizedUtil.select(this._store, DipDataFileStatusHistoryState, state => state.history);
queryParametersHistoryObs: Observable<QueryParameters> = MemoizedUtil.select(this._store, DipDataFileStatusHistoryState, state => state.queryParameters);
@ViewChild("formPresentational", {static: false})
readonly formPresentational: DipFormPresentational;
columns: DataTableColumns<DipDataFile>[];
actions: DataTableActions<DipDataFile>[];
readonly KEY_PARAM_NAME: keyof Dip & string = undefined;
constructor(protected readonly _store: Store,
protected readonly _route: ActivatedRoute,
protected readonly _actions$: Actions,
protected readonly _changeDetector: ChangeDetectorRef,
protected readonly _dialog: MatDialog) {
super(_store, _route, _actions$, _changeDetector, _dialog, LocalStateEnum.preservation_dip, preservationDipActionNameSpace, LocalStateEnum.preservation);
}
ngOnInit(): void {
super.ngOnInit();
this.getCurrentModelOnParent();
this.columns = [
{
field: "fileName",
header: TRANSLATE("deposit.datafile.table.fileName"),
type: FieldTypeEnum.string,
order: OrderEnum.none,
isSortable: true,
isFilterable: false,
},
{
field: "creation.when" as any,
header: TRANSLATE("deposit.datafile.table.creation.when"),
type: FieldTypeEnum.datetime,
order: OrderEnum.none,
isFilterable: false,
isSortable: true,
},
{
field: "status",
header: TRANSLATE("deposit.datafile.table.status"),
type: FieldTypeEnum.singleSelect,
order: OrderEnum.none,
isSortable: false,
isFilterable: false,
translate: true,
filterEnum: [
{
key: DataFileStatusEnum.IN_ERROR,
value: TRANSLATE("IN_ERROR"),
},
{
key: DataFileStatusEnum.READY,
value: TRANSLATE("READY"),
},
{
key: DataFileStatusEnum.RECEIVED,
value: TRANSLATE("RECEIVED"),
},
{
key: DataFileStatusEnum.CHANGE_RELATIVE_LOCATION,
value: TRANSLATE("CHANGE_RELATIVE_LOCATION"),
},
{
key: DataFileStatusEnum.TO_PROCESS,
value: TRANSLATE("TO_PROCESS"),
},
{
key: DataFileStatusEnum.PROCESSED,
value: TRANSLATE("PROCESSED"),
},
{
key: DataFileStatusEnum.FILE_FORMAT_IDENTIFIED,
value: TRANSLATE("FILE_FORMAT_IDENTIFIED"),
},
{
key: DataFileStatusEnum.FILE_FORMAT_UNKNOWN,
value: TRANSLATE("FILE_FORMAT_UNKNOWN"),
},
{
key: DataFileStatusEnum.VIRUS_CHECKED,
value: TRANSLATE("VIRUS_CHECKED"),
},
{
key: DataFileStatusEnum.CLEANING,
value: TRANSLATE("CLEANING"),
},
{
key: DataFileStatusEnum.CLEANED,
value: TRANSLATE("CLEANED"),
},
],
},
{
field: "complianceLevel",
header: TRANSLATE("deposit.datafile.table.complianceLevel"),
type: FieldTypeEnum.singleSelect,
order: OrderEnum.none,
isSortable: false,
isFilterable: false,
translate: true,
component: DataTableComponentEnum.conformityLevelStar,
filterEnum: [
{
key: ComplianceLevelEnum.FULL_COMPLIANCE,
value: TRANSLATE("FULL_COMPLIANCE"),
},
{
key: ComplianceLevelEnum.AVERAGE_COMPLIANCE,
value: TRANSLATE("AVERAGE_COMPLIANCE"),
},
{
key: ComplianceLevelEnum.WEAK_COMPLIANCE,
value: TRANSLATE("WEAK_COMPLIANCE"),
},
{
key: ComplianceLevelEnum.NO_COMPLIANCE,
value: TRANSLATE("NO_COMPLIANCE"),
},
{
key: ComplianceLevelEnum.NOT_ASSESSED,
value: TRANSLATE("NOT_ASSESSED"),
},
],
},
];
this.actions = [
{
logo: "warning",
callback: (dipDataFile: DipDataFile) => this.resumeDataFile(this._resId, dipDataFile),
placeholder: TRANSLATE("crud.list.action.resume"),
displayOnCondition: current => isNullOrUndefined(current) || current.status === DataFileStatusEnum.IN_ERROR,
},
{
logo: "file_download",
callback: (dipDataFile: DipDataFile) => this.downloadDataFile(this._resId, dipDataFile),
placeholder: TRANSLATE("crud.list.action.download"),
displayOnCondition: (dipDataFile: DipDataFile) => true,
},
];
}
private getCurrentModelOnParent(): void {
this._resId = this._route.snapshot.parent.paramMap.get(AppRoutesEnum.paramIdWithoutPrefixParam);
this.getDepositById(this._resId);
}
private getDepositById(id: string): void {
// this._store.dispatch(ResourceActionHelper.getById(preservationDipActionNameSpace, id, true));
this.getSubResourceWithParentId(id);
}
getSubResourceWithParentId(id: string): void {
// const queryParameter = new QueryParameters();
// MappingObjectUtil.set(queryParameter.search.searchItems, "relativeLocation", "/");
this._store.dispatch(new PreservationDipDataFileAction.GetAll(id, null, true));
// this._store.dispatch(new PreservationDipDataFileAction.GetListFolder(id));
}
onQueryParametersEvent(queryParameters: QueryParameters): void {
this._store.dispatch(new PreservationDipDataFileAction.ChangeQueryParameters(this._resId, queryParameters, true));
// this._changeDetector.detectChanges(); // Allow to display spinner the first time
}
refresh(): void {
this._store.dispatch(new PreservationDipDataFileAction.Refresh(this._resId));
}
download($event: DipDataFile): void {
this._store.dispatch(new PreservationDipDataFileAction.Download(this._resId, $event));
}
showDetail(dipDataFile: DipDataFile): void {
const dialogRef = this._dialog.open(SharedFileDetailDialog, {
data: {
dataFile: dipDataFile,
parentId: this._resId,
isReadonly: true,
isLoading: this.isLoadingHistoryObs,
statusHistory: this.dataFileHistoryObs,
queryParametersObs: this.queryParametersHistoryObs,
state: PreservationDipDataFileStatusHistoryAction,
name: LocalStateEnum.preservation_dip,
buttons: [
{
labelToTranslate: TRANSLATE("deposit.file.button.download"),
color: "accent",
icon: "file_download",
callback: (current) => this.downloadDataFile(this._resId, dipDataFile),
order: 2,
},
{
labelToTranslate: TRANSLATE("deposit.file.button.resume"),
color: "accent",
icon: "warning",
callback: (current) => this.resumeDataFile(this._resId, dipDataFile),
displayCondition: current => current.status === DataFileStatusEnum.IN_ERROR,
order: 3,
},
],
} as SharedFileDetailDialogData<DipDataFile>,
width: environment.modalWidth,
});
}
private downloadDataFile(parentId: string, dataFile: DipDataFile): void {
this._store.dispatch(new PreservationDipDataFileAction.Download(parentId, dataFile));
}
private resumeDataFile(parentId: string, dataFile: DipDataFile): void {
this._store.dispatch(new PreservationDipDataFileAction.Resume(parentId, dataFile));
}
}
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
OnInit,
} from "@angular/core";
import {MatDialog} from "@angular/material/dialog";
import {ActivatedRoute} from "@angular/router";
import {DipStateModel} from "@app/features/preservation/dip/stores/dip.state";
import {
Dip,
PreservationJob,
} from "@app/generated-api";
import {SharedAbstractListRoutable} from "@app/shared/components/routables/shared-abstract-list/shared-abstract-list.routable";
import {FieldTypeEnum} from "@app/shared/enums/field-type.enum";
import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
import {appAuthorizedOrganizationalUnitNameSpace} from "@app/stores/authorized-organizational-unit/app-authorized-organizational-unit.action";
import {AppAuthorizedOrganizationalUnitState} from "@app/stores/authorized-organizational-unit/app-authorized-organizational-unit.state";
import {
Actions,
Store,
} from "@ngxs/store";
import {
PreservationDipAction,
preservationDipActionNameSpace,
} from "@preservation/dip/stores/dip.action";
import {PackageStatusEnumHelper} from "@shared/enums/business/package-status.enum";
import {DataTableActions} from "@shared/models/data-table-actions.model";
import {
OrderEnum,
ResourceNameSpace,
TRANSLATE,
} from "solidify-frontend";
@Component({
selector: "dlcm-dip-list-routable",
templateUrl: "../../../../../../shared/components/routables/shared-abstract-list/shared-abstract-list.routable.html",
styleUrls: ["../../../../../../shared/components/routables/shared-abstract-list/shared-abstract-list.routable.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DipListRoutable extends SharedAbstractListRoutable<Dip, DipStateModel> implements OnInit {
readonly KEY_CREATE_BUTTON: string = undefined;
readonly KEY_REFRESH_BUTTON: string = TRANSLATE("preservation.dip.refresh");
readonly KEY_BACK_BUTTON: string = TRANSLATE("preservation.dip.back");
readonly KEY_PARAM_NAME: keyof Dip & string = undefined;
appAuthorizedOrganizationalUnitNameSpace: ResourceNameSpace = appAuthorizedOrganizationalUnitNameSpace;
appAuthorizedOrganizationalUnitState: typeof AppAuthorizedOrganizationalUnitState = AppAuthorizedOrganizationalUnitState;
constructor(protected readonly _store: Store,
protected readonly _changeDetector: ChangeDetectorRef,
protected readonly _route: ActivatedRoute,
protected readonly _actions$: Actions,
protected readonly _dialog: MatDialog) {
super(_store, _changeDetector, _route, _actions$, _dialog, LocalStateEnum.preservation_dip, preservationDipActionNameSpace, {
canCreate: false,
}, LocalStateEnum.preservation);
}
conditionDisplayEditButton(model: Dip | undefined): boolean {
return false;
}
conditionDisplayDeleteButton(model: Dip | undefined): boolean {
return false;
}
ngOnInit(): void {
super.ngOnInit();
}
defineColumns(): void {
this.columns = [
{
field: "info.name" as any,
header: TRANSLATE("preservation.dip.table.header.title"),
type: FieldTypeEnum.string,
order: OrderEnum.none,
isFilterable: true,
isSortable: true,
},
// {
// field: "organizationalUnit.name" as any,
// header: TRANSLATE("preservation.dip.table.header.organizationalUnit"),
// type: FieldTypeEnum.searchableSingleSelect,
// order: OrderEnum.none,
// isFilterable: false,
// // isSortable: true,
// resourceNameSpace: this.appAuthorizedOrganizationalUnitNameSpace,
// resourceState: this.appAuthorizedOrganizationalUnitState as any,
// filterableField: "info.organizationalUnitId" as any,
// },
{
field: "creation.when" as any,
header: TRANSLATE("preservation.dip.table.header.creation.when"),
type: FieldTypeEnum.datetime,
order: OrderEnum.none,
isFilterable: true,
isSortable: true,
},
{
field: "lastUpdate.when" as any,
header: TRANSLATE("preservation.dip.table.header.lastUpdate.when"),
type: FieldTypeEnum.datetime,
order: OrderEnum.descending,
isFilterable: true,
isSortable: true,
},
{
field: "info.status" as any,
header: TRANSLATE("preservation.dip.table.header.status"),
type: FieldTypeEnum.singleSelect,
order: OrderEnum.none,
isFilterable: true,
isSortable: true,
translate: true,
filterEnum: PackageStatusEnumHelper.getListKeyValue(),
},
];
}
// @Override
protected defineActions(): DataTableActions<PreservationJob>[] {
return [
{
logo: "file_download",
callback: (model: Dip) => this.download(model),
placeholder: TRANSLATE("crud.list.action.download"),
displayOnCondition: (model: Dip) => true,
},
];
}
private download(dip: Dip): void {
this._store.dispatch(new PreservationDipAction.Download(dip.resId));
}
}
<div class="wrapper"
[dlcmSpinner]="(isLoadingObs | async)"
>
<dlcm-dip-form #formPresentational
*ngIf="isReadyToBeDisplayedObs | async"
[model]="currentObs| async"
[readonly]="!isEdit"
(submitChange)="update($event)"
(dirtyChange)="updateCanDeactivate($event)"
>
</dlcm-dip-form>
</div>
@import "../sass/abstracts/variables";
@import "../sass/abstracts/mixins";
:host {
.wrapper {
min-height: 300px;
}
}
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
ViewChild,
} from "@angular/core";
import {MatDialog} from "@angular/material";
import {ActivatedRoute} from "@angular/router";
import {
DipState,
DipStateModel,
} from "@app/features/preservation/dip/stores/dip.state";
import {Dip} from "@app/generated-api";
import {DepositFormPresentational} from "@deposit/components/presentationals/deposit-form/deposit-form.presentational";
import {
Actions,
Select,
Store,
} from "@ngxs/store";
import {preservationDipActionNameSpace} from "@preservation/dip/stores/dip.action";
import {SharedAbstractDetailEditRoutable} from "@shared/components/routables/shared-abstract-detail-edit/shared-abstract-detail-edit.routable";
import {LocalStateEnum} from "@shared/enums/local-state.enum";
import {Observable} from "rxjs";
@Component({
selector: "dlcm-dip-metadata-routable",
templateUrl: "./dip-metadata.routable.html",
styleUrls: ["./dip-metadata.routable.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DipMetadataRoutable extends SharedAbstractDetailEditRoutable<Dip, DipStateModel> implements OnInit, OnDestroy {
@Select(DipState.isLoadingWithDependency) isLoadingWithDependencyObs: Observable<boolean>;
@Select(DipState.isReadyToBeDisplayed) isReadyToBeDisplayedObs: Observable<boolean>;
@ViewChild("formPresentational", {static: false})
readonly formPresentational: DepositFormPresentational;
readonly KEY_PARAM_NAME: keyof Dip & string = undefined;
constructor(protected readonly _store: Store,
protected readonly _route: ActivatedRoute,
protected readonly _actions$: Actions,
protected readonly _changeDetector: ChangeDetectorRef,
protected readonly _dialog: MatDialog) {
super(_store, _route, _actions$, _changeDetector, _dialog, LocalStateEnum.preservation_dip, preservationDipActionNameSpace, LocalStateEnum.preservation);
}
ngOnInit(): void {
super.ngOnInit();
}
ngOnDestroy(): void {
super.ngOnDestroy();
}
protected getSubResourceWithParentId(id: string): void {
}
}
import {NgModule} from "@angular/core";
import {RouterModule} from "@angular/router";
import {
AppRoutesEnum,
PreservationPlanningRoutesEnum,
} from "@app/shared/enums/routes.enum";
import {DlcmRoutes} from "@app/shared/models/dlcm-route.model";
import {DipDetailEditRoutable} from "@preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable";
import {DipFileRoutable} from "@preservation/dip/components/routables/dip-file/dip-file.routable";
import {DipListRoutable} from "@preservation/dip/components/routables/dip-list/dip-list.routable";
import {DipMetadataRoutable} from "@preservation/dip/components/routables/dip-metadata/dip-metadata.routable";
import {DipState} from "@preservation/dip/stores/dip.state";
import {CanDeactivateGuard} from "@shared/services/can-deactivate-guard.service";
import {TRANSLATE} from "solidify-frontend";
const routes: DlcmRoutes = [
{
path: AppRoutesEnum.root,
component: DipListRoutable,
data: {},
},
{
path: PreservationPlanningRoutesEnum.dipDetail + AppRoutesEnum.separator + AppRoutesEnum.paramId,
redirectTo: PreservationPlanningRoutesEnum.dipDetail + AppRoutesEnum.separator + AppRoutesEnum.paramId + AppRoutesEnum.separator + PreservationPlanningRoutesEnum.dipMetadata,
pathMatch: "full",
},
{
path: PreservationPlanningRoutesEnum.dipDetail + AppRoutesEnum.separator + AppRoutesEnum.paramId,
component: DipDetailEditRoutable,
data: {
breadcrumbMemoizedSelector: DipState.currentTitle,
},
children: [
{
path: PreservationPlanningRoutesEnum.dipMetadata,
component: DipMetadataRoutable,
data: {
breadcrumb: TRANSLATE("breadcrumb.preservation.dip.metadata"),
noBreadcrumbLink: true,
},
children: [
{
path: PreservationPlanningRoutesEnum.dipEdit,
data: {
breadcrumb: TRANSLATE("breadcrumb.preservation.dip.edit"),
},
canDeactivate: [CanDeactivateGuard],
},
],
},
{
path: PreservationPlanningRoutesEnum.dipFiles,
component: DipFileRoutable,
data: {
breadcrumb: TRANSLATE("breadcrumb.preservation.dip.file"),
noBreadcrumbLink: true,
},
children: [
{
path: PreservationPlanningRoutesEnum.dipEdit,
data: {
breadcrumb: TRANSLATE("breadcrumb.preservation.dip.edit"),
},
canDeactivate: [CanDeactivateGuard],
},
],
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class DipRoutingModule {
}
import {NgModule} from "@angular/core";
import {DipFormPresentational} from "@app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational";
import {DipFileRoutable} from "@app/features/preservation/dip/components/routables/dip-file/dip-file.routable";
import {DipListRoutable} from "@app/features/preservation/dip/components/routables/dip-list/dip-list.routable";
import {DipMetadataRoutable} from "@app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable";
import {DipDataFileState} from "@app/features/preservation/dip/stores/data-file/dip-data-file.state";
import {DipDataFileStatusHistoryState} from "@app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state";
import {DipState} from "@app/features/preservation/dip/stores/dip.state";
import {DipStatusHistoryState} from "@app/features/preservation/dip/stores/status-history/dip-status-history.state";
import {SharedModule} from "@app/shared/shared.module";
import {TranslateModule} from "@ngx-translate/core";
import {NgxsModule} from "@ngxs/store";
import {DipRoutingModule} from "@preservation/dip/dip-routing.module";
import {DipDetailEditRoutable} from "./components/routables/dip-detail-edit/dip-detail-edit.routable";
const routables = [
DipListRoutable,
DipDetailEditRoutable,
DipFileRoutable,
DipMetadataRoutable,
];
const containers = [];
const dialogs = [];
const presentationals = [
DipFormPresentational,
];
@NgModule({
declarations: [
...routables,
...containers,
...dialogs,
...presentationals,
],
imports: [
SharedModule,
DipRoutingModule,
TranslateModule.forChild({}),
NgxsModule.forFeature([
DipState,
DipDataFileState,
DipStatusHistoryState,
DipDataFileStatusHistoryState,
]),
],
entryComponents: [
...dialogs,
],
exports: [
...routables,
],
providers: [],
})
export class DipModule {
}
export enum DipTabEnum {
metadata = 0,
file = 1,
}
import {ActivatedRoute} from "@angular/router";
import {DipTabEnum} from "@preservation/dip/enums/dip-tab.enum";
import {PreservationPlanningRoutesEnum} from "@shared/enums/routes.enum";
export class DipHelper {
static getTabRouteSelected(route: ActivatedRoute): PreservationPlanningRoutesEnum | undefined {
const children = route.snapshot.children;
if (children.length > 0 && children[0].url.length > 0) {
const mode = children[0].url[0].path;
return mode as PreservationPlanningRoutesEnum;
}
return undefined;
}
static getTabSelectedIndexWithRoute(tabRouteSelected: PreservationPlanningRoutesEnum): DipTabEnum | undefined {
if (tabRouteSelected === PreservationPlanningRoutesEnum.dipMetadata) {
return DipTabEnum.metadata;
}
if (tabRouteSelected === PreservationPlanningRoutesEnum.dipFiles) {
return DipTabEnum.file;
}
return undefined;
}
static getTabRouteSelectedWithTabIndex(tabIndexSelected: DipTabEnum): PreservationPlanningRoutesEnum | undefined {
if (tabIndexSelected === DipTabEnum.metadata) {
return PreservationPlanningRoutesEnum.dipMetadata;
}
if (tabIndexSelected === DipTabEnum.file) {
return PreservationPlanningRoutesEnum.dipFiles;
}
return undefined;
}
}
import {DataFile} from "@shared/models/business/data-file.model";
export interface DipDataFile extends DataFile {
}
import {Dip} from "@app/generated-api";
export interface DipExtended extends Dip {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment