Skip to content

Commit 5b2037e

Browse files
PascalRepondjma
andcommitted
fix(validation): restore ValidationComponent accidentally deleted
The ValidationComponent was removed in commit ced084f during the signal refactoring. This component is required for the project validation workflow in HEPVS. - Restore validation.component.ts and validation.component.html - Update import path for enums (./constants -> ../../enum/validation) - Add ValidationComponent to app.module.ts declarations - Extract validation status to severity mapping into a shared constant VALIDATION_STATUS_SEVERITY in validation.ts. Use getter properties in both project and deposit brief-view components to simplify templates and centralize the status-to-severity logic. - Adds the current user organisation information when a new project is created. - Adds a new method to return the current user organisation to the user service. - Force ngx-formly to version 7.0.0 to prevent issues with arrays. Co-Authored-by: Pascal Repond <pascal.repond@rero.ch> Co-Authored-by: Johnny Mariéthoz <Johnny.Mariethoz@rero.ch>
1 parent 1571c7e commit 5b2037e

File tree

11 files changed

+313
-32
lines changed

11 files changed

+313
-32
lines changed

package-lock.json

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

projects/sonar/src/app/app-routing.module.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export const typeResolver: ResolveFn<string> = (route) => {
156156
export class AppRoutingModule {
157157

158158
private translateService: TranslateService = inject(TranslateService);
159-
private router: Router= inject(Router);
159+
private router: Router = inject(Router);
160160
private route: ActivatedRoute = inject(ActivatedRoute);
161161
private userService: UserService = inject(UserService);
162162
private httpClient: HttpClient = inject(HttpClient);
@@ -279,7 +279,8 @@ export class AppRoutingModule {
279279
Accept: 'application/rero+json'
280280
}
281281
},
282-
files: {...fileConfig,
282+
files: {
283+
...fileConfig,
283284
filterList: (item: any) => {
284285
return (
285286
item.metadata &&
@@ -396,6 +397,29 @@ export class AppRoutingModule {
396397
editorSettings: {
397398
longMode: true,
398399
},
400+
preCreateRecord: (record: any) => {
401+
const user = this.userService.currentUser();
402+
// add organisation reference to the new record
403+
const organisationCode = user.organisation.code;
404+
if (organisationCode) {
405+
record.metadata.organisation = {
406+
$ref: this.apiService.getRefEndpoint(
407+
'organisations',
408+
organisationCode
409+
)
410+
};
411+
}
412+
const userPid = user.pid;
413+
if (userPid) {
414+
record.metadata.user = {
415+
$ref: this.apiService.getRefEndpoint(
416+
'users',
417+
userPid
418+
)
419+
};
420+
}
421+
return record;
422+
},
399423
exportFormats: [
400424
{
401425
label: 'CSV',
@@ -474,8 +498,8 @@ export class AppRoutingModule {
474498
if (user) {
475499
/** Removes collections and subdivisions routes on the organisation shared */
476500
if (!('isDedicated' in user.organisation) || !(user.organisation.isDedicated)) {
477-
recordsRoutesConfiguration = recordsRoutesConfiguration
478-
.filter(route => !(['collections', 'subdivisions'].includes(route.type)));
501+
recordsRoutesConfiguration = recordsRoutesConfiguration
502+
.filter(route => !(['collections', 'subdivisions'].includes(route.type)));
479503
}
480504

481505
recordsRoutesConfiguration.forEach((config: any) => {
@@ -521,6 +545,7 @@ export class AppRoutingModule {
521545
recordResource: config.recordResource || null,
522546
exportFormats: config.exportFormats || null,
523547
sortOptions: config.sortOptions || null,
548+
preCreateRecord: config.preCreateRecord || null,
524549
canAdd: () => this._can(config.type, 'add'),
525550
canUpdate: (record: any) => this._can(config.type, 'update', record),
526551
canDelete: (record: any) => this._can(config.type, 'delete', record),
@@ -634,7 +659,7 @@ export class AppRoutingModule {
634659
private _documentAggregationsOrder(): Observable<any> {
635660
return of(null).pipe(
636661
switchMap(() => {
637-
const {view} = this.route.snapshot.children[0].params;
662+
const { view } = this.route.snapshot.children[0].params;
638663

639664
let params = new HttpParams();
640665
if (view) {

projects/sonar/src/app/app.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import { BriefViewComponent as ProjectBriefViewComponent } from './record/projec
9595
import { DetailComponent as ProjectDetailComponent } from './record/project/detail/detail.component';
9696
import { BriefViewComponent as SubdivisionBriefViewComponent } from './record/subdivision/brief-view/brief-view.component';
9797
import { UserComponent } from './record/user/user.component';
98+
import { ValidationComponent } from './record/validation/validation.component';
9899
import { UserService } from './user.service';
99100
import { LicensePipe } from './record/document/license.pipe';
100101
import { BucketNameService } from './bucket-name.service';
@@ -145,7 +146,8 @@ export function minElementError(err: any, field: FormlyFieldConfig) {
145146
MetadataComponent,
146147
FilesComponent,
147148
SwisscoveryComponent,
148-
LicensePipe
149+
LicensePipe,
150+
ValidationComponent
149151
],
150152
bootstrap: [AppComponent],
151153
schemas: [CUSTOM_ELEMENTS_SCHEMA],

projects/sonar/src/app/deposit/brief-view/brief-view.component.html

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,8 @@ <h4 class="ui:flex-grow">
6262
@if(!record.metadata.logs || record.metadata.logs.length === 1) {
6363
<p-tag severity="contrast" [value]="'New' | translate" />
6464
}
65-
@switch(record.metadata.status) {
66-
@case('in_progress') {
67-
<p-tag severity="primary" [value]="('deposit_status_' + record.metadata.status) | translate" />
68-
}
69-
@case('to_validate') {
70-
<p-tag severity="info" [value]="('deposit_status_' + record.metadata.status) | translate" />
71-
}
72-
@case('ask_for_changes') {
73-
<p-tag severity="warn" [value]="('deposit_status_' + record.metadata.status) | translate" />
74-
}
75-
@case('validated') {
76-
<p-tag severity="success" [value]="('deposit_status_' + record.metadata.status) | translate" />
77-
}
78-
@case('rejected') {
79-
<p-tag severity="danger" [value]="('deposit_status_' + record.metadata.status) | translate" />
80-
}
65+
@if(statusSeverity) {
66+
<p-tag [severity]="statusSeverity" [value]="('deposit_status_' + record.metadata.status) | translate" />
8167
}
8268
</div>
8369

projects/sonar/src/app/deposit/brief-view/brief-view.component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
import { Component, computed, inject, OnDestroy, OnInit, signal } from '@angular/core';
1818
import { Subscription } from 'rxjs';
19+
import { VALIDATION_STATUS_SEVERITY } from '../../enum/validation';
1920
import { UserService } from '../../user.service';
2021

2122
@Component({
@@ -48,6 +49,12 @@ export class BriefViewComponent implements OnInit, OnDestroy {
4849
this.userService.hasRole(['moderator', 'admin', 'superuser'])
4950
);
5051

52+
get statusSeverity(): string | null {
53+
return this.record?.metadata?.status
54+
? VALIDATION_STATUS_SEVERITY[this.record.metadata.status]
55+
: null;
56+
}
57+
5158
private subscription: Subscription = new Subscription();
5259

5360
ngOnInit(): void {

projects/sonar/src/app/enum/validation.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,11 @@ export enum validation_action {
3030
'REJECT' = 'reject',
3131
'ASK_FOR_CHANGES' = 'ask_for_changes'
3232
}
33+
34+
export const VALIDATION_STATUS_SEVERITY: Record<string, string> = {
35+
[validation_status.IN_PROGRESS]: 'primary',
36+
[validation_status.TO_VALIDATE]: 'info',
37+
[validation_status.ASK_FOR_CHANGES]: 'warn',
38+
[validation_status.VALIDATED]: 'success',
39+
[validation_status.REJECTED]: 'danger'
40+
};

projects/sonar/src/app/record/project/brief-view/brief-view.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ <h5>
2121
</h5>
2222
<div class="ui:flex ui:gap-1">
2323
<p-tag [value]="record.metadata.organisation.name" />
24-
@if(record.metadata?.validation?.status !== validationStatus.VALIDATED) {
25-
<p-tag severity="warn" [value]="'This record is not published' | translate" />
24+
@if(validationSeverity) {
25+
<p-tag [severity]="validationSeverity" [value]="record.metadata.validation.status | translate" />
2626
}
2727
</div>
2828
<span>

projects/sonar/src/app/record/project/brief-view/brief-view.component.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,13 @@
1616
*/
1717
import { Component } from '@angular/core';
1818
import { ResultItem } from '@rero/ng-core';
19-
import { validation_status } from '../../../enum/validation';
19+
import { VALIDATION_STATUS_SEVERITY } from '../../../enum/validation';
2020

2121
@Component({
2222
templateUrl: './brief-view.component.html',
2323
standalone: false
2424
})
2525
export class BriefViewComponent implements ResultItem {
26-
// Constant for validation status.
27-
readonly validationStatus = validation_status;
28-
2926
// Record data.
3027
record: any;
3128

@@ -34,4 +31,10 @@ export class BriefViewComponent implements ResultItem {
3431

3532
// Detail URL object.
3633
detailUrl: { link: string, external: boolean };
34+
35+
get validationSeverity(): string | null {
36+
return this.record?.metadata?.validation?.status
37+
? VALIDATION_STATUS_SEVERITY[this.record.metadata.validation.status]
38+
: null;
39+
}
3740
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
<!--
2+
SONAR User Interface
3+
Copyright (C) 2021 RERO
4+
5+
This program is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU Affero General Public License as published by
7+
the Free Software Foundation, version 3 of the License.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Affero General Public License for more details.
13+
14+
You should have received a copy of the GNU Affero General Public License
15+
along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
-->
17+
@if(validation && user && (isModerator() || isOwner())) {
18+
<p-panel [header]="'Validation' | translate">
19+
<div class="ui:flex ui:flex-col ui:gap-2 ui:justify-center ui:p-2">
20+
@if(validation.status === validationStatus.IN_PROGRESS || validation.status === validationStatus.ASK_FOR_CHANGES) {
21+
<p-message class="ui:w-full" severity="warn" showTransitionOptions="0ms">
22+
{{ "The record is currently in status \"\{\{ status \}\}\"." | translate: { status: (validation.status) | translate } }}
23+
@if(isOwner()) {
24+
&nbsp;<a href="#" class="alert-link" (click)="$event.preventDefault(); updateValidation(validationAction.PUBLISH)" translate>
25+
Submit it
26+
</a>.
27+
}
28+
</p-message>
29+
}
30+
@if(validation.status === validationStatus.TO_VALIDATE) {
31+
<p-message class="ui:w-full" severity="warn" showTransitionOptions="0ms">
32+
{{"The record is in validation. It will be reviewed by a moderator before publishing." | translate}}
33+
</p-message>
34+
}
35+
@if(validation.status === validationStatus.REJECTED) {
36+
<p-message class="ui:w-full" severity="error" showTransitionOptions="0ms">
37+
{{ "The record has been rejected after a review from a moderator." | translate}}
38+
</p-message>
39+
}
40+
@if(validation.status === validationStatus.VALIDATED) {
41+
<p-message class="ui:w-full" severity="success" showTransitionOptions="0ms">
42+
{{ "The record is published." | translate }}
43+
</p-message>
44+
45+
}
46+
@if(validation.status === validationStatus.TO_VALIDATE && isModerator()) {
47+
<textarea
48+
#comment
49+
class="ui:min-w-lg ui:my-4"
50+
pTextarea
51+
[autoResize]="true"
52+
[placeholder]="'Leave a comment...' | translate"
53+
></textarea>
54+
<div class="ui:flex ui:justify-center">
55+
<p-buttongroup class="ui:mx-auto">
56+
<p-button
57+
size="large"
58+
severity="success"
59+
(onClick)="updateValidation(validationAction.APPROVE)"
60+
[label]="'Approve' | translate"
61+
/>
62+
<p-button
63+
size="large"
64+
severity="warn"
65+
(onClick)="updateValidation(validationAction.ASK_FOR_CHANGES)"
66+
[label]="'Ask for changes' | translate"
67+
/>
68+
<p-button
69+
size="large"
70+
severity="danger"
71+
(onClick)="updateValidation(validationAction.REJECT)"
72+
[label]="'Reject' | translate"
73+
/>
74+
</p-buttongroup>
75+
</div>
76+
}
77+
@if(validation.logs) {
78+
<p-button
79+
[text]="true"
80+
[label]="(showLogs ? 'Hide logs' : 'Show logs') | translate"
81+
(onClick)="showLogs = !showLogs"
82+
/>
83+
@if(showLogs) {
84+
<p-table [value]="validation.logs" [tableStyle]="{ 'min-width': '50rem' }">
85+
<ng-template #header>
86+
<tr>
87+
<th translate>Status</th>
88+
<th translate>Date</th>
89+
<th translate>User</th>
90+
<th translate>Comment</th>
91+
</tr>
92+
</ng-template>
93+
<ng-template #body let-log>
94+
<tr>
95+
<td>{{ (log.status) | translate }}</td>
96+
<td>{{ log.date | dateTranslate: 'medium' }}</td>
97+
<td>{{ log.user.name }}</td>
98+
<td [innerHtml]="log.comment | nl2br"></td>
99+
</tr>
100+
</ng-template>
101+
</p-table>
102+
}
103+
}
104+
</div>
105+
</p-panel>
106+
}

0 commit comments

Comments
 (0)