forked from scorelab/Bassa-mobile
-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Guide
Gayashan Bombuwala edited this page Jul 29, 2018
·
5 revisions
Bassa-mobile directly depends on the Bassa-backend and you can't go beyond the Sign-In screen, if you haven't configured it properly.
Go through the following steps to configure it.
- Navigate to the
./app/constants folder
from theroot
folder and open the API.js file. - Replace the values of the following properties according to the configurations of your Bassa-backend.
const APIConstants = {`
`HOST_URL: 'http://10.0.3.2',`
`HOST_PORT: 5000,`
`KEY: '123456789',`
`};
** HOST_URL property can contain one of the following 3 values, depending on your device.**
10.0.3.2
10.0.2.2
obtain the IP of your computer using the ifconfig
command on Unix-like OS or ipconfig
command on Windows. (Computer and the device should be on the same network)
-
./app/actions/
- Redux actions that change the Redux store -
./app/components/
- Components that does't get connected with the Redux store (i.e. ActivityLoader component). -
./app/constants/
- Reusable constants related to the project (i.e. API constants). -
./app/containers/
- Containers/Components that gets connected with the Redux store (i.e. QuotaUsage component). -
./app/containers/CustomDrawer.js
- Drawer component used in the app. -
./app/helpers/
- Helper functions related to the project such as API request interceptors and common utility funtions -
./app/images/
- Static image files related to the project (i.e. App logo). -
./app/reducers/
- Redux reducers that handle state changes -
./app/containers/RootNavigator.js
- Navigation routes used in the app. -
./app/sagas/
- Redux sagas that perform async actions in the app (i.e. Setting the auth token to the API). -
./app/services/
- API calls that return Promises (i.e. signIn). -
./app/store/
- Redux store configurations. -
./app/styles/
- Common styles used in the app (i.e. Status bar color). -
./__tests__/
- Unit testing files.
Let's see how we can use the above mentioned directory structure, in order to develop the Sign-In workflow.
- Implement the draft Sign-In container and connect to the Redux store.
...
class SignIn {
...
}
export default connect(mapStateToProps, mapDispatchToProps)(SignIn);
...
- Define the navigation routes.
...
const AppNavigator = createStackNavigator({
...
SignIn: { screen: SignIn },
...
});
...
- Define the constants required for action types.
export const userActions = {
USER_SIGN_IN: 'USER_SIGN_IN',
AUTHENTICATE_USER_SUCCESS: 'AUTHENTICATE_USER_SUCCESS',
AUTHENTICATE_USER_FAIL: 'AUTHENTICATE_USER_FAIL',
};
- Define the Redux actions.
export const signIn = (username, password) => ({
type: userActions.USER_SIGN_IN,
payload: { user_name: username, password },
});
- Define the Redux reducer.
...
const initialState = {
currentUser: {
username: '',
isAdmin: false,
timestamp: null,
},
};
function userReducer(state = initialState, action) {
switch (action.type) {
case userActions.AUTHENTICATE_USER_SUCCESS:
return {
...state,
currentUser: {
...state.currentUser,
username: action.payload.username,
isAdmin: action.payload.isAdmin,
timestamp: action.payload.timestamp ? action.payload.timestamp : Date.now(),
},
};
default:
return state;
}
}
export default userReducer;
- Define the required API calls as a service.
import APIBuilder from '../helpers/APIBuilder';
import { prepareRequestBody } from '../helpers/utils';
const signIn = credentials => APIBuilder.API.post('/api/login', prepareRequestBody(credentials));
- Define a Redux Saga to handle async operations involved in the Sign-In workflow.
...
function* signInUser({ payload }) {
try {
const response = yield call(UserService.signIn, payload);
if (response.status === 200) {
yield call(KeychainService.setGenericPassword, payload.user_name, payload.password);
yield put(handleAuthSuccess({
username: payload.user_name,
isAdmin: Number(response.data.auth) === 0 ? true : false,
}));
yield put(setTokenToHeader(response.headers.token));
yield put(resetToMainDrawer());
}
}
...
}
...
export default function* userSaga() {
yield all([
takeEvery(userActions.USER_SIGN_IN, signInUser),
]);
}
- Complete the implementation of the SignIn container (component) with the help of the above defined artifacts.
- Write tests to validate the new code (i.e Snapshot testing, Unit testing).
...
describe('User Reducer', () => {
it('should return the initial state', () => {
expect(userReducer(undefined, {})).toEqual(
{
currentUser: {
username: '',
isAdmin: false,
timestamp: null,
},
}
)
});
...