diff --git a/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js
index 95a48eabd3c70..2b1b0641c1528 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.container.js
@@ -5,13 +5,23 @@
*/
import { connect } from 'react-redux';
-import { JobActionMenu as JobActionMenuComponent } from './job_action_menu';
+
+import { isUpdating } from '../../../store/selectors';
+
import {
startJobs,
stopJobs,
deleteJobs,
} from '../../../store/actions';
+import { JobActionMenu as JobActionMenuComponent } from './job_action_menu';
+
+const mapStateToProps = (state) => {
+ return {
+ isUpdating: isUpdating(state),
+ };
+};
+
const mapDispatchToProps = (dispatch, { jobs }) => {
const jobIds = jobs.map(job => job.id);
return {
@@ -27,4 +37,4 @@ const mapDispatchToProps = (dispatch, { jobs }) => {
};
};
-export const JobActionMenu = connect(undefined, mapDispatchToProps)(JobActionMenuComponent);
+export const JobActionMenu = connect(mapStateToProps, mapDispatchToProps)(JobActionMenuComponent);
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js
index 6e7a7de948d3d..acdd44882b9ca 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/components/job_action_menu/job_action_menu.js
@@ -6,13 +6,17 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-import { injectI18n } from '@kbn/i18n/react';
+import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import {
EuiButton,
EuiContextMenu,
+ EuiFlexGroup,
+ EuiFlexItem,
EuiIcon,
+ EuiLoadingSpinner,
EuiPopover,
+ EuiText,
} from '@elastic/eui';
import { ConfirmDeleteModal } from './confirm_delete_modal';
@@ -23,6 +27,7 @@ class JobActionMenuUi extends Component {
startJobs: PropTypes.func.isRequired,
stopJobs: PropTypes.func.isRequired,
deleteJobs: PropTypes.func.isRequired,
+ isUpdating: PropTypes.bool.isRequired,
iconSide: PropTypes.string,
anchorPosition: PropTypes.string,
label: PropTypes.node,
@@ -89,19 +94,21 @@ class JobActionMenuUi extends Component {
});
}
- items.push({
- name: intl.formatMessage({
- id: 'xpack.rollupJobs.jobActionMenu.deleteJobLabel',
- defaultMessage: 'Delete {isSingleSelection, plural, one {job} other {jobs}}',
- }, {
- isSingleSelection,
- }),
- icon: ,
- onClick: () => {
- this.closePopover();
- this.openDeleteConfirmationModal();
- },
- });
+ if (this.canDeleteJobs()) {
+ items.push({
+ name: intl.formatMessage({
+ id: 'xpack.rollupJobs.jobActionMenu.deleteJobLabel',
+ defaultMessage: 'Delete {isSingleSelection, plural, one {job} other {jobs}}',
+ }, {
+ isSingleSelection,
+ }),
+ icon: ,
+ onClick: () => {
+ this.closePopover();
+ this.openDeleteConfirmationModal();
+ },
+ });
+ }
const panelTree = {
id: 0,
@@ -145,6 +152,12 @@ class JobActionMenuUi extends Component {
return jobs.some(job => job.status === 'started');
}
+ canDeleteJobs() {
+ const { jobs } = this.props;
+ const areAllJobsStopped = jobs.findIndex(job => job.status === 'started') === -1;
+ return areAllJobsStopped;
+ }
+
confirmDeleteModal = () => {
const { showDeleteConfirmation } = this.state;
@@ -179,7 +192,27 @@ class JobActionMenuUi extends Component {
};
render() {
- const { intl } = this.props;
+ const { intl, isUpdating } = this.props;
+
+ if (isUpdating) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
const jobCount = this.props.jobs.length;
const {
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js
index 94814bd0b5957..25d4968a44868 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/job_create/navigation/navigation.js
@@ -6,6 +6,7 @@
import React from 'react';
import PropTypes from 'prop-types';
+import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
import {
EuiButton,
@@ -16,7 +17,7 @@ import {
EuiLoadingSpinner,
} from '@elastic/eui';
-export const Navigation = ({
+const NavigationUi = ({
isSaving,
hasNextStep,
hasPreviousStep,
@@ -33,7 +34,12 @@ export const Navigation = ({
- Saving
+
+
+
);
@@ -47,7 +53,10 @@ export const Navigation = ({
iconType="arrowLeft"
onClick={goToPreviousStep}
>
- Back
+
);
@@ -64,7 +73,10 @@ export const Navigation = ({
isDisabled={!canGoToNextStep}
fill
>
- Next
+
);
@@ -77,7 +89,10 @@ export const Navigation = ({
onClick={save}
fill
>
- Save
+
);
@@ -91,7 +106,7 @@ export const Navigation = ({
);
};
-Navigation.propTypes = {
+NavigationUi.propTypes = {
hasNextStep: PropTypes.bool.isRequired,
hasPreviousStep: PropTypes.bool.isRequired,
isSaving: PropTypes.bool.isRequired,
@@ -100,3 +115,5 @@ Navigation.propTypes = {
save: PropTypes.func.isRequired,
canGoToNextStep: PropTypes.bool.isRequired,
};
+
+export const Navigation = injectI18n(NavigationUi);
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js
index b0281994b55a5..e728a58313a0c 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.container.js
@@ -5,7 +5,6 @@
*/
import { connect } from 'react-redux';
-import { JobList as JobListView } from './job_list';
import {
getPageOfJobs,
@@ -20,6 +19,8 @@ import {
closeDetailPanel,
} from '../../store/actions';
+import { JobList as JobListView } from './job_list';
+
const mapStateToProps = (state) => {
return {
jobs: getPageOfJobs(state),
diff --git a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js
index 7c292181e76da..d9b4ce1bf5ba7 100644
--- a/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js
+++ b/x-pack/plugins/rollup/public/crud_app/sections/job_list/job_list.js
@@ -87,6 +87,7 @@ export class JobListUi extends Component {
// this page.
this.props.closeDetailPanel();
}
+
getHeaderSection() {
return (
@@ -101,6 +102,7 @@ export class JobListUi extends Component {
);
}
+
renderNoPermission() {
const { intl } = this.props;
const title = intl.formatMessage({
@@ -124,10 +126,11 @@ export class JobListUi extends Component {
);
}
+
renderEmpty() {
return (
setTimeout(() => {
+ resolve();
+ }, 300));
+
+ return Promise.all([promise, noticeableDelay]);
+}
diff --git a/x-pack/plugins/rollup/public/crud_app/store/action_types.js b/x-pack/plugins/rollup/public/crud_app/store/action_types.js
index 81ebb45278354..9c3235d3ac427 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/action_types.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/action_types.js
@@ -22,6 +22,11 @@ export const CREATE_JOB_SUCCESS = 'CREATE_JOB_SUCCESS';
export const CREATE_JOB_FAILURE = 'CREATE_JOB_FAILURE';
export const CLEAR_CREATE_JOB_ERRORS = 'CLEAR_CREATE_JOB_ERRORS';
+// Update job (start, stop, delete)
+export const UPDATE_JOB_START = 'UPDATE_JOB_START';
+export const UPDATE_JOB_SUCCESS = 'UPDATE_JOB_SUCCESS';
+export const UPDATE_JOB_FAILURE = 'UPDATE_JOB_FAILURE';
+
// Table state
export const FILTER_CHANGED = 'FILTER_CHANGED';
export const PAGE_CHANGED = 'PAGE_CHANGED';
diff --git a/x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js b/x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js
index 9174869187335..fe26807944569 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/actions/change_job_status.js
@@ -8,25 +8,57 @@ import { toastNotifications } from 'ui/notify';
import {
startJobs as sendStartJobsRequest,
stopJobs as sendStopJobsRequest,
+ createNoticeableDelay,
} from '../../services';
+
+import {
+ UPDATE_JOB_START,
+ UPDATE_JOB_SUCCESS,
+ UPDATE_JOB_FAILURE,
+} from '../action_types';
+
import { refreshJobs } from './refresh_jobs';
export const startJobs = (jobIds) => async (dispatch) => {
+ dispatch({
+ type: UPDATE_JOB_START,
+ });
+
try {
- await sendStartJobsRequest(jobIds);
+ await createNoticeableDelay(sendStartJobsRequest(jobIds));
} catch (error) {
+ dispatch({
+ type: UPDATE_JOB_FAILURE,
+ });
+
return toastNotifications.addDanger(error.data.message);
}
+ dispatch({
+ type: UPDATE_JOB_SUCCESS,
+ });
+
dispatch(refreshJobs());
};
export const stopJobs = (jobIds) => async (dispatch) => {
+ dispatch({
+ type: UPDATE_JOB_START,
+ });
+
try {
- await sendStopJobsRequest(jobIds);
+ await createNoticeableDelay(sendStopJobsRequest(jobIds));
} catch (error) {
+ dispatch({
+ type: UPDATE_JOB_FAILURE,
+ });
+
return toastNotifications.addDanger(error.data.message);
}
+ dispatch({
+ type: UPDATE_JOB_SUCCESS,
+ });
+
dispatch(refreshJobs());
};
diff --git a/x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js b/x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
index 2404ab3a02c93..6ab2913870b66 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/actions/delete_jobs.js
@@ -6,16 +6,30 @@
import { toastNotifications } from 'ui/notify';
-import { deleteJobs as sendDeleteJobsRequest } from '../../services';
+import { deleteJobs as sendDeleteJobsRequest, createNoticeableDelay } from '../../services';
import { getDetailPanelJob } from '../selectors';
+import {
+ UPDATE_JOB_START,
+ UPDATE_JOB_SUCCESS,
+ UPDATE_JOB_FAILURE,
+} from '../action_types';
+
import { refreshJobs } from './refresh_jobs';
import { closeDetailPanel } from './detail_panel';
export const deleteJobs = (jobIds) => async (dispatch, getState) => {
+ dispatch({
+ type: UPDATE_JOB_START,
+ });
+
try {
- await sendDeleteJobsRequest(jobIds);
+ await createNoticeableDelay(sendDeleteJobsRequest(jobIds));
} catch (error) {
+ dispatch({
+ type: UPDATE_JOB_FAILURE,
+ });
+
return toastNotifications.addDanger(error.data.message);
}
@@ -31,5 +45,9 @@ export const deleteJobs = (jobIds) => async (dispatch, getState) => {
dispatch(closeDetailPanel());
}
+ dispatch({
+ type: UPDATE_JOB_SUCCESS,
+ });
+
dispatch(refreshJobs());
};
diff --git a/x-pack/plugins/rollup/public/crud_app/store/reducers/index.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/index.js
index 2fa141a50ab27..1653adae82ea5 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/reducers/index.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/reducers/index.js
@@ -9,10 +9,12 @@ import { jobs } from './jobs';
import { tableState } from './table_state';
import { detailPanel } from './detail_panel';
import { createJob } from './create_job';
+import { updateJob } from './update_job';
export const rollupJobs = combineReducers({
jobs,
tableState,
detailPanel,
createJob,
+ updateJob,
});
diff --git a/x-pack/plugins/rollup/public/crud_app/store/reducers/update_job.js b/x-pack/plugins/rollup/public/crud_app/store/reducers/update_job.js
new file mode 100644
index 0000000000000..3be9857bba18f
--- /dev/null
+++ b/x-pack/plugins/rollup/public/crud_app/store/reducers/update_job.js
@@ -0,0 +1,40 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import {
+ UPDATE_JOB_START,
+ UPDATE_JOB_SUCCESS,
+ UPDATE_JOB_FAILURE,
+} from '../action_types';
+
+const initialState = {
+ isUpdating: false,
+ error: undefined,
+};
+
+export function updateJob(state = initialState, action) {
+ const { type } = action;
+
+ switch (type) {
+ case UPDATE_JOB_START:
+ return {
+ isUpdating: true,
+ };
+
+ case UPDATE_JOB_SUCCESS:
+ return {
+ isUpdating: false,
+ };
+
+ case UPDATE_JOB_FAILURE:
+ return {
+ isUpdating: false,
+ };
+
+ default:
+ return state;
+ }
+}
diff --git a/x-pack/plugins/rollup/public/crud_app/store/selectors/index.js b/x-pack/plugins/rollup/public/crud_app/store/selectors/index.js
index 5a6072e5e3d8a..5a0de43c8c8d6 100644
--- a/x-pack/plugins/rollup/public/crud_app/store/selectors/index.js
+++ b/x-pack/plugins/rollup/public/crud_app/store/selectors/index.js
@@ -24,6 +24,7 @@ export const isLoading = (state) => state.jobs.isLoading;
export const jobLoadError = (state) => state.jobs.jobLoadError;
export const isSaving = (state) => state.createJob.isSaving;
export const getCreateJobError = (state) => state.createJob.error;
+export const isUpdating = (state) => state.updateJob.isUpdating;
export const getJobStatusByJobName = (state, jobName) => {
const jobs = getJobs(state);