From 62ad7fb68e091be16b32f4d52ab3734a85d0608f Mon Sep 17 00:00:00 2001
From: Florent Poittevin <florent.poittevin@unige.ch>
Date: Fri, 10 Jan 2020 14:18:18 +0100
Subject: [PATCH] feat: 865 Manage DIP

---
 .../deposit-form.presentational.html          |   2 +-
 .../dip-form/dip-form.presentational.html     |  99 +++++
 .../dip-form/dip-form.presentational.scss     |   3 +
 .../dip-form/dip-form.presentational.ts       | 132 +++++++
 .../dip-detail-edit.routable.html             |  40 ++
 .../dip-detail-edit.routable.scss             |  27 ++
 .../dip-detail-edit.routable.ts               | 174 +++++++++
 .../routables/dip-file/dip-file.routable.html |  43 +++
 .../routables/dip-file/dip-file.routable.scss |  51 +++
 .../routables/dip-file/dip-file.routable.ts   | 276 ++++++++++++++
 .../routables/dip-list/dip-list.routable.ts   | 137 +++++++
 .../dip-metadata/dip-metadata.routable.html   |  12 +
 .../dip-metadata/dip-metadata.routable.scss   |   8 +
 .../dip-metadata/dip-metadata.routable.ts     |  61 +++
 .../preservation/dip/dip-routing.module.ts    |  77 ++++
 .../features/preservation/dip/dip.module.ts   |  55 +++
 .../preservation/dip/enums/dip-tab.enum.ts    |   4 +
 .../preservation/dip/helpers/dip.helper.ts    |  34 ++
 .../dip/models/dip-data-file.model.ts         |   4 +
 .../dip/models/dip-extended.model.ts          |   4 +
 .../stores/data-file/dip-data-file.action.ts  | 104 +++++
 .../stores/data-file/dip-data-file.state.ts   | 116 ++++++
 .../dip-data-file-status-history.action.ts    |  27 ++
 .../dip-data-file-status-history.state.ts     |  44 +++
 .../preservation/dip/stores/dip.action.ts     | 130 +++++++
 .../preservation/dip/stores/dip.state.ts      | 167 ++++++++
 .../dip-status-history.action.ts              |  27 ++
 .../dip-status-history.state.ts               |  44 +++
 .../preservation-routing.module.ts            |   9 +
 .../preservation/preservation.module.ts       |  10 +-
 .../preservation/stores/preservation.state.ts |   9 +-
 src/app/shared/enums/api.enum.ts              |   6 +-
 src/app/shared/enums/local-state.enum.ts      |   5 +
 src/app/shared/enums/routes.enum.ts           |   5 +-
 .../shared/utils/store-route-local.util.ts    |   6 +
 src/assets/i18n/de.json                       | 360 ++++++++++--------
 src/assets/i18n/en.json                       |  76 +++-
 src/assets/i18n/fr.json                       |  78 +++-
 38 files changed, 2286 insertions(+), 180 deletions(-)
 create mode 100644 src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.html
 create mode 100644 src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.scss
 create mode 100644 src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.ts
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.html
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.scss
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.ts
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.html
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.scss
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.ts
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-list/dip-list.routable.ts
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.html
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.scss
 create mode 100644 src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.ts
 create mode 100644 src/app/features/preservation/dip/dip-routing.module.ts
 create mode 100644 src/app/features/preservation/dip/dip.module.ts
 create mode 100644 src/app/features/preservation/dip/enums/dip-tab.enum.ts
 create mode 100644 src/app/features/preservation/dip/helpers/dip.helper.ts
 create mode 100644 src/app/features/preservation/dip/models/dip-data-file.model.ts
 create mode 100644 src/app/features/preservation/dip/models/dip-extended.model.ts
 create mode 100644 src/app/features/preservation/dip/stores/data-file/dip-data-file.action.ts
 create mode 100644 src/app/features/preservation/dip/stores/data-file/dip-data-file.state.ts
 create mode 100644 src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action.ts
 create mode 100644 src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state.ts
 create mode 100644 src/app/features/preservation/dip/stores/dip.action.ts
 create mode 100644 src/app/features/preservation/dip/stores/dip.state.ts
 create mode 100644 src/app/features/preservation/dip/stores/status-history/dip-status-history.action.ts
 create mode 100644 src/app/features/preservation/dip/stores/status-history/dip-status-history.state.ts

diff --git a/src/app/features/deposit/components/presentationals/deposit-form/deposit-form.presentational.html b/src/app/features/deposit/components/presentationals/deposit-form/deposit-form.presentational.html
index 2dda8114f..ef70fcfb5 100644
--- a/src/app/features/deposit/components/presentationals/deposit-form/deposit-form.presentational.html
+++ b/src/app/features/deposit/components/presentationals/deposit-form/deposit-form.presentational.html
@@ -296,7 +296,7 @@
             type="submit"
             [disabled]="!form.valid || !form.dirty"
     >
-      {{'deposit.submit' | translate }}
+      {{'deposit.submit' | translate}}
     </button>
   </div>
 </form>
