[i18n] Translate ML - annotations table (#28079)

* Translate annotations table

* Fix test

* Update snapshot

* Fix id names
This commit is contained in:
Nox911 2019-01-09 13:54:20 +03:00 committed by GitHub
parent 90bf43d958
commit f05e8b6bd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 33 deletions

View file

@ -121,6 +121,12 @@ exports[`AnnotationsTable Minimal initialization without props. 1`] = `
color="primary" color="primary"
iconType="iInCircle" iconType="iInCircle"
size="m" size="m"
title="No annotations created for this job" title={
<FormattedMessage
defaultMessage="No annotations created for this job"
id="xpack.ml.annotationsTable.annotationsNotCreatedTitle"
values={Object {}}
/>
}
/> />
`; `;

View file

@ -44,13 +44,22 @@ import { mlTableService } from '../../services/table_service';
import { ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search'; import { ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE } from '../../../common/constants/search';
import { isTimeSeriesViewJob } from '../../../common/util/job_utils'; import { isTimeSeriesViewJob } from '../../../common/util/job_utils';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
/** /**
* Table component for rendering the lists of annotations for an ML job. * Table component for rendering the lists of annotations for an ML job.
*/ */
class AnnotationsTable extends Component { const AnnotationsTable = injectI18n(class AnnotationsTable extends Component {
static propTypes = {
annotations: PropTypes.array,
jobs: PropTypes.array,
isSingleMetricViewerLinkVisible: PropTypes.bool,
isNumberBadgeVisible: PropTypes.bool
};
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -214,7 +223,8 @@ class AnnotationsTable extends Component {
render() { render() {
const { const {
isSingleMetricViewerLinkVisible = true, isSingleMetricViewerLinkVisible = true,
isNumberBadgeVisible = false isNumberBadgeVisible = false,
intl
} = this.props; } = this.props;
if (this.props.annotations === undefined) { if (this.props.annotations === undefined) {
@ -242,13 +252,28 @@ class AnnotationsTable extends Component {
if (annotations.length === 0) { if (annotations.length === 0) {
return ( return (
<EuiCallOut <EuiCallOut
title="No annotations created for this job" title={<FormattedMessage
id="xpack.ml.annotationsTable.annotationsNotCreatedTitle"
defaultMessage="No annotations created for this job"
/>}
iconType="iInCircle" iconType="iInCircle"
> >
{this.state.jobId && isTimeSeriesViewJob(this.getJob(this.state.jobId)) && {this.state.jobId && isTimeSeriesViewJob(this.getJob(this.state.jobId)) &&
<p> <p>
To create an annotation, <FormattedMessage
open the <EuiLink onClick={() => this.openSingleMetricView()}>Single Metric Viewer</EuiLink> id="xpack.ml.annotationsTable.howToCreateAnnotationDescription"
defaultMessage="To create an annotation, open the {linkToSingleMetricView}"
values={{
linkToSingleMetricView: (
<EuiLink onClick={() => this.openSingleMetricView()}>
<FormattedMessage
id="xpack.ml.annotationsTable.howToCreateAnnotationDescription.singleMetricViewerLinkText"
defaultMessage="Single Metric Viewer"
/>
</EuiLink>
)
}}
/>
</p> </p>
} }
</EuiCallOut> </EuiCallOut>
@ -260,45 +285,66 @@ class AnnotationsTable extends Component {
const columns = [ const columns = [
{ {
field: 'annotation', field: 'annotation',
name: 'Annotation', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.annotationColumnName',
defaultMessage: 'Annotation',
}),
sortable: true sortable: true
}, },
{ {
field: 'timestamp', field: 'timestamp',
name: 'From', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.fromColumnName',
defaultMessage: 'From',
}),
dataType: 'date', dataType: 'date',
render: renderDate, render: renderDate,
sortable: true, sortable: true,
}, },
{ {
field: 'end_timestamp', field: 'end_timestamp',
name: 'To', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.toColumnName',
defaultMessage: 'To',
}),
dataType: 'date', dataType: 'date',
render: renderDate, render: renderDate,
sortable: true, sortable: true,
}, },
{ {
field: 'create_time', field: 'create_time',
name: 'Creation date', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.creationDateColumnName',
defaultMessage: 'Creation date',
}),
dataType: 'date', dataType: 'date',
render: renderDate, render: renderDate,
sortable: true, sortable: true,
}, },
{ {
field: 'create_username', field: 'create_username',
name: 'Created by', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.createdByColumnName',
defaultMessage: 'Created by',
}),
sortable: true, sortable: true,
}, },
{ {
field: 'modified_time', field: 'modified_time',
name: 'Last modified date', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.lastModifiedDateColumnName',
defaultMessage: 'Last modified date',
}),
dataType: 'date', dataType: 'date',
render: renderDate, render: renderDate,
sortable: true, sortable: true,
}, },
{ {
field: 'modified_username', field: 'modified_username',
name: 'Last modified by', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.lastModifiedByColumnName',
defaultMessage: 'Last modified by',
}),
sortable: true, sortable: true,
}, },
]; ];
@ -307,7 +353,10 @@ class AnnotationsTable extends Component {
if (jobIds.length > 1) { if (jobIds.length > 1) {
columns.unshift({ columns.unshift({
field: 'job_id', field: 'job_id',
name: 'job ID', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.jobIdColumnName',
defaultMessage: 'job ID',
}),
sortable: true, sortable: true,
}); });
} }
@ -315,7 +364,10 @@ class AnnotationsTable extends Component {
if (isNumberBadgeVisible) { if (isNumberBadgeVisible) {
columns.unshift({ columns.unshift({
field: 'key', field: 'key',
name: 'Label', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.labelColumnName',
defaultMessage: 'Label',
}),
sortable: true, sortable: true,
width: '60px', width: '60px',
render: (key) => { render: (key) => {
@ -332,23 +384,45 @@ class AnnotationsTable extends Component {
columns.push({ columns.push({
align: RIGHT_ALIGNMENT, align: RIGHT_ALIGNMENT,
width: '60px', width: '60px',
name: 'View', name: intl.formatMessage({
id: 'xpack.ml.annotationsTable.viewColumnName',
defaultMessage: 'View',
}),
render: (annotation) => { render: (annotation) => {
const isDrillDownAvailable = isTimeSeriesViewJob(this.getJob(annotation.job_id)); const isDrillDownAvailable = isTimeSeriesViewJob(this.getJob(annotation.job_id));
const openInSingleMetricViewerText = isDrillDownAvailable const openInSingleMetricViewerTooltipText = isDrillDownAvailable ? (
? 'Open in Single Metric Viewer' <FormattedMessage
: 'Job configuration not supported in Single Metric Viewer'; id="xpack.ml.annotationsTable.openInSingleMetricViewerTooltip"
defaultMessage="Open in Single Metric Viewer"
/>
) : (
<FormattedMessage
id="xpack.ml.annotationsTable.jobConfigurationNotSupportedInSingleMetricViewerTooltip"
defaultMessage="Job configuration not supported in Single Metric Viewer"
/>
);
const openInSingleMetricViewerAriaLabelText = isDrillDownAvailable ? (
<FormattedMessage
id="xpack.ml.annotationsTable.openInSingleMetricViewerAriaLabel"
defaultMessage="Open in Single Metric Viewer"
/>
) : (
<FormattedMessage
id="xpack.ml.annotationsTable.jobConfigurationNotSupportedInSingleMetricViewerAriaLabel"
defaultMessage="Job configuration not supported in Single Metric Viewer"
/>
);
return ( return (
<EuiToolTip <EuiToolTip
position="bottom" position="bottom"
content={openInSingleMetricViewerText} content={openInSingleMetricViewerTooltipText}
> >
<EuiButtonIcon <EuiButtonIcon
onClick={() => this.openSingleMetricView(annotation)} onClick={() => this.openSingleMetricView(annotation)}
disabled={!isDrillDownAvailable} disabled={!isDrillDownAvailable}
iconType="stats" iconType="stats"
aria-label={openInSingleMetricViewerText} aria-label={openInSingleMetricViewerAriaLabelText}
/> />
</EuiToolTip> </EuiToolTip>
); );
@ -381,12 +455,6 @@ class AnnotationsTable extends Component {
/> />
); );
} }
} });
AnnotationsTable.propTypes = {
annotations: PropTypes.array,
jobs: PropTypes.array,
isSingleMetricViewerLinkVisible: PropTypes.bool,
isNumberBadgeVisible: PropTypes.bool
};
export { AnnotationsTable }; export { AnnotationsTable };

View file

@ -7,7 +7,7 @@
import jobConfig from '../../../common/types/__mocks__/job_config_farequote'; import jobConfig from '../../../common/types/__mocks__/job_config_farequote';
import mockAnnotations from './__mocks__/mock_annotations.json'; import mockAnnotations from './__mocks__/mock_annotations.json';
import { shallow } from 'enzyme'; import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import React from 'react'; import React from 'react';
import { AnnotationsTable } from './annotations_table'; import { AnnotationsTable } from './annotations_table';
@ -33,17 +33,17 @@ jest.mock('../../services/ml_api_service', () => ({
describe('AnnotationsTable', () => { describe('AnnotationsTable', () => {
test('Minimal initialization without props.', () => { test('Minimal initialization without props.', () => {
const wrapper = shallow(<AnnotationsTable />); const wrapper = shallowWithIntl(<AnnotationsTable.WrappedComponent />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('Initialization with job config prop.', () => { test('Initialization with job config prop.', () => {
const wrapper = shallow(<AnnotationsTable jobs={[jobConfig]} />); const wrapper = shallowWithIntl(<AnnotationsTable.WrappedComponent jobs={[jobConfig]} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('Initialization with annotations prop.', () => { test('Initialization with annotations prop.', () => {
const wrapper = shallow(<AnnotationsTable annotations={mockAnnotations} />); const wrapper = shallowWithIntl(<AnnotationsTable.WrappedComponent annotations={mockAnnotations} />);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });

View file

@ -23,6 +23,8 @@ const module = uiModules.get('apps/ml');
import chrome from 'ui/chrome'; import chrome from 'ui/chrome';
const mlAnnotationsEnabled = chrome.getInjected('mlAnnotationsEnabled', false); const mlAnnotationsEnabled = chrome.getInjected('mlAnnotationsEnabled', false);
import { I18nProvider } from '@kbn/i18n/react';
module.directive('mlAnnotationTable', function () { module.directive('mlAnnotationTable', function () {
function link(scope, element) { function link(scope, element) {
@ -39,7 +41,9 @@ module.directive('mlAnnotationTable', function () {
}; };
ReactDOM.render( ReactDOM.render(
React.createElement(AnnotationsTable, props), <I18nProvider>
{React.createElement(AnnotationsTable, props)}
</I18nProvider>,
element[0] element[0]
); );
} }