mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[i18n] Translate ML - settings - calendar management (#27839)
* Translate settings -> calendar management * Update snapshots * Update test for calendar form * Minor fix for id name
This commit is contained in:
parent
63999aa7c7
commit
6a455833da
27 changed files with 524 additions and 189 deletions
|
@ -11,7 +11,7 @@ exports[`NewCalendar Renders new calendar form 1`] = `
|
|||
panelPaddingSize="l"
|
||||
verticalPosition="center"
|
||||
>
|
||||
<CalendarForm
|
||||
<InjectIntl(CalendarForm)
|
||||
calendarId=""
|
||||
canCreateCalendar={true}
|
||||
canDeleteCalendar={true}
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CalendarForm CalendarId shown as title when editing 1`] = `
|
||||
<EuiTitle
|
||||
size="m"
|
||||
textTransform="none"
|
||||
>
|
||||
<h1
|
||||
className="euiTitle euiTitle--medium"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Calendar {calendarId}"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.calendarTitle"
|
||||
values={
|
||||
Object {
|
||||
"calendarId": "test-calendar",
|
||||
}
|
||||
}
|
||||
>
|
||||
Calendar test-calendar
|
||||
</FormattedMessage>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
`;
|
||||
|
||||
exports[`CalendarForm Renders calendar form 1`] = `
|
||||
<EuiForm>
|
||||
<React.Fragment>
|
||||
|
@ -7,14 +30,19 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
describedByIds={Array []}
|
||||
error={
|
||||
Array [
|
||||
"Use lowercase alphanumerics (a-z and 0-9), hyphens or underscores;
|
||||
must start and end with an alphanumeric character",
|
||||
"Use lowercase alphanumerics (a-z and 0-9), hyphens or underscores; must start and end with an alphanumeric character",
|
||||
]
|
||||
}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
isInvalid={true}
|
||||
label="Calendar ID"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Calendar ID"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.calendarIdLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
compressed={false}
|
||||
|
@ -30,7 +58,13 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
describedByIds={Array []}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Description"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Description"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.descriptionLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
compressed={false}
|
||||
|
@ -47,7 +81,13 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
describedByIds={Array []}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Jobs"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Jobs"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.jobsLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
compressed={false}
|
||||
|
@ -64,7 +104,13 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
describedByIds={Array []}
|
||||
fullWidth={false}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Groups"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Groups"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.groupsLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiComboBox
|
||||
compressed={false}
|
||||
|
@ -85,9 +131,15 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
describedByIds={Array []}
|
||||
fullWidth={true}
|
||||
hasEmptyLabelSpace={false}
|
||||
label="Events"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Events"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.eventsLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EventsTable
|
||||
<InjectIntl(EventsTable)
|
||||
canCreateCalendar={true}
|
||||
canDeleteCalendar={true}
|
||||
eventsList={Array []}
|
||||
|
@ -122,7 +174,11 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
onClick={[MockFunction]}
|
||||
type="button"
|
||||
>
|
||||
Save
|
||||
<FormattedMessage
|
||||
defaultMessage="Save"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.saveButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
|
@ -137,7 +193,11 @@ exports[`CalendarForm Renders calendar form 1`] = `
|
|||
isDisabled={false}
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
id="xpack.ml.calendarsEdit.calendarForm.cancelButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
|
@ -25,6 +25,8 @@ import {
|
|||
import chrome from 'ui/chrome';
|
||||
import { EventsTable } from '../events_table/';
|
||||
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
|
||||
function EditHeader({
|
||||
calendarId,
|
||||
|
@ -33,7 +35,13 @@ function EditHeader({
|
|||
return (
|
||||
<Fragment>
|
||||
<EuiTitle>
|
||||
<h1>Calendar {calendarId}</h1>
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.calendarTitle"
|
||||
defaultMessage="Calendar {calendarId}"
|
||||
values={{ calendarId }}
|
||||
/>
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
<EuiText>
|
||||
<p>
|
||||
|
@ -45,7 +53,7 @@ function EditHeader({
|
|||
);
|
||||
}
|
||||
|
||||
export function CalendarForm({
|
||||
export const CalendarForm = injectI18n(function CalendarForm({
|
||||
calendarId,
|
||||
canCreateCalendar,
|
||||
canDeleteCalendar,
|
||||
|
@ -67,10 +75,14 @@ export function CalendarForm({
|
|||
saving,
|
||||
selectedGroupOptions,
|
||||
selectedJobOptions,
|
||||
showNewEventModal
|
||||
showNewEventModal,
|
||||
intl
|
||||
}) {
|
||||
const msg = `Use lowercase alphanumerics (a-z and 0-9), hyphens or underscores;
|
||||
must start and end with an alphanumeric character`;
|
||||
const msg = intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.calendarForm.allowedCharactersDescription',
|
||||
defaultMessage: 'Use lowercase alphanumerics (a-z and 0-9), hyphens or underscores; ' +
|
||||
'must start and end with an alphanumeric character'
|
||||
});
|
||||
const helpText = (isNewCalendarIdValid === true && !isEdit) ? msg : undefined;
|
||||
const error = (isNewCalendarIdValid === false && !isEdit) ? [msg] : undefined;
|
||||
const saveButtonDisabled = (canCreateCalendar === false || saving || !isNewCalendarIdValid || calendarId === '');
|
||||
|
@ -80,7 +92,10 @@ export function CalendarForm({
|
|||
{!isEdit &&
|
||||
<Fragment>
|
||||
<EuiFormRow
|
||||
label="Calendar ID"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.calendarIdLabel"
|
||||
defaultMessage="Calendar ID"
|
||||
/>}
|
||||
helpText={helpText}
|
||||
error={error}
|
||||
isInvalid={!isNewCalendarIdValid}
|
||||
|
@ -94,7 +109,10 @@ export function CalendarForm({
|
|||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow
|
||||
label="Description"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.descriptionLabel"
|
||||
defaultMessage="Description"
|
||||
/>}
|
||||
>
|
||||
<EuiFieldText
|
||||
name="description"
|
||||
|
@ -111,7 +129,10 @@ export function CalendarForm({
|
|||
description={description}
|
||||
/>}
|
||||
<EuiFormRow
|
||||
label="Jobs"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.jobsLabel"
|
||||
defaultMessage="Jobs"
|
||||
/>}
|
||||
>
|
||||
<EuiComboBox
|
||||
options={jobIds}
|
||||
|
@ -122,7 +143,10 @@ export function CalendarForm({
|
|||
</EuiFormRow>
|
||||
|
||||
<EuiFormRow
|
||||
label="Groups"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.groupsLabel"
|
||||
defaultMessage="Groups"
|
||||
/>}
|
||||
>
|
||||
<EuiComboBox
|
||||
onCreateOption={onCreateGroupOption}
|
||||
|
@ -136,7 +160,10 @@ export function CalendarForm({
|
|||
<EuiSpacer size="xl" />
|
||||
|
||||
<EuiFormRow
|
||||
label="Events"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.eventsLabel"
|
||||
defaultMessage="Events"
|
||||
/>}
|
||||
fullWidth
|
||||
>
|
||||
<EventsTable
|
||||
|
@ -158,7 +185,13 @@ export function CalendarForm({
|
|||
onClick={isEdit ? onEdit : onCreate}
|
||||
isDisabled={saveButtonDisabled}
|
||||
>
|
||||
{saving ? 'Saving...' : 'Save'}
|
||||
{saving ? (<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.savingButtonLabel"
|
||||
defaultMessage="Saving…"
|
||||
/>) : (<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.saveButtonLabel"
|
||||
defaultMessage="Save"
|
||||
/>)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -166,15 +199,18 @@ export function CalendarForm({
|
|||
isDisabled={saving}
|
||||
href={`${chrome.getBasePath()}/app/ml#/settings/calendars_list`}
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.calendarForm.cancelButtonLabel"
|
||||
defaultMessage="Cancel"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiForm>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
CalendarForm.propTypes = {
|
||||
CalendarForm.WrappedComponent.propTypes = {
|
||||
calendarId: PropTypes.string.isRequired,
|
||||
canCreateCalendar: PropTypes.bool.isRequired,
|
||||
canDeleteCalendar: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -11,7 +11,7 @@ jest.mock('ui/chrome', () => ({
|
|||
}));
|
||||
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { CalendarForm } from './calendar_form';
|
||||
|
||||
|
@ -43,8 +43,8 @@ const testProps = {
|
|||
describe('CalendarForm', () => {
|
||||
|
||||
test('Renders calendar form', () => {
|
||||
const wrapper = shallow(
|
||||
<CalendarForm {...testProps}/>
|
||||
const wrapper = shallowWithIntl(
|
||||
<CalendarForm.WrappedComponent {...testProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -57,16 +57,12 @@ describe('CalendarForm', () => {
|
|||
calendarId: 'test-calendar',
|
||||
description: 'test description',
|
||||
};
|
||||
const wrapper = mount(
|
||||
<CalendarForm {...editProps} />
|
||||
const wrapper = mountWithIntl(
|
||||
<CalendarForm.WrappedComponent {...editProps} />
|
||||
);
|
||||
const calendarId = wrapper.find('EuiTitle');
|
||||
|
||||
expect(
|
||||
calendarId.containsMatchingElement(
|
||||
<h1>Calendar test-calendar</h1>
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(calendarId).toMatchSnapshot();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -20,6 +20,8 @@ import { getCreateCalendarBreadcrumbs, getEditCalendarBreadcrumbs } from '../../
|
|||
|
||||
import uiRoutes from 'ui/routes';
|
||||
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
const template = `
|
||||
<ml-nav-menu name="settings" />
|
||||
<div class="mlCalendarManagement">
|
||||
|
@ -64,7 +66,9 @@ module.directive('mlNewCalendar', function ($route) {
|
|||
};
|
||||
|
||||
ReactDOM.render(
|
||||
React.createElement(NewCalendar, props),
|
||||
<I18nProvider>
|
||||
{React.createElement(NewCalendar, props)}
|
||||
</I18nProvider>,
|
||||
element[0]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -140,7 +140,11 @@ exports[`EventsTable Renders events table with search bar 1`] = `
|
|||
size="s"
|
||||
type="button"
|
||||
>
|
||||
New event
|
||||
<FormattedMessage
|
||||
defaultMessage="New event"
|
||||
id="xpack.ml.calendarsEdit.eventsTable.newEventButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>,
|
||||
<EuiButton
|
||||
color="primary"
|
||||
|
@ -153,7 +157,11 @@ exports[`EventsTable Renders events table with search bar 1`] = `
|
|||
size="s"
|
||||
type="button"
|
||||
>
|
||||
Import events
|
||||
<FormattedMessage
|
||||
defaultMessage="Import events"
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>,
|
||||
],
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import {
|
|||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
export const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
||||
function DeleteButton({ onClick, canDeleteCalendar }) {
|
||||
|
@ -28,20 +30,24 @@ function DeleteButton({ onClick, canDeleteCalendar }) {
|
|||
onClick={onClick}
|
||||
isDisabled={canDeleteCalendar === false}
|
||||
>
|
||||
Delete
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.deleteButtonLabel"
|
||||
defaultMessage="Delete"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
export function EventsTable({
|
||||
export const EventsTable = injectI18n(function EventsTable({
|
||||
canCreateCalendar,
|
||||
canDeleteCalendar,
|
||||
eventsList,
|
||||
onDeleteClick,
|
||||
showSearchBar,
|
||||
showImportModal,
|
||||
showNewEventModal
|
||||
showNewEventModal,
|
||||
intl
|
||||
}) {
|
||||
const sorting = {
|
||||
sort: {
|
||||
|
@ -58,13 +64,19 @@ export function EventsTable({
|
|||
const columns = [
|
||||
{
|
||||
field: 'description',
|
||||
name: 'Description',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.eventsTable.descriptionColumnName',
|
||||
defaultMessage: 'Description'
|
||||
}),
|
||||
sortable: true,
|
||||
truncateText: true
|
||||
},
|
||||
{
|
||||
field: 'start_time',
|
||||
name: 'Start',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.eventsTable.startColumnName',
|
||||
defaultMessage: 'Start'
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timeMs) => {
|
||||
const time = moment(timeMs);
|
||||
|
@ -73,7 +85,10 @@ export function EventsTable({
|
|||
},
|
||||
{
|
||||
field: 'end_time',
|
||||
name: 'End',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.eventsTable.endColumnName',
|
||||
defaultMessage: 'End'
|
||||
}),
|
||||
sortable: true,
|
||||
render: (timeMs) => {
|
||||
const time = moment(timeMs);
|
||||
|
@ -103,7 +118,10 @@ export function EventsTable({
|
|||
iconType="plusInCircle"
|
||||
onClick={showNewEventModal}
|
||||
>
|
||||
New event
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.newEventButtonLabel"
|
||||
defaultMessage="New event"
|
||||
/>
|
||||
</EuiButton>),
|
||||
(
|
||||
<EuiButton
|
||||
|
@ -114,7 +132,10 @@ export function EventsTable({
|
|||
iconType="importAction"
|
||||
onClick={showImportModal}
|
||||
>
|
||||
Import events
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsButtonLabel"
|
||||
defaultMessage="Import events"
|
||||
/>
|
||||
</EuiButton>
|
||||
)],
|
||||
box: {
|
||||
|
@ -136,9 +157,9 @@ export function EventsTable({
|
|||
/>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
EventsTable.propTypes = {
|
||||
EventsTable.WrappedComponent.propTypes = {
|
||||
canCreateCalendar: PropTypes.bool,
|
||||
canDeleteCalendar: PropTypes.bool,
|
||||
eventsList: PropTypes.array.isRequired,
|
||||
|
@ -148,7 +169,7 @@ EventsTable.propTypes = {
|
|||
showSearchBar: PropTypes.bool,
|
||||
};
|
||||
|
||||
EventsTable.defaultProps = {
|
||||
EventsTable.WrappedComponent.defaultProps = {
|
||||
showSearchBar: false,
|
||||
canCreateCalendar: true,
|
||||
canDeleteCalendar: true
|
||||
|
|
|
@ -11,7 +11,7 @@ jest.mock('ui/chrome', () => ({
|
|||
}));
|
||||
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { EventsTable } from './events_table';
|
||||
|
||||
|
@ -33,8 +33,8 @@ const testProps = {
|
|||
describe('EventsTable', () => {
|
||||
|
||||
test('Renders events table with no search bar', () => {
|
||||
const wrapper = shallow(
|
||||
<EventsTable {...testProps}/>
|
||||
const wrapper = shallowWithIntl(
|
||||
<EventsTable.WrappedComponent {...testProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
@ -46,8 +46,8 @@ describe('EventsTable', () => {
|
|||
showSearchBar: true,
|
||||
};
|
||||
|
||||
const wrapper = shallow(
|
||||
<EventsTable {...showSearchBarProps} />
|
||||
const wrapper = shallowWithIntl(
|
||||
<EventsTable.WrappedComponent {...showSearchBarProps} />
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
|
|
@ -21,7 +21,11 @@ exports[`ImportModal Renders import modal 1`] = `
|
|||
grow={false}
|
||||
>
|
||||
<EuiModalHeaderTitle>
|
||||
Import events
|
||||
<FormattedMessage
|
||||
defaultMessage="Import events"
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiModalHeaderTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
|
@ -29,7 +33,11 @@ exports[`ImportModal Renders import modal 1`] = `
|
|||
grow={false}
|
||||
>
|
||||
<p>
|
||||
Import events from an ICS file.
|
||||
<FormattedMessage
|
||||
defaultMessage="Import events from an ICS file."
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsDescription"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -66,7 +74,11 @@ exports[`ImportModal Renders import modal 1`] = `
|
|||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Import
|
||||
<FormattedMessage
|
||||
defaultMessage="Import"
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
<EuiButtonEmpty
|
||||
color="primary"
|
||||
|
@ -74,7 +86,11 @@ exports[`ImportModal Renders import modal 1`] = `
|
|||
onClick={[MockFunction]}
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
id="xpack.ml.calendarsEdit.eventsTable.cancelButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiModalFooter>
|
||||
</EuiModal>
|
||||
|
|
|
@ -27,9 +27,16 @@ import {
|
|||
import { ImportedEvents } from '../imported_events';
|
||||
import { readFile, parseICSFile, filterEvents } from './utils';
|
||||
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
const MAX_FILE_SIZE_MB = 100;
|
||||
|
||||
export class ImportModal extends Component {
|
||||
export const ImportModal = injectI18n(class ImportModal extends Component {
|
||||
static propTypes = {
|
||||
addImportedEvents: PropTypes.func.isRequired,
|
||||
closeImportModal: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -45,7 +52,10 @@ export class ImportModal extends Component {
|
|||
|
||||
handleImport = async (loadedFile) => {
|
||||
const incomingFile = loadedFile[0];
|
||||
const errorMessage = 'Could not parse ICS file.';
|
||||
const errorMessage = this.props.intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.importModal.couldNotParseICSFileErrorMessage',
|
||||
defaultMessage: 'Could not parse ICS file.'
|
||||
});
|
||||
let events = [];
|
||||
|
||||
if (incomingFile && incomingFile.size <= (MAX_FILE_SIZE_MB * 1000000)) {
|
||||
|
@ -107,7 +117,7 @@ export class ImportModal extends Component {
|
|||
);
|
||||
|
||||
render() {
|
||||
const { closeImportModal } = this.props;
|
||||
const { closeImportModal, intl } = this.props;
|
||||
const {
|
||||
fileLoading,
|
||||
fileLoaded,
|
||||
|
@ -143,11 +153,19 @@ export class ImportModal extends Component {
|
|||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiModalHeaderTitle >
|
||||
Import events
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsTitle"
|
||||
defaultMessage="Import events"
|
||||
/>
|
||||
</EuiModalHeaderTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<p>Import events from an ICS file.</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importEventsDescription"
|
||||
defaultMessage="Import events from an ICS file."
|
||||
/>
|
||||
</p>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiModalHeader>
|
||||
|
@ -157,7 +175,10 @@ export class ImportModal extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiFilePicker
|
||||
compressed
|
||||
initialPromptText="Select or drag and drop a file"
|
||||
initialPromptText={intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.importModal.selectOrDragAndDropFilePromptText',
|
||||
defaultMessage: 'Select or drag and drop a file'
|
||||
})}
|
||||
onChange={this.handleImport}
|
||||
disabled={fileLoading}
|
||||
/>
|
||||
|
@ -182,21 +203,22 @@ export class ImportModal extends Component {
|
|||
fill
|
||||
disabled={fileLoaded === false || errorMessage !== null}
|
||||
>
|
||||
Import
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.importButtonLabel"
|
||||
defaultMessage="Import"
|
||||
/>
|
||||
</EuiButton>
|
||||
<EuiButtonEmpty
|
||||
onClick={closeImportModal}
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.eventsTable.cancelButtonLabel"
|
||||
defaultMessage="Cancel"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiModalFooter>
|
||||
</EuiModal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ImportModal.propTypes = {
|
||||
addImportedEvents: PropTypes.func.isRequired,
|
||||
closeImportModal: PropTypes.func.isRequired,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { ImportModal } from './import_modal';
|
||||
|
||||
|
@ -34,16 +34,16 @@ const events = [{
|
|||
describe('ImportModal', () => {
|
||||
|
||||
test('Renders import modal', () => {
|
||||
const wrapper = shallow(
|
||||
<ImportModal {...testProps}/>
|
||||
const wrapper = shallowWithIntl(
|
||||
<ImportModal.WrappedComponent {...testProps}/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Deletes selected event from event table', () => {
|
||||
const wrapper = mount(
|
||||
<ImportModal {...testProps} />
|
||||
const wrapper = mountWithIntl(
|
||||
<ImportModal.WrappedComponent {...testProps} />
|
||||
);
|
||||
|
||||
const testState = {
|
||||
|
|
|
@ -14,8 +14,15 @@ exports[`ImportedEvents Renders imported events 1`] = `
|
|||
size="m"
|
||||
>
|
||||
<h4>
|
||||
Events to import:
|
||||
1
|
||||
<FormattedMessage
|
||||
defaultMessage="Events to import: {eventsCount}"
|
||||
id="xpack.ml.calendarsEdit.importedEvents.eventsToImportTitle"
|
||||
values={
|
||||
Object {
|
||||
"eventsCount": 1,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</h4>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
@ -23,9 +30,7 @@ exports[`ImportedEvents Renders imported events 1`] = `
|
|||
component="div"
|
||||
grow={false}
|
||||
>
|
||||
<EventsTable
|
||||
canCreateCalendar={true}
|
||||
canDeleteCalendar={true}
|
||||
<InjectIntl(EventsTable)
|
||||
eventsList={
|
||||
Array [
|
||||
Object {
|
||||
|
@ -38,7 +43,6 @@ exports[`ImportedEvents Renders imported events 1`] = `
|
|||
]
|
||||
}
|
||||
onDeleteClick={[MockFunction]}
|
||||
showSearchBar={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiSpacer
|
||||
|
@ -54,7 +58,13 @@ exports[`ImportedEvents Renders imported events 1`] = `
|
|||
disabled={false}
|
||||
id="ml-include-past-events"
|
||||
indeterminate={false}
|
||||
label="Include past events"
|
||||
label={
|
||||
<FormattedMessage
|
||||
defaultMessage="Include past events"
|
||||
id="xpack.ml.calendarsEdit.importedEvents.includePastEventsLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
onChange={[MockFunction]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
EuiSpacer
|
||||
} from '@elastic/eui';
|
||||
import { EventsTable } from '../events_table/';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
|
||||
export function ImportedEvents({
|
||||
|
@ -27,10 +28,21 @@ export function ImportedEvents({
|
|||
<EuiSpacer size="s"/>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<h4>Events to import: {events.length}</h4>
|
||||
<h4>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.importedEvents.eventsToImportTitle"
|
||||
defaultMessage="Events to import: {eventsCount}"
|
||||
values={{ eventsCount: events.length }}
|
||||
/>
|
||||
</h4>
|
||||
{showRecurringWarning && (
|
||||
<EuiText color="danger">
|
||||
<p>Recurring events not supported. Only the first event will be imported.</p>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.importedEvents.recurringEventsNotSupportedDescription"
|
||||
defaultMessage="Recurring events not supported. Only the first event will be imported."
|
||||
/>
|
||||
</p>
|
||||
</EuiText>)
|
||||
}
|
||||
</EuiText>
|
||||
|
@ -45,7 +57,10 @@ export function ImportedEvents({
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiCheckbox
|
||||
id="ml-include-past-events"
|
||||
label="Include past events"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.importedEvents.includePastEventsLabel"
|
||||
defaultMessage="Include past events"
|
||||
/>}
|
||||
checked={includePastEvents}
|
||||
onChange={onCheckboxToggle}
|
||||
/>
|
||||
|
|
|
@ -11,7 +11,7 @@ jest.mock('ui/chrome', () => ({
|
|||
}));
|
||||
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { ImportedEvents } from './imported_events';
|
||||
|
||||
|
@ -33,7 +33,7 @@ const testProps = {
|
|||
describe('ImportedEvents', () => {
|
||||
|
||||
test('Renders imported events', () => {
|
||||
const wrapper = shallow(
|
||||
const wrapper = shallowWithIntl(
|
||||
<ImportedEvents {...testProps} />
|
||||
);
|
||||
|
||||
|
|
|
@ -25,7 +25,15 @@ import { ImportModal } from './import_modal';
|
|||
import { ml } from '../../../services/ml_api_service';
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
|
||||
export class NewCalendar extends Component {
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
export const NewCalendar = injectI18n(class NewCalendar extends Component {
|
||||
static propTypes = {
|
||||
calendarId: PropTypes.string,
|
||||
canCreateCalendar: PropTypes.bool.isRequired,
|
||||
canDeleteCalendar: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -99,7 +107,12 @@ export class NewCalendar extends Component {
|
|||
} catch (error) {
|
||||
console.log(error);
|
||||
this.setState({ loading: false });
|
||||
toastNotifications.addDanger('An error occurred loading calendar form data. Try refreshing the page.');
|
||||
toastNotifications.addDanger(
|
||||
this.props.intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.errorWithLoadingCalendarFromDataErrorMessage',
|
||||
defaultMessage: 'An error occurred loading calendar form data. Try refreshing the page.'
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,9 +130,18 @@ export class NewCalendar extends Component {
|
|||
|
||||
onCreate = async () => {
|
||||
const { formCalendarId } = this.state;
|
||||
const { intl } = this.props;
|
||||
|
||||
if (this.isDuplicateId()) {
|
||||
toastNotifications.addDanger(`Cannot create calendar with id [${formCalendarId}] as it already exists.`);
|
||||
toastNotifications.addDanger(
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: 'xpack.ml.calendarsEdit.canNotCreateCalendarWithExistingIdErrorMessag',
|
||||
defaultMessage: 'Cannot create calendar with id [{formCalendarId}] as it already exists.'
|
||||
},
|
||||
{ formCalendarId }
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const calendar = this.setUpCalendarForApi();
|
||||
this.setState({ saving: true });
|
||||
|
@ -130,7 +152,15 @@ export class NewCalendar extends Component {
|
|||
} catch (error) {
|
||||
console.log('Error saving calendar', error);
|
||||
this.setState({ saving: false });
|
||||
toastNotifications.addDanger(`An error occurred creating calendar ${calendar.calendarId}`);
|
||||
toastNotifications.addDanger(
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: 'xpack.ml.calendarsEdit.errorWithCreatingCalendarErrorMessage',
|
||||
defaultMessage: 'An error occurred creating calendar {calendarId}'
|
||||
},
|
||||
{ calendarId: calendar.calendarId }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +175,15 @@ export class NewCalendar extends Component {
|
|||
} catch (error) {
|
||||
console.log('Error saving calendar', error);
|
||||
this.setState({ saving: false });
|
||||
toastNotifications.addDanger(`An error occurred saving calendar ${calendar.calendarId}. Try refreshing the page.`);
|
||||
toastNotifications.addDanger(
|
||||
this.props.intl.formatMessage(
|
||||
{
|
||||
id: 'xpack.ml.calendarsEdit.errorWithUpdatingCalendarErrorMessage',
|
||||
defaultMessage: 'An error occurred saving calendar {calendarId}. Try refreshing the page.'
|
||||
},
|
||||
{ calendarId: calendar.calendarId }
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,10 +368,4 @@ export class NewCalendar extends Component {
|
|||
</EuiPage>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
NewCalendar.propTypes = {
|
||||
calendarId: PropTypes.string,
|
||||
canCreateCalendar: PropTypes.bool.isRequired,
|
||||
canDeleteCalendar: PropTypes.bool.isRequired,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ jest.mock('./utils', () => ({
|
|||
})),
|
||||
}));
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { NewCalendar } from './new_calendar';
|
||||
|
||||
|
@ -84,16 +84,16 @@ const props = {
|
|||
describe('NewCalendar', () => {
|
||||
|
||||
test('Renders new calendar form', () => {
|
||||
const wrapper = shallow(
|
||||
<NewCalendar {...props}/>
|
||||
const wrapper = shallowWithIntl(
|
||||
<NewCalendar.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Import modal shown on Import Events button click', () => {
|
||||
const wrapper = mount(
|
||||
<NewCalendar {...props}/>
|
||||
const wrapper = mountWithIntl(
|
||||
<NewCalendar.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
const importButton = wrapper.find('[data-testid="ml_import_events"]');
|
||||
|
@ -104,8 +104,8 @@ describe('NewCalendar', () => {
|
|||
});
|
||||
|
||||
test('New event modal shown on New event button click', () => {
|
||||
const wrapper = mount(
|
||||
<NewCalendar {...props}/>
|
||||
const wrapper = mountWithIntl(
|
||||
<NewCalendar.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
const importButton = wrapper.find('[data-testid="ml_new_event"]');
|
||||
|
@ -116,8 +116,8 @@ describe('NewCalendar', () => {
|
|||
});
|
||||
|
||||
test('isDuplicateId returns true if form calendar id already exists in calendars', () => {
|
||||
const wrapper = mount(
|
||||
<NewCalendar {...props}/>
|
||||
const wrapper = mountWithIntl(
|
||||
<NewCalendar.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
const instance = wrapper.instance();
|
||||
|
@ -135,8 +135,8 @@ describe('NewCalendar', () => {
|
|||
canCreateCalendar: false,
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<NewCalendar {...noCreateProps} />
|
||||
const wrapper = mountWithIntl(
|
||||
<NewCalendar.WrappedComponent {...noCreateProps} />
|
||||
);
|
||||
|
||||
const buttons = wrapper.find('[data-testid="ml_save_calendar_button"]');
|
||||
|
|
|
@ -31,9 +31,16 @@ import moment from 'moment';
|
|||
import { TIME_FORMAT } from '../events_table/';
|
||||
import { generateTempId } from '../utils';
|
||||
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
const VALID_DATE_STRING_LENGTH = 19;
|
||||
|
||||
export class NewEventModal extends Component {
|
||||
export const NewEventModal = injectI18n(class NewEventModal extends Component {
|
||||
static propTypes = {
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
addEvent: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -158,11 +165,19 @@ export class NewEventModal extends Component {
|
|||
endDateString,
|
||||
} = this.state;
|
||||
|
||||
const { intl } = this.props;
|
||||
|
||||
const timeInputs = (
|
||||
<Fragment>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="From:" helpText={TIME_FORMAT}>
|
||||
<EuiFormRow
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.fromLabel"
|
||||
defaultMessage="From:"
|
||||
/>}
|
||||
helpText={TIME_FORMAT}
|
||||
>
|
||||
<EuiFieldText
|
||||
name="startTime"
|
||||
onChange={this.handleTimeStartChange}
|
||||
|
@ -172,7 +187,13 @@ export class NewEventModal extends Component {
|
|||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow label="To:" helpText={TIME_FORMAT}>
|
||||
<EuiFormRow
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.toLabel"
|
||||
defaultMessage="To:"
|
||||
/>}
|
||||
helpText={TIME_FORMAT}
|
||||
>
|
||||
<EuiFieldText
|
||||
name="endTime"
|
||||
onChange={this.handleTimeEndChange}
|
||||
|
@ -203,7 +224,10 @@ export class NewEventModal extends Component {
|
|||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
isInvalid={startDate > endDate}
|
||||
aria-label="Start date"
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.newEventModal.startDateAriaLabel',
|
||||
defaultMessage: 'Start date'
|
||||
})}
|
||||
timeFormat={TIME_FORMAT}
|
||||
dateFormat={TIME_FORMAT}
|
||||
/>
|
||||
|
@ -217,7 +241,10 @@ export class NewEventModal extends Component {
|
|||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
isInvalid={startDate > endDate}
|
||||
aria-label="End date"
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsEdit.newEventModal.endDateAriaLabel',
|
||||
defaultMessage: 'End date'
|
||||
})}
|
||||
timeFormat={TIME_FORMAT}
|
||||
dateFormat={TIME_FORMAT}
|
||||
/>
|
||||
|
@ -241,14 +268,20 @@ export class NewEventModal extends Component {
|
|||
>
|
||||
<EuiModalHeader>
|
||||
<EuiModalHeaderTitle >
|
||||
Create new event
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.createNewEventTitle"
|
||||
defaultMessage="Create new event"
|
||||
/>
|
||||
</EuiModalHeaderTitle>
|
||||
</EuiModalHeader>
|
||||
|
||||
<EuiModalBody>
|
||||
<EuiForm>
|
||||
<EuiFormRow
|
||||
label="Description"
|
||||
label={<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.descriptionLabel"
|
||||
defaultMessage="Description"
|
||||
/>}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
|
@ -269,21 +302,22 @@ export class NewEventModal extends Component {
|
|||
fill
|
||||
disabled={!description}
|
||||
>
|
||||
Add
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.addButtonLabel"
|
||||
defaultMessage="Add"
|
||||
/>
|
||||
</EuiButton>
|
||||
<EuiButtonEmpty
|
||||
onClick={closeModal}
|
||||
>
|
||||
Cancel
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsEdit.newEventModal.cancelButtonLabel"
|
||||
defaultMessage="Cancel"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiModalFooter>
|
||||
</EuiModal>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
NewEventModal.propTypes = {
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
addEvent: PropTypes.func.isRequired,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { NewEventModal } from './new_event_modal';
|
||||
import moment from 'moment';
|
||||
|
@ -24,8 +24,8 @@ const stateTimestamps = {
|
|||
describe('NewEventModal', () => {
|
||||
|
||||
it('Add button disabled if description empty', () => {
|
||||
const wrapper = shallow(
|
||||
<NewEventModal {...testProps} />
|
||||
const wrapper = shallowWithIntl(
|
||||
<NewEventModal.WrappedComponent {...testProps} />
|
||||
);
|
||||
|
||||
const addButton = wrapper.find('EuiButton').first();
|
||||
|
@ -33,7 +33,7 @@ describe('NewEventModal', () => {
|
|||
});
|
||||
|
||||
it('if endDate is less than startDate should set startDate one day before endDate', () => {
|
||||
const wrapper = shallow(<NewEventModal {...testProps} />);
|
||||
const wrapper = shallowWithIntl(<NewEventModal.WrappedComponent {...testProps} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState({
|
||||
startDate: moment(stateTimestamps.startDate),
|
||||
|
@ -53,7 +53,7 @@ describe('NewEventModal', () => {
|
|||
});
|
||||
|
||||
it('if startDate is greater than endDate should set endDate one day after startDate', () => {
|
||||
const wrapper = shallow(<NewEventModal {...testProps} />);
|
||||
const wrapper = shallowWithIntl(<NewEventModal.WrappedComponent {...testProps} />);
|
||||
const instance = wrapper.instance();
|
||||
instance.setState({
|
||||
startDate: moment(stateTimestamps.startDate),
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
import { isJobIdValid } from '../../../../common/util/job_utils';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
|
||||
function getJobIds() {
|
||||
|
@ -17,7 +18,10 @@ function getJobIds() {
|
|||
resolve(resp.map((job) => job.id));
|
||||
})
|
||||
.catch((err) => {
|
||||
const errorMessage = `Error fetching job summaries: ${err}`;
|
||||
const errorMessage = i18n.translate('xpack.ml.calendarsEdit.errorWithFetchingJobSummariesErrorMessage', {
|
||||
defaultMessage: 'Error fetching job summaries: {err}',
|
||||
values: { err }
|
||||
});
|
||||
console.log(errorMessage);
|
||||
reject(errorMessage);
|
||||
});
|
||||
|
@ -31,7 +35,10 @@ function getGroupIds() {
|
|||
resolve(resp.map((group) => group.id));
|
||||
})
|
||||
.catch((err) => {
|
||||
const errorMessage = `Error loading groups: ${err}`;
|
||||
const errorMessage = i18n.translate('xpack.ml.calendarsEdit.errorWithLoadingGroupsErrorMessage', {
|
||||
defaultMessage: 'Error loading groups: {err}',
|
||||
values: { err }
|
||||
});
|
||||
console.log(errorMessage);
|
||||
reject(errorMessage);
|
||||
});
|
||||
|
@ -45,7 +52,10 @@ function getCalendars() {
|
|||
resolve(resp);
|
||||
})
|
||||
.catch((err) => {
|
||||
const errorMessage = `Error loading calendars: ${err}`;
|
||||
const errorMessage = i18n.translate('xpack.ml.calendarsEdit.errorWithLoadingCalendarsErrorMessage', {
|
||||
defaultMessage: 'Error loading calendars: {err}',
|
||||
values: { err }
|
||||
});
|
||||
console.log(errorMessage);
|
||||
reject(errorMessage);
|
||||
});
|
||||
|
|
|
@ -11,7 +11,7 @@ exports[`CalendarsList Renders calendar list with calendars 1`] = `
|
|||
panelPaddingSize="l"
|
||||
verticalPosition="center"
|
||||
>
|
||||
<CalendarsListTable
|
||||
<InjectIntl(CalendarsListTable)
|
||||
calendarsList={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -24,8 +24,14 @@ import { ml } from '../../../services/ml_api_service';
|
|||
import { toastNotifications } from 'ui/notify';
|
||||
import { mlNodesAvailable } from '../../../ml_nodes_check/check_ml_nodes';
|
||||
import { deleteCalendars } from './delete_calendars';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
export const CalendarsList = injectI18n(class CalendarsList extends Component {
|
||||
static propTypes = {
|
||||
canCreateCalendar: PropTypes.bool.isRequired,
|
||||
canDeleteCalendar: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export class CalendarsList extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -50,7 +56,12 @@ export class CalendarsList extends Component {
|
|||
} catch (error) {
|
||||
console.log(error);
|
||||
this.setState({ loading: false });
|
||||
toastNotifications.addDanger('An error occurred loading the list of calendars.');
|
||||
toastNotifications.addDanger(
|
||||
this.props.intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsList.errorWithLoadingListOfCalendarsErrorMessage',
|
||||
defaultMessage: 'An error occurred loading the list of calendars.'
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,20 +111,32 @@ export class CalendarsList extends Component {
|
|||
destroyModal = (
|
||||
<EuiOverlayMask>
|
||||
<EuiConfirmModal
|
||||
title="Delete calendar"
|
||||
title={<FormattedMessage
|
||||
id="xpack.ml.calendarsList.deleteCalendarsModal.deleteCalendarTitle"
|
||||
defaultMessage="Delete calendar"
|
||||
/>}
|
||||
onCancel={this.closeDestroyModal}
|
||||
onConfirm={this.deleteCalendars}
|
||||
cancelButtonText="Cancel"
|
||||
confirmButtonText="Delete"
|
||||
cancelButtonText={<FormattedMessage
|
||||
id="xpack.ml.calendarsList.deleteCalendarsModal.cancelButtonLabel"
|
||||
defaultMessage="Cancel"
|
||||
/>}
|
||||
confirmButtonText={<FormattedMessage
|
||||
id="xpack.ml.calendarsList.deleteCalendarsModal.deleteButtonLabel"
|
||||
defaultMessage="Delete"
|
||||
/>}
|
||||
buttonColor="danger"
|
||||
defaultFocusedButton={EUI_MODAL_CONFIRM_BUTTON}
|
||||
>
|
||||
<p>
|
||||
{
|
||||
`Delete ${selectedForDeletion.length === 1 ? 'this' : 'these'}
|
||||
calendar${selectedForDeletion.length === 1 ? '' : 's'}?
|
||||
${selectedForDeletion.map((c) => c.calendar_id).join(', ')}`
|
||||
}
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsList.deleteCalendarsModal.deleteCalendarsDescription"
|
||||
defaultMessage="Delete {calendarsCount, plural, one {this calendar} other {these calendars}}? {calendarsList}"
|
||||
values={{
|
||||
calendarsCount: selectedForDeletion.length,
|
||||
calendarsList: (selectedForDeletion.map((c) => c.calendar_id).join(', '))
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</EuiConfirmModal>
|
||||
</EuiOverlayMask>
|
||||
|
@ -142,9 +165,4 @@ export class CalendarsList extends Component {
|
|||
</EuiPage>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
CalendarsListTable.propTypes = {
|
||||
canCreateCalendar: PropTypes.bool.isRequired,
|
||||
canDeleteCalendar: PropTypes.bool.isRequired,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@ jest.mock('../../../services/ml_api_service', () => ({
|
|||
}
|
||||
}));
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
|
||||
|
@ -78,16 +78,16 @@ describe('CalendarsList', () => {
|
|||
|
||||
test('loads calendars on mount', () => {
|
||||
ml.calendars = jest.fn();
|
||||
shallow(
|
||||
<CalendarsList {...props}/>
|
||||
shallowWithIntl(
|
||||
<CalendarsList.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
expect(ml.calendars).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Renders calendar list with calendars', () => {
|
||||
const wrapper = shallow(
|
||||
<CalendarsList {...props}/>
|
||||
const wrapper = shallowWithIntl(
|
||||
<CalendarsList.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
wrapper.instance().setState(testingState);
|
||||
|
@ -96,8 +96,8 @@ describe('CalendarsList', () => {
|
|||
});
|
||||
|
||||
test('Sets selected calendars list on checkbox change', () => {
|
||||
const wrapper = mount(
|
||||
<CalendarsList {...props}/>
|
||||
const wrapper = mountWithIntl(
|
||||
<CalendarsList.WrappedComponent {...props}/>
|
||||
);
|
||||
|
||||
const instance = wrapper.instance();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { toastNotifications } from 'ui/notify';
|
||||
import { ml } from '../../../services/ml_api_service';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
|
||||
export async function deleteCalendars(calendarsToDelete, callback) {
|
||||
|
@ -15,9 +16,17 @@ export async function deleteCalendars(calendarsToDelete, callback) {
|
|||
|
||||
// Delete each of the specified calendars in turn, waiting for each response
|
||||
// before deleting the next to minimize load on the cluster.
|
||||
const messageId = `${(calendarsToDelete.length > 1) ?
|
||||
`${calendarsToDelete.length} calendars` : calendarsToDelete[0].calendar_id}`;
|
||||
toastNotifications.add(`Deleting ${messageId}`);
|
||||
const messageId = (calendarsToDelete.length > 1)
|
||||
? i18n.translate('xpack.ml.calendarsList.deleteCalendars.calendarsLabel', {
|
||||
defaultMessage: '{calendarsToDeleteCount} calendars',
|
||||
values: { calendarsToDeleteCount: calendarsToDelete.length }
|
||||
}) : `${calendarsToDelete[0].calendar_id}`;
|
||||
toastNotifications.add(
|
||||
i18n.translate('xpack.ml.calendarsList.deleteCalendars.deletingCalendarsNotificationMessage', {
|
||||
defaultMessage: 'Deleting {messageId}',
|
||||
values: { messageId }
|
||||
})
|
||||
);
|
||||
|
||||
for(const calendar of calendarsToDelete) {
|
||||
const calendarId = calendar.calendar_id;
|
||||
|
@ -25,14 +34,22 @@ export async function deleteCalendars(calendarsToDelete, callback) {
|
|||
await ml.deleteCalendar({ calendarId });
|
||||
} catch (error) {
|
||||
console.log('Error deleting calendar:', error);
|
||||
let errorMessage = `An error occurred deleting calendar ${calendar.calendar_id}`;
|
||||
if (error.message) {
|
||||
errorMessage += ` : ${error.message}`;
|
||||
}
|
||||
const errorMessage = i18n.translate('xpack.ml.calendarsList.deleteCalendars.deletingCalendarErrorMessage', {
|
||||
defaultMessage: 'An error occurred deleting calendar {calendarId}{errorMessage}',
|
||||
values: {
|
||||
calendarId: calendar.calendar_id,
|
||||
errorMessage: error.message ? ` : ${error.message}` : ''
|
||||
}
|
||||
});
|
||||
toastNotifications.addDanger(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
toastNotifications.addSuccess(`${messageId} deleted`);
|
||||
toastNotifications.addSuccess(
|
||||
i18n.translate('xpack.ml.calendarsList.deleteCalendars.deletingCalendarSuccessNotificationMessage', {
|
||||
defaultMessage: '{messageId} deleted',
|
||||
values: { messageId }
|
||||
})
|
||||
);
|
||||
callback();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ import { getCalendarManagementBreadcrumbs } from '../../breadcrumbs';
|
|||
|
||||
import uiRoutes from 'ui/routes';
|
||||
|
||||
import { I18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
const template = `
|
||||
<ml-nav-menu name="settings" />
|
||||
<div class="mlCalendarManagement">
|
||||
|
@ -54,7 +56,9 @@ module.directive('mlCalendarsList', function () {
|
|||
};
|
||||
|
||||
ReactDOM.render(
|
||||
React.createElement(CalendarsList, props),
|
||||
<I18nProvider>
|
||||
{React.createElement(CalendarsList, props)}
|
||||
</I18nProvider>,
|
||||
element[0]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -76,7 +76,11 @@ exports[`CalendarsListTable renders the table with all calendars 1`] = `
|
|||
size="s"
|
||||
type="button"
|
||||
>
|
||||
New
|
||||
<FormattedMessage
|
||||
defaultMessage="New"
|
||||
id="xpack.ml.calendarsList.table.newButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>,
|
||||
<EuiButton
|
||||
color="danger"
|
||||
|
@ -88,7 +92,11 @@ exports[`CalendarsListTable renders the table with all calendars 1`] = `
|
|||
size="s"
|
||||
type="button"
|
||||
>
|
||||
Delete
|
||||
<FormattedMessage
|
||||
defaultMessage="Delete"
|
||||
id="xpack.ml.calendarsList.table.deleteButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>,
|
||||
],
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@ import {
|
|||
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
export function CalendarsListTable({
|
||||
|
||||
export const CalendarsListTable = injectI18n(function CalendarsListTable({
|
||||
calendarsList,
|
||||
onDeleteClick,
|
||||
setSelectedCalendarList,
|
||||
|
@ -26,7 +28,8 @@ export function CalendarsListTable({
|
|||
canCreateCalendar,
|
||||
canDeleteCalendar,
|
||||
mlNodesAvailable,
|
||||
itemsSelected
|
||||
itemsSelected,
|
||||
intl
|
||||
}) {
|
||||
|
||||
const sorting = {
|
||||
|
@ -44,7 +47,10 @@ export function CalendarsListTable({
|
|||
const columns = [
|
||||
{
|
||||
field: 'calendar_id',
|
||||
name: 'ID',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsList.table.idColumnName',
|
||||
defaultMessage: 'ID'
|
||||
}),
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
render: (id) => (
|
||||
|
@ -57,15 +63,27 @@ export function CalendarsListTable({
|
|||
},
|
||||
{
|
||||
field: 'job_ids_string',
|
||||
name: 'Jobs',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsList.table.jobsColumnName',
|
||||
defaultMessage: 'Jobs'
|
||||
}),
|
||||
sortable: true,
|
||||
truncateText: true,
|
||||
},
|
||||
{
|
||||
field: 'events_length',
|
||||
name: 'Events',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.calendarsList.table.eventsColumnName',
|
||||
defaultMessage: 'Events'
|
||||
}),
|
||||
sortable: true,
|
||||
render: (eventsLength) => `${eventsLength} ${eventsLength === 1 ? 'event' : 'events'}`
|
||||
render: (eventsLength) => intl.formatMessage(
|
||||
{
|
||||
id: 'xpack.ml.calendarsList.table.eventsCountLabel',
|
||||
defaultMessage: '{eventsLength, plural, one {# event} other {# events}}'
|
||||
},
|
||||
{ eventsLength }
|
||||
)
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -83,7 +101,10 @@ export function CalendarsListTable({
|
|||
href={`${chrome.getBasePath()}/app/ml#/settings/calendars_list/new_calendar`}
|
||||
isDisabled={(canCreateCalendar === false || mlNodesAvailable === false)}
|
||||
>
|
||||
New
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsList.table.newButtonLabel"
|
||||
defaultMessage="New"
|
||||
/>
|
||||
</EuiButton>
|
||||
),
|
||||
(
|
||||
|
@ -94,7 +115,10 @@ export function CalendarsListTable({
|
|||
onClick={onDeleteClick}
|
||||
isDisabled={(canDeleteCalendar === false || mlNodesAvailable === false || itemsSelected === false)}
|
||||
>
|
||||
Delete
|
||||
<FormattedMessage
|
||||
id="xpack.ml.calendarsList.table.deleteButtonLabel"
|
||||
defaultMessage="Delete"
|
||||
/>
|
||||
</EuiButton>
|
||||
)
|
||||
],
|
||||
|
@ -119,9 +143,9 @@ export function CalendarsListTable({
|
|||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
CalendarsListTable.propTypes = {
|
||||
CalendarsListTable.WrappedComponent.propTypes = {
|
||||
calendarsList: PropTypes.array.isRequired,
|
||||
onDeleteClick: PropTypes.func.isRequired,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
|
||||
import { shallow, mount } from 'enzyme';
|
||||
import { shallowWithIntl, mountWithIntl } from 'test_utils/enzyme_helpers';
|
||||
import React from 'react';
|
||||
|
||||
import { CalendarsListTable } from './table';
|
||||
|
@ -41,15 +41,15 @@ const props = {
|
|||
describe('CalendarsListTable', () => {
|
||||
|
||||
test('renders the table with all calendars', () => {
|
||||
const wrapper = shallow(
|
||||
<CalendarsListTable {...props} />
|
||||
const wrapper = shallowWithIntl(
|
||||
<CalendarsListTable.WrappedComponent {...props} />
|
||||
);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('New button enabled if permission available', () => {
|
||||
const wrapper = mount(
|
||||
<CalendarsListTable {...props} />
|
||||
const wrapper = mountWithIntl(
|
||||
<CalendarsListTable.WrappedComponent {...props} />
|
||||
);
|
||||
|
||||
const buttons = wrapper.find('[data-testid="new_calendar_button"]');
|
||||
|
@ -64,8 +64,8 @@ describe('CalendarsListTable', () => {
|
|||
canCreateCalendar: false
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<CalendarsListTable {...disableProps} />
|
||||
const wrapper = mountWithIntl(
|
||||
<CalendarsListTable.WrappedComponent {...disableProps} />
|
||||
);
|
||||
|
||||
const buttons = wrapper.find('[data-testid="new_calendar_button"]');
|
||||
|
@ -81,8 +81,8 @@ describe('CalendarsListTable', () => {
|
|||
mlNodesAvailable: false
|
||||
};
|
||||
|
||||
const wrapper = mount(
|
||||
<CalendarsListTable {...disableProps} />
|
||||
const wrapper = mountWithIntl(
|
||||
<CalendarsListTable.WrappedComponent {...disableProps} />
|
||||
);
|
||||
|
||||
const buttons = wrapper.find('[data-testid="new_calendar_button"]');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue