diff --git a/CHANGELOG.md b/CHANGELOG.md index 82b7b31b25..1d439fab97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). _**For better traceability add the corresponding GitHub issue number in each changelog entry, please.**_ ## [UNRELEASED - DD.MM.YYYY] + +### Added + +- #999 Added notification processing feedback in FE + ### Changed - #1173 Update IRS-Helm from 7.1.4 to 7.2.0 - updated Compatibility Matrix - #1082 fix duplicate key errors when synchronizing assets with IRS diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts index 288a8bcc0b..0e59f02eec 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.assembler.spec.ts @@ -79,7 +79,6 @@ const mockPolicyResponse: PolicyResponseMap = { describe('PoliciesAssembler', () => { it('should assemble policy', () => { const assembledPolicy = PoliciesAssembler.assemblePolicy(mockPolicy2); - console.log(assembledPolicy.constraints); expect(assembledPolicy.policyName).toBe(mockPolicy2.policyId); expect(assembledPolicy.createdOn).toBe('2024-01-01T00:00'); expect(assembledPolicy.validUntil).toBe('2024-12-31T23:59'); diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.component.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.component.ts index 9bb3de39c3..0ecd770ec6 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.component.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policies/policies.component.ts @@ -87,7 +87,6 @@ export class PoliciesComponent { this.selectedPoliciesInfoLabel = selectedPolicies.length === 1 ? 'pageAdmin.policyManagement.selectedPolicy' : 'pageAdmin.policyManagement.selectedPolicies'; this.selectedPolicies = selectedPolicies; this.isDefaultSelected = this.selectedPolicies.filter(policy => policy?.policyId === 'default-policy').length > 0; - console.log(this.isDefaultSelected); } openDetailedView(selectedPolicy: Record) { diff --git a/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts b/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts index 8136da9798..faac5cc379 100644 --- a/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts +++ b/frontend/src/app/modules/page/admin/presentation/policy-management/policy-editor/policy-editor.component.ts @@ -74,7 +74,6 @@ export class PolicyEditorComponent { this.selectedPolicySubscription = this.policyFacade.selectedPolicy$.subscribe(next => { this.selectedPolicy = next?.data; if (next?.data) { - console.log(next.data); this.updatePolicyForm(this.selectedPolicy); } }); diff --git a/frontend/src/app/modules/page/notifications/detail/notification-detail.component.html b/frontend/src/app/modules/page/notifications/detail/notification-detail.component.html index 60680a8679..7784f0cbf2 100644 --- a/frontend/src/app/modules/page/notifications/detail/notification-detail.component.html +++ b/frontend/src/app/modules/page/notifications/detail/notification-detail.component.html @@ -32,19 +32,19 @@
edit @@ -57,7 +57,7 @@ onkeydown="notificationCommonModalComponent?.show(NotificationStatus.APPROVED)" (click)="notificationCommonModalComponent?.show(NotificationStatus.APPROVED)" [color]="'primary'" - [isDisabled]="!actionHelperService.isAuthorizedForButton(NotificationAction.APPROVE)" + [isDisabled]="!actionHelperService.isAuthorizedForButton(NotificationAction.APPROVE) || isProcessing()" >
share @@ -66,19 +66,19 @@
cancel @@ -87,19 +87,19 @@
close @@ -108,19 +108,19 @@
assignment_turned_in @@ -129,19 +129,19 @@
work @@ -150,19 +150,19 @@
assignment_late diff --git a/frontend/src/app/modules/page/notifications/detail/notification-detail.component.ts b/frontend/src/app/modules/page/notifications/detail/notification-detail.component.ts index da17a6aba8..b472adc1a3 100644 --- a/frontend/src/app/modules/page/notifications/detail/notification-detail.component.ts +++ b/frontend/src/app/modules/page/notifications/detail/notification-detail.component.ts @@ -31,6 +31,7 @@ import { ToastService } from '@shared/components/toasts/toast.service'; import { Notification, NotificationStatus, NotificationType } from '@shared/model/notification.model'; import { View } from '@shared/model/view.model'; import { NotificationAction } from '@shared/modules/notification/notification-action.enum'; +import { NotificationProcessingService } from '@shared/service/notification-processing.service'; import { StaticIdService } from '@shared/service/staticId.service'; import { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs'; import { filter, first, tap } from 'rxjs/operators'; @@ -78,18 +79,20 @@ export class NotificationDetailComponent implements AfterViewInit, OnDestroy { private router: Router, private readonly route: ActivatedRoute, private readonly toastService: ToastService, + private readonly notificationProcessingService: NotificationProcessingService, ) { 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(); + const formattedStatus = result?.context?.notificationStatus?.charAt(0)?.toUpperCase() + result?.context?.notificationStatus?.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.notificationProcessingService.notificationIdsInLoadingState.delete(result?.context?.notificationId); this.ngAfterViewInit(); }, }); @@ -228,6 +231,10 @@ export class NotificationDetailComponent implements AfterViewInit, OnDestroy { .subscribe(); } + isProcessing() { + return this.notificationProcessingService.isInLoadingProcess(this.selectedNotification); + } + protected readonly NotificationType = NotificationType; protected readonly NotificationAction = NotificationAction; diff --git a/frontend/src/app/modules/page/notifications/presentation/notifications.component.ts b/frontend/src/app/modules/page/notifications/presentation/notifications.component.ts index 252a610543..29619ea054 100644 --- a/frontend/src/app/modules/page/notifications/presentation/notifications.component.ts +++ b/frontend/src/app/modules/page/notifications/presentation/notifications.component.ts @@ -39,6 +39,7 @@ import { NotificationType, } from '@shared/model/notification.model'; import { TranslationContext } from '@shared/model/translation-context.model'; +import { NotificationProcessingService } from '@shared/service/notification-processing.service'; import { Subscription } from 'rxjs'; @Component({ @@ -74,6 +75,7 @@ export class NotificationsComponent { private readonly route: ActivatedRoute, private readonly cd: ChangeDetectorRef, private readonly toastService: ToastService, + private readonly notificationProcessingService: NotificationProcessingService, ) { this.notificationsReceived$ = this.notificationsFacade.notificationsReceived$; this.notificationsQueuedAndRequested$ = this.notificationsFacade.notificationsQueuedAndRequested$; @@ -87,13 +89,14 @@ export class NotificationsComponent { this.toastActionSubscription = this.toastService.retryAction.subscribe({ next: result => { - const formatted = result?.context?.charAt(0)?.toUpperCase() + result?.context?.slice(1)?.toLowerCase(); + const formatted = result?.context?.notificationStatus?.charAt(0)?.toUpperCase() + result?.context?.notificationStatus?.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(); + this.notificationProcessingService.notificationIdsInLoadingState.delete(result?.context?.notificationId); }, }); } @@ -114,6 +117,7 @@ export class NotificationsComponent { this.menuActionsConfig = NotificationMenuActionsAssembler.getMenuActions( this.actionHelperService, this.notificationCommonModalComponent, + this.notificationProcessingService, ); this.cd.detectChanges(); } diff --git a/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.spec.ts b/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.spec.ts index 4f8eb99913..d3fb65a75b 100644 --- a/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.spec.ts +++ b/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.spec.ts @@ -28,12 +28,14 @@ import { NotificationMenuActionsAssembler } from '@shared/assembler/notification import { NotificationCommonModalComponent } from '@shared/components/notification-common-modal/notification-common-modal.component'; import { Notification, NotificationStatus, NotificationType } from '@shared/model/notification.model'; import { Severity } from '@shared/model/severity.model'; +import { NotificationProcessingService } from '@shared/service/notification-processing.service'; import { KeycloakService } from 'keycloak-angular'; describe('NotificationMenuActionsAssembler', () => { let helperService: NotificationHelperService; let notificationCommonModalComponent: NotificationCommonModalComponent; let notificationActionHelperService: NotificationActionHelperService; + let notificationProcessingService: NotificationProcessingService; beforeEach(function() { TestBed.configureTestingModule({ @@ -56,11 +58,13 @@ describe('NotificationMenuActionsAssembler', () => { notificationCommonModalComponent = TestBed.inject(NotificationCommonModalComponent); helperService = TestBed.inject(NotificationHelperService); notificationActionHelperService = TestBed.inject(NotificationActionHelperService); + notificationProcessingService = TestBed.inject(NotificationProcessingService); }); it('should return menuActions', function() { // Arrange let showSpy = spyOn(notificationCommonModalComponent, 'show').and.returnValue(undefined); + let isLoadingSpy = spyOn(notificationProcessingService, 'isInLoadingProcess'); const notificationTemplate: Notification = { id: 'id-1', @@ -80,7 +84,7 @@ describe('NotificationMenuActionsAssembler', () => { }; // Act - let menuActions = NotificationMenuActionsAssembler.getMenuActions(notificationActionHelperService, notificationCommonModalComponent); + let menuActions = NotificationMenuActionsAssembler.getMenuActions(notificationActionHelperService, notificationCommonModalComponent, notificationProcessingService); // Assert menuActions.map(item => { @@ -89,6 +93,10 @@ describe('NotificationMenuActionsAssembler', () => { expect(showSpy).toHaveBeenCalled(); let conditionAction = item.condition(notificationTemplate); expect(conditionAction).not.toBe(undefined); + expect(item.isLoading).toBeDefined(); + item.isLoading(notificationTemplate); + expect(isLoadingSpy).toHaveBeenCalled(); + }); }); diff --git a/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.ts b/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.ts index 036039f8c3..5d5da004c2 100644 --- a/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.ts +++ b/frontend/src/app/modules/shared/assembler/notificationMenuActions.assembler.ts @@ -21,9 +21,10 @@ import { NotificationCommonModalComponent } from '@shared/components/notificatio import { MenuActionConfig } from '@shared/components/table/table.model'; import { Notification, NotificationStatus } from '@shared/model/notification.model'; import { NotificationAction } from '@shared/modules/notification/notification-action.enum'; +import { NotificationProcessingService } from '@shared/service/notification-processing.service'; export class NotificationMenuActionsAssembler { - public static getMenuActions(helperService: NotificationActionHelperService, modal: NotificationCommonModalComponent): MenuActionConfig[] { + public static getMenuActions(helperService: NotificationActionHelperService, modal: NotificationCommonModalComponent, notificationProcessingService: NotificationProcessingService): MenuActionConfig[] { return [ { label: 'actions.close', @@ -31,6 +32,7 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.CLOSED, data), condition: data => helperService.showCloseButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.CLOSE), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), }, { label: 'actions.approve', @@ -38,6 +40,8 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.APPROVED, data), condition: data => helperService.showApproveButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.APPROVE), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), + }, { label: 'actions.cancel', @@ -45,6 +49,7 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.CANCELED, data), condition: data => helperService.showCancelButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.CANCEL), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), }, { label: 'actions.acknowledge', @@ -52,6 +57,7 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.ACKNOWLEDGED, data), condition: data => helperService.showAcknowledgeButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.ACKNOWLEDGE), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), }, { label: 'actions.accept', @@ -59,6 +65,7 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.ACCEPTED, data), condition: data => helperService.showAcceptButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.ACCEPT), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), }, { label: 'actions.decline', @@ -66,6 +73,7 @@ export class NotificationMenuActionsAssembler { action: data => modal.show(NotificationStatus.DECLINED, data), condition: data => helperService.showDeclineButton(data), isAuthorized: helperService.isAuthorizedForButton(NotificationAction.DECLINE), + isLoading: data => notificationProcessingService.isInLoadingProcess(data), }, ]; } diff --git a/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.html b/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.html index c598471174..ff4b04a479 100644 --- a/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.html +++ b/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.html @@ -32,18 +32,16 @@
{{ 'table.column.description' | i18n }} - {{ - notification?.description + {{ + notification?.description }}
{{ 'table.column.status' | i18n }} - - {{ 'commonAlert.status.' + notification?.status | i18n }} - + + +
{{ 'table.column.createdDate' | i18n }} @@ -58,25 +56,25 @@
{{ 'table.column.createdBy' | i18n }} - {{notification.createdBy}} + {{ notification.createdBy }}
{{ 'table.column.createdByName' | i18n }} - {{notification.createdByName}} + {{ notification.createdByName }}
{{ 'table.column.sendTo' | i18n }} - {{notification.sendTo}} + {{ notification.sendTo }}
{{ 'table.column.sendToName' | i18n }} - {{notification.sendToName}} + {{ notification.sendToName }}
@@ -111,3 +109,24 @@ {{ date }} + + + + {{ 'commonAlert.status.' + notification?.status | i18n }} + + + + + + + + diff --git a/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.ts b/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.ts index c30cae0326..a9adbf9eac 100644 --- a/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.ts +++ b/frontend/src/app/modules/shared/components/notification-overview/notification-overview.component.ts @@ -21,6 +21,8 @@ import { Component, Input } from '@angular/core'; import { Notification } from '@shared/model/notification.model'; +import { NotificationAction } from '@shared/modules/notification/notification-action.enum'; +import { NotificationProcessingService } from '@shared/service/notification-processing.service'; @Component({ selector: 'app-notification-overview', @@ -34,4 +36,9 @@ import { Notification } from '@shared/model/notification.model'; export class NotificationOverviewComponent { @Input() notification: Notification; @Input() showNotification = true; + + constructor(public notificationProcessingService: NotificationProcessingService) { + } + + protected readonly NotificationAction = NotificationAction; } diff --git a/frontend/src/app/modules/shared/components/table/table.component.html b/frontend/src/app/modules/shared/components/table/table.component.html index 2e60fae8e0..f75e98219a 100644 --- a/frontend/src/app/modules/shared/components/table/table.component.html +++ b/frontend/src/app/modules/shared/components/table/table.component.html @@ -333,17 +333,17 @@

{{ 'table.noResultFound' | i18n }}