From 81e7d483a75318fe7cf46cb6598a6891cd7f5fe0 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Thu, 25 Jul 2019 16:06:51 +0200 Subject: [PATCH] De-angularize discover kbnTableHeader (#41259) * Add TableHeader + TableHeaderColumn react components * Migration of kbnTableHeader to use react component * Disable mocha tests * Add jest tests --- .../doc_table/__tests__/lib/rows_headers.js | 152 ----------- .../doc_table/components/_table_header.scss | 4 +- .../doc_table/components/table_header.html | 79 ------ .../doc_table/components/table_header.js | 136 +--------- .../__snapshots__/table_header.test.tsx.snap | 236 ++++++++++++++++++ .../components/table_header/helpers.tsx | 81 ++++++ .../table_header/table_header.test.tsx | 203 +++++++++++++++ .../components/table_header/table_header.tsx | 67 +++++ .../table_header/table_header_column.tsx | 154 ++++++++++++ .../public/index_patterns/_index_pattern.d.ts | 2 + .../public/index_patterns/_index_pattern.js | 5 + src/test_utils/public/stub_index_pattern.js | 1 + .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 14 files changed, 763 insertions(+), 361 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.html create mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap create mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/helpers.tsx create mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.test.tsx create mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header.tsx create mode 100644 src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/table_header_column.tsx diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js b/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js index b2660facf7a5aa..1081528e2566ff 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js +++ b/src/legacy/core_plugins/kibana/public/discover/doc_table/__tests__/lib/rows_headers.js @@ -27,9 +27,6 @@ import $ from 'jquery'; import 'plugins/kibana/discover/index'; import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern'; -const SORTABLE_FIELDS = ['bytes', '@timestamp']; -const UNSORTABLE_FIELDS = ['request_body']; - describe('Doc Table', function () { let $parentScope; let $scope; @@ -119,155 +116,6 @@ describe('Doc Table', function () { }); }; - describe('kbnTableHeader', function () { - const $elem = angular.element(` - - `); - - beforeEach(function () { - init($elem, { - columns: [], - sortOrder: [], - onChangeSortOrder: sinon.stub(), - moveColumn: sinon.spy(), - removeColumn: sinon.spy(), - }); - }); - - afterEach(function () { - destroy(); - }); - - describe('adding and removing columns', function () { - columnTests('[data-test-subj~="docTableHeaderField"]', $elem); - }); - - describe('sorting button', function () { - beforeEach(function () { - $parentScope.columns = ['bytes', '_source']; - $elem.scope().$digest(); - }); - - it('should show for sortable columns', function () { - expect($elem.find(`[data-test-subj="docTableHeaderFieldSort_bytes"]`).length).to.be(1); - }); - - it('should not be shown for unsortable columns', function () { - expect($elem.find(`[data-test-subj="docTableHeaderFieldSort__source"]`).length).to.be(0); - }); - }); - - describe('cycleSortOrder function', function () { - it('should exist', function () { - expect($scope.cycleSortOrder).to.be.a(Function); - }); - - it('should call onChangeSortOrder with ascending order for a sortable field without sort order', function () { - $scope.sortOrder = []; - $scope.cycleSortOrder(SORTABLE_FIELDS[0]); - expect($scope.onChangeSortOrder.callCount).to.be(1); - expect($scope.onChangeSortOrder.firstCall.args).to.eql([SORTABLE_FIELDS[0], 'asc']); - }); - - it('should call onChangeSortOrder with ascending order for a sortable field already sorted by in descending order', function () { - $scope.sortOrder = [SORTABLE_FIELDS[0], 'desc']; - $scope.cycleSortOrder(SORTABLE_FIELDS[0]); - expect($scope.onChangeSortOrder.callCount).to.be(1); - expect($scope.onChangeSortOrder.firstCall.args).to.eql([SORTABLE_FIELDS[0], 'asc']); - }); - - it('should call onChangeSortOrder with ascending order for a sortable field when already sorted by an different field', function () { - $scope.sortOrder = [SORTABLE_FIELDS[1], 'asc']; - $scope.cycleSortOrder(SORTABLE_FIELDS[0]); - expect($scope.onChangeSortOrder.callCount).to.be(1); - expect($scope.onChangeSortOrder.firstCall.args).to.eql([SORTABLE_FIELDS[0], 'asc']); - }); - - it('should call onChangeSortOrder with descending order for a sortable field already sorted by in ascending order', function () { - $scope.sortOrder = [SORTABLE_FIELDS[0], 'asc']; - $scope.cycleSortOrder(SORTABLE_FIELDS[0]); - expect($scope.onChangeSortOrder.callCount).to.be(1); - expect($scope.onChangeSortOrder.firstCall.args).to.eql([SORTABLE_FIELDS[0], 'desc']); - }); - - it('should not call onChangeSortOrder for an unsortable field', function () { - $scope.sortOrder = []; - $scope.cycleSortOrder(UNSORTABLE_FIELDS[0]); - expect($scope.onChangeSortOrder.callCount).to.be(0); - }); - - it('should not try to call onChangeSortOrder when it is not defined', function () { - $scope.onChangeSortOrder = undefined; - expect(() => $scope.cycleSortOrder(SORTABLE_FIELDS[0])).to.not.throwException(); - }); - }); - - describe('headerClass function', function () { - it('should exist', function () { - expect($scope.headerClass).to.be.a(Function); - }); - - it('should return list including kbnDocTableHeader__sortChange for a sortable field not currently sorted by', function () { - expect($scope.headerClass(SORTABLE_FIELDS[0])).to.contain('kbnDocTableHeader__sortChange'); - }); - - it('should return undefined for an unsortable field', function () { - expect($scope.headerClass(UNSORTABLE_FIELDS[0])).to.be(undefined); - }); - - it('should return list including fa-sort-up for a sortable field not currently sorted by', function () { - expect($scope.headerClass(SORTABLE_FIELDS[0])).to.contain('fa-sort-up'); - }); - - it('should return list including fa-sort-up for a sortable field currently sorted by in ascending order', function () { - $scope.sortOrder = [SORTABLE_FIELDS[0], 'asc']; - expect($scope.headerClass(SORTABLE_FIELDS[0])).to.contain('fa-sort-up'); - }); - - it('should return list including fa-sort-down for a sortable field currently sorted by in descending order', function () { - $scope.sortOrder = [SORTABLE_FIELDS[0], 'desc']; - expect($scope.headerClass(SORTABLE_FIELDS[0])).to.contain('fa-sort-down'); - }); - }); - - describe('moving columns', function () { - beforeEach(function () { - $parentScope.columns = ['bytes', 'request_body', '@timestamp', 'point']; - $elem.scope().$digest(); - }); - - it('should move columns to the right', function () { - $scope.moveColumnRight('bytes'); - expect($scope.onMoveColumn.callCount).to.be(1); - expect($scope.onMoveColumn.firstCall.args).to.eql(['bytes', 1]); - }); - - it('shouldnt move the last column to the right', function () { - $scope.moveColumnRight('point'); - expect($scope.onMoveColumn.callCount).to.be(0); - }); - - it('should move columns to the left', function () { - $scope.moveColumnLeft('@timestamp'); - expect($scope.onMoveColumn.callCount).to.be(1); - expect($scope.onMoveColumn.firstCall.args).to.eql(['@timestamp', 1]); - }); - - it('shouldnt move the first column to the left', function () { - $scope.moveColumnLeft('bytes'); - expect($scope.onMoveColumn.callCount).to.be(0); - }); - }); - }); - describe('kbnTableRow', function () { const $elem = angular.element( ' - - - - - - - - - - {{getShortDotsName(name)}} - - - - - - - diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.js b/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.js index 60d440b1f957d8..3af22a363e6dbb 100644 --- a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.js +++ b/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header.js @@ -16,133 +16,19 @@ * specific language governing permissions and limitations * under the License. */ - -import _ from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { shortenDottedString } from '../../../../common/utils/shorten_dotted_string'; -import headerHtml from './table_header.html'; +import { wrapInI18nContext } from 'ui/i18n'; import { uiModules } from 'ui/modules'; +import { TableHeader } from './table_header/table_header'; const module = uiModules.get('app/discover'); - -module.directive('kbnTableHeader', function () { - return { - restrict: 'A', - scope: { - columns: '=', - sortOrder: '=', - indexPattern: '=', - onChangeSortOrder: '=?', - onRemoveColumn: '=?', - onMoveColumn: '=?', - }, - template: headerHtml, - controller: function ($scope, config) { - $scope.hideTimeColumn = config.get('doc_table:hideTimeColumn'); - $scope.isShortDots = config.get('shortDots:enable'); - - $scope.getShortDotsName = function getShortDotsName(columnName) { - return $scope.isShortDots ? shortenDottedString(columnName) : columnName; - }; - - $scope.isSortableColumn = function isSortableColumn(columnName) { - return ( - !!$scope.indexPattern - && _.isFunction($scope.onChangeSortOrder) - && _.get($scope, ['indexPattern', 'fields', 'byName', columnName, 'sortable'], false) - ); - }; - - $scope.tooltip = function (column) { - if (!$scope.isSortableColumn(column)) return ''; - const name = $scope.isShortDots ? shortenDottedString(column) : column; - return i18n.translate('kbn.docTable.tableHeader.sortByColumnTooltip', { - defaultMessage: 'Sort by {columnName}', - values: { columnName: name }, - }); - }; - - $scope.canMoveColumnLeft = function canMoveColumn(columnName) { - return ( - _.isFunction($scope.onMoveColumn) - && $scope.columns.indexOf(columnName) > 0 - ); - }; - - $scope.canMoveColumnRight = function canMoveColumn(columnName) { - return ( - _.isFunction($scope.onMoveColumn) - && $scope.columns.indexOf(columnName) < $scope.columns.length - 1 - ); - }; - - $scope.canRemoveColumn = function canRemoveColumn(columnName) { - return ( - _.isFunction($scope.onRemoveColumn) - && (columnName !== '_source' || $scope.columns.length > 1) - ); - }; - - $scope.headerClass = function (column) { - if (!$scope.isSortableColumn(column)) return; - - const sortOrder = $scope.sortOrder; - const defaultClass = ['fa', 'fa-sort-up', 'kbnDocTableHeader__sortChange']; - - if (!sortOrder || column !== sortOrder[0]) return defaultClass; - return ['fa', sortOrder[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down']; - }; - - $scope.moveColumnLeft = function moveLeft(columnName) { - const newIndex = $scope.columns.indexOf(columnName) - 1; - - if (newIndex < 0) { - return; - } - - $scope.onMoveColumn(columnName, newIndex); - }; - - $scope.moveColumnRight = function moveRight(columnName) { - const newIndex = $scope.columns.indexOf(columnName) + 1; - - if (newIndex >= $scope.columns.length) { - return; - } - - $scope.onMoveColumn(columnName, newIndex); - }; - - $scope.cycleSortOrder = function cycleSortOrder(columnName) { - if (!$scope.isSortableColumn(columnName)) { - return; - } - - const [currentColumnName, currentDirection = 'asc'] = $scope.sortOrder; - const newDirection = ( - (columnName === currentColumnName && currentDirection === 'asc') - ? 'desc' - : 'asc' - ); - - $scope.onChangeSortOrder(columnName, newDirection); - }; - - $scope.getAriaLabelForColumn = function getAriaLabelForColumn(name) { - if (!$scope.isSortableColumn(name)) return null; - - const [currentColumnName, currentDirection = 'asc'] = $scope.sortOrder; - if(name === currentColumnName && currentDirection === 'asc') { - return i18n.translate('kbn.docTable.tableHeader.sortByColumnDescendingAriaLabel', { - defaultMessage: 'Sort {columnName} descending', - values: { columnName: name }, - }); - } - return i18n.translate('kbn.docTable.tableHeader.sortByColumnAscendingAriaLabel', { - defaultMessage: 'Sort {columnName} ascending', - values: { columnName: name }, - }); - }; +module.directive('kbnTableHeader', function (reactDirective, config) { + return reactDirective( + wrapInI18nContext(TableHeader), + undefined, + { restrict: 'A' }, + { + hideTimeColumn: config.get('doc_table:hideTimeColumn'), + isShortDots: config.get('shortDots:enable'), } - }; + ); }); diff --git a/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap b/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap new file mode 100644 index 00000000000000..689ec97154a157 --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/discover/doc_table/components/table_header/__snapshots__/table_header.test.tsx.snap @@ -0,0 +1,236 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TableHeader with time column renders correctly 1`] = ` + + + + + Time + +