Skip to content

Commit 8a92d20

Browse files
authored
Merge pull request #1318 from utmstack/release/v10.9.2
Release/v10.9.2
2 parents 3d2db6d + 86c2ed0 commit 8a92d20

File tree

41 files changed

+1273
-296
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1273
-296
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
# UTMStack 10.9.0 Release Notes
1+
# UTMStack 10.9.1 Release Notes
22

3-
- Added New Suricata Integration.
3+
-- Dashboard Rendering with Time Filters
4+
Resolved performance issues affecting dashboard responsiveness when applying time-based filters.

frontend/src/app/dashboard/dashboard-overview/dashboard-overview.component.html

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
<div class="container-fluid dashboard-container pr-3 pl-3 pt-2">
1+
<div class="container-fluid dashboard-container px-1 pt-2">
22
<div *ngIf="!pdfExport" class="d-flex justify-content-between align-items-center mb-2">
33
<h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h5>
44
<div class="header-elements d-flex justify-content-end align-items-center">
5+
<app-refresh-filter></app-refresh-filter>
56
<app-elastic-filter-time [invertContent]="true"
67
[isEmitter]="true"
78
container="body"></app-elastic-filter-time>
@@ -20,14 +21,10 @@ <h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h
2021
</div>
2122
<div class="row">
2223
<div class="col-lg-4 col-md-12 col-sm-12">
23-
<app-chart-alert-daily-week [refreshInterval]="refreshInterval"
24-
(loaded)="onRun()">
25-
</app-chart-alert-daily-week>
24+
<app-chart-alert-daily-week (loaded)="onRun()"></app-chart-alert-daily-week>
2625
</div>
2726
<div class="col-lg-8 col-md-12 col-sm-12">
28-
<app-chart-alert-by-status [refreshInterval]="refreshInterval"
29-
(loaded)="onRun()">
30-
</app-chart-alert-by-status>
27+
<app-chart-alert-by-status (loaded)="onRun()"></app-chart-alert-by-status>
3128
</div>
3229
</div>
3330

@@ -39,8 +36,8 @@ <h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h
3936
[navigateUrl]="ALERT_ROUTE"
4037
[paramClick]="paramAlertSeverityCLick"
4138
[params]="paramsAlertSeverity"
42-
(loaded)="onRun()"
43-
[refreshInterval]="refreshInterval">
39+
[type]="RefreshType.CHART_COMMON_PIE_SEVERITY"
40+
(loaded)="onRun()">
4441
</app-chart-common-pie>
4542
</div>
4643
<div class="col-lg-5 col-md-12 col-sm-12">
@@ -54,8 +51,8 @@ <h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h
5451
[navigateUrl]="ALERT_ROUTE"
5552
[paramClick]="tableTopAlertsParamsClick"
5653
[params]="tableTopAlertsParams"
57-
(loaded)="onRun()"
58-
[refreshInterval]="refreshInterval">
54+
[type]="RefreshType.CHART_COMMON_TABLE_TOP_ALERT"
55+
(loaded)="onRun()">
5956
</app-chart-common-table>
6057
</div>
6158
</div>
@@ -74,10 +71,10 @@ <h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h
7471
[paramClick]="paramEventByTypeCLick"
7572
[params]="paramsEventByType"
7673
(loaded)="onRun()"
77-
[refreshInterval]="refreshInterval"></app-chart-common-pie>
74+
[type]="RefreshType.CHART_COMMON_PIE_EVENT"></app-chart-common-pie>
7875
</div>
7976
<div class="col-lg-5 col-md-12 col-sm-12">
80-
<app-chart-event-in-time [refreshInterval]="refreshInterval"
77+
<app-chart-event-in-time [type]="RefreshType.CHART_EVENT_IN_TIME"
8178
(loaded)="onRun()"></app-chart-event-in-time>
8279
</div>
8380
<div class="col-lg-4 col-md-12 col-sm-12">
@@ -86,8 +83,8 @@ <h5 class="card-title label-header mb-0 text-uppercase label-header">Overview</h
8683
[navigateUrl]="LOG_ANALYZER_ROUTE"
8784
[paramClick]="paramEvenTopCLick"
8885
[params]="paramsTopEvent"
89-
(loaded)="onRun()"
90-
[refreshInterval]="refreshInterval">
86+
[type]="RefreshType.CHART_COMMON_TABLE_TOP_EVENT"
87+
(loaded)="onRun()">
9188
</app-chart-common-table>
9289
</div>
9390
</div>

