From 3a6e5883658fc1cac71b939f351f7a3661b07480 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Wed, 1 Jul 2015 10:36:31 +0800 Subject: [PATCH 01/42] A basic node server to serve frontend The server serves: 1. The `./public` folder as the document root. 2. The `/scripts/env.js` returns object of environment variable(s). --- .gitignore | 1 + includes/envars.js | 33 +++++++++++++++++++++++++++++++++ package.json | 16 ++++++++++++++++ public/.gitignore | 0 server.js | 28 ++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+) create mode 100644 .gitignore create mode 100644 includes/envars.js create mode 100644 package.json create mode 100644 public/.gitignore create mode 100644 server.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/includes/envars.js b/includes/envars.js new file mode 100644 index 0000000..9202981 --- /dev/null +++ b/includes/envars.js @@ -0,0 +1,33 @@ + + +// add trailing slash +function trailSlash(str) { + if (str.substr(-1) != '/') { + str += '/'; + } + return str +} + +// wait for environment to be ready +exports.ready = function (callback) { + if (typeof process.env["API_BASE_URL"] == "undefined") { + // if API_BASE_URL is not defined, prompt user to define + (function (process, callback) { + var prompt = require('prompt'); + prompt.start(); + console.log('Missing environment variable'); + prompt.get(['API_BASE_URL'], function (err, result) { + if (err) { return onErr(err); } + var url = trailSlash(result.API_BASE_URL); + console.log('API_BASE_URL: ' + url); + process.env["API_BASE_URL"] = url; + callback(); + }); + })(process, callback) + } else { + process.env["API_BASE_URL"] = + trailSlash(process.env["API_BASE_URL"]); + console.log('API_BASE_URL: ' + process.env["API_BASE_URL"]); + callback(); + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3cba8eb --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "newsdiff-frontend", + "version": "0.0.1", + "description": "", + "repository": { + "type": "git", + "url": "https://github.com/code4hk/Newsdiff-Frontend.git" + }, + "author": "Code4HK", + "license": "GPLv3", + "dependencies": { + "express": "^4.13.0", + "body-parser": "^1.13.0", + "prompt": "^0.2.14" + } +} diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/server.js b/server.js new file mode 100644 index 0000000..9e64aaa --- /dev/null +++ b/server.js @@ -0,0 +1,28 @@ +var fs = require('fs'); +var path = require('path'); +var express = require('express'); +var bodyParser = require('body-parser'); +var app = express(); + +var envars = require('./includes/envars.js') + +envars.ready(function () { + + app.set('port', (process.env.PORT || 3000)); + app.use('/', express.static(path.join(__dirname, 'public'))); + app.use(bodyParser.json()); + app.use(bodyParser.urlencoded({extended: true})); + + app.get('/scripts/env.js', function(req, res) { + var js = 'var env = ' + JSON.stringify({ + "api_base_url": process.env["API_BASE_URL"] + }) + ';'; + res.setHeader('Cache-Control', 'no-cache'); + res.send(js); + }); + + app.listen(app.get('port'), function() { + console.log('Server started: http://localhost:' + app.get('port') + '/'); + }); + +}) From ae06909d9c12ec4f49ee471d7504de4302a887d4 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Wed, 1 Jul 2015 15:08:02 +0800 Subject: [PATCH 02/42] Proxy API request to prevent origin problem Cannot directly use API server (same origin policy problem). Proxy the API to local folder "/api" to avoid problem. --- includes/forward.js | 16 ++++++++++++++++ server.js | 7 +++++++ 2 files changed, 23 insertions(+) create mode 100644 includes/forward.js diff --git a/includes/forward.js b/includes/forward.js new file mode 100644 index 0000000..000e4d3 --- /dev/null +++ b/includes/forward.js @@ -0,0 +1,16 @@ + +var request = require('request') + +module.exports = function(pattern, host){ + return function(req, res, next){ + if(req.url.match(pattern)){ + var db_path = req.url.match(pattern)[1] + , db_url = [host, db_path].join(''); + console.log(db_url); + req.pipe(request[req.method.toLowerCase()](db_url)).pipe(res); + }else{ + console.log("next"); + next(); + } + } +} diff --git a/server.js b/server.js index 9e64aaa..4e08c60 100644 --- a/server.js +++ b/server.js @@ -5,6 +5,7 @@ var bodyParser = require('body-parser'); var app = express(); var envars = require('./includes/envars.js') +var forward = require('./includes/forward.js') envars.ready(function () { @@ -12,11 +13,17 @@ envars.ready(function () { app.use('/', express.static(path.join(__dirname, 'public'))); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); + app.use(forward(/^\/api\/(.+?)$/, process.env["API_BASE_URL"])); app.get('/scripts/env.js', function(req, res) { + /* var js = 'var env = ' + JSON.stringify({ "api_base_url": process.env["API_BASE_URL"] }) + ';'; + */ + var js = 'var env = ' + JSON.stringify({ + "api_base_url": '/api/' + }) + ';'; res.setHeader('Cache-Control', 'no-cache'); res.send(js); }); From fc85379703da4a21d6fba881622cba4566463074 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Wed, 1 Jul 2015 15:33:26 +0800 Subject: [PATCH 03/42] Basic react site to list all news items --- includes/forward.js | 2 -- public/css/style.css | 0 public/index.html | 16 +++++++++ public/scripts/api.js | 62 ++++++++++++++++++++++++++++++++ public/scripts/main.jsx | 78 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 public/css/style.css create mode 100644 public/index.html create mode 100644 public/scripts/api.js create mode 100644 public/scripts/main.jsx diff --git a/includes/forward.js b/includes/forward.js index 000e4d3..fb85281 100644 --- a/includes/forward.js +++ b/includes/forward.js @@ -6,10 +6,8 @@ module.exports = function(pattern, host){ if(req.url.match(pattern)){ var db_path = req.url.match(pattern)[1] , db_url = [host, db_path].join(''); - console.log(db_url); req.pipe(request[req.method.toLowerCase()](db_url)).pipe(res); }else{ - console.log("next"); next(); } } diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..e69de29 diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..7474831 --- /dev/null +++ b/public/index.html @@ -0,0 +1,16 @@ + + + + Newsdiff HK + + + + + + + + +
+ + + \ No newline at end of file diff --git a/public/scripts/api.js b/public/scripts/api.js new file mode 100644 index 0000000..c205bec --- /dev/null +++ b/public/scripts/api.js @@ -0,0 +1,62 @@ + +// get API response +var api = api || {}; +(function (exports, env, $) { + + // retrieve publishers + // GET /api/publishers + exports.getPublishers = function (options) { + $.extend(options, { + url: env.api_base_url + 'publishers', + dataType: 'json', + cache: false + }); + $.ajax(options); + } + + // retrieve all differed-news + // GET /api/news + exports.getItems = function (options) { + $.extend(options, { + url: env.api_base_url + 'news', + dataType: 'json', + cache: false + }) + $.ajax(options); + } + + // retrieve all differed-news from a publisher + // GET /api/publisher/{publisher_code}/news + exports.getPublisherItems = function (publisher_code, options) { + $.extend(options, { + url: env.api_base_url + 'publisher/'+publisher_code+'/news', + dataType: 'json', + cache: false + }); + $.ajax(options); + } + + // retrieve details of a differed-news + // GET /api/news/{news_id} + exports.getItem = function (news_id, options) { + $.extend(options, { + url: env.api_base_url + 'news/'+news_id, + dataType: 'json', + cache: false + }); + $.ajax(options); + } + + // search for differed-news + // POST /api/search/news + exports.searchItem = function (options) { + $.extend(options, { + url: env.api_base_url + 'search/news', + method: 'POST', + dataType: 'json', + cache: false + }); + $.ajax(options); + } + +})(api, env, jQuery) diff --git a/public/scripts/main.jsx b/public/scripts/main.jsx new file mode 100644 index 0000000..9f94070 --- /dev/null +++ b/public/scripts/main.jsx @@ -0,0 +1,78 @@ + +// extract id from a news item +var newsId = function (item) { + return item._id.$oid; +} + +var NewsListItem = React.createClass({ + render: function() { + return ( +
+

