@@ -13,7 +13,9 @@ import { ConnectError } from '@connectrpc/connect';
1313import { Alert , AlertIcon , Box , Button , createStandaloneToast , DataTable , Flex , SearchField } from '@redpanda-data/ui' ;
1414import { Link } from '@tanstack/react-router' ;
1515import type { ColumnDef , SortingState } from '@tanstack/react-table' ;
16+ import { Button as RegistryButton } from 'components/redpanda-ui/components/button' ;
1617import { isEmbedded , isFeatureFlagEnabled } from 'config' ;
18+ import { RefreshCcw } from 'lucide-react' ;
1719import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
1820import { toast as sonnerToast } from 'sonner' ;
1921import { formatToastErrorMessageGRPC } from 'utils/toast.utils' ;
@@ -40,6 +42,7 @@ import {
4042import type { TopicMessage } from '../../../state/rest-interfaces' ;
4143import { PartitionOffsetOrigin } from '../../../state/ui' ;
4244import { sanitizeString } from '../../../utils/filter-helper' ;
45+ import { isFilterMatch } from '../../../utils/message-table-helpers' ;
4346import { DefaultSkeleton , QuickTable , TimestampDisplay } from '../../../utils/tsx-utils' ;
4447import { decodeURIComponentPercents , delay , encodeBase64 } from '../../../utils/utils' ;
4548import PageContent from '../../misc/page-content' ;
@@ -259,7 +262,7 @@ const PipelineEditor = (p: { pipeline: Pipeline }) => {
259262 ) ;
260263} ;
261264
262- export const LogsTab = ( p : { pipeline : Pipeline } ) => {
265+ export const LogsTab = ( { pipeline , variant = 'card' } : { pipeline : Pipeline ; variant ?: 'ghost' | 'card' } ) => {
263266 const topicName = '__redpanda.connect.logs' ;
264267 const topic = api . topics ?. first ( ( x ) => x . topicName === topicName ) ;
265268
@@ -273,18 +276,19 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
273276 const searchRef = useRef < MessageSearch | null > ( null ) ;
274277 const [ refreshCount , setRefreshCount ] = useState ( 0 ) ;
275278
279+ // biome-ignore lint/correctness/useExhaustiveDependencies: intentional to force message search to re-run when pipeline.id and refreshCount changes
276280 useEffect ( ( ) => {
277281 searchRef . current ?. stopSearch ( ) ;
278282 const search = createMessageSearch ( ) ;
279283 searchRef . current = search ;
280284 queueMicrotask ( ( ) => setLogState ( { messages : [ ] , isComplete : false } ) ) ;
281- executeMessageSearch ( search , topicName , p . pipeline . id ) . finally ( ( ) => {
285+ executeMessageSearch ( search , topicName , pipeline . id ) . finally ( ( ) => {
282286 setLogState ( { messages : [ ...search . messages ] , isComplete : true } ) ;
283287 } ) ;
284288 return ( ) => {
285289 search . stopSearch ( ) ;
286290 } ;
287- } , [ refreshCount ] ) ;
291+ } , [ refreshCount , pipeline . id ] ) ;
288292
289293 useEffect ( ( ) => {
290294 const interval = setInterval ( ( ) => {
@@ -320,7 +324,9 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
320324 if ( loadedMessages && loadedMessages . length === 1 ) {
321325 setLogState ( ( prev ) => {
322326 const idx = prev . messages . findIndex ( ( x ) => x . partitionID === partitionID && x . offset === offset ) ;
323- if ( idx === - 1 ) return prev ;
327+ if ( idx === - 1 ) {
328+ return prev ;
329+ }
324330 const updated = [ ...prev . messages ] ;
325331 updated [ idx ] = loadedMessages [ 0 ] ;
326332 return { ...prev , messages : updated } ;
@@ -348,11 +354,7 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
348354 header : 'Value' ,
349355 accessorKey : 'value' ,
350356 cell : ( { row : { original } } ) => (
351- < MessagePreview
352- isCompactTopic = { isCompactTopic }
353- msg = { original }
354- previewFields = { ( ) => [ ] }
355- />
357+ < MessagePreview isCompactTopic = { isCompactTopic } msg = { original } previewFields = { ( ) => [ ] } />
356358 ) ,
357359 size : Number . MAX_SAFE_INTEGER ,
358360 } ,
@@ -364,11 +366,7 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
364366 ( { row : { original } } : { row : { original : TopicMessage } } ) => (
365367 < ExpandedMessage
366368 loadLargeMessage = { ( ) =>
367- loadLargeMessage (
368- searchRef . current ?. searchRequest ?. topicName ?? '' ,
369- original . partitionID ,
370- original . offset
371- )
369+ loadLargeMessage ( searchRef . current ?. searchRequest ?. topicName ?? '' , original . partitionID , original . offset )
372370 }
373371 msg = { original }
374372 />
@@ -377,26 +375,27 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
377375 ) ;
378376
379377 const filteredMessages = useMemo (
380- ( ) => messages . filter ( ( x ) => {
381- if ( ! logsQuickSearch ) {
382- return true ;
383- }
384- return isFilterMatch ( logsQuickSearch , x ) ;
385- } ) ,
378+ ( ) =>
379+ messages . filter ( ( x ) => {
380+ if ( ! logsQuickSearch ) {
381+ return true ;
382+ }
383+ return isFilterMatch ( logsQuickSearch , x ) ;
384+ } ) ,
386385 [ messages , logsQuickSearch ]
387386 ) ;
388387
389388 return (
390389 < >
391390 < Box my = "1rem" > The logs below are for the last five hours.</ Box >
392391
393- < Section minWidth = "800px" >
394- < Flex mb = "6 ">
392+ < Section borderColor = { variant === 'ghost' ? 'transparent' : undefined } minWidth = "800px" overflowY = "auto ">
393+ < div className = "mb-6 flex items-center justify-between gap-2 ">
395394 < SearchField searchText = { logsQuickSearch } setSearchText = { setLogsQuickSearch } width = "230px" />
396- < Button ml = "auto" onClick = { ( ) => setRefreshCount ( ( c ) => c + 1 ) } variant = "outline " >
397- Refresh logs
398- </ Button >
399- </ Flex >
395+ < RegistryButton onClick = { ( ) => setRefreshCount ( ( c ) => c + 1 ) } size = "icon" variant = "ghost " >
396+ < RefreshCcw />
397+ </ RegistryButton >
398+ </ div >
400399
401400 < DataTable < TopicMessage >
402401 columns = { messageTableColumns }
@@ -415,20 +414,6 @@ export const LogsTab = (p: { pipeline: Pipeline }) => {
415414 ) ;
416415} ;
417416
418- function isFilterMatch ( str : string , m : TopicMessage ) {
419- const lowerStr = str . toLowerCase ( ) ;
420- if ( m . offset . toString ( ) . toLowerCase ( ) . includes ( lowerStr ) ) {
421- return true ;
422- }
423- if ( m . keyJson ?. toLowerCase ( ) . includes ( lowerStr ) ) {
424- return true ;
425- }
426- if ( m . valueJson ?. toLowerCase ( ) . includes ( lowerStr ) ) {
427- return true ;
428- }
429- return false ;
430- }
431-
432417function executeMessageSearch ( search : MessageSearch , topicName : string , pipelineId : string ) {
433418 const filterCode : string = `return key == "${ pipelineId } ";` ;
434419
0 commit comments