Skip to content

Commit

Permalink
Merge pull request #1136 from eclipse-tractusx/bug/#1009-try-again-bu…
Browse files Browse the repository at this point in the history
…tton-fix

Bug/#1009 try again button fix
  • Loading branch information
ds-mwesener authored Jul 3, 2024
2 parents c08ef66 + e94d3a8 commit 12fefb5
Show file tree
Hide file tree
Showing 16 changed files with 169 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ _**For better traceability add the corresponding GitHub issue number in each cha
- #639 handle expired or incorrect policies when sending notifications
- #786 Added authorization as admin for submodel api & registry api
- #884 Upgraded tractionBatteryCode from 1.0.0 to 2.0.0
- #1009 reimplemented retry request logic for notification approval
- #786 Added alternative port (only accessible within same cluster) for application which is used for unsecured API endpoints.
- #786 Introduced internal url for notification contracts.
- #994 improved bpn edc configuration view uux
- #1082 fix update of parts when synchronizing with IRS


### Added
- #832 added policymanagement list view, creator and editor
- #737 Added concept: Contract table -> parts link action
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/app/modules/core/api/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { AuthService } from '../auth/auth.service';
providedIn: 'root',
})
export class ApiService {
lastRequest: { execute?: () => Observable<void>, context?: any };
constructor(private readonly httpClient: HttpClient, private readonly authService: AuthService) {
}

Expand Down Expand Up @@ -111,6 +112,16 @@ export class ApiService {
});
}

/**
* set the public class property 'lastRequest' from where you made the request
* before retrying
*/
public retryLastRequest(): Observable<any> | null {
if (this.lastRequest.execute) {
return this.lastRequest.execute();
}
}