diff --git a/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.html b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.html
new file mode 100644
index 000000000..f1c4a431b
--- /dev/null
+++ b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.html
@@ -0,0 +1,99 @@
+<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>
diff --git a/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.scss b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.scss
new file mode 100644
index 000000000..2315c003d
--- /dev/null
+++ b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.scss
@@ -0,0 +1,3 @@
+@import "../sass/abstracts/mixins";
+@import "../sass/abstracts/variables";
+@import "../../src/app/shared/components/presentationals/shared-abstract-form/shared-abstract-form.presentational.scss";
diff --git a/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.ts b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.ts
new file mode 100644
index 000000000..afb394497
--- /dev/null
+++ b/src/app/features/preservation/dip/components/presentationals/dip-form/dip-form.presentational.ts
@@ -0,0 +1,132 @@
+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;
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.html b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.html
new file mode 100644
index 000000000..db50badde
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.html
@@ -0,0 +1,40 @@
+<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>
diff --git a/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.scss b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.scss
new file mode 100644
index 000000000..6157c9dad
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.scss
@@ -0,0 +1,27 @@
+@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;
+    }
+  }
+}
+
diff --git a/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.ts b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.ts
new file mode 100644
index 000000000..94b9336fa
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-detail-edit/dip-detail-edit.routable.ts
@@ -0,0 +1,174 @@
+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));
+  }
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.html b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.html
new file mode 100644
index 000000000..d60f63010
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.html
@@ -0,0 +1,43 @@
+<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>
diff --git a/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.scss b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.scss
new file mode 100644
index 000000000..06cbc8968
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.scss
@@ -0,0 +1,51 @@
+@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);
+            }
+          }
+        }
+      }
+    }
+  }
+
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.ts b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.ts
new file mode 100644
index 000000000..c55df2267
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-file/dip-file.routable.ts
@@ -0,0 +1,276 @@
+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));
+
+  }
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-list/dip-list.routable.ts b/src/app/features/preservation/dip/components/routables/dip-list/dip-list.routable.ts
new file mode 100644
index 000000000..061131baf
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-list/dip-list.routable.ts
@@ -0,0 +1,137 @@
+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));
+  }
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.html b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.html
new file mode 100644
index 000000000..086a86f89
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.html
@@ -0,0 +1,12 @@
+<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>
diff --git a/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.scss b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.scss
new file mode 100644
index 000000000..d288fce4d
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.scss
@@ -0,0 +1,8 @@
+@import "../sass/abstracts/variables";
+@import "../sass/abstracts/mixins";
+
+:host {
+  .wrapper {
+    min-height: 300px;
+  }
+}
diff --git a/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.ts b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.ts
new file mode 100644
index 000000000..e466d13bd
--- /dev/null
+++ b/src/app/features/preservation/dip/components/routables/dip-metadata/dip-metadata.routable.ts
@@ -0,0 +1,61 @@
+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 {
+  }
+}
diff --git a/src/app/features/preservation/dip/dip-routing.module.ts b/src/app/features/preservation/dip/dip-routing.module.ts
new file mode 100644
index 000000000..3221da4fd
--- /dev/null
+++ b/src/app/features/preservation/dip/dip-routing.module.ts
@@ -0,0 +1,77 @@
+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 {
+}
diff --git a/src/app/features/preservation/dip/dip.module.ts b/src/app/features/preservation/dip/dip.module.ts
new file mode 100644
index 000000000..5459c00e0
--- /dev/null
+++ b/src/app/features/preservation/dip/dip.module.ts
@@ -0,0 +1,55 @@
+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 {
+}
diff --git a/src/app/features/preservation/dip/enums/dip-tab.enum.ts b/src/app/features/preservation/dip/enums/dip-tab.enum.ts
new file mode 100644
index 000000000..928996421
--- /dev/null
+++ b/src/app/features/preservation/dip/enums/dip-tab.enum.ts
@@ -0,0 +1,4 @@
+export enum DipTabEnum {
+  metadata = 0,
+  file = 1,
+}
diff --git a/src/app/features/preservation/dip/helpers/dip.helper.ts b/src/app/features/preservation/dip/helpers/dip.helper.ts
new file mode 100644
index 000000000..9442b3c38
--- /dev/null
+++ b/src/app/features/preservation/dip/helpers/dip.helper.ts
@@ -0,0 +1,34 @@
+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;
+  }
+}
diff --git a/src/app/features/preservation/dip/models/dip-data-file.model.ts b/src/app/features/preservation/dip/models/dip-data-file.model.ts
new file mode 100644
index 000000000..85250dbc3
--- /dev/null
+++ b/src/app/features/preservation/dip/models/dip-data-file.model.ts
@@ -0,0 +1,4 @@
+import {DataFile} from "@shared/models/business/data-file.model";
+
+export interface DipDataFile extends DataFile {
+}
diff --git a/src/app/features/preservation/dip/models/dip-extended.model.ts b/src/app/features/preservation/dip/models/dip-extended.model.ts
new file mode 100644
index 000000000..baa0c2eaa
--- /dev/null
+++ b/src/app/features/preservation/dip/models/dip-extended.model.ts
@@ -0,0 +1,4 @@
+import {Dip} from "@app/generated-api";
+
+export interface DipExtended extends Dip {
+}
diff --git a/src/app/features/preservation/dip/stores/data-file/dip-data-file.action.ts b/src/app/features/preservation/dip/stores/data-file/dip-data-file.action.ts
new file mode 100644
index 000000000..bd41229f4
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/data-file/dip-data-file.action.ts
@@ -0,0 +1,104 @@
+import {DipDataFile} from "@preservation/dip/models/dip-data-file.model";
+import {LocalStateEnum} from "@shared/enums/local-state.enum";
+import {
+  BaseAction,
+  CompositionAction,
+  CompositionNameSpace,
+  QueryParameters,
+  TypeDefaultAction,
+} from "solidify-frontend";
+
+const state = LocalStateEnum.preservation_dip_dataFile;
+
+export namespace PreservationDipDataFileAction {
+  @TypeDefaultAction(state)
+  export class GetAll extends CompositionAction.GetAll {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetAllSuccess extends CompositionAction.GetAllSuccess<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetAllFail extends CompositionAction.GetAllFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetById extends CompositionAction.GetById {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByIdSuccess extends CompositionAction.GetByIdSuccess<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByIdFail extends CompositionAction.GetByIdFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class Update extends CompositionAction.Update<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class UpdateSuccess extends CompositionAction.UpdateSuccess<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class UpdateFail extends CompositionAction.UpdateFail<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class Create extends CompositionAction.Create<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class CreateSuccess extends CompositionAction.CreateSuccess<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class CreateFail extends CompositionAction.CreateFail<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class Delete extends CompositionAction.Delete<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class DeleteSuccess extends CompositionAction.DeleteSuccess<DipDataFile> {
+  }
+
+  @TypeDefaultAction(state)
+  export class DeleteFail extends CompositionAction.DeleteFail<DipDataFile> {
+  }
+
+  export class ChangeQueryParameters extends BaseAction {
+    static readonly type: string = `[${state}] Change Query Parameters`;
+
+    constructor(public parentId: string, public queryParameters: QueryParameters, public keepCurrentContext: boolean = false) {
+      super();
+    }
+  }
+
+  export class Refresh {
+    static readonly type: string = `[${state}] Refresh`;
+
+    constructor(public parentId: string) {
+    }
+  }
+
+  export class Download {
+    static readonly type: string = `[${state}] Download`;
+
+    constructor(public parentId: string, public dataFile: DipDataFile) {
+    }
+  }
+
+  export class Resume {
+    static readonly type: string = `[${state}] Resume`;
+
+    constructor(public parentId: string, public dataFile: DipDataFile) {
+    }
+  }
+}
+
+export const preservationDipDataFileActionNameSpace: CompositionNameSpace = PreservationDipDataFileAction;
diff --git a/src/app/features/preservation/dip/stores/data-file/dip-data-file.state.ts b/src/app/features/preservation/dip/stores/data-file/dip-data-file.state.ts
new file mode 100644
index 000000000..3b44107b1
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/data-file/dip-data-file.state.ts
@@ -0,0 +1,116 @@
+import {Inject} from "@angular/core";
+import {WINDOW} from "@app/app.module";
+import {
+  PreservationDipDataFileAction,
+  preservationDipDataFileActionNameSpace,
+} from "@app/features/preservation/dip/stores/data-file/dip-data-file.action";
+import {ApiActionEnum} from "@app/shared/enums/api-action.enum";
+import {ApiResourceNameEnum} from "@app/shared/enums/api-resource-name.enum";
+import {AccessResourceApiEnum} from "@app/shared/enums/api.enum";
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+import {
+  Action,
+  Actions,
+  Selector,
+  State,
+  StateContext,
+  Store,
+} from "@ngxs/store";
+import {DipDataFile} from "@preservation/dip/models/dip-data-file.model";
+import {
+  DipDataFileStatusHistoryState,
+  DipDataFileStatusHistoryStateModel,
+} from "@preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state";
+import {DownloadService} from "@shared/services/download.service";
+import {defaultStatusHistoryInitValue} from "@shared/stores/status-history/status-history.state";
+import {Observable} from "rxjs";
+import {tap} from "rxjs/internal/operators/tap";
+import {
+  ApiService,
+  CompositionState,
+  CompositionStateModel,
+  defaultCompositionStateInitValue,
+  NotificationService,
+  TRANSLATE,
+} from "solidify-frontend";
+
+export const defaultDipDataFileValue: () => DipDataFileStateModel = () =>
+  ({
+    ...defaultCompositionStateInitValue(),
+    preservation_dip_dataFile_statusHistory: defaultStatusHistoryInitValue(),
+    listFolders: [],
+    numberFilesInErrors: undefined,
+    numberFiles: undefined,
+  });
+
+export interface DipDataFileStateModel extends CompositionStateModel<DipDataFile> {
+  preservation_dip_dataFile_statusHistory: DipDataFileStatusHistoryStateModel;
+  listFolders: string[];
+  numberFilesInErrors: number | undefined;
+  numberFiles: number | undefined;
+}
+
+@State<DipDataFileStateModel>({
+  name: LocalStateEnum.preservation_dip_dataFile,
+  defaults: {
+    ...defaultDipDataFileValue(),
+  },
+  children: [
+    DipDataFileStatusHistoryState,
+  ],
+})
+export class DipDataFileState extends CompositionState<DipDataFileStateModel, DipDataFile> {
+  constructor(protected apiService: ApiService,
+              protected store: Store,
+              protected notificationService: NotificationService,
+              protected actions$: Actions,
+              @Inject(WINDOW) private _window: Window,
+              private downloadService: DownloadService) {
+    super(apiService, store, notificationService, actions$, {
+      nameSpace: preservationDipDataFileActionNameSpace,
+      resourceName: ApiResourceNameEnum.DATAFILE,
+    });
+  }
+
+  protected get _urlResource(): string {
+    return AccessResourceApiEnum.dip;
+  }
+
+  @Selector()
+  static listFolders(state: DipDataFileStateModel): string[] {
+    return state.listFolders;
+  }
+
+  @Action(PreservationDipDataFileAction.Refresh)
+  refresh(ctx: StateContext<DipDataFileStateModel>, action: PreservationDipDataFileAction.Refresh): void {
+    ctx.dispatch(new PreservationDipDataFileAction.GetAll(action.parentId, undefined, true));
+  }
+
+  @Action(PreservationDipDataFileAction.Download)
+  download(ctx: StateContext<DipDataFileStateModel>, action: PreservationDipDataFileAction.Download): void {
+    const url = `${this._urlResource}/${action.parentId}/${this._resourceName}/${action.dataFile.resId}/${ApiActionEnum.DL}`;
+    this.notificationService.showInformation(TRANSLATE("notification.deposit.file.download"), true);
+    this.downloadService.download(url, action.dataFile.fileName, action.dataFile.fileSize).subscribe(() => {
+      this.notificationService.showSuccess(TRANSLATE("notification.deposit.file.downloadWithSuccess"), true);
+    });
+  }
+
+  @Action(PreservationDipDataFileAction.ChangeQueryParameters)
+  changeQueryParameters(ctx: StateContext<DipDataFileStateModel>, action: PreservationDipDataFileAction.ChangeQueryParameters): void {
+    ctx.patchState({
+      queryParameters: action.queryParameters,
+    });
+    ctx.dispatch(new PreservationDipDataFileAction.GetAll(action.parentId, undefined, action.keepCurrentContext));
+  }
+
+  @Action(PreservationDipDataFileAction.Resume)
+  resume(ctx: StateContext<DipDataFileStateModel>, action: PreservationDipDataFileAction.Resume): Observable<void> {
+    return this.apiService.post<void>(`${this._urlResource}/${action.parentId}/${this._resourceName}/${action.dataFile.resId}/${ApiActionEnum.RESUME}`)
+      .pipe(
+        tap(() => {
+          this.notificationService.showInformation(TRANSLATE("notification.deposit.file.resumed"), true);
+          ctx.dispatch(new PreservationDipDataFileAction.GetAll(action.parentId, undefined, true));
+        }),
+      );
+  }
+}
diff --git a/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action.ts b/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action.ts
new file mode 100644
index 000000000..d3a3bd276
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action.ts
@@ -0,0 +1,27 @@
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+import {StatusHistoryNamespace} from "@shared/stores/status-history/status-history-namespace.model";
+import {StatusHistoryAction} from "@shared/stores/status-history/status-history.action";
+import {TypeDefaultAction} from "solidify-frontend";
+
+const state = LocalStateEnum.preservation_dip_dataFile_statusHistory;
+
+export namespace PreservationDipDataFileStatusHistoryAction {
+
+  @TypeDefaultAction(state)
+  export class History extends StatusHistoryAction.History {
+  }
+
+  @TypeDefaultAction(state)
+  export class HistorySuccess extends StatusHistoryAction.HistorySuccess {
+  }
+
+  @TypeDefaultAction(state)
+  export class HistoryFail extends StatusHistoryAction.HistoryFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class ChangeQueryParameters extends StatusHistoryAction.ChangeQueryParameters {
+  }
+}
+
+export const preservationDipDataFileStatusHistoryNamespace: StatusHistoryNamespace = PreservationDipDataFileStatusHistoryAction;
diff --git a/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state.ts b/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state.ts
new file mode 100644
index 000000000..0d7471020
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state.ts
@@ -0,0 +1,44 @@
+import {preservationDipDataFileStatusHistoryNamespace} from "@app/features/preservation/dip/stores/data-file/status-history/dip-data-file-status-history.action";
+import {AccessResourceApiEnum} from "@app/shared/enums/api.enum";
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+
+import {
+  Actions,
+  State,
+  Store,
+} from "@ngxs/store";
+import {DipDataFile} from "@preservation/dip/models/dip-data-file.model";
+import {
+  defaultStatusHistoryInitValue,
+  StatusHistoryState,
+  StatusHistoryStateModel,
+} from "@shared/stores/status-history/status-history.state";
+import {
+  ApiService,
+  NotificationService,
+} from "solidify-frontend";
+
+export interface DipDataFileStatusHistoryStateModel extends StatusHistoryStateModel<DipDataFile> {
+}
+
+@State<DipDataFileStatusHistoryStateModel>({
+  name: LocalStateEnum.preservation_dip_dataFile_statusHistory,
+  defaults: {
+    ...defaultStatusHistoryInitValue(),
+  },
+})
+export class DipDataFileStatusHistoryState extends StatusHistoryState<DipDataFileStatusHistoryStateModel, DipDataFile> {
+
+  constructor(protected apiService: ApiService,
+              protected store: Store,
+              protected notificationService: NotificationService,
+              protected actions$: Actions) {
+    super(apiService, store, notificationService, actions$, {
+      nameSpace: preservationDipDataFileStatusHistoryNamespace,
+    });
+  }
+
+  protected get _urlResource(): string {
+    return AccessResourceApiEnum.dipDataFile;
+  }
+}
diff --git a/src/app/features/preservation/dip/stores/dip.action.ts b/src/app/features/preservation/dip/stores/dip.action.ts
new file mode 100644
index 000000000..208686e16
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/dip.action.ts
@@ -0,0 +1,130 @@
+import {Dip} from "@app/generated-api";
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+import {
+  BaseAction,
+  BaseSubAction,
+  ResourceAction,
+  ResourceNameSpace,
+  TypeDefaultAction,
+} from "solidify-frontend";
+
+const state = LocalStateEnum.preservation_dip;
+
+export namespace PreservationDipAction {
+  @TypeDefaultAction(state)
+  export class LoadResource extends ResourceAction.LoadResource {
+  }
+
+  @TypeDefaultAction(state)
+  export class LoadResourceSuccess extends ResourceAction.LoadResourceSuccess {
+  }
+
+  @TypeDefaultAction(state)
+  export class LoadResourceFail extends ResourceAction.LoadResourceFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class ChangeQueryParameters extends ResourceAction.ChangeQueryParameters {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetAll extends ResourceAction.GetAll {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetAllSuccess extends ResourceAction.GetAllSuccess<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetAllFail extends ResourceAction.GetAllFail<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByListId extends ResourceAction.GetByListId {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByListIdSuccess extends ResourceAction.GetByListIdSuccess {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByListIdFail extends ResourceAction.GetByListIdFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetById extends ResourceAction.GetById {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByIdSuccess extends ResourceAction.GetByIdSuccess<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class GetByIdFail extends ResourceAction.GetByIdFail<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class Create extends ResourceAction.Create<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class CreateSuccess extends ResourceAction.CreateSuccess<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class CreateFail extends ResourceAction.CreateFail<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class Update extends ResourceAction.Update<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class UpdateSuccess extends ResourceAction.UpdateSuccess<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class UpdateFail extends ResourceAction.UpdateFail<Dip> {
+  }
+
+  @TypeDefaultAction(state)
+  export class Delete extends ResourceAction.Delete {
+  }
+
+  @TypeDefaultAction(state)
+  export class DeleteSuccess extends ResourceAction.DeleteSuccess {
+  }
+
+  @TypeDefaultAction(state)
+  export class DeleteFail extends ResourceAction.DeleteFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class Clean extends ResourceAction.Clean {
+  }
+
+  export class Download {
+    static readonly type: string = `[${state}] Download`;
+
+    constructor(public id: string) {
+    }
+  }
+
+  export class Resume extends BaseAction {
+    static readonly type: string = `[${state}] Resume`;
+
+    constructor(public id: string) {
+      super();
+    }
+  }
+
+  export class ResumeSuccess extends BaseSubAction<Resume> {
+    static readonly type: string = `[${state}] Resume Success`;
+  }
+
+  export class ResumeFail extends BaseSubAction<Resume> {
+    static readonly type: string = `[${state}] Resume Fail`;
+  }
+}
+
+export const preservationDipActionNameSpace: ResourceNameSpace = PreservationDipAction;
diff --git a/src/app/features/preservation/dip/stores/dip.state.ts b/src/app/features/preservation/dip/stores/dip.state.ts
new file mode 100644
index 000000000..dee209939
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/dip.state.ts
@@ -0,0 +1,167 @@
+import {HttpClient} from "@angular/common/http";
+import {
+  defaultDipDataFileValue,
+  DipDataFileState,
+  DipDataFileStateModel,
+} from "@app/features/preservation/dip/stores/data-file/dip-data-file.state";
+import {
+  PreservationDipAction,
+  preservationDipActionNameSpace,
+} from "@app/features/preservation/dip/stores/dip.action";
+import {
+  DipStatusHistoryState,
+  DipStatusHistoryStateModel,
+} from "@app/features/preservation/dip/stores/status-history/dip-status-history.state";
+import {Dip} from "@app/generated-api";
+import {AccessResourceApiEnum} from "@app/shared/enums/api.enum";
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+import {Navigate} from "@ngxs/router-plugin";
+import {
+  Action,
+  Actions,
+  Selector,
+  State,
+  StateContext,
+  Store,
+} from "@ngxs/store";
+import {ApiActionEnum} from "@shared/enums/api-action.enum";
+import {
+  DepositRoutesEnum,
+  RoutesEnum,
+} from "@shared/enums/routes.enum";
+import {DownloadService} from "@shared/services/download.service";
+import {defaultStatusHistoryInitValue} from "@shared/stores/status-history/status-history.state";
+import {Observable} from "rxjs";
+import {
+  catchError,
+  tap,
+} from "rxjs/operators";
+import {
+  ApiService,
+  defaultResourceStateInitValue,
+  isNullOrUndefined,
+  NotificationService,
+  OverrideDefaultAction,
+  ResourceState,
+  ResourceStateModel,
+  StoreUtil,
+  TRANSLATE,
+} from "solidify-frontend";
+
+export interface DipStateModel extends ResourceStateModel<Dip> {
+  preservation_dip_dataFile: DipDataFileStateModel;
+  isLoadingDataFile: boolean;
+  preservation_dip_statusHistory: DipStatusHistoryStateModel;
+}
+
+@State<DipStateModel>({
+  name: LocalStateEnum.preservation_dip,
+  defaults: {
+    ...defaultResourceStateInitValue(),
+    preservation_dip_dataFile: defaultDipDataFileValue(),
+    isLoadingDataFile: false,
+    preservation_dip_statusHistory: {...defaultStatusHistoryInitValue()},
+  },
+  children: [
+    DipDataFileState,
+    DipStatusHistoryState,
+  ],
+})
+export class DipState extends ResourceState<DipStateModel, Dip> {
+  constructor(protected apiService: ApiService,
+              protected store: Store,
+              protected notificationService: NotificationService,
+              protected actions$: Actions,
+              protected httpClient: HttpClient,
+              private downloadService: DownloadService) {
+    super(apiService, store, notificationService, actions$, {
+      nameSpace: preservationDipActionNameSpace,
+      notificationResourceUpdateFailTextToTranslate: TRANSLATE("dip.notification.resource.update.fail"),
+    });
+  }
+
+  protected get _urlResource(): string {
+    return AccessResourceApiEnum.dip;
+  }
+
+  @Selector()
+  static isLoading(state: DipStateModel): boolean {
+    return StoreUtil.isLoadingState(state);
+  }
+
+  @Selector()
+  static currentTitle(state: DipStateModel): string | undefined {
+    if (isNullOrUndefined(state.current)) {
+      return undefined;
+    }
+    return state.current.info.name;
+  }
+
+  @Selector()
+  static isLoadingWithDependency(state: DipStateModel): boolean {
+    return this.isLoading(state);
+  }
+
+  @Selector()
+  static isReadyToBeDisplayed(state: DipStateModel): boolean {
+    return this.isReadyToBeDisplayedInCreateMode
+      && !isNullOrUndefined(state.current);
+  }
+
+  @Selector()
+  static isReadyToBeDisplayedInCreateMode(state: DipStateModel): boolean {
+    return true;
+  }
+
+  @OverrideDefaultAction()
+  @Action(PreservationDipAction.UpdateSuccess)
+  updateSuccess(ctx: StateContext<DipStateModel>, action: PreservationDipAction.UpdateSuccess): void {
+    super.updateSuccess(ctx, action);
+
+    ctx.dispatch([
+      new Navigate([RoutesEnum.preservationDipDetail, action.model.resId, DepositRoutesEnum.files]),
+    ]);
+  }
+
+  @Action(PreservationDipAction.Download)
+  download(ctx: StateContext<DipStateModel>, action: PreservationDipAction.Download): void {
+    const fileName = "dip_" + action.id + ".zip";
+    this.notificationService.showInformation(TRANSLATE("notification.deposit.file.download"), true);
+    this.downloadService.download(`${this._urlResource}/${action.id}/${ApiActionEnum.DL}`, fileName).subscribe(() => {
+      this.notificationService.showInformation(TRANSLATE("notification.deposit.file.downloadWithSuccess"), true);
+    });
+  }
+
+  @Action(PreservationDipAction.Resume)
+  resume(ctx: StateContext<DipStateModel>, action: PreservationDipAction.Resume): Observable<string> {
+    ctx.patchState({
+      isLoadingCounter: ctx.getState().isLoadingCounter + 1,
+    });
+    return this.httpClient.post<string>(`${this._urlResource}/${action.id}/${ApiActionEnum.RESUME}`, null)
+      .pipe(
+        tap(result => {
+          ctx.dispatch(new PreservationDipAction.ResumeSuccess(action));
+        }),
+        catchError(error => {
+          ctx.dispatch(new PreservationDipAction.ResumeFail(action));
+          throw error;
+        }),
+      );
+  }
+
+  @Action(PreservationDipAction.ResumeSuccess)
+  resumeSuccess(ctx: StateContext<DipStateModel>, action: PreservationDipAction.ResumeSuccess): void {
+    ctx.patchState({
+      isLoadingCounter: ctx.getState().isLoadingCounter - 1,
+    });
+    this.notificationService.showInformation(TRANSLATE("notification.dip.action.resume.success"), true);
+  }
+
+  @Action(PreservationDipAction.ResumeFail)
+  resumeFail(ctx: StateContext<DipStateModel>, action: PreservationDipAction.ResumeFail): void {
+    ctx.patchState({
+      isLoadingCounter: ctx.getState().isLoadingCounter - 1,
+    });
+    this.notificationService.showError(TRANSLATE("notification.dip.action.resume.fail"), true);
+  }
+}
diff --git a/src/app/features/preservation/dip/stores/status-history/dip-status-history.action.ts b/src/app/features/preservation/dip/stores/status-history/dip-status-history.action.ts
new file mode 100644
index 000000000..49ed8e7ed
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/status-history/dip-status-history.action.ts
@@ -0,0 +1,27 @@
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+import {StatusHistoryNamespace} from "@shared/stores/status-history/status-history-namespace.model";
+import {StatusHistoryAction} from "@shared/stores/status-history/status-history.action";
+import {TypeDefaultAction} from "solidify-frontend";
+
+const state = LocalStateEnum.preservation_dip_statusHistory;
+
+export namespace PreservationDipStatusHistoryAction {
+
+  @TypeDefaultAction(state)
+  export class History extends StatusHistoryAction.History {
+  }
+
+  @TypeDefaultAction(state)
+  export class HistorySuccess extends StatusHistoryAction.HistorySuccess {
+  }
+
+  @TypeDefaultAction(state)
+  export class HistoryFail extends StatusHistoryAction.HistoryFail {
+  }
+
+  @TypeDefaultAction(state)
+  export class ChangeQueryParameters extends StatusHistoryAction.ChangeQueryParameters {
+  }
+}
+
+export const preservationDipStatusHistoryNamespace: StatusHistoryNamespace = PreservationDipStatusHistoryAction;
diff --git a/src/app/features/preservation/dip/stores/status-history/dip-status-history.state.ts b/src/app/features/preservation/dip/stores/status-history/dip-status-history.state.ts
new file mode 100644
index 000000000..154ac38ca
--- /dev/null
+++ b/src/app/features/preservation/dip/stores/status-history/dip-status-history.state.ts
@@ -0,0 +1,44 @@
+import {preservationDipStatusHistoryNamespace} from "@app/features/preservation/dip/stores/status-history/dip-status-history.action";
+import {Dip} from "@app/generated-api";
+import {AccessResourceApiEnum} from "@app/shared/enums/api.enum";
+import {LocalStateEnum} from "@app/shared/enums/local-state.enum";
+
+import {
+  Actions,
+  State,
+  Store,
+} from "@ngxs/store";
+import {
+  defaultStatusHistoryInitValue,
+  StatusHistoryState,
+  StatusHistoryStateModel,
+} from "@shared/stores/status-history/status-history.state";
+import {
+  ApiService,
+  NotificationService,
+} from "solidify-frontend";
+
+export interface DipStatusHistoryStateModel extends StatusHistoryStateModel<Dip> {
+}
+
+@State<DipStatusHistoryStateModel>({
+  name: LocalStateEnum.preservation_dip_statusHistory,
+  defaults: {
+    ...defaultStatusHistoryInitValue(),
+  },
+})
+export class DipStatusHistoryState extends StatusHistoryState<DipStatusHistoryStateModel, Dip> {
+
+  constructor(protected apiService: ApiService,
+              protected store: Store,
+              protected notificationService: NotificationService,
+              protected actions$: Actions) {
+    super(apiService, store, notificationService, actions$, {
+      nameSpace: preservationDipStatusHistoryNamespace,
+    });
+  }
+
+  protected get _urlResource(): string {
+    return AccessResourceApiEnum.dip;
+  }
+}
diff --git a/src/app/features/preservation/preservation-routing.module.ts b/src/app/features/preservation/preservation-routing.module.ts
index a86b9ee60..7015a56c4 100644
--- a/src/app/features/preservation/preservation-routing.module.ts
+++ b/src/app/features/preservation/preservation-routing.module.ts
@@ -80,6 +80,15 @@ const routes: Routes = [
     },
     canActivate: [ApplicationRoleGuardService],
   },
+  {
+    path: PreservationPlanningRoutesEnum.dip,
+    // @ts-ignore Dynamic import
+    loadChildren: () => import("./dip/dip.module").then(m => m.DipModule),
+    data: {
+      breadcrumb: TRANSLATE("breadcrumb.preservation.dip.root"),
+    },
+    canActivate: [ApplicationRoleGuardService],
+  },
 ];
 
 @NgModule({
diff --git a/src/app/features/preservation/preservation.module.ts b/src/app/features/preservation/preservation.module.ts
index 0be704b2a..09ec7c831 100644
--- a/src/app/features/preservation/preservation.module.ts
+++ b/src/app/features/preservation/preservation.module.ts
@@ -14,6 +14,10 @@ import {NgxsModule} from "@ngxs/store";
 import {PreservationAipAipState} from "@preservation/aip/stores/aip-aip/aip-aip.state";
 import {PreservationAipAipStatusHistoryState} from "@preservation/aip/stores/aip-aip/status-history/aip-aip-status-history.state";
 import {PreservationAipStatusHistoryState} from "@preservation/aip/stores/status-history/aip-status-history.state";
+import {DipDataFileState} from "@preservation/dip/stores/data-file/dip-data-file.state";
+import {DipDataFileStatusHistoryState} from "@preservation/dip/stores/data-file/status-history/dip-data-file-status-history.state";
+import {DipState} from "@preservation/dip/stores/dip.state";
+import {DipStatusHistoryState} from "@preservation/dip/stores/status-history/dip-status-history.state";
 import {SipDataFileState} from "@preservation/sip/stores/data-file/sip-data-file.state";
 import {SipDataFileStatusHistoryState} from "@preservation/sip/stores/data-file/status-history/sip-data-file-status-history.state";
 import {SipState} from "@preservation/sip/stores/sip.state";
@@ -47,11 +51,15 @@ const presentationals = [];
       SipDataFileState,
       SipStatusHistoryState,
       SipDataFileStatusHistoryState,
+      DipState,
+      DipDataFileState,
+      DipStatusHistoryState,
+      DipDataFileStatusHistoryState,
       PreservationAipState,
       PreservationAipOrganizationalUnitState,
       PreservationAipAipState,
       PreservationAipStatusHistoryState,
-      PreservationAipAipStatusHistoryState
+      PreservationAipAipStatusHistoryState,
     ]),
   ],
   entryComponents: [
diff --git a/src/app/features/preservation/stores/preservation.state.ts b/src/app/features/preservation/stores/preservation.state.ts
index 361f1a69f..c1fba9111 100644
--- a/src/app/features/preservation/stores/preservation.state.ts
+++ b/src/app/features/preservation/stores/preservation.state.ts
@@ -16,6 +16,10 @@ import {
   State,
   Store,
 } from "@ngxs/store";
+import {
+  DipState,
+  DipStateModel,
+} from "@preservation/dip/stores/dip.state";
 import {
   SipState,
   SipStateModel,
@@ -27,6 +31,7 @@ export interface PreservationStateModel extends BaseStateModel {
   preservation_job: PreservationJobStateModel | undefined;
   preservation_aipStatus: PreservationAipStatusStateModel | undefined;
   preservation_sip: SipStateModel | undefined;
+  preservation_dip: DipStateModel | undefined;
 }
 
 @State<PreservationStateModel>({
@@ -37,13 +42,15 @@ export interface PreservationStateModel extends BaseStateModel {
     preservation_job: undefined,
     preservation_aipStatus: undefined,
     preservation_sip: undefined,
+    preservation_dip: undefined,
   },
   children: [
     PreservationMonitoringState,
     PreservationJobState,
     PreservationAipStatusState,
     SipState,
-    PreservationAipState
+    DipState,
+    PreservationAipState,
   ],
 })
 export class PreservationState {
diff --git a/src/app/shared/enums/api.enum.ts b/src/app/shared/enums/api.enum.ts
index 92dba977d..c0b311d59 100644
--- a/src/app/shared/enums/api.enum.ts
+++ b/src/app/shared/enums/api.enum.ts
@@ -73,6 +73,10 @@ export class AccessResourceApiEnum implements ResourceApiEnum {
     return BaseResourceApiEnum.access + SEPARATOR + ApiResourceNameEnum.DIP;
   }
 
+  static get dipDataFile(): string {
+    return BaseResourceApiEnum.ingest + SEPARATOR + ApiResourceNameEnum.DIP + parentIdInUrl + ApiResourceNameEnum.DATAFILE;
+  }
+
   static get allMetadata(): string {
     return BaseResourceApiEnum.access + SEPARATOR + ApiResourceNameEnum.ALL_METADATA;
   }
@@ -226,7 +230,7 @@ export class ArchivalStorageResourceApiEnum implements ResourceApiEnum {
     archivalStorageList.forEach(url => {
       newList.push({
         index: url.index,
-        url: url.url + SEPARATOR + ApiResourceNameEnum.AIP + parentIdInUrl + ApiResourceNameEnum.DATAFILE
+        url: url.url + SEPARATOR + ApiResourceNameEnum.AIP + parentIdInUrl + ApiResourceNameEnum.DATAFILE,
       });
     });
     return newList;
diff --git a/src/app/shared/enums/local-state.enum.ts b/src/app/shared/enums/local-state.enum.ts
index 6633bd7ca..2053bf25b 100644
--- a/src/app/shared/enums/local-state.enum.ts
+++ b/src/app/shared/enums/local-state.enum.ts
@@ -80,4 +80,9 @@ export enum LocalStateEnum {
   preservation_sip_statusHistory = "preservation_sip_statusHistory",
   preservation_sip_dataFile = "preservation_sip_dataFile",
   preservation_sip_dataFile_statusHistory = "preservation_sip_dataFile_statusHistory",
+
+  preservation_dip = "preservation_dip",
+  preservation_dip_statusHistory = "preservation_dip_statusHistory",
+  preservation_dip_dataFile = "preservation_dip_dataFile",
+  preservation_dip_dataFile_statusHistory = "preservation_dip_dataFile_statusHistory",
 }
diff --git a/src/app/shared/enums/routes.enum.ts b/src/app/shared/enums/routes.enum.ts
index cffc9efac..cae162e27 100644
--- a/src/app/shared/enums/routes.enum.ts
+++ b/src/app/shared/enums/routes.enum.ts
@@ -131,9 +131,10 @@ export enum PreservationPlanningRoutesEnum {
   storagionNumberWithoutPrefixParam = "storagion",
 
   dip = "dip",
-  dipCreate = "create",
   dipDetail = "detail",
   dipEdit = "edit",
+  dipMetadata = "metadata",
+  dipFiles = "files",
 
   sip = "sip",
   sipDetail = "detail",
@@ -215,9 +216,7 @@ export class RoutesEnum implements RoutesEnum {
   static preservationSipDetail: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.sip + urlSeparator + PreservationPlanningRoutesEnum.sipDetail;
 
   static preservationDip: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.dip;
-  static preservationDipCreate: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.dip + urlSeparator + PreservationPlanningRoutesEnum.dipCreate;
   static preservationDipDetail: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.dip + urlSeparator + PreservationPlanningRoutesEnum.dipDetail;
-  static preservationDipEdit: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.dip + urlSeparator + PreservationPlanningRoutesEnum.dipEdit;
 
   static preservationPreservationPlanning: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.preservationPlanning;
   static preservationPreservationPlanningCreate: string = AppRoutesEnum.preservation + urlSeparator + PreservationPlanningRoutesEnum.preservationPlanning + urlSeparator + PreservationPlanningRoutesEnum.preservationPlanningCreate;
diff --git a/src/app/shared/utils/store-route-local.util.ts b/src/app/shared/utils/store-route-local.util.ts
index 08b7be1bc..31f4937db 100644
--- a/src/app/shared/utils/store-route-local.util.ts
+++ b/src/app/shared/utils/store-route-local.util.ts
@@ -60,6 +60,9 @@ export class StoreRouteLocalUtil {
     if (state === LocalStateEnum.preservation_sip) {
       return RoutesEnum.preservationSipDetail;
     }
+    if (state === LocalStateEnum.preservation_dip) {
+      return RoutesEnum.preservationDipDetail;
+    }
     throw Error(StringUtil.format(StoreRouteLocalUtil.messageNotFound, "Detail", state));
   }
 
@@ -158,6 +161,9 @@ export class StoreRouteLocalUtil {
     if (state === LocalStateEnum.preservation_sip) {
       return RoutesEnum.preservationSip;
     }
+    if (state === LocalStateEnum.preservation_dip) {
+      return RoutesEnum.preservationDip;
+    }
     throw Error(StringUtil.format(StoreRouteLocalUtil.messageNotFound, "Root", state));
   }
 
diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json
index b6f9b03ae..97e9e0825 100644
--- a/src/assets/i18n/de.json
+++ b/src/assets/i18n/de.json
@@ -62,8 +62,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the dissemination policy '{{name}}' ?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following dissemination policy: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -74,14 +74,14 @@
         "type": "Type"
       },
       "home": {
-        "subtitle": "Describe dissemination policy",
+        "subtitle": "Describes dissemination policies",
         "title": "Dissemination policy"
       },
       "notification": {
         "resource": {
-          "create": "Dissemination policy successfully created",
-          "delete": "Dissemination policy successfully deleted",
-          "update": "Dissemination policy successfully updated"
+          "create": "Dissemination policy created",
+          "delete": "Dissemination policy deleted",
+          "update": "Dissemination policy updated"
         }
       },
       "table": {
@@ -91,7 +91,7 @@
           },
           "destinationServer": "Destination server",
           "lastUpdate": {
-            "when": "Modified"
+            "when": "Updated"
           },
           "name": "Name",
           "subFolder": "Subfolder",
@@ -108,8 +108,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the funding agency '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following funding agency: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -121,14 +121,14 @@
         "url": "Url"
       },
       "home": {
-        "subtitle": "Describe funding agency",
+        "subtitle": "Describes funding agencies",
         "title": "Funding agency"
       },
       "notification": {
         "resource": {
-          "create": "Funding agency created with success",
-          "delete": "Funding agency deleted with success",
-          "update": "Role updated with success"
+          "create": "Funding agency created",
+          "delete": "Funding agency deleted",
+          "update": "Funding agency updated"
         }
       },
       "table": {
@@ -150,8 +150,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Confirm",
-          "message": "Are you sure you want to delete this institution?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following institution: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -161,14 +161,14 @@
         "url": "url"
       },
       "home": {
-        "subtitle": "Describe institution",
+        "subtitle": "Describes institutions",
         "title": "Institution"
       },
       "notification": {
         "resource": {
-          "create": "Institution created with success",
-          "delete": "Institution deleted with success",
-          "update": "Institution updated with success"
+          "create": "Institution created",
+          "delete": "Institution deleted",
+          "update": "Institution updated"
         }
       },
       "table": {
@@ -177,7 +177,7 @@
             "when": "Creation date"
           },
           "lastUpdate": {
-            "when": "Last update"
+            "when": "Updated"
           },
           "name": "name"
         }
@@ -192,8 +192,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Confirm",
-          "message": "Are you sure you want to delete this license?",
-          "title": "Confirm Deletion"
+          "message": "Are you sure you want to delete the following license: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -212,14 +212,14 @@
         "url": "URL"
       },
       "home": {
-        "subtitle": "Describe license for a deposit",
+        "subtitle": "Describes licenses for a deposit",
         "title": "License"
       },
       "notification": {
         "resource": {
-          "create": "License created with success",
-          "delete": "License deleted with success",
-          "update": "License updated with success"
+          "create": "License created",
+          "delete": "License deleted",
+          "update": "License updated"
         }
       },
       "table": {
@@ -245,8 +245,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete this OAI set?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following OAI set: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -258,15 +258,15 @@
         "submit": "Save"
       },
       "home": {
-        "subtitle": "Describe OAI sets",
+        "subtitle": "Describes OAI sets",
         "title": "OAI Sets"
       },
       "notification": {
-        "bulkCreateSuccess": "OAI sets created successfully",
+        "bulkCreateSuccess": "OAI sets created",
         "resource": {
-          "create": "OAI set created successfully",
-          "delete": "OAI set deleted successfully",
-          "update": "OAI set updated successfully"
+          "create": "OAI set created",
+          "delete": "OAI set deleted",
+          "update": "OAI set updated"
         }
       },
       "table": {
@@ -291,8 +291,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the Client '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following client: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -311,14 +311,14 @@
       },
       "notification": {
         "resource": {
-          "create": "OAuth2 Client created with success",
-          "delete": "OAuth2 Client deleted with success",
-          "update": "OAuth2 Client updated with success"
+          "create": "OAuth2 Client created",
+          "delete": "OAuth2 Client deleted",
+          "update": "OAuth2 Client updated"
         }
       },
       "table": {
         "header": {
-          "clientId": "ID Client",
+          "clientId": "Client ID",
           "name": "Name",
           "redirectUri": "URL Redirection"
         }
@@ -329,8 +329,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the organizational unit '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following organizational unit: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -351,15 +351,15 @@
         "url": "Url"
       },
       "home": {
-        "subtitle": "Describe organizational unit",
+        "subtitle": "Describes organizational units",
         "title": "OrganizationalUnit"
       },
       "new": "Create new organizational unit",
       "notification": {
         "resource": {
-          "create": "Organizational Unit created with success",
-          "delete": "Organizational Unit deleted with success",
-          "update": "Organizational Unit updated with success"
+          "create": "Organizational Unit created",
+          "delete": "Organizational Unit deleted",
+          "update": "Organizational Unit updated"
         }
       },
       "refresh": "Refresh",
@@ -382,14 +382,14 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete this person ?",
-          "title": "Delete confirmation"
+          "message": "Are you sure you want to delete the following person: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
-        "firstName": "FirstName",
+        "firstName": "First Name",
         "institution": "Institution",
-        "lastName": "LastName",
+        "lastName": "Last Name",
         "orcid": "ORCID",
         "submit": "Save"
       },
@@ -399,15 +399,15 @@
       },
       "notification": {
         "resource": {
-          "create": "Person created with success",
-          "delete": "Person deleted with success",
-          "update": "Person updated with success"
+          "create": "Person created",
+          "delete": "Person deleted",
+          "update": "Person updated"
         }
       },
       "table": {
         "header": {
-          "firstName": "FirstName",
-          "lastName": "LastName",
+          "firstName": "First Name",
+          "lastName": "Last Name",
           "orcid": "ORCID"
         }
       }
@@ -417,12 +417,12 @@
         "notification": {
           "deleteCache": {
             "fail": "Unable to clear cache",
-            "success": "Cache cleared with success"
+            "success": "Cache cleared"
           }
         },
         "table": {
           "header": {
-            "creationDate": "Creation date",
+            "creationDate": "Created",
             "name": "Name",
             "resId": "Id",
             "summary": "Status"
@@ -439,8 +439,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the preservation policy '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following preservation policy: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -450,14 +450,14 @@
         "submit": "Save"
       },
       "home": {
-        "subtitle": "Describe the preservation policy for a deposit",
+        "subtitle": "Describes the preservation policies for a deposit",
         "title": "Preservation Policy"
       },
       "notification": {
         "resource": {
-          "create": "Preservation Policy created with success",
-          "delete": "Preservation Policy deleted with success",
-          "update": "Preservation Policy updated with success"
+          "create": "Preservation Policy created",
+          "delete": "Preservation Policy deleted",
+          "update": "Preservation Policy updated"
         }
       },
       "table": {
@@ -467,7 +467,7 @@
           },
           "dispositionApproval": "Disposition Approval",
           "lastUpdate": {
-            "when": "Last updated"
+            "when": "Updated"
           },
           "name": "Name",
           "retention": "Retention"
@@ -488,9 +488,9 @@
       },
       "notification": {
         "resource": {
-          "create": "Role created with success",
-          "delete": "Role deleted with success",
-          "update": "Role updated with success"
+          "create": "Role created",
+          "delete": "Role deleted",
+          "update": "Role updated"
         }
       },
       "table": {
@@ -508,8 +508,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the submission policy '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following submission policy: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -519,14 +519,14 @@
         "timeToKeep": "Time To Keep"
       },
       "home": {
-        "subtitle": "Describe the submission policy for a deposit",
+        "subtitle": "Describes the submission policies for a deposit",
         "title": "Submission Policy"
       },
       "notification": {
         "resource": {
-          "create": "Submission Policy created with success",
-          "delete": "Submission Policy deleted with success",
-          "update": "Submission Policy updated with success"
+          "create": "Submission Policy created",
+          "delete": "Submission Policy deleted",
+          "update": "Submission Policy updated"
         }
       },
       "table": {
@@ -535,7 +535,7 @@
             "when": "Created"
           },
           "lastUpdate": {
-            "when": "Last updated"
+            "when": "Updated"
           },
           "name": "Name",
           "submissionApproval": "Submission Approval",
@@ -552,23 +552,23 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete the User '{{name}}'?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following user: '{{name}}' ?",
+          "title": "Confirm delete action"
         },
         "editOwnRoles": {
           "cancel": "Cancel",
           "confirm": "Yes, I'm sure!",
           "looseAdminRole": "You will lose access to the administration features.",
-          "noMoreRight": "You have removed all your rights which will prevent you from accessing the application!",
+          "noMoreRight": "You have removed all of your permissions. This will prevent you from accessing the application!",
           "summary": {
             "addedRoles": "Added roles :",
             "removedRoles": "Removed roles :"
           },
-          "title": "Be careful, you will modify your roles!",
-          "warning": "This will result in a change of rights within the application.\nYou're going to be dislodged."
+          "title": "Be careful, you are modifying your own roles!",
+          "warning": "This action will result in a change of permissions within the application.\nYou will be logged out."
         }
       },
-      "editCurrentUser": "Warning, you will edit your own informations !",
+      "editCurrentUser": "Warning, you may be editing your own information!",
       "form": {
         "accessToken": "Access Token",
         "email": "Email",
@@ -583,14 +583,14 @@
         "targetedUid": "targeted Uid"
       },
       "home": {
-        "subtitle": "Describe the User",
+        "subtitle": "Describes Users",
         "title": "User"
       },
       "notification": {
         "resource": {
-          "create": "User created with success",
-          "delete": "User deleted with success",
-          "update": "User updated with success"
+          "create": "User created",
+          "delete": "User deleted",
+          "update": "User updated"
         }
       },
       "table": {
@@ -620,10 +620,10 @@
       },
       "licence": "Licence",
       "name": "Name",
-      "organizationUnit": "Organization unit",
+      "organizationUnit": "Organizational unit",
       "resId": "ResId",
       "size": "Size",
-      "status": "Statut",
+      "status": "Status",
       "yearOfcreation": "Year"
     },
     "table": {
@@ -632,7 +632,7 @@
           "when": "Created"
         },
         "lastUpdate": {
-          "when": "Last updated"
+          "when": "Updated"
         },
         "name": "Name",
         "organizationalUnit": "Organizational unit",
@@ -681,14 +681,14 @@
       "button": {
         "backToHome": "Back to home page"
       },
-      "title": "The requested resource does not exist or no longer exist..."
+      "title": "The requested resource does not exist or no longer exists..."
     },
     "notification": {
       "tokenCopiedToClipboardFail": "Unable to copy the token to the clipboard",
       "tokenCopiedToClipboardSuccess": "Token copied to the clipboard"
     },
     "status": {
-      "backToOnline": "You are back to online",
+      "backToOnline": "You are back online",
       "newVersionAvailable": "A new version of the application is available",
       "offline": "Your are currently offline"
     },
