diff --git a/backend/api/utils/jaas_jwt_builder.py b/backend/api/utils/jaas_jwt_builder.py
index b70e5ee4..93c89fec 100644
--- a/backend/api/utils/jaas_jwt_builder.py
+++ b/backend/api/utils/jaas_jwt_builder.py
@@ -1,9 +1,10 @@
import time, uuid
from authlib.jose import jwt
+
class JaaSJwtBuilder:
"""
- The JaaSJwtBuilder class helps with the generation of the JaaS JWT.
+ The JaaSJwtBuilder class helps with the generation of the JaaS JWT.
"""
EXP_TIME_DELAY_SEC = 7200
@@ -13,22 +14,24 @@ class JaaSJwtBuilder:
# Used as a delay for the nbf claim value.
def __init__(self) -> None:
- self.header = { 'alg' : 'RS256' }
+ self.header = {"alg": "RS256"}
self.userClaims = {}
self.featureClaims = {}
self.payloadClaims = {}
def withDefaults(self):
"""Returns the JaaSJwtBuilder with default valued claims."""
- return self.withExpTime(int(time.time() + JaaSJwtBuilder.EXP_TIME_DELAY_SEC)) \
- .withNbfTime(int(time.time() - JaaSJwtBuilder.NBF_TIME_DELAY_SEC)) \
- .withLiveStreamingEnabled(True) \
- .withRecordingEnabled(True) \
- .withOutboundCallEnabled(True) \
- .withTranscriptionEnabled(True) \
- .withModerator(True) \
- .withRoomName('*') \
- .withUserId(str(uuid.uuid4()))
+ return (
+ self.withExpTime(int(time.time() + JaaSJwtBuilder.EXP_TIME_DELAY_SEC))
+ .withNbfTime(int(time.time() - JaaSJwtBuilder.NBF_TIME_DELAY_SEC))
+ .withLiveStreamingEnabled(True)
+ .withRecordingEnabled(True)
+ .withOutboundCallEnabled(True)
+ .withTranscriptionEnabled(True)
+ .withModerator(True)
+ .withRoomName("*")
+ .withUserId(str(uuid.uuid4()))
+ )
def withApiKey(self, apiKey):
"""
@@ -36,7 +39,7 @@ def withApiKey(self, apiKey):
:param apiKey A string as the API Key https://jaas.8x8.vc/#/apikeys
"""
- self.header['kid'] = apiKey
+ self.header["kid"] = apiKey
return self
def withUserAvatar(self, avatarUrl):
@@ -45,7 +48,7 @@ def withUserAvatar(self, avatarUrl):
:param avatarUrl A string representing the url to get the user avatar.
"""
- self.userClaims['avatar'] = avatarUrl
+ self.userClaims["avatar"] = avatarUrl
return self
def withModerator(self, isModerator):
@@ -54,7 +57,7 @@ def withModerator(self, isModerator):
:param isModerator A boolean if set to True, user is moderator and False otherwise.
"""
- self.userClaims['moderator'] = 'true' if isModerator == True else 'false'
+ self.userClaims["moderator"] = "true" if isModerator == True else "false"
return self
def withUserName(self, userName):
@@ -63,7 +66,7 @@ def withUserName(self, userName):
:param userName A string representing the user's name.
"""
- self.userClaims['name'] = userName
+ self.userClaims["name"] = userName
return self
def withUserEmail(self, userEmail):
@@ -72,7 +75,7 @@ def withUserEmail(self, userEmail):
:param userEmail A string representing the user's email address.
"""
- self.userClaims['email'] = userEmail
+ self.userClaims["email"] = userEmail
return self
def withLiveStreamingEnabled(self, isEnabled):
@@ -81,7 +84,7 @@ def withLiveStreamingEnabled(self, isEnabled):
:param isEnabled A boolean if set to True, live streaming is enabled and False otherwise.
"""
- self.featureClaims['livestreaming'] = 'true' if isEnabled == True else 'false'
+ self.featureClaims["livestreaming"] = "true" if isEnabled == True else "false"
return self
def withRecordingEnabled(self, isEnabled):
@@ -90,7 +93,7 @@ def withRecordingEnabled(self, isEnabled):
:param isEnabled A boolean if set to True, recording is enabled and False otherwise.
"""
- self.featureClaims['recording'] = 'true' if isEnabled == True else 'false'
+ self.featureClaims["recording"] = "true" if isEnabled == True else "false"
return self
def withTranscriptionEnabled(self, isEnabled):
@@ -99,7 +102,7 @@ def withTranscriptionEnabled(self, isEnabled):
:param isEnabled A boolean if set to True, transcription is enabled and False otherwise.
"""
- self.featureClaims['transcription'] = 'true' if isEnabled == True else 'false'
+ self.featureClaims["transcription"] = "true" if isEnabled == True else "false"
return self
def withOutboundCallEnabled(self, isEnabled):
@@ -108,7 +111,7 @@ def withOutboundCallEnabled(self, isEnabled):
:param isEnabled A boolean if set to True, outbound calls are enabled and False otherwise.
"""
- self.featureClaims['outbound-call'] = 'true' if isEnabled == True else 'false'
+ self.featureClaims["outbound-call"] = "true" if isEnabled == True else "false"
return self
def withExpTime(self, expTime):
@@ -117,7 +120,7 @@ def withExpTime(self, expTime):
:param expTime Unix time in seconds since epochs plus a delay. Expiration time of the JWT.
"""
- self.payloadClaims['exp'] = expTime
+ self.payloadClaims["exp"] = expTime
return self
def withNbfTime(self, nbfTime):
@@ -126,7 +129,7 @@ def withNbfTime(self, nbfTime):
:param nbfTime Unix time in seconds since epochs.
"""
- self.payloadClaims['nbfTime'] = nbfTime
+ self.payloadClaims["nbfTime"] = nbfTime
return self
def withRoomName(self, roomName):
@@ -135,7 +138,7 @@ def withRoomName(self, roomName):
:param roomName A string representing the room to join.
"""
- self.payloadClaims['room'] = roomName
+ self.payloadClaims["room"] = roomName
return self
def withAppID(self, AppId):
@@ -144,7 +147,7 @@ def withAppID(self, AppId):
:param AppId A string representing the unique AppID (previously tenant).
"""
- self.payloadClaims['sub'] = AppId
+ self.payloadClaims["sub"] = AppId
return self
def withUserId(self, userId):
@@ -153,7 +156,7 @@ def withUserId(self, userId):
:param A string representing the user, should be unique from your side.
"""
- self.userClaims['id'] = userId
+ self.userClaims["id"] = userId
return self
def signWith(self, key):
@@ -162,8 +165,8 @@ def signWith(self, key):
:param key A string representing the private key in PEM format.
"""
- context = { 'user': self.userClaims, 'features': self.featureClaims }
- self.payloadClaims['context'] = context
- self.payloadClaims['iss'] = 'chat'
- self.payloadClaims['aud'] = 'jitsi'
+ context = {"user": self.userClaims, "features": self.featureClaims}
+ self.payloadClaims["context"] = context
+ self.payloadClaims["iss"] = "chat"
+ self.payloadClaims["aud"] = "jitsi"
return jwt.encode(self.header, self.payloadClaims, key)
diff --git a/backend/api/views/meeting.py b/backend/api/views/meeting.py
index 7a83abd5..7f1e4a37 100644
--- a/backend/api/views/meeting.py
+++ b/backend/api/views/meeting.py
@@ -14,7 +14,8 @@
API_KEY = os.environ.get("EIGHT_X_EIGHT_API_KEY")
APP_ID = os.environ.get("EIGHT_X_EIGHT_APP_ID")
-ENCODED_PRIVATE_KEY = os.environ.get('EIGHT_X_EIGHT_ENCODED_PRIVATE_KEY')
+ENCODED_PRIVATE_KEY = os.environ.get("EIGHT_X_EIGHT_ENCODED_PRIVATE_KEY")
+
@meeting.route("/generateToken", methods=["GET"])
def generateToken():
@@ -23,17 +24,21 @@ def generateToken():
PRIVATE_KEY = base64.b64decode(ENCODED_PRIVATE_KEY)
print(PRIVATE_KEY)
jaasJwt = JaaSJwtBuilder()
- token = jaasJwt.withDefaults() \
- .withApiKey(API_KEY) \
- .withUserName("User Name") \
- .withUserEmail("email_address@email.com") \
- .withModerator(False) \
- .withAppID(APP_ID) \
- .withUserAvatar("https://asda.com/avatar") \
- .signWith(PRIVATE_KEY)
-
- return create_response(data={"token": token.decode('utf-8'), "appID": APP_ID})
+ token = (
+ jaasJwt.withDefaults()
+ .withApiKey(API_KEY)
+ .withUserName("User Name")
+ .withUserEmail("email_address@email.com")
+ .withModerator(False)
+ .withAppID(APP_ID)
+ .withUserAvatar("https://asda.com/avatar")
+ .signWith(PRIVATE_KEY)
+ )
+
+ return create_response(data={"token": token.decode("utf-8"), "appID": APP_ID})
except Exception as error:
print(error)
- return create_response(status=422, message=f'Failed to generate token for meeting')
\ No newline at end of file
+ return create_response(
+ status=422, message=f"Failed to generate token for meeting"
+ )
diff --git a/backend/tests/test_explore.py b/backend/tests/test_explore.py
index 0ee138a8..9837ca51 100644
--- a/backend/tests/test_explore.py
+++ b/backend/tests/test_explore.py
@@ -19,7 +19,7 @@ def test_find_mentee(client):
accounts = result["accounts"]
-# There is no need to write assertion on db level data because its change frequently (Database assertion)
+ # There is no need to write assertion on db level data because its change frequently (Database assertion)
# get the public mentee instances in the database
mentee_users = MenteeProfile.objects.filter(is_private=False).count()
@@ -41,7 +41,7 @@ def test_find_mentor(client):
assert "accounts" in result
accounts = result["accounts"]
- #get the mentor instances in the database
+ # get the mentor instances in the database
mentor_users = MentorProfile.objects.count()
assert len(accounts) > 0
assert (
diff --git a/frontend/src/app/App.js b/frontend/src/app/App.js
index e8a13d4e..a70d38e8 100644
--- a/frontend/src/app/App.js
+++ b/frontend/src/app/App.js
@@ -1,579 +1,579 @@
-import React, { useEffect, useState } from "react";
-import { BrowserRouter as Router } from "react-router-dom";
-import { Layout, ConfigProvider, Result } from "antd";
-import { useTranslation } from "react-i18next";
-import { getAntdLocale } from "utils/translations";
-import Appointments from "components/pages/Appointments";
-import MenteeAppointments from "components/pages/MenteeAppointments";
-import Videos from "components/pages/Videos";
-import Profile from "components/pages/Profile";
-import Gallery from "components/pages/Gallery";
-import PublicProfile from "components/pages/PublicProfile";
-import NewTrainingConfirm from "components/pages/NewTrainingConfirm";
-import Login from "components/pages/Login";
-import AdminLogin from "components/pages/AdminLogin";
-import SupportLogin from "components/pages/SupportLogin";
-import ForgotPassword from "components/pages/ForgotPassword";
-import ApplicationOrganizer from "components/pages/ApplicationOrganizer";
-import AdminAccountData from "components/pages/AdminAccountData";
-import AdminAppointmentData from "components/pages/AdminAppointmentData";
-import MenteeGallery from "components/pages/MenteeGallery";
-import Messages from "components/pages/Messages";
-import GroupMessages from "components/pages/GroupMessages";
-import ApplicationForm from "components/pages/ApplicationForm";
-import SocketComponent from "components/SocketComponent";
-import AdminTraining from "components/pages/AdminTraining";
-import TrainingData from "components/pages/TrainingData";
-import EventDetail from "components/pages/EventDetail";
-import { Languages } from "components/Languages";
-import { Hubs } from "components/Hubs";
-import { Specializations } from "components/Specializations";
-import { AdminMessages } from "components/pages/AdminSeeMessages";
-import PartnerGallery from "components/pages/PartnerGallery";
-import NavigationHeader from "components/NavigationHeader";
-import HubFooter from "components/HubFooter";
-import NavigationSider from "components/NavigationSider";
-import Initiator from "components/Initiator";
-import PrivateRoute from "components/PrivateRoute";
-import HomeLayout from "components/pages/HomeLayout";
-import Home from "components/pages/Home";
-import Apply from "components/pages/Apply";
-import { getRole } from "utils/auth.service";
-import PublicRoute from "components/PublicRoute";
-import Training from "components/pages/Training";
-import BuildProfile from "components/pages/BuildProfile";
-import Events from "components/pages/Events";
-import HubInviteLink from "components/pages/HubInviteLink";
-import { useSelector } from "react-redux";
-import { ACCOUNT_TYPE } from "utils/consts";
-import { fetchAccounts } from "utils/api";
-import CreateMeetingLink from "components/CreateMeetingLink";
-import MeetingPanel from 'components/MeetingPanel';
-
-const { Content } = Layout;
-
-function App() {
- const [startPathTime, setStartPathTime] = useState(new Date().getTime());
-
- const { t, i18n } = useTranslation();
- const [antdLocale, setAntdLocale] = useState(getAntdLocale(i18n.language));
- const { user } = useSelector((state) => state.user);
- const path = window.location.href;
- const [role, setRole] = useState(getRole());
- const [allHubData, setAllHubData] = useState({});
-
- // TODO: Remove this when we have a proper solution for this
- // some kind of cached method of updating on login status change
- // useEffect(() => {
- // setRole(getRole());
- // }, [user]);
-
- useEffect(() => {
- const getData = async () => {
- let data = await fetchAccounts(ACCOUNT_TYPE.HUB);
- if (data) {
- var temp = {};
- data.map((item) => {
- temp["/" + item.url] = item;
- return true;
- });
- setAllHubData(temp);
- }
- };
- getData();
- }, []);
-
- useEffect(() => {
- setRole(getRole());
- }, [user]);
-
- useEffect(() => {
- setStartPathTime(new Date().getTime());
- }, [path]);
-
- useEffect(() => {
- setAntdLocale(getAntdLocale(i18n.language));
- }, [i18n.language]);
-
- const cur_time = new Date().getTime();
-
- return (
- <>
-
-
-
-
-
- {role && }
-
- {role && }
- {role == ACCOUNT_TYPE.HUB && }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {Object.keys(allHubData).map((hub_url) => {
- return (
- <>
-
-
-
- {allHubData[hub_url].invite_key && (
-
-
-
- )}
- >
- );
- })}
-
-
-
-
-
- {role == ACCOUNT_TYPE.SUPPORT ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.SUPPORT ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.SUPPORT ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTOR ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTOR ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTOR ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
-
- {role == ACCOUNT_TYPE.MENTEE ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTEE ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTOR ||
- role == ACCOUNT_TYPE.MENTEE ||
- role == ACCOUNT_TYPE.PARTNER ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
-
- {role == ACCOUNT_TYPE.MENTEE ||
- role == ACCOUNT_TYPE.GUEST ||
- role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
- {Object.keys(allHubData).map((hub_url) => {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
- })}
-
- {role == ACCOUNT_TYPE.PARTNER ||
- role == ACCOUNT_TYPE.GUEST ||
- role == ACCOUNT_TYPE.HUB ||
- role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.MENTOR ||
- role == ACCOUNT_TYPE.MENTEE ||
- role == ACCOUNT_TYPE.GUEST ||
- role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
-
-
-
-
-
-
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN || role == ACCOUNT_TYPE.HUB ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
- {role == ACCOUNT_TYPE.ADMIN ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
-
- {role == ACCOUNT_TYPE.PARTNER || role == ACCOUNT_TYPE.HUB ? (
-
- ) : (
- <>
- {cur_time - startPathTime > 100 && (
-
- )}
- >
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
-
-export default App;
+import React, { useEffect, useState } from "react";
+import { BrowserRouter as Router } from "react-router-dom";
+import { Layout, ConfigProvider, Result } from "antd";
+import { useTranslation } from "react-i18next";
+import { getAntdLocale } from "utils/translations";
+import Appointments from "components/pages/Appointments";
+import MenteeAppointments from "components/pages/MenteeAppointments";
+import Videos from "components/pages/Videos";
+import Profile from "components/pages/Profile";
+import Gallery from "components/pages/Gallery";
+import PublicProfile from "components/pages/PublicProfile";
+import NewTrainingConfirm from "components/pages/NewTrainingConfirm";
+import Login from "components/pages/Login";
+import AdminLogin from "components/pages/AdminLogin";
+import SupportLogin from "components/pages/SupportLogin";
+import ForgotPassword from "components/pages/ForgotPassword";
+import ApplicationOrganizer from "components/pages/ApplicationOrganizer";
+import AdminAccountData from "components/pages/AdminAccountData";
+import AdminAppointmentData from "components/pages/AdminAppointmentData";
+import MenteeGallery from "components/pages/MenteeGallery";
+import Messages from "components/pages/Messages";
+import GroupMessages from "components/pages/GroupMessages";
+import ApplicationForm from "components/pages/ApplicationForm";
+import SocketComponent from "components/SocketComponent";
+import AdminTraining from "components/pages/AdminTraining";
+import TrainingData from "components/pages/TrainingData";
+import EventDetail from "components/pages/EventDetail";
+import { Languages } from "components/Languages";
+import { Hubs } from "components/Hubs";
+import { Specializations } from "components/Specializations";
+import { AdminMessages } from "components/pages/AdminSeeMessages";
+import PartnerGallery from "components/pages/PartnerGallery";
+import NavigationHeader from "components/NavigationHeader";
+import HubFooter from "components/HubFooter";
+import NavigationSider from "components/NavigationSider";
+import Initiator from "components/Initiator";
+import PrivateRoute from "components/PrivateRoute";
+import HomeLayout from "components/pages/HomeLayout";
+import Home from "components/pages/Home";
+import Apply from "components/pages/Apply";
+import { getRole } from "utils/auth.service";
+import PublicRoute from "components/PublicRoute";
+import Training from "components/pages/Training";
+import BuildProfile from "components/pages/BuildProfile";
+import Events from "components/pages/Events";
+import HubInviteLink from "components/pages/HubInviteLink";
+import { useSelector } from "react-redux";
+import { ACCOUNT_TYPE } from "utils/consts";
+import { fetchAccounts } from "utils/api";
+import CreateMeetingLink from "components/CreateMeetingLink";
+import MeetingPanel from "components/MeetingPanel";
+
+const { Content } = Layout;
+
+function App() {
+ const [startPathTime, setStartPathTime] = useState(new Date().getTime());
+
+ const { t, i18n } = useTranslation();
+ const [antdLocale, setAntdLocale] = useState(getAntdLocale(i18n.language));
+ const { user } = useSelector((state) => state.user);
+ const path = window.location.href;
+ const [role, setRole] = useState(getRole());
+ const [allHubData, setAllHubData] = useState({});
+
+ // TODO: Remove this when we have a proper solution for this
+ // some kind of cached method of updating on login status change
+ // useEffect(() => {
+ // setRole(getRole());
+ // }, [user]);
+
+ useEffect(() => {
+ const getData = async () => {
+ let data = await fetchAccounts(ACCOUNT_TYPE.HUB);
+ if (data) {
+ var temp = {};
+ data.map((item) => {
+ temp["/" + item.url] = item;
+ return true;
+ });
+ setAllHubData(temp);
+ }
+ };
+ getData();
+ }, []);
+
+ useEffect(() => {
+ setRole(getRole());
+ }, [user]);
+
+ useEffect(() => {
+ setStartPathTime(new Date().getTime());
+ }, [path]);
+
+ useEffect(() => {
+ setAntdLocale(getAntdLocale(i18n.language));
+ }, [i18n.language]);
+
+ const cur_time = new Date().getTime();
+
+ return (
+ <>
+
+
+
+
+
+ {role && }
+
+ {role && }
+ {role == ACCOUNT_TYPE.HUB && }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {Object.keys(allHubData).map((hub_url) => {
+ return (
+ <>
+
+
+
+ {allHubData[hub_url].invite_key && (
+
+
+
+ )}
+ >
+ );
+ })}
+
+
+
+
+
+ {role == ACCOUNT_TYPE.SUPPORT ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.SUPPORT ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.SUPPORT ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTOR ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTOR ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTOR ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+
+ {role == ACCOUNT_TYPE.MENTEE ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTEE ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTOR ||
+ role == ACCOUNT_TYPE.MENTEE ||
+ role == ACCOUNT_TYPE.PARTNER ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+
+ {role == ACCOUNT_TYPE.MENTEE ||
+ role == ACCOUNT_TYPE.GUEST ||
+ role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+ {Object.keys(allHubData).map((hub_url) => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ })}
+
+ {role == ACCOUNT_TYPE.PARTNER ||
+ role == ACCOUNT_TYPE.GUEST ||
+ role == ACCOUNT_TYPE.HUB ||
+ role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.MENTOR ||
+ role == ACCOUNT_TYPE.MENTEE ||
+ role == ACCOUNT_TYPE.GUEST ||
+ role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN || role == ACCOUNT_TYPE.HUB ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+ {role == ACCOUNT_TYPE.ADMIN ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+
+ {role == ACCOUNT_TYPE.PARTNER || role == ACCOUNT_TYPE.HUB ? (
+
+ ) : (
+ <>
+ {cur_time - startPathTime > 100 && (
+
+ )}
+ >
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+export default App;
diff --git a/frontend/src/app/store.js b/frontend/src/app/store.js
index f4c8e9a5..d6cc0b60 100644
--- a/frontend/src/app/store.js
+++ b/frontend/src/app/store.js
@@ -3,7 +3,7 @@ import userReducer from "features/userSlice";
import notificationsReducer from "features/notificationsSlice";
import messagesReducer from "features/messagesSlice";
import optionsReducer from "features/optionsSlice";
-import meetingPanelReducer from 'features/meetingPanelSlice';
+import meetingPanelReducer from "features/meetingPanelSlice";
export default configureStore({
reducer: {
diff --git a/frontend/src/components/CreateMeetingLink.js b/frontend/src/components/CreateMeetingLink.js
index fd84ff00..07df9c29 100644
--- a/frontend/src/components/CreateMeetingLink.js
+++ b/frontend/src/components/CreateMeetingLink.js
@@ -1,132 +1,167 @@
-import React, { useState, useEffect, useRef } from "react";
-import { Modal, Button, Input, Typography, message } from "antd";
-import { CopyOutlined } from "@ant-design/icons";
-import { useTranslation } from "react-i18next";
-import { generateToken } from "utils/api";
-import { useDispatch } from 'react-redux';
-import { setPanel, removePanel } from 'features/meetingPanelSlice';
-import { useHistory } from "react-router-dom";
-
-const { Title } = Typography;
-
-function Meeting() {
- const joinButtonRef = useRef(null);
- const [urlModalVisible, setUrlModalVisible] = useState(true);
- const [RoomName, setRoomName] = useState("");
- const [Token, setToken] = useState("");
- const [AppID, setAppID] = useState("");
- const history = useHistory();
- const dispatch = useDispatch();
- const { t } = useTranslation();
-
- const copyToClipboard = () => {
- try {
- navigator.clipboard.writeText('https://8x8.vc/' + AppID + '/' + RoomName);
- message.success(t("meeting.copyMessage"));
- } catch (error) {
- console.error(t("meeting.errorCopy"), error);
- message.error(t("meeting.errorCopy"));
- }
- };
-
- const getRoomName = () => {
- try {
- const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- let generatedRoomName = '';
- for (let i = 0; i < 10; i++) {
- generatedRoomName += characters.charAt(Math.floor(Math.random() * characters.length));
- }
- setRoomName(generatedRoomName.split('/').pop());
- } catch (error) {
- console.error(t("meeting.errorGenerating"));
- message.error(t("meeting.errorGenerating"));
- }
- };
-
- const joinMeeting = async () => {
- try {
- if (!RoomName) {
- console.error(t("meeting.roomName"));
- message.error(t("meeting.roomName"));
- return;
- }
-
- const response = await getToken();
- dispatch(removePanel());
- setTimeout(() => {
- dispatch(setPanel({ app_id: response.appID, room_name: RoomName, token: response.token }));
- }, 500);
- } catch (error) {
- console.error("Error: ", error);
- message.error(t("meeting.getToken"));
- }
- };
-
- const getToken = async () => {
- try {
- const resp = await generateToken();
- setToken(resp.token);
- setAppID(resp.appID);
- return resp
- } catch (error) {
- console.error('Error:', error);
- message.error(t("meeting.generateToken"));
- }
- };
-
- const redirectBack = () => {
- history.goBack();
- };
-
- const handleCancel = () => {
- setUrlModalVisible(false);
- redirectBack();
- };
-
- return (
- <>
-
- ,
-
- ,
- ,
-
-
- ]}
- >
-
-
{t("meeting.generatedURL")}
-
- setRoomName(e.target.value.split('/').pop())}
- placeholder={t("meeting.placeHolder")}
- />
- }
- onClick={copyToClipboard}
- style={{ marginLeft: "8px" }}
- />
-
-
-
- {t("meeting.limitWarning")}
-
-
- >
- );
-}
-
-export default Meeting;
+import React, { useState, useEffect, useRef } from "react";
+import { Modal, Button, Input, Typography, message } from "antd";
+import { CopyOutlined } from "@ant-design/icons";
+import { useTranslation } from "react-i18next";
+import { generateToken } from "utils/api";
+import { useDispatch } from "react-redux";
+import { setPanel, removePanel } from "features/meetingPanelSlice";
+import { useHistory } from "react-router-dom";
+
+const { Title } = Typography;
+
+function Meeting() {
+ const joinButtonRef = useRef(null);
+ const [urlModalVisible, setUrlModalVisible] = useState(true);
+ const [RoomName, setRoomName] = useState("");
+ const [Token, setToken] = useState("");
+ const [AppID, setAppID] = useState("");
+ const history = useHistory();
+ const dispatch = useDispatch();
+ const { t } = useTranslation();
+
+ const copyToClipboard = () => {
+ try {
+ navigator.clipboard.writeText("https://8x8.vc/" + AppID + "/" + RoomName);
+ message.success(t("meeting.copyMessage"));
+ } catch (error) {
+ console.error(t("meeting.errorCopy"), error);
+ message.error(t("meeting.errorCopy"));
+ }
+ };
+
+ const getRoomName = () => {
+ try {
+ const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ let generatedRoomName = "";
+ for (let i = 0; i < 10; i++) {
+ generatedRoomName += characters.charAt(
+ Math.floor(Math.random() * characters.length)
+ );
+ }
+ setRoomName(generatedRoomName.split("/").pop());
+ } catch (error) {
+ console.error(t("meeting.errorGenerating"));
+ message.error(t("meeting.errorGenerating"));
+ }
+ };
+
+ const joinMeeting = async () => {
+ try {
+ if (!RoomName) {
+ console.error(t("meeting.roomName"));
+ message.error(t("meeting.roomName"));
+ return;
+ }
+
+ const response = await getToken();
+ dispatch(removePanel());
+ setTimeout(() => {
+ dispatch(
+ setPanel({
+ app_id: response.appID,
+ room_name: RoomName,
+ token: response.token,
+ })
+ );
+ }, 500);
+ } catch (error) {
+ console.error("Error: ", error);
+ message.error(t("meeting.getToken"));
+ }
+ };
+
+ const getToken = async () => {
+ try {
+ const resp = await generateToken();
+ setToken(resp.token);
+ setAppID(resp.appID);
+ return resp;
+ } catch (error) {
+ console.error("Error:", error);
+ message.error(t("meeting.generateToken"));
+ }
+ };
+
+ const redirectBack = () => {
+ history.goBack();
+ };
+
+ const handleCancel = () => {
+ setUrlModalVisible(false);
+ redirectBack();
+ };
+
+ return (
+ <>
+
+
+ ,
+
+
+ ,
+
+ ,
+
+ ,
+ ]}
+ >
+
+
{t("meeting.generatedURL")}
+
+ setRoomName(e.target.value.split("/").pop())}
+ placeholder={t("meeting.placeHolder")}
+ />
+ }
+ onClick={copyToClipboard}
+ style={{ marginLeft: "8px" }}
+ />
+
+
+
+ {t("meeting.limitWarning")}
+
+
+ >
+ );
+}
+
+export default Meeting;
diff --git a/frontend/src/components/MeetingPanel.js b/frontend/src/components/MeetingPanel.js
index 24d9fbda..6872fc12 100644
--- a/frontend/src/components/MeetingPanel.js
+++ b/frontend/src/components/MeetingPanel.js
@@ -1,64 +1,66 @@
-import { useSelector, useDispatch } from 'react-redux';
-import { JaaSMeeting, JitsiMeeting } from '@jitsi/react-sdk';
-import React, { useRef, useState } from 'react';
-import { setPanel, removePanel } from 'features/meetingPanelSlice';
-
-const MeetingPanel = () => {
- const dispatch = useDispatch();
- var panelComponent = useSelector((state) => state.meetingPanel.panelComponent);
-
- const ClosePanel = (event) => {
- if (event === undefined) {
- dispatch(removePanel());
- }
- };
-
- if (panelComponent)
- {
- return (
-
- {
- iframeRef.style.position = 'fixed';
- iframeRef.style.bottom = 0;
- iframeRef.style.right = 0;
- iframeRef.style.width = '30%';
- iframeRef.style.height = '100%';
- }}
- appId={panelComponent.app_id}
- roomName={panelComponent.room_name}
- jwt={panelComponent.token}
- configOverwrite={{
- disableThirdPartyRequests: true,
- disableLocalVideoFlip: true,
- backgroundAlpha: 0.5
- }}
- interfaceConfigOverwrite={{
- VIDEO_LAYOUT_FIT: 'nocrop',
- MOBILE_APP_PROMO: false,
- TILE_VIEW_MAX_COLUMNS: 4
- }}
- onReadyToClose={ClosePanel}
- />
-
-
- );
- }
- else {return }
-};
-
-export default MeetingPanel;
\ No newline at end of file
+import { useSelector, useDispatch } from "react-redux";
+import { JaaSMeeting, JitsiMeeting } from "@jitsi/react-sdk";
+import React, { useRef, useState } from "react";
+import { setPanel, removePanel } from "features/meetingPanelSlice";
+
+const MeetingPanel = () => {
+ const dispatch = useDispatch();
+ var panelComponent = useSelector(
+ (state) => state.meetingPanel.panelComponent
+ );
+
+ const ClosePanel = (event) => {
+ if (event === undefined) {
+ dispatch(removePanel());
+ }
+ };
+
+ if (panelComponent) {
+ return (
+
+ {
+ iframeRef.style.position = "fixed";
+ iframeRef.style.bottom = 0;
+ iframeRef.style.right = 0;
+ iframeRef.style.width = "30%";
+ iframeRef.style.height = "100%";
+ }}
+ appId={panelComponent.app_id}
+ roomName={panelComponent.room_name}
+ jwt={panelComponent.token}
+ configOverwrite={{
+ disableThirdPartyRequests: true,
+ disableLocalVideoFlip: true,
+ backgroundAlpha: 0.5,
+ }}
+ interfaceConfigOverwrite={{
+ VIDEO_LAYOUT_FIT: "nocrop",
+ MOBILE_APP_PROMO: false,
+ TILE_VIEW_MAX_COLUMNS: 4,
+ }}
+ onReadyToClose={ClosePanel}
+ />
+
+
+ );
+ } else {
+ return ;
+ }
+};
+
+export default MeetingPanel;
diff --git a/frontend/src/components/MenteeSidebar.js b/frontend/src/components/MenteeSidebar.js
index 594099b8..52c17ffa 100644
--- a/frontend/src/components/MenteeSidebar.js
+++ b/frontend/src/components/MenteeSidebar.js
@@ -1,49 +1,47 @@
-import React from "react";
-import {
- UserOutlined,
- CalendarOutlined,
- MailOutlined,
- LinkOutlined,
-} from "@ant-design/icons";
-import Sidebar from "./Sidebar";
-import { useTranslation } from "react-i18next";
-import { useAuth } from "utils/hooks/useAuth";
-import CreateMeetingLink from "./components/CreateMeetingLink";
-
-function MenteeSidebar(props) {
- const { t } = useTranslation();
- const { role } = useAuth();
-
-
- const pages = {
- appointments: {
- name: t("sidebars.appointments"),
- path: "/mentee-appointments",
- icon: ,
- },
- profile: {
- name: t("sidebars.profile"),
- path: "/profile",
- icon: ,
- },
- message: {
- name: t("common.messages"),
- path: "/messages/" + role,
- icon: ,
- },
- };
-
- //return ;
-
- return (
-
-
-
-
- {/* Other sidebar content within Sidebar.Item components */}
-
- );
-
-}
-
-export default MenteeSidebar;
+import React from "react";
+import {
+ UserOutlined,
+ CalendarOutlined,
+ MailOutlined,
+ LinkOutlined,
+} from "@ant-design/icons";
+import Sidebar from "./Sidebar";
+import { useTranslation } from "react-i18next";
+import { useAuth } from "utils/hooks/useAuth";
+import CreateMeetingLink from "./components/CreateMeetingLink";
+
+function MenteeSidebar(props) {
+ const { t } = useTranslation();
+ const { role } = useAuth();
+
+ const pages = {
+ appointments: {
+ name: t("sidebars.appointments"),
+ path: "/mentee-appointments",
+ icon: ,
+ },
+ profile: {
+ name: t("sidebars.profile"),
+ path: "/profile",
+ icon: ,
+ },
+ message: {
+ name: t("common.messages"),
+ path: "/messages/" + role,
+ icon: ,
+ },
+ };
+
+ //return ;
+
+ return (
+
+
+
+
+ {/* Other sidebar content within Sidebar.Item components */}
+
+ );
+}
+
+export default MenteeSidebar;
diff --git a/frontend/src/components/MentorSidebar.js b/frontend/src/components/MentorSidebar.js
index 204094d8..030cccf1 100644
--- a/frontend/src/components/MentorSidebar.js
+++ b/frontend/src/components/MentorSidebar.js
@@ -1,51 +1,51 @@
-import React from "react";
-import {
- UserOutlined,
- VideoCameraOutlined,
- CalendarOutlined,
- MailOutlined,
-} from "@ant-design/icons";
-import Sidebar from "./Sidebar";
-import { useTranslation } from "react-i18next";
-import { useAuth } from "utils/hooks/useAuth";
-import CreateMeetingLink from "./components/CreateMeetingLink";
-
-function MentorSidebar(props) {
- const { t } = useTranslation();
- const { role } = useAuth();
- const pages = {
- appointments: {
- name: t("sidebars.appointments"),
- path: "/appointments",
- icon: ,
- },
- videos: {
- name: t("sidebars.videos"),
- path: "/videos",
- icon: ,
- },
- profile: {
- name: t("sidebars.profile"),
- path: "/profile",
- icon: ,
- },
- message: {
- name: t("common.messages"),
- path: "/messages/" + role,
- icon: ,
- },
- };
-
- //return ;
-
- return (
-
-
-
-
- {/* Other sidebar content within Sidebar.Item components */}
-
- );
-}
-
-export default MentorSidebar;
+import React from "react";
+import {
+ UserOutlined,
+ VideoCameraOutlined,
+ CalendarOutlined,
+ MailOutlined,
+} from "@ant-design/icons";
+import Sidebar from "./Sidebar";
+import { useTranslation } from "react-i18next";
+import { useAuth } from "utils/hooks/useAuth";
+import CreateMeetingLink from "./components/CreateMeetingLink";
+
+function MentorSidebar(props) {
+ const { t } = useTranslation();
+ const { role } = useAuth();
+ const pages = {
+ appointments: {
+ name: t("sidebars.appointments"),
+ path: "/appointments",
+ icon: ,
+ },
+ videos: {
+ name: t("sidebars.videos"),
+ path: "/videos",
+ icon: ,
+ },
+ profile: {
+ name: t("sidebars.profile"),
+ path: "/profile",
+ icon: ,
+ },
+ message: {
+ name: t("common.messages"),
+ path: "/messages/" + role,
+ icon: ,
+ },
+ };
+
+ //return ;
+
+ return (
+
+
+
+
+ {/* Other sidebar content within Sidebar.Item components */}
+
+ );
+}
+
+export default MentorSidebar;
diff --git a/frontend/src/components/PartnerSidebar.js b/frontend/src/components/PartnerSidebar.js
index 96fa6f60..2775ec92 100644
--- a/frontend/src/components/PartnerSidebar.js
+++ b/frontend/src/components/PartnerSidebar.js
@@ -1,40 +1,39 @@
-import React from "react";
-import {
- UserOutlined,
- CalendarOutlined,
- MailOutlined,
-} from "@ant-design/icons";
-import Sidebar from "./Sidebar";
-import { useTranslation } from "react-i18next";
-import { useAuth } from "utils/hooks/useAuth";
-import CreateMeetingLink from "./components/CreateMeetingLink";
-
-function PartnerSidebar(props) {
- const { t } = useTranslation();
- const { role } = useAuth();
- const pages = {
- profile: {
- name: t("sidebars.profile"),
- path: "/profile",
- icon: ,
- },
- message: {
- name: t("common.messages"),
- path: "/messages/" + role,
- icon: ,
- },
- };
-
- //return ;
- return (
-
-
-
-
- {/* Other sidebar content within Sidebar.Item components */}
-
- );
-
-}
-
-export default PartnerSidebar;
+import React from "react";
+import {
+ UserOutlined,
+ CalendarOutlined,
+ MailOutlined,
+} from "@ant-design/icons";
+import Sidebar from "./Sidebar";
+import { useTranslation } from "react-i18next";
+import { useAuth } from "utils/hooks/useAuth";
+import CreateMeetingLink from "./components/CreateMeetingLink";
+
+function PartnerSidebar(props) {
+ const { t } = useTranslation();
+ const { role } = useAuth();
+ const pages = {
+ profile: {
+ name: t("sidebars.profile"),
+ path: "/profile",
+ icon: ,
+ },
+ message: {
+ name: t("common.messages"),
+ path: "/messages/" + role,
+ icon: ,
+ },
+ };
+
+ //return ;
+ return (
+
+
+
+
+ {/* Other sidebar content within Sidebar.Item components */}
+
+ );
+}
+
+export default PartnerSidebar;
diff --git a/frontend/src/features/meetingPanelSlice.js b/frontend/src/features/meetingPanelSlice.js
index 01a30b2c..85460a6b 100644
--- a/frontend/src/features/meetingPanelSlice.js
+++ b/frontend/src/features/meetingPanelSlice.js
@@ -1,7 +1,7 @@
-import { createSlice } from '@reduxjs/toolkit';
+import { createSlice } from "@reduxjs/toolkit";
const meetingPanelSlice = createSlice({
- name: 'meetingPanel',
+ name: "meetingPanel",
initialState: {
panelComponent: null,
},