return getJSON('/api/ce/task_types').then(r => r.taskTypes);
}
-export function getWorkers(): Promise<{ canSetWorkerCount: boolean; value: number } | Response> {
+export function getWorkers(): Promise<{ canSetWorkerCount: boolean; value: number }> {
return getJSON('/api/ce/worker_count').catch(throwGlobalError);
}
<p className="big-spacer-bottom markdown">{translate('branches.no_support.header.text')}</p>
<p>
<a href="https://redirect.sonarsource.com/doc/branches.html" target="_blank">
- {translate('branches.learn_more')}
+ {translate('learn_more')}
</a>
<a
className="button spacer-left"
href="https://redirect.sonarsource.com/doc/branches.html"
target="_blank"
>
- branches.learn_more
+ learn_more
</a>
<a
className="button spacer-left"
+++ /dev/null
-/*
- * 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 Workers from './Workers';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- component?: Object
-};
-*/
-
-export default function Header(props /*: Props */) {
- return (
- <header className="page-header">
- <h1 className="page-title">{translate('background_tasks.page')}</h1>
- {!props.component && (
- <div className="page-actions">
- <Workers />
- </div>
- )}
- <p className="page-description">{translate('background_tasks.page.description')}</p>
- </header>
- );
-}
--- /dev/null
+/*
+ * 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.
+ */
+import * as React from 'react';
+import Workers from './Workers';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ component?: any;
+}
+
+export default function Header(props: Props) {
+ return (
+ <header className="page-header">
+ <h1 className="page-title">{translate('background_tasks.page')}</h1>
+ {!props.component && (
+ <div className="page-actions">
+ <Workers />
+ </div>
+ )}
+ <p className="page-description">{translate('background_tasks.page.description')}</p>
+ </header>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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.
+ */
+import * as React from 'react';
+import BubblePopup from '../../../components/common/BubblePopup';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ popupPosition?: any;
+}
+
+export default function NoWorkersSupportPopup(props: Props) {
+ return (
+ <BubblePopup position={props.popupPosition} customClass="bubble-popup-bottom-right">
+ <div className="abs-width-400">
+ <h6 className="spacer-bottom">{translate('background_tasks.add_more_workers')}</h6>
+ <p className="big-spacer-bottom markdown">
+ {translate('background_tasks.add_more_workers.text')}
+ </p>
+ <p>
+ <a href="https://redirect.sonarsource.com/plugins/governance.html" target="_blank">
+ {translate('learn_more')}
+ </a>
+ </p>
+ </div>
+ </BubblePopup>
+ );
+}
+++ /dev/null
-/*
- * 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 (
- <div>
- {!loading &&
- workerCount > 1 && (
- <Tooltip overlay={translate('background_tasks.number_of_workers.warning')}>
- <i className="icon-alert-warn little-spacer-right bt-workers-warning-icon" />
- </Tooltip>
- )}
-
- {translate('background_tasks.number_of_workers')}
-
- {loading ? (
- <i className="spinner little-spacer-left" />
- ) : (
- <strong className="little-spacer-left">{workerCount}</strong>
- )}
-
- {!loading &&
- canSetWorkerCount && (
- <Tooltip overlay={translate('background_tasks.change_number_of_workers')}>
- <a className="icon-edit spacer-left" href="#" onClick={this.handleChangeClick} />
- </Tooltip>
- )}
-
- {formOpen && <WorkersForm onClose={this.closeForm} workerCount={this.state.workerCount} />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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.
+ */
+import * as React from 'react';
+import WorkersForm from './WorkersForm';
+import NoWorkersSupportPopup from './NoWorkersSupportPopup';
+import Tooltip from '../../../components/controls/Tooltip';
+import { getWorkers } from '../../../api/ce';
+import { translate } from '../../../helpers/l10n';
+import HelpIcon from '../../../components/icons-components/HelpIcon';
+import BubblePopupHelper from '../../../components/common/BubblePopupHelper';
+
+interface State {
+ canSetWorkerCount: boolean;
+ formOpen: boolean;
+ loading: boolean;
+ noSupportPopup: boolean;
+ workerCount: number;
+}
+
+export default class Workers extends React.PureComponent<{}, State> {
+ mounted: boolean;
+ state: State = {
+ canSetWorkerCount: false,
+ formOpen: false,
+ loading: true,
+ noSupportPopup: false,
+ 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: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ this.setState({ formOpen: true });
+ };
+
+ handleHelpClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
+ event.preventDefault();
+ event.stopPropagation();
+ this.toggleNoSupportPopup();
+ };
+
+ toggleNoSupportPopup = (show?: boolean) => {
+ if (show != undefined) {
+ this.setState({ noSupportPopup: show });
+ } else {
+ this.setState(state => ({ noSupportPopup: !state.noSupportPopup }));
+ }
+ };
+
+ render() {
+ const { canSetWorkerCount, formOpen, loading, workerCount } = this.state;
+
+ return (
+ <div>
+ {!loading &&
+ workerCount > 1 && (
+ <Tooltip overlay={translate('background_tasks.number_of_workers.warning')}>
+ <i className="icon-alert-warn little-spacer-right bt-workers-warning-icon" />
+ </Tooltip>
+ )}
+
+ {translate('background_tasks.number_of_workers')}
+
+ {loading ? (
+ <i className="spinner little-spacer-left" />
+ ) : (
+ <strong className="little-spacer-left">{workerCount}</strong>
+ )}
+
+ {!loading &&
+ canSetWorkerCount && (
+ <Tooltip overlay={translate('background_tasks.change_number_of_workers')}>
+ <a className="icon-edit spacer-left" href="#" onClick={this.handleChangeClick} />
+ </Tooltip>
+ )}
+
+ {!loading &&
+ !canSetWorkerCount && (
+ <span className="spacer-left">
+ <a className="link-no-underline" href="#" onClick={this.handleHelpClick}>
+ <HelpIcon className="text-text-bottom" fill="#cdcdcd" />
+ </a>
+ <BubblePopupHelper
+ isOpen={this.state.noSupportPopup}
+ position="bottomright"
+ popup={<NoWorkersSupportPopup />}
+ togglePopup={this.toggleNoSupportPopup}
+ />
+ </span>
+ )}
+
+ {formOpen && <WorkersForm onClose={this.closeForm} workerCount={this.state.workerCount} />}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 (
- <Modal
- isOpen={true}
- contentLabel={translate('background_tasks.change_number_of_workers')}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.handleClose}>
- <header className="modal-head">
- <h2>{translate('background_tasks.change_number_of_workers')}</h2>
- </header>
- <form onSubmit={this.handleSubmit}>
- <div className="modal-body">
- <Select
- className="input-tiny spacer-top"
- clearable={false}
- onChange={this.handleWorkerCountChange}
- options={options}
- searchable={false}
- value={this.state.newWorkerCount}
- />
- <div className="big-spacer-top alert alert-success markdown">
- {translate('background_tasks.change_number_of_workers.hint')}
- </div>
- </div>
- <footer className="modal-foot">
- <div>
- {this.state.submitting && <i className="spinner spacer-right" />}
- <button disabled={this.state.submitting} type="submit">
- {translate('save')}
- </button>
- <button type="reset" className="button-link" onClick={this.handleClose}>
- {translate('cancel')}
- </button>
- </div>
- </footer>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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.
+ */
+import * as React from 'react';
+import Modal from 'react-modal';
+import * as Select from 'react-select';
+import { times } from 'lodash';
+import { setWorkerCount } from '../../../api/ce';
+import { translate } from '../../../helpers/l10n';
+
+const MAX_WORKERS = 10;
+
+interface Props {
+ onClose: (newWorkerCount?: number) => void;
+ workerCount: number;
+}
+
+interface State {
+ newWorkerCount: number;
+ submitting: boolean;
+}
+
+export default class WorkersForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ 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: React.SyntheticEvent<HTMLFormElement>) => {
+ 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: String(i + 1), value: i + 1 }));
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={translate('background_tasks.change_number_of_workers')}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.handleClose}>
+ <header className="modal-head">
+ <h2>{translate('background_tasks.change_number_of_workers')}</h2>
+ </header>
+ <form onSubmit={this.handleSubmit}>
+ <div className="modal-body">
+ <Select
+ className="input-tiny spacer-top"
+ clearable={false}
+ onChange={this.handleWorkerCountChange}
+ options={options}
+ searchable={false}
+ value={this.state.newWorkerCount}
+ />
+ <div className="big-spacer-top alert alert-success markdown">
+ {translate('background_tasks.change_number_of_workers.hint')}
+ </div>
+ </div>
+ <footer className="modal-foot">
+ <div>
+ {this.state.submitting && <i className="spinner spacer-right" />}
+ <button disabled={this.state.submitting} type="submit">
+ {translate('save')}
+ </button>
+ <button type="reset" className="button-link" onClick={this.handleClose}>
+ {translate('cancel')}
+ </button>
+ </div>
+ </footer>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import Workers from '../Workers';
-import { click } from '../../../../helpers/testUtils';
-
-it('renders', () => {
- const wrapper = shallow(<Workers />);
- expect(wrapper).toMatchSnapshot();
-
- wrapper.setState({
- canSetWorkerCount: true,
- loading: false,
- workerCount: 1
- });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.setState({ canSetWorkerCount: false });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.setState({ workerCount: 2 });
- expect(wrapper).toMatchSnapshot();
-});
-
-it('opens form', () => {
- const wrapper = shallow(<Workers />);
-
- wrapper.setState({
- canSetWorkerCount: true,
- loading: false,
- workerCount: 1
- });
- expect(wrapper).toMatchSnapshot();
-
- click(wrapper.find('.icon-edit'));
- expect(wrapper).toMatchSnapshot();
-});
-
-it('updates worker count', () => {
- const wrapper = shallow(<Workers />);
-
- wrapper.setState({
- canSetWorkerCount: true,
- formOpen: true,
- loading: false,
- workerCount: 1
- });
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('WorkersForm').prop('onClose')(7);
- wrapper.update();
- expect(wrapper).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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.
+ */
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import Workers from '../Workers';
+import { click } from '../../../../helpers/testUtils';
+
+it('renders', () => {
+ const wrapper = shallow(<Workers />);
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.setState({
+ canSetWorkerCount: true,
+ loading: false,
+ workerCount: 1
+ });
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.setState({ workerCount: 2 });
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.setState({ canSetWorkerCount: false });
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('opens form', () => {
+ const wrapper = shallow(<Workers />);
+
+ wrapper.setState({
+ canSetWorkerCount: true,
+ loading: false,
+ workerCount: 1
+ });
+ expect(wrapper).toMatchSnapshot();
+
+ click(wrapper.find('.icon-edit'));
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('updates worker count', () => {
+ const wrapper = shallow(<Workers />);
+
+ wrapper.setState({
+ canSetWorkerCount: true,
+ formOpen: true,
+ loading: false,
+ workerCount: 1
+ });
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.find('WorkersForm').prop<Function>('onClose')(7);
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import WorkersForm from '../WorkersForm';
-import { submit, doAsync } from '../../../../helpers/testUtils';
-
-jest.mock('../../../../api/ce', () => ({
- setWorkerCount: () => Promise.resolve()
-}));
-
-it('changes select', () => {
- const wrapper = shallow(<WorkersForm onClose={jest.fn()} workerCount={1} />);
- expect(wrapper).toMatchSnapshot();
-
- wrapper.find('Select').prop('onChange')({ value: 7 });
- wrapper.update();
- expect(wrapper).toMatchSnapshot();
-});
-
-it('returns new worker count', () => {
- const onClose = jest.fn();
- const wrapper = shallow(<WorkersForm onClose={onClose} workerCount={1} />);
- // $FlowFixMe
- wrapper.instance().mounted = true;
- wrapper.find('Select').prop('onChange')({ value: 7 });
-
- wrapper.update();
- submit(wrapper.find('form'));
-
- return doAsync(() => {
- expect(onClose).toBeCalled();
- });
-});
--- /dev/null
+/*
+ * 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.
+ */
+jest.mock('../../../../api/ce', () => ({
+ setWorkerCount: () => Promise.resolve()
+}));
+
+import * as React from 'react';
+import { shallow } from 'enzyme';
+import WorkersForm from '../WorkersForm';
+import { submit } from '../../../../helpers/testUtils';
+
+it('changes select', () => {
+ const wrapper = shallow(<WorkersForm onClose={jest.fn()} workerCount={1} />);
+ expect(wrapper).toMatchSnapshot();
+
+ wrapper.find('Select').prop<Function>('onChange')({ value: 7 });
+ wrapper.update();
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('returns new worker count', async () => {
+ const onClose = jest.fn();
+ const wrapper = shallow(<WorkersForm onClose={onClose} workerCount={1} />);
+ (wrapper.instance() as WorkersForm).mounted = true;
+ wrapper.find('Select').prop<Function>('onChange')({ value: 7 });
+
+ wrapper.update();
+ submit(wrapper.find('form'));
+
+ await new Promise(setImmediate);
+ expect(onClose).toBeCalled();
+});
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`opens form 1`] = `
-<div>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 1
- </strong>
- <Tooltip
- overlay="background_tasks.change_number_of_workers"
- placement="bottom"
- >
- <a
- className="icon-edit spacer-left"
- href="#"
- onClick={[Function]}
- />
- </Tooltip>
-</div>
-`;
-
-exports[`opens form 2`] = `
-<div>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 1
- </strong>
- <Tooltip
- overlay="background_tasks.change_number_of_workers"
- placement="bottom"
- >
- <a
- className="icon-edit spacer-left"
- href="#"
- onClick={[Function]}
- />
- </Tooltip>
- <WorkersForm
- onClose={[Function]}
- workerCount={1}
- />
-</div>
-`;
-
-exports[`renders 1`] = `
-<div>
- background_tasks.number_of_workers
- <i
- className="spinner little-spacer-left"
- />
-</div>
-`;
-
-exports[`renders 2`] = `
-<div>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 1
- </strong>
- <Tooltip
- overlay="background_tasks.change_number_of_workers"
- placement="bottom"
- >
- <a
- className="icon-edit spacer-left"
- href="#"
- onClick={[Function]}
- />
- </Tooltip>
-</div>
-`;
-
-exports[`renders 3`] = `
-<div>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 1
- </strong>
-</div>
-`;
-
-exports[`renders 4`] = `
-<div>
- <Tooltip
- overlay="background_tasks.number_of_workers.warning"
- placement="bottom"
- >
- <i
- className="icon-alert-warn little-spacer-right bt-workers-warning-icon"
- />
- </Tooltip>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 2
- </strong>
-</div>
-`;
-
-exports[`updates worker count 1`] = `
-<div>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 1
- </strong>
- <Tooltip
- overlay="background_tasks.change_number_of_workers"
- placement="bottom"
- >
- <a
- className="icon-edit spacer-left"
- href="#"
- onClick={[Function]}
- />
- </Tooltip>
- <WorkersForm
- onClose={[Function]}
- workerCount={1}
- />
-</div>
-`;
-
-exports[`updates worker count 2`] = `
-<div>
- <Tooltip
- overlay="background_tasks.number_of_workers.warning"
- placement="bottom"
- >
- <i
- className="icon-alert-warn little-spacer-right bt-workers-warning-icon"
- />
- </Tooltip>
- background_tasks.number_of_workers
- <strong
- className="little-spacer-left"
- >
- 7
- </strong>
- <Tooltip
- overlay="background_tasks.change_number_of_workers"
- placement="bottom"
- >
- <a
- className="icon-edit spacer-left"
- href="#"
- onClick={[Function]}
- />
- </Tooltip>
-</div>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`opens form 1`] = `
+<div>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 1
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+</div>
+`;
+
+exports[`opens form 2`] = `
+<div>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 1
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+ <WorkersForm
+ onClose={[Function]}
+ workerCount={1}
+ />
+</div>
+`;
+
+exports[`renders 1`] = `
+<div>
+ background_tasks.number_of_workers
+ <i
+ className="spinner little-spacer-left"
+ />
+</div>
+`;
+
+exports[`renders 2`] = `
+<div>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 1
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+</div>
+`;
+
+exports[`renders 3`] = `
+<div>
+ <Tooltip
+ overlay="background_tasks.number_of_workers.warning"
+ placement="bottom"
+ >
+ <i
+ className="icon-alert-warn little-spacer-right bt-workers-warning-icon"
+ />
+ </Tooltip>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 2
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+</div>
+`;
+
+exports[`renders 4`] = `
+<div>
+ <Tooltip
+ overlay="background_tasks.number_of_workers.warning"
+ placement="bottom"
+ >
+ <i
+ className="icon-alert-warn little-spacer-right bt-workers-warning-icon"
+ />
+ </Tooltip>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 2
+ </strong>
+ <span
+ className="spacer-left"
+ >
+ <a
+ className="link-no-underline"
+ href="#"
+ onClick={[Function]}
+ >
+ <HelpIcon
+ className="text-text-bottom"
+ fill="#cdcdcd"
+ />
+ </a>
+ <BubblePopupHelper
+ isOpen={false}
+ popup={<NoWorkersSupportPopup />}
+ position="bottomright"
+ togglePopup={[Function]}
+ />
+ </span>
+</div>
+`;
+
+exports[`updates worker count 1`] = `
+<div>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 1
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+ <WorkersForm
+ onClose={[Function]}
+ workerCount={1}
+ />
+</div>
+`;
+
+exports[`updates worker count 2`] = `
+<div>
+ <Tooltip
+ overlay="background_tasks.number_of_workers.warning"
+ placement="bottom"
+ >
+ <i
+ className="icon-alert-warn little-spacer-right bt-workers-warning-icon"
+ />
+ </Tooltip>
+ background_tasks.number_of_workers
+ <strong
+ className="little-spacer-left"
+ >
+ 7
+ </strong>
+ <Tooltip
+ overlay="background_tasks.change_number_of_workers"
+ placement="bottom"
+ >
+ <a
+ className="icon-edit spacer-left"
+ href="#"
+ onClick={[Function]}
+ />
+ </Tooltip>
+</div>
+`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`changes select 1`] = `
-<Modal
- ariaHideApp={true}
- bodyOpenClassName="ReactModal__Body--open"
- className="modal"
- closeTimeoutMS={0}
- contentLabel="background_tasks.change_number_of_workers"
- isOpen={true}
- onRequestClose={[Function]}
- overlayClassName="modal-overlay"
- parentSelector={[Function]}
- portalClassName="ReactModalPortal"
- shouldCloseOnOverlayClick={true}
->
- <header
- className="modal-head"
- >
- <h2>
- background_tasks.change_number_of_workers
- </h2>
- </header>
- <form
- onSubmit={[Function]}
- >
- <div
- className="modal-body"
- >
- <Select
- addLabelText="Add \\"{label}\\"?"
- arrowRenderer={[Function]}
- autosize={true}
- backspaceRemoves={true}
- backspaceToRemoveMessage="Press backspace to remove {label}"
- className="input-tiny spacer-top"
- clearAllText="Clear all"
- clearRenderer={[Function]}
- clearValueText="Clear value"
- clearable={false}
- deleteRemoves={true}
- delimiter=","
- disabled={false}
- escapeClearsValue={true}
- filterOptions={[Function]}
- ignoreAccents={true}
- ignoreCase={true}
- inputProps={Object {}}
- isLoading={false}
- joinValues={false}
- labelKey="label"
- matchPos="any"
- matchProp="any"
- menuBuffer={0}
- menuRenderer={[Function]}
- multi={false}
- noResultsText="No results found"
- onBlurResetsInput={true}
- onChange={[Function]}
- onCloseResetsInput={true}
- optionComponent={[Function]}
- options={
- Array [
- Object {
- "label": 1,
- "value": 1,
- },
- Object {
- "label": 2,
- "value": 2,
- },
- Object {
- "label": 3,
- "value": 3,
- },
- Object {
- "label": 4,
- "value": 4,
- },
- Object {
- "label": 5,
- "value": 5,
- },
- Object {
- "label": 6,
- "value": 6,
- },
- Object {
- "label": 7,
- "value": 7,
- },
- Object {
- "label": 8,
- "value": 8,
- },
- Object {
- "label": 9,
- "value": 9,
- },
- Object {
- "label": 10,
- "value": 10,
- },
- ]
- }
- pageSize={5}
- placeholder="Select..."
- required={false}
- scrollMenuIntoView={true}
- searchable={false}
- simpleValue={false}
- tabSelectsValue={true}
- value={1}
- valueComponent={[Function]}
- valueKey="value"
- />
- <div
- className="big-spacer-top alert alert-success markdown"
- >
- background_tasks.change_number_of_workers.hint
- </div>
- </div>
- <footer
- className="modal-foot"
- >
- <div>
- <button
- disabled={false}
- type="submit"
- >
- save
- </button>
- <button
- className="button-link"
- onClick={[Function]}
- type="reset"
- >
- cancel
- </button>
- </div>
- </footer>
- </form>
-</Modal>
-`;
-
-exports[`changes select 2`] = `
-<Modal
- ariaHideApp={true}
- bodyOpenClassName="ReactModal__Body--open"
- className="modal"
- closeTimeoutMS={0}
- contentLabel="background_tasks.change_number_of_workers"
- isOpen={true}
- onRequestClose={[Function]}
- overlayClassName="modal-overlay"
- parentSelector={[Function]}
- portalClassName="ReactModalPortal"
- shouldCloseOnOverlayClick={true}
->
- <header
- className="modal-head"
- >
- <h2>
- background_tasks.change_number_of_workers
- </h2>
- </header>
- <form
- onSubmit={[Function]}
- >
- <div
- className="modal-body"
- >
- <Select
- addLabelText="Add \\"{label}\\"?"
- arrowRenderer={[Function]}
- autosize={true}
- backspaceRemoves={true}
- backspaceToRemoveMessage="Press backspace to remove {label}"
- className="input-tiny spacer-top"
- clearAllText="Clear all"
- clearRenderer={[Function]}
- clearValueText="Clear value"
- clearable={false}
- deleteRemoves={true}
- delimiter=","
- disabled={false}
- escapeClearsValue={true}
- filterOptions={[Function]}
- ignoreAccents={true}
- ignoreCase={true}
- inputProps={Object {}}
- isLoading={false}
- joinValues={false}
- labelKey="label"
- matchPos="any"
- matchProp="any"
- menuBuffer={0}
- menuRenderer={[Function]}
- multi={false}
- noResultsText="No results found"
- onBlurResetsInput={true}
- onChange={[Function]}
- onCloseResetsInput={true}
- optionComponent={[Function]}
- options={
- Array [
- Object {
- "label": 1,
- "value": 1,
- },
- Object {
- "label": 2,
- "value": 2,
- },
- Object {
- "label": 3,
- "value": 3,
- },
- Object {
- "label": 4,
- "value": 4,
- },
- Object {
- "label": 5,
- "value": 5,
- },
- Object {
- "label": 6,
- "value": 6,
- },
- Object {
- "label": 7,
- "value": 7,
- },
- Object {
- "label": 8,
- "value": 8,
- },
- Object {
- "label": 9,
- "value": 9,
- },
- Object {
- "label": 10,
- "value": 10,
- },
- ]
- }
- pageSize={5}
- placeholder="Select..."
- required={false}
- scrollMenuIntoView={true}
- searchable={false}
- simpleValue={false}
- tabSelectsValue={true}
- value={7}
- valueComponent={[Function]}
- valueKey="value"
- />
- <div
- className="big-spacer-top alert alert-success markdown"
- >
- background_tasks.change_number_of_workers.hint
- </div>
- </div>
- <footer
- className="modal-foot"
- >
- <div>
- <button
- disabled={false}
- type="submit"
- >
- save
- </button>
- <button
- className="button-link"
- onClick={[Function]}
- type="reset"
- >
- cancel
- </button>
- </div>
- </footer>
- </form>
-</Modal>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`changes select 1`] = `
+<Modal
+ ariaHideApp={true}
+ bodyOpenClassName="ReactModal__Body--open"
+ className="modal"
+ closeTimeoutMS={0}
+ contentLabel="background_tasks.change_number_of_workers"
+ isOpen={true}
+ onRequestClose={[Function]}
+ overlayClassName="modal-overlay"
+ parentSelector={[Function]}
+ portalClassName="ReactModalPortal"
+ shouldCloseOnOverlayClick={true}
+>
+ <header
+ className="modal-head"
+ >
+ <h2>
+ background_tasks.change_number_of_workers
+ </h2>
+ </header>
+ <form
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-body"
+ >
+ <Select
+ addLabelText="Add \\"{label}\\"?"
+ arrowRenderer={[Function]}
+ autosize={true}
+ backspaceRemoves={true}
+ backspaceToRemoveMessage="Press backspace to remove {label}"
+ className="input-tiny spacer-top"
+ clearAllText="Clear all"
+ clearRenderer={[Function]}
+ clearValueText="Clear value"
+ clearable={false}
+ deleteRemoves={true}
+ delimiter=","
+ disabled={false}
+ escapeClearsValue={true}
+ filterOptions={[Function]}
+ ignoreAccents={true}
+ ignoreCase={true}
+ inputProps={Object {}}
+ isLoading={false}
+ joinValues={false}
+ labelKey="label"
+ matchPos="any"
+ matchProp="any"
+ menuBuffer={0}
+ menuRenderer={[Function]}
+ multi={false}
+ noResultsText="No results found"
+ onBlurResetsInput={true}
+ onChange={[Function]}
+ onCloseResetsInput={true}
+ optionComponent={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "1",
+ "value": 1,
+ },
+ Object {
+ "label": "2",
+ "value": 2,
+ },
+ Object {
+ "label": "3",
+ "value": 3,
+ },
+ Object {
+ "label": "4",
+ "value": 4,
+ },
+ Object {
+ "label": "5",
+ "value": 5,
+ },
+ Object {
+ "label": "6",
+ "value": 6,
+ },
+ Object {
+ "label": "7",
+ "value": 7,
+ },
+ Object {
+ "label": "8",
+ "value": 8,
+ },
+ Object {
+ "label": "9",
+ "value": 9,
+ },
+ Object {
+ "label": "10",
+ "value": 10,
+ },
+ ]
+ }
+ pageSize={5}
+ placeholder="Select..."
+ required={false}
+ scrollMenuIntoView={true}
+ searchable={false}
+ simpleValue={false}
+ tabSelectsValue={true}
+ value={1}
+ valueComponent={[Function]}
+ valueKey="value"
+ />
+ <div
+ className="big-spacer-top alert alert-success markdown"
+ >
+ background_tasks.change_number_of_workers.hint
+ </div>
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <div>
+ <button
+ disabled={false}
+ type="submit"
+ >
+ save
+ </button>
+ <button
+ className="button-link"
+ onClick={[Function]}
+ type="reset"
+ >
+ cancel
+ </button>
+ </div>
+ </footer>
+ </form>
+</Modal>
+`;
+
+exports[`changes select 2`] = `
+<Modal
+ ariaHideApp={true}
+ bodyOpenClassName="ReactModal__Body--open"
+ className="modal"
+ closeTimeoutMS={0}
+ contentLabel="background_tasks.change_number_of_workers"
+ isOpen={true}
+ onRequestClose={[Function]}
+ overlayClassName="modal-overlay"
+ parentSelector={[Function]}
+ portalClassName="ReactModalPortal"
+ shouldCloseOnOverlayClick={true}
+>
+ <header
+ className="modal-head"
+ >
+ <h2>
+ background_tasks.change_number_of_workers
+ </h2>
+ </header>
+ <form
+ onSubmit={[Function]}
+ >
+ <div
+ className="modal-body"
+ >
+ <Select
+ addLabelText="Add \\"{label}\\"?"
+ arrowRenderer={[Function]}
+ autosize={true}
+ backspaceRemoves={true}
+ backspaceToRemoveMessage="Press backspace to remove {label}"
+ className="input-tiny spacer-top"
+ clearAllText="Clear all"
+ clearRenderer={[Function]}
+ clearValueText="Clear value"
+ clearable={false}
+ deleteRemoves={true}
+ delimiter=","
+ disabled={false}
+ escapeClearsValue={true}
+ filterOptions={[Function]}
+ ignoreAccents={true}
+ ignoreCase={true}
+ inputProps={Object {}}
+ isLoading={false}
+ joinValues={false}
+ labelKey="label"
+ matchPos="any"
+ matchProp="any"
+ menuBuffer={0}
+ menuRenderer={[Function]}
+ multi={false}
+ noResultsText="No results found"
+ onBlurResetsInput={true}
+ onChange={[Function]}
+ onCloseResetsInput={true}
+ optionComponent={[Function]}
+ options={
+ Array [
+ Object {
+ "label": "1",
+ "value": 1,
+ },
+ Object {
+ "label": "2",
+ "value": 2,
+ },
+ Object {
+ "label": "3",
+ "value": 3,
+ },
+ Object {
+ "label": "4",
+ "value": 4,
+ },
+ Object {
+ "label": "5",
+ "value": 5,
+ },
+ Object {
+ "label": "6",
+ "value": 6,
+ },
+ Object {
+ "label": "7",
+ "value": 7,
+ },
+ Object {
+ "label": "8",
+ "value": 8,
+ },
+ Object {
+ "label": "9",
+ "value": 9,
+ },
+ Object {
+ "label": "10",
+ "value": 10,
+ },
+ ]
+ }
+ pageSize={5}
+ placeholder="Select..."
+ required={false}
+ scrollMenuIntoView={true}
+ searchable={false}
+ simpleValue={false}
+ tabSelectsValue={true}
+ value={7}
+ valueComponent={[Function]}
+ valueKey="value"
+ />
+ <div
+ className="big-spacer-top alert alert-success markdown"
+ >
+ background_tasks.change_number_of_workers.hint
+ </div>
+ </div>
+ <footer
+ className="modal-foot"
+ >
+ <div>
+ <button
+ disabled={false}
+ type="submit"
+ >
+ save
+ </button>
+ <button
+ className="button-link"
+ onClick={[Function]}
+ type="reset"
+ >
+ cancel
+ </button>
+ </div>
+ </footer>
+ </form>
+</Modal>
+`;
.bubble-popup-bottom-right {
.bubble-popup-bottom;
margin-left: 0;
- margin-right: -@popupArrowSize;
+ margin-right: -16px;
.bubble-popup-arrow {
left: auto;
right: 15px;
- border-right-width: 0;
- border-left-color: barBorderColor;
}
}
inheritance=Inheritance
key=Key
language=Language
+learn_more=Learn More
library=Library
line_number=Line Number
links=Links
background_tasks.number_of_workers.warning=Configuring additional workers without first vertically scaling your server could have negative performance impacts.
background_tasks.change_number_of_workers=Edit CE Workers
background_tasks.change_number_of_workers.hint=If your queue backs up behind the analysis reports from large projects, increasing the number of Compute Engine workers will allow you to take full advantage of having configured increased Compute Engine memory on a multi-core server (vertical scaling).
-background_tasks.add_more_with_governance=Add more with Governance
+background_tasks.add_more_workers=Speed up your analysis by adding more Workers
+background_tasks.add_more_workers.text=Increase the number of Compute Engine Workers with the Governance product. Available in our commercial editions.
background_tasks.search_by_task_or_component=Search by Task or Component
background_tasks.failing_count=Count of projects where processing of most recent analysis report failed
branches.last_analysis_date=Last Analysis Date
branches.no_support.header=Get the most out of SonarQube with branches analysis
branches.no_support.header.text=Analyze each branch of your project separately with our Developer Pack.
-branches.learn_more=Learn More
branches.buy_developer_pack=Buy Developer Pack