Log Viewer: Add text mode option (#3177)

- Add an option to display the log in "Text mode" vs "Table mode".
- In Text Mode, the "Copy" button will copy the log as plain text. In
  Table Mode, the "Copy" button does what it used to do before.
- Hovering the mouse pointer over the log name reveals the full name
- Clicking on the log line still brings up the detail dialog
- You can select the text, and copy / paste it into a text file

---------

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
pull/3192/head
jimtng 2025-05-16 19:49:43 +10:00 committed by GitHub
parent 1ae5fc6ec5
commit 794f5e9ee1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 76 additions and 5 deletions

View File

@ -222,6 +222,10 @@
<f7-icon v-else f7="exclamationmark_triangle" />
</f7-link>
<f7-link icon-f7="pencil" tooltip="Configure highlights" data-popup=".loghighlights-popup" class="popup-open" />
<f7-segmented>
<f7-button outline small :active="!textMode" icon-f7="table" :icon-size="$theme.aurora ? 20 : 22" class="no-ripple" @click="setTextMode(false)" tooltip="Show logs in a table" />
<f7-button outline small :active="textMode" icon-f7="text_justifyleft" :icon-size="$theme.aurora ? 20 : 22" class="no-ripple" @click="setTextMode(true)" tooltip="Show logs as plain text" />
</f7-segmented>
<f7-link icon-f7="gear" tooltip="Configure logging" data-popup=".logsettings-popup" class="popup-open" />
</f7-toolbar>
@ -330,6 +334,38 @@
tr.trace
color rgb(112, 112, 112)
td.text
font-family monospace
font-size 0.9em
padding-left 4em
line-height 1.2em
color grey
span
margin-right 5px
.time
margin-left -3.2em
.level
width 3em
display inline-block
margin-right 0
.logger
width 20em
display inline-block
vertical-align middle
margin-right 0
.msg
font-weight bold
.error
color red
.warn
color orange
.info
color green
.debug
color teal
.trace
color teal
.disabled-link
pointer-events none
opacity 0.5
@ -398,6 +434,11 @@
</style>
<script lang="ts">
import Vue from 'vue'
import Clipboard from 'v-clipboard'
Vue.use(Clipboard)
import MovablePopupMixin from '@/pages/settings/movable-popup-mixin'
export default {
@ -419,6 +460,7 @@ export default {
showErrors: false,
loadingLoggers: true,
loggerPackages: [],
textMode: localStorage.getItem('openhab.ui:logviewer.textMode') === 'true',
tableData: [],
batchUpdatePending: false,
batchLogs: [],
@ -554,7 +596,6 @@ export default {
},
renderEntry (entity) {
let tr = document.createElement('tr')
tr.className = 'table-rows ' + entity.level.toLowerCase()
let icon = 'question_diamond'
switch (entity.level) {
case 'TRACE':
@ -573,10 +614,19 @@ export default {
icon = 'exclamationmark_octagon_fill'
break
}
tr.innerHTML = '<td class="sticky"><i class="icon f7-icons" style="font-size: 18px;">' + icon + `</i> ${entity.time}<span class="milliseconds">${entity.milliseconds}</span></td>` +
`<td class="level">${entity.level}</td>` +
`<td class="logger"><span class="logger">${entity.loggerName}</span></td>` +
`<td class="nowrap">${this.highlightText(entity.message)}</td>`
const levelLowerCased = entity.level.toLowerCase()
if (this.textMode) {
tr.innerHTML = `<td class="text"><span class="time">${entity.time}${entity.milliseconds}</span>` +
`[<span class="level ${levelLowerCased}">${entity.level}</span>] ` +
`[<span class="logger" title="${entity.loggerName}">${entity.loggerName}</span>] - ` +
`<span class="msg ${levelLowerCased}">${this.highlightText(entity.message)}</span></td>`
} else {
tr.className = 'table-rows ' + levelLowerCased
tr.innerHTML = '<td class="sticky"><i class="icon f7-icons" style="font-size: 18px;">' + icon + `</i> ${entity.time}<span class="milliseconds">${entity.milliseconds}</span></td>` +
`<td class="level">${entity.level}</td>` +
`<td class="logger"><span class="logger" title="${entity.loggerName}">${entity.loggerName}</span></td>` +
`<td class="nowrap">${this.highlightText(entity.message)}</td>`
}
tr.addEventListener('click', () => {
this.onRowClick(entity.id)
})
@ -833,6 +883,21 @@ export default {
return [headers, ...rows].join('\n')
},
copyTableToClipboard () {
if (this.textMode) {
const logs = this.filteredTableData.map((log) => {
return `${log.time}${log.milliseconds} [${log.level}] [${log.loggerName}] - ${log.message}`
}).join('\n')
// v-clipboard works without https, but it can only copy plain text
if (this.$clipboard(logs)) {
this.$f7.toast.create({
text: 'Table copied as text to clipboard',
destroyOnClose: true,
closeTimeout: 2000
}).open()
}
return
}
const table = this.$refs.dataTable
if (!table) {
return
@ -856,6 +921,7 @@ export default {
.then(() => {
this.$f7.toast.create({
text: 'Table copied as HTML to clipboard',
destroyOnClose: true,
closeTimeout: 2000
}).open()
})
@ -863,6 +929,11 @@ export default {
console.error('Failed to copy table: ', err)
})
},
setTextMode (textModeEnabled) {
this.textMode = textModeEnabled
localStorage.setItem('openhab.ui:logviewer.textMode', this.textMode)
this.updateFilter()
},
prefilterHighlights () {
this.activeHighlights.length = 0
for (const entry of this.highlightFilters) {