@@ -718,14 +718,14 @@
         "updateAfter": "Later",
         "updateNow": "Yes"
       },
-      "title": "New version of the available application"
+      "title": "A new version of the application is available"
     },
     "user": {
       "administrative": {
         "form": {
           "email": "Email",
           "firstName": "First name",
-          "homeOrganization": "Organization Unit",
+          "homeOrganization": "Organizational Unit",
           "lastName": "Last name",
           "roles": "Roles"
         },
@@ -754,7 +754,7 @@
       "disseminationPolicy": {
         "create": "Create",
         "edit": "Edit",
-        "root": "Dissemination policy"
+        "root": "Dissemination policies"
       },
       "funding-agencies": {
         "create": "Create",
@@ -829,12 +829,18 @@
     },
     "preservation": {
       "aip-statuses": {
-        "root": "AIPs Statuses"
+        "root": "AIP Status"
       },
       "aip": {
-        "root": "Storagion",
+        "file": "Files",
+        "metadata": "Metadata",
+        "root": "Storagion"
+      },
+      "dip": {
+        "edit": "Edit",
+        "file": "Data files",
         "metadata": "Metadata",
-        "file": "Files"
+        "root": "DIP"
       },
       "job": {
         "create": "Create",
@@ -857,10 +863,10 @@
       "action": {
         "delete": "Delete",
         "download": "Download",
+        "goToAip": "Go to Aip",
         "goToEdit": "Edit",
         "resume": "Resume",
-        "start": "Run",
-        "goToAip": "Go to Aip"
+        "start": "Run"
       }
     }
   },
@@ -872,7 +878,7 @@
         "completed": "The submission of the deposit has been completed",
         "error": "The deposit is in error. Please submit it later",
         "processed": "Ongoing filing process",
-        "rejected": "The submission of the deposit was rejected"
+        "rejected": "This deposit has been rejected"
       }
     },
     "approve": "Approve",
