From 182533f565037b216662f13efdd87409697bede1 Mon Sep 17 00:00:00 2001 From: Stratoula Kalafateli Date: Tue, 14 Sep 2021 11:57:42 +0300 Subject: [PATCH] [Datatable] Removes the old implementation (#111339) * [Datatable] Removes the angular implementation * Fix i18n errors * Fix types * Remove unecessary funtional tests * Fix documentation Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- scripts/functional_tests.js | 1 - src/plugins/vis_type_table/README.md | 7 +- src/plugins/vis_type_table/common/index.ts | 5 +- src/plugins/vis_type_table/config.ts | 1 - src/plugins/vis_type_table/kibana.json | 2 +- src/plugins/vis_type_table/public/index.ts | 5 +- .../table_vis_legacy_fn.test.ts.snap | 44 - .../public/legacy/_table_vis.scss | 25 - .../public/legacy/agg_table/_agg_table.scss | 42 - .../public/legacy/agg_table/_index.scss | 1 - .../public/legacy/agg_table/agg_table.html | 34 - .../public/legacy/agg_table/agg_table.js | 253 ------ .../public/legacy/agg_table/agg_table.test.js | 488 ----------- .../legacy/agg_table/agg_table_group.html | 77 -- .../legacy/agg_table/agg_table_group.js | 45 - .../legacy/agg_table/agg_table_group.test.js | 132 --- .../public/legacy/agg_table/tabified_data.js | 784 ------------------ .../public/legacy/get_inner_angular.ts | 88 -- .../vis_type_table/public/legacy/index.scss | 10 - .../vis_type_table/public/legacy/index.ts | 9 - .../public/legacy/paginated_table/_index.scss | 1 - .../paginated_table/_table_cell_filter.scss | 30 - .../paginated_table/paginated_table.html | 55 -- .../legacy/paginated_table/paginated_table.js | 98 --- .../paginated_table/paginated_table.test.ts | 464 ----------- .../public/legacy/paginated_table/rows.js | 130 --- .../paginated_table/table_cell_filter.html | 23 - .../public/legacy/register_legacy_vis.ts | 26 - .../public/legacy/table_vis.html | 29 - .../public/legacy/table_vis_controller.js | 45 - .../legacy/table_vis_controller.test.ts | 245 ------ .../public/legacy/table_vis_legacy_fn.test.ts | 67 -- .../public/legacy/table_vis_legacy_fn.ts | 62 -- .../public/legacy/table_vis_legacy_module.ts | 30 - .../legacy/table_vis_legacy_renderer.tsx | 42 - .../table_vis_legacy_response_handler.ts | 95 --- .../public/legacy/table_vis_legacy_type.ts | 85 -- .../public/legacy/to_ast_legacy.ts | 70 -- .../public/legacy/vis_controller.ts | 121 --- src/plugins/vis_type_table/public/plugin.ts | 32 +- .../vis_type_table/public/register_vis.ts | 6 +- src/plugins/vis_type_table/server/index.ts | 3 - .../apps/visualize/legacy/_data_table.ts | 321 ------- .../functional/apps/visualize/legacy/index.ts | 39 - test/functional/config.legacy.ts | 28 - .../translations/translations/ja-JP.json | 8 +- .../translations/translations/zh-CN.json | 8 +- 47 files changed, 14 insertions(+), 4202 deletions(-) delete mode 100644 src/plugins/vis_type_table/public/legacy/__snapshots__/table_vis_legacy_fn.test.ts.snap delete mode 100644 src/plugins/vis_type_table/public/legacy/_table_vis.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/_index.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js delete mode 100644 src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js delete mode 100644 src/plugins/vis_type_table/public/legacy/get_inner_angular.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/index.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/index.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/rows.js delete mode 100644 src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html delete mode 100644 src/plugins/vis_type_table/public/legacy/register_legacy_vis.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis.html delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_controller.js delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_controller.test.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.test.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_response_handler.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/to_ast_legacy.ts delete mode 100644 src/plugins/vis_type_table/public/legacy/vis_controller.ts delete mode 100644 test/functional/apps/visualize/legacy/_data_table.ts delete mode 100644 test/functional/apps/visualize/legacy/index.ts delete mode 100644 test/functional/config.legacy.ts diff --git a/scripts/functional_tests.js b/scripts/functional_tests.js index c541b9faaeccc..ce62face43906 100644 --- a/scripts/functional_tests.js +++ b/scripts/functional_tests.js @@ -13,7 +13,6 @@ const alwaysImportedTests = [ require.resolve('../test/ui_capabilities/newsfeed_err/config.ts'), require.resolve('../test/new_visualize_flow/config.ts'), require.resolve('../test/security_functional/config.ts'), - require.resolve('../test/functional/config.legacy.ts'), ]; // eslint-disable-next-line no-restricted-syntax const onlyNotInCoverageTests = [ diff --git a/src/plugins/vis_type_table/README.md b/src/plugins/vis_type_table/README.md index a17d1142f0c09..b3aa1983fb8ef 100644 --- a/src/plugins/vis_type_table/README.md +++ b/src/plugins/vis_type_table/README.md @@ -1,8 +1,3 @@ Contains the data table visualization, that allows presenting data in a simple table format. -By default a new version of visualization will be used. To use the previous version of visualization the config must have the `vis_type_table.legacyVisEnabled: true` setting -configured in `kibana.dev.yml` or `kibana.yml`, as shown in the example below: - -```yaml -vis_type_table.legacyVisEnabled: true -``` \ No newline at end of file +Aggregation-based datatable visualizations use the EuiDataGrid component. diff --git a/src/plugins/vis_type_table/common/index.ts b/src/plugins/vis_type_table/common/index.ts index 59cfa7e715f3b..ad8e27c95a5ec 100644 --- a/src/plugins/vis_type_table/common/index.ts +++ b/src/plugins/vis_type_table/common/index.ts @@ -6,7 +6,4 @@ * Side Public License, v 1. */ -// TODO: https://github.com/elastic/kibana/issues/110891 -/* eslint-disable @kbn/eslint/no_export_all */ - -export * from './types'; +export { AggTypes, TableVisParams, VIS_TYPE_TABLE } from './types'; diff --git a/src/plugins/vis_type_table/config.ts b/src/plugins/vis_type_table/config.ts index ee027b79d5b5c..b831d26854c30 100644 --- a/src/plugins/vis_type_table/config.ts +++ b/src/plugins/vis_type_table/config.ts @@ -10,7 +10,6 @@ import { schema, TypeOf } from '@kbn/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), - legacyVisEnabled: schema.boolean({ defaultValue: false }), }); export type ConfigSchema = TypeOf; diff --git a/src/plugins/vis_type_table/kibana.json b/src/plugins/vis_type_table/kibana.json index 389094802e999..b3ebd5117bbc8 100644 --- a/src/plugins/vis_type_table/kibana.json +++ b/src/plugins/vis_type_table/kibana.json @@ -20,5 +20,5 @@ "name": "Vis Editors", "githubTeam": "kibana-vis-editors" }, - "description": "Registers the datatable aggregation-based visualization. Currently it contains two implementations, the one based on EUI datagrid and the angular one. The second one is going to be removed in future minors." + "description": "Registers the datatable aggregation-based visualization." } diff --git a/src/plugins/vis_type_table/public/index.ts b/src/plugins/vis_type_table/public/index.ts index e0ddf6e97e5ce..700a794e5a4c7 100644 --- a/src/plugins/vis_type_table/public/index.ts +++ b/src/plugins/vis_type_table/public/index.ts @@ -6,9 +6,8 @@ * Side Public License, v 1. */ -import { PluginInitializerContext } from 'kibana/public'; import { TableVisPlugin as Plugin } from './plugin'; -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(initializerContext); +export function plugin() { + return new Plugin(); } diff --git a/src/plugins/vis_type_table/public/legacy/__snapshots__/table_vis_legacy_fn.test.ts.snap b/src/plugins/vis_type_table/public/legacy/__snapshots__/table_vis_legacy_fn.test.ts.snap deleted file mode 100644 index a32609c2e3d34..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/__snapshots__/table_vis_legacy_fn.test.ts.snap +++ /dev/null @@ -1,44 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`interpreter/functions#table returns an object with the correct structure 1`] = ` -Object { - "as": "table_vis", - "type": "render", - "value": Object { - "visConfig": Object { - "dimensions": Object { - "buckets": Array [], - "metrics": Array [ - Object { - "accessor": 0, - "aggType": "count", - "format": Object { - "id": "number", - }, - "params": Object {}, - }, - ], - }, - "perPage": 10, - "showMetricsAtAllLevels": false, - "showPartialRows": false, - "showTotal": false, - "sort": Object { - "columnIndex": null, - "direction": null, - }, - "title": "My Chart title", - "totalFunc": "sum", - }, - "visData": Object { - "tables": Array [ - Object { - "columns": Array [], - "rows": Array [], - }, - ], - }, - "visType": "table", - }, -} -`; diff --git a/src/plugins/vis_type_table/public/legacy/_table_vis.scss b/src/plugins/vis_type_table/public/legacy/_table_vis.scss deleted file mode 100644 index 6ae3ddcca81a9..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/_table_vis.scss +++ /dev/null @@ -1,25 +0,0 @@ -// SASSTODO: Update naming to BEM -// This chart is actively being re-written to React and EUI -// Putting off renaming to avoid conflicts -.table-vis { - display: flex; - flex-direction: column; - flex: 1 1 0; - overflow: auto; - - @include euiScrollBar; -} - -.table-vis-container { - kbn-agg-table-group > .table > tbody > tr > td { - border-top: 0; - } - - .pagination-other-pages { - justify-content: flex-end; - } - - .pagination-size { - display: none; - } -} diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss b/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss deleted file mode 100644 index 89c7f6664c2fa..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/_agg_table.scss +++ /dev/null @@ -1,42 +0,0 @@ -kbn-agg-table, -kbn-agg-table-group { - display: block; -} - -.kbnAggTable { - display: flex; - flex: 1 1 auto; - flex-direction: column; -} - -.kbnAggTable__paginated { - flex: 1 1 auto; - overflow: auto; - - th { - text-align: left; - font-weight: $euiFontWeightBold; - } - - tr:hover td, - .kbnTableCellFilter { - background-color: $euiColorLightestShade; - } -} - -.kbnAggTable__controls { - flex: 0 0 auto; - display: flex; - align-items: center; - margin: $euiSizeS $euiSizeXS; - - > paginate-controls { - flex: 1 0 auto; - margin: 0; - padding: 0; - } -} - -.small { - font-size: .9em !important; -} diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/_index.scss b/src/plugins/vis_type_table/public/legacy/agg_table/_index.scss deleted file mode 100644 index 340e08a76f1bd..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './agg_table'; diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html deleted file mode 100644 index 5107bd2048286..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.html +++ /dev/null @@ -1,34 +0,0 @@ - - -
-    - - - -     - - - - - -
-
diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js deleted file mode 100644 index 8864326c0edc9..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.js +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../../share/public'; -import aggTableTemplate from './agg_table.html'; -import { getFormatService } from '../../services'; -import { i18n } from '@kbn/i18n'; - -export function KbnAggTable(config, RecursionHelper) { - return { - restrict: 'E', - template: aggTableTemplate, - scope: { - table: '=', - dimensions: '=', - perPage: '=?', - sort: '=?', - exportTitle: '=?', - showTotal: '=', - totalFunc: '=', - percentageCol: '=', - filter: '=', - }, - controllerAs: 'aggTable', - compile: function ($el) { - // Use the compile function from the RecursionHelper, - // And return the linking function(s) which it returns - return RecursionHelper.compile($el); - }, - controller: function ($scope) { - const self = this; - - self._saveAs = require('@elastic/filesaver').saveAs; - self.csv = { - separator: config.get(CSV_SEPARATOR_SETTING), - quoteValues: config.get(CSV_QUOTE_VALUES_SETTING), - }; - - self.exportAsCsv = function (formatted) { - const csv = new Blob([self.toCsv(formatted)], { type: 'text/plain;charset=utf-8' }); - self._saveAs(csv, self.csv.filename); - }; - - self.toCsv = function (formatted) { - const rows = $scope.rows; - const columns = $scope.formattedColumns; - - const nonAlphaNumRE = /[^a-zA-Z0-9]/; - const allDoubleQuoteRE = /"/g; - - function escape(val) { - if (!formatted && _.isObject(val)) val = val.valueOf(); - val = String(val); - if (self.csv.quoteValues && nonAlphaNumRE.test(val)) { - val = '"' + val.replace(allDoubleQuoteRE, '""') + '"'; - } - return val; - } - - const csvRows = []; - for (const row of rows) { - const rowArray = []; - for (const col of columns) { - const value = row[col.id]; - const formattedValue = - formatted && col.formatter ? escape(col.formatter.convert(value)) : escape(value); - rowArray.push(formattedValue); - } - csvRows.push(rowArray); - } - - // add the columns to the rows - csvRows.unshift(columns.map(({ title }) => escape(title))); - - return csvRows - .map(function (row) { - return row.join(self.csv.separator) + '\r\n'; - }) - .join(''); - }; - - $scope.$watchMulti( - ['table', 'exportTitle', 'percentageCol', 'totalFunc', '=scope.dimensions'], - function () { - const { table, exportTitle, percentageCol } = $scope; - const showPercentage = percentageCol !== ''; - - if (!table) { - $scope.rows = null; - $scope.formattedColumns = null; - return; - } - - self.csv.filename = (exportTitle || table.title || 'unsaved') + '.csv'; - $scope.rows = table.rows; - $scope.formattedColumns = []; - - if (typeof $scope.dimensions === 'undefined') return; - - const { buckets, metrics } = $scope.dimensions; - - $scope.formattedColumns = table.columns - .map(function (col, i) { - const isBucket = buckets.find((bucket) => bucket.accessor === i); - const dimension = isBucket || metrics.find((metric) => metric.accessor === i); - - const formatter = dimension - ? getFormatService().deserialize(dimension.format) - : undefined; - - const formattedColumn = { - id: col.id, - title: col.name, - formatter: formatter, - filterable: !!isBucket, - }; - - if (!dimension) return; - - const last = i === table.columns.length - 1; - - if (last || !isBucket) { - formattedColumn.class = 'visualize-table-right'; - } - - const isDate = - dimension.format?.id === 'date' || dimension.format?.params?.id === 'date'; - const allowsNumericalAggregations = formatter?.allowsNumericalAggregations; - - let { totalFunc } = $scope; - if (typeof totalFunc === 'undefined' && showPercentage) { - totalFunc = 'sum'; - } - - if (allowsNumericalAggregations || isDate || totalFunc === 'count') { - const sum = (tableRows) => { - return _.reduce( - tableRows, - function (prev, curr) { - // some metrics return undefined for some of the values - // derivative is an example of this as it returns undefined in the first row - if (curr[col.id] === undefined) return prev; - return prev + curr[col.id]; - }, - 0 - ); - }; - - formattedColumn.sumTotal = sum(table.rows); - switch (totalFunc) { - case 'sum': { - if (!isDate) { - const total = formattedColumn.sumTotal; - formattedColumn.formattedTotal = formatter.convert(total); - formattedColumn.total = formattedColumn.sumTotal; - } - break; - } - case 'avg': { - if (!isDate) { - const total = sum(table.rows) / table.rows.length; - formattedColumn.formattedTotal = formatter.convert(total); - formattedColumn.total = total; - } - break; - } - case 'min': { - const total = _.chain(table.rows).map(col.id).min().value(); - formattedColumn.formattedTotal = formatter.convert(total); - formattedColumn.total = total; - break; - } - case 'max': { - const total = _.chain(table.rows).map(col.id).max().value(); - formattedColumn.formattedTotal = formatter.convert(total); - formattedColumn.total = total; - break; - } - case 'count': { - const total = table.rows.length; - formattedColumn.formattedTotal = total; - formattedColumn.total = total; - break; - } - default: - break; - } - } - - return formattedColumn; - }) - .filter((column) => column); - - if (showPercentage) { - const insertAtIndex = _.findIndex($scope.formattedColumns, { title: percentageCol }); - - // column to show percentage for was removed - if (insertAtIndex < 0) return; - - const { cols, rows } = addPercentageCol( - $scope.formattedColumns, - percentageCol, - table.rows, - insertAtIndex - ); - $scope.rows = rows; - $scope.formattedColumns = cols; - } - } - ); - }, - }; -} - -/** - * @param {Object[]} columns - the formatted columns that will be displayed - * @param {String} title - the title of the column to add to - * @param {Object[]} rows - the row data for the columns - * @param {Number} insertAtIndex - the index to insert the percentage column at - * @returns {Object} - cols and rows for the table to render now included percentage column(s) - */ -function addPercentageCol(columns, title, rows, insertAtIndex) { - const { id, sumTotal } = columns[insertAtIndex]; - const newId = `${id}-percents`; - const formatter = getFormatService().deserialize({ id: 'percent' }); - const i18nTitle = i18n.translate('visTypeTable.params.percentageTableColumnName', { - defaultMessage: '{title} percentages', - values: { title }, - }); - const newCols = insert(columns, insertAtIndex, { - title: i18nTitle, - id: newId, - formatter, - }); - const newRows = rows.map((row) => ({ - [newId]: row[id] / sumTotal, - ...row, - })); - - return { cols: newCols, rows: newRows }; -} - -function insert(arr, index, ...items) { - const newArray = [...arr]; - newArray.splice(index + 1, 0, ...items); - return newArray; -} diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js deleted file mode 100644 index ecb4ade51b36c..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table.test.js +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import $ from 'jquery'; -import moment from 'moment-timezone'; -import angular from 'angular'; -import 'angular-mocks'; -import sinon from 'sinon'; -import { round } from 'lodash'; - -import { getFieldFormatsRegistry } from '../../../../data/public/test_utils'; -import { coreMock } from '../../../../../core/public/mocks'; -import { initAngularBootstrap } from '../../../../kibana_legacy/public/angular_bootstrap'; -import { setUiSettings } from '../../../../data/public/services'; -import { FORMATS_UI_SETTINGS } from '../../../../field_formats/common/'; -import { CSV_SEPARATOR_SETTING, CSV_QUOTE_VALUES_SETTING } from '../../../../share/public'; - -import { setFormatService } from '../../services'; -import { getInnerAngular } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../table_vis_legacy_module'; -import { tabifiedData } from './tabified_data'; - -const uiSettings = new Map(); - -describe('Table Vis - AggTable Directive', function () { - const core = coreMock.createStart(); - - core.uiSettings.set = jest.fn((key, value) => { - uiSettings.set(key, value); - }); - - core.uiSettings.get = jest.fn((key) => { - const defaultValues = { - dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', - 'dateFormat:tz': 'UTC', - [FORMATS_UI_SETTINGS.SHORT_DOTS_ENABLE]: true, - [FORMATS_UI_SETTINGS.FORMAT_CURRENCY_DEFAULT_PATTERN]: '($0,0.[00])', - [FORMATS_UI_SETTINGS.FORMAT_NUMBER_DEFAULT_PATTERN]: '0,0.[000]', - [FORMATS_UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN]: '0,0.[000]%', - [FORMATS_UI_SETTINGS.FORMAT_NUMBER_DEFAULT_LOCALE]: 'en', - [FORMATS_UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP]: {}, - [CSV_SEPARATOR_SETTING]: ',', - [CSV_QUOTE_VALUES_SETTING]: true, - }; - - return defaultValues[key] || uiSettings.get(key); - }); - - let $rootScope; - let $compile; - let settings; - - const initLocalAngular = () => { - const tableVisModule = getInnerAngular('kibana/table_vis', core); - initTableVisLegacyModule(tableVisModule); - }; - - beforeAll(async () => { - await initAngularBootstrap(); - }); - beforeEach(() => { - setUiSettings(core.uiSettings); - setFormatService(getFieldFormatsRegistry(core)); - initLocalAngular(); - angular.mock.module('kibana/table_vis'); - angular.mock.inject(($injector, config) => { - settings = config; - - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); - }); - }); - - let $scope; - beforeEach(function () { - $scope = $rootScope.$new(); - }); - afterEach(function () { - $scope.$destroy(); - }); - - test('renders a simple response properly', function () { - $scope.dimensions = { - metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], - buckets: [], - }; - $scope.table = tabifiedData.metricOnly.tables[0]; - - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(1); - expect($el.find('td').length).toBe(1); - expect($el.find('td').text()).toEqual('1,000'); - }); - - test('renders nothing if the table is empty', function () { - $scope.dimensions = {}; - $scope.table = null; - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(0); - }); - - test('renders a complex response properly', async function () { - $scope.dimensions = { - buckets: [ - { accessor: 0, params: {} }, - { accessor: 2, params: {} }, - { accessor: 4, params: {} }, - ], - metrics: [ - { accessor: 1, params: {} }, - { accessor: 3, params: {} }, - { accessor: 5, params: {} }, - ], - }; - $scope.table = tabifiedData.threeTermBuckets.tables[0]; - const $el = $(''); - $compile($el)($scope); - $scope.$digest(); - - expect($el.find('tbody').length).toBe(1); - - const $rows = $el.find('tbody tr'); - expect($rows.length).toBeGreaterThan(0); - - function validBytes(str) { - const num = str.replace(/,/g, ''); - if (num !== '-') { - expect(num).toMatch(/^\d+$/); - } - } - - $rows.each(function () { - // 6 cells in every row - const $cells = $(this).find('td'); - expect($cells.length).toBe(6); - - const txts = $cells.map(function () { - return $(this).text().trim(); - }); - - // two character country code - expect(txts[0]).toMatch(/^(png|jpg|gif|html|css)$/); - validBytes(txts[1]); - - // country - expect(txts[2]).toMatch(/^\w\w$/); - validBytes(txts[3]); - - // os - expect(txts[4]).toMatch(/^(win|mac|linux)$/); - validBytes(txts[5]); - }); - }); - - describe('renders totals row', function () { - async function totalsRowTest(totalFunc, expected) { - function setDefaultTimezone() { - moment.tz.setDefault(settings.get('dateFormat:tz')); - } - - const oldTimezoneSetting = settings.get('dateFormat:tz'); - settings.set('dateFormat:tz', 'UTC'); - setDefaultTimezone(); - - $scope.dimensions = { - buckets: [ - { accessor: 0, params: {} }, - { accessor: 1, format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } } }, - ], - metrics: [ - { accessor: 2, format: { id: 'number' } }, - { accessor: 3, format: { id: 'date' } }, - { accessor: 4, format: { id: 'number' } }, - { accessor: 5, format: { id: 'number' } }, - ], - }; - $scope.table = - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative.tables[0]; - $scope.showTotal = true; - $scope.totalFunc = totalFunc; - const $el = $(``); - $compile($el)($scope); - $scope.$digest(); - - expect($el.find('tfoot').length).toBe(1); - - const $rows = $el.find('tfoot tr'); - expect($rows.length).toBe(1); - - const $cells = $($rows[0]).find('th'); - expect($cells.length).toBe(6); - - for (let i = 0; i < 6; i++) { - expect($($cells[i]).text().trim()).toBe(expected[i]); - } - settings.set('dateFormat:tz', oldTimezoneSetting); - setDefaultTimezone(); - } - test('as count', async function () { - await totalsRowTest('count', ['18', '18', '18', '18', '18', '18']); - }); - test('as min', async function () { - await totalsRowTest('min', [ - '', - '2014-09-28', - '9,283', - 'Sep 28, 2014 @ 00:00:00.000', - '1', - '11', - ]); - }); - test('as max', async function () { - await totalsRowTest('max', [ - '', - '2014-10-03', - '220,943', - 'Oct 3, 2014 @ 00:00:00.000', - '239', - '837', - ]); - }); - test('as avg', async function () { - await totalsRowTest('avg', ['', '', '87,221.5', '', '64.667', '206.833']); - }); - test('as sum', async function () { - await totalsRowTest('sum', ['', '', '1,569,987', '', '1,164', '3,723']); - }); - }); - - describe('aggTable.toCsv()', function () { - test('escapes rows and columns properly', function () { - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - const $tableScope = $el.isolateScope(); - const aggTable = $tableScope.aggTable; - $tableScope.rows = [{ a: 1, b: 2, c: '"foobar"' }]; - $tableScope.formattedColumns = [ - { id: 'a', title: 'one' }, - { id: 'b', title: 'two' }, - { id: 'c', title: 'with double-quotes(")' }, - ]; - - expect(aggTable.toCsv()).toBe( - 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n' - ); - }); - - test('exports rows and columns properly', async function () { - $scope.dimensions = { - buckets: [ - { accessor: 0, params: {} }, - { accessor: 2, params: {} }, - { accessor: 4, params: {} }, - ], - metrics: [ - { accessor: 1, params: {} }, - { accessor: 3, params: {} }, - { accessor: 5, params: {} }, - ], - }; - $scope.table = tabifiedData.threeTermBuckets.tables[0]; - - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - const $tableScope = $el.isolateScope(); - const aggTable = $tableScope.aggTable; - $tableScope.table = $scope.table; - - const raw = aggTable.toCsv(false); - expect(raw).toBe( - '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + - '\r\n' + - 'png,412032,IT,9299,win,0' + - '\r\n' + - 'png,412032,IT,9299,mac,9299' + - '\r\n' + - 'png,412032,US,8293,linux,3992' + - '\r\n' + - 'png,412032,US,8293,mac,3029' + - '\r\n' + - 'css,412032,MX,9299,win,4992' + - '\r\n' + - 'css,412032,MX,9299,mac,5892' + - '\r\n' + - 'css,412032,US,8293,linux,3992' + - '\r\n' + - 'css,412032,US,8293,mac,3029' + - '\r\n' + - 'html,412032,CN,9299,win,4992' + - '\r\n' + - 'html,412032,CN,9299,mac,5892' + - '\r\n' + - 'html,412032,FR,8293,win,3992' + - '\r\n' + - 'html,412032,FR,8293,mac,3029' + - '\r\n' - ); - }); - - test('exports formatted rows and columns properly', async function () { - $scope.dimensions = { - buckets: [ - { accessor: 0, params: {} }, - { accessor: 2, params: {} }, - { accessor: 4, params: {} }, - ], - metrics: [ - { accessor: 1, params: {} }, - { accessor: 3, params: {} }, - { accessor: 5, params: {} }, - ], - }; - $scope.table = tabifiedData.threeTermBuckets.tables[0]; - - const $el = $compile('')( - $scope - ); - $scope.$digest(); - - const $tableScope = $el.isolateScope(); - const aggTable = $tableScope.aggTable; - $tableScope.table = $scope.table; - - // Create our own converter since the ones we use for tests don't actually transform the provided value - $tableScope.formattedColumns[0].formatter.convert = (v) => `${v}_formatted`; - - const formatted = aggTable.toCsv(true); - expect(formatted).toBe( - '"extension: Descending","Average bytes","geo.src: Descending","Average bytes","machine.os: Descending","Average bytes"' + - '\r\n' + - '"png_formatted",412032,IT,9299,win,0' + - '\r\n' + - '"png_formatted",412032,IT,9299,mac,9299' + - '\r\n' + - '"png_formatted",412032,US,8293,linux,3992' + - '\r\n' + - '"png_formatted",412032,US,8293,mac,3029' + - '\r\n' + - '"css_formatted",412032,MX,9299,win,4992' + - '\r\n' + - '"css_formatted",412032,MX,9299,mac,5892' + - '\r\n' + - '"css_formatted",412032,US,8293,linux,3992' + - '\r\n' + - '"css_formatted",412032,US,8293,mac,3029' + - '\r\n' + - '"html_formatted",412032,CN,9299,win,4992' + - '\r\n' + - '"html_formatted",412032,CN,9299,mac,5892' + - '\r\n' + - '"html_formatted",412032,FR,8293,win,3992' + - '\r\n' + - '"html_formatted",412032,FR,8293,mac,3029' + - '\r\n' - ); - }); - }); - - test('renders percentage columns', async function () { - $scope.dimensions = { - buckets: [ - { accessor: 0, params: {} }, - { accessor: 1, format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } } }, - ], - metrics: [ - { accessor: 2, format: { id: 'number' } }, - { accessor: 3, format: { id: 'date' } }, - { accessor: 4, format: { id: 'number' } }, - { accessor: 5, format: { id: 'number' } }, - ], - }; - $scope.table = - tabifiedData.oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative.tables[0]; - $scope.percentageCol = 'Average bytes'; - - const $el = $(``); - - $compile($el)($scope); - $scope.$digest(); - - const $headings = $el.find('th'); - expect($headings.length).toBe(7); - expect($headings.eq(3).text().trim()).toBe('Average bytes percentages'); - - const countColId = $scope.table.columns.find((col) => col.name === $scope.percentageCol).id; - const counts = $scope.table.rows.map((row) => row[countColId]); - const total = counts.reduce((sum, curr) => sum + curr, 0); - const $percentageColValues = $el.find('tbody tr').map((i, el) => $(el).find('td').eq(3).text()); - - $percentageColValues.each((i, value) => { - const percentage = `${round((counts[i] / total) * 100, 3)}%`; - expect(value).toBe(percentage); - }); - }); - - describe('aggTable.exportAsCsv()', function () { - let origBlob; - function FakeBlob(slices, opts) { - this.slices = slices; - this.opts = opts; - } - - beforeEach(function () { - origBlob = window.Blob; - window.Blob = FakeBlob; - }); - - afterEach(function () { - window.Blob = origBlob; - }); - - test('calls _saveAs properly', function () { - const $el = $compile('')($scope); - $scope.$digest(); - - const $tableScope = $el.isolateScope(); - const aggTable = $tableScope.aggTable; - - const saveAs = sinon.stub(aggTable, '_saveAs'); - $tableScope.rows = [{ a: 1, b: 2, c: '"foobar"' }]; - $tableScope.formattedColumns = [ - { id: 'a', title: 'one' }, - { id: 'b', title: 'two' }, - { id: 'c', title: 'with double-quotes(")' }, - ]; - - aggTable.csv.filename = 'somefilename.csv'; - aggTable.exportAsCsv(); - - expect(saveAs.callCount).toBe(1); - const call = saveAs.getCall(0); - expect(call.args[0]).toBeInstanceOf(FakeBlob); - expect(call.args[0].slices).toEqual([ - 'one,two,"with double-quotes("")"' + '\r\n' + '1,2,"""foobar"""' + '\r\n', - ]); - expect(call.args[0].opts).toEqual({ - type: 'text/plain;charset=utf-8', - }); - expect(call.args[1]).toBe('somefilename.csv'); - }); - - test('should use the export-title attribute', function () { - const expected = 'export file name'; - const $el = $compile( - `` - )($scope); - $scope.$digest(); - - const $tableScope = $el.isolateScope(); - const aggTable = $tableScope.aggTable; - $tableScope.table = { - columns: [], - rows: [], - }; - $tableScope.exportTitle = expected; - $scope.$digest(); - - expect(aggTable.csv.filename).toEqual(`${expected}.csv`); - }); - }); -}); diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html deleted file mode 100644 index 4567b80b5f66c..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - -
- {{ table.title }} -
- - - -
- - - - - - - - - - - - -
- {{ table.title }} -
- - - -
diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js deleted file mode 100644 index e9e71806a2bc3..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import aggTableGroupTemplate from './agg_table_group.html'; - -export function KbnAggTableGroup(RecursionHelper) { - return { - restrict: 'E', - template: aggTableGroupTemplate, - scope: { - group: '=', - dimensions: '=', - perPage: '=?', - sort: '=?', - exportTitle: '=?', - showTotal: '=', - totalFunc: '=', - percentageCol: '=', - filter: '=', - }, - compile: function ($el) { - // Use the compile function from the RecursionHelper, - // And return the linking function(s) which it returns - return RecursionHelper.compile($el, { - post: function ($scope) { - $scope.$watch('group', function (group) { - // clear the previous "state" - $scope.rows = $scope.columns = false; - - if (!group || !group.tables.length) return; - - const childLayout = group.direction === 'row' ? 'rows' : 'columns'; - - $scope[childLayout] = group.tables; - }); - }, - }); - }, - }; -} diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js b/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js deleted file mode 100644 index ba04b2f449f6d..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/agg_table_group.test.js +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import $ from 'jquery'; -import angular from 'angular'; -import 'angular-mocks'; -import expect from '@kbn/expect'; - -import { getFieldFormatsRegistry } from '../../../../data/public/test_utils'; -import { coreMock } from '../../../../../core/public/mocks'; -import { setUiSettings } from '../../../../data/public/services'; -import { setFormatService } from '../../services'; -import { getInnerAngular } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../table_vis_legacy_module'; -import { initAngularBootstrap } from '../../../../kibana_legacy/public/angular_bootstrap'; -import { tabifiedData } from './tabified_data'; - -const uiSettings = new Map(); - -describe('Table Vis - AggTableGroup Directive', function () { - const core = coreMock.createStart(); - let $rootScope; - let $compile; - - core.uiSettings.set = jest.fn((key, value) => { - uiSettings.set(key, value); - }); - - core.uiSettings.get = jest.fn((key) => { - return uiSettings.get(key); - }); - - const initLocalAngular = () => { - const tableVisModule = getInnerAngular('kibana/table_vis', core); - initTableVisLegacyModule(tableVisModule); - }; - - beforeAll(async () => { - await initAngularBootstrap(); - }); - beforeEach(() => { - setUiSettings(core.uiSettings); - setFormatService(getFieldFormatsRegistry(core)); - initLocalAngular(); - angular.mock.module('kibana/table_vis'); - angular.mock.inject(($injector) => { - $rootScope = $injector.get('$rootScope'); - $compile = $injector.get('$compile'); - }); - }); - - let $scope; - beforeEach(function () { - $scope = $rootScope.$new(); - }); - afterEach(function () { - $scope.$destroy(); - }); - - it('renders a simple split response properly', function () { - $scope.dimensions = { - metrics: [{ accessor: 0, format: { id: 'number' }, params: {} }], - buckets: [], - }; - $scope.group = tabifiedData.metricOnly; - $scope.sort = { - columnIndex: null, - direction: null, - }; - const $el = $( - '' - ); - - $compile($el)($scope); - $scope.$digest(); - - // should create one sub-tbale - expect($el.find('kbn-agg-table').length).to.be(1); - }); - - it('renders nothing if the table list is empty', function () { - const $el = $( - '' - ); - - $scope.group = { - tables: [], - }; - - $compile($el)($scope); - $scope.$digest(); - - const $subTables = $el.find('kbn-agg-table'); - expect($subTables.length).to.be(0); - }); - - it('renders a complex response properly', function () { - $scope.dimensions = { - splitRow: [{ accessor: 0, params: {} }], - buckets: [ - { accessor: 2, params: {} }, - { accessor: 4, params: {} }, - ], - metrics: [ - { accessor: 1, params: {} }, - { accessor: 3, params: {} }, - { accessor: 5, params: {} }, - ], - }; - const group = ($scope.group = tabifiedData.threeTermBucketsWithSplit); - const $el = $( - '' - ); - $compile($el)($scope); - $scope.$digest(); - - const $subTables = $el.find('kbn-agg-table'); - expect($subTables.length).to.be(3); - - const $subTableHeaders = $el.find('.kbnAggTable__groupHeader'); - expect($subTableHeaders.length).to.be(3); - - $subTableHeaders.each(function (i) { - expect($(this).text()).to.be(group.tables[i].title); - }); - }); -}); diff --git a/src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js b/src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js deleted file mode 100644 index 54da06f2a5f90..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/agg_table/tabified_data.js +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const tabifiedData = { - metricOnly: { - tables: [ - { - columns: [ - { - id: 'col-0-1', - name: 'Count', - }, - ], - rows: [ - { - 'col-0-1': 1000, - }, - ], - }, - ], - }, - threeTermBuckets: { - tables: [ - { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_1', - name: 'Average bytes', - }, - { - id: 'col-2-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - { - id: 'col-4-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-5-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'png', - 'col-2-agg_3': 'IT', - 'col-4-agg_4': 'win', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 0, - }, - { - 'col-0-agg_2': 'png', - 'col-2-agg_3': 'IT', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 9299, - }, - { - 'col-0-agg_2': 'png', - 'col-2-agg_3': 'US', - 'col-4-agg_4': 'linux', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3992, - }, - { - 'col-0-agg_2': 'png', - 'col-2-agg_3': 'US', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3029, - }, - { - 'col-0-agg_2': 'css', - 'col-2-agg_3': 'MX', - 'col-4-agg_4': 'win', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 4992, - }, - { - 'col-0-agg_2': 'css', - 'col-2-agg_3': 'MX', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 5892, - }, - { - 'col-0-agg_2': 'css', - 'col-2-agg_3': 'US', - 'col-4-agg_4': 'linux', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3992, - }, - { - 'col-0-agg_2': 'css', - 'col-2-agg_3': 'US', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3029, - }, - { - 'col-0-agg_2': 'html', - 'col-2-agg_3': 'CN', - 'col-4-agg_4': 'win', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 4992, - }, - { - 'col-0-agg_2': 'html', - 'col-2-agg_3': 'CN', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 9299, - 'col-5-agg_1': 5892, - }, - { - 'col-0-agg_2': 'html', - 'col-2-agg_3': 'FR', - 'col-4-agg_4': 'win', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3992, - }, - { - 'col-0-agg_2': 'html', - 'col-2-agg_3': 'FR', - 'col-4-agg_4': 'mac', - 'col-1-agg_1': 412032, - 'col-3-agg_1': 8293, - 'col-5-agg_1': 3029, - }, - ], - }, - ], - }, - threeTermBucketsWithSplit: { - tables: [ - { - title: 'png: extension: Descending', - name: 'extension: Descending', - key: 'png', - column: 0, - row: 0, - table: { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 0, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 9299, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - tables: [ - { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 0, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 9299, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - ], - }, - { - title: 'css: extension: Descending', - name: 'extension: Descending', - key: 'css', - column: 0, - row: 4, - table: { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 0, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 9299, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - tables: [ - { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - ], - }, - { - title: 'html: extension: Descending', - name: 'extension: Descending', - key: 'html', - column: 0, - row: 8, - table: { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 0, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'IT', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 9299, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'png', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'MX', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'linux', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'css', - 'col-1-agg_3': 'US', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - tables: [ - { - columns: [ - { - id: 'col-0-agg_2', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_3', - name: 'geo.src: Descending', - }, - { - id: 'col-2-agg_4', - name: 'machine.os: Descending', - }, - { - id: 'col-3-agg_1', - name: 'Average bytes', - }, - ], - rows: [ - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 4992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'CN', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 5892, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'win', - 'col-3-agg_1': 3992, - }, - { - 'col-0-agg_2': 'html', - 'col-1-agg_3': 'FR', - 'col-2-agg_4': 'mac', - 'col-3-agg_1': 3029, - }, - ], - }, - ], - }, - ], - direction: 'row', - }, - oneTermOneHistogramBucketWithTwoMetricsOneTopHitOneDerivative: { - tables: [ - { - columns: [ - { - id: 'col-0-agg_3', - name: 'extension: Descending', - }, - { - id: 'col-1-agg_4', - name: '@timestamp per day', - }, - { - id: 'col-2-agg_1', - name: 'Average bytes', - }, - { - id: 'col-3-agg_2', - name: 'Min @timestamp', - }, - { - id: 'col-4-agg_5', - name: 'Derivative of Count', - }, - { - id: 'col-5-agg_6', - name: 'Last bytes', - }, - ], - rows: [ - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1411862400000, - 'col-2-agg_1': 9283, - 'col-3-agg_2': 1411862400000, - 'col-5-agg_6': 23, - }, - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1411948800000, - 'col-2-agg_1': 28349, - 'col-3-agg_2': 1411948800000, - 'col-4-agg_5': 203, - 'col-5-agg_6': 39, - }, - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1412035200000, - 'col-2-agg_1': 84330, - 'col-3-agg_2': 1412035200000, - 'col-4-agg_5': 200, - 'col-5-agg_6': 329, - }, - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1412121600000, - 'col-2-agg_1': 34992, - 'col-3-agg_2': 1412121600000, - 'col-4-agg_5': 103, - 'col-5-agg_6': 22, - }, - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1412208000000, - 'col-2-agg_1': 145432, - 'col-3-agg_2': 1412208000000, - 'col-4-agg_5': 153, - 'col-5-agg_6': 93, - }, - { - 'col-0-agg_3': 'png', - 'col-1-agg_4': 1412294400000, - 'col-2-agg_1': 220943, - 'col-3-agg_2': 1412294400000, - 'col-4-agg_5': 239, - 'col-5-agg_6': 72, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1411862400000, - 'col-2-agg_1': 9283, - 'col-3-agg_2': 1411862400000, - 'col-5-agg_6': 75, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1411948800000, - 'col-2-agg_1': 28349, - 'col-3-agg_2': 1411948800000, - 'col-4-agg_5': 10, - 'col-5-agg_6': 11, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1412035200000, - 'col-2-agg_1': 84330, - 'col-3-agg_2': 1412035200000, - 'col-4-agg_5': 24, - 'col-5-agg_6': 238, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1412121600000, - 'col-2-agg_1': 34992, - 'col-3-agg_2': 1412121600000, - 'col-4-agg_5': 49, - 'col-5-agg_6': 343, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1412208000000, - 'col-2-agg_1': 145432, - 'col-3-agg_2': 1412208000000, - 'col-4-agg_5': 100, - 'col-5-agg_6': 837, - }, - { - 'col-0-agg_3': 'css', - 'col-1-agg_4': 1412294400000, - 'col-2-agg_1': 220943, - 'col-3-agg_2': 1412294400000, - 'col-4-agg_5': 23, - 'col-5-agg_6': 302, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1411862400000, - 'col-2-agg_1': 9283, - 'col-3-agg_2': 1411862400000, - 'col-5-agg_6': 30, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1411948800000, - 'col-2-agg_1': 28349, - 'col-3-agg_2': 1411948800000, - 'col-4-agg_5': 1, - 'col-5-agg_6': 43, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1412035200000, - 'col-2-agg_1': 84330, - 'col-3-agg_2': 1412035200000, - 'col-4-agg_5': 5, - 'col-5-agg_6': 88, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1412121600000, - 'col-2-agg_1': 34992, - 'col-3-agg_2': 1412121600000, - 'col-4-agg_5': 10, - 'col-5-agg_6': 91, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1412208000000, - 'col-2-agg_1': 145432, - 'col-3-agg_2': 1412208000000, - 'col-4-agg_5': 43, - 'col-5-agg_6': 534, - }, - { - 'col-0-agg_3': 'html', - 'col-1-agg_4': 1412294400000, - 'col-2-agg_1': 220943, - 'col-3-agg_2': 1412294400000, - 'col-4-agg_5': 1, - 'col-5-agg_6': 553, - }, - ], - }, - ], - }, -}; diff --git a/src/plugins/vis_type_table/public/legacy/get_inner_angular.ts b/src/plugins/vis_type_table/public/legacy/get_inner_angular.ts deleted file mode 100644 index 412dd904a5e87..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/get_inner_angular.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// inner angular imports -// these are necessary to bootstrap the local angular. -// They can stay even after NP cutover -import angular from 'angular'; -// required for `ngSanitize` angular module -import 'angular-sanitize'; -import 'angular-recursion'; -import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular'; -import { CoreStart, IUiSettingsClient, PluginInitializerContext } from 'kibana/public'; -import { - PaginateDirectiveProvider, - PaginateControlsDirectiveProvider, - PrivateProvider, - watchMultiDecorator, - KbnAccessibleClickProvider, -} from '../../../kibana_legacy/public'; - -const thirdPartyAngularDependencies = ['ngSanitize', 'ui.bootstrap', 'RecursionHelper']; - -export function getAngularModule(name: string, core: CoreStart, context: PluginInitializerContext) { - const uiModule = getInnerAngular(name, core); - return uiModule; -} - -let initialized = false; - -export function getInnerAngular(name = 'kibana/table_vis', core: CoreStart) { - if (!initialized) { - createLocalPrivateModule(); - createLocalI18nModule(); - createLocalConfigModule(core.uiSettings); - createLocalPaginateModule(); - initialized = true; - } - return angular - .module(name, [ - ...thirdPartyAngularDependencies, - 'tableVisPaginate', - 'tableVisConfig', - 'tableVisPrivate', - 'tableVisI18n', - ]) - .config(watchMultiDecorator) - .directive('kbnAccessibleClick', KbnAccessibleClickProvider); -} - -function createLocalPrivateModule() { - angular.module('tableVisPrivate', []).provider('Private', PrivateProvider); -} - -function createLocalConfigModule(uiSettings: IUiSettingsClient) { - angular.module('tableVisConfig', []).provider('config', function () { - return { - $get: () => ({ - get: (value: string) => { - return uiSettings ? uiSettings.get(value) : undefined; - }, - // set method is used in agg_table mocha test - set: (key: string, value: string) => { - return uiSettings ? uiSettings.set(key, value) : undefined; - }, - }), - }; - }); -} - -function createLocalI18nModule() { - angular - .module('tableVisI18n', []) - .provider('i18n', I18nProvider) - .filter('i18n', i18nFilter) - .directive('i18nId', i18nDirective); -} - -function createLocalPaginateModule() { - angular - .module('tableVisPaginate', []) - .directive('paginate', PaginateDirectiveProvider) - .directive('paginateControls', PaginateControlsDirectiveProvider); -} diff --git a/src/plugins/vis_type_table/public/legacy/index.scss b/src/plugins/vis_type_table/public/legacy/index.scss deleted file mode 100644 index 0972c85e0dbe0..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/index.scss +++ /dev/null @@ -1,10 +0,0 @@ -// Prefix all styles with "tbv" to avoid conflicts. -// Examples -// tbvChart -// tbvChart__legend -// tbvChart__legend--small -// tbvChart__legend-isLoading - -@import './agg_table/index'; -@import './paginated_table/index'; -@import './table_vis'; diff --git a/src/plugins/vis_type_table/public/legacy/index.ts b/src/plugins/vis_type_table/public/legacy/index.ts deleted file mode 100644 index 6f7eb0686852f..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { registerLegacyVis } from './register_legacy_vis'; diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss b/src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss deleted file mode 100644 index 23d56c09b2818..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './_table_cell_filter'; diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss b/src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss deleted file mode 100644 index 05d050362ce0b..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/_table_cell_filter.scss +++ /dev/null @@ -1,30 +0,0 @@ -.kbnTableCellFilter__hover { - position: relative; - - /** - * 1. Center vertically regardless of row height. - */ - .kbnTableCellFilter { - position: absolute; - white-space: nowrap; - right: 0; - top: 50%; /* 1 */ - transform: translateY(-50%); /* 1 */ - display: none; - } - - &:hover { - .kbnTableCellFilter { - display: inline; - } - - .kbnTableCellFilter__hover-show { - visibility: visible; - } - } -} - -.kbnTableCellFilter__hover-show { - // so that the cell doesn't change size on hover - visibility: hidden; -} diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html deleted file mode 100644 index 12731eb386566..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.html +++ /dev/null @@ -1,55 +0,0 @@ - -
- - - - - - - - - - - - - -
- - - - - - -
- {{ col.formattedTotal }} -
-
- - - -
-
diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js deleted file mode 100644 index 066134dbb5dc5..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import paginatedTableTemplate from './paginated_table.html'; - -export function PaginatedTable($filter) { - const orderBy = $filter('orderBy'); - - return { - restrict: 'E', - template: paginatedTableTemplate, - transclude: true, - scope: { - table: '=', - rows: '=', - columns: '=', - linkToTop: '=', - perPage: '=?', - sortHandler: '=?', - sort: '=?', - showSelector: '=?', - showTotal: '=', - totalFunc: '=', - filter: '=', - percentageCol: '=', - }, - controllerAs: 'paginatedTable', - controller: function ($scope) { - const self = this; - self.sort = { - columnIndex: null, - direction: null, - }; - - self.sortColumn = function (colIndex, sortDirection = 'asc') { - const col = $scope.columns[colIndex]; - - if (!col) return; - if (col.sortable === false) return; - - if (self.sort.columnIndex === colIndex) { - const directions = { - null: 'asc', - asc: 'desc', - desc: null, - }; - sortDirection = directions[self.sort.direction]; - } - - self.sort.columnIndex = colIndex; - self.sort.direction = sortDirection; - if ($scope.sort) { - _.assign($scope.sort, self.sort); - } - }; - - function valueGetter(row) { - const col = $scope.columns[self.sort.columnIndex]; - let value = row[col.id]; - if (typeof value === 'boolean') value = value ? 0 : 1; - return value; - } - - // Set the sort state if it is set - if ($scope.sort && $scope.sort.columnIndex !== null) { - self.sortColumn($scope.sort.columnIndex, $scope.sort.direction); - } - - function resortRows() { - const newSort = $scope.sort; - if (newSort && !_.isEqual(newSort, self.sort)) { - self.sortColumn(newSort.columnIndex, newSort.direction); - } - - if (!$scope.rows || !$scope.columns) { - $scope.sortedRows = false; - return; - } - - const sort = self.sort; - if (sort.direction == null) { - $scope.sortedRows = $scope.rows.slice(0); - } else { - $scope.sortedRows = orderBy($scope.rows, valueGetter, sort.direction === 'desc'); - } - } - - // update the sortedRows result - $scope.$watchMulti(['rows', 'columns', '[]sort', '[]paginatedTable.sort'], resortRows); - }, - }; -} diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts b/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts deleted file mode 100644 index 3feff52f86792..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/paginated_table.test.ts +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { isNumber, times, identity, random } from 'lodash'; -import angular, { IRootScopeService, IScope, ICompileService } from 'angular'; -import $ from 'jquery'; -import 'angular-sanitize'; -import 'angular-mocks'; - -import { initAngularBootstrap } from '../../../../kibana_legacy/public/angular_bootstrap'; -import { getAngularModule } from '../get_inner_angular'; -import { initTableVisLegacyModule } from '../table_vis_legacy_module'; -import { coreMock } from '../../../../../core/public/mocks'; - -interface Sort { - columnIndex: number; - direction: string; -} - -interface Row { - [key: string]: number | string; -} - -interface Column { - id?: string; - title: string; - formatter?: { - convert?: (val: string) => string; - }; - sortable?: boolean; -} - -interface Table { - columns: Column[]; - rows: Row[]; -} - -interface PaginatedTableScope extends IScope { - table?: Table; - cols?: Column[]; - rows?: Row[]; - perPage?: number; - sort?: Sort; - linkToTop?: boolean; -} - -describe('Table Vis - Paginated table', () => { - let $el: JQuery; - let $rootScope: IRootScopeService; - let $compile: ICompileService; - let $scope: PaginatedTableScope; - const defaultPerPage = 10; - let paginatedTable: any; - - beforeAll(async () => { - await initAngularBootstrap(); - }); - - const initLocalAngular = () => { - const tableVisModule = getAngularModule( - 'kibana/table_vis', - coreMock.createStart(), - coreMock.createPluginInitializerContext() - ); - initTableVisLegacyModule(tableVisModule); - }; - - beforeEach(initLocalAngular); - beforeEach(angular.mock.module('kibana/table_vis')); - - beforeEach( - angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { - $rootScope = _$rootScope_; - $compile = _$compile_; - $scope = $rootScope.$new(); - }) - ); - - afterEach(() => { - $scope.$destroy(); - }); - - const makeData = (colCount: number | Column[], rowCount: number | string[][]) => { - let columns: Column[] = []; - let rows: Row[] = []; - - if (isNumber(colCount)) { - times(colCount, (i) => { - columns.push({ id: `${i}`, title: `column${i}`, formatter: { convert: identity } }); - }); - } else { - columns = colCount.map( - (col, i) => - ({ - id: `${i}`, - title: col.title, - formatter: col.formatter || { convert: identity }, - } as Column) - ); - } - - if (isNumber(rowCount)) { - times(rowCount, (row) => { - const rowItems: Row = {}; - - times(columns.length, (col) => { - rowItems[`${col}`] = `item-${col}-${row}`; - }); - - rows.push(rowItems); - }); - } else { - rows = rowCount.map((row: string[]) => { - const newRow: Row = {}; - row.forEach((v, i) => (newRow[i] = v)); - return newRow; - }); - } - - return { - columns, - rows, - }; - }; - - const renderTable = ( - table: { columns: Column[]; rows: Row[] } | null, - cols: Column[], - rows: Row[], - perPage?: number, - sort?: Sort, - linkToTop?: boolean - ) => { - $scope.table = table || { columns: [], rows: [] }; - $scope.cols = cols || []; - $scope.rows = rows || []; - $scope.perPage = perPage || defaultPerPage; - $scope.sort = sort; - $scope.linkToTop = linkToTop; - - const template = ` - `; - const element = $compile(template)($scope); - $el = $(element); - - $scope.$digest(); - paginatedTable = element.controller('paginatedTable'); - }; - - describe('rendering', () => { - test('should not display without rows', () => { - const cols: Column[] = [ - { - id: 'col-1-1', - title: 'test1', - }, - ]; - const rows: Row[] = []; - - renderTable(null, cols, rows); - expect($el.children().length).toBe(0); - }); - - test('should render columns and rows', () => { - const data = makeData(2, 2); - const cols = data.columns; - const rows = data.rows; - - renderTable(data, cols, rows); - expect($el.children().length).toBe(1); - const tableRows = $el.find('tbody tr'); - - // should contain the row data - expect(tableRows.eq(0).find('td').eq(0).text()).toBe(rows[0][0]); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe(rows[0][1]); - expect(tableRows.eq(1).find('td').eq(0).text()).toBe(rows[1][0]); - expect(tableRows.eq(1).find('td').eq(1).text()).toBe(rows[1][1]); - }); - - test('should paginate rows', () => { - // note: paginate truncates pages, so don't make too many - const rowCount = random(16, 24); - const perPageCount = random(5, 8); - const data = makeData(3, rowCount); - const pageCount = Math.ceil(rowCount / perPageCount); - - renderTable(data, data.columns, data.rows, perPageCount); - const tableRows = $el.find('tbody tr'); - expect(tableRows.length).toBe(perPageCount); - // add 2 for the first and last page links - expect($el.find('paginate-controls button').length).toBe(pageCount + 2); - }); - - test('should not show blank rows on last page', () => { - const rowCount = 7; - const perPageCount = 10; - const data = makeData(3, rowCount); - - renderTable(data, data.columns, data.rows, perPageCount); - const tableRows = $el.find('tbody tr'); - expect(tableRows.length).toBe(rowCount); - }); - - test('should not show link to top when not set', () => { - const data = makeData(5, 5); - renderTable(data, data.columns, data.rows, 10); - - const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); - expect(linkToTop.length).toBe(0); - }); - - test('should show link to top when set', () => { - const data = makeData(5, 5); - renderTable(data, data.columns, data.rows, 10, undefined, true); - - const linkToTop = $el.find('[data-test-subj="paginateControlsLinkToTop"]'); - expect(linkToTop.length).toBe(1); - }); - }); - - describe('sorting', () => { - let data: Table; - let lastRowIndex: number; - - beforeEach(() => { - data = makeData(3, [ - ['bbbb', 'aaaa', 'zzzz'], - ['cccc', 'cccc', 'aaaa'], - ['zzzz', 'bbbb', 'bbbb'], - ['aaaa', 'zzzz', 'cccc'], - ]); - - lastRowIndex = data.rows.length - 1; - renderTable(data, data.columns, data.rows); - }); - - test('should not sort by default', () => { - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe(data.rows[0][0]); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).toBe(data.rows[lastRowIndex][0]); - }); - - test('should do nothing when sorting by invalid column id', () => { - // sortColumn - paginatedTable.sortColumn(999); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('aaaa'); - expect(tableRows.eq(0).find('td').eq(2).text()).toBe('zzzz'); - }); - - test('should do nothing when sorting by non sortable column', () => { - data.columns[0].sortable = false; - - // sortColumn - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('aaaa'); - expect(tableRows.eq(0).find('td').eq(2).text()).toBe('zzzz'); - }); - - test("should set the sort direction to asc when it's not explicitly set", () => { - paginatedTable.sortColumn(1); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(2).find('td').eq(1).text()).toBe('cccc'); - expect(tableRows.eq(1).find('td').eq(1).text()).toBe('bbbb'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('aaaa'); - }); - - test('should allow you to explicitly set the sort direction', () => { - paginatedTable.sortColumn(1, 'desc'); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('zzzz'); - expect(tableRows.eq(1).find('td').eq(1).text()).toBe('cccc'); - expect(tableRows.eq(2).find('td').eq(1).text()).toBe('bbbb'); - }); - - test('should sort ascending on first invocation', () => { - // sortColumn - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('aaaa'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).toBe('zzzz'); - }); - - test('should sort descending on second invocation', () => { - // sortColumn - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('zzzz'); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).toBe('aaaa'); - }); - - test('should clear sorting on third invocation', () => { - // sortColumn - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - paginatedTable.sortColumn(0); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe(data.rows[0][0]); - expect(tableRows.eq(lastRowIndex).find('td').eq(0).text()).toBe('aaaa'); - }); - - test('should sort new column ascending', () => { - // sort by first column - paginatedTable.sortColumn(0); - $scope.$digest(); - - // sort by second column - paginatedTable.sortColumn(1); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('aaaa'); - expect(tableRows.eq(lastRowIndex).find('td').eq(1).text()).toBe('zzzz'); - }); - }); - - describe('sorting duplicate columns', () => { - let data; - const colText = 'test row'; - - beforeEach(() => { - const cols: Column[] = [{ title: colText }, { title: colText }, { title: colText }]; - const rows = [ - ['bbbb', 'aaaa', 'zzzz'], - ['cccc', 'cccc', 'aaaa'], - ['zzzz', 'bbbb', 'bbbb'], - ['aaaa', 'zzzz', 'cccc'], - ]; - data = makeData(cols, rows); - - renderTable(data, data.columns, data.rows); - }); - - test('should have duplicate column titles', () => { - const columns = $el.find('thead th span'); - columns.each((i, col) => { - expect($(col).text()).toBe(colText); - }); - }); - - test('should handle sorting on columns with the same name', () => { - // sort by the last column - paginatedTable.sortColumn(2); - $scope.$digest(); - - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('cccc'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('cccc'); - expect(tableRows.eq(0).find('td').eq(2).text()).toBe('aaaa'); - expect(tableRows.eq(1).find('td').eq(2).text()).toBe('bbbb'); - expect(tableRows.eq(2).find('td').eq(2).text()).toBe('cccc'); - expect(tableRows.eq(3).find('td').eq(2).text()).toBe('zzzz'); - }); - - test('should sort correctly between columns', () => { - // sort by the last column - paginatedTable.sortColumn(2); - $scope.$digest(); - - let tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('cccc'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('cccc'); - expect(tableRows.eq(0).find('td').eq(2).text()).toBe('aaaa'); - - // sort by the first column - paginatedTable.sortColumn(0); - $scope.$digest(); - - tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('td').eq(0).text()).toBe('aaaa'); - expect(tableRows.eq(0).find('td').eq(1).text()).toBe('zzzz'); - expect(tableRows.eq(0).find('td').eq(2).text()).toBe('cccc'); - - expect(tableRows.eq(1).find('td').eq(0).text()).toBe('bbbb'); - expect(tableRows.eq(2).find('td').eq(0).text()).toBe('cccc'); - expect(tableRows.eq(3).find('td').eq(0).text()).toBe('zzzz'); - }); - - test('should not sort duplicate columns', () => { - paginatedTable.sortColumn(1); - $scope.$digest(); - - const sorters = $el.find('thead th i'); - expect(sorters.eq(0).hasClass('fa-sort')).toBe(true); - expect(sorters.eq(1).hasClass('fa-sort')).toBe(false); - expect(sorters.eq(2).hasClass('fa-sort')).toBe(true); - }); - }); - - describe('object rows', () => { - let cols: Column[]; - let rows: any; - - beforeEach(() => { - cols = [ - { - title: 'object test', - id: '0', - formatter: { - convert: (val) => { - return val === 'zzz' ? '

hello

' : val; - }, - }, - }, - ]; - rows = [['aaaa'], ['zzz'], ['bbbb']]; - renderTable({ columns: cols, rows }, cols, rows); - }); - - test('should append object markup', () => { - const tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('h1').length).toBe(0); - expect(tableRows.eq(1).find('h1').length).toBe(1); - expect(tableRows.eq(2).find('h1').length).toBe(0); - }); - - test('should sort using object value', () => { - paginatedTable.sortColumn(0); - $scope.$digest(); - let tableRows = $el.find('tbody tr'); - expect(tableRows.eq(0).find('h1').length).toBe(0); - expect(tableRows.eq(1).find('h1').length).toBe(0); - // html row should be the last row - expect(tableRows.eq(2).find('h1').length).toBe(1); - - paginatedTable.sortColumn(0); - $scope.$digest(); - tableRows = $el.find('tbody tr'); - // html row should be the first row - expect(tableRows.eq(0).find('h1').length).toBe(1); - expect(tableRows.eq(1).find('h1').length).toBe(0); - expect(tableRows.eq(2).find('h1').length).toBe(0); - }); - }); -}); diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/rows.js b/src/plugins/vis_type_table/public/legacy/paginated_table/rows.js deleted file mode 100644 index d06e9e3bd870e..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/rows.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import $ from 'jquery'; -import _ from 'lodash'; -import angular from 'angular'; -import tableCellFilterHtml from './table_cell_filter.html'; - -export function KbnRows($compile) { - return { - restrict: 'A', - link: function ($scope, $el, attr) { - function addCell($tr, contents, column, row) { - function createCell() { - return $(document.createElement('td')); - } - - function createFilterableCell(value) { - const $template = $(tableCellFilterHtml); - $template.addClass('kbnTableCellFilter__hover'); - - const scope = $scope.$new(); - - scope.onFilterClick = (event, negate) => { - // Don't add filter if a link was clicked. - if ($(event.target).is('a')) { - return; - } - - $scope.filter({ - name: 'filterBucket', - data: { - data: [ - { - table: $scope.table, - row: $scope.rows.findIndex((r) => r === row), - column: $scope.table.columns.findIndex((c) => c.id === column.id), - value, - }, - ], - negate, - }, - }); - }; - - return $compile($template)(scope); - } - - let $cell; - let $cellContent; - - const contentsIsDefined = contents !== null && contents !== undefined; - - if (column.filterable && contentsIsDefined) { - $cell = createFilterableCell(contents); - // in jest tests 'angular' is using jqLite. In jqLite the method find lookups only by tags. - // Because of this, we should change a way how we get cell content so that tests will pass. - $cellContent = angular.element($cell[0].querySelector('[data-cell-content]')); - } else { - $cell = $cellContent = createCell(); - } - - // An AggConfigResult can "enrich" cell contents by applying a field formatter, - // which we want to do if possible. - contents = contentsIsDefined ? column.formatter.convert(contents, 'html') : ''; - - if (_.isObject(contents)) { - if (contents.attr) { - $cellContent.attr(contents.attr); - } - - if (contents.class) { - $cellContent.addClass(contents.class); - } - - if (contents.scope) { - $cellContent = $compile($cellContent.prepend(contents.markup))(contents.scope); - } else { - $cellContent.prepend(contents.markup); - } - - if (contents.attr) { - $cellContent.attr(contents.attr); - } - } else { - if (contents === '') { - $cellContent.prepend(' '); - } else { - $cellContent.prepend(contents); - } - } - - $tr.append($cell); - } - - $scope.$watchMulti([attr.kbnRows, attr.kbnRowsMin], function (vals) { - let rows = vals[0]; - const min = vals[1]; - - $el.empty(); - - if (!Array.isArray(rows)) rows = []; - - if (isFinite(min) && rows.length < min) { - // clone the rows so that we can add elements to it without upsetting the original - rows = _.clone(rows); - // crate the empty row which will be pushed into the row list over and over - const emptyRow = {}; - // push as many empty rows into the row array as needed - _.times(min - rows.length, function () { - rows.push(emptyRow); - }); - } - - rows.forEach(function (row) { - const $tr = $(document.createElement('tr')).appendTo($el); - $scope.columns.forEach((column) => { - const value = row[column.id]; - addCell($tr, value, column, row); - }); - }); - }); - }, - }; -} diff --git a/src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html b/src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html deleted file mode 100644 index 57ecb9b221611..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/paginated_table/table_cell_filter.html +++ /dev/null @@ -1,23 +0,0 @@ - -
- - - - - -
- diff --git a/src/plugins/vis_type_table/public/legacy/register_legacy_vis.ts b/src/plugins/vis_type_table/public/legacy/register_legacy_vis.ts deleted file mode 100644 index 447140267a3db..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/register_legacy_vis.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { METRIC_TYPE } from '@kbn/analytics'; -import { PluginInitializerContext, CoreSetup } from 'kibana/public'; - -import { TablePluginSetupDependencies, TablePluginStartDependencies } from '../plugin'; -import { createTableVisLegacyFn } from './table_vis_legacy_fn'; -import { getTableVisLegacyRenderer } from './table_vis_legacy_renderer'; -import { tableVisLegacyTypeDefinition } from './table_vis_legacy_type'; - -export const registerLegacyVis = ( - core: CoreSetup, - { expressions, visualizations, usageCollection }: TablePluginSetupDependencies, - context: PluginInitializerContext -) => { - usageCollection?.reportUiCounter('vis_type_table', METRIC_TYPE.LOADED, 'legacyVisEnabled'); - expressions.registerFunction(createTableVisLegacyFn); - expressions.registerRenderer(getTableVisLegacyRenderer(core, context)); - visualizations.createBaseVisualization(tableVisLegacyTypeDefinition); -}; diff --git a/src/plugins/vis_type_table/public/legacy/table_vis.html b/src/plugins/vis_type_table/public/legacy/table_vis.html deleted file mode 100644 index c469cd250755c..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis.html +++ /dev/null @@ -1,29 +0,0 @@ -
-
-
- - -
-
- -

-

-
-
- -
- - -
-
diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_controller.js b/src/plugins/vis_type_table/public/legacy/table_vis_controller.js deleted file mode 100644 index 038c0947d3ed6..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_controller.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { assign } from 'lodash'; - -export function TableVisController($scope) { - const uiStateSort = $scope.uiState ? $scope.uiState.get('vis.params.sort') : {}; - assign($scope.visParams.sort, uiStateSort); - - $scope.sort = $scope.visParams.sort; - $scope.$watchCollection('sort', function (newSort) { - $scope.uiState.set('vis.params.sort', newSort); - }); - - /** - * Recreate the entire table when: - * - the underlying data changes (esResponse) - * - one of the view options changes (vis.params) - */ - $scope.$watch('renderComplete', function () { - let tableGroups = ($scope.tableGroups = null); - let hasSomeRows = ($scope.hasSomeRows = null); - - if ($scope.esResponse) { - tableGroups = $scope.esResponse; - - hasSomeRows = tableGroups.tables.some(function haveRows(table) { - if (table.tables) return table.tables.some(haveRows); - return table.rows.length > 0; - }); - } - - $scope.hasSomeRows = hasSomeRows; - if (hasSomeRows) { - $scope.dimensions = $scope.visParams.dimensions; - $scope.tableGroups = tableGroups; - } - $scope.renderComplete(); - }); -} diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_controller.test.ts b/src/plugins/vis_type_table/public/legacy/table_vis_controller.test.ts deleted file mode 100644 index e53d4e879bb3b..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_controller.test.ts +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import angular, { ICompileService, IRootScopeService, IScope } from 'angular'; -import 'angular-mocks'; -import 'angular-sanitize'; -import $ from 'jquery'; - -import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './table_vis_legacy_module'; -import { initAngularBootstrap } from '../../../kibana_legacy/public/angular_bootstrap'; -import { tableVisLegacyTypeDefinition } from './table_vis_legacy_type'; -import { Vis } from '../../../visualizations/public'; -import { createStubIndexPattern, stubFieldSpecMap } from '../../../data/public/stubs'; -import { tableVisLegacyResponseHandler } from './table_vis_legacy_response_handler'; -import { coreMock } from '../../../../core/public/mocks'; -import { IAggConfig, IndexPattern, search } from '../../../data/public'; -import { searchServiceMock } from '../../../data/public/search/mocks'; - -const { createAggConfigs } = searchServiceMock.createStartContract().aggs; - -const { tabifyAggResponse } = search; - -interface TableVisScope extends IScope { - [key: string]: any; -} - -const oneRangeBucket = { - hits: { - total: 6039, - max_score: 0, - hits: [], - }, - aggregations: { - agg_2: { - buckets: { - '0.0-1000.0': { - from: 0, - from_as_string: '0.0', - to: 1000, - to_as_string: '1000.0', - doc_count: 606, - }, - '1000.0-2000.0': { - from: 1000, - from_as_string: '1000.0', - to: 2000, - to_as_string: '2000.0', - doc_count: 298, - }, - }, - }, - }, -}; - -describe('Table Vis - Controller', () => { - let $rootScope: IRootScopeService & { [key: string]: any }; - let $compile: ICompileService; - let $scope: TableVisScope; - let $el: JQuery; - let tableAggResponse: any; - let tabifiedResponse: any; - let stubIndexPattern: IndexPattern; - - const initLocalAngular = () => { - const tableVisModule = getAngularModule( - 'kibana/table_vis', - coreMock.createStart(), - coreMock.createPluginInitializerContext() - ); - initTableVisLegacyModule(tableVisModule); - }; - - beforeAll(async () => { - await initAngularBootstrap(); - }); - beforeEach(initLocalAngular); - beforeEach(angular.mock.module('kibana/table_vis')); - - beforeEach( - angular.mock.inject((_$rootScope_: IRootScopeService, _$compile_: ICompileService) => { - $rootScope = _$rootScope_; - $compile = _$compile_; - tableAggResponse = tableVisLegacyResponseHandler; - }) - ); - - beforeEach(() => { - stubIndexPattern = createStubIndexPattern({ - spec: { - id: 'logstash-*', - title: 'logstash-*', - timeFieldName: 'time', - fields: stubFieldSpecMap, - }, - }); - }); - - function getRangeVis(params?: object) { - return ({ - type: tableVisLegacyTypeDefinition, - params: Object.assign({}, tableVisLegacyTypeDefinition.visConfig?.defaults, params), - data: { - aggs: createAggConfigs(stubIndexPattern, [ - { type: 'count', schema: 'metric' }, - { - type: 'range', - schema: 'bucket', - params: { - field: 'bytes', - ranges: [ - { from: 0, to: 1000 }, - { from: 1000, to: 2000 }, - ], - }, - }, - ]), - }, - } as unknown) as Vis; - } - - const dimensions = { - buckets: [ - { - accessor: 0, - }, - ], - metrics: [ - { - accessor: 1, - format: { id: 'range' }, - }, - ], - }; - - // basically a parameterized beforeEach - function initController(vis: Vis) { - vis.data.aggs!.aggs.forEach((agg: IAggConfig, i: number) => { - agg.id = 'agg_' + (i + 1); - }); - - tabifiedResponse = tabifyAggResponse(vis.data.aggs!, oneRangeBucket); - $rootScope.vis = vis; - $rootScope.visParams = vis.params; - $rootScope.uiState = { - get: jest.fn(), - set: jest.fn(), - }; - $rootScope.renderComplete = () => {}; - $rootScope.newScope = (scope: TableVisScope) => { - $scope = scope; - }; - - $el = $('
') - .attr('ng-controller', 'KbnTableVisController') - .attr('ng-init', 'newScope(this)'); - - $compile($el)($rootScope); - } - - // put a response into the controller - function attachEsResponseToScope(resp: object) { - $rootScope.esResponse = resp; - $rootScope.$apply(); - } - - // remove the response from the controller - function removeEsResponseFromScope() { - delete $rootScope.esResponse; - $rootScope.renderComplete = () => {}; - $rootScope.$apply(); - } - - test('exposes #tableGroups and #hasSomeRows when a response is attached to scope', async () => { - const vis: Vis = getRangeVis(); - initController(vis); - - expect(!$scope.tableGroups).toBeTruthy(); - expect(!$scope.hasSomeRows).toBeTruthy(); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).toBeTruthy(); - expect($scope.tableGroups.tables).toBeDefined(); - expect($scope.tableGroups.tables.length).toBe(1); - expect($scope.tableGroups.tables[0].columns.length).toBe(2); - expect($scope.tableGroups.tables[0].rows.length).toBe(2); - }); - - test('clears #tableGroups and #hasSomeRows when the response is removed', async () => { - const vis = getRangeVis(); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - removeEsResponseFromScope(); - - expect(!$scope.hasSomeRows).toBeTruthy(); - expect(!$scope.tableGroups).toBeTruthy(); - }); - - test('sets the sort on the scope when it is passed as a vis param', async () => { - const sortObj = { - columnIndex: 1, - direction: 'asc', - }; - const vis = getRangeVis({ sort: sortObj }); - initController(vis); - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.sort.columnIndex).toEqual(sortObj.columnIndex); - expect($scope.sort.direction).toEqual(sortObj.direction); - }); - - test('sets #hasSomeRows properly if the table group is empty', async () => { - const vis = getRangeVis(); - initController(vis); - - tabifiedResponse.rows = []; - - attachEsResponseToScope(await tableAggResponse(tabifiedResponse, dimensions)); - - expect($scope.hasSomeRows).toBeFalsy(); - expect(!$scope.tableGroups).toBeTruthy(); - }); - - test('passes partialRows:true to tabify based on the vis params', () => { - const vis = getRangeVis({ showPartialRows: true }); - initController(vis); - - expect((vis.type.hierarchicalData as Function)(vis)).toEqual(true); - }); - - test('passes partialRows:false to tabify based on the vis params', () => { - const vis = getRangeVis({ showPartialRows: false }); - initController(vis); - - expect((vis.type.hierarchicalData as Function)(vis)).toEqual(false); - }); -}); diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.test.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.test.ts deleted file mode 100644 index 694edc66914be..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { createTableVisLegacyFn } from './table_vis_legacy_fn'; -import { tableVisLegacyResponseHandler } from './table_vis_legacy_response_handler'; - -import { functionWrapper } from '../../../expressions/common/expression_functions/specs/tests/utils'; - -jest.mock('./table_vis_legacy_response_handler', () => ({ - tableVisLegacyResponseHandler: jest.fn().mockReturnValue({ - tables: [{ columns: [], rows: [] }], - }), -})); - -describe('interpreter/functions#table', () => { - const fn = functionWrapper(createTableVisLegacyFn()); - const context = { - type: 'datatable', - rows: [{ 'col-0-1': 0 }], - columns: [{ id: 'col-0-1', name: 'Count' }], - }; - const visConfig = { - title: 'My Chart title', - perPage: 10, - showPartialRows: false, - showMetricsAtAllLevels: false, - sort: { - columnIndex: null, - direction: null, - }, - showTotal: false, - totalFunc: 'sum', - dimensions: { - metrics: [ - { - accessor: 0, - format: { - id: 'number', - }, - params: {}, - aggType: 'count', - }, - ], - buckets: [], - }, - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('returns an object with the correct structure', async () => { - const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined); - expect(actual).toMatchSnapshot(); - }); - - it('calls response handler with correct values', async () => { - await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined); - expect(tableVisLegacyResponseHandler).toHaveBeenCalledTimes(1); - expect(tableVisLegacyResponseHandler).toHaveBeenCalledWith(context, visConfig.dimensions); - }); -}); diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.ts deleted file mode 100644 index 01f0e45ec9c26..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_fn.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { ExpressionFunctionDefinition, Datatable, Render } from 'src/plugins/expressions/public'; -import { tableVisLegacyResponseHandler, TableContext } from './table_vis_legacy_response_handler'; -import { TableVisConfig } from '../types'; -import { VIS_TYPE_TABLE } from '../../common'; - -export type Input = Datatable; - -interface Arguments { - visConfig: string | null; -} - -export interface TableVisRenderValue { - visData: TableContext; - visType: typeof VIS_TYPE_TABLE; - visConfig: TableVisConfig; -} - -export type TableExpressionFunctionDefinition = ExpressionFunctionDefinition< - 'kibana_table', - Input, - Arguments, - Render ->; - -export const createTableVisLegacyFn = (): TableExpressionFunctionDefinition => ({ - name: 'kibana_table', - type: 'render', - inputTypes: ['datatable'], - help: i18n.translate('visTypeTable.function.help', { - defaultMessage: 'Table visualization', - }), - args: { - visConfig: { - types: ['string', 'null'], - default: '"{}"', - help: '', - }, - }, - fn(input, args) { - const visConfig = args.visConfig && JSON.parse(args.visConfig); - const convertedData = tableVisLegacyResponseHandler(input, visConfig.dimensions); - - return { - type: 'render', - as: 'table_vis', - value: { - visData: convertedData, - visType: VIS_TYPE_TABLE, - visConfig, - }, - }; - }, -}); diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts deleted file mode 100644 index 59ee876c04278..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_module.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { IModule } from 'angular'; - -// @ts-ignore -import { TableVisController } from './table_vis_controller.js'; -// @ts-ignore -import { KbnAggTable } from './agg_table/agg_table'; -// @ts-ignore -import { KbnAggTableGroup } from './agg_table/agg_table_group'; -// @ts-ignore -import { KbnRows } from './paginated_table/rows'; -// @ts-ignore -import { PaginatedTable } from './paginated_table/paginated_table'; - -/** @internal */ -export const initTableVisLegacyModule = (angularIns: IModule): void => { - angularIns - .controller('KbnTableVisController', TableVisController) - .directive('kbnAggTable', KbnAggTable) - .directive('kbnAggTableGroup', KbnAggTableGroup) - .directive('kbnRows', KbnRows) - .directive('paginatedTable', PaginatedTable); -}; diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx deleted file mode 100644 index bab973209c28c..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_renderer.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CoreSetup, PluginInitializerContext } from 'kibana/public'; -import { ExpressionRenderDefinition } from 'src/plugins/expressions'; -import { TablePluginStartDependencies } from '../plugin'; -import { TableVisRenderValue } from '../table_vis_fn'; -import { TableVisLegacyController } from './vis_controller'; - -const tableVisRegistry = new Map(); - -export const getTableVisLegacyRenderer: ( - core: CoreSetup, - context: PluginInitializerContext -) => ExpressionRenderDefinition = (core, context) => ({ - name: 'table_vis', - reuseDomNode: true, - render: async (domNode, config, handlers) => { - let registeredController = tableVisRegistry.get(domNode); - - if (!registeredController) { - const { getTableVisualizationControllerClass } = await import('./vis_controller'); - - const Controller = getTableVisualizationControllerClass(core, context); - registeredController = new Controller(domNode); - tableVisRegistry.set(domNode, registeredController); - - handlers.onDestroy(() => { - registeredController?.destroy(); - tableVisRegistry.delete(domNode); - }); - } - - await registeredController.render(config.visData, config.visConfig, handlers); - handlers.done(); - }, -}); diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_response_handler.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_response_handler.ts deleted file mode 100644 index cb40b151eb31a..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_response_handler.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Required } from '@kbn/utility-types'; - -import { SchemaConfig } from 'src/plugins/visualizations/public'; -import { getFormatService } from '../services'; -import { Input } from './table_vis_legacy_fn'; - -interface Dimensions { - buckets: SchemaConfig[]; - metrics: SchemaConfig[]; - splitColumn?: SchemaConfig[]; - splitRow?: SchemaConfig[]; -} - -export interface TableContext { - tables: Array; - direction?: 'row' | 'column'; -} - -export interface TableGroup { - $parent: TableContext; - table: Input; - tables: Table[]; - title: string; - name: string; - key: any; - column: number; - row: number; -} - -export interface Table { - $parent?: TableGroup; - columns: Input['columns']; - rows: Input['rows']; -} - -export function tableVisLegacyResponseHandler(table: Input, dimensions: Dimensions): 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 = getFormatService().deserialize(split[0].format); - const splitColumn = table.columns[splitColumnIndex]; - const splitMap: Record = {}; - let splitIndex = 0; - - table.rows.forEach((row, rowIndex) => { - const splitValue = row[splitColumn.id]; - - if (!splitMap.hasOwnProperty(splitValue)) { - splitMap[splitValue] = splitIndex++; - const tableGroup: Required = { - $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] as TableGroup).tables[0].rows.push(row); - }); - } else { - converted.tables.push({ - columns: table.columns, - rows: table.rows, - }); - } - - return converted; -} diff --git a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts b/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts deleted file mode 100644 index e582f098a5fd5..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/table_vis_legacy_type.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { AggGroupNames } from '../../../data/public'; -import { VisTypeDefinition } from '../../../visualizations/public'; - -import { TableOptions } from '../components/table_vis_options_lazy'; -import { VIS_EVENT_TO_TRIGGER } from '../../../visualizations/public'; -import { TableVisParams, VIS_TYPE_TABLE } from '../../common'; -import { toExpressionAstLegacy } from './to_ast_legacy'; - -export const tableVisLegacyTypeDefinition: VisTypeDefinition = { - name: VIS_TYPE_TABLE, - title: i18n.translate('visTypeTable.tableVisTitle', { - defaultMessage: 'Data table', - }), - icon: 'visTable', - description: i18n.translate('visTypeTable.tableVisDescription', { - defaultMessage: 'Display data in rows and columns.', - }), - getSupportedTriggers: () => { - return [VIS_EVENT_TO_TRIGGER.filter]; - }, - visConfig: { - defaults: { - perPage: 10, - showPartialRows: false, - showMetricsAtAllLevels: false, - sort: { - columnIndex: null, - direction: null, - }, - showTotal: false, - totalFunc: 'sum', - percentageCol: '', - }, - }, - editorConfig: { - optionsTemplate: TableOptions, - schemas: [ - { - group: AggGroupNames.Metrics, - name: 'metric', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.metricTitle', { - defaultMessage: 'Metric', - }), - aggFilter: ['!geo_centroid', '!geo_bounds', '!filtered_metric', '!single_percentile'], - aggSettings: { - top_hits: { - allowStrings: true, - }, - }, - min: 1, - defaults: [{ type: 'count', schema: 'metric' }], - }, - { - group: AggGroupNames.Buckets, - name: 'bucket', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.bucketTitle', { - defaultMessage: 'Split rows', - }), - aggFilter: ['!filter'], - }, - { - group: AggGroupNames.Buckets, - name: 'split', - title: i18n.translate('visTypeTable.tableVisEditorConfig.schemas.splitTitle', { - defaultMessage: 'Split table', - }), - min: 0, - max: 1, - aggFilter: ['!filter'], - }, - ], - }, - toExpressionAst: toExpressionAstLegacy, - hierarchicalData: (vis) => vis.params.showPartialRows || vis.params.showMetricsAtAllLevels, - requiresSearch: true, -}; diff --git a/src/plugins/vis_type_table/public/legacy/to_ast_legacy.ts b/src/plugins/vis_type_table/public/legacy/to_ast_legacy.ts deleted file mode 100644 index b4c8505bbde76..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/to_ast_legacy.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '../../../data/public'; -import { buildExpression, buildExpressionFunction } from '../../../expressions/public'; -import { getVisSchemas, VisToExpressionAst } from '../../../visualizations/public'; -import { TableVisParams } from '../../common'; -import { TableExpressionFunctionDefinition } from './table_vis_legacy_fn'; - -const buildTableVisConfig = ( - schemas: ReturnType, - visParams: TableVisParams -) => { - const metrics = schemas.metric; - const buckets = schemas.bucket || []; - const visConfig = { - dimensions: { - metrics, - buckets, - splitRow: schemas.split_row, - splitColumn: schemas.split_column, - }, - }; - - if (visParams.showPartialRows && !visParams.showMetricsAtAllLevels) { - // Handle case where user wants to see partial rows but not metrics at all levels. - // This requires calculating how many metrics will come back in the tabified response, - // and removing all metrics from the dimensions except the last set. - const metricsPerBucket = metrics.length / buckets.length; - visConfig.dimensions.metrics.splice(0, metricsPerBucket * buckets.length - metricsPerBucket); - } - return visConfig; -}; - -export const toExpressionAstLegacy: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: vis.params.showPartialRows, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - - const schemas = getVisSchemas(vis, params); - - const visConfig = { - ...vis.params, - ...buildTableVisConfig(schemas, vis.params), - title: vis.title, - }; - - const table = buildExpressionFunction('kibana_table', { - visConfig: JSON.stringify(visConfig), - }); - - const ast = buildExpression([esaggs, table]); - - return ast.toAst(); -}; diff --git a/src/plugins/vis_type_table/public/legacy/vis_controller.ts b/src/plugins/vis_type_table/public/legacy/vis_controller.ts deleted file mode 100644 index a9cb22a056913..0000000000000 --- a/src/plugins/vis_type_table/public/legacy/vis_controller.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CoreSetup, PluginInitializerContext } from 'kibana/public'; -import angular, { IModule, auto, IRootScopeService, IScope, ICompileService } from 'angular'; -import $ from 'jquery'; - -import './index.scss'; - -import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; -import { getAngularModule } from './get_inner_angular'; -import { initTableVisLegacyModule } from './table_vis_legacy_module'; -// @ts-ignore -import tableVisTemplate from './table_vis.html'; -import { TablePluginStartDependencies } from '../plugin'; -import { TableVisConfig, TableVisData } from '../types'; - -const innerAngularName = 'kibana/table_vis'; - -export type TableVisLegacyController = InstanceType< - ReturnType ->; - -export function getTableVisualizationControllerClass( - core: CoreSetup, - context: PluginInitializerContext -) { - return class TableVisualizationController { - tableVisModule: IModule | undefined; - injector: auto.IInjectorService | undefined; - el: JQuery; - $rootScope: IRootScopeService | null = null; - $scope: (IScope & { [key: string]: any }) | undefined; - $compile: ICompileService | undefined; - - constructor(domeElement: Element) { - this.el = $(domeElement); - } - - getInjector() { - if (!this.injector) { - const mountpoint = document.createElement('div'); - mountpoint.className = 'visualization'; - this.injector = angular.bootstrap(mountpoint, [innerAngularName]); - this.el.append(mountpoint); - } - - return this.injector; - } - - async initLocalAngular() { - if (!this.tableVisModule) { - const [coreStart, { kibanaLegacy }] = await core.getStartServices(); - await kibanaLegacy.loadAngularBootstrap(); - this.tableVisModule = getAngularModule(innerAngularName, coreStart, context); - initTableVisLegacyModule(this.tableVisModule); - kibanaLegacy.loadFontAwesome(); - } - } - - async render( - esResponse: TableVisData, - visParams: TableVisConfig, - handlers: IInterpreterRenderHandlers - ): Promise { - await this.initLocalAngular(); - - return new Promise(async (resolve, reject) => { - try { - if (!this.$rootScope) { - const $injector = this.getInjector(); - this.$rootScope = $injector.get('$rootScope'); - this.$compile = $injector.get('$compile'); - } - - const updateScope = () => { - if (!this.$scope) { - return; - } - - this.$scope.visState = { - params: visParams, - title: visParams.title, - }; - this.$scope.esResponse = esResponse; - this.$scope.visParams = visParams; - this.$scope.renderComplete = resolve; - this.$scope.renderFailed = reject; - this.$scope.resize = Date.now(); - this.$scope.$apply(); - }; - - if (!this.$scope && this.$compile) { - this.$scope = this.$rootScope.$new(); - this.$scope.uiState = handlers.uiState; - this.$scope.filter = handlers.event; - updateScope(); - this.el.find('div').append(this.$compile(tableVisTemplate)(this.$scope)); - this.$scope.$apply(); - } else { - updateScope(); - } - } catch (error) { - reject(error); - } - }); - } - - destroy() { - if (this.$rootScope) { - this.$rootScope.$destroy(); - this.$rootScope = null; - } - } - }; -} diff --git a/src/plugins/vis_type_table/public/plugin.ts b/src/plugins/vis_type_table/public/plugin.ts index 0a9d477c26691..2ae8b68bba701 100644 --- a/src/plugins/vis_type_table/public/plugin.ts +++ b/src/plugins/vis_type_table/public/plugin.ts @@ -6,18 +6,14 @@ * Side Public License, v 1. */ -import { PluginInitializerContext, CoreSetup, CoreStart, AsyncPlugin } from 'kibana/public'; +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; import { VisualizationsSetup } from '../../visualizations/public'; import { UsageCollectionSetup } from '../../usage_collection/public'; import { DataPublicPluginStart } from '../../data/public'; import { setFormatService } from './services'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; - -interface ClientConfigType { - legacyVisEnabled: boolean; -} +import { registerTableVis } from './register_vis'; /** @internal */ export interface TablePluginSetupDependencies { @@ -29,31 +25,13 @@ export interface TablePluginSetupDependencies { /** @internal */ export interface TablePluginStartDependencies { data: DataPublicPluginStart; - kibanaLegacy: KibanaLegacyStart; } /** @internal */ export class TableVisPlugin - implements AsyncPlugin { - initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this.initializerContext = initializerContext; - } - - public async setup( - core: CoreSetup, - deps: TablePluginSetupDependencies - ) { - const { legacyVisEnabled } = this.initializerContext.config.get(); - - if (legacyVisEnabled) { - const { registerLegacyVis } = await import('./legacy'); - registerLegacyVis(core, deps, this.initializerContext); - } else { - const { registerTableVis } = await import('./register_vis'); - registerTableVis(core, deps, this.initializerContext); - } + implements Plugin { + public setup(core: CoreSetup, deps: TablePluginSetupDependencies) { + registerTableVis(core, deps); } public start(core: CoreStart, { data }: TablePluginStartDependencies) { diff --git a/src/plugins/vis_type_table/public/register_vis.ts b/src/plugins/vis_type_table/public/register_vis.ts index cf15203b04864..b80dccccaff0a 100644 --- a/src/plugins/vis_type_table/public/register_vis.ts +++ b/src/plugins/vis_type_table/public/register_vis.ts @@ -6,8 +6,7 @@ * Side Public License, v 1. */ -import { PluginInitializerContext, CoreSetup } from 'kibana/public'; - +import { CoreSetup } from 'kibana/public'; import { TablePluginSetupDependencies, TablePluginStartDependencies } from './plugin'; import { createTableVisFn } from './table_vis_fn'; import { getTableVisRenderer } from './table_vis_renderer'; @@ -15,8 +14,7 @@ import { tableVisTypeDefinition } from './table_vis_type'; export const registerTableVis = async ( core: CoreSetup, - { expressions, visualizations }: TablePluginSetupDependencies, - context: PluginInitializerContext + { expressions, visualizations }: TablePluginSetupDependencies ) => { const [coreStart] = await core.getStartServices(); expressions.registerFunction(createTableVisFn); diff --git a/src/plugins/vis_type_table/server/index.ts b/src/plugins/vis_type_table/server/index.ts index b3b20c22aaf52..b98fdd9c445db 100644 --- a/src/plugins/vis_type_table/server/index.ts +++ b/src/plugins/vis_type_table/server/index.ts @@ -13,9 +13,6 @@ import { configSchema, ConfigSchema } from '../config'; import { registerVisTypeTableUsageCollector } from './usage_collector'; export const config: PluginConfigDescriptor = { - exposeToBrowser: { - legacyVisEnabled: true, - }, schema: configSchema, deprecations: ({ renameFromRoot }) => [ renameFromRoot('table_vis.enabled', 'vis_type_table.enabled'), diff --git a/test/functional/apps/visualize/legacy/_data_table.ts b/test/functional/apps/visualize/legacy/_data_table.ts deleted file mode 100644 index 6613e3d13a31b..0000000000000 --- a/test/functional/apps/visualize/legacy/_data_table.ts +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from 'test/functional/ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const log = getService('log'); - const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects([ - 'visualize', - 'timePicker', - 'visEditor', - 'visChart', - 'legacyDataTableVis', - ]); - - describe('legacy data table visualization', function indexPatternCreation() { - before(async function () { - await PageObjects.visualize.initTests(); - log.debug('navigateToApp visualize'); - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - log.debug('clickDataTable'); - await PageObjects.visualize.clickDataTable(); - log.debug('clickNewSearch'); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - log.debug('Bucket = Split rows'); - await PageObjects.visEditor.clickBucket('Split rows'); - log.debug('Aggregation = Histogram'); - await PageObjects.visEditor.selectAggregation('Histogram'); - log.debug('Field = bytes'); - await PageObjects.visEditor.selectField('bytes'); - log.debug('Interval = 2000'); - await PageObjects.visEditor.setInterval('2000', { type: 'numeric' }); - await PageObjects.visEditor.clickGo(); - }); - - it('should show percentage columns', async () => { - async function expectValidTableData() { - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['≥ 0B and < 1,000B', '1,351', '64.703%'], - ['≥ 1,000B and < 1.953KB', '737', '35.297%'], - ]); - } - - // load a plain table - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - await PageObjects.visualize.clickDataTable(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Range'); - await PageObjects.visEditor.selectField('bytes'); - await PageObjects.visEditor.clickGo(); - await PageObjects.visEditor.clickOptionsTab(); - await PageObjects.visEditor.setSelectByOptionText( - 'datatableVisualizationPercentageCol', - 'Count' - ); - await PageObjects.visEditor.clickGo(); - - await expectValidTableData(); - - // check that it works after selecting a column that's deleted - await PageObjects.visEditor.clickDataTab(); - await PageObjects.visEditor.clickBucket('Metric', 'metrics'); - await PageObjects.visEditor.selectAggregation('Average', 'metrics'); - await PageObjects.visEditor.selectField('bytes', 'metrics'); - await PageObjects.visEditor.removeDimension(1); - await PageObjects.visEditor.clickGo(); - await PageObjects.visEditor.clickOptionsTab(); - - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['≥ 0B and < 1,000B', '344.094B'], - ['≥ 1,000B and < 1.953KB', '1.697KB'], - ]); - }); - - it('should show correct data for a data table with date histogram', async () => { - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - await PageObjects.visualize.clickDataTable(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Date Histogram'); - await PageObjects.visEditor.selectField('@timestamp'); - await PageObjects.visEditor.setInterval('Day'); - await PageObjects.visEditor.clickGo(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['2015-09-20', '4,757'], - ['2015-09-21', '4,614'], - ['2015-09-22', '4,633'], - ]); - }); - - describe('otherBucket', () => { - before(async () => { - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - await PageObjects.visualize.clickDataTable(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('extension.raw'); - await PageObjects.visEditor.setSize(2); - await PageObjects.visEditor.clickGo(); - - await PageObjects.visEditor.toggleOtherBucket(); - await PageObjects.visEditor.toggleMissingBucket(); - await PageObjects.visEditor.clickGo(); - }); - - it('should show correct data', async () => { - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['jpg', '9,109'], - ['css', '2,159'], - ['Other', '2,736'], - ]); - }); - - it('should apply correct filter', async () => { - await PageObjects.legacyDataTableVis.filterOnTableCell(1, 3); - await PageObjects.visChart.waitForVisualizationRenderingStabilized(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['png', '1,373'], - ['gif', '918'], - ['Other', '445'], - ]); - }); - }); - - describe('metricsOnAllLevels', () => { - before(async () => { - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - await PageObjects.visualize.clickDataTable(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('extension.raw'); - await PageObjects.visEditor.setSize(2); - await PageObjects.visEditor.toggleOpenEditor(2, 'false'); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('geo.dest'); - await PageObjects.visEditor.toggleOpenEditor(3, 'false'); - await PageObjects.visEditor.clickGo(); - }); - - it('should show correct data without showMetricsAtAllLevels', async () => { - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['jpg', 'CN', '1,718'], - ['jpg', 'IN', '1,511'], - ['jpg', 'US', '770'], - ['jpg', 'ID', '314'], - ['jpg', 'PK', '244'], - ['css', 'CN', '422'], - ['css', 'IN', '346'], - ['css', 'US', '189'], - ['css', 'ID', '68'], - ['css', 'BR', '58'], - ]); - }); - - it('should show correct data without showMetricsAtAllLevels even if showPartialRows is selected', async () => { - await PageObjects.visEditor.clickOptionsTab(); - await testSubjects.setCheckbox('showPartialRows', 'check'); - await PageObjects.visEditor.clickGo(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['jpg', 'CN', '1,718'], - ['jpg', 'IN', '1,511'], - ['jpg', 'US', '770'], - ['jpg', 'ID', '314'], - ['jpg', 'PK', '244'], - ['css', 'CN', '422'], - ['css', 'IN', '346'], - ['css', 'US', '189'], - ['css', 'ID', '68'], - ['css', 'BR', '58'], - ]); - }); - - it('should show metrics on each level', async () => { - await PageObjects.visEditor.clickOptionsTab(); - await testSubjects.setCheckbox('showMetricsAtAllLevels', 'check'); - await PageObjects.visEditor.clickGo(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['jpg', '9,109', 'CN', '1,718'], - ['jpg', '9,109', 'IN', '1,511'], - ['jpg', '9,109', 'US', '770'], - ['jpg', '9,109', 'ID', '314'], - ['jpg', '9,109', 'PK', '244'], - ['css', '2,159', 'CN', '422'], - ['css', '2,159', 'IN', '346'], - ['css', '2,159', 'US', '189'], - ['css', '2,159', 'ID', '68'], - ['css', '2,159', 'BR', '58'], - ]); - }); - - it('should show metrics other than count on each level', async () => { - await PageObjects.visEditor.clickDataTab(); - await PageObjects.visEditor.clickBucket('Metric', 'metrics'); - await PageObjects.visEditor.selectAggregation('Average', 'metrics'); - await PageObjects.visEditor.selectField('bytes', 'metrics'); - await PageObjects.visEditor.clickGo(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - ['jpg', '9,109', '5.469KB', 'CN', '1,718', '5.477KB'], - ['jpg', '9,109', '5.469KB', 'IN', '1,511', '5.456KB'], - ['jpg', '9,109', '5.469KB', 'US', '770', '5.371KB'], - ['jpg', '9,109', '5.469KB', 'ID', '314', '5.424KB'], - ['jpg', '9,109', '5.469KB', 'PK', '244', '5.41KB'], - ['css', '2,159', '5.566KB', 'CN', '422', '5.712KB'], - ['css', '2,159', '5.566KB', 'IN', '346', '5.754KB'], - ['css', '2,159', '5.566KB', 'US', '189', '5.333KB'], - ['css', '2,159', '5.566KB', 'ID', '68', '4.82KB'], - ['css', '2,159', '5.566KB', 'BR', '58', '5.915KB'], - ]); - }); - }); - - describe('split tables', () => { - before(async () => { - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - await PageObjects.visualize.clickDataTable(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - await PageObjects.visEditor.clickBucket('Split table'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('extension.raw'); - await PageObjects.visEditor.setSize(2); - await PageObjects.visEditor.toggleOpenEditor(2, 'false'); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('geo.dest'); - await PageObjects.visEditor.setSize(3, 3); - await PageObjects.visEditor.toggleOpenEditor(3, 'false'); - await PageObjects.visEditor.clickBucket('Split rows'); - await PageObjects.visEditor.selectAggregation('Terms'); - await PageObjects.visEditor.selectField('geo.src'); - await PageObjects.visEditor.setSize(3, 4); - await PageObjects.visEditor.toggleOpenEditor(4, 'false'); - await PageObjects.visEditor.clickGo(); - }); - - it('should have a splitted table', async () => { - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - [ - ['CN', 'CN', '330'], - ['CN', 'IN', '274'], - ['CN', 'US', '140'], - ['IN', 'CN', '286'], - ['IN', 'IN', '281'], - ['IN', 'US', '133'], - ['US', 'CN', '135'], - ['US', 'IN', '134'], - ['US', 'US', '52'], - ], - [ - ['CN', 'CN', '90'], - ['CN', 'IN', '84'], - ['CN', 'US', '27'], - ['IN', 'CN', '69'], - ['IN', 'IN', '58'], - ['IN', 'US', '34'], - ['US', 'IN', '36'], - ['US', 'CN', '29'], - ['US', 'US', '13'], - ], - ]); - }); - - it('should show metrics for split bucket when using showMetricsAtAllLevels', async () => { - await PageObjects.visEditor.clickOptionsTab(); - await testSubjects.setCheckbox('showMetricsAtAllLevels', 'check'); - await PageObjects.visEditor.clickGo(); - const data = await PageObjects.legacyDataTableVis.getTableVisContent(); - expect(data).to.be.eql([ - [ - ['CN', '1,718', 'CN', '330'], - ['CN', '1,718', 'IN', '274'], - ['CN', '1,718', 'US', '140'], - ['IN', '1,511', 'CN', '286'], - ['IN', '1,511', 'IN', '281'], - ['IN', '1,511', 'US', '133'], - ['US', '770', 'CN', '135'], - ['US', '770', 'IN', '134'], - ['US', '770', 'US', '52'], - ], - [ - ['CN', '422', 'CN', '90'], - ['CN', '422', 'IN', '84'], - ['CN', '422', 'US', '27'], - ['IN', '346', 'CN', '69'], - ['IN', '346', 'IN', '58'], - ['IN', '346', 'US', '34'], - ['US', '189', 'IN', '36'], - ['US', '189', 'CN', '29'], - ['US', '189', 'US', '13'], - ], - ]); - }); - }); - }); -} diff --git a/test/functional/apps/visualize/legacy/index.ts b/test/functional/apps/visualize/legacy/index.ts deleted file mode 100644 index 37cf8a5950592..0000000000000 --- a/test/functional/apps/visualize/legacy/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { FORMATS_UI_SETTINGS } from '../../../../../src/plugins/field_formats/common'; - -export default function ({ getPageObjects, getService, loadTestFile }: FtrProviderContext) { - const browser = getService('browser'); - const log = getService('log'); - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects(['visualize']); - - describe('visualize with legacy visualizations', () => { - before(async () => { - await PageObjects.visualize.initTests(); - log.debug('Starting visualize legacy before method'); - await browser.setWindowSize(1280, 800); - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); - await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/visualize.json'); - await kibanaServer.uiSettings.replace({ - defaultIndex: 'logstash-*', - [FORMATS_UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0,0.[000]b', - }); - }); - - describe('legacy data table visualization', function () { - this.tags('ciGroup9'); - - loadTestFile(require.resolve('./_data_table')); - }); - }); -} diff --git a/test/functional/config.legacy.ts b/test/functional/config.legacy.ts deleted file mode 100644 index d38f30a32ef61..0000000000000 --- a/test/functional/config.legacy.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrConfigProviderContext } from '@kbn/test'; - -// eslint-disable-next-line import/no-default-export -export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const defaultConfig = await readConfigFile(require.resolve('./config')); - - return { - ...defaultConfig.getAll(), - - testFiles: [require.resolve('./apps/visualize/legacy')], - - kbnTestServer: { - ...defaultConfig.get('kbnTestServer'), - serverArgs: [ - ...defaultConfig.get('kbnTestServer.serverArgs'), - '--vis_type_table.legacyVisEnabled=true', - ], - }, - }; -} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 61e89e8b37161..a8e690c69c951 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -5023,12 +5023,7 @@ "visTypePie.pie.splitTitle": "チャートを分割", "visTypePie.valuesFormats.percent": "割合を表示", "visTypePie.valuesFormats.value": "値を表示", - "visTypeTable.aggTable.exportLabel": "エクスポート:", - "visTypeTable.aggTable.formattedLabel": "フォーマット済み", - "visTypeTable.aggTable.rawLabel": "未加工", "visTypeTable.defaultAriaLabel": "データ表ビジュアライゼーション", - "visTypeTable.directives.tableCellFilter.filterForValueTooltip": "値でフィルター", - "visTypeTable.directives.tableCellFilter.filterOutValueTooltip": "値を除外", "visTypeTable.function.adimension.buckets": "バケット", "visTypeTable.function.args.bucketsHelpText": "バケットディメンション構成", "visTypeTable.function.args.metricsHelpText": "メトリックディメンション構成", @@ -5076,7 +5071,6 @@ "visTypeTable.vis.controls.exportButtonLabel": "エクスポート", "visTypeTable.vis.controls.formattedCSVButtonLabel": "フォーマット済み", "visTypeTable.vis.controls.rawCSVButtonLabel": "未加工", - "visTypeTable.vis.noResultsFoundTitle": "結果が見つかりませんでした", "visTypeTagCloud.orientations.multipleText": "複数", "visTypeTagCloud.orientations.rightAngledText": "直角", "visTypeTagCloud.orientations.singleText": "単一", @@ -26901,4 +26895,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a9859b8618efd..822e172138abb 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -5068,12 +5068,7 @@ "visTypePie.pie.splitTitle": "拆分图表", "visTypePie.valuesFormats.percent": "显示百分比", "visTypePie.valuesFormats.value": "显示值", - "visTypeTable.aggTable.exportLabel": "导出:", - "visTypeTable.aggTable.formattedLabel": "格式化", - "visTypeTable.aggTable.rawLabel": "原始", "visTypeTable.defaultAriaLabel": "数据表可视化", - "visTypeTable.directives.tableCellFilter.filterForValueTooltip": "筛留值", - "visTypeTable.directives.tableCellFilter.filterOutValueTooltip": "筛除值", "visTypeTable.function.adimension.buckets": "存储桶", "visTypeTable.function.args.bucketsHelpText": "存储桶维度配置", "visTypeTable.function.args.metricsHelpText": "指标维度配置", @@ -5121,7 +5116,6 @@ "visTypeTable.vis.controls.exportButtonLabel": "导出", "visTypeTable.vis.controls.formattedCSVButtonLabel": "格式化", "visTypeTable.vis.controls.rawCSVButtonLabel": "原始", - "visTypeTable.vis.noResultsFoundTitle": "找不到结果", "visTypeTagCloud.orientations.multipleText": "多个", "visTypeTagCloud.orientations.rightAngledText": "直角", "visTypeTagCloud.orientations.singleText": "单个", @@ -27347,4 +27341,4 @@ "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} +} \ No newline at end of file