Skip to content

Commit

Permalink
[Lens] Improve suggestions when dragging field for the second time (#…
Browse files Browse the repository at this point in the history
…60687)

* [Lens] Improve suggestions when dragging into an existing visualization

* Include 0 metrics case

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
Wylie Conlon and elasticmachine committed Mar 23, 2020
1 parent ec2972c commit f7a3049
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ describe('IndexPattern Data Source suggestions', () => {
expect(suggestions[0].table.columns[0].operation.isBucketed).toBeFalsy();
});

it('prepends a terms column on string field', () => {
it('appends a terms column on string field', () => {
const initialState = stateWithNonEmptyTables();
const suggestions = getDatasourceSuggestionsForField(initialState, '1', {
name: 'dest',
Expand All @@ -795,7 +795,7 @@ describe('IndexPattern Data Source suggestions', () => {
layers: {
previousLayer: initialState.layers.previousLayer,
currentLayer: expect.objectContaining({
columnOrder: ['id1', 'cola', 'colb'],
columnOrder: ['cola', 'id1', 'colb'],
columns: {
...initialState.layers.currentLayer.columns,
id1: expect.objectContaining({
Expand All @@ -810,7 +810,7 @@ describe('IndexPattern Data Source suggestions', () => {
);
});

it('appends a metric column on a number field', () => {
it('replaces a metric column on a number field if only one other metric is already set', () => {
const initialState = stateWithNonEmptyTables();
const suggestions = getDatasourceSuggestionsForField(initialState, '1', {
name: 'memory',
Expand All @@ -819,15 +819,57 @@ describe('IndexPattern Data Source suggestions', () => {
searchable: true,
});

expect(suggestions).toContainEqual(
expect.objectContaining({
state: expect.objectContaining({
layers: expect.objectContaining({
currentLayer: expect.objectContaining({
columnOrder: ['cola', 'id1'],
columns: {
cola: initialState.layers.currentLayer.columns.cola,
id1: expect.objectContaining({
operationType: 'avg',
sourceField: 'memory',
}),
},
}),
}),
}),
})
);
});

it('adds a metric column on a number field if no other metrics set', () => {
const initialState = stateWithNonEmptyTables();
const modifiedState: IndexPatternPrivateState = {
...initialState,
layers: {
...initialState.layers,
currentLayer: {
...initialState.layers.currentLayer,
columns: {
cola: initialState.layers.currentLayer.columns.cola,
},
columnOrder: ['cola'],
},
},
};
const suggestions = getDatasourceSuggestionsForField(modifiedState, '1', {
name: 'memory',
type: 'number',
aggregatable: true,
searchable: true,
});

expect(suggestions).toContainEqual(
expect.objectContaining({
state: expect.objectContaining({
layers: {
previousLayer: initialState.layers.previousLayer,
previousLayer: modifiedState.layers.previousLayer,
currentLayer: expect.objectContaining({
columnOrder: ['cola', 'colb', 'id1'],
columnOrder: ['cola', 'id1'],
columns: {
...initialState.layers.currentLayer.columns,
...modifiedState.layers.currentLayer.columns,
id1: expect.objectContaining({
operationType: 'avg',
sourceField: 'memory',
Expand All @@ -840,10 +882,30 @@ describe('IndexPattern Data Source suggestions', () => {
);
});

it('appends a metric column with a different operation on a number field if field is already in use', () => {
it('adds a metric column on a number field if 2 or more other metric', () => {
const initialState = stateWithNonEmptyTables();
const suggestions = getDatasourceSuggestionsForField(initialState, '1', {
name: 'bytes',
const modifiedState: IndexPatternPrivateState = {
...initialState,
layers: {
...initialState.layers,
currentLayer: {
...initialState.layers.currentLayer,
columns: {
...initialState.layers.currentLayer.columns,
colc: {
dataType: 'number',
isBucketed: false,
sourceField: 'dest',
label: 'Unique count of dest',
operationType: 'cardinality',
},
},
columnOrder: ['cola', 'colb', 'colc'],
},
},
};
const suggestions = getDatasourceSuggestionsForField(modifiedState, '1', {
name: 'memory',
type: 'number',
aggregatable: true,
searchable: true,
Expand All @@ -853,14 +915,14 @@ describe('IndexPattern Data Source suggestions', () => {
expect.objectContaining({
state: expect.objectContaining({
layers: {
previousLayer: initialState.layers.previousLayer,
previousLayer: modifiedState.layers.previousLayer,
currentLayer: expect.objectContaining({
columnOrder: ['cola', 'colb', 'id1'],
columnOrder: ['cola', 'colb', 'colc', 'id1'],
columns: {
...initialState.layers.currentLayer.columns,
...modifiedState.layers.currentLayer.columns,
id1: expect.objectContaining({
operationType: 'sum',
sourceField: 'bytes',
operationType: 'avg',
sourceField: 'memory',
}),
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,29 @@ function addFieldAsMetricOperation(
field,
});
const newColumnId = generateId();
const updatedColumns = {
...layer.columns,
[newColumnId]: newColumn,
};
const updatedColumnOrder = [...layer.columnOrder, newColumnId];

const [, metrics] = separateBucketColumns(layer);

// Add metrics if there are 0 or > 1 metric
if (metrics.length !== 1) {
return {
indexPatternId: indexPattern.id,
columns: {
...layer.columns,
[newColumnId]: newColumn,
},
columnOrder: [...layer.columnOrder, newColumnId],
};
}

// If only one metric, replace instead of add
const newColumns = { ...layer.columns, [newColumnId]: newColumn };
delete newColumns[metrics[0]];

return {
indexPatternId: indexPattern.id,
columns: updatedColumns,
columnOrder: updatedColumnOrder,
columns: newColumns,
columnOrder: [...layer.columnOrder.filter(c => c !== metrics[0]), newColumnId],
};
}

Expand All @@ -231,21 +244,34 @@ function addFieldAsBucketOperation(
...layer.columns,
[newColumnId]: newColumn,
};

const oldDateHistogramIndex = layer.columnOrder.findIndex(
columnId => layer.columns[columnId].operationType === 'date_histogram'
);
const oldDateHistogramId =
oldDateHistogramIndex > -1 ? layer.columnOrder[oldDateHistogramIndex] : null;

let updatedColumnOrder: string[] = [];
if (applicableBucketOperation === 'terms') {
updatedColumnOrder = [newColumnId, ...buckets, ...metrics];
} else {
const oldDateHistogramColumn = layer.columnOrder.find(
columnId => layer.columns[columnId].operationType === 'date_histogram'
);
if (oldDateHistogramColumn) {
delete updatedColumns[oldDateHistogramColumn];
if (oldDateHistogramId) {
if (applicableBucketOperation === 'terms') {
// Insert the new terms bucket above the first date histogram
updatedColumnOrder = [
...buckets.slice(0, oldDateHistogramIndex),
newColumnId,
...buckets.slice(oldDateHistogramIndex, buckets.length),
...metrics,
];
} else if (applicableBucketOperation === 'date_histogram') {
// Replace date histogram with new date histogram
delete updatedColumns[oldDateHistogramId];
updatedColumnOrder = layer.columnOrder.map(columnId =>
columnId !== oldDateHistogramColumn ? columnId : newColumnId
columnId !== oldDateHistogramId ? columnId : newColumnId
);
} else {
updatedColumnOrder = [...buckets, newColumnId, ...metrics];
}
} else {
// Insert the new bucket after existing buckets. Users will see the same data
// they already had, with an extra level of detail.
updatedColumnOrder = [...buckets, newColumnId, ...metrics];
}
return {
indexPatternId: indexPattern.id,
Expand Down

0 comments on commit f7a3049

Please sign in to comment.