diff --git a/src/components/TurkHit/index.js b/src/components/TurkHit/index.js index 1c3e9383715552cf40df60ab2d6693f701c894d8..517143a2ddd99a726ce1f8a8388381f2980c1956 100644 --- a/src/components/TurkHit/index.js +++ b/src/components/TurkHit/index.js @@ -1,73 +1,126 @@ -import React, { PropTypes } from 'react'; +import React, { PropTypes, Component } from 'react'; import defaultForm from './defaultForm'; import './styles.scss'; +import turkHitPropTypes from '../../containers/Dimensions/propTypes'; +import turkStatus from './turkStatus'; -export default function TurkHit({ createHit, hitDecision, address, building_id, hit }) { - let hitStatus =
; - const createBtn = ( - - ); +class TurkHit extends Component { + constructor(props) { + super(props); - // Loading HIT - if (hit.loading) { - return

Loading...

; - } else if (hit.error.message && hit.error.response.status !== 404) { - return

{hit.error.message}

; + // TODO not being used + this.state = { + error: false, + }; } - if (!hit.error.message && hit.status !== '') { - let fileActions =
; + renderDownloadLink = () => { + const buildings = this.props.hit.boxBuildingList; + /* eslint-disable jsx-a11y/href-no-hash*/ + return ( + 0 ? buildings.slice(-1)[0].url_download : '#'} + > + Download + + ); + } + + renderCreateHitButton = () => { + const { createHit, address, building_id } = this.props; + return ( + + ); + } + + renderHitActions = () => { + const { hitDecision, building_id } = this.props; + return ( +
+ + +
+ ); + } + + render() { + const { hit } = this.props; + const { status } = this.props.hit; + let mainContent =
; + + if (hit.loading) { + return

Loading...

; + } else if (hit.error && hit.error.response.status !== 404) { + return ( +
+ Retrieving HIT error. Response message: {hit.error.message} +
+ ); + } - if (hit.status === 'Reviewable') { - fileActions = ( + if (status !== '') { + const currStatus = turkStatus[status]; + mainContent = ( +
+ {turkStatus[status].message} + {currStatus.createBtn && this.renderCreateHitButton()} +
+ {currStatus.downloadLink && this.renderDownloadLink()} + {currStatus.fileActions && this.renderHitActions()} +
+
+ ); + } else { + mainContent = (
- Download File - - +

HIT has not been created yet.

+ {this.renderCreateHitButton()}
); - } else if (hit.status === 'Rejected' - || hit.status === 'Expired' - || hit.status === 'Disposed') { - fileActions = createBtn; } - hitStatus = ( + return (
- HIT Status: {hit.status} - {fileActions} +
+ Failed to create HIT. Response message: {hit.create.error.message} +
+ +

Mechanical Turk

+
Definitions
+

+ Amazon Mechanical Turk is a marketplace for workers to complete Human + Intelligence Tasks or HITs. +
+ We will be creating HITs for workers to measure the dimensions of a building. + HITs have 6 days to be completed from date of creation. +

+ + {mainContent}
); - } else { - hitStatus = createBtn; - } - - // Creating HIT -- error message - if (hit.create.error.message) { - return

{hit.create.error.message}

; } - - return ( -
- {hitStatus} -
- ); } TurkHit.propTypes = { @@ -75,14 +128,7 @@ TurkHit.propTypes = { hitDecision: PropTypes.func, address: PropTypes.string, building_id: PropTypes.number, - hit: PropTypes.shape({ - id: PropTypes.string, - status: PropTypes.string, - loading: PropTypes.boolean, - error: PropTypes.boolean, - create: PropTypes.shape({ - loading: PropTypes.boolean, - error: PropTypes.boolean, - }), - }), + hit: turkHitPropTypes, }; + +export default TurkHit; diff --git a/src/components/TurkHit/turkStatus.js b/src/components/TurkHit/turkStatus.js new file mode 100644 index 0000000000000000000000000000000000000000..5b9478b42459456d04a201b17a543edecd16eec9 --- /dev/null +++ b/src/components/TurkHit/turkStatus.js @@ -0,0 +1,44 @@ +export default { + Assignable: { + message: 'HIT has been submitted to mechanical turk and is waiting for worker.', + createBtn: false, + fileActions: false, + downloadLink: false, + }, + Unassignable: { + message: 'Worker is finding the measurements of the building.', + createBtn: false, + fileActions: false, + downloadLink: false, + }, + Reviewable: { + message: 'Measurements have been submitted. Check if the file is correct and either approve or reject.', + createBtn: false, + fileActions: true, + downloadLink: true, + }, + Accepted: { + message: 'HIT is completed and has been accepted.', + createBtn: false, + fileActions: false, + downloadLink: true, + }, + Rejected: { + message: 'The HIT has been rejected.', + createBtn: true, + fileActions: false, + downloadLink: true, + }, + Disposed: { + message: 'The HIT has been deleted from mechanical turk. Create a new HIT.', + createBtn: true, + fileActions: false, + downloadLink: false, + }, + Expired: { + message: 'The HIT has been expired and must be recreated.', + createBtn: true, + fileActions: false, + downloadLink: false, + }, +}; diff --git a/src/containers/BuildingOverview/constants.js b/src/containers/BuildingOverview/constants.js index 4ed5fd68462fab08fa820f6f60430820d4a0c1e7..25650cab4a7ecc0110cac9202331cfc7ff8c005f 100644 --- a/src/containers/BuildingOverview/constants.js +++ b/src/containers/BuildingOverview/constants.js @@ -1,12 +1,3 @@ export const LOAD_BUILDING_DETAIL = 'LOAD_BUILDING_DETAIL'; export const LOAD_BUILDING_DETAIL_SUCCEES = 'LOAD_BUILDING_DETAIL_SUCCEES'; export const LOAD_BUILDING_DETAIL_ERROR = 'LOAD_BUILDING_DETAIL_ERROR'; -export const LOAD_HIT = 'LOAD_HIT'; -export const LOAD_HIT_SUCCESS = 'LOAD_HIT_SUCCESS'; -export const LOAD_HIT_ERROR = 'LOAD_HIT_ERROR'; -export const CREATE_HIT = 'CREATE_HIT'; -export const CREATE_HIT_SUCCESS = 'CREATE_HIT_SUCCESS'; -export const CREATE_HIT_ERROR = 'CREATE_HIT_ERROR'; -export const DECIDE_HIT = 'DECIDE_HIT'; -export const DECIDE_HIT_SUCCESS = 'DECIDE_HIT_SUCCESS'; -export const DECIDE_HIT_ERROR = 'DECIDE_HIT_ERROR'; diff --git a/src/containers/BuildingOverview/index.js b/src/containers/BuildingOverview/index.js index 24e62a013bad97834df47bcb6eea584a9196f5fd..f55618172b7d4d57a639a822b5aa65a1494ebbe9 100644 --- a/src/containers/BuildingOverview/index.js +++ b/src/containers/BuildingOverview/index.js @@ -3,27 +3,19 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import buildingDetailPropTypes from './buildingDetailPropType'; -import { - loadBuildingDetail, - loadHit, - createHit, - hitDecision, -} from './actions'; +import { loadBuildingDetail } from './actions'; import './styles.scss'; import BuildingOverviewTop from '../../components/BuildingOverviewTop'; -import TurkHit from '../../components/TurkHit'; class BuildingOverview extends Component { componentDidMount() { this.props.loadBuildingDetail(this.props.params.buildingID); - this.props.loadHit(this.props.params.buildingID); } render() { let mainContent =
; - let hit =
; if (this.props.buildingDetail.overview.error) { mainContent = ( @@ -37,22 +29,11 @@ class BuildingOverview extends Component { building={this.props.buildingDetail.overview} /> ); - - hit = ( - - ); } return (
{mainContent} - {hit}
); } @@ -62,17 +43,11 @@ BuildingOverview.propTypes = { buildingDetail: buildingDetailPropTypes, params: PropTypes.objectOf(PropTypes.string), loadBuildingDetail: PropTypes.func, - loadHit: PropTypes.func, - createHit: PropTypes.func, - hitDecision: PropTypes.func, }; function mapDispatchToProps(dispatch) { return bindActionCreators({ loadBuildingDetail, - loadHit, - createHit, - hitDecision, }, dispatch); } diff --git a/src/containers/BuildingOverview/reducer.js b/src/containers/BuildingOverview/reducer.js index fca4094058eef1955ce2d35672e13ac8e92a3d1a..198aa937aec6ba919354178094adb739a62a71df 100644 --- a/src/containers/BuildingOverview/reducer.js +++ b/src/containers/BuildingOverview/reducer.js @@ -2,15 +2,6 @@ import { LOAD_BUILDING_DETAIL, LOAD_BUILDING_DETAIL_SUCCEES, LOAD_BUILDING_DETAIL_ERROR, - LOAD_HIT, - LOAD_HIT_SUCCESS, - LOAD_HIT_ERROR, - CREATE_HIT, - CREATE_HIT_SUCCESS, - CREATE_HIT_ERROR, - DECIDE_HIT, - DECIDE_HIT_SUCCESS, - DECIDE_HIT_ERROR, } from './constants'; const initState = { @@ -18,20 +9,6 @@ const initState = { loading: false, error: false, }, - hit: { - id: '', - status: '', - loading: false, - error: false, - create: { - loading: false, - error: false, - }, - approval: { - loading: false, - error: false, - }, - }, }; export default function (state = initState, action) { @@ -66,115 +43,6 @@ export default function (state = initState, action) { }, }; - case LOAD_HIT: - return { - ...state, - hit: { - ...state.hit, - status: '', - loading: true, - error: false, - }, - }; - - case LOAD_HIT_SUCCESS: - return { - ...state, - hit: { - ...state.hit, - status: action.payload.data.status, - url: action.payload.data.hit_url, - loading: false, - error: false, - }, - }; - - case LOAD_HIT_ERROR: - return { - ...state, - hit: { - ...state.hit, - loading: false, - error: action.error, - }, - }; - - case CREATE_HIT: - return { - ...state, - hit: { - ...state.hit, - create: { - loading: true, - error: false, - }, - }, - }; - - case CREATE_HIT_SUCCESS: - return { - ...state, - hit: { - id: action.payload.data.hit_id, - status: action.payload.data.status, - loading: false, - error: false, - create: { - loading: false, - error: false, - }, - }, - }; - - case CREATE_HIT_ERROR: - return { - ...state, - hit: { - ...state.hit, - create: { - loading: false, - error: action.error, - }, - }, - }; - - case DECIDE_HIT: - return { - ...state, - hit: { - ...state.hit, - approval: { - loading: true, - error: false, - }, - }, - }; - - case DECIDE_HIT_SUCCESS: - return { - ...state, - hit: { - ...state.hit, - status: action.payload.data.hit_status, - approval: { - loading: false, - error: false, - }, - }, - }; - - case DECIDE_HIT_ERROR: - return { - ...state, - hit: { - ...state.hit, - approval: { - loading: false, - error: action.error, - }, - }, - }; - default: return state; } diff --git a/src/containers/BuildingOverview/sagas.js b/src/containers/BuildingOverview/sagas.js index 2a410499591eb17fbb8889f814f018186ce27c88..284e2d74fe22b0be394ca7d9cd6611fde7babcc5 100644 --- a/src/containers/BuildingOverview/sagas.js +++ b/src/containers/BuildingOverview/sagas.js @@ -1,23 +1,14 @@ import { call, put, takeEvery } from 'redux-saga/effects'; import request from '../../utils/request'; -import { getHeaders, turkURL, buildingsURL } from '../../utils/rest_services'; +import { getHeaders, buildingsURL } from '../../utils/rest_services'; import { LOAD_BUILDING_DETAIL, - LOAD_HIT, - CREATE_HIT, - DECIDE_HIT, } from './constants'; import { buildingDetailLoaded, buildingDetailLoadingError, - hitLoaded, - hitLoadingError, - createHitSuccess, - createHitError, - hitDecisionSuccess, - hitDecisionError, } from './actions'; /** @@ -42,68 +33,12 @@ function* getBuildingDetail(action) { } } -function* loadHit(action) { - const buildingId = action.payload; - const data = yield call(request, `${turkURL}${buildingId}`, { - method: 'GET', - headers: getHeaders(), - }); - - if (!data.err) { - yield put(hitLoaded(data)); - } else { - yield put(hitLoadingError(data.err)); - } -} - -/** - * Mechanical Turk HIT creation request/response handler - * - * @param {object} action Form data of mechanical turk job - */ -function* createHit(action) { - const turkHitFormData = action.payload; - const data = yield call(request, turkURL, { - method: 'POST', - headers: getHeaders(), - body: JSON.stringify(turkHitFormData), - }); - - if (!data.err) { - yield put(createHitSuccess(data)); - } else { - yield put(createHitError(data.err)); - } -} - -/** - * Approve or reject HIT request/response handler - * - * @param {number} action 1 or 0 representing approve or reject - */ -function* approveHit(action) { - const data = yield call(request, `${turkURL}${action.buildingId}`, { - method: 'PUT', - headers: getHeaders(), - body: JSON.stringify({ accept: action.decision }), - }); - - if (!data.err) { - yield put(hitDecisionSuccess(data)); - } else { - yield put(hitDecisionError(data.err)); - } -} - /** * Watches for LOAD_BUILDING_DETAIL & CREATE_HIT actions and calls * the appropriate handler function. */ function* buildingDetailWatcher() { yield takeEvery(LOAD_BUILDING_DETAIL, getBuildingDetail); - yield takeEvery(LOAD_HIT, loadHit); - yield takeEvery(CREATE_HIT, createHit); - yield takeEvery(DECIDE_HIT, approveHit); } export default buildingDetailWatcher; diff --git a/src/containers/Dimensions/actions.js b/src/containers/Dimensions/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..0600cfea77247821da68142fa3a042a5f93e5033 --- /dev/null +++ b/src/containers/Dimensions/actions.js @@ -0,0 +1,137 @@ +import 'whatwg-fetch'; +import { + LOAD_HIT, + LOAD_HIT_SUCCESS, + LOAD_HIT_ERROR, + CREATE_HIT, + CREATE_HIT_SUCCESS, + CREATE_HIT_ERROR, + DECIDE_HIT, + DECIDE_HIT_SUCCESS, + DECIDE_HIT_ERROR, +} from './constants'; + +/** + * Load status of HIT + * TODO The HIT status should be loaded from the building detail route + * + * @param {string} buildingId The current buildingID + * @returns {object} An action object with a type of + * LOAD_HIT passing the building_id + */ +export function loadHit(buildingId) { + return { + type: LOAD_HIT, + payload: buildingId, + }; +} + +/** + * Dispatched when the hit status was successfully loaded + * + * @param {string} hitStatus The HIT status + * @returns {object} An action object with a type of + * LOAD_HIT_SUCCESS passing the hit status + */ +export function hitLoaded(hitStatus) { + return { + type: LOAD_HIT_SUCCESS, + payload: hitStatus, + }; +} + +/** + * Dispatched when loading the hit status fails + * + * @param {object} error The error + * @returns {object} An action object with a type of + * LOAD_HIT passing the hit status + */ +export function hitLoadingError(error) { + return { + type: LOAD_HIT_ERROR, + error, + }; +} + +/** + * Create mturk HIT, this action starts the request saga + * + * @param {object} formData The mturk form data + * @returns {object} An action object with a type of CREATE_HIT + */ +export function createHit(formData) { + return { + type: CREATE_HIT, + payload: formData, + }; +} + +/** + * Dispatched when the mturk HIT was successfully created + * + * @param {object} hitData The created hit data + * @returns {object} An action object with a type of CREATE_HIT_SUCCESS + */ +export function createHitSuccess(hitData) { + return { + type: CREATE_HIT_SUCCESS, + payload: hitData, + }; +} + +/** + * Dispatched when creating the mturk HIT fails + * + * @param {object} error The error + * @return {object} An action object with a type of CREATE_HIT_ERROR + * passing the error + */ +export function createHitError(error) { + return { + type: CREATE_HIT_ERROR, + error, + }; +} + +/** + * Dispatched when user selects approve or reject HIT + * + * @param {int} buildingId Id of building + * @param {int} decision 1 or 0 representing approve or reject + * @returns {object} An action object with a type of DECIDE_HIT + * passing the decision of the user + */ +export function hitDecision(buildingId, decision) { + return { + type: DECIDE_HIT, + buildingId, + decision, + }; +} + +/** + * Dispatched when the hit was successfully approved or disapproved + * + * @returns {object} + */ +export function hitDecisionSuccess(data) { + return { + type: DECIDE_HIT_SUCCESS, + payload: data, + }; +} + +/** + * Dispatched when there is a error approving or rejecting a HIT + * + * @param error The error + * @returns {object} An action object with a type of DECIDE_HIT_ERROR + * passing the error + */ +export function hitDecisionError(error) { + return { + type: DECIDE_HIT_ERROR, + error, + }; +} diff --git a/src/containers/Dimensions/constants.js b/src/containers/Dimensions/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..7d202767b2d5df08df3049adc550d2d234cfa050 --- /dev/null +++ b/src/containers/Dimensions/constants.js @@ -0,0 +1,9 @@ +export const LOAD_HIT = 'LOAD_HIT'; +export const LOAD_HIT_SUCCESS = 'LOAD_HIT_SUCCESS'; +export const LOAD_HIT_ERROR = 'LOAD_HIT_ERROR'; +export const CREATE_HIT = 'CREATE_HIT'; +export const CREATE_HIT_SUCCESS = 'CREATE_HIT_SUCCESS'; +export const CREATE_HIT_ERROR = 'CREATE_HIT_ERROR'; +export const DECIDE_HIT = 'DECIDE_HIT'; +export const DECIDE_HIT_SUCCESS = 'DECIDE_HIT_SUCCESS'; +export const DECIDE_HIT_ERROR = 'DECIDE_HIT_ERROR'; diff --git a/src/containers/Dimensions/index.js b/src/containers/Dimensions/index.js new file mode 100644 index 0000000000000000000000000000000000000000..70077e5628618c0b9954a66c63d1df85e50e93ee --- /dev/null +++ b/src/containers/Dimensions/index.js @@ -0,0 +1,73 @@ +import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; + +import { + loadHit, + createHit, + hitDecision, +} from './actions'; + +import { + loadBuildingDetail, +} from '../BuildingOverview/actions'; + +import buildingDetailPropTypes from '../BuildingOverview/buildingDetailPropType'; +import turkHitPropTypes from './propTypes'; + +import './styles.css'; +import TurkHit from '../../components/TurkHit'; + + +class Dimensions extends Component { + componentDidMount() { + /* eslint-disable camelcase */ + const { address, building_id } = this.props.buildingDetail.overview; + + this.props.loadHit(this.props.buildingId); + if (!address || this.props.buildingId !== building_id) { + this.props.loadBuildingDetail(this.props.buildingId); + } + } + + render() { + return ( +
+ +
+ ); + } +} + +Dimensions.propTypes = { + buildingId: PropTypes.string, + buildingDetail: buildingDetailPropTypes, + dimensions: PropTypes.shape({ + hit: turkHitPropTypes, + }), + loadHit: PropTypes.func, + createHit: PropTypes.func, + hitDecision: PropTypes.func, + loadBuildingDetail: PropTypes.func, +}; + +function mapDispatchToProps(dispatch) { + return bindActionCreators({ + loadHit, + createHit, + hitDecision, + loadBuildingDetail, + }, dispatch); +} + +function mapStateToProps({ dimensions, buildingDetail }) { + return { dimensions, buildingDetail }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(Dimensions); diff --git a/src/containers/Dimensions/propTypes.js b/src/containers/Dimensions/propTypes.js new file mode 100644 index 0000000000000000000000000000000000000000..8ca01f5449d61c939fb643775d06922f962c13d4 --- /dev/null +++ b/src/containers/Dimensions/propTypes.js @@ -0,0 +1,17 @@ +import { PropTypes } from 'react'; + +export default PropTypes.shape({ + id: PropTypes.string, + status: PropTypes.string, + loading: PropTypes.boolean, + error: PropTypes.boolean, + boxBuildingList: PropTypes.arrayOf( + PropTypes.shape({ + url_download: PropTypes.string, + }) + ), + create: PropTypes.shape({ + loading: PropTypes.boolean, + error: PropTypes.boolean, + }), +}); diff --git a/src/containers/Dimensions/reducer.js b/src/containers/Dimensions/reducer.js new file mode 100644 index 0000000000000000000000000000000000000000..bed3ed97a8625d4fc4fa175497a2aeca17a25f64 --- /dev/null +++ b/src/containers/Dimensions/reducer.js @@ -0,0 +1,136 @@ +import { + LOAD_HIT, + LOAD_HIT_SUCCESS, + LOAD_HIT_ERROR, + CREATE_HIT, + CREATE_HIT_SUCCESS, + CREATE_HIT_ERROR, + DECIDE_HIT, + DECIDE_HIT_SUCCESS, + DECIDE_HIT_ERROR, +} from './constants'; + +const initState = { + hit: { + id: '', + status: '', + loading: false, + error: false, + boxBuildingList: [], + create: { + loading: false, + error: false, + }, + approval: { + loading: false, + error: false, + }, + }, +}; + +export default function (state = initState, action) { + switch (action.type) { + case LOAD_HIT: + return { + hit: { + ...state.hit, + status: '', + loading: true, + error: false, + }, + }; + + case LOAD_HIT_SUCCESS: + return { + hit: { + ...state.hit, + status: action.payload.data.status, + boxBuildingList: action.payload.data.box_building_list, + loading: false, + error: false, + }, + }; + + case LOAD_HIT_ERROR: + return { + hit: { + ...state.hit, + loading: false, + error: action.error, + }, + }; + + case CREATE_HIT: + return { + hit: { + ...state.hit, + create: { + loading: true, + error: false, + }, + }, + }; + + case CREATE_HIT_SUCCESS: + return { + hit: { + id: action.payload.data.hit_id, + status: action.payload.data.status, + loading: false, + error: false, + create: { + loading: false, + error: false, + }, + }, + }; + + case CREATE_HIT_ERROR: + return { + hit: { + ...state.hit, + create: { + loading: false, + error: action.error, + }, + }, + }; + + case DECIDE_HIT: + return { + hit: { + ...state.hit, + approval: { + loading: true, + error: false, + }, + }, + }; + + case DECIDE_HIT_SUCCESS: + return { + hit: { + ...state.hit, + status: action.payload.data.hit_status, + approval: { + loading: false, + error: false, + }, + }, + }; + + case DECIDE_HIT_ERROR: + return { + hit: { + ...state.hit, + approval: { + loading: false, + error: action.error, + }, + }, + }; + + default: + return state; + } +} diff --git a/src/containers/Dimensions/sagas.js b/src/containers/Dimensions/sagas.js new file mode 100644 index 0000000000000000000000000000000000000000..ee04cd3c617ac50c669a23137fb3b4f7da5fe34d --- /dev/null +++ b/src/containers/Dimensions/sagas.js @@ -0,0 +1,88 @@ +import { call, put, takeEvery } from 'redux-saga/effects'; +import request from '../../utils/request'; +import { getHeaders, turkURL } from '../../utils/rest_services'; + +import { + LOAD_HIT, + CREATE_HIT, + DECIDE_HIT, +} from './constants'; + +import { + hitLoaded, + hitLoadingError, + createHitSuccess, + createHitError, + hitDecisionSuccess, + hitDecisionError, +} from './actions'; + +/** + * Load Mechanical Turk HIT request/response handler + * + * @param {object} action Payload attribute with buildingId + */ +function* loadHit(action) { + const buildingId = action.payload; + const data = yield call(request, `${turkURL}${buildingId}`, { + method: 'GET', + headers: getHeaders(), + }); + + if (!data.err) { + yield put(hitLoaded(data)); + } else { + yield put(hitLoadingError(data.err)); + } +} + +/** + * Mechanical Turk HIT creation request/response handler + * + * @param {object} action Form data of mechanical turk job + */ +function* createHit(action) { + const turkHitFormData = action.payload; + const data = yield call(request, turkURL, { + method: 'POST', + headers: getHeaders(), + body: JSON.stringify(turkHitFormData), + }); + + if (!data.err) { + yield put(createHitSuccess(data)); + } else { + yield put(createHitError(data.err)); + } +} + +/** + * Approve or reject HIT request/response handler + * + * @param {number} action 1 or 0 representing approve or reject + */ +function* approveHit(action) { + const data = yield call(request, `${turkURL}${action.buildingId}`, { + method: 'PUT', + headers: getHeaders(), + body: JSON.stringify({ accept: action.decision }), + }); + + if (!data.err) { + yield put(hitDecisionSuccess(data)); + } else { + yield put(hitDecisionError(data.err)); + } +} + +/** + * Watches for LOAD_BUILDING_DETAIL & CREATE_HIT actions and calls + * the appropriate handler function. + */ +function* dimensionsWatcher() { + yield takeEvery(LOAD_HIT, loadHit); + yield takeEvery(CREATE_HIT, createHit); + yield takeEvery(DECIDE_HIT, approveHit); +} + +export default dimensionsWatcher; diff --git a/src/containers/Dimensions/styles.css b/src/containers/Dimensions/styles.css new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/reducers.js b/src/reducers.js index 248796275a16072b312dcd8cf15073b220110e3c..6870601e215350285ac1fffc1c76a57a40dedfab 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -4,10 +4,12 @@ import { routerReducer } from 'react-router-redux'; import SearchBarReducer from './containers/SearchBar/reducer'; import BuildingOverviewReducer from './containers/BuildingOverview/reducer'; import GoogleLoginReducer from './containers/GoogleLogin/reducer'; +import DimensionsReducer from './containers/Dimensions/reducer'; export default combineReducers({ routing: routerReducer, buildingList: SearchBarReducer, buildingDetail: BuildingOverviewReducer, googleLogin: GoogleLoginReducer, + dimensions: DimensionsReducer, }); diff --git a/src/routes.js b/src/routes.js index c64dc2a6222300e7819750bba89ad3e9e19d5082..4410848dac39d82c76bac89c313ba151331feb88 100644 --- a/src/routes.js +++ b/src/routes.js @@ -8,6 +8,7 @@ import NotFound from './screens/NotFound'; import HomePage from './screens/HomePage'; import BuildingDetail from './screens/BuildingDetail'; import BuildingOverview from './containers/BuildingOverview'; +import Dimensions from './containers/Dimensions'; import Utilities from './components/Utilities'; import Dummy from './components/dummyComponent'; @@ -21,7 +22,7 @@ export default ( - + diff --git a/src/sagas.js b/src/sagas.js index 09714c28f5379d808a6964ddd7c9f85c5a863d00..1f35dcd14a543fdd3d029faa7f3065980c09c2a0 100644 --- a/src/sagas.js +++ b/src/sagas.js @@ -1,7 +1,9 @@ import buildingOverviewSaga from './containers/BuildingOverview/sagas'; +import dimensionsSaga from './containers/Dimensions/sagas'; export default function* rootSaga() { yield [ buildingOverviewSaga(), + dimensionsSaga(), ]; }