Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
REACT_APP_SSO_CLIENT_ID=react-boilerplate
REACT_APP_SSO_CLIENT_ID=vote
REACT_APP_SSO_AUTHORITY=https://sso.csh.rit.edu/auth/realms/csh
7 changes: 6 additions & 1 deletion client/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { Component } from "react";
import { Switch, Route, BrowserRouter as Router } from "react-router-dom";
import { withOidcSecure } from "@axa-fr/react-oidc-context";
import { Home, Vote, Create } from "./index";
import { Home, Vote, Create, Result } from "./index";
import PageContainer from "../containers/PageContainer";

class App extends Component {
Expand All @@ -17,6 +17,11 @@ class App extends Component {
component={withOidcSecure(Vote)}
/>
<Route exact path="/create" component={withOidcSecure(Create)} />
<Route
exact
path="/result/:voteId"
component={withOidcSecure(Result)}
/>
</Switch>
</PageContainer>
</Router>
Expand Down
10 changes: 8 additions & 2 deletions client/src/components/NavBar/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,21 @@ import {
} from "reactstrap";
import { NavLink } from "react-router-dom";
import Profile from "./Profile";
import { useReactOidc } from "@axa-fr/react-oidc-context";

const NavBar: React.FunctionComponent = () => {
const [isOpen, setIsOpen] = React.useState<boolean>(false);

const toggle = () => {
setIsOpen(!isOpen);
};
const { oidcUser } = useReactOidc();
let evals = false;
if (oidcUser) {
evals = oidcUser.profile.groups.includes("eboard-evaluations");

}

const isEvals = true;

return (
<div>
Expand All @@ -34,7 +40,7 @@ const NavBar: React.FunctionComponent = () => {
Home
</NavLink>
</NavItem>
{isEvals ?
{evals ?
<NavItem>
<NavLink to="/create" className={"nav-link"}>
Create
Expand Down
15 changes: 11 additions & 4 deletions client/src/components/Pages/Create/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import React, { useState } from "react";
import { useHistory } from 'react-router-dom';
import Spinner from "../../Spinner";
import "./create.css";
import { useReactOidc } from "@axa-fr/react-oidc-context";

export const Create: React.FunctionComponent = () =>{
const [pollType, setPollType] = useState("PassFail");
const [pollTitle, setPollTitle] = useState("");
const [pollOptions, setPollOptions] = useState(["Pass", "Fail or Conditional", "Abstain"]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const { oidcUser } = useReactOidc();
const evals = oidcUser.profile.groups.includes("eboard-evaluations");

let history = useHistory();

function handleSelectPollType(changeEvent:React.FormEvent<HTMLInputElement>) {
Expand Down Expand Up @@ -52,10 +56,14 @@ export const Create: React.FunctionComponent = () =>{
setLoading(true);
const body = {
"title": pollTitle,
"options": pollOptions
"options": pollOptions,
"type": pollType
}
fetch("http://localhost:5000/api/initializePoll", {
headers: {"content-type": "application/json"},
headers: new Headers({
'Authorization': 'Bearer ' + oidcUser.access_token,
"content-type": "application/json"
}),
method: "POST",
body: JSON.stringify(body)
})
Expand All @@ -73,13 +81,12 @@ export const Create: React.FunctionComponent = () =>{
.catch((error) => {
setLoading(false);
setError(true);
console.log(error);
});
}

return(
loading ? <Spinner className="vote"></Spinner> :
error ? <div>Something went wrong : (</div> :
error || !evals ? <div>Something went wrong : (</div> :
<div>
<div className="create-poll-box">
<div className="create-poll-title-panel">Create Vote</div>
Expand Down
9 changes: 0 additions & 9 deletions client/src/components/Pages/Home/index.test.tsx

This file was deleted.

65 changes: 26 additions & 39 deletions client/src/components/Pages/Home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@
import React, {Component} from "react";
import React, {useEffect, useState} from "react";
import Spinner from "../../Spinner";
import PollList from "../../PollList";
import { useReactOidc } from "@axa-fr/react-oidc-context";

type HomeProps = {};
type HomeState = {
error: null | string,
isLoaded: boolean,
currentPolls: Array<any>
}
class Home extends Component<HomeProps, HomeState>{
constructor(props:HomeProps) {
super(props);
this.state = {
error: null,
isLoaded: false,
currentPolls: []
};
}
componentDidMount() {
fetch("http://localhost:5000/api/getCurrentPolls")
export const Home: React.FunctionComponent = () =>{
const [error, setError] = useState(null);
const [isLoaded, setLoaded] = useState(false);
const [currentPolls, setCurrentPolls] = useState([]);
const { oidcUser } = useReactOidc();

useEffect(() => {

fetch("http://localhost:5000/api/getCurrentPolls", { headers: new Headers({
'Authorization': 'Bearer ' + oidcUser.access_token
})})
.then(res => res.json())
.then((result) => {
this.setState({
isLoaded: true,
currentPolls: result
});
setLoaded(true);
setCurrentPolls(result);
},
(error) => {
this.setState({
isLoaded: true,
error
});
setLoaded(true);
setError(error);
});
}
render() {
const {error, isLoaded, currentPolls} = this.state;
if (error) {
return(
}, [oidcUser.access_token ])

return (
error ?
<div>Something went wrong! Please Try again</div>
);
} else if(!isLoaded) {
return(<Spinner className="home"/>)
}else {
return(
<PollList currentPolls={currentPolls}/>
)}
}
: !isLoaded ?
<Spinner className="home"/>
: <PollList currentPolls={currentPolls}/>
)

}

export default Home;
150 changes: 150 additions & 0 deletions client/src/components/Pages/Result/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import React, { useEffect, useState } from "react";
import { useParams, useHistory } from 'react-router-dom';
import Spinner from "../../Spinner";
import "./result.css";
import { useReactOidc } from "@axa-fr/react-oidc-context";

type RouteParams = {
voteId: string
}

type Poll = {
name: string,
results: Object
}

export const Result: React.FunctionComponent = () =>{
const { voteId } = useParams<RouteParams>();
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);

const [poll, setPoll] = useState<Poll|undefined>(undefined);
const [ended, setEnded] = useState(false);
let history = useHistory();
const { oidcUser } = useReactOidc();
const evals = oidcUser.profile.groups.includes("eboard-evaluations");
useEffect(() => {
const interval = setInterval(() => {
if(!ended) {
fetch("http://localhost:5000/api/getCount", {
headers: new Headers({
'Authorization': 'Bearer ' + oidcUser.access_token,
"content-type": "application/json"
}),
method: "POST",
body: JSON.stringify({"voteId": voteId})
})
.then((res) => {
switch(res.status) {
case 200:
return res.json()
case 404:
return undefined
default:
throw new Error("Error Getting Poll Details");
}
})
.then((result) => {
setLoading(false);
setPoll(result)
},
(error) => {
setLoading(false);
setError(true);
});
}
}, 10000);
return () => clearInterval(interval);
}, [voteId, ended, oidcUser.access_token]);

useEffect(() => {
fetch("http://localhost:5000/api/getCount", {
headers: new Headers({
'Authorization': 'Bearer ' + oidcUser.access_token,
"content-type": "application/json"
}),
method: "POST",
body: JSON.stringify({"voteId": voteId})
})
.then((res) => {
switch(res.status) {
case 200:
return res.json()
case 404:
return undefined
default:
throw new Error("Error Getting Poll Details");
}
})
.then((result) => {
setLoading(false);
setPoll(result)
},
(error) => {
setLoading(false);
setError(true);
});
}, [voteId, oidcUser.access_token])

function endVoting() {
if(window.confirm("End Voting?")){
setLoading(true)
fetch("http://localhost:5000/api/endPoll", {
headers: new Headers({
'Authorization': 'Bearer ' + oidcUser.access_token,
"content-type": "application/json"
}),
method: "POST",
body: JSON.stringify({"voteId": voteId})
})
.then((res) => {
switch(res.status) {
case 200:
return res.json()
case 404:
return undefined
default:
throw new Error("Error Getting Poll Details");
}
})
.then((result) => {
setLoading(false);
setPoll(result)
setEnded(true)
},
(error) => {
setLoading(false);
setError(true);
});
}
}

return(
loading ? <Spinner className="vote"></Spinner> :
error ? <div>Something went wrong : (</div> :
poll === undefined ?
<div>Poll not found : (</div> :
<div>
<div className="result-list">
<div className="result-title-panel">{poll.name} {ended ? "Final" : null} Results </div>
<div>
{ended? null :<div className="refresh-message">These are refreshed every 10 seconds</div>}
<div className="result-list-items">
{Object.entries(poll.results).map(function(option, idx){
return (<li key={idx}>{option[0]} : {option[1]}</li>)
})}
</div>
</div>
</div>
<div className="exit-button">
{evals && !ended ? <button className="btn btn-danger" onClick={() => endVoting()}>End Voting</button> : <button
onClick={() => history.push("/")}
className="btn btn-primary submit-button"
>Exit</button>}
</div>

</div>
)
}

export default Result;
32 changes: 32 additions & 0 deletions client/src/components/Pages/Result/result.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.result-title-panel {
color: inherit;
font-size: 20px;
padding: 20px;
}

.result-list {
border: none;
border-radius: 2px;
box-shadow: 0 1px 4px rgba(0,0,0,.3);
}

.refresh-message {
padding: 12px;
}

.result-list-items{
background-color: white;
font-size: 14px;
padding:12px;
padding-right: 16px;
}

.result-list-items li {
list-style: none;
padding-top: 12px;
}

.exit-button {
margin-top: 24px;
text-align: center;
}
Loading