Skip to content
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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,74 @@ describe('IndexPattern Data Source', () => {
<IndexPatternDimensionPanel
state={state}
setState={() => {}}
columnId={'col2'}
filterOperations={(operation: Operation) => true}
/>
);

expect(wrapper).toMatchSnapshot();
});

it('should call the filterOperations function', () => {
const filterOperations = jest.fn().mockReturnValue(true);

shallow(
<IndexPatternDimensionPanel
state={state}
setState={() => {}}
columnId={'col2'}
filterOperations={filterOperations}
/>
);

expect(filterOperations).toBeCalledTimes(3);
});

it('should filter out all selections if the filter returns false', () => {
const wrapper = shallow(
<IndexPatternDimensionPanel
state={state}
setState={() => {}}
columnId={'col2'}
filterOperations={() => false}
/>
);

expect(wrapper.find(EuiComboBox)!.prop('options')!.length).toEqual(0);
});

it('should update the datasource state on selection', () => {
const setState = jest.fn();

const wrapper = shallow(
<IndexPatternDimensionPanel
state={state}
setState={setState}
columnId={'col2'}
filterOperations={() => true}
/>
);

const comboBox = wrapper.find(EuiComboBox)!;
const firstOption = comboBox.prop('options')![0];

comboBox.prop('onChange')!([firstOption]);

expect(setState).toHaveBeenCalledWith({
...state,
columns: {
...state.columns,
col2: {
operationId: firstOption.value,
label: 'Value of timestamp',
dataType: 'date',
isBucketed: false,
operationType: 'value',
},
},
columnOrder: ['col1', 'col2'],
});
});
});
});
});
83 changes: 71 additions & 12 deletions x-pack/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface IndexPatternColumn {
operationId: string;
label: string;
dataType: DataType;
isBucketed: false;
isBucketed: boolean;

// Private
operationType: OperationType;
Expand Down Expand Up @@ -99,7 +99,69 @@ export type IndexPatternDimensionPanelProps = DatasourceDimensionPanelProps & {
};

export function IndexPatternDimensionPanel(props: IndexPatternDimensionPanelProps) {
return <div>Dimension Panel</div>;
const fields = props.state.indexPatterns[props.state.currentIndexPatternId].fields;
const columns: IndexPatternColumn[] = fields.map((field, index) => ({
operationId: `${index}`,
label: `Value of ${field.name}`,
dataType: field.type as DataType,
isBucketed: false,

operationType: 'value' as OperationType,
}));

const filteredColumns = columns.filter(col => {
const { operationId, label, dataType, isBucketed } = col;

return props.filterOperations({
id: operationId,
label,
dataType,
isBucketed,
});
});

const selectedColumn: IndexPatternColumn | null = props.state.columns[props.columnId] || null;

return (
<div>
Dimension Panel
<EuiComboBox
data-test-subj="indexPattern-dimension"
options={filteredColumns.map(col => ({
label: col.label,
value: col.operationId,
}))}
selectedOptions={
selectedColumn
? [
{
label: selectedColumn.label,
value: selectedColumn.operationId,
},
]
: []
}
singleSelection={{ asPlainText: true }}
isClearable={false}
onChange={choices => {
const column: IndexPatternColumn = columns.find(
({ operationId }) => operationId === choices[0].value
)!;
const newColumns: IndexPatternPrivateState['columns'] = {
...props.state.columns,
[props.columnId]: column,
};

props.setState({
...props.state,
columns: newColumns,
// Order is not meaningful until we aggregate
columnOrder: Object.keys(newColumns),
});
}}
/>
</div>
);
}

export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: ToastNotifications) {
Expand Down Expand Up @@ -151,16 +213,13 @@ export function getIndexPatternDatasource(chrome: Chrome, toastNotifications: To
},
getOperationForColumnId: (columnId: string) => {
const column = state.columns[columnId];
if (columnId) {
const { dataType, label, isBucketed, operationId } = column;
return {
id: operationId,
label,
dataType,
isBucketed,
};
}
return null;
const { dataType, label, isBucketed, operationId } = column;
return {
id: operationId,
label,
dataType,
isBucketed,
};
},

renderDimensionPanel: (domElement: Element, props: DatasourceDimensionPanelProps) => {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/lens/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export interface DatasourceDataPanelProps<T = unknown> {
// The only way a visualization has to restrict the query building
export interface DatasourceDimensionPanelProps {
// If no columnId is passed, it will render as empty
columnId?: string;
columnId: string;

// Visualizations can restrict operations based on their own rules
filterOperations: (operation: Operation) => boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

import React from 'react';
import { render } from 'react-dom';
import { Visualization } from '../types';
import { Visualization, Operation } from '../types';
import { NativeRenderer } from '../native_renderer';

export interface XyVisualizationState {
roles: string[];
Expand All @@ -26,7 +27,20 @@ export const xyVisualization: Visualization<XyVisualizationState, XyVisualizatio
},

renderConfigPanel: (domElement, props) => {
render(<div>XY Visualization</div>, domElement);
render(
<div>
XY Visualization
<NativeRenderer
nativeProps={{
columnId: 'col1',
filterOperations: (op: Operation) => true,
suggestedOrder: 1,
}}
render={props.datasource.renderDimensionPanel}
/>
</div>,
domElement
);
},

getSuggestions: options => [],
Expand Down