diff --git a/x-pack/plugins/lens/public/indexpattern_plugin/__snapshots__/indexpattern.test.tsx.snap b/x-pack/plugins/lens/public/indexpattern_plugin/__snapshots__/indexpattern.test.tsx.snap new file mode 100644 index 0000000000000..fb8abf6ccb664 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_plugin/__snapshots__/indexpattern.test.tsx.snap @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IndexPattern Data Source #getPublicAPI renderDimensionPanel should render a dimension panel 1`] = ` +
+ Dimension Panel +
+`; + +exports[`IndexPattern Data Source #renderDataPanel should match snapshot 1`] = ` +
+ Index Pattern Data Source +
+ +
+
+ timestamp +
+
+ bytes +
+
+ source +
+
+
+
+`; diff --git a/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.tsx similarity index 69% rename from x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts rename to x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.tsx index 40c119de69667..4130c42617eb2 100644 --- a/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.test.tsx @@ -4,10 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ +import { shallow } from 'enzyme'; +import React from 'react'; +import { EuiComboBox } from '@elastic/eui'; import { getIndexPatternDatasource, IndexPatternPersistedState, IndexPatternPrivateState, + IndexPatternDataPanel, + IndexPatternDimensionPanel, } from './indexpattern'; import { DatasourcePublicAPI, Operation, Datasource } from '../types'; @@ -75,7 +80,7 @@ describe('IndexPattern Data Source', () => { indexPatternDatasource = getIndexPatternDatasource(); persistedState = { - currentIndexPattern: '1', + currentIndexPatternId: '1', columnOrder: ['col1'], columns: { col1: { @@ -95,7 +100,7 @@ describe('IndexPattern Data Source', () => { it('should load a default state', async () => { const state = await indexPatternDatasource.initialize(); expect(state).toEqual({ - currentIndexPattern: '1', + currentIndexPatternId: '1', indexPatterns: expectedIndexPatterns, columns: {}, columnOrder: [], @@ -104,7 +109,6 @@ describe('IndexPattern Data Source', () => { it('should initialize from saved state', async () => { const state = await indexPatternDatasource.initialize(persistedState); - expect(state).toEqual({ ...persistedState, indexPatterns: expectedIndexPatterns, @@ -112,6 +116,40 @@ describe('IndexPattern Data Source', () => { }); }); + describe('#renderDataPanel', () => { + let state: IndexPatternPrivateState; + + beforeEach(async () => { + state = await indexPatternDatasource.initialize(persistedState); + }); + + it('should match snapshot', () => { + expect( + shallow( {}} />) + ).toMatchSnapshot(); + }); + + it('should call setState when the index pattern is switched', async () => { + const setState = jest.fn(); + + const wrapper = shallow(); + + const comboBox = wrapper.find(EuiComboBox); + + comboBox.prop('onChange')!([ + { + label: expectedIndexPatterns['2'].title, + value: '2', + }, + ]); + + expect(setState).toHaveBeenCalledWith({ + ...state, + currentIndexPatternId: '2', + }); + }); + }); + describe('#getPersistedState', () => { it('should persist from saved state', async () => { const state = await indexPatternDatasource.initialize(persistedState); @@ -148,5 +186,25 @@ describe('IndexPattern Data Source', () => { } as Operation); }); }); + + describe('renderDimensionPanel', () => { + let state: IndexPatternPrivateState; + + beforeEach(async () => { + state = await indexPatternDatasource.initialize(persistedState); + }); + + it('should render a dimension panel', () => { + const wrapper = shallow( + {}} + filterOperations={(operation: Operation) => true} + /> + ); + + expect(wrapper).toMatchSnapshot(); + }); + }); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.tsx index 0355bb8ae18c8..140c54031677f 100644 --- a/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.tsx @@ -5,9 +5,10 @@ */ import React from 'react'; +import { render } from 'react-dom'; import { Chrome } from 'ui/chrome'; import { ToastNotifications } from 'ui/notify/toasts/toast_notifications'; -import { render } from 'react-dom'; +import { EuiComboBox } from '@elastic/eui'; import { Datasource, DataType } from '..'; import { DatasourceDimensionPanelProps, DatasourceDataPanelProps } from '../types'; import { getIndexPatterns } from './loader'; @@ -41,7 +42,7 @@ export interface IndexPatternField { } export interface IndexPatternPersistedState { - currentIndexPattern: string; + currentIndexPatternId: string; columnOrder: string[]; columns: Record; @@ -51,6 +52,56 @@ export type IndexPatternPrivateState = IndexPatternPersistedState & { indexPatterns: Record; }; +export function IndexPatternDataPanel(props: DatasourceDataPanelProps) { + return ( +
+ Index Pattern Data Source +
+ ({ + label: title, + value: id, + }))} + selectedOptions={ + props.state.currentIndexPatternId + ? [ + { + label: props.state.indexPatterns[props.state.currentIndexPatternId].title, + value: props.state.indexPatterns[props.state.currentIndexPatternId].id, + }, + ] + : undefined + } + singleSelection={{ asPlainText: true }} + isClearable={false} + onChange={choices => { + props.setState({ + ...props.state, + currentIndexPatternId: choices[0].value as string, + }); + }} + /> +
+ {props.state.currentIndexPatternId && + props.state.indexPatterns[props.state.currentIndexPatternId].fields.map(field => ( +
{field.name}
+ ))} +
+
+
+ ); +} + +export type IndexPatternDimensionPanelProps = DatasourceDimensionPanelProps & { + state: IndexPatternPrivateState; + setState: (newState: IndexPatternPrivateState) => void; +}; + +export function IndexPatternDimensionPanel(props: IndexPatternDimensionPanelProps) { + return
Dimension Panel
; +} + export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: ToastNotifications) { // Not stateful. State is persisted to the frame const indexPatternDatasource: Datasource = { @@ -71,15 +122,15 @@ export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: To }; } return { - currentIndexPattern: indexPatternObjects ? indexPatternObjects[0].id : '', + currentIndexPatternId: indexPatternObjects ? indexPatternObjects[0].id : '', indexPatterns, columns: {}, columnOrder: [], }; }, - getPersistableState({ currentIndexPattern, columns, columnOrder }: IndexPatternPrivateState) { - return { currentIndexPattern, columns, columnOrder }; + getPersistableState({ currentIndexPatternId, columns, columnOrder }: IndexPatternPrivateState) { + return { currentIndexPatternId, columns, columnOrder }; }, toExpression(state: IndexPatternPrivateState) { @@ -90,18 +141,7 @@ export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: To domElement: Element, props: DatasourceDataPanelProps ) { - render( -
- Index Pattern Data Source -
- {props.state.currentIndexPattern && - Object.keys(props.state.indexPatterns).map(key => ( -
{props.state.indexPatterns[key].title}
- ))} -
-
, - domElement - ); + render(, domElement); }, getPublicAPI(state, setState) { @@ -123,7 +163,12 @@ export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: To return null; }, - renderDimensionPanel: (domElement: Element, props: DatasourceDimensionPanelProps) => {}, + renderDimensionPanel: (domElement: Element, props: DatasourceDimensionPanelProps) => { + render( + , + domElement + ); + }, removeColumnInTableSpec: (columnId: string) => [], moveColumnTo: (columnId: string, targetIndex: number) => {},