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({