@@ -6,6 +6,7 @@ import React, { useEffect, useMemo, useState } from "react";
66
77const TableRender = ( { columns, url, include = [ ] , exclude = [ ] } ) : React . JSX . Element => {
88 const [ jsonContent , setJsonContent ] = useState ( [ ] ) ;
9+ const [ isLoading , setIsLoading ] = useState ( true ) ;
910 const { colorMode } = useColorMode ( ) ;
1011
1112 const theme = useMemo ( ( ) => {
@@ -21,48 +22,58 @@ const TableRender = ({ columns, url, include = [], exclude = [] }): React.JSX.El
2122 } ) ;
2223 } , [ colorMode ] ) ;
2324
25+ // biome-ignore lint/correctness/useExhaustiveDependencies: exclude/include are stable
2426 useEffect ( ( ) => {
27+ setIsLoading ( true ) ;
2528 fetch ( url )
26- . then ( ( res ) => res . json ( ) )
29+ . then ( ( res ) => {
30+ if ( ! res . ok ) {
31+ throw new Error ( `HTTP error! status: ${ res . status } ` ) ;
32+ }
33+ return res . json ( ) ;
34+ } )
2735 . then ( ( data ) => {
2836 const updatedData = [ ] ;
29- const names = [ ] ;
37+ const names = new Set ( ) ;
3038
31- Object . keys ( data ) . forEach ( ( key ) => {
39+ for ( const key of Object . keys ( data ) ) {
3240 // filter duplicate names
3341 const item = data [ key ] ;
3442 const name = item . name ;
35- for ( const element of exclude ) {
36- if ( name . includes ( element ) ) {
37- return ;
38- }
43+
44+ if ( names . has ( name ) ) {
45+ continue ;
3946 }
40- for ( const element of include ) {
41- if ( ! name . includes ( element ) ) {
42- return ;
43- }
47+
48+ if ( exclude . some ( ( excluded ) => name . includes ( excluded ) ) ) {
49+ continue ;
4450 }
45- if ( names . includes ( name ) ) {
46- return ;
51+
52+ if ( ! include . every ( ( included ) => name . includes ( included ) ) ) {
53+ continue ;
4754 }
4855
49- names . push ( name ) ;
56+ names . add ( name ) ;
5057 updatedData . push ( {
5158 ...item ,
52- // flattening list of strings into CSV strings allow global filtering on them
53- // /!\ it requires special handling in the rendering side (see crowdsec-docs/docs/cti_api/taxonomy) /!\
59+ // flattening list of strings into CSV strings to allow global filtering on them
60+ // /!\ requires special handling in the rendering side (see crowdsec-docs/docs/cti_api/taxonomy) /!\
5461 ...( item . behaviors ? { behaviors : item . behaviors . join ( "\n" ) } : { } ) ,
5562 ...( item . mitre_attacks ? { mitre_attacks : item . mitre_attacks . join ( "\n" ) } : { } ) ,
5663 ...( item . cves ? { cves : item . cves . join ( "\n" ) } : { } ) ,
5764 } ) ;
58- } ) ;
65+ }
5966
6067 setJsonContent ( updatedData ) ;
68+ setIsLoading ( false ) ;
69+ } )
70+ . catch ( ( error ) => {
71+ console . error ( "Error fetching data:" , error ) ;
72+ setIsLoading ( false ) ;
6173 } ) ;
62- // execute this fetch only once (on mount)
63- } , [ include , exclude , url ] ) ;
74+ } , [ url ] ) ;
6475
65- if ( ! columns || ! jsonContent ) {
76+ if ( ! columns || ( ! jsonContent && ! isLoading ) ) {
6677 return null ;
6778 }
6879
@@ -81,6 +92,7 @@ const TableRender = ({ columns, url, include = [], exclude = [] }): React.JSX.El
8192 muiPaginationProps = { {
8293 rowsPerPageOptions : [ 10 , 15 , 25 , 50 , 100 ] ,
8394 } }
95+ state = { { isLoading } }
8496 />
8597 </ ThemeProvider >
8698 ) }
0 commit comments