From 93338a0a823b262a4cf7a6cd09f4691146964f34 Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Fri, 21 Nov 2025 15:52:12 -0800 Subject: [PATCH] Fixhancement: more log viewer improvements (#11426) --- src-ui/setup-jest.ts | 4 ++ .../components/admin/logs/logs.component.html | 24 ++++++------ .../components/admin/logs/logs.component.scss | 16 ++++++-- .../admin/logs/logs.component.spec.ts | 7 ++++ .../components/admin/logs/logs.component.ts | 39 +++++++++++++------ 5 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src-ui/setup-jest.ts b/src-ui/setup-jest.ts index c7bcabddb..df5e9d175 100644 --- a/src-ui/setup-jest.ts +++ b/src-ui/setup-jest.ts @@ -145,6 +145,10 @@ HTMLCanvasElement.prototype.getContext = < typeof HTMLCanvasElement.prototype.getContext >jest.fn() +if (!HTMLElement.prototype.scrollTo) { + HTMLElement.prototype.scrollTo = jest.fn() +} + jest.mock('uuid', () => ({ v4: jest.fn(() => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (char: string) => { diff --git a/src-ui/src/app/components/admin/logs/logs.component.html b/src-ui/src/app/components/admin/logs/logs.component.html index 70dcda86d..b3df5ff89 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.html +++ b/src-ui/src/app/components/admin/logs/logs.component.html @@ -41,21 +41,21 @@ } -
- - +
@if (loading && !logFiles.length) {
Loading...
+ } @else { +

{{log.message}}

} -

- {{log.message}} -

- +
+ diff --git a/src-ui/src/app/components/admin/logs/logs.component.scss b/src-ui/src/app/components/admin/logs/logs.component.scss index 56fd2e8f3..25ab0b8ac 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.scss +++ b/src-ui/src/app/components/admin/logs/logs.component.scss @@ -16,11 +16,21 @@ } .log-container { - overflow-y: scroll; - height: calc(100vh - 200px); - top: 0; + height: calc(100vh - 190px); + overflow-y: auto; p { white-space: pre-wrap; } } + +.jump-to-bottom { + opacity: 0; + pointer-events: none; + transition: opacity 120ms ease-in-out; +} + +.jump-to-bottom.visible { + opacity: 1; + pointer-events: auto; +} diff --git a/src-ui/src/app/components/admin/logs/logs.component.spec.ts b/src-ui/src/app/components/admin/logs/logs.component.spec.ts index 728916830..1b8425427 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.spec.ts +++ b/src-ui/src/app/components/admin/logs/logs.component.spec.ts @@ -110,4 +110,11 @@ describe('LogsComponent', () => { jest.advanceTimersByTime(1) expect(reloadSpy).toHaveBeenCalledTimes(initialCalls + 1) }) + + it('should update jump to bottom visibility on scroll', () => { + component.showJumpToBottom = false + jest.spyOn(component as any, 'isNearBottom').mockReturnValue(false) + component.onScroll() + expect(component.showJumpToBottom).toBe(true) + }) }) diff --git a/src-ui/src/app/components/admin/logs/logs.component.ts b/src-ui/src/app/components/admin/logs/logs.component.ts index 68b88265d..e186b27b0 100644 --- a/src-ui/src/app/components/admin/logs/logs.component.ts +++ b/src-ui/src/app/components/admin/logs/logs.component.ts @@ -1,11 +1,8 @@ -import { - CdkVirtualScrollViewport, - ScrollingModule, -} from '@angular/cdk/scrolling' import { CommonModule } from '@angular/common' import { ChangeDetectorRef, Component, + ElementRef, OnDestroy, OnInit, ViewChild, @@ -28,8 +25,6 @@ import { LoadingComponentWithPermissions } from '../../loading-component/loading CommonModule, FormsModule, ReactiveFormsModule, - CdkVirtualScrollViewport, - ScrollingModule, ], }) export class LogsComponent @@ -49,9 +44,11 @@ export class LogsComponent public limit: number = 5000 + public showJumpToBottom = false + private readonly limitChange$ = new Subject() - @ViewChild('logContainer') logContainer: CdkVirtualScrollViewport + @ViewChild('logContainer') logContainer: ElementRef ngOnInit(): void { this.limitChange$ @@ -89,6 +86,7 @@ export class LogsComponent reloadLogs() { this.loading = true + const shouldStickToBottom = this.isNearBottom() this.logService .get(this.activeLog, this.limit) .pipe(takeUntil(this.unsubscribeNotifier)) @@ -108,7 +106,10 @@ export class LogsComponent }) if (hasChanges) { this.logs = parsed - this.scrollToBottom() + if (shouldStickToBottom) { + this.scrollToBottom() + } + this.showJumpToBottom = !shouldStickToBottom } }, error: () => { @@ -142,9 +143,25 @@ export class LogsComponent } scrollToBottom(): void { - this.changedetectorRef.detectChanges() - if (this.logContainer) { - this.logContainer.scrollToIndex(this.logs.length - 1) + const viewport = this.logContainer?.nativeElement + if (!viewport) { + return } + this.changedetectorRef.detectChanges() + viewport.scrollTop = viewport.scrollHeight + this.showJumpToBottom = false + } + + private isNearBottom(): boolean { + if (!this.logContainer?.nativeElement) return true + const distanceFromBottom = + this.logContainer.nativeElement.scrollHeight - + this.logContainer.nativeElement.scrollTop - + this.logContainer.nativeElement.clientHeight + return distanceFromBottom <= 40 + } + + onScroll(): void { + this.showJumpToBottom = !this.isNearBottom() } }