Feature search logs (#182)
* feature: search logs wip * feature: Log search
This commit is contained in:
parent
5739091773
commit
912fd8089e
|
|
@ -35,9 +35,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section id = "contentLogs" title = "Logs" hidden>
|
<section id = "contentLogs" title = "Logs" hidden>
|
||||||
|
<div class = "toolbar">
|
||||||
|
<input placeholder = "Search for action name" id = "logSearchBox" />
|
||||||
|
<button id = "searchLogsClear" title = "Clear search filter" disabled>X</button>
|
||||||
|
</div>
|
||||||
<table title = "Logs">
|
<table title = "Logs">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr title = "untitled">
|
||||||
<th>Timestamp</th>
|
<th>Timestamp</th>
|
||||||
<th>Log</th>
|
<th>Log</th>
|
||||||
<th>Exit Code</th>
|
<th>Exit Code</th>
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export function marshalActionButtonsJsonToHtml (json) {
|
||||||
export function marshalLogsJsonToHtml (json) {
|
export function marshalLogsJsonToHtml (json) {
|
||||||
for (const logEntry of json.logs) {
|
for (const logEntry of json.logs) {
|
||||||
const tpl = document.getElementById('tplLogRow')
|
const tpl = document.getElementById('tplLogRow')
|
||||||
const row = tpl.content.cloneNode(true)
|
const row = tpl.content.querySelector('tr').cloneNode(true)
|
||||||
|
|
||||||
if (logEntry.stdout.length === 0) {
|
if (logEntry.stdout.length === 0) {
|
||||||
logEntry.stdout = '(empty)'
|
logEntry.stdout = '(empty)'
|
||||||
|
|
@ -56,6 +56,7 @@ export function marshalLogsJsonToHtml (json) {
|
||||||
row.querySelector('pre.stdout').innerText = logEntry.stdout
|
row.querySelector('pre.stdout').innerText = logEntry.stdout
|
||||||
row.querySelector('pre.stderr').innerText = logEntry.stderr
|
row.querySelector('pre.stderr').innerText = logEntry.stderr
|
||||||
row.querySelector('.exit-code').innerText = logTableExitCode
|
row.querySelector('.exit-code').innerText = logTableExitCode
|
||||||
|
row.setAttribute('title', logEntry.actionTitle)
|
||||||
|
|
||||||
for (const tag of logEntry.tags) {
|
for (const tag of logEntry.tags) {
|
||||||
const domTag = document.createElement('span')
|
const domTag = document.createElement('span')
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,27 @@
|
||||||
import { marshalActionButtonsJsonToHtml, marshalLogsJsonToHtml } from './js/marshaller.js'
|
import { marshalActionButtonsJsonToHtml, marshalLogsJsonToHtml } from './js/marshaller.js'
|
||||||
import { checkWebsocketConnection } from './js/websocket.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) {
|
function showSection (name) {
|
||||||
for (const otherName of ['Actions', 'Logs']) {
|
for (const otherName of ['Actions', 'Logs']) {
|
||||||
document.getElementById('show' + otherName).classList.remove('activeSection')
|
document.getElementById('show' + otherName).classList.remove('activeSection')
|
||||||
|
|
@ -22,6 +43,11 @@ function setupSections () {
|
||||||
showSection('Actions')
|
showSection('Actions')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupLogSearchBox () {
|
||||||
|
document.getElementById('logSearchBox').oninput = searchLogs
|
||||||
|
document.getElementById('searchLogsClear').onclick = searchLogsClear
|
||||||
|
}
|
||||||
|
|
||||||
function refreshLoop () {
|
function refreshLoop () {
|
||||||
if (window.websocketAvailable) {
|
if (window.websocketAvailable) {
|
||||||
// Websocket updates are streamed live, not updated on a loop.
|
// Websocket updates are streamed live, not updated on a loop.
|
||||||
|
|
@ -117,6 +143,7 @@ function processWebuiSettingsJson (settings) {
|
||||||
|
|
||||||
function main () {
|
function main () {
|
||||||
setupSections()
|
setupSections()
|
||||||
|
setupLogSearchBox()
|
||||||
|
|
||||||
window.fetch('webUiSettings.json').then(res => {
|
window.fetch('webUiSettings.json').then(res => {
|
||||||
return res.json()
|
return res.json()
|
||||||
|
|
|
||||||
|
|
@ -232,9 +232,9 @@ action-button details summary div span:first-child {
|
||||||
padding: 0.2em;
|
padding: 0.2em;
|
||||||
background-color: #efefef;
|
background-color: #efefef;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-left: 1px solid #999;
|
border-left: 1px solid #666;
|
||||||
border-right: 1px solid #999;
|
border-right: 1px solid #666;
|
||||||
border-bottom: 1px solid #999;
|
border-bottom: 1px solid #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
execution-button button {
|
execution-button button {
|
||||||
|
|
@ -404,6 +404,20 @@ span.tag {
|
||||||
padding: 0.2em;
|
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) {
|
@media (prefers-color-scheme: dark) {
|
||||||
body {
|
body {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
|
|
@ -472,4 +486,8 @@ span.tag {
|
||||||
tr:hover td {
|
tr:hover td {
|
||||||
background-color: #666;
|
background-color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.toolbar {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue