Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • wimma-lab-2019/overflow/ehasa-frontend
1 result
Show changes
Commits on Source (4)
node_modules
npm-debug.log
\ No newline at end of file
FROM node:10.15.3-alpine as build
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package*.json ./
RUN npm install
RUN npm install react-scripts@3.0.1 -g
COPY . .
RUN npm run build
# production environment
FROM nginx:1.16.0-alpine
COPY --from=build /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
{
"name": "leaflet-test",
"name": "ehasa-frontend",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
......@@ -1310,6 +1310,20 @@
"@babel/types": "^7.3.0"
}
},
"@types/cookie": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz",
"integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow=="
},
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/istanbul-lib-coverage": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz",
......@@ -1337,11 +1351,30 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.3.tgz",
"integrity": "sha512-zkOxCS/fA+3SsdA+9Yun0iANxzhQRiNwTvJSr6N95JhuJ/x27z9G2URx1Jpt3zYFfCGUXZGL5UDxt5eyLE7wgw=="
},
"@types/object-assign": {
"version": "4.0.30",
"resolved": "https://registry.npmjs.org/@types/object-assign/-/object-assign-4.0.30.tgz",
"integrity": "sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI="
},
"@types/prop-types": {
"version": "15.7.1",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.1.tgz",
"integrity": "sha512-CFzn9idOEpHrgdw8JsoTkaDDyRWk1jrzIV8djzcgpq0y9tG4B4lFT+Nxh52DVpDXV+n4+NPNv7M1Dj5uMp6XFg=="
},
"@types/q": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw=="
},
"@types/react": {
"version": "16.8.19",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.19.tgz",
"integrity": "sha512-QzEzjrd1zFzY9cDlbIiFvdr+YUmefuuRYrPxmkwG0UQv5XF35gFIi7a95m1bNVcFU0VimxSZ5QVGSiBmlggQXQ==",
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"
}
},
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
......@@ -3881,6 +3914,11 @@
"cssom": "0.3.x"
}
},
"csstype": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.5.tgz",
"integrity": "sha512-JsTaiksRsel5n7XwqPAfB0l3TFKdpjW/kgAELf9vrb5adGA7UCPLajKK5s3nFrcFm3Rkyp/Qkgl73ENc1UY3cA=="
},
"cyclist": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
......@@ -9994,6 +10032,16 @@
"whatwg-fetch": "3.0.0"
}
},
"react-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.0.0.tgz",
"integrity": "sha512-om/HB4MBHt4k+moR8Mb5h1kmKxcmOxK2U6aaQZ8Y+f+igICcE5bpng7yCiAo3kKN0btFpzvQ70XnpONOC0xkdA==",
"requires": {
"@types/hoist-non-react-statics": "^3.0.1",
"hoist-non-react-statics": "^3.0.0",
"universal-cookie": "^4.0.0"
}
},
"react-dev-utils": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.0.1.tgz",
......@@ -11881,6 +11929,24 @@
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz",
"integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ=="
},
"universal-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.0.tgz",
"integrity": "sha512-6JVx+3oGPjslGqFhQ8YSIBHmYTx8HbyAEH++2/b6SKNXsbsdQ7lU7wRG2bYcRB5JVCz8GYgQ+Ixew91hn3Dy9w==",
"requires": {
"@types/cookie": "^0.3.1",
"@types/object-assign": "^4.0.30",
"cookie": "^0.3.1",
"object-assign": "^4.1.0"
},
"dependencies": {
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
}
}
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
......
......@@ -5,9 +5,11 @@
"dependencies": {
"leaflet": "^1.5.1",
"react": "^16.8.6",
"react-cookie": "^4.0.0",
"react-dom": "^16.8.6",
"react-leaflet": "^2.3.0",
"react-scripts": "3.0.1"
"react-scripts": "3.0.1",
"universal-cookie": "^4.0.0"
},
"scripts": {
"start": "react-scripts start",
......
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.hidden {
display: none;
}
/* UserMap */
.map {
position: absolute;
margin-top: 50px;
height: 95vh;
width: 100vw;
}
/* Header */
div.header {
position: absolute;
top: 0;
height: 50px;
width: 100%;
background: white;
z-index: 1000;
}
div.header button {
transition-property: background-color;
transition-duration: 0.5s;
transition-timing-function: ease;
background-color: #279fd9;
color: white;
font-weight: bold;
border: 0px;
padding: 0.5em;
margin: 0em 1em;
width: 10%;
height: 100%;
font-size: 18px;
float: right;
}
div.header button:hover {
background-color: darkblue;
cursor: pointer;
}
/* Login&RegisterForm */
div.fade-main {
position: fixed;
top: 0;
z-index: 1000;
height: 100vh;
width: 100vw;
}
\ No newline at end of file
margin: auto;
text-align: center;
background-color: rgba(0, 0, 0, 0.85);
}
div.sticky {
position: fixed;
top: 0px;
right: 0px;
height: 100px;
width: 100px;
margin-right: 150px;
}
.close {
position: fixed;
color: #f1f1f1;
height: 85px;
font-size: 100px;
font-weight: bold;
transition: transform 0.4s ease-in-out;
line-height: 70%;
}
.close:hover,
.close:focus {
color: #bbb;
text-decoration: none;
cursor: pointer;
transform: rotate(90deg);
}
div.login {
height: 60vh;
width: 40vw;
margin: auto;
margin-top: 5%;
padding-top: 25px;
}
div.login h1 {
color: rgb(0, 200, 255);
margin-bottom: 0.5em;
font-size: 3em;
}
div.login h2 {
color: rgb(255, 0, 0);
margin-top: 2em;
font-size: 1.5em;
}
div.login input {
background: none;
border: none;
outline: none;
width: 60%;
padding: 12px 20px;
margin-bottom: 1em;
display: inline-block;
box-sizing: border-box;
font-size: 180%;
color: white;
border-bottom: 3px solid rgb(0, 200, 255);
}
div.login button {
transition-property: background-color;
transition-duration: 0.5s;
transition-timing-function: ease;
background-color: #279fd9;
color: white;
font-weight: bold;
border: 0px;
padding: 0.5em;
margin: 0em 2em;
width: 20%;
font-size: 20px;
}
div.login button:hover {
background-color: darkblue;
cursor: pointer;
}
import React, { Component } from 'react';
import styles from './App.css';
import UserMap from './components/UserMap.js'
import styles from './App.css';
import UserMap from './components/UserMap';
import Header from './components/Header';
class App extends Component {
constructor() {
......@@ -11,13 +11,17 @@ class App extends Component {
this.state = {
lat: 62.2416479,
lng: 25.7597186,
zoom: 13,
}
zoom: 13
};
}
render(){
const initialPosition = [this.state.lat, this.state.lng];
render() {
const initialPosition = [this.state.lat, this.state.lng];
return (
<UserMap position={initialPosition} zoom={this.state.zoom}/>
<div>
<UserMap position={initialPosition} zoom={this.state.zoom} />,
<Header />
</div>
);
}
}
......
import React from 'react';
import LoginForm from './LoginForm';
import RegisterForm from './RegisterForm';
class Header extends React.Component {
state = {
login: false,
register: false,
username: null,
token: null
};
// toggles the login/register view
toggleView = view => {
this.setState(prevState => {
return {
[view]: view === 'login' ? !prevState.login : !prevState.register
};
});
};
handleState = data => {
sessionStorage.setItem('name', data.name);
sessionStorage.setItem('token', data.token);
this.setState({ username: data.name, token: data.token });
};
handleLogout = () => {
this.setState({ username: null, token: null });
sessionStorage.removeItem('token');
};
// verifies the token (if it exists) on element mount with backend server
componentDidMount() {
let token = sessionStorage.getItem('token');
if (token) {
fetch('http://localhost:5000/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();
}
},
error => {
console.log(error);
}
);
}
}
render() {
return (
<div>
<div className='header'>
{!this.state.username && (
<button onClick={() => this.toggleView('register')}>
register
</button>
)}
{!this.state.username && (
<button onClick={() => this.toggleView('login')}>login</button>
)}
{this.state.username && (
<button onClick={this.handleLogout}>logout</button>
)}
{this.state.username && <button>{this.state.username}</button>}
</div>
{this.state.register && (
<RegisterForm
view='register'
handleState={this.handleState}
toggleView={this.toggleView}
/>
)}
{this.state.login && (
<LoginForm
view='login'
handleState={this.handleState}
toggleView={this.toggleView}
/>
)}
</div>
);
}
}
export default Header;
import React from 'react';
export class LoginForm extends React.Component {
constructor(props) {
super(props);
this.state = {
errorMsg: '',
username: '',
password: ''
};
}
handleError = error => {
this.setState({ errorMsg: error });
};
handleChange = e => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
// show/hide this form
handleView = e => {
this.props.toggleView(this.props.view);
};
// remove login view with ESC
handleEsc = e => {
if (e.keyCode === 27) {
this.handleView();
}
};
handleLogin = e => {
const name = this.state.username;
const password = this.state.password;
e.preventDefault();
// Send login info to the server
fetch('http://localhost:5000/user/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
password: password
})
})
.then(res => res.json())
.then(
result => {
if (result.name) {
this.props.handleState(result);
this.handleView();
} else {
this.handleError(result.errorResponse.message);
}
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
error => {
console.log(error);
}
);
};
componentDidMount() {
document.addEventListener('keyup', this.handleEsc);
}
componentWillUnmount() {
document.removeEventListener('keyup', this.handleEsc);
}
render() {
return (
<div className='fade-main'>
<div className='sticky'>
<span className='close' onClick={this.handleView}>
×
</span>
</div>
<div className='login'>
<form onSubmit={this.handleLogin}>
<h1>demo login</h1>
<br />
<input
placeholder='Enter Username'
name='username'
value={this.state.username}
onChange={this.handleChange}
required
/>
<br />
<input
placeholder='Enter password'
type='password'
name='password'
value={this.state.password}
onChange={this.handleChange}
required
/>
<br />
<button type='submit'>login</button>
<h2>{this.state.errorMsg}</h2>
</form>
</div>
</div>
);
}
}
export default LoginForm;
import React from 'react';
export class RegisterForm extends React.Component {
constructor(props) {
super(props);
this.state = {
errorMsg: '',
username: '',
password: '',
password2: ''
};
}
// shows error messages associated with registering
handleError = error => {
this.setState({ errorMsg: error });
};
// updates state with input values
handleChange = e => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
// show/hide this form
handleView = e => {
this.props.toggleView(this.props.view);
};
// remove register view with ESC
handleEsc = e => {
if (e.keyCode === 27) {
this.handleView();
}
};
handleRegister = e => {
const name = this.state.username;
const password = this.state.password;
e.preventDefault();
if (this.state.password !== this.state.password2) {
this.handleError('Passwords do not match');
} else {
// Send register info to the server
fetch('http://localhost:5000/user/register', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
password: password
})
})
.then(res => res.json())
.then(
result => {
if (result.name) {
this.props.handleState(result);
this.handleView();
} else {
this.handleError(result.errorResponse.message);
}
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
error => {
console.log(error);
}
);
}
};
componentDidMount() {
document.addEventListener('keyup', this.handleEsc);
}
componentWillUnmount() {
document.removeEventListener('keyup', this.handleEsc);
}
render() {
return (
<div className='fade-main'>
<div className='sticky'>
<span className='close' onClick={this.handleView}>
×
</span>
</div>
<div className='login'>
<form onSubmit={this.handleRegister}>
<h1>register new user</h1>
<br />
<input
placeholder='Enter Username'
name='username'
value={this.state.username}
onChange={this.handleChange}
required
/>
<br />
<input
placeholder='Enter password'
type='password'
name='password'
value={this.state.password}
onChange={this.handleChange}
required
/>
<br />
<input
placeholder='Verify password'
type='password'
name='password2'
value={this.state.password2}
onChange={this.handleChange}
required
/>
<br />
<button type='submit'>register</button>
<h2>{this.state.errorMsg}</h2>
</form>
</div>
</div>
);
}
}
export default RegisterForm;
import React, {Component} from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet'
import React, { Component } from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
class UserMap extends Component{
render(){
class UserMap extends Component {
render() {
return (
<Map className="map" center={this.props.position} zoom={this.props.zoom}>
<TileLayer
attribution='Maanmittauslaitoksen kartta'
url=" https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg"
/>
<Marker position={this.props.position}>
<Popup>
Se on perjantai, my dudes <br />
</Popup>
</Marker>
</Map>)
<Map className='map' center={this.props.position} zoom={this.props.zoom}>
<TileLayer
attribution='Maanmittauslaitoksen kartta'
url=' https://tiles.kartat.kapsi.fi/taustakartta/{z}/{x}/{y}.jpg'
/>
<Marker position={this.props.position}>
<Popup>
Se on perjantai, my dudes <br />
</Popup>
</Marker>
</Map>
);
}
}
export default UserMap;
\ No newline at end of file
export default UserMap;
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
......@@ -11,13 +11,11 @@ import * as serviceWorker from './serviceWorker';
// make the default marker work with react (dunno if this is a weird hack)
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
ReactDOM.render(<App />, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
......