diff options
Diffstat (limited to 'src/app/modules/alerting')
-rw-r--r-- | src/app/modules/alerting/alert.component.css | 63 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.component.html | 106 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.component.spec.ts | 49 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.component.ts | 138 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.model.ts | 47 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.module.ts | 32 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.service.spec.ts | 93 | ||||
-rw-r--r-- | src/app/modules/alerting/alert.service.ts | 66 | ||||
-rw-r--r-- | src/app/modules/alerting/index.ts | 22 |
9 files changed, 616 insertions, 0 deletions
diff --git a/src/app/modules/alerting/alert.component.css b/src/app/modules/alerting/alert.component.css new file mode 100644 index 0000000..aeadd64 --- /dev/null +++ b/src/app/modules/alerting/alert.component.css @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +span { + width: 500px; +} +.alert-success { + color: #6bb324 !important; +} + +.alert-success > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%236bb324'/%3E%3C/svg%3E") !important; +} +.alert-info { + color: #00a0de !important; +} + +.alert-info > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%2300a0de'/%3E%3C/svg%3E") !important; +} +.alert-warning { + color: #87604e !important; + border-color: #87604e !important; +} + +.alert-warning > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%2387604E'/%3E%3C/svg%3E") !important; +} +.alert-danger { + color: #d90000 !important; +} + +.alert-danger > button.close::before { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M15.81,14.99l-6.99-7l6.99-7c0.24-0.24,0.2-0.63-0.04-0.83c-0.24-0.2-0.59-0.2-0.79,0l-6.99,7l-6.99-7 C0.75-0.08,0.36-0.04,0.16,0.2c-0.2,0.24-0.2,0.59,0,0.79l6.99,7l-6.99,7c-0.24,0.24-0.2,0.63,0.04,0.83c0.24,0.2,0.59,0.2,0.79,0 l6.99-7l6.99,7c0.24,0.24,0.59,0.24,0.83,0.04C16.04,15.66,16.08,15.26,15.81,14.99C15.85,15.03,15.81,15.03,15.81,14.99z' fill='%23d90000'/%3E%3C/svg%3E") !important; +} + +.custom-margin { + margin-right: 20px; +} + +i.bi { + font-size: 22px; +} + +.text-breaking { + word-break: break-word; +} diff --git a/src/app/modules/alerting/alert.component.html b/src/app/modules/alerting/alert.component.html new file mode 100644 index 0000000..157966f --- /dev/null +++ b/src/app/modules/alerting/alert.component.html @@ -0,0 +1,106 @@ +<!-- + ~ Copyright (c) 2022. Deutsche Telekom AG + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~ + ~ SPDX-License-Identifier: Apache-2.0 + --> + + +<div class="d-flex justify-content-center"> + <span> + <ngb-alert *ngFor="let alert of alerts" type="alert" class="{{ cssClass(alert) }}" [dismissible]="false"> + <button + type="button" + class="close" + [attr.aria-label]="'common.buttons.close' | translate" + (click)="removeAlert(alert)" + ></button> + <div class="d-flex text-breaking"> + <i + class="bi custom-margin" + [class.bi-info-circle-fill]="informativeAlerts.includes(alert.type)" + [class.bi-exclamation-triangle-fill]="!informativeAlerts.includes(alert.type)" + aria-hidden="true" + ></i> + + <div *ngIf="alert.type === AlertType.Error"> + <ng-container *ngIf="alert.id === 'keycloak'; else defaultErrorAlert"> + <span>{{ alert.message }}</span> + <ng-container *ngTemplateOutlet="supportTpl"></ng-container> + </ng-container> + </div> + + <div *ngIf="alert.type !== AlertType.Error"> + <span class="text-justify">{{ alert.message }}</span> + <ng-container *ngIf="alert.id === 'onap_logging'"> + <span>{{ 'common.alert.contactSupport.part1' | translate }}</span> + <a [href]="environment.supportUrlLink">{{ 'common.alert.support' | translate }}</a> + </ng-container> + </div> + </div> + + <ng-template #defaultErrorAlert> + <span *ngIf="alert.urlTree">{{ alert.message }}</span> + <span *ngIf="!alert.errorDetail">{{ alert.message }}</span> + <div *ngIf="alert?.errorDetail?.downstreamSystem as downstreamSystem"> + <span *ngIf="downstreamSystem"> + {{ 'common.alert.errorReporter' | translate: { system: 'common.systems.' + downstreamSystem | translate } }} + </span> + </div> + <div *ngIf="alert.errorDetail?.detail as detail"> + "{{ alert.errorDetail?.detail }}" + <div + *ngIf=" + alert.errorDetail?.downstreamSystem === DownstreamSystem.KEYCLOAK && + alert.errorDetail?.downstreamStatus === 409 + " + > + <span *ngIf="detail.split(' ').pop() === 'username'"> + {{ 'common.block.userAdministration.helpUserNameExists' | translate }} + </span> + <span *ngIf="detail.split(' ').pop() === 'email'"> + {{ 'common.block.userAdministration.helpUserEmailExists' | translate }} + </span> + </div> + </div> + <ng-container *ngTemplateOutlet="supportTpl"></ng-container> + </ng-template> + <ng-template #supportTpl> + <div> + {{ 'common.alert.support' | translate }} + <button + class="btn btn-sm p-0" + (click)="collapse.toggle()" + [attr.aria-expanded]="!isCollapsed" + aria-controls="collapseSupportInfo" + > + <i *ngIf="isCollapsed" class="bi bi-chevron-right text-danger" style="font-size: 18px" aria-hidden="true" [attr.aria-label]="'common.buttons.openSupportLink' | translate"></i> + <i *ngIf="!isCollapsed" class="bi bi-chevron-down text-danger" style="font-size: 18px" aria-hidden="true" [attr.aria-label]="'common.buttons.closeSupportLink' | translate"></i> + </button> + </div> + + <div #collapse="ngbCollapse" [(ngbCollapse)]="isCollapsed"> + <span>{{ 'common.alert.contactSupport.part1' | translate }}</span + ><a [href]="environment.supportUrlLink" target="_blank">{{ 'common.alert.support' | translate }}</a> + <ng-container *ngIf="alert?.requestId"> + <span>{{ 'common.alert.contactSupport.part2' | translate }}</span> + <div> + {{ alert?.requestId }} + </div> + </ng-container> + </div> + </ng-template> + </ngb-alert> + </span> +</div> diff --git a/src/app/modules/alerting/alert.component.spec.ts b/src/app/modules/alerting/alert.component.spec.ts new file mode 100644 index 0000000..abaf52e --- /dev/null +++ b/src/app/modules/alerting/alert.component.spec.ts @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { AlertComponent } from './alert.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { Router } from '@angular/router'; + +describe('AlertComponent', () => { + let component: AlertComponent; + let fixture: ComponentFixture<AlertComponent>; + const router = jasmine.createSpyObj('Router', ['navigate']); + beforeEach(async(() => { + TestBed.configureTestingModule({ + providers: [AlertComponent, { provide: Router, useValue: router }], + }).compileComponents(); + fixture = TestBed.createComponent(AlertComponent); + component = fixture.componentInstance; + })); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('Setting value to id properties', () => { + component.id = 'testId'; + fixture.detectChanges(); + }); + it('Setting value to fade properties', () => { + expect(component.fade).toBe(true); + component.fade = false; + fixture.detectChanges(); + }); +}); diff --git a/src/app/modules/alerting/alert.component.ts b/src/app/modules/alerting/alert.component.ts new file mode 100644 index 0000000..91d22f4 --- /dev/null +++ b/src/app/modules/alerting/alert.component.ts @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Component, Input, OnInit } from '@angular/core'; +import { NavigationStart, Router } from '@angular/router'; +import { Subscription } from 'rxjs'; + +import { Alert, AlertType } from './alert.model'; +import { AlertService } from './alert.service'; +import { UnsubscribeService } from 'src/app/services/unsubscribe/unsubscribe.service'; +import { takeUntil } from 'rxjs/operators'; +import { environment } from 'src/environments/environment'; +import { Problem } from '../../../../openapi/output'; +import DownstreamSystemEnum = Problem.DownstreamSystemEnum; + +@Component({ + selector: 'app-alert', + templateUrl: 'alert.component.html', + styleUrls: ['alert.component.css'], + providers: [UnsubscribeService], +}) +export class AlertComponent implements OnInit { + @Input() id = 'default-alert'; + @Input() fade = true; + + isCollapsed = true; + informativeAlerts: AlertType[] = [AlertType.Success, AlertType.Info]; + alerts: Alert[] = []; + alertSubscription!: Subscription; + routeSubscription!: Subscription; + AlertType = AlertType; + environment = environment; + DownstreamSystem = DownstreamSystemEnum; + constructor( + private router: Router, + private alertService: AlertService, + private unsubscribeService: UnsubscribeService, + ) {} + + ngOnInit() { + // subscribe to new alert notifications + this.alertSubscription = this.alertService.alerts + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(alert => { + // clear alerts when an empty alert is received + if (!alert.message) { + // filter out alerts without 'keepAfterRouteChange' flag + this.alerts = this.alerts.filter(x => x.keepAfterRouteChange); + + // remove 'keepAfterRouteChange' flag on the rest + this.alerts.forEach(x => delete x.keepAfterRouteChange); + return; + } + if (this.alerts.filter(a => a.message === alert.message).length === 0) { + // add alert to array + this.alerts.push(alert); + } + // auto close alert if required + if (alert.type === AlertType.Warning) { + setTimeout(() => this.removeAlert(alert), 10000); + } + }); + + // clear alerts on location change + this.routeSubscription = this.router.events + .pipe(takeUntil(this.unsubscribeService.unsubscribe$)) + .subscribe(event => { + if (event instanceof NavigationStart) { + this.alertService.clear(this.id); + } + }); + } + + removeAlert(alert: Alert) { + // check if already removed to prevent error on auto close + if (!this.alerts.includes(alert)) { + return; + } + + if (this.fade) { + // fade out alert + this.alerts.find(x => x === alert)!.fade = true; + + // remove alert after faded out + setTimeout(() => { + this.alerts = this.alerts.filter(x => x !== alert); + }, 250); + } else { + // remove alert + this.alerts = this.alerts.filter(x => x !== alert); + } + } + + cssClass(alert: Alert) { + if (!alert) { + return; + } + + const classes = ['show', 'alert', 'alert-dismissable']; + + const alertTypeClass = { + /* + [AlertType.Success]: 'alert alert-success', + [AlertType.Error]: 'alert alert-danger', + [AlertType.Info]: 'alert alert-info', + [AlertType.Warning]: 'alert alert-warning' + */ + [AlertType.Success]: 'alert-success', + [AlertType.Error]: 'alert-danger', + [AlertType.Info]: 'alert-info', + [AlertType.Warning]: 'alert-warning', + }; + + classes.push(alertTypeClass[alert.type]); + + if (alert.fade) { + classes.push('fade'); + } + + return classes.join(' '); + } +} diff --git a/src/app/modules/alerting/alert.model.ts b/src/app/modules/alerting/alert.model.ts new file mode 100644 index 0000000..6e280ce --- /dev/null +++ b/src/app/modules/alerting/alert.model.ts @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Inject, Injectable } from '@angular/core'; +import { Problem } from '../../../../openapi/output'; + +@Injectable({ providedIn: 'root' }) +export class Alert { + id?: string; + type!: AlertType; + message?: string; + autoClose?: boolean; + keepAfterRouteChange?: boolean; + fade?: boolean; + errorDetail?: Problem; + requestId?: string; + urlTree?: string[] + + constructor(@Inject(Alert) init?: Partial<Alert>) { + Object.assign(this, init); + } +} + + + +export enum AlertType { + Success, + Error, + Info, + Warning, +} diff --git a/src/app/modules/alerting/alert.module.ts b/src/app/modules/alerting/alert.module.ts new file mode 100644 index 0000000..064bb32 --- /dev/null +++ b/src/app/modules/alerting/alert.module.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { NgModule } from '@angular/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { CommonModule } from '@angular/common'; + +import { AlertComponent } from './alert.component'; +import { TranslateModule } from '@ngx-translate/core'; + +@NgModule({ + imports: [CommonModule, NgbModule, TranslateModule], + declarations: [AlertComponent], + exports: [AlertComponent], +}) +export class AlertModule {} diff --git a/src/app/modules/alerting/alert.service.spec.ts b/src/app/modules/alerting/alert.service.spec.ts new file mode 100644 index 0000000..5c9d219 --- /dev/null +++ b/src/app/modules/alerting/alert.service.spec.ts @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +// https://dev.to/coly010/unit-testing-angular-services-1anm +import { Alert, AlertType } from './alert.model'; +import { TestBed } from '@angular/core/testing'; +import { AlertModule } from './alert.module'; +import { AlertService } from './alert.service'; +import { Subject } from 'rxjs'; +import SpyObj = jasmine.SpyObj; + +/** + * describe sets up the Test Suite for the TileService + */ +describe('AlertService', () => { + let service: AlertService; + let mockAlert: Alert; + let message: string; + let spyAlert: SpyObj<any>; + let subject: Subject<Alert>; + + /** + * beforeEach tells the test runner to run this code before every test in the Test Suite + * It is using Angular's TestBed to create the testing environment and finally it is injecting the TilesService + * and placing a reference to it in the service variable defined earlier. + */ + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AlertService, AlertModule, Subject], + }); + service = TestBed.inject(AlertService); + subject = TestBed.inject(Subject); + mockAlert = TestBed.inject(Alert); + spyAlert = spyOn(service, 'alert'); + message = 'This is a test-alert'; + mockAlert.message = message; + }); + + it('should be create', () => { + expect(service).toBeTruthy(); + }); + /** + * tests for the alert methods info, warning, error and success with a spyobject + */ + it('should return success alert', () => { + mockAlert.type = AlertType.Success; + service.success(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return warning alert', () => { + mockAlert.type = AlertType.Warning; + service.warn(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return error alert', () => { + mockAlert.type = AlertType.Error; + service.error(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('should return info alert', () => { + mockAlert.type = AlertType.Info; + service.info(message); + expect(spyAlert).toHaveBeenCalledWith(mockAlert); + }); + + it('clear ', () => { + subject = service['subject']; + const spy = spyOn(subject, 'next'); + const alert = new Alert(); + alert.id = 'default-alert'; + service.clear(); + expect(spy).toHaveBeenCalledWith(alert); + }); +}); diff --git a/src/app/modules/alerting/alert.service.ts b/src/app/modules/alerting/alert.service.ts new file mode 100644 index 0000000..4d81397 --- /dev/null +++ b/src/app/modules/alerting/alert.service.ts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +import { Injectable } from '@angular/core'; +import { Observable, Subject } from 'rxjs'; +import { filter } from 'rxjs/operators'; + +import { Alert, AlertType } from './alert.model'; + +@Injectable({ providedIn: 'root' }) +export class AlertService { + private subject = new Subject<Alert>(); + private defaultId = 'default-alert'; + + // enable subscribing to alerts observable + onAlert(id = this.defaultId): Observable<Alert> { + return this.subject.asObservable().pipe(filter(x => x && x.id === id)); + } + get alerts() { + return this.subject; + } + + // convenience methods + success(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Success, message })); + } + + error(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Error, message })); + } + + info(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Info, message })); + } + + warn(message: string, options?: Partial<Alert>) { + this.alert(new Alert({ ...options, type: AlertType.Warning, message })); + } + + // main alert method + alert(alert: Alert) { + alert.id = alert.id || this.defaultId; + this.subject.next(alert); + } + + // clear alerts + clear(id = this.defaultId) { + this.subject.next(new Alert({ id })); + } +} diff --git a/src/app/modules/alerting/index.ts b/src/app/modules/alerting/index.ts new file mode 100644 index 0000000..492986c --- /dev/null +++ b/src/app/modules/alerting/index.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022. Deutsche Telekom AG + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +export * from './alert.module'; +export * from './alert.service'; +export * from './alert.model'; |