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
@@ -9,8 +9,8 @@
</button>
@if (canViewSystemStatus) {
<button class="btn btn-sm btn-outline-primary position-relative ms-md-5 me-1" (click)="showSystemStatus()"
[disabled]="!systemStatus">
@if (!systemStatus) {
[disabled]="!systemStatus()">
@if (!systemStatus()) {
<div class="spinner-border spinner-border-sm me-2 h-75" role="status"></div>
} @else {
<i-bs class="me-2" name="card-checklist"></i-bs>
@@ -313,7 +313,7 @@
<span i18n>Default Owner</span>
</div>
<div class="col-md-5">
<pngx-input-select [items]="users" bindLabel="username" formControlName="defaultPermsOwner" [allowNull]="true"></pngx-input-select>
<pngx-input-select [items]="users()" bindLabel="username" formControlName="defaultPermsOwner" [allowNull]="true"></pngx-input-select>
<small class="form-text text-muted text-end d-block mt-n2" i18n>Objects without an owner can be viewed and edited by all users</small>
</div>
</div>
@@ -99,6 +99,13 @@ const status: SystemStatus = {
llmindex_status: SystemStatusItemStatus.DISABLED,
llmindex_last_modified: new Date().toISOString(),
llmindex_error: null,
summary: {
days: 30,
total_count: 12,
pending_count: 1,
success_count: 10,
failure_count: 1,
},
},
}
@@ -161,7 +168,7 @@ describe('SettingsComponent', () => {
viewportScroller = TestBed.inject(ViewportScroller)
toastService = TestBed.inject(ToastService)
settingsService = TestBed.inject(SettingsService)
settingsService.currentUser = users[0]
settingsService.currentUser.set(users[0])
userService = TestBed.inject(UserService)
permissionsService = TestBed.inject(PermissionsService)
modalService = TestBed.inject(NgbModal)
@@ -202,7 +209,7 @@ describe('SettingsComponent', () => {
fixture.detectChanges()
}
it('should support tabbed settings & change URL, prevent navigation if dirty confirmation rejected', () => {
it('should support tabbed settings & change URL, prevent navigation if dirty confirmation rejected', async () => {
completeSetup()
const navigateSpy = jest.spyOn(router, 'navigate')
const tabButtons = fixture.debugElement.queryAll(By.directive(NgbNavLink))
@@ -210,16 +217,19 @@ describe('SettingsComponent', () => {
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'documents'])
tabButtons[2].nativeElement.dispatchEvent(new MouseEvent('click'))
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'permissions'])
await fixture.whenStable()
const initSpy = jest.spyOn(component, 'initialize')
component.isDirty = true // mock dirty
navigateSpy.mockResolvedValueOnce(false) // nav rejected cause dirty
tabButtons[0].nativeElement.dispatchEvent(new MouseEvent('click'))
await fixture.whenStable()
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'general'])
expect(initSpy).not.toHaveBeenCalled()
navigateSpy.mockResolvedValueOnce(true) // nav accepted even though dirty
tabButtons[2].nativeElement.dispatchEvent(new MouseEvent('click'))
await fixture.whenStable()
expect(navigateSpy).toHaveBeenCalledWith(['settings', 'permissions'])
expect(initSpy).toHaveBeenCalled()
})
@@ -340,13 +350,13 @@ describe('SettingsComponent', () => {
type === PermissionType.SystemMonitoring
)
completeSetup()
expect(component['systemStatus']).toEqual(status) // private
expect(component.systemStatus()).toEqual(status)
expect(component.systemStatusHasErrors).toBeTruthy()
// coverage
component['systemStatus'].database.status = SystemStatusItemStatus.OK
component['systemStatus'].tasks.redis_status = SystemStatusItemStatus.OK
component['systemStatus'].tasks.celery_status = SystemStatusItemStatus.OK
component['systemStatus'].tasks.sanity_check_status =
component.systemStatus().database.status = SystemStatusItemStatus.OK
component.systemStatus().tasks.redis_status = SystemStatusItemStatus.OK
component.systemStatus().tasks.celery_status = SystemStatusItemStatus.OK
component.systemStatus().tasks.sanity_check_status =
SystemStatusItemStatus.OK
expect(component.systemStatusHasErrors).toBeFalsy()
})
@@ -6,6 +6,7 @@ import {
OnDestroy,
OnInit,
inject,
signal,
} from '@angular/core'
import {
FormControl,
@@ -189,10 +190,10 @@ export class SettingsComponent
unsubscribeNotifier: Subject<any> = new Subject()
savePending: boolean = false
users: User[]
groups: Group[]
readonly users = signal<User[]>(undefined)
readonly groups = signal<Group[]>(undefined)
public systemStatus: SystemStatus
public readonly systemStatus = signal<SystemStatus>(undefined)
public readonly GlobalSearchType = GlobalSearchType
@@ -203,16 +204,18 @@ export class SettingsComponent
public readonly documentDetailFieldOptions = documentDetailFieldOptions
get systemStatusHasErrors(): boolean {
const status = this.systemStatus()
if (!status) {
return false
}
return (
this.systemStatus.database.status === SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.redis_status === SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.celery_status === SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.index_status === SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.classifier_status ===
SystemStatusItemStatus.ERROR ||
this.systemStatus.tasks.sanity_check_status ===
SystemStatusItemStatus.ERROR ||
this.systemStatus.websocket_connected === SystemStatusItemStatus.ERROR
status.database.status === SystemStatusItemStatus.ERROR ||
status.tasks.redis_status === SystemStatusItemStatus.ERROR ||
status.tasks.celery_status === SystemStatusItemStatus.ERROR ||
status.tasks.index_status === SystemStatusItemStatus.ERROR ||
status.tasks.classifier_status === SystemStatusItemStatus.ERROR ||
status.tasks.sanity_check_status === SystemStatusItemStatus.ERROR ||
status.websocket_connected === SystemStatusItemStatus.ERROR
)
}
@@ -246,7 +249,7 @@ export class SettingsComponent
.pipe(first())
.subscribe({
next: (r) => {
this.users = r.results
this.users.set(r.results)
},
error: (e) => {
this.toastService.showError($localize`Error retrieving users`, e)
@@ -265,7 +268,7 @@ export class SettingsComponent
.pipe(first())
.subscribe({
next: (r) => {
this.groups = r.results
this.groups.set(r.results)
},
error: (e) => {
this.toastService.showError($localize`Error retrieving groups`, e)
@@ -431,7 +434,7 @@ export class SettingsComponent
if (this.canViewSystemStatus) {
this.systemStatusService.get().subscribe((status) => {
this.systemStatus = status
this.systemStatus.set(status)
})
}
}
@@ -664,6 +667,6 @@ export class SettingsComponent
size: 'xl',
}
)
modal.componentInstance.status = this.systemStatus
modal.componentInstance.status.set(this.systemStatus())
}
}