diff --git a/src/plugins/vis_augmenter/public/test_constants.ts b/src/plugins/vis_augmenter/public/test_constants.ts index 0e45fdc05725..61ced45b41ea 100644 --- a/src/plugins/vis_augmenter/public/test_constants.ts +++ b/src/plugins/vis_augmenter/public/test_constants.ts @@ -14,6 +14,8 @@ const TEST_VALUE_AXIS_ID_DIRTY = 'test.value.axis.id'; const TEST_X_AXIS_TITLE = 'time'; const TEST_VALUE_AXIS_TITLE = 'avg value'; const TEST_PLUGIN = 'test-plugin'; +const TEST_PLUGIN_EVENT_TYPE = 'test-plugin-event-type'; +const TEST_PLUGIN_EVENT_TYPE_2 = 'test-plugin-event-type-2'; const TEST_PLUGIN_RESOURCE_TYPE = 'test-resource-type'; const TEST_PLUGIN_RESOURCE_ID = 'test-resource-id'; const TEST_PLUGIN_RESOURCE_ID_2 = 'test-resource-id-2'; @@ -25,18 +27,18 @@ const TEST_PLUGIN_RESOURCE_PATH_2 = `${TEST_PLUGIN}/${TEST_PLUGIN_RESOURCE_TYPE} const TEST_VALUES_SINGLE_ROW_NO_VIS_LAYERS = [{ [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5 }]; const TEST_VALUES_SINGLE_ROW_SINGLE_VIS_LAYER = [ - { [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_RESOURCE_ID]: 3 }, + { [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_EVENT_TYPE]: 3 }, ]; const TEST_VALUES_ONLY_VIS_LAYERS = [ { [TEST_X_AXIS_ID]: 0 }, - { [TEST_X_AXIS_ID]: 5, [TEST_PLUGIN_RESOURCE_ID]: 2 }, + { [TEST_X_AXIS_ID]: 5, [TEST_PLUGIN_EVENT_TYPE]: 2 }, { [TEST_X_AXIS_ID]: 10 }, { [TEST_X_AXIS_ID]: 15 }, { [TEST_X_AXIS_ID]: 20 }, { [TEST_X_AXIS_ID]: 25 }, { [TEST_X_AXIS_ID]: 30 }, - { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_RESOURCE_ID]: 1 }, + { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_EVENT_TYPE]: 1 }, { [TEST_X_AXIS_ID]: 40 }, { [TEST_X_AXIS_ID]: 45 }, { [TEST_X_AXIS_ID]: 50 }, @@ -72,20 +74,20 @@ const TEST_VALUES_NO_VIS_LAYERS_DIRTY = [ const TEST_VALUES_SINGLE_VIS_LAYER = [ { [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5 }, - { [TEST_X_AXIS_ID]: 5, [TEST_VALUE_AXIS_ID]: 10, [TEST_PLUGIN_RESOURCE_ID]: 2 }, + { [TEST_X_AXIS_ID]: 5, [TEST_VALUE_AXIS_ID]: 10, [TEST_PLUGIN_EVENT_TYPE]: 2 }, { [TEST_X_AXIS_ID]: 10, [TEST_VALUE_AXIS_ID]: 6 }, { [TEST_X_AXIS_ID]: 15, [TEST_VALUE_AXIS_ID]: 4 }, { [TEST_X_AXIS_ID]: 20, [TEST_VALUE_AXIS_ID]: 5 }, { [TEST_X_AXIS_ID]: 25 }, { [TEST_X_AXIS_ID]: 30 }, - { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_RESOURCE_ID]: 1 }, + { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_EVENT_TYPE]: 1 }, { [TEST_X_AXIS_ID]: 40 }, { [TEST_X_AXIS_ID]: 45, [TEST_VALUE_AXIS_ID]: 3 }, { [TEST_X_AXIS_ID]: 50, [TEST_VALUE_AXIS_ID]: 5 }, ]; const TEST_VALUES_SINGLE_VIS_LAYER_ON_BOUNDS = [ - { [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_RESOURCE_ID]: 2 }, + { [TEST_X_AXIS_ID]: 0, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_EVENT_TYPE]: 2 }, { [TEST_X_AXIS_ID]: 5, [TEST_VALUE_AXIS_ID]: 10 }, { [TEST_X_AXIS_ID]: 10, [TEST_VALUE_AXIS_ID]: 6 }, { [TEST_X_AXIS_ID]: 15, [TEST_VALUE_AXIS_ID]: 4 }, @@ -95,7 +97,7 @@ const TEST_VALUES_SINGLE_VIS_LAYER_ON_BOUNDS = [ { [TEST_X_AXIS_ID]: 35 }, { [TEST_X_AXIS_ID]: 40 }, { [TEST_X_AXIS_ID]: 45, [TEST_VALUE_AXIS_ID]: 3 }, - { [TEST_X_AXIS_ID]: 50, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_RESOURCE_ID]: 1 }, + { [TEST_X_AXIS_ID]: 50, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_EVENT_TYPE]: 1 }, ]; const TEST_VALUES_MULTIPLE_VIS_LAYERS = [ @@ -103,18 +105,18 @@ const TEST_VALUES_MULTIPLE_VIS_LAYERS = [ { [TEST_X_AXIS_ID]: 5, [TEST_VALUE_AXIS_ID]: 10, - [TEST_PLUGIN_RESOURCE_ID]: 2, - [TEST_PLUGIN_RESOURCE_ID_2]: 1, + [TEST_PLUGIN_EVENT_TYPE]: 2, + [TEST_PLUGIN_EVENT_TYPE_2]: 1, }, { [TEST_X_AXIS_ID]: 10, [TEST_VALUE_AXIS_ID]: 6 }, - { [TEST_X_AXIS_ID]: 15, [TEST_VALUE_AXIS_ID]: 4, [TEST_PLUGIN_RESOURCE_ID_2]: 1 }, + { [TEST_X_AXIS_ID]: 15, [TEST_VALUE_AXIS_ID]: 4, [TEST_PLUGIN_EVENT_TYPE_2]: 1 }, { [TEST_X_AXIS_ID]: 20, [TEST_VALUE_AXIS_ID]: 5 }, { [TEST_X_AXIS_ID]: 25 }, { [TEST_X_AXIS_ID]: 30 }, - { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_RESOURCE_ID]: 1 }, + { [TEST_X_AXIS_ID]: 35, [TEST_PLUGIN_EVENT_TYPE]: 1 }, { [TEST_X_AXIS_ID]: 40 }, { [TEST_X_AXIS_ID]: 45, [TEST_VALUE_AXIS_ID]: 3 }, - { [TEST_X_AXIS_ID]: 50, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_RESOURCE_ID_2]: 2 }, + { [TEST_X_AXIS_ID]: 50, [TEST_VALUE_AXIS_ID]: 5, [TEST_PLUGIN_EVENT_TYPE_2]: 2 }, ]; export const TEST_COLUMNS_NO_VIS_LAYERS = [ @@ -142,8 +144,8 @@ export const TEST_COLUMNS_NO_VIS_LAYERS_DIRTY = [ export const TEST_COLUMNS_SINGLE_VIS_LAYER = [ ...TEST_COLUMNS_NO_VIS_LAYERS, { - id: TEST_PLUGIN_RESOURCE_ID, - name: TEST_PLUGIN_RESOURCE_NAME, + id: TEST_PLUGIN_EVENT_TYPE, + name: `${TEST_PLUGIN_EVENT_TYPE} count`, meta: { type: VIS_LAYER_COLUMN_TYPE, }, @@ -153,8 +155,8 @@ export const TEST_COLUMNS_SINGLE_VIS_LAYER = [ export const TEST_COLUMNS_MULTIPLE_VIS_LAYERS = [ ...TEST_COLUMNS_SINGLE_VIS_LAYER, { - id: TEST_PLUGIN_RESOURCE_ID_2, - name: TEST_PLUGIN_RESOURCE_NAME_2, + id: TEST_PLUGIN_EVENT_TYPE_2, + name: `${TEST_PLUGIN_EVENT_TYPE_2} count`, meta: { type: VIS_LAYER_COLUMN_TYPE, }, @@ -322,6 +324,7 @@ export const TEST_VIS_LAYERS_SINGLE = [ name: TEST_PLUGIN_RESOURCE_NAME, urlPath: TEST_PLUGIN_RESOURCE_PATH, }, + pluginEventType: TEST_PLUGIN_EVENT_TYPE, events: [ { timestamp: 4, @@ -355,6 +358,7 @@ export const TEST_VIS_LAYERS_SINGLE_INVALID_BOUNDS = [ name: TEST_PLUGIN_RESOURCE_NAME, urlPath: TEST_PLUGIN_RESOURCE_PATH, }, + pluginEventType: TEST_PLUGIN_EVENT_TYPE, events: [ { timestamp: -5, @@ -388,6 +392,7 @@ export const TEST_VIS_LAYERS_SINGLE_EMPTY_EVENTS = [ name: TEST_PLUGIN_RESOURCE_NAME, urlPath: TEST_PLUGIN_RESOURCE_PATH, }, + pluginEventType: TEST_PLUGIN_EVENT_TYPE, }, ]; @@ -401,6 +406,7 @@ export const TEST_VIS_LAYERS_SINGLE_ON_BOUNDS = [ name: TEST_PLUGIN_RESOURCE_NAME, urlPath: TEST_PLUGIN_RESOURCE_PATH, }, + pluginEventType: TEST_PLUGIN_EVENT_TYPE, events: [ { timestamp: 0, @@ -435,6 +441,7 @@ export const TEST_VIS_LAYERS_MULTIPLE = [ name: TEST_PLUGIN_RESOURCE_NAME_2, urlPath: TEST_PLUGIN_RESOURCE_PATH_2, }, + pluginEventType: TEST_PLUGIN_EVENT_TYPE_2, events: [ { timestamp: 5, @@ -466,7 +473,7 @@ export const TEST_VIS_LAYERS_MULTIPLE = [ const TEST_RULE_LAYER_SINGLE_VIS_LAYER = { mark: { type: 'rule', color: 'red', opacity: 1 }, - transform: [{ filter: `datum['${TEST_PLUGIN_RESOURCE_ID}'] > 0` }], + transform: [{ filter: `datum['${TEST_PLUGIN_EVENT_TYPE}'] > 0` }], encoding: { x: { field: TEST_X_AXIS_ID, type: 'temporal' }, opacity: { value: 0, condition: { empty: false, param: HOVER_PARAM, value: 1 } }, @@ -477,7 +484,7 @@ const TEST_RULE_LAYER_MULTIPLE_VIS_LAYERS = { ...TEST_RULE_LAYER_SINGLE_VIS_LAYER, transform: [ { - filter: `datum['${TEST_PLUGIN_RESOURCE_ID}'] > 0 || datum['${TEST_PLUGIN_RESOURCE_ID_2}'] > 0`, + filter: `datum['${TEST_PLUGIN_EVENT_TYPE}'] > 0 || datum['${TEST_PLUGIN_EVENT_TYPE_2}'] > 0`, }, ], }; @@ -491,9 +498,10 @@ const TEST_EVENTS_LAYER_SINGLE_VIS_LAYER = { filled: true, opacity: 1, style: [`${VisAnnotationType.POINT_IN_TIME_ANNOTATION}`], + tooltip: true, }, transform: [ - { filter: `datum['${TEST_PLUGIN_RESOURCE_ID}'] > 0` }, + { filter: `datum['${TEST_PLUGIN_EVENT_TYPE}'] > 0` }, { calculate: `'${VisAnnotationType.POINT_IN_TIME_ANNOTATION}'`, as: 'annotationType' }, ], params: [{ name: HOVER_PARAM, select: { type: 'point', on: 'mouseover' } }], @@ -532,6 +540,7 @@ const TEST_EVENTS_LAYER_SINGLE_VIS_LAYER = { }, }, size: { condition: { empty: false, param: HOVER_PARAM, value: 140 }, value: 100 }, + tooltip: [{ field: TEST_PLUGIN_EVENT_TYPE }], }, }; @@ -539,10 +548,14 @@ const TEST_EVENTS_LAYER_MULTIPLE_VIS_LAYERS = { ...TEST_EVENTS_LAYER_SINGLE_VIS_LAYER, transform: [ { - filter: `datum['${TEST_PLUGIN_RESOURCE_ID}'] > 0 || datum['${TEST_PLUGIN_RESOURCE_ID_2}'] > 0`, + filter: `datum['${TEST_PLUGIN_EVENT_TYPE}'] > 0 || datum['${TEST_PLUGIN_EVENT_TYPE_2}'] > 0`, }, { calculate: `'${VisAnnotationType.POINT_IN_TIME_ANNOTATION}'`, as: 'annotationType' }, ], + encoding: { + ...TEST_EVENTS_LAYER_SINGLE_VIS_LAYER.encoding, + tooltip: [{ field: TEST_PLUGIN_EVENT_TYPE }, { field: TEST_PLUGIN_EVENT_TYPE_2 }], + }, }; export const TEST_RESULT_SPEC_SINGLE_VIS_LAYER = { diff --git a/src/plugins/vis_augmenter/public/types.ts b/src/plugins/vis_augmenter/public/types.ts index d7a75c12d125..6c63ccae3144 100644 --- a/src/plugins/vis_augmenter/public/types.ts +++ b/src/plugins/vis_augmenter/public/types.ts @@ -37,7 +37,6 @@ export type VisLayers = VisLayer[]; export interface EventMetadata { pluginResourceId: string; - tooltip?: string; } export interface PointInTimeEvent { @@ -47,6 +46,7 @@ export interface PointInTimeEvent { export interface PointInTimeEventsVisLayer extends VisLayer { events: PointInTimeEvent[]; + pluginEventType: string; } export const isPointInTimeEventsVisLayer = (obj: any) => { diff --git a/src/plugins/vis_augmenter/public/vega/helpers.test.ts b/src/plugins/vis_augmenter/public/vega/helpers.test.ts index 3f0145dc16d0..f0df25a81546 100644 --- a/src/plugins/vis_augmenter/public/vega/helpers.test.ts +++ b/src/plugins/vis_augmenter/public/vega/helpers.test.ts @@ -15,6 +15,7 @@ import { addMissingRowsToTableBounds, addPointInTimeEventsLayersToTable, addPointInTimeEventsLayersToSpec, + generateVisLayerTooltipFields, } from './helpers'; import { VIS_LAYER_COLUMN_TYPE, VisLayerTypes, PointInTimeEventsVisLayer, VisLayer } from '../'; import { @@ -178,6 +179,24 @@ describe('helpers', function () { }); }); + describe('generateVisLayerTooltipFields()', function () { + it('empty array returns empty', function () { + const visLayerColumnIds = [] as string[]; + const tooltipFields = [] as Array<{ field: string }>; + expect(generateVisLayerTooltipFields(visLayerColumnIds)).toStrictEqual(tooltipFields); + }); + it('array with one value returns correct array', function () { + const visLayerColumnIds = ['test-id-1']; + const tooltipFields = [{ field: 'test-id-1' }]; + expect(generateVisLayerTooltipFields(visLayerColumnIds)).toStrictEqual(tooltipFields); + }); + it('array with multiple values returns correct array', function () { + const visLayerColumnIds = ['test-id-1', 'test-id-2']; + const tooltipFields = [{ field: 'test-id-1' }, { field: 'test-id-2' }]; + expect(generateVisLayerTooltipFields(visLayerColumnIds)).toStrictEqual(tooltipFields); + }); + }); + describe('addMissingRowsToTableBounds()', function () { const columnId = 'test-id'; const columnName = 'test-name'; @@ -356,7 +375,7 @@ describe('helpers', function () { TEST_VIS_LAYERS_SINGLE ) ).toStrictEqual({ - ...TEST_DATATABLE_SINGLE_VIS_LAYER_EMPTY, + ...TEST_DATATABLE_NO_VIS_LAYERS, rows: [], }); }); diff --git a/src/plugins/vis_augmenter/public/vega/helpers.ts b/src/plugins/vis_augmenter/public/vega/helpers.ts index 086f2c4f4ae2..2c4044754727 100644 --- a/src/plugins/vis_augmenter/public/vega/helpers.ts +++ b/src/plugins/vis_augmenter/public/vega/helpers.ts @@ -123,6 +123,16 @@ export const generateVisLayerFilterString = (visLayerColumnIds: string[]): strin } }; +export const generateVisLayerTooltipFields = ( + visLayerColumnIds: string[] +): Array<{ field: string }> => { + return visLayerColumnIds.map((id) => { + return { + field: id, + }; + }); +}; + /** * By default, the source datatable will not include rows with empty data. * For handling events that may belong in missing buckets that are not yet @@ -195,28 +205,34 @@ export const addPointInTimeEventsLayersToTable = ( const augmentedTable = addMissingRowsToTableBounds(datatable, dimensions); const xAxisId = getXAxisId(dimensions, augmentedTable.columns); - if (isEmpty(visLayers)) return augmentedTable; + if (isEmpty(visLayers) || augmentedTable.rows.length === 0) return augmentedTable; - visLayers.every((visLayer: PointInTimeEventsVisLayer) => { - const visLayerColumnId = `${visLayer.pluginResource.id}`; - const visLayerColumnName = `${visLayer.pluginResource.name}`; + // Create columns for every unique event type. This is so we can aggregate on the different event types + // (e.g., 'Anomalies', 'Alerts') + [ + ...new Set(visLayers.map((visLayer: PointInTimeEventsVisLayer) => visLayer.pluginEventType)), + ].forEach((pluginEventType: string) => { augmentedTable.columns.push({ - id: visLayerColumnId, - name: visLayerColumnName, + id: pluginEventType, + name: `${pluginEventType} count`, meta: { type: VIS_LAYER_COLUMN_TYPE, }, }); + }); - if (augmentedTable.rows.length === 0 || isEmpty(visLayer.events)) return false; + visLayers.forEach((visLayer: PointInTimeEventsVisLayer) => { + if (isEmpty(visLayer.events)) return; + const visLayerColumnId = `${visLayer.pluginEventType}`; // if only one row / one datapoint, put all events into this bucket if (augmentedTable.rows.length === 1) { augmentedTable.rows[0] = { ...augmentedTable.rows[0], - [visLayerColumnId]: visLayer.events.length, + [visLayerColumnId]: + (get(augmentedTable.rows[0], visLayerColumnId, 0) as number) + visLayer.events.length, }; - return false; + return; } // Bin the timestamps to the closest x-axis key, adding @@ -267,8 +283,6 @@ export const addPointInTimeEventsLayersToTable = ( break; } }); - - return true; }); return augmentedTable; }; @@ -372,6 +386,7 @@ export const addPointInTimeEventsLayersToSpec = ( condition: { empty: false, param: HOVER_PARAM, value: EVENT_MARK_SIZE_ENLARGED }, value: EVENT_MARK_SIZE, }, + tooltip: generateVisLayerTooltipFields(visLayerColumnIds), }, });