Teaching Assistant feedback + deployment
This commit is contained in:
		
							parent
							
								
									29f463f248
								
							
						
					
					
						commit
						e14db4b382
					
				
							
								
								
									
										14
									
								
								src/client/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								src/client/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -4869,7 +4869,6 @@ | ||||
|       "dependencies": { | ||||
|         "anymatch": "~3.1.2", | ||||
|         "braces": "~3.0.2", | ||||
|         "fsevents": "~2.3.2", | ||||
|         "glob-parent": "~5.1.2", | ||||
|         "is-binary-path": "~2.1.0", | ||||
|         "is-glob": "~4.0.1", | ||||
| @ -6117,8 +6116,7 @@ | ||||
|         "esprima": "^4.0.1", | ||||
|         "estraverse": "^5.2.0", | ||||
|         "esutils": "^2.0.2", | ||||
|         "optionator": "^0.8.1", | ||||
|         "source-map": "~0.6.1" | ||||
|         "optionator": "^0.8.1" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "escodegen": "bin/escodegen.js", | ||||
| @ -8726,7 +8724,6 @@ | ||||
|         "@types/node": "*", | ||||
|         "anymatch": "^3.0.3", | ||||
|         "fb-watchman": "^2.0.0", | ||||
|         "fsevents": "^2.3.2", | ||||
|         "graceful-fs": "^4.2.9", | ||||
|         "jest-regex-util": "^27.5.1", | ||||
|         "jest-serializer": "^27.5.1", | ||||
| @ -10032,14 +10029,9 @@ | ||||
|       "integrity": "sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA==", | ||||
|       "dependencies": { | ||||
|         "copy-anything": "^2.0.1", | ||||
|         "errno": "^0.1.1", | ||||
|         "graceful-fs": "^4.1.2", | ||||
|         "image-size": "~0.5.0", | ||||
|         "make-dir": "^2.1.0", | ||||
|         "mime": "^1.4.1", | ||||
|         "needle": "^2.5.2", | ||||
|         "parse-node-version": "^1.0.1", | ||||
|         "source-map": "~0.6.0", | ||||
|         "tslib": "^2.3.0" | ||||
|       }, | ||||
|       "bin": { | ||||
| @ -12415,7 +12407,6 @@ | ||||
|         "eslint-webpack-plugin": "^3.1.1", | ||||
|         "file-loader": "^6.2.0", | ||||
|         "fs-extra": "^10.0.0", | ||||
|         "fsevents": "^2.3.2", | ||||
|         "html-webpack-plugin": "^5.5.0", | ||||
|         "identity-obj-proxy": "^3.0.0", | ||||
|         "jest": "^27.4.3", | ||||
| @ -12835,9 +12826,6 @@ | ||||
|       "version": "2.70.1", | ||||
|       "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.70.1.tgz", | ||||
|       "integrity": "sha512-CRYsI5EuzLbXdxC6RnYhOuRdtz4bhejPMSWjsFLfVM/7w/85n2szZv6yExqUXsBdz5KT8eoubeyDUDjhLHEslA==", | ||||
|       "dependencies": { | ||||
|         "fsevents": "~2.3.2" | ||||
|       }, | ||||
|       "bin": { | ||||
|         "rollup": "dist/bin/rollup" | ||||
|       }, | ||||
|  | ||||
| @ -114,7 +114,7 @@ function TournamentListItem(props) { | ||||
|                | ||||
|               <Typography variant="h5" color="text.primary" gutterBottom> Particpants: {props.tournament.teamCount} / {props.tournament.teamLimit} </Typography> | ||||
|               <Description /> | ||||
|               <Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trohpy" color="gold"/>  Prize: {props.tournament.prize} </Typography> | ||||
|               <Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trophy" color="gold"/>  Prize: {props.tournament.prize} </Typography> | ||||
|               <Countdown /> | ||||
|                | ||||
|               <Box sx={{flexGrow: 1, marginTop: "20px"}}> | ||||
| @ -205,36 +205,36 @@ let showError = (message) => {}; | ||||
| 
 | ||||
| export default function App() { | ||||
|   const [user, setUser] = React.useState({}); | ||||
|   let fetchUser = () => { | ||||
|     fetch(process.env.REACT_APP_API_URL + `/users/getSavedUser`) | ||||
|       .then(res => res.json()) | ||||
|       .then(data => { | ||||
|         if (data.status !== "OK") { | ||||
|           setUser({ isManager: false, isLoggedIn: false }); | ||||
|           console.log(data.data); // "No user logged in"
 | ||||
|           return; | ||||
|         } | ||||
|         let u  = data.data; | ||||
|         u.isLoggedIn = true; | ||||
|         console.log("User is logged in") | ||||
|         setUser(u); | ||||
|       }) | ||||
|       .catch((err) => { | ||||
|         showError(err.message); | ||||
|         setUser({ isManager: false, isLoggedIn: false }); | ||||
|       }); | ||||
|   } | ||||
|   // // Debug mode, allow all:
 | ||||
|   // let fetchUser = () => {
 | ||||
|   //   setUser({
 | ||||
|   //     name: "TEST USERTEST",
 | ||||
|   //     isManager: true,
 | ||||
|   //     isLoggedIn: true,
 | ||||
|   //     email: "testesen@gmail.com",
 | ||||
|   //     asuraId: "123456789",
 | ||||
|   //     googleId: "234"
 | ||||
|   //   });
 | ||||
|   //   fetch(process.env.REACT_APP_API_URL + `/users/getSavedUser`)
 | ||||
|   //     .then(res => res.json())
 | ||||
|   //     .then(data => {
 | ||||
|   //       if (data.status !== "OK") {
 | ||||
|   //         setUser({ isManager: false, isLoggedIn: false });
 | ||||
|   //         console.log(data.data); // "No user logged in"
 | ||||
|   //         return;
 | ||||
|   //       }
 | ||||
|   //       let u  = data.data;
 | ||||
|   //       u.isLoggedIn = true;
 | ||||
|   //       console.log("User is logged in")
 | ||||
|   //       setUser(u);
 | ||||
|   //     })
 | ||||
|   //     .catch((err) => {
 | ||||
|   //       showError(err.message);
 | ||||
|   //       setUser({ isManager: false, isLoggedIn: false });
 | ||||
|   //     });
 | ||||
|   // }
 | ||||
|   // Debug mode, allow all:
 | ||||
|   let fetchUser = () => { | ||||
|     setUser({ | ||||
|       name: "TEST USERTEST", | ||||
|       isManager: true, | ||||
|       isLoggedIn: true, | ||||
|       email: "testesen@gmail.com", | ||||
|       asuraId: "123456789", | ||||
|       googleId: "234" | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   React.useEffect(() => { | ||||
|     fetchUser(); | ||||
|  | ||||
| @ -56,7 +56,7 @@ function shorten(description, maxLength) { | ||||
|                  | ||||
|                 <Typography variant="h5" color="text.primary" gutterBottom> Participants: {props.tournament.teamCount} / {props.tournament.teamLimit} </Typography> | ||||
|                 <Description /> | ||||
|                 <Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trohpy" color="gold" align="vertical-center"/>  Prize: {props.tournament.prize} </Typography> | ||||
|                 <Typography variant="body" color="text.primary"><EmojiEventsIcon alt="A trophy" color="gold" align="vertical-center"/>  Prize: {props.tournament.prize} </Typography> | ||||
| 
 | ||||
|                 <Box sx={{flexGrow: 1, marginTop: "20px"}}> | ||||
|                   <Grid container spacing={4} justifyContent="center" wrap="wrap"> | ||||
| @ -135,13 +135,13 @@ function shorten(description, maxLength) { | ||||
|     } | ||||
|   } | ||||
|    | ||||
|     return <> | ||||
|     <TextField type="text" id="searchInput" label="Search" placeholder="Tournament Name" InputLabelProps={{shrink: true}} onChange={search}/> | ||||
|     return <Container sx={{minHeight: "30vh", width: "90vw", padding: "20px 20px", alignContent:'center'}}> | ||||
|     <TextField sx={{width: '50%', marginLeft: '25%', color: 'black', fontSize: '1.5em'}} size="large" type="text" id="searchInput" label="Search finished tournaments" placeholder="Tournament Name" InputLabelProps={{shrink: true}} onChange={search}/> | ||||
|     <Stack spacing={3} sx={{margin: "10px auto"}}> | ||||
|       {tournamentList && tournamentList.map((tournamentObject) => <TournamentListItem key={tournamentObject.id.toString()} tournament={tournamentObject} />)} | ||||
|     </Stack> | ||||
|        | ||||
|     </>; | ||||
|     </Container>; | ||||
|   } | ||||
| 
 | ||||
| export default function TournamentHistory(props) { | ||||
| @ -149,12 +149,7 @@ export default function TournamentHistory(props) { | ||||
|   return ( | ||||
|       <> | ||||
|         <Appbar user={props.user} pageTitle="Tournament History" /> | ||||
|           <Container sx={{minHeight: "30vh", width: "90vw", padding: "20px 20px"}} component={Container} direction="column" align="center"> | ||||
|             <Box component={Stack} direction="row" align="center" justifyContent="center" alignItems="center" sx={{flexGrow: 1, margin:'2.5% 0'}}> | ||||
|               <Typography sx={{fontSize:['1.5rem','2rem','2rem']}}>Past Tournaments</Typography> | ||||
|             </Box> | ||||
|             <TournamentList /> | ||||
|           </Container> | ||||
|         <TournamentList /> | ||||
|       </> | ||||
|     ); | ||||
| } | ||||
| @ -91,7 +91,7 @@ function Match(props){ | ||||
|                 {team1Name} | ||||
|               </Typography> | ||||
|               { props.match.winnerId && (props.match.team1Id === props.match.winnerId) && | ||||
|               <EmojiEventsIcon alt="A trohpy" sx={{width:['0.75em','1em','1.25em'], height:['0.75em','1em','1.25em']}} /> | ||||
|               <EmojiEventsIcon alt="A trophy" sx={{width:['0.75em','1em','1.25em'], height:['0.75em','1em','1.25em']}} /> | ||||
|               } | ||||
|               <Box component={Stack} direction={'row'} spacing={-1.25}> | ||||
|               { props.match.team1Id !== null && !props.tournament.hasEnded && props.match.tier !== Math.log2(props.tournament.teamLimit) - 1 && props.match.winnerId === null && props.user.isLoggedIn && | ||||
| @ -111,7 +111,7 @@ function Match(props){ | ||||
|                 {team2Name} | ||||
|               </Typography> | ||||
|               { props.match.winnerId && (props.match.team2Id === props.match.winnerId) && | ||||
|               <EmojiEventsIcon alt="A trohpy" sx={{width:['0.75em','1em','1.25em'], height:['0.75em','1em','1.25em']}} /> | ||||
|               <EmojiEventsIcon alt="A trophy" sx={{width:['0.75em','1em','1.25em'], height:['0.75em','1em','1.25em']}} /> | ||||
|               } | ||||
|               { props.match.team2Id !== null && !props.tournament.hasEnded && props.match.tier !== Math.log2(props.tournament.teamLimit) - 1 && props.match.winnerId === null && props.user.isLoggedIn && | ||||
|               <IconButton color="error" aria-label="remove winner" component="span" onClick={curryUnsetContestant(props.match.team2Id)}><BackspaceIcon sx={{width:['0.75em','1em','1.25em'], height:['0.75em','1em','1.25em']}} /></IconButton> | ||||
| @ -162,7 +162,7 @@ function WinnerDisplay(props) { | ||||
|       <Typography sx={{fontSize:['1em','1em','1.5em','2em']}} className="winner"> | ||||
|         {props.team.name} | ||||
|       </Typography> | ||||
|       <EmojiEventsIcon alt="A trohpy" /> | ||||
|       <EmojiEventsIcon alt="A trophy" /> | ||||
|     </div> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| @ -71,17 +71,49 @@ function TeamList(props) { | ||||
|       .catch(error => showError(error)); | ||||
|   } | ||||
| 
 | ||||
|   function search() { | ||||
|     let searchBase = [] | ||||
|     let searchResult = [] | ||||
|     let originalList = props.originalList | ||||
|     originalList.map((tournament) => searchBase.push(tournament.name)) | ||||
|     let input = document.getElementById("searchInput") | ||||
|     let inputUpperCase = input.value.toUpperCase() | ||||
|     for (let i = 0; i < searchBase.length; i++) { | ||||
|       let tournamentName = searchBase[i].toUpperCase() | ||||
|       if(tournamentName.indexOf(inputUpperCase) >= 0) { | ||||
|         searchResult.push(tournamentName) | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     let searchedList = [] | ||||
|     for (let i = 0; i < originalList.length; i++) { | ||||
|       let name = originalList[i].name | ||||
|       for (let j = 0; j < searchResult.length; j++) { | ||||
|         if (name.toUpperCase() == searchResult[j]) { | ||||
|           searchedList.push(originalList[i]) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (input.value == "") { | ||||
|       props.setTeams(originalList) | ||||
|     } else { | ||||
|       props.setTeams(searchedList) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|   <Paper sx={{minHeight: "30vh", width: "90vw", margin: "10px auto"}} component={Stack} direction="column" justifyContent="center"> | ||||
|   <div align="center" > | ||||
|   <h2><b>Teams:</b></h2> | ||||
|   {/* TODO: scroll denne menyen, eventuelt søkefelt */} | ||||
|   {/* Make a horizontal stack */} | ||||
|     <TextField sx={{margin:'2.5% 0 0 0', width: '50%'}} type="text" id="searchInput" label="Search" placeholder="Team Name" InputLabelProps={{shrink: true}} onChange={search}/>    | ||||
|   | ||||
|       <Table aria-label="simple table"> | ||||
|         <TableHead> | ||||
|           <TableRow> | ||||
|             <TableCell>Team Name</TableCell> | ||||
|             <TableCell><h2>Team Name</h2></TableCell> | ||||
|             {/* <TableCell align="right">Team Members</TableCell> */} | ||||
|             <TableCell align="center">Actions</TableCell> | ||||
|             <TableCell align="center"><h2>Actions</h2></TableCell> | ||||
|           </TableRow> | ||||
|         </TableHead> | ||||
|         <TableBody> | ||||
| @ -91,7 +123,6 @@ function TeamList(props) { | ||||
|               <TableCell component="th" scope="row"> <b> | ||||
|                 {team.name} | ||||
|               </b></TableCell> | ||||
|               {/* <TableCell align="right">{team.members}</TableCell> */} | ||||
|               <TableCell align="center"> | ||||
|                 <Button variant="contained" sx={{margin: "auto 5px"}} color="primary" onClick={() => {props.setSelectedTeamId(team.id); window.scrollTo(0, document.body.scrollHeight)}} endIcon={<EditIcon />}>Edit</Button> | ||||
|                 <Button variant="contained" sx={{margin: "auto 5px"}} color="error" onClick={() => {deleteTeam(team.id)}} endIcon={<DeleteIcon />}>Delete</Button> | ||||
| @ -184,6 +215,7 @@ let showError = (message) => {}; | ||||
| export default function TournamentTeams(props) { | ||||
|   const [teams, setTeams] = React.useState([]); | ||||
|   const [selectedTeamId, setSelectedTeamId] = React.useState(-1); | ||||
|   const [originalList, setOriginalList] = React.useState([]) | ||||
|   const { tournamentId } = useParams(); | ||||
| 
 | ||||
|   function getTeams() { | ||||
| @ -194,6 +226,7 @@ export default function TournamentTeams(props) { | ||||
|           showError(data.data); | ||||
|         } | ||||
|         setTeams(data.data); | ||||
|         setOriginalList(data.data) | ||||
|         //setselectedTeamId(teams[0].id);
 | ||||
|       }) | ||||
|       .catch((err) => showError(err)); | ||||
| @ -218,7 +251,7 @@ export default function TournamentTeams(props) { | ||||
|     <TournamentBar pageTitle="Manage Teams" /> | ||||
|     <div className="tournamentTeams"> | ||||
|       <TeamCreator tournamentId={tournamentId} teams={teams} onTeamCreated={getTeams} /> | ||||
|       <TeamList teams={teams} setTeams={setTeams} selectedTeamId={selectedTeamId} setSelectedTeamId={setSelectedTeamId} /> | ||||
|       <TeamList teams={teams} setTeams={setTeams} selectedTeamId={selectedTeamId} setSelectedTeamId={setSelectedTeamId} originalList={originalList} setOriginalList={setOriginalList} /> | ||||
|       <TeamEditor teams={teams} setTeams={setTeams} selectedTeamId={selectedTeamId} setSelectedTeamId={setSelectedTeamId} /> | ||||
|     </div> | ||||
|     <ErrorSnackbar message={errorMessage} open={openError} setOpen={setOpenError} /> | ||||
|  | ||||
| @ -25,11 +25,11 @@ function LoggedInMenu(props) { | ||||
| 
 | ||||
|   return ( | ||||
|     <> | ||||
|       <Link to="/profile"><Button sx={{color:'white', marginTop:'5px'}} startIcon={<AccountCircleIcon />}>{props.user.name}</Button></Link> | ||||
|       <IconButton size="large" edge="start" color="inherit" aria-label="menu"  onClick={handleClick}> | ||||
|         <MenuIcon /> | ||||
|         </IconButton> | ||||
|         <Menu anchorEl={anchorEl} open={open} onClose={handleClose} MenuListProps={{'aria-labelledby': 'basic-button',}} sx={{position:"absolute"}}> | ||||
|           <Link to="/profile" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<AccountCircleIcon />}>{props.user.name}</Button></MenuItem></Link> | ||||
|           <Link to="/history" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<HistoryIcon />}>History</Button></MenuItem></Link> | ||||
|           { props.user.isManager &&  | ||||
|           <Link to="/admins" style={{color:"black"}}><MenuItem onClick={handleClose}><Button startIcon={<EditIcon />} >Admins</Button></MenuItem></Link> | ||||
| @ -71,7 +71,7 @@ export default function Appbar(props) { | ||||
|                 </Link> | ||||
|                   { props.pageTitle !== "Asura Tournaments" && | ||||
|                   <Link to="/" style={{color:"white"}}> | ||||
|                     <Typography component="div" align="center" sx={{fontSize:['1em','1em','1.5em','2em']}}> | ||||
|                     <Typography component="div" align="center" sx={{fontSize:['1em','1em','1.5em']}}> | ||||
|                           Home | ||||
|                     </Typography> | ||||
|                   </Link> | ||||
|  | ||||
| @ -48,13 +48,13 @@ function ButtonLink(props) { | ||||
| export default function TournamentBar(props) { | ||||
|     const { tournamentId } = useParams(); | ||||
|     return ( | ||||
|         <Paper sx={{width: ["90vw",], fontSize:['1rem','1rem','1.5rem','2rem'], margin: "1.5% auto"}} component={Stack} direction="column" justifyContent="center" alignItems="center">  | ||||
|         <Paper sx={{width: ["90vw",], fontSize:['1rem','1rem','1.5rem'], margin: "1.5% auto"}} component={Stack} direction="column" justifyContent="center" alignItems="center">  | ||||
|           <Stack direction="row" paddingTop={'0.5%'} sx={{fontSize:['1rem','1rem','1.5rem','2rem'], margin:'1.5%'}} spacing={2}> | ||||
|             <ButtonLink targetPath="" tournamentId={tournamentId} activeTitle={props.pageTitle} title="View Tournament" viewTournament={props.viewTournament}/> | ||||
|             <ButtonLink targetPath="/manage" tournamentId={tournamentId} activeTitle={props.pageTitle} title="Edit Tournament" /> | ||||
|             <ButtonLink targetPath="/teams" tournamentId={tournamentId} activeTitle={props.pageTitle} title="Manage Teams" /> | ||||
|           </Stack> | ||||
|           <Stack direction="row" paddingBottom={'0.5%'}> | ||||
|           <Stack direction="row" paddingBottom={'0.5%'} component={Stack}> | ||||
|             <ClipboardButton clipboardContent={"https://discord.gg/asura"} name="Discord Invite Link" /> | ||||
|             <ClipboardButton clipboardContent={"https://asura.feal.no/tournament/" + tournamentId} name="Tournament Link" /> | ||||
|           </Stack> | ||||
|  | ||||
| @ -43,14 +43,16 @@ app.use(require('express-log-url')); | ||||
| // #region frontend
 | ||||
| 
 | ||||
| // Serve static files from the React app
 | ||||
| app.use('/', express.static(path.join(__dirname, 'clientbuild'))); | ||||
| app.use('/login', express.static(path.join(__dirname, 'clientbuild', 'index.html'))); | ||||
| app.use('/history', express.static(path.join(__dirname, 'clientbuild', 'index.html'))); | ||||
| app.use('/admins', express.static(path.join(__dirname, 'clientbuild', 'index.html'))); | ||||
| app.use('/profile', express.static(path.join(__dirname, 'clientbuild', 'index.html'))); | ||||
| app.use('/tournament/*', express.static(path.join(__dirname, 'clientbuild', 'index.html'))); | ||||
| app.use('/static', express.static(path.join(__dirname, 'clientbuild/static'))); | ||||
| app.use('/static/*', express.static(path.join(__dirname, 'clientbuild/static'))); | ||||
| const indexhtmlPath = path.join(process.env.CLIENT_BUILD_DIR, "index.html"); | ||||
| const staticPath = path.join(process.env.CLIENT_BUILD_DIR, "static"); | ||||
| app.use('/', express.static(process.env.CLIENT_BUILD_DIR)); | ||||
| app.use('/login', express.static(indexhtmlPath)); | ||||
| app.use('/history', express.static(indexhtmlPath)); | ||||
| app.use('/admins', express.static(indexhtmlPath)); | ||||
| app.use('/profile', express.static(indexhtmlPath)); | ||||
| app.use('/tournament/*', express.static(indexhtmlPath)); | ||||
| app.use('/static', express.static(staticPath)); | ||||
| app.use('/static/*', express.static(staticPath)); | ||||
| // #endregion
 | ||||
| 
 | ||||
| // #region PASSPORT / OAUTH
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user