Skip to content

Commit

Permalink
feat: enable data grid in Chatbot
Browse files Browse the repository at this point in the history
Signed-off-by: SuZhou-Joe <[email protected]>
  • Loading branch information
SuZhou-Joe committed Jan 8, 2024
1 parent c8fb54e commit eaba163
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
EuiDataGridColumn,
EuiDataGridSorting,
EuiPanel,
EuiDataGridProps,
} from '@elastic/eui';
import moment from 'moment';
import { MutableRefObject } from 'react';
Expand All @@ -28,11 +29,10 @@ import { FlyoutButton } from './docViewRow';
import { useFetchEvents } from '../../hooks';
import { redoQuery } from '../../utils/utils';

interface DataGridProps {
export interface DataGridProps {
http: HttpSetup;
pplService: PPLService;
rows: any[];
rowsAll: any[];
explorerFields: IExplorerFields;
timeStampField: string;
rawQuery: string;
Expand All @@ -41,21 +41,26 @@ interface DataGridProps {
startTime: string;
endTime: string;
storedSelectedColumns: IField[];
formatGridColumn?: (columns: EuiDataGridColumn[]) => EuiDataGridColumn[];
OUIDataGridProps?: Partial<EuiDataGridProps>;
}

const defaultFormatGrid = (columns: EuiDataGridColumn[]) => columns;

export function DataGrid(props: DataGridProps) {
const {
http,
pplService,
rows,
rowsAll,
explorerFields,
timeStampField,
rawQuery,
totalHits,
requestParams,
startTime,
endTime,
formatGridColumn = defaultFormatGrid,
OUIDataGridProps,
} = props;
const { fetchEvents } = useFetchEvents({
pplService,
Expand Down Expand Up @@ -105,7 +110,7 @@ export function DataGrid(props: DataGridProps) {
// creates the header for each column listing what that column is
const dataGridColumns = useMemo(() => {
const columns: EuiDataGridColumn[] = [];
selectedColumns.map(({ name, type }) => {
selectedColumns.map(({ name }) => {
if (name === 'timestamp') {
columns.push(DEFAULT_TIMESTAMP_COLUMN);
} else if (name === '_source') {
Expand All @@ -118,8 +123,8 @@ export function DataGrid(props: DataGridProps) {
});
}
});
return columns;
}, [explorerFields, totalHits]);
return formatGridColumn(columns);
}, [explorerFields, totalHits, formatGridColumn]);

// used for which columns are visible and their order
const dataGridColumnVisibility = useMemo(() => {
Expand All @@ -130,7 +135,7 @@ export function DataGrid(props: DataGridProps) {
});
return {
visibleColumns: columns,
setVisibleColumns: (visibleColumns: string[]) => {
setVisibleColumns: () => {
// TODO: implement with sidebar field order (dragability) changes
},
};
Expand Down Expand Up @@ -268,6 +273,7 @@ export function DataGrid(props: DataGridProps) {
showStyleSelector: false,
}}
rowHeightsOptions={rowHeightsOptions}
{...OUIDataGridProps}
/>
</div>
</EuiPanel>
Expand Down
7 changes: 4 additions & 3 deletions public/components/event_analytics/utils/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,11 @@ export const redoQuery = (
const start = datemath.parse(startTime)?.utc().format(DATE_PICKER_FORMAT);
const end = datemath.parse(endTime, { roundUp: true })?.utc().format(DATE_PICKER_FORMAT);
const tokens = rawQuery.replaceAll(PPL_NEWLINE_REGEX, '').match(PPL_INDEX_INSERT_POINT_REGEX);
const timeRange = timeStampField
? `| where ${timeStampField} >= '${start}' and ${timeStampField} <= '${end}'`
: '';

finalQuery = `${tokens![1]}=${
tokens![2]
} | where ${timeStampField} >= '${start}' and ${timeStampField} <= '${end}'`;
finalQuery = `${tokens![1]}=${tokens![2]} ${timeRange}`;

finalQuery += tokens![3];

Expand Down
107 changes: 107 additions & 0 deletions public/dependencies/components/data_grid_container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState, useEffect, useCallback } from 'react';
import { useSelector } from 'react-redux';
import { EuiDataGridColumn } from '@elastic/eui';
import {
DataGrid,
DataGridProps,
} from '../../components/event_analytics/explorer/events_views/data_grid';
import { getOSDHttp, getPPLService } from '../../../common/utils';
import { selectFields } from '../../components/event_analytics/redux/slices/field_slice';
import { initialTabId } from '../../framework/redux/store/shared_state';
import { useFetchEvents } from '../../components/event_analytics/hooks';
import { redoQuery } from '../../components/event_analytics/utils/utils';
import { DEFAULT_TIMESTAMP_COLUMN } from '../../../common/constants/explorer';
import { RenderProps } from '../../types';

export const DataGridContainer = (
props: Pick<DataGridProps, 'rawQuery'> & { renderProps: RenderProps }
) => {
const { renderProps, ...others } = props;
const pplService = getPPLService();
const http = getOSDHttp();
const tabId = initialTabId;
const explorerFields = useSelector(selectFields)[tabId];
const { fetchEvents } = useFetchEvents({
pplService,
requestParams: {
tabId,
},
});
const [data, setData] = useState<any[]>([]);
const isFullScreen = renderProps.chatContext.flyoutFullScreen;
useEffect(() => {
if (props.rawQuery) {
redoQuery(
'',
'',
props.rawQuery || '',
'',
{ current: [] },
{ current: [0, 5] },
fetchEvents,
setData
);
}
}, [props.rawQuery]);
const formatGridColumn = useCallback(
(columns: EuiDataGridColumn[]) =>
columns.map((item) => {
if (item.id === DEFAULT_TIMESTAMP_COLUMN.id) {
const { initialWidth, ...otherConfig } = item;
return {
...otherConfig,
initialWidth: renderProps.chatContext.flyoutFullScreen ? initialWidth : 50,
};
}

return item;
}),
[renderProps.chatContext.flyoutFullScreen]
);
if (!data.length || !props.rawQuery) {
return null;
}
return (
<div style={{ overflowX: 'hidden' }}>
<DataGrid
http={http}
pplService={pplService}
rows={data}
explorerFields={explorerFields}
timeStampField="timestamp"
totalHits={data.length}
requestParams={{
tabId,
}}
startTime={''}
endTime="now"
storedSelectedColumns={[]}
formatGridColumn={formatGridColumn}
OUIDataGridProps={{
gridStyle: isFullScreen
? {}
: {
fontSize: 's',
cellPadding: 's',
},
/**
* Chatbot's default width is smaller than 478
*/
minSizeForControls: 300,
/**
* In non-fullscreen mode, it requires at least 80px to avoid truncate.
*/
rowHeightsOptions: {
defaultHeight: isFullScreen ? undefined : 80,
},
}}
{...others}
/>
</div>
);
};
78 changes: 0 additions & 78 deletions public/dependencies/components/ppl_visualization_model.tsx

This file was deleted.

56 changes: 8 additions & 48 deletions public/dependencies/register_assistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,61 +3,21 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { merge } from 'lodash';
import React from 'react';
import { toMountPoint } from '../../../../src/plugins/opensearch_dashboards_react/public';
import { SavedVisualization } from '../../common/types/explorer';
import { SavedObjectVisualization } from '../components/visualizations/saved_object_visualization';
import { coreRefs } from '../framework/core_refs';
import { Provider } from 'react-redux';
import { AssistantSetup } from '../types';
import { PPLVisualizationModal } from './components/ppl_visualization_model';
import { store } from '../framework/redux/store';
import { DataGridContainer } from './components/data_grid_container';

export const registerAsssitantDependencies = (setup?: AssistantSetup) => {
if (!setup) return;

setup.registerContentRenderer('ppl_visualization', (content) => {
const params = content as Partial<SavedVisualization>;
const savedVisualization = createSavedVisualization(params);
setup.registerContentRenderer('ppl_data_grid', (content, renderProps) => {
const params = content as string;
return (
<SavedObjectVisualization
savedVisualization={savedVisualization}
timeRange={{
from: savedVisualization.selected_date_range.start,
to: savedVisualization.selected_date_range.end,
}}
/>
<Provider store={store}>
<DataGridContainer rawQuery={params} renderProps={renderProps} />
</Provider>
);
});

setup.registerActionExecutor('view_ppl_visualization', async (params) => {
const savedVisualization = createSavedVisualization(params as Partial<SavedVisualization>);
const modal = coreRefs.core!.overlays.openModal(
toMountPoint(
<PPLVisualizationModal
savedVisualization={savedVisualization}
onClose={() => modal.close()}
/>
)
);
});
};

const createSavedVisualization = (params: Partial<SavedVisualization>) => {
return merge(
{
query: params.query,
selected_date_range: { start: 'now-14d', end: 'now', text: '' },
selected_timestamp: { name: 'timestamp', type: 'timestamp' },
selected_fields: { tokens: [], text: '' },
name: params.name,
description: '',
type: 'line',
sub_type: 'visualization',
},
{
selected_date_range: params.selected_date_range,
selected_timestamp: params.selected_timestamp,
type: params.type,
}
) as SavedVisualization;
};
2 changes: 1 addition & 1 deletion public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ export interface ObservabilityStart {}
* It will gives an type error when dashboards-assistant is not installed so add a ts-ignore to suppress the error.
*/
// @ts-ignore
export type { AssistantSetup } from "../../dashboards-assistant/public";
export type { AssistantSetup, RenderProps } from '../../dashboards-assistant/public';
Loading

0 comments on commit eaba163

Please sign in to comment.