1
1
'use client'
2
2
3
3
import { Loader2 , Trash } from 'lucide-react'
4
- import { useMemo } from 'react'
4
+ import { useMemo , useState } from 'react'
5
5
import type { Core } from '@openint/api-v1/models'
6
6
import { Button } from '@openint/shadcn/ui'
7
7
import {
@@ -15,6 +15,7 @@ import {
15
15
AlertDialogTitle ,
16
16
AlertDialogTrigger ,
17
17
} from '@openint/shadcn/ui/alert-dialog'
18
+ import { Sheet , SheetContent , SheetTitle } from '@openint/shadcn/ui/sheet'
18
19
import { CommandPopover } from '@openint/ui-v1'
19
20
import { DataTable , type ColumnDef } from '@openint/ui-v1/components/DataTable'
20
21
import { useMutation , useSuspenseQuery } from '@openint/ui-v1/trpc'
@@ -59,6 +60,11 @@ export function ConnectionList(props: {
59
60
} ) {
60
61
const { initialData} = props
61
62
const trpc = useTRPC ( )
63
+ const [ sheetOpen , setSheetOpen ] = useState ( false )
64
+ const [ selectedConnection , setSelectedConnection ] = useState <
65
+ Core [ 'connection' ] | null
66
+ > ( null )
67
+
62
68
const connectionData = useSuspenseQuery (
63
69
trpc . listConnections . queryOptions (
64
70
{ } ,
@@ -77,7 +83,12 @@ export function ConnectionList(props: {
77
83
} ,
78
84
} ) ,
79
85
)
86
+
80
87
const definitions = useCommandDefinitionMap ( )
88
+ const handleRowClick = ( connection : Core [ 'connection' ] ) => {
89
+ setSelectedConnection ( connection )
90
+ setSheetOpen ( true )
91
+ }
81
92
const columnsWithActions = useMemo (
82
93
( ) => [
83
94
...columns ,
@@ -100,19 +111,268 @@ export function ConnectionList(props: {
100
111
)
101
112
102
113
return (
103
- < div >
104
- < DataTable < Core [ 'connection' ] , string | number | string [ ] >
105
- data = { connectionData . data . items }
106
- columns = { columnsWithActions } >
107
- < DataTable . Header >
108
- < DataTable . SearchInput />
109
- < DataTable . ColumnVisibilityToggle />
110
- </ DataTable . Header >
111
- < DataTable . Table />
112
- < DataTable . Footer >
113
- < DataTable . Pagination />
114
- </ DataTable . Footer >
115
- </ DataTable >
116
- </ div >
114
+ < >
115
+ < div >
116
+ < DataTable < Core [ 'connection' ] , string | number | string [ ] >
117
+ data = { connectionData . data . items }
118
+ columns = { columnsWithActions }
119
+ onRowClick = { handleRowClick } >
120
+ < DataTable . Header >
121
+ < DataTable . SearchInput />
122
+ < DataTable . ColumnVisibilityToggle />
123
+ </ DataTable . Header >
124
+ < DataTable . Table />
125
+ < DataTable . Footer >
126
+ < DataTable . Pagination />
127
+ </ DataTable . Footer >
128
+ </ DataTable >
129
+ </ div >
130
+
131
+ < Sheet
132
+ open = { sheetOpen }
133
+ onOpenChange = { ( open ) => {
134
+ setSheetOpen ( open )
135
+ if ( ! open ) setSelectedConnection ( null )
136
+ } } >
137
+ < SheetContent side = "right" className = "w-[600px] p-0" >
138
+ < div className = "flex h-full flex-col" >
139
+ < div className = "border-b p-4" >
140
+ < SheetTitle className = "text-xl font-semibold" >
141
+ Connection Details
142
+ </ SheetTitle >
143
+ </ div >
144
+
145
+ { selectedConnection && (
146
+ < div className = "flex-1 overflow-y-auto p-4" >
147
+ < div className = "space-y-6" >
148
+ { /* Basic Connection Info */ }
149
+ < section >
150
+ < h3 className = "mb-3 text-lg font-semibold" >
151
+ Connection Information
152
+ </ h3 >
153
+ < div className = "space-y-2" >
154
+ < div >
155
+ < h4 className = "text-muted-foreground text-sm font-medium" >
156
+ Connection ID
157
+ </ h4 >
158
+ < p className = "font-mono text-sm" >
159
+ { selectedConnection . id }
160
+ </ p >
161
+ </ div >
162
+ < div >
163
+ < h4 className = "text-muted-foreground text-sm font-medium" >
164
+ Connector Name
165
+ </ h4 >
166
+ < p className = "font-mono text-sm" >
167
+ { selectedConnection . connector_name }
168
+ </ p >
169
+ </ div >
170
+ < div >
171
+ < h4 className = "text-muted-foreground text-sm font-medium" >
172
+ Config ID
173
+ </ h4 >
174
+ < p className = "font-mono text-sm" >
175
+ { selectedConnection . connector_config_id }
176
+ </ p >
177
+ </ div >
178
+ </ div >
179
+ </ section >
180
+
181
+ { /* OAuth Credentials */ }
182
+ { selectedConnection . settings ?. oauth ?. credentials && (
183
+ < section >
184
+ < h3 className = "mb-3 text-lg font-semibold" >
185
+ Authorization
186
+ </ h3 >
187
+ < div className = "space-y-4" >
188
+ < div >
189
+ < h4 className = "text-muted-foreground text-sm font-medium" >
190
+ Access Token
191
+ </ h4 >
192
+ < div className = "relative mt-1" >
193
+ < pre className = "overflow-x-auto rounded-md bg-slate-950 p-3 text-sm" >
194
+ < code className = "whitespace-pre-wrap break-all text-slate-50" >
195
+ {
196
+ selectedConnection . settings . oauth . credentials
197
+ . access_token
198
+ }
199
+ </ code >
200
+ </ pre >
201
+ < Button
202
+ variant = "ghost"
203
+ size = "sm"
204
+ className = "absolute right-2 top-2"
205
+ onClick = { ( ) =>
206
+ navigator . clipboard . writeText (
207
+ selectedConnection . settings . oauth . credentials
208
+ . access_token ,
209
+ )
210
+ } >
211
+ Copy
212
+ </ Button >
213
+ </ div >
214
+ </ div >
215
+
216
+ < div >
217
+ < h4 className = "text-muted-foreground text-sm font-medium" >
218
+ Refresh Token
219
+ </ h4 >
220
+ < div className = "relative mt-1" >
221
+ < pre className = "overflow-x-auto rounded-md bg-slate-950 p-3 text-sm" >
222
+ < code className = "whitespace-pre-wrap break-all text-slate-50" >
223
+ {
224
+ selectedConnection . settings . oauth . credentials
225
+ . refresh_token
226
+ }
227
+ </ code >
228
+ </ pre >
229
+ < Button
230
+ variant = "ghost"
231
+ size = "sm"
232
+ className = "absolute right-2 top-2"
233
+ onClick = { ( ) =>
234
+ navigator . clipboard . writeText (
235
+ selectedConnection . settings . oauth . credentials
236
+ . refresh_token ,
237
+ )
238
+ } >
239
+ Copy
240
+ </ Button >
241
+ </ div >
242
+ </ div >
243
+
244
+ < div className = "grid grid-cols-2 gap-4" >
245
+ < div >
246
+ < h4 className = "text-muted-foreground text-sm font-medium" >
247
+ Token Type
248
+ </ h4 >
249
+ < p className = "font-mono text-sm" >
250
+ {
251
+ selectedConnection . settings . oauth . credentials
252
+ . token_type
253
+ }
254
+ </ p >
255
+ </ div >
256
+ < div >
257
+ < h4 className = "text-muted-foreground text-sm font-medium" >
258
+ Expires In
259
+ </ h4 >
260
+ < p className = "font-mono text-sm" >
261
+ {
262
+ selectedConnection . settings . oauth . credentials
263
+ . expires_in
264
+ }
265
+ s
266
+ </ p >
267
+ </ div >
268
+ </ div >
269
+
270
+ < div >
271
+ < h4 className = "text-muted-foreground text-sm font-medium" >
272
+ Scope
273
+ </ h4 >
274
+ < p className = "break-all font-mono text-sm" >
275
+ {
276
+ selectedConnection . settings . oauth . credentials
277
+ . scope
278
+ }
279
+ </ p >
280
+ </ div >
281
+
282
+ < div >
283
+ < h4 className = "text-muted-foreground text-sm font-medium" >
284
+ Expires At
285
+ </ h4 >
286
+ < p className = "font-mono text-sm" >
287
+ { new Date (
288
+ selectedConnection . settings . oauth . credentials . expires_at ,
289
+ ) . toLocaleString ( ) }
290
+ </ p >
291
+ </ div >
292
+ </ div >
293
+ </ section >
294
+ ) }
295
+
296
+ { /* Timestamps */ }
297
+ < section >
298
+ < h3 className = "mb-3 text-lg font-semibold" > Timestamps</ h3 >
299
+ < div className = "space-y-2" >
300
+ < div >
301
+ < h4 className = "text-muted-foreground text-sm font-medium" >
302
+ Created
303
+ </ h4 >
304
+ < p className = "font-mono text-sm" >
305
+ { new Date (
306
+ selectedConnection . created_at ,
307
+ ) . toLocaleString ( ) }
308
+ </ p >
309
+ </ div >
310
+ < div >
311
+ < h4 className = "text-muted-foreground text-sm font-medium" >
312
+ Last Updated
313
+ </ h4 >
314
+ < p className = "font-mono text-sm" >
315
+ { new Date (
316
+ selectedConnection . updated_at ,
317
+ ) . toLocaleString ( ) }
318
+ </ p >
319
+ </ div >
320
+ { selectedConnection . settings ?. oauth ?. last_fetched_at && (
321
+ < div >
322
+ < h4 className = "text-muted-foreground text-sm font-medium" >
323
+ Last Fetched
324
+ </ h4 >
325
+ < p className = "font-mono text-sm" >
326
+ { new Date (
327
+ selectedConnection . settings . oauth . last_fetched_at ,
328
+ ) . toLocaleString ( ) }
329
+ </ p >
330
+ </ div >
331
+ ) }
332
+ </ div >
333
+ </ section >
334
+
335
+ { /* Raw Response */ }
336
+ { selectedConnection . settings ?. oauth ?. credentials ?. raw && (
337
+ < section >
338
+ < h3 className = "mb-3 text-lg font-semibold" >
339
+ Raw Token Response
340
+ </ h3 >
341
+ < div className = "relative" >
342
+ < pre className = "mt-2 overflow-x-auto rounded-lg bg-slate-950 p-4" >
343
+ < code className = "text-sm text-slate-50" >
344
+ { JSON . stringify (
345
+ selectedConnection . settings . oauth . credentials . raw ,
346
+ null ,
347
+ 2 ,
348
+ ) }
349
+ </ code >
350
+ </ pre >
351
+ < Button
352
+ variant = "ghost"
353
+ size = "sm"
354
+ className = "absolute right-2 top-2"
355
+ onClick = { ( ) =>
356
+ navigator . clipboard . writeText (
357
+ JSON . stringify (
358
+ selectedConnection . settings . oauth . credentials
359
+ . raw ,
360
+ null ,
361
+ 2 ,
362
+ ) ,
363
+ )
364
+ } >
365
+ Copy
366
+ </ Button >
367
+ </ div >
368
+ </ section >
369
+ ) }
370
+ </ div >
371
+ </ div >
372
+ ) }
373
+ </ div >
374
+ </ SheetContent >
375
+ </ Sheet >
376
+ </ >
117
377
)
118
378
}
0 commit comments