diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..75d1a71c9ec995f3ab6e2f4f3ad2933e576be245 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +REACT_APP_URL = "http://localhost:5000" \ No newline at end of file diff --git a/src/components/EditGameForm.js b/src/components/EditGameForm.js index 9158f27231a3d5402f62de0717c77cf87a377854..ac56b351fd779e57de73dfe363637af7518d754e 100644 --- a/src/components/EditGameForm.js +++ b/src/components/EditGameForm.js @@ -1,27 +1,24 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { - Map, - TileLayer -} from 'react-leaflet' +import { Map, TileLayer } from 'react-leaflet'; -export class EditGameForm extends React.Component{ - constructor(props){ +export class EditGameForm extends React.Component { + constructor(props) { super(props); this.state = { - gamename: "", - description: "", - startDate: "", - startTime: "", - endDate: "", - endTime: "", + gamename: '', + description: '', + startDate: '', + startTime: '', + endDate: '', + endTime: '', zoom: 13, mapCenter: { lat: 62.2416479, lng: 25.7597186 } - } + }; this.handleMapDrag = this.handleMapDrag.bind(this); } @@ -51,33 +48,34 @@ export class EditGameForm extends React.Component{ this.setState({ mapCenter: e.target.getCenter() }); - } + }; handleMapScroll = e => { this.setState({ zoom: e.target.getZoom() }); - } + }; handleGameSave = e => { - let startDate = this.state.startDate + "T" + this.state.startTime + ":00.000Z"; - let endDate = this.state.endDate + "T" + this.state.endTime + ":00.000Z"; + let startDate = + this.state.startDate + 'T' + this.state.startTime + ':00.000Z'; + let endDate = this.state.endDate + 'T' + this.state.endTime + ':00.000Z'; const gameObject = { name: this.state.gamename, desc: this.state.description, - map: "", + map: '', startdate: startDate, enddate: endDate, center: this.state.mapCenter - } + }; e.preventDefault(); let token = sessionStorage.getItem('token'); // Send Game info to the server - fetch('http://localhost:5000/game/' + this.props.gameId, { + fetch(`${process.env.REACT_APP_URL}/game/edit/` + this.props.gameId, { method: 'PUT', headers: { Authorization: 'Bearer ' + token, @@ -85,7 +83,8 @@ export class EditGameForm extends React.Component{ 'Content-Type': 'application/json' }, body: JSON.stringify(gameObject) - }).then(res => res.json()) + }) + .then(res => res.json()) .then(result => { alert(result.message); this.handleView(); @@ -102,34 +101,38 @@ export class EditGameForm extends React.Component{ document.removeEventListener('keyup', this.handleEsc); } - getGameInfo(gameId){ - fetch('http://localhost:5000/game/' + gameId) + getGameInfo(gameId) { + fetch(`${process.env.REACT_APP_URL}/game/` + gameId) .then(response => response.json()) .then(json => this.handleGameInfo(json)) .catch(error => console.log(error)); } - handleGameInfo(json){ + handleGameInfo(json) { this.setState({ gamename: json.name, description: json.desc, - startDate: json.startdate.substring(0,10), - startTime: json.startdate.substring(11,16), - endDate: json.enddate.substring(0,10), - endTime: json.enddate.substring(11,16), + startDate: json.startdate.substring(0, 10), + startTime: json.startdate.substring(11, 16), + endDate: json.enddate.substring(0, 10), + endTime: json.enddate.substring(11, 16), zoom: 13, mapCenter: { lat: json.center.lat, lng: json.center.lng } - }) + }); } render() { - return ReactDOM.createPortal ( + return ReactDOM.createPortal( <div className='fade-main'> <div className='sticky'> - <span className='close' onClick={this.handleView}> + <span + id='closeEditGameFormX' + className='close' + onClick={this.handleView} + > × </span> </div> @@ -142,7 +145,7 @@ export class EditGameForm extends React.Component{ name='gamename' value={this.state.gamename} onChange={this.handleChange} - required + id='editGameNameInput' /> <br /> <input @@ -151,7 +154,7 @@ export class EditGameForm extends React.Component{ name='description' value={this.state.description} onChange={this.handleChange} - required + id='editGameDescriptionInput' /> <br /> <label className=''>Start:</label> @@ -161,7 +164,7 @@ export class EditGameForm extends React.Component{ name='startDate' value={this.state.startDate} onChange={this.handleChange} - required + id='editGameDateStartInput' /> <input className='formTime' @@ -169,7 +172,7 @@ export class EditGameForm extends React.Component{ name='startTime' value={this.state.startTime} onChange={this.handleChange} - required + rid='editGameTimeStartInput' /> <br /> <label className=''>End:</label> @@ -180,7 +183,7 @@ export class EditGameForm extends React.Component{ value={this.state.endDate} onChange={this.handleChange} min={this.state.startDate} - required + id='editGameDateEndInput' /> <input className='formTime' @@ -188,26 +191,36 @@ export class EditGameForm extends React.Component{ name='endTime' value={this.state.endTime} onChange={this.handleChange} - required + id='editGameTimeEndInput' /> <br /> <label>Map things</label> <br /> - <Map className='' center={[this.state.mapCenter.lat, this.state.mapCenter.lng]} zoom={this.state.zoom} style={{height: '400px', width: '400px'} } onmoveend={this.handleMapDrag} onzoomend={this.handleMapScroll}> + <Map + id='editGameCenterMap' + className='' + center={[this.state.mapCenter.lat, this.state.mapCenter.lng]} + zoom={this.state.zoom} + style={{ height: '400px', width: '400px' }} + onmoveend={this.handleMapDrag} + onzoomend={this.handleMapScroll} + > <TileLayer attribution='Maanmittauslaitoksen kartta' url=' https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg' /> </Map> <br /> - <button type='submit'>Save changes</button> + <button id='editGameSubmitButton' type='submit'> + Save changes + </button> <h2>{this.state.errorMsg}</h2> </form> </div> - </div> - ,document.getElementById('form') + </div>, + document.getElementById('form') ); } } -export default EditGameForm; \ No newline at end of file +export default EditGameForm; diff --git a/src/components/GameList.js b/src/components/GameList.js index 6b68d64393a4c25713bea74fa511ff0b0f92558b..e1b0fa1d69aa8307eaa160a3c90ce845e6611fb1 100644 --- a/src/components/GameList.js +++ b/src/components/GameList.js @@ -2,13 +2,13 @@ import React, { Fragment } from 'react'; import EditGameForm from './EditGameForm'; class GameList extends React.Component { - constructor(props){ + constructor(props) { super(props); this.state = { games: [], selectedGame: null, editForm: false - } + }; this.toggleView = this.toggleView.bind(this); } @@ -17,39 +17,42 @@ class GameList extends React.Component { this.getGames(); } - getGames(){ - fetch('http://localhost:5000/game/listgames') - .then(response => response.json()) - .then(games => { - this.setState({ - games: games, - selectedGame: games !== null && games[0].id + getGames() { + fetch(`${process.env.REACT_APP_URL}/game/listgames`) + .then(response => response.json()) + .then(games => { + this.setState({ + games: games, + selectedGame: games !== null && games[0].id + }); + }) + .catch(error => { + console.log(error); }); - }) - .catch(error => {console.log(error);}) } - handleChange = (e) =>{ + handleChange = e => { this.setState({ selectedGame: e.target.value }); - } + }; - handleEditClick = (e) => { - if(this.state.selectedGame === null){alert('No game selected');} - else{ + handleEditClick = e => { + if (this.state.selectedGame === null) { + alert('No game selected'); + } else { this.setState({ editForm: true }); } - } + }; - toggleView = (e) =>{ + toggleView = e => { this.setState({ editForm: !this.state.editForm }); this.getGames(); - } + }; render() { let items = []; @@ -57,23 +60,32 @@ class GameList extends React.Component { for (let i = 0; i < this.state.games.length; i++) { const element = this.state.games[i]; items.push( - <option key={element.id} value={element.id}>{element.name}</option> + <option key={element.id} value={element.id}> + {element.name} + </option> ); } return ( <Fragment> <label>Game: </label> - <select onChange={this.handleChange}> + <select id='changeActiveGameList' onChange={this.handleChange}> {items} - </select> - {sessionStorage.getItem('token') - && <button onClick={this.handleEditClick}>Edit game</button>} - {(this.state.editForm && this.state.selectedGame !== null) - && <EditGameForm gameId={this.state.selectedGame} toggleView={this.toggleView}/>} + </select> + {sessionStorage.getItem('token') && ( + <button id='editGameButton' onClick={this.handleEditClick}> + Edit game + </button> + )} + {this.state.editForm && this.state.selectedGame !== null && ( + <EditGameForm + gameId={this.state.selectedGame} + toggleView={this.toggleView} + /> + )} </Fragment> ); } } - -export default GameList; \ No newline at end of file + +export default GameList; diff --git a/src/components/Header.js b/src/components/Header.js index 6eff8b4572bd8e4404d9a167fbb556756ac6bf40..c3b0d558801e1b219339a977f5b504bde9d581b0 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -7,7 +7,7 @@ import NewGameForm from './NewGameForm'; class Header extends React.Component { state = { - form: "", // Popup form (login, register etc.) + form: '', // Popup form (login, register etc.) username: null, token: null }; @@ -34,29 +34,29 @@ class Header extends React.Component { componentDidMount() { let token = sessionStorage.getItem('token'); if (token) { - fetch('http://localhost:5000/user/verify', { + fetch(`${process.env.REACT_APP_URL}/user/verify`, { headers: { Authorization: 'Bearer ' + token } }) - .then(res => res.json()) - .then( - result => { - // if token is still valid, login user - if (result === true) { - this.setState({ - username: sessionStorage.getItem('name'), - token: token - }); - // logout user if token has expired / is invalid - } else { - this.handleLogout(); + .then(res => res.json()) + .then( + result => { + // if token is still valid, login user + if (result === true) { + this.setState({ + username: sessionStorage.getItem('name'), + token: token + }); + // logout user if token has expired / is invalid + } else { + this.handleLogout(); + } + }, + error => { + console.log(error); } - }, - error => { - console.log(error); - } - ); + ); } } @@ -65,21 +65,35 @@ class Header extends React.Component { <div> <div className='header'> {!this.state.username && ( - <button onClick={() => this.toggleView('register')}> + <button + id='registerButton' + onClick={() => this.toggleView('register')} + > register </button> )} {!this.state.username && ( - <button onClick={() => this.toggleView('login')}>login</button> + <button id='loginButton' onClick={() => this.toggleView('login')}> + login + </button> )} {this.state.username && ( - <button onClick={() => this.toggleView('newgame')}>New Game</button> + <button + id='newGameButton' + onClick={() => this.toggleView('newgame')} + > + New Game + </button> )} {this.state.username && ( - <button onClick={this.handleLogout}>logout</button> + <button id='logoutButton' onClick={this.handleLogout}> + logout + </button> )} {this.state.username && <button>{this.state.username}</button>} - <button onClick={this.props.handleLayerChange}>change layer</button> + <button id='changeLayerButton' onClick={this.props.handleLayerChange}> + change layer + </button> <GameList /> </div> {this.state.form === 'register' && ( diff --git a/src/components/LoginForm.js b/src/components/LoginForm.js index 7893bb8c967509d8589d31665e1f1a57c4b34fcb..7dca5868027d18c729ad3cbb43913ec3edd63f24 100644 --- a/src/components/LoginForm.js +++ b/src/components/LoginForm.js @@ -38,7 +38,7 @@ export class LoginForm extends React.Component { e.preventDefault(); // Send login info to the server - fetch('http://localhost:5000/user/login', { + fetch(`${process.env.REACT_APP_URL}/user/login`, { method: 'POST', headers: { Accept: 'application/json', @@ -56,7 +56,7 @@ export class LoginForm extends React.Component { this.props.handleState(result); this.handleView(); } else { - this.handleError(result.errorResponse.message); + this.handleError(result.message); } }, // Note: it's important to handle errors here @@ -80,7 +80,11 @@ export class LoginForm extends React.Component { return ( <div className='fade-main'> <div className='sticky'> - <span className='close' onClick={this.handleView}> + <span + id='closeLoginFormX' + className='close' + onClick={this.handleView} + > × </span> </div> @@ -93,7 +97,7 @@ export class LoginForm extends React.Component { name='username' value={this.state.username} onChange={this.handleChange} - required + id='loginUsernameInput' /> <br /> <input @@ -102,10 +106,12 @@ export class LoginForm extends React.Component { name='password' value={this.state.password} onChange={this.handleChange} - required + id='loginPasswordInput' /> <br /> - <button type='submit'>login</button> + <button id='submitLoginButton' type='submit'> + login + </button> <h2>{this.state.errorMsg}</h2> </form> </div> diff --git a/src/components/NewGameForm.js b/src/components/NewGameForm.js index 5f133377d5a4b415a394038b0442b71cc928f93b..e681b0c725908fb6f1a5a6b3f31083eda31ba7a7 100644 --- a/src/components/NewGameForm.js +++ b/src/components/NewGameForm.js @@ -1,28 +1,25 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { - Map, - TileLayer -} from 'react-leaflet' +import { Map, TileLayer } from 'react-leaflet'; -export class NewGameForm extends React.Component{ - constructor(props){ +export class NewGameForm extends React.Component { + constructor(props) { super(props); this.state = { - gamename: "", - description: "", - startDate: "", - startTime: "", - endDate: "", - endTime: "", + gamename: '', + description: '', + startDate: '', + startTime: '', + endDate: '', + endTime: '', passwords: [], zoom: 13, mapCenter: { lat: 62.2416479, lng: 25.7597186 } - } + }; this.handleMapDrag = this.handleMapDrag.bind(this); } @@ -52,34 +49,35 @@ export class NewGameForm extends React.Component{ this.setState({ mapCenter: e.target.getCenter() }); - } + }; handleMapScroll = e => { this.setState({ zoom: e.target.getZoom() }); - } + }; handleGameCreation = e => { - let startDate = this.state.startDate + "T" + this.state.startTime + ":00.000Z"; - let endDate = this.state.endDate + "T" + this.state.endTime + ":00.000Z"; + let startDate = + this.state.startDate + 'T' + this.state.startTime + ':00.000Z'; + let endDate = this.state.endDate + 'T' + this.state.endTime + ':00.000Z'; const gameObject = { name: this.state.gamename, desc: this.state.description, - map: "", + map: '', startdate: startDate, enddate: endDate, passwords: [this.state.password], center: this.state.mapCenter - } + }; e.preventDefault(); let token = sessionStorage.getItem('token'); // Send Game info to the server - fetch('http://localhost:5000/game/new', { + fetch(`${process.env.REACT_APP_URL}/game/new`, { method: 'POST', headers: { Authorization: 'Bearer ' + token, @@ -87,7 +85,8 @@ export class NewGameForm extends React.Component{ 'Content-Type': 'application/json' }, body: JSON.stringify(gameObject) - }).then(res => res.json()) + }) + .then(res => res.json()) .then(result => { this.handleView(); }) @@ -103,10 +102,14 @@ export class NewGameForm extends React.Component{ } render() { - return ReactDOM.createPortal ( + return ReactDOM.createPortal( <div className='fade-main'> <div className='sticky'> - <span className='close' onClick={this.handleView}> + <span + id='closeNewGameFormX' + className='close' + onClick={this.handleView} + > × </span> </div> @@ -119,7 +122,7 @@ export class NewGameForm extends React.Component{ name='gamename' value={this.state.gamename} onChange={this.handleChange} - required + id='newGameNameInput' /> <br /> <input @@ -128,7 +131,7 @@ export class NewGameForm extends React.Component{ name='description' value={this.state.description} onChange={this.handleChange} - required + id='newGameDescriptionInput' /> <br /> <label className=''>Start:</label> @@ -138,14 +141,14 @@ export class NewGameForm extends React.Component{ name='startDate' value={this.state.startDate} onChange={this.handleChange} - required + id='newGameDateStartInput' /> <input className='formTime' type='time' name='startTime' onChange={this.handleChange} - required + id='newGameTimeStartInput' /> <br /> <label className=''>End:</label> @@ -156,33 +159,43 @@ export class NewGameForm extends React.Component{ value={this.state.endDate} onChange={this.handleChange} min={this.state.startDate} - required + id='newGameDateEndInput' /> <input className='formTime' type='time' name='endTime' onChange={this.handleChange} - required + id='newGameTimeEndInput' /> <br /> <label>Map things</label> <br /> - <Map className='' center={[this.state.mapCenter.lat, this.state.mapCenter.lng]} zoom={this.state.zoom} style={{height: '400px', width: '400px'} } onmoveend={this.handleMapDrag} onzoomend={this.handleMapScroll}> + <Map + id='newGameCenterMap' + className='' + center={[this.state.mapCenter.lat, this.state.mapCenter.lng]} + zoom={this.state.zoom} + style={{ height: '400px', width: '400px' }} + onmoveend={this.handleMapDrag} + onzoomend={this.handleMapScroll} + > <TileLayer attribution='Maanmittauslaitoksen kartta' url=' https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg' /> </Map> <br /> - <button type='submit'>Submit</button> + <button id='newGameSubmitButton' type='submit'> + Submit + </button> <h2>{this.state.errorMsg}</h2> </form> </div> - </div> - ,document.getElementById('form') + </div>, + document.getElementById('form') ); } } -export default NewGameForm; \ No newline at end of file +export default NewGameForm; diff --git a/src/components/RegisterForm.js b/src/components/RegisterForm.js index f0ead02cce19af21937d132a54443f593d8ad9d4..a2706f12668bdfe6306cd7b2c9d6c0d405da08f1 100644 --- a/src/components/RegisterForm.js +++ b/src/components/RegisterForm.js @@ -44,7 +44,7 @@ export class RegisterForm extends React.Component { this.handleError('Passwords do not match'); } else { // Send register info to the server - fetch('http://localhost:5000/user/register', { + fetch(`${process.env.REACT_APP_URL}/user/register`, { method: 'POST', headers: { Accept: 'application/json', @@ -62,7 +62,7 @@ export class RegisterForm extends React.Component { this.props.handleState(result); this.handleView(); } else { - this.handleError(result.errorResponse.message); + this.handleError(result.message); } }, // Note: it's important to handle errors here @@ -87,7 +87,11 @@ export class RegisterForm extends React.Component { return ( <div className='fade-main'> <div className='sticky'> - <span className='close' onClick={this.handleView}> + <span + id='closeRegisterFormX' + className='close' + onClick={this.handleView} + > × </span> </div> @@ -100,7 +104,7 @@ export class RegisterForm extends React.Component { name='username' value={this.state.username} onChange={this.handleChange} - required + id='registerUsernameInput' /> <br /> <input @@ -109,7 +113,7 @@ export class RegisterForm extends React.Component { name='password' value={this.state.password} onChange={this.handleChange} - required + id='registerPasswordInput' /> <br /> <input @@ -118,10 +122,12 @@ export class RegisterForm extends React.Component { name='password2' value={this.state.password2} onChange={this.handleChange} - required + id='registerPasswordVerifyInput' /> <br /> - <button type='submit'>register</button> + <button id='submitRegisterButton' type='submit'> + register + </button> <h2>{this.state.errorMsg}</h2> </form> </div>