diff --git a/modules/ui/src/app/components/device-item/device-item.component.scss b/modules/ui/src/app/components/device-item/device-item.component.scss index e4aa3d37b..717ffa704 100644 --- a/modules/ui/src/app/components/device-item/device-item.component.scss +++ b/modules/ui/src/app/components/device-item/device-item.component.scss @@ -141,6 +141,8 @@ $border-radius: 12px; padding-right: variables.$icon-size; .item-manufacturer-text { + width: 210px; + max-width: 240px; margin: 0; text-overflow: ellipsis; white-space: nowrap; @@ -188,4 +190,7 @@ mat-icon { mat-icon { color: colors.$on-error-container; } + .item-manufacturer-text { + max-width: 150px; + } } diff --git a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts index 763645cc1..a65fa417a 100644 --- a/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts +++ b/modules/ui/src/app/pages/risk-assessment/profile-form/profile-form.component.ts @@ -128,7 +128,7 @@ export class ProfileFormComponent implements OnInit, AfterViewInit { @Output() saveProfile = new EventEmitter(); @Output() deleteCopy = new EventEmitter(); - @Output() discard = new EventEmitter(); + @Output() discard = new EventEmitter(); @Output() delete = new EventEmitter(); @Output() copyProfile = new EventEmitter(); ngOnInit() { @@ -297,7 +297,7 @@ export class ProfileFormComponent implements OnInit, AfterViewInit { } onDiscardClick() { - this.discard.emit(this.selectedProfile!); + this.discard.emit(); } onDeleteClick(): void { diff --git a/modules/ui/src/app/pages/risk-assessment/profile-item/profile-item.component.scss b/modules/ui/src/app/pages/risk-assessment/profile-item/profile-item.component.scss index a005792f6..509ef9d2c 100644 --- a/modules/ui/src/app/pages/risk-assessment/profile-item/profile-item.component.scss +++ b/modules/ui/src/app/pages/risk-assessment/profile-item/profile-item.component.scss @@ -24,10 +24,6 @@ $profile-item-container-gap: 8px; width: 100%; height: 100%; display: grid; - grid-template-columns: minmax(160px, 1fr) repeat( - 2, - $profile-icon-container-size - ); gap: $profile-item-container-gap; box-sizing: border-box; align-items: center; @@ -83,6 +79,7 @@ $profile-item-container-gap: 8px; } .profile-item-name { + max-width: 170px; font-size: 16px; color: colors.$on-surface; line-height: 24px; diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.html b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.html index 49c44420f..8d464ee6b 100644 --- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.html +++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.html @@ -47,7 +47,7 @@ (deleteCopy)="deleteCopy($event, vm.profiles)" (delete)="deleteProfile($event)" (copyProfile)="copyProfile($event, vm.profiles)" - (discard)="discard($event)"> + (discard)="discard($event, vm.profiles)"> diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts index c23f0c7ab..b2d7b0281 100644 --- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts +++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.spec.ts @@ -70,6 +70,7 @@ describe('RiskAssessmentComponent', () => { 'setFocusOnSelectedProfile', 'setFocusOnProfileForm', 'updateProfiles', + 'removeProfile', ]); await TestBed.configureTestingModule({ @@ -407,26 +408,26 @@ describe('RiskAssessmentComponent', () => { 'openCloseDialog' ).and.returnValue(of(true)); - component.discard(null); + component.discard(null, []); expect(openCloseDialogSpy).toHaveBeenCalled(); openCloseDialogSpy.calls.reset(); }); - describe('with no selected profile', () => { + describe('after dialog closed with discard selected', () => { beforeEach(() => { spyOn( component.form(), 'openCloseDialog' ).and.returnValue(of(true)); - component.discard(null); + component.discard(null, []); }); - it('should call setFocusOnCreateButton', () => { + it('should update selected profile', () => { expect( - mockRiskAssessmentStore.setFocusOnCreateButton - ).toHaveBeenCalled(); + mockRiskAssessmentStore.updateSelectedProfile + ).toHaveBeenCalledWith(null); }); it('should close the form', () => { @@ -434,26 +435,19 @@ describe('RiskAssessmentComponent', () => { }); }); - describe('with selected profile', () => { + describe('with selected copy profile', () => { beforeEach(fakeAsync(() => { spyOn( component.form(), 'openCloseDialog' ).and.returnValue(of(true)); - component.discard(PROFILE_MOCK); + component.isCopyProfile = true; + component.discard(DRAFT_COPY_PROFILE_MOCK, [DRAFT_COPY_PROFILE_MOCK]); tick(100); })); - it('should call setFocusOnCreateButton', fakeAsync(() => { - expect( - mockRiskAssessmentStore.setFocusOnSelectedProfile - ).toHaveBeenCalled(); - })); - - it('should update selected profile', () => { - expect( - mockRiskAssessmentStore.updateSelectedProfile - ).toHaveBeenCalledWith(null); + it('should remove copy if not saved', () => { + expect(mockRiskAssessmentStore.removeProfile).toHaveBeenCalled(); }); }); }); diff --git a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts index f85a4bd80..ac2eb0f4f 100644 --- a/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts +++ b/modules/ui/src/app/pages/risk-assessment/risk-assessment.component.ts @@ -22,6 +22,7 @@ import { inject, viewChild, ChangeDetectorRef, + ElementRef, } from '@angular/core'; import { RiskAssessmentStore } from './risk-assessment.store'; import { SimpleDialogComponent } from '../../components/simple-dialog/simple-dialog.component'; @@ -93,6 +94,7 @@ export class RiskAssessmentComponent private store = inject(RiskAssessmentStore); private liveAnnouncer = inject(LiveAnnouncer); cd = inject(ChangeDetectorRef); + private elementRef = inject(ElementRef); private destroy$: Subject = new Subject(); dialog = inject(MatDialog); element = inject(ViewContainerRef); @@ -171,7 +173,9 @@ export class RiskAssessmentComponent name: profileName, onDelete: (idx = 0) => { this.closeFormAfterDelete(profileName, profile); - this.setFocus(idx); + timer(100).subscribe(() => { + this.setFocus(idx); + }); }, }); } else { @@ -203,36 +207,55 @@ export class RiskAssessmentComponent } } - discard(selectedProfile: Profile | null) { + discard(selectedProfile: Profile | null, profiles: Profile[]) { this.liveAnnouncer.clear(); - this.openCloseDialog(selectedProfile); + this.openCloseDialog(selectedProfile, profiles); } copyProfile(profile: Profile, profiles: Profile[]) { this.copyProfileAndOpenForm(profile, profiles); } - private openCloseDialog(selectedProfile: Profile | null) { + private openCloseDialog( + selectedProfile: Profile | null, + profiles: Profile[] + ) { this.form() ?.openCloseDialog() .pipe(takeUntil(this.destroy$)) .subscribe(close => { if (close) { - if (selectedProfile) { - timer(100).subscribe(() => { - this.store.setFocusOnSelectedProfile(); - }); - } else { - this.store.setFocusOnCreateButton(); + if (selectedProfile && this.isCopyProfile) { + this.deleteCopy(selectedProfile, profiles); } this.isCopyProfile = false; this.isOpenProfileForm = false; this.store.updateSelectedProfile(null); this.cd.markForCheck(); + timer(100).subscribe(() => { + this.focusSelectedButton(); + }); } }); } + private focusSelectedButton() { + const selectedButton = this.elementRef.nativeElement.querySelector( + 'app-profile-item.selected .profile-item-container' + ); + if (selectedButton) { + selectedButton.focus(); + } else { + this.focusAddButton(); + } + } + + private focusAddButton(): void { + const addButton = + this.elementRef.nativeElement.querySelector('.add-entity-button'); + addButton?.focus(); + } + deleteCopy(copyOfProfile: Profile, profiles: Profile[]) { this.isCopyProfile = false; this.store.removeProfile(copyOfProfile.name, profiles); @@ -338,14 +361,15 @@ export class RiskAssessmentComponent } private setFocus(index: number): void { - const nextItem = window.document.querySelector( - `.profile-item-${index + 1}` - ) as HTMLElement; - const firstItem = window.document.querySelector( - `.profile-item-0` - ) as HTMLElement; - - this.store.setFocus({ nextItem, firstItem }); + const nextItem = this.elementRef.nativeElement.querySelectorAll( + 'app-profile-item .profile-item-info' + )[index]; + + if (nextItem) { + nextItem.focus(); + } else { + this.focusAddButton(); + } } private openSaveDialog( diff --git a/modules/ui/src/theming/mixins.scss b/modules/ui/src/theming/mixins.scss index ba402bd1d..5910e5deb 100644 --- a/modules/ui/src/theming/mixins.scss +++ b/modules/ui/src/theming/mixins.scss @@ -95,11 +95,11 @@ left: 32px; bottom: 25px; display: flex; + flex-wrap: wrap; align-items: center; gap: 10px; justify-content: space-between; width: calc(100% - 64px); - height: 80px; padding: 16px; box-sizing: border-box; background: colors.$surface;