From 34308c849c8ec2fa6e001210105982f7fa521ed3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Jun 2024 22:37:02 +0000 Subject: [PATCH] [BUG][Discover] Check if the timestamp is already included to remove duplicate col (#6983) * check if the timestamp is already included to remove duplicate col --------- Signed-off-by: Anan Zhuang Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com> (cherry picked from commit 0db58488a5b629c4d45d6762a289dc1df4a33951) Signed-off-by: github-actions[bot] --- changelogs/fragments/6983.yml | 2 + .../default_discover_table/helper.test.tsx | 120 ++++++++++++++++++ .../default_discover_table/helper.tsx | 10 +- .../doc_viewer/doc_viewer_render_tab.tsx | 2 +- 4 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 changelogs/fragments/6983.yml create mode 100644 src/plugins/discover/public/application/components/default_discover_table/helper.test.tsx diff --git a/changelogs/fragments/6983.yml b/changelogs/fragments/6983.yml new file mode 100644 index 000000000000..35d5dc1bddda --- /dev/null +++ b/changelogs/fragments/6983.yml @@ -0,0 +1,2 @@ +fix: +- [Discover] Check if the timestamp is already included to remove duplicate col ([#6983](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/6983)) \ No newline at end of file diff --git a/src/plugins/discover/public/application/components/default_discover_table/helper.test.tsx b/src/plugins/discover/public/application/components/default_discover_table/helper.test.tsx new file mode 100644 index 000000000000..2db30554c431 --- /dev/null +++ b/src/plugins/discover/public/application/components/default_discover_table/helper.test.tsx @@ -0,0 +1,120 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { getLegacyDisplayedColumns } from './helper'; +import { IndexPattern } from '../../../opensearch_dashboards_services'; + +const mockGetFieldByName = jest.fn(); + +describe('getLegacyDisplayedColumns', () => { + let indexPattern: IndexPattern; + + beforeEach(() => { + indexPattern = ({ + getFieldByName: mockGetFieldByName, + timeFieldName: 'timestamp', + } as unknown) as IndexPattern; + mockGetFieldByName.mockReset(); + }); + + it('should return correct column properties without time column', () => { + mockGetFieldByName.mockReturnValue({ sortable: true }); + const result = getLegacyDisplayedColumns(['column1'], indexPattern, true, false); + expect(result).toEqual([ + { + name: 'column1', + displayName: 'column1', + isSortable: true, + isRemoveable: true, + colLeftIdx: -1, + colRightIdx: -1, + }, + ]); + }); + + it('should prepend time column if not hidden, indexPattern has timeFieldName, and columns do not include timeFieldName', () => { + mockGetFieldByName.mockReturnValue({ sortable: true }); + const result = getLegacyDisplayedColumns(['column1'], indexPattern, false, false); + expect(result).toEqual([ + { + name: 'timestamp', + displayName: 'Time', + isSortable: true, + isRemoveable: false, + colLeftIdx: -1, + colRightIdx: -1, + }, + { + name: 'column1', + displayName: 'column1', + isSortable: true, + isRemoveable: true, + colLeftIdx: -1, + colRightIdx: -1, + }, + ]); + }); + + it('should not prepend time column if hideTimeField is true', () => { + mockGetFieldByName.mockReturnValue({ sortable: true }); + const result = getLegacyDisplayedColumns(['column1'], indexPattern, true, false); + expect(result).toEqual([ + { + name: 'column1', + displayName: 'column1', + isSortable: true, + isRemoveable: true, + colLeftIdx: -1, + colRightIdx: -1, + }, + ]); + }); + + it('should not prepend time column if timeFieldName is included in columns', () => { + mockGetFieldByName.mockReturnValue({ sortable: true }); + const result = getLegacyDisplayedColumns(['column1', 'timestamp'], indexPattern, false, false); + expect(result).toEqual([ + { + name: 'column1', + displayName: 'column1', + isSortable: true, + isRemoveable: true, + colLeftIdx: -1, + colRightIdx: 1, + }, + { + name: 'timestamp', + displayName: 'timestamp', + isSortable: true, + isRemoveable: true, + colLeftIdx: 0, + colRightIdx: -1, + }, + ]); + }); + + it('should shorten dotted string in displayName if isShortDots is true', () => { + mockGetFieldByName.mockReturnValue({ sortable: true }); + const result = getLegacyDisplayedColumns(['column.with.dots'], indexPattern, false, true); + expect(result).toEqual([ + { + name: 'timestamp', + displayName: 'Time', + isSortable: true, + isRemoveable: false, + colLeftIdx: -1, + colRightIdx: -1, + }, + { + name: 'column.with.dots', + displayName: 'c.w.dots', + isSortable: true, + isRemoveable: true, + colLeftIdx: -1, + colRightIdx: -1, + }, + ]); + }); +}); diff --git a/src/plugins/discover/public/application/components/default_discover_table/helper.tsx b/src/plugins/discover/public/application/components/default_discover_table/helper.tsx index 82ac73acd784..08f98117e603 100644 --- a/src/plugins/discover/public/application/components/default_discover_table/helper.tsx +++ b/src/plugins/discover/public/application/components/default_discover_table/helper.tsx @@ -94,7 +94,13 @@ export function getLegacyDisplayedColumns( colRightIdx: idx + 1 >= columns.length ? -1 : idx + 1, }; }); - return !hideTimeField && indexPattern.timeFieldName - ? [getTimeColumn(indexPattern.timeFieldName), ...columnProps] + + const shouldIncludeTimeField = + !hideTimeField && + typeof indexPattern.timeFieldName === 'string' && + !columns.includes(indexPattern.timeFieldName); + + return shouldIncludeTimeField + ? [getTimeColumn(indexPattern.timeFieldName as string), ...columnProps] : columnProps; } diff --git a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_render_tab.tsx b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_render_tab.tsx index 043d0f7a60eb..17736de5de2a 100644 --- a/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_render_tab.tsx +++ b/src/plugins/discover/public/application/components/doc_viewer/doc_viewer_render_tab.tsx @@ -29,7 +29,7 @@ */ import React, { useRef, useEffect } from 'react'; -import { DocViewRenderFn, DocViewRenderProps } from '../../../doc_views/doc_views_types'; +import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types'; interface Props { render: DocViewRenderFn;