-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathLog.js
More file actions
125 lines (117 loc) · 3.23 KB
/
Log.js
File metadata and controls
125 lines (117 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import { format } from 'date-fns'
import React from 'react'
import FontAwesome from 'react-fontawesome'
import msToString from '../util/msToString'
import stringify from '../util/stringify'
import KeyValue from './KeyValue'
import Placeholder from './Placeholder'
const LEVEL_TO_ICON = {
info: 'info',
warn: 'exclamation-triangle',
error: 'times'
}
class LogItem extends React.PureComponent {
render () {
const {
timestamp,
timeDelta,
timeTotal,
level,
category,
text,
metadata
} = this.props
const classNames = `level-${level} category-${category.toLowerCase()}`
const timeTooltip =
timeDelta >= 0
? `Elapsed: ${msToString(timeDelta)} since previous, ${msToString(
timeTotal
)} total`
: null
const textWithMetadata =
metadata == null
? (
text
)
: (
<>
{text}
<div className="metadata">
<KeyValue data={metadata} serializer={stringify} />
</div>
</>
)
return (
<>
<tr className={`${classNames} first`}>
<td className="time" title={timeTooltip}>
{format(timestamp, 'HH:mm:ss.SSS')}
</td>
<td className="level">
<span className="icon">
<FontAwesome name={LEVEL_TO_ICON[level]} />
</span>
<span className="label">{level}</span>
</td>
<td className="category">{category}</td>
<td className="text">{textWithMetadata}</td>
</tr>
<tr className={`${classNames} second`}>
<td className="category">{category}</td>
<td className="text" colSpan="3">
{textWithMetadata}
</td>
</tr>
</>
)
}
}
class Log extends React.PureComponent {
constructor (props) {
super(props)
this._containerRef = React.createRef()
}
getSnapshotBeforeUpdate (prevProps) {
if (prevProps.events.length === this.props.events.length) {
return false
}
const container = this._containerRef.current
const parent = container.parentNode
return parent.scrollTop + parent.clientHeight === parent.scrollHeight
}
componentDidUpdate (prevProps, prevState, snapshot) {
if (snapshot) {
const container = this._containerRef.current
container.querySelector('.last').scrollIntoView()
}
}
render () {
const { events } = this.props
if (events.length === 0) {
return <Placeholder>No log items to show</Placeholder>
}
const startTime = events[0].timestamp
return (
<div className="log" ref={this._containerRef}>
<table>
<tbody>
{events.map(({ timestamp, level, category, text, metadata }, i) => (
<LogItem
key={i}
timestamp={timestamp}
timeDelta={i > 0 ? timestamp - events[i - 1].timestamp : -1}
timeTotal={timestamp - startTime}
level={level}
category={category}
text={text}
metadata={metadata}
/>
))}
<tr className="last" />
</tbody>
</table>
</div>
)
}
}
export default Log