@@ -887,7 +893,7 @@
       "table": {
         "complianceLevel": "Compliance level",
         "creation": {
-          "when": "Sending date"
+          "when": "Uploaded"
         },
         "fileName": "File name",
         "status": "Status"
@@ -899,14 +905,14 @@
       "delete": {
         "cancel": "Cancel",
         "confirm": "Yes",
-        "message": "Are you sure you want to delete the deposit '{{name}}'?",
-        "title": "Confirm deletion"
+        "message": "Are you sure you want to delete the following deposit: '{{name}}'?",
+        "title": "Confirm delete action"
       }
     },
     "doi": "DOI",
     "edit": "Edit",
     "error": {
-      "fileInError": "The data file has an Error",
+      "fileInError": "One or more data files contain errors",
       "noFile": "You have to upload a file to submit the deposit"
     },
     "file": {
@@ -993,9 +999,9 @@
         "notification": {
           "error": "There was a problem with the upload of the file",
           "info": {
-            "canceled": "The file upload has been cancelled with success"
+            "canceled": "The file upload has been cancelled"
           },
-          "success": "File uploaded with success"
+          "success": "File uploaded"
         },
         "retry": "Retry"
       }
@@ -1039,12 +1045,12 @@
       },
       "reserveDOI": {
         "fail": "There was an error when reserving DOI of the deposit",
-        "success": "DOI reserved with success"
+        "success": "DOI reserved"
       },
       "resource": {
-        "create": "Deposit created with success",
-        "delete": "Deposit deleted with success",
-        "update": "Deposit updated with success"
+        "create": "Deposit created",
+        "delete": "Deposit deleted",
+        "update": "Deposit updated"
       },
       "submit": {
         "fail": "There was an error when submitting the deposit",
@@ -1081,7 +1087,7 @@
     "reject": "Reject",
     "reserveDOI": "Reserve DOI",
     "submissionPolicy": "Submission Policy",
-    "submit": "Save",
+    "submit": "Submit",
     "tab": {
       "datafiles": "Files",
       "details": "Metadata"
@@ -1092,7 +1098,7 @@
           "when": "Created"
         },
         "lastUpdate": {
-          "when": "Last updated"
+          "when": "Updated"
         },
         "publicationDate": "Publication date",
         "status": "Status",
@@ -1124,21 +1130,30 @@
       "submissionPolicy": "Shows the options that were defined during your preservation space's (i.e. organizational unit) creation. \n\nSee the documentation for more information"
     }
   },