private buildHeaders(): HttpHeaders {
return new HttpHeaders({
Access: 'application/json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,22 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { MockedKeycloakService } from '@core/auth/mocked-keycloak.service';
import { TableSettingsService } from '@core/user/table-settings.service';
import { TableType } from '@shared/components/multi-select-autocomplete/table-type.model';
import { TableViewConfig } from '@shared/components/parts-table/table-view-config.model';
import { ToastService } from '@shared/components/toasts/toast.service';
import { KeycloakService } from 'keycloak-angular';

describe('TableSettingsService', () => {
let service: TableSettingsService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [ TableSettingsService ],
imports: [ HttpClientTestingModule ],
providers: [ TableSettingsService, ToastService, { provide: KeycloakService, useValue: MockedKeycloakService } ],
});
service = TestBed.inject(TableSettingsService);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@
</ng-template>

<ng-template #reasonInfoTmp let-view="view">
<app-notification-reason [notification]="view.data"></app-notification-reason>
<app-notification-reason [notificationMessages]="view.data?.messages"></app-notification-reason>
</ng-template>

<ng-template #errorTmp let-view="view">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import { ActivatedRoute } from '@angular/router';
import { NotificationDetailComponent } from '@page/notifications/detail/notification-detail.component';
import { NotificationsModule } from '@page/notifications/notifications.module';
import { NotificationAssembler } from '@shared/assembler/notification.assembler';
import { NotificationService } from '@shared/service/notification.service';
import { screen, waitFor } from '@testing-library/angular';
import { renderComponent } from '@tests/test-render.utils';
import { of } from 'rxjs';
import { MockEmptyAlert } from '../../../../mocks/services/alerts-mock/alerts.test.model';

describe('NotificationDetailComponent', () => {

Expand Down Expand Up @@ -58,4 +60,23 @@ describe('NotificationDetailComponent', () => {
await waitFor(() => expect(screen.getByText('actions.goBack')).toBeInTheDocument());
});

it('should correctly behave on toast retry action', async () => {
const { fixture } = await renderNotificationDetail('id-1');
const { componentInstance } = fixture;
const ngSpy = spyOn(componentInstance, 'ngAfterViewInit').and.returnValue(null);
const toastSuccessSpy = spyOn(componentInstance['toastService'], 'success');
const toastErrorSpy = spyOn(componentInstance['toastService'], 'error');

componentInstance.selectedNotification = NotificationAssembler.assembleNotification(MockEmptyAlert);
componentInstance['toastService'].retryAction.emit({ success: true });
expect(toastSuccessSpy).toHaveBeenCalled();

componentInstance['toastService'].retryAction.emit({ error: true });
expect(toastErrorSpy).toHaveBeenCalled();

expect(ngSpy).toHaveBeenCalled();

});


});
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export class NotificationDetailComponent implements AfterViewInit, OnDestroy {
public selectedNotification: Notification;

private paramSubscription: Subscription;
private toastActionSubscription: Subscription;

constructor(
public readonly helperService: NotificationHelperService,
Expand All @@ -81,6 +82,18 @@ export class NotificationDetailComponent implements AfterViewInit, OnDestroy {
this.notificationPartsInformation$ = this.notificationDetailFacade.notificationPartsInformation$;
this.supplierPartsDetailInformation$ = this.notificationDetailFacade.supplierPartsInformation$;

this.toastActionSubscription = this.toastService.retryAction.subscribe({
next: result => {
const formattedStatus = result?.context?.charAt(0)?.toUpperCase() + result?.context?.slice(1)?.toLowerCase();
if (result?.success) {
this.toastService.success(`requestNotification.successfully${ formattedStatus }`);
} else if (result?.error) {
this.toastService.error(`requestNotification.failed${ formattedStatus }`, 15000, true);
}
this.ngAfterViewInit();
},
});

this.selected$ = this.notificationDetailFacade.selected$;

this.paramSubscription = this.route.queryParams.subscribe(params => {
Expand Down Expand Up @@ -111,6 +124,7 @@ export class NotificationDetailComponent implements AfterViewInit, OnDestroy {
this.subscription?.unsubscribe();
this.notificationDetailFacade.unsubscribeSubscriptions();
this.paramSubscription?.unsubscribe();
this.toastActionSubscription?.unsubscribe();
}

public navigateToEditView() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,21 @@ describe('NotificationsComponent', () => {
expect(notificationsComponent['notificationReceivedSortList']).toEqual([]);
});

it('should correctly behave on toast retry action', async () => {
const { fixture } = await renderNotifications();
const { componentInstance } = fixture;
const handleConfirmSpy = spyOn(componentInstance, 'handleConfirmActionCompletedEvent');
const toastSuccessSpy = spyOn(componentInstance['toastService'], 'success');
const toastErrorSpy = spyOn(componentInstance['toastService'], 'error');

componentInstance['toastService'].retryAction.emit({ success: true });
expect(toastSuccessSpy).toHaveBeenCalled();

componentInstance['toastService'].retryAction.emit({ error: true });
expect(toastErrorSpy).toHaveBeenCalled();

expect(handleConfirmSpy).toHaveBeenCalled();

});

});
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { NotificationChannel } from '@shared/components/multi-select-autocomplet
import { NotificationCommonModalComponent } from '@shared/components/notification-common-modal/notification-common-modal.component';
import { TableSortingUtil } from '@shared/components/table/table-sorting.util';
import { MenuActionConfig, TableEventConfig, TableHeaderSort } from '@shared/components/table/table.model';
import { ToastService } from '@shared/components/toasts/toast.service';
import { createDeeplinkNotificationFilter } from '@shared/helper/notification-helper';
import { setMultiSorting } from '@shared/helper/table-helper';
import { NotificationTabInformation } from '@shared/model/notification-tab-information';
Expand Down Expand Up @@ -58,6 +59,7 @@ export class NotificationsComponent {
private ctrlKeyState: boolean = false;

private paramSubscription: Subscription;
private toastActionSubscription: Subscription;

receivedFilter: NotificationFilter;
requestedFilter: NotificationFilter;
Expand All @@ -71,6 +73,7 @@ export class NotificationsComponent {
private readonly router: Router,
private readonly route: ActivatedRoute,
private readonly cd: ChangeDetectorRef,
private readonly toastService: ToastService,
) {
this.notificationsReceived$ = this.notificationsFacade.notificationsReceived$;
this.notificationsQueuedAndRequested$ = this.notificationsFacade.notificationsQueuedAndRequested$;
Expand All @@ -81,6 +84,18 @@ export class NotificationsComponent {
window.addEventListener('keyup', (event) => {
this.ctrlKeyState = setMultiSorting(event);
});

this.toastActionSubscription = this.toastService.retryAction.subscribe({
next: result => {
const formatted = result?.context?.charAt(0)?.toUpperCase() + result?.context?.slice(1)?.toLowerCase();
if (result?.success) {
this.toastService.success(`requestNotification.successfully${ formatted }`);
} else if (result?.error) {
this.toastService.error(`requestNotification.failed${ formatted }`, 15000, true);
}
this.handleConfirmActionCompletedEvent();
},
});
}

public ngOnInit(): void {
Expand All @@ -106,6 +121,7 @@ export class NotificationsComponent {
public ngOnDestroy(): void {
this.notificationsFacade.stopNotifications();
this.paramSubscription?.unsubscribe();
this.toastActionSubscription?.unsubscribe();
}

public onReceivedTableConfigChange(pagination: TableEventConfig) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ describe('NotificationReasonComponent', () => {
},
]
};
component.notification = notification;
component.notificationMessages = notification.messages;
component.ngOnInit();
expect(component.textMessages.length).toBe(2);
expect(component.textMessages[0].message).toEqual('Hello');
expect(component.textMessages[1].direction).toEqual('left');
Expand Down Expand Up @@ -102,7 +103,7 @@ describe('NotificationReasonComponent', () => {
isFromSender: true,
messages: []
};
component.notification = notification;
component.notificationMessages = notification.messages;
expect(component.textMessages.length).toBe(0);
});

Expand All @@ -122,7 +123,7 @@ describe('NotificationReasonComponent', () => {
isFromSender: true,
messages: []
};
component.notification = notification;
component.notificationMessages = notification.messages;
// Since date is invalid, sorting and processing might behave unexpectedly, expecting no error thrown and no messages processed
expect(component.textMessages.length).toBe(0);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import { Component, Input } from '@angular/core';
import { environment } from '@env';
import { Notification, NotificationStatus } from '@shared/model/notification.model';
import { NotificationMessage, NotificationStatus } from '@shared/model/notification.model';

type TextMessageDirection = 'left' | 'right';

Expand All @@ -42,31 +42,26 @@ interface TextMessage {
})
export class NotificationReasonComponent {
public textMessages: TextMessage[] = [];
@Input() notificationMessages: NotificationMessage[];

@Input() set notification({
description,
status,
isFromSender,
createdDate,
createdBy,
createdByName,
sendTo,
sendToName,
messages,
}: Notification) {
ngOnInit() {
if (!this.notificationMessages) {
return;
}
let sortedMessagesAfterDates = [ ...this.notificationMessages ];

const sortedMessagesAfterDates = messages.sort((a, b) => new Date(a.messageDate).valueOf() - new Date(b.messageDate).valueOf());
sortedMessagesAfterDates.sort((a, b) => new Date(a.messageDate).valueOf() - new Date(b.messageDate).valueOf());

sortedMessagesAfterDates.forEach(message => {
this.textMessages.push({
message: message.message,
direction: environment.bpn === message.sentBy ? 'right' : 'left',
user: message.sentByName,
bpn: message.sentBy,
status: message.status,
date: message.messageDate,
errorMessage: message.errorMessage,
});
sortedMessagesAfterDates?.forEach(message => {
this.textMessages.push({
message: message.message,
direction: environment.bpn === message.sentBy ? 'right' : 'left',
user: message.sentByName,
bpn: message.sentBy,
status: message.status,
date: message.messageDate,
errorMessage: message.errorMessage,
});
});

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
********************************************************************************/

import { EventEmitter, Injectable } from '@angular/core';
import { ApiService } from '@core/api/api.service';
import { I18nMessage } from '@shared/model/i18n-message';
import { Observable, Subject } from 'rxjs';
import { CallAction, ToastMessage, ToastStatus } from './toast-message/toast-message.model';
Expand All @@ -32,6 +33,9 @@ export class ToastService {
private idx = 0;
retryAction = new EventEmitter<any>();

constructor(private readonly apiService: ApiService) {
}

public getCurrentToast$(): Observable<ToastMessage> {
return this.toastStore.asObservable();
}
Expand All @@ -56,7 +60,10 @@ export class ToastService {
this.toastStore.next(new ToastMessage(this.idx++, message, ToastStatus.Warning, timeout));
}

public emitClick(event?: any) {
this.retryAction.emit();
public emitClick(): void {
this.apiService.retryLastRequest()?.subscribe({
next: (next) => this.retryAction.emit({ success: next, context: this.apiService.lastRequest?.context }),
error: (err) => this.retryAction.emit({ error: err, context: this.apiService.lastRequest?.context }),
});
};
}
18 changes: 11 additions & 7 deletions frontend/src/app/modules/shared/components/toasts/toast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

import {TestBed} from '@angular/core/testing';
import {SharedModule} from '@shared/shared.module';
import {screen} from '@testing-library/angular';
import {renderComponent} from '@tests/test-render.utils';
import {ToastService} from './toast.service';
import { TestBed } from '@angular/core/testing';
import { ApiService } from '@core/api/api.service';
import { SharedModule } from '@shared/shared.module';
import { screen } from '@testing-library/angular';
import { renderComponent } from '@tests/test-render.utils';
import { ToastService } from './toast.service';

describe('toasts', () => {
const renderToastLayout = async () => {
await renderComponent(`<app-toast-container></app-toast-container>`, { imports: [ SharedModule ] });
await renderComponent(`<app-toast-container></app-toast-container>`, {
imports: [ SharedModule ],
providers: [ ApiService ],
});
return TestBed.inject(ToastService);
};

Expand Down Expand Up @@ -68,7 +72,7 @@ describe('toasts', () => {

it('should emit click action on toast', async () => {
const toastService = await renderToastLayout();
const toastActionSpy = spyOn(toastService.retryAction, 'emit')
const toastActionSpy = spyOn(toastService['apiService'], 'retryLastRequest');
toastService.emitClick();
expect(toastActionSpy).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</mat-card>
<mat-card class="max-h-74 overflow-y-scroll">
<mat-card-content>
<app-notification-reason [notification]="notification"></app-notification-reason>
<app-notification-reason [notificationMessages]="notification?.messages"></app-notification-reason>
</mat-card-content>
</mat-card>
</div>
Loading

0 comments on commit 12fefb5

Please sign in to comment.