Unverified Commit 9d89be15 authored by Zhou (Link)  Fang's avatar Zhou (Link) Fang Committed by GitHub
Browse files

Portal Landing Page - Left sidebar and Dashboard FAQs (#144)

* Added basic router and navigation layout

* finished navigation logic

* made the left nav bar a component and improved the styles

* Added a demo collapse section

* finished the basic faq collapse list

* finished the basic faq collapse list

* finished style for FAQs part

* removed unused imports

* minor update to fix a React warning

* Added fetch for user name and avatar

* made some improvements based on feedback

* Added basic components and styles

* commented out home

* fixed unused variables issue

* Server responds 302 redirect when there is no token/q_session #193



Adds property that stops auto redirect when there is an issue with
authentication and source is Javascript.

* Changed some of the navs to sub navs

* simplified the style of panels
Co-authored-by: Martin Lowe's avatarMartin Lowe <martin.lowe@eclipse-foundation.org>
parent 8eaa3f99
......@@ -54,6 +54,7 @@
]
},
"devDependencies": {
"@types/react-router-dom": "^5.1.7",
"@openapi-contrib/openapi-schema-to-json-schema": "^3.1.1",
"@stoplight/json-ref-resolver": "^3.1.2",
"decamelize": "^5.0.0",
......@@ -65,6 +66,6 @@
},
"prettier": {
"singleQuote": true,
"printWidth": 80
"printWidth": 120
}
}
......@@ -3,13 +3,7 @@ import './App.css';
import AppTemplate from './components/UIComponents/Templates/AppTemplate';
import MembershipContext from './Context/MembershipContext';
import { createMuiTheme, ThemeProvider } from '@material-ui/core';
import {
HashRouter,
BrowserRouter,
Switch,
Route,
Redirect,
} from 'react-router-dom';
import { HashRouter, BrowserRouter, Switch, Route, Redirect } from 'react-router-dom';
import Application from './components/Application/Application';
import Portal from './components/Portal/Portal';
import NotFound404 from './components/ErrorPages/NotFound404';
......@@ -49,8 +43,10 @@ const App = () => {
<ThemeProvider theme={theme}>
<BrowserRouter>
<Switch>
<Route exact path="/portal">
<Portal />
<Route path="/portal">
<BrowserRouter hashType="noslash">
<Portal />
</BrowserRouter>
</Route>
<Route exact path="/application">
......@@ -81,7 +77,6 @@ const App = () => {
{/* Redirect user to 404 page for all the unknown pathnames/urls */}
<Redirect to="404" />
</Switch>
</BrowserRouter>
</ThemeProvider>
......
......@@ -4,6 +4,18 @@
* The purpose of this file is try to avoid using strings directly everywhere,
* just hope to use consistent variables for strings.
*/
import {
// Home as HomeIcon,
Assessment as AssessmentIcon,
Business as BusinessIcon,
BusinessCenter as BusinessCenterIcon,
PeopleAlt as PeopleAltIcon,
Description as DescriptionIcon,
Help as HelpIcon,
RecentActors as RecentActorsIcon,
} from '@material-ui/icons';
export const api_prefix = () => {
return '//' + window.location.host + '/api';
};
......@@ -18,8 +30,7 @@ export const SIGNING_AUTHORITY = 'Signing Authority';
export const REVIEW = 'Review';
export const HAS_TOKEN_EXPIRED = 'HAS_TOKEN_EXPIRED';
export const LOGIN_EXPIRED_MSG =
'Your session has expired, please sign in again.';
export const LOGIN_EXPIRED_MSG = 'Your session has expired, please sign in again.';
export const PATH_NAME_ARRAY = [
'/company-info',
......@@ -148,3 +159,55 @@ export const FULL_WORKING_GROUP_LIST_FOR_REACT_ONLY = [
],
},
];
export const NAV_OPTIONS_DATA = [
// {
// name: 'Home',
// path: '/home',
// icon: <HomeIcon />,
// },
{
name: 'Dashboard',
path: '/portal/dashboard',
icon: <AssessmentIcon />,
},
{
name: 'Your Organization Profile',
path: '/portal/org-profile',
// don't find an icon match the design
icon: <BusinessIcon />,
},
{
name: 'Projects and Working Groups',
path: '/portal/dashboard#projects-wg',
icon: <BusinessCenterIcon />,
},
{
name: 'Committers and Contributors',
path: '/portal/dashboard#committers-contributors',
icon: <PeopleAltIcon />,
},
{
name: 'Resources',
path: '/portal/dashboard#resources',
icon: <DescriptionIcon />,
},
{
name: 'FAQs',
path: '/portal/dashboard#faqs',
icon: <HelpIcon />,
},
{
name: 'Contact Management',
path: '/portal/contact-management',
icon: <RecentActorsIcon />,
},
];
// Constants for styles
export const drawerWidth = 280;
export const themeBlack = '#0B0B0B';
export const darkOrange = '#DD730A';
export const iconGray = '#9B9BAE';
export const borderRadiusSize = 5;
export const mainContentBGColor = '#fff';
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 373.33 195"><defs><style>.cls-1{fill:#fff;}</style></defs><title>EF_all_colours_ai</title><g id="Layer_1" data-name="Layer 1"><path class="cls-1" d="M316.56,131.3l-8.67-11h-2.71V138h3.34v-12l9.31,12h2.07V120.31h-3.34ZM284.15,123c4.17,0,5.84,3.34,5.79,6.33s-1.62,6-5.79,6-5.74-3.11-5.81-6S280,123,284.15,123Zm0-3c-6.12,0-9.1,4.68-9.1,9.33s2.88,9.13,9.1,9.13,9-4.58,9.08-9.16S290.25,120,284.15,120Zm-21.23,18V120.31H259.6V138Zm-23.56,0h3.34V123.34h5.61v-3H233.74v3h5.62Zm-18.91-6.44h-6.58l3.29-7.56Zm2.83,6.44h3.64L219,120.31h-3.64L207.4,138H211l1.51-3.33h9.26Zm-38-14.56h3.64c3.85,0,5.46,2.76,5.54,5.52s-1.52,5.83-5.54,5.83h-3.64Zm3.64-3.16H182V138h6.95c6.2,0,8.93-4.52,8.85-9S195,120.31,188.92,120.31Zm-22.37,11-8.67-11h-2.71V138h3.34v-12l9.3,12h2.08V120.31h-3.34Zm-27.46-10.94V130.5c0,3-1.56,4.88-4.32,4.88s-4.58-1.69-4.58-4.88V120.36h-3.31V130.5c0,5.33,3.62,7.91,7.86,7.91,4.45,0,7.67-2.68,7.67-7.91V120.36Zm-33,2.65c4.17,0,5.84,3.34,5.79,6.33s-1.62,6-5.79,6-5.74-3.11-5.82-6S101.93,123,106.1,123Zm0-3c-6.12,0-9.1,4.68-9.1,9.33s2.88,9.13,9.1,9.13,9-4.58,9.08-9.16S112.19,120,106.1,120ZM76.32,138v-6.54h8.87V128.4H76.32v-4.83H85.7v-3.21H73V138Z"/><path class="cls-1" d="M320.23,101.75H298.06V92.84h21.38V85.9H298.06V76.76h22.17V69.54H290.67v39.54h29.56Zm-40-25.66c-3-6.1-9.36-7.84-15.51-7.84-7.28,0-15.29,3.38-15.29,11.5,0,8.86,7.45,11,15.51,12,5.25.56,9.14,2.09,9.14,5.81,0,4.29-4.4,5.92-9.08,5.92s-9.36-1.92-11.11-6.26l-6.21,3.22c2.94,7.22,9.14,9.7,17.21,9.7,8.8,0,16.58-3.78,16.58-12.58,0-9.42-7.67-11.56-15.91-12.58-4.73-.56-8.79-1.52-8.79-5,0-2.93,2.65-5.25,8.17-5.25,4.29,0,8,2.15,9.37,4.4Zm-53.34-6.55c-6.21-.05-12.41,0-18.62,0v39.54h7.45V97.46h11.17C246.25,97.46,246.2,69.54,226.91,69.54Zm-11.17,7.11h11.17c9.47,0,9.53,14,0,14H215.74Zm-18,32.43V69.54h-7.39v39.54Zm-44-39.54v39.54h27.75V102.2H161.22V69.54ZM141.55,99a14.53,14.53,0,0,1-9.92,4c-9.76,0-13.54-6.82-13.6-13.37s4.06-13.7,13.6-13.7a13.56,13.56,0,0,1,9.53,3.72l5-4.79a20.35,20.35,0,0,0-14.49-6c-14.27,0-21,10.49-20.93,20.81S117,110,131.63,110a20.83,20.83,0,0,0,15-5.87Zm-39,2.76H80.37V92.84h21.38V85.9H80.37V76.76h22.17V69.54H73v39.54h29.56Z"/><path class="cls-1" d="M60.66,65.52c9-14.1,27.15-19,42.25-12.25l-1-.69a33.16,33.16,0,1,0-35.8,55.83l1.05.63C54.69,98.14,51.61,79.63,60.66,65.52Z"/><path class="cls-1" d="M323,73.41v0a4.58,4.58,0,1,1,9.16,0v0a4.58,4.58,0,1,1-9.16,0Zm8.63,0v0a4.05,4.05,0,1,0-8.1,0v0a4,4,0,0,0,4.05,4.08A4.07,4.07,0,0,0,331.67,73.38Zm-5.94-2.47H328c1.11,0,1.92.5,1.92,1.58A1.46,1.46,0,0,1,328.83,74L330,75.67h-1.39l-1-1.5h-.74v1.5h-1.15Zm2.15,2.31c.53,0,.82-.26.82-.65s-.32-.66-.82-.66h-1v1.31Z"/></g></svg>
\ No newline at end of file
import { Typography } from '@material-ui/core';
export default function CommitersAndContributors() {
return (
<div
style={{
margin: '40px 0',
}}
>
<Typography variant="h4">Commiters and Contributors</Typography>
</div>
);
}
import { Typography } from '@material-ui/core';
export default function ContactManagement() {
return (
<>
<Typography variant="h4">Contact Management</Typography>
{
// below are placeholders
}
<div
style={{
display: 'flex',
margin: '20px 0 60px',
justifyContent: 'space-between',
}}
>
<div
style={{
width: '48%',
height: 260,
backgroundColor: '#DCDFE5',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Fields 1</h5>
</div>
<div
style={{
width: '48%',
height: 260,
backgroundColor: '#A09C9C',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Fields 2</h5>
</div>
</div>
<div
style={{
width: '100%',
height: 260,
backgroundColor: '#DCDFE5',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Table</h5>
</div>
</>
);
}
import DashboardCommittersAndContributors from './DashboardCommittersAndContributors';
import DashboardFAQs from './DashboardFAQs';
import DashboardIntro from './DashboardIntro';
import DashboardOverview from './DashboardOverview';
import DashboardProjectsAndWG from './DashboardProjectsAndWG';
import DashboardResources from './DashboardResources';
export default function Dashboard() {
return (
<>
<DashboardIntro />
<DashboardOverview />
<DashboardProjectsAndWG />
<DashboardCommittersAndContributors />
<DashboardResources />
<DashboardFAQs />
</>
);
}
import { Typography } from '@material-ui/core';
export default function DashboardCommittersAndContributors() {
return (
<div
style={{
paddingTop: 90,
display: 'flex',
flexDirection: 'column',
}}
id="committers-contributors"
>
<Typography variant="h4">Committers and Contributors</Typography>
{
// below are placeholders
}
<div
style={{
display: 'flex',
margin: '40px 0',
justifyContent: 'space-between',
}}
>
<div
style={{
width: '48%',
display: 'flex',
flexDirection: 'column',
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
marginBottom: 20,
}}
>
<div
style={{
width: '48%',
height: 180,
backgroundColor: '#fff',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Lorem Ipsum</h5>
</div>
<div
style={{
width: '48%',
height: 180,
backgroundColor: '#fff',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Lorem Ipsum</h5>
</div>
</div>
<div>
<div
style={{
width: '100%',
height: 80,
backgroundColor: 'orange',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Lorem Ipsum</h5>
</div>
</div>
</div>
<div
style={{
width: '48%',
height: 280,
backgroundColor: '#fff',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Lorem Ipsum</h5>
</div>
</div>
<div>
<div
style={{
width: '100%',
height: 300,
backgroundColor: '#DCDFE5',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 40,
}}
>
<h5>Chart 1</h5>
</div>
<div
style={{
width: '100%',
height: 300,
backgroundColor: '#DCDFE5',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Chart 2</h5>
</div>
</div>
</div>
);
}
import { useState } from 'react';
import {
ListItem,
ListItemText,
Collapse,
Container,
makeStyles,
createStyles,
ListItemIcon,
List,
Typography,
} from '@material-ui/core';
import ContactSupportIcon from '@material-ui/icons/ContactSupport';
import ExpandLessIcon from '@material-ui/icons/ExpandLess';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { borderRadiusSize, iconGray, mainContentBGColor } from '../../../Constants/Constants';
const faqItems = [
{
question: 'Question-1',
answer:
"Lorem Ipsum 1 is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s. Lorem Ipsum 1 is simply dummy text of the printing and typesetting industry.",
},
{
question: 'Question-2',
answer:
"Lorem Ipsum 2 is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.",
},
{
question: 'Question-3',
answer:
"Lorem Ipsum 3 is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.",
},
{
question: 'Question-4',
answer:
"Lorem Ipsum 4 is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.",
},
];
const useStyles = makeStyles(() =>
createStyles({
faqContainer: {
position: 'relative',
display: 'flex',
marginTop: 40,
paddingLeft: 64,
paddingRight: 0,
border: '2px #DCDFE5 solid',
borderRadius: borderRadiusSize,
},
faqIcon: {
position: 'absolute',
top: -30,
left: 12,
color: iconGray,
backgroundColor: mainContentBGColor,
fontSize: 60,
},
faqIconForBG: {
fontSize: 200,
opacity: 0.15,
color: iconGray,
marginTop: 42,
},
faqList: {
marginTop: 30,
marginBottom: 25,
padding: 10,
},
faqItemCtn: {
padding: 0,
border: '2px #EDEDED solid',
borderRadius: borderRadiusSize,
marginBottom: 5,
},
faqQuestion: {
backgroundColor: '#EDEDED',
cursor: 'pointer',
},
faqExpandIcon: {
flexDirection: 'row-reverse',
},
faqAnswer: {
padding: '16px 32px',
},
})
);
export default function DashboardFAQs() {
const [shouldCollapse, setShouldCollapse] = useState<Array<boolean>>([]);
const classes = useStyles();
const handleClick = (index: number) => {
const newShouldCollapse = [...shouldCollapse];
newShouldCollapse[index] = !newShouldCollapse[index];
setShouldCollapse(newShouldCollapse);
};
const renderFAQs = faqItems.map((item, index) => (
<List className={classes.faqItemCtn} key={index}>
<ListItem className={classes.faqQuestion}>
<ListItemText primary={item.question} onClick={() => handleClick(index)} />
<ListItemIcon className={classes.faqExpandIcon}>
{shouldCollapse[index] ? <ExpandLessIcon /> : <ExpandMoreIcon />}
</ListItemIcon>
</ListItem>
<Collapse in={shouldCollapse[index]} timeout="auto" unmountOnExit>
<ListItem className={classes.faqAnswer}>
<ListItemText primary={item.answer} />
</ListItem>
</Collapse>
</List>
));
return (
<div
style={{
paddingTop: 90,
}}
id="faqs"
>
<Typography variant="h4">FAQs</Typography>
<Container className={classes.faqContainer}>
<ContactSupportIcon className={classes.faqIcon} />
<Container className={classes.faqList}>{renderFAQs}</Container>
<ContactSupportIcon className={classes.faqIconForBG} />
</Container>
</div>
);
}
export default function DashboardIntro() {
// below are placeholders
return (
<div
style={{
display: 'flex',
justifyContent: 'space-between',
}}
>
<div
style={{
width: '30%',
height: 260,
backgroundColor: '#DCDFE5',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Your Company Logo</h5>
</div>
<div
style={{
width: '30%',
height: 260,
backgroundColor: '#A09C9C',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Your Company Rep</h5>
</div>
<div
style={{
width: '30%',
height: 260,
backgroundColor: '#fff',
boxShadow: '1px 1px 15px rgba(0,0,0,0.1)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<h5>Lorem Ipsum</h5>
</div>
</div>
);
}
import { Typography } from '@material-ui/core';
export default function DashboardOverview() {
return (
<div
style={{
paddingTop: 90,
}}
>
<Typography variant="h4">Overview</Typography>
{
// below are placeholders
}
<div
style={{
display: 'flex',
marginTop: 40,
justifyContent: 'space-between',
}}
></