Commit b515f433 authored by Zhou Fang's avatar Zhou Fang
Browse files

Moved states into Context to reduce API call times

parent 6cd8cc9e
......@@ -57,6 +57,21 @@ const App = () => {
const [msgContent, setMsgContent] = useState('');
const [isError, setIsError] = useState(false);
const [orgInfo, setOrgInfo] = useState(null);
const [allRelations, setAllRelations] = useState(null);
const [currentLinks, setCurrentLinks] = useState(null);
const [orgRepData, setOrgRepData] = useState(null);
const [resourcesData, setResourcesData] = useState(null);
const [committers, setCommitters] = useState(null);
const [contributors, setContributors] = useState(null);
const [cbiData, setCBIData] = useState(null);
const [chartCommits, setChartCommits] = useState(null);
const [chartCommitters, setChartCommitters] = useState(null);
const [interestedProjectsData, setInterestedProjectsData] = useState(null);
const [yourProjectsData, setYourProjectsData] = useState(null);
const [allYourProjectsData, setAllYourProjectsData] = useState(null);
const [yourWGData, setYourWGData] = useState(null);
const [allYourWGData, setAllYourWGData] = useState(null);
const [interestedWGData, setInterestedWGData] = useState(null);
const failedToExecute = (msg) => {
setShouldShowMsg(true);
......@@ -100,6 +115,36 @@ const App = () => {
setContactData,
orgInfo,
setOrgInfo,
allRelations,
setAllRelations,
currentLinks,
setCurrentLinks,
orgRepData,
setOrgRepData,
resourcesData,
setResourcesData,
committers,
setCommitters,
contributors,
setContributors,
cbiData,
setCBIData,
chartCommits,
setChartCommits,
chartCommitters,
setChartCommitters,
interestedProjectsData,
setInterestedProjectsData,
yourProjectsData,
setYourProjectsData,
allYourProjectsData,
setAllYourProjectsData,
yourWGData,
setYourWGData,
allYourWGData,
setAllYourWGData,
interestedWGData,
setInterestedWGData,
};
useEffect(() => {
......
import React from 'react';
import { ContactBackend, OrgInfoBackend } from '../Interfaces/portal_interface';
import {
AllRelationsFrontend,
CBIData,
CommitterOrContributor,
ContactBackend,
CurrentLink,
OrgInfoBackend,
OrgRep,
ProjectsAndWGItem,
ResourcesData,
} from '../Interfaces/portal_interface';
interface PortalContextType {
orgId: number;
......@@ -10,6 +20,36 @@ interface PortalContextType {
setContactData: (data: Array<ContactBackend>) => void;
orgInfo: OrgInfoBackend | null;
setOrgInfo: (orgInfo: OrgInfoBackend) => void;
allRelations: AllRelationsFrontend | null;
setAllRelations: (relations: AllRelationsFrontend) => void;
currentLinks: Array<CurrentLink> | null;
setCurrentLinks: (links: Array<CurrentLink>) => void;
orgRepData: Array<OrgRep> | null;
setOrgRepData: (repData: Array<OrgRep>) => void;
resourcesData: Array<ResourcesData> | null;
setResourcesData: (resourcesData: Array<ResourcesData>) => void;
committers: Array<CommitterOrContributor> | null;
setCommitters: (committersData: Array<CommitterOrContributor>) => void;
contributors: Array<CommitterOrContributor> | null;
setContributors: (contributorsData: Array<CommitterOrContributor>) => void;
cbiData: CBIData | null;
setCBIData: (cbiData: CBIData) => void;
chartCommits: Array<number> | null;
setChartCommits: (commitsData: Array<number>) => void;
chartCommitters: Array<number> | null;
setChartCommitters: (committersData: Array<number>) => void;
interestedProjectsData: Array<ProjectsAndWGItem> | null;
setInterestedProjectsData: (interestedProjectsData: Array<ProjectsAndWGItem>) => void;
yourProjectsData: Array<ProjectsAndWGItem> | null;
setYourProjectsData: (yourProjectsData: Array<ProjectsAndWGItem>) => void;
allYourProjectsData: Array<ProjectsAndWGItem> | null;
setAllYourProjectsData: (allYourProjectsData: Array<ProjectsAndWGItem>) => void;
yourWGData: Array<ProjectsAndWGItem> | null;
setYourWGData: (yourWGData: Array<ProjectsAndWGItem>) => void;
allYourWGData: Array<ProjectsAndWGItem> | null;
setAllYourWGData: (allYourWGData: Array<ProjectsAndWGItem>) => void;
interestedWGData: Array<ProjectsAndWGItem> | null;
setInterestedWGData: (interestedWGData: Array<ProjectsAndWGItem>) => void;
}
const PortalContext = React.createContext<PortalContextType>({
......@@ -21,6 +61,36 @@ const PortalContext = React.createContext<PortalContextType>({
setContactData: (data: Array<ContactBackend>) => {},
orgInfo: null,
setOrgInfo: (orgInfo: OrgInfoBackend) => {},
allRelations: null,
setAllRelations: (relations: AllRelationsFrontend) => {},
currentLinks: null,
setCurrentLinks: (links: Array<CurrentLink>) => {},
orgRepData: null,
setOrgRepData: (repData: Array<OrgRep>) => {},
resourcesData: null,
setResourcesData: (resourcesData: Array<ResourcesData>) => {},
committers: null,
setCommitters: (committersData: Array<CommitterOrContributor>) => {},
contributors: null,
setContributors: (contributorsData: Array<CommitterOrContributor>) => {},
cbiData: null,
setCBIData: (cbiData: CBIData) => {},
chartCommits: null,
setChartCommits: (commitsData: Array<number>) => {},
chartCommitters: null,
setChartCommitters: (committersData: Array<number>) => {},
interestedProjectsData: null,
setInterestedProjectsData: (interestedProjectsData: Array<ProjectsAndWGItem>) => {},
yourProjectsData: null,
setYourProjectsData: (yourProjectsData: Array<ProjectsAndWGItem>) => {},
allYourProjectsData: null,
setAllYourProjectsData: (allYourProjectsData: Array<ProjectsAndWGItem>) => {},
yourWGData: null,
setYourWGData: (yourWGData: Array<ProjectsAndWGItem>) => {},
allYourWGData: null,
setAllYourWGData: (allYourWGData: Array<ProjectsAndWGItem>) => {},
interestedWGData: null,
setInterestedWGData: (interestedWGData: Array<ProjectsAndWGItem>) => {},
});
export default PortalContext;
......@@ -63,3 +63,33 @@ export interface OrgInfoBackend {
website: null | string;
wgpas: Array<WGPA>;
}
export interface AllRelationsFrontend {
[key: string]: string;
}
export interface CurrentLink {
id: number;
title: string;
description: string;
url: string;
}
export interface ResourcesListItem {
name: string;
url: string;
}
export interface ResourcesData {
subtitle: string;
listItems: Array<ResourcesListItem>;
}
export interface CommitterOrContributor {
name: string;
url: string;
}
export interface CBIData {
inUse: number;
allocated: number;
}
......@@ -29,7 +29,12 @@ import EditIcon from '@material-ui/icons/Edit';
import PersonAddIcon from '@material-ui/icons/PersonAdd';
import Input from '../../UIComponents/Inputs/Input';
import ModalWindow from '../../UIComponents/Notifications/ModalWindow';
import { ContactBackend, OrganizationRoles, OrganizationRolesKeys } from '../../../Interfaces/portal_interface';
import {
AllRelationsFrontend,
ContactBackend,
OrganizationRoles,
OrganizationRolesKeys,
} from '../../../Interfaces/portal_interface';
import { fetchWrapper, fetchWrapperPagination, isProd } from '../../../Utils/formFunctionHelpers';
import GlobalContext from '../../../Context/GlobalContext';
import { checkPermission } from '../../../Utils/portalFunctionHelpers';
......@@ -147,10 +152,6 @@ interface AllRelationsBackend {
sort_order: string;
}
interface AllRelationsFrontend {
[key: string]: string;
}
interface RoleDescription {
[key: string]: string;
}
......@@ -182,7 +183,8 @@ const customOperators = [
export default function ContactManagement() {
const classes = useStyle();
const { currentUser, succeededToExecute, failedToExecute } = useContext(GlobalContext);
const { contactFilterRole, setContactFilterRole, orgId, contactData, setContactData } = useContext(PortalContext);
const { contactFilterRole, setContactFilterRole, orgId, contactData, setContactData, allRelations, setAllRelations } =
useContext(PortalContext);
const columns: GridColDef[] = [
{
......@@ -278,7 +280,6 @@ export default function ContactManagement() {
name: '',
});
const [checkedRoles, setCheckedRoles] = useState(INITIAL_CHECKED_ROLES);
const [allRelations, setAllRelations] = useState<AllRelationsFrontend | null>(null);
const [roleDescription, setRoleDescription] = useState('');
const [anchorEle, setAnchorEle] = useState<HTMLElement | null>(null);
const openPopover = Boolean(anchorEle);
......@@ -471,7 +472,7 @@ export default function ContactManagement() {
if (allRelations === null) {
fetchWrapperPagination(api_prefix() + '/sys/relations?type=CO&page=', 1, saveAllRelations);
}
}, [allRelations]);
}, [allRelations, setAllRelations]);
useEffect(() => {
if (contactData === null || allRelations === null) {
......
......@@ -4,47 +4,14 @@ import DashboardIntro from './DashboardIntro';
import DashboardOverview from './DashboardOverview';
import DashboardProjectsAndWG from './DashboardProjectsAndWG/DashboardProjectsAndWG';
import DashboardResources from './DashboardResources';
import { useContext, useEffect, useState } from 'react';
import { useContext, useEffect } from 'react';
import { fetchWrapper } from '../../../Utils/formFunctionHelpers';
import { api_prefix, FETCH_METHOD, getCurrentMode, MODE_REACT_ONLY } from '../../../Constants/Constants';
import { OrganizationRoles, OrgInfoBackend, OrgRep } from '../../../Interfaces/portal_interface';
import { OrgInfoBackend } from '../../../Interfaces/portal_interface';
import PortalContext from '../../../Context/PortalContext';
export default function Dashboard() {
const { orgId, orgInfo, setOrgInfo } = useContext(PortalContext);
const [orgRepData, setOrgRepData] = useState<Array<OrgRep> | null>(null);
useEffect(() => {
if (orgId === 0 || orgRepData !== null) {
return;
}
const urlForOrgInfo =
getCurrentMode() === MODE_REACT_ONLY
? '/membership_data/test_org_rep.json'
: `${api_prefix()}/organizations/${orgId}/representatives`;
const saveOrgRep = (data: any) => {
const repCR: Array<OrgRep> = [];
const repCRA: Array<OrgRep> = [];
const repMA: Array<OrgRep> = [];
const updateOrgRepData = (contact: any, relation: 'CR' | 'CRA' | 'MA', repArray: Array<OrgRep>) => {
contact.relations.includes(relation) &&
repArray.push({ name: `${contact.first_name} ${contact.last_name}`, type: OrganizationRoles[relation] });
};
data.forEach((item: any) => {
updateOrgRepData(item, 'CR', repCR);
updateOrgRepData(item, 'CRA', repCRA);
updateOrgRepData(item, 'MA', repMA);
});
setOrgRepData([...repCR, ...repCRA, ...repMA]);
};
fetchWrapper(urlForOrgInfo, FETCH_METHOD.GET, saveOrgRep);
}, [orgId, orgRepData]);
useEffect(() => {
if (orgId === 0 || orgInfo !== null) {
......@@ -64,7 +31,7 @@ export default function Dashboard() {
return (
<>
<DashboardIntro orgRepData={orgRepData} />
<DashboardIntro />
<DashboardOverview />
<DashboardProjectsAndWG />
<DashboardCommittersAndContributors />
......
......@@ -132,37 +132,27 @@ const useStyles = makeStyles((theme: Theme) =>
})
);
interface CommitterOrContributor {
name: string;
url: string;
}
interface CBIData {
inUse: number;
allocated: number;
}
const isReactOnlyMode = getCurrentMode() === MODE_REACT_ONLY;
export default function DashboardCommittersAndContributors() {
const classes = useStyles();
const history = useHistory();
const [committers, setCommitters] = useState<Array<CommitterOrContributor>>([]);
const [contributors, setContributors] = useState<Array<CommitterOrContributor>>([]);
const [cbiData, setCBIData] = useState<CBIData>();
const [isFetchingCommitters, setIsFetchingCommitters] = useState(true);
const [isFetchingContributors, setIsFetchingContributors] = useState(true);
const [isFetchingCBI, setIsFetchingCBI] = useState(true);
const [anchorEle, setanchorEle] = useState<HTMLElement | null>(null);
const { orgId, setContactFilterRole } = useContext(PortalContext);
const [anchorEle, setAnchorEle] = useState<HTMLElement | null>(null);
const { orgId, setContactFilterRole, committers, setCommitters, contributors, setContributors, cbiData, setCBIData } =
useContext(PortalContext);
const { currentUser } = useContext(GlobalContext);
const open = Boolean(anchorEle);
useEffect(() => {
if (!orgId) {
if (!orgId || committers !== null) {
committers !== null && setIsFetchingCommitters(false);
return;
}
const isReactOnlyMode = getCurrentMode() === MODE_REACT_ONLY;
// For committers
const urlForCommitters = isReactOnlyMode
......@@ -179,7 +169,14 @@ export default function DashboardCommittersAndContributors() {
setIsFetchingCommitters(false);
};
orgId !== 0 && fetchWrapper(urlForCommitters, FETCH_METHOD.GET, saveCommittersData);
fetchWrapper(urlForCommitters, FETCH_METHOD.GET, saveCommittersData);
}, [orgId, committers, setCommitters]);
useEffect(() => {
if (!orgId || contributors !== null) {
contributors !== null && setIsFetchingContributors(false);
return;
}
// For contributors
const urlForContributors = isReactOnlyMode
......@@ -195,7 +192,14 @@ export default function DashboardCommittersAndContributors() {
setContributors(fiveRandomContributors);
setIsFetchingContributors(false);
};
orgId !== 0 && fetchWrapper(urlForContributors, FETCH_METHOD.GET, saveContributorsData);
fetchWrapper(urlForContributors, FETCH_METHOD.GET, saveContributorsData);
}, [orgId, contributors, setContributors]);
useEffect(() => {
if (!orgId || cbiData !== null) {
cbiData !== null && setIsFetchingCBI(false);
return;
}
// For CBI data
const urlForCBIData = isReactOnlyMode
......@@ -213,8 +217,8 @@ export default function DashboardCommittersAndContributors() {
setCBIData({ inUse, allocated });
setIsFetchingCBI(false);
};
orgId !== 0 && fetchWrapper(urlForCBIData, FETCH_METHOD.GET, saveCBIData);
}, [orgId]);
fetchWrapper(urlForCBIData, FETCH_METHOD.GET, saveCBIData);
}, [orgId, cbiData, setCBIData]);
const canViewCommiters = checkPermission(PERMISSIONS_BASED_ON_ROLES.viewCommitters, currentUser?.relation);
const canViewContributors = checkPermission(PERMISSIONS_BASED_ON_ROLES.viewContributors, currentUser?.relation);
......@@ -232,7 +236,7 @@ export default function DashboardCommittersAndContributors() {
subtitle="Your Committers"
color={brightBlue}
icon={<PeopleAltIcon />}
listItems={committers}
listItems={committers || []}
urlText="View more"
callBackFunc={() => {
setContactFilterRole('committer');
......@@ -248,7 +252,7 @@ export default function DashboardCommittersAndContributors() {
subtitle="Your Contributors"
color={brightBlue}
icon={<PeopleAltIcon />}
listItems={contributors}
listItems={contributors || []}
urlText="View more"
callBackFunc={() => {
setContactFilterRole('contributor');
......@@ -294,7 +298,7 @@ export default function DashboardCommittersAndContributors() {
</div>
</>
)}
<div className={classes.helpButton} onClick={(ev) => setanchorEle(ev.currentTarget)}>
<div className={classes.helpButton} onClick={(ev) => setAnchorEle(ev.currentTarget)}>
<HelpIcon className={classes.helpIcon} />
</div>
<Popover
......@@ -303,7 +307,7 @@ export default function DashboardCommittersAndContributors() {
elevation={4}
open={open}
anchorEl={anchorEle}
onClose={() => setanchorEle(null)}
onClose={() => setAnchorEle(null)}
anchorOrigin={{
vertical: -65,
horizontal: 'center',
......
......@@ -33,10 +33,8 @@ const useStyles = makeStyles(() =>
function DashboardCommittersAndContributorsChart() {
const classes = useStyles();
const [chartCommits, setChartCommits] = useState<Array<number>>([]);
const [chartCommitters, setChartCommitters] = useState<Array<number>>([]);
const [chartMonths, setChartMonths] = useState<Array<string>>([]);
const { orgId } = useContext(PortalContext);
const { orgId, chartCommits, setChartCommits, chartCommitters, setChartCommitters } = useContext(PortalContext);
const DATA_FOR_BAR_LINE_CHART = {
labels: chartMonths,
......@@ -47,22 +45,22 @@ function DashboardCommittersAndContributorsChart() {
borderColor: brightBlue,
borderWidth: 2,
fill: false,
data: chartCommitters,
data: chartCommitters || [],
},
{
type: 'bar',
label: 'Commits',
backgroundColor: '#F0F2F8',
data: chartCommits,
data: chartCommits || [],
},
],
};
useEffect(() => {
if (!orgId) {
if (!orgId || chartCommits !== null) {
return;
}
// For chart - commits data
const urlForChartCommits = isReactOnlyMode
? '/membership_data/test_chart_commits.json'
......@@ -90,7 +88,13 @@ function DashboardCommittersAndContributorsChart() {
setChartCommits(dataCommitsArray);
setChartMonths(monthArray);
};
orgId !== 0 && fetchWrapper(urlForChartCommits, FETCH_METHOD.GET, saveChartCommitsData);
fetchWrapper(urlForChartCommits, FETCH_METHOD.GET, saveChartCommitsData);
}, [orgId, chartCommits, setChartCommits]);
useEffect(() => {
if (!orgId || chartCommitters !== null) {
return;
}
// For chart - committers data
const urlForChartCommitters = isReactOnlyMode
......@@ -105,12 +109,12 @@ function DashboardCommittersAndContributorsChart() {
const dataCommittersArray = sortedData.map((item) => item.count);
setChartCommitters(dataCommittersArray);
};
orgId !== 0 && fetchWrapper(urlForChartCommitters, FETCH_METHOD.GET, saveChartCommittersData);
}, [orgId]);
fetchWrapper(urlForChartCommitters, FETCH_METHOD.GET, saveChartCommittersData);
}, [orgId, chartCommitters, setChartCommitters]);
return (
<div className={classes.fullWidthChartCtn}>
{chartCommits.length > 0 && chartCommitters.length > 0 ? (
{chartCommits && chartCommitters ? (
<Bar data={DATA_FOR_BAR_LINE_CHART} options={CONFIG_FOR_BAR_LINE_CHART} />
) : (
<div className={classes.loadingCtn}>
......
......@@ -21,9 +21,11 @@ import NoteIcon from '@material-ui/icons/Note';
import GroupIcon from '@material-ui/icons/Group';
import EmailIcon from '@material-ui/icons/Email';
import AssignmentIcon from '@material-ui/icons/Assignment';
import { OrgRep } from '../../../Interfaces/portal_interface';
import { OrganizationRoles, OrgRep } from '../../../Interfaces/portal_interface';
import PortalContext from '../../../Context/PortalContext';
import ModalWindow from '../../UIComponents/Notifications/ModalWindow';
import { api_prefix, FETCH_METHOD, getCurrentMode, MODE_REACT_ONLY } from '../../../Constants/Constants';
import { fetchWrapper } from '../../../Utils/formFunctionHelpers';
const useStyles = makeStyles((theme: Theme) =>
createStyles({
......@@ -124,10 +126,9 @@ const useStyles = makeStyles((theme: Theme) =>
})
);
export default function DashboardIntro(props: { orgRepData: Array<OrgRep> | null }) {
export default function DashboardIntro() {
const classes = useStyles();
const { orgRepData } = props;
const { orgInfo } = useContext(PortalContext);
const { orgId, orgInfo, orgRepData, setOrgRepData } = useContext(PortalContext);
const [orgIntro, setOrgIntro] = useState({ imageURL: '', name: '', website: '' });
const [open, setOpen] = useState(false);
......@@ -149,6 +150,38 @@ export default function DashboardIntro(props: { orgRepData: Array<OrgRep> | null
setOrgIntro({ imageURL: orgInfo.logos.web || '', name: orgInfo.name, website: orgInfo.website || '' });
}, [orgInfo]);
useEffect(() => {
if (orgId === 0 || orgRepData !== null) {
return;
}
const urlForOrgInfo =
getCurrentMode() === MODE_REACT_ONLY
? '/membership_data/test_org_rep.json'
: `${api_prefix()}/organizations/${orgId}/representatives`;
const saveOrgRep = (data: any) => {
const repCR: Array<OrgRep> = [];
const repCRA: Array<OrgRep> = [];
const repMA: Array<OrgRep> = [];
const updateOrgRepData = (contact: any, relation: 'CR' | 'CRA' | 'MA', repArray: Array<OrgRep>) => {
contact.relations.includes(relation) &&
repArray.push({ name: `${contact.first_name} ${contact.last_name}`, type: OrganizationRoles[relation] });
};
data.forEach((item: any) => {
updateOrgRepData(item, 'CR', repCR);
updateOrgRepData(item, 'CRA', repCRA);
updateOrgRepData(item, 'MA', repMA);
});
setOrgRepData([...repCR, ...repCRA, ...repMA]);
};
fetchWrapper(urlForOrgInfo, FETCH_METHOD.GET, saveOrgRep);
}, [orgId, orgRepData,setOrgRepData]);
return (
<Container className={classes.introCtn}>
<Card className={classNames(classes.card, classes.companyLogoCard)}>
......
......@@ -12,17 +12,31 @@ import BusinessCenterIcon from '@material-ui/icons/BusinessCenter';
import { fetchWrapper, fetchWrapperPagination } from '../../../../Utils/formFunctionHelpers';
import { pickRandomItems } from '../../../../Utils/portalFunctionHelpers';
import PortalContext from '../../../../Context/PortalContext';
import { DashboardProjectsAndWGProps, ProjectsAndWGItem } from '../../../../Interfaces/portal_interface';
import { DashboardProjectsAndWGProps } from '../../../../Interfaces/portal_interface';
export default function DashboardProjects({ setSelectedItemArray, setOpen }: DashboardProjectsAndWGProps) {
const [yourProjectsData, setYourProjectsData] = useState<Array<ProjectsAndWGItem>>([]);
const [allYourProjectsData, setAllYourProjectsData] = useState<Array<ProjectsAndWGItem>>([]);
const [isFetchingYourProjects, setIsFetchingYourProjects] = useState(true);
const [interestedProjectsData, setInterestedProjectsData] = useState<Array<ProjectsAndWGItem>>([]);
const [isFetchingInterestedProjects, setIsFetchingInterestedProjects] = useState(true);
const { orgId } = useContext(PortalContext);