Skip to content
This repository has been archived by the owner on Sep 30, 2022. It is now read-only.

feat: Added statistics #246

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gui/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
"style": "scss"
}
},
"architect": {
Expand Down
337 changes: 273 additions & 64 deletions gui/package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions gui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
"@fortawesome/free-solid-svg-icons": "5.15.4",
"@ngx-translate/core": "14.0.0",
"@ngx-translate/http-loader": "7.0.0",
"@swimlane/ngx-charts": "^20.0.1",
"angular-bootstrap-md": "12.2.0",
"bootstrap": "4.6.1",
"chart.js": "^3.7.0",
"core-js": "3.20.3",
"eslint": "8.8.0",
"font-awesome": "4.7.0",
Expand Down
7 changes: 7 additions & 0 deletions gui/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ import {NotAuthorizedPageComponent} from './shared/not-authorized-page/not-autho
import {LoginComponent} from './login/login.component';
import {DocumentSignComponent} from './document-sign/document-sign.component';
import {ToolsComponent} from './tools/tools.component';
import {
FacilitiesServicesListComponent
} from "./statistics/facilities-services-list/facilities-services-list.component";

const routes: Routes = [

{
path: '',
component: LoginComponent,
},
{
path: 'services',
component: FacilitiesServicesListComponent,
},
{
path: 'auth',
component: MainMenuComponent,
Expand Down
5 changes: 5 additions & 0 deletions gui/src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
{{'MENU.HOME' | translate}}
</a>
</li>
<li class="nav-item menu-item-l2" [class.active]="currentUrl !== undefined && currentUrl === '/services'">
<a class="no-hover-decoration" routerLink="/services">
{{'MENU.STATISTICS' | translate}}
</a>
</li>
<ng-container *ngIf="hasUser() && getUser().isAppAdmin">
<li class="nav-item menu-spacer admin-spacer menu-item-l1">
{{'MENU.ADMIN' | translate}}
Expand Down
34 changes: 32 additions & 2 deletions gui/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {APP_INITIALIZER, NgModule} from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand All @@ -20,11 +20,29 @@ import {AttributeValuePipe} from './attribute-value.pipe';
import {DocumentSignItemLocalePipe} from "./document-sign-item-locale.pipe";
import {LanguageEntryPipe} from "./language-entry.pipe";
import { HammerModule} from '@angular/platform-browser';
import { NgxChartsModule } from '@swimlane/ngx-charts';
import {StatisticsModule} from "./statistics/statistics.module";
import {ConfService} from "./shared/conf-service";
import {map} from "rxjs";

export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

function initialize(http: HttpClient, config: ConfService) {
return (): Promise<boolean> => {
return new Promise<boolean>((resolve: (a: boolean) => void): void => {
http.get('/assets/config/config.json')
.pipe(
map((x: ConfService) => {
config.statisticsDisplayedAttributes = x.statisticsDisplayedAttributes;
resolve(true);
})
).subscribe();
});
};
}

@NgModule({
declarations: [
AppComponent,
Expand Down Expand Up @@ -54,8 +72,20 @@ export function HttpLoaderFactory(http: HttpClient) {
MatDialogModule,
MatTabsModule,
HammerModule,
StatisticsModule,
NgxChartsModule
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initialize,
deps: [
HttpClient,
ConfService
],
multi: true
}
],
providers: [ ],
bootstrap: [AppComponent]
})
export class AppModule {}
30 changes: 30 additions & 0 deletions gui/src/app/core/models/ProvidedServiceOverview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export class ProvidedServiceOverview {
constructor(item: any) {
if (!item) {
return;
}

this.name = new Map<string, string>();
if (item.hasOwnProperty('description') && item.name !== null && item.name !== undefined) {
for (const k of Object.keys(item.name)) {
this.name.set(k.toLowerCase(), item.name[k]);
}
}

this.description = new Map<string, string>();
if (item.hasOwnProperty('description') && item.description !== null && item.description !== undefined) {
for (const k of Object.keys(item.description)) {
this.description.set(k.toLowerCase(), item.description[k]);
}
}

this.protocol = item.protocol;
this.environment = item.environment;
}

name: Map<string, string>;
description: Map<string, string>;
environment: string;
protocol: string;

}
57 changes: 57 additions & 0 deletions gui/src/app/core/models/ProvidedServicesOverview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {ProvidedServiceOverview} from "./ProvidedServiceOverview";

export class ProvidedServicesOverview {
samlServicesCount: Map<string, number>;
oidcServicesCount: Map<string, number>;

productionServices: ProvidedServiceOverview[] = [];
stagingServices: ProvidedServiceOverview[] = [];
testingServices: ProvidedServiceOverview[] = [];

displayableProductionServices = false;
displayableStagingServices = false;
displayableTestingServices = false;

constructor(item: any) {
this.samlServicesCount = new Map<string, number>();
this.oidcServicesCount = new Map<string, number>();
this.productionServices = [];
this.stagingServices = [];
this.testingServices = [];
this.displayableProductionServices = false;
this.displayableStagingServices = false;
this.displayableTestingServices = false;

if (!item) {
return;
}

if (item['samlServicesCount']) {
for (const k of Object.keys(item.samlServicesCount)) {
this.samlServicesCount.set(k, item.samlServicesCount[k]);
}
}

if (item['oidcServicesCount']) {
for (const k of Object.keys(item.oidcServicesCount)) {
this.oidcServicesCount.set(k, item.oidcServicesCount[k]);
}
}

if (item['services'] && item.services['PRODUCTION']) {
this.displayableProductionServices = true;
item.services['PRODUCTION'].map(s => this.productionServices.push(new ProvidedServiceOverview(s)));
}

if (item['services'] && item.services['STAGING']) {
this.displayableStagingServices = true;
item.services['STAGING'].map(s => this.stagingServices.push(new ProvidedServiceOverview(s)));
}

if (item['services'] && item.services['TESTING']) {
this.displayableTestingServices = true;
item.services['TESTING'].map(s => this.testingServices.push(new ProvidedServiceOverview(s)));
}
}

}
4 changes: 4 additions & 0 deletions gui/src/app/core/services/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ export class ConfigService {
getLanguages(): Observable<string[]> {
return this.apiService.get('/config/langs');
}

getEnvironments(): Observable<string[]> {
return this.apiService.get('/config/envs');
}
}
5 changes: 5 additions & 0 deletions gui/src/app/core/services/facilities.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Request } from "../models/Request";
import {PerunAttribute} from "../models/PerunAttribute";
import {LinkCode} from "../models/LinkCode";
import {ProvidedService} from "../models/ProvidedService";
import {ProvidedServicesOverview} from "../models/ProvidedServicesOverview";

@Injectable({
providedIn: 'root'
Expand All @@ -20,6 +21,10 @@ export class FacilitiesService {
return this.apiService.get('/allFacilities');
}

getProvidedServicesOverview(): Observable<ProvidedServicesOverview> {
return this.apiService.get('/services')
}

getAllExternalFacilities(): Observable<ProvidedService[]> {
return this.apiService.get('/allFacilitiesExternal');
}
Expand Down
6 changes: 1 addition & 5 deletions gui/src/app/facilities/facilities.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ import { FacilitiesRoutingModule } from './facilities-routing.module';
import { FacilitiesUserComponent } from './facilities-user/facilities-user.component';
import { SharedModule } from '../shared/shared.module';
import { FacilitiesDetailComponent } from './facilities-detail/facilities-detail.component';
import {FacilitiesAttributeValuePipe} from './facilities-attribute-value.pipe';
import { FacilityMoveToProductionComponent } from './facilities-detail/facility-move-to-production/facility-move-to-production.component';
import { FacilitiesDetailDeleteDialogComponent } from './facilities-detail/facilities-detail-delete-dialog/facilities-detail-delete-dialog.component';
import { FacilityAddAdminComponent } from './facilities-detail/facility-add-admin/facility-add-admin.component';
import { FacilityAddAdminSignComponent } from './facilities-detail/facility-add-admin/facility-add-admin-sign/facility-add-admin-sign.component';
import { FacilitiesAdminComponent } from './facilities-admin/facilities-admin.component';
import { FacilitiesEditComponent } from './facilities-edit/facilities-edit.component';
import {FacilitiesEnvironmentPipe} from './facilities-environment.pipe';
import {MatTabsModule} from '@angular/material/tabs';
import {MatDialogModule} from '@angular/material/dialog';
import {MatPaginatorIntl, MatPaginatorModule} from '@angular/material/paginator';
Expand All @@ -34,7 +32,6 @@ import {FacilitiesRemoveAdminDialogComponent} from "./facilities-detail/faciliti
declarations: [
FacilitiesUserComponent,
FacilitiesDetailComponent,
FacilitiesAttributeValuePipe,
FacilityMoveToProductionComponent,
FacilitiesEditComponent,
FacilityMoveToProductionComponent,
Expand All @@ -43,8 +40,7 @@ import {FacilitiesRemoveAdminDialogComponent} from "./facilities-detail/faciliti
FacilitiesDetailClientSecretDialogComponent,
FacilityAddAdminComponent,
FacilityAddAdminSignComponent,
FacilitiesAdminComponent,
FacilitiesEnvironmentPipe
FacilitiesAdminComponent
],
providers: [
{
Expand Down
3 changes: 3 additions & 0 deletions gui/src/app/main-menu/main-menu.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ <h4>{{'MENU.MAIN' | translate}}</h4>

<ng-container>
<div class="row">
<app-menu-button class="col-sm-12 col-md-6 col-lg-6 col-xl-4 mb-5"
[icon]="statisticsIcon" [route]="'/services'" [text]="'MENU.STATISTICS'">
</app-menu-button>
<app-menu-button class="col-sm-12 col-md-6 col-lg-6 col-xl-4 mb-5"
[icon]="requestsIcon" [route]="'requests/myRequests'" [text]="'MENU.MY_REQUESTS'">
</app-menu-button>
Expand Down
3 changes: 2 additions & 1 deletion gui/src/app/main-menu/main-menu.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Component, OnInit} from '@angular/core';
import {faClipboardList, faNotesMedical, faServer, faToolbox} from '@fortawesome/free-solid-svg-icons';
import {faChartPie, faClipboardList, faNotesMedical, faServer, faToolbox} from '@fortawesome/free-solid-svg-icons';
import {User} from '../core/models/User';
import {AppComponent} from '../app.component';
import {UsersService} from "../core/services/users.service";
Expand All @@ -21,6 +21,7 @@ export class MainMenuComponent implements OnInit {
facilitiesIcon = faServer;
newRequestIcon = faNotesMedical;
toolboxIcon = faToolbox;
statisticsIcon = faChartPie;

ngOnInit() {
this.usersService.getUser().subscribe(user => {
Expand Down
10 changes: 10 additions & 0 deletions gui/src/app/shared/conf-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class ConfService {
"statisticsDisplayedAttributes": string[];

constructor() { }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class FacilitiesEnvironmentPipe implements PipeTransform {

private testEnvText: string = "TEXT";
private prodEnvText: string = "TEXT2";
private stagingEnvText: string = "TEXT3";

constructor(
private translate: TranslateService
Expand All @@ -18,12 +19,16 @@ export class FacilitiesEnvironmentPipe implements PipeTransform {
this.translate.get('FACILITIES.ENV_PROD').subscribe(text => {
this.prodEnvText = text;
});
this.translate.get('FACILITIES.ENV_STAGING').subscribe(text => {
this.stagingEnvText = text;
});
}

transform(env: any, args?: any): any {
switch(env) {
case "TESTING": return this.testEnvText;
case "PRODUCTION": return this.prodEnvText;
case "STAGING": return this.stagingEnvText;
}
}

Expand Down
10 changes: 8 additions & 2 deletions gui/src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import {DetailedViewItemValuePipe} from './detailed-view-item-value.pipe';
import {ItemLocalePipe} from './item-locale.pipe';
import {RequestItemInputErrorComponent} from './request-item-input/request-item-input-error/request-item-input-error.component';
import {RequestInputItemSelectComponent} from "./request-item-input/request-item-input-select/request-input-item-select.component";
import {FacilitiesAttributeValuePipe} from "./facilities-attribute-value.pipe";
import {FacilitiesEnvironmentPipe} from "./facilities-environment.pipe";

@NgModule({
imports: [
Expand Down Expand Up @@ -109,7 +111,9 @@ import {RequestInputItemSelectComponent} from "./request-item-input/request-item
DetailItemSubCommentButtonComponent,
DetailedViewItemValuePipe,
ItemLocalePipe,
AuditTypePipe
AuditTypePipe,
FacilitiesAttributeValuePipe,
FacilitiesEnvironmentPipe
],
exports: [
FontAwesomeModule,
Expand Down Expand Up @@ -154,7 +158,9 @@ import {RequestInputItemSelectComponent} from "./request-item-input/request-item
DetailItemSubCommentButtonComponent,
ItemLocalePipe,
DetailedViewItemValuePipe,
AuditTypePipe
AuditTypePipe,
FacilitiesAttributeValuePipe,
FacilitiesEnvironmentPipe
],
})
export class SharedModule { }
Loading