{this.props.data.title}

+
    +
  • [ + Original Link + ] +
  • +
  • Publisher: {this.props.data.publisher}
  • +
  • Language: {this.props.data.lang}
  • +
  • % of change: {this.props.data.changes}
  • +
  • Created At: {this.props.data.created_at}
  • +
  • Updated At: {this.props.data.updated_at}
  • +
  • Last Checked: {this.props.data.last_check}
  • +
  • Versions: {this.props.data.count}
  • +
+
+ ); + } +}); + +var NewsList = React.createClass({ + render: function() { + var newsItems = this.props.items.map(function(data, index) { + return ( + + ); + }); + return ( +
+ {newsItems} +
+ ); + } +}); + +var NewsListPage = React.createClass({ + getInitialState: function() { + return { + items: [], + meta: {} + }; + }, + componentDidMount: function() { + api.getItems({ + success: function(data) { + console.log('items', data.news); + this.setState({items: data.news, meta: data.meta}); + }.bind(this), + error: function(xhr, status, err) { + console.error(this.props.url, status, err.toString()); + }.bind(this) + }) + }, + render: function() { + return ( +
+

News

+ +
+ ); + } +}); + +React.render( + , + document.getElementById('content') +); From 1a01798637da0280c4cdd45c606aaae68ca6f01e Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Thu, 2 Jul 2015 20:05:03 +0800 Subject: [PATCH 04/42] Update server structure to use webpack Use webpack to bundle and parse javascript, jsx into bundle.js. Prepare for isomorphic javascript structure. --- .gitignore | 1 + README.md | 27 ++++++++++++++ app/api.js | 56 +++++++++++++++++++++++++++++ {public/scripts => app}/main.jsx | 5 +++ package.json | 34 ++++++++++-------- public/index.html | 5 ++- public/scripts/.gitignore | 2 ++ public/scripts/api.js | 62 -------------------------------- webpack.config.js | 30 ++++++++++++++++ 9 files changed, 143 insertions(+), 79 deletions(-) create mode 100644 app/api.js rename {public/scripts => app}/main.jsx (96%) create mode 100644 public/scripts/.gitignore delete mode 100644 public/scripts/api.js create mode 100644 webpack.config.js diff --git a/.gitignore b/.gitignore index 3c3629e..eb03e3e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +*.log diff --git a/README.md b/README.md index 97a2f97..42ed5d5 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,30 @@ README ====== Frontend for Watchdog (previously NewsdiffHK) project. + +Install +------- + +The server depends on packages. The serving scripts needs to build into bundle before running. Run these commands. + +```bash +npm install +npm run build +``` + +Run +--- + +To start the server: + +```bash +npm run start +``` + +The server will prompt you to enter the API_BASE_URL. To suppress the prompt, you may also add API_BASE_URL to the environment like this: + +```bash +API_BASE_URL=http://api.server.com:3000/api npm run start +``` + +Replace `http://api.server.com:3000` with the appropriate host and port number. diff --git a/app/api.js b/app/api.js new file mode 100644 index 0000000..b03937f --- /dev/null +++ b/app/api.js @@ -0,0 +1,56 @@ + +// retrieve publishers +// GET /api/publishers +module.exports.getPublishers = function (options) { + $.extend(options, { + url: env.api_base_url + 'publishers', + dataType: 'json', + cache: false + }); + $.ajax(options); +} + +// retrieve all differed-news +// GET /api/news +module.exports.getItems = function (options) { + $.extend(options, { + url: env.api_base_url + 'news', + dataType: 'json', + cache: false + }) + $.ajax(options); +} + +// retrieve all differed-news from a publisher +// GET /api/publisher/{publisher_code}/news +module.exports.getPublisherItems = function (publisher_code, options) { + $.extend(options, { + url: env.api_base_url + 'publisher/'+publisher_code+'/news', + dataType: 'json', + cache: false + }); + $.ajax(options); +} + +// retrieve details of a differed-news +// GET /api/news/{news_id} +module.exports.getItem = function (news_id, options) { + $.extend(options, { + url: env.api_base_url + 'news/'+news_id, + dataType: 'json', + cache: false + }); + $.ajax(options); +} + +// search for differed-news +// POST /api/search/news +module.exports.searchItem = function (options) { + $.extend(options, { + url: env.api_base_url + 'search/news', + method: 'POST', + dataType: 'json', + cache: false + }); + $.ajax(options); +} diff --git a/public/scripts/main.jsx b/app/main.jsx similarity index 96% rename from public/scripts/main.jsx rename to app/main.jsx index 9f94070..aa2a302 100644 --- a/public/scripts/main.jsx +++ b/app/main.jsx @@ -1,4 +1,9 @@ +'use strict' + +var React = require('react'); +var api = require('./api.js'); + // extract id from a news item var newsId = function (item) { return item._id.$oid; diff --git a/package.json b/package.json index 3cba8eb..3b4220e 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,22 @@ { - "name": "newsdiff-frontend", - "version": "0.0.1", - "description": "", - "repository": { - "type": "git", - "url": "https://github.com/code4hk/Newsdiff-Frontend.git" - }, - "author": "Code4HK", - "license": "GPLv3", - "dependencies": { - "express": "^4.13.0", - "body-parser": "^1.13.0", - "prompt": "^0.2.14" - } + "name": "newsdiff-frontend", + "version": "0.0.1", + "description": "", + "scripts": { + "build": "webpack", + "start": "node server.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/code4hk/Newsdiff-Frontend.git" + }, + "author": "Code4HK", + "license": "GPLv3", + "dependencies": { + "express": "^4.13.0", + "body-parser": "^1.13.0", + "prompt": "^0.2.14", + "jsx-loader": "^0.13.2", + "react": "^0.13.3" + } } diff --git a/public/index.html b/public/index.html index 7474831..d200762 100644 --- a/public/index.html +++ b/public/index.html @@ -7,10 +7,9 @@ -
- + - \ No newline at end of file + diff --git a/public/scripts/.gitignore b/public/scripts/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/public/scripts/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/public/scripts/api.js b/public/scripts/api.js deleted file mode 100644 index c205bec..0000000 --- a/public/scripts/api.js +++ /dev/null @@ -1,62 +0,0 @@ - -// get API response -var api = api || {}; -(function (exports, env, $) { - - // retrieve publishers - // GET /api/publishers - exports.getPublishers = function (options) { - $.extend(options, { - url: env.api_base_url + 'publishers', - dataType: 'json', - cache: false - }); - $.ajax(options); - } - - // retrieve all differed-news - // GET /api/news - exports.getItems = function (options) { - $.extend(options, { - url: env.api_base_url + 'news', - dataType: 'json', - cache: false - }) - $.ajax(options); - } - - // retrieve all differed-news from a publisher - // GET /api/publisher/{publisher_code}/news - exports.getPublisherItems = function (publisher_code, options) { - $.extend(options, { - url: env.api_base_url + 'publisher/'+publisher_code+'/news', - dataType: 'json', - cache: false - }); - $.ajax(options); - } - - // retrieve details of a differed-news - // GET /api/news/{news_id} - exports.getItem = function (news_id, options) { - $.extend(options, { - url: env.api_base_url + 'news/'+news_id, - dataType: 'json', - cache: false - }); - $.ajax(options); - } - - // search for differed-news - // POST /api/search/news - exports.searchItem = function (options) { - $.extend(options, { - url: env.api_base_url + 'search/news', - method: 'POST', - dataType: 'json', - cache: false - }); - $.ajax(options); - } - -})(api, env, jQuery) diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..72559e7 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,30 @@ +module.exports = [ + { + name: "browser", + context: __dirname + "/app", + entry: "./main.jsx", + module: { + loaders: [ + { + //tell webpack to use jsx-loader for all *.jsx files + test: /\.jsx$/, + loaders: [ + 'jsx-loader?insertPragma=React.DOM&harmony' + ] + } + ] + }, + externals: { + //don't bundle the 'react' npm package with our bundle.js + //but get it from a global 'React' variable + 'react': 'React' + }, + resolve: { + extensions: ['', '.js', '.jsx'] + }, + output: { + path: __dirname + "/public/scripts", + filename: "bundle.js" + } + } +] From a61f0402617b9cdac6933fadbbecea1ccd49c594 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Fri, 3 Jul 2015 00:05:34 +0800 Subject: [PATCH 05/42] Fix package.json for webpack Added webpack to dependency --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3b4220e..39973ba 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "body-parser": "^1.13.0", "prompt": "^0.2.14", "jsx-loader": "^0.13.2", - "react": "^0.13.3" + "react": "^0.13.3", + "webpack": "^1.10.1" } } From 69adc83ddc48bfa6907b4373020221bc077fa8d0 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Fri, 3 Jul 2015 02:18:26 +0800 Subject: [PATCH 06/42] Added React-Router for routing Separated components into different jsx files. Added 1 dummy page component "AboutPage". Use ReactRouter for browser routing. --- app/components/menu.jsx | 18 +++++++ app/components/news_list.jsx | 28 +++++++++++ app/components/news_list_item.jsx | 28 +++++++++++ app/main.jsx | 81 ++----------------------------- app/pages/about.jsx | 18 +++++++ app/pages/news_list.jsx | 38 +++++++++++++++ app/routes.jsx | 31 ++++++++++++ package.json | 1 + 8 files changed, 166 insertions(+), 77 deletions(-) create mode 100644 app/components/menu.jsx create mode 100644 app/components/news_list.jsx create mode 100644 app/components/news_list_item.jsx create mode 100644 app/pages/about.jsx create mode 100644 app/pages/news_list.jsx create mode 100644 app/routes.jsx diff --git a/app/components/menu.jsx b/app/components/menu.jsx new file mode 100644 index 0000000..0a2c08d --- /dev/null +++ b/app/components/menu.jsx @@ -0,0 +1,18 @@ + +'use strict' + +var React = require('react'); + +// NewsListItem +module.exports = React.createClass({ + render: function() { + return ( + + ); + } +}); diff --git a/app/components/news_list.jsx b/app/components/news_list.jsx new file mode 100644 index 0000000..7626428 --- /dev/null +++ b/app/components/news_list.jsx @@ -0,0 +1,28 @@ + +'use strict' + +var React = require('react'); +var NewsListItem = require('./news_list_item'); + +// extract id from a news item +var newsId = function (item) { + return item._id.$oid; +} + +// NewsList +module.exports = React.createClass({ + render: function() { + var newsItems = this.props.items.map(function(data, index) { + return ( + + ); + }); + return ( +
+ {newsItems} +
+ ); + } +}); diff --git a/app/components/news_list_item.jsx b/app/components/news_list_item.jsx new file mode 100644 index 0000000..16aa04a --- /dev/null +++ b/app/components/news_list_item.jsx @@ -0,0 +1,28 @@ + +'use strict' + +var React = require('react'); + +// NewsListItem +module.exports = React.createClass({ + render: function() { + return ( +
+

