diff --git a/src/routes/MyRequest/modules/MyRequest.js b/src/routes/MyRequest/modules/MyRequest.js
index 406f546..7fe4840 100644
--- a/src/routes/MyRequest/modules/MyRequest.js
+++ b/src/routes/MyRequest/modules/MyRequest.js
@@ -6,7 +6,9 @@ import { handleActions } from 'redux-actions';
export const sendRequest = (values) => new Promise((resolve) => {
+ /* eslint-disable no-alert */
alert(JSON.stringify(values, null, 2));
+ /* eslint-enable no-alert */
resolve();
});
diff --git a/src/routes/ServiceRequest/modules/ServiceRequest.js b/src/routes/ServiceRequest/modules/ServiceRequest.js
index df34dd0..10cdfeb 100644
--- a/src/routes/ServiceRequest/modules/ServiceRequest.js
+++ b/src/routes/ServiceRequest/modules/ServiceRequest.js
@@ -6,7 +6,9 @@ import { handleActions } from 'redux-actions';
export const sendRequest = (values) => new Promise((resolve) => {
+ /* eslint-disable no-alert */
alert(JSON.stringify(values, null, 2));
+ /* eslint-enable no-alert */
resolve();
});
diff --git a/src/routes/index.js b/src/routes/index.js
index 1068fb0..241d406 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -1,6 +1,8 @@
import CoreLayout from 'layouts/CoreLayout';
import ServiceRequestRoute from './ServiceRequest';
import DashboardRoute from './Dashboard';
+import MissionList from './MissionList';
+import MissionPlanner from './MissionPlanner';
import MyRequestRoute from './MyRequest';
export const createRoutes = (store) => ({
@@ -17,6 +19,8 @@ export const createRoutes = (store) => ({
childRoutes: [
ServiceRequestRoute(store),
DashboardRoute(store),
+ MissionList(store),
+ MissionPlanner(store),
MyRequestRoute(store),
],
});
diff --git a/src/services/APIService.js b/src/services/APIService.js
new file mode 100644
index 0000000..14272fe
--- /dev/null
+++ b/src/services/APIService.js
@@ -0,0 +1,103 @@
+import superagent from 'superagent';
+import superagentPromise from 'superagent-promise';
+import _ from 'lodash';
+import config from '../../config/default';
+
+const request = superagentPromise(superagent, Promise);
+
+/*
+ As there is no Authorization implemented in the project.
+ Here I've hardcoded automatic registering and authorization of a dumb user to make requests to the server.
+ This should be removed when real authorizatin is implemented.
+ */
+const testUser = {
+ firstName: 'test',
+ lastName: 'test',
+ email: 'kj2h34jh23424h2l34h324ljh1@khj4k234hl234hjl.com',
+ phone: '42',
+ password: 'qwerty',
+};
+
+const register = () => request
+ .post(`${config.API_BASE_PATH}/api/v1/register`)
+ .send(testUser)
+ .set('Content-Type', 'application/json')
+ .end();
+
+const authorize = () => request
+ .post(`${config.API_BASE_PATH}/api/v1/login`)
+ .set('Content-Type', 'application/json')
+ .send(_.pick(testUser, 'email', 'password'))
+ .end();
+
+const regAndAuth = () => authorize().then(
+ authorize,
+ () => register().then(authorize),
+);
+
+export default class APIService {
+ static fetchMissionList() {
+ return regAndAuth().then((authRes) => {
+ const accessToken = authRes.body.accessToken;
+
+ return request
+ .get(`${config.API_BASE_PATH}/api/v1/missions`)
+ .set('Authorization', `Bearer ${accessToken}`)
+ .end()
+ .then((res) => res.body.items.map((item) => ({
+ ...item,
+ downloadLink: `${config.API_BASE_PATH}/api/v1/missions/${item.id}/download?token=${accessToken}`,
+ })));
+ });
+ }
+
+ static getMission(id) {
+ return regAndAuth().then((authRes) => {
+ const accessToken = authRes.body.accessToken;
+
+ return request
+ .get(`${config.API_BASE_PATH}/api/v1/missions/${id}`)
+ .set('Authorization', `Bearer ${accessToken}`)
+ .end()
+ .then((res) => res.body);
+ });
+ }
+
+ static createMission(mission) {
+ return regAndAuth().then((authRes) => {
+ const accessToken = authRes.body.accessToken;
+
+ return request
+ .post(`${config.API_BASE_PATH}/api/v1/missions`)
+ .set('Authorization', `Bearer ${accessToken}`)
+ .send(mission)
+ .end()
+ .then((res) => res.body);
+ });
+ }
+
+ static updateMission(id, mission) {
+ return regAndAuth().then((authRes) => {
+ const accessToken = authRes.body.accessToken;
+
+ return request
+ .put(`${config.API_BASE_PATH}/api/v1/missions/${id}`)
+ .set('Authorization', `Bearer ${accessToken}`)
+ .send(mission)
+ .end()
+ .then((res) => res.body);
+ });
+ }
+
+ static deleteMission(id) {
+ return regAndAuth().then((authRes) => {
+ const accessToken = authRes.body.accessToken;
+
+ return request
+ .del(`${config.API_BASE_PATH}/api/v1/missions/${id}`)
+ .set('Authorization', `Bearer ${accessToken}`)
+ .end()
+ .then((res) => res.body);
+ });
+ }
+}
diff --git a/src/static/img/icon-waypoint-blue.png b/src/static/img/icon-waypoint-blue.png
new file mode 100644
index 0000000..b13347d
Binary files /dev/null and b/src/static/img/icon-waypoint-blue.png differ
diff --git a/src/store/reducers.js b/src/store/reducers.js
index c1533ea..da5018b 100644
--- a/src/store/reducers.js
+++ b/src/store/reducers.js
@@ -2,6 +2,7 @@ import { combineReducers } from 'redux';
import { routerReducer as router } from 'react-router-redux';
import { reducer as reduxAsyncConnect } from 'redux-connect';
import { reducer as form } from 'redux-form';
+import { reducer as toastr } from 'react-redux-toastr';
import global from './modules/global';
export const makeRootReducer = (asyncReducers) => combineReducers({
@@ -10,6 +11,7 @@ export const makeRootReducer = (asyncReducers) => combineReducers({
form,
reduxAsyncConnect,
...asyncReducers,
+ toastr,
});
export const injectReducer = (store, { key, reducer }) => {
diff --git a/src/styles/_base.scss b/src/styles/_base.scss
index cf68df2..a522d01 100644
--- a/src/styles/_base.scss
+++ b/src/styles/_base.scss
@@ -29,7 +29,7 @@ body {
font-size: 14px;
line-height: 20px;
color: #131313;
- background-color: #fff;
+ background-color: #f3f3f3;
}
html, body {
diff --git a/src/styles/img/icon-dropdown-caret-sm.png b/src/styles/img/icon-dropdown-caret-sm.png
new file mode 100644
index 0000000..db72e6e
Binary files /dev/null and b/src/styles/img/icon-dropdown-caret-sm.png differ
diff --git a/src/styles/main.scss b/src/styles/main.scss
index a6aa32d..8ec6cf3 100644
--- a/src/styles/main.scss
+++ b/src/styles/main.scss
@@ -2,6 +2,7 @@
@import "../../node_modules/react-date-picker/index.css";
@import "../../node_modules/react-select/dist/react-select.css";
+@import "../../node_modules/react-redux-toastr/src/styles/index.scss";
@import "mixins";
@import "fonts";
diff --git a/webpack.config-test.babel.js b/webpack.config-test.babel.js
new file mode 100644
index 0000000..95733df
--- /dev/null
+++ b/webpack.config-test.babel.js
@@ -0,0 +1,51 @@
+const nodeExternals = require('webpack-node-externals');
+const path = require('path');
+
+export default {
+ target: 'node',
+ externals: [nodeExternals()],
+ module: {
+ loaders: [
+ {
+ test: /\.(jsx|js)$/,
+ exclude: /node_modules/,
+ loader: 'babel',
+ query: {
+ cacheDirectory: true,
+ plugins: ['transform-runtime'],
+ presets: ['es2015', 'react', 'stage-0'],
+ },
+ },
+ {
+ test: /\.scss$/,
+ exclude: /styles/,
+ loaders: [
+ 'style',
+ 'css?sourceMap&-minimize&modules&importLoaders=2&localIdentName=[name]__[local]___[hash:base64:5]',
+ 'postcss',
+ 'sass?sourceMap',
+ ],
+ },
+ {
+ test: /\.css$/,
+ loader: 'style!css?modules',
+ include: /flexboxgrid/,
+ },
+ { test: /\.(png|jpg)$/, loader: 'url?limit=8192' },
+ ],
+ },
+ resolve: {
+ root: path.join(__dirname, './src'),
+ extensions: ['', '.jsx', '.js', '.json'],
+ fallback: [
+ path.join(__dirname, './src/styles/img'),
+ ],
+ alias: {
+ store: path.join(__dirname, './src/store'),
+ containers: path.join(__dirname, './src/containers'),
+ services: path.join(__dirname, './src/services'),
+ layouts: path.join(__dirname, './src/layouts'),
+ components: path.join(__dirname, './src/components'),
+ },
+ },
+};
diff --git a/webpack.config.js b/webpack.config.js
index ffe7f77..03a4bfb 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -153,6 +153,11 @@ module.exports = {
'sass?sourceMap',
],
}),
+ fixStyleLoader({
+ test: /\.css$/,
+ loaders: ['style','css?modules'],
+ include: /flexboxgrid/,
+ }),
{
test: /\.woff(\?.*)?$/,
loader: 'url?prefix=fonts/&name=[path][name].[ext]&limit=10000&mimetype=application/font-woff',