Skip to content

Commit c0ef873

Browse files
author
Hassane Diaby
committed
Story #15575 : Collect - Errors displaying improvement
1 parent f888d4a commit c0ef873

29 files changed

+513
-70
lines changed

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/archive-preview.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
[extended]="isPanelextended"
33
[title]="archiveUnit | unitI18n: 'Title' | truncate: 29"
44
[icon]="getArchiveUnitIcon(archiveUnit)"
5+
[badge]="addStatusBadgeforArchiveUnitWithErrors(archiveUnit)"
56
[hasToolTipOnTitle]="true"
67
[toolTipTitleText]="archiveUnit | unitI18n: 'Title'"
78
[toolTipTitleDuration]="300"
@@ -31,6 +32,7 @@
3132
<app-archive-unit-information-tab
3233
[archiveUnit]="archiveUnit"
3334
(showNormalPanel)="showNormalPanel()"
35+
(openObjectsTab)="selectedTabChangeEvent($event)"
3436
></app-archive-unit-information-tab>
3537
</mat-tab>
3638

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/archive-preview.component.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import { AfterViewInit, Component, EventEmitter, HostListener, Input, OnChanges, Output, SimpleChanges, ViewChild } from '@angular/core';
3838
import { MatTab, MatTabChangeEvent, MatTabGroup, MatTabHeader } from '@angular/material/tabs';
3939
import { TranslateService } from '@ngx-translate/core';
40-
import { Unit, unitToVitamuiIcon } from 'vitamui-library';
40+
import { Unit, unitToVitamuiIcon, ArchiveUnit, addErrorStatusBadgeIfArchiveUnitHasErrors } from 'vitamui-library';
4141
import { ArchiveUnitDescriptionTabComponent } from './archive-unit-description-tab/archive-unit-description-tab.component';
4242
import { ArchiveSharedDataService } from '../../core/archive-shared-data.service';
4343

@@ -151,4 +151,8 @@ export class ArchivePreviewComponent implements OnChanges, AfterViewInit {
151151
getArchiveUnitIcon(unit: Unit) {
152152
return unitToVitamuiIcon(unit);
153153
}
154+
155+
addStatusBadgeforArchiveUnitWithErrors(archiveUnit: ArchiveUnit) {
156+
return addErrorStatusBadgeIfArchiveUnitHasErrors(archiveUnit);
157+
}
154158
}

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/archive-unit-information-tab/archive-unit-information-tab.component.html

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
<div class="gap-2 align-items-stretch">
2-
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.NAME' | translate" [value]="archiveUnit | unitI18n: 'Title'" />
2+
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.NAME' | translate" [value]="archiveUnit() | unitI18n: 'Title'" />
33

4-
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.GUID' | translate" [value]="archiveUnit['#opi']" />
4+
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.GUID' | translate" [value]="archiveUnit()['#opi']" />
55

6-
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.UAID' | translate" [value]="archiveUnit['#id']" />
6+
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.UAID' | translate" [value]="archiveUnit()['#id']" />
77

88
<vitamui-common-data
99
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.DESCRIPTION' | translate"
10-
[value]="archiveUnit | unitI18n: 'Description'"
10+
[value]="archiveUnit() | unitI18n: 'Description'"
1111
/>
1212

1313
<div class="hgap-4 align-items-baseline">
1414
<vitamui-common-data
1515
class="w-50"
1616
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.SP' | translate"
17-
[value]="archiveUnit['#originating_agency']"
17+
[value]="archiveUnit()['#originating_agency']"
1818
/>
1919
<vitamui-common-data
2020
class="w-50"
2121
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.SP_LABEL' | translate"
22-
[value]="archiveUnit?.originating_agencyName"
22+
[value]="archiveUnit()?.originating_agencyName"
2323
/>
2424
</div>
2525

@@ -35,32 +35,43 @@
3535
<vitamui-common-data
3636
class="w-50"
3737
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.DESCRIPTION_LEVEL' | translate"
38-
[value]="'UNIT_UPDATE.' + archiveUnit.DescriptionLevel.toUpperCase() | translate"
38+
[value]="'UNIT_UPDATE.' + archiveUnit().DescriptionLevel.toUpperCase() | translate"
3939
/>
4040
</div>
4141

4242
<div class="hgap-4 align-items-baseline">
4343
<vitamui-common-data
4444
class="w-50"
4545
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.START_DATE' | translate"
46-
[value]="archiveUnit?.StartDate | dateTime: 'dd/MM/yyyy'"
46+
[value]="archiveUnit()?.StartDate | dateTime: 'dd/MM/yyyy'"
4747
/>
4848
<vitamui-common-data
4949
class="w-50"
5050
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.END_DATE' | translate"
51-
[value]="archiveUnit?.EndDate | dateTime: 'dd/MM/yyyy'"
51+
[value]="archiveUnit()?.EndDate | dateTime: 'dd/MM/yyyy'"
5252
/>
5353
</div>
5454

55-
@if (hasErrorMessages) {
56-
<vitamui-common-data [label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.ENCOUNTERED_ERRORS' | translate" [value]="errorMessages" />
55+
@if (technicalObjectsGroupErrors().length || objectsGroupErrors().length) {
56+
<vitamui-information-bloc
57+
[withObjectsTabLink]="true"
58+
[decoration]="'bordered'"
59+
(openObjectsTab)="goToObjectsTab()"
60+
></vitamui-information-bloc>
61+
}
62+
63+
@if (archiveUnitErrors().length) {
64+
<div class="text normal bold danger">{{ 'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.ENCOUNTERED_ERRORS' | translate | uppercase }}</div>
65+
@for (error of archiveUnitErrors(); track $index) {
66+
<vitamui-information-detail [error]="error" [hideEvDetData]="true"></vitamui-information-detail>
67+
}
5768
}
5869
</div>
5970

6071
<button
6172
class="btn primary download-btn"
62-
[disabled]="!archiveUnit['#object'] || !hasDownloadDocumentRole"
63-
(click)="onDownloadObjectFromUnit(archiveUnit)"
73+
[disabled]="!archiveUnit()['#object'] || !hasDownloadDocumentRole"
74+
(click)="onDownloadObjectFromUnit(archiveUnit())"
6475
>
6576
<span>{{ 'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.DOWNLOAD_DOC' | translate }}</span>
6677
<i class="vitamui-icon vitamui-icon-deposit"></i>

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/archive-unit-information-tab/archive-unit-information-tab.component.ts

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@
3434
* The fact that you are presently reading this means that you have had
3535
* knowledge of the CeCILL-C license and that you accept its terms.
3636
*/
37-
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
38-
import { TranslateService } from '@ngx-translate/core';
37+
import { Component, computed, EventEmitter, input, InputSignal, OnChanges, Output, Signal, SimpleChanges } from '@angular/core';
3938
import { Observable } from 'rxjs';
40-
import { TenantSelectionService, Unit } from 'vitamui-library';
39+
import {
40+
TenantSelectionService,
41+
Unit,
42+
getErrorsOnArchiveUnit,
43+
getErrorOnTechnicalObjectsGroup,
44+
getErrorOnObjectsGroup,
45+
ValidationError,
46+
} from 'vitamui-library';
4147
import { ArchiveCollectService } from '../../archive-collect.service';
4248

4349
@Component({
@@ -47,18 +53,29 @@ import { ArchiveCollectService } from '../../archive-collect.service';
4753
standalone: false,
4854
})
4955
export class ArchiveUnitInformationTabComponent implements OnChanges {
50-
@Input() archiveUnit: Unit;
56+
OBJECTS_TAB_INDEX = 3;
5157

58+
archiveUnit: InputSignal<Unit> = input(null);
5259
@Output() showNormalPanel = new EventEmitter<any>();
60+
@Output() openObjectsTab = new EventEmitter<any>();
5361

5462
uaPath$: Observable<{ fullPath: string; resumePath: string }>;
5563
fullPath = false;
5664
hasDownloadDocumentRole = false;
5765

66+
archiveUnitErrors: Signal<ValidationError[]> = computed(() => {
67+
return getErrorsOnArchiveUnit(this.archiveUnit());
68+
});
69+
technicalObjectsGroupErrors: Signal<ValidationError[]> = computed(() => {
70+
return getErrorOnTechnicalObjectsGroup(this.archiveUnit());
71+
});
72+
objectsGroupErrors: Signal<ValidationError[]> = computed(() => {
73+
return getErrorOnObjectsGroup(this.archiveUnit());
74+
});
75+
5876
constructor(
5977
private archiveService: ArchiveCollectService,
6078
private tenantSelectionService: TenantSelectionService,
61-
private translateService: TranslateService,
6279
) {}
6380

6481
ngOnChanges(changes: SimpleChanges): void {
@@ -72,31 +89,15 @@ export class ArchiveUnitInformationTabComponent implements OnChanges {
7289
}
7390

7491
onDownloadObjectFromUnit(archiveUnit: Unit) {
75-
return this.archiveService.downloadObjectFromUnit(archiveUnit['#id'], this.archiveUnit['#object']);
92+
return this.archiveService.downloadObjectFromUnit(archiveUnit['#id'], this.archiveUnit()['#object']);
7693
}
7794

7895
showArchiveUniteFullPath() {
7996
this.fullPath = true;
8097
}
8198

82-
get hasErrorMessages(): boolean {
83-
return this.archiveUnit['#errors']?.length > 0 || this.archiveUnit['#ogInfo']?.['#errors']?.length > 0;
84-
}
85-
86-
get errorMessages(): string[] | undefined {
87-
if (!this.hasErrorMessages) return;
88-
const unitValidationErrors = this.archiveUnit['#errors']?.map((error) => error.outMessg) ?? [];
89-
const nbObjectGroupValidationErrors = this.archiveUnit['#ogInfo']?.['#errors']?.length ?? 0;
90-
91-
const result = [...unitValidationErrors];
92-
if (nbObjectGroupValidationErrors > 0) {
93-
result.push(
94-
this.translateService.instant('COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.OBJECT_GROUP_VALIDATION_ERRORS', {
95-
nbErrors: nbObjectGroupValidationErrors,
96-
}),
97-
);
98-
}
99-
return result;
99+
goToObjectsTab() {
100+
this.openObjectsTab.emit({ index: this.OBJECTS_TAB_INDEX, tab: null });
100101
}
101102

102103
private checkDownloadPermissions() {

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/collect-object-group-details-tab/collect-object-group-details-tab.component.html

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
<div class="object-details-group IDS" *ngIf="unitObject">
2+
@if (objectsGroupErrors().length) {
3+
<div class="mb-3">
4+
<vitamui-information-bloc [decoration]="'bordered'"></vitamui-information-bloc>
5+
</div>
6+
}
7+
28
<div class="row">
39
<div class="col title">
410
{{ 'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.TECHNICAL_OBJECT_GROUP' | translate }}
@@ -27,17 +33,15 @@
2733
</div>
2834
</div>
2935

30-
@if (errorMessagesGot && errorMessagesGot['null']) {
31-
<div class="row-separator"></div>
32-
<div class="row">
33-
<div class="col title">
36+
@if (technicalObjectsGroupErrors().length) {
37+
<div class="d-flex flex-column gap-2 align-items-stretch">
38+
<div class="text normal bold danger">
3439
{{ 'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.ENCOUNTERED_ERRORS' | translate | uppercase }}
3540
</div>
41+
@for (error of technicalObjectsGroupErrors(); track error) {
42+
<vitamui-information-detail [error]="error"></vitamui-information-detail>
43+
}
3644
</div>
37-
<vitamui-common-data
38-
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.LABEL' | translate"
39-
[value]="errorMessagesGot['null']"
40-
></vitamui-common-data>
4145
}
4246
</div>
4347

@@ -290,14 +294,13 @@
290294
</div>
291295

292296
@if (errorMessagesGot && errorMessagesGot[versionWithQualifier['#id']]) {
293-
<div class="object-details-group">
294-
<div class="row title">
297+
<div class="d-flex flex-column gap-2 align-items-stretch">
298+
<div class="text normal bold danger">
295299
{{ 'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.ENCOUNTERED_ERRORS' | translate | uppercase }}
296300
</div>
297-
<vitamui-common-data
298-
[label]="'COLLECT.ARCHIVE_UNIT_PREVIEW.FIELDS.LABEL' | translate"
299-
[value]="errorMessagesGot[versionWithQualifier['#id']]"
300-
></vitamui-common-data>
301+
@for (error of errorMessagesGot[versionWithQualifier['#id']]; track $index) {
302+
<vitamui-information-detail [error]="error"></vitamui-information-detail>
303+
}
301304
</div>
302305
}
303306

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-preview/collect-object-group-details-tab/collect-object-group-details-tab.component.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
*/
3737
import { animate, AUTO_STYLE, state, style, transition, trigger } from '@angular/animations';
3838
import { Clipboard } from '@angular/cdk/clipboard';
39-
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
39+
import { Component, computed, input, InputSignal, OnChanges, Signal, SimpleChanges } from '@angular/core';
4040
import {
4141
ApiUnitObject,
4242
DescriptionLevel,
@@ -46,6 +46,9 @@ import {
4646
TenantSelectionService,
4747
Unit,
4848
VersionWithQualifierDto,
49+
ValidationError,
50+
getErrorOnTechnicalObjectsGroup,
51+
getErrorOnObjectsGroup,
4952
} from 'vitamui-library';
5053
import { ArchiveCollectService } from '../../archive-collect.service';
5154

@@ -64,12 +67,20 @@ import { ArchiveCollectService } from '../../archive-collect.service';
6467
standalone: false,
6568
})
6669
export class CollectObjectGroupDetailsTabComponent implements OnChanges {
67-
@Input() archiveUnit: Unit;
70+
archiveUnit: InputSignal<Unit> = input(null);
71+
6872
unitObject: ApiUnitObject;
6973
versionsWithQualifiersOrdered: Array<VersionWithQualifierDto>;
7074
hasDownloadDocumentRole = false;
7175
private allowedDescriptionLevel = [DescriptionLevel.ITEM, DescriptionLevel.RECORD_GRP];
72-
errorMessagesGot: Record<string, string[]>;
76+
errorMessagesGot: Record<string, ValidationError[]>;
77+
78+
technicalObjectsGroupErrors: Signal<ValidationError[]> = computed(() => {
79+
return getErrorOnTechnicalObjectsGroup(this.archiveUnit());
80+
});
81+
objectsGroupErrors: Signal<ValidationError[]> = computed(() => {
82+
return getErrorOnObjectsGroup(this.archiveUnit());
83+
});
7384

7485
constructor(
7586
private archiveCollectService: ArchiveCollectService,
@@ -84,20 +95,20 @@ export class CollectObjectGroupDetailsTabComponent implements OnChanges {
8495
this.unitObject = null;
8596
this.versionsWithQualifiersOrdered = null;
8697
if (this.unitHasObject()) {
87-
this.getObjectGroupDetailsById(this.archiveUnit);
98+
this.getObjectGroupDetailsById(this.archiveUnit());
8899
}
89100
}
90101
}
91102

92103
unitHasObject(): boolean {
93-
return this.allowedDescriptionLevel.includes(this.archiveUnit.DescriptionLevel) && !!this.archiveUnit['#object'];
104+
return this.allowedDescriptionLevel.includes(this.archiveUnit().DescriptionLevel) && !!this.archiveUnit()['#object'];
94105
}
95106

96107
onClickDownloadObject(event: Event, versionWithQualifier: VersionWithQualifierDto) {
97108
event.stopPropagation();
98109
return this.archiveCollectService.downloadObjectFromUnit(
99-
this.archiveUnit['#id'],
100-
this.archiveUnit['#object'],
110+
this.archiveUnit()['#id'],
111+
this.archiveUnit()['#object'],
101112
versionWithQualifier.qualifier,
102113
versionWithQualifier.version,
103114
);
@@ -114,10 +125,10 @@ export class CollectObjectGroupDetailsTabComponent implements OnChanges {
114125
this.errorMessagesGot = this.unitObject['#errors']?.reduce(
115126
(acc, err) => {
116127
const key = err.obId || 'null';
117-
acc[key] = [...(acc[key] || []), err.outMessg];
128+
acc[key] = [...(acc[key] || []), err];
118129
return acc;
119130
},
120-
{} as Record<string, string[]>,
131+
{} as Record<string, ValidationError[]>,
121132
);
122133
this.setFirstVersionWithQualifierOpen();
123134
});

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-search-collect.component.html

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,11 @@ <h5>{{ 'APPLICATION.COLLECT_APP.NAME' | translate }} : {{ projectName }}</h5>
395395
<span class="table-filter-icon" [ngSwitch]="getArchiveUnitType(archiveUnit)">
396396
<ng-container *ngSwitchCase="UnitType.INGEST">
397397
<span class="table-filter-icon">
398-
<ng-container *ngIf="!archiveUnit?.['#object']">
399-
<i class="vitamui-icon vitamui-icon-folder vitamui-row-icon status-badge"></i>
400-
</ng-container>
401-
<ng-container *ngIf="!!archiveUnit?.['#object']">
402-
<i class="vitamui-icon vitamui-icon-file vitamui-row-icon status-badge"></i>
403-
</ng-container>
398+
<i
399+
class="vitamui-icon vitamui-icon-{{
400+
getProperArchiveUnitIcon(archiveUnit)
401+
}} vitamui-row-icon status-badge status-badge-{{ addStatusBadgeforArchiveUnitWithErrors(archiveUnit) }}"
402+
></i>
404403
</span>
405404
</ng-container>
406405
<ng-container *ngSwitchCase="UnitType.HOLDING_UNIT">

ui/ui-frontend/projects/collect/src/app/collect/archive-search-collect/archive-search-collect.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ import {
7979
TermsFacet,
8080
Transaction,
8181
TransactionStatus,
82+
ArchiveUnit,
83+
addErrorStatusBadgeIfArchiveUnitHasErrors,
8284
Unit,
8385
UnitType,
8486
VALID_COMPUTED_INHERITED_RULES_FACET,
@@ -1331,6 +1333,14 @@ export class ArchiveSearchCollectComponent extends SidenavPage<any> implements O
13311333
}
13321334
}
13331335

1336+
getProperArchiveUnitIcon(archiveUnit: ArchiveUnit) {
1337+
return !archiveUnit?.['#object'] ? 'folder' : 'file';
1338+
}
1339+
1340+
addStatusBadgeforArchiveUnitWithErrors(archiveUnit: ArchiveUnit) {
1341+
return addErrorStatusBadgeIfArchiveUnitHasErrors(archiveUnit);
1342+
}
1343+
13341344
private addCriteria(
13351345
keyElt: string,
13361346
valueElt: CriteriaValue,

ui/ui-frontend/projects/design-system/src/app/app-routing.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ import { TypographyComponent } from './components/tokens/typography/typography.c
5151
import { DesignSystemComponent } from './components/design-system/design-system.component';
5252
import { DesignSystemChipsComponent } from './components/atoms/chips/design-system-chips.component';
5353
import { DesignSystemBadgesComponent } from './components/atoms/badges/design-system-badges.component';
54+
import { DesignSystemInformationBlocComponent } from './components/atoms/design-system-information-bloc/design-system-information-bloc.component';
55+
import { DesignSystemInformationDetailComponent } from './components/atoms/design-system-information-detail/design-system-information-detail.component';
5456
import { SpacingComponent } from './components/tokens/spacing/spacing.component';
5557
import { DesignSystemCheckboxComponent } from './components/molecules/inputs/checkbox/design-system-checkbox.component';
5658
import { DesignSystemSelectComponent } from './components/molecules/inputs/select/design-system-select.component';
@@ -94,6 +96,8 @@ const routes: Routes = [
9496
{ path: 'buttons', component: ButtonsComponent },
9597
{ path: 'chips', component: DesignSystemChipsComponent },
9698
{ path: 'badges', component: DesignSystemBadgesComponent },
99+
{ path: 'information-bloc', component: DesignSystemInformationBlocComponent },
100+
{ path: 'information-detail', component: DesignSystemInformationDetailComponent },
97101
{ path: 'icons', component: IconsComponent },
98102
{ path: 'slide-toggle', component: SlideToggleComponent },
99103
{ path: 'tooltip', component: TooltipComponent },

0 commit comments

Comments
 (0)