diff --git a/package.json b/package.json index f1d5ede0870..3652a6e3952 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "@fortawesome/free-regular-svg-icons": "6.7.2", "@fortawesome/free-solid-svg-icons": "6.7.2", "@fortawesome/react-fontawesome": "0.2.2", + "@mui/material": "7.1.1", + "@mui/styled-engine-sc": "npm:@mui/styled-engine-sc@latest", "@types/react": "*", "@types/react-dom": "*", "ajv": "8.17.1", @@ -70,7 +72,6 @@ }, "devDependencies": { "@babel/core": "7.26.10", - "@babel/eslint-parser": "7.25.9", "@babel/eslint-parser": "7.26.10", "@babel/plugin-proposal-class-properties": "7.18.6", "@babel/plugin-syntax-dynamic-import": "7.8.3", @@ -135,6 +136,7 @@ "test:watch": "node ./node_modules/jest/bin/jest --watch" }, "resolutions": { - "cacache": "19.0.1" + "cacache": "19.0.1", + "@mui/styled-engine": "npm:@mui/styled-engine-sc@latest" } } diff --git a/ui/css/react-table.css b/ui/css/react-table.css index d417fa8f8b0..3ecc6beb997 100644 --- a/ui/css/react-table.css +++ b/ui/css/react-table.css @@ -504,3 +504,12 @@ -ms-user-select: none; user-select: none; } + +.ReactTable .MuiAutocomplete-inputRoot { + max-height: 2em; +} + +.ReactTable .MuiAutocomplete-inputRoot .MuiOutlinedInput-input { + border: none; + height: 1em; +} diff --git a/ui/intermittent-failures/MainView.jsx b/ui/intermittent-failures/MainView.jsx index 2dad5b5fe3c..6de670a8b21 100644 --- a/ui/intermittent-failures/MainView.jsx +++ b/ui/intermittent-failures/MainView.jsx @@ -3,6 +3,10 @@ import { Row, Col, Breadcrumb, BreadcrumbItem } from 'reactstrap'; import PropTypes from 'prop-types'; import moment from 'moment'; import ReactTable from 'react-table-6'; +import Checkbox from '@mui/material/Checkbox'; +import TextField from '@mui/material/TextField'; +import Autocomplete from '@mui/material/Autocomplete'; +import Popper from '@mui/material/Popper'; import { bugsEndpoint } from '../helpers/url'; import { setUrlParam, getUrlParam } from '../helpers/location'; @@ -18,6 +22,16 @@ import withView from './View'; import Layout from './Layout'; import DateRangePicker from './DateRangePicker'; +const CustomPopper = (props) => { + return ( + + ); +}; + const MainView = (props) => { const { graphData, @@ -32,6 +46,10 @@ const MainView = (props) => { updateAppState, } = props; + const [selectedFilter, setSelectedFilter] = React.useState({ + product: [], + component: [], + }); const textFilter = (filter, row) => { if (getUrlParam(filter.id) !== filter.value) { setUrlParam(filter.id, filter.value); @@ -43,6 +61,49 @@ const MainView = (props) => { } }; + const autoCompleteFilter = ({ column, onChange }) => { + const options = [...new Set(tableData.map((d) => d[column.id]))]; + options.sort(); + return ( + { + setUrlParam(column.id, values); + onChange(values); + setSelectedFilter({ ...selectedFilter, [column.id]: values }); + }} + disableCloseOnSelect + defaultValue={selectedFilter[column.id]} + fullWidth + renderOption={(props, option, { selected }) => { + const { key, ...optionProps } = props; + return ( +
  • + + {option} +
  • + ); + }} + renderInput={(params) => ( + + )} + /> + ); + }; + const columns = [ { Header: 'Bug', @@ -75,13 +136,29 @@ const MainView = (props) => { Header: 'Product', accessor: 'product', maxWidth: 100, - filterMethod: (filter, row) => textFilter(filter, row), + filterMethod: (filter, row) => { + if (filter.value) { + const regex = RegExp(filter.value.join('|'), 'i'); + if (regex.test(row.product)) { + return row; + } + } + }, + Filter: autoCompleteFilter, }, { Header: 'Component', accessor: 'component', maxWidth: 100, - filterMethod: (filter, row) => textFilter(filter, row), + filterMethod: (filter, row) => { + if (filter.value) { + const regex = RegExp(filter.value.join('|'), 'i'); + if (regex.test(row.component)) { + return row; + } + } + }, + Filter: autoCompleteFilter, }, { Header: 'Summary', @@ -128,7 +205,22 @@ const MainView = (props) => { for (const header of ['product', 'component', 'summary', 'whiteboard']) { const param = getUrlParam(header); if (param) { - filters.push({ id: header, value: getUrlParam(header) }); + if (header === 'product') { + filters.push({ id: header, value: param.split(',') }); + if (selectedFilter.product.length === 0) { + setSelectedFilter({ ...selectedFilter, product: param.split(',') }); + } + } else if (header === 'component') { + filters.push({ id: header, value: param.split(',') }); + if (selectedFilter.component.length === 0) { + setSelectedFilter({ + ...selectedFilter, + component: param.split(','), + }); + } + } else { + filters.push({ id: header, value: param }); + } } } return filters; diff --git a/yarn.lock b/yarn.lock index b56ad159c7e..401e1c48ade 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1015,6 +1015,11 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.27.1", "@babel/runtime@^7.5.5": + version "7.27.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.6.tgz#ec4070a04d76bae8ddbb10770ba55714a417b7c6" + integrity sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q== + "@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0", "@babel/template@^7.3.3": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" @@ -1583,6 +1588,93 @@ dependencies: "@types/whatwg-streams" "^0.0.7" +"@mui/core-downloads-tracker@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.1.tgz#43532ccf57be19055eb20e7802508520293cf286" + integrity sha512-yBckQs4aQ8mqukLnPC6ivIRv6guhaXi8snVl00VtyojBbm+l6VbVhyTSZ68Abcx7Ah8B+GZhrB7BOli+e+9LkQ== + +"@mui/material@7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/material/-/material-7.1.1.tgz#5f75b25936925be14cb34abe0489cda82a6f8413" + integrity sha512-mTpdmdZCaHCGOH3SrYM41+XKvNL0iQfM9KlYgpSjgadXx/fEKhhvOktxm8++Xw6FFeOHoOiV+lzOI8X1rsv71A== + dependencies: + "@babel/runtime" "^7.27.1" + "@mui/core-downloads-tracker" "^7.1.1" + "@mui/system" "^7.1.1" + "@mui/types" "^7.4.3" + "@mui/utils" "^7.1.1" + "@popperjs/core" "^2.11.8" + "@types/react-transition-group" "^4.4.12" + clsx "^2.1.1" + csstype "^3.1.3" + prop-types "^15.8.1" + react-is "^19.1.0" + react-transition-group "^4.4.5" + +"@mui/private-theming@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-7.1.1.tgz#c2ecc57a9b97fbfdd850430de500c42a0f2571fe" + integrity sha512-M8NbLUx+armk2ZuaxBkkMk11ultnWmrPlN0Xe3jUEaBChg/mcxa5HWIWS1EE4DF36WRACaAHVAvyekWlDQf0PQ== + dependencies: + "@babel/runtime" "^7.27.1" + "@mui/utils" "^7.1.1" + prop-types "^15.8.1" + +"@mui/styled-engine-sc@npm:@mui/styled-engine-sc@latest": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/styled-engine-sc/-/styled-engine-sc-7.1.1.tgz#44fb74e14f36a091a37b64da0cab5f2678dd1367" + integrity sha512-wUh1/aUMLQ1JAD33oL+ZFdx97JB8On1XLFtpsllJR5lNNMAkeLKj+ZDRB4Bm2VqPgGMuv3aVYFYtlJR2FFg73A== + dependencies: + "@babel/runtime" "^7.27.1" + "@types/hoist-non-react-statics" "^3.3.6" + csstype "^3.1.3" + hoist-non-react-statics "^3.3.2" + prop-types "^15.8.1" + +"@mui/styled-engine@^7.1.1", "@mui/styled-engine@npm:@mui/styled-engine-sc@latest": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/styled-engine-sc/-/styled-engine-sc-7.1.1.tgz#44fb74e14f36a091a37b64da0cab5f2678dd1367" + integrity sha512-wUh1/aUMLQ1JAD33oL+ZFdx97JB8On1XLFtpsllJR5lNNMAkeLKj+ZDRB4Bm2VqPgGMuv3aVYFYtlJR2FFg73A== + dependencies: + "@babel/runtime" "^7.27.1" + "@types/hoist-non-react-statics" "^3.3.6" + csstype "^3.1.3" + hoist-non-react-statics "^3.3.2" + prop-types "^15.8.1" + +"@mui/system@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/system/-/system-7.1.1.tgz#eff52e597b0bfed8ecf2e973f4575ef737430727" + integrity sha512-Kj1uhiqnj4Zo7PDjAOghtXJtNABunWvhcRU0O7RQJ7WOxeynoH6wXPcilphV8QTFtkKaip8EiNJRiCD+B3eROA== + dependencies: + "@babel/runtime" "^7.27.1" + "@mui/private-theming" "^7.1.1" + "@mui/styled-engine" "^7.1.1" + "@mui/types" "^7.4.3" + "@mui/utils" "^7.1.1" + clsx "^2.1.1" + csstype "^3.1.3" + prop-types "^15.8.1" + +"@mui/types@^7.4.3": + version "7.4.3" + resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.4.3.tgz#b205ee3404db0478cd93227fc21967e2cb8630fe" + integrity sha512-2UCEiK29vtiZTeLdS2d4GndBKacVyxGvReznGXGr+CzW/YhjIX+OHUdCIczZjzcRAgKBGmE9zCIgoV9FleuyRQ== + dependencies: + "@babel/runtime" "^7.27.1" + +"@mui/utils@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-7.1.1.tgz#de315ec45ac9e16c637dcc2b32cd7912edb4e234" + integrity sha512-BkOt2q7MBYl7pweY2JWwfrlahhp+uGLR8S+EhiyRaofeRYUWL2YKbSGQvN4hgSN1i8poN0PaUiii1kEMrchvzg== + dependencies: + "@babel/runtime" "^7.27.1" + "@mui/types" "^7.4.3" + "@types/prop-types" "^15.7.14" + clsx "^2.1.1" + prop-types "^15.8.1" + react-is "^19.1.0" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -1715,6 +1807,11 @@ qs "^6.10.1" url-parse "^1.5.3" +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + "@puppeteer/browsers@2.7.1": version "2.7.1" resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.7.1.tgz#6df07e95d8e22239b77599f3ceaef4041b933e62" @@ -2042,7 +2139,7 @@ dependencies: "@types/node" "*" -"@types/hoist-non-react-statics@^3.3.1": +"@types/hoist-non-react-statics@^3.3.1", "@types/hoist-non-react-statics@^3.3.6": version "3.3.6" resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010" integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw== @@ -2129,6 +2226,11 @@ dependencies: undici-types "~6.20.0" +"@types/prop-types@^15.7.14": + version "15.7.15" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.15.tgz#e6e5a86d602beaca71ce5163fadf5f95d70931c7" + integrity sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw== + "@types/qs@*": version "6.9.18" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.18.tgz#877292caa91f7c1b213032b34626505b746624c2" @@ -2144,6 +2246,11 @@ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89" integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg== +"@types/react-transition-group@^4.4.12": + version "4.4.12" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz#b5d76568485b02a307238270bfe96cb51ee2a044" + integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w== + "@types/react@*": version "19.0.12" resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.12.tgz#338b3f7854adbb784be454b3a83053127af96bd3" @@ -3400,7 +3507,7 @@ clsx@^1.0.4: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -clsx@^2.0.0: +clsx@^2.0.0, clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== @@ -3772,7 +3879,7 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -csstype@3.1.3, csstype@^3.0.2: +csstype@3.1.3, csstype@^3.0.2, csstype@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== @@ -4170,7 +4277,7 @@ dom-helpers@^3.4.0: dependencies: "@babel/runtime" "^7.1.2" -dom-helpers@^5.1.3: +dom-helpers@^5.0.1, dom-helpers@^5.1.3: version "5.2.1" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== @@ -8564,6 +8671,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== +react-is@^19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.1.0.tgz#805bce321546b7e14c084989c77022351bbdd11b" + integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg== + react-lazylog@4.5.3: version "4.5.3" resolved "https://registry.yarnpkg.com/react-lazylog/-/react-lazylog-4.5.3.tgz#289e24995b5599e75943556ac63f5e2c04d0001e" @@ -8725,6 +8837,16 @@ react-transition-group@^3.0.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" +react-transition-group@^4.4.5: + version "4.4.5" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" + integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react-virtualized@^9.21.0: version "9.22.6" resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.6.tgz#3ae2aa69eca61cf3af332e2f9d6b4aa5638786d5"