diff --git a/scripts/start.js b/scripts/start.js index 90ffd0910dc765ccaeb3393b06811be22cc740a0..c7e84267c6fb24fc98fe57ca1764fc727993fc09 100644 --- a/scripts/start.js +++ b/scripts/start.js @@ -26,7 +26,7 @@ if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { } // Tools like Cloud9 rely on this. -var DEFAULT_PORT = process.env.PORT || 5305; +var DEFAULT_PORT = process.env.PORT || 5501; var compiler; var handleCompile; diff --git a/src/components/BuildingListTable/index.js b/src/components/BuildingListTable/index.js index 1693664dde4ebbc9e56da8754746dd3840f82f87..45ca7cea53cad9310755aa20db14591d05dec663 100644 --- a/src/components/BuildingListTable/index.js +++ b/src/components/BuildingListTable/index.js @@ -19,7 +19,7 @@ export default function BuildingListTable({ buildings }) { React router Link component does not support relative paths */} - + {building.address} diff --git a/src/components/BuildingOverview/index.js b/src/components/BuildingOverviewTop/index.js similarity index 100% rename from src/components/BuildingOverview/index.js rename to src/components/BuildingOverviewTop/index.js diff --git a/src/components/BuildingOverview/styles.scss b/src/components/BuildingOverviewTop/styles.scss similarity index 100% rename from src/components/BuildingOverview/styles.scss rename to src/components/BuildingOverviewTop/styles.scss diff --git a/src/components/SideBarDetail/index.js b/src/components/SideBarDetail/index.js index fb62883ea388069d22fa287c021c4634b11a6f16..6530ad2c82319cb53851099772a601b64de79076 100644 --- a/src/components/SideBarDetail/index.js +++ b/src/components/SideBarDetail/index.js @@ -1,10 +1,28 @@ -import React from 'react'; +import React, { PropTypes } from 'react'; +import { Link } from 'react-router'; import './styles.scss'; -export default function SideBarDetail() { +export default function SideBarDetail({ buildingId }) { + const rootURL = `/buildings/${buildingId}`; return (
-

Sidebar

