diff --git a/env-example b/env-example
index 41ab5ca..fd5771f 100644
--- a/env-example
+++ b/env-example
@@ -1 +1,2 @@
-EVENT_API_BASE_URL=https://studentersamfundet.no
\ No newline at end of file
+EVENT_API_URL=https://studentersamfundet.no
+DUSKEN_API_URL=https://galtinn.neuf.no
\ No newline at end of file
diff --git a/package.json b/package.json
index 9de2405..c4c5b9d 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"react-navigation": "^1.0.0-beta.11",
"react-redux": "^5.0.5",
"redux": "^3.7.2",
+ "redux-logger": "^3.0.6",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
diff --git a/src/App.js b/src/App.js
index d5c3b3a..df9d998 100644
--- a/src/App.js
+++ b/src/App.js
@@ -2,10 +2,11 @@ import Dusken from "./Dusken";
import React, {Component} from 'react';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
+import logger from 'redux-logger';
import thunk from 'redux-thunk';
import duskenApp from "./reducers";
-let store = createStore(duskenApp, applyMiddleware(thunk));
+let store = createStore(duskenApp, applyMiddleware(...[logger, thunk]));
export default class App extends Component {
render() {
diff --git a/src/Dusken.js b/src/Dusken.js
index 88a3a5c..9b6c015 100644
--- a/src/Dusken.js
+++ b/src/Dusken.js
@@ -7,9 +7,11 @@ import EventsScreen from "./screens/EventScreen";
import EventDetailsScreen from "./screens/EventDetailsScreen";
import AboutScreen from "./screens/AboutScreen";
import MembershipScreen from "./screens/MembershipScreen";
+import Login from "./modules/login/Login";
const tabBarRoutes = {
+ // Login: { screen: LoginScreen },
Events: { screen: EventsScreen },
Membership: { screen: MembershipScreen },
About: { screen: AboutScreen },
diff --git a/src/actions.js b/src/actions.js
index 4c42f0b..d909ca1 100644
--- a/src/actions.js
+++ b/src/actions.js
@@ -1,3 +1,5 @@
+import Config from 'react-native-config';
+
const LOGIN_REQUEST = 'LOGIN_REQUEST';
const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
const LOGIN_FAILURE = 'LOGIN_FAILURE';
@@ -20,10 +22,10 @@ function loginSuccess(username, token) {
}
}
-function loginFailure(errorMessage) {
+function loginFailure(loginError) {
return {
type: LOGIN_FAILURE,
- errorMessage
+ loginError
}
}
@@ -66,9 +68,9 @@ export {
export function requestLogin(username, password) {
return (dispatch) => {
// We are now logging in
- dispatch(loginRequest())
-
- return fetch('http://10.0.0.10:3000/auth/obtain-token/', {
+ dispatch(loginRequest());
+ const apiURL = Config.DUSKEN_API_URL;
+ return fetch(`${apiURL}/auth/obtain-token/`, {
method: 'POST',
headers: {
'Accept': 'application/json',
@@ -91,7 +93,8 @@ export function requestLogin(username, password) {
dispatch(loginSuccess(username, data.token))
},
data => {
- dispatch(loginFailure(data.error || 'Log in failed'))
+ console.log(data);
+ dispatch(loginFailure(data || {'non_field_errors': ['Kunne ikke logge inn, prøv igjen']}))
}
)
}
@@ -100,9 +103,10 @@ export function requestLogin(username, password) {
export function requestUserData(token) {
return (dispatch) => {
// We are now fetching user data
- dispatch(userDataRequest())
+ dispatch(userDataRequest());
- return fetch('http://10.0.0.10:3000/api/me/', {
+ const apiURL = Config.DUSKEN_API_URL;
+ return fetch(`${apiURL}/api/me/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
diff --git a/src/modules/events/EventListContainer.js b/src/modules/events/EventListContainer.js
index 87a3b02..6bcf938 100644
--- a/src/modules/events/EventListContainer.js
+++ b/src/modules/events/EventListContainer.js
@@ -2,9 +2,9 @@ import {connect} from "react-redux";
import EventList from "./EventList";
import React from 'react';
+import Config from 'react-native-config';
import moment from "moment";
import 'moment/locale/nb';
-import Config from 'react-native-config'
moment.locale('nb');
@@ -74,7 +74,7 @@ class EventListContainer extends React.Component {
fetchEvents() {
const { page } = this.state;
- const url = `${Config.EVENT_API_BASE_URL}/wp-json/wp/v2/events?page=${page}&future=1`;
+ const url = `${Config.EVENT_API_URL}/wp-json/wp/v2/events?page=${page}&future=1`;
this.setState({ loading: true });
fetch(url)
diff --git a/src/modules/login/Login.js b/src/modules/login/Login.js
index 7c15302..6f7d615 100644
--- a/src/modules/login/Login.js
+++ b/src/modules/login/Login.js
@@ -1,87 +1,104 @@
import React, { Component } from 'react';
-import {Button, Image, StyleSheet, Text, TextInput, View} from 'react-native';
-import { Spinner } from 'native-base';
-
-// import { login } from "../../actions";
+import {StyleSheet, View} from 'react-native';
+import { Container, Header, Content, Form, Item, Input, Label, Spinner, Button, Text as NBText, Icon} from 'native-base';
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
- isAuthenticated: false,
- isLoggingIn: false,
- errorMessage: null,
email: '',
password: ''
}
}
- componentWillReceiveProps(nextProps) {
- if(this.state.isAuthenticated !== nextProps.isAuthenticated) {
- this.setState({
- isAuthenticated: nextProps.isAuthenticated
- })
- if (nextProps.isAuthenticated) {
- this.onLogin();
- }
- }
- if(this.state.isLoggingIn !== nextProps.isLoggingIn) {
- this.setState({
- isLoggingIn: nextProps.isLoggingIn
- })
- }
- if(this.state.errorMessage !== nextProps.errorMessage) {
- this.setState({
- errorMessage: nextProps.errorMessage
- })
- }
- }
-
- render() {
- const pic = {
- uri: 'https://dusken.neuf.no/static/dist/images/logo.png'
- };
- return (
-
- Det Norske Studentersamfund
- Chateau Neuf
-
-
+
+ {
- this.refs.passwordInput.focus();
+ this.passwordInputEl._root.focus();
}}
/>
- ;
+ }
+
+ return -
+
+ {
+ this.passwordInputEl._root.focus();
+ }}
+ />
+
;
+ }
+
+ passwordInput() {
+ if(this.props.loginError && this.props.loginError.password) {
+ return -
+
+ { this.passwordInputEl = input; }}
onChangeText={this.handlePassword}
onSubmitEditing={this.onLoginPress}
/>
-
-
-
- {this.spinIfLoggingIn}
-
+
+ }
+ return -
+
+ { this.passwordInputEl = input; }}
+ onChangeText={this.handlePassword}
+ onSubmitEditing={this.onLoginPress}
+ />
+
+ }
+
+ render() {
+ return (
+
+
+
+
+
);
}
- spinIfLoggingIn = () => {
- if (this.state.isLoggingIn) {
- return
+ showError= () => {
+ if (this.props.loginError) {
+ const err = this.props.loginError.non_field_errors;
+ let errorFormatted = err ? err[0] : 'Feil brukernavn eller passord, prøv igjen...';
+ // TODO: Format these and highlight error fields
+ return {errorFormatted}
}
- }
+ else {
+ return
+ }
+ };
+
+ showSpinner = () => {
+ if (this.props.isLoggingIn) {
+ return
+ }
+ };
handleEmail = (text) => {
this.setState({ email: text })
@@ -95,30 +112,28 @@ export default class Login extends Component {
this.props.requestLogin(this.state.email, this.state.password)
};
- onLogin = () => {
- this.props.onLogin();
- }
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
+ backgroundColor: 'white'
},
input: {
width: 320,
fontSize: 20,
height: 52,
},
- button: {
- marginTop: 20,
- padding: 10,
- width: 240,
+ loginButton: {
+ marginVertical: 16,
+ marginHorizontal: 16
},
- text: {
- fontSize: 18,
- fontWeight: 'bold'
+ errorBox: {
+ marginVertical: 16,
+ },
+ errorMessage: {
+ textAlign: 'center',
+ color: 'red',
}
});
\ No newline at end of file
diff --git a/src/modules/login/LoginContainer.js b/src/modules/login/LoginContainer.js
index 94f22af..55f61cb 100644
--- a/src/modules/login/LoginContainer.js
+++ b/src/modules/login/LoginContainer.js
@@ -1,13 +1,42 @@
+import React, {Component} from 'react';
import {connect} from "react-redux";
-import { bindActionCreators } from "redux";
import Login from "./Login";
-import { requestLogin } from "../../actions";
+import {requestLogin} from "../../actions";
+
+class LoginContainer extends Component {
+ constructor(state) {
+ super(state);
+ this.state = {
+ isAuthenticated: false,
+ isLoggingIn: false,
+ loginError: null,
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (this.state.isAuthenticated !== nextProps.isAuthenticated) {
+ if (nextProps.isAuthenticated) {
+ this.props.onLogin();
+ }
+ }
+ if (this.state.isLoggingIn !== nextProps.isLoggingIn) {
+ this.setState({isLoggingIn: nextProps.isLoggingIn})
+ }
+ if (this.state.loginError !== nextProps.loginError) {
+ this.setState({loginError: nextProps.loginError})
+ }
+ }
+
+ render() {
+ return
+ }
+}
export default connect(
- (state) => ({
- isAuthenticated: state.isAuthenticated,
- isLoggingIn: state.isLoggingIn,
- errorMessage: state.errorMessage,
- }),
- { requestLogin }
-)(Login);
+ (state) => ({
+ isAuthenticated: state.isAuthenticated,
+ isLoggingIn: state.isLoggingIn,
+ loginError: state.loginError,
+ }),
+ {requestLogin}
+)(LoginContainer);
diff --git a/src/modules/membership/Membership.js b/src/modules/membership/Membership.js
index 53dca0c..2a6f6d8 100644
--- a/src/modules/membership/Membership.js
+++ b/src/modules/membership/Membership.js
@@ -30,8 +30,8 @@ export default class Membership extends Component {
};
onPurchasePress() {
- // FIXME: Move this to process.env.DUSKEN_URL and use babel thing to do search replace
- Linking.openURL('https://medlem.neuf.no');
+ // FIXME: Move this to .env as DUSKEN_URL
+ Linking.openURL('https://galtinn.neuf.no');
};
onLoginPress = () => {
diff --git a/src/modules/membership/MembershipContainer.js b/src/modules/membership/MembershipContainer.js
index 979ca82..51ef01e 100644
--- a/src/modules/membership/MembershipContainer.js
+++ b/src/modules/membership/MembershipContainer.js
@@ -26,7 +26,7 @@ class MembershipContainer extends React.Component {
this.setState({isAuthenticated: nextProps.isAuthenticated})
}
if(this.state.userToken !== nextProps.userToken) {
- this.setState({userToken: nextProps.userToken})
+ this.setState({userToken: nextProps.userToken});
this.fetchUser();
}
if(this.state.user !== nextProps.user) {
@@ -37,11 +37,11 @@ class MembershipContainer extends React.Component {
fetchUser = () => {
if (!this.state.userToken) { return; }
this.props.requestUserData(this.state.userToken)
- }
+ };
onLoginPress = () => {
this.props.onLoginPress();
- }
+ };
render() {
if (this.state.user) {
diff --git a/src/reducers.js b/src/reducers.js
index e2539bd..9a7f84a 100644
--- a/src/reducers.js
+++ b/src/reducers.js
@@ -14,19 +14,21 @@ const initialState = {
isFetchingUserData: false,
userToken: null,
user: null,
+ loginError: null,
};
export default function duskenApp(state = initialState, action) {
switch (action.type) {
case LOGIN_REQUEST:
return Object.assign({}, state, {
- isLoggingIn: true
+ isLoggingIn: true,
+ loginError: null,
});
case LOGIN_FAILURE:
return Object.assign({}, state, {
isLoggingIn: false,
- errorMessage: action.errorMessage
+ loginError: action.loginError
});
case LOGIN_SUCCESS:
@@ -37,7 +39,7 @@ export default function duskenApp(state = initialState, action) {
});
case LOGOUT:
- return initialState
+ return initialState;
case USER_DATA_REQUEST:
return Object.assign({}, state, {
diff --git a/yarn.lock b/yarn.lock
index 7be9140..5100f45 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1377,6 +1377,10 @@ decamelize@^1.0.0, decamelize@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+deep-diff@^0.3.5:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84"
+
deep-extend@~0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
@@ -3705,6 +3709,12 @@ rebound@^0.0.13:
version "0.0.13"
resolved "https://registry.yarnpkg.com/rebound/-/rebound-0.0.13.tgz#4a225254caf7da756797b19c5817bf7a7941fac1"
+redux-logger@^3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf"
+ dependencies:
+ deep-diff "^0.3.5"
+
redux-thunk@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5"