From fe3a174bb04ac8032a791cc406bea97124d81dcf Mon Sep 17 00:00:00 2001 From: Danil Kostromin Date: Thu, 22 Feb 2024 12:05:19 +0200 Subject: [PATCH] feat(run): add ability to highlight param difference This will add ability to highlight parameters difference relative clicked result row Signed-off-by: Danil Kostromin --- libs/bublik/features/run/src/lib/hooks.tsx | 1 + .../run/src/lib/result-table/matcher.ts | 18 ++++--- .../lib/result-table/result-table.columns.tsx | 52 +++++++++++-------- .../result-table/result-table.component.tsx | 51 +++++++++++------- .../result-table/result-table.container.tsx | 52 ++++++++++++++++--- 5 files changed, 121 insertions(+), 53 deletions(-) diff --git a/libs/bublik/features/run/src/lib/hooks.tsx b/libs/bublik/features/run/src/lib/hooks.tsx index 3e3e1e94..02792595 100644 --- a/libs/bublik/features/run/src/lib/hooks.tsx +++ b/libs/bublik/features/run/src/lib/hooks.tsx @@ -42,6 +42,7 @@ export const useRunRowStateContext = () => { export interface RowState { rowId: string; requests?: Record; + referenceDiffRowId?: string; } export const useRunTableRowState = () => { diff --git a/libs/bublik/features/run/src/lib/result-table/matcher.ts b/libs/bublik/features/run/src/lib/result-table/matcher.ts index 2e976709..4c2d1b99 100644 --- a/libs/bublik/features/run/src/lib/result-table/matcher.ts +++ b/libs/bublik/features/run/src/lib/result-table/matcher.ts @@ -31,9 +31,15 @@ export function calculateGroupSize( return groupSize; } -export function highlightDifferences(dataset: string[][]) { - console.log(calculateGroupSize(dataset, 10)); - const referenceSet = dataset[0]; +type DiffValue = { + value: string; + isDifferent?: boolean; +}; + +export function highlightDifferences( + dataset: string[][], + referenceSet: string[] +): DiffValue[][] { const highlightedDataset = []; const referenceMap = new Map( Array.from(referenceSet, (item) => item.split('=')) as [string, string][] @@ -44,7 +50,7 @@ export function highlightDifferences(dataset: string[][]) { const currentSetMap = new Map( Array.from(currentSet, (item) => item.split('=')) as [string, string][] ); - const highlightedSet = []; + const highlightedSet: DiffValue[] = []; for (let j = 0; j < referenceSet.length; j++) { const referenceKeyValue = referenceSet[j].split('='); @@ -54,9 +60,9 @@ export function highlightDifferences(dataset: string[][]) { referenceMap.get(referenceKeyValue[0]) !== currentSetMap.get(currentKeyValue[0]) ) { - highlightedSet.push(`***${currentSet[j]}***`); + highlightedSet.push({ value: currentSet[j], isDifferent: true }); } else { - highlightedSet.push(currentSet[j]); + highlightedSet.push({ value: currentSet[j] }); } } diff --git a/libs/bublik/features/run/src/lib/result-table/result-table.columns.tsx b/libs/bublik/features/run/src/lib/result-table/result-table.columns.tsx index d194d115..6ead6c04 100644 --- a/libs/bublik/features/run/src/lib/result-table/result-table.columns.tsx +++ b/libs/bublik/features/run/src/lib/result-table/result-table.columns.tsx @@ -4,10 +4,11 @@ import { ColumnDef } from '@tanstack/react-table'; import { RunDataResults, RESULT_TYPE } from '@/shared/types'; import { ResultLinksContainer } from '@/bublik/features/result-links'; -import { VerdictList, BadgeList, cn } from '@/shared/tailwind-ui'; +import { VerdictList, cn } from '@/shared/tailwind-ui'; import { KeyList } from './key-list'; import { highlightDifferences } from './matcher'; +import { useRunTableRowState } from '../hooks'; export interface ResultLinksProps { runId: string; @@ -23,9 +24,12 @@ const ResultLinks = ({ runId, resultId, result }: ResultLinksProps) => { export const getColumns = ( runId: string, + rowId: string, data: RunDataResults[] ): ColumnDef[] => { - const dataset = data.map((item) => item.parameters); + const parametersDataset = Object.fromEntries( + data.map((item) => [String(item.result_id), item.parameters]) + ); return [ { @@ -90,32 +94,36 @@ export const getColumns = ( }, { header: 'Parameters', - accessorFn: (data) => { - return { parameters: data.parameters.map((payload) => ({ payload })) }; - }, + accessorFn: (data) => data.parameters, cell: (cell) => { - const value = cell.getValue<{ parameters: { payload: string }[] }>(); + const value = cell.getValue(); + const referenceDiffRowId = + useRunTableRowState().rowState[rowId]?.referenceDiffRowId; + + const referenceSet = referenceDiffRowId + ? parametersDataset[referenceDiffRowId] + : value; return (
    - {highlightDifferences(dataset)[cell.row.index].map( - (item, index) => ( -
    - {item.startsWith('***') ? item.slice(3, -3) : item} -
    - ) - )} + {highlightDifferences( + Object.values(parametersDataset), + referenceSet + )[cell.row.index].map((item, index) => ( +
    + {item.value} +
    + ))}
); - - return ; } } ]; diff --git a/libs/bublik/features/run/src/lib/result-table/result-table.component.tsx b/libs/bublik/features/run/src/lib/result-table/result-table.component.tsx index d68565c6..2b9cac1b 100644 --- a/libs/bublik/features/run/src/lib/result-table/result-table.component.tsx +++ b/libs/bublik/features/run/src/lib/result-table/result-table.component.tsx @@ -1,16 +1,22 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* SPDX-FileCopyrightText: 2021-2023 OKTET Labs Ltd. */ -import { FC, memo, useMemo } from 'react'; +import { memo, useMemo } from 'react'; import { RunDataResults } from '@/shared/types'; -import { TwTable, TableClassNames, cn, Skeleton } from '@/shared/tailwind-ui'; +import { + TwTable, + TableClassNames, + cn, + Skeleton, + TwTableProps +} from '@/shared/tailwind-ui'; import { getColumns } from './result-table.columns'; export interface SkeletonProps { rowCount?: number; } -export const ResultTableLoading: FC = ({ rowCount = 25 }) => { +export const ResultTableLoading = ({ rowCount = 25 }: SkeletonProps) => { return (
@@ -51,21 +57,30 @@ const classNames: TableClassNames = { export interface ResultTableProps { runId: string; data: RunDataResults[]; + rowId: string; + getRowProps: TwTableProps['getRowProps']; } -export const ResultTable = memo(({ runId, data = [] }: ResultTableProps) => { - const columns = useMemo(() => getColumns(runId, data), [data, runId]); +export const ResultTable = memo( + ({ runId, data = [], rowId, getRowProps }: ResultTableProps) => { + const columns = useMemo( + () => getColumns(runId, rowId, data), + [data, rowId, runId] + ); - return ( -
- - data={data} - columns={columns} - classNames={classNames} - stickyOffset={-69} - manualPagination - enableSorting={false} - /> -
- ); -}); + return ( +
+ + data={data} + getRowId={(row) => String(row.result_id)} + columns={columns} + classNames={classNames} + stickyOffset={-69} + manualPagination + enableSorting={false} + getRowProps={getRowProps} + /> +
+ ); + } +); diff --git a/libs/bublik/features/run/src/lib/result-table/result-table.container.tsx b/libs/bublik/features/run/src/lib/result-table/result-table.container.tsx index 9c12d7b3..f7e2e674 100644 --- a/libs/bublik/features/run/src/lib/result-table/result-table.container.tsx +++ b/libs/bublik/features/run/src/lib/result-table/result-table.container.tsx @@ -1,15 +1,16 @@ /* SPDX-License-Identifier: Apache-2.0 */ /* SPDX-FileCopyrightText: 2021-2023 OKTET Labs Ltd. */ -import { FC, useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { Row } from '@tanstack/react-table'; -import { RunData } from '@/shared/types'; +import { RunData, RunDataResults } from '@/shared/types'; import { useGetResultsTableQuery } from '@/services/bublik-api'; +import { TwTableProps } from '@/shared/tailwind-ui'; import { useRunTableRowState } from '../hooks'; import { ColumnId } from '../run-table/types'; import { ResultTableLoading, ResultTable } from './result-table.component'; -import { getRowValues } from '../run-table/utils'; +import { getRowValues } from '../run-table'; const DEFAULT_REQUEST = { [ColumnId.Total]: { results: [], resultProperties: [] } @@ -20,12 +21,14 @@ export interface ResultTableContainerProps { row: Row; } -export const ResultTableContainer: FC = ({ +export const ResultTableContainer = ({ runId, row -}) => { +}: ResultTableContainerProps) => { const { id: rowId } = row; const rowState = useRunTableRowState().rowState[rowId]; + const { updateRowState } = useRunTableRowState(); + const requests = rowState?.requests ? Object.keys(rowState.requests).length ? rowState.requests @@ -49,11 +52,46 @@ export const ResultTableContainer: FC = ({ ); }, [requests, values]); - if (isError) return
Something went wrong...
; + const getRowProps = useCallback< + NonNullable['getRowProps']> + >( + (_, row) => { + const className = + rowState?.referenceDiffRowId === row.id ? 'border-primary' : ''; + return { + className, + onClick: (e) => { + if (rowState?.referenceDiffRowId === row.id) { + updateRowState({ + rowId, + referenceDiffRowId: undefined, + requests: rowState?.requests + }); + } else { + updateRowState({ + rowId, + referenceDiffRowId: row.id, + requests: rowState?.requests + }); + } + } + }; + }, + [rowId, rowState?.referenceDiffRowId, rowState?.requests, updateRowState] + ); + + if (isError) return
Something went wrong...
; if (isFetching) return ; if (!data) return
No data...
; - return ; + return ( + + ); };