diff --git a/src/App.css b/src/App.css index b3004ac40734d1b05cd893b254948d77559da7dc..4b1a814b09da13bed06a89bfedef6cfa3f883355 100644 --- a/src/App.css +++ b/src/App.css @@ -13,7 +13,7 @@ body { /* UserMap */ .map { position: absolute; - margin-top: 50px; + /* margin-top: 50px; */ height: 95vh; width: 100vw; } @@ -233,3 +233,17 @@ div.login button:hover { display: flex; flex-direction: column; } + +.notification-popup { + position: absolute; + z-index: 1010; +} + +.notification-popup.warning { + background-color: yellow; + color: black; +} + +.notification-popup.alert { + background-color: red; +} diff --git a/src/components/GameView.js b/src/components/GameView.js index fab8c7924692b479409ab99fc6ca70198417d3a5..8f1859ef62276669867d227c899f01cb94df50a4 100644 --- a/src/components/GameView.js +++ b/src/components/GameView.js @@ -64,7 +64,6 @@ export default class GameView extends React.Component { handleLeaveFaction = e => { let token = sessionStorage.getItem("token"); - let error = false; fetch( `${process.env.REACT_APP_API_URL}/faction/leave/${ this.state.gameInfo.id @@ -78,7 +77,6 @@ export default class GameView extends React.Component { ) .then(res => { if (!res.ok) { - error = true; } return res.json(); }) @@ -91,7 +89,6 @@ export default class GameView extends React.Component { // setting the socket signal automatically fires shouldComponentUpdate function where socketSignal prop is present // setting socketSignal to null immediately after to avoid multiple database fetches getSocketSignal = data => { - console.log(data); this.setState( { socketSignal: data @@ -112,7 +109,6 @@ export default class GameView extends React.Component { render() { const initialPosition = [this.state.lat, this.state.lng]; - return ( <div> <Link to="/"> @@ -186,13 +182,11 @@ export default class GameView extends React.Component { zoom={this.state.zoom} mapUrl={this.state.mapUrl} currentGameId={this.state.gameInfo.id} - socketSignal={ - this.state.socketSignal !== null - ? this.state.socketSignal - : null - } - /> - <NotificationPopup socketSignal={this.state.socketSignal} /> + socketSignal={this.state.socketSignal} + > + <NotificationPopup socketSignal={this.state.socketSignal} /> + </UserMap> + {this.state.form === "edit" && ( <EditGameForm gameId={this.state.gameInfo.id} @@ -221,6 +215,12 @@ export default class GameView extends React.Component { gameId={this.state.gameInfo.id} toggleView={() => this.setState({ form: "" })} socket={this.state.socket} + role={this.state.role} + gameState={ + this.state.gameInfo !== undefined + ? this.state.gameInfo.state + : "" + } /> )} </div> diff --git a/src/components/NotificationCard.js b/src/components/NotificationCard.js new file mode 100644 index 0000000000000000000000000000000000000000..cf49d28f285a8f6f662007b947b1d7a42cc682fc --- /dev/null +++ b/src/components/NotificationCard.js @@ -0,0 +1,11 @@ +import React from "react"; + +export default class NotificationCard extends React.Component { + render() { + return ( + <div> + {this.props.notification.type} : {this.props.notification.message} + </div> + ); + } +} diff --git a/src/components/NotificationPopup.js b/src/components/NotificationPopup.js index 99f50cb253383da8f2e891745f2a08fd0e8707fd..2d41ed57ee8988b93577a981c75f50b3afb6c220 100644 --- a/src/components/NotificationPopup.js +++ b/src/components/NotificationPopup.js @@ -1,16 +1,57 @@ import React from "react"; export default class NotificationPopup extends React.Component { + state = { + lastNotification: null, + visible: true + }; + componentDidUpdate(prevProps, prevState) { - if (prevProps.socketSignal === "alert") { - console.log("alert"); - } - if (prevProps.socketSignal === "note") { - console.log("note"); + if ( + prevProps.socketSignal !== null && + prevProps.socketSignal !== this.state.lastNotification + ) { + if (prevProps.socketSignal.type === "alert") { + this.setState({ + lastNotification: prevProps.socketSignal, + visible: true + }); + } + if (prevProps.socketSignal.type === "note") { + this.setState({ + lastNotification: prevProps.socketSignal, + visible: true + }); + } } } render() { + if (this.state.lastNotification !== null && this.state.visible) { + return ( + <div + className={ + this.state.lastNotification.type === "alert" + ? "notification-popup alert" + : "notification-popup warning" + } + > + <button + onClick={() => { + this.setState({ visible: false }); + }} + > + Close + </button> + <br /> + <label> + {this.state.lastNotification.type === "alert" ? "ALERT" : "Note"} + </label> + <p>{this.state.lastNotification.message}</p> + </div> + ); + } + return false; } } diff --git a/src/components/NotificationView.js b/src/components/NotificationView.js index 8d261a15fe1969e6a522050e6cfda3cc5cc70de7..d7538066f6ac3058ec27c6cd2716383de6eed215 100644 --- a/src/components/NotificationView.js +++ b/src/components/NotificationView.js @@ -1,9 +1,11 @@ import React from "react"; +import NotificationCard from "./NotificationCard"; export default class NotificationView extends React.Component { state = { notifications: [], - notificationInput: "" + notificationInput: "", + notificationTypeInput: "note" }; componentDidMount() { @@ -19,39 +21,59 @@ export default class NotificationView extends React.Component { }) .then(res => res.json()) .then(res => { - console.log(res); - //this.setState({ notifications: res }); + this.setState({ notifications: res.reverse() }); }); } handleSend = e => { e.preventDefault(); - console.log(this.props.socket); - - this.props.socket.emit(this.props.gameId, { - type: "alert", - message: "asd" - }); + if (this.state.notificationInput === "") { + alert("notification message can't be empty"); + } else { + this.props.socket.emit("game-info", { + type: this.state.notificationTypeInput, + message: this.state.notificationInput, + game: this.props.gameId + }); + this.getNotifications(this.props.gameId); + this.setState({ notificationInput: "" }); + } }; render() { + let notifications = this.state.notifications.map(notification => ( + <NotificationCard key={notification.id} notification={notification} /> + )); + return ( <div className="fade-main"> <button onClick={() => this.props.toggleView()}>Close</button> <div> - <form onSubmit={this.handleSend}> - <input - type="text" - value={this.state.notificationInput} - onChange={e => - this.setState({ notificationInput: e.target.value }) - } - placeholder="Notification text..." - /> - <button type="submit">Send Notification</button> - </form> + {this.props.role === "admin" && this.props.gameState !== "ENDED" && ( + <form onSubmit={this.handleSend}> + <select + value={this.state.notificationTypeInput} + onChange={e => + this.setState({ notificationTypeInput: e.target.value }) + } + > + <option value="note">Note</option> + <option value="alert">Alert</option> + </select> + <input + type="text" + value={this.state.notificationInput} + onChange={e => + this.setState({ notificationInput: e.target.value }) + } + placeholder="Notification message..." + /> + <button type="submit">Send Notification</button> + </form> + )} </div> + {notifications} </div> ); } diff --git a/src/components/Socket.js b/src/components/Socket.js index 438b278725bacaa83ef5669dca40a233be7f7467..22940ce13df8453a1c60d20338daa7bb623b6971 100644 --- a/src/components/Socket.js +++ b/src/components/Socket.js @@ -17,7 +17,7 @@ export default class ClientSocket extends React.Component { // initiate the socket on component mount async componentWillMount() { - console.log("hi socket"); + // console.log("hi socket"); // need to explicitly update drawings and trackings when gameID first becomes available if (this.props.gameId !== null) { await this.props.getSocketSignal("drawing-update"); @@ -38,7 +38,7 @@ export default class ClientSocket extends React.Component { // disconnect the socket on component dismount componentWillUnmount() { - console.log("bye socket"); + // console.log("bye socket"); this.state.sock.disconnect(); } @@ -47,7 +47,6 @@ export default class ClientSocket extends React.Component { // set the socket to listen gameId-thread socket.on(this.props.gameId, data => { - console.log("on " + data); this.props.getSocketSignal(data); // check socket update type this.setState({ update: data.type }); diff --git a/src/components/UserMap.js b/src/components/UserMap.js index c5347fa78df07b4092296702fae1e70ee1704f8f..2a3397abd4bc3fbcb1280eef6820906541cc35d4 100644 --- a/src/components/UserMap.js +++ b/src/components/UserMap.js @@ -149,38 +149,41 @@ class UserMap extends Component { render() { return ( - <Map - className="map" - center={this.props.position} - zoom={this.props.zoom} - minZoom="7" - maxZoom="17" - zoomControl={false} - > - <TileLayer - attribution='© <a href="https://www.maanmittauslaitos.fi/">Maanmittauslaitos</a>' - url={this.props.mapUrl} - /> - <ZoomControl position="topright" /> - <DrawTools - position={this.props.position} - sendGeoJSON={this.sendGeoJSON} - geoJSONLayer={this.state.geoJSONLayer} - currentGameId={this.props.currentGameId} - /> - {this.state.ownLat !== null && ( - <Marker position={[this.state.ownLat, this.state.ownLng]}> - <Popup> - User's real position. - <br /> - </Popup> - </Marker> - )} - <Player - currentGameId={this.props.currentGameId} - socketSignal={this.props.socketSignal} - /> - </Map> + <div> + <Map + className="map" + center={this.props.position} + zoom={this.props.zoom} + minZoom="7" + maxZoom="17" + zoomControl={false} + > + <TileLayer + attribution='© <a href="https://www.maanmittauslaitos.fi/">Maanmittauslaitos</a>' + url={this.props.mapUrl} + /> + <ZoomControl position="topright" /> + <DrawTools + position={this.props.position} + sendGeoJSON={this.sendGeoJSON} + geoJSONLayer={this.state.geoJSONLayer} + currentGameId={this.props.currentGameId} + /> + {this.state.ownLat !== null && ( + <Marker position={[this.state.ownLat, this.state.ownLng]}> + <Popup> + User's real position. + <br /> + </Popup> + </Marker> + )} + <Player + currentGameId={this.props.currentGameId} + socketSignal={this.props.socketSignal} + /> + </Map> + {this.props.children} + </div> ); } }