From 143e6d7d8b605db0d6ab87d2ff84bc13772f9775 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 17 May 2018 14:28:54 +0200 Subject: [PATCH] [ML] Migrate field-type-icon to EUI/React. (#19159) (#19168) Migrates the field-type-icon directive to use EUI/React. Instead of the angular/bootstrap tooltip attribute on the directive's tag, there's now an option tooltip-enabled which when true wraps the component inside EuiToolTip. --- .../field_data_card/field_data_card.html | 8 +- .../field_type_icon_view.test.js.snap | 32 ++++++ .../field_type_icon/field_type_icon.html | 37 ------- .../field_type_icon_directive.js | 28 ++++-- .../field_type_icon/field_type_icon_view.js | 97 +++++++++++++++++++ .../field_type_icon_view.test.js | 41 ++++++++ 6 files changed, 195 insertions(+), 48 deletions(-) create mode 100644 x-pack/plugins/ml/public/components/field_type_icon/__snapshots__/field_type_icon_view.test.js.snap delete mode 100644 x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html create mode 100644 x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js create mode 100644 x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js diff --git a/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html b/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html index 34c55763ad6e0e..399a29fd001707 100644 --- a/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html +++ b/x-pack/plugins/ml/public/components/field_data_card/field_data_card.html @@ -1,11 +1,9 @@
- + type="card.type" + tooltip-enabled="true" + />
+ + + + +`; + +exports[`FieldTypeIcon render component when type matches a field type 1`] = ` + +`; + +exports[`FieldTypeIcon update component 1`] = ` + +`; diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html deleted file mode 100644 index d60055c38d67e3..00000000000000 --- a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js index 024c751b0e72e3..4fef02f0c8bfd2 100644 --- a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_directive.js @@ -6,8 +6,10 @@ -import template from './field_type_icon.html'; -import { ML_JOB_FIELD_TYPES } from 'plugins/ml/../common/constants/field_types'; +import React from 'react'; +import ReactDOM from 'react-dom'; + +import { FieldTypeIcon } from './field_type_icon_view.js'; import { uiModules } from 'ui/modules'; const module = uiModules.get('apps/ml'); @@ -15,13 +17,27 @@ const module = uiModules.get('apps/ml'); module.directive('mlFieldTypeIcon', function () { return { restrict: 'E', - replace: true, + replace: false, scope: { + tooltipEnabled: '=', type: '=' }, - template, - controller: function ($scope) { - $scope.ML_JOB_FIELD_TYPES = ML_JOB_FIELD_TYPES; + link: function (scope, element) { + scope.$watch('type', updateComponent); + + updateComponent(); + + function updateComponent() { + const props = { + tooltipEnabled: scope.tooltipEnabled, + type: scope.type + }; + + ReactDOM.render( + React.createElement(FieldTypeIcon, props), + element[0] + ); + } } }; }); diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js new file mode 100644 index 00000000000000..89275999e9ff92 --- /dev/null +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.js @@ -0,0 +1,97 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import PropTypes from 'prop-types'; +import React from 'react'; + +import { EuiToolTip } from '@elastic/eui'; + +// don't use something like plugins/ml/../common +// because it won't work with the jest tests +import { ML_JOB_FIELD_TYPES } from '../../../common/constants/field_types'; + +export function FieldTypeIcon({ tooltipEnabled = false, type }) { + let ariaLabel = ''; + let iconClass = ''; + let iconChar = ''; + + switch (type) { + case ML_JOB_FIELD_TYPES.BOOLEAN: + ariaLabel = 'Boolean field'; + iconClass = 'fa-adjust'; + break; + case ML_JOB_FIELD_TYPES.DATE: + ariaLabel = 'Date field'; + iconClass = 'fa-clock-o'; + break; + case ML_JOB_FIELD_TYPES.NUMBER: + ariaLabel = 'Metric field'; + iconChar = '#'; + break; + case ML_JOB_FIELD_TYPES.GEO_POINT: + ariaLabel = 'Geo-point field'; + iconClass = 'fa-globe'; + break; + case ML_JOB_FIELD_TYPES.KEYWORD: + ariaLabel = 'Aggregatable string field'; + iconChar = 't'; + break; + case ML_JOB_FIELD_TYPES.TEXT: + ariaLabel = 'String field'; + iconClass = 'fa-file-text-o'; + break; + case ML_JOB_FIELD_TYPES.IP: + ariaLabel = 'IP address field'; + iconClass = 'fa-laptop'; + break; + default: + // if type doesn't match one of ML_JOB_FIELD_TYPES + // don't render the component at all + return null; + } + + let className = 'field-type-icon'; + if (iconClass !== '') { + className += ' kuiIcon ' + iconClass; + } + + const containerProps = { + ariaLabel, + className, + iconChar + }; + + if (tooltipEnabled === true) { + // wrap the inner component inside because EuiToolTip doesn't seem + // to support having another component directly inside the tooltip anchor + // see https://github.com/elastic/eui/issues/839 + return ( + + + + ); + } + + return ; +} +FieldTypeIcon.propTypes = { + tooltipEnabled: PropTypes.bool, + type: PropTypes.string +}; + +function FieldTypeIconContainer({ ariaLabel, className, iconChar }) { + return ( + + {(iconChar === '') ? ( + + ) : ( + + + + )} + + ); +} diff --git a/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js new file mode 100644 index 00000000000000..0f89deddade19e --- /dev/null +++ b/x-pack/plugins/ml/public/components/field_type_icon/field_type_icon_view.test.js @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { shallow } from 'enzyme'; +import React from 'react'; + +import { FieldTypeIcon } from './field_type_icon_view'; + +describe('FieldTypeIcon', () => { + + test(`don't render component when type is undefined`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + }); + + test(`don't render component when type doesn't match a field type`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + }); + + test(`render component when type matches a field type`, () => { + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + test(`render component inside tooltip wrapper`, () => { + const wrapper = shallow(); + expect(wrapper).toMatchSnapshot(); + }); + + test(`update component`, () => { + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBeTruthy(); + wrapper.setProps({ type: 'keyword' }); + expect(wrapper).toMatchSnapshot(); + }); + +});