@@ -10,7 +10,7 @@ import { useInfiniteQuery, useIsFetching } from '@tanstack/react-query'
10
10
import { useVirtualizer } from '@tanstack/react-virtual'
11
11
import cn from 'classnames'
12
12
import { differenceInMilliseconds } from 'date-fns'
13
- import { memo , useCallback , useMemo , useRef , useState } from 'react'
13
+ import { useMemo , useRef } from 'react'
14
14
15
15
import { api } from '@oxide/api'
16
16
import { Logs16Icon , Logs24Icon } from '@oxide/design-system/icons/react'
@@ -25,93 +25,12 @@ import { Spinner } from '~/ui/lib/Spinner'
25
25
import { toSyslogDateString , toSyslogTimeString } from '~/util/date'
26
26
import { docLinks } from '~/util/links'
27
27
28
- // silly faux highlighting
29
- // avoids unnecessary import of a library and all that overhead
30
- const HighlightJSON = memo ( ( { jsonString } : { jsonString : string } ) => {
31
- const Indent = ( { depth } : { depth : number } ) => (
32
- < span className = "inline-block" style = { { width : `${ depth * 4 + 1 } ch` } } />
33
- )
34
-
35
- const Primitive = ( { value } : { value : null | boolean | number | string } ) => (
36
- < span className = "text-[var(--base-blue-600)]" >
37
- { value === null ? 'null' : typeof value === 'string' ? `"${ value } "` : String ( value ) }
38
- </ span >
39
- )
40
-
41
- const renderValue = (
42
- value : null | boolean | number | string | object ,
43
- depth = 0
44
- ) : React . ReactNode => {
45
- if (
46
- value === null ||
47
- typeof value === 'boolean' ||
48
- typeof value === 'number' ||
49
- typeof value === 'string'
50
- ) {
51
- return < Primitive value = { value } />
52
- }
53
-
54
- if ( Array . isArray ( value ) ) {
55
- if ( value . length === 0 ) return < span className = "text-quaternary" > []</ span >
56
-
57
- return (
58
- < >
59
- < span className = "text-quaternary" > [</ span >
60
- { '\n' }
61
- { value . map ( ( item , index ) => (
62
- < span key = { index } >
63
- < Indent depth = { depth + 1 } />
64
- { renderValue ( item , depth + 1 ) }
65
- { index < value . length - 1 && < span className = "text-quaternary" > ,</ span > }
66
- { '\n' }
67
- </ span >
68
- ) ) }
69
- < Indent depth = { depth } />
70
- < span className = "text-quaternary" > ]</ span >
71
- </ >
72
- )
73
- }
74
-
75
- if ( typeof value === 'object' ) {
76
- const entries = Object . entries ( value )
77
- if ( entries . length === 0 ) return < span className = "text-quaternary" > { '{}' } </ span >
78
-
79
- return (
80
- < >
81
- < span className = "text-quaternary" > { '{' } </ span >
82
- { '\n' }
83
- { entries . map ( ( [ key , val ] , index ) => (
84
- < span key = { key } >
85
- < Indent depth = { depth + 1 } />
86
- < span className = "text-default" > { key } </ span >
87
- < span className = "text-quaternary" > : </ span >
88
- { renderValue ( val , depth + 1 ) }
89
- { index < entries . length - 1 && < span className = "text-quaternary" > ,</ span > }
90
- { '\n' }
91
- </ span >
92
- ) ) }
93
- < Indent depth = { depth } />
94
- < span className = "text-quaternary" > { '}' } </ span >
95
- </ >
96
- )
97
- }
98
-
99
- return String ( value )
100
- }
101
-
102
- try {
103
- const parsed = JSON . parse ( jsonString )
104
- return < > { renderValue ( parsed ) } </ >
105
- } catch {
106
- return < > { jsonString } </ >
107
- }
108
- } )
109
-
110
28
export const handle = { crumb : 'Audit Log' }
111
29
112
- export default function SiloAuditLogsPage ( ) {
113
- const [ expandedItem , setExpandedItem ] = useState < string | null > ( null )
30
+ // for virtualizer
31
+ const estimateSize = ( ) => 36
114
32
33
+ export default function SiloAuditLogsPage ( ) {
115
34
// pass refetch interval to this to keep the date up to date
116
35
const { preset, startTime, endTime, dateTimeRangePicker, onRangeChange } =
117
36
useDateTimeRangePicker ( {
@@ -161,28 +80,13 @@ export default function SiloAuditLogsPage() {
161
80
162
81
const parentRef = useRef < HTMLDivElement > ( null )
163
82
164
- const EXPANDED_HEIGHT = 282
165
-
166
83
const rowVirtualizer = useVirtualizer ( {
167
84
count : auditLogs . length ,
168
85
getScrollElement : ( ) => document . querySelector ( '#scroll-container' ) ,
169
- estimateSize : useCallback (
170
- ( index ) => {
171
- return expandedItem === index . toString ( ) ? 36 + EXPANDED_HEIGHT : 36
172
- } ,
173
- [ expandedItem , EXPANDED_HEIGHT ]
174
- ) ,
86
+ estimateSize,
175
87
overscan : 20 ,
176
88
} )
177
89
178
- const handleToggle = useCallback (
179
- ( index : string | null ) => {
180
- setExpandedItem ( index )
181
- rowVirtualizer . measure ( )
182
- } ,
183
- [ rowVirtualizer ]
184
- )
185
-
186
90
const LogTable = ( ) => (
187
91
< >
188
92
< div
@@ -193,8 +97,6 @@ export default function SiloAuditLogsPage() {
193
97
>
194
98
{ rowVirtualizer . getVirtualItems ( ) . map ( ( virtualRow ) => {
195
99
const log = auditLogs [ virtualRow . index ]
196
- const isExpanded = expandedItem === virtualRow . index . toString ( )
197
- const jsonString = JSON . stringify ( log , null , 2 )
198
100
199
101
return (
200
102
< div
@@ -205,58 +107,44 @@ export default function SiloAuditLogsPage() {
205
107
transform : `translateY(${ virtualRow . start } px)` ,
206
108
} }
207
109
>
208
- < div >
209
- < button
210
- className = { cn (
211
- 'grid h-9 w-full cursor-pointer items-center gap-8 px-[var(--content-gutter)] text-left text-sans-md border-secondary' ,
212
- isExpanded ? 'bg-raise' : 'hover:bg-raise' ,
213
- virtualRow . index !== 0 && 'border-t'
214
- ) }
215
- style = { {
216
- gridTemplateColumns : '7rem 4.25rem 180px 120px 120px 120px 300px 300px' ,
217
- } }
218
- onClick = { ( ) => {
219
- const newValue = isExpanded ? null : virtualRow . index . toString ( )
220
- handleToggle ( newValue )
221
- } }
222
- type = "button"
223
- >
224
- < div className = "overflow-hidden whitespace-nowrap text-mono-sm" >
225
- < span className = "text-tertiary" >
226
- { toSyslogDateString ( log . timeCompleted ) }
227
- </ span > { ' ' }
228
- { toSyslogTimeString ( log . timeCompleted ) }
229
- </ div >
230
- < div className = "flex gap-1 overflow-hidden whitespace-nowrap" >
231
- < span className = "text-mono-sm text-tertiary" > POST</ span >
232
- < Badge > 200</ Badge >
233
- </ div >
234
- < div >
110
+ < div
111
+ className = { cn (
112
+ 'grid h-9 w-full items-center gap-8 px-[var(--content-gutter)] text-left text-sans-md border-secondary' ,
113
+ virtualRow . index !== 0 && 'border-t'
114
+ ) }
115
+ style = { {
116
+ gridTemplateColumns : '7rem 4.25rem 180px 120px 120px 120px 300px 300px' ,
117
+ } }
118
+ onClick = { ( ) => { } }
119
+ >
120
+ < div className = "overflow-hidden whitespace-nowrap text-mono-sm" >
121
+ < span className = "text-tertiary" >
122
+ { toSyslogDateString ( log . timeCompleted ) }
123
+ </ span > { ' ' }
124
+ { toSyslogTimeString ( log . timeCompleted ) }
125
+ </ div >
126
+ < div className = "flex gap-1 overflow-hidden whitespace-nowrap" >
127
+ < span className = "text-mono-sm text-tertiary" > POST</ span >
128
+ < Badge > 200</ Badge >
129
+ </ div >
130
+ < div >
131
+ < Badge color = "neutral" className = "text-tertiary" >
132
+ { log . operationId . split ( '_' ) . join ( ' ' ) }
133
+ </ Badge >
134
+ </ div >
135
+ < div className = "text-secondary" > hannah.arendt</ div >
136
+ < div >
137
+ { ! ! log . accessMethod && (
235
138
< Badge color = "neutral" className = "text-tertiary" >
236
- { log . operationId . split ( '_' ) . join ( ' ' ) }
139
+ { log . accessMethod . split ( '_' ) . join ( ' ' ) }
237
140
</ Badge >
238
- </ div >
239
- < div className = "text-secondary" > hannah.arendt</ div >
240
- < div >
241
- { ! ! log . accessMethod && (
242
- < Badge color = "neutral" className = "text-tertiary" >
243
- { log . accessMethod . split ( '_' ) . join ( ' ' ) }
244
- </ Badge >
245
- ) }
246
- </ div >
247
- < div className = "text-secondary" > maze-war</ div >
248
- < div className = "text-secondary" >
249
- { differenceInMilliseconds ( new Date ( log . timeCompleted ) , log . timeStarted ) }
250
- ms
251
- </ div >
252
- </ button >
253
- { isExpanded && (
254
- < div className = "border-t px-[var(--content-gutter)] py-3 border-secondary" >
255
- < pre className = "h-full overflow-auto border-l pl-4 text-mono-code border-secondary" >
256
- < HighlightJSON jsonString = { jsonString } />
257
- </ pre >
258
- </ div >
259
- ) }
141
+ ) }
142
+ </ div >
143
+ < div className = "text-secondary" > maze-war</ div >
144
+ < div className = "text-secondary" >
145
+ { differenceInMilliseconds ( new Date ( log . timeCompleted ) , log . timeStarted ) }
146
+ ms
147
+ </ div >
260
148
</ div >
261
149
</ div >
262
150
)
0 commit comments