{this.props.data.title}

+
    +
  • [ + Original Link + ] +
  • +
  • Publisher: {this.props.data.publisher}
  • +
  • Language: {this.props.data.lang}
  • +
  • % of change: {this.props.data.changes}
  • +
  • Created At: {this.props.data.created_at}
  • +
  • Updated At: {this.props.data.updated_at}
  • +
  • Last Checked: {this.props.data.last_check}
  • +
  • Versions: {this.props.data.count}
  • +
+
+ ); + } +}); diff --git a/app/main.jsx b/app/main.jsx index aa2a302..2db7827 100644 --- a/app/main.jsx +++ b/app/main.jsx @@ -2,82 +2,9 @@ 'use strict' var React = require('react'); -var api = require('./api.js'); +var Router = require('react-router'); +var routes = require('./routes'); -// extract id from a news item -var newsId = function (item) { - return item._id.$oid; -} - -var NewsListItem = React.createClass({ - render: function() { - return ( -
-

{this.props.data.title}

-
    -
  • [ - Original Link - ] -
  • -
  • Publisher: {this.props.data.publisher}
  • -
  • Language: {this.props.data.lang}
  • -
  • % of change: {this.props.data.changes}
  • -
  • Created At: {this.props.data.created_at}
  • -
  • Updated At: {this.props.data.updated_at}
  • -
  • Last Checked: {this.props.data.last_check}
  • -
  • Versions: {this.props.data.count}
  • -
