Skip to content

Commit d9fd1ac

Browse files
committed
Add invites v1
1 parent 4fe298d commit d9fd1ac

36 files changed

Lines changed: 2895 additions & 27 deletions

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"redux-logger": "^3.0.6",
5252
"redux-persist": "^6.0.0",
5353
"reselect": "^5.1.1",
54+
"rrule": "^2.8.1",
5455
"socket.io-client": "^4.8.0",
5556
"typescript": "^5.9.3",
5657
"uuid": "^9.0.1",

public/config/config.example.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ var config = {
9898
*/
9999
myRoomsTabEnabled: true,
100100

101+
/**
102+
* Enable/disable tab 'My meetings' (upcoming calendar invites) on landing page
103+
*/
104+
myMeetingsTabEnabled: true,
101105

102106
/**
103107
* Optional: enable countdown timer in UI.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { useEffect, useState } from 'react';
2+
import EventIcon from '@mui/icons-material/Event';
3+
import ControlButton, { ControlButtonProps } from './ControlButton';
4+
import { useAppDispatch, useAppSelector } from '../../store/hooks';
5+
import { getData } from '../../store/actions/managementActions';
6+
import edumeetConfig from '../../utils/edumeetConfig';
7+
import MeetingsDialog from '../meetingsdialog/MeetingsDialog';
8+
import { upcomingMeetingsLabel } from '../translated/translatedComponents';
9+
10+
const MeetingsButton = ({
11+
...props
12+
}: ControlButtonProps): React.JSX.Element | null => {
13+
const dispatch = useAppDispatch();
14+
const loggedIn = useAppSelector((state) => state.permissions.loggedIn);
15+
const myMeetingsTabEnabled = edumeetConfig.myMeetingsTabEnabled;
16+
17+
const [ invitesEnabled, setInvitesEnabled ] = useState(false);
18+
const [ open, setOpen ] = useState(false);
19+
20+
useEffect(() => {
21+
// always hide until the current async check confirms invites are on
22+
setInvitesEnabled(false);
23+
if (!loggedIn || !myMeetingsTabEnabled) return;
24+
25+
let cancelled = false;
26+
27+
dispatch(getData('tenantInviteConfigs'))
28+
.then((res: unknown) => {
29+
if (cancelled) return;
30+
const list = (res && typeof res === 'object' && 'data' in res)
31+
? (res as { data: Array<{ enabled?: boolean }> }).data
32+
: [];
33+
const hasEnabled = Array.isArray(list) && list.some((c) => c.enabled);
34+
35+
setInvitesEnabled(Boolean(hasEnabled));
36+
})
37+
.catch(() => {
38+
if (!cancelled) setInvitesEnabled(false);
39+
});
40+
41+
return () => {
42+
cancelled = true;
43+
};
44+
}, [ loggedIn, myMeetingsTabEnabled ]);
45+
46+
if (!loggedIn || !myMeetingsTabEnabled || !invitesEnabled) return null;
47+
48+
return (
49+
<>
50+
<ControlButton
51+
toolTip={upcomingMeetingsLabel()}
52+
onClick={() => setOpen(true)}
53+
{ ...props }
54+
>
55+
<EventIcon />
56+
</ControlButton>
57+
<MeetingsDialog open={open} onClose={() => setOpen(false)} />
58+
</>
59+
);
60+
};
61+
62+
export default MeetingsButton;

0 commit comments

Comments
 (0)