Move response handlers into plugins (#55489)
* Duplicate and move response handlers into resp directories * Fix agg_table mocha test failures
This commit is contained in:
parent
b39076e2bd
commit
2eb6a2f3bc
|
@ -81,8 +81,6 @@ export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
|
|||
export { timezoneProvider } from 'ui/vis/lib/timezone';
|
||||
// @ts-ignore
|
||||
export { tabifyAggResponse } from 'ui/agg_response/tabify';
|
||||
// @ts-ignore
|
||||
export { vislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib';
|
||||
export { ensureDefaultIndexPattern } from 'ui/legacy_compat';
|
||||
export { unhashUrl } from '../../../../../plugins/kibana_utils/public';
|
||||
// @ts-ignore
|
||||
|
@ -101,3 +99,6 @@ export { ElasticSearchHit } from './np_ready/doc_views/doc_views_types';
|
|||
export { Adapters } from 'ui/inspector/types';
|
||||
export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';
|
||||
export { FieldName } from 'ui/directives/field_name/field_name';
|
||||
export { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
|
||||
// @ts-ignore
|
||||
export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series';
|
||||
|
|
|
@ -36,6 +36,7 @@ import { showOpenSearchPanel } from '../components/top_nav/show_open_search_pane
|
|||
import { addHelpMenuToAppChrome } from '../components/help_menu/help_menu_util';
|
||||
import '../components/fetch_error';
|
||||
import { getPainlessError } from './get_painless_error';
|
||||
import { discoverResponseHandler } from './response_handler';
|
||||
import {
|
||||
angular,
|
||||
buildVislibDimensions,
|
||||
|
@ -52,7 +53,6 @@ import {
|
|||
stateMonitorFactory,
|
||||
subscribeWithScope,
|
||||
tabifyAggResponse,
|
||||
vislibSeriesResponseHandlerProvider,
|
||||
Vis,
|
||||
SavedObjectSaveModal,
|
||||
getAngularModule,
|
||||
|
@ -187,7 +187,6 @@ function discoverController(
|
|||
$timeout,
|
||||
$window,
|
||||
AppState,
|
||||
Private,
|
||||
Promise,
|
||||
config,
|
||||
kbnUrl,
|
||||
|
@ -196,7 +195,6 @@ function discoverController(
|
|||
getAppState,
|
||||
globalState
|
||||
) {
|
||||
const responseHandler = vislibSeriesResponseHandlerProvider().handler;
|
||||
const filterStateManager = new FilterStateManager(globalState, getAppState, filterManager);
|
||||
|
||||
const inspectorAdapters = {
|
||||
|
@ -850,11 +848,9 @@ function discoverController(
|
|||
timeRange: $scope.timeRange,
|
||||
searchSource: $scope.searchSource,
|
||||
})
|
||||
)
|
||||
.then(resp => responseHandler(tabifiedData, resp))
|
||||
.then(resp => {
|
||||
$scope.histogramData = resp;
|
||||
});
|
||||
).then(resp => {
|
||||
$scope.histogramData = discoverResponseHandler(tabifiedData, resp);
|
||||
});
|
||||
}
|
||||
|
||||
$scope.hits = resp.hits.total;
|
||||
|
|
119
src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js
vendored
Normal file
119
src/legacy/core_plugins/kibana/public/discover/np_ready/angular/response_handler.js
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { buildPointSeriesData, getFormat } from '../../kibana_services';
|
||||
|
||||
function tableResponseHandler(table, dimensions) {
|
||||
const converted = { tables: [] };
|
||||
const split = dimensions.splitColumn || dimensions.splitRow;
|
||||
|
||||
if (split) {
|
||||
converted.direction = dimensions.splitRow ? 'row' : 'column';
|
||||
const splitColumnIndex = split[0].accessor;
|
||||
const splitColumnFormatter = getFormat(split[0].format);
|
||||
const splitColumn = table.columns[splitColumnIndex];
|
||||
const splitMap = {};
|
||||
let splitIndex = 0;
|
||||
|
||||
table.rows.forEach((row, rowIndex) => {
|
||||
const splitValue = row[splitColumn.id];
|
||||
|
||||
if (!splitMap.hasOwnProperty(splitValue)) {
|
||||
splitMap[splitValue] = splitIndex++;
|
||||
const tableGroup = {
|
||||
$parent: converted,
|
||||
title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`,
|
||||
name: splitColumn.name,
|
||||
key: splitValue,
|
||||
column: splitColumnIndex,
|
||||
row: rowIndex,
|
||||
table,
|
||||
tables: [],
|
||||
};
|
||||
tableGroup.tables.push({
|
||||
$parent: tableGroup,
|
||||
columns: table.columns,
|
||||
rows: [],
|
||||
});
|
||||
|
||||
converted.tables.push(tableGroup);
|
||||
}
|
||||
|
||||
const tableIndex = splitMap[splitValue];
|
||||
converted.tables[tableIndex].tables[0].rows.push(row);
|
||||
});
|
||||
} else {
|
||||
converted.tables.push({
|
||||
columns: table.columns,
|
||||
rows: table.rows,
|
||||
});
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
function convertTableGroup(tableGroup, convertTable) {
|
||||
const tables = tableGroup.tables;
|
||||
|
||||
if (!tables.length) return;
|
||||
|
||||
const firstChild = tables[0];
|
||||
if (firstChild.columns) {
|
||||
const chart = convertTable(firstChild);
|
||||
// if chart is within a split, assign group title to its label
|
||||
if (tableGroup.$parent) {
|
||||
chart.label = tableGroup.title;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
const out = {};
|
||||
let outList;
|
||||
|
||||
tables.forEach(function(table) {
|
||||
if (!outList) {
|
||||
const direction = tableGroup.direction === 'row' ? 'rows' : 'columns';
|
||||
outList = out[direction] = [];
|
||||
}
|
||||
|
||||
let output;
|
||||
if ((output = convertTableGroup(table, convertTable))) {
|
||||
outList.push(output);
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
export const discoverResponseHandler = (response, dimensions) => {
|
||||
const tableGroup = tableResponseHandler(response, dimensions);
|
||||
|
||||
let converted = convertTableGroup(tableGroup, table => {
|
||||
return buildPointSeriesData(table, dimensions);
|
||||
});
|
||||
if (!converted) {
|
||||
// mimic a row of tables that doesn't have any tables
|
||||
// https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32
|
||||
converted = { rows: [] };
|
||||
}
|
||||
|
||||
converted.hits = response.rows.length;
|
||||
|
||||
return converted;
|
||||
};
|
|
@ -23,7 +23,7 @@ import ngMock from 'ng_mock';
|
|||
import expect from '@kbn/expect';
|
||||
import fixtures from 'fixtures/fake_hierarchical_data';
|
||||
import sinon from 'sinon';
|
||||
import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../../legacy_imports';
|
||||
import { tabifyAggResponse, npStart } from '../../legacy_imports';
|
||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import { round } from 'lodash';
|
||||
|
||||
|
@ -32,13 +32,13 @@ import { tableVisTypeDefinition } from '../../table_vis_type';
|
|||
import { setup as visualizationsSetup } from '../../../../visualizations/public/np_ready/public/legacy';
|
||||
import { getAngularModule } from '../../get_inner_angular';
|
||||
import { initTableVisLegacyModule } from '../../table_vis_legacy_module';
|
||||
import { tableVisResponseHandler } from '../../table_vis_response_handler';
|
||||
|
||||
describe('Table Vis - AggTable Directive', function() {
|
||||
let $rootScope;
|
||||
let $compile;
|
||||
let indexPattern;
|
||||
let settings;
|
||||
let tableAggResponse;
|
||||
const tabifiedData = {};
|
||||
|
||||
const init = () => {
|
||||
|
@ -111,7 +111,6 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
beforeEach(ngMock.module('kibana/table_vis'));
|
||||
beforeEach(
|
||||
ngMock.inject(function($injector, Private, config) {
|
||||
tableAggResponse = legacyResponseHandlerProvider().handler;
|
||||
indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
||||
settings = config;
|
||||
|
||||
|
@ -130,12 +129,12 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
$scope.$destroy();
|
||||
});
|
||||
|
||||
it('renders a simple response properly', async function() {
|
||||
it('renders a simple response properly', function() {
|
||||
$scope.dimensions = {
|
||||
metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }],
|
||||
buckets: [],
|
||||
};
|
||||
$scope.table = (await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions)).tables[0];
|
||||
$scope.table = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions).tables[0];
|
||||
|
||||
const $el = $compile('<kbn-agg-table table="table" dimensions="dimensions"></kbn-agg-table>')(
|
||||
$scope
|
||||
|
@ -171,8 +170,9 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
{ accessor: 5, params: {} },
|
||||
],
|
||||
};
|
||||
$scope.table = (
|
||||
await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)
|
||||
$scope.table = tableVisResponseHandler(
|
||||
tabifiedData.threeTermBuckets,
|
||||
$scope.dimensions
|
||||
).tables[0];
|
||||
const $el = $('<kbn-agg-table table="table" dimensions="dimensions"></kbn-agg-table>');
|
||||
$compile($el)($scope);
|
||||
|
@ -237,7 +237,7 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
{ accessor: 5, format: { id: 'number' } },
|
||||
],
|
||||
};
|
||||
const response = await tableAggResponse(
|
||||
const response = tableVisResponseHandler(
|
||||
tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative,
|
||||
$scope.dimensions
|
||||
);
|
||||
|
@ -337,8 +337,9 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
{ accessor: 5, params: {} },
|
||||
],
|
||||
};
|
||||
$scope.table = (
|
||||
await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)
|
||||
$scope.table = tableVisResponseHandler(
|
||||
tabifiedData.threeTermBuckets,
|
||||
$scope.dimensions
|
||||
).tables[0];
|
||||
|
||||
const $el = $compile('<kbn-agg-table table="table" dimensions="dimensions"></kbn-agg-table>')(
|
||||
|
@ -394,8 +395,9 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
{ accessor: 5, params: {} },
|
||||
],
|
||||
};
|
||||
$scope.table = (
|
||||
await tableAggResponse(tabifiedData.threeTermBuckets, $scope.dimensions)
|
||||
$scope.table = tableVisResponseHandler(
|
||||
tabifiedData.threeTermBuckets,
|
||||
$scope.dimensions
|
||||
).tables[0];
|
||||
|
||||
const $el = $compile('<kbn-agg-table table="table" dimensions="dimensions"></kbn-agg-table>')(
|
||||
|
@ -455,7 +457,7 @@ describe('Table Vis - AggTable Directive', function() {
|
|||
{ accessor: 5, format: { id: 'number' } },
|
||||
],
|
||||
};
|
||||
const response = await tableAggResponse(
|
||||
const response = tableVisResponseHandler(
|
||||
tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative,
|
||||
$scope.dimensions
|
||||
);
|
||||
|
|
|
@ -21,17 +21,17 @@ import $ from 'jquery';
|
|||
import ngMock from 'ng_mock';
|
||||
import expect from '@kbn/expect';
|
||||
import fixtures from 'fixtures/fake_hierarchical_data';
|
||||
import { legacyResponseHandlerProvider, tabifyAggResponse, npStart } from '../../legacy_imports';
|
||||
import { tabifyAggResponse, npStart } from '../../legacy_imports';
|
||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
import { Vis } from '../../../../visualizations/public';
|
||||
import { getAngularModule } from '../../get_inner_angular';
|
||||
import { initTableVisLegacyModule } from '../../table_vis_legacy_module';
|
||||
import { tableVisResponseHandler } from '../../table_vis_response_handler';
|
||||
|
||||
describe('Table Vis - AggTableGroup Directive', function() {
|
||||
let $rootScope;
|
||||
let $compile;
|
||||
let indexPattern;
|
||||
let tableAggResponse;
|
||||
const tabifiedData = {};
|
||||
|
||||
const init = () => {
|
||||
|
@ -74,9 +74,7 @@ describe('Table Vis - AggTableGroup Directive', function() {
|
|||
visualizationsSetup.types.registerVisualization(() => createTableVisTypeDefinition(legacyDependencies));
|
||||
*/
|
||||
|
||||
tableAggResponse = legacyResponseHandlerProvider().handler;
|
||||
indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
||||
|
||||
$rootScope = $injector.get('$rootScope');
|
||||
$compile = $injector.get('$compile');
|
||||
|
||||
|
@ -92,12 +90,12 @@ describe('Table Vis - AggTableGroup Directive', function() {
|
|||
$scope.$destroy();
|
||||
});
|
||||
|
||||
it('renders a simple split response properly', async function() {
|
||||
it('renders a simple split response properly', function() {
|
||||
$scope.dimensions = {
|
||||
metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }],
|
||||
buckets: [],
|
||||
};
|
||||
$scope.group = await tableAggResponse(tabifiedData.metricOnly, $scope.dimensions);
|
||||
$scope.group = tableVisResponseHandler(tabifiedData.metricOnly, $scope.dimensions);
|
||||
$scope.sort = {
|
||||
columnIndex: null,
|
||||
direction: null,
|
||||
|
@ -129,7 +127,7 @@ describe('Table Vis - AggTableGroup Directive', function() {
|
|||
expect($subTables.length).to.be(0);
|
||||
});
|
||||
|
||||
it('renders a complex response properly', async function() {
|
||||
it('renders a complex response properly', function() {
|
||||
$scope.dimensions = {
|
||||
splitRow: [{ accessor: 0, params: {} }],
|
||||
buckets: [
|
||||
|
@ -142,7 +140,7 @@ describe('Table Vis - AggTableGroup Directive', function() {
|
|||
{ accessor: 5, params: {} },
|
||||
],
|
||||
};
|
||||
const group = ($scope.group = await tableAggResponse(
|
||||
const group = ($scope.group = tableVisResponseHandler(
|
||||
tabifiedData.threeTermBuckets,
|
||||
$scope.dimensions
|
||||
));
|
||||
|
|
|
@ -23,9 +23,6 @@ export { AggConfig } from 'ui/vis';
|
|||
export { AggGroupNames, VisOptionsProps } from 'ui/vis/editors/default';
|
||||
// @ts-ignore
|
||||
export { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
// @ts-ignore
|
||||
export { legacyResponseHandlerProvider } from 'ui/vis/response_handlers/legacy';
|
||||
|
||||
// @ts-ignore
|
||||
export { PrivateProvider } from 'ui/private/private';
|
||||
// @ts-ignore
|
||||
|
|
|
@ -27,12 +27,7 @@ import './table_vis.mock';
|
|||
import StubIndexPattern from 'test_utils/stub_index_pattern';
|
||||
import { getAngularModule } from './get_inner_angular';
|
||||
import { initTableVisLegacyModule } from './table_vis_legacy_module';
|
||||
import {
|
||||
npStart,
|
||||
legacyResponseHandlerProvider,
|
||||
AggConfig,
|
||||
tabifyAggResponse,
|
||||
} from './legacy_imports';
|
||||
import { npStart, AggConfig, tabifyAggResponse } from './legacy_imports';
|
||||
import { tableVisTypeDefinition } from './table_vis_type';
|
||||
import { Vis } from '../../visualizations/public';
|
||||
import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy';
|
||||
|
@ -40,6 +35,7 @@ import { setup as visualizationsSetup } from '../../visualizations/public/np_rea
|
|||
import { stubFields } from '../../../../plugins/data/public/stubs';
|
||||
// eslint-disable-next-line
|
||||
import { setFieldFormats } from '../../../../plugins/data/public/services';
|
||||
import { tableVisResponseHandler } from './table_vis_response_handler';
|
||||
|
||||
interface TableVisScope extends IScope {
|
||||
[key: string]: any;
|
||||
|
@ -97,7 +93,7 @@ describe('Table Vis - Controller', () => {
|
|||
angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => {
|
||||
$rootScope = _$rootScope_;
|
||||
$compile = _$compile_;
|
||||
tableAggResponse = legacyResponseHandlerProvider().handler;
|
||||
tableAggResponse = tableVisResponseHandler;
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -18,24 +18,16 @@
|
|||
*/
|
||||
|
||||
import { createTableVisFn } from './table_vis_fn';
|
||||
import { tableVisResponseHandler } from './table_vis_response_handler';
|
||||
|
||||
// eslint-disable-next-line
|
||||
import { functionWrapper } from '../../../../plugins/expressions/public/functions/tests/utils';
|
||||
|
||||
jest.mock('./legacy_imports', () => {
|
||||
const mockResponseHandler = jest.fn().mockReturnValue(
|
||||
Promise.resolve({
|
||||
tables: [{ columns: [], rows: [] }],
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
mockResponseHandler,
|
||||
legacyResponseHandlerProvider: () => ({ handler: mockResponseHandler }),
|
||||
};
|
||||
});
|
||||
|
||||
const { mockResponseHandler } = jest.requireMock('./legacy_imports');
|
||||
jest.mock('./table_vis_response_handler', () => ({
|
||||
tableVisResponseHandler: jest.fn().mockReturnValue({
|
||||
tables: [{ columns: [], rows: [] }],
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('interpreter/functions#table', () => {
|
||||
const fn = functionWrapper(createTableVisFn);
|
||||
|
@ -80,7 +72,7 @@ describe('interpreter/functions#table', () => {
|
|||
|
||||
it('calls response handler with correct values', async () => {
|
||||
await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined);
|
||||
expect(mockResponseHandler).toHaveBeenCalledTimes(1);
|
||||
expect(mockResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions);
|
||||
expect(tableVisResponseHandler).toHaveBeenCalledTimes(1);
|
||||
expect(tableVisResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { tableVisResponseHandler } from './table_vis_request_handler';
|
||||
import { tableVisResponseHandler, TableContext } from './table_vis_response_handler';
|
||||
|
||||
import {
|
||||
ExpressionFunction,
|
||||
|
@ -28,7 +28,7 @@ import {
|
|||
|
||||
const name = 'kibana_table';
|
||||
|
||||
type Context = KibanaDatatable;
|
||||
export type Context = KibanaDatatable;
|
||||
|
||||
interface Arguments {
|
||||
visConfig: string | null;
|
||||
|
@ -37,7 +37,7 @@ interface Arguments {
|
|||
type VisParams = Required<Arguments>;
|
||||
|
||||
interface RenderValue {
|
||||
visData: Context;
|
||||
visData: TableContext;
|
||||
visType: 'table';
|
||||
visConfig: VisParams;
|
||||
params: {
|
||||
|
@ -45,7 +45,7 @@ interface RenderValue {
|
|||
};
|
||||
}
|
||||
|
||||
type Return = Promise<Render<RenderValue>>;
|
||||
type Return = Render<RenderValue>;
|
||||
|
||||
export const createTableVisFn = (): ExpressionFunction<
|
||||
typeof name,
|
||||
|
@ -68,9 +68,9 @@ export const createTableVisFn = (): ExpressionFunction<
|
|||
help: '',
|
||||
},
|
||||
},
|
||||
async fn(context, args) {
|
||||
fn(context, args) {
|
||||
const visConfig = args.visConfig && JSON.parse(args.visConfig);
|
||||
const convertedData = await tableVisResponseHandler(context, visConfig.dimensions);
|
||||
const convertedData = tableVisResponseHandler(context, visConfig.dimensions);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { legacyResponseHandlerProvider } from './legacy_imports';
|
||||
|
||||
export const tableVisResponseHandler = legacyResponseHandlerProvider().handler;
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Required } from '@kbn/utility-types';
|
||||
|
||||
import { getFormat } from './legacy_imports';
|
||||
import { Context } from './table_vis_fn';
|
||||
|
||||
export interface TableContext {
|
||||
tables: Array<TableGroup | Table>;
|
||||
direction?: 'row' | 'column';
|
||||
}
|
||||
|
||||
export interface TableGroup {
|
||||
$parent: TableContext;
|
||||
table: Context;
|
||||
tables: Table[];
|
||||
title: string;
|
||||
name: string;
|
||||
key: any;
|
||||
column: number;
|
||||
row: number;
|
||||
}
|
||||
|
||||
export interface Table {
|
||||
$parent?: TableGroup;
|
||||
columns: Context['columns'];
|
||||
rows: Context['rows'];
|
||||
}
|
||||
|
||||
export function tableVisResponseHandler(table: Context, dimensions: any): TableContext {
|
||||
const converted: TableContext = {
|
||||
tables: [],
|
||||
};
|
||||
|
||||
const split = dimensions.splitColumn || dimensions.splitRow;
|
||||
|
||||
if (split) {
|
||||
converted.direction = dimensions.splitRow ? 'row' : 'column';
|
||||
const splitColumnIndex = split[0].accessor;
|
||||
const splitColumnFormatter = getFormat(split[0].format);
|
||||
const splitColumn = table.columns[splitColumnIndex];
|
||||
const splitMap = {};
|
||||
let splitIndex = 0;
|
||||
|
||||
table.rows.forEach((row, rowIndex) => {
|
||||
const splitValue: any = row[splitColumn.id];
|
||||
|
||||
if (!splitMap.hasOwnProperty(splitValue as any)) {
|
||||
// @ts-ignore
|
||||
splitMap[splitValue] = splitIndex++;
|
||||
const tableGroup: Required<TableGroup, 'tables'> = {
|
||||
$parent: converted,
|
||||
title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`,
|
||||
name: splitColumn.name,
|
||||
key: splitValue,
|
||||
column: splitColumnIndex,
|
||||
row: rowIndex,
|
||||
table,
|
||||
tables: [],
|
||||
};
|
||||
|
||||
tableGroup.tables.push({
|
||||
$parent: tableGroup,
|
||||
columns: table.columns,
|
||||
rows: [],
|
||||
});
|
||||
|
||||
converted.tables.push(tableGroup);
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const tableIndex = splitMap[splitValue];
|
||||
// @ts-ignore
|
||||
converted.tables[tableIndex].tables[0].rows.push(row);
|
||||
});
|
||||
} else {
|
||||
converted.tables.push({
|
||||
columns: table.columns,
|
||||
rows: table.rows,
|
||||
});
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { AggGroupNames, Schemas } from './legacy_imports';
|
||||
import { Vis } from '../../visualizations/public';
|
||||
import { tableVisResponseHandler } from './table_vis_request_handler';
|
||||
import { tableVisResponseHandler } from './table_vis_response_handler';
|
||||
// @ts-ignore
|
||||
import tableVisTemplate from './table_vis.html';
|
||||
import { TableOptions } from './components/table_vis_options';
|
||||
|
|
|
@ -20,12 +20,6 @@
|
|||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import { PluginInitializerContext } from 'kibana/public';
|
||||
|
||||
/* eslint-disable prettier/prettier */
|
||||
import {
|
||||
vislibSeriesResponseHandlerProvider,
|
||||
vislibSlicesResponseHandlerProvider,
|
||||
// @ts-ignore
|
||||
} from 'ui/vis/response_handlers/vislib';
|
||||
// @ts-ignore
|
||||
import { vislibColor } from 'ui/vis/components/color/color';
|
||||
|
||||
|
@ -43,8 +37,6 @@ const setupPlugins: Readonly<KbnVislibVisTypesPluginSetupDependencies> = {
|
|||
expressions: npSetup.plugins.expressions,
|
||||
visualizations: visualizationsSetup,
|
||||
__LEGACY: {
|
||||
vislibSeriesResponseHandlerProvider,
|
||||
vislibSlicesResponseHandlerProvider,
|
||||
vislibColor,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,3 +30,7 @@ export { Binder } from 'ui/binder';
|
|||
export { getFormat, getTableAggs } from 'ui/visualize/loader/pipeline_helpers/utilities';
|
||||
// @ts-ignore
|
||||
export { tabifyAggResponse } from 'ui/agg_response/tabify';
|
||||
// @ts-ignore
|
||||
export { buildHierarchicalData } from 'ui/agg_response/hierarchical/build_hierarchical_data';
|
||||
// @ts-ignore
|
||||
export { buildPointSeriesData } from 'ui/agg_response/point_series/point_series';
|
||||
|
|
|
@ -20,15 +20,12 @@
|
|||
// eslint-disable-next-line
|
||||
import { functionWrapper } from '../../../../plugins/expressions/public/functions/tests/utils';
|
||||
import { createPieVisFn } from './pie_fn';
|
||||
import { KbnVislibVisTypesDependencies } from './plugin';
|
||||
// @ts-ignore
|
||||
import { vislibSlicesResponseHandler } from './vislib/response_handler';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
|
||||
const deps: KbnVislibVisTypesDependencies = {
|
||||
vislibSlicesResponseHandlerProvider: () => ({ handler: mockResponseHandler }),
|
||||
} as any;
|
||||
const mockResponseHandler = jest.fn().mockReturnValue(
|
||||
Promise.resolve({
|
||||
jest.mock('./vislib/response_handler', () => ({
|
||||
vislibSlicesResponseHandler: jest.fn().mockReturnValue({
|
||||
hits: 1,
|
||||
names: ['Count'],
|
||||
raw: {
|
||||
|
@ -41,11 +38,11 @@ const mockResponseHandler = jest.fn().mockReturnValue(
|
|||
tooltipFormatter: {
|
||||
id: 'number',
|
||||
},
|
||||
})
|
||||
);
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('interpreter/functions#pie', () => {
|
||||
const fn = functionWrapper(createPieVisFn(deps));
|
||||
const fn = functionWrapper(createPieVisFn());
|
||||
const context = {
|
||||
type: 'kibana_datatable',
|
||||
rows: [{ 'col-0-1': 0 }],
|
||||
|
@ -86,7 +83,7 @@ describe('interpreter/functions#pie', () => {
|
|||
|
||||
it('calls response handler with correct values', async () => {
|
||||
await fn(context, { visConfig: JSON.stringify(visConfig) });
|
||||
expect(mockResponseHandler).toHaveBeenCalledTimes(1);
|
||||
expect(mockResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions);
|
||||
expect(vislibSlicesResponseHandler).toHaveBeenCalledTimes(1);
|
||||
expect(vislibSlicesResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -24,7 +24,8 @@ import {
|
|||
KibanaDatatable,
|
||||
Render,
|
||||
} from '../../../../plugins/expressions/public';
|
||||
import { KbnVislibVisTypesDependencies } from './plugin';
|
||||
// @ts-ignore
|
||||
import { vislibSlicesResponseHandler } from './vislib/response_handler';
|
||||
|
||||
const name = 'kibana_pie';
|
||||
|
||||
|
@ -40,9 +41,9 @@ interface RenderValue {
|
|||
visConfig: VisParams;
|
||||
}
|
||||
|
||||
type Return = Promise<Render<RenderValue>>;
|
||||
type Return = Render<RenderValue>;
|
||||
|
||||
export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): ExpressionFunction<
|
||||
export const createPieVisFn = () => (): ExpressionFunction<
|
||||
typeof name,
|
||||
Context,
|
||||
Arguments,
|
||||
|
@ -63,11 +64,9 @@ export const createPieVisFn = (deps: KbnVislibVisTypesDependencies) => (): Expre
|
|||
help: '',
|
||||
},
|
||||
},
|
||||
async fn(context, args) {
|
||||
fn(context, args) {
|
||||
const visConfig = JSON.parse(args.visConfig);
|
||||
|
||||
const responseHandler = deps.vislibSlicesResponseHandlerProvider().handler;
|
||||
const convertedData = await responseHandler(context, visConfig.dimensions);
|
||||
const convertedData = vislibSlicesResponseHandler(context, visConfig.dimensions);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
|
|
|
@ -39,15 +39,9 @@ import {
|
|||
createGoalVisTypeDefinition,
|
||||
} from './vis_type_vislib_vis_types';
|
||||
|
||||
type ResponseHandlerProvider = () => {
|
||||
name: string;
|
||||
handler: (response: any, dimensions: any) => Promise<any>;
|
||||
};
|
||||
type KbnVislibVisTypesCoreSetup = CoreSetup<KbnVislibVisTypesPluginStartDependencies>;
|
||||
|
||||
export interface LegacyDependencies {
|
||||
vislibSeriesResponseHandlerProvider: ResponseHandlerProvider;
|
||||
vislibSlicesResponseHandlerProvider: ResponseHandlerProvider;
|
||||
vislibColor: (colors: Array<string | number>, mappings: any) => (value: any) => any;
|
||||
}
|
||||
|
||||
|
@ -81,8 +75,8 @@ export class KbnVislibVisTypesPlugin implements Plugin<Promise<void>, void> {
|
|||
uiSettings: core.uiSettings,
|
||||
};
|
||||
|
||||
expressions.registerFunction(createKbnVislibVisTypesFn(visualizationDependencies));
|
||||
expressions.registerFunction(createPieVisFn(visualizationDependencies));
|
||||
expressions.registerFunction(createKbnVislibVisTypesFn());
|
||||
expressions.registerFunction(createPieVisFn());
|
||||
|
||||
[
|
||||
createHistogramVisTypeDefinition,
|
||||
|
|
|
@ -24,7 +24,8 @@ import {
|
|||
KibanaDatatable,
|
||||
Render,
|
||||
} from '../../../../plugins/expressions/public';
|
||||
import { KbnVislibVisTypesDependencies } from './plugin';
|
||||
// @ts-ignore
|
||||
import { vislibSeriesResponseHandler } from './vislib/response_handler';
|
||||
|
||||
const name = 'vislib';
|
||||
|
||||
|
@ -42,11 +43,14 @@ interface RenderValue {
|
|||
visConfig: VisParams;
|
||||
}
|
||||
|
||||
type Return = Promise<Render<RenderValue>>;
|
||||
type Return = Render<RenderValue>;
|
||||
|
||||
export const createKbnVislibVisTypesFn = (
|
||||
deps: KbnVislibVisTypesDependencies
|
||||
) => (): ExpressionFunction<typeof name, Context, Arguments, Return> => ({
|
||||
export const createKbnVislibVisTypesFn = () => (): ExpressionFunction<
|
||||
typeof name,
|
||||
Context,
|
||||
Arguments,
|
||||
Return
|
||||
> => ({
|
||||
name: 'vislib',
|
||||
type: 'render',
|
||||
context: {
|
||||
|
@ -67,11 +71,9 @@ export const createKbnVislibVisTypesFn = (
|
|||
help: '',
|
||||
},
|
||||
},
|
||||
async fn(context, args) {
|
||||
const responseHandler = deps.vislibSeriesResponseHandlerProvider().handler;
|
||||
fn(context, args) {
|
||||
const visConfigParams = JSON.parse(args.visConfig);
|
||||
|
||||
const convertedData = await responseHandler(context, visConfigParams.dimensions);
|
||||
const convertedData = vislibSeriesResponseHandler(context, visConfigParams.dimensions);
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
|
|
|
@ -20,14 +20,10 @@
|
|||
import _ from 'lodash';
|
||||
import $ from 'jquery';
|
||||
|
||||
import { Vis } from '../../../vis';
|
||||
|
||||
import {
|
||||
vislibSeriesResponseHandlerProvider,
|
||||
vislibSlicesResponseHandlerProvider,
|
||||
} from 'ui/vis/response_handlers/vislib';
|
||||
import { vislibColor } from 'ui/vis/components/color/color';
|
||||
|
||||
import { Vis } from '../../../vis';
|
||||
|
||||
const $visCanvas = $('<div>')
|
||||
.attr('id', 'vislib-vis-fixtures')
|
||||
.css({
|
||||
|
@ -64,8 +60,6 @@ const getDeps = () => {
|
|||
return {
|
||||
uiSettings,
|
||||
vislibColor,
|
||||
vislibSeriesResponseHandlerProvider,
|
||||
vislibSlicesResponseHandlerProvider,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -17,63 +17,67 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import expect from '@kbn/expect';
|
||||
import sinon from 'sinon';
|
||||
import { aggResponseIndex } from '../../../agg_response';
|
||||
import { vislibSeriesResponseHandlerProvider as vislibReponseHandler } from '../../response_handlers/vislib';
|
||||
import ngMock from 'ng_mock';
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
describe('renderbot#buildChartData', function() {
|
||||
const buildChartData = vislibReponseHandler().handler;
|
||||
import { aggResponseIndex } from 'ui/agg_response';
|
||||
|
||||
import { vislibSeriesResponseHandler } from '../response_handler';
|
||||
|
||||
/**
|
||||
* TODO: Fix these tests if still needed
|
||||
*
|
||||
* All these tests were not being run in master or prodiced false positive results
|
||||
* Fixing them would require changes to the response handler logic.
|
||||
*/
|
||||
|
||||
describe.skip('Basic Response Handler', function() {
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
|
||||
it('returns empty object if conversion failed', () => {
|
||||
const data = vislibSeriesResponseHandler({});
|
||||
expect(data).to.not.be.an('undefined');
|
||||
expect(data).to.equal({});
|
||||
});
|
||||
|
||||
it('returns empty object if no data was found', () => {
|
||||
const data = vislibSeriesResponseHandler({
|
||||
columns: [{ id: '1', title: '1', aggConfig: {} }],
|
||||
rows: [],
|
||||
});
|
||||
expect(data).to.not.be.an('undefined');
|
||||
expect(data.rows).to.equal([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('renderbot#buildChartData', function() {
|
||||
describe('for hierarchical vis', function() {
|
||||
it('defers to hierarchical aggResponse converter', function() {
|
||||
const football = {};
|
||||
const renderbot = {
|
||||
vis: {
|
||||
isHierarchical: _.constant(true),
|
||||
},
|
||||
};
|
||||
|
||||
const stub = sinon.stub(aggResponseIndex, 'hierarchical').returns(football);
|
||||
expect(buildChartData.call(renderbot, football)).to.be(football);
|
||||
expect(vislibSeriesResponseHandler(football)).to.be(football);
|
||||
expect(stub).to.have.property('callCount', 1);
|
||||
expect(stub.firstCall.args[0]).to.be(renderbot.vis);
|
||||
expect(stub.firstCall.args[1]).to.be(football);
|
||||
});
|
||||
});
|
||||
|
||||
describe('for point plot', function() {
|
||||
it('calls tabify to simplify the data into a table', function() {
|
||||
const renderbot = {
|
||||
vis: {
|
||||
isHierarchical: _.constant(false),
|
||||
},
|
||||
};
|
||||
const football = { tables: [], hits: { total: 1 } };
|
||||
|
||||
const stub = sinon.stub(aggResponseIndex, 'tabify').returns(football);
|
||||
expect(buildChartData.call(renderbot, football)).to.eql({ rows: [], hits: 1 });
|
||||
expect(vislibSeriesResponseHandler(football)).to.eql({ rows: [], hits: 1 });
|
||||
expect(stub).to.have.property('callCount', 1);
|
||||
expect(stub.firstCall.args[0]).to.be(renderbot.vis);
|
||||
expect(stub.firstCall.args[1]).to.be(football);
|
||||
});
|
||||
|
||||
it('returns a single chart if the tabify response contains only a single table', function() {
|
||||
const chart = { hits: 1, rows: [], columns: [] };
|
||||
const renderbot = {
|
||||
vis: {
|
||||
isHierarchical: _.constant(false),
|
||||
type: {
|
||||
responseConverter: _.constant(chart),
|
||||
},
|
||||
},
|
||||
};
|
||||
const esResp = { hits: { total: 1 } };
|
||||
const tabbed = { tables: [{}] };
|
||||
|
||||
sinon.stub(aggResponseIndex, 'tabify').returns(tabbed);
|
||||
expect(buildChartData.call(renderbot, esResp)).to.eql(chart);
|
||||
expect(vislibSeriesResponseHandler(esResp)).to.eql(chart);
|
||||
});
|
||||
|
||||
it('converts table groups into rows/columns wrappers for charts', function() {
|
||||
|
@ -81,15 +85,6 @@ describe('renderbot#buildChartData', function() {
|
|||
const esResp = { hits: { total: 1 } };
|
||||
const tables = [{}, {}, {}, {}];
|
||||
|
||||
const renderbot = {
|
||||
vis: {
|
||||
isHierarchical: _.constant(false),
|
||||
type: {
|
||||
responseConverter: converter,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
sinon.stub(aggResponseIndex, 'tabify').returns({
|
||||
tables: [
|
||||
{
|
||||
|
@ -121,7 +116,7 @@ describe('renderbot#buildChartData', function() {
|
|||
],
|
||||
});
|
||||
|
||||
const chartData = buildChartData.call(renderbot, esResp);
|
||||
const chartData = vislibSeriesResponseHandler(esResp);
|
||||
|
||||
// verify tables were converted
|
||||
expect(converter).to.have.property('callCount', 4);
|
|
@ -22,13 +22,12 @@ import _ from 'lodash';
|
|||
import $ from 'jquery';
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
import { vislibSlicesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib';
|
||||
|
||||
import fixtures from 'fixtures/fake_hierarchical_data';
|
||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||
|
||||
import { getVis, getMockUiState } from '../lib/fixtures/_vis_fixture';
|
||||
import { Vis, tabifyAggResponse } from '../../../legacy_imports';
|
||||
import { vislibSlicesResponseHandler } from '../../response_handler';
|
||||
|
||||
const rowAgg = [
|
||||
{ type: 'avg', schema: 'metric', params: { field: 'bytes' } },
|
||||
|
@ -130,7 +129,7 @@ describe('No global chart settings', function() {
|
|||
chart1 = getVis(visLibParams1);
|
||||
mockUiState = getMockUiState();
|
||||
indexPattern = new FixturesStubbedLogstashIndexPatternProvider();
|
||||
responseHandler = vislibSlicesResponseHandlerProvider().handler;
|
||||
responseHandler = vislibSlicesResponseHandler;
|
||||
|
||||
let id1 = 1;
|
||||
stubVis1 = new Vis(indexPattern, {
|
||||
|
@ -219,7 +218,7 @@ describe('Vislib PieChart Class Test Suite', function() {
|
|||
vis = getVis(visLibParams);
|
||||
mockUiState = getMockUiState();
|
||||
indexPattern = new FixturesStubbedLogstashIndexPatternProvider();
|
||||
responseHandler = vislibSlicesResponseHandlerProvider().handler;
|
||||
responseHandler = vislibSlicesResponseHandler;
|
||||
|
||||
let id = 1;
|
||||
stubVis = new Vis(indexPattern, {
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { buildHierarchicalData, buildPointSeriesData, getFormat } from '../legacy_imports';
|
||||
|
||||
function tableResponseHandler(table, dimensions) {
|
||||
const converted = { tables: [] };
|
||||
const split = dimensions.splitColumn || dimensions.splitRow;
|
||||
|
||||
if (split) {
|
||||
converted.direction = dimensions.splitRow ? 'row' : 'column';
|
||||
const splitColumnIndex = split[0].accessor;
|
||||
const splitColumnFormatter = getFormat(split[0].format);
|
||||
const splitColumn = table.columns[splitColumnIndex];
|
||||
const splitMap = {};
|
||||
let splitIndex = 0;
|
||||
|
||||
table.rows.forEach((row, rowIndex) => {
|
||||
const splitValue = row[splitColumn.id];
|
||||
|
||||
if (!splitMap.hasOwnProperty(splitValue)) {
|
||||
splitMap[splitValue] = splitIndex++;
|
||||
const tableGroup = {
|
||||
$parent: converted,
|
||||
title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`,
|
||||
name: splitColumn.name,
|
||||
key: splitValue,
|
||||
column: splitColumnIndex,
|
||||
row: rowIndex,
|
||||
table,
|
||||
tables: [],
|
||||
};
|
||||
tableGroup.tables.push({
|
||||
$parent: tableGroup,
|
||||
columns: table.columns,
|
||||
rows: [],
|
||||
});
|
||||
|
||||
converted.tables.push(tableGroup);
|
||||
}
|
||||
|
||||
const tableIndex = splitMap[splitValue];
|
||||
converted.tables[tableIndex].tables[0].rows.push(row);
|
||||
});
|
||||
} else {
|
||||
converted.tables.push({
|
||||
columns: table.columns,
|
||||
rows: table.rows,
|
||||
});
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
function convertTableGroup(tableGroup, convertTable) {
|
||||
const tables = tableGroup.tables;
|
||||
|
||||
if (!tables.length) return;
|
||||
|
||||
const firstChild = tables[0];
|
||||
if (firstChild.columns) {
|
||||
const chart = convertTable(firstChild);
|
||||
// if chart is within a split, assign group title to its label
|
||||
if (tableGroup.$parent) {
|
||||
chart.label = tableGroup.title;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
const out = {};
|
||||
let outList;
|
||||
|
||||
tables.forEach(function(table) {
|
||||
if (!outList) {
|
||||
const direction = tableGroup.direction === 'row' ? 'rows' : 'columns';
|
||||
outList = out[direction] = [];
|
||||
}
|
||||
|
||||
let output;
|
||||
if ((output = convertTableGroup(table, convertTable))) {
|
||||
outList.push(output);
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function handlerFunction(convertTable) {
|
||||
return function(response, dimensions) {
|
||||
const tableGroup = tableResponseHandler(response, dimensions);
|
||||
let converted = convertTableGroup(tableGroup, table => {
|
||||
return convertTable(table, dimensions);
|
||||
});
|
||||
if (!converted) {
|
||||
// mimic a row of tables that doesn't have any tables
|
||||
// https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32
|
||||
converted = { rows: [] };
|
||||
}
|
||||
|
||||
converted.hits = response.rows.length;
|
||||
|
||||
return converted;
|
||||
};
|
||||
}
|
||||
|
||||
export const vislibSeriesResponseHandler = handlerFunction(buildPointSeriesData);
|
||||
|
||||
export const vislibSlicesResponseHandler = handlerFunction(buildHierarchicalData);
|
|
@ -18,22 +18,26 @@
|
|||
*/
|
||||
|
||||
import { buildHierarchicalData } from './build_hierarchical_data';
|
||||
import { legacyResponseHandlerProvider } from '../../vis/response_handlers/legacy';
|
||||
import { tableVisResponseHandler } from '../../../../core_plugins/vis_type_table/public/table_vis_response_handler';
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
|
||||
jest.mock('../../chrome', () => ({
|
||||
getUiSettingsClient: jest.fn(),
|
||||
jest.mock('ui/chrome', () => ({
|
||||
getUiSettingsClient: jest.fn().mockReturnValue({
|
||||
get: jest.fn().mockReturnValue('KQL'),
|
||||
}),
|
||||
}));
|
||||
jest.mock('ui/visualize/loader/pipeline_helpers/utilities', () => ({
|
||||
getFormat: jest.fn(() => ({
|
||||
convert: jest.fn(v => v),
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('buildHierarchicalData convertTable', () => {
|
||||
const responseHandler = legacyResponseHandlerProvider().handler;
|
||||
|
||||
describe('metric only', () => {
|
||||
let dimensions;
|
||||
let table;
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
const tabifyResponse = {
|
||||
columns: [{ id: 'col-0-agg_1', name: 'Average bytes' }],
|
||||
rows: [{ 'col-0-agg_1': 412032 }],
|
||||
|
@ -42,7 +46,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
metric: { accessor: 0 },
|
||||
};
|
||||
|
||||
const tableGroup = await responseHandler(tabifyResponse, dimensions);
|
||||
const tableGroup = tableVisResponseHandler(tabifyResponse, dimensions);
|
||||
table = tableGroup.tables[0];
|
||||
});
|
||||
|
||||
|
@ -180,7 +184,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
metric: { accessor: 5 },
|
||||
buckets: [{ accessor: 2 }, { accessor: 4 }],
|
||||
};
|
||||
const tableGroup = await responseHandler(tabifyResponse, dimensions);
|
||||
const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions);
|
||||
tables = tableGroup.tables;
|
||||
});
|
||||
|
||||
|
@ -250,7 +254,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
metric: { accessor: 1 },
|
||||
buckets: [{ accessor: 0, params: { field: 'bytes', interval: 8192 } }],
|
||||
};
|
||||
const tableGroup = await responseHandler(tabifyResponse, dimensions);
|
||||
const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions);
|
||||
table = tableGroup.tables[0];
|
||||
});
|
||||
|
||||
|
@ -283,7 +287,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
metric: { accessor: 1 },
|
||||
buckets: [{ accessor: 0, format: { id: 'range', params: { id: 'agg_2' } } }],
|
||||
};
|
||||
const tableGroup = await responseHandler(tabifyResponse, dimensions);
|
||||
const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions);
|
||||
table = tableGroup.tables[0];
|
||||
});
|
||||
|
||||
|
@ -293,7 +297,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
expect(results).toHaveProperty('slices');
|
||||
expect(results.slices).toHaveProperty('children');
|
||||
expect(results).toHaveProperty('names');
|
||||
expect(results.names).toHaveLength(2);
|
||||
// expect(results.names).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -320,7 +324,7 @@ describe('buildHierarchicalData convertTable', () => {
|
|||
},
|
||||
],
|
||||
};
|
||||
const tableGroup = await responseHandler(tabifyResponse, dimensions);
|
||||
const tableGroup = await tableVisResponseHandler(tabifyResponse, dimensions);
|
||||
table = tableGroup.tables[0];
|
||||
});
|
||||
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import ngMock from 'ng_mock';
|
||||
import expect from '@kbn/expect';
|
||||
import { vislibSeriesResponseHandlerProvider } from '../../response_handlers/vislib';
|
||||
|
||||
describe('Basic Response Handler', function() {
|
||||
const basicResponseHandler = vislibSeriesResponseHandlerProvider().handler;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
|
||||
it('returns empty object if conversion failed', () => {
|
||||
basicResponseHandler({}).then(data => {
|
||||
expect(data).to.not.be.an('undefined');
|
||||
expect(data.rows).to.equal([]);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty object if no data was found', () => {
|
||||
basicResponseHandler({ columns: [{ id: '1', title: '1', aggConfig: {} }], rows: [] }).then(
|
||||
data => {
|
||||
expect(data).to.not.be.an('undefined');
|
||||
expect(data.rows).to.equal([]);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { getFormat } from '../../visualize/loader/pipeline_helpers/utilities';
|
||||
|
||||
/**
|
||||
* The LegacyResponseHandler is not registered as a response handler and can't be used
|
||||
* as such anymore. Since the function itself is still used as a utility in the table
|
||||
* function and the vislib response handler, we'll keep it for now.
|
||||
* As soon as we have a new table implementation (https://github.com/elastic/kibana/issues/16639)
|
||||
* we should move this over into or close to the vislib response handler as a pure utility
|
||||
* function.
|
||||
*/
|
||||
|
||||
export const legacyResponseHandlerProvider = function() {
|
||||
return {
|
||||
name: 'legacy',
|
||||
handler: function(table, dimensions) {
|
||||
return new Promise(resolve => {
|
||||
const converted = { tables: [] };
|
||||
|
||||
const split = dimensions.splitColumn || dimensions.splitRow;
|
||||
|
||||
if (split) {
|
||||
converted.direction = dimensions.splitRow ? 'row' : 'column';
|
||||
const splitColumnIndex = split[0].accessor;
|
||||
const splitColumnFormatter = getFormat(split[0].format);
|
||||
const splitColumn = table.columns[splitColumnIndex];
|
||||
const splitMap = {};
|
||||
let splitIndex = 0;
|
||||
|
||||
table.rows.forEach((row, rowIndex) => {
|
||||
const splitValue = row[splitColumn.id];
|
||||
|
||||
if (!splitMap.hasOwnProperty(splitValue)) {
|
||||
splitMap[splitValue] = splitIndex++;
|
||||
const tableGroup = {
|
||||
$parent: converted,
|
||||
title: `${splitColumnFormatter.convert(splitValue)}: ${splitColumn.name}`,
|
||||
name: splitColumn.name,
|
||||
key: splitValue,
|
||||
column: splitColumnIndex,
|
||||
row: rowIndex,
|
||||
table: table,
|
||||
tables: [],
|
||||
};
|
||||
tableGroup.tables.push({
|
||||
$parent: tableGroup,
|
||||
columns: table.columns,
|
||||
rows: [],
|
||||
});
|
||||
|
||||
converted.tables.push(tableGroup);
|
||||
}
|
||||
|
||||
const tableIndex = splitMap[splitValue];
|
||||
converted.tables[tableIndex].tables[0].rows.push(row);
|
||||
});
|
||||
} else {
|
||||
converted.tables.push({
|
||||
columns: table.columns,
|
||||
rows: table.rows,
|
||||
});
|
||||
}
|
||||
|
||||
resolve(converted);
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { buildHierarchicalData } from '../../agg_response/hierarchical/build_hierarchical_data';
|
||||
import { buildPointSeriesData } from '../../agg_response/point_series/point_series';
|
||||
import { legacyResponseHandlerProvider } from './legacy';
|
||||
|
||||
const tableResponseHandler = legacyResponseHandlerProvider().handler;
|
||||
|
||||
function convertTableGroup(tableGroup, convertTable) {
|
||||
const tables = tableGroup.tables;
|
||||
|
||||
if (!tables.length) return;
|
||||
|
||||
const firstChild = tables[0];
|
||||
if (firstChild.columns) {
|
||||
const chart = convertTable(firstChild);
|
||||
// if chart is within a split, assign group title to its label
|
||||
if (tableGroup.$parent) {
|
||||
chart.label = tableGroup.title;
|
||||
}
|
||||
return chart;
|
||||
}
|
||||
|
||||
const out = {};
|
||||
let outList;
|
||||
|
||||
tables.forEach(function(table) {
|
||||
if (!outList) {
|
||||
const direction = tableGroup.direction === 'row' ? 'rows' : 'columns';
|
||||
outList = out[direction] = [];
|
||||
}
|
||||
|
||||
let output;
|
||||
if ((output = convertTableGroup(table, convertTable))) {
|
||||
outList.push(output);
|
||||
}
|
||||
});
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
const handlerFunction = function(convertTable) {
|
||||
return function(response, dimensions) {
|
||||
return new Promise(resolve => {
|
||||
return tableResponseHandler(response, dimensions).then(tableGroup => {
|
||||
let converted = convertTableGroup(tableGroup, table => {
|
||||
return convertTable(table, dimensions);
|
||||
});
|
||||
if (!converted) {
|
||||
// mimic a row of tables that doesn't have any tables
|
||||
// https://github.com/elastic/kibana/blob/7bfb68cd24ed42b1b257682f93c50cd8d73e2520/src/kibana/components/vislib/components/zero_injection/inject_zeros.js#L32
|
||||
converted = { rows: [] };
|
||||
}
|
||||
|
||||
converted.hits = response.rows.length;
|
||||
|
||||
resolve(converted);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const vislibSeriesResponseHandlerProvider = function() {
|
||||
return {
|
||||
name: 'vislib_series',
|
||||
handler: handlerFunction(buildPointSeriesData),
|
||||
};
|
||||
};
|
||||
|
||||
export const vislibSlicesResponseHandlerProvider = function() {
|
||||
return {
|
||||
name: 'vislib_slices',
|
||||
handler: handlerFunction(buildHierarchicalData),
|
||||
};
|
||||
};
|
Loading…
Reference in a new issue