-
- ); - } -}); - -var NewsList = React.createClass({ - render: function() { - var newsItems = this.props.items.map(function(data, index) { - return ( - - ); - }); - return ( -
- {newsItems} -
- ); - } +Router.run(routes, Router.HashLocation, (Root) => { + React.render(, document.getElementById('content')); }); - -var NewsListPage = React.createClass({ - getInitialState: function() { - return { - items: [], - meta: {} - }; - }, - componentDidMount: function() { - api.getItems({ - success: function(data) { - console.log('items', data.news); - this.setState({items: data.news, meta: data.meta}); - }.bind(this), - error: function(xhr, status, err) { - console.error(this.props.url, status, err.toString()); - }.bind(this) - }) - }, - render: function() { - return ( -
-

News

- -
- ); - } -}); - -React.render( - , - document.getElementById('content') -); diff --git a/app/pages/about.jsx b/app/pages/about.jsx new file mode 100644 index 0000000..b324799 --- /dev/null +++ b/app/pages/about.jsx @@ -0,0 +1,18 @@ + +'use strict' + +var React = require('react'); +var Menu = require('../components/menu'); + +// AboutPage +module.exports = React.createClass({ + render: function () { + return ( +
+ +

About Us

+

Hello world

+
+ ); + } +}); diff --git a/app/pages/news_list.jsx b/app/pages/news_list.jsx new file mode 100644 index 0000000..c474348 --- /dev/null +++ b/app/pages/news_list.jsx @@ -0,0 +1,38 @@ + +'use strict' + +var api = require('../api'); + +var React = require('react'); +var NewsList = require('../components/news_list'); +var Menu = require('../components/menu'); + +// NewsListPage +module.exports = React.createClass({ + getInitialState: function() { + return { + items: [], + meta: {} + }; + }, + componentDidMount: function() { + api.getItems({ + success: function(data) { + console.log('items', data.news); + this.setState({items: data.news, meta: data.meta}); + }.bind(this), + error: function(xhr, status, err) { + console.error(this.props.url, status, err.toString()); + }.bind(this) + }) + }, + render: function() { + return ( +
+ +

News

+ +
+ ); + } +}); diff --git a/app/routes.jsx b/app/routes.jsx new file mode 100644 index 0000000..1c627fe --- /dev/null +++ b/app/routes.jsx @@ -0,0 +1,31 @@ + +'use strict' + +// Router +var Router = require('react-router'); +var Route = Router.Route; +var DefaultRoute = Router.DefaultRoute; + +// pages +var NewsListPage = require('./pages/news_list') +var AboutPage = require('./pages/about') + +// App +var React = require('react'); +var RouteHandler = require('react-router').RouteHandler; +var App = React.createClass({ + render () { + return ( + + ); + } +}); + +// declare our routes and their hierarchy +module.exports = ( + + + + + +); diff --git a/package.json b/package.json index 39973ba..44d9d52 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "prompt": "^0.2.14", "jsx-loader": "^0.13.2", "react": "^0.13.3", + "react-router": "^0.13.3", "webpack": "^1.10.1" } } From 01d8a9a1dab61d8a93e212e98039fa6006756fb9 Mon Sep 17 00:00:00 2001 From: Koala Yeung Date: Fri, 3 Jul 2015 17:20:19 +0800 Subject: [PATCH 07/42] Rewrite components and scripts in ES6 style --- app/api.js | 118 ++++++++++++++++-------------- app/app.jsx | 13 ++++ app/components/menu.jsx | 4 +- app/components/news_list.jsx | 6 +- app/components/news_list_item.jsx | 4 +- app/main.jsx | 6 +- app/pages/about.jsx | 6 +- app/pages/news_list.jsx | 11 ++- app/routes.jsx | 24 +----- package.json | 1 + webpack.config.js | 43 +++++++---- 11 files changed, 128 insertions(+), 108 deletions(-) create mode 100644 app/app.jsx diff --git a/app/api.js b/app/api.js index b03937f..b3b0b80 100644 --- a/app/api.js +++ b/app/api.js @@ -1,56 +1,64 @@ -// retrieve publishers -// GET /api/publishers -module.exports.getPublishers = function (options) { - $.extend(options, { - url: env.api_base_url + 'publishers', - dataType: 'json', - cache: false - }); - $.ajax(options); -} - -// retrieve all differed-news -// GET /api/news -module.exports.getItems = function (options) { - $.extend(options, { - url: env.api_base_url + 'news', - dataType: 'json', - cache: false - }) - $.ajax(options); -} - -// retrieve all differed-news from a publisher -// GET /api/publisher/{publisher_code}/news -module.exports.getPublisherItems = function (publisher_code, options) { - $.extend(options, { - url: env.api_base_url + 'publisher/'+publisher_code+'/news', - dataType: 'json', - cache: false - }); - $.ajax(options); -} - -// retrieve details of a differed-news -// GET /api/news/{news_id} -module.exports.getItem = function (news_id, options) { - $.extend(options, { - url: env.api_base_url + 'news/'+news_id, - dataType: 'json', - cache: false - }); - $.ajax(options); -} - -// search for differed-news -// POST /api/search/news -module.exports.searchItem = function (options) { - $.extend(options, { - url: env.api_base_url + 'search/news', - method: 'POST', - dataType: 'json', - cache: false - }); - $.ajax(options); -} +'use strict' + +var api = { + + // retrieve publishers + // GET /api/publishers + "getPublishers": function (options) { + $.extend(options, { + url: env.api_base_url + 'publishers', + dataType: 'json', + cache: false + }); + $.ajax(options); + }, + + // retrieve all differed-news + // GET /api/news + "getItems": function (options) { + $.extend(options, { + url: env.api_base_url + 'news', + dataType: 'json', + cache: false + }) + $.ajax(options); + }, + + // retrieve all differed-news from a publisher + // GET /api/publisher/{publisher_code}/news + "getPublisherItems": function (publisher_code, options) { + $.extend(options, { + url: env.api_base_url + 'publisher/'+publisher_code+'/news', + dataType: 'json', + cache: false + }); + $.ajax(options); + }, + + // retrieve details of a differed-news + // GET /api/news/{news_id} + "getItem": function (news_id, options) { + $.extend(options, { + url: env.api_base_url + 'news/'+news_id, + dataType: 'json', + cache: false + }); + $.ajax(options); + }, + + // search for differed-news + // POST /api/search/news + "searchItem": function (options) { + $.extend(options, { + url: env.api_base_url + 'search/news', + method: 'POST', + dataType: 'json', + cache: false + }); + $.ajax(options); + } + +}; + +export default api; diff --git a/app/app.jsx b/app/app.jsx new file mode 100644 index 0000000..6c82d9e --- /dev/null +++ b/app/app.jsx @@ -0,0 +1,13 @@ + +'use strict' + +import {RouteHandler} from 'react-router'; +import React from 'react'; + +export default React.createClass({ + render () { + return ( + + ); + } +}); diff --git a/app/components/menu.jsx b/app/components/menu.jsx index 0a2c08d..6b23d1b 100644 --- a/app/components/menu.jsx +++ b/app/components/menu.jsx @@ -1,10 +1,10 @@ 'use strict' -var React = require('react'); +import React from 'react'; // NewsListItem -module.exports = React.createClass({ +export default React.createClass({ render: function() { return (