Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Data Explorer][Discover 2.0] Implement data fetch, index pattern, saved search for table vis #4564

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions src/plugins/discover/public/__mock__/index_pattern_mock.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? Cant we use import { getStubIndexPattern } from '../../../../../../data/public/test_utils'; like the one found in src/plugins/discover/public/application/components/sidebar/lib/field_calculator.test.ts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we could. This is a great finding. I think we just need to add a new data in fixture. Let me do it in a follow up PR.

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 = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const toolbarVisibility = {
export const TOOLBAR_VISIBILITY = {

nit:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change

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