diff --git a/src/client/components/Task/index.jsx b/src/client/components/Task/index.jsx index a959c2dc74c..c7cf8b0e906 100644 --- a/src/client/components/Task/index.jsx +++ b/src/client/components/Task/index.jsx @@ -15,6 +15,8 @@ import Err from './Error' import ProgressIndicator from '../ProgressIndicator' import AccessDenied from '../AccessDenied' +const DEFAULT_PROGRESS_DELAY = 100 + const StyledLoadingBox = styled(LoadingBox)({ paddingBottom: 0, }) @@ -45,6 +47,10 @@ const startOnRenderPropTypes = { * result of a _tasks_ success. If set, a {SuccessAction} with this value * as its `type` will be dispatched when the _task_ succeeds, but before the * _task_ is _cleared_. + * @property {number} [progressDelay=100] - The duration in milliseconds + * for which switching a task to a progress state should be delayed. + * This is to avoid showing the progress indicator for tasks which resolve + * immediately. */ /** @@ -122,13 +128,18 @@ const startOnRenderPropTypes = { const Task = connect( (state) => state.tasks, (dispatch) => ({ - start: (name, id, { payload, onSuccessDispatch }) => + start: ( + name, + id, + { payload, onSuccessDispatch, progressDelay = DEFAULT_PROGRESS_DELAY } + ) => dispatch({ type: TASK__START, payload, id, name, onSuccessDispatch, + progressDelay, }), cancel: (name, id) => dispatch({ @@ -174,11 +185,13 @@ Task.propTypes = { * @example * */ +// TODO: Re-implement with Task.StartOnRender = connect( (state, { name, id }) => get(state, ['tasks', name, id], {}), (dispatch, { id, name }) => ({ start: (options) => dispatch({ + progressDelay: DEFAULT_PROGRESS_DELAY, ...options, type: TASK__START, id, diff --git a/src/client/components/Task/saga.js b/src/client/components/Task/saga.js index ec095351e25..fa7d5b64431 100644 --- a/src/client/components/Task/saga.js +++ b/src/client/components/Task/saga.js @@ -7,6 +7,7 @@ import { call, select, cancel, + delay, } from 'redux-saga/effects' import { @@ -18,15 +19,22 @@ import { TASK__CANCEL, } from '../../actions' +function* switchToProgressAfterDelay(action) { + yield delay(action.progressDelay || 0) + yield put({ ...action, type: TASK__PROGRESS }) +} + /** * Starts a task and waits for its resolution or rejection * @param {Task} task - the task function * @param {TaskStartAction} action - the `TASK__START` action */ function* startTask(task, action) { - yield put({ ...action, type: TASK__PROGRESS }) + const progressDelayProcess = yield fork(switchToProgressAfterDelay, action) + try { const result = yield call(task, action.payload, action.id) + yield cancel(progressDelayProcess) const { id, name, payload, onSuccessDispatch } = action if (onSuccessDispatch) { yield put({