-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #366 from catenax-ng/feature/TRACEFOSS-1549-Create…
…-alert-detailed-view Feature/tracefoss 1549 create alert detailed view
- Loading branch information
Showing
25 changed files
with
1,012 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
frontend/src/app/modules/page/alerts/core/alert-detail.facade.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Apache License, Version 2.0 which is available at | ||
* https://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 { TitleCasePipe } from '@angular/common'; | ||
import { TestBed } from '@angular/core/testing'; | ||
import { CalendarDateModel } from '@core/model/calendar-date.model'; | ||
import { AlertDetailFacade } from '@page/alerts/core/alert-detail.facade'; | ||
import { AlertDetailState } from '@page/alerts/core/alert-detail.state'; | ||
import { Notification } from '@shared/model/notification.model'; | ||
import { Severity } from '@shared/model/severity.model'; | ||
import { PartsService } from '@shared/service/parts.service'; | ||
|
||
describe('AlertDetailFacade', () => { | ||
let alertDetailFacade: AlertDetailFacade; | ||
let alertDetailState: AlertDetailState; | ||
let partsService: jasmine.SpyObj<PartsService>; | ||
let titleCasePipe: jasmine.SpyObj<TitleCasePipe>; | ||
|
||
let testNotification: Notification = { | ||
id: 'id-1', | ||
description: 'Alert No 1', | ||
createdBy: { name: 'OEM xxxxxxxxxxxxxxx A', bpn: 'BPN10000000OEM0A' }, | ||
sendTo: { name: 'OEM xxxxxxxxxxxxxxx B', bpn: 'BPN20000000OEM0B' }, | ||
reason: { close: '', accept: '', decline: '' }, | ||
isFromSender: true, | ||
assetIds: [], | ||
status: null, | ||
severity: Severity.MINOR, | ||
createdDate: new CalendarDateModel('2022-05-01T10:34:12.000Z'), | ||
} | ||
|
||
beforeEach(() => { | ||
/* | ||
alertDetailState = jasmine.createSpyObj('AlertDetailState', [ | ||
'getIdsFromPartList', | ||
'setAlertPartsInformation', | ||
'getAlertPartsInformation', | ||
'setSupplierPartsInformation', | ||
'getSupplierPartsInformation' | ||
]); | ||
*/ | ||
alertDetailState = new AlertDetailState(); | ||
partsService = jasmine.createSpyObj('PartsService', [ 'getPartDetailOfIds' ]); | ||
titleCasePipe = jasmine.createSpyObj('TitleCasePipe', [ 'transform' ]); | ||
|
||
TestBed.configureTestingModule({ | ||
providers: [ | ||
AlertDetailFacade, | ||
{ provide: AlertDetailState, useValue: alertDetailState }, | ||
{ provide: PartsService, useValue: partsService }, | ||
{ provide: TitleCasePipe, useValue: titleCasePipe } | ||
] | ||
}); | ||
|
||
alertDetailFacade = TestBed.inject(AlertDetailFacade); | ||
}); | ||
|
||
it('should create the component facade', () => { | ||
expect(alertDetailFacade).toBeTruthy(); | ||
}); | ||
|
||
it('should set empty data if no asset ids are provided', () => { | ||
|
||
let callSpy = spyOn(alertDetailFacade, 'setAlertPartsInformation'); | ||
let setSpy = spyOnProperty(alertDetailState, 'alertPartsInformation', 'set').and.callThrough(); | ||
|
||
alertDetailFacade.setAlertPartsInformation(testNotification); | ||
expect(callSpy).toHaveBeenCalledWith(testNotification); | ||
|
||
}) | ||
}); |
131 changes: 131 additions & 0 deletions
131
frontend/src/app/modules/page/alerts/core/alert-detail.facade.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Apache License, Version 2.0 which is available at | ||
* https://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 { TitleCasePipe } from '@angular/common'; | ||
import { Injectable } from '@angular/core'; | ||
import { AlertDetailState } from '@page/alerts/core/alert-detail.state'; | ||
import { Part, SemanticDataModel } from '@page/parts/model/parts.model'; | ||
import { Notification } from '@shared/model/notification.model'; | ||
import { View } from '@shared/model/view.model'; | ||
import { PartsService } from '@shared/service/parts.service'; | ||
import { Observable, of, Subscription } from 'rxjs'; | ||
import { filter, map, switchMap } from 'rxjs/operators'; | ||
import { SortDirection } from '../../../../mocks/services/pagination.helper'; | ||
|
||
@Injectable() | ||
export class AlertDetailFacade { | ||
private notificationPartsInformationDescription: Subscription; | ||
private supplierPartsSubscription: Subscription; | ||
|
||
constructor( | ||
private readonly partsService: PartsService, | ||
private readonly alertDetailState: AlertDetailState, | ||
private readonly titleCasePipe: TitleCasePipe, | ||
) { | ||
} | ||
|
||
public get notificationPartsInformation$(): Observable<View<Part[]>> { | ||
return this.alertDetailState.alertPartsInformation$; | ||
} | ||
|
||
public get supplierPartsInformation$(): Observable<View<Part[]>> { | ||
return this.alertDetailState.supplierPartsInformation$; | ||
} | ||
|
||
public get selected$(): Observable<View<Notification>> { | ||
return this.alertDetailState.selected$; | ||
} | ||
|
||
public set selected(selectedAlert: View<Notification>) { | ||
this.alertDetailState.selected = selectedAlert; | ||
} | ||
|
||
public get selected(): View<Notification> { | ||
return this.alertDetailState.selected; | ||
} | ||
|
||
public setAlertPartsInformation(notification: Notification): void { | ||
this.notificationPartsInformationDescription?.unsubscribe(); | ||
this.alertDetailState.alertPartsInformation = { loader: true }; | ||
|
||
if (!notification.assetIds.length) { | ||
this.alertDetailState.alertPartsInformation = { data: [] }; | ||
return; | ||
} | ||
|
||
this.notificationPartsInformationDescription = this.partsService | ||
.getPartDetailOfIds(notification.assetIds) | ||
.subscribe({ | ||
next: data => { | ||
data.forEach(part => { | ||
part.semanticDataModel = <SemanticDataModel>this.titleCasePipe.transform(part.semanticDataModel); | ||
}) | ||
this.alertDetailState.alertPartsInformation = { data }; | ||
}, | ||
error: error => (this.alertDetailState.alertPartsInformation = { error }), | ||
}); | ||
} | ||
|
||
public setAndSupplierPartsInformation(): void { | ||
this.supplierPartsSubscription?.unsubscribe(); | ||
this.alertDetailState.supplierPartsInformation = { loader: true }; | ||
|
||
this.supplierPartsSubscription = this.alertDetailState.alertPartsInformation$ | ||
.pipe( | ||
filter(view => !!view.data), | ||
map(({ data }) => this.getIdsFromPartList(data)), | ||
switchMap(partIds => (!!partIds && !!partIds.length ? this.partsService.getPartDetailOfIds(partIds) : of([]))), | ||
) | ||
.subscribe({ | ||
next: data => { | ||
data.forEach(part => { | ||
part.semanticDataModel = this.titleCasePipe.transform(part.semanticDataModel); | ||
}) | ||
this.alertDetailState.supplierPartsInformation = { data }; | ||
}, | ||
error: error => (this.alertDetailState.supplierPartsInformation = { error }), | ||
}); | ||
} | ||
|
||
public sortNotificationParts(key: string, direction: SortDirection): void { | ||
const { data } = this.alertDetailState.alertPartsInformation; | ||
if (!data) return; | ||
|
||
const sortedData = this.partsService.sortParts(data, key, direction); | ||
this.alertDetailState.alertPartsInformation = { data: [ ...sortedData ] }; | ||
} | ||
|
||
public sortSupplierParts(key: string, direction: SortDirection): void { | ||
const { data } = this.alertDetailState.supplierPartsInformation; | ||
if (!data) return; | ||
|
||
const sortedData = this.partsService.sortParts(data, key, direction); | ||
this.alertDetailState.supplierPartsInformation = { data: [ ...sortedData ] }; | ||
} | ||
|
||
public unsubscribeSubscriptions(): void { | ||
this.notificationPartsInformationDescription?.unsubscribe(); | ||
this.supplierPartsSubscription?.unsubscribe(); | ||
} | ||
|
||
private getIdsFromPartList(parts: Part[]): string[] { | ||
const childIds = parts.map(part => part.children).reduce((p, c) => [ ...p, ...c ], []); | ||
return [ ...new Set(childIds) ]; | ||
} | ||
} |
73 changes: 73 additions & 0 deletions
73
frontend/src/app/modules/page/alerts/core/alert-detail.state.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2023 Contributors to the Eclipse Foundation | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information regarding copyright ownership. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Apache License, Version 2.0 which is available at | ||
* https://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 { Part } from '@page/parts/model/parts.model'; | ||
import { Notification } from '@shared/model/notification.model'; | ||
import { State } from '@shared/model/state'; | ||
import { View } from '@shared/model/view.model'; | ||
import { Observable } from 'rxjs'; | ||
|
||
@Injectable() | ||
export class AlertDetailState { | ||
private readonly _alertPartsInformation$ = new State<View<Part[]>>({ loader: true }); | ||
private readonly _supplierPartsInformation$ = new State<View<Part[]>>({ loader: true }); | ||
|
||
private readonly _selected$ = new State<View<Notification>>({ loader: true }); | ||
|
||
// Detailed information for parts assigned to an alert | ||
public get alertPartsInformation$(): Observable<View<Part[]>> { | ||
return this._alertPartsInformation$.observable; | ||
} | ||
|
||
public get alertPartsInformation(): View<Part[]> { | ||
return this._alertPartsInformation$.snapshot; | ||
} | ||
|
||
public set alertPartsInformation(view: View<Part[]>) { | ||
this._alertPartsInformation$.update(view); | ||
} | ||
|
||
// Detailed information for child parts assigned to an alert | ||
public get supplierPartsInformation$(): Observable<View<Part[]>> { | ||
return this._supplierPartsInformation$.observable; | ||
} | ||
|
||
public get supplierPartsInformation(): View<Part[]> { | ||
return this._supplierPartsInformation$.snapshot; | ||
} | ||
|
||
public set supplierPartsInformation(view: View<Part[]>) { | ||
this._supplierPartsInformation$.update(view); | ||
} | ||
|
||
// Selected Notification | ||
public get selected$(): Observable<View<Notification>> { | ||
return this._selected$.observable; | ||
} | ||
|
||
public set selected({ data, loader, error }: View<Notification>) { | ||
const view: View<Notification> = { data, loader, error }; | ||
this._selected$.update(view); | ||
} | ||
|
||
get selected(): View<Notification> { | ||
return this._selected$.snapshot; | ||
} | ||
} |
Oops, something went wrong.