Skip to content

Commit

Permalink
[Data Explorer][Discover 2.0] Implement data fetch, index pattern, sa…
Browse files Browse the repository at this point in the history
…ved search for table vis (#4564)

* Implement table using table gird and remove doc_viewer_link

Issue Resolve
#4442

Signed-off-by: ananzh <ananzh@amazon.com>

* [Data Explorer] Implement data fetch logic in Discover 2.0

Issue Resolve:
#4397

Signed-off-by: ananzh <ananzh@amazon.com>

* fix comments

Signed-off-by: ananzh <ananzh@amazon.com>

---------

Signed-off-by: ananzh <ananzh@amazon.com>
  • Loading branch information
ananzh committed Jul 26, 2023
1 parent 6e87e28 commit 146cc36
Show file tree
Hide file tree
Showing 27 changed files with 1,877 additions and 140 deletions.
100 changes: 100 additions & 0 deletions src/plugins/discover/public/__mock__/index_pattern_mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { indexPatterns } from '../../../data/public';
import { IndexPattern } from '../opensearch_dashboards_services';
import { IIndexPatternFieldList } from '../../../data/common';

// Initial data of index pattern fields
const fieldsData = [
{
name: '_id',
type: 'string',
scripted: false,
aggregatable: true,
filterable: true,
searchable: true,
sortable: true,
},
{
name: '_index',
type: 'string',
scripted: false,
filterable: true,
aggregatable: true,
searchable: true,
sortable: true,
},
{
name: '_source',
type: '_source',
scripted: false,
aggregatable: false,
filterable: false,
searchable: false,
sortable: false,
},
];

// Create a mock object for index pattern fields with methods: getAll, getByName and getByType
export const indexPatternFieldMock = {
getAll: () => fieldsData,
getByName: (name) => fieldsData.find((field) => field.name === name),
getByType: (type) => fieldsData.filter((field) => field.type === type),
} as IIndexPatternFieldList;

// Create a mock for the initial index pattern
export const indexPatternInitialMock = ({
id: '123',
title: 'test_index',
fields: indexPatternFieldMock,
timeFieldName: 'order_date',
formatHit: jest.fn((hit) => (hit.fields ? hit.fields : hit._source)),
flattenHit: undefined,
formatField: undefined,
metaFields: ['_id', '_index', '_source'],
getFieldByName: jest.fn(() => ({})),
} as unknown) as IndexPattern;

// Add a flattenHit method to the initial index pattern mock using flattenHitWrapper
const flatternHitMock = indexPatterns.flattenHitWrapper(
indexPatternInitialMock,
indexPatternInitialMock.metaFields
);
indexPatternInitialMock.flattenHit = flatternHitMock;

// Add a formatField method to the initial index pattern mock
const formatFieldMock = (hit, field) => {
return field === '_source' ? hit._source : indexPatternInitialMock.flattenHit(hit)[field];
};
indexPatternInitialMock.formatField = formatFieldMock;

// Export the fully set up index pattern mock
export const indexPatternMock = indexPatternInitialMock;

// Export a function that allows customization of index pattern mocks, by adding extra fields to the fieldsData
export const getMockedIndexPatternWithCustomizedFields = (fields) => {
const customizedFieldsData = [...fieldsData, ...fields];
const customizedFieldsMock = {
getAll: () => customizedFieldsData,
getByName: (name) => customizedFieldsData.find((field) => field.name === name),
getByType: (type) => customizedFieldsData.filter((field) => field.type === type),
} as IIndexPatternFieldList;

return {
...indexPatternMock,
fields: customizedFieldsMock,
};
};

// Export a function that allows customization of index pattern mocks with both extra fields and time field
export const getMockedIndexPatternWithTimeField = (fields, timeFiledName: string) => {
const indexPatternWithTimeFieldMock = getMockedIndexPatternWithCustomizedFields(fields);

return {
...indexPatternWithTimeFieldMock,
timeFieldName: timeFiledName,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const toolbarVisibility = {
showColumnSelector: {
allowHide: false,
allowReorder: true,
},
showStyleSelector: false,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState, useMemo, useCallback } from 'react';
import { EuiDataGrid } from '@elastic/eui';
import { IndexPattern } from '../../../opensearch_dashboards_services';
import { fetchTableDataCell } from './data_grid_table_cell_value';
import { buildDataGridColumns, computeVisibleColumns } from './data_grid_table_columns';
import { DocViewExpandButton } from './data_grid_table_docview_expand_button';
import { DataGridFlyout } from './data_grid_table_flyout';
import { DataGridContext } from './data_grid_table_context';
import { toolbarVisibility } from './constants';
import { DocViewFilterFn } from '../../doc_views/doc_views_types';
import { DiscoverServices } from '../../../build_services';
import { OpenSearchSearchHit } from '../../doc_views/doc_views_types';
import { usePagination } from '../utils/use_pagination';

export interface DataGridTableProps {
columns: string[];
indexPattern: IndexPattern;
onAddColumn: (column: string) => void;
onFilter: DocViewFilterFn;
onRemoveColumn: (column: string) => void;
onSort: (sort: string[][]) => void;
rows: OpenSearchSearchHit[];
onSetColumns: (columns: string[]) => void;
sort: Array<[string, string]>;
displayTimeColumn: boolean;
services: DiscoverServices;
}

export const DataGridTable = ({
columns,
indexPattern,
onAddColumn,
onFilter,
onRemoveColumn,
onSetColumns,
onSort,
sort,
rows,
displayTimeColumn,
services,
}: DataGridTableProps) => {
const [docViewExpand, setDocViewExpand] = useState(undefined);
const rowCount = useMemo(() => (rows ? rows.length : 0), [rows]);
const pagination = usePagination(rowCount);

const sortingColumns = useMemo(() => sort.map(([id, direction]) => ({ id, direction })), [sort]);

const onColumnSort = useCallback(
(cols) => {
onSort(cols.map(({ id, direction }: any) => [id, direction]));
},
[onSort]
);

const renderCellValue = useMemo(() => fetchTableDataCell(indexPattern, rows), [
indexPattern,
rows,
]);

const dataGridTableColumns = useMemo(
() => buildDataGridColumns(columns, indexPattern, displayTimeColumn),
[columns, indexPattern, displayTimeColumn]
);

const dataGridTableColumnsVisibility = useMemo(
() => ({
visibleColumns: computeVisibleColumns(columns, indexPattern, displayTimeColumn) as string[],
setVisibleColumns: (newColumns: string[]) => {
onSetColumns(newColumns);
},
}),
[columns, indexPattern, displayTimeColumn, onSetColumns]
);

const sorting = useMemo(() => ({ columns: sortingColumns, onSort: onColumnSort }), [
sortingColumns,
onColumnSort,
]);

const leadingControlColumns = useMemo(() => {
return [
{
id: 'expandCollapseColumn',
headerCellRender: () => null,
rowCellRender: DocViewExpandButton,
width: 40,
},
];
}, []);

return (
<DataGridContext.Provider
value={{
docViewExpand,
onFilter,
setDocViewExpand,
rows: rows || [],
indexPattern,
}}
>
<>
<EuiDataGrid
aria-labelledby="aria-labelledby"
columns={dataGridTableColumns}
columnVisibility={dataGridTableColumnsVisibility}
leadingControlColumns={leadingControlColumns}
data-test-subj="docTable"
pagination={pagination}
renderCellValue={renderCellValue}
rowCount={rowCount}
sorting={sorting}
toolbarVisibility={toolbarVisibility}
/>
{docViewExpand && (
<DataGridFlyout
indexPattern={indexPattern}
hit={docViewExpand}
columns={columns}
onRemoveColumn={onRemoveColumn}
onAddColumn={onAddColumn}
onFilter={onFilter}
onClose={() => setDocViewExpand(undefined)}
services={services}
/>
)}
</>
</DataGridContext.Provider>
);
};
Loading

0 comments on commit 146cc36

Please sign in to comment.