diff --git a/client/src/components/Jobs/Jobs.jsx b/client/src/components/Jobs/Jobs.jsx
index 1945d1bf7..48473b331 100644
--- a/client/src/components/Jobs/Jobs.jsx
+++ b/client/src/components/Jobs/Jobs.jsx
@@ -233,6 +233,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..71d13c10c
--- /dev/null
+++ b/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.jsx
@@ -0,0 +1,53 @@
+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';
+import './HighlightSearchTerm.scss';
+
+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;
\ No newline at end of file
diff --git a/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.scss b/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.scss
new file mode 100644
index 000000000..9f234d308
--- /dev/null
+++ b/client/src/components/_common/HighlightSearchTerm/HighlightSearchTerm.scss
@@ -0,0 +1,4 @@
+.highlight {
+ padding: 2.8px 0;
+ background-color: yellow;
+}
\ No newline at end of file
diff --git a/client/src/components/_common/HighlightSearchTerm/index.js b/client/src/components/_common/HighlightSearchTerm/index.js
new file mode 100644
index 000000000..aee968c3c
--- /dev/null
+++ b/client/src/components/_common/HighlightSearchTerm/index.js
@@ -0,0 +1,3 @@
+import HighlightSearchTerm from './HighlightSearchTerm';
+
+export default HighlightSearchTerm;
\ No newline at end of file
diff --git a/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx b/client/src/components/_common/InfiniteScrollTable/InfiniteScrollTable.jsx
index a3bbe85e5..e8fcfeaa6 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]);
@@ -101,7 +103,18 @@ const InfiniteScrollTable = ({
className: cell.column.className,
})}
>
- {cell.render('Cell')}
+ {searchTerm !== '' &&
+ (cell.column.id === 'name' ||
+ cell.column.id === 'Output Location' ||
+ cell.column.id === 'uuid') ? (
+
+ ) : (
+ cell.render('Cell')
+ )}
);
})}
@@ -128,12 +141,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';