diff --git a/viz-lib/src/visualizations/table/Renderer.tsx b/viz-lib/src/visualizations/table/Renderer.tsx index 3812e82b82..a5b571bbaf 100644 --- a/viz-lib/src/visualizations/table/Renderer.tsx +++ b/viz-lib/src/visualizations/table/Renderer.tsx @@ -92,13 +92,19 @@ export default function Renderer({ options, data }: any) { // @ts-expect-error ts-migrate(2322) FIXME: Type '(event: any) => void' is not assignable to t... Remove this comment to see the full error message setSearchTerm(event.target.value)} /> ) : null; - return prepareColumns(options.columns, searchInput, orderBy, (newOrderBy: any) => { - setOrderBy(newOrderBy); - // Remove text selection - may occur accidentally - // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. - document.getSelection().removeAllRanges(); - }); - }, [options.columns, searchColumns, orderBy]); + return prepareColumns( + options.columns, + searchInput, + orderBy, + (newOrderBy: any) => { + setOrderBy(newOrderBy); + // Remove text selection - may occur accidentally + // @ts-expect-error ts-migrate(2531) FIXME: Object is possibly 'null'. + document.getSelection().removeAllRanges(); + }, + searchTerm + ); + }, [options.columns, searchColumns, orderBy, searchTerm]); const preparedRows = useMemo(() => sortRows(filterRows(initRows(data.rows), searchTerm, searchColumns), orderBy), [ data.rows, diff --git a/viz-lib/src/visualizations/table/utils.tsx b/viz-lib/src/visualizations/table/utils.tsx index 298cdb7f96..e9e2179239 100644 --- a/viz-lib/src/visualizations/table/utils.tsx +++ b/viz-lib/src/visualizations/table/utils.tsx @@ -4,6 +4,34 @@ import cx from "classnames"; import Tooltip from "antd/lib/tooltip"; import ColumnTypes from "./columns"; +function highlightSearchTerm(text: string, searchTerm: string) { + if (!searchTerm || searchTerm === "" || !text) { + return text; + } + + const textStr = toString(text); + const upperText = textStr.toUpperCase(); + const upperSearchTerm = searchTerm.toUpperCase(); + + const index = upperText.indexOf(upperSearchTerm); + + if (index >= 0) { + const before = textStr.substring(0, index); + const match = textStr.substring(index, index + searchTerm.length); + const after = textStr.substring(index + searchTerm.length); + + return ( + + {before} + {match} + {after} + + ); + } + + return text; +} + function nextOrderByDirection(direction: any) { switch (direction) { case "ascend": @@ -50,7 +78,7 @@ function getOrderByInfo(orderBy: any) { return result; } -export function prepareColumns(columns: any, searchInput: any, orderBy: any, onOrderByChange: any) { +export function prepareColumns(columns: any, searchInput: any, orderBy: any, onOrderByChange: any, searchTerm: string = '') { columns = filter(columns, "visible"); columns = sortBy(columns, "order"); @@ -102,10 +130,24 @@ export function prepareColumns(columns: any, searchInput: any, orderBy: any, onO const initColumn = ColumnTypes[column.displayAs]; const Component = initColumn(column); // @ts-expect-error ts-migrate(2339) FIXME: Property 'render' does not exist on type '{ key: a... Remove this comment to see the full error message - result.render = (unused: any, row: any) => ({ - children: , - props: { className: `display-as-${column.displayAs}` }, - }); + result.render = (unused: any, row: any) => { + const isSearchable = column.allowSearch === true; + + if (searchTerm && isSearchable) { + const { prepareData } = initColumn(column); + const { text } = prepareData(row.record); + + return { + children: highlightSearchTerm(text, searchTerm), + props: { className: `display-as-${column.displayAs}` }, + }; + } + + return { + children: , + props: { className: `display-as-${column.displayAs}` }, + }; + }; return result; });