@@ -2,20 +2,23 @@ import { useEffect, useState } from "react";
2
2
import { DataTable } from "primereact/datatable" ;
3
3
import { Column } from "primereact/column" ;
4
4
import { weatherTemplate , getWeatherIndex } from "../components/weatherTemplate" ;
5
+ import { basePath } from "../next.config.js" ;
6
+ import { SearchForm } from "../components/searchForm" ;
5
7
6
8
7
9
export default function Home ( ) {
8
- const [ loading , setLoading ] = useState ( true ) ;
9
- const [ jobs , setJobs ] = useState ( [ ] ) ;
10
- const [ rows , setRows ] = useState ( [ ] ) ;
11
- const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
10
+ const [ loading , setLoading ] = useState ( true ) ;
11
+ const [ jobs , setJobs ] = useState ( [ ] ) ;
12
+ const [ rows , setRows ] = useState ( [ ] ) ;
13
+ const [ expandedRows , setExpandedRows ] = useState ( [ ] ) ;
14
+ const [ keepSearch , setKeepSearch ] = useState ( true ) ;
12
15
13
16
useEffect ( ( ) => {
14
17
const fetchData = async ( ) => {
15
18
let data = { } ;
16
19
17
20
if ( process . env . NODE_ENV === "development" ) {
18
- data = ( await import ( "../job_stats.json" ) ) . default ;
21
+ data = ( await import ( "../localData/ job_stats.json" ) ) . default ;
19
22
} else {
20
23
const response = await fetch (
21
24
"https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" +
@@ -41,15 +44,59 @@ export default function Home() {
41
44
fetchData ( ) ;
42
45
} , [ ] ) ;
43
46
47
+ // Filters the jobs s.t. all values must be contained in the name.
48
+ const matchAll = ( filteredJobs , values ) => {
49
+ return filteredJobs . filter ( ( job ) => {
50
+ const jobName = job . name . toLowerCase ( ) ;
51
+ return values . every ( ( val ) => {
52
+ const decodedValue = decodeURIComponent ( val ) . toLowerCase ( ) ;
53
+ return jobName . includes ( decodedValue ) ;
54
+ } ) ;
55
+ } ) ;
56
+ } ;
57
+
58
+ // Filters the jobs s.t. at least one value must be contained in the name.
59
+ const matchAny = ( filteredJobs , values ) => {
60
+ return filteredJobs . filter ( ( job ) => {
61
+ const jobName = job . name . toLowerCase ( ) ;
62
+ return values . some ( ( val ) => {
63
+ const decodedValue = decodeURIComponent ( val ) . toLowerCase ( ) ;
64
+ return jobName . includes ( decodedValue ) ;
65
+ } ) ;
66
+ } ) ;
67
+ } ;
68
+
69
+
44
70
useEffect ( ( ) => {
45
71
setLoading ( true ) ;
72
+ let filteredJobs = jobs ;
73
+
74
+ //Filter based on the URL.
75
+ const urlParams = new URLSearchParams ( window . location . search ) ;
76
+ switch ( urlParams . get ( "matchMode" ) ) {
77
+ case "and" :
78
+ filteredJobs = matchAll ( filteredJobs , urlParams . getAll ( "value" ) ) ;
79
+ break ;
80
+ case "or" :
81
+ filteredJobs = matchAny ( filteredJobs , urlParams . getAll ( "value" ) ) ;
82
+ break ;
83
+ default :
84
+ break ;
85
+ }
86
+
87
+
88
+ //Set the rows for the table.
89
+ setRows (
90
+ filteredJobs . map ( ( job ) => ( {
91
+ name : job . name ,
92
+ runs : job . runs ,
93
+ fails : job . fails ,
94
+ skips : job . skips ,
95
+ required : job . required ,
96
+ weather : getWeatherIndex ( job ) ,
97
+ } ) )
98
+ ) ;
46
99
47
- // Create rows to set into table.
48
- const rows = jobs . map ( ( job ) => ( {
49
- ...job ,
50
- weather : getWeatherIndex ( job ) ,
51
- } ) ) ;
52
- setRows ( rows ) ;
53
100
setLoading ( false ) ;
54
101
} , [ jobs ] ) ;
55
102
@@ -66,6 +113,11 @@ export default function Home() {
66
113
setExpandedRows ( updatedExpandedRows ) ;
67
114
} ;
68
115
116
+ const buttonClass = ( active ) => `tab md:px-4 px-2 py-2 border-2
117
+ ${ active ? "border-blue-500 bg-blue-500 text-white"
118
+ : "border-gray-300 bg-white hover:bg-gray-100" } `;
119
+
120
+
69
121
// Template for rendering the Name column as a clickable item
70
122
const nameTemplate = ( rowData ) => {
71
123
return (
@@ -120,6 +172,39 @@ export default function Home() {
120
172
) ;
121
173
} ;
122
174
175
+ // Apply search terms to the URL and reload the page.
176
+ const handleSearch = ( e ) => {
177
+ // Prevent the default behavior so that we can keep search terms.
178
+ e . preventDefault ( ) ;
179
+ const matchMode = e . target . matchMode . value ;
180
+ const value = e . target . value . value . trimEnd ( ) ;
181
+ if ( value ) {
182
+ // Append the new matchMode regardless of if search terms were kept.
183
+ const path = new URLSearchParams ( ) ;
184
+ path . append ( "matchMode" , matchMode ) ;
185
+ if ( keepSearch ) {
186
+ // If keepSearch is true, add existing parameters in the URL.
187
+ const urlParams = new URLSearchParams ( window . location . search ) ;
188
+ urlParams . getAll ( "value" ) . forEach ( ( val ) => {
189
+ path . append ( "value" , val ) ;
190
+ } ) ;
191
+ }
192
+ //Add the search term from the form and redirect.
193
+ path . append ( "value" , value ) ;
194
+ window . location . assign ( `${ basePath } /?${ path . toString ( ) } ` ) ;
195
+ }
196
+ } ;
197
+
198
+ // Clear the search parameters, but only if they exist.
199
+ const clearSearch = ( ) => {
200
+ const urlParts = window . location . href . split ( "?" ) ;
201
+ if ( urlParts [ 1 ] !== undefined ) {
202
+ window . location . assign ( urlParts [ 0 ] ) ;
203
+ }
204
+ }
205
+
206
+
207
+
123
208
const renderTable = ( ) => (
124
209
< DataTable
125
210
value = { rows }
@@ -178,9 +263,28 @@ export default function Home() {
178
263
"m-0 h-full p-4 overflow-x-hidden overflow-y-auto bg-surface-ground font-normal text-text-color antialiased select-text"
179
264
}
180
265
>
266
+ < div className = "space-x-2 mx-auto" >
267
+ < button
268
+ className = { buttonClass ( ) }
269
+ onClick = { ( ) => clearSearch ( ) } >
270
+ Clear Search
271
+ </ button >
272
+ < button
273
+ className = { buttonClass ( keepSearch ) }
274
+ onClick = { ( ) => setKeepSearch ( ! keepSearch ) } >
275
+ Keep URL Search Terms
276
+ </ button >
277
+ </ div >
278
+
279
+ < SearchForm handleSearch = { handleSearch } />
280
+
281
+ < div className = "mt-1 text-center md:text-lg text-base" >
282
+ Total Rows: { rows . length }
283
+ </ div >
284
+
181
285
< div > { renderTable ( ) } </ div >
182
286
< div className = "mt-4 text-lg" > Total Rows: { rows . length } </ div >
183
287
</ main >
184
288
</ div >
185
289
) ;
186
- }
290
+ }
0 commit comments