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

[Lens] Hide some suggestions in preparation for pie charts #64740

Merged
merged 4 commits into from
Apr 30, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ export const datatableVisualization: Visualization<
],
},
previewIcon: chartTableSVG,
// dont show suggestions for reduced versions or single-line tables
hide: table.changeType === 'reduced' || !table.isMultiRow,
// tables are hidden from suggestion bar, but used for drag & drop and chart switching
hide: true,
},
];
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,62 @@ describe('IndexPattern Data Source suggestions', () => {
expect(suggestions[0].table.columns.length).toBe(1);
expect(suggestions[0].table.columns[0].operation.label).toBe('Sum of field1');
});

it('contains a reordering suggestion when there are exactly 2 buckets', () => {
const initialState = testInitialState();
const state: IndexPatternPrivateState = {
indexPatternRefs: [],
existingFields: {},
currentIndexPatternId: '1',
indexPatterns: expectedIndexPatterns,
showEmptyFields: true,
layers: {
first: {
...initialState.layers.first,
columns: {
id1: {
label: 'Date histogram',
dataType: 'date',
isBucketed: true,

operationType: 'date_histogram',
sourceField: 'field2',
params: {
interval: 'd',
},
},
id2: {
label: 'Top 5',
dataType: 'string',
isBucketed: true,

operationType: 'terms',
sourceField: 'field1',
params: { size: 5, orderBy: { type: 'alphabetical' }, orderDirection: 'asc' },
},
id3: {
label: 'Average of field1',
dataType: 'number',
isBucketed: false,

operationType: 'avg',
sourceField: 'field1',
},
},
columnOrder: ['id1', 'id2', 'id3'],
},
},
};

const suggestions = getDatasourceSuggestionsFromCurrentState(state);
expect(suggestions).toContainEqual(
expect.objectContaining({
table: expect.objectContaining({
changeType: 'reorder',
}),
})
);
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ function createChangedNestingSuggestion(state: IndexPatternPrivateState, layerId
layerId,
updatedLayer,
label: getNestedTitle([layer.columns[secondBucket], layer.columns[firstBucket]]),
changeType: 'extended',
changeType: 'reorder',
});
}

