More direct signals conversion

This commit is contained in:
shamoon
2026-07-08 12:58:40 -07:00
parent 0ed4f3cba6
commit b7836d7cfd
11 changed files with 45 additions and 87 deletions
@@ -11,19 +11,19 @@
type="number"
min="100"
step="100"
[(ngModel)]="limit"
(ngModelChange)="onLimitChange($event)"
[ngModel]="limit()"
(ngModelChange)="limit.set($event); onLimitChange($event)"
style="width: 100px;">
<span class="input-group-text text-muted" i18n>lines</span>
</div>
<div class="form-check form-switch mt-1">
<input class="form-check-input" type="checkbox" role="switch" [(ngModel)]="autoRefreshEnabled">
<input class="form-check-input" type="checkbox" role="switch" [ngModel]="autoRefreshEnabled()" (ngModelChange)="autoRefreshEnabled.set($event)">
<label class="form-check-label" for="autoRefreshSwitch" i18n>Auto refresh</label>
</div>
</div>
</pngx-page-header>
<ul ngbNav #nav="ngbNav" [(activeId)]="activeLog" (activeIdChange)="reloadLogs()" class="nav-tabs">
<ul ngbNav #nav="ngbNav" [activeId]="activeLog()" (activeIdChange)="activeLog.set($event); reloadLogs()" class="nav-tabs">
@for (logFile of logFiles(); track logFile) {
<li [ngbNavItem]="logFile">
<a ngbNavLink>
@@ -86,7 +86,7 @@ describe('LogsComponent', () => {
throwError(() => new Error('error getting logs'))
)
component.reloadLogs()
expect(component.logs).toHaveLength(0)
expect(component.logs()).toHaveLength(0)
})
it('should auto refresh, allow toggle', () => {
@@ -97,7 +97,7 @@ describe('LogsComponent', () => {
jest.advanceTimersByTime(6000)
expect(reloadSpy).toHaveBeenCalledTimes(2)
component.autoRefreshEnabled = false
component.autoRefreshEnabled.set(false)
jest.advanceTimersByTime(6000)
expect(reloadSpy).toHaveBeenCalledTimes(2)
})
@@ -112,9 +112,9 @@ describe('LogsComponent', () => {
})
it('should update jump to bottom visibility on scroll', () => {
component.showJumpToBottom = false
component.showJumpToBottom.set(false)
jest.spyOn(component as any, 'isNearBottom').mockReturnValue(false)
component.onScroll()
expect(component.showJumpToBottom).toBe(true)
expect(component.showJumpToBottom()).toBe(true)
})
})
@@ -35,17 +35,17 @@ export class LogsComponent
private logService = inject(LogService)
private changedetectorRef = inject(ChangeDetectorRef)
private readonly logs = signal<Array<{ message: string; level: number }>>([])
readonly logs = signal<Array<{ message: string; level: number }>>([])
private readonly logFiles = signal<string[]>([])
readonly logFiles = signal<string[]>([])
private readonly activeLog = signal<string>(undefined)
readonly activeLog = signal<string>(undefined)
private readonly autoRefreshEnabled = signal<boolean>(true)
readonly autoRefreshEnabled = signal<boolean>(true)
private readonly limit = signal<number>(5000)
readonly limit = signal<number>(5000)
private readonly showJumpToBottom = signal<boolean>(false)
readonly showJumpToBottom = signal<boolean>(false)
private readonly limitChange$ = new Subject<number>()
@@ -7,7 +7,7 @@
>
</pngx-page-header>
@if (canViewUsers && users) {
@if (canViewUsers && users()) {
<h4 class="d-flex">
<ng-container i18n>Users</ng-container>
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editUser()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.User }">
@@ -23,7 +23,7 @@
<div class="col" i18n>Actions</div>
</div>
</li>
@for (user of users; track user) {
@for (user of users(); track user) {
<li class="list-group-item">
<div class="row">
<div class="col d-flex align-items-center" [class.opacity-50]="!user.is_active"><button class="btn btn-link p-0 text-start" type="button" (click)="editUser(user)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.User)">{{user.username}}</button></div>
@@ -45,7 +45,7 @@
</ul>
}
@if (canViewGroups && groups) {
@if (canViewGroups && groups()) {
<h4 class="mt-4 d-flex">
<ng-container i18n>Groups</ng-container>
<button type="button" class="btn btn-sm btn-outline-primary ms-4" (click)="editGroup()" *pngxIfPermissions="{ action: PermissionAction.Add, type: PermissionType.Group }">
@@ -61,7 +61,7 @@
<div class="col" i18n>Actions</div>
</div>
</li>
@for (group of groups; track group) {
@for (group of groups(); track group) {
<li class="list-group-item">
<div class="row">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editGroup(group)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.Group)">{{group.name}}</button></div>
@@ -80,13 +80,13 @@
</div>
</li>
}
@if (groups.length === 0) {
@if (groups().length === 0) {
<li class="list-group-item" i18n>No groups defined</li>
}
</ul>
}
@if ((canViewUsers && !users) || (canViewGroups && !groups)) {
@if ((canViewUsers && !users()) || (canViewGroups && !groups())) {
<div>
<div class="spinner-border spinner-border-sm fw-normal ms-2 me-auto" role="status"></div>
<div class="visually-hidden" i18n>Loading...</div>
@@ -43,24 +43,8 @@ export class UsersAndGroupsComponent
permissionsService = inject(PermissionsService)
private settings = inject(SettingsService)
private usersSignal = signal<User[]>(null)
private groupsSignal = signal<Group[]>(null)
get users(): User[] {
return this.usersSignal()
}
set users(value: User[]) {
this.usersSignal.set(value)
}
get groups(): Group[] {
return this.groupsSignal()
}
set groups(value: Group[]) {
this.groupsSignal.set(value)
}
readonly users = signal<User[]>(null)
readonly groups = signal<Group[]>(null)
unsubscribeNotifier: Subject<any> = new Subject()
@@ -85,7 +69,7 @@ export class UsersAndGroupsComponent
.pipe(first(), takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (r) => {
this.users = r.results
this.users.set(r.results)
},
error: (e) => {
this.toastService.showError($localize`Error retrieving users`, e)
@@ -99,7 +83,7 @@ export class UsersAndGroupsComponent
.pipe(first(), takeUntil(this.unsubscribeNotifier))
.subscribe({
next: (r) => {
this.groups = r.results
this.groups.set(r.results)
},
error: (e) => {
this.toastService.showError($localize`Error retrieving groups`, e)
@@ -141,7 +125,7 @@ export class UsersAndGroupsComponent
$localize`Saved user "${newUser.username}".`
)
this.usersService.listAll().subscribe((r) => {
this.users = r.results
this.users.set(r.results)
})
}
})
@@ -168,7 +152,7 @@ export class UsersAndGroupsComponent
modal.close()
this.toastService.showInfo($localize`Deleted user "${user.username}"`)
this.usersService.listAll().subscribe((r) => {
this.users = r.results
this.users.set(r.results)
})
},
error: (e) => {
@@ -195,7 +179,7 @@ export class UsersAndGroupsComponent
.subscribe((newGroup) => {
this.toastService.showInfo($localize`Saved group "${newGroup.name}".`)
this.groupsService.listAll().subscribe((r) => {
this.groups = r.results
this.groups.set(r.results)
})
})
modal.componentInstance.failed
@@ -221,7 +205,7 @@ export class UsersAndGroupsComponent
modal.close()
this.toastService.showInfo($localize`Deleted group "${group.name}"`)
this.groupsService.listAll().subscribe((r) => {
this.groups = r.results
this.groups.set(r.results)
})
},
error: (e) => {
@@ -235,6 +219,6 @@ export class UsersAndGroupsComponent
}
getGroupName(id: number): string {
return this.groups?.find((g) => g.id === id)?.name ?? ''
return this.groups()?.find((g) => g.id === id)?.name ?? ''
}
}
@@ -45,7 +45,7 @@
</div>
</div>
}
@for (v of dashboardViews; track v.id) {
@for (v of dashboardViews(); track v.id) {
<div class="col">
<pngx-saved-view-widget
[savedView]="v"
@@ -47,20 +47,12 @@ export class DashboardComponent extends ComponentWithPermissions {
private tourService = inject(TourService)
private toastService = inject(ToastService)
private dashboardViewsSignal = signal<SavedView[]>([])
get dashboardViews(): SavedView[] {
return this.dashboardViewsSignal()
}
set dashboardViews(value: SavedView[]) {
this.dashboardViewsSignal.set(value)
}
readonly dashboardViews = signal<SavedView[]>([])
constructor() {
super()
this.savedViewService.listAll().subscribe(() => {
this.dashboardViews = this.savedViewService.dashboardViews
this.dashboardViews.set(this.savedViewService.dashboardViews)
})
}
@@ -89,14 +81,12 @@ export class DashboardComponent extends ComponentWithPermissions {
}
onDrop(event: CdkDragDrop<SavedView[]>) {
moveItemInArray(
this.dashboardViews,
event.previousIndex,
event.currentIndex
)
const dashboardViews = [...this.dashboardViews()]
moveItemInArray(dashboardViews, event.previousIndex, event.currentIndex)
this.dashboardViews.set(dashboardViews)
this.settingsService
.updateDashboardViewsSort(this.dashboardViews)
.updateDashboardViewsSort(this.dashboardViews())
.subscribe({
next: () => {
this.toastService.showInfo($localize`Dashboard updated`)
@@ -15,7 +15,7 @@
</li>
}
@for (field of fields; track field) {
@for (field of fields(); track field) {
<li class="list-group-item">
<div class="row fade" [class.show]="show">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editField(field)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.CustomField)">{{field.name}}</button></div>
@@ -64,7 +64,7 @@
</div>
</li>
}
@if (!loading && fields.length === 0) {
@if (!loading && fields().length === 0) {
<li class="list-group-item" i18n>No fields defined.</li>
}
</ul>
@@ -51,15 +51,7 @@ export class CustomFieldsComponent
private readonly documentService = inject(DocumentService)
private readonly savedViewService = inject(SavedViewService)
private fieldsSignal = signal<CustomField[]>([])
public get fields(): CustomField[] {
return this.fieldsSignal()
}
public set fields(fields: CustomField[]) {
this.fieldsSignal.set(fields)
}
readonly fields = signal<CustomField[]>([])
ngOnInit() {
this.reload()
@@ -72,7 +64,7 @@ export class CustomFieldsComponent
.pipe(
takeUntil(this.unsubscribeNotifier),
tap((r) => {
this.fields = r.results
this.fields.set(r.results)
})
)
.subscribe(() => {
@@ -22,14 +22,14 @@
</div>
</li>
@if (loading && workflows.length === 0) {
@if (loading && workflows().length === 0) {
<li class="list-group-item">
<div class="spinner-border spinner-border-sm me-2" role="status"></div>
<ng-container i18n>Loading...</ng-container>
</li>
}
@for (workflow of workflows; track workflow.id) {
@for (workflow of workflows(); track workflow.id) {
<li class="list-group-item">
<div class="row fade" [class.show]="show">
<div class="col d-flex align-items-center"><button class="btn btn-link p-0 text-start" type="button" (click)="editWorkflow(workflow)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.Workflow)">{{workflow.name}}</button></div>
@@ -76,7 +76,7 @@
</div>
</li>
}
@if (!loading && workflows.length === 0) {
@if (!loading && workflows().length === 0) {
<li class="list-group-item" [class.show]="show" i18n>No workflows defined.</li>
}
</ul>
@@ -39,15 +39,7 @@ export class WorkflowsComponent
private modalService = inject(NgbModal)
private toastService = inject(ToastService)
private workflowsSignal = signal<Workflow[]>([])
public get workflows(): Workflow[] {
return this.workflowsSignal()
}
public set workflows(workflows: Workflow[]) {
this.workflowsSignal.set(workflows)
}
readonly workflows = signal<Workflow[]>([])
ngOnInit() {
this.reload()
@@ -59,7 +51,7 @@ export class WorkflowsComponent
.listAll()
.pipe(
takeUntil(this.unsubscribeNotifier),
tap((r) => (this.workflows = r.results))
tap((r) => this.workflows.set(r.results))
)
.subscribe(() => {
this.show = true