diff --git a/.env b/.env
new file mode 100644
index 0000000..21685c1
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+GOOGLE_API_KEY=AIzaSyCrL-O319wNJK8kk8J_JAYsWgu6yo5YsDI
+REACT_APP_API_BASE_PATH=http://localhost:3500
+REACT_APP_AUTH0_CLIENT_ID=3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK
+REACT_APP_AUTH0_CLIENT_DOMAIN=dronetest.auth0.com
+REACT_APP_SOCKET_URL=http://localhost:3500
diff --git a/.env.example b/.env.example
index 4a42b68..3830cb2 100644
--- a/.env.example
+++ b/.env.example
@@ -1,5 +1,5 @@
-REACT_APP_API_BASE_PATH=https://kb-dsp-server.herokuapp.com
-REACT_APP_SOCKET_URL=https://kb-dsp-server.herokuapp.com
-REACT_APP_AUTH0_CLIEND_ID=3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK
-REACT_APP_AUTH0_DOMAIN=dronetest.auth0.com
-REACT_APP_GOOGLE_API_KEY=AIzaSyCR3jfBdv9prCBYBOf-fPUDhjPP4K05YjE
+GOOGLE_API_KEY=AIzaSyCrL-O319wNJK8kk8J_JAYsWgu6yo5YsDI
+REACT_APP_API_BASE_PATH=http://localhost:3500
+REACT_APP_AUTH0_CLIENT_ID=3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK
+REACT_APP_AUTH0_CLIENT_DOMAIN=dronetest.auth0.com
+REACT_APP_SOCKET_URL=http://localhost:3500
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 20c36db..e043f42 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,3 @@ node_modules
dist
coverage
.tmp
-/.env
diff --git a/README.md b/README.md
index f8cfdec..6389d32 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,24 @@ See Guild https://github.com/lorenwest/node-config/wiki/Configuration-Files
|`REACT_APP_AUTH0_DOMAIN`| The React app auth0 domain`|
Environment variables will be loaded from the .env file during build. Create the .env file based on the provided env.example
+### Auth0 setup
+- Create an account on auth0.
+- Click on clients in left side menu, it will redirect you to client page. Click on CREATE CLIENT button
+ to create a new client.
+- Copy the client id and client domain and export them as environment variables.
+- Add `http://localhost:3000` as Allowed callback url's in client settings.
+
+### Add social connections
+
+### Facebook social connection
+- To add facebook social connection to auth0, you have to create a facebook app.
+ Go to facebook [developers](https://developers.facebook.com/apps) and create a new app.
+- Copy the app secret and app id to auth0 social connections facebook tab.
+- You have to setup the oauth2 callback in app oauth settings.
+- For more information visit auth0 [docs](https://auth0.com/docs/connections/social/facebook)
+
+### Google social connection
+- For more information on how to connect google oauth2 client, visit official [docs](https://auth0.com/docs/connections/social/google)
## Install dependencies
`npm i`
diff --git a/config/default.js b/config/default.js
index f1bbbf3..d35b608 100644
--- a/config/default.js
+++ b/config/default.js
@@ -1,6 +1,6 @@
/* eslint-disable import/no-commonjs */
/**
- * Main config file
+ * Main config file for the server which is hosting the reat app
*/
module.exports = {
// below env variables are NOT visible in frontend
diff --git a/src/api/User.js b/src/api/User.js
index 70c1728..53466dc 100644
--- a/src/api/User.js
+++ b/src/api/User.js
@@ -24,7 +24,6 @@ class UserApi {
login(email, password) {
const url = `${this.basePath}/api/v1/login`;
-
return reqwest({
url,
method: 'post',
@@ -40,7 +39,7 @@ class UserApi {
});
}
- register(name, email, password) {
+ register(firstName, lastName, email, password) {
const url = `${this.basePath}/api/v1/register`;
return reqwest({
url,
@@ -48,15 +47,15 @@ class UserApi {
type: 'json',
contentType: 'application/json',
data: JSON.stringify({
- firstName: name,
- lastName: name,
+ firstName,
+ lastName,
email,
phone: '1',
password,
})});
}
- registerSocialUser(name, email) {
+ registerSocialUser(name, email, token) {
const url = `${this.basePath}/api/v1/login/social`;
return reqwest({
@@ -64,6 +63,9 @@ class UserApi {
method: 'post',
type: 'json',
contentType: 'application/json',
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
data: JSON.stringify({
name,
email,
diff --git a/src/components/AdminHeader/AdminHeader.jsx b/src/components/AdminHeader/AdminHeader.jsx
index a822dd2..32da13e 100644
--- a/src/components/AdminHeader/AdminHeader.jsx
+++ b/src/components/AdminHeader/AdminHeader.jsx
@@ -2,6 +2,8 @@ import React from 'react';
import CSSModules from 'react-css-modules';
import {Link} from 'react-router';
import styles from './AdminHeader.scss';
+import Dropdown from '../Dropdown';
+import Notification from '../Notification';
export const AdminHeader = () => (
);
diff --git a/src/components/AdminHeader/AdminHeader.scss b/src/components/AdminHeader/AdminHeader.scss
index dcabbf5..ca74fa9 100644
--- a/src/components/AdminHeader/AdminHeader.scss
+++ b/src/components/AdminHeader/AdminHeader.scss
@@ -10,4 +10,8 @@
composes: pages from '../Header/Header.scss'
}
+.notifications {
+ composes: notifications from '../Header/Header.scss'
+}
+
diff --git a/src/components/Dropdown/Dropdown.jsx b/src/components/Dropdown/Dropdown.jsx
index d0a020b..5412451 100644
--- a/src/components/Dropdown/Dropdown.jsx
+++ b/src/components/Dropdown/Dropdown.jsx
@@ -3,18 +3,17 @@ import CSSModules from 'react-css-modules';
import ReactDropdown, {DropdownTrigger, DropdownContent} from 'react-simple-dropdown';
import styles from './Dropdown.scss';
-export const Dropdown = ({title, children}) => (
-
-
- {title}
-
- {children}
-
-
-
+export const Dropdown = ({onRef, title, children}) => (
+
+ {title}
+
+ {children}
+
+
);
Dropdown.propTypes = {
+ onRef: PropTypes.func,
title: PropTypes.any.isRequired,
children: PropTypes.any.isRequired,
};
diff --git a/src/components/Dropdown/Dropdown.scss b/src/components/Dropdown/Dropdown.scss
index 9acd9d2..61de447 100644
--- a/src/components/Dropdown/Dropdown.scss
+++ b/src/components/Dropdown/Dropdown.scss
@@ -1,18 +1,12 @@
-.dropdown {
- :global {
- .dropdown {
- display: inline-block;
- }
-
-
- .dropdown--active .dropdown__content {
- display: block;
- }
+:global {
+ .dropdown {
+ display: inline-block;
+ }
+ .dropdown--active .dropdown__content {
+ display: block;
}
}
-
-
.content {
display: none;
position: absolute;
diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.jsx
index 5467cd4..55e9742 100644
--- a/src/components/Header/Header.jsx
+++ b/src/components/Header/Header.jsx
@@ -8,64 +8,86 @@ import Dropdown from '../Dropdown';
import Notification from '../Notification';
import styles from './Header.scss';
-export const Header = ({
+/**
+ * TODO: This component cries: 'REFACTOR ME!'
+ * Seriously, it is such a mess now, should be split into separate sub-components!
+ */
+
+export function Header({
location, selectedCategory, categories, user, notifications,
- routes, handleNotification, toggleNotif, loggedUser,
-}) => (
+ handleNotification, logoutAction, toggleNotif, loggedUser,
+}) {
+ // Holds a reference to the function which hides the user dropdown (Profile,
+ // Logout, etc.).
+ let hideUserDropdown;
-
+ );
+}
Header.propTypes = {
- routes: PropTypes.any.isRequired,
+ // routes: PropTypes.any.isRequired,
location: PropTypes.string.isRequired,
selectedCategory: PropTypes.string.isRequired,
categories: PropTypes.array.isRequired,
notifications: PropTypes.array.isRequired,
user: PropTypes.object.isRequired,
handleNotification: PropTypes.func,
+ logoutAction: PropTypes.func.isRequired,
toggleNotif: PropTypes.bool,
loggedUser: PropTypes.bool,
};
diff --git a/src/components/MapHistory/MapHistory.scss b/src/components/MapHistory/MapHistory.scss
index 317e61e..dfffff0 100644
--- a/src/components/MapHistory/MapHistory.scss
+++ b/src/components/MapHistory/MapHistory.scss
@@ -24,7 +24,7 @@
left:0;
right:0;
margin:0 auto;
- width:520px;
+ width:85%;
height: 80px;
background-color: #FFF;
.slider{
diff --git a/src/components/TextField/TextField.scss b/src/components/TextField/TextField.scss
index 46a04ab..56f5f52 100644
--- a/src/components/TextField/TextField.scss
+++ b/src/components/TextField/TextField.scss
@@ -2,6 +2,7 @@
width: 100%;
border: 1px solid #ebebeb;
+ input[type="password"],
input[type="text"] {
width: 100%;
padding: 0 10px;
diff --git a/src/config/index.js b/src/config/index.js
index c6b575d..23bf78c 100644
--- a/src/config/index.js
+++ b/src/config/index.js
@@ -1,23 +1,16 @@
+/* eslint-disable import/no-commonjs */
/**
- * Copyright (c) 2016 Topcoder Inc, All rights reserved.
+ * Main config file for the react app
*/
-
-/**
- * Webapp configuration
- *
- * @author TCSCODER
- * @version 1.0.0
- */
-
-const config = {
+module.exports = {
api: {
basePath: process.env.REACT_APP_API_BASE_PATH || 'http://localhost:3500',
},
socket: {
url: process.env.REACT_APP_SOCKET_URL || 'http://localhost:3500',
},
- AUTH0_CLIEND_ID: process.env.REACT_APP_AUTH0_CLIEND_ID || '3CGKzjS2nVSqHxHHE64RhvvKY6e0TYpK',
- AUTH0_DOMAIN: process.env.REACT_APP_AUTH0_DOMAIN || 'dronetest.auth0.com',
-};
+ AUTH0_CLIENT_ID: process.env.REACT_APP_AUTH0_CLIENT_ID || 'h7p6V93Shau3SSvqGrl6V4xrATlkrVGm',
+ AUTH0_CLIENT_DOMAIN: process.env.REACT_APP_AUTH0_CLIENT_DOMAIN || 'spanhawk.auth0.com',
+ AUTH0_CALLBACK: 'http://localhost:3000',
-export default config;
+};
diff --git a/src/containers/HeaderContainer.js b/src/containers/HeaderContainer.js
index 9128459..a9a2110 100644
--- a/src/containers/HeaderContainer.js
+++ b/src/containers/HeaderContainer.js
@@ -1,12 +1,17 @@
import Header from 'components/Header';
import {asyncConnect} from 'redux-connect';
-import {toggleNotification, loginAction} from '../store/modules/global';
+import {actions, toggleNotification, logoutAction} from '../store/modules/global';
const resolve = [{
promise: () => Promise.resolve(),
}];
-const mapState = (state) => state.global;
+const mapState = (state) => ({...state.global});
+
+/*
+ TODO: This is not used anymore, should be checked if this is safe to remove
+ (i.e. if the toggleNotification and loginAction actions are part of
+ the acetions object, injected into the asyncConnect call below).
const mapDispatchToProps = (dispatch) => ({
handleNotification: (value) => {
@@ -14,6 +19,6 @@ const mapDispatchToProps = (dispatch) => ({
},
handleLogin: (userObj) => dispatch(loginAction(userObj)),
});
+*/
-export default asyncConnect(resolve, mapState, mapDispatchToProps)(Header);
-
+export default asyncConnect(resolve, mapState, {...actions, logoutAction})(Header);
diff --git a/src/routes/Home/components/LoginModal/LoginModal.jsx b/src/routes/Home/components/LoginModal/LoginModal.jsx
index 5bd807e..eb7799c 100644
--- a/src/routes/Home/components/LoginModal/LoginModal.jsx
+++ b/src/routes/Home/components/LoginModal/LoginModal.jsx
@@ -7,6 +7,12 @@ import Button from 'components/Button';
import Checkbox from 'components/Checkbox';
import TextField from 'components/TextField';
import styles from './LoginModal.scss';
+import APIService from '../../../../services/APIService';
+import {toastr} from 'react-redux-toastr';
+import {defaultAuth0Service} from '../../../../services/AuthService';
+
+const EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
+
/*
* customStyles
*/
@@ -50,10 +56,11 @@ FormField.propTypes = {
*/
class LogInModal extends React.Component {
- constructor() {
- super();
+ constructor(props) {
+ super(props);
this.state = {
modalLoginIsOpen: false,
+ showForgetPassword: false,
};
}
@@ -62,28 +69,60 @@ class LogInModal extends React.Component {
}
closeLoginModal() {
- this.setState({modalLoginIsOpen: false});
+ this.setState({modalLoginIsOpen: false, showForgetPassword: false});
}
login() {
this.setState({modalLoginIsOpen: true});
}
- handleLogin(handleLoggedIn, loggedUser) {
- handleLoggedIn();
- const _self = this;
- setTimeout(() => {
- handleLoggedIn();
- if (loggedUser) {
- _self.setState({modalLoginIsOpen: false});
- _self.setState({modalSignupIsOpen: false});
+ forgetPassword() {
+ this.setState({showForgetPassword: true});
+ }
+
+ /**
+ * Login using google social network,
+ * this method internally uses auth0 service
+ */
+ googleLogin() {
+ defaultAuth0Service.login({connection: 'google-oauth2'}, (error) => {
+ if (error) {
+ const message = error.message || 'something went wrong, please try again';
+ toastr.error(message);
}
- }, 100);
+ });
}
- render() {
- const {handleSubmit, fields, handleLoggedIn, loggedUser, hasError, errorText} = this.props;
+ /**
+ * Login using facebook social network,
+ * this method internally uses auth0 service
+ */
+ facebookLogin() {
+ defaultAuth0Service.login({connection: 'facebook'}, (error) => {
+ if (error) {
+ const message = error.message || 'something went wrong, please try again';
+ toastr.error(message);
+ }
+ });
+ }
+
+ /**
+ * This method is invoked when reset password request is submitted
+ */
+ handleForgetPassword(data) {
+ APIService.forgotPassword({email: data.emailUp}).then(() => {
+ toastr.success('', 'Reset password link emailed to your email address');
+ this.closeLoginModal();
+ }).catch((reason) => {
+ const message = reason.response.body.error || 'something went wrong, please try again';
+ toastr.error(message);
+ this.closeLoginModal();
+ });
+ }
+ render() {
+ const _self = this;
+ const {handleSubmit, fields, hasError, errorText} = this.props;
return (
@@ -100,81 +139,98 @@ class LogInModal extends React.Component {
-
Login to Your Account
+ {this.state.showForgetPassword === false &&
Login to Your Account
}
+ {this.state.showForgetPassword === true &&
Reset forgotten password
}
+ {this.state.showForgetPassword === false &&
+