Expand Down
9 changes: 8 additions & 1 deletion x-pack/plugins/lens/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,16 @@ export interface TableSuggestion {
* * `unchanged` means the table is the same in the currently active configuration
* * `reduced` means the table is a reduced version of the currently active table (some columns dropped, but not all of them)
* * `extended` means the table is an extended version of the currently active table (added one or multiple additional columns)
* * `reorder` means the table columns have changed order, which change the data as well
Copy link
Contributor

Choose a reason for hiding this comment

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

out of curiosity, this is not possible yet in current lens?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah we were calling these "extended" tables, but that was before wanting to do special handling of these for the XY chart.

* * `layers` means the change is a change to the layer structure, not to the table
*/
export type TableChangeType = 'initial' | 'unchanged' | 'reduced' | 'extended' | 'layers';
export type TableChangeType =
| 'initial'
| 'unchanged'
| 'reduced'
| 'extended'
| 'reorder'
| 'layers';

export interface DatasourceSuggestion<T = unknown> {
state: T;
Expand Down
72 changes: 69 additions & 3 deletions x-pack/plugins/lens/public/xy_visualization/xy_suggestions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ describe('xy_suggestions', () => {
isMultiRow: true,
columns: [numCol('price'), numCol('quantity'), dateCol('date'), strCol('product')],
layerId: 'first',
changeType: 'unchanged',
changeType: 'extended',
label: 'Datasource title',
},
keptLayerIds: [],
Expand All @@ -196,6 +196,34 @@ describe('xy_suggestions', () => {
expect(suggestion.title).toEqual('Datasource title');
});

test('suggests only stacked bar chart when xy chart is inactive', () => {
const [suggestion, ...rest] = getSuggestions({
table: {
isMultiRow: true,
columns: [dateCol('date'), numCol('price')],
layerId: 'first',
changeType: 'unchanged',
label: 'Datasource title',
},
keptLayerIds: [],
});

expect(rest).toHaveLength(0);
expect(suggestion.title).toEqual('Bar chart');
expect(suggestion.state).toEqual(
expect.objectContaining({
layers: [
expect.objectContaining({
seriesType: 'bar_stacked',
xAccessor: 'date',
accessors: ['price'],
splitAccessor: undefined,
}),
],
})
);
});

test('hides reduced suggestions if there is a current state', () => {
const [suggestion, ...rest] = getSuggestions({
table: {
Expand Down Expand Up @@ -224,7 +252,7 @@ describe('xy_suggestions', () => {
expect(suggestion.hide).toBeTruthy();
});

test('does not hide reduced suggestions if xy visualization is not active', () => {
test('hides reduced suggestions if xy visualization is not active', () => {
const [suggestion, ...rest] = getSuggestions({
table: {
isMultiRow: true,
Expand All @@ -236,7 +264,7 @@ describe('xy_suggestions', () => {
});

expect(rest).toHaveLength(0);
expect(suggestion.hide).toBeFalsy();
expect(suggestion.hide).toBeTruthy();
});

test('only makes a seriesType suggestion for unchanged table without split', () => {
Expand Down Expand Up @@ -419,6 +447,44 @@ describe('xy_suggestions', () => {
});
});

test('changes column mappings when suggestion is reorder', () => {
const currentState: XYState = {
legend: { isVisible: true, position: 'bottom' },
preferredSeriesType: 'bar',
layers: [
{
accessors: ['price'],
layerId: 'first',
seriesType: 'bar',
splitAccessor: 'category',
xAccessor: 'product',
},
],
};
const [suggestion, ...rest] = getSuggestions({
table: {
isMultiRow: true,
columns: [strCol('category'), strCol('product'), numCol('price')],
layerId: 'first',
changeType: 'reorder',
},
state: currentState,
keptLayerIds: [],
});

expect(rest).toHaveLength(0);
expect(suggestion.state).toEqual({
...currentState,
layers: [
{
...currentState.layers[0],
xAccessor: 'category',
splitAccessor: 'product',
},
],
});
});

test('overwrites column to dimension mappings if a date dimension is added', () => {
(generateId as jest.Mock).mockReturnValueOnce('dummyCol');
const currentState: XYState = {
Expand Down
26 changes: 22 additions & 4 deletions x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,14 @@ function getBucketMappings(table: TableSuggestion, currentState?: State) {
// reverse the buckets before prioritization to always use the most inner
// bucket of the highest-prioritized group as x value (don't use nested
// buckets as split series)
const prioritizedBuckets = prioritizeColumns(buckets.reverse());
const prioritizedBuckets = prioritizeColumns([...buckets].reverse());

if (!currentLayer || table.changeType === 'initial') {
return prioritizedBuckets;
}
if (table.changeType === 'reorder') {
return buckets;
}

// if existing table is just modified, try to map buckets to the current dimensions
const currentXColumnIndex = prioritizedBuckets.findIndex(
Expand Down Expand Up @@ -175,12 +178,24 @@ function getSuggestionsForLayer({
keptLayerIds,
};

const isSameState = currentState && changeType === 'unchanged';
// handles the simplest cases, acting as a chart switcher
if (!currentState && changeType === 'unchanged') {
return [
{
...buildSuggestion(options),
title: i18n.translate('xpack.lens.xySuggestions.barChartTitle', {
defaultMessage: 'Bar chart',
}),
},
];
}

const isSameState = currentState && changeType === 'unchanged';
if (!isSameState) {
return buildSuggestion(options);
}

// Suggestions are either changing the data, or changing the way the data is used
const sameStateSuggestions: Array<VisualizationSuggestion<State>> = [];

// if current state is using the same data, suggest same chart with different presentational configuration
Expand Down Expand Up @@ -374,8 +389,11 @@ function buildSuggestion({
return {
title,
score: getScore(yValues, splitBy, changeType),
// don't advertise chart of same type but with less data
hide: currentState && changeType === 'reduced',
hide:
// Only advertise very clear changes when XY chart is not active
(!currentState && changeType !== 'unchanged' && changeType !== 'extended') ||
// Don't advertise removing dimensions
(currentState && changeType === 'reduced'),
state,
previewIcon: getIconForSeries(seriesType),
};
Expand Down