From 933fdc989efd678147fc61035ec8ad9f7233bf44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tina=20M=C3=BCller?= Date: Wed, 7 Aug 2024 17:59:53 +0200 Subject: [PATCH] Proof of Concept: Interactive log viewer Issue: https://progress.opensuse.org/issues/162218 --- assets/javascripts/test_result.js | 108 +++++++++++++++++++++++++- templates/webapi/test/logfile.html.ep | 4 +- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/assets/javascripts/test_result.js b/assets/javascripts/test_result.js index 63daaf2fb07e..ca28809f5948 100644 --- a/assets/javascripts/test_result.js +++ b/assets/javascripts/test_result.js @@ -578,14 +578,102 @@ function setupResult(jobid, state, result, status_url) { setInfoPanelClassName(state, result); } -function loadEmbeddedLogFiles() { +function delay(callback, ms) { + let timer = 0; + return function () { + const input = this; + const args = arguments; + clearTimeout(timer); + timer = setTimeout(function () { + callback.apply(input, args); + }, ms || 0); + }; +} + +function filterLogLines(input) { + if (input === undefined) { + return; + } + const string = input.value; + let regex = undefined; + const match = string.match(/^\/(.*)\/([i]*)$/); + if (match) { + regex = new RegExp(match[1], match[2]); + } + displaySearchInfo('Searching…'); + $('.embedded-logfile').each(function (index, logFileElement) { + let content = logFileElement.dataset.content; + if (content === undefined) { + return; + } + if (string.length > 0) { + const lines = content.split(/\r?\n/); + const wanted = []; + for (let i = 0; i < lines.length; i++) { + if (regex) { + if (lines[i].match(regex)) { + wanted.push(lines[i]); + } + continue; + } + if (lines[i].includes(string)) { + wanted.push(lines[i]); + } + } + content = wanted.join('\n'); + displaySearchInfo('Showing ' + wanted.length + ' / ' + lines.length + ' lines'); + } else { + displaySearchInfo(''); + } + logFileElement.innerHTML = ansiToHtml(content); + }); + const fullCurrentUrl = window.location.href; + const currentUrl = fullCurrentUrl.split('#')[0]; + const fragment = fullCurrentUrl.split('#')[1]; + if (string.length > 0) { + window.location.href = `${currentUrl}#filter=${encodeURIComponent(string)}`; + } else { + if (fragment) { + // leaving off the # here would reload the page + window.location.href = currentUrl + '#'; + } + } +} + +function filterEmbeddedLogFiles() { + const searchBox = document.getElementById('search-log-file'); + if (searchBox) { + const currentUrl = window.location.href; + const fragment = currentUrl.split('#')[1]; + if (fragment) { + const params = fragment.split('&'); + for (let i = 0; i < params.length; i++) { + const keyval = params[i].split('='); + if (keyval[0] === 'filter') { + searchBox.value = decodeURIComponent(keyval[1]); + } + } + } + } + const filter = function () { + filterLogLines(searchBox); + }; + loadEmbeddedLogFiles(filter); +} + +function loadEmbeddedLogFiles(filter) { $('.embedded-logfile').each(function (index, logFileElement) { if (logFileElement.dataset.contentsLoaded) { return; } $.ajax(logFileElement.dataset.src) .done(function (response) { - logFileElement.innerHTML = ansiToHtml(response); + logFileElement.dataset.content = response; + if (filter) { + filter(); + } else { + logFileElement.innerHTML = ansiToHtml(response); + } logFileElement.dataset.contentsLoaded = true; }) .fail(function (jqXHR, textStatus, errorThrown) { @@ -594,6 +682,22 @@ function loadEmbeddedLogFiles() { }); } +window.onload = function () { + const searchBox = document.getElementById('search-log-file'); + if (!searchBox) { + return; + } + const filter = function () { + filterLogLines(searchBox); + }; + searchBox.addEventListener('keyup', delay(filter), 1000); + searchBox.addEventListener('change', filter, false); +}; + +function displaySearchInfo(text) { + document.getElementById('search-info').innerHTML = text; +} + function setCurrentPreviewFromStepLinkIfPossible(stepLink) { if (tabConfiguration.details.hasContents && !stepLink.parent().is('.current_preview')) { setCurrentPreview(stepLink.parent()); diff --git a/templates/webapi/test/logfile.html.ep b/templates/webapi/test/logfile.html.ep index 24c7afb03ce2..7fa140034a26 100644 --- a/templates/webapi/test/logfile.html.ep +++ b/templates/webapi/test/logfile.html.ep @@ -5,11 +5,13 @@ %= asset $_ for qw(test_result.js anser.js ansi-colors.css) % end % content_for 'ready_function' => begin - loadEmbeddedLogFiles(); + filterEmbeddedLogFiles(); % end % my $url = url_for('test_file', testid => $testid, filename => $filename);
+ + Back to job <%= $testid %>