forked from openedx/frontend-app-authoring
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOutOfSyncAlert.tsx
More file actions
76 lines (71 loc) · 2.63 KB
/
OutOfSyncAlert.tsx
File metadata and controls
76 lines (71 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import React, { useEffect } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import { Button } from '@openedx/paragon';
import { Loop } from '@openedx/paragon/icons';
import AlertMessage from '../generic/alert-message';
import { useEntityLinksSummaryByDownstreamContext } from './data/apiHooks';
import messages from './messages';
interface OutOfSyncAlertProps {
showAlert: boolean,
setShowAlert: React.Dispatch<React.SetStateAction<boolean>>,
courseId: string,
onDismiss?: () => void;
onReview: () => void;
}
/**
* Shows an alert when library components used in the current course were updated and the blocks
* in course can be updated. Following are the conditions for displaying the alert.
*
* * The alert is displayed if components are out of sync.
* * If the user clicks on dismiss button, the state of dismiss is stored in localstorage of user
* in this format: outOfSyncCountAlert-${courseId} = <datetime value in milliseconds>.
* * If there are not new published components for the course and the user opens outline
* in the same browser, they don't see the alert again.
* * If there is a new published component upstream, the alert is displayed again.
*/
export const OutOfSyncAlert: React.FC<OutOfSyncAlertProps> = ({
showAlert,
setShowAlert,
courseId,
onDismiss,
onReview,
}) => {
const intl = useIntl();
const { data, isPending } = useEntityLinksSummaryByDownstreamContext(courseId);
const outOfSyncCount = data?.reduce((count, lib) => count + (lib.readyToSyncCount || 0), 0);
const lastPublishedDate = data?.map(lib => new Date(lib.lastPublishedAt || 0).getTime())
.reduce((acc, lastPublished) => Math.max(lastPublished, acc), 0);
const alertKey = `outOfSyncCountAlert-${courseId}`;
useEffect(() => {
if (isPending) {
return;
}
if (outOfSyncCount === 0) {
localStorage.removeItem(alertKey);
setShowAlert(false);
return;
}
const dismissedAlertDate = parseInt(localStorage.getItem(alertKey) ?? '0', 10);
setShowAlert((lastPublishedDate ?? 0) > dismissedAlertDate);
}, [outOfSyncCount, lastPublishedDate, isPending, data]);
const dismissAlert = () => {
setShowAlert(false);
localStorage.setItem(alertKey, Date.now().toString());
onDismiss?.();
};
return (
<AlertMessage
title={intl.formatMessage(messages.outOfSyncCountAlertTitle, { outOfSyncCount })}
dismissible
show={showAlert}
icon={Loop}
variant="info"
onClose={dismissAlert}
actions={[
<Button key="review-btn" onClick={onReview}>
{intl.formatMessage(messages.outOfSyncCountAlertReviewBtn)}
</Button>,
]}
/>
);
};