Feature/translate ml - jobs(part 2) (#25528)
Translate ml -> jobs - jobs-list(part_2)
This commit is contained in:
parent
7b688066a8
commit
d86996be01
|
@ -26,11 +26,16 @@ import { toastNotifications } from 'ui/notify';
|
|||
import { loadFullJob } from '../utils';
|
||||
import { mlCreateWatchService } from '../../../../jobs/new_job/simple/components/watcher/create_watch_service';
|
||||
import { CreateWatch } from '../../../../jobs/new_job/simple/components/watcher/create_watch_view';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
|
||||
function getSuccessToast(id, url) {
|
||||
function getSuccessToast(id, url, intl) {
|
||||
return {
|
||||
title: `Watch ${id} created successfully`,
|
||||
title: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.createWatchFlyout.watchCreatedSuccessfullyNotificationMessage',
|
||||
defaultMessage: 'Watch {id} created successfully' },
|
||||
{ id }
|
||||
),
|
||||
text: (
|
||||
<React.Fragment>
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
|
||||
|
@ -41,7 +46,10 @@ function getSuccessToast(id, url) {
|
|||
target="_blank"
|
||||
iconType="link"
|
||||
>
|
||||
Edit watch
|
||||
{intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.createWatchFlyout.editWatchButtonLabel',
|
||||
defaultMessage: 'Edit watch' }
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -50,7 +58,7 @@ function getSuccessToast(id, url) {
|
|||
};
|
||||
}
|
||||
|
||||
export class CreateWatchFlyout extends Component {
|
||||
class CreateWatchFlyoutUI extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -95,13 +103,17 @@ export class CreateWatchFlyout extends Component {
|
|||
}
|
||||
|
||||
save = () => {
|
||||
const { intl } = this.props;
|
||||
mlCreateWatchService.createNewWatch(this.state.jobId)
|
||||
.then((resp) => {
|
||||
toastNotifications.addSuccess(getSuccessToast(resp.id, resp.url));
|
||||
toastNotifications.addSuccess(getSuccessToast(resp.id, resp.url, intl));
|
||||
this.closeFlyout();
|
||||
})
|
||||
.catch((error) => {
|
||||
toastNotifications.addDanger(`Could not save watch`);
|
||||
toastNotifications.addDanger(intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.createWatchFlyout.watchNotSavedErrorNotificationMessage',
|
||||
defaultMessage: 'Could not save watch'
|
||||
}));
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
@ -125,7 +137,11 @@ export class CreateWatchFlyout extends Component {
|
|||
<EuiFlyoutHeader>
|
||||
<EuiTitle>
|
||||
<h2>
|
||||
Create watch for {jobId}
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.createWatchFlyout.pageTitle"
|
||||
defaultMessage="Create watch for {jobId}"
|
||||
values={{ jobId }}
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
|
@ -145,7 +161,10 @@ export class CreateWatchFlyout extends Component {
|
|||
onClick={this.closeFlyout}
|
||||
flush="left"
|
||||
>
|
||||
Close
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.createWatchFlyout.closeButtonLabel"
|
||||
defaultMessage="Close"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -153,7 +172,10 @@ export class CreateWatchFlyout extends Component {
|
|||
onClick={this.save}
|
||||
fill
|
||||
>
|
||||
Save
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.createWatchFlyout.saveButtonLabel"
|
||||
defaultMessage="Save"
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -169,8 +191,9 @@ export class CreateWatchFlyout extends Component {
|
|||
|
||||
}
|
||||
}
|
||||
CreateWatchFlyout.propTypes = {
|
||||
CreateWatchFlyoutUI.propTypes = {
|
||||
setShowFunction: PropTypes.func.isRequired,
|
||||
unsetShowFunction: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export const CreateWatchFlyout = injectI18n(CreateWatchFlyoutUI);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { detectorToString } from 'plugins/ml/util/string_utils';
|
||||
import { formatValues, filterObjects } from './format_values';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export function extractJobDetails(job) {
|
||||
|
||||
|
@ -15,14 +16,18 @@ export function extractJobDetails(job) {
|
|||
}
|
||||
|
||||
const general = {
|
||||
title: 'General',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.generalTitle', {
|
||||
defaultMessage: 'General'
|
||||
}),
|
||||
position: 'left',
|
||||
items: filterObjects(job, true).map(formatValues)
|
||||
};
|
||||
|
||||
|
||||
const customUrl = {
|
||||
title: 'Custom URLs',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.customUrlsTitle', {
|
||||
defaultMessage: 'Custom URLs'
|
||||
}),
|
||||
position: 'right',
|
||||
items: []
|
||||
};
|
||||
|
@ -31,7 +36,9 @@ export function extractJobDetails(job) {
|
|||
}
|
||||
|
||||
const node = {
|
||||
title: 'Node',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.nodeTitle', {
|
||||
defaultMessage: 'Node'
|
||||
}),
|
||||
position: 'right',
|
||||
items: []
|
||||
};
|
||||
|
@ -40,7 +47,9 @@ export function extractJobDetails(job) {
|
|||
}
|
||||
|
||||
const detectors = {
|
||||
title: 'Detectors',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.detectorsTitle', {
|
||||
defaultMessage: 'Detectors'
|
||||
}),
|
||||
position: 'left',
|
||||
items: []
|
||||
};
|
||||
|
@ -55,31 +64,41 @@ export function extractJobDetails(job) {
|
|||
}
|
||||
|
||||
const influencers = {
|
||||
title: 'Influencers',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.influencersTitle', {
|
||||
defaultMessage: 'Influencers'
|
||||
}),
|
||||
position: 'left',
|
||||
items: job.analysis_config.influencers.map(i => ['', i])
|
||||
};
|
||||
|
||||
const analysisConfig = {
|
||||
title: 'Analysis config',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.analysisConfigTitle', {
|
||||
defaultMessage: 'Analysis config'
|
||||
}),
|
||||
position: 'left',
|
||||
items: filterObjects(job.analysis_config)
|
||||
};
|
||||
|
||||
const analysisLimits = {
|
||||
title: 'Analysis limits',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.analysisLimitsTitle', {
|
||||
defaultMessage: 'Analysis limits'
|
||||
}),
|
||||
position: 'left',
|
||||
items: filterObjects(job.analysis_limits)
|
||||
};
|
||||
|
||||
const dataDescription = {
|
||||
title: 'Data description',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.dataDescriptionTitle', {
|
||||
defaultMessage: 'Data description'
|
||||
}),
|
||||
position: 'right',
|
||||
items: filterObjects(job.data_description)
|
||||
};
|
||||
|
||||
const datafeed = {
|
||||
title: 'Datafeed',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.datafeedTitle', {
|
||||
defaultMessage: 'Datafeed'
|
||||
}),
|
||||
position: 'left',
|
||||
items: filterObjects(job.datafeed_config, true, true)
|
||||
};
|
||||
|
@ -88,13 +107,17 @@ export function extractJobDetails(job) {
|
|||
}
|
||||
|
||||
const counts = {
|
||||
title: 'Counts',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.countsTitle', {
|
||||
defaultMessage: 'Counts'
|
||||
}),
|
||||
position: 'left',
|
||||
items: filterObjects(job.data_counts).map(formatValues)
|
||||
};
|
||||
|
||||
const modelSizeStats = {
|
||||
title: 'Model size stats',
|
||||
title: i18n.translate('xpack.ml.jobsList.jobDetails.modelSizeStatsTitle', {
|
||||
defaultMessage: 'Model size stats'
|
||||
}),
|
||||
position: 'right',
|
||||
items: filterObjects(job.model_size_stats).map(formatValues)
|
||||
};
|
||||
|
|
|
@ -28,6 +28,7 @@ import chrome from 'ui/chrome';
|
|||
import { FORECAST_REQUEST_STATE } from 'plugins/ml/../common/constants/states';
|
||||
import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed';
|
||||
import { mlForecastService } from 'plugins/ml/services/forecast_service';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
const MAX_FORECASTS = 500;
|
||||
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
@ -35,7 +36,7 @@ const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
|||
/**
|
||||
* Table component for rendering the lists of forecasts run on an ML job.
|
||||
*/
|
||||
class ForecastsTable extends Component {
|
||||
class ForecastsTableUI extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -63,7 +64,10 @@ class ForecastsTable extends Component {
|
|||
console.log('Error loading list of forecasts for jobs list:', resp);
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
errorMessage: 'Error loading the list of forecasts run on this job',
|
||||
errorMessage: this.props.intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.loadingErrorMessage',
|
||||
defaultMessage: 'Error loading the list of forecasts run on this job'
|
||||
}),
|
||||
forecasts: []
|
||||
});
|
||||
});
|
||||
|
@ -150,65 +154,110 @@ class ForecastsTable extends Component {
|
|||
if (forecasts.length === 0) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
title="No forecasts have been run for this job"
|
||||
title={(<FormattedMessage
|
||||
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsTitle"
|
||||
defaultMessage="No forecasts have been run for this job"
|
||||
/>)}
|
||||
iconType="iInCircle"
|
||||
>
|
||||
<p>
|
||||
To run a forecast,
|
||||
open the <EuiLink onClick={() => this.openSingleMetricView()}>Single Metric Viewer</EuiLink>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsDescription"
|
||||
defaultMessage="To run a forecast, open the {singleMetricViewerLink}"
|
||||
values={{
|
||||
singleMetricViewerLink: (
|
||||
<EuiLink onClick={() => this.openSingleMetricView()}>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.jobDetails.forecastsTable.noForecastsDescription.linkText"
|
||||
defaultMessage="Single Metric Viewer"
|
||||
/>
|
||||
</EuiLink>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
}
|
||||
|
||||
const { intl } = this.props;
|
||||
|
||||
const columns = [
|
||||
{
|
||||
field: 'forecast_create_timestamp',
|
||||
name: 'Created',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.createdLabel',
|
||||
defaultMessage: 'Created'
|
||||
}),
|
||||
dataType: 'date',
|
||||
render: (date) => formatDate(date, TIME_FORMAT),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_start_timestamp',
|
||||
name: 'From',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.fromLabel',
|
||||
defaultMessage: 'From'
|
||||
}),
|
||||
dataType: 'date',
|
||||
render: (date) => formatDate(date, TIME_FORMAT),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_end_timestamp',
|
||||
name: 'To',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.toLabel',
|
||||
defaultMessage: 'To'
|
||||
}),
|
||||
dataType: 'date',
|
||||
render: (date) => formatDate(date, TIME_FORMAT),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_status',
|
||||
name: 'Status',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.statusLabel',
|
||||
defaultMessage: 'Status'
|
||||
}),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_memory_bytes',
|
||||
name: 'Memory size',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.memorySizeLabel',
|
||||
defaultMessage: 'Memory size'
|
||||
}),
|
||||
render: (bytes) => formatNumber(bytes, '0b'),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'processing_time_ms',
|
||||
name: 'Processing time',
|
||||
render: (ms) => `${ms} ms`,
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.processingTimeLabel',
|
||||
defaultMessage: 'Processing time'
|
||||
}),
|
||||
render: (ms) => intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.msTimeUnitLabel',
|
||||
defaultMessage: '{ms} ms' }, {
|
||||
ms
|
||||
}),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_expiry_timestamp',
|
||||
name: 'Expires',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.expiresLabel',
|
||||
defaultMessage: 'Expires'
|
||||
}),
|
||||
render: (date) => formatDate(date, TIME_FORMAT),
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'forecast_messages',
|
||||
name: 'Messages',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.messagesLabel',
|
||||
defaultMessage: 'Messages'
|
||||
}),
|
||||
sortable: false,
|
||||
render: (messages) => {
|
||||
return (
|
||||
|
@ -221,7 +270,10 @@ class ForecastsTable extends Component {
|
|||
}
|
||||
},
|
||||
{
|
||||
name: 'View',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.forecastsTable.viewLabel',
|
||||
defaultMessage: 'View'
|
||||
}),
|
||||
render: (forecast) => (
|
||||
<EuiButton
|
||||
onClick={() => this.openSingleMetricView(forecast)}
|
||||
|
@ -247,8 +299,10 @@ class ForecastsTable extends Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
ForecastsTable.propTypes = {
|
||||
ForecastsTableUI.propTypes = {
|
||||
job: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
const ForecastsTable = injectI18n(ForecastsTableUI);
|
||||
|
||||
export { ForecastsTable };
|
||||
|
|
|
@ -21,8 +21,9 @@ import { DatafeedPreviewPane } from './datafeed_preview_tab';
|
|||
import { ForecastsTable } from './forecasts_table';
|
||||
import { JobDetailsPane } from './job_details_pane';
|
||||
import { JobMessagesPane } from './job_messages_pane';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
export class JobDetails extends Component {
|
||||
class JobDetailsUI extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -63,38 +64,64 @@ export class JobDetails extends Component {
|
|||
modelSizeStats
|
||||
} = extractJobDetails(job);
|
||||
|
||||
const { intl } = this.props;
|
||||
|
||||
const tabs = [{
|
||||
id: 'job-settings',
|
||||
name: 'Job settings',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.jobSettingsLabel',
|
||||
defaultMessage: 'Job settings'
|
||||
}),
|
||||
content: <JobDetailsPane sections={[general, customUrl, node]} />,
|
||||
time: job.open_time
|
||||
}, {
|
||||
id: 'job-config',
|
||||
name: 'Job config',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.jobConfigLabel',
|
||||
defaultMessage: 'Job config'
|
||||
}),
|
||||
content: <JobDetailsPane sections={[detectors, influencers, analysisConfig, analysisLimits, dataDescription]} />,
|
||||
}, {
|
||||
id: 'datafeed',
|
||||
name: 'Datafeed',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.datafeedLabel',
|
||||
defaultMessage: 'Datafeed'
|
||||
}),
|
||||
content: <JobDetailsPane sections={[datafeed]} />,
|
||||
}, {
|
||||
id: 'counts',
|
||||
name: 'Counts',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.countsLabel',
|
||||
defaultMessage: 'Counts'
|
||||
}),
|
||||
content: <JobDetailsPane sections={[counts, modelSizeStats]} />,
|
||||
}, {
|
||||
id: 'json',
|
||||
name: 'JSON',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.jsonLabel',
|
||||
defaultMessage: 'JSON'
|
||||
}),
|
||||
content: <JsonPane job={job} />,
|
||||
}, {
|
||||
id: 'job-messages',
|
||||
name: 'Job messages',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.jobMessagesLabel',
|
||||
defaultMessage: 'Job messages'
|
||||
}),
|
||||
content: <JobMessagesPane job={job} />,
|
||||
}, {
|
||||
id: 'datafeed-preview',
|
||||
name: 'Datafeed preview',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.datafeedPreviewLabel',
|
||||
defaultMessage: 'Datafeed preview'
|
||||
}),
|
||||
content: <DatafeedPreviewPane job={job} />,
|
||||
}, {
|
||||
id: 'forecasts',
|
||||
name: 'Forecasts',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.tabs.forecastsLabel',
|
||||
defaultMessage: 'Forecasts'
|
||||
}),
|
||||
content: <ForecastsTable job={job} />,
|
||||
}
|
||||
];
|
||||
|
@ -111,9 +138,11 @@ export class JobDetails extends Component {
|
|||
}
|
||||
}
|
||||
}
|
||||
JobDetails.propTypes = {
|
||||
JobDetailsUI.propTypes = {
|
||||
jobId: PropTypes.string.isRequired,
|
||||
job: PropTypes.object,
|
||||
addYourself: PropTypes.func.isRequired,
|
||||
removeYourself: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export const JobDetails = injectI18n(JobDetailsUI);
|
||||
|
|
|
@ -18,10 +18,11 @@ import {
|
|||
import { formatDate } from '@elastic/eui/lib/services/format';
|
||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||
import { JobIcon } from '../job_message_icon';
|
||||
import { injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
||||
|
||||
export class JobMessagesPane extends Component {
|
||||
class JobMessagesPaneUI extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -44,18 +45,28 @@ export class JobMessagesPane extends Component {
|
|||
|
||||
render() {
|
||||
const { messages } = this.state;
|
||||
const { intl } = this.props;
|
||||
const columns = [{
|
||||
name: '',
|
||||
render: item => (<JobIcon message={item} />)
|
||||
}, {
|
||||
name: 'Time',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.messagesPane.timeLabel',
|
||||
defaultMessage: 'Time'
|
||||
}),
|
||||
render: item => formatDate(item.timestamp, TIME_FORMAT)
|
||||
}, {
|
||||
field: 'node_name',
|
||||
name: 'Node',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.messagesPane.nodeLabel',
|
||||
defaultMessage: 'Node'
|
||||
}),
|
||||
}, {
|
||||
field: 'message',
|
||||
name: 'Message',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobDetails.messagesPane.messageLabel',
|
||||
defaultMessage: 'Message'
|
||||
}),
|
||||
}
|
||||
];
|
||||
return (
|
||||
|
@ -71,7 +82,8 @@ export class JobMessagesPane extends Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
JobMessagesPane.propTypes = {
|
||||
JobMessagesPaneUI.propTypes = {
|
||||
job: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export const JobMessagesPane = injectI18n(JobMessagesPaneUI);
|
||||
|
|
|
@ -20,6 +20,7 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
|
||||
|
||||
function loadGroups() {
|
||||
return ml.jobs.groups()
|
||||
|
@ -28,7 +29,14 @@ function loadGroups() {
|
|||
value: g.id,
|
||||
view: (
|
||||
<div className="group-item">
|
||||
<JobGroup name={g.id} /> <span>({g.jobIds.length} job{(g.jobIds.length === 1) ? '' : 's'})</span>
|
||||
<JobGroup name={g.id} />
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="xpack.ml.jobsList.jobFilterBar.jobGroupTitle"
|
||||
defaultMessage="({jobsCount, plural, one {# job} other {# jobs}})"
|
||||
values={{ jobsCount: g.jobIds.length }}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}));
|
||||
|
@ -39,7 +47,7 @@ function loadGroups() {
|
|||
});
|
||||
}
|
||||
|
||||
export class JobFilterBar extends Component {
|
||||
class JobFilterBarUI extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -69,7 +77,12 @@ export class JobFilterBar extends Component {
|
|||
<EuiFlexItem grow={false}>
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
title={`Invalid search: ${error.message}`}
|
||||
title={(<FormattedMessage
|
||||
id="xpack.ml.jobsList.jobFilterBar.invalidSearchErrorMessage"
|
||||
defaultMessage="Invalid search: {errorMessage}"
|
||||
values={{ errorMessage: error.message }}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<EuiSpacer size="l" />
|
||||
</EuiFlexItem>
|
||||
|
@ -77,6 +90,7 @@ export class JobFilterBar extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props;
|
||||
const filters = [
|
||||
{
|
||||
type: 'field_value_toggle_group',
|
||||
|
@ -84,15 +98,24 @@ export class JobFilterBar extends Component {
|
|||
items: [
|
||||
{
|
||||
value: 'opened',
|
||||
name: 'Opened'
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.openedLabel',
|
||||
defaultMessage: 'Opened'
|
||||
})
|
||||
},
|
||||
{
|
||||
value: 'closed',
|
||||
name: 'Closed'
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.closedLabel',
|
||||
defaultMessage: 'Closed'
|
||||
})
|
||||
},
|
||||
{
|
||||
value: 'failed',
|
||||
name: 'Failed'
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.failedLabel',
|
||||
defaultMessage: 'Failed'
|
||||
})
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -102,18 +125,27 @@ export class JobFilterBar extends Component {
|
|||
items: [
|
||||
{
|
||||
value: 'started',
|
||||
name: 'Started'
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.startedLabel',
|
||||
defaultMessage: 'Started'
|
||||
})
|
||||
},
|
||||
{
|
||||
value: 'stopped',
|
||||
name: 'Stopped'
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.stoppedLabel',
|
||||
defaultMessage: 'Stopped'
|
||||
})
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'field_value_selection',
|
||||
field: 'groups',
|
||||
name: 'Group',
|
||||
name: intl.formatMessage({
|
||||
id: 'xpack.ml.jobsList.jobFilterBar.groupLabel',
|
||||
defaultMessage: 'Group'
|
||||
}),
|
||||
multiSelect: 'or',
|
||||
cache: 10000,
|
||||
options: () => loadGroups()
|
||||
|
@ -138,7 +170,8 @@ export class JobFilterBar extends Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
JobFilterBar.propTypes = {
|
||||
JobFilterBarUI.propTypes = {
|
||||
setFilters: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export const JobFilterBar = injectI18n(JobFilterBarUI);
|
||||
|
|
|
@ -11,6 +11,7 @@ import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar
|
|||
import { mlJobService } from 'plugins/ml/services/job_service';
|
||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||
import { JOB_STATE, DATAFEED_STATE } from 'plugins/ml/../common/constants/states';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export function loadFullJob(jobId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -49,7 +50,9 @@ export function forceStartDatafeeds(jobs, start, end, finish = () => {}) {
|
|||
})
|
||||
.catch((error) => {
|
||||
mlMessageBarService.notify.error(error);
|
||||
toastNotifications.addDanger(`Jobs failed to start`, error);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.startJobErrorMessage', {
|
||||
defaultMessage: 'Jobs failed to start'
|
||||
}), error);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -64,7 +67,9 @@ export function stopDatafeeds(jobs, finish = () => {}) {
|
|||
})
|
||||
.catch((error) => {
|
||||
mlMessageBarService.notify.error(error);
|
||||
toastNotifications.addDanger(`Jobs failed to stop`, error);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.stopJobErrorMessage', {
|
||||
defaultMessage: 'Jobs failed to stop'
|
||||
}), error);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -87,30 +92,54 @@ function showResults(resp, action) {
|
|||
let actionText = '';
|
||||
let actionTextPT = '';
|
||||
if (action === DATAFEED_STATE.STARTED) {
|
||||
actionText = 'start';
|
||||
actionTextPT = 'started';
|
||||
actionText = i18n.translate('xpack.ml.jobsList.startActionStatusText', {
|
||||
defaultMessage: 'start'
|
||||
});
|
||||
actionTextPT = i18n.translate('xpack.ml.jobsList.startedActionStatusText', {
|
||||
defaultMessage: 'started'
|
||||
});
|
||||
} else if (action === DATAFEED_STATE.STOPPED) {
|
||||
actionText = 'stop';
|
||||
actionTextPT = 'stopped';
|
||||
actionText = i18n.translate('xpack.ml.jobsList.stopActionStatusText', {
|
||||
defaultMessage: 'stop'
|
||||
});
|
||||
actionTextPT = i18n.translate('xpack.ml.jobsList.stoppedActionStatusText', {
|
||||
defaultMessage: 'stopped'
|
||||
});
|
||||
} else if (action === DATAFEED_STATE.DELETED) {
|
||||
actionText = 'delete';
|
||||
actionTextPT = 'deleted';
|
||||
actionText = i18n.translate('xpack.ml.jobsList.deleteActionStatusText', {
|
||||
defaultMessage: 'delete'
|
||||
});
|
||||
actionTextPT = i18n.translate('xpack.ml.jobsList.deletedActionStatusText', {
|
||||
defaultMessage: 'deleted'
|
||||
});
|
||||
} else if (action === JOB_STATE.CLOSED) {
|
||||
actionText = 'close';
|
||||
actionTextPT = 'closed';
|
||||
actionText = i18n.translate('xpack.ml.jobsList.closeActionStatusText', {
|
||||
defaultMessage: 'close'
|
||||
});
|
||||
actionTextPT = i18n.translate('xpack.ml.jobsList.closedActionStatusText', {
|
||||
defaultMessage: 'closed'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (successes.length > 1) {
|
||||
toastNotifications.addSuccess(`${successes.length} jobs ${actionTextPT} successfully`);
|
||||
} else if (successes.length === 1) {
|
||||
toastNotifications.addSuccess(`${successes[0]} ${actionTextPT} successfully`);
|
||||
}
|
||||
toastNotifications.addSuccess(i18n.translate('xpack.ml.jobsList.actionExecuteSuccessfullyNotificationMessage', {
|
||||
defaultMessage: '{successesJobsCount, plural, one{{successJob}} other{# jobs}} {actionTextPT} successfully',
|
||||
values: {
|
||||
successesJobsCount: successes.length,
|
||||
successJob: successes[0],
|
||||
actionTextPT
|
||||
}
|
||||
}));
|
||||
|
||||
if (failures.length > 0) {
|
||||
failures.forEach((f) => {
|
||||
mlMessageBarService.notify.error(f.result.error);
|
||||
toastNotifications.addDanger(`${f.id} failed to ${actionText}`);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.actionFailedNotificationMessage', {
|
||||
defaultMessage: '{failureId} failed to {actionText}',
|
||||
values: {
|
||||
failureId: f.id,
|
||||
actionText
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +152,10 @@ export function cloneJob(jobId) {
|
|||
})
|
||||
.catch((error) => {
|
||||
mlMessageBarService.notify.error(error);
|
||||
toastNotifications.addDanger(`Could not clone ${jobId}. Job could not be found`);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.cloneJobErrorMessage', {
|
||||
defaultMessage: 'Could not clone {jobId}. Job could not be found',
|
||||
values: { jobId }
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -136,7 +168,9 @@ export function closeJobs(jobs, finish = () => {}) {
|
|||
})
|
||||
.catch((error) => {
|
||||
mlMessageBarService.notify.error(error);
|
||||
toastNotifications.addDanger(`Jobs failed to close`, error);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.closeJobErrorMessage', {
|
||||
defaultMessage: 'Jobs failed to close',
|
||||
}), error);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -150,7 +184,9 @@ export function deleteJobs(jobs, finish = () => {}) {
|
|||
})
|
||||
.catch((error) => {
|
||||
mlMessageBarService.notify.error(error);
|
||||
toastNotifications.addDanger(`Jobs failed to delete`, error);
|
||||
toastNotifications.addDanger(i18n.translate('xpack.ml.jobsList.deleteJobErrorMessage', {
|
||||
defaultMessage: 'Jobs failed to delete',
|
||||
}), error);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue