From 688751999be74880da9498ebb74f2066bcc6c05e Mon Sep 17 00:00:00 2001 From: Lisa Cho Date: Wed, 16 Mar 2016 00:17:08 -0700 Subject: [PATCH] My opinions followed stop following and ignore buttons work and refactored voterguidestore --- src/js/actions/.BallotActions.js | 84 --- src/js/actions/GuideActions.js | 53 +- src/js/components/FollowOrIgnore.jsx | 69 +- src/js/components/VoterGuide/GuideList.jsx | 83 +-- .../components/VoterGuide/VoterGuideItem.jsx | 41 +- src/js/routes/More/OpinionsFollowed.jsx | 33 +- src/js/routes/Opinions.jsx | 33 +- src/js/routes/Requests.jsx | 1 - src/js/stores/.BallotStore.js | 681 ------------------ src/js/stores/GuideStore.js | 161 +++-- src/js/stores/VoterGuideStore.js | 321 --------- 11 files changed, 186 insertions(+), 1374 deletions(-) delete mode 100644 src/js/actions/.BallotActions.js delete mode 100644 src/js/stores/.BallotStore.js delete mode 100644 src/js/stores/VoterGuideStore.js diff --git a/src/js/actions/.BallotActions.js b/src/js/actions/.BallotActions.js deleted file mode 100644 index 29b8f02e0..000000000 --- a/src/js/actions/.BallotActions.js +++ /dev/null @@ -1,84 +0,0 @@ -"use strict"; -var AppDispatcher = require("../dispatcher/AppDispatcher"); -var BallotConstants = require("../constants/BallotConstants"); - -// In the stores, there are AppDispatcher blocks that listen for these actionType constants (ex/ VOTER_SUPPORTING_SAVE) -// When action calls one of these functions, we are telling the code in the AppDispatcher block to run -module.exports = { - - // positionsRetrieved: function (we_vote_id, payload) { - // AppDispatcher.dispatch({ - // actionType: BallotConstants.POSITIONS_RETRIEVED, - // payload: payload, - // we_vote_id: we_vote_id - // }); - // }, - // - // starStatusRetrieved: function (we_vote_id, payload) { - // AppDispatcher.dispatch({ - // actionType: BallotConstants.STAR_STATUS_RETRIEVED, - // payload: payload, - // we_vote_id: we_vote_id - // }); - // }, - - candidateItemRetrieved: function (we_vote_id, parameter, parameter_alias, payload) { // CANDIDATE_DETAIL_RETRIEVED - AppDispatcher.dispatch({ - actionType: BallotConstants.CANDIDATE_DETAIL_RETRIEVED, - payload: payload, - parameter: parameter, - parameter_alias: parameter_alias, - we_vote_id: we_vote_id - }); - }, - - candidateRetrieved: function (payload) { // CANDIDATE_RETRIEVED - AppDispatcher.dispatch({ - actionType: BallotConstants.CANDIDATE_RETRIEVED, - payload: payload, - we_vote_id: payload.we_vote_id - }); - }, - - voterSupportingSave: function (we_vote_id) { // VOTER_SUPPORTING_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_SUPPORTING_SAVE, - we_vote_id - }); - }, - - voterStopSupportingSave: function (we_vote_id) { // VOTER_STOP_SUPPORTING_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_STOP_SUPPORTING_SAVE, - we_vote_id - }); - }, - - voterOpposingSave: function (we_vote_id) { // VOTER_OPPOSING_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_OPPOSING_SAVE, - we_vote_id - }); - }, - - voterStopOpposingSave: function (we_vote_id) { // VOTER_STOP_OPPOSING_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_STOP_OPPOSING_SAVE, - we_vote_id - }); - }, - - voterStarOnSave: function (we_vote_id) { // VOTER_STAR_ON_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_STAR_ON_SAVE, - we_vote_id - }); - }, - - voterStarOffSave: function (we_vote_id) { // VOTER_STAR_OFF_SAVE - AppDispatcher.dispatch({ - actionType: BallotConstants.VOTER_STAR_OFF_SAVE, - we_vote_id - }); - } -}; diff --git a/src/js/actions/GuideActions.js b/src/js/actions/GuideActions.js index 2716ae666..101c8ccfb 100644 --- a/src/js/actions/GuideActions.js +++ b/src/js/actions/GuideActions.js @@ -1,24 +1,29 @@ -import AppDispatcher from "../dispatcher/AppDispatcher"; -import GuideConstants from "../constants/GuideConstants"; - -const GuideActions = { - /** - * @param {String} id to ignore - */ - ignore: function (id) { - AppDispatcher.dispatch({ - actionType: GuideConstants.ORG_IGNORE, id - }); - }, - - /** - * @param {String} id to follow - */ - follow: function (id) { - AppDispatcher.dispatch({ - actionType: GuideConstants.ORG_FOLLOW, id - }); - } -}; - -export default GuideActions; +var Dispatcher = require("../dispatcher/Dispatcher"); + +var GuideActions = (function (_Dispatcher) { + function _GuideActions () { } + + _GuideActions.prototype.ignore = function ignore (we_vote_id) { + _Dispatcher.loadEndpoint("organizationFollowIgnore", { organization_we_vote_id: we_vote_id} ); + }; + + _GuideActions.prototype.follow = function follow (we_vote_id) { + _Dispatcher.loadEndpoint("organizationFollow", { organization_we_vote_id: we_vote_id} ); + }; + + _GuideActions.prototype.stopFollowing = function stopFollowing (we_vote_id) { + _Dispatcher.loadEndpoint("organizationStopFollowing", { organization_we_vote_id: we_vote_id} ); + }; + + _GuideActions.prototype.retrieveGuidesToFollow = function retrieveGuidesToFollow (election_id){ + _Dispatcher.loadEndpoint("voterGuidesToFollowRetrieve", { google_civic_election_id: election_id }); + }; + + _GuideActions.prototype.retrieveGuidesFollowed = function retrieveGuidesFollowed (){ + _Dispatcher.loadEndpoint("voterGuidesFollowedRetrieve"); + }; + + return new _GuideActions(); +}(Dispatcher)); + +module.exports = GuideActions; diff --git a/src/js/components/FollowOrIgnore.jsx b/src/js/components/FollowOrIgnore.jsx index 4f80aa6ab..c1f1615b7 100644 --- a/src/js/components/FollowOrIgnore.jsx +++ b/src/js/components/FollowOrIgnore.jsx @@ -1,79 +1,26 @@ "use strict"; - import React, { Component, PropTypes } from "react"; import { Button, ButtonToolbar } from "react-bootstrap"; -import VoterGuideStore from "../stores/VoterGuideStore"; +import GuideActions from "../actions/GuideActions"; export default class FollowOrIgnore extends Component { static propTypes = { - organization_we_vote_id: PropTypes.string, - action: PropTypes.object.isRequired, - action_text: PropTypes.string, - OrganizationFollowed: PropTypes.string + organization_we_vote_id: PropTypes.string.isRequired, }; - constructor(props) { - super(props); - - this.state = { - OrganizationFollowed: this.props.OrganizationFollowed, - }; - } - - toggleFollow (evt) { - evt.stopPropagation(); - if (this.state.OrganizationFollowed == "Yes") - this.props.action.stopFollowingOrg(this.props.organization_we_vote_id); - else - this.props.action.followOrg(this.props.organization_we_vote_id); - } - - ignoreOrgLocal (evt) { - evt.stopPropagation(); - this.props.action.ignoreOrg(this.props.organization_we_vote_id); - } + render () { + var ignoreFunc = GuideActions.ignore.bind(this, this.props.organization_we_vote_id); + var stopFollowingFunc = GuideActions.stopFollowing.bind(this, this.props.organization_we_vote_id); - componentDidMount () { - this.changeListener = this._onChange.bind(this); - VoterGuideStore.addChangeListener(this.changeListener); - } - - componentWillUnmount() { - VoterGuideStore.removeChangeListener(this.changeListener); - } - - _onChange () { - VoterGuideStore.getVoterGuideByWeVoteId( - this.props.we_vote_id, voter_guide => this.setState({ - OrganizationFollowed: voter_guide.OrganizationFollowed, - }) - ); - } - - render() { var floatRight = { float: "right" }; - var action_text; - if (this.props.action_text) { - action_text = this.props.action_text; - } else { - if (this.state.OrganizationFollowed == "Yes") { - action_text = "Followed"; - } else { - action_text = "Follow"; - } - } - var ignore_code; - if (this.state.OrganizationFollowed != "Yes") { - ignore_code = - } - + return ( - - {ignore_code} + + ); diff --git a/src/js/components/VoterGuide/GuideList.jsx b/src/js/components/VoterGuide/GuideList.jsx index cb39bb795..e76ad1c48 100644 --- a/src/js/components/VoterGuide/GuideList.jsx +++ b/src/js/components/VoterGuide/GuideList.jsx @@ -1,8 +1,6 @@ import React, { Component, PropTypes } from "react"; import ReactCSSTransitionGroup from "react-addons-css-transition-group"; import Organization from "./Organization"; - -import GuideStore from "../../stores/GuideStore"; import GuideActions from "../../actions/GuideActions"; export default class GuideList extends Component { @@ -11,88 +9,33 @@ export default class GuideList extends Component { organizations: PropTypes.array }; - constructor (props) { - super(props); - - var { organizations: orgs } = this.props; - - /** - * this is being done because of issue #85... - * https://github.com/wevote/WeVoteServer/issues/85 - - * READ: - * -- GuideStore is naturally unique per item key - * -- so... store data and then convert it to an array - - * SEE BELOW: - * GuideStore.addOrganization - * then -> - * GuideStore.toArray() - - * this is inefficient but it needs to be done to create unique - * organizations in the list because the backend is not unique. - */ - - orgs.forEach(GuideStore.addOrganization); - this.state = { orgList: GuideStore.toArray() }; - - } - - componentDidMount () { - GuideStore.addChangeListener(this.storeChange.bind(this)); - } - - componentWillUnmount () { - GuideStore.removeChangeListener(this.storeChange.bind(this)); - } - - storeChange () { - this.setState({ orgList: GuideStore.toArray() }); - } - /** - * when a user clicks ignore, make the org disappear - * @param {Integer} i index in array of the item clicked + * when a user clicks ignore or follow, make the org disappear */ - handleIgnore (i) { - - var { - organization_we_vote_id: id - } = this.state.orgList.slice().splice(i, 1)[0]; - + handleIgnore (id) { GuideActions.ignore(id); - } - handleFollow (i) { - var { - organization_we_vote_id: id - } = this.state.orgList.slice().splice(i, 1)[0]; - + handleFollow (id) { GuideActions.follow(id); } render () { - let orgs = this.state.orgList.map( (org, i) => { - - var { - organization_we_vote_id: id, - voter_guide_display_name: displayName, - voter_guide_image_url: imageUrl, - twitter_followers_count: followers - } = org; - - // Key can be id once issue #85 is resolved on server - // https://github.com/wevote/WeVoteServer/issues/85 - const key = id + "-" + i; + let orgs = this.props.organizations.map( (org, i) => { const organization = - - - ; diff --git a/src/js/components/VoterGuide/VoterGuideItem.jsx b/src/js/components/VoterGuide/VoterGuideItem.jsx index 10ef5a149..c3ec9d5c0 100644 --- a/src/js/components/VoterGuide/VoterGuideItem.jsx +++ b/src/js/components/VoterGuide/VoterGuideItem.jsx @@ -1,9 +1,7 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component, PropTypes } from "react"; import FollowOrIgnore from "../../components/FollowOrIgnore"; -import VoterGuideActions from '../../actions/VoterGuideActions'; -import VoterGuideStore from '../../stores/VoterGuideStore'; -function numberWithCommas(x) { +function numberWithCommas (x) { var parts = x.toString().split("."); parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ","); return parts.join("."); @@ -24,35 +22,7 @@ export default class VoterGuideItem extends Component { OrganizationIgnored: PropTypes.string }; - constructor (props) { - super(props); - - this.state = {} - } - - componentDidMount () { - this.state = { - OrganizationFollowed: null, - OrganizationIgnored: null - }; - this.changeListener = this._onChange.bind(this); - VoterGuideStore.addChangeListener(this.changeListener); - } - - componentWillUnmount() { - VoterGuideStore.removeChangeListener(this.changeListener); - } - - _onChange () { - VoterGuideStore.getVoterGuideByWeVoteId( - this.props.we_vote_id, voter_guide_item => this.setState({ - OrganizationFollowed: voter_guide_item.OrganizationFollowed, - OrganizationIgnored: voter_guide_item.OrganizationIgnored - }) - ); - } - - render() { + render () { var twitterFollowers; var twitterFollowersCount = numberWithCommas(this.props.twitter_followers_count); if (this.props.twitter_followers_count) { @@ -76,13 +46,12 @@ export default class VoterGuideItem extends Component { { this.props.voter_guide_display_name }
- +
{twitterFollowers}
- ) + ); } } diff --git a/src/js/routes/More/OpinionsFollowed.jsx b/src/js/routes/More/OpinionsFollowed.jsx index 88101a2ed..207128b33 100755 --- a/src/js/routes/More/OpinionsFollowed.jsx +++ b/src/js/routes/More/OpinionsFollowed.jsx @@ -1,8 +1,8 @@ import React, {Component, PropTypes } from "react"; - -import VoterGuideStore from "../../stores/VoterGuideStore"; +import ReactCSSTransitionGroup from "react-addons-css-transition-group"; +import GuideStore from "../../stores/GuideStore"; +import GuideActions from "../../actions/GuideActions"; import VoterGuideItem from "../../components/VoterGuide/VoterGuideItem"; - import LoadingWheel from "../../components/LoadingWheel"; /* VISUAL DESIGN HERE: https://invis.io/8F53FDX9G */ @@ -18,13 +18,23 @@ export default class OpinionsFollowed extends Component { } componentDidMount () { - VoterGuideStore.initializeGuidesFollowed( function (voter_guide_followed_list) { - if (voter_guide_followed_list !== undefined && voter_guide_followed_list.length > 0){ - this.setState({ voter_guide_followed_list }); - } else { - this.props.history.push("/opinions"); - } - }.bind(this)); + this.listener = GuideStore.addListener(this._onChange.bind(this)); + GuideActions.retrieveGuidesFollowed(); + } + + componentWillUnmount (){ + this.listener.remove(); + } + + _onChange (){ + var list = GuideStore.followedList(); + + if (list !== undefined && list.length > 0){ + this.setState({ voter_guide_followed_list: GuideStore.followedList() }); + } else { + this.props.history.push("/opinions"); + } + } render () { @@ -36,13 +46,14 @@ export default class OpinionsFollowed extends Component { placeholder="Search by name or twitter handle." />
*/}
+ { this.state.voter_guide_followed_list ? this.state.voter_guide_followed_list.map( item => ) : LoadingWheel - } +
; diff --git a/src/js/routes/Opinions.jsx b/src/js/routes/Opinions.jsx index 19413230b..60abe4b6c 100755 --- a/src/js/routes/Opinions.jsx +++ b/src/js/routes/Opinions.jsx @@ -1,9 +1,9 @@ import React, {Component, PropTypes } from "react"; -import { $ajax } from "../utils/service"; - import LoadingWheel from "../components/LoadingWheel"; import BallotStore from "../stores/BallotStore"; +import GuideActions from "../actions/GuideActions"; +import GuideStore from "../stores/GuideStore"; import GuideList from "../components/VoterGuide/GuideList"; /* VISUAL DESIGN HERE: https://invis.io/TR4A1NYAQ */ @@ -21,34 +21,28 @@ export default class Opinions extends Component { } componentDidMount () { + this.listener = GuideStore.addListener(this._onChange.bind(this)); if (! this.electionId ) this.props.history.push("/ballot"); else - $ajax({ - endpoint: "voterGuidesToFollowRetrieve", - data: { "google_civic_election_id": this.electionId }, - - success: (res) => { - this.guideList = res.voter_guides; - this.setState({ loading: false }); - console.log(res); - }, - - error: (err) => { - console.error(err); - this.setState({ loading: false, error: true }); - } - }); + GuideActions.retrieveGuidesToFollow(this.electionId); + } + _onChange (){ + this.setState({ loading: false, error: false, guideList: GuideStore.toFollowList() }); + } + + componentWillUnmount (){ + this.listener.remove(); } render () { const EMPTY_TEXT = "You do not have a ballot yet!"; - const { loading, error } = this.state; - const { guideList, electionId } = this; + const { loading, error, guideList } = this.state; + const { electionId } = this; let guides; @@ -66,7 +60,6 @@ export default class Opinions extends Component { else if (guideList instanceof Array && guideList.length > 0) guides = ; - else guides = EMPTY_TEXT; diff --git a/src/js/routes/Requests.jsx b/src/js/routes/Requests.jsx index e2a3d6535..6cdd98032 100644 --- a/src/js/routes/Requests.jsx +++ b/src/js/routes/Requests.jsx @@ -1,7 +1,6 @@ import React, { Component } from 'react'; import FollowOrIgnore from '../components/FollowOrIgnore'; -import VoterGuideActions from '../actions/VoterGuideActions'; export default class RequestsPage extends Component { constructor(props) { diff --git a/src/js/stores/.BallotStore.js b/src/js/stores/.BallotStore.js deleted file mode 100644 index 4cd9a7a34..000000000 --- a/src/js/stores/.BallotStore.js +++ /dev/null @@ -1,681 +0,0 @@ -import { get } from "../utils/service"; -import { createStore } from "../utils/createStore"; -import { shallowClone } from "../utils/object-utils"; - -const AppDispatcher = require("../dispatcher/AppDispatcher"); -const BallotConstants = require("../constants/BallotConstants"); -const BallotActions = require("../actions/BallotActions"); - -let _ballot_store = {}; -let _ballot_order_ids = []; -let _google_civic_election_id = null; - -const MEASURE = "MEASURE"; - -function defaultSuccess (res) { /*console.warn(res);*/ return res; } - -function addItemById (id, item) { - _ballot_store[id] = item; -} - -const BallotAPIWorker = { - voterBallotItemsRetrieveFromGoogleCivic: function (text_for_map_search, success ) { - return get({ - endpoint: "voterBallotItemsRetrieveFromGoogleCivic", - query: { text_for_map_search }, success: success || defaultSuccess - }); - }, - - candidatesRetrieve: function (office_we_vote_id, success ) { - return get({ - endpoint: "candidatesRetrieve", - query: { office_we_vote_id: office_we_vote_id }, - success: success || defaultSuccess - }); - }, - - candidateRetrieve: function (we_vote_id, success ) { - return get({ - endpoint: "candidateRetrieve", - query: { candidate_we_vote_id: we_vote_id }, - success: success - }); - }, - - officeRetrieve: function (we_vote_id, success ) { - return get({ - endpoint: "officeRetrieve", - query: { office_we_vote_id: we_vote_id }, - success: success - }); - }, - - // get the ballot items - voterBallotItemsRetrieve: function ( success ) { - return get({ endpoint: "voterBallotItemsRetrieve", - success: success || defaultSuccess }); - }, - - positionListForBallotItem: function (id, kind_of_ballot_item, success) { - return get({ - endpoint: "positionListForBallotItem", - query: { - ballot_item_id: id, - kind_of_ballot_item: kind_of_ballot_item - }, - success: success || defaultSuccess - }); - }, - - positionOpposeCountForBallotItem: function (we_vote_id, success ) { - return get({ - endpoint: "positionOpposeCountForBallotItem", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - // get measure support an opposition - positionSupportCountForBallotItem: function (we_vote_id, success ) { - return get({ - endpoint: "positionSupportCountForBallotItem", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterPositionRetrieve: function ( ballot_item_we_vote_id, success ) { - return get({ - endpoint: "voterPositionRetrieve", - query: { - ballot_item_we_vote_id: ballot_item_we_vote_id, - kind_of_ballot_item: _ballot_store[ballot_item_we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterStarStatusRetrieve: function ( we_vote_id, success ) { - return get({ - endpoint: "voterStarStatusRetrieve", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterStarOnSave: function (we_vote_id, success ) { - console.log("voterStarOnSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterStarOnSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterStarOffSave: function (we_vote_id, success ) { - console.log("voterStarOffSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterStarOffSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterSupportingSave: function (we_vote_id, success ) { - console.log("voterSupportingSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterSupportingSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterStopSupportingSave: function (we_vote_id, success ) { - console.log("voterStopSupportingSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterStopSupportingSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterOpposingSave: function (we_vote_id, success ) { - console.log("voterOpposingSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterOpposingSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - }, - - voterStopOpposingSave: function (we_vote_id, success ) { - console.log("voterStopOpposingSave, we_vote_id:, ", we_vote_id); - return get({ - endpoint: "voterStopOpposingSave", - query: { - ballot_item_id: _ballot_store[we_vote_id].id, - kind_of_ballot_item: _ballot_store[we_vote_id].kind_of_ballot_item - }, success: success || defaultSuccess - }); - } - -}; - -const BallotStore = createStore({ - - /** - * initialize the ballot store with data, if no data - * and callback with the ordered items - * @return {Boolean} - */ - - initialize: function (callback) { - var promiseQueue = []; - var getOrderedBallotItems = this.getOrderedBallotItems.bind(this); - - if (!callback || typeof callback !== "function") - throw new Error("initialize must be called with callback"); - - // Do we have the Ballot data stored in the browser? - if (Object.keys(_ballot_store).length) - return callback(getOrderedBallotItems()); - - else { - - BallotAPIWorker - .voterBallotItemsRetrieve() - .then( (res) => { - - _google_civic_election_id = res.google_civic_election_id; - - addItemsToBallotStore( - res.ballot_item_list - ); - - _ballot_order_ids = res.ballot_item_list.map( (ballot) => ballot.we_vote_id ); - _google_civic_election_id = res.google_civic_election_id; - - _ballot_order_ids.forEach( we_vote_id => { - - promiseQueue - .push( - BallotAPIWorker - .voterStarStatusRetrieve(we_vote_id) - .then( (res) => _ballot_store[we_vote_id].is_starred = res.is_starred ) - ); - - if ( ballotItemIsMeasure(we_vote_id) ) { - promiseQueue - .push( - BallotAPIWorker - .positionOpposeCountForBallotItem( we_vote_id ) - ); - - promiseQueue - .push( - BallotAPIWorker - .positionSupportCountForBallotItem( we_vote_id ) - ); - - promiseQueue - .push( - BallotAPIWorker - .voterPositionRetrieve( we_vote_id ) - ); - - } else { // Ballot item is Office - - promiseQueue - .push( - - BallotAPIWorker - .candidatesRetrieve( we_vote_id ) - .then( (response) => { - var office_display_name = _ballot_store[response.office_we_vote_id].ballot_item_display_name; - var cand_list = _ballot_store [ - response.office_we_vote_id - ] . candidate_list = []; - - response - .candidate_list - .forEach( (candidate) => { - var { we_vote_id: candidate_we_vote_id } = candidate; - cand_list . push(candidate_we_vote_id); - _ballot_store [ candidate_we_vote_id ] = shallowClone( candidate ); - _ballot_store [ candidate_we_vote_id ].office_display_name = office_display_name; - - promiseQueue - .push( - BallotAPIWorker - .positionOpposeCountForBallotItem(candidate_we_vote_id) - .then( (res) => - _ballot_store [ - candidate_we_vote_id - ] . opposeCount = res.count - ) - ); - - promiseQueue - .push( - BallotAPIWorker - .positionSupportCountForBallotItem(candidate_we_vote_id) - .then( (res) => - _ballot_store [ - candidate_we_vote_id - ] . supportCount = res.count - ) - ); - - promiseQueue - .push( - BallotAPIWorker - .voterStarStatusRetrieve(candidate_we_vote_id) - .then( (res) => - _ballot_store [ - candidate_we_vote_id - ] . is_starred = res.is_starred - ) - ); - - promiseQueue - .push( - BallotAPIWorker - .voterPositionRetrieve(candidate_we_vote_id) - .then( (res) => { - _ballot_store [ - candidate_we_vote_id - ] . is_oppose = res.is_oppose; - - _ballot_store [ - candidate_we_vote_id - ] . is_support = res.is_support; - }) - ); - - - }); - }) - ); - } - }); - - //check for no results, then return empty array rather than creating promises from queue - if (res.ballot_item_list.length === 0 ){ - callback(getOrderedBallotItems()); - return; - } - - // this function polls requests for complete status. - new Promise( (resolve) => { - var counted = []; - var count = 0; - - var interval = setInterval( () => { - - res.ballot_item_list.forEach( (item) => { - var { we_vote_id } = item; - - item = _ballot_store [we_vote_id]; - - if ( ballotItemIsMeasure(we_vote_id) && counted.indexOf(we_vote_id) < 0 ) { - // We are incrementing by 4 because... ??? - count += 4; - counted.push(we_vote_id); - } else - if ( item.candidate_list && counted.indexOf(we_vote_id) < 0 ) { - // We are incrementing by 2 because... ??? - count += 2 + item.candidate_list.length * 4; - counted.push(we_vote_id); - } - }); - - if (count === promiseQueue.length && promiseQueue.length !== 0) { - clearInterval(interval); - Promise.all(promiseQueue).then(resolve); - } - - }, 1000); - - }).then(() => callback(getOrderedBallotItems())); - }); - } - }, - - getOrFetchCandidateByWeVoteId: function (candidate_we_vote_id) { - var candidate = this.getCandidateByWeVoteId(candidate_we_vote_id); - if (candidate && candidate.is_oppose && candidate.position_list) { //candidate already retrieved - return candidate; - } - _ballot_store[candidate_we_vote_id] = {}; - _ballot_store[candidate_we_vote_id].kind_of_ballot_item = "CANDIDATE"; - - BallotAPIWorker.candidateRetrieve(candidate_we_vote_id, function (res){ - BallotActions.candidateRetrieved(res); - BallotStore.fetchCandidateDetails(candidate_we_vote_id); - }); - - return _ballot_store[candidate_we_vote_id]; - }, - - fetchCandidateDetails: function (we_vote_id){ - this.fetchCandidateStarStatus(we_vote_id); - this.fetchCandidatePositions(we_vote_id); - this.fetchCandidateOffice(we_vote_id); - this.fetchCandidateOpposeCount(we_vote_id); - this.fetchCandidateSupportCount(we_vote_id); - this.fetchCandidateOpposeCount(we_vote_id); - }, - - fetchCandidatePositions: function (we_vote_id){ - BallotAPIWorker.positionListForBallotItem( - _ballot_store[we_vote_id].id, - _ballot_store[we_vote_id].kind_of_ballot_item).then( res => { - BallotActions.candidateItemRetrieved(we_vote_id, "position_list", "position_list", res); - }); - }, - - fetchCandidateStarStatus: function ( we_vote_id){ - BallotAPIWorker.voterStarStatusRetrieve(we_vote_id).then( (res) =>{ - BallotActions.candidateItemRetrieved(we_vote_id, "is_starred", "is_starred", res); - }); - }, - - fetchCandidateOffice: function (we_vote_id){ - var office_we_vote_id = _ballot_store[we_vote_id].contest_office_we_vote_id; - BallotAPIWorker.officeRetrieve(office_we_vote_id).then( res => { - BallotActions.candidateItemRetrieved(we_vote_id, "office_display_name", "ballot_item_display_name", res); - }); - }, - - fetchCandidateOpposeCount: function (we_vote_id){ - BallotAPIWorker.positionOpposeCountForBallotItem(we_vote_id).then( res => { - BallotActions.candidateItemRetrieved(we_vote_id, "opposeCount", "count", res); - }); - }, - - fetchCandidateSupportCount: function (we_vote_id){ - BallotAPIWorker.positionSupportCountForBallotItem(we_vote_id).then( res => { - BallotActions.candidateItemRetrieved(we_vote_id, "supportCount", "count", res); - }); - }, - - /** - * get ballot ordered key array and ballots - * @return {Object} ordered keys and store data - */ - getOrderedBallotItems: function () { - var temp = []; - _ballot_order_ids - .forEach( (id) => - temp - .push( - shallowClone( _ballot_store[id] ) - ) - ); - - return temp; - }, - - /** - * get the number of orgs and friends that the Voter follows who support this ballot item - * @param {String} we_vote_id ballot items we_vote_id - * @return {Boolean} is the item starred or not? - */ - getSupportCount: function (we_vote_id) { - return _ballot_store[we_vote_id].supportCount; - }, - - /** - * get the number of orgs and friends that the Voter follows who oppose this ballot item - * @param {String} we_vote_id ballot items we_vote_id - * @return {Boolean} is the item starred or not? - */ - getOpposeCount: function (we_vote_id) { - return _ballot_store[we_vote_id].opposeCount; - }, - - /** - * get the ballot item by its we_vote_id, and return whether the voter opposes or not - * @param {String} we_vote_id for the ballot item - * @return {Boolean} is the item supported by the voter or not? - */ - getIsSupportState: function (we_vote_id) { - return _ballot_store[we_vote_id].is_support; - }, - - /** - * get the ballot item by its we_vote_id, and return whether the voter opposes or not - * @param {String} we_vote_id for the ballot item - * @return {Boolean} is the item opposed by voter or not? - */ - getIsOpposeState: function (we_vote_id) { - return _ballot_store[we_vote_id].is_oppose; - }, - - /** - * get the ballot item by its we_vote_id, and return whether the voter has starred it or not - * @param {String} we_vote_id for the ballot item - * @return {Boolean} is the item opposed by voter or not? - */ - getStarState: function (we_vote_id) { - return _ballot_store[we_vote_id].is_starred; - }, - - getCandidateByWeVoteId: function (candidate_we_vote_id) { - return shallowClone( - _ballot_store [ candidate_we_vote_id ] - ) || null; - }, - - getBallotItemByWeVoteId: function (ballot_item_we_vote_id) { - return shallowClone( - _ballot_store [ ballot_item_we_vote_id ] - ) || null; - }, - - /** - * return ballot item object by we_vote_id - * @param {String} we_vote_id for office or measure - * @return {Object} office or measure - */ - getCandidateById: function (office_we_vote_id, candidate_we_vote_id) { - return _ballot_store [ - office_we_vote_id - ] . candidate_list.indexOf(candidate_we_vote_id) > -1 ? - shallowClone( _ballot_store[candidate_we_vote_id] ) : undefined; - }, - - getCandidatesForBallot: function (office_we_vote_id) { - return _ballot_store [ - office_we_vote_id - ].candidate_list.map( candidate_we_vote_id => this.getCandidateById(office_we_vote_id, candidate_we_vote_id) ) || undefined; - }, - - /** - * return google_civic_election_id - * @return {String} google_civic_election_id - */ - getGoogleCivicElectionId: function () { - return _google_civic_election_id; - } -}); - - -// These methods are used by the AppDispatcher code to change variables in the store -function addItemsToBallotStore (ballot_item_list) { - ballot_item_list.forEach( ballot_item => { - _ballot_store[ballot_item.we_vote_id] = shallowClone(ballot_item); - _ballot_store[ballot_item.we_vote_id].opposeCount = 0; - _ballot_store[ballot_item.we_vote_id].supportCount = 0; - }); -} - -function ballotItemIsMeasure (we_vote_id) { - return _ballot_store[we_vote_id].kind_of_ballot_item === MEASURE; -} - -function setCandidateDetail (we_vote_id, parameter, alias, payload) { - _ballot_store[we_vote_id][parameter] = payload[alias]; - return true; -} - -function addCandidateToStore (res) { - _ballot_store[res.we_vote_id] = res; - _ballot_store[res.we_vote_id].kind_of_ballot_item = "CANDIDATE"; - return true; -} - - /** - * toggle the star state of a ballot item by its we_vote_id - * @param {string} we_vote_id identifier for lookup in stored - * @return {Boolean} starred or not starred - */ -function toggleStarState (we_vote_id) { - var item = _ballot_store[we_vote_id]; - item.is_starred = ! item.is_starred; - console.log(item.is_starred); - return true; -} - - /** - * toggle the support state of a ballot item to on by its we_vote_id - */ -function setLocalSupportOnState (we_vote_id) { - var item = _ballot_store[we_vote_id]; - //console.log("setLocalSupportOnState BEFORE, is_support:", item.is_support, ", supportCount", item.supportCount); - if (item.is_support !== true) { - // Cheat and increase the counter without hitting the API - item.supportCount += 1; - } - item.is_support = true; - //console.log("setLocalSupportOnState AFTER, is_support:", item.is_support, ", supportCount", item.supportCount); - return true; -} - - /** - * toggle the support state of a ballot item to off by its we_vote_id - */ -function setLocalSupportOffState (we_vote_id) { - var item = _ballot_store[we_vote_id]; - //console.log("setLocalSupportOffState BEFORE, is_support:", item.is_support, ", supportCount", item.supportCount); - if (item.is_support === true) { - // Cheat and decrease the counter without hitting the API - item.supportCount -= 1; - } - item.is_support = false; - //console.log("setLocalSupportOffState AFTER, is_support:", item.is_support, ", supportCount", item.supportCount); - return true; -} - - /** - * toggle the oppose state of a ballot item to On by its we_vote_id - */ -function setLocalOpposeOnState (we_vote_id) { - var item = _ballot_store[we_vote_id]; - //console.log("setLocalOpposeOnState BEFORE, is_oppose:", item.is_oppose, ", opposeCount", item.opposeCount); - if (item.is_oppose !== true) { - // Cheat and increase the counter without hitting the API - item.opposeCount += 1; - } - item.is_oppose = true; - //console.log("setLocalOpposeOnState AFTER, is_oppose:", item.is_oppose, ", opposeCount", item.opposeCount); - return true; -} - - /** - * toggle the oppose state of a ballot item to Off by its we_vote_id - */ -function setLocalOpposeOffState (we_vote_id) { - var item = _ballot_store[we_vote_id]; - //console.log("setLocalOpposeOffState BEFORE, is_oppose:", item.is_oppose, ", opposeCount", item.opposeCount); - if (item.is_oppose === true) { - // Cheat and decrease the counter without hitting the API - item.opposeCount -= 1; - } - item.is_oppose = false; - //console.log("setLocalOpposeOffState AFTER, is_oppose:", item.is_oppose, ", opposeCount", item.opposeCount); - return true; -} - -// This block is reacting to actions triggered in BallotActions.js. We update store variables, and then emitChange -BallotStore.dispatchToken = AppDispatcher.register( action => { - var { we_vote_id } = action; - switch (action.actionType) { - - case BallotConstants.BALLOT_ITEM_ADDED: - addItemById(action.id, action.item); - BallotStore.emitChange(); - break; - - case BallotConstants.CANDIDATE_DETAIL_RETRIEVED: - setCandidateDetail(action.we_vote_id, action.parameter, action.parameter_alias, action.payload); - BallotStore.emitChange(); - break; - - case BallotConstants.CANDIDATE_RETRIEVED: - addCandidateToStore(action.payload); - BallotStore.emitChange(); - break; - - case BallotConstants.VOTER_SUPPORTING_SAVE: - BallotAPIWorker.voterSupportingSave( - we_vote_id, () => setLocalSupportOnState(we_vote_id) && - setLocalOpposeOffState(we_vote_id) && - BallotStore.emitChange() - ); - break; - - case BallotConstants.VOTER_STOP_SUPPORTING_SAVE: - BallotAPIWorker.voterStopSupportingSave( - we_vote_id, () => setLocalSupportOffState(we_vote_id) && - BallotStore.emitChange() - ); - break; - case BallotConstants.VOTER_OPPOSING_SAVE: - BallotAPIWorker.voterOpposingSave( - we_vote_id, () => setLocalOpposeOnState(we_vote_id) && - setLocalSupportOffState(we_vote_id) && - BallotStore.emitChange() - ); - break; - case BallotConstants.VOTER_STOP_OPPOSING_SAVE: - BallotAPIWorker.voterStopOpposingSave( - we_vote_id, () => setLocalOpposeOffState(we_vote_id) && - BallotStore.emitChange() - ); - break; - case BallotConstants.VOTER_STAR_ON_SAVE: - BallotAPIWorker - .voterStarOnSave( - we_vote_id, () => toggleStarState(we_vote_id) && - BallotStore.emitChange() - ); - break; - case BallotConstants.VOTER_STAR_OFF_SAVE: - BallotAPIWorker - .voterStarOffSave( - we_vote_id, () => toggleStarState(we_vote_id) && - BallotStore.emitChange() - ); - break; - default: - break; - } -}); - -export default BallotStore; diff --git a/src/js/stores/GuideStore.js b/src/js/stores/GuideStore.js index 203a45660..bd0c366f1 100644 --- a/src/js/stores/GuideStore.js +++ b/src/js/stores/GuideStore.js @@ -1,77 +1,108 @@ -import AppDispatcher from "../dispatcher/AppDispatcher"; -import GuideConstants from "../constants/GuideConstants"; - -import { $ajax } from "../utils/service"; -import { createStore } from "../utils/createStore"; - -const _guide_store = {}; - -const GuideStore = createStore({ - addOrganization: function (org) { - _guide_store[org.organization_we_vote_id] = org; - }, - - toArray: function () { - var t = []; - - Object.keys(_guide_store).forEach( (id) => { - if (_guide_store.hasOwnProperty(id)) - t.push(_guide_store[id]); - }); - - return t; - } -}); - -const we_vote_id = "organization_we_vote_id"; +var Dispatcher = require("../dispatcher/Dispatcher"); +var FluxMapStore = require("flux/lib/FluxMapStore"); +class GuideStore extends FluxMapStore { + +/* The store keeps nested attributes of voter guides in data, whereas the followed, ignoring, to_follow are just lists of ids.*/ + getInitialState () { + return { + following: [], + ignoring: [], + to_follow: [], + data: {} + }; + } -GuideStore.dispatchToken = - AppDispatcher.register( (action) => { - switch (action.actionType) { - case GuideConstants.ORG_IGNORE: +/* Given a list of ids, retrieve the complete data with all attributes and return as array */ + getOrgsFromArr (arr) { + var state = this.getState(); + var orgs = []; + // voterGuidesFollowedRetrieve API returns more than one voter guide per organization some times. + var uniq_arr = arr.filter( (value, index, self) => { return self.indexOf(value) === index; }); + uniq_arr.forEach( id => { + orgs.push( state.data[id] ); + }); + return orgs; + } - $ajax({ - endpoint: "organizationFollowIgnore", - data: { [we_vote_id]: action.id }, + toFollowList () { + return this.getOrgsFromArr(this.getState().to_follow); + } - success: (res) => { - const { organization_we_vote_id: id, success } = res; + followedList (){ + return this.getOrgsFromArr(this.getState().following); + } - if (success) { - delete _guide_store[id]; - GuideStore.emitChange(); - } - }, + reduce (state, action) { + var voter_guides; + var data; + var id; - error: (err) => console.error(err) + switch (action.type) { + case "voterGuidesToFollowRetrieve": + voter_guides = action.res.voter_guides; + data = state.data; + var to_follow = []; + voter_guides.forEach( item => { + data[item.organization_we_vote_id] = item; + to_follow.push(item.organization_we_vote_id); }); - - break; - - case GuideConstants.ORG_FOLLOW: - - $ajax({ - endpoint: "organizationFollow", - data: { [we_vote_id]: action.id }, - - success: (res) => { - const { organization_we_vote_id: id, success } = res; - - if (success) { - delete _guide_store[id]; - GuideStore.emitChange(); - } - }, - - error: (err) => console.error(err) - + return { + ...state, + to_follow: to_follow, + data: data + }; + + case "voterGuidesFollowedRetrieve": + voter_guides = action.res.voter_guides; + data = state.data; + var following = []; + voter_guides.forEach( item => { + data[item.organization_we_vote_id] = item; + following.push(item.organization_we_vote_id); }); - break; + return { + ...state, + following: following, + data: data + }; + + case "organizationFollow": + id = action.res.organization_we_vote_id; + return { + ...state, + following: state.following.concat(id), + to_follow: state.to_follow.filter( el => { return el !== id; }), + ignoring: state.ignoring.filter( el => { return el !== id; }) + }; + + case "organizationStopFollowing": + id = action.res.organization_we_vote_id; + return { + ...state, + following: state.following.filter( el => { return el !== id; }), + to_follow: state.to_follow.concat(id) + }; + + case "organizationFollowIgnore": + id = action.res.organization_we_vote_id; + return { + ...state, + ignoring: state.ignoring.concat(id), + to_follow: state.to_follow.filter( el => { return el !== id; }), + following: state.following.filter( el => { return el !== id; }) + }; + + case "error-organizationFollowIgnore" || "error-organizationFollow": + console.log(action); + return state; default: - break; + return state; } - }); -export default GuideStore; + } + +} + +module.exports = new GuideStore(Dispatcher); diff --git a/src/js/stores/VoterGuideStore.js b/src/js/stores/VoterGuideStore.js deleted file mode 100644 index 98f510ff1..000000000 --- a/src/js/stores/VoterGuideStore.js +++ /dev/null @@ -1,321 +0,0 @@ -import BallotStore from "../stores/BallotStore"; -import { createStore } from "../utils/createStore"; -import { shallowClone } from "../utils/object-utils"; - -const AppDispatcher = require("../dispatcher/AppDispatcher"); -const VoterGuideConstants = require("../constants/VoterGuideConstants"); - -const cookies = require("../utils/cookies"); -const request = require("superagent"); -const web_app_config = require("../config"); - -let _organization_store = {}; -let _organization_list = []; // A summary of all organizations (list of organization we_vote_id's) -let _voter_guide_store = {}; -//let _voter_guide_list = []; // A summary of all voter_guides (list of organization we_vote_id's) -let _voter_guides_to_follow_order = []; -let _voter_guides_to_follow_list = []; // A summary of all voter guides to follow (list of voter guide we_vote_id's) -//let _voter_guides_to_ignore_list = []; // A summary of voter guides to follow (list of voter guide we_vote_id's) -let _voter_guides_followed_order = []; -let _voter_guides_followed_list = []; // A summary of voter guides already followed (list of voter guide we_vote_id's) - - -//.query({ ballot_item_we_vote_id: "wv01cand2968" }) -//.query({ kind_of_ballot_item: "CANDIDATE" }) -function retrieveVoterGuidesToFollowList () { - console.log(BallotStore.getGoogleCivicElectionId()); - return new Promise( (resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}voterGuidesToFollowRetrieve/`) - .withCredentials() - .query(web_app_config.test) - .query({ google_civic_election_id: BallotStore.getGoogleCivicElectionId() }) - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .end( function (err, res) { - if (err || !res.body.success) - reject(err || res.body.status); - - console.log("retrieveVoterGuidesToFollowList SUCCESS"); - resolve(res.body); - }) - ); -} - -function addVoterGuidesToFollowToVoterGuideStore (data) { - console.log("ENTERING addVoterGuidesToFollowToVoterGuideStore"); - data.voter_guides.forEach( item => { - _voter_guide_store[item.we_vote_id] = shallowClone(item); - _voter_guides_to_follow_order.push(item.we_vote_id); - _voter_guides_to_follow_list.push(item.we_vote_id); - _organization_list.push(item.organization_we_vote_id); // To be retrieved in retrieveOrganizations - }); - console.log("addVoterGuidesToFollowToVoterGuideStore SUCCESS"); - - return data; -} - -function retrieveVoterGuidesFollowedList () { - return new Promise( (resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}voterGuidesFollowedRetrieve/`) - .withCredentials() - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .end( function (err, res) { - if (err || !res.body.success){ - reject(res.body); - // reject(err || res.body.status); - console.log("Reached out to retrieveVoterGuidesFollowedList"); - } else { - resolve(res.body); - } - }) - ); -} - -function addVoterGuidesFollowedToVoterGuideStore (data) { - console.log("ENTERING addVoterGuidesFollowedToVoterGuideStore"); - data.voter_guides.forEach( item => { - _voter_guide_store[item.we_vote_id] = shallowClone(item); - _voter_guides_followed_order.push(item.we_vote_id); - _voter_guides_followed_list.push(item.we_vote_id); - }); - - return data; -} - -// Cycle through the list of organizations that we know we need, and request the organization information -function retrieveOrganizations (data) { - var organizations_count = 0; - - return new Promise( (resolve, reject) => _organization_list - .forEach(we_vote_id => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}organizationRetrieve/`) - .withCredentials() - .query({ organization_we_vote_id: we_vote_id }) - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .end( function (err, res) { - if (res.body.success) { - _organization_store[res.body.organization_we_vote_id] = shallowClone(res.body); - } - else if (err) throw err || res.body; - - organizations_count ++; - - if (organizations_count === _organization_list.length) { - console.log("retrieveOrganizations FOUND ALL"); - resolve(data); - } - }) - ) - ); -} - -function retrieveOrganizationsFollowedList () { - return new Promise( (resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}organizationsFollowedRetrieve/`) - .withCredentials() - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .end( function (err, res) { - if (err || !res.body.success) - reject(err || res.body.status); - - resolve(res.body); - }) - ); -} - -function addOrganizationsFollowedToStore (data) { - data.organization_list.forEach( item => { - _organization_store[item.organization_we_vote_id] = shallowClone(item); - _organization_list.push(item.organization_we_vote_id); - }); - - return data; -} - -function followOrganization (we_vote_id) { - console.log("followOrganization: " + we_vote_id + ", id: " + _organization_store[we_vote_id].organization_id); - return new Promise((resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}organizationFollow/`) - .withCredentials() - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .query({ organization_id: _organization_store[we_vote_id].organization_id }) - .end( function (err, res) { - if (res.body.success) { - _organization_store[we_vote_id].OrganizationFollowed = "Yes"; - _organization_store[we_vote_id].OrganizationIgnored = "No"; - } - else if (err) - reject(err || res.body.status); - - resolve(res.body); - }) - ); -} - -function ignoreOrganization (we_vote_id) { - console.log("ignoreOrganization: " + we_vote_id); - return new Promise((resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}organizationFollowIgnore/`) - .withCredentials() - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .query({ organization_id: _organization_store[we_vote_id].organization_id }) - .end( function (err, res) { - if (res.body.success) { - _organization_store[we_vote_id].OrganizationFollowed = "No"; - _organization_store[we_vote_id].OrganizationIgnored = "Yes"; - } - else if (err) - reject(err || res.body.status); - - resolve(res.body); - }) - ); -} - -function stopFollowingOrganization (we_vote_id) { - console.log("stopFollowingOrganization: " + we_vote_id); - return new Promise((resolve, reject) => request - .get(`${web_app_config.WE_VOTE_SERVER_API_ROOT_URL}organizationStopFollowing/`) - .withCredentials() - .query({ voter_device_id: cookies.getItem("voter_device_id") }) - .query({ organization_id: _organization_store[we_vote_id].id }) - .end( function (err, res) { - if (res.body.success) { - _organization_store[we_vote_id].OrganizationFollowed = "No"; - } - else if (err) - reject(err || res.body.status); - - resolve(res.body); - }) - ); -} - -const VoterGuideStore = createStore({ - /** - * initialize the voter guide store with "guides to follow" data, if no data - * and callback with the ordered items - * @return {Boolean} - */ - initialize: function (callback) { - var getItems = this.getOrderedVoterGuides.bind(this); - - if (!callback || typeof callback !== "function") - throw new Error("initialize must be called with callback"); - - // Do we have Voter Guide data stored in the browser? - if (Object.keys(_voter_guides_to_follow_list).length) - callback(getItems()); - - else - // If here, we don't have any ballot items stored in the browser - - retrieveVoterGuidesToFollowList() - .then(addVoterGuidesToFollowToVoterGuideStore) // Uses data retrieved with retrieveVoterGuidesToFollowList - .then(retrieveOrganizations) - .then(data => callback(getItems())) - .catch(err => callback(err)); - }, - - /** - * initialize the voter guide store with "guides to follow" data, if no data - * and callback with the ordered items - * @return {Boolean} - */ - initializeGuidesFollowed: function (callback) { - console.log("ENTERED initializeGuidesFollowed"); - var getFollowedItems = this.getOrderedVoterGuidesFollowed.bind(this); - - if (!callback || typeof callback !== "function") - throw new Error("initialize must be called with callback"); - - // Do we have Voter Guide data stored in the browser? - if (Object.keys(_voter_guides_followed_list).length) { - console.log("(_voter_guides_followed_list).length): " + Object.keys(_voter_guides_followed_list).length); - callback(getFollowedItems()); - } - - else - // If here, we don't have any voter guides that have been followed that have been stored in the browser - retrieveVoterGuidesFollowedList() - .then(addVoterGuidesFollowedToVoterGuideStore) - .then(retrieveOrganizationsFollowedList) - .then(addOrganizationsFollowedToStore) // Uses data from retrieveOrganizationsFollowedList - .then(data => callback(getFollowedItems())) - .catch(err => callback(err)); - }, - - /** - * start with _voter_guides_to_follow_order, and create a new ordered array with the we_vote_id as the key, - * and the voter_guide as the value - * @return {Object} ordered keys and store data - */ - getOrderedVoterGuides: function () { - var temp = []; - _voter_guides_to_follow_order.forEach(we_vote_id => temp - .push(shallowClone(_voter_guide_store[we_vote_id])) - ); - return temp; - }, - - /** - * start with _voter_guides_to_follow_order, and create a new ordered array with the we_vote_id as the key, - * and the voter_guide as the value - * @return {Object} ordered keys and store data - */ - getOrderedVoterGuidesFollowed: function () { - var temp = []; - _voter_guides_followed_order.forEach(we_vote_id => temp - .push(shallowClone(_voter_guide_store[we_vote_id])) - ); - return temp; - }, - - /** - * return organization object by we_vote_id - * @param {String} we_vote_id for organization - * @return {Object} office or measure - */ - getOrganizationByWeVoteId: function (we_vote_id, callback) { - callback(shallowClone(_organization_store[we_vote_id])); - }, - - /** - * return voter_guide object by we_vote_id - * @param {String} we_vote_id for voter guide - * @return {Object} office or measure - */ - getVoterGuideByWeVoteId: function (we_vote_id, callback) { - callback(shallowClone(_voter_guide_store[we_vote_id])); - } -}); - -AppDispatcher.register( action => { - switch (action.actionType) { - case VoterGuideConstants.VOTER_GUIDES_TO_FOLLOW: // retrieveVoterGuidesToFollowList - retrieveVoterGuidesToFollowList(action.we_vote_id); // API call: voterGuidesToFollowRetrieve - VoterGuideStore.emitChange(); - break; - case VoterGuideConstants.VOTER_GUIDES_FOLLOWED: // retrieveVoterGuidesFollowedList - retrieveVoterGuidesFollowedList(action.we_vote_id); // API call: voterGuidesFollowedRetrieve - VoterGuideStore.emitChange(); - break; - case VoterGuideConstants.RETRIEVE_ORGANIZATIONS: // retrieveOrganizations - retrieveOrganizations(action.we_vote_id); // API call: organizationRetrieve - VoterGuideStore.emitChange(); - break; - case VoterGuideConstants.FOLLOW_ORGANIZATION: // followOrganization - followOrganization(action.we_vote_id); // API call: organizationFollow - VoterGuideStore.emitChange(); - break; - case VoterGuideConstants.IGNORE_ORGANIZATION: // ignoreOrganization - ignoreOrganization(action.we_vote_id); // API call: organizationFollowIgnore - VoterGuideStore.emitChange(); - break; - case VoterGuideConstants.STOP_FOLLOWING_ORGANIZATION: // stopFollowingOrganization - stopFollowingOrganization(action.we_vote_id); // API call: organizationStopFollowing - VoterGuideStore.emitChange(); - break; - } -}); - -export default VoterGuideStore;