+ Home +
+ Overview +
+ Dimensions +
+ Weather +
+ Utilities +
+ Occupancy +
+ Financials
); } + +SideBarDetail.propTypes = { + buildingId: PropTypes.string, +}; diff --git a/src/components/TurkHit/defaultForm.js b/src/components/TurkHit/defaultForm.js index b8fa47c87c48c8304d0a37a71cce5bffbbe46256..782777cb85d9786916082b8b7c3142cc7b8f7178 100644 --- a/src/components/TurkHit/defaultForm.js +++ b/src/components/TurkHit/defaultForm.js @@ -7,10 +7,10 @@ const defaultTurkHit = { title: 'Measure building dimensions', description: 'Use google earth to measure building\'s dimensions, windows, and doors', keywords: 'building, dimensions, google earth', - duration: '300', + duration: '7200', reward: '5', - MIN_FILE_BYTES: 1, - MAX_FILE_BYTES: 10, + min_file_bytes: 1, + max_file_bytes: 50000000, }; export default defaultTurkHit; diff --git a/src/components/TurkHit/index.js b/src/components/TurkHit/index.js index a3d13882b662d6a528c50a46cfbbc99918d10721..1c3e9383715552cf40df60ab2d6693f701c894d8 100644 --- a/src/components/TurkHit/index.js +++ b/src/components/TurkHit/index.js @@ -2,31 +2,69 @@ import React, { PropTypes } from 'react'; import defaultForm from './defaultForm'; import './styles.scss'; -export default function TurkHit({ createHit, address, building_id, hit }) { + +export default function TurkHit({ createHit, hitDecision, address, building_id, hit }) { let hitStatus =
; + const createBtn = ( + + ); + + // Loading HIT + if (hit.loading) { + return

Loading...

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

{hit.error.message}

; + } + if (!hit.error.message && hit.status !== '') { + let fileActions =
; + + if (hit.status === 'Reviewable') { + fileActions = ( +
+ Download File + + +
+ ); + } else if (hit.status === 'Rejected' + || hit.status === 'Expired' + || hit.status === 'Disposed') { + fileActions = createBtn; + } + hitStatus = (
-

HIT Id: {hit.id}

-

HIT Status: {hit.status}

+ HIT Status: {hit.status} + {fileActions}
); } else { - hitStatus = ( -
-

{hit.error.message}

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

{hit.create.error.message}

; } return (
- {hitStatus}
); @@ -34,6 +72,7 @@ export default function TurkHit({ createHit, address, building_id, hit }) { TurkHit.propTypes = { createHit: PropTypes.func, + hitDecision: PropTypes.func, address: PropTypes.string, building_id: PropTypes.number, hit: PropTypes.shape({ @@ -41,5 +80,9 @@ TurkHit.propTypes = { status: PropTypes.string, loading: PropTypes.boolean, error: PropTypes.boolean, + create: PropTypes.shape({ + loading: PropTypes.boolean, + error: PropTypes.boolean, + }), }), }; diff --git a/src/components/dummyComponent.js b/src/components/dummyComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..2cec953e1a7cbd51b2fc02867b985dcd0f874955 --- /dev/null +++ b/src/components/dummyComponent.js @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function dummyComponent() { + return

Coming Soon!

; +} diff --git a/src/containers/BuildingDetail/actions.js b/src/containers/BuildingDetail/actions.js deleted file mode 100644 index 5a574bc8f5cd81edbebe19a771f6a5b0d4539a91..0000000000000000000000000000000000000000 --- a/src/containers/BuildingDetail/actions.js +++ /dev/null @@ -1,93 +0,0 @@ -import 'whatwg-fetch'; -import { - LOAD_BUILDING_DETAIL, - LOAD_BUILDING_DETAIL_SUCCEES, - LOAD_BUILDING_DETAIL_ERROR, - CREATE_HIT, - CREATE_HIT_SUCCEES, - CREATE_HIT_ERROR, -} from './constants'; - -/** - * Load building details, this action starts the request saga - * - * @param buildingID The current buildingID - * @returns {object} An action object with a type of LOAD_BUILDING_DETAIL - * passing the building detail - */ -export function loadBuildingDetail(buildingID) { - return { - type: LOAD_BUILDING_DETAIL, - payload: buildingID, - }; -} - -/** - * Dispatched when the building details are loaded by the request saga - * - * @param {object} buildingDetail The building data - * @returns {object} An action object with a type of - * LOAD_BUILDING_DETAIL_SUCCEES - */ -export function buildingDetailLoaded(buildingDetail) { - return { - type: LOAD_BUILDING_DETAIL_SUCCEES, - payload: buildingDetail, - }; -} - -/** - * Dispatched when loading the building detail fails - * - * @param {object} error The error - * - * @return {object} An action object with a type of - * LOAD_BUILDING_DETAIL_ERROR passing the error - */ -export function buildingDetailLoadingError(error) { - return { - type: LOAD_BUILDING_DETAIL_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_SUCCEES - */ -export function createHitSuccess(hitData) { - return { - type: CREATE_HIT_SUCCEES, - 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, - }; -} diff --git a/src/containers/BuildingDetail/constants.js b/src/containers/BuildingDetail/constants.js deleted file mode 100644 index 873b9080d77454308cb96f389e1c36077d58b7c8..0000000000000000000000000000000000000000 --- a/src/containers/BuildingDetail/constants.js +++ /dev/null @@ -1,6 +0,0 @@ -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 CREATE_HIT = 'CREATE_HIT'; -export const CREATE_HIT_SUCCEES = 'CREATE_HIT_SUCCEES'; -export const CREATE_HIT_ERROR = 'CREATE_HIT_ERROR'; diff --git a/src/containers/BuildingDetail/reducer.js b/src/containers/BuildingDetail/reducer.js deleted file mode 100644 index 457c6ed739417d42b920af95be052ddff1bdb7b4..0000000000000000000000000000000000000000 --- a/src/containers/BuildingDetail/reducer.js +++ /dev/null @@ -1,89 +0,0 @@ -import { - LOAD_BUILDING_DETAIL, - LOAD_BUILDING_DETAIL_SUCCEES, - LOAD_BUILDING_DETAIL_ERROR, - CREATE_HIT, - CREATE_HIT_SUCCEES, - CREATE_HIT_ERROR, -} from './constants'; - -const initState = { - overview: { - loading: false, - error: false, - }, - hit: { - id: '', - status: '', - loading: false, - error: false, - }, -}; - -export default function (state = initState, action) { - switch (action.type) { - case LOAD_BUILDING_DETAIL: - return { - ...state, - overview: { - ...state.overview, - loading: true, - error: false, - }, - }; - - case LOAD_BUILDING_DETAIL_SUCCEES: - return { - ...state, - overview: { - ...state.overview, - ...action.payload.data, - loading: false, - }, - }; - - case LOAD_BUILDING_DETAIL_ERROR: - return { - ...state, - overview: { - ...state.overview, - loading: true, - error: action.error, - }, - }; - - case CREATE_HIT: - return { - ...state, - hit: { - ...state.hit, - loading: true, - error: false, - }, - }; - - case CREATE_HIT_SUCCEES: - return { - ...state, - hit: { - ...state.hit, - id: action.payload.data.hit_id, - status: 'Submitted', - loading: false, - }, - }; - - case CREATE_HIT_ERROR: - return { - ...state, - hit: { - ...state.hit, - loading: false, - error: action.error, - }, - }; - - default: - return state; - } -} diff --git a/src/containers/BuildingList/index.js b/src/containers/BuildingList/index.js index f7a5355b7d65c3a7d284c42cbe319506759251a0..4b7040723473b3149c406344f3fe9daefba447d8 100644 --- a/src/containers/BuildingList/index.js +++ b/src/containers/BuildingList/index.js @@ -7,14 +7,12 @@ import BuildingListTable from '../../components/BuildingListTable'; import './styles.scss'; import { SearchSVG } from '../../components/bpl'; -// TODO remove this address -const INITIAL_TERM = '107 broadway'; class BuildingList extends Component { constructor(props) { super(props); - this.state = { term: INITIAL_TERM }; + this.state = { term: this.props.buildingList.term }; this.onInputChange = this.onInputChange.bind(this); this.onFormSubmit = this.onFormSubmit.bind(this); } diff --git a/src/containers/BuildingList/reducer.js b/src/containers/BuildingList/reducer.js index 13acd7e523fec1da413e9c3b9d1c88e9f2602256..230de775b591aac379e702e7251a310a5061a310 100644 --- a/src/containers/BuildingList/reducer.js +++ b/src/containers/BuildingList/reducer.js @@ -1,6 +1,11 @@ import { FETCH_BUILDINGS, SEARCH_TERM } from './constants'; -export default function (state = {}, action) { +// TODO remove hard coded search term +const initState = { + term: '107 broadway', +}; + +export default function (state = initState, action) { switch (action.type) { case FETCH_BUILDINGS: return { ...state, buildings: action.payload.buildings }; diff --git a/src/containers/BuildingOverview/actions.js b/src/containers/BuildingOverview/actions.js new file mode 100644 index 0000000000000000000000000000000000000000..28840a22deeefdc87f5416101a489c6958eb0824 --- /dev/null +++ b/src/containers/BuildingOverview/actions.js @@ -0,0 +1,182 @@ +import 'whatwg-fetch'; +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'; + +/** + * Load building details, this action starts the request saga + * + * @param buildingID The current buildingID + * @returns {object} An action object with a type of LOAD_BUILDING_DETAIL + * passing the building detail + */ +export function loadBuildingDetail(buildingID) { + return { + type: LOAD_BUILDING_DETAIL, + payload: buildingID, + }; +} + +/** + * Dispatched when the building details are loaded by the request saga + * + * @param {object} buildingDetail The building data + * @returns {object} An action object with a type of + * LOAD_BUILDING_DETAIL_SUCCEES + */ +export function buildingDetailLoaded(buildingDetail) { + return { + type: LOAD_BUILDING_DETAIL_SUCCEES, + payload: buildingDetail, + }; +} + +/** + * Dispatched when loading the building detail fails + * + * @param {object} error The error + * @return {object} An action object with a type of + * LOAD_BUILDING_DETAIL_ERROR passing the error + */ +export function buildingDetailLoadingError(error) { + return { + type: LOAD_BUILDING_DETAIL_ERROR, + error, + }; +} + +/** + * 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/BuildingOverview/constants.js b/src/containers/BuildingOverview/constants.js new file mode 100644 index 0000000000000000000000000000000000000000..4ed5fd68462fab08fa820f6f60430820d4a0c1e7 --- /dev/null +++ b/src/containers/BuildingOverview/constants.js @@ -0,0 +1,12 @@ +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/BuildingDetail/index.js b/src/containers/BuildingOverview/index.js similarity index 66% rename from src/containers/BuildingDetail/index.js rename to src/containers/BuildingOverview/index.js index 01b3490952add4c69cd8fbde5720b87d16fb2e38..c813797f51b75ef17911e9852cbb624cdcd59ce9 100644 --- a/src/containers/BuildingDetail/index.js +++ b/src/containers/BuildingOverview/index.js @@ -2,15 +2,22 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; -import { loadBuildingDetail, createHit } from './actions'; +import { + loadBuildingDetail, + loadHit, + createHit, + hitDecision, +} from './actions'; + import './styles.scss'; -import SideBarDetail from '../../components/SideBarDetail'; +import BuildingOverviewTop from '../../components/BuildingOverviewTop'; import TurkHit from '../../components/TurkHit'; -class BuildingDetail extends Component { +class BuildingOverview extends Component { componentDidMount() { this.props.loadBuildingDetail(this.props.params.buildingID); + this.props.loadHit(this.props.params.buildingID); } render() { @@ -24,14 +31,17 @@ class BuildingDetail extends Component {

); } else { - mainContent = React.cloneElement(this.props.children, { - building: this.props.buildingDetail.overview, - }); + mainContent = ( + + ); hit = ( @@ -39,20 +49,15 @@ class BuildingDetail extends Component { } return ( -
-
- -
-
- {mainContent} - {hit} -
+
+ {mainContent} + {hit}
); } } -BuildingDetail.propTypes = { +BuildingOverview.propTypes = { buildingDetail: PropTypes.shape({ overview: PropTypes.shape({ address: PropTypes.string, @@ -73,16 +78,22 @@ BuildingDetail.propTypes = { }), params: PropTypes.objectOf(PropTypes.string), loadBuildingDetail: PropTypes.func, + loadHit: PropTypes.func, createHit: PropTypes.func, - children: React.PropTypes.element, + hitDecision: PropTypes.func, }; function mapDispatchToProps(dispatch) { - return bindActionCreators({ loadBuildingDetail, createHit }, dispatch); + return bindActionCreators({ + loadBuildingDetail, + loadHit, + createHit, + hitDecision, + }, dispatch); } function mapStateToProps({ buildingDetail }) { return { buildingDetail }; } -export default connect(mapStateToProps, mapDispatchToProps)(BuildingDetail); +export default connect(mapStateToProps, mapDispatchToProps)(BuildingOverview); diff --git a/src/containers/BuildingOverview/reducer.js b/src/containers/BuildingOverview/reducer.js new file mode 100644 index 0000000000000000000000000000000000000000..fca4094058eef1955ce2d35672e13ac8e92a3d1a --- /dev/null +++ b/src/containers/BuildingOverview/reducer.js @@ -0,0 +1,181 @@ +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 = { + overview: { + 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) { + switch (action.type) { + case LOAD_BUILDING_DETAIL: + return { + ...state, + overview: { + loading: true, + error: false, + }, + }; + + case LOAD_BUILDING_DETAIL_SUCCEES: + return { + ...state, + overview: { + ...state.overview, + ...action.payload.data, + loading: false, + error: false, + }, + }; + + case LOAD_BUILDING_DETAIL_ERROR: + return { + ...state, + overview: { + ...state.overview, + loading: true, + error: action.error, + }, + }; + + 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/BuildingDetail/sagas.js b/src/containers/BuildingOverview/sagas.js similarity index 63% rename from src/containers/BuildingDetail/sagas.js rename to src/containers/BuildingOverview/sagas.js index 55c0fae730a95f8f8a8dda3bd27e9c77356c0c0c..2aa9622c449cb1e0b85619f2d3cc87f4f478020c 100644 --- a/src/containers/BuildingDetail/sagas.js +++ b/src/containers/BuildingOverview/sagas.js @@ -3,14 +3,20 @@ import request from '../../utils/request'; import { LOAD_BUILDING_DETAIL, + LOAD_HIT, CREATE_HIT, + DECIDE_HIT, } from './constants'; import { buildingDetailLoaded, buildingDetailLoadingError, + hitLoaded, + hitLoadingError, createHitSuccess, createHitError, + hitDecisionSuccess, + hitDecisionError, } from './actions'; const BUILDING_SERVICE_URL = `${process.env.REACT_APP_BUILDING_SERVICE}`; @@ -40,6 +46,20 @@ function* getBuildingDetail(action) { } } +function* loadHit(action) { + const buildingId = action.payload; + const data = yield call(request, `${BUILDING_SERVICE_URL}/turkhit/${buildingId}`, { + method: 'GET', + headers: HEADERS, + }); + + if (!data.err) { + yield put(hitLoaded(data)); + } else { + yield put(hitLoadingError(data.err)); + } +} + /** * Mechanical Turk HIT creation request/response handler * @@ -60,13 +80,34 @@ function* createHit(action) { } } +/** + * 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, `${BUILDING_SERVICE_URL}/turkhit/${action.buildingId}`, { + method: 'PUT', + headers: HEADERS, + 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/BuildingDetail/styles.scss b/src/containers/BuildingOverview/styles.scss similarity index 100% rename from src/containers/BuildingDetail/styles.scss rename to src/containers/BuildingOverview/styles.scss diff --git a/src/reducers.js b/src/reducers.js index 3568c2e97cbcec614ecf80980febf3020f658e45..82192a2c5c1b8cb9cfca1170b836e3fc470d3cb5 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -2,10 +2,10 @@ import { combineReducers } from 'redux'; import { routerReducer } from 'react-router-redux'; import BuildingListReducer from './containers/BuildingList/reducer'; -import BuildingDetailReducer from './containers/BuildingDetail/reducer'; +import BuildingOverviewReducer from './containers/BuildingOverview/reducer'; export default combineReducers({ routing: routerReducer, buildingList: BuildingListReducer, - buildingDetail: BuildingDetailReducer, + buildingDetail: BuildingOverviewReducer, }); diff --git a/src/routes.js b/src/routes.js index a86d916e0ce21d33dccf0784fe09d433cbe9ad09..7e471c18c575a6168cf46f3ff9edfba965dfeccd 100644 --- a/src/routes.js +++ b/src/routes.js @@ -1,17 +1,26 @@ import React from 'react'; import { Route, IndexRoute, IndexRedirect } from 'react-router'; + +import BuildingDetail from './screens/BuildingDetail'; import BuildingList from './containers/BuildingList'; -import BuildingDetail from './containers/BuildingDetail'; -import BuildingOverview from './components/BuildingOverview'; +import BuildingOverview from './containers/BuildingOverview'; +import NotFound from './screens/NotFound'; +import Dummy from './components/dummyComponent'; export default ( - - + + - + + + + + + + ); diff --git a/src/sagas.js b/src/sagas.js index 644286f84cd58aca32892992442cbcdb1562dde0..09714c28f5379d808a6964ddd7c9f85c5a863d00 100644 --- a/src/sagas.js +++ b/src/sagas.js @@ -1,7 +1,7 @@ -import buildingDetailSaga from './containers/BuildingDetail/sagas'; +import buildingOverviewSaga from './containers/BuildingOverview/sagas'; export default function* rootSaga() { yield [ - buildingDetailSaga(), + buildingOverviewSaga(), ]; } diff --git a/src/screens/BuildingDetail/index.js b/src/screens/BuildingDetail/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8c3f4d9418af00a3744d8fd001f32965c7a64ad3 --- /dev/null +++ b/src/screens/BuildingDetail/index.js @@ -0,0 +1,23 @@ +import React, { PropTypes } from 'react'; +import SideBarDetail from '../../components/SideBarDetail'; + + +export default function BuildingDetail(props) { + return ( +
+
+ +
+
+ {props.children} +
+
+ ); +} + +BuildingDetail.propTypes = { + children: PropTypes.element, + params: PropTypes.shape({ + buildingID: PropTypes.string, + }), +}; diff --git a/src/screens/BuildingDetail/styles.scss b/src/screens/BuildingDetail/styles.scss new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/screens/NotFound/index.js b/src/screens/NotFound/index.js new file mode 100644 index 0000000000000000000000000000000000000000..b67b113bd2dabade0f4b1cfe6ffccc2022a7767c --- /dev/null +++ b/src/screens/NotFound/index.js @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function NotFound() { + return

Page Not Found!

; +}