frontend/src/app/dashboard/dashboard-overview/dashboard-overview.component.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {OverviewAlertDashboardService} from '../../shared/services/charts-overvi
2323
import {IndexPatternService} from '../../shared/services/elasticsearch/index-pattern.service';
2424
import {LocalFieldService} from '../../shared/services/elasticsearch/local-field.service';
2525
import {ExportPdfService} from '../../shared/services/util/export-pdf.service';
26+
import {RefreshService, RefreshType} from '../../shared/services/util/refresh.service';
2627
import {ChartSerieValueType} from '../../shared/types/chart-reponse/chart-serie-value.type';
2728
import {ElasticFilterType} from '../../shared/types/filter/elastic-filter.type';
2829
import {UtmIndexPatternFields} from '../../shared/types/index-pattern/utm-index-pattern-fields';
@@ -66,9 +67,6 @@ export class DashboardOverviewComponent implements OnInit, OnDestroy {
6667
indexPattern: IndexPatternSystemEnumName.LOG
6768
};
6869
paramEvenTopCLick = 'logx.wineventlog.event_name.keyword';
69-
70-
adActive: boolean;
71-
vulActive: boolean;
7270
alertSeverityColorMap: { value: string, color: string }[] = [
7371
{color: '#42A5F5', value: LOW_TEXT},
7472
{color: '#FF9800', value: MEDIUM_TEXT},
@@ -81,6 +79,8 @@ export class DashboardOverviewComponent implements OnInit, OnDestroy {
8179
runList = 0;
8280
visualizationRender = 8;
8381
preparingPrint = true;
82+
RefreshType = RefreshType;
83+
timeOutId: any;
8484

8585

8686
constructor(private overviewAlertDashboardService: OverviewAlertDashboardService,
@@ -92,7 +92,8 @@ export class DashboardOverviewComponent implements OnInit, OnDestroy {
9292
private exportPdfService: ExportPdfService,
9393
private activatedRoute: ActivatedRoute,
9494
private timeFilterBehavior: TimeFilterBehavior,
95-
private utmToastService: UtmToastService) {
95+
private utmToastService: UtmToastService,
96+
private refreshService: RefreshService) {
9697
}
9798

9899
ngOnInit() {
@@ -129,7 +130,7 @@ export class DashboardOverviewComponent implements OnInit, OnDestroy {
129130
// }
130131
// });
131132

132-
setTimeout(() => {
133+
this.timeOutId = setTimeout(() => {
133134
this.synchronizeFields();
134135
}, 100000);
135136

@@ -266,6 +267,7 @@ export class DashboardOverviewComponent implements OnInit, OnDestroy {
266267
ngOnDestroy(): void {
267268
this.destroy$.next();
268269
this.destroy$.complete();
270+
this.refreshService.stopInterval();
271+
clearTimeout(this.timeOutId);
269272
}
270-
271273
}

frontend/src/app/dashboard/dashboard-render/dashboard-render.component.html

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ <h5 class="card-title mb-0 label-header">{{dashboard.name}}
44
</h5>
55
<div class="header-elements d-flex justify-content-end align-items-center">
66
<app-dashboard-filter-view [filters]="filters"></app-dashboard-filter-view>
7+
<app-refresh-filter></app-refresh-filter>
78
<app-elastic-filter-time [invertContent]="true"
89
[isEmitter]="true"
9-
class="ml-3"
1010
container="body"></app-elastic-filter-time>
11-
<button (click)="exportToPdf()" [disabled]="pdfExport || !visualizationRender || loadingVisualizations"
11+
<button (click)="exportToPdf()" [disabled]="pdfExport || loadingVisualizations"
1212
class="btn utm-button utm-button-primary ml-2">
1313
<i [ngClass]="pdfExport?'icon-download10':'icon-file-pdf'" class="mr-1"></i>
1414
{{pdfExport ? 'Generating...' : 'Save to PDF'}}
@@ -17,21 +17,20 @@ <h5 class="card-title mb-0 label-header">{{dashboard.name}}
1717
</div>
1818
</div>
1919
<div class="w-100 h-100 mb-3">
20-
<gridster *ngIf="layout.length>0 && !loadingVisualizations"
21-
[options]="options" style="background-color: #f1f1f1;z-index: 0; margin-bottom: 15px">
20+
<gridster [options]="options" style="background-color: #f1f1f1;z-index: 0; margin-bottom: 15px">
2221
<gridster-item #gridsterItem
23-
*ngFor="let item of layout; let index = index" [item]="item.grid"
22+
*ngFor="let item of layout$ | async; trackBy: trackByFn; let index = index" [item]="item.grid"
2423
(mouseenter)="activeTimeGridster=item.visualization.id"
2524
[ngStyle]="{'z-index':(activeTimeGridster===item.visualization.id?100:0)+''}">
26-
<app-utm-viewer [building]="false"
27-
style="z-index: 10"
28-
[chart]="item.visualization.chartType"
29-
[chartId]="item.visualization.id"
30-
[height]="(gridsterItem.height-38)+'px'"
31-
[showTime]="timeEnable.includes(item.visualization.id)"
32-
[visualization]="item.visualization"
33-
[width]="gridsterItem.width+'px'">
34-
</app-utm-viewer>
25+
<app-utm-viewer [building]="false"
26+
style="z-index: 10"
27+
[chart]="item.visualization.chartType"
28+
[chartId]="item.visualization.id"
29+
[height]="(gridsterItem.height-38)+'px'"
30+
[showTime]="item.visualization.showTime"
31+
[visualization]="item.visualization"
32+
[width]="gridsterItem.width+'px'">
33+
</app-utm-viewer>
3534
</gridster-item>
3635
</gridster>
3736
<div style="height: 15px"></div>

frontend/src/app/dashboard/dashboard-render/dashboard-render.component.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import {AfterViewInit, ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
2-
import {ActivatedRoute} from '@angular/router';
3-
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
1+
import {AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit} from '@angular/core';
2+
import {ActivatedRoute, Router} from '@angular/router';
43
import {CompactType, GridsterConfig, GridsterItem, GridType} from 'angular-gridster2';
54
import {UUID} from 'angular2-uuid';
5+
import {NgxSpinnerService} from 'ngx-spinner';
6+
import {Observable} from 'rxjs';
7+
import {map, tap} from 'rxjs/operators';
68
import {IComponent} from '../../graphic-builder/dashboard-builder/shared/services/layout.service';
79
import {rebuildVisualizationFilterTime} from '../../graphic-builder/shared/util/chart-filter/chart-filter.util';
810
import {DashboardBehavior} from '../../shared/behaviors/dashboard.behavior';
@@ -11,20 +13,20 @@ import {UtmDashboardVisualizationType} from '../../shared/chart/types/dashboard/
1113
import {UtmDashboardType} from '../../shared/chart/types/dashboard/utm-dashboard.type';
1214
import {VisualizationType} from '../../shared/chart/types/visualization.type';
1315
import {ChartTypeEnum} from '../../shared/enums/chart-type.enum';
16+
import {ExportPdfService} from '../../shared/services/util/export-pdf.service';
17+
import {RefreshService} from '../../shared/services/util/refresh.service';
1418
import {DashboardFilterType} from '../../shared/types/filter/dashboard-filter.type';
1519
import {ElasticFilterType} from '../../shared/types/filter/elastic-filter.type';
1620
import {mergeParams, sanitizeFilters} from '../../shared/util/elastic-filter.util';
1721
import {filtersToStringParam} from '../../shared/util/query-params-to-filter.util';
1822
import {normalizeString} from '../../shared/util/string-util';
1923
import {RenderLayoutService} from '../shared/services/render-layout.service';
20-
import {UtmRenderVisualization} from '../shared/services/utm-render-visualization.service';
21-
import {ExportPdfService} from "../../shared/services/util/export-pdf.service";
22-
import {NgxSpinnerService} from "ngx-spinner";
2324

2425
@Component({
2526
selector: 'app-dashboard-render',
2627
templateUrl: './dashboard-render.component.html',
27-
styleUrls: ['./dashboard-render.component.scss']
28+
styleUrls: ['./dashboard-render.component.scss'],
29+
changeDetection: ChangeDetectionStrategy.OnPush
2830
})
2931
export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewInit {
3032
dashboardId: number;
@@ -59,25 +61,37 @@ export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewIni
5961
swap: false
6062
};
6163
filtersValues: ElasticFilterType[] = [];
62-
timeEnable: number[] = [];
64+
layout$: Observable<{ grid: GridsterItem, visualization: VisualizationType } []>;
6365

6466
constructor(private activatedRoute: ActivatedRoute,
6567
private layoutService: RenderLayoutService,
6668
private cdr: ChangeDetectorRef,
67-
private modalService: NgbModal,
6869
private dashboardBehavior: DashboardBehavior,
6970
private timeFilterBehavior: TimeFilterBehavior,
70-
private utmRenderVisualization: UtmRenderVisualization,
7171
private exportPdfService: ExportPdfService,
72-
private spinner: NgxSpinnerService) {
72+
private spinner: NgxSpinnerService,
73+
private refreshService: RefreshService,
74+
private router: Router) {
7375
}
7476

7577
ngOnInit() {
76-
console.log('Init dashboard');
77-
7878
document.body.classList.add('overflow-hidden');
7979
this.loadingVisualizations = true;
80-
this.activatedRoute.params.subscribe(params => {
80+
this.layout$ = this.activatedRoute.data
81+
.pipe(
82+
tap((visualizations) => {
83+
this.dashboard = this.layoutService.dashboard;
84+
this.filters = this.dashboard && this.dashboard.filters ? JSON.parse(this.dashboard.filters) : [];
85+
/* if (this.dashboard.refreshTime) {
86+
console.log(this.dashboard.refreshTime);
87+
this.onRefreshTime(this.dashboard.refreshTime);
88+
}*/
89+
this.loadingVisualizations = false;
90+
}),
91+
map(data => data.response)
92+
);
93+
94+
/*this.activatedRoute.params.subscribe(params => {
8195
this.dashboardId = params.id;
8296
if (this.dashboardId) {
8397
const request = {
@@ -105,14 +119,15 @@ export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewIni
105119
this.loadingVisualizations = false;
106120
});
107121
}
108-
});
122+
});*/
109123
this.dashboardBehavior.$filterDashboard.subscribe(dashboardFilter => {
110124
if (dashboardFilter) {
111125
mergeParams(dashboardFilter.filter, this.filtersValues).then(newFilters => {
112126
this.filtersValues = sanitizeFilters(newFilters);
113127
});
114128
}
115129
});
130+
116131
this.timeFilterBehavior.$time.subscribe(time => {
117132
if (time) {
118133
rebuildVisualizationFilterTime({timeFrom: time.from, timeTo: time.to}, this.filtersValues).then(filters => {
@@ -146,9 +161,7 @@ export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewIni
146161
ngOnDestroy(): void {
147162
document.body.classList.remove('overflow-hidden');
148163
clearInterval(this.interval);
149-
this.visualizationRender = [];
150-
this.layoutService.layout = [];
151-
this.timeEnable = [];
164+
this.layoutService.clearLayout();
152165
this.dashboardBehavior.$filterDashboard.next(null);
153166
}
154167

@@ -164,7 +177,7 @@ export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewIni
164177
exportToPdf() {
165178
filtersToStringParam(this.filtersValues).then(queryParams => {
166179
this.spinner.show('buildPrintPDF');
167-
const url = '/dashboard/export/' + this.dashboardId + '/' + normalizeString(this.dashboard.name) + '?' + queryParams;
180+
const url = '/dashboard/export/' + this.dashboard.id + '/' + normalizeString(this.dashboard.name) + '?' + queryParams;
168181
// window.open('/dashboard/export/' + this.dashboardId + '/' + normalizeString(this.dashboard.name) + '?' + queryParams, '_blank');
169182
this.exportPdfService.getPdf(url, this.dashboard.name, 'PDF_TYPE_TOKEN').subscribe(response => {
170183
this.spinner.hide('buildPrintPDF').then(() =>
@@ -175,5 +188,9 @@ export class DashboardRenderComponent implements OnInit, OnDestroy, AfterViewIni
175188
});
176189
});
177190
}
191+
192+
trackByFn(index: number, item: { grid: GridsterItem, visualization: VisualizationType }) {
193+
return item.visualization.id;
194+
}
178195
}
179196

frontend/src/app/dashboard/dashboard-routing.module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {DashboardOverviewComponent} from './dashboard-overview/dashboard-overvie
1010
import {DashboardRenderComponent} from './dashboard-render/dashboard-render.component';
1111
import {DashboardViewComponent} from './dashboard-view/dashboard-view.component';
1212
import {ReportExportComponent} from './report-export/report-export.component';
13+
import {DashboardResolverService} from './shared/services/dashboard-resolver.service';
1314

1415
const routes: Routes = [
1516
{path: '', redirectTo: 'overview', pathMatch: 'full'},
@@ -35,7 +36,10 @@ const routes: Routes = [
3536
path: 'render/:id/:dashboard',
3637
component: DashboardRenderComponent,
3738
canActivate: [UserRouteAccessService],
38-
data: {authorities: [USER_ROLE, ADMIN_ROLE]}
39+
data: {authorities: [USER_ROLE, ADMIN_ROLE]},
40+
resolve: {
41+
response: DashboardResolverService
42+
}
3943
},
4044
{
4145
path: 'export/:id/:dashboard',

frontend/src/app/dashboard/dashboard.module.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {DashboardRoutingModule} from './dashboard-routing.module';
1919
import {DashboardViewComponent} from './dashboard-view/dashboard-view.component';
2020
import {ReportExportComponent} from './report-export/report-export.component';
2121
import {UtmDashboardSharedModule} from './shared/utm-dashboard-shared.module';
22+
import {DashboardResolverService} from "./shared/services/dashboard-resolver.service";
2223

2324
@NgModule({
2425
declarations: [DashboardViewComponent,
@@ -43,6 +44,9 @@ import {UtmDashboardSharedModule} from './shared/utm-dashboard-shared.module';
4344
VulnerabilitySharedModule,
4445
GridsterModule
4546
],
47+
providers: [
48+
DashboardResolverService
49+
],
4650
entryComponents: [DashboardExportPreviewComponent],
4751
exports: [
4852
DashboardViewComponent

0 commit comments

Comments
 (0)