@@ -43,6 +43,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
4343
4444 const [ schemaData , setSchemaData ] = useState < any [ ] > ( [ ] ) ;
4545 const [ schemaColumns , setSchemaColumns ] = useState < string [ ] > ( [ ] ) ;
46+ const [ isSchemaTabular , setIsSchemaTabular ] = useState < boolean > ( false ) ;
4647
4748 const [ listData , setListData ] = useState < any [ ] [ ] > ( [ ] ) ;
4849 const [ listColumns , setListColumns ] = useState < string [ ] [ ] > ( [ ] ) ;
@@ -62,6 +63,18 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
6263 } , [ interpretationInProgress ] ) ;
6364
6465 useEffect ( ( ) => {
66+ if ( row . status === 'running' || row . status === 'queued' || row . status === 'scheduled' ) {
67+ setSchemaData ( [ ] ) ;
68+ setSchemaColumns ( [ ] ) ;
69+ setListData ( [ ] ) ;
70+ setListColumns ( [ ] ) ;
71+ setLegacyData ( [ ] ) ;
72+ setLegacyColumns ( [ ] ) ;
73+ setIsLegacyData ( false ) ;
74+ setIsSchemaTabular ( false ) ;
75+ return ;
76+ }
77+
6578 if ( ! row . serializableOutput ) return ;
6679
6780 if ( ! row . serializableOutput . scrapeSchema &&
@@ -76,20 +89,29 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
7689 setIsLegacyData ( false ) ;
7790
7891 if ( row . serializableOutput . scrapeSchema && Object . keys ( row . serializableOutput . scrapeSchema ) . length > 0 ) {
79- processDataCategory ( row . serializableOutput . scrapeSchema , setSchemaData , setSchemaColumns ) ;
92+ processSchemaData ( row . serializableOutput . scrapeSchema ) ;
8093 }
8194
8295 if ( row . serializableOutput . scrapeList ) {
8396 processScrapeList ( row . serializableOutput . scrapeList ) ;
8497 }
85- } , [ row . serializableOutput ] ) ;
98+ } , [ row . serializableOutput , row . status ] ) ;
8699
87100 useEffect ( ( ) => {
101+ if ( row . status === 'running' || row . status === 'queued' || row . status === 'scheduled' ) {
102+ setScreenshotKeys ( [ ] ) ;
103+ setCurrentScreenshotIndex ( 0 ) ;
104+ return ;
105+ }
106+
88107 if ( row . binaryOutput && Object . keys ( row . binaryOutput ) . length > 0 ) {
89108 setScreenshotKeys ( Object . keys ( row . binaryOutput ) ) ;
90109 setCurrentScreenshotIndex ( 0 ) ;
110+ } else {
111+ setScreenshotKeys ( [ ] ) ;
112+ setCurrentScreenshotIndex ( 0 ) ;
91113 }
92- } , [ row . binaryOutput ] ) ;
114+ } , [ row . binaryOutput , row . status ] ) ;
93115
94116 const processLegacyData = ( legacyOutput : Record < string , any > ) => {
95117 let allData : any [ ] = [ ] ;
@@ -115,20 +137,57 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
115137 }
116138 } ;
117139
118- const processDataCategory = (
119- categoryData : Record < string , any > ,
120- setData : React . Dispatch < React . SetStateAction < any [ ] > > ,
121- setColumns : React . Dispatch < React . SetStateAction < string [ ] > >
122- ) => {
140+ const processSchemaData = ( schemaOutput : any ) => {
141+ if ( Array . isArray ( schemaOutput ) ) {
142+ const filteredData = schemaOutput . filter ( row =>
143+ row && Object . values ( row ) . some ( value => value !== undefined && value !== "" )
144+ ) ;
145+
146+ if ( filteredData . length > 0 ) {
147+ const allColumns = new Set < string > ( ) ;
148+ filteredData . forEach ( item => {
149+ Object . keys ( item ) . forEach ( key => allColumns . add ( key ) ) ;
150+ } ) ;
151+
152+ setSchemaData ( filteredData ) ;
153+ setSchemaColumns ( Array . from ( allColumns ) ) ;
154+ setIsSchemaTabular ( filteredData . length > 1 ) ;
155+ return ;
156+ }
157+ }
158+
159+ if ( schemaOutput [ 'schema-tabular' ] ) {
160+ const tabularData = schemaOutput [ 'schema-tabular' ] ;
161+ if ( Array . isArray ( tabularData ) && tabularData . length > 0 ) {
162+ const filteredData = tabularData . filter ( row =>
163+ Object . values ( row ) . some ( value => value !== undefined && value !== "" )
164+ ) ;
165+
166+ if ( filteredData . length > 0 ) {
167+ const allColumns = new Set < string > ( ) ;
168+ filteredData . forEach ( item => {
169+ Object . keys ( item ) . forEach ( key => allColumns . add ( key ) ) ;
170+ } ) ;
171+
172+ setSchemaData ( filteredData ) ;
173+ setSchemaColumns ( Array . from ( allColumns ) ) ;
174+ setIsSchemaTabular ( true ) ;
175+ return ;
176+ }
177+ }
178+ }
179+
123180 let allData : any [ ] = [ ] ;
181+ let hasMultipleEntries = false ;
124182
125- Object . keys ( categoryData ) . forEach ( key => {
126- const data = categoryData [ key ] ;
183+ Object . keys ( schemaOutput ) . forEach ( key => {
184+ const data = schemaOutput [ key ] ;
127185 if ( Array . isArray ( data ) ) {
128186 const filteredData = data . filter ( row =>
129187 Object . values ( row ) . some ( value => value !== undefined && value !== "" )
130188 ) ;
131189 allData = [ ...allData , ...filteredData ] ;
190+ if ( filteredData . length > 1 ) hasMultipleEntries = true ;
132191 }
133192 } ) ;
134193
@@ -138,8 +197,9 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
138197 Object . keys ( item ) . forEach ( key => allColumns . add ( key ) ) ;
139198 } ) ;
140199
141- setData ( allData ) ;
142- setColumns ( Array . from ( allColumns ) ) ;
200+ setSchemaData ( allData ) ;
201+ setSchemaColumns ( Array . from ( allColumns ) ) ;
202+ setIsSchemaTabular ( hasMultipleEntries || allData . length > 1 ) ;
143203 }
144204 } ;
145205
@@ -193,28 +253,29 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
193253 setCurrentListIndex ( 0 ) ;
194254 } ;
195255
196- // Function to convert table data to CSV format
197- const convertToCSV = ( data : any [ ] , columns : string [ ] , isSchemaData : boolean = false ) : string => {
198- if ( isSchemaData ) {
199- // For schema data, export as Label-Value pairs
256+ const convertToCSV = ( data : any [ ] , columns : string [ ] , isSchemaData : boolean = false , isTabular : boolean = false ) : string => {
257+ if ( isSchemaData && ! isTabular && data . length === 1 ) {
200258 const header = 'Label,Value' ;
201259 const rows = columns . map ( column =>
202260 `"${ column } ","${ data [ 0 ] [ column ] || "" } "`
203261 ) ;
204262 return [ header , ...rows ] . join ( '\n' ) ;
205263 } else {
206- // For regular table data, export as normal table
207- const header = columns . join ( ',' ) ;
264+ const header = columns . map ( col => `"${ col } "` ) . join ( ',' ) ;
208265 const rows = data . map ( row =>
209- columns . map ( col => JSON . stringify ( row [ col ] || "" , null , 2 ) ) . join ( ',' )
266+ columns . map ( col => {
267+ const value = row [ col ] || "" ;
268+ const escapedValue = String ( value ) . replace ( / " / g, '""' ) ;
269+ return `"${ escapedValue } "` ;
270+ } ) . join ( ',' )
210271 ) ;
211272 return [ header , ...rows ] . join ( '\n' ) ;
212273 }
213274 } ;
214275
215276 // Function to download a specific dataset as CSV
216- const downloadCSV = ( data : any [ ] , columns : string [ ] , filename : string , isSchemaData : boolean = false ) => {
217- const csvContent = convertToCSV ( data , columns , isSchemaData ) ;
277+ const downloadCSV = ( data : any [ ] , columns : string [ ] , filename : string , isSchemaData : boolean = false , isTabular : boolean = false ) => {
278+ const csvContent = convertToCSV ( data , columns , isSchemaData , isTabular ) ;
218279 const blob = new Blob ( [ csvContent ] , { type : 'text/csv;charset=utf-8;' } ) ;
219280 const url = URL . createObjectURL ( blob ) ;
220281
@@ -224,6 +285,10 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
224285 document . body . appendChild ( link ) ;
225286 link . click ( ) ;
226287 document . body . removeChild ( link ) ;
288+
289+ setTimeout ( ( ) => {
290+ URL . revokeObjectURL ( url ) ;
291+ } , 100 ) ;
227292 } ;
228293
229294 const downloadJSON = ( data : any [ ] , filename : string ) => {
@@ -261,11 +326,12 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
261326
262327 const renderDataTable = (
263328 data : any [ ] ,
264- columns : any [ ] ,
329+ columns : string [ ] ,
265330 title : string ,
266331 csvFilename : string ,
267332 jsonFilename : string ,
268- isPaginatedList : boolean = false
333+ isPaginatedList : boolean = false ,
334+ isSchemaData : boolean = false
269335 ) => {
270336 if ( ! isPaginatedList && data . length === 0 ) return null ;
271337 if ( isPaginatedList && ( listData . length === 0 || currentListIndex >= listData . length ) ) return null ;
@@ -275,7 +341,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
275341
276342 if ( ! currentData || currentData . length === 0 ) return null ;
277343
278- const isSchemaData = title . toLowerCase ( ) . includes ( 'text' ) || title . toLowerCase ( ) . includes ( 'schema' ) ;
344+ const shouldShowAsKeyValue = isSchemaData && ! isSchemaTabular && currentData . length === 1 ;
279345
280346 return (
281347 < Accordion defaultExpanded sx = { { mb : 2 } } >
@@ -314,7 +380,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
314380
315381 < Button
316382 component = "a"
317- onClick = { ( ) => downloadCSV ( currentData , currentColumns , csvFilename , isSchemaData ) }
383+ onClick = { ( ) => downloadCSV ( currentData , currentColumns , csvFilename , isSchemaData , isSchemaTabular ) }
318384 sx = { {
319385 color : '#FF00C3' ,
320386 textTransform : 'none' ,
@@ -366,7 +432,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
366432 < Table stickyHeader aria-label = "sticky table" >
367433 < TableHead >
368434 < TableRow >
369- { isSchemaData ? (
435+ { shouldShowAsKeyValue ? (
370436 < >
371437 < TableCell
372438 sx = { {
@@ -404,7 +470,8 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
404470 </ TableRow >
405471 </ TableHead >
406472 < TableBody >
407- { isSchemaData ? (
473+ { shouldShowAsKeyValue ? (
474+ // Single schema entry - show as key-value pairs
408475 currentColumns . map ( ( column ) => (
409476 < TableRow key = { column } >
410477 < TableCell sx = { { fontWeight : 500 } } >
@@ -416,6 +483,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
416483 </ TableRow >
417484 ) )
418485 ) : (
486+ // Multiple entries or list data - show as table
419487 currentData . map ( ( row , index ) => (
420488 < TableRow key = { index } >
421489 { ( isPaginatedList ? currentColumns : columns ) . map ( ( column ) => (
@@ -536,15 +604,17 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
536604 { renderDataTable (
537605 schemaData ,
538606 schemaColumns ,
539- t ( 'run_content.captured_data.schema_title' ) ,
607+ t ( 'run_content.captured_data.schema_title' , 'Captured Texts' ) ,
540608 'schema_data.csv' ,
541- 'schema_data.json'
609+ 'schema_data.json' ,
610+ false ,
611+ true
542612 ) }
543613
544614 { listData . length > 0 && renderDataTable (
545- listData ,
546- listColumns ,
547- t ( 'run_content.captured_data.list_title' ) ,
615+ [ ] ,
616+ [ ] ,
617+ t ( 'run_content.captured_data.list_title' , 'Captured Lists' ) ,
548618 'list_data.csv' ,
549619 'list_data.json' ,
550620 true
0 commit comments