From d907e6ec4ec374124061f6d397b4e863a8eb2ce1 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Wed, 9 Apr 2025 14:36:42 +0300 Subject: [PATCH 1/2] fix awaiting for project updates to propagate --- src/containers/ProjectInvitations/index.js | 20 +++++++++++------ src/util/delay.js | 25 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 src/util/delay.js diff --git a/src/containers/ProjectInvitations/index.js b/src/containers/ProjectInvitations/index.js index 89048b82..1b6ce528 100644 --- a/src/containers/ProjectInvitations/index.js +++ b/src/containers/ProjectInvitations/index.js @@ -11,6 +11,7 @@ import ConfirmationModal from '../../components/Modal/ConfirmationModal' import styles from './ProjectInvitations.module.scss' import { updateProjectMemberInvite } from '../../services/projectMemberInvites' import { PROJECT_MEMBER_INVITE_STATUS_ACCEPTED, PROJECT_MEMBER_INVITE_STATUS_REFUSED } from '../../config/constants' +import { delay } from '../../util/delay' const theme = { container: styles.modalContainer @@ -44,7 +45,14 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet const updateInvite = useCallback(async (status) => { setIsUpdating(status) await updateProjectMemberInvite(projectId, invitation.id, status) + + // await for the project details to propagate + await delay(1000) + await loadProject(projectId) toastr.success('Success', `Successfully ${status} the invitation.`) + + // await for the project details to fetch + await delay(1000) history.push(status === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED ? `/projects/${projectId}/challenges` : '/projects') }, [invitation]) @@ -56,13 +64,11 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet return } - setTimeout(() => { - if (automaticAction === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED) { - acceptInvite() - } else if (automaticAction === PROJECT_MEMBER_INVITE_STATUS_REFUSED) { - declineInvite() - } - }, [1500]) + if (automaticAction === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED) { + acceptInvite() + } else if (automaticAction === PROJECT_MEMBER_INVITE_STATUS_REFUSED) { + declineInvite() + } }, [invitation, automaticAction]) return ( diff --git a/src/util/delay.js b/src/util/delay.js new file mode 100644 index 00000000..411a2ed4 --- /dev/null +++ b/src/util/delay.js @@ -0,0 +1,25 @@ +/** + * Creates a delay that can be awaited, and optionally aborted via an AbortSignal. + * + * @param ms - The number of milliseconds to delay. + * @param signal - Optional AbortSignal to cancel the delay early. + * @returns A Promise that resolves after the delay, or rejects if aborted. + */ +export function delay (ms, signal) { + return new Promise((resolve, reject) => { + // Start a timer that will resolve the promise after `ms` milliseconds + const timeout = setTimeout(resolve, ms) + + // If an AbortSignal is provided, handle abort events + if (signal) { + // Listen for the 'abort' event + signal.addEventListener('abort', () => { + // Cancel the timeout so it doesn't resolve the promise later + clearTimeout(timeout) + // Reject the promise with a DOMException for consistency with other abortable APIs + // eslint-disable-next-line no-undef + reject(new DOMException('Delay aborted', 'AbortError')) + }, { once: true }) // 'once' ensures the handler is removed automatically after it runs + } + }) +} From 7c2a793f1fce1b5cc42dcae7f5886beafc475993 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Wed, 9 Apr 2025 14:45:52 +0300 Subject: [PATCH 2/2] PR feedback --- src/containers/ProjectInvitations/index.js | 2 +- src/util/delay.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/containers/ProjectInvitations/index.js b/src/containers/ProjectInvitations/index.js index 1b6ce528..d39eb0ae 100644 --- a/src/containers/ProjectInvitations/index.js +++ b/src/containers/ProjectInvitations/index.js @@ -54,7 +54,7 @@ const ProjectInvitations = ({ match, auth, isProjectLoading, history, projectDet // await for the project details to fetch await delay(1000) history.push(status === PROJECT_MEMBER_INVITE_STATUS_ACCEPTED ? `/projects/${projectId}/challenges` : '/projects') - }, [invitation]) + }, [projectId, invitation, loadProject, history]) const acceptInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_ACCEPTED), [updateInvite]) const declineInvite = useCallback(() => updateInvite(PROJECT_MEMBER_INVITE_STATUS_REFUSED), [updateInvite]) diff --git a/src/util/delay.js b/src/util/delay.js index 411a2ed4..398f3d08 100644 --- a/src/util/delay.js +++ b/src/util/delay.js @@ -1,8 +1,8 @@ /** * Creates a delay that can be awaited, and optionally aborted via an AbortSignal. * - * @param ms - The number of milliseconds to delay. - * @param signal - Optional AbortSignal to cancel the delay early. + * @param {number} ms - The number of milliseconds to delay. + * @param {AbortSignal} signal - Optional AbortSignal to cancel the delay early. * @returns A Promise that resolves after the delay, or rejects if aborted. */ export function delay (ms, signal) {