Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import { NotyService } from '../../../../../layouts/coreui/noty.service';
import { BadgeOutlineComponent } from '../../../../../layouts/coreui/badge-outline/badge-outline.component';

import { IntervalPickerComponent } from '../../../../../components/interval-picker/interval-picker.component';
import _ from 'lodash';

@Component({
selector: 'oitc-customalerts-index',
Expand Down Expand Up @@ -250,13 +251,18 @@ export class CustomalertsIndexComponent implements OnInit, OnDestroy, IndexPage
}

if (filterstring && filterstring.length > 0) {
//cnditions to apply old bookmarks
this.cdr.markForCheck();
//conditions to apply old bookmarks
const bookmarkfilter = JSON.parse(filterstring);
let filter: CustomAlertsIndexFilter = getDefaultCustomAlertsIndexFilter();
filter.Customalerts.message = bookmarkfilter.Customalerts.message || '';
filter.Customalerts.state = bookmarkfilter.Customalerts.state || [true, true, false, false];
filter.Hosts.container_id = bookmarkfilter.Hosts.container_id || [];
filter.Hosts.name = bookmarkfilter.Hosts.name || '';
filter.Customalerts.message = bookmarkfilter.Customalerts?.message || '';
filter.Customalerts.state = bookmarkfilter.Customalerts?.state || [true, true, false, false];

filter.Hosts.container_id = bookmarkfilter.Hosts?.container_id.filter((containerId: number) => {
return _.find(this.containers, {key: containerId});
}) || [];

filter.Hosts.name = bookmarkfilter.Hosts?.name || '';
filter.servicename = bookmarkfilter.servicename || '';
filter.recursive = bookmarkfilter.recursive || false;
this.setFilterAndLoad(filter);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { EventcorrelationsSummaryWidgetComponent } from './eventcorrelations-summary-widget.component';

describe('EventcorrelationsSummaryWidgetComponent', () => {
let component: EventcorrelationsSummaryWidgetComponent;
let fixture: ComponentFixture<EventcorrelationsSummaryWidgetComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [EventcorrelationsSummaryWidgetComponent]
})
.compileComponents();

fixture = TestBed.createComponent(EventcorrelationsSummaryWidgetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
import {
ColComponent,
FormCheckComponent,
FormCheckInputDirective,
FormCheckLabelDirective,
FormControlDirective,
InputGroupComponent,
InputGroupTextDirective,
RowComponent,
TextColorDirective
} from '@coreui/angular';
import { BaseWidgetComponent } from '../../../../pages/dashboards/widgets/base-widget/base-widget.component';
import { KtdGridLayout, KtdResizeEnd } from '@katoid/angular-grid-layout';
import { FaIconComponent, FaStackComponent, FaStackItemSizeDirective } from '@fortawesome/angular-fontawesome';

import { TranslocoDirective, TranslocoPipe } from '@jsverse/transloco';
import { AnimationEvent } from '@angular/animations';
import { EventcorrelationsSummaryWidgetService } from './eventcorrelations-summary-widget.service';

import { EvcTreeDirection } from '../../pages/eventcorrelations/eventcorrelations-view/evc-tree/evc-tree.enum';
import { EvcsSummary, EventcorrelationsSummaryWidgetConfig } from './eventcorrelations-summary-widget.interface';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { XsButtonDirective } from '../../../../layouts/coreui/xsbutton-directive/xsbutton.directive';
import {
AfterViewInit,
ChangeDetectionStrategy,
Component,
effect,
ElementRef,
inject,
signal,
ViewChild
} from '@angular/core';
import { GenericValidationError } from '../../../../generic-responses';
import { SelectKeyValue } from '../../../../layouts/primeng/select.interface';
import { NotyService } from '../../../../layouts/coreui/noty.service';
import { NgSelectComponent } from '@ng-select/ng-select';
import { MultiSelectComponent } from '../../../../layouts/primeng/multi-select/multi-select/multi-select.component';
import {
RegexHelperTooltipComponent
} from '../../../../layouts/coreui/regex-helper-tooltip/regex-helper-tooltip.component';
import { HostgroupsLoadHostgroupsByStringParams } from '../../../../pages/hostgroups/hostgroups.interface';
import { HostgroupsService } from '../../../../pages/hostgroups/hostgroups.service';
import { ServicegroupsService } from '../../../../pages/servicegroups/servicegroups.service';
import _ from 'lodash';
import { NgClass } from '@angular/common';
import {
EvcServicestatusToasterService
} from '../../pages/eventcorrelations/eventcorrelations-view/evc-tree/evc-servicestatus-toaster/evc-servicestatus-toaster.service';
import {
EvcServicestatusToasterComponent
} from '../../pages/eventcorrelations/eventcorrelations-view/evc-tree/evc-servicestatus-toaster/evc-servicestatus-toaster.component';


@Component({
selector: 'oitc-evencorrelations-summary-widget',
imports: [
FaIconComponent,
TranslocoDirective,
XsButtonDirective,
ColComponent,
ReactiveFormsModule,
RowComponent,
FormsModule,
FormCheckComponent,
FormCheckLabelDirective,
NgSelectComponent,
TranslocoPipe,
InputGroupComponent,
InputGroupTextDirective,
FaStackComponent,
MultiSelectComponent,
FaStackItemSizeDirective,
FormControlDirective,
FormCheckInputDirective,
RegexHelperTooltipComponent,
NgClass,
EvcServicestatusToasterComponent,
TextColorDirective
],
templateUrl: './eventcorrelations-summary-widget.component.html',
styleUrl: './eventcorrelations-summary-widget.component.css',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EventcorrelationsSummaryWidgetComponent extends BaseWidgetComponent implements AfterViewInit {

protected flipped = signal<boolean>(false);
@ViewChild('boxContainer') boxContainer?: ElementRef;
public widgetHeight: number = 0;

public show: boolean = true;


private readonly EventcorrelationsSummaryWidgetService = inject(EventcorrelationsSummaryWidgetService);
private readonly EvcServicestatusToasterService = inject(EvcServicestatusToasterService);

public readonly HostgroupsService: HostgroupsService = inject(HostgroupsService);
public readonly ServicegroupsService: ServicegroupsService = inject(ServicegroupsService);
// widget config will be loaded from the server
public config!: EventcorrelationsSummaryWidgetConfig;
public summary!: EvcsSummary[];
protected hostgroups: SelectKeyValue[] = [];
protected servicegroups: SelectKeyValue[] = [];
public configHostKeyWords: string[] = [];
public configHostNotKeyWords: string[] = [];
public configServiceKeyWords: string[] = [];
public configServiceNotKeyWords: string[] = [];
public servicegroupKeywords: string[] = [];
public servicegroupNotKeywords: string[] = [];
public hostgroupKeywords: string[] = [];
public hostgroupNotKeywords: string[] = [];
protected hostgroupsIds: number[] = [];

private readonly notyService = inject(NotyService);
public priorityFilter: { 1: boolean; 2: boolean; 3: boolean; 4: boolean; 5: boolean } = {
1: false,
2: false,
3: false,
4: false,
5: false
};
private toasterTimeout: any = null;

constructor() {
super();
effect(() => {
if (this.flipped()) {
this.loadHostgroups('');
this.loadServicegroups('');
}
this.cdr.markForCheck();
});
}

public override load() {
if (this.widget) {
this.EventcorrelationsSummaryWidgetService.loadWidgetConfig(this.widget.id).subscribe((response: any) => {
this.config = response.config;
this.configHostKeyWords = this.config.Host.keywords.split(',').filter(Boolean);
this.configHostNotKeyWords = this.config.Host.not_keywords.split(',').filter(Boolean);
this.configServiceKeyWords = this.config.Service.keywords.split(',').filter(Boolean);
this.configServiceNotKeyWords = this.config.Service.not_keywords.split(',').filter(Boolean);
this.hostgroupKeywords = this.config.Hostgroup.keywords.split(',').filter(Boolean);
this.hostgroupNotKeywords = this.config.Hostgroup.not_keywords.split(',').filter(Boolean);
this.servicegroupKeywords = this.config.Servicegroup.keywords.split(',').filter(Boolean);
this.servicegroupNotKeywords = this.config.Servicegroup.not_keywords.split(',').filter(Boolean);
this.summary = response.summary;

_.map(this.config.servicepriority,
(value) => {
if (this.priorityFilter.hasOwnProperty(value)) {
this.priorityFilter[value as keyof typeof this.priorityFilter] = true;
}
}
);

this.cdr.markForCheck();
});
}
}

public ngAfterViewInit(): void {
//this.calcEvcHeight();
}

protected loadHostgroups = (search: string) => {
let hostgroupIds: number[] = [];
if (this.config?.Hostgroup._ids) {
hostgroupIds = this.config.Hostgroup._ids;
}
this.subscriptions.add(this.HostgroupsService.loadHostgroupsByString({
'filter[Containers.name]': search,
'selected[]': hostgroupIds
} as HostgroupsLoadHostgroupsByStringParams).subscribe((data: SelectKeyValue[]) => {
this.hostgroups = data;
this.cdr.markForCheck();
}));
}

protected loadServicegroups = (search: string) => {
let servicegroupIds: number[] = [];
if (this.config?.Servicegroup._ids) {
servicegroupIds = this.config.Servicegroup._ids;
}
this.subscriptions.add(this.ServicegroupsService.loadServicegroupsByString({
'filter[Containers.name]': search,
'selected[]': servicegroupIds
} as HostgroupsLoadHostgroupsByStringParams).subscribe((data: SelectKeyValue[]) => {
this.servicegroups = data;
this.cdr.markForCheck();
}));
}


public override onAnimationStart(event: AnimationEvent) {


super.onAnimationStart(event);
}


public override onAnimationDone(event: AnimationEvent) {
super.onAnimationDone(event);

if (!event.toState) {
// "false" means show content.

// We have to remove the EVC from the DOM and re-add
// otherwise the lines are not drawn correctly
this.show = true;
this.cdr.markForCheck();
} else {
// "true" means show config.
// The animation has stopped, and we are in the config view - so we can now remove the EVC from the DOM
// We hide the EVC case if we flip back to the content, the EVC is messed up and needs to be re-rendered
this.show = false;
this.cdr.markForCheck();
}
}

private calcEvcHeight() {
this.widgetHeight = this.boxContainer?.nativeElement.offsetHeight;

let height = this.widgetHeight - 29 - 12; //Unit: px
// ^ Show / Hide Config button
// ^ Some Padding

if (height < 15) {
height = 15;
}

this.widgetHeight = height;
this.cdr.markForCheck();
}

public resetHandler($event: EvcTreeDirection) {
this.show = false;
this.cdr.markForCheck();
setTimeout(() => {
this.show = true;
this.cdr.markForCheck();
}, 100);
}

public saveConfig() {
if (this.widget) {


// Close config
this.flipped.set(false);
}
}

public submit() {
if (!this.widget || !this.config) {
return;
}

this.config.Host.keywords = this.configHostKeyWords.join(',');
this.config.Host.not_keywords = this.configHostNotKeyWords.join(',');
this.config.Service.keywords = this.configServiceKeyWords.join(',');
this.config.Service.not_keywords = this.configServiceNotKeyWords.join(',');
this.config.Hostgroup.keywords = this.hostgroupKeywords.join(',');
this.config.Hostgroup.not_keywords = this.hostgroupNotKeywords.join(',');
this.config.Servicegroup.keywords = this.servicegroupKeywords.join(',');
this.config.Servicegroup.not_keywords = this.servicegroupNotKeywords.join(',');

this.config.servicepriority = [];
_.map(this.priorityFilter,
(value, key) => {
if (value) {
this.config.servicepriority.push(Number(key));
}
}
);

this.subscriptions.add(this.EventcorrelationsSummaryWidgetService.saveWidgetConfig(this.widget.id, this.config)
.subscribe({
next: (result) => {
this.cdr.markForCheck();
const title = this.TranslocoService.translate('Success');
const msg = this.TranslocoService.translate('Data saved successfully');

this.notyService.genericSuccess(msg, title);
this.notyService.scrollContentDivToTop();
this.load();
this.flipped.set(false);

return;
},
// Error
error: (error) => {
const errorResponse = error as GenericValidationError;
this.notyService.genericError();
}
}));

}

public override ngOnDestroy() {
super.ngOnDestroy();
}

public override resizeWidget(event?: KtdResizeEnd) {
this.calcEvcHeight();
}

public override layoutUpdate(event: KtdGridLayout) {

}

public toggleToaster(serviceId: number | undefined): void {
this.cancelToaster();
if (serviceId) {
this.toasterTimeout = setTimeout(() => {
this.EvcServicestatusToasterService.setServiceIdToaster(serviceId);
}, 500);
}
}

public cancelToaster() {
if (this.toasterTimeout) {
clearTimeout(this.toasterTimeout);
}

this.toasterTimeout = null;
}

protected readonly Number = Number;
protected readonly alert = alert;
}
Loading