From 62cf8db6a02ce58c35a52894645823c63cb33ec9 Mon Sep 17 00:00:00 2001 From: Asim Regmi Date: Wed, 4 Oct 2023 09:35:53 -0500 Subject: [PATCH] highlighted searched query string in Job History InfiniteScrollTable --- client/src/components/Jobs/Jobs.jsx | 4 +- .../HighlightSearchTerm.jsx | 52 +++++++++++++++++++ .../_common/HighlightSearchTerm/index.js | 3 ++ .../InfiniteScrollTable.jsx | 18 ++++++- client/src/components/_common/index.js | 1 + 5 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.jsx create mode 100644 client/src/components/_common/HighlightSearchTerm/index.js diff --git a/client/src/components/Jobs/Jobs.jsx b/client/src/components/Jobs/Jobs.jsx index bbef04a96..c5734987c 100644 --- a/client/src/components/Jobs/Jobs.jsx +++ b/client/src/components/Jobs/Jobs.jsx @@ -6,6 +6,7 @@ import { AppIcon, InfiniteScrollTable, Message, + HighlightSearchTerm, SectionMessage, Section, } from '_common'; @@ -88,7 +89,6 @@ function JobsView({ }, }) => { const query = queryStringParser.parse(useLocation().search); - // TODOv3: dropV2Jobs const jobsPathname = uuid ? `/jobs/${uuid}` : `/jobsv2/${id}`; return ( @@ -205,7 +205,6 @@ function JobsView({ ]; const filterColumns = columns.filter((f) => f.show !== false); - return ( <> {includeSearchbar && ( @@ -231,6 +230,7 @@ function JobsView({ } getRowProps={rowProps} columnMemoProps={[version]} /* TODOv3: dropV2Jobs. */ + searchTerm={query.query_string} /> diff --git a/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.jsx b/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.jsx new file mode 100644 index 000000000..4b34f4c12 --- /dev/null +++ b/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.jsx @@ -0,0 +1,52 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Link, useLocation } from 'react-router-dom'; +import * as ROUTES from '../../../constants/routes'; +import { getOutputPath } from 'utils/jobsUtil'; + +const HighlightSearchTerm = ({ searchTerm, cell, id }) => { + const highlightParts = (content) => { + const parts = content.split(new RegExp(`(${searchTerm})`, 'gi')); + return parts.map((part, i) => + part.toLowerCase() === searchTerm.toLowerCase() ? ( + {part} + ) : ( + part + ) + ); + }; + + if (id == 'Output Location') { + const outputLocation = getOutputPath(cell.row.original); + + return outputLocation ? ( + + {highlightParts(outputLocation)} + + ) : null; + } else if (id == 'uuid') { + return {cell.render('Cell')}; + } else if (id == 'name') { + const jobName = cell.row.values[id]; + + return {highlightParts(jobName)}; + } + + return null; +}; + +HighlightSearchTerm.propTypes = { + searchTerm: PropTypes.string, + cell: PropTypes.object, + id: PropTypes.string, +}; + +HighlightSearchTerm.defaultProps = { + searchTerm: '', + outputLocation: '', +}; + +export default HighlightSearchTerm; diff --git a/client/src/components/_common/HighlightSearchTerm/index.js b/client/src/components/_common/HighlightSearchTerm/index.js new file mode 100644 index 000000000..ccb240cb7 --- /dev/null +++ b/client/src/components/_common/HighlightSearchTerm/index.js @@ -0,0 +1,3 @@ +import HighlightSearchTerm from './HighlightSearchTerm'; + +export default HighlightSearchTerm; diff --git a/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx b/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx index f8496eeb8..73e60a332 100644 --- a/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx +++ b/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx @@ -3,6 +3,7 @@ import { useTable } from 'react-table'; import PropTypes from 'prop-types'; import LoadingSpinner from '../LoadingSpinner'; import './InfiniteScrollTable.scss'; +import { HighlightSearchTerm } from '_common'; const rowContentPropType = PropTypes.oneOfType([ PropTypes.string, @@ -54,6 +55,7 @@ const InfiniteScrollTable = ({ noDataText, getRowProps, columnMemoProps, + searchTerm, }) => { const columns = React.useMemo(() => tableColumns, columnMemoProps); const data = React.useMemo(() => tableData, [tableData]); @@ -93,7 +95,18 @@ const InfiniteScrollTable = ({ - {cell.render('Cell')} + {searchTerm !== '' && + (cell.column.id === 'name' || + cell.column.id === 'Output Location' || + cell.column.id === 'uuid') ? ( + + ) : ( + cell.render('Cell') + )} ); })} @@ -119,12 +132,15 @@ InfiniteScrollTable.propTypes = { noDataText: rowContentPropType, getRowProps: PropTypes.func, columnMemoProps: PropTypes.arrayOf(PropTypes.any), + searchTerm: PropTypes.string, + cell: PropTypes.object, }; InfiniteScrollTable.defaultProps = { onInfiniteScroll: (offset) => {}, isLoading: false, className: '', noDataText: '', + searchTerm: '', getRowProps: (row) => {}, columnMemoProps: [], }; diff --git a/client/src/components/_common/index.js b/client/src/components/_common/index.js index 3812495d2..ec663f8ca 100644 --- a/client/src/components/_common/index.js +++ b/client/src/components/_common/index.js @@ -16,6 +16,7 @@ export { default as Icon } from './Icon'; export { default as Message } from './Message'; export { default as InlineMessage } from './InlineMessage'; export { default as SectionMessage } from './SectionMessage'; +export { default as HighlightSearchTerm } from './HighlightSearchTerm'; export { default as Sidebar } from './Sidebar'; export { default as DescriptionList } from './DescriptionList'; export { default as DropdownSelector } from './DropdownSelector';