+  "dip": {
+    "notification": {
+      "resource": {
+        "update": {
+          "fail": "Unable to update the DIP"
+        }
+      }
+    }
+  },
   "doi": {
     "copyLongDoi": "Copy long DOI",
     "copyShortDoi": "Copy short DOI",
     "copyUrlLongDoi": "Copy url with long DOI",
     "copyUrlShortLongDoi": "Copy url with short DOI",
     "notification": {
-      "longDoiCopyToClipboard": "Long DOI copy to clipboard",
+      "longDoiCopyToClipboard": "Long DOI copied to clipboard",
       "shortDoiCopyToClipboard": {
         "fail": "Unable to retrieve the short DOI",
-        "success": "Short DOI copy to clipboard"
+        "success": "Short DOI copied to clipboard"
       },
-      "urlLongDoiCopyToClipboard": "Url with long DOI copy to clipboard",
+      "urlLongDoiCopyToClipboard": "Url with long DOI copied to clipboard",
       "urlShortDoiCopyToClipboard": {
         "fail": "Unable to retrieve the short DOI",
-        "success": "Url with short DOI copy to clipboard"
+        "success": "Url with short DOI copied to clipboard"
       }
     }
   },
@@ -1194,7 +1209,7 @@
           "notification": {
             "error": "An error occurs during the preparation of package",
             "inPreparation": "Package in preparation. The download will start soon",
-            "success": "Package downloaded successfully"
+            "success": "Package downloaded"
           }
         }
       },
@@ -1247,11 +1262,11 @@
       "action": {
         "deepChecksum": {
           "fail": "Impossible to do a deep checksum",
-          "success": "AIP's deep checksums will be checked"
+          "success": "The AIP's deep checksums will be checked"
         },
         "reindex": {
           "fail": "Impossible to reindex the AIP",
-          "success": "TThe AIP will be reindexed"
+          "success": "The AIP will be reindexed"
         },
         "resume": {
           "fail": "Impossible to restart AIP processing",
@@ -1259,19 +1274,27 @@
         },
         "simpleChecksum": {
           "fail": "Impossible to do a simple checkum",
-          "success": "AIP's simple checksums will be checked"
+          "success": "The AIP's simple checksums will be checked"
         }
       },
       "file": {
         "download": "Download in progress",
-        "downloadWithSuccess": "notification.aip.file.downloadWithSuccess"
+        "downloadWithSuccess": "AIP downloaded"
       }
     },
     "deposit": {
       "file": {
         "download": "Download in progress",
-        "downloadWithSuccess": "notification.deposit.file.downloadWithSuccess",
-        "resumed": "Resource resumed successfully"
+        "downloadWithSuccess": "Deposit downloaded",
+        "resumed": "Resource resumed"
+      }
+    },
+    "dip": {
+      "action": {
+        "resume": {
+          "fail": "Impossible to restart DIP processing",
+          "success": "DIP processing has been restarted"
+        }
       }
     },
     "sip": {
@@ -1299,16 +1322,16 @@
     "new": "Create new organizational unit",
     "notification": {
       "resource": {
-        "create": "Organizational Unit created with success",
-        "delete": "Organizational Unit deleted with success",
-        "update": "Organizational Unit updated with success"
+        "create": "Organizational Unit created",
+        "delete": "Organizational Unit deleted",
+        "update": "Organizational Unit updated"
       }
     },
     "openingDate": "Opening Date",
     "refresh": "Refresh",
     "security": {
       "notification": {
-        "noRightForThisAction": "You do not have the right to carry out this action"
+        "noRightForThisAction": "You do not have permission to carry out this action"
       }
     },
     "submit": "Save",
@@ -1324,6 +1347,12 @@
   },
   "preservation": {
     "aip": {
+      "aip": {
+        "aipOfAip": "Aips",
+        "table": {
+          "aipName": "Aip Name"
+        }
+      },
       "back": "Back",
       "button": {
         "back": "Back",
@@ -1336,12 +1365,6 @@
       "tab": {
         "aip": "AIP",
         "details": "Metadata"
-      },
-      "aip": {
-        "aipOfAip": "Aips",
-        "table": {
-          "aipName": "Aip Name"
-        }
       }
     },
     "aipStats": {
@@ -1364,9 +1387,42 @@
       }
     },
     "dip": {
+      "back": "Back",
+      "button": {
+        "download": "Download",
+        "resume": "Resume"
+      },
+      "form": {
+        "access": "Access",
+        "aip": "AIP",
+        "complianceLevel": "Compliance level",
+        "description": "Description",
+        "name": "Name",
+        "organizationalUnitName": "Organizational unit",
+        "resId": "Identification",
+        "status": "Status",
+        "submit": "Save"
+      },
       "home": {
         "subtitle": "Dissemination Information Package",
         "title": "DIP"
+      },
+      "refresh": "Refresh",
+      "tab": {
+        "datafiles": "Files",
+        "details": "Metadata"
+      },
+      "table": {
+        "header": {
+          "creation": {
+            "when": "Created"
+          },
+          "lastUpdate": {
+            "when": "Updated"
+          },
+          "status": "Status",
+          "title": "Title"
+        }
       }
     },
     "home": {
@@ -1383,8 +1439,8 @@
         "delete": {
           "cancel": "Cancel",
           "confirm": "Yes",
-          "message": "Are you sure you want to delete this job?",
-          "title": "Confirm deletion"
+          "message": "Are you sure you want to delete the following job: '{{name}}' ?",
+          "title": "Confirm delete action"
         }
       },
       "form": {
@@ -1415,21 +1471,21 @@
       },
       "notification": {
         "init": {
-          "fail": "Unable to init jobs",
-          "success": "Jobs init with success"
+          "fail": "Unable to initiate jobs",
+          "success": "Jobs initiated"
         },
         "resource": {
-          "create": "Job created successfully",
-          "delete": "Job deleted successfully",
-          "update": "Job updated successfully"
+          "create": "Job created",
+          "delete": "Job deleted",
+          "update": "Job updated"
         },
         "resume": {
           "fail": "Unable to resume the job",
-          "success": "Job resumed successfully"
+          "success": "Job resumed"
         },
         "start": {
           "fail": "Unable to start the job",
-          "success": "Job started successfully"
+          "success": "Job started"
         }
       },
       "state": {
@@ -1442,7 +1498,7 @@
           "jobRecurrence": "Recurrence",
           "jobType": "Type",
           "name": "Name",
-          "when": "Last modification"
+          "when": "Updated"
         }
       }
     },
@@ -1463,12 +1519,12 @@
       },
       "notification": {
         "resume": {
-          "fail": "Unable to resume the job execution",
-          "success": "Job execution resumed with success"
+          "fail": "Unable to resume the job",
+          "success": "Job resumed"
         },
         "start": {
-          "fail": "Unable to start the job execution",
-          "success": "Job execution started with success"
+          "fail": "Unable to start the job",
+          "success": "Job started"
         }
       },
       "table": {
@@ -1488,11 +1544,11 @@
         "start": "Start"
       },
       "ignoredItems": "Ignored items",
-      "inErrorItems": "In error items",
+      "inErrorItems": "Items in error",
       "processedItems": "Processed items",
       "runNumber": "Run number",
       "status": "Status",
-      "title": "Detail job execution",
+      "title": "Job execution detail",
       "totalItems": "Total items"
     },
     "jobs": {
@@ -1503,7 +1559,7 @@
     },
     "monitoring": {
       "home": {
-        "subtitle": "Allows to check the status of the solution",
+        "subtitle": "Shows the state of the platform's services",
         "title": "Monitoring"
       }
     },
@@ -1539,7 +1595,7 @@
             "when": "Created"
           },
           "lastUpdate": {
-            "when": "Last updated"
+            "when": "Updated"
           },
           "organizationalUnit": "Organizational unit",
           "status": "Status",
@@ -1557,9 +1613,9 @@
     "person": {
       "notification": {
         "resource": {
-          "create": "Person created with success",
-          "delete": "Person deleted with success",
-          "update": "Person updated with success"
+          "create": "Person created",
+          "delete": "Person deleted",
+          "update": "Person updated"
         }
       }
     },
@@ -1613,7 +1669,7 @@
   "welcome": {
     "rss": {
       "notification": {
-        "error": "There is an error while retrieving the RSS feed"
+        "error": "There was an error while retrieving the RSS feed"
       }
     }
   }
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json
index c763fef2a..97e9e0825 100644
--- a/src/assets/i18n/en.json
+++ b/src/assets/i18n/en.json
@@ -832,9 +832,15 @@
         "root": "AIP Status"
       },
       "aip": {
-        "root": "Storagion",
+        "file": "Files",
         "metadata": "Metadata",
-        "file": "Files"
+        "root": "Storagion"
+      },
+      "dip": {
+        "edit": "Edit",
+        "file": "Data files",
+        "metadata": "Metadata",
+        "root": "DIP"
       },
       "job": {
         "create": "Create",
@@ -857,10 +863,10 @@
       "action": {
         "delete": "Delete",
         "download": "Download",
+        "goToAip": "Go to Aip",
         "goToEdit": "Edit",
         "resume": "Resume",
-        "start": "Run",
-        "goToAip": "Go to Aip"
+        "start": "Run"
       }
     }
   },
@@ -1124,6 +1130,15 @@
       "submissionPolicy": "Shows the options that were defined during your preservation space's (i.e. organizational unit) creation. \n\nSee the documentation for more information"
     }
   },
+  "dip": {
+    "notification": {
+      "resource": {
+        "update": {
+          "fail": "Unable to update the DIP"
+        }
+      }
+    }
+  },
   "doi": {
     "copyLongDoi": "Copy long DOI",
     "copyShortDoi": "Copy short DOI",
@@ -1274,6 +1289,14 @@
         "resumed": "Resource resumed"
       }
     },
+    "dip": {
+      "action": {
+        "resume": {
+          "fail": "Impossible to restart DIP processing",
+          "success": "DIP processing has been restarted"
+        }
+      }
+    },
     "sip": {
       "action": {
         "resume": {
@@ -1324,6 +1347,12 @@
   },
   "preservation": {
     "aip": {
+      "aip": {
+        "aipOfAip": "Aips",
+        "table": {
+          "aipName": "Aip Name"
+        }
+      },
       "back": "Back",
       "button": {
         "back": "Back",
@@ -1336,12 +1365,6 @@
       "tab": {
         "aip": "AIP",
         "details": "Metadata"
-      },
-      "aip": {
-        "aipOfAip": "Aips",
-        "table": {
-          "aipName": "Aip Name"
-        }
       }
     },
     "aipStats": {
@@ -1364,9 +1387,42 @@
       }
     },
     "dip": {
+      "back": "Back",
+      "button": {
+        "download": "Download",
+        "resume": "Resume"
+      },
+      "form": {
+        "access": "Access",
+        "aip": "AIP",
+        "complianceLevel": "Compliance level",
+        "description": "Description",
+        "name": "Name",
+        "organizationalUnitName": "Organizational unit",
+        "resId": "Identification",
+        "status": "Status",
+        "submit": "Save"
+      },
       "home": {
         "subtitle": "Dissemination Information Package",
         "title": "DIP"
+      },
+      "refresh": "Refresh",
+      "tab": {
+        "datafiles": "Files",
+        "details": "Metadata"
+      },
+      "table": {
+        "header": {
+          "creation": {
+            "when": "Created"
+          },
+          "lastUpdate": {
+            "when": "Updated"
+          },
+          "status": "Status",
+          "title": "Title"
+        }
       }
     },
     "home": {
diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json
index ac0e5ffc1..367bbe125 100644
--- a/src/assets/i18n/fr.json
+++ b/src/assets/i18n/fr.json
@@ -832,9 +832,15 @@
         "root": "Statuts des AIPs"
       },
       "aip": {
-        "root": "Storagion",
         "file": "Fichiers",
-        "metadata": "Métadonnées"
+        "metadata": "Métadonnées",
+        "root": "Storagion"
+      },
+      "dip": {
+        "edit": "Modifier",
+        "file": "Fichiers",
+        "metadata": "Métadonnées",
+        "root": "DIP"
       },
       "job": {
         "create": "Créer",
@@ -857,10 +863,10 @@
       "action": {
         "delete": "Supprimer",
         "download": "Télécharger",
+        "goToAip": "Aller à Aip",
         "goToEdit": "Modifier",
         "resume": "Relancer",
-        "start": "Lancer",
-        "goToAip": "Aller à Aip"
+        "start": "Lancer"
       }
     }
   },
@@ -1124,6 +1130,15 @@
       "submissionPolicy": "Montre les options qui ont été choisies lors de la création de votre espace de préservation (ou unité organisationnelle).\n\nVoir la documentation pour plus d'informations"
     }
   },
+  "dip": {
+    "notification": {
+      "resource": {
+        "update": {
+          "fail": "Impossible de mettre à jour le DIP"
+        }
+      }
+    }
+  },
   "doi": {
     "copyLongDoi": "Copier le DOI long",
     "copyShortDoi": "Copier le DOI court",
@@ -1274,6 +1289,14 @@
         "resumed": "Processus d'ingestion relancé avec succès"
       }
     },
+    "dip": {
+      "action": {
+        "resume": {
+          "fail": "Impossible de relancer le traitement du DIP",
+          "success": "Le traitement du DIP a été relancé"
+        }
+      }
+    },
     "sip": {
       "action": {
         "resume": {
@@ -1324,6 +1347,12 @@
   },
   "preservation": {
     "aip": {
+      "aip": {
+        "aipOfAip": "Aips",
+        "table": {
+          "aipName": "Nom du Aip"
+        }
+      },
       "back": "Retour",
       "button": {
         "back": "Retour",
@@ -1336,12 +1365,6 @@
       "tab": {
         "aip": "AIP",
         "details": "Métadonnées"
-      },
-      "aip": {
-        "aipOfAip": "Aips",
-        "table": {
-          "aipName": "Nom du Aip"
-        }
       }
     },
     "aipStats": {
@@ -1364,9 +1387,42 @@
       }
     },
     "dip": {
+      "back": "Retour",
+      "button": {
+        "download": "Télécharger",
+        "resume": "Relancer"
+      },
+      "form": {
+        "access": "Accès",
+        "aip": "AIP",
+        "complianceLevel": "Niveau de conformité des données",
+        "description": "Description",
+        "name": "Nom",
+        "organizationalUnitName": "Unité organisationnelle",
+        "resId": "Identifiant",
+        "status": "Statut",
+        "submit": "Enregistrer"
+      },
       "home": {
-        "subtitle": "Paquet d'information diffusé",
+        "subtitle": "Paquet d'information à disséminer",
         "title": "DIP"
+      },
+      "refresh": "Rafraichir",
+      "tab": {
+        "datafiles": "Fichiers",
+        "details": "Métadonnées"
+      },
+      "table": {
+        "header": {
+          "creation": {
+            "when": "Date de création"
+          },
+          "lastUpdate": {
+            "when": "Dernière mise à jour"
+          },
+          "status": "Statut",
+          "title": "Titre"
+        }
       }
     },
     "home": {
-- 
GitLab