,
- private readonly router: Router
+ private router: Router
) {
this.dataSource = dataSourceBuilder.create(this.data, this.getters);
}
@@ -53,7 +54,6 @@ export class ObjectiveTableComponent implements OnInit {
untilDestroyed(this)
).subscribe({
next: (pentests: Pentest[]) => {
- // ToDo: Change assignement here
this.pentests$.next(pentests);
this.data = transformPentestsToObjectiveEntries(pentests);
this.dataSource.setData(this.data, this.getters);
@@ -66,16 +66,14 @@ export class ObjectiveTableComponent implements OnInit {
});
}
- selectPentest(selectedPentest: Pentest): void {
- /* ToDo: Include again after fixing pentest route
- this.router.navigate([Route.PENTEST])
+ onClickRouteToObjectivePentest(selectedPentest: Pentest): void {
+ this.router.navigate([Route.PENTEST_OBJECTIVE])
.then(
() => this.store.reset({
...this.store.snapshot(),
- // [PROJECT_STATE_NAME]: pentest
})
).finally();
- */
+ // Change Pentest State
const statePentest: Pentest = this.pentests$.getValue().find(pentest => pentest.refNumber === selectedPentest.refNumber);
if (statePentest) {
this.store.dispatch(new ChangePentest(statePentest));
@@ -111,5 +109,5 @@ enum ObjectiveColumns {
TEST_ID = 'testId',
TITLE = 'title',
STATUS = 'status',
- FINDINGS = 'findings'
+ FINDINGS_AND_COMMENTS = 'findings&comments'
}
diff --git a/security-c4po-angular/src/app/pentest/pentest-content/pentest-comments/pentest-comments.component.html b/security-c4po-angular/src/app/pentest/pentest-content/pentest-comments/pentest-comments.component.html
index a53374e..ec1cb2f 100644
--- a/security-c4po-angular/src/app/pentest/pentest-content/pentest-comments/pentest-comments.component.html
+++ b/security-c4po-angular/src/app/pentest/pentest-content/pentest-comments/pentest-comments.component.html
@@ -39,7 +39,7 @@
0; else NoRelatedFindings">
-
+
{{ 'comment.no.relatedFindings' | translate }}
diff --git a/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.html b/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.html
index 3ed76ee..9195082 100644
--- a/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.html
+++ b/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.html
@@ -9,7 +9,7 @@
+ badgeText="{{currentNumberOfComments$.getValue()}}" badgeStatus="control">
diff --git a/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.ts b/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.ts
index f692de9..2117c49 100644
--- a/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.ts
+++ b/security-c4po-angular/src/app/pentest/pentest-content/pentest-content.component.ts
@@ -7,6 +7,8 @@ import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy';
import {Pentest} from '@shared/models/pentest.model';
import {PentestService} from '@shared/services/api/pentest.service';
import {NotificationService} from '@shared/services/toaster-service/notification.service';
+import {Router} from '@angular/router';
+import {Route} from '@shared/models/route.enum';
@UntilDestroy()
@Component({
@@ -25,6 +27,7 @@ export class PentestContentComponent implements OnInit {
constructor(
private readonly pentestService: PentestService,
private notificationService: NotificationService,
+ private router: Router,
private store: Store) {
}
@@ -33,11 +36,15 @@ export class PentestContentComponent implements OnInit {
untilDestroyed(this)
).subscribe({
next: (selectedPentest: Pentest) => {
- this.pentest$.next(selectedPentest);
- const findings = selectedPentest.findingIds ? selectedPentest.findingIds.length : 0;
- this.currentNumberOfFindings$.next(findings);
- const comments = selectedPentest.commentIds ? selectedPentest.commentIds.length : 0;
- this.currentNumberOfComments$.next(comments);
+ if (selectedPentest) {
+ this.pentest$.next(selectedPentest);
+ const findings = selectedPentest.findingIds ? selectedPentest.findingIds.length : 0;
+ this.currentNumberOfFindings$.next(findings);
+ const comments = selectedPentest.commentIds ? selectedPentest.commentIds.length : 0;
+ this.currentNumberOfComments$.next(comments);
+ } else {
+ this.router.navigate([Route.PROJECT_OVERVIEW]);
+ }
},
error: err => {
console.error(err);
diff --git a/security-c4po-angular/src/app/pentest/pentest-header/pentest-header.component.ts b/security-c4po-angular/src/app/pentest/pentest-header/pentest-header.component.ts
index 68d1ac9..d8a32ee 100644
--- a/security-c4po-angular/src/app/pentest/pentest-header/pentest-header.component.ts
+++ b/security-c4po-angular/src/app/pentest/pentest-header/pentest-header.component.ts
@@ -79,7 +79,7 @@ export class PentestHeaderComponent implements OnInit {
onClickRouteBack(): void {
// ToDo: Change to Objective Overview after routing is fixed
- this.router.navigate([Route.PROJECT_OVERVIEW])
+ this.router.navigate([Route.OBJECTIVE_OVERVIEW])
.then(
() => {
this.store.dispatch(new ChangePentest(null));
diff --git a/security-c4po-angular/src/app/pentest/pentest-routing.module.ts b/security-c4po-angular/src/app/pentest/pentest-routing.module.ts
index e46ee7e..ec2a531 100644
--- a/security-c4po-angular/src/app/pentest/pentest-routing.module.ts
+++ b/security-c4po-angular/src/app/pentest/pentest-routing.module.ts
@@ -1,12 +1,7 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
-import {PentestComponent} from './pentest.component';
const routes: Routes = [
- {
- path: '',
- component: PentestComponent
- },
];
@NgModule({
diff --git a/security-c4po-angular/src/app/project-overview/project-overview-routing.module.ts b/security-c4po-angular/src/app/project-overview/project-overview-routing.module.ts
index 2618199..1f9a77b 100644
--- a/security-c4po-angular/src/app/project-overview/project-overview-routing.module.ts
+++ b/security-c4po-angular/src/app/project-overview/project-overview-routing.module.ts
@@ -1,14 +1,10 @@
import { NgModule } from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
-import {ProjectOverviewComponent} from './project-overview.component';
+import {Route} from '@shared/models/route.enum';
const routes: Routes = [
{
- path: '',
- component: ProjectOverviewComponent,
- },
- {
- path: 'id',
+ path: Route.OBJECTIVE_OVERVIEW,
loadChildren: () => import('./project').then(mod => mod.ProjectModule),
}
];
diff --git a/security-c4po-angular/src/app/project-overview/project-overview.component.html b/security-c4po-angular/src/app/project-overview/project-overview.component.html
index 2cbcc18..be1d742 100644
--- a/security-c4po-angular/src/app/project-overview/project-overview.component.html
+++ b/security-c4po-angular/src/app/project-overview/project-overview.component.html
@@ -5,13 +5,13 @@
routerLink="id"
fragment="{{project.id}}"
class="project-link project-header"
- [state]="{selectedProject:project}">
+ (click)="onClickRouteToProject(project)">
{{project?.title}}
+ (click)="onClickRouteToProject(project)">
diff --git a/security-c4po-angular/src/app/project-overview/project-overview.component.ts b/security-c4po-angular/src/app/project-overview/project-overview.component.ts
index cefc269..9865178 100644
--- a/security-c4po-angular/src/app/project-overview/project-overview.component.ts
+++ b/security-c4po-angular/src/app/project-overview/project-overview.component.ts
@@ -9,6 +9,10 @@ import {catchError, filter, mergeMap, switchMap, tap} from 'rxjs/operators';
import {DialogService} from '@shared/services/dialog-service/dialog.service';
import {ProjectDialogComponent} from '@shared/modules/project-dialog/project-dialog.component';
import {ProjectDialogService} from '@shared/modules/project-dialog/service/project-dialog.service';
+import {Router} from '@angular/router';
+import {Route} from '@shared/models/route.enum';
+import {InitProjectState} from '@shared/stores/project-state/project-state.actions';
+import {Store} from '@ngxs/store';
@UntilDestroy()
@Component({
@@ -25,6 +29,8 @@ export class ProjectOverviewComponent implements OnInit {
constructor(
private readonly notificationService: NotificationService,
+ private store: Store,
+ private router: Router,
private projectService: ProjectService,
private dialogService: DialogService,
private projectDialogService: ProjectDialogService) {
@@ -163,6 +169,18 @@ export class ProjectOverviewComponent implements OnInit {
}
}
+ onClickRouteToProject(project): void {
+ this.router.navigate([Route.OBJECTIVE_OVERVIEW]).then(() => {
+ this.store.dispatch(new InitProjectState(
+ project,
+ [],
+ []
+ )).pipe(untilDestroyed(this)).subscribe();
+ }, err => {
+ console.error(err);
+ });
+ }
+
// HTML only
isLoading(): Observable {
return this.loading$.asObservable();
diff --git a/security-c4po-angular/src/app/project-overview/project-overview.module.ts b/security-c4po-angular/src/app/project-overview/project-overview.module.ts
index bc89afd..c30838a 100644
--- a/security-c4po-angular/src/app/project-overview/project-overview.module.ts
+++ b/security-c4po-angular/src/app/project-overview/project-overview.module.ts
@@ -11,6 +11,7 @@ import {ProjectDialogModule} from '@shared/modules/project-dialog/project-dialog
import {CommonAppModule} from '../common-app.module';
import {ConfirmDialogModule} from '@shared/modules/confirm-dialog/confirm-dialog.module';
import {SecurityConfirmDialogModule} from '@shared/modules/security-confirm-dialog/security-confirm-dialog.module';
+import {RouterModule} from '@angular/router';
@NgModule({
declarations: [
@@ -20,6 +21,10 @@ import {SecurityConfirmDialogModule} from '@shared/modules/security-confirm-dial
imports: [
CommonModule,
CommonAppModule,
+ RouterModule.forChild([{
+ path: '',
+ component: ProjectOverviewComponent
+ }]),
NbCardModule,
NbButtonModule,
NbProgressBarModule,
diff --git a/security-c4po-angular/src/app/project-overview/project/project-routing.module.ts b/security-c4po-angular/src/app/project-overview/project/project-routing.module.ts
index 820ac2c..5972e2c 100644
--- a/security-c4po-angular/src/app/project-overview/project/project-routing.module.ts
+++ b/security-c4po-angular/src/app/project-overview/project/project-routing.module.ts
@@ -1,14 +1,10 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
-import {ProjectComponent} from './project.component';
+import {Route} from '@shared/models/route.enum';
const routes: Routes = [
{
- path: '',
- component: ProjectComponent
- },
- {
- path: 'pentest',
+ path: Route.PENTEST_OBJECTIVE,
loadChildren: () => import('../../pentest').then(mod => mod.PentestModule),
},
];
diff --git a/security-c4po-angular/src/app/project-overview/project/project.component.ts b/security-c4po-angular/src/app/project-overview/project/project.component.ts
index b121c95..4ace5fb 100644
--- a/security-c4po-angular/src/app/project-overview/project/project.component.ts
+++ b/security-c4po-angular/src/app/project-overview/project/project.component.ts
@@ -1,9 +1,9 @@
import {Component, OnInit} from '@angular/core';
import {Store} from '@ngxs/store';
-import {InitProjectState} from '@shared/stores/project-state/project-state.actions';
import {Router} from '@angular/router';
-import {Route} from '@shared/models/route.enum';
import {UntilDestroy, untilDestroyed} from '@ngneat/until-destroy';
+import {Route} from '@shared/models/route.enum';
+import {ProjectState} from '@shared/stores/project-state/project-state';
import {Project} from '@shared/models/project.model';
@UntilDestroy()
@@ -20,19 +20,23 @@ export class ProjectComponent implements OnInit {
}
ngOnInit(): void {
- if (history?.state && 'selectedProject' in history?.state) {
- this.initProjectStore();
- } else {
- this.router.navigate([Route.PROJECT_OVERVIEW]).finally();
- }
+ this.store.select(ProjectState.project).pipe(
+ untilDestroyed(this)
+ ).subscribe({
+ next: (selectedProject: Project) => {
+ this.initProjectStore();
+ },
+ error: err => {
+ console.error(err);
+ }
+ });
}
private initProjectStore(): void {
- const project: Project = history?.state?.selectedProject ? history?.state?.selectedProject : null;
- this.store.dispatch(new InitProjectState(
- project,
- [],
- []
- )).pipe(untilDestroyed(this)).subscribe();
+ this.router.navigate([Route.OBJECTIVE_OVERVIEW]).then(() => {
+ }, err => {
+ this.router.navigate([Route.PROJECT_OVERVIEW]);
+ console.error(err);
+ });
}
}
diff --git a/security-c4po-angular/src/assets/i18n/de-DE.json b/security-c4po-angular/src/assets/i18n/de-DE.json
index fa93e35..3937b6d 100644
--- a/security-c4po-angular/src/assets/i18n/de-DE.json
+++ b/security-c4po-angular/src/assets/i18n/de-DE.json
@@ -216,6 +216,7 @@
"title": "Titel",
"findings": "Funde",
"comments": "Kommentare",
+ "findings&comments": "Funde & Kommentare",
"status": "Status",
"statusText": {
"not_started": "Nicht angefangen",
diff --git a/security-c4po-angular/src/assets/i18n/en-US.json b/security-c4po-angular/src/assets/i18n/en-US.json
index 3a38877..a5d3455 100644
--- a/security-c4po-angular/src/assets/i18n/en-US.json
+++ b/security-c4po-angular/src/assets/i18n/en-US.json
@@ -216,6 +216,7 @@
"title": "Title",
"findings": "Findings",
"comments": "Comments",
+ "findings&comments": "Findings & Comments",
"status": "Status",
"statusText": {
"not_started": "Not Started",
diff --git a/security-c4po-angular/src/shared/functions/calculate-percentage.ts b/security-c4po-angular/src/shared/functions/calculate-percentage.ts
new file mode 100644
index 0000000..5b24cb5
--- /dev/null
+++ b/security-c4po-angular/src/shared/functions/calculate-percentage.ts
@@ -0,0 +1,11 @@
+import {Loading, LoadingState} from '@shared/models/loading.model';
+
+export function calculatePercentage(download: Loading, event): Loading {
+ return {
+ progress: event.total
+ ? Math.round((100 * event.loaded) / event.total)
+ : download.progress,
+ state: LoadingState.IN_PROGRESS,
+ content: null
+ };
+}
diff --git a/security-c4po-angular/src/shared/functions/download-file.function.ts b/security-c4po-angular/src/shared/functions/download-file.function.ts
index 43e6f03..3900f08 100644
--- a/security-c4po-angular/src/shared/functions/download-file.function.ts
+++ b/security-c4po-angular/src/shared/functions/download-file.function.ts
@@ -8,6 +8,7 @@ export function downloadFile(data: any, type: string): void {
const url = window.URL.createObjectURL(blob);
const pwa = window.open(url);
if (!pwa || pwa.closed || typeof pwa.closed === 'undefined') {
- alert('Please disable your Pop-up blocker and try again.');
+ // ToDo: Do not use! Alert bugs loading progress bar
+ // alert('Please disable your Pop-up blocker and try again.');
}
}
diff --git a/security-c4po-angular/src/shared/functions/load-content.ts b/security-c4po-angular/src/shared/functions/load-content.ts
new file mode 100644
index 0000000..f7d48c2
--- /dev/null
+++ b/security-c4po-angular/src/shared/functions/load-content.ts
@@ -0,0 +1,49 @@
+import {HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse} from '@angular/common/http';
+import {Observable} from 'rxjs';
+import {distinctUntilChanged, scan} from 'rxjs/operators';
+import {calculatePercentage} from '@shared/functions/calculate-percentage';
+import {Loading, LoadingState} from '@shared/models/loading.model';
+
+function isHttpResponse(event: HttpEvent): event is HttpResponse {
+ return event.type === HttpEventType.Response;
+}
+
+function isHttpProgressEvent(
+ event: HttpEvent
+): event is HttpProgressEvent {
+ return (
+ event.type === HttpEventType.DownloadProgress ||
+ event.type === HttpEventType.UploadProgress
+ );
+}
+
+export function loadContent(
+ media?: (b: T) => void
+): (source: Observable>) => Observable> {
+ return (source: Observable>) =>
+ source.pipe(
+ scan(
+ (download: Loading, event): Loading => {
+ if (isHttpProgressEvent(event)) {
+ return calculatePercentage(download, event);
+ }
+ if (isHttpResponse(event)) {
+ if (media) {
+ media(event.body);
+ }
+ return {
+ progress: 100,
+ state: LoadingState.DONE,
+ content: event.body
+ };
+ }
+ return download;
+ },
+ {state: LoadingState.PENDING, progress: 0, content: null}
+ ),
+ distinctUntilChanged((a, b) => a.state === b.state
+ && a.progress === b.progress
+ && a.content === b.content
+ )
+ );
+}
diff --git a/security-c4po-angular/src/shared/models/loading.model.ts b/security-c4po-angular/src/shared/models/loading.model.ts
new file mode 100644
index 0000000..7207bf6
--- /dev/null
+++ b/security-c4po-angular/src/shared/models/loading.model.ts
@@ -0,0 +1,11 @@
+export class Loading {
+ content?: T | null;
+ progress: number;
+ state: LoadingState;
+}
+
+export enum LoadingState {
+ PENDING = 'PENDING',
+ IN_PROGRESS = 'IN_PROGRESS',
+ DONE = 'DONE'
+}
diff --git a/security-c4po-angular/src/shared/models/pentest.model.ts b/security-c4po-angular/src/shared/models/pentest.model.ts
index 9f36c16..0673585 100644
--- a/security-c4po-angular/src/shared/models/pentest.model.ts
+++ b/security-c4po-angular/src/shared/models/pentest.model.ts
@@ -63,6 +63,7 @@ export function transformPentestsToObjectiveEntries(pentests: Pentest[]): Object
refNumber: value.refNumber,
status: value.status,
findings: value.findingIds ? value.findingIds.length : 0,
+ comments: value.commentIds ? value.commentIds.length : 0,
kind: value.childEntries ? 'dir' : 'cell',
childEntries: value.childEntries ? value.childEntries : null,
expanded: !!value.childEntries
diff --git a/security-c4po-angular/src/shared/models/route.enum.ts b/security-c4po-angular/src/shared/models/route.enum.ts
index ed0ce6c..eedc634 100644
--- a/security-c4po-angular/src/shared/models/route.enum.ts
+++ b/security-c4po-angular/src/shared/models/route.enum.ts
@@ -1,5 +1,8 @@
export enum Route {
+ LOGIN = 'login',
HOME = 'home',
PROJECT_OVERVIEW = 'projects',
+ OBJECTIVE_OVERVIEW = 'project/objectives',
+ PENTEST_OBJECTIVE = 'project/objectives/pentest',
PENTEST_OVERVIEW = 'pentest'
}
diff --git a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.html b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.html
index 1c2130b..9debb2f 100644
--- a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.html
+++ b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.html
@@ -8,11 +8,12 @@
{{ 'global.project' | translate }}:
- {{selectedProject$.getValue()?.title}}
+ {{dialogData.options[0].additionalData.title}}
-
+
{{'popup.info' | translate}} {{ 'report.hint' | translate: this.completedProjectPentests$?.getValue() }}
@@ -64,4 +65,4 @@
-
+
diff --git a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.spec.ts b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.spec.ts
index 4c9d806..4640d90 100644
--- a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.spec.ts
+++ b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.spec.ts
@@ -82,7 +82,7 @@ describe('ExportReportDialogComponent', () => {
TestBed.overrideProvider(NB_DIALOG_CONFIG, {useValue: mockedExportPentestDialogData});
fixture = TestBed.createComponent(ExportReportDialogComponent);
component = fixture.componentInstance;
- component.selectedProject$.next(mockProject);
+ component.selectedEvaluatedProject$.next(mockProject);
fixture.detectChanges();
});
diff --git a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.ts b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.ts
index c2cf810..f8570d8 100644
--- a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.ts
+++ b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.component.ts
@@ -10,8 +10,10 @@ import {BehaviorSubject, Observable} from 'rxjs';
import {NotificationService, PopupType} from '@shared/services/toaster-service/notification.service';
import {ProjectService} from '@shared/services/api/project.service';
import {PentestStatus} from '@shared/models/pentest-status.model';
-import {tap} from 'rxjs/operators';
+import {shareReplay, tap} from 'rxjs/operators';
import {downloadFile} from '@shared/functions/download-file.function';
+import {Loading, LoadingState} from '@shared/models/loading.model';
+import {HttpEvent, HttpEventType} from '@angular/common/http';
@Component({
selector: 'app-export-report-dialog',
@@ -41,10 +43,14 @@ export class ExportReportDialogComponent implements OnInit {
dialogData: GenericDialogData;
- selectedProject$: BehaviorSubject = new BehaviorSubject(null);
+ selectedEvaluatedProject$: BehaviorSubject = new BehaviorSubject(null);
completedProjectPentests$: BehaviorSubject = new BehaviorSubject({completedObjectivesNumber: 0});
loading$: BehaviorSubject = new BehaviorSubject(true);
+ // Loading Bar Property
+ downloadPentestReport$: Observable>;
+ progress = 0;
+
ngOnInit(): void {
this.dialogData = this.data;
this.loadEvaluatedProject();
@@ -61,7 +67,7 @@ export class ExportReportDialogComponent implements OnInit {
)
.subscribe({
next: (project: Project) => {
- this.selectedProject$.next(project);
+ this.selectedEvaluatedProject$.next(project);
const completedPentestObjectives = project.projectPentests.filter(pentest => pentest.status === PentestStatus.COMPLETED);
this.completedProjectPentests$.next({completedObjectivesNumber: completedPentestObjectives.length});
this.loading$.next(false);
@@ -75,18 +81,26 @@ export class ExportReportDialogComponent implements OnInit {
}
onClickExport(reportFormat: string, reportLanguage: string): void {
+ // Get project id from dialog data
+ const projectId = this.dialogData.options[0].additionalData.id;
// Loading is true as long as there is a response from the reporting service
this.loading$.next(true);
// Export pentest in choosen format
switch (reportFormat) {
case ExportFormatOptions.PDF: {
- this.reportingService.getReportPDFforProjectById(this.selectedProject$.getValue().id).pipe(
- untilDestroyed(this)
- ).subscribe({
+ // @ts-ignore
+ this.downloadPentestReport$ = this.reportingService.getReportPDFforProjectById(projectId)
+ .pipe(
+ shareReplay(),
+ untilDestroyed(this)
+ );
+ this.downloadPentestReport$.subscribe({
next: (response) => {
- downloadFile(response, 'application/pdf');
- this.loading$.next(false);
- this.notificationService.showPopup('report.popup.generation.success', PopupType.SUCCESS);
+ if (response.state === LoadingState.DONE) {
+ downloadFile(response.content, 'application/pdf');
+ this.loading$.next(false);
+ this.notificationService.showPopup('report.popup.generation.success', PopupType.SUCCESS);
+ }
},
error: error => {
console.error(error);
diff --git a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.module.ts b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.module.ts
index 3e94bc2..5f7ac8f 100644
--- a/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.module.ts
+++ b/security-c4po-angular/src/shared/modules/export-report-dialog/export-report-dialog.module.ts
@@ -10,25 +10,27 @@ import {ExportReportDialogComponent} from '@shared/modules/export-report-dialog/
import {ExportReportDialogService} from '@shared/modules/export-report-dialog/service/export-report-dialog.service';
import {ReportingService} from '@shared/services/reporting/reporting.service';
import {ObjectiveChartModule} from '@shared/modules/objective-chart/objective-chart.module';
+import {LoadingBarModule} from '@shared/widgets/loading-bar/loading-bar.module';
@NgModule({
declarations: [
ExportReportDialogComponent
],
- imports: [
- CommonModule,
- CommonAppModule,
- NbCardModule,
- NbButtonModule,
- NbFormFieldModule,
- NbInputModule,
- FlexLayoutModule,
- FontAwesomeModule,
- TranslateModule,
- ReactiveFormsModule,
- NbRadioModule,
- ObjectiveChartModule
- ],
+ imports: [
+ CommonModule,
+ CommonAppModule,
+ NbCardModule,
+ NbButtonModule,
+ NbFormFieldModule,
+ NbInputModule,
+ FlexLayoutModule,
+ FontAwesomeModule,
+ TranslateModule,
+ ReactiveFormsModule,
+ NbRadioModule,
+ ObjectiveChartModule,
+ LoadingBarModule
+ ],
providers: [
ExportReportDialogService,
ReportingService
diff --git a/security-c4po-angular/src/shared/services/reporting/reporting.service.ts b/security-c4po-angular/src/shared/services/reporting/reporting.service.ts
index 1d04fe8..b61468a 100644
--- a/security-c4po-angular/src/shared/services/reporting/reporting.service.ts
+++ b/security-c4po-angular/src/shared/services/reporting/reporting.service.ts
@@ -1,7 +1,9 @@
import {Injectable} from '@angular/core';
import {environment} from '../../../environments/environment';
-import {HttpClient} from '@angular/common/http';
-import {Observable} from 'rxjs';
+import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
+import {BehaviorSubject, Observable} from 'rxjs';
+import {Loading} from '@shared/models/loading.model';
+import { loadContent } from '@shared/functions/load-content';
@Injectable({
providedIn: 'root'
@@ -16,8 +18,31 @@ export class ReportingService {
/**
* Get PDF Report by project id
*/
+ public getReportPDFforProjectById(projectId: string): Observable> {
+ return this.http.get(`${this.reportBaseURL}/${projectId}/pdf`,
+ {
+ // @ts-ignore
+ responseType: 'arraybuffer',
+ reportProgress: true,
+ observe: 'events'
+ }
+ ).pipe(loadContent());
+ }
+
+ /* ToDo: Remove report function without observing report progress
public getReportPDFforProjectById(projectId: string): Observable {
// @ts-ignore
return this.http.get(`${this.reportBaseURL}/${projectId}/pdf`, {responseType: 'arraybuffer'})
- }
+ }*/
+}
+
+export interface ReportDownloadConfiguration {
+ options: {
+ headers: HttpHeaders;
+ params: HttpParams;
+ observe: 'events';
+ reportProgress: true;
+ responseType: 'arraybuffer';
+ withCredentials?: boolean;
+ };
}
diff --git a/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.html b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.html
new file mode 100644
index 0000000..0589e8f
--- /dev/null
+++ b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.html
@@ -0,0 +1,9 @@
+
diff --git a/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.scss b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.scss
new file mode 100644
index 0000000..4431b1e
--- /dev/null
+++ b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.scss
@@ -0,0 +1,14 @@
+@import '../../../assets/@theme/styles/themes';
+
+.comment-widget {
+ align-items: center;
+
+ .comment-icon {
+ color: nb-theme(basic-text-color);
+ }
+
+ .comments-count {
+ margin-left: 0.45rem;
+ color: nb-theme(basic-text-color);
+ }
+}
diff --git a/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.spec.ts b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.spec.ts
new file mode 100644
index 0000000..8f9873a
--- /dev/null
+++ b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.spec.ts
@@ -0,0 +1,31 @@
+import {ComponentFixture, TestBed} from '@angular/core/testing';
+
+import {CommentWidgetComponent} from './comment-widget.component';
+import {FontAwesomeTestingModule} from '@fortawesome/angular-fontawesome/testing';
+
+describe('CommentWidgetComponent', () => {
+ let component: CommentWidgetComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [
+ CommentWidgetComponent
+ ],
+ imports: [
+ FontAwesomeTestingModule
+ ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CommentWidgetComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.ts b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.ts
new file mode 100644
index 0000000..800f86b
--- /dev/null
+++ b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.component.ts
@@ -0,0 +1,20 @@
+import {Component, Input, OnInit} from '@angular/core';
+import * as FA from '@fortawesome/free-solid-svg-icons';
+
+@Component({
+ selector: 'app-comment-widget',
+ templateUrl: './comment-widget.component.html',
+ styleUrls: ['./comment-widget.component.scss']
+})
+export class CommentWidgetComponent implements OnInit {
+ @Input() numberOfComments: number;
+
+ // HTML only
+ readonly fa = FA;
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.module.ts b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.module.ts
new file mode 100644
index 0000000..b966531
--- /dev/null
+++ b/security-c4po-angular/src/shared/widgets/comment-widget/comment-widget.module.ts
@@ -0,0 +1,20 @@
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
+import {CommentWidgetComponent} from '@shared/widgets/comment-widget/comment-widget.component';
+
+
+@NgModule({
+ declarations: [
+ CommentWidgetComponent
+ ],
+ imports: [
+ CommonModule,
+ FontAwesomeModule
+ ],
+ exports: [
+ CommentWidgetComponent
+ ]
+})
+export class CommentWidgetModule {
+}
diff --git a/security-c4po-angular/src/shared/widgets/findig-widget/findig-widget.component.html b/security-c4po-angular/src/shared/widgets/findig-widget/findig-widget.component.html
index 2e1bd5e..4c6de06 100644
--- a/security-c4po-angular/src/shared/widgets/findig-widget/findig-widget.component.html
+++ b/security-c4po-angular/src/shared/widgets/findig-widget/findig-widget.component.html
@@ -1,7 +1,7 @@
|