fix(logs): preserve manual follow state and hide filtered lines

This commit is contained in:
Andras Bacsai
2026-08-13 15:04:01 +02:00
parent 3bcef578de
commit 447a26568e
4 changed files with 34 additions and 2 deletions
+4
View File
@@ -3209,6 +3209,10 @@ html[data-theme="custom"] .logs-viewer-timestamp {
padding-block: 0.125rem;
}
.logs-viewer-line.hidden {
display: none;
}
.logs-viewer-timestamp {
flex-shrink: 0;
font-size: 0.625rem;
@@ -17,6 +17,7 @@
<div x-data="{
fullscreen: @entangle('fullscreen'),
alwaysScroll: {{ $isKeepAliveOn ? 'true' : 'false' }},
followManuallyDisabled: false,
rafId: null,
scrollTimeout: null,
scrollDebounce: null,
@@ -90,7 +91,7 @@
this.scrollDebounce = setTimeout(() => {
if (this.destroyed) return;
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
if (!this.alwaysScroll && distanceFromBottom <= 10) {
if (!this.alwaysScroll && !this.followManuallyDisabled && distanceFromBottom <= 10) {
this.alwaysScroll = true;
this.scheduleScroll();
}
@@ -109,8 +110,10 @@
toggleScroll() {
this.alwaysScroll = !this.alwaysScroll;
if (this.alwaysScroll) {
this.followManuallyDisabled = false;
this.scheduleScroll();
} else {
this.followManuallyDisabled = true;
this.cancelScrollLoop();
}
},
@@ -5,6 +5,7 @@
logsLoaded: false,
fullscreen: false,
alwaysScroll: false,
followManuallyDisabled: false,
rafId: null,
scrollDebounce: null,
colorLogs: localStorage.getItem('coolify-color-logs') === 'true',
@@ -80,8 +81,10 @@
toggleScroll() {
this.alwaysScroll = !this.alwaysScroll;
if (this.alwaysScroll) {
this.followManuallyDisabled = false;
this.scheduleScroll();
} else {
this.followManuallyDisabled = true;
if (this.rafId) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
@@ -94,7 +97,7 @@
this.scrollDebounce = setTimeout(() => {
const el = event.target;
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
if (!this.alwaysScroll && distanceFromBottom <= 10) {
if (!this.alwaysScroll && !this.followManuallyDisabled && distanceFromBottom <= 10) {
this.alwaysScroll = true;
this.scheduleScroll();
}
@@ -23,3 +23,25 @@ test('deployment logs use light surfaces in light mode and dark surfaces in dark
->toMatch('/\.logs-viewer\s*\{[^}]*background:\s*#fff;[^}]*color:\s*#262626;/s')
->toMatch('/\.dark \.logs-viewer\s*\{[^}]*background:\s*var\(--color-log\);/s');
});
test('log search hides lines that do not match', function () {
$styles = file_get_contents(resource_path('css/app.css'));
expect($styles)
->toMatch('/\.logs-viewer-line\.hidden\s*\{[^}]*display:\s*none;/s');
});
test('turning off follow logs stays off at the bottom of the log viewer', function () {
$views = [
resource_path('views/livewire/project/application/deployment/show.blade.php'),
resource_path('views/livewire/project/shared/get-logs.blade.php'),
];
foreach ($views as $view) {
expect(file_get_contents($view))
->toContain('followManuallyDisabled: false')
->toContain('!this.followManuallyDisabled && distanceFromBottom <= 10')
->toContain('this.followManuallyDisabled = true')
->toContain('this.followManuallyDisabled = false');
}
});