Chorehancement: update to Angular v22, 'zoneless' / 'reactive' (#13114)

This commit is contained in:
shamoon
2026-07-10 00:42:16 -07:00
committed by GitHub
parent f244442c65
commit 106b41a15c
213 changed files with 5363 additions and 5842 deletions
@@ -31,7 +31,7 @@
</div>
</div>
<pngx-input-select i18n-title title="Groups" [items]="groups" multiple="true" formControlName="groups"></pngx-input-select>
<pngx-input-select i18n-title title="Groups" [items]="groups()" multiple="true" formControlName="groups"></pngx-input-select>
@if (object?.is_mfa_enabled && currentUserIsSuperUser) {
<label class="form-label" i18n>Two-factor Authentication</label>
@@ -42,7 +42,7 @@
i18n-title
buttonClasses="btn-outline-danger btn-sm"
iconName="trash"
[disabled]="totpLoading"
[disabled]="totpLoading()"
(confirm)="deactivateTotp()">
</pngx-confirm-button>
}
@@ -73,7 +73,7 @@ describe('UserEditDialogComponent', () => {
fixture = TestBed.createComponent(UserEditDialogComponent)
settingsService = TestBed.inject(SettingsService)
settingsService.currentUser = { id: 99, username: 'user99' }
settingsService.currentUser.set({ id: 99, username: 'user99' })
permissionsService = TestBed.inject(PermissionsService)
toastService = TestBed.inject(ToastService)
component = fixture.componentInstance
@@ -82,13 +82,13 @@ describe('UserEditDialogComponent', () => {
})
it('should support create and edit modes', () => {
component.dialogMode = EditDialogMode.CREATE
component.dialogMode.set(EditDialogMode.CREATE)
const createTitleSpy = jest.spyOn(component, 'getCreateTitle')
const editTitleSpy = jest.spyOn(component, 'getEditTitle')
fixture.detectChanges()
expect(createTitleSpy).toHaveBeenCalled()
expect(editTitleSpy).not.toHaveBeenCalled()
component.dialogMode = EditDialogMode.EDIT
component.dialogMode.set(EditDialogMode.EDIT)
fixture.detectChanges()
expect(editTitleSpy).toHaveBeenCalled()
})
@@ -114,17 +114,17 @@ describe('UserEditDialogComponent', () => {
it('should detect whether password was changed in form on save', () => {
component.objectForm.get('password').setValue(null)
component.save()
expect(component.passwordIsSet).toBeFalsy()
expect(component.passwordIsSet()).toBeFalsy()
// unchanged pw
component.objectForm.get('password').setValue('*******')
component.save()
expect(component.passwordIsSet).toBeFalsy()
expect(component.passwordIsSet()).toBeFalsy()
// unchanged pw
component.objectForm.get('password').setValue('helloworld')
component.save()
expect(component.passwordIsSet).toBeTruthy()
expect(component.passwordIsSet()).toBeTruthy()
})
it('should support deactivation of TOTP', () => {
@@ -1,11 +1,12 @@
import { Component, OnInit, inject } from '@angular/core'
import { Component, OnInit, inject, signal } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import {
FormControl,
FormGroup,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms'
import { first } from 'rxjs'
import { first, map } from 'rxjs'
import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component'
import { Group } from 'src/app/data/group'
import { User } from 'src/app/data/user'
@@ -38,22 +39,19 @@ export class UserEditDialogComponent
implements OnInit
{
private toastService = inject(ToastService)
private groupsService: GroupService
private readonly groupsService = inject(GroupService)
groups: Group[]
passwordIsSet: boolean = false
public totpLoading: boolean = false
readonly groups = toSignal(
this.groupsService.listAll().pipe(map((result) => result.results)),
{ initialValue: undefined as Group[] }
)
readonly passwordIsSet = signal(false)
readonly totpLoading = signal(false)
constructor() {
super()
this.service = inject(UserService)
this.groupsService = inject(GroupService)
this.settingsService = inject(SettingsService)
this.groupsService
.listAll()
.pipe(first())
.subscribe((result) => (this.groups = result.results))
}
ngOnInit(): void {
@@ -103,14 +101,15 @@ export class UserEditDialogComponent
if (!groupsVal) return []
else
return groupsVal.flatMap(
(id) => this.groups.find((g) => g.id == id)?.permissions
(id) => this.groups()?.find((g) => g.id == id)?.permissions
)
}
save(): void {
this.passwordIsSet =
this.passwordIsSet.set(
this.objectForm.get('password').value?.toString().replaceAll('*', '')
.length > 0
)
super.save()
}
@@ -119,13 +118,13 @@ export class UserEditDialogComponent
}
deactivateTotp() {
this.totpLoading = true
this.totpLoading.set(true)
;(this.service as UserService)
.deactivateTotp(this.object)
.pipe(first())
.subscribe({
next: (result) => {
this.totpLoading = false
this.totpLoading.set(false)
if (result) {
this.toastService.showInfo($localize`Totp deactivated`)
this.object.is_mfa_enabled = false
@@ -134,7 +133,7 @@ export class UserEditDialogComponent
}
},
error: (e) => {
this.totpLoading = false
this.totpLoading.set(false)
this.toastService.showError($localize`Totp deactivation failed`, e)
},
})