From 1a7302915609f4f74e5bbcd6e01a8c1b066dd1dd Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Wed, 17 Oct 2018 13:39:10 +0100 Subject: [PATCH] [ML] Add button for refreshing job list without full page refresh. (#24084) * Add refresh button for job list * Show load icon while refreshing * Move view build logic to jobsListView * Align job action buttons in ui * Extract RefreshJobsListButton component * update jobStatsBar to take list as prop --- .../jobs_list_view/jobs_list_view.js | 66 +++++++++++++++++-- .../jobs_list_view/styles/main.less | 12 ++++ .../jobs_stats_bar/jobs_stats_bar.js | 54 ++++----------- .../refresh_jobs_list_button/index.js | 9 +++ .../refresh_jobs_list_button.js | 29 ++++++++ .../plugins/ml/public/jobs/jobs_list/jobs.js | 57 ++-------------- .../ml/public/jobs/jobs_list/styles/main.less | 11 ---- 7 files changed, 126 insertions(+), 112 deletions(-) create mode 100644 x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/index.js create mode 100644 x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js delete mode 100644 x-pack/plugins/ml/public/jobs/jobs_list/styles/main.less diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js index d5594933cf86a..7dc842cf8cd93 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js @@ -18,12 +18,21 @@ import { DeleteJobModal } from '../delete_job_modal'; import { StartDatafeedModal } from '../start_datafeed_modal'; import { CreateWatchFlyout } from '../create_watch_flyout'; import { MultiJobActions } from '../multi_job_actions'; +import { NewJobButton } from '../new_job_button'; +import { JobStatsBar } from '../jobs_stats_bar'; +import { NodeAvailableWarning } from '../node_available_warning'; +import { RefreshJobsListButton } from '../refresh_jobs_list_button'; -import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from '@elastic/eui'; + const DEFAULT_REFRESH_INTERVAL_MS = 30000; const MINIMUM_REFRESH_INTERVAL_MS = 5000; let jobsRefreshInterval = null; @@ -33,6 +42,7 @@ export class JobsListView extends Component { super(props); this.state = { + isRefreshing: false, jobsSummaryList: [], filteredJobsSummaryList: [], fullJobsList: {}, @@ -204,7 +214,6 @@ export class JobsListView extends Component { return this.showCreateWatchFlyout; } - selectJobChange = (selectedJobs) => { this.setState({ selectedJobs }); } @@ -229,6 +238,14 @@ export class JobsListView extends Component { }); } + onRefreshClick = () => { + this.setState({ isRefreshing: true }); + this.refreshJobSummaryList(true); + } + isDoneRefreshing = () => { + this.setState({ isRefreshing: false }); + } + refreshJobSummaryList(forceRefresh = false) { if (forceRefresh === true || this.blockRefresh === false) { const expandedJobsIds = Object.keys(this.state.itemIdToExpandedRowMap); @@ -246,12 +263,13 @@ export class JobsListView extends Component { const filteredJobsSummaryList = filterJobs(jobsSummaryList, this.state.filterClauses); this.setState({ jobsSummaryList, filteredJobsSummaryList, fullJobsList }, () => { this.refreshSelectedJobs(); - this.props.updateJobStats(jobsSummaryList); }); Object.keys(this.updateFunctions).forEach((j) => { this.updateFunctions[j].setState({ job: fullJobsList[j] }); }); + + this.isDoneRefreshing(); }) .catch((error) => { console.error(error); @@ -259,7 +277,7 @@ export class JobsListView extends Component { } } - render() { + renderJobsListComponents() { const jobIds = this.state.jobsSummaryList.map(j => j.id); return (
@@ -310,7 +328,41 @@ export class JobsListView extends Component {
); } + + render() { + const { isRefreshing, jobsSummaryList } = this.state; + + return ( + + +
+ +
+
+ + + + + + + + +
+
+ +
+ + + + { this.renderJobsListComponents() } + + + ); + } } -JobsListView.propTypes = { - updateJobStats: PropTypes.func.isRequired, -}; + diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/styles/main.less b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/styles/main.less index 6ecb6002da3fa..59d59b5a2cc4b 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/styles/main.less +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_list_view/styles/main.less @@ -8,3 +8,15 @@ & > div:nth-child(2) { } } + +.job-management { + padding: 20px; +} + +.job-buttons-container { + float: right; +} + +.clear { + clear: both; +} diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js index 7f43d65bd1596..85bb66fca34f6 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/jobs_stats_bar/jobs_stats_bar.js @@ -9,9 +9,7 @@ import './styles/main.less'; import { JOB_STATE, DATAFEED_STATE } from 'plugins/ml/../common/constants/states'; import PropTypes from 'prop-types'; -import React, { - Component, -} from 'react'; +import React from 'react'; function createJobStats(jobsSummaryList) { @@ -76,46 +74,20 @@ Stat.propTypes = { stat: PropTypes.object.isRequired, }; -export class JobStatsBar extends Component { - constructor(props) { - super(props); - this.state = { - jobsSummaryList: [], - jobStats: {}, - }; - } - - updateJobStats = (jobsSummaryList) => { - const jobStats = createJobStats(jobsSummaryList); - this.setState({ - jobsSummaryList, - jobStats, - }); - }; +export const JobStatsBar = ({ jobsSummaryList }) => { + const jobStats = createJobStats(jobsSummaryList); + const stats = Object.keys(jobStats).map(k => jobStats[k]); - componentDidMount() { - this.props.setUpdateJobStats(this.updateJobStats); - } - - componentWillUnmount() { - this.props.unsetUpdateJobStats(); - } + return ( +
+ { + stats.filter(s => (s.show)).map(s => ) + } +
+ ); +}; - render() { - const { jobStats } = this.state; - const stats = Object.keys(jobStats).map(k => jobStats[k]); - - return ( -
- { - stats.filter(s => (s.show)).map(s => ) - } -
- ); - } -} JobStatsBar.propTypes = { - setUpdateJobStats: PropTypes.func.isRequired, - unsetUpdateJobStats: PropTypes.func.isRequired, + jobsSummaryList: PropTypes.array.isRequired, }; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/index.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/index.js new file mode 100644 index 0000000000000..ab7fe719bb04f --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/index.js @@ -0,0 +1,9 @@ +/* + * 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. + */ + + + +export { RefreshJobsListButton } from './refresh_jobs_list_button'; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js new file mode 100644 index 0000000000000..3aecf95d55f56 --- /dev/null +++ b/x-pack/plugins/ml/public/jobs/jobs_list/components/refresh_jobs_list_button/refresh_jobs_list_button.js @@ -0,0 +1,29 @@ +/* + * 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 React from 'react'; +import PropTypes from 'prop-types'; + +import { + EuiButtonEmpty, +} from '@elastic/eui'; + + +export const RefreshJobsListButton = ({ onRefreshClick, isRefreshing }) => ( + + Refresh + +); + +RefreshJobsListButton.propTypes = { + onRefreshClick: PropTypes.func.isRequired, + isRefreshing: PropTypes.bool.isRequired +}; diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/jobs.js b/x-pack/plugins/ml/public/jobs/jobs_list/jobs.js index 7e3c8516030b2..4d9c5a01db49b 100644 --- a/x-pack/plugins/ml/public/jobs/jobs_list/jobs.js +++ b/x-pack/plugins/ml/public/jobs/jobs_list/jobs.js @@ -5,60 +5,11 @@ */ -import './styles/main.less'; -import { NewJobButton } from './components/new_job_button'; import { JobsListView } from './components/jobs_list_view'; -import { JobStatsBar } from './components/jobs_stats_bar'; -import { NodeAvailableWarning } from './components/node_available_warning'; +import React from 'react'; -import React, { - Component -} from 'react'; -import { - EuiSpacer, -} from '@elastic/eui'; +export const JobsPage = () => ( + +); - -export class JobsPage extends Component { - constructor(props) { - super(props); - this.state = { - jobsSummaryList: [], - updateJobStats: () => {}, - }; - } - - setUpdateJobStats = (updateJobStats) => { - this.setState({ updateJobStats }); - } - - unsetUpdateJobStats = () => { - this.setUpdateJobStats(() => {}); - } - - render() { - return ( - - -
- -
-
- -
-
- -
- - - - -
- - ); - } -} diff --git a/x-pack/plugins/ml/public/jobs/jobs_list/styles/main.less b/x-pack/plugins/ml/public/jobs/jobs_list/styles/main.less deleted file mode 100644 index f203d785c603c..0000000000000 --- a/x-pack/plugins/ml/public/jobs/jobs_list/styles/main.less +++ /dev/null @@ -1,11 +0,0 @@ -.job-management { - padding: 20px; -} - -.new-job-button-container { - float: right; -} - -.clear { - clear: both; -}