diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2016-05-13 11:57:27 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2016-05-13 11:57:27 +0200 |
commit | 9a74d1aeb8d8bdbcf5c5b2a98fb2b2eefd1414a7 (patch) | |
tree | 502787d1156ea973de182fbc68ad48a3b6f43891 /server/sonar-web/src/main/js/apps | |
parent | ecd8c71b84b8691dd9c1d40f349f5b11a35c28cf (diff) | |
download | sonarqube-9a74d1aeb8d8bdbcf5c5b2a98fb2b2eefd1414a7.tar.gz sonarqube-9a74d1aeb8d8bdbcf5c5b2a98fb2b2eefd1414a7.zip |
SONAR-7431 Keep filters state in url on background page (#965)
Diffstat (limited to 'server/sonar-web/src/main/js/apps')
26 files changed, 480 insertions, 661 deletions
diff --git a/server/sonar-web/src/main/js/apps/background-tasks/app.js b/server/sonar-web/src/main/js/apps/background-tasks/app.js index d1626102c8f..c5ed780faa5 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/app.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/app.js @@ -19,22 +19,24 @@ */ import React from 'react'; import ReactDOM from 'react-dom'; -import { Provider } from 'react-redux'; +import { Router, Route, Redirect, useRouterHistory } from 'react-router'; +import { createHistory } from 'history'; -import BackgroundTasksAppContainer from './containers/BackgroundTasksAppContainer'; -import rootReducer from './store/reducers'; -import configureStore from '../../components/store/configureStore'; - -import './styles/background-tasks.css'; +import BackgroundTasksApp from './components/BackgroundTasksApp'; window.sonarqube.appStarted.then(options => { const el = document.querySelector(options.el); - const store = configureStore(rootReducer); + const history = useRouterHistory(createHistory)({ + basename: window.baseUrl + (options.component ? '/project/background_tasks' : '/background_tasks') + }); + + const App = props => <BackgroundTasksApp {...props} component={options.component}/>; ReactDOM.render(( - <Provider store={store}> - <BackgroundTasksAppContainer options={options}/> - </Provider> + <Router history={history}> + <Redirect from="/index" to="/"/> + <Route path="/" component={App}/> + </Router> ), el); }); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/styles/background-tasks.css b/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css index 2bad2aba5a0..2bad2aba5a0 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/styles/background-tasks.css +++ b/server/sonar-web/src/main/js/apps/background-tasks/background-tasks.css 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 382e5e32983..0ca7ebb5cac 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 @@ -17,59 +17,210 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import moment from 'moment'; -import React, { Component } from 'react'; +import React from 'react'; +import shallowCompare from 'react-addons-shallow-compare'; +import debounce from 'lodash/debounce'; +import { PropTypes as RouterPropTypes } from 'react-router'; -import { DATE } from './../constants'; +import { DEFAULT_FILTERS, DEBOUNCE_DELAY, STATUSES, CURRENTS } from './../constants'; import Header from './Header'; import Footer from './Footer'; -import StatsContainer from '../containers/StatsContainer'; -import SearchContainer from '../containers/SearchContainer'; -import TasksContainer from '../containers/TasksContainer'; +import Stats from '../components/Stats'; +import Search from '../components/Search'; +import Tasks from '../components/Tasks'; +import { getTypes, getActivity, getStatus, cancelAllTasks, cancelTask as cancelTaskAPI } from '../../../api/ce'; +import { updateTask, mapFiltersToParameters } from '../utils'; +import '../background-tasks.css'; + +export default class BackgroundTasksApp extends React.Component { + static contextTypes = { + router: React.PropTypes.object.isRequired + }; + + static propTypes = { + component: React.PropTypes.object, + location: RouterPropTypes.location.isRequired + }; + + state = { + loading: true, + tasks: [], + + // filters + query: '', + + // stats + pendingCount: 0, + failingCount: 0 + }; + + componentWillMount () { + this.loadTasksDebounced = debounce(this.loadTasks.bind(this), DEBOUNCE_DELAY); + } -export default class BackgroundTasksApp extends Component { componentDidMount () { - this.props.initApp(this.props.options.component); + this.mounted = true; + + getTypes().then(types => { + this.setState({ types }); + this.loadTasks(); + }); } - getComponentFilter () { - if (this.props.options.component) { - return { componentId: this.props.options.component.id }; - } else { - return {}; + shouldComponentUpdate (nextProps, nextState) { + return shallowCompare(this, nextProps, nextState); + } + + componentDidUpdate (prevProps) { + if (prevProps.component !== this.props.component || + prevProps.location !== this.props.location) { + this.loadTasksDebounced(); } } - getDateFilter () { - const DATE_FORMAT = 'YYYY-MM-DD'; - const filter = {}; - switch (this.state.dateFilter) { - case DATE.TODAY: - filter.minSubmittedAt = moment().startOf('day').format(DATE_FORMAT); - break; - case DATE.CUSTOM: - if (this.state.minDate) { - filter.minSubmittedAt = moment(this.state.minDate).format(DATE_FORMAT); - } - if (this.state.maxDate) { - filter.maxExecutedAt = moment(this.state.maxDate).format(DATE_FORMAT); - } - break; - default: - - // do nothing + componentWillUnmount () { + this.mounted = false; + } + + loadTasks () { + this.setState({ loading: true }); + + const status = this.props.location.query.status || DEFAULT_FILTERS.status; + const taskType = this.props.location.query.taskType || DEFAULT_FILTERS.taskType; + const currents = this.props.location.query.currents || DEFAULT_FILTERS.currents; + const minSubmittedAt = this.props.location.query.minSubmittedAt || DEFAULT_FILTERS.minSubmittedAt; + const maxExecutedAt = this.props.location.query.maxExecutedAt || DEFAULT_FILTERS.maxExecutedAt; + const query = this.props.location.query.query || DEFAULT_FILTERS.query; + + const filters = { status, taskType, currents, minSubmittedAt, maxExecutedAt, query }; + const parameters = mapFiltersToParameters(filters); + + if (this.props.component) { + parameters.componentId = this.props.component.id; } - return filter; + + Promise.all([ + getActivity(parameters), + getStatus(parameters.componentId) + ]).then(responses => { + if (this.mounted) { + const [activity, status] = responses; + const tasks = activity.tasks; + + const pendingCount = status.pending; + const failingCount = status.failing; + + this.setState({ + tasks, + pendingCount, + failingCount, + loading: false + }); + } + }); + } + + handleFilterUpdate (nextState) { + const nextQuery = { ...this.props.location.query, ...nextState }; + + // remove defaults + Object.keys(DEFAULT_FILTERS).forEach(key => { + if (nextQuery[key] === DEFAULT_FILTERS[key]) { + delete nextQuery[key]; + } + }); + + this.context.router.push({ + pathname: '/', + query: nextQuery + }); + } + + handleCancelTask (task) { + this.setState({ loading: true }); + + cancelTaskAPI(task.id).then(nextTask => { + if (this.mounted) { + const tasks = updateTask(this.state.tasks, nextTask); + this.setState({ tasks, loading: false }); + } + }); + } + + handleFilterTask (task) { + this.handleFilterUpdate({ query: task.componentKey }); + } + + handleShowFailing () { + this.handleFilterUpdate({ + ...DEFAULT_FILTERS, + status: STATUSES.FAILED, + currents: CURRENTS.ONLY_CURRENTS + }); + } + + handleCancelAllPending () { + this.setState({ loading: true }); + + cancelAllTasks().then(() => { + if (this.mounted) { + this.loadTasks(); + } + }); } render () { + const { component } = this.props; + const { loading, types, tasks, pendingCount, failingCount } = this.state; + + if (!types) { + return ( + <div className="page"> + <i className="spinner"/> + </div> + ); + } + + const status = this.props.location.query.status || DEFAULT_FILTERS.status; + const taskType = this.props.location.query.taskType || DEFAULT_FILTERS.taskType; + const currents = this.props.location.query.currents || DEFAULT_FILTERS.currents; + const minSubmittedAt = this.props.location.query.minSubmittedAt || ''; + const maxExecutedAt = this.props.location.query.maxExecutedAt || ''; + const query = this.props.location.query.query || ''; + return ( <div className="page"> <Header/> - <StatsContainer/> - <SearchContainer/> - <TasksContainer/> - <Footer tasks={this.props.tasks}/> + + <Stats + component={component} + pendingCount={pendingCount} + failingCount={failingCount} + onShowFailing={this.handleShowFailing.bind(this)} + onCancelAllPending={this.handleCancelAllPending.bind(this)}/> + + <Search + loading={loading} + component={component} + status={status} + currents={currents} + minSubmittedAt={minSubmittedAt} + maxExecutedAt={maxExecutedAt} + query={query} + taskType={taskType} + types={types} + onFilterUpdate={this.handleFilterUpdate.bind(this)} + onReload={this.loadTasksDebounced}/> + + <Tasks + loading={loading} + component={component} + types={types} + tasks={tasks} + onCancelTask={this.handleCancelTask.bind(this)} + onFilterTask={this.handleFilterTask.bind(this)}/> + + <Footer tasks={tasks}/> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js index 2468594bbd9..be19157bb88 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/CurrentsFilter.js @@ -22,7 +22,7 @@ import React from 'react'; import Checkbox from '../../../components/shared/checkbox'; import { CURRENTS } from '../constants'; -export default function CurrentsFilter ({ value, onChange }) { +const CurrentsFilter = ({ value, onChange }) => { function handleChange (value) { const newValue = value ? CURRENTS.ONLY_CURRENTS : CURRENTS.ALL; onChange(newValue); @@ -48,4 +48,6 @@ export default function CurrentsFilter ({ value, onChange }) { style={{ cursor: 'pointer' }}>Yes</label> </div> ); -} +}; + +export default CurrentsFilter; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js index 83e90c9caf3..ace8d6e428d 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/DateFilter.js @@ -64,14 +64,14 @@ export default class DateFilter extends Component { } render () { - const { minSubmittedAt, maxExecutedAt } = this.props.value; + const { minSubmittedAt, maxExecutedAt } = this.props; return ( <div> <input className="input-small" value={minSubmittedAt} - onChange={this.handleChange.bind(this)} + onChange={() => true} ref="minDate" type="text" placeholder="From"/> @@ -79,7 +79,7 @@ export default class DateFilter extends Component { <input className="input-small" value={maxExecutedAt} - onChange={this.handleChange.bind(this)} + onChange={() => true} ref="maxDate" type="text" placeholder="To"/> diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js index 3fbf337976e..8cc1f251797 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Header.js @@ -21,7 +21,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default function Header () { +const Header = () => { return ( <header className="page-header"> <h1 className="page-title"> @@ -32,4 +32,6 @@ export default function Header () { </p> </header> ); -} +}; + +export default Header; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js index fda9220cfff..bfffb1021e4 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js @@ -23,53 +23,88 @@ import StatusFilter from './StatusFilter'; import TypesFilter from './TypesFilter'; import CurrentsFilter from './CurrentsFilter'; import DateFilter from './DateFilter'; +import { DEFAULT_FILTERS } from './../constants'; import { translate } from '../../../helpers/l10n'; -export default React.createClass({ +export default class Search extends React.Component { + static propTypes = { + loading: React.PropTypes.bool.isRequired, + status: React.PropTypes.any.isRequired, + taskType: React.PropTypes.any.isRequired, + currents: React.PropTypes.any.isRequired, + query: React.PropTypes.string.isRequired, + onFilterUpdate: React.PropTypes.func.isRequired, + onReload: React.PropTypes.func.isRequired + }; - onSearchFormSubmit(e) { + handleStatusChange (status) { + this.props.onFilterUpdate({ status }); + } + + handleTypeChange (taskType) { + this.props.onFilterUpdate({ taskType }); + } + + handleCurrentsChange (currents) { + this.props.onFilterUpdate({ currents }); + } + + handleDateChange (date) { + this.props.onFilterUpdate(date); + } + + handleQueryChange (query) { + this.props.onFilterUpdate({ query }); + } + + handleReload (e) { + e.target.blur(); + this.props.onReload(); + } + + handleReset (e) { e.preventDefault(); - this.onSearch(); - }, + e.target.blur(); + this.props.onFilterUpdate(DEFAULT_FILTERS); + } - onSearch() { - const searchInput = this.refs.searchInput; - const query = searchInput.value; - this.props.onSearch(query); - }, + renderSearchBox () { + const { component, query } = this.props; - renderSearchBox() { - if (this.props.component) { + if (component) { // do not render search form on the project-level page return null; } + return ( <li> <h6 className="bt-search-form-label"> Search by Task or Component </h6> - <input onChange={this.onSearch} - value={this.props.query} - ref="searchInput" - className="js-search input-large" - type="search" - placeholder="Search"/> + <input + onChange={e => this.handleQueryChange(e.target.value)} + value={query} + ref="searchInput" + className="js-search input-large" + type="search" + placeholder="Search"/> </li> ); - }, - - refresh(e) { - e.preventDefault(); - this.props.onRefresh(); - }, + } - handleReset(e) { - e.preventDefault(); - this.props.onReset(); - }, + render () { + const { + loading, + component, + types, + status, + taskType, + currents, + minSubmittedAt, + maxExecutedAt + } = this.props; - render() { return ( <section className="big-spacer-top big-spacer-bottom"> <ul className="bt-search-form"> @@ -78,28 +113,28 @@ export default React.createClass({ Status </h6> <StatusFilter - value={this.props.status} - onChange={this.props.onStatusChange}/> + value={status} + onChange={this.handleStatusChange.bind(this)}/> </li> - {this.props.types.length > 1 && ( + {types.length > 1 && ( <li> <h6 className="bt-search-form-label"> Type </h6> <TypesFilter - value={this.props.taskType} - onChange={this.props.onTypeChange} - types={this.props.types}/> + value={taskType} + types={types} + onChange={this.handleTypeChange.bind(this)}/> </li> )} - {!this.props.component && ( + {!component && ( <li> <h6 className="bt-search-form-label"> Only Latest Analysis </h6> <CurrentsFilter - value={this.props.currents} - onChange={this.props.onCurrentsChange}/> + value={currents} + onChange={this.handleCurrentsChange.bind(this)}/> </li> )} <li> @@ -107,8 +142,9 @@ export default React.createClass({ Date </h6> <DateFilter - value={this.props.date} - onChange={this.props.onDateChange}/> + minSubmittedAt={minSubmittedAt} + maxExecutedAt={maxExecutedAt} + onChange={this.handleDateChange.bind(this)}/> </li> {this.renderSearchBox()} @@ -116,15 +152,15 @@ export default React.createClass({ <li className="bt-search-form-right"> <button ref="reloadButton" - onClick={this.refresh} - disabled={this.props.fetching}> + onClick={this.handleReload.bind(this)} + disabled={loading}> {translate('reload')} </button> {' '} <button ref="resetButton" - onClick={this.handleReset} - disabled={this.props.fetching}> + onClick={this.handleReset.bind(this)} + disabled={loading}> {translate('reset_verb')} </button> </li> @@ -132,4 +168,4 @@ export default React.createClass({ </section> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js index 450a5098671..6fe1e555236 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js @@ -17,18 +17,32 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React, { Component } from 'react'; +import React from 'react'; +import shallowCompare from 'react-addons-shallow-compare'; import { translate } from '../../../helpers/l10n'; -export default class Stats extends Component { +export default class Stats extends React.Component { + static propTypes = { + failingCount: React.PropTypes.number, + pendingCount: React.PropTypes.number, + onShowFailing: React.PropTypes.func.isRequired, + onCancelAllPending: React.PropTypes.func.isRequired + }; + + shouldComponentUpdate (nextProps, nextState) { + return shallowCompare(this, nextProps, nextState); + } + handleCancelAllPending (e) { e.preventDefault(); + e.target.blur(); this.props.onCancelAllPending(); } handleShowFailing (e) { e.preventDefault(); + e.target.blur(); this.props.onShowFailing(); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js index c156d0fb1c6..5228ad42f16 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/StatusFilter.js @@ -23,7 +23,7 @@ import Select from 'react-select'; import { STATUSES } from '../constants'; import { translate } from '../../../helpers/l10n'; -export default function StatusFilter ({ value, onChange }) { +const StatusFilter = ({ value, onChange }) => { const options = [ { value: STATUSES.ALL, label: translate('background_task.status.ALL') }, { value: STATUSES.ALL_EXCEPT_PENDING, label: translate('background_task.status.ALL_EXCEPT_PENDING') }, @@ -43,4 +43,6 @@ export default function StatusFilter ({ value, onChange }) { clearable={false} searchable={false}/> ); -} +}; + +export default StatusFilter; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js index 87ce4286d0b..4ef215963b0 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; +import shallowCompare from 'react-addons-shallow-compare'; import TaskStatus from './TaskStatus'; import TaskComponent from './TaskComponent'; @@ -28,43 +29,61 @@ import TaskCancelButton from './TaskCancelButton'; import TaskLogsLink from './TaskLogsLink'; import { STATUSES } from './../constants'; -export default function Task ({ task, index, tasks, component, types, onCancelTask, onFilterTask }) { - function handleFilterTask (task, e) { +export default class Task extends React.Component { + static propTypes = { + task: React.PropTypes.object.isRequired, + index: React.PropTypes.number.isRequired, + tasks: React.PropTypes.array.isRequired, + component: React.PropTypes.object, + types: React.PropTypes.array.isRequired, + onCancelTask: React.PropTypes.func.isRequired, + onFilterTask: React.PropTypes.func.isRequired + }; + + shouldComponentUpdate (nextProps, nextState) { + return shallowCompare(this, nextProps, nextState); + } + + handleFilterTask (task, e) { e.preventDefault(); - onFilterTask(task); + this.props.onFilterTask(task); } - const prevTask = index > 0 ? tasks[index - 1] : null; + render () { + const { task, index, tasks, component, types, onCancelTask } = this.props; - return ( - <tr> - <TaskStatus task={task}/> - <TaskComponent task={task} types={types}/> - <TaskDay task={task} prevTask={prevTask}/> - <TaskDate date={task.submittedAt} baseDate={task.submittedAt} format="LTS"/> - <TaskDate date={task.startedAt} baseDate={task.submittedAt} format="LTS"/> - <TaskDate date={task.executedAt} baseDate={task.submittedAt} format="LTS"/> - <TaskExecutionTime task={task}/> + const prevTask = index > 0 ? tasks[index - 1] : null; - <td className="thin nowrap text-right"> - {task.logs && ( - <TaskLogsLink task={task}/> - )} - {task.status === STATUSES.PENDING && ( - <TaskCancelButton task={task} onCancelTask={onCancelTask}/> - )} - </td> + return ( + <tr> + <TaskStatus task={task}/> + <TaskComponent task={task} types={types}/> + <TaskDay task={task} prevTask={prevTask}/> + <TaskDate date={task.submittedAt} baseDate={task.submittedAt} format="LTS"/> + <TaskDate date={task.startedAt} baseDate={task.submittedAt} format="LTS"/> + <TaskDate date={task.executedAt} baseDate={task.submittedAt} format="LTS"/> + <TaskExecutionTime task={task}/> - <td className="thin nowrap"> - {!component && ( - <a - onClick={handleFilterTask.bind(this, task)} - className="icon-filter icon-half-transparent spacer-left" - href="#" - title={`Show only "${task.componentName}" tasks`} - data-toggle="tooltip"/> - )} - </td> - </tr> - ); + <td className="thin nowrap text-right"> + {task.logs && ( + <TaskLogsLink task={task}/> + )} + {task.status === STATUSES.PENDING && ( + <TaskCancelButton task={task} onCancelTask={onCancelTask}/> + )} + </td> + + <td className="thin nowrap"> + {!component && ( + <a + onClick={this.handleFilterTask.bind(this, task)} + className="icon-filter icon-half-transparent spacer-left" + href="#" + title={`Show only "${task.componentName}" tasks`} + data-toggle="tooltip"/> + )} + </td> + </tr> + ); + } } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js index f5b793db0fb..d6469deba43 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskCancelButton.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default function TaskCancelButton ({ task, onCancelTask }) { +const TaskCancelButton = ({ task, onCancelTask }) => { function handleClick (e) { e.preventDefault(); onCancelTask(task); @@ -34,4 +34,6 @@ export default function TaskCancelButton ({ task, onCancelTask }) { data-toggle="tooltip" href="#"/> ); -} +}; + +export default TaskCancelButton; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js index d191442ff4a..581f5250d18 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDate.js @@ -20,7 +20,7 @@ import moment from 'moment'; import React from 'react'; -export default function TaskDate ({ date, baseDate, format }) { +const TaskDate = ({ date, baseDate, format }) => { const m = moment(date); const baseM = moment(baseDate); const diff = (date && baseDate) ? m.diff(baseM, 'days') : 0; @@ -34,4 +34,6 @@ export default function TaskDate ({ date, baseDate, format }) { {date ? moment(date).format(format) : ''} </td> ); -} +}; + +export default TaskDate; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js index 663cffa59be..60972ebf86a 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskDay.js @@ -24,7 +24,7 @@ function isAnotherDay (a, b) { return !moment(a).isSame(moment(b), 'day'); } -export default function TaskDay ({ task, prevTask }) { +const TaskDay = ({ task, prevTask }) => { const shouldDisplay = !prevTask || isAnotherDay(task.submittedAt, prevTask.submittedAt); return ( @@ -32,4 +32,6 @@ export default function TaskDay ({ task, prevTask }) { {shouldDisplay ? moment(task.submittedAt).format('LL') : ''} </td> ); -} +}; + +export default TaskDay; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js index 07e830d148a..98173c1af04 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskExecutionTime.js @@ -18,12 +18,14 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import { formatDuration } from './../helpers'; +import { formatDuration } from '../utils'; -export default function TaskExecutionTime ({ task }) { +const TaskExecutionTime = ({ task }) => { return ( <td className="thin nowrap text-right"> {formatDuration(task.executionTimeMs)} </td> ); -} +}; + +export default TaskExecutionTime; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskLogsLink.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskLogsLink.js index 2f5893e8bed..e05dfb1f2cb 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskLogsLink.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskLogsLink.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default function TaskLogsLink ({ task }) { +const TaskLogsLink = ({ task }) => { const url = `${window.baseUrl}/api/ce/logs?taskId=${task.id}`; return ( @@ -30,4 +30,6 @@ export default function TaskLogsLink ({ task }) { {translate('background_tasks.logs')} </a> ); -} +}; + +export default TaskLogsLink; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js index 060e397a137..69e4ad97cf1 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskStatus.js @@ -23,7 +23,7 @@ import { STATUSES } from './../constants'; import PendingIcon from '../../../components/shared/pending-icon'; import { translate } from '../../../helpers/l10n'; -export default function TaskStatus ({ task }) { +const TaskStatus = ({ task }) => { let inner; switch (task.status) { @@ -47,4 +47,6 @@ export default function TaskStatus ({ task }) { } return <td className="thin spacer-right">{inner}</td>; -} +}; + +export default TaskStatus; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js index c086e2a110d..0cb1ddf0822 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js @@ -18,14 +18,36 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; +import shallowCompare from 'react-addons-shallow-compare'; +import classNames from 'classnames'; import Task from './Task'; import { translate } from '../../../helpers/l10n'; -export default function Tasks ({ tasks, component, types, onCancelTask, onFilterTask }) { - return ( - <table className="data zebra zebra-hover background-tasks"> - <thead> +export default class Tasks extends React.Component { + static propTypes = { + tasks: React.PropTypes.array.isRequired, + component: React.PropTypes.object, + types: React.PropTypes.array.isRequired, + loading: React.PropTypes.bool.isRequired, + onCancelTask: React.PropTypes.func.isRequired, + onFilterTask: React.PropTypes.func.isRequired + }; + + shouldComponentUpdate (nextProps, nextState) { + return shallowCompare(this, nextProps, nextState); + } + + render () { + const { tasks, component, types, loading, onCancelTask, onFilterTask } = this.props; + + const className = classNames('data zebra zebra-hover background-tasks', { + 'new-loading': loading + }); + + return ( + <table className={className}> + <thead> <tr> <th> </th> <th> </th> @@ -36,8 +58,8 @@ export default function Tasks ({ tasks, component, types, onCancelTask, onFilter <th>{translate('background_tasks.table.duration')}</th> <th> </th> </tr> - </thead> - <tbody> + </thead> + <tbody> {tasks.map((task, index, tasks) => ( <Task key={task.id} @@ -49,7 +71,8 @@ export default function Tasks ({ tasks, component, types, onCancelTask, onFilter onCancelTask={onCancelTask} onFilterTask={onFilterTask}/> ))} - </tbody> - </table> - ); + </tbody> + </table> + ); + } } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js index 5e6696a468b..825ba90fb6a 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TypesFilter.js @@ -23,7 +23,7 @@ import Select from 'react-select'; import { ALL_TYPES } from '../constants'; import { translate } from '../../../helpers/l10n'; -export default function TypesFilter ({ value, onChange, types }) { +const TypesFilter = ({ value, onChange, types }) => { const options = types.map(t => { return { value: t, @@ -45,4 +45,6 @@ export default function TypesFilter ({ value, onChange, types }) { clearable={false} searchable={false}/> ); -} +}; + +export default TypesFilter; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/constants.js b/server/sonar-web/src/main/js/apps/background-tasks/constants.js index 7915c37540a..ed5f571d2a8 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/constants.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/constants.js @@ -44,7 +44,8 @@ export const DEFAULT_FILTERS = { status: STATUSES.ALL_EXCEPT_PENDING, taskType: ALL_TYPES, currents: CURRENTS.ALL, - date: {}, + minSubmittedAt: '', + maxExecutedAt: '', query: '' }; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/containers/BackgroundTasksAppContainer.js b/server/sonar-web/src/main/js/apps/background-tasks/containers/BackgroundTasksAppContainer.js deleted file mode 100644 index 478c53f2dfc..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/containers/BackgroundTasksAppContainer.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 { connect } from 'react-redux'; - -import Main from '../components/BackgroundTasksApp'; -import { initApp } from '../store/actions'; - -function mapStateToProps (state) { - return { - tasks: state.tasks - }; -} - -function mapDispatchToProps (dispatch) { - return { - initApp: component => dispatch(initApp(component)) - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Main); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/containers/SearchContainer.js b/server/sonar-web/src/main/js/apps/background-tasks/containers/SearchContainer.js deleted file mode 100644 index 6314eab7cee..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/containers/SearchContainer.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 { connect } from 'react-redux'; - -import Search from '../components/Search'; -import { filterTasks, search } from '../store/actions'; -import { STATUSES, CURRENTS, DEFAULT_FILTERS } from '../constants'; - -function mapStateToProps (state) { - return { - fetching: state.fetching, - status: state.status, - currents: state.currents, - date: state.date, - query: state.query, - taskType: state.taskType, - types: state.types, - component: state.component - }; -} - -function updateStatusQuery (status) { - if (status === STATUSES.PENDING) { - return { status, currents: CURRENTS.ALL }; - } else { - return { status }; - } -} - -function mapDispatchToProps (dispatch) { - return { - onRefresh: () => dispatch(filterTasks()), - onReset: () => dispatch(filterTasks(DEFAULT_FILTERS)), - onStatusChange: status => dispatch(filterTasks(updateStatusQuery(status))), - onTypeChange: taskType => dispatch(filterTasks({ taskType })), - onCurrentsChange: currents => dispatch(filterTasks({ currents, status: STATUSES.ALL_EXCEPT_PENDING })), - onDateChange: date => dispatch(filterTasks({ date })), - onSearch: query => dispatch(search(query)) - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Search); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/containers/StatsContainer.js b/server/sonar-web/src/main/js/apps/background-tasks/containers/StatsContainer.js deleted file mode 100644 index 510295faf54..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/containers/StatsContainer.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 { connect } from 'react-redux'; - -import Stats from '../components/Stats'; -import { filterTasks, cancelAllPending } from '../store/actions'; -import { STATUSES, CURRENTS, DEFAULT_FILTERS } from '../constants'; - -function mapStateToProps (state) { - return { - pendingCount: state.pendingCount, - failingCount: state.failingCount, - component: state.component - }; -} - -function mapDispatchToProps (dispatch) { - return { - onShowFailing: () => dispatch(filterTasks({ - ...DEFAULT_FILTERS, - status: STATUSES.FAILED, - currents: CURRENTS.ONLY_CURRENTS - })), - onCancelAllPending: () => dispatch(cancelAllPending()) - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Stats); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/containers/TasksContainer.js b/server/sonar-web/src/main/js/apps/background-tasks/containers/TasksContainer.js deleted file mode 100644 index 783b304934e..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/containers/TasksContainer.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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 { connect } from 'react-redux'; - -import Tasks from '../components/Tasks'; -import { cancelTask, filterTasks } from '../store/actions'; -import { DEFAULT_FILTERS } from '../constants'; - -function mapStateToProps (state) { - return { - fetching: state.fetching, - tasks: state.tasks, - component: state.component, - types: state.types - }; -} - -function mapDispatchToProps (dispatch) { - return { - onCancelTask: task => dispatch(cancelTask(task)), - onFilterTask: task => dispatch(filterTasks(Object.assign({}, DEFAULT_FILTERS, { query: task.componentKey }))) - }; -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(Tasks); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/store/actions.js b/server/sonar-web/src/main/js/apps/background-tasks/store/actions.js deleted file mode 100644 index 095f659f0ca..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/store/actions.js +++ /dev/null @@ -1,210 +0,0 @@ -/* - * 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 _ from 'underscore'; -import { getTypes, getActivity, getStatus, cancelAllTasks, cancelTask as cancelTaskAPI } from '../../../api/ce'; - -import { STATUSES, ALL_TYPES, CURRENTS, DEBOUNCE_DELAY } from '../constants'; - -export const INIT = 'INIT'; -export const REQUEST_TASKS = 'REQUEST_TASKS'; -export const RECEIVE_TASKS = 'RECEIVE_TASKS'; -export const UPDATE_QUERY = 'UPDATE_QUERY'; -export const RECEIVE_STATS = 'RECEIVE_STATS'; -export const CANCEL_ALL_PENDING = 'CANCEL_ALL_PENDING'; -export const CANCEL_TASK = 'CANCEL_TASK'; -export const FINISH_CANCEL_TASK = 'FINISH_CANCEL_TASK'; - -export function init (component, types) { - return { - type: INIT, - component, - types - }; -} - -export function requestTasks (filters) { - return { - type: REQUEST_TASKS, - ...filters - }; -} - -export function receiveTasks (tasks) { - return { - type: RECEIVE_TASKS, - tasks - }; -} - -export function updateQuery (query) { - return { - type: UPDATE_QUERY, - query - }; -} - -export function receiveStats ({ pendingCount, failingCount }) { - return { - type: RECEIVE_STATS, - pendingCount, - failingCount - }; -} - -export function cancelAllPendingAction () { - return { - type: CANCEL_ALL_PENDING - }; -} - -export function cancelTaskAction (task) { - return { - type: CANCEL_TASK, - task - }; -} - -export function finishCancelTaskAction (task) { - return { - type: FINISH_CANCEL_TASK, - task - }; -} - -function mapFiltersToParameters (filters = {}) { - const parameters = {}; - - if (filters.status === STATUSES.ALL) { - parameters.status = [ - STATUSES.PENDING, - STATUSES.IN_PROGRESS, - STATUSES.SUCCESS, - STATUSES.FAILED, - STATUSES.CANCELED - ].join(); - } else if (filters.status === STATUSES.ALL_EXCEPT_PENDING) { - parameters.status = [ - STATUSES.IN_PROGRESS, - STATUSES.SUCCESS, - STATUSES.FAILED, - STATUSES.CANCELED - ].join(); - } else { - parameters.status = filters.status; - } - - if (filters.taskType !== ALL_TYPES) { - parameters.type = filters.taskType; - } - - if (filters.currents !== CURRENTS.ALL) { - parameters.onlyCurrents = true; - } - - if (filters.date.minSubmittedAt) { - parameters.minSubmittedAt = filters.date.minSubmittedAt; - } - - if (filters.date.maxExecutedAt) { - parameters.maxExecutedAt = filters.date.maxExecutedAt; - } - - if (filters.query) { - parameters.componentQuery = filters.query; - } - - if (filters.lastPage !== 1) { - parameters.p = filters.lastPage; - } - - return parameters; -} - -function fetchTasks (filters) { - return (dispatch, getState) => { - const { component } = getState(); - const parameters = mapFiltersToParameters(filters); - - if (component) { - parameters.componentId = component.id; - } - - dispatch(requestTasks(filters)); - - return Promise.all([ - getActivity(parameters), - getStatus(parameters.componentId) - ]).then(responses => { - const [activity, status] = responses; - const tasks = activity.tasks; - - dispatch(receiveTasks(tasks)); - - const pendingCount = status.pending; - const failingCount = status.failing; - - dispatch(receiveStats({ pendingCount, failingCount })); - }); - }; -} - -export function filterTasks (overriddenFilters) { - return (dispatch, getState) => { - const { status, taskType, currents, date, query } = getState(); - const filters = { status, taskType, currents, date, query }; - const finalFilters = { ...filters, ...overriddenFilters }; - - dispatch(fetchTasks(finalFilters)); - }; -} - -const debouncedFilter = _.debounce((dispatch, overriddenFilters) => { - dispatch(filterTasks(overriddenFilters)); -}, DEBOUNCE_DELAY); - -export function search (query) { - return dispatch => { - dispatch(updateQuery(query)); - debouncedFilter(dispatch, { query }); - }; -} - -export function cancelAllPending () { - return dispatch => { - dispatch(cancelAllPendingAction()); - cancelAllTasks().then(() => dispatch(filterTasks())); - }; -} - -export function cancelTask (task) { - return dispatch => { - dispatch(cancelTaskAction(task)); - cancelTaskAPI(task.id).then(nextTask => dispatch(finishCancelTaskAction(nextTask))); - }; -} - -export function initApp (component) { - return dispatch => { - getTypes().then(types => { - dispatch(init(component, types)); - dispatch(filterTasks()); - }); - }; -} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/store/reducers.js b/server/sonar-web/src/main/js/apps/background-tasks/store/reducers.js deleted file mode 100644 index 5ac2f53ee93..00000000000 --- a/server/sonar-web/src/main/js/apps/background-tasks/store/reducers.js +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 { - INIT, - REQUEST_TASKS, - RECEIVE_TASKS, - UPDATE_QUERY, - RECEIVE_STATS, - CANCEL_ALL_PENDING, - FINISH_CANCEL_TASK -} from './actions'; -import { DEFAULT_FILTERS } from '../constants'; - -export const initialState = { - fetching: false, - tasks: [], - - types: [], - - // filters - ...DEFAULT_FILTERS, - - // stats - pendingCount: 0, - failingCount: 0 -}; - -function updateTask (tasks, newTask) { - return tasks.map(task => task.id === newTask.id ? newTask : task); -} - -export default function (state = initialState, action = {}) { - switch (action.type) { - case INIT: - return { - ...state, - component: action.component, - types: action.types - }; - case REQUEST_TASKS: - return { - ...state, - fetching: true, - status: action.status, - currents: action.currents, - date: action.date, - query: action.query, - taskType: action.taskType - }; - case RECEIVE_TASKS: - return { - ...state, - fetching: false, - tasks: action.tasks - }; - case UPDATE_QUERY: - return { - ...state, - query: action.query - }; - case RECEIVE_STATS: - return { - ...state, - pendingCount: action.pendingCount, - failingCount: action.failingCount - }; - case CANCEL_ALL_PENDING: - return { - ...state, - fetching: true - }; - case FINISH_CANCEL_TASK: - return { - ...state, - tasks: updateTask(state.tasks, action.task) - }; - default: - return state; - } -} diff --git a/server/sonar-web/src/main/js/apps/background-tasks/helpers.js b/server/sonar-web/src/main/js/apps/background-tasks/utils.js index a3c797b6985..97207fa9864 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/helpers.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/utils.js @@ -17,6 +17,61 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { STATUSES, ALL_TYPES, CURRENTS } from './constants'; + +export function updateTask (tasks, newTask) { + return tasks.map(task => task.id === newTask.id ? newTask : task); +} + +export function mapFiltersToParameters (filters = {}) { + const parameters = {}; + + if (filters.status === STATUSES.ALL) { + parameters.status = [ + STATUSES.PENDING, + STATUSES.IN_PROGRESS, + STATUSES.SUCCESS, + STATUSES.FAILED, + STATUSES.CANCELED + ].join(); + } else if (filters.status === STATUSES.ALL_EXCEPT_PENDING) { + parameters.status = [ + STATUSES.IN_PROGRESS, + STATUSES.SUCCESS, + STATUSES.FAILED, + STATUSES.CANCELED + ].join(); + } else { + parameters.status = filters.status; + } + + if (filters.taskType !== ALL_TYPES) { + parameters.type = filters.taskType; + } + + if (filters.currents !== CURRENTS.ALL) { + parameters.onlyCurrents = true; + } + + if (filters.minSubmittedAt) { + parameters.minSubmittedAt = filters.minSubmittedAt; + } + + if (filters.maxExecutedAt) { + parameters.maxExecutedAt = filters.maxExecutedAt; + } + + if (filters.query) { + parameters.componentQuery = filters.query; + } + + if (filters.lastPage !== 1) { + parameters.p = filters.lastPage; + } + + return parameters; +} + const ONE_SECOND = 1000; const ONE_MINUTE = 60 * ONE_SECOND; |