From 5b33b6a0a0d5a77132fcd15bd5bb87a00515f0b9 Mon Sep 17 00:00:00 2001 From: Kevin Lee Date: Wed, 20 Apr 2016 20:10:45 -0700 Subject: [PATCH] Load articles off wire (#33) * successfully load articles from heroku * delete mock article json, alt * add todo comment --- app/actions/actions.js | 2 ++ app/api.js | 38 ++++++++++++++++++++++++ app/assets/tmpArticles.json | 17 ----------- app/components/annotation/Article.js | 2 +- app/components/annotation/Tua.js | 27 +++++++++++------ app/components/quiz/Quiz.js | 2 +- app/reducers/articleReducers.js | 27 +++++++++++------ app/routes.js | 2 +- app/styles/Article.scss | 1 + app/styles/_styleguide.scss | 1 + app/styles/fade.scss | 28 ++++++++++++++++++ app/styles/fadeIn.scss | 8 ------ app/utils/alt.js | 2 -- notes.json | 43 ++++++++++++++++++++++++++++ package.json | 1 - 15 files changed, 153 insertions(+), 48 deletions(-) create mode 100644 app/api.js delete mode 100644 app/assets/tmpArticles.json create mode 100644 app/styles/fade.scss delete mode 100644 app/styles/fadeIn.scss delete mode 100644 app/utils/alt.js create mode 100644 notes.json diff --git a/app/actions/actions.js b/app/actions/actions.js index ee41dd9..56a5337 100644 --- a/app/actions/actions.js +++ b/app/actions/actions.js @@ -9,6 +9,8 @@ export function activateTopic(topic) { } export function newArticle(article) { + // Where article is the index of the next article to get, or null to indicate + // we should hit the backend for a fresh batch of articles return { type: types.NEW_ARTICLE, article }; } diff --git a/app/api.js b/app/api.js new file mode 100644 index 0000000..bb96850 --- /dev/null +++ b/app/api.js @@ -0,0 +1,38 @@ +import data from 'assets/tua.json'; +import $ from 'jquery'; + +const USE_DOCKER = false; +let BASE_URL = 'http://text-thresher.herokuapp.com'; +if (USE_DOCKER) { + BASE_URL = 'http://192.168.99.100:5000'; +} +const ARTICLES_URL = BASE_URL + '/api/articles/'; +const HIGHLIGHTS_URL = BASE_URL + '/api/highlight_groups/'; + +export default class api { + static getArticles() { + // TODO: consider somehow not synch doing this + var res = $.ajax({ url: ARTICLES_URL, async: false }); + if (res.status !== 200) { + return { article: data.results }; + } + // need to have conversation with backend about where these legacy properties + // i.e. topics comes from + var articles = []; + res = JSON.parse(res.responseText); + for (var article of res.results) { + articles.push(Object.assign({}, + { article, analysis_type: { topics: [{ name: 'Event type' }] } }) + ); + } + return articles; + } + + static sendHighlights(highlights) { + // TODO: finish this function + $.ajax({ url: HIGHLIGHTS_URL, + method: 'POST', + data: highlights, + success: _ => _ }); + } +} diff --git a/app/assets/tmpArticles.json b/app/assets/tmpArticles.json deleted file mode 100644 index 9ec5e8d..0000000 --- a/app/assets/tmpArticles.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "results": [ - { - "analysis_type": { - "topics": [ - { - "topic_id": 1, - "name": "Event type" - } - ] - }, - "article": { - "text": "'Occupy Atlanta' rallies at Capitol\nATLANTA — \n\nProtesters who have been camped out in a downtown Atlanta park for more than a week left their posts for the state Capitol on Saturday. They are demanding jobs.\nOccupy Atlanta protesters chanted for change as they made the mile-long journey from Woodruff Park on Peachtree Street to the state Capitol on Washington Street. The Beatles song “Revolution” was playing at their destination. Demonstrators said they want jobs, not cuts to government programs.\n“This march is specifically to support the unions and support they need for more investments in jobs and less cuts in Georgia,\" protester Natalie Stohl told Channel 2’s Sophia Choi.\nAfter the march, demonstrators headed back to Woodruff Park. The city initially said they had to pack up their tents and leave the park by Monday, but Atlanta Mayor Kasim Reed said Friday that deadline is not firm. He said he may allow them to stay longer, but not indefinitely.\nDemonstrators said they plan to stay until they see change from the government.\n“We know that come Monday, we're committed to non-violence, but we're also committed to occupy this park,” protester Tim Franzen said.\nProtesters plan to hold a non-violence seminar at Woodruff Park on Sunday, so everyone will know how to handle themselves if police try to kick them out." - } - } - ] -} diff --git a/app/components/annotation/Article.js b/app/components/annotation/Article.js index a702887..7e8123f 100644 --- a/app/components/annotation/Article.js +++ b/app/components/annotation/Article.js @@ -88,7 +88,7 @@ const Article = React.createClass({ } return ( -
+
Focus on the bold text about '{topic.name}' and answer the questions.
diff --git a/app/components/annotation/Tua.js b/app/components/annotation/Tua.js index 067b5fc..dd74d90 100644 --- a/app/components/annotation/Tua.js +++ b/app/components/annotation/Tua.js @@ -1,12 +1,12 @@ import { newArticle } from 'actions/actions'; import Article from 'components/annotation/article'; import React from 'react'; +import ReactDOM from 'react-dom'; import ReactCSSTransitionsGroup from 'react-addons-css-transition-group'; import { connect } from 'react-redux'; import TopicPicker from 'components/annotation/topicPicker'; -import tmpdata from 'assets/tmpArticles.json'; -import 'fadeIn.scss'; +import 'fade.scss'; const mapDispatchToProps = dispatch => { return { @@ -17,7 +17,8 @@ const mapDispatchToProps = dispatch => { } const mapStateToProps = state => { - return { articles: state.articleReducers.article }; + return { articles: state.articleReducers.articles, + curArticle: state.articleReducers.curArticle }; } const Tua = React.createClass({ @@ -36,16 +37,20 @@ const Tua = React.createClass({ propTypes: { articles: React.PropTypes.array, onNewArticle: React.PropTypes.func, - params: React.PropTypes.object.isRequired + params: React.PropTypes.object.isRequired, + curArticle: React.PropTypes.number }, handleNext() { - this.props.onNewArticle(tmpdata.results); + this.props.onNewArticle(this.props.curArticle + 1); + ReactDOM.findDOMNode(this).scrollIntoView(); }, render() { - const {tua_id}: string = this.props.params; - let tua = this.props.articles[tua_id]; + // TODO: we need to have a larger discussion of route design + // const {cur_article}: string = this.props.params; + let cur_article = this.props.curArticle; + let tua = this.props.articles[cur_article]; let article = tua.article; let topics = tua.analysis_type.topics; @@ -57,7 +62,13 @@ const Tua = React.createClass({ transitionLeaveTimeout={500}>
-
+ +
+
diff --git a/app/components/quiz/Quiz.js b/app/components/quiz/Quiz.js index 3e3ef91..a127944 100644 --- a/app/components/quiz/Quiz.js +++ b/app/components/quiz/Quiz.js @@ -7,7 +7,7 @@ import { connect } from 'react-redux'; import tmpQuestions from 'assets/tmpQuestions.json'; import 'Quiz.scss'; -import 'fadeIn.scss'; +import 'fade.scss'; const mapDispatchToProps = dispatch => { return { diff --git a/app/reducers/articleReducers.js b/app/reducers/articleReducers.js index eab002d..2d05a41 100644 --- a/app/reducers/articleReducers.js +++ b/app/reducers/articleReducers.js @@ -1,17 +1,22 @@ import { ADD_HIGHLIGHT, NEW_ARTICLE, ACTIVATE_TOPIC } from '../actions/actionTypes'; -import data from 'assets/tua.json'; +import api from '../api.js'; // Note: not 100% sure this is the 'proper' reducer layout - we'll find out more // as we go -const initialState = { - // For testing purposes there will be a default static article - article: data.results, - highlights: [], +function getInitialState() { + return { articles: api.getArticles() }; } +const initialState = Object.assign({ + articles: [], + highlights: [], + // TODO: somehow track what the user's seen in their sessions not just count + curArticle: 0, +}, getInitialState()); + function mergeHighlights(list) { // TODO: write tests for me var newlist = []; @@ -55,12 +60,16 @@ export default function articleReducer(state = initialState, action) { return Object.assign({}, state, { highlights: mergeHighlights(newHighlights) }); case NEW_ARTICLE: - // TODO: save highlights before deleting htem - return Object.assign({}, state, { article: action.article, highlights: [] }); - + api.sendHighlights(state.highlights); + if (!action.article || action.article >= state.articles.length) { + return Object.assign({}, state, { articles: api.getArticles(), + highlights: [], + curArticle: 0 }); + } + return Object.assign({}, state, { highlights: [], + curArticle: state.curArticle + 1 }); case ACTIVATE_TOPIC: return Object.assign({}, state, { currentTopic: action.topic }); - default: return state; } diff --git a/app/routes.js b/app/routes.js index 8fb9bf1..d33fc1b 100644 --- a/app/routes.js +++ b/app/routes.js @@ -9,7 +9,7 @@ export default (