From 373c5888e080843bf252bb4f776e8c17c4b667e2 Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 6 Jul 2017 14:37:46 +0200 Subject: [PATCH] SONAR-9508 Display worker counter in background tasks page --- server/sonar-web/src/main/js/api/ce.js | 7 + .../background-tasks/background-tasks.css | 9 + .../components/BackgroundTasksApp.js | 2 +- .../background-tasks/components/Header.js | 15 +- .../background-tasks/components/Workers.js | 108 +++++++ .../components/WorkersForm.js | 126 ++++++++ .../components/__tests__/Workers-test.js | 72 +++++ .../components/__tests__/WorkersForm-test.js | 52 ++++ .../__snapshots__/Workers-test.js.snap | 175 +++++++++++ .../__snapshots__/WorkersForm-test.js.snap | 283 ++++++++++++++++++ .../sonar-web/src/main/less/init/forms.less | 12 + .../resources/org/sonar/l10n/core.properties | 6 + 12 files changed, 862 insertions(+), 5 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/Workers-test.js create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/WorkersForm-test.js create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/Workers-test.js.snap create mode 100644 server/sonar-web/src/main/js/apps/background-tasks/components/__tests__/__snapshots__/WorkersForm-test.js.snap diff --git a/server/sonar-web/src/main/js/api/ce.js b/server/sonar-web/src/main/js/api/ce.js index bc4eb2283e2..4fa75478b1d 100644 --- a/server/sonar-web/src/main/js/api/ce.js +++ b/server/sonar-web/src/main/js/api/ce.js @@ -19,6 +19,7 @@ */ // @flow import { getJSON, post } from '../helpers/request'; +import throwGlobalError from '../app/utils/throwGlobalError'; export const getActivity = (data?: Object): Promise<*> => getJSON('/api/ce/activity', data); @@ -42,3 +43,9 @@ export const getTasksForComponent = (componentKey: string): Promise<*> => getJSON('/api/ce/component', { componentKey }); export const getTypes = (): Promise<*> => getJSON('/api/ce/task_types').then(r => r.taskTypes); + +export const getWorkers = (): Promise<{ canSetWorkerCount: boolean, value: number }> => + getJSON('/api/ce/worker_count').catch(throwGlobalError); + +export const setWorkerCount = (count: number): Promise => + post('/api/ce/set_worker_count', { count }).catch(throwGlobalError); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css b/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css index 2bad2aba5a0..a957b5f0250 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css +++ b/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css @@ -18,3 +18,12 @@ .bt-search-form-right { margin-left: auto !important; } + +.bt-workers-warning-icon { + position: relative; + top: -1px; +} + +.bt-workers-warning-icon::before { + color: #d3d3d3; +} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js index 4062eaea41a..a26112033ff 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js @@ -214,7 +214,7 @@ class BackgroundTasksApp extends React.PureComponent { return (
-
+
{ +type Props = { + component?: Object +}; + +export default function Header(props: Props) { return (

{translate('background_tasks.page')}

+ {!props.component && +
+ +
}

{translate('background_tasks.page.description')}

); -}; - -export default Header; +} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js new file mode 100644 index 00000000000..b37622a54f7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Workers.js @@ -0,0 +1,108 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +// @flow +import React from 'react'; +import WorkersForm from './WorkersForm'; +import Tooltip from '../../../components/controls/Tooltip'; +import { getWorkers } from '../../../api/ce'; +import { translate } from '../../../helpers/l10n'; + +type State = { + canSetWorkerCount: boolean, + formOpen: boolean, + loading: boolean, + workerCount: number +}; + +export default class Workers extends React.PureComponent { + mounted: boolean; + state: State = { + canSetWorkerCount: false, + formOpen: false, + loading: true, + workerCount: 1 + }; + + componentDidMount() { + this.mounted = true; + this.loadWorkers(); + } + + componentWillUnmount() { + this.mounted = false; + } + + loadWorkers = () => { + this.setState({ loading: true }); + getWorkers().then(({ canSetWorkerCount, value }) => { + if (this.mounted) { + this.setState({ + canSetWorkerCount, + loading: false, + workerCount: value + }); + } + }); + }; + + closeForm = (newWorkerCount?: number) => + (newWorkerCount + ? this.setState({ formOpen: false, workerCount: newWorkerCount }) + : this.setState({ formOpen: false })); + + handleChangeClick = (event: Event) => { + event.preventDefault(); + this.setState({ formOpen: true }); + }; + + render() { + const { canSetWorkerCount, formOpen, loading, workerCount } = this.state; + + return ( +
+ {!loading && + workerCount > 1 && + + + } + + {translate('background_tasks.number_of_workers')} + + {loading + ? + : {workerCount}} + + {!loading && + (canSetWorkerCount + ? + + + : + {translate('background_tasks.add_more_with_governance')} + )} + + {formOpen && } +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js new file mode 100644 index 00000000000..2f66fe8ab3d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/WorkersForm.js @@ -0,0 +1,126 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +// @flow +import React from 'react'; +import Modal from 'react-modal'; +import Select from 'react-select'; +import { times } from 'lodash'; +import { setWorkerCount } from '../../../api/ce'; +import { translate } from '../../../helpers/l10n'; + +const MAX_WORKERS = 10; + +type Props = { + onClose: (newWorkerCount?: number) => void, + workerCount: number +}; + +type State = { + newWorkerCount: number, + submitting: boolean +}; + +export default class WorkersForm extends React.PureComponent { + mounted: boolean; + props: Props; + state: State; + + constructor(props: Props) { + super(props); + this.state = { + newWorkerCount: props.workerCount, + submitting: false + }; + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleClose = () => this.props.onClose(); + + handleWorkerCountChange = (option: { value: number }) => + this.setState({ newWorkerCount: option.value }); + + handleSubmit = (event: Event) => { + event.preventDefault(); + this.setState({ submitting: true }); + const { newWorkerCount } = this.state; + setWorkerCount(newWorkerCount).then( + () => { + if (this.mounted) { + this.props.onClose(newWorkerCount); + } + }, + () => { + if (this.mounted) { + this.setState({ submitting: false }); + } + } + ); + }; + + render() { + const options = times(MAX_WORKERS).map((_, i) => ({ label: i + 1, value: i + 1 })); + + return ( + +
+

{translate('background_tasks.change_number_of_workers')}

+
+
+
+ +
+ background_tasks.change_number_of_workers.hint +
+
+
+
+ + +
+
+
+
+`; + +exports[`changes select 2`] = ` + +
+

+ background_tasks.change_number_of_workers +

+
+
+
+