Skip to content

Commit e5c05e2

Browse files
committed
Merge remote-tracking branch 'origin/backlog/compliance-evaluation' into backlog/compliance-evaluation
2 parents db38d2c + 06e9990 commit e5c05e2

19 files changed

Lines changed: 359 additions & 51 deletions

frontend/src/app/compliance/compliance-latest-evaluations-view/compliance-latest-evaluation-view-detail/compliance-latest-evaluation-view-detail.component.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

frontend/src/app/compliance/compliance-latest-evaluations-view/compliance-latest-evaluations-view.component.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
Output
1111
} from '@angular/core';
1212
import {EMPTY, Observable, Subject} from 'rxjs';
13-
import {catchError, distinctUntilChanged, filter, map, switchMap, takeUntil, tap} from 'rxjs/operators';
13+
import {catchError, filter, map, switchMap, takeUntil, tap} from 'rxjs/operators';
1414
import {UtmToastService} from '../../shared/alert/utm-toast.service';
1515
import {SortEvent} from '../../shared/directives/sortable/type/sort-event';
1616
import {TimezoneFormatService} from '../../shared/services/utm-timezone.service';
@@ -40,10 +40,10 @@ export class ComplianceLatestEvaluationsViewComponent implements OnInit, OnChang
4040
totalItems = 0;
4141
sortEvent: SortEvent = {
4242
column: 'controlName',
43-
direction: 'desc'
43+
direction: 'asc'
4444
};
4545
destroy$: Subject<void> = new Subject();
46-
sort = 'controlName,desc';
46+
sort = 'controlName,asc';
4747
search: string;
4848
viewportHeight: number;
4949
dateFormat$: Observable<DatePipeDefaultOptions>;
@@ -66,14 +66,6 @@ export class ComplianceLatestEvaluationsViewComponent implements OnInit, OnChang
6666
this.controls$ = this.controlsService.onRefresh$
6767
.pipe(
6868
takeUntil(this.destroy$),
69-
distinctUntilChanged((prev, curr) =>
70-
prev &&
71-
curr &&
72-
prev.loading === curr.loading &&
73-
prev.page === curr.page &&
74-
prev.reportSelected === curr.reportSelected &&
75-
prev.sectionId === curr.sectionId
76-
),
7769
filter(reportRefresh =>
7870
!!reportRefresh && reportRefresh.loading
7971
),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
@media print {
3+
.report-loading {
4+
display: none;
5+
}
6+
7+
.compliance {
8+
padding: 15px;
9+
margin: 10px 0;
10+
border: 1px solid #ccc;
11+
background-color: #fff;
12+
box-shadow: none;
13+
}
14+
15+
.compliance-header {
16+
font-size: 1.1rem;
17+
}
18+
19+
.compliance-status, .compliance-time {
20+
font-size: 1rem;
21+
margin-bottom: 8px;
22+
}
23+
24+
.standard-prev {
25+
font-size: 1.4rem;
26+
text-align: center;
27+
font-weight: bold;
28+
}
29+
30+
.font-weight-bold {
31+
font-weight: bold;
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<h3 class="standard-prev text-center mb-4">
2+
<strong>Compliance Assessment</strong>
3+
</h3>
4+
5+
<div *ngFor="let control of controls$ | async" class="report-container mb-4">
6+
<div class="compliance d-print-block border rounded p-4">
7+
<div class="compliance-header mb-3">
8+
<h4 class="text-dark">{{ control.controlName}}</h4>
9+
</div>
10+
11+
<div class="compliance-status mb-3">
12+
<p class="font-weight-bold">Status:</p>
13+
{{ control.lastEvaluationStatus | complianceStatusLabel }}
14+
</div>
15+
16+
<div class="compliance-time mb-3">
17+
<p class="font-weight-bold">Last Evaluation:</p>
18+
<span *ngIf="dateFormat$ | async as dateFormat">
19+
{{ control.lastEvaluationTimestamp | date:dateFormat.dateFormat:dateFormat.timezone }}
20+
</span>
21+
</div>
22+
23+
<div class="compliance mb-3">
24+
<p class="font-weight-bold">Description:</p>
25+
{{ control.controlSolution }}
26+
</div>
27+
</div>
28+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { HttpErrorResponse } from '@angular/common/http';
2+
import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit, Output} from '@angular/core';
3+
import { ActivatedRoute } from '@angular/router';
4+
import {EMPTY, Observable} from 'rxjs';
5+
import {catchError, concatMap, filter, map, tap} from 'rxjs/operators';
6+
import { UtmToastService } from 'src/app/shared/alert/utm-toast.service';
7+
import {TimezoneFormatService} from '../../../../shared/services/utm-timezone.service';
8+
import {DatePipeDefaultOptions} from '../../../../shared/types/date-pipe-default-options';
9+
import {CpControlConfigService} from '../../../shared/services/cp-control-config.service';
10+
import {ComplianceControlLatestEvaluationType} from '../../../shared/type/compliance-control-latest-evaluation.type';
11+
12+
13+
@Component({
14+
selector: 'app-compliance-latest-eval-print-view',
15+
templateUrl: './compliance-latest-eval-print-view.component.html',
16+
styleUrls: ['./compliance-latest-eval-print-view.component.css'],
17+
changeDetection: ChangeDetectionStrategy.OnPush
18+
})
19+
export class ComplianceLatestEvalPrintViewComponent implements OnInit, OnDestroy {
20+
controls$: Observable<ComplianceControlLatestEvaluationType[]>;
21+
dateFormat$: Observable<DatePipeDefaultOptions>;
22+
23+
constructor(private controlsService: CpControlConfigService,
24+
private toastService: UtmToastService,
25+
private route: ActivatedRoute,
26+
private timezoneFormatService: TimezoneFormatService) { }
27+
28+
ngOnInit() {
29+
this.dateFormat$ = this.timezoneFormatService.getDateFormatSubject();
30+
this.controls$ = this.route.queryParams
31+
.pipe(
32+
filter((params) => !!params.section),
33+
map((params) => JSON.parse(decodeURIComponent(params.section))),
34+
concatMap((params) => this.controlsService.fetchData({
35+
page: params.page,
36+
size: params.size,
37+
sectionId: params.id,
38+
sort: params.sort,
39+
})),
40+
map((res) => {
41+
return res.body.map((r, index) => {
42+
return {
43+
...r,
44+
};
45+
});
46+
}),
47+
catchError((err: HttpErrorResponse) => {
48+
this.toastService.showError('Error',
49+
'Unable to retrieve the list of reports. Please try again or contact support.');
50+
return EMPTY;
51+
}));
52+
}
53+
54+
ngOnDestroy(): void {
55+
throw new Error('Method not implemented.');
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<div *ngIf="control">
2+
<h3 class="standard-prev text-center mb-4">
3+
Compliance report: {{ control.controlName }}
4+
</h3>
5+
6+
<div class="report-container mb-4">
7+
<div class="compliance d-print-block border rounded p-4">
8+
<div class="compliance-status mb-3">
9+
<span class="font-weight-bold">Status:</span>
10+
{{ control.lastEvaluationStatus | complianceStatusLabel }}
11+
</div>
12+
13+
<div class="compliance-time mb-3">
14+
<span class="font-weight-bold">Last Evaluation:</span>
15+
<span *ngIf="dateFormat$ | async as dateFormat">
16+
{{ control.lastEvaluationTimestamp | date:dateFormat.dateFormat:dateFormat.timezone }}
17+
</span>
18+
</div>
19+
20+
<div class="compliance mb-3">
21+
<span class="font-weight-bold">Compliance report scope:</span>
22+
<p class="mb-0">{{ control.section.standard.standardName }}</p>
23+
<p class="mb-0">{{ control.section.standard.standardDescription }}</p>
24+
</div>
25+
26+
<div class="compliance mb-3">
27+
<span class="font-weight-bold">Compliance section:</span>
28+
<p class="mb-0">{{ control.section.standardSectionName }}</p>
29+
<p class="mb-0">{{ control.section.standardSectionDescription }}</p>
30+
</div>
31+
32+
<div class="compliance mb-3">
33+
<span class="font-weight-bold">Solution:</span>
34+
<p class="mb-0"> {{ control.controlSolution }} </p>
35+
</div>
36+
37+
<div class="compliance mb-3" *ngIf="control.lastEvaluationStatus === ComplianceStatusExtendedEnum.NON_COMPLIANT">
38+
<span class="font-weight-bold">Remediation:</span>
39+
<p class="mb-0"> {{ control.controlRemediation }} </p>
40+
</div>
41+
</div>
42+
</div>
43+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
@media print {
2+
.report-loading {
3+
display: none;
4+
}
5+
6+
.compliance {
7+
padding: 15px;
8+
margin: 10px 0;
9+
border: 1px solid #ccc;
10+
background-color: #fff;
11+
box-shadow: none;
12+
}
13+
14+
.compliance-header {
15+
font-size: 1.1rem;
16+
}
17+
18+
.compliance-status, .compliance-time {
19+
font-size: 1rem;
20+
margin-bottom: 8px;
21+
}
22+
23+
.standard-prev {
24+
font-size: 1.4rem;
25+
text-align: center;
26+
font-weight: bold;
27+
}
28+
29+
.font-weight-bold {
30+
font-weight: bold;
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {HttpErrorResponse} from '@angular/common/http';
2+
import {Component, OnInit} from '@angular/core';
3+
import {ActivatedRoute} from '@angular/router';
4+
import {EMPTY, Observable} from 'rxjs';
5+
import {catchError} from 'rxjs/operators';
6+
import {UtmToastService} from '../../../../../shared/alert/utm-toast.service';
7+
import {TimezoneFormatService} from '../../../../../shared/services/utm-timezone.service';
8+
import {DatePipeDefaultOptions} from '../../../../../shared/types/date-pipe-default-options';
9+
import {ComplianceStatusExtendedEnum} from '../../../../shared/enums/compliance-status.enum';
10+
import {CpControlConfigService} from '../../../../shared/services/cp-control-config.service';
11+
import {ComplianceControlLatestEvaluationType} from '../../../../shared/type/compliance-control-latest-evaluation.type';
12+
13+
@Component({
14+
selector: 'app-compliance-detail-print-view',
15+
templateUrl: './compliance-latest-eval-detail-print-view.component.html',
16+
styleUrls: ['./compliance-latest-eval-detail-print-view.component.scss']
17+
})
18+
export class ComplianceLatestEvalDetailPrintViewComponent implements OnInit {
19+
reportId: number;
20+
control: ComplianceControlLatestEvaluationType;
21+
dateFormat$: Observable<DatePipeDefaultOptions>;
22+
23+
protected readonly ComplianceStatusExtendedEnum = ComplianceStatusExtendedEnum;
24+
25+
constructor(private activatedRoute: ActivatedRoute,
26+
private cpControlConfigService: CpControlConfigService,
27+
private timezoneFormatService: TimezoneFormatService,
28+
private toastService: UtmToastService) {
29+
}
30+
31+
ngOnInit() {
32+
this.dateFormat$ = this.timezoneFormatService.getDateFormatSubject();
33+
this.activatedRoute.params.subscribe(params => {
34+
this.reportId = params.id;
35+
this.getTemplate();
36+
});
37+
}
38+
39+
getTemplate() {
40+
this.cpControlConfigService.find(this.reportId)
41+
.pipe(
42+
catchError((err: HttpErrorResponse) => {
43+
this.toastService.showError(
44+
'Error',
45+
'Unable to retrieve the report template. Please try again or contact support.'
46+
);
47+
return EMPTY;
48+
})
49+
)
50+
.subscribe(response => {
51+
this.control = response.body;
52+
});
53+
}
54+
55+
}

frontend/src/app/compliance/compliance-latest-evaluations-view/compliance-latest-evaluation-view-detail/compliance-latest-evaluation-view-detail.component.css renamed to frontend/src/app/compliance/compliance-latest-evaluations-view/components/compliance-latest-evaluation-view-detail/compliance-latest-evaluation-view-detail.component.css

File renamed without changes.

frontend/src/app/compliance/compliance-latest-evaluations-view/compliance-latest-evaluation-view-detail/compliance-latest-evaluation-view-detail.component.html renamed to frontend/src/app/compliance/compliance-latest-evaluations-view/components/compliance-latest-evaluation-view-detail/compliance-latest-evaluation-view-detail.component.html

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@
3434
</div>
3535
</div>
3636
<div class="p-3">
37+
<div class="d-flex justify-content-around align-content-center">
38+
<div class="alert-details w-100 d-flex justify-content-start align-items-center">
39+
<span class="text-blue-800 font-weight-light mr-2">Compliance report scope:</span>
40+
</div>
41+
<button (click)="exportToPdf()"
42+
class="btn utm-button utm-button-primary mb-2">
43+
<i class="mr-1 icon-file-pdf"></i>
44+
Save to PDF
45+
</button>
46+
</div>
47+
<div class="alert-details w-100 d-flex justify-content-start align-items-center mb-2">
48+
<p class="font-size-base">{{ control.section.standard.standardName }}</p>
49+
</div>
50+
<div class="alert-details w-100 d-flex justify-content-start align-items-center mb-2">
51+
<app-utm-collapsible-text class="font-size-base" [maxLength]="200" [text]="control.section.standard.standardDescription"></app-utm-collapsible-text>
52+
</div>
53+
3754
<div class="alert-details w-100 d-flex justify-content-start align-items-center mt-3">
3855
<span class="text-blue-800 font-weight-light mr-2">Compliance section:</span>
3956
</div>
@@ -47,7 +64,6 @@
4764
<div class="alert-details w-100 d-flex justify-content-start align-items-center mt-3">
4865
<span class="text-blue-800 font-weight-light mr-2">Compliance report:</span>
4966
</div>
50-
5167
<div class="alert-details w-100 d-flex justify-content-start align-items-center mb-2">
5268
<app-utm-collapsible-text class="font-size-base" [maxLength]="200" [text]="control.controlSolution"></app-utm-collapsible-text>
5369
</div>
@@ -56,7 +72,6 @@
5672
<div class="alert-details w-100 d-flex justify-content-start align-items-center mt-3">
5773
<span class="text-blue-800 font-weight-light mr-2">Compliance remediation:</span>
5874
</div>
59-
6075
<div class="alert-details w-100 d-flex justify-content-start align-items-center mb-2">
6176
<app-utm-collapsible-text class="font-size-base" [maxLength]="200" [text]="control.controlRemediation"></app-utm-collapsible-text>
6277
</div>

0 commit comments

Comments
 (0)