translate logstash (#26176) (#26610)

translate logstash
This commit is contained in:
pavel06081991 2018-12-04 15:58:18 +03:00 committed by GitHub
parent 8dc41eb197
commit 197e5b094c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 540 additions and 83 deletions

View file

@ -6,26 +6,42 @@ exports[`PipelinesTable component renders component as expected 1`] = `
Array [
Object {
"field": "id",
"name": "Id",
"name": <FormattedMessage
defaultMessage="Id"
id="xpack.logstash.pipelinesTable.idColumnLabel"
values={Object {}}
/>,
"render": [Function],
"sortable": true,
},
Object {
"field": "description",
"name": "Description",
"name": <FormattedMessage
defaultMessage="Description"
id="xpack.logstash.pipelinesTable.descriptionColumnLabel"
values={Object {}}
/>,
"render": [Function],
"sortable": true,
"truncateText": true,
},
Object {
"field": "lastModifiedHumanized",
"name": "Last Modified",
"name": <FormattedMessage
defaultMessage="Last Modified"
id="xpack.logstash.pipelinesTable.lastModifiedColumnLabel"
values={Object {}}
/>,
"render": [Function],
"sortable": true,
},
Object {
"field": "username",
"name": "Modified By",
"name": <FormattedMessage
defaultMessage="Modified By"
id="xpack.logstash.pipelinesTable.modifiedByColumnLabel"
values={Object {}}
/>,
"render": [Function],
"sortable": true,
},
@ -73,7 +89,11 @@ exports[`PipelinesTable component renders component as expected 1`] = `
Object {
"field": "id",
"multiSelect": false,
"name": "Filter by ID",
"name": <FormattedMessage
defaultMessage="Filter by ID"
id="xpack.logstash.pipelinesTable.filterByIdLabel"
values={Object {}}
/>,
"options": Array [
Object {
"name": "testPipeline",
@ -94,7 +114,11 @@ exports[`PipelinesTable component renders component as expected 1`] = `
onClick={[MockFunction]}
type="button"
>
Create pipeline
<FormattedMessage
defaultMessage="Create pipeline"
id="xpack.logstash.pipelinesTable.createPipelineButtonLabel"
values={Object {}}
/>
</EuiButton>,
}
}

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import pluralize from 'pluralize';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import {
EuiCallOut,
@ -19,7 +19,7 @@ import { InfoAlerts } from './info_alerts';
import { PipelinesTable } from './pipelines_table';
import { ConfirmDeleteModal } from './confirm_delete_modal';
export class PipelineList extends React.Component {
class PipelineListUi extends React.Component {
constructor(props) {
super(props);
@ -50,28 +50,55 @@ export class PipelineList extends React.Component {
getEmptyPrompt = () => (
<EuiEmptyPrompt
title={<h2>No pipelines</h2>}
title={(
<h2>
<FormattedMessage
id="xpack.logstash.pipelineList.noPipelinesTitle"
defaultMessage="No pipelines"
/>
</h2>
)}
titleSize="xs"
body="There are no pipelines defined."
body={(
<FormattedMessage
id="xpack.logstash.pipelineList.noPipelinesDescription"
defaultMessage="There are no pipelines defined."
/>
)}
/>
);
getErrorPrompt = () => (
<EuiEmptyPrompt
title={<h2>Error</h2>}
title={(
<h2>
<FormattedMessage
id="xpack.logstash.pipelineList.pipelinesLoadingErrorTitle"
defaultMessage="Error"
/>
</h2>
)}
titleSize="xs"
body="Error encountered while loading pipelines."
body={(
<FormattedMessage
id="xpack.logstash.pipelineList.pipelinesLoadingErrorDescription"
defaultMessage="Error encountered while loading pipelines."
/>
)}
/>
);
loadPipelines = () => {
const { isReadOnly, licenseService, pipelinesService, toastNotifications } = this.props;
const { isReadOnly, licenseService, pipelinesService, toastNotifications, intl } = this.props;
this.setState({
message: (
<div>
<EuiLoadingSpinner size="m" />
&nbsp; Loading pipelines....
&nbsp; <FormattedMessage
id="xpack.logstash.pipelineList.pipelinesLoadingMessage"
defaultMessage="Loading pipelines…"
/>
</div>
),
});
@ -110,7 +137,12 @@ export class PipelineList extends React.Component {
}
} else {
this.setState({ isForbidden: false });
toastNotifications.addDanger(`Couldn't load pipeline. Error: "${err.statusText}".`);
toastNotifications.addDanger(intl.formatMessage({
id: 'xpack.logstash.pipelineList.pipelineLoadingErrorNotification',
defaultMessage: `Couldn't load pipeline. Error: "{errStatusText}".`
}, {
errStatusText: err.statusText,
}));
}
});
});
@ -133,9 +165,19 @@ export class PipelineList extends React.Component {
<EuiCallOut
color="danger"
iconType="cross"
title="You do not have permission to manage Logstash pipelines."
title={(
<FormattedMessage
id="xpack.logstash.pipelineList.noPermissionToManageTitle"
defaultMessage="You do not have permission to manage Logstash pipelines."
/>
)}
>
<p>Please contact your administrator.</p>
<p>
<FormattedMessage
id="xpack.logstash.pipelineList.noPermissionToManageDescription"
defaultMessage="Please contact your administrator."
/>
</p>
</EuiCallOut>
) : null;
};
@ -158,32 +200,54 @@ export class PipelineList extends React.Component {
deleteSelectedPipelines = () => {
this.hideDeletePipelinesModal();
const { licenseService, pipelinesService, toastNotifications } = this.props;
const { licenseService, pipelinesService, toastNotifications, intl } = this.props;
const { selection } = this.state;
const numPipelinesSelected = selection.length;
const totalPluralized = pluralize('Pipeline', numPipelinesSelected);
const pipelineIds = selection.map(({ id }) => id);
return pipelinesService
.deletePipelines(pipelineIds)
.then(results => {
const { numSuccesses, numErrors } = results;
const errorPluralized = pluralize('Pipeline', numErrors);
if (numSuccesses === 1 && numErrors === 0) {
toastNotifications.addSuccess(`Deleted "${selection[0].id}"`);
toastNotifications.addSuccess(intl.formatMessage({
id: 'xpack.logstash.pipelineList.pipelinesSuccessfullyDeletedNotification',
defaultMessage: 'Deleted "{id}"',
}, {
id: selection[0].id,
}));
} else if (numSuccesses) {
let text;
if (numErrors) {
text = `But ${numErrors} ${errorPluralized} couldn't be deleted.`;
text = intl.formatMessage({
id: 'xpack.logstash.pipelineList.pipelinesCouldNotBeDeletedDescription',
defaultMessage: `But {numErrors, plural, one {# Pipeline} other {# Pipelines}} couldn't be deleted.`,
}, {
numErrors,
});
}
toastNotifications.addSuccess({
title: `Deleted ${numSuccesses} out of ${numPipelinesSelected} ${totalPluralized}`,
title: intl.formatMessage({
id: 'xpack.logstash.pipelineList.successfullyDeletedPipelinesNotification',
defaultMessage:
'Deleted {numSuccesses} out of {numPipelinesSelected, plural, one {# Pipeline} other {# Pipelines}}',
}, {
numSuccesses,
numPipelinesSelected,
numPipelinesSelected,
}),
text,
});
} else if (numErrors) {
toastNotifications.addError(`Failed to delete ${numErrors} ${errorPluralized}`);
toastNotifications.addError(intl.formatMessage({
id: 'xpack.logstash.pipelineList.couldNotDeletePipelinesNotification',
defaultMessage:
'Failed to delete {numErrors, plural, one {# Pipeline} other {# Pipelines}}',
}, {
numErrors,
}));
}
this.loadPipelines();
@ -233,3 +297,5 @@ export class PipelineList extends React.Component {
);
}
}
export const PipelineList = injectI18n(PipelineListUi);

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import { shallow } from 'enzyme';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { PipelineList } from './pipeline_list';
describe('PipelineList component', () => {
@ -54,7 +54,7 @@ describe('PipelineList component', () => {
});
async function renderWithProps() {
const wrapper = shallow(<PipelineList {...props} />);
const wrapper = shallowWithIntl(<PipelineList.WrappedComponent {...props} />);
await Promise.all([wrapper.instance().componentDidMount]);
return wrapper;
}

View file

@ -6,13 +6,19 @@
import React from 'react';
import { EuiButton, EuiButtonEmpty, EuiIconTip, EuiInMemoryTable, EuiLink } from '@elastic/eui';
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import { PIPELINE_LIST } from './constants';
function getColumns(openPipeline, clonePipeline) {
return [
{
field: 'id',
name: 'Id',
name: (
<FormattedMessage
id="xpack.logstash.pipelinesTable.idColumnLabel"
defaultMessage="Id"
/>
),
sortable: true,
render: (id, { isCentrallyManaged }) => {
const openPipelineClicked = () => openPipeline(id);
@ -33,20 +39,35 @@ function getColumns(openPipeline, clonePipeline) {
},
{
field: 'description',
name: 'Description',
name: (
<FormattedMessage
id="xpack.logstash.pipelinesTable.descriptionColumnLabel"
defaultMessage="Description"
/>
),
render: description => <span data-test-subj="cellDescription">{description}</span>,
sortable: true,
truncateText: true,
},
{
field: 'lastModifiedHumanized',
name: 'Last Modified',
name: (
<FormattedMessage
id="xpack.logstash.pipelinesTable.lastModifiedColumnLabel"
defaultMessage="Last Modified"
/>
),
render: lastModified => <span data-test-subj="cellLastModified">{lastModified}</span>,
sortable: true,
},
{
field: 'username',
name: 'Modified By',
name: (
<FormattedMessage
id="xpack.logstash.pipelinesTable.modifiedByColumnLabel"
defaultMessage="Modified By"
/>
),
render: username => <span data-test-subj="cellUsername">{username}</span>,
sortable: true,
},
@ -64,7 +85,10 @@ function getColumns(openPipeline, clonePipeline) {
onClick={cloneClicked}
size="xs"
>
Clone
<FormattedMessage
id="xpack.logstash.pipelinesTable.cloneButtonLabel"
defaultMessage="Clone"
/>
</EuiButtonEmpty>
) : null;
},
@ -74,7 +98,7 @@ function getColumns(openPipeline, clonePipeline) {
];
}
export function PipelinesTable({
function PipelinesTableUi({
clonePipeline,
createPipeline,
isReadOnly,
@ -86,6 +110,7 @@ export function PipelinesTable({
pipelines,
selection,
pageIndex,
intl,
}) {
const pagination = {
pageIndex,
@ -96,7 +121,12 @@ export function PipelinesTable({
const selectableMessage = (selectable, { id }) =>
selectable
? `Select pipeline "${id}"`
? intl.formatMessage({
id: 'xpack.logstash.pipelinesTable.selectablePipelineMessage',
defaultMessage: `Select pipeline "{id}"`
}, {
id,
})
: PIPELINE_LIST.PIPELINE_NOT_CENTRALLY_MANAGED_TOOLTIP_TEXT;
const selectionOptions = isSelectable
@ -116,7 +146,10 @@ export function PipelinesTable({
onClick={onDeleteSelectedPipelines}
data-test-subj="btnDeletePipeline"
>
Delete
<FormattedMessage
id="xpack.logstash.pipelinesTable.deleteButtonLabel"
defaultMessage="Delete"
/>
</EuiButton>
) : null;
@ -126,7 +159,12 @@ export function PipelinesTable({
{
type: 'field_value_selection',
field: 'id',
name: 'Filter by ID',
name: (
<FormattedMessage
id="xpack.logstash.pipelinesTable.filterByIdLabel"
defaultMessage="Filter by ID"
/>
),
multiSelect: false,
options: pipelines.map(({ id }) => {
return {
@ -146,7 +184,10 @@ export function PipelinesTable({
onClick={createPipeline}
data-test-subj="btnAdd"
>
Create pipeline
<FormattedMessage
id="xpack.logstash.pipelinesTable.createPipelineButtonLabel"
defaultMessage="Create pipeline"
/>
</EuiButton>
),
};
@ -168,3 +209,5 @@ export function PipelinesTable({
/>
);
}
export const PipelinesTable = injectI18n(PipelinesTableUi);

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
import { PipelinesTable } from './pipelines_table';
describe('PipelinesTable component', () => {
@ -38,33 +38,33 @@ describe('PipelinesTable component', () => {
});
it('renders component as expected', () => {
const wrapper = shallow(<PipelinesTable {...props} />);
const wrapper = shallowWithIntl(<PipelinesTable.WrappedComponent {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('calls clone when cloned button clicked', () => {
props.pipelines = [{ id: 'testPipeline', isCentrallyManaged: true }];
const wrapper = mount(<PipelinesTable {...props} />);
const wrapper = mountWithIntl(<PipelinesTable.WrappedComponent {...props} />);
wrapper.find('[iconType="copy"]').simulate('click');
expect(clonePipeline).toHaveBeenCalled();
});
it('calls createPipeline on create button clicked', () => {
const wrapper = mount(<PipelinesTable {...props} />);
const wrapper = mountWithIntl(<PipelinesTable.WrappedComponent {...props} />);
wrapper.find('.euiButton--primary').simulate('click');
expect(createPipeline).toHaveBeenCalled();
});
it('calls delete prompt on delete click', () => {
props.selection = [{ id: 'testPipeline' }];
const wrapper = mount(<PipelinesTable {...props} />);
const wrapper = mountWithIntl(<PipelinesTable.WrappedComponent {...props} />);
wrapper.find('.euiButton--danger').simulate('click');
expect(onDeleteSelectedPipelines).toHaveBeenCalled();
});
it('calls openPipeline on id click', () => {
props.pipelines = [{ id: 'testPipeline', isCentrallyManaged: true }];
const wrapper = mount(<PipelinesTable {...props} />);
const wrapper = mountWithIntl(<PipelinesTable.WrappedComponent {...props} />);
wrapper.find('EuiLink').simulate('click');
expect(openPipeline).toHaveBeenCalledWith('testPipeline');
});

View file

@ -2,6 +2,88 @@
exports[`UpgradeFailure component passes expected text for new pipeline 1`] = `
<UpgradeFailure
intl={
Object {
"defaultFormats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
}
isManualUpgrade={true}
isNewPipeline={true}
onClose={[MockFunction]}
@ -282,7 +364,13 @@ exports[`UpgradeFailure component passes expected text for new pipeline 1`] = `
<span
className="euiButtonEmpty__text"
>
Go back
<FormattedMessage
defaultMessage="Go back"
id="xpack.logstash.upgradeFailureActions.goBackButtonLabel"
values={Object {}}
>
Go back
</FormattedMessage>
</span>
</span>
</button>
@ -304,6 +392,88 @@ exports[`UpgradeFailure component passes expected text for new pipeline 1`] = `
exports[`UpgradeFailure component passes expected text for not manual upgrade 1`] = `
<UpgradeFailure
intl={
Object {
"defaultFormats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
}
isManualUpgrade={false}
isNewPipeline={true}
onClose={[MockFunction]}
@ -584,7 +754,13 @@ exports[`UpgradeFailure component passes expected text for not manual upgrade 1`
<span
className="euiButtonEmpty__text"
>
Go back
<FormattedMessage
defaultMessage="Go back"
id="xpack.logstash.upgradeFailureActions.goBackButtonLabel"
values={Object {}}
>
Go back
</FormattedMessage>
</span>
</span>
</button>
@ -606,6 +782,88 @@ exports[`UpgradeFailure component passes expected text for not manual upgrade 1`
exports[`UpgradeFailure component passes expected text for not new pipeline 1`] = `
<UpgradeFailure
intl={
Object {
"defaultFormats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
}
isManualUpgrade={true}
isNewPipeline={false}
onClose={[MockFunction]}
@ -886,7 +1144,13 @@ exports[`UpgradeFailure component passes expected text for not new pipeline 1`]
<span
className="euiButtonEmpty__text"
>
Go back
<FormattedMessage
defaultMessage="Go back"
id="xpack.logstash.upgradeFailureActions.goBackButtonLabel"
values={Object {}}
>
Go back
</FormattedMessage>
</span>
</span>
</button>

View file

@ -34,7 +34,11 @@ exports[`UpgradeFailureActions component renders component as expected 1`] = `
onClick={[MockFunction]}
type="button"
>
Go back
<FormattedMessage
defaultMessage="Go back"
id="xpack.logstash.upgradeFailureActions.goBackButtonLabel"
values={Object {}}
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -4,17 +4,31 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export const UPGRADE_FAILURE = {
TITLE: {
IS_MANUAL_UPGRADE: 'Upgrade failed',
NOT_MANUAL_UPGRADE: 'Time for an upgrade!',
IS_MANUAL_UPGRADE: i18n.translate('xpack.logstash.upgradeFailedTitle', {
defaultMessage: 'Upgrade failed',
}),
NOT_MANUAL_UPGRADE: i18n.translate('xpack.logstash.notManualUpgradeTitle', {
defaultMessage: 'Time for an upgrade!',
}),
},
MESSAGE: {
IS_NEW_PIPELINE: 'Before you can add a pipeline, we need to upgrade your configuration.',
NOT_NEW_PIPELINE: 'Before you can edit this pipeline, we need to upgrade your configuration.',
IS_NEW_PIPELINE: i18n.translate('xpack.logstash.newPipelineMessage', {
defaultMessage: 'Before you can add a pipeline, we need to upgrade your configuration.',
}),
NOT_NEW_PIPELINE: i18n.translate('xpack.logstash.notNewPipelineMessage', {
defaultMessage: 'Before you can edit this pipeline, we need to upgrade your configuration.',
}),
},
UPGRADE_BUTTON_TEXT: {
IS_MANUAL_UPGRADE: 'Try again',
NOT_MANUAL_UPGRADE: 'Upgrade',
IS_MANUAL_UPGRADE: i18n.translate('xpack.logstash.manualUpgradeButtonLabel', {
defaultMessage: 'Try again',
}),
NOT_MANUAL_UPGRADE: i18n.translate('xpack.logstash.notManualUpgradeButtonLabel', {
defaultMessage: 'Upgrade',
}),
},
};

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
import { UpgradeFailure } from './upgrade_failure';
describe('UpgradeFailure component', () => {
@ -26,29 +26,29 @@ describe('UpgradeFailure component', () => {
});
it('renders component as expected', () => {
const wrapper = shallow(<UpgradeFailure {...props} />);
const wrapper = shallowWithIntl(<UpgradeFailure {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('passes expected text for new pipeline', () => {
const wrapper = mount(<UpgradeFailure {...props} />);
const wrapper = mountWithIntl(<UpgradeFailure {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('passes expected text for not new pipeline', () => {
props.isNewPipeline = false;
const wrapper = mount(<UpgradeFailure {...props} />);
const wrapper = mountWithIntl(<UpgradeFailure {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('passes expected text for not manual upgrade', () => {
props.isManualUpgrade = false;
const wrapper = mount(<UpgradeFailure {...props} />);
const wrapper = mountWithIntl(<UpgradeFailure {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('propogates onClose and onRetry functions to child', () => {
const wrapper = mount(<UpgradeFailure {...props} />);
const wrapper = mountWithIntl(<UpgradeFailure {...props} />);
expect(wrapper.find('UpgradeFailureActions').props().onClose).toEqual(onClose);
expect(wrapper.find('UpgradeFailureActions').props().onRetry).toEqual(onRetry);
});

View file

@ -7,6 +7,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
export function UpgradeFailureActions({ onClose, onRetry, upgradeButtonText }) {
return (
@ -18,7 +19,10 @@ export function UpgradeFailureActions({ onClose, onRetry, upgradeButtonText }) {
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty color="primary" onClick={onClose}>
Go back
<FormattedMessage
id="xpack.logstash.upgradeFailureActions.goBackButtonLabel"
defaultMessage="Go back"
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -5,7 +5,7 @@
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
import { UpgradeFailureActions } from './upgrade_failure_actions';
describe('UpgradeFailureActions component', () => {
@ -24,18 +24,18 @@ describe('UpgradeFailureActions component', () => {
});
it('renders component as expected', () => {
const wrapper = shallow(<UpgradeFailureActions {...props} />);
const wrapper = shallowWithIntl(<UpgradeFailureActions {...props} />);
expect(wrapper).toMatchSnapshot();
});
it('calls onRetry on update click', () => {
const wrapper = mount(<UpgradeFailureActions {...props} />);
const wrapper = mountWithIntl(<UpgradeFailureActions {...props} />);
wrapper.find('EuiButton').simulate('click');
expect(onRetry).toHaveBeenCalledTimes(1);
});
it('calls onClose on "Go back" click', () => {
const wrapper = mount(<UpgradeFailureActions {...props} />);
const wrapper = mountWithIntl(<UpgradeFailureActions {...props} />);
wrapper.find('EuiButtonEmpty').simulate('click');
expect(onClose).toHaveBeenCalledTimes(1);
});

View file

@ -6,7 +6,7 @@
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
FeatureCatalogueRegistryProvider.register(($injector) => {
FeatureCatalogueRegistryProvider.register(($injector, i18n) => {
const licenseService = $injector.get('logstashLicenseService');
if (!licenseService.enableLinks) {
@ -15,8 +15,12 @@ FeatureCatalogueRegistryProvider.register(($injector) => {
return {
id: 'management_logstash',
title: 'Logstash Pipelines',
description: 'Create, delete, update, and clone data ingestion pipelines.',
title: i18n('xpack.logstash.homeFeature.logstashPipelinesTitle', {
defaultMessage: 'Logstash Pipelines',
}),
description: i18n('xpack.logstash.homeFeature.logstashPipelinesDescription', {
defaultMessage: 'Create, delete, update, and clone data ingestion pipelines.',
}),
icon: 'pipelineApp',
path: '/app/kibana#/management/logstash/pipelines',
showOnHomePage: true,

View file

@ -8,6 +8,7 @@ import React from 'react';
import { render } from 'react-dom';
import { isEmpty } from 'lodash';
import { uiModules } from 'ui/modules';
import { I18nProvider } from '@kbn/i18n/react';
import { UpgradeFailure } from '../../../../components/upgrade_failure';
const app = uiModules.get('xpack/logstash');
@ -29,12 +30,14 @@ app.directive('upgradeFailure', $injector => {
const isManualUpgrade = !!$route.current.params.retry;
render(
<UpgradeFailure
isNewPipeline={isNewPipeline}
isManualUpgrade={isManualUpgrade}
onRetry={onRetry}
onClose={onClose}
/>,
<I18nProvider>
<UpgradeFailure
isNewPipeline={isNewPipeline}
isManualUpgrade={isManualUpgrade}
onRetry={onRetry}
onClose={onClose}
/>
</I18nProvider>,
el[0]
);
},

View file

@ -6,6 +6,7 @@
import routes from 'ui/routes';
import { toastNotifications } from 'ui/notify';
import { i18n } from '@kbn/i18n';
import template from './pipeline_edit_route.html';
import 'plugins/logstash/services/pipeline';
import 'plugins/logstash/services/license';
@ -50,7 +51,12 @@ routes
return licenseService.checkValidity()
.then(() => {
if (err.status !== 403) {
toastNotifications.addDanger(`Couldn't load pipeline. Error: '${err.statusText}'.`);
toastNotifications.addDanger(i18n.translate('xpack.logstash.couldNotLoadPipelineErrorNotification', {
defaultMessage: `Couldn't load pipeline. Error: '{errStatusText}'.`,
values: {
errStatusText: err.statusText,
},
}));
}
kbnUrl.redirect('/management/logstash/pipelines');

View file

@ -5,9 +5,12 @@
*/
import { management } from 'ui/management';
import { i18n } from '@kbn/i18n';
management.getSection('logstash').register('pipelines', {
display: 'Pipelines',
display: i18n.translate('xpack.logstash.managementSection.pipelinesTitle', {
defaultMessage: 'Pipelines',
}),
order: 10,
url: '#/management/logstash/pipelines/'
});
@ -17,13 +20,17 @@ management.getSection('logstash/pipelines').register('pipeline', {
});
management.getSection('logstash/pipelines/pipeline').register('edit', {
display: 'Edit pipeline',
display: i18n.translate('xpack.logstash.managementSection.editPipelineTitle', {
defaultMessage: 'Edit pipeline',
}),
order: 1,
visible: false
});
management.getSection('logstash/pipelines/pipeline').register('new', {
display: 'Create pipeline',
display: i18n.translate('xpack.logstash.managementSection.createPipelineTitle', {
defaultMessage: 'Create pipeline',
}),
order: 1,
visible: false
});

View file

@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export function checkLicense(xpackLicenseInfo) {
// If, for some reason, we cannot get the license information
// from Elasticsearch, assume worst case and disable the Logstash pipeline UI
@ -12,7 +14,9 @@ export function checkLicense(xpackLicenseInfo) {
isAvailable: false,
enableLinks: false,
isReadOnly: false,
message: 'You cannot manage Logstash pipelines because license information is not available at this time.'
message: i18n.translate('xpack.logstash.managementSection.notPossibleToManagePipelinesMessage', {
defaultMessage: 'You cannot manage Logstash pipelines because license information is not available at this time.',
})
};
}
@ -30,8 +34,10 @@ export function checkLicense(xpackLicenseInfo) {
// Security is not enabled in ES
if (!isSecurityEnabled) {
const message = 'Security must be enabled in order to use Logstash pipeline management features.'
+ ' Please set xpack.security.enabled: true in your elasticsearch.yml.';
const message = i18n.translate('xpack.logstash.managementSection.enableSecurityDescription', {
defaultMessage: 'Security must be enabled in order to use Logstash pipeline management features.' +
' Please set xpack.security.enabled: true in your elasticsearch.yml.',
});
return {
isAvailable: false,
enableLinks: false,
@ -46,7 +52,10 @@ export function checkLicense(xpackLicenseInfo) {
isAvailable: false,
enableLinks: false,
isReadOnly: false,
message: `Your ${licenseType} license does not support Logstash pipeline management features. Please upgrade your license.`
message: i18n.translate('xpack.logstash.managementSection.licenseDoesNotSupportDescription', {
defaultMessage: 'Your {licenseType} license does not support Logstash pipeline management features. Please upgrade your license.',
values: { licenseType },
}),
};
}
@ -56,7 +65,10 @@ export function checkLicense(xpackLicenseInfo) {
isAvailable: true,
enableLinks: true,
isReadOnly: true,
message: `You cannot edit, create, or delete your Logstash pipelines because your ${licenseType} license has expired.`
message: i18n.translate('xpack.logstash.managementSection.pipelineCrudOperationsNotAllowedDescription', {
defaultMessage: 'You cannot edit, create, or delete your Logstash pipelines because your {licenseType} license has expired.',
values: { licenseType },
}),
};
}

View file

@ -5,6 +5,7 @@
*/
import Boom from 'boom';
import { i18n } from '@kbn/i18n';
/**
* Wraps ES errors into a Boom error response and returns it
@ -16,7 +17,9 @@ import Boom from 'boom';
export function wrapEsError(err) {
const statusCode = err.statusCode;
if (statusCode === 403) {
return Boom.forbidden('Insufficient user permissions for managing Logstash pipelines');
return Boom.forbidden(i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', {
defaultMessage: 'Insufficient user permissions for managing Logstash pipelines',
}));
}
return Boom.boomify(err, { statusCode: err.statusCode });
}

View file

@ -7,6 +7,7 @@
import moment from 'moment';
import { badRequest } from 'boom';
import { get } from 'lodash';
import { i18n } from '@kbn/i18n';
/**
* This model deals with a pipeline object from ES and converts it to Kibana downstream
@ -70,7 +71,9 @@ export class Pipeline {
// generate Pipeline object from elasticsearch response
static fromUpstreamJSON(upstreamPipeline) {
if (!upstreamPipeline._id) {
throw badRequest('upstreamPipeline argument must contain an id property');
throw badRequest(i18n.translate('xpack.logstash.upstreamPipelineArgumentMustContainAnIdPropertyErrorMessage', {
defaultMessage: 'upstreamPipeline argument must contain an id property',
}));
}
const id = get(upstreamPipeline, '_id');
const description = get(upstreamPipeline, '_source.description');