diff --git a/webui/index.html b/webui/index.html
index dd8c19c..0a9cc26 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -35,9 +35,13 @@
+
+
+
+
-
+
| Timestamp |
Log |
Exit Code |
diff --git a/webui/js/marshaller.js b/webui/js/marshaller.js
index 1ef96fc..65b8677 100644
--- a/webui/js/marshaller.js
+++ b/webui/js/marshaller.js
@@ -30,7 +30,7 @@ export function marshalActionButtonsJsonToHtml (json) {
export function marshalLogsJsonToHtml (json) {
for (const logEntry of json.logs) {
const tpl = document.getElementById('tplLogRow')
- const row = tpl.content.cloneNode(true)
+ const row = tpl.content.querySelector('tr').cloneNode(true)
if (logEntry.stdout.length === 0) {
logEntry.stdout = '(empty)'
@@ -56,6 +56,7 @@ export function marshalLogsJsonToHtml (json) {
row.querySelector('pre.stdout').innerText = logEntry.stdout
row.querySelector('pre.stderr').innerText = logEntry.stderr
row.querySelector('.exit-code').innerText = logTableExitCode
+ row.setAttribute('title', logEntry.actionTitle)
for (const tag of logEntry.tags) {
const domTag = document.createElement('span')
diff --git a/webui/main.js b/webui/main.js
index 0cd6ea1..ebab0e3 100644
--- a/webui/main.js
+++ b/webui/main.js
@@ -3,6 +3,27 @@
import { marshalActionButtonsJsonToHtml, marshalLogsJsonToHtml } from './js/marshaller.js'
import { checkWebsocketConnection } from './js/websocket.js'
+function searchLogs (e) {
+ document.getElementById('searchLogsClear').disabled = false
+
+ const searchText = e.target.value.toLowerCase()
+
+ for (const row of document.querySelectorAll('tr.log-row')) {
+ const actionTitle = row.getAttribute('title').toLowerCase()
+
+ row.hidden = !actionTitle.includes(searchText)
+ }
+}
+
+function searchLogsClear () {
+ for (const row of document.querySelectorAll('tr.log-row')) {
+ row.hidden = false
+ }
+
+ document.getElementById('searchLogsClear').disabled = true
+ document.getElementById('logSearchBox').value = ''
+}
+
function showSection (name) {
for (const otherName of ['Actions', 'Logs']) {
document.getElementById('show' + otherName).classList.remove('activeSection')
@@ -22,6 +43,11 @@ function setupSections () {
showSection('Actions')
}
+function setupLogSearchBox () {
+ document.getElementById('logSearchBox').oninput = searchLogs
+ document.getElementById('searchLogsClear').onclick = searchLogsClear
+}
+
function refreshLoop () {
if (window.websocketAvailable) {
// Websocket updates are streamed live, not updated on a loop.
@@ -117,6 +143,7 @@ function processWebuiSettingsJson (settings) {
function main () {
setupSections()
+ setupLogSearchBox()
window.fetch('webUiSettings.json').then(res => {
return res.json()
diff --git a/webui/style.css b/webui/style.css
index 0b58c5b..82a06aa 100644
--- a/webui/style.css
+++ b/webui/style.css
@@ -232,9 +232,9 @@ action-button details summary div span:first-child {
padding: 0.2em;
background-color: #efefef;
border-top: 0;
- border-left: 1px solid #999;
- border-right: 1px solid #999;
- border-bottom: 1px solid #999;
+ border-left: 1px solid #666;
+ border-right: 1px solid #666;
+ border-bottom: 1px solid #666;
}
execution-button button {
@@ -404,6 +404,20 @@ span.tag {
padding: 0.2em;
}
+div.toolbar {
+ padding: .4em;
+ text-align: left;
+ background-color: #efefef;
+ border: 1px solid #999;
+ border-bottom: 0;
+ display: flex;
+ flex-direction: row;
+}
+
+div.toolbar * {
+ margin-right: 1em;
+}
+
@media (prefers-color-scheme: dark) {
body {
background-color: #333;
@@ -472,4 +486,8 @@ span.tag {
tr:hover td {
background-color: #666;
}
+
+ div.toolbar {
+ background-color: black;
+ }
}