Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backend] - Public/Private Ownership - Central UI Changes #1096

Open
wants to merge 12 commits into
base: drew-hart--backend-public-private
Choose a base branch
from
34 changes: 25 additions & 9 deletions central/src/components/GameCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,25 @@ import {
import MoreVertIcon from '@material-ui/icons/MoreVert';
import CCSS from './CCSS';
import RightOnPlaceHolder from '../images/RightOnPlaceholder.svg';
import { PublicPrivateType } from '@righton/networking';
export default function GameCard({
game,
index,
handleClick,
handleClose,
editHandler,
cloneHandler,
deleteHandler,
addquestion,
match,
isUserAuth,
onClick,
anchorEl,
activeIndex
activeIndex,
publicPrivateQueryType
}) {
const classes = useStyles();
const { id, title, description, cluster, domain, grade, standard, imageUrl } = game;
const { id, title, description, cluster, domain, grade, standard, imageUrl, owner } = game;
const questionCount = game?.questionTemplates.length || 0;
const history = useHistory();
return (
Expand All @@ -48,9 +51,16 @@ export default function GameCard({
</Typography>
</Grid>
</Grid>
<Typography className={classes.title} >
{title}
</Typography>
<>
<Typography className={classes.title} >
{title}
</Typography>
{ publicPrivateQueryType === PublicPrivateType.PUBLIC &&
<Typography className={classes.owner} >
Created by: {owner}
</Typography>
}
</>
<Typography className={classes.textSecondary} color="textSecondary" >
{description}
</Typography>
Expand All @@ -76,9 +86,9 @@ export default function GameCard({
onClose={handleClose}
onClick={(event) => { if (!match) event.stopPropagation(); }}
>
<MenuItem onClick={(event) => { history.push(`/gamemaker/${game.id}`); event.stopPropagation(); handleClose(); }}>Edit</MenuItem>
<MenuItem onClick={cloneHandler(game)}>Clone</MenuItem>
<MenuItem onClick={deleteHandler(game.id)}>Delete</MenuItem>
<MenuItem onClick={(event) => editHandler(game, event)}> Edit </MenuItem>
<MenuItem onClick={(event) => cloneHandler(game, event)}>Clone</MenuItem>
<MenuItem onClick={(event) => deleteHandler(game, event)}>Delete</MenuItem>
</Menu>
</Grid>
}
Expand Down Expand Up @@ -125,7 +135,13 @@ const useStyles = makeStyles(theme => ({
},
title: {
fontWeight: 700,
height: '80%',
lineHeight: '1.2',
color: '#384466',
textOverflow: 'ellipsis',
},
owner: {
fontWeight: 400,
height: '60%',
color: '#384466',
display: '-webkit-box',
WebkitBoxOrient: 'vertical',
Expand Down
57 changes: 48 additions & 9 deletions central/src/components/GameDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import LoadingIndicator from './LoadingIndicator';
import GameCard from './GameCard';
import InfiniteScroll from 'react-infinite-scroll-component';

export default function GameDashboard({ loading, nextToken, games, handleScrollDown, deleteGame, cloneGameTemplate, gameId, isUserAuth }) {
export default function GameDashboard({ checkGameOwner, loading, nextToken, publicPrivateQueryType, games, handleScrollDown, deleteGame, cloneGameTemplate, gameId, isUserAuth, setGameDetails }) {
const classes = useStyles();
const history = useHistory();
const match = useRouteMatch('/games/:gameIndex');
Expand All @@ -22,16 +22,53 @@ export default function GameDashboard({ loading, nextToken, games, handleScrollD
setAnchorEl(null);
setActiveIndex(null);
};
const cloneHandler = (game) => () => {
cloneGameTemplate(game);
handleClose();
const editHandler = async (game) => {
try {
const isOwner = await checkGameOwner(game);
if (isOwner){
setGameDetails(game);
history.push(`/gamemaker/${game.id}`);
handleClose();
} else {
handleClose();
alert('You do not have the required authorization to edit this game.');
}
}catch (error){
console.log(error);
}
};

const cloneHandler = async (game, event) => {
try {
const isOwner = await checkGameOwner(game);
if (isOwner){
cloneGameTemplate(game);
handleClose();
} else {
handleClose();
alert('You do not have the required authorization to clone this game.');
}
} catch (error){
console.log(error);
}
};
const deleteHandler = (id) => () => {
const confirmDelete = window.confirm('Are you sure you want to delete this game?');
if (confirmDelete) {
deleteGame(id);

const deleteHandler = async (game) => {
try {
const isOwner = await checkGameOwner(game);
if (isOwner){
const confirmDelete = window.confirm('Are you sure you want to delete this game?');
if (confirmDelete) {
deleteGame(game.id);
}
handleClose();
} else {
handleClose();
alert('You do not have the required authorization to delete this game.');
}
} catch (error) {
console.log(error);
}
handleClose();
};

const renderGames = (loading) => {
Expand Down Expand Up @@ -80,6 +117,7 @@ export default function GameDashboard({ loading, nextToken, games, handleScrollD
index={index}
handleClick={handleClick}
handleClose={handleClose}
editHandler={editHandler}
cloneHandler={cloneHandler}
deleteHandler={deleteHandler}
addquestion={addquestion}
Expand All @@ -88,6 +126,7 @@ export default function GameDashboard({ loading, nextToken, games, handleScrollD
anchorEl={anchorEl}
activeIndex={activeIndex}
onClick={() => history.push(`/games/${game.id}`)}
publicPrivateQueryType={publicPrivateQueryType}
/>
</Grid>
) :
Expand Down
4 changes: 2 additions & 2 deletions central/src/components/GameLaunch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const useStyles = makeStyles(theme => ({
},
}));

function GameLaunch({ loading, game, gameId, saveGame, deleteQuestion, handleDeleteGameTemplate, handleCloneGameTemplate, isUserAuth, handleDeleteGameQuestion }) {
function GameLaunch({ publicPrivateQueryType, loading, game, gameId, saveGame, deleteQuestion, handleDeleteGameTemplate, handleCloneGameTemplate, isUserAuth, handleDeleteGameQuestion }) {
useEffect(() => {
document.title = 'RightOn! | Game launcher';
return () => { document.title = 'RightOn! | Game management'; }
Expand Down Expand Up @@ -171,7 +171,7 @@ function GameLaunch({ loading, game, gameId, saveGame, deleteQuestion, handleDel
if (loading) return <Skeleton variant="rect" height={500} />;
const questions = game?.questionTemplates || [];
const questionCount = game?.questionTemplates.length || 0;
const LAUNCH_GAME_URL = `http://dev-host.rightoneducation.com/new/${game.id}`;
const LAUNCH_GAME_URL = `http://dev-host.rightoneducation.com/new/${publicPrivateQueryType}/${game.id}`;

return (
<Box className={classes.root}>
Expand Down
54 changes: 31 additions & 23 deletions central/src/components/GameMaker.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useState, useEffect } from 'react';
import { Route, Switch, useHistory } from 'react-router-dom';
import { makeStyles } from '@material-ui/core/styles';
import { Button, IconButton, Divider, Grid, MenuItem, TextField, Typography, Card, CardContent, Box } from '@material-ui/core';
import { Button, IconButton, Divider, Grid, MenuItem, TextField, Typography, Card, CardContent, Box, Radio } from '@material-ui/core';
import { Cancel } from '@material-ui/icons';
import { isNullOrUndefined } from '@righton/networking';
import { PublicPrivateType, isNullOrUndefined } from '@righton/networking';
import RightOnPlaceHolder from './../images/RightOnPlaceholder.svg';
import CCSS from './CCSS';
import GameCCSS from './GameMakerCCSS';
Expand All @@ -14,18 +14,6 @@ import SortByDropdown from './SortByDropdown';
import QuestionDashboard from './QuestionDashboard';
import { v4 as uuidv4 } from 'uuid';

// New "empty" game
const newGame = {
title: '',
description: '',
grade: '',
domain: '',
phaseOneTime: 180,
phaseTwoTime: 180,
imageUrl: '',
questionTemplates: [],
}

// Preset times
const times = [
{
Expand Down Expand Up @@ -53,9 +41,12 @@ const times = [
export default function GameMaker({
loading,
questions,
gameDetails,
setGameDetails,
game,
games,
handleQuestionBankClick,
handleCreateQuestionTemplateClick,
selectedQuestions,
setSelectedQuestions,
saveGameTemplate,
Expand All @@ -79,21 +70,15 @@ export default function GameMaker({
nextToken,
localQuestionTemplates,
setLocalQuestionTemplates,
publicPrivateQueryType,
handlePublicPrivateChange
}) {
useEffect(() => {
document.title = 'RightOn! | Game editor';
return () => { document.title = 'RightOn! | Game management'; }
}, []);
const classes = useStyles();
const history = useHistory();
const [gameDetails, setGameDetails] = useState(() => {
if (game) {
return { ...game };
}
else {
return {id: gameId, ...newGame};
}
});

const selectedQuestionTemplates = selectedQuestions.map(question => {
return {questionTemplate: question, gameQuestionId: null }
Expand Down Expand Up @@ -141,7 +126,9 @@ export default function GameMaker({
setSelectedQuestions([]);
setLocalQuestionTemplates([]);
gameDetails.questionTemplates = localQuestionTemplates;
gameDetails.id = gameId;
saveGameTemplate(game, gameDetails);
setGameDetails({});
event.preventDefault();
history.push('/');
};
Expand Down Expand Up @@ -245,6 +232,27 @@ export default function GameMaker({
<Grid container item xs={12} sm={4} justifyContent='center'>
{gameDetails.imageUrl ? <img src={gameDetails.imageUrl} alt="" width={'60%'} /> : <img src={RightOnPlaceHolder} alt="Placeholder" height={'275px'} />}
</Grid>
<Grid container item xs={12} sm={4} style={{display: 'flex', alignItems: 'center', gap: 10}}>
<Typography style={{ fontWeight: 200, fontSize: '1 rem', color: 'rgba(0,0,0,0.75)' }}> Game Type: </Typography>
<Box style={{ display: 'flex', justifyContainer: 'center', alignItems: 'center'}}>
<Typography style={{ fontWeight: 200, fontSize: '15px', color: 'rgba(0,0,0,0.75)' }}> Public </Typography>
<Radio
checked={publicPrivateQueryType === PublicPrivateType.PUBLIC}
value={PublicPrivateType.PUBLIC}
onChange={handlePublicPrivateChange}
color='default'
/>
</Box>
<Box style={{display: 'flex', justifyContainer: 'center', alignItems: 'center'}}>
<Typography style={{ fontWeight: 200, fontSize: '15px', color: 'rgba(0,0,0,0.75)'}}> Private </Typography>
<Radio
checked={publicPrivateQueryType === PublicPrivateType.PRIVATE}
value={PublicPrivateType.PRIVATE}
onChange={handlePublicPrivateChange}
color='default'
/>
</Box>
</Grid>
</Grid>
</Grid>

Expand Down Expand Up @@ -325,7 +333,7 @@ export default function GameMaker({
</Grid>

<Grid container item xs={6} justifyContent='center'>
<Button variant='contained' disableElevation className={classes.greenButton} onClick={() => history.push(`/gamemaker/${gameDetails.id}/questionmaker/${uuidv4()}`)}>
<Button variant='contained' disableElevation className={classes.greenButton} onClick={() => handleCreateQuestionTemplateClick(gameDetails)}>
Create Question
</Button>
</Grid>
Expand Down
Loading