From 97598ba7e88c73af1018869855a8ab3f59a3e20c Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Tue, 30 Aug 2016 02:45:56 +0000 Subject: [PATCH 1/8] changes --- client/assets/scss/Content.scss | 1 + client/js/components/Preview.js | 4 +++- client/js/pages/Index.js | 2 +- client/js/redux/actions.js | 6 ++++++ client/js/redux/constants.js | 3 ++- client/js/redux/reducers.js | 14 ++++++-------- package.json | 5 +++-- server.go | 10 +++++++--- 8 files changed, 29 insertions(+), 16 deletions(-) diff --git a/client/assets/scss/Content.scss b/client/assets/scss/Content.scss index 1d23a1c..55c9552 100644 --- a/client/assets/scss/Content.scss +++ b/client/assets/scss/Content.scss @@ -1,6 +1,7 @@ .Content { flex: 1; flex-wrap: wrap; + min-width: 0; .post + .post { margin-top: 2em; } diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index 59069a3..db6f688 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -22,6 +22,8 @@ export default class Preview extends React.Component{

); + + if(i >= this.props.postLimit) break; } return elements; @@ -32,7 +34,7 @@ export default class Preview extends React.Component{ return (
- {posts.length > 0 ? this.insertPosts(posts): ""} + {posts.length > 0 ? this.insertPosts(posts): null}
); } diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 51f19f4..3c21c8d 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -43,7 +43,7 @@ export default class Index extends React.Component {
- {typeof this.page === 'undefined' && !fetching ? : null} + {typeof this.page === 'undefined' && !fetching ? : null} {this.page === 'post' && !fetching ? : null} {fetching ? loadingElement : null} diff --git a/client/js/redux/actions.js b/client/js/redux/actions.js index 47adfdd..a191abd 100644 --- a/client/js/redux/actions.js +++ b/client/js/redux/actions.js @@ -2,6 +2,12 @@ import * as types from "./constants"; import marked from 'marked'; import 'whatwg-fetch'; +export function increasePostLimit(){ + return { + type: types.INCREASE_POST_LIMIT + } +} + function initPreview(posts) { return { type: types.INIT_PREVIEW, diff --git a/client/js/redux/constants.js b/client/js/redux/constants.js index d9cc693..6d21a68 100644 --- a/client/js/redux/constants.js +++ b/client/js/redux/constants.js @@ -2,4 +2,5 @@ export const INIT_PREVIEW = 'INIT_PREVIEW'; export const FILTER_PREVIEW = 'FILTER_PREVIEW'; export const LOAD_POST = 'LOAD_POST'; -export const FETCHING = 'FETCHING'; \ No newline at end of file +export const FETCHING = 'FETCHING'; +export const INCREASE_POST_LIMIT = 'INCREASE_POST_LIMIT'; \ No newline at end of file diff --git a/client/js/redux/reducers.js b/client/js/redux/reducers.js index 37bfec8..ebf0d11 100644 --- a/client/js/redux/reducers.js +++ b/client/js/redux/reducers.js @@ -14,12 +14,10 @@ const defaultState = { preview: { posts: [] }, - filteredPreview: { - posts: [] - }, post: "", fetched: false, - fetching: false + fetching: false, + postLimit: 10 }; //default reducer @@ -32,10 +30,6 @@ function reducer(state = defaultState, action) { fetched: true, fetching: false }); - case types.FILTER_PREVIEW: - return Object.assign({}, state, { - filteredPreview: Object.assign({}, state.filteredPreview, action.posts) - }); case types.LOAD_POST: return Object.assign({}, state, { post: action.post, @@ -47,6 +41,10 @@ function reducer(state = defaultState, action) { fetched : false, fetching: true }); + case types.INCREASE_POST_LIMIT: + return Object.assign({}, state, { + postLimit : state.postLimit + 10 + }); } //return present state if no actions get called diff --git a/package.json b/package.json index b0cfce2..e744041 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,9 @@ "build": "webpack && babel-node metadata.js", "c9": "webpack-dev-server --port $PORT --host $IP --hot --content-base dist --history-api-fallback", "dev": "webpack-dev-server --content-base public --inline --hot --history-api-fallback", - "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js", - "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js" + "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js && go build", + "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build", + "deploy" : "npm run prod && ./mywebsite" }, "repository": { "type": "git", diff --git a/server.go b/server.go index 9377d20..6199475 100644 --- a/server.go +++ b/server.go @@ -4,7 +4,8 @@ import ( "log" "net/http" "strconv" - + "github.com/NYTimes/gziphandler" + //local import paths relative to app.yaml file "mywebsite/server/controller/api" "mywebsite/server/db" @@ -34,7 +35,10 @@ func main(){ api.Configure(configurations.Api) db.Mongo.Connect() - + + //register middleware + handle := gziphandler.GzipHandler(route.Routes()) + log.Println("Starting Server...") - log.Println(http.ListenAndServe(":"+strconv.Itoa(configurations.Port), route.Routes())) + log.Println(http.ListenAndServe(":"+strconv.Itoa(configurations.Port), handle)) } From 0c531a30c254a140fbed4ea4f7d359a7811fa6a5 Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Wed, 31 Aug 2016 17:46:05 +0000 Subject: [PATCH 2/8] new post - updated server directories --- package.json | 4 +- .../Web Stuff/2016-08-30-ubuntu16-mongodb.md | 206 ++++++++++++++++++ server/controller/redirect.go | 2 +- server/model/raw_sensor/raw_sensor.go | 53 +---- server.go => server/mywebsite.go | 16 -- server/utils/config.go | 2 +- 6 files changed, 213 insertions(+), 70 deletions(-) create mode 100644 posts/Web Stuff/2016-08-30-ubuntu16-mongodb.md rename server.go => server/mywebsite.go (66%) diff --git a/package.json b/package.json index e744041..2221191 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "build": "webpack && babel-node metadata.js", "c9": "webpack-dev-server --port $PORT --host $IP --hot --content-base dist --history-api-fallback", "dev": "webpack-dev-server --content-base public --inline --hot --history-api-fallback", - "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js && go build", - "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build", + "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go", + "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go", "deploy" : "npm run prod && ./mywebsite" }, "repository": { diff --git a/posts/Web Stuff/2016-08-30-ubuntu16-mongodb.md b/posts/Web Stuff/2016-08-30-ubuntu16-mongodb.md new file mode 100644 index 0000000..57b2997 --- /dev/null +++ b/posts/Web Stuff/2016-08-30-ubuntu16-mongodb.md @@ -0,0 +1,206 @@ +# Installing and setting up authentication with MongoDB on Ubuntu 16.04.1 + +I recently spun up a new virtual machine on Digital Ocean and I decided to try the latest version +of Ubuntu.. because why not? I wanted to just host a MongoDB instance because I was going to host my site on Google's App Engine. +Turns out Google blocks any outgoing requests that are not HTTP. +(This prevents the Go [MGO](https://godoc.org/gopkg.in/mgo.v2) driver from connecting) + +*** + +## Installing MongoDB + +Luckily Digital Ocean offers great documentation when it comes to installing software. They usually have guides +and tutorials that are fairly up to date. I first followed [this guide](https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-16-04) +to get MongoDB installed. + +On previous versions of Ubuntu, MongoDB was installed as a service. Newer versions use Systemd to run the database. +Systemd uses different commands to check database statistics. + +The Systemd configuration is located in a few different places, but mine seems to work in the following directory. +Here the run command can be edited, although this probably does not need to be done +as most settings can be adjusted in the MongoDB config file. + +MongoDB systemd config +```bash + /lib/systemd/system/mongod.service +``` + +MongoDB config +```bash + /etc/mongod.conf +``` + +Service as well as systemd can be used to start and stop MongoDB. +These commands will do the same thing, which is nice. +```bash + sudo service mongod + sudo systemctl mongod +``` + +Although you can start, stop, and restart MongoDB with service and systemctl, +MongoDB does not show up when listing all services. +```bash + sudo service --status-all +``` + +Systemclt must now be used +```bash + sudo systemctl status +``` + +## Enabling security for external connections + +Any time a port is opened up for a MongoDB instance security precautions must be taken. +[There are thousands of MongoDB instances that are exposed to the internet.](http://www.securityweek.com/thousands-mongodb-databases-found-exposed-internet) +There are a few reasons for this. MongoDB is usually run on the same machine of web applications, +therefore the port it is running on should not be opened up at all. MongoDB can also be tricky to configure properly +and a system admin must know exactly what they are doing in making the database secure. Login credentials do not +even need to be set up if the port it is running on is not even open. As soon as that port is opened up, +unwanted guests can gain easy access, especially if it is running on the default port (27018). + +The first thing to do when running MongoDB for external access is to run it on a completely different port. +Why run it on the port where attackers know exactly what they are looking for? + +Security authentication must be enabled in the MongoDB config file. It is turned off by default. +Make sure to do this after creating user accounts or else access will be denied. + +## Creating user accounts + +Although this probably isn't the most secure thing to do, I start out by creating a root admin. +I do this because it allows me control over any database and it gives me easier access and power. +My database doesn't store any sensative information so I am okay with this. + +A root admin can be created by connecting to the server with the command `mongo` using the admin database. +```bash + mongo + use admin +``` + +Databases can also be listed +```bash + show dbs +``` + +Use the admin database and create a root user +```bash + db.createUser( + { + user: "admin", + pwd: "password", + roles: ["root"] + } + ) +``` + +Verify that the user was created +```bash + db.getUsers() +``` + +Lets go enable security +```bash + sudo nano /etc/mongod.conf +``` + +Uncomment `#security` by removing the `#` and add this line after +```bash + security: + authorization: enabled +``` + +Restart database or reboot the system +```bash + sudo systemctl restart mongod +``` + +We can now authenticate to the database as our newly created root admin +```bash + mongo admin --port 27017 -u 'admin' -p 'password' +``` + +## Difficulties configuring users + +When I first started setting up users I had a heck of a time. I wasn't sure which database to use for certain +users or what permissions I had to give them. Part of this is due to my impatience of not reading the +documentation thoroughly. + +Server wide users/admins MUST be in the admin database. We created a root use in the admin database +previously so that user should have access to any database in the server. All database users must be in +their respective database. For example if we want to use the "test" database, users must be created +within this database in order to gain access. Although access can be gained with a root admin account, +this is something that should not be done in production. + +Lets create a read/write user for the "test" database +```bash + use test + + db.createUser( + { + user: "user", + pwd: "password", + roles: ["readWrite"] + } + ) +``` + +Verify that the user was created +```bash + db.getUsers() +``` + +Login as this user +```bash + mongo test --port 27017 -u 'user' -p 'admin' +``` + +Now a proper user should be set up for read/write access. This is the exact method I used to +gain access to an external database the Go's MGO MongoDB database driver. + +### Scripts for easier access to the database + +I created some shell scripts on my database server with credentials saved because I use long random passwords +that I cannot remember off the top of my head. (keep in mind this increases security risks) +It took me awhile to get this to work because some syntax did not work for me when inside of a shell script. + +I created a file called `mongo_admin.sh` and one called `mongo_user.sh`. + +The files look like this +```bash + mongo admin --port 27017 -u 'user' -p 'password' +``` + +This was frustrating because I figured out it would not work when using double quotes +inside of the shell script, although double quotes work when issuing the command manually. +I also realized that a database must be specified in order to connect. This can be done +like above, or like this. +```bash + mongo --port 27017 -u 'user' -p 'password' --authenticationDatabase admin +``` + +## Firewall + +Firewall rules must be changed to enable external database access. First of all, edit the MongoDB config +file and change the default database port. Once that is changed use [UFW](https://help.ubuntu.com/community/UFW) +to change firewall rules. For this example I will change MongoDB to run on port 27018. + +```bash + ufw enable + ufw status + ufw allow 27018/tcp +``` + +This will allow all incoming connections to the database. It is advised to only allow +incoming connections from the web application server that is being used. + +Allow to certain ip +```bash + ufw allow from to any port 27018 +``` + +## Conclusion + +MongoDB can be tricky to set up, but it is highly recommened to go through the entire process. +In the end I decided not to host my MongoDB instance externally so I did not go through +the entire [MongoDB security check list](https://docs.mongodb.com/v2.6/administration/security-checklist/#audit-system-activity). +There are a few other things to do such as adding encryption and monitoring system activity, but +I covered most of the important issues. \ No newline at end of file diff --git a/server/controller/redirect.go b/server/controller/redirect.go index 0b78f0f..35299bd 100644 --- a/server/controller/redirect.go +++ b/server/controller/redirect.go @@ -11,7 +11,7 @@ func DiscordRedirect(w http.ResponseWriter, r *http.Request, _ httprouter.Params http.Redirect(w, r, "https://discordapp.com/invite/0Z2tzxKECEj2BHwj", 301) } -// Redirect to discord +// Redirect to vpn func VPNRedirect(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { http.Redirect(w, r, "https://mitchel.io:943", 301) } diff --git a/server/model/raw_sensor/raw_sensor.go b/server/model/raw_sensor/raw_sensor.go index c329a09..9b91b54 100644 --- a/server/model/raw_sensor/raw_sensor.go +++ b/server/model/raw_sensor/raw_sensor.go @@ -34,6 +34,7 @@ func (s *Data) toJson() string { } +//default store structure func (s *Data) StoreData() error { if db.Mongo.Connected() { @@ -57,13 +58,13 @@ func (s *Data) StoreData() error { } //handle queries for all sensors page -//******************************************************************************** type DataStore_AllSensors struct { ID string `json:"location" bson:"_id"` Temperature float64 `json:"temperature" bson:"temperature"` Updated time.Time `json:"updated" bson:"updated"` } +//get latest update from each unique sensor func GetAllSensors() ([]DataStore_AllSensors, error) { s := []DataStore_AllSensors{} @@ -88,52 +89,4 @@ func GetAllSensors() ([]DataStore_AllSensors, error) { } else { return s, errors.New("Query failed") } -} - -//******************************************************************************** - -//get sensor information by location -//******************************************************************************** -type DataStore_SensorByLocation struct { - Id sensorByLocation `json:"_id" bson:"_id"` -} - -type sensorByLocation struct { - Year int `json:"year" bson:"year"` - Month int `json:"month" bson:"month"` - Location string `json:"location" bson:"location"` -} - -/* -func GetSensorInfoByLocation(sensor_location string) ([]DataStore_SensorByLocation, error) { - s := []DataStore_SensorByLocation{} - if db.Mongo.Connected() == true { - session := db.Mongo.Session.Copy() - defer session.Close() - c := session.DB(db.Mongo.Info.Database).C(collection) - err := c.Pipe([]bson.M{{"$project": bson.M{"location": "$location", "year": bson.M{"$year": "$updated"}, "month": bson.M{"$month": "$updated"}}}, - bson.M{"$match": bson.M{"location": sensor_location}}, - bson.M{"$group": bson.M{"_id": bson.M{"year": "$year", "month": "$month", "location": "$location"}}}, - bson.M{"$sort": bson.M{"_id.year": -1, "_id.month": -1}}}).All(&s) - if err != nil { - log.Println(err) - return s, nil - } - return s, nil - } else { - return s, errors.New("Query failed") - } -} -*/ - -//******************************************************************************** - -/************************* -testStore := model.SensorData{ - ID: bson.NewObjectId(), - Temperature: 34.2, - Humidity: 33.22, - Location: "Grand Meadow", - Updated: time.Now(), -} -**************************/ +} \ No newline at end of file diff --git a/server.go b/server/mywebsite.go similarity index 66% rename from server.go rename to server/mywebsite.go index 6199475..edb23b2 100644 --- a/server.go +++ b/server/mywebsite.go @@ -6,28 +6,12 @@ import ( "strconv" "github.com/NYTimes/gziphandler" - //local import paths relative to app.yaml file "mywebsite/server/controller/api" "mywebsite/server/db" "mywebsite/server/route" "mywebsite/server/utils" ) -/* for app engine -func init() { - configurations := utils.ReadConfig() - - db.Configure(configurations.Database) - api.Configure(configurations.Api) - - db.Mongo.Connect() - - router := route.Routes() - - http.Handle("/", router) -} -*/ - func main(){ configurations := utils.ReadConfig() diff --git a/server/utils/config.go b/server/utils/config.go index 4b60f40..e6b45b8 100644 --- a/server/utils/config.go +++ b/server/utils/config.go @@ -14,7 +14,7 @@ import ( type Config struct { Database db.DatabaseInfo `json:"database"` Api api.ApiInfo `json:"api"` - Port int `json:"port"` + Port int `json:"port"` } //read the config file and return JsonObject struct From f8ccec7ae0b7abcb6ad0bc7e03fe6e06257c6ef0 Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Thu, 1 Sep 2016 04:25:58 +0000 Subject: [PATCH 3/8] finished paging --- client/assets/scss/Content.scss | 3 +++ client/assets/scss/main.scss | 13 +++++++++++++ client/js/components/Preview.js | 9 +++++---- client/js/components/sensors/SensorList.js | 1 - client/js/pages/Index.js | 6 +++++- package.json | 6 ++++-- readme.md | 13 +++++-------- server/utils/config.go | 2 -- 8 files changed, 35 insertions(+), 18 deletions(-) diff --git a/client/assets/scss/Content.scss b/client/assets/scss/Content.scss index 55c9552..fdd6a11 100644 --- a/client/assets/scss/Content.scss +++ b/client/assets/scss/Content.scss @@ -29,4 +29,7 @@ pre { white-space: pre-wrap; } + .btn{ + width: 100%; + } } diff --git a/client/assets/scss/main.scss b/client/assets/scss/main.scss index 9e9b508..0c58bf9 100644 --- a/client/assets/scss/main.scss +++ b/client/assets/scss/main.scss @@ -1,6 +1,7 @@ @import './utils.scss'; $linkColor: #3598db; +$backgroundColor: #FFFFFF; html { font-family: 'Roboto Slab', serif; @@ -9,6 +10,7 @@ html { overflow-y: scroll; } body { + background-color: $backgroundColor; max-width: 100%; overflow-x: hidden; position: relative; @@ -79,3 +81,14 @@ hr { flex: 1; justify-content: center; } +.btn{ + background-color: $backgroundColor; + border: 1px solid #DADADA; + border-radius: .2em; + cursor: pointer; + padding: .5em; + + &:hover{ + background-color: #F3F3F3; + } +} \ No newline at end of file diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index db6f688..8c38a30 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -7,7 +7,7 @@ export default class Preview extends React.Component{ insertPosts(posts){ let elements = []; - for (let i in posts){ + for (let i = 0; i < this.props.postLimit && i < posts.length; i++){ elements.push(
@@ -22,8 +22,6 @@ export default class Preview extends React.Component{

); - - if(i >= this.props.postLimit) break; } return elements; @@ -31,10 +29,13 @@ export default class Preview extends React.Component{ render(){ const posts = this.props.posts; - + return (
{posts.length > 0 ? this.insertPosts(posts): null} + {posts.length > this.props.postLimit ? + + : null}
); } diff --git a/client/js/components/sensors/SensorList.js b/client/js/components/sensors/SensorList.js index f13a7fc..5e2983f 100644 --- a/client/js/components/sensors/SensorList.js +++ b/client/js/components/sensors/SensorList.js @@ -50,7 +50,6 @@ export default class SensorList extends React.Component { ); } render(){ - console.log(this.state); return (
{this.state.fetched ? this.state.sensors.map(this.insertSensorData) : null} diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 3c21c8d..4b6468e 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -43,7 +43,11 @@ export default class Index extends React.Component {
- {typeof this.page === 'undefined' && !fetching ? : null} + {typeof this.page === 'undefined' && !fetching + ? + : null} {this.page === 'post' && !fetching ? : null} {fetching ? loadingElement : null} diff --git a/package.json b/package.json index 2221191..2ad0b69 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,12 @@ "scripts": { "build": "webpack && babel-node metadata.js", "c9": "webpack-dev-server --port $PORT --host $IP --hot --content-base dist --history-api-fallback", + "check_gzip_size": "gzip -9 -c ./public/client.min.js | wc -c | numfmt --to=iec-i --suffix=B --padding=10", + "deploy" : "npm run get_dependencies && npm run prod && ./mywebsite", "dev": "webpack-dev-server --content-base public --inline --hot --history-api-fallback", + "get_dependencies": "npm install & go get ./server", "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go", - "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go", - "deploy" : "npm run prod && ./mywebsite" + "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go" }, "repository": { "type": "git", diff --git a/readme.md b/readme.md index 0e7b72b..7f0b8fc 100644 --- a/readme.md +++ b/readme.md @@ -4,20 +4,17 @@ - Go App Engine `npm run build` - builds the application using webpack and runs metadata.js - +`npm run - metadata.js recursivly scans the posts folder for markdown files and then parses each into into a json object - the posts folder is then copied into the dist folder ## TODO -- fix font sizing +- sticky footer - clean up css - adjust animations -- fix goapp serve and webpack-dev-server so paths work correctly -- posts page +- fix go and webpack-dev-server so paths work correctly - add sensor page -- finally do writeups on my projects -- clean go code up -- host on app engine (run mongodb on compute engine???) -- pull everything off digital ocean - add paging + +- finally do writeups on my projects \ No newline at end of file diff --git a/server/utils/config.go b/server/utils/config.go index e6b45b8..5085ad6 100644 --- a/server/utils/config.go +++ b/server/utils/config.go @@ -31,8 +31,6 @@ func ReadConfig() Config { log.Printf("%s\n", string(file)) - //m := new(Dispatch) - //var m interface{} var result Config err := json.Unmarshal(file, &result) From f8c89b4486bbc668531176ff3690283f6bf4c79e Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Thu, 1 Sep 2016 13:11:17 +0000 Subject: [PATCH 4/8] beautified --- client/assets/js/bubble.js | 2 +- client/assets/scss/Content.scss | 21 +++++---- client/assets/scss/Sidebar.scss | 2 +- client/assets/scss/main.scss | 20 ++++++--- client/js/app.js | 14 +++--- client/js/components/Footer.js | 6 +-- client/js/components/Header.js | 8 ++-- client/js/components/Post.js | 18 ++++---- client/js/components/Preview.js | 10 ++--- client/js/components/Sidebar.js | 10 ++--- client/js/components/sensors/SensorList.js | 10 ++--- client/js/pages/Index.js | 52 +++++++++++----------- client/js/redux/actions.js | 12 ++--- client/js/redux/constants.js | 6 +-- client/js/redux/reducers.js | 12 ++--- client/js/redux/store.js | 8 ++-- 16 files changed, 107 insertions(+), 104 deletions(-) diff --git a/client/assets/js/bubble.js b/client/assets/js/bubble.js index 9f5d455..79c0537 100644 --- a/client/assets/js/bubble.js +++ b/client/assets/js/bubble.js @@ -1,4 +1,4 @@ -var width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true; +let width, height, largeHeader, canvas, ctx, circles, target, animateHeader = true; // Main export function bubble() { diff --git a/client/assets/scss/Content.scss b/client/assets/scss/Content.scss index fdd6a11..1972f84 100644 --- a/client/assets/scss/Content.scss +++ b/client/assets/scss/Content.scss @@ -1,20 +1,19 @@ .Content { - flex: 1; - flex-wrap: wrap; - min-width: 0; - .post + .post { + flex: 1; + flex-wrap: wrap; + min-width: 0; + .post+ .post { margin-top: 2em; } .date { display: block; margin: 0; opacity: 0.7; - - @media (min-width: 1200px){ - position: absolute; - width: 7em; - text-align: right; - margin-left: -8em; + @media (min-width: 1200px) { + position: absolute; + width: 7em; + text-align: right; + margin-left: -8em; } } .intro { @@ -29,7 +28,7 @@ pre { white-space: pre-wrap; } - .btn{ + .btn { width: 100%; } } diff --git a/client/assets/scss/Sidebar.scss b/client/assets/scss/Sidebar.scss index c3f86f0..d62afa2 100644 --- a/client/assets/scss/Sidebar.scss +++ b/client/assets/scss/Sidebar.scss @@ -33,7 +33,7 @@ $transitionDuration: 0.4s; &:before { content: " "; display: block; - background: rgba(0,0,0,0.4); + background: rgba(0, 0, 0, 0.4); position: absolute; height: 100%; width: 100vw; diff --git a/client/assets/scss/main.scss b/client/assets/scss/main.scss index 0c58bf9..9cc7924 100644 --- a/client/assets/scss/main.scss +++ b/client/assets/scss/main.scss @@ -1,14 +1,13 @@ @import './utils.scss'; - $linkColor: #3598db; $backgroundColor: #FFFFFF; - html { font-family: 'Roboto Slab', serif; max-width: 100%; overflow-x: hidden; overflow-y: scroll; } + body { background-color: $backgroundColor; max-width: 100%; @@ -17,6 +16,7 @@ body { -webkit-font-smoothing: subpixel-antialiased; font-weight: 300; } + h1, h2, h3, @@ -27,9 +27,11 @@ h6 { font-weight: 400; line-height: 1em; } + p { font-weight: 300; } + *, *:after, *:before { @@ -37,6 +39,7 @@ p { -moz-box-sizing: border-box; box-sizing: border-box; } + a { background-color: transparent; color: $linkColor; @@ -45,11 +48,13 @@ a { color: $linkColor; } } + hr { margin: 1em; border: 0; border-top: 1px solid #eee; } + .Footer, .Main { display: flex; @@ -61,9 +66,11 @@ hr { width: 1em; } } + .Main { padding-top: 1em; } + .Header { width: 100%; background: url("../images/header.jpg"); @@ -76,19 +83,20 @@ hr { text-align: center; } } -.Loading{ + +.Loading { display: flex; flex: 1; justify-content: center; } -.btn{ + +.btn { background-color: $backgroundColor; border: 1px solid #DADADA; border-radius: .2em; cursor: pointer; padding: .5em; - - &:hover{ + &:hover { background-color: #F3F3F3; } } \ No newline at end of file diff --git a/client/js/app.js b/client/js/app.js index 65d0f33..54c9c80 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -13,22 +13,22 @@ import * as actions from './redux/actions'; import Index from './pages/Index'; -class Main extends React.Component{ - render(){ - return( +class Main extends React.Component { + render() { + return (
{React.cloneElement(this.props.children, this.props)}
); } } -function mapStateToProps(state){ +function mapStateToProps(state) { return { redux: state.reducer } } -function mapDispatchToProps(dispatch){ - return{ +function mapDispatchToProps(dispatch) { + return { actions: bindActionCreators(actions, dispatch) } } @@ -44,4 +44,4 @@ ReactDOM.render(( -),document.getElementById('app')); +), document.getElementById('app')); diff --git a/client/js/components/Footer.js b/client/js/components/Footer.js index a15159c..068eea4 100644 --- a/client/js/components/Footer.js +++ b/client/js/components/Footer.js @@ -2,10 +2,10 @@ import React from 'react'; import '../../assets/scss/Footer.scss'; -export default class Footer extends React.Component{ +export default class Footer extends React.Component { - render(){ - return( + render() { + return ( diff --git a/client/js/components/Header.js b/client/js/components/Header.js index 880c266..491e357 100644 --- a/client/js/components/Header.js +++ b/client/js/components/Header.js @@ -1,13 +1,13 @@ import React from 'react'; import {bubble} from '../../assets/js/bubble'; -export default class Header extends React.Component{ - componentDidMount(){ +export default class Header extends React.Component { + componentDidMount() { bubble(); } - render(){ - return( + render() { + return ( diff --git a/client/js/components/Post.js b/client/js/components/Post.js index 169e054..a6c0d0a 100644 --- a/client/js/components/Post.js +++ b/client/js/components/Post.js @@ -1,23 +1,23 @@ +import hljs from 'highlight.js'; +import marked from 'marked'; import React from 'react'; import {Link} from 'react-router'; -import marked from 'marked'; -import hljs from 'highlight.js'; import '../../assets/scss/Content.scss'; const renderer = new marked.Renderer(); marked.setOptions({ - langPrefix: 'hljs ', - highlight: (code) => { - return hljs.highlightAuto(code).value; - } + langPrefix: 'hljs ', + highlight: (code) => { + return hljs.highlightAuto(code).value; + } }); -export default class Post extends React.Component{ +export default class Post extends React.Component { - render(){ - return( + render() { + return (
diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index 8c38a30..d4dc511 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -3,11 +3,11 @@ import {Link} from 'react-router'; import '../../assets/scss/Content.scss'; -export default class Preview extends React.Component{ +export default class Preview extends React.Component { - insertPosts(posts){ + insertPosts(posts) { let elements = []; - for (let i = 0; i < this.props.postLimit && i < posts.length; i++){ + for (let i = 0; i < this.props.postLimit && i < posts.length; i++) { elements.push(
@@ -27,9 +27,9 @@ export default class Preview extends React.Component{ return elements; } - render(){ + render() { const posts = this.props.posts; - + return (
{posts.length > 0 ? this.insertPosts(posts): null} diff --git a/client/js/components/Sidebar.js b/client/js/components/Sidebar.js index a0026c2..33cce28 100644 --- a/client/js/components/Sidebar.js +++ b/client/js/components/Sidebar.js @@ -7,9 +7,9 @@ import SensorList from './sensors/SensorList'; import me from '../../assets/images/me.jpg'; import '../../assets/scss/Sidebar.scss'; -export default class Sidebar extends React.Component{ +export default class Sidebar extends React.Component { - constructor(){ + constructor() { super(); this.state = { @@ -19,7 +19,7 @@ export default class Sidebar extends React.Component{ this.onToggle = this.onToggle.bind(this); } - onToggle(){ + onToggle() { let temp = this.state.toggler; temp = temp === "open" ? "" : "open"; @@ -28,8 +28,8 @@ export default class Sidebar extends React.Component{ }); } - render(){ - return( + render() { + return (
); } - render(){ + render() { return (
{this.state.fetched ? this.state.sensors.map(this.insertSensorData) : null} diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 4b6468e..09602e2 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -17,31 +17,31 @@ import '../../assets/css/dracula.css'; import loading from '../../assets/images/loading.svg'; export default class Index extends React.Component { - componentDidMount() { - this.props.actions.fetchPreview(); - this.page = this.props.params.page; - this.page === 'post' ? this.props.actions.fetchPost(this.props.params.category, this.props.params.post) : ""; + componentDidMount() { + this.props.actions.fetchPreview(); + this.page = this.props.params.page; + this.page === 'post' ? this.props.actions.fetchPost(this.props.params.category, this.props.params.post) : ""; + } + + + componentWillReceiveProps(nextProps) { + if (this.props.params !== nextProps.params) { + const params = nextProps.params; + this.page = params.page; + + if (typeof params.post !== 'undefined' && typeof params.category !== 'undefined') { + this.props.actions.fetchPost(params.category, params.post); + } } + } + render() { + const fetched = this.props.redux.fetched; + const fetching = this.props.redux.fetching; - componentWillReceiveProps(nextProps){ - if(this.props.params !== nextProps.params){ - const params = nextProps.params; - this.page = params.page; - - if(typeof params.post !== 'undefined' && typeof params.category !== 'undefined'){ - this.props.actions.fetchPost(params.category, params.post); - } - } - } - - render() { - const fetched = this.props.redux.fetched; - const fetching = this.props.redux.fetching; - - return ( -
-
+ return ( +
+
{typeof this.page === 'undefined' && !fetching ? : null} {fetching ? loadingElement : null} - +
-
+
- ); - } + ); + } } const loadingElement =
diff --git a/client/js/redux/actions.js b/client/js/redux/actions.js index a191abd..77568f9 100644 --- a/client/js/redux/actions.js +++ b/client/js/redux/actions.js @@ -2,7 +2,7 @@ import * as types from "./constants"; import marked from 'marked'; import 'whatwg-fetch'; -export function increasePostLimit(){ +export function increasePostLimit() { return { type: types.INCREASE_POST_LIMIT } @@ -15,15 +15,15 @@ function initPreview(posts) { } } -function loadPost(post){ +function loadPost(post) { return { - type: types.LOAD_POST, - post + type: types.LOAD_POST, + post } } -function fetching(){ - return{ +function fetching() { + return { type: types.FETCHING } } diff --git a/client/js/redux/constants.js b/client/js/redux/constants.js index 6d21a68..5eb537f 100644 --- a/client/js/redux/constants.js +++ b/client/js/redux/constants.js @@ -1,6 +1,6 @@ //constants +export const INCREASE_POST_LIMIT = 'INCREASE_POST_LIMIT'; export const INIT_PREVIEW = 'INIT_PREVIEW'; -export const FILTER_PREVIEW = 'FILTER_PREVIEW'; -export const LOAD_POST = 'LOAD_POST'; export const FETCHING = 'FETCHING'; -export const INCREASE_POST_LIMIT = 'INCREASE_POST_LIMIT'; \ No newline at end of file +export const FILTER_PREVIEW = 'FILTER_PREVIEW'; +export const LOAD_POST = 'LOAD_POST'; \ No newline at end of file diff --git a/client/js/redux/reducers.js b/client/js/redux/reducers.js index ebf0d11..79a76d2 100644 --- a/client/js/redux/reducers.js +++ b/client/js/redux/reducers.js @@ -1,10 +1,6 @@ //just using one reducer - use combineReducers from redux to modularize things -import { - combineReducers -} from 'redux'; -import { - routerReducer -} from 'react-router-redux'; +import {combineReducers} from 'redux'; +import {routerReducer} from 'react-router-redux'; //import typs import * as types from './constants'; @@ -38,12 +34,12 @@ function reducer(state = defaultState, action) { }); case types.FETCHING: return Object.assign({}, state, { - fetched : false, + fetched: false, fetching: true }); case types.INCREASE_POST_LIMIT: return Object.assign({}, state, { - postLimit : state.postLimit + 10 + postLimit: state.postLimit + 10 }); } diff --git a/client/js/redux/store.js b/client/js/redux/store.js index fc5dc04..4206e8e 100644 --- a/client/js/redux/store.js +++ b/client/js/redux/store.js @@ -1,8 +1,8 @@ -import {applyMiddleware, createStore} from 'redux'; -import {syncHistoryWithStore} from 'react-router-redux'; -import {browserHistory} from 'react-router'; -import thunk from 'redux-thunk'; import logger from 'redux-logger'; +import thunk from 'redux-thunk'; +import {applyMiddleware, createStore} from 'redux'; +import {browserHistory} from 'react-router'; +import {syncHistoryWithStore} from 'react-router-redux'; import reducers from './reducers'; From 00d50fea7a0b508a4826ce7193d154b88a4fd3e0 Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Thu, 1 Sep 2016 20:19:55 +0000 Subject: [PATCH 5/8] fixed scrolling issue --- client/assets/scss/main.scss | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/client/assets/scss/main.scss b/client/assets/scss/main.scss index 9cc7924..2d8e3d9 100644 --- a/client/assets/scss/main.scss +++ b/client/assets/scss/main.scss @@ -3,17 +3,18 @@ $linkColor: #3598db; $backgroundColor: #FFFFFF; html { font-family: 'Roboto Slab', serif; - max-width: 100%; - overflow-x: hidden; - overflow-y: scroll; + overflow: auto; + + @media (max-width: 768px) { + overflow-x: hidden; + } } body { + overflow: hidden; background-color: $backgroundColor; - max-width: 100%; - overflow-x: hidden; position: relative; - -webkit-font-smoothing: subpixel-antialiased; + -webkit-font-smoothing: antialiased; font-weight: 300; } From 6bf367f9bea9c09802e6bf6bd52eefac29b989ae Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Fri, 2 Sep 2016 18:19:28 +0000 Subject: [PATCH 6/8] fixed html in preview --- client/js/components/Preview.js | 3 +-- client/js/pages/Index.js | 3 +-- metadata.js | 4 ++-- package.json | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index d4dc511..c37b087 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -13,8 +13,7 @@ export default class Preview extends React.Component {
{posts[i].date}
-

{posts[i].title.toString()}

-

{posts[i].intro.toString()}

+

continue reading diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 09602e2..c6aa2f3 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -23,7 +23,6 @@ export default class Index extends React.Component { this.page === 'post' ? this.props.actions.fetchPost(this.props.params.category, this.props.params.post) : ""; } - componentWillReceiveProps(nextProps) { if (this.props.params !== nextProps.params) { const params = nextProps.params; @@ -58,6 +57,6 @@ export default class Index extends React.Component { } } -const loadingElement =

+const loadingElement =
loading...
; diff --git a/metadata.js b/metadata.js index 6762140..fa3bce8 100644 --- a/metadata.js +++ b/metadata.js @@ -40,8 +40,8 @@ function parse_dir(dir, folder_name){ filename: post.slice(0, post.length - 3), category: folder_name, date: post.slice(0, 10), - title: tokens[0].text, - intro: tokens[1].text + title: `

${tokens[0].text}

`, + intro: marked(tokens[1].text) } json.posts.push(temp); } diff --git a/package.json b/package.json index 2ad0b69..72b6bf9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "check_gzip_size": "gzip -9 -c ./public/client.min.js | wc -c | numfmt --to=iec-i --suffix=B --padding=10", "deploy" : "npm run get_dependencies && npm run prod && ./mywebsite", "dev": "webpack-dev-server --content-base public --inline --hot --history-api-fallback", - "get_dependencies": "npm install & go get ./server", + "get_dependencies": "go get ./server && npm install", "prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go", "prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js && go build ./server/mywebsite.go" }, From be5e95b6cfe85b92844fae9dc8967cd7c210d762 Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Fri, 2 Sep 2016 20:38:01 +0000 Subject: [PATCH 7/8] fixed routing --- client/js/app.js | 18 ++++------ client/js/components/Post.js | 21 ++++++++++-- client/js/components/Preview.js | 26 +++++++++++---- client/js/components/sensors/SensorInfo.js | 11 +++++++ client/js/components/utils/Loading.js | 14 ++++++++ client/js/pages/Index.js | 38 ++-------------------- 6 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 client/js/components/sensors/SensorInfo.js create mode 100644 client/js/components/utils/Loading.js diff --git a/client/js/app.js b/client/js/app.js index 54c9c80..f8913dc 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -12,14 +12,9 @@ import store, {history} from './redux/store'; import * as actions from './redux/actions'; import Index from './pages/Index'; - -class Main extends React.Component { - render() { - return ( -
{React.cloneElement(this.props.children, this.props)}
- ); - } -} +import Preview from './components/Preview'; +import Post from './components/Post'; +import SensorInfo from './components/sensors/SensorInfo'; function mapStateToProps(state) { return { @@ -33,14 +28,15 @@ function mapDispatchToProps(dispatch) { } } -const App = connect(mapStateToProps, mapDispatchToProps)(Main); +const App = connect(mapStateToProps, mapDispatchToProps)(Index); ReactDOM.render(( - - + + + diff --git a/client/js/components/Post.js b/client/js/components/Post.js index a6c0d0a..4f1d13a 100644 --- a/client/js/components/Post.js +++ b/client/js/components/Post.js @@ -3,6 +3,9 @@ import marked from 'marked'; import React from 'react'; import {Link} from 'react-router'; +//components +import Loading from './utils/Loading'; + import '../../assets/scss/Content.scss'; const renderer = new marked.Renderer(); @@ -16,13 +19,25 @@ marked.setOptions({ export default class Post extends React.Component { + componentDidMount() { + const params = this.props.params; + this.props.actions.fetchPost(params.category, params.post); + } + render() { + const post = this.props.redux.post; + const fetched = this.props.redux.fetched; + const fetching = this.props.redux.fetching; + return (
-
+ {fetched ? +
+
+ Home +
+ : }
- Home -
); } } diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index c37b087..bfeaae9 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -1,13 +1,20 @@ import React from 'react'; import {Link} from 'react-router'; +//components +import Loading from './utils/Loading'; + import '../../assets/scss/Content.scss'; export default class Preview extends React.Component { + componentDidMount() { + this.props.actions.fetchPreview(); + } + insertPosts(posts) { let elements = []; - for (let i = 0; i < this.props.postLimit && i < posts.length; i++) { + for (let i = 0; i < this.props.redux.postLimit && i < posts.length; i++) { elements.push(
@@ -27,14 +34,21 @@ export default class Preview extends React.Component { } render() { - const posts = this.props.posts; + const posts = this.props.redux.preview.posts; + const postLimit = this.props.redux.postLimit; + const increasePostLimit = this.props.actions.increasePostLimit; + const fetched = this.props.redux.fetched; return (
- {posts.length > 0 ? this.insertPosts(posts): null} - {posts.length > this.props.postLimit ? - - : null} + {fetched ? +
+ {posts.length > 0 ? this.insertPosts(posts): null} + {posts.length > postLimit ? + + : null} +
+ : }
); } diff --git a/client/js/components/sensors/SensorInfo.js b/client/js/components/sensors/SensorInfo.js new file mode 100644 index 0000000..38c80fc --- /dev/null +++ b/client/js/components/sensors/SensorInfo.js @@ -0,0 +1,11 @@ +import React from 'react'; + +export default class SensorInfo extends React.Component{ + + + render(){ + return( +
Test123
+ ); + } +} \ No newline at end of file diff --git a/client/js/components/utils/Loading.js b/client/js/components/utils/Loading.js new file mode 100644 index 0000000..8b59fe9 --- /dev/null +++ b/client/js/components/utils/Loading.js @@ -0,0 +1,14 @@ +import React from 'react'; + +//loading icon +import loading from '../../../assets/images/loading.svg'; + +export default class Loading extends React.Component{ + render(){ + return( +
+ loading... +
+ ); + } +} \ No newline at end of file diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index c6aa2f3..33c1408 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -2,10 +2,8 @@ import React from 'react'; //components import Header from '../components/Header'; -import Preview from '../components/Preview'; import Footer from '../components/Footer'; import Sidebar from '../components/Sidebar'; -import Post from '../components/Post'; //css import '../../assets/css/normalize.css'; @@ -13,50 +11,18 @@ import '../../assets/scss/main.scss'; import 'font-awesome/css/font-awesome.min.css'; import '../../assets/css/dracula.css'; -//loading icon -import loading from '../../assets/images/loading.svg'; - export default class Index extends React.Component { - componentDidMount() { - this.props.actions.fetchPreview(); - this.page = this.props.params.page; - this.page === 'post' ? this.props.actions.fetchPost(this.props.params.category, this.props.params.post) : ""; - } - - componentWillReceiveProps(nextProps) { - if (this.props.params !== nextProps.params) { - const params = nextProps.params; - this.page = params.page; - - if (typeof params.post !== 'undefined' && typeof params.category !== 'undefined') { - this.props.actions.fetchPost(params.category, params.post); - } - } - } render() { - const fetched = this.props.redux.fetched; - const fetching = this.props.redux.fetching; - return (
- {typeof this.page === 'undefined' && !fetching - ? - : null} - {this.page === 'post' && !fetching ? : null} - {fetching ? loadingElement : null} + {React.cloneElement(this.props.children, this.props)}
); } -} - -const loadingElement =
- loading... -
; +} \ No newline at end of file From 0e8d2e5b2be240e839c76763d22030be6b90550e Mon Sep 17 00:00:00 2001 From: mgerb42 Date: Mon, 5 Sep 2016 18:27:52 +0000 Subject: [PATCH 8/8] handling sensors with redux --- client/js/app.js | 9 +- client/js/components/Post.js | 8 +- client/js/components/Preview.js | 12 +-- client/js/components/Sidebar.js | 2 +- client/js/components/sensors/SensorInfo.js | 7 +- client/js/components/sensors/SensorList.js | 39 +-------- client/js/pages/Index.js | 7 +- .../js/redux/{actions.js => actions/app.js} | 2 +- client/js/redux/actions/sensor.js | 83 +++++++++++++++++++ .../redux/{constants.js => constants/app.js} | 0 client/js/redux/constants/sensor.js | 10 +++ .../js/redux/{reducers.js => reducers/app.js} | 15 +--- client/js/redux/reducers/reducers.js | 14 ++++ client/js/redux/reducers/sensor.js | 59 +++++++++++++ client/js/redux/store.js | 2 +- 15 files changed, 200 insertions(+), 69 deletions(-) rename client/js/redux/{actions.js => actions/app.js} (96%) create mode 100644 client/js/redux/actions/sensor.js rename client/js/redux/{constants.js => constants/app.js} (100%) create mode 100644 client/js/redux/constants/sensor.js rename client/js/redux/{reducers.js => reducers/app.js} (75%) create mode 100644 client/js/redux/reducers/reducers.js create mode 100644 client/js/redux/reducers/sensor.js diff --git a/client/js/app.js b/client/js/app.js index f8913dc..9560bed 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -9,7 +9,8 @@ import {connect, Provider} from 'react-redux'; import store, {history} from './redux/store'; //import actions -import * as actions from './redux/actions'; +import * as appActions from './redux/actions/app'; +import * as sensorActions from './redux/actions/sensor'; import Index from './pages/Index'; import Preview from './components/Preview'; @@ -18,13 +19,15 @@ import SensorInfo from './components/sensors/SensorInfo'; function mapStateToProps(state) { return { - redux: state.reducer + app: state.app, + sensor: state.sensor } } function mapDispatchToProps(dispatch) { return { - actions: bindActionCreators(actions, dispatch) + appActions: bindActionCreators(appActions, dispatch), + sensorActions: bindActionCreators(sensorActions, dispatch) } } diff --git a/client/js/components/Post.js b/client/js/components/Post.js index 4f1d13a..188153b 100644 --- a/client/js/components/Post.js +++ b/client/js/components/Post.js @@ -21,13 +21,13 @@ export default class Post extends React.Component { componentDidMount() { const params = this.props.params; - this.props.actions.fetchPost(params.category, params.post); + this.props.appActions.fetchPost(params.category, params.post); } render() { - const post = this.props.redux.post; - const fetched = this.props.redux.fetched; - const fetching = this.props.redux.fetching; + const post = this.props.app.post; + const fetched = this.props.app.fetched; + const fetching = this.props.app.fetching; return (
diff --git a/client/js/components/Preview.js b/client/js/components/Preview.js index bfeaae9..9355c84 100644 --- a/client/js/components/Preview.js +++ b/client/js/components/Preview.js @@ -9,12 +9,12 @@ import '../../assets/scss/Content.scss'; export default class Preview extends React.Component { componentDidMount() { - this.props.actions.fetchPreview(); + this.props.appActions.fetchPreview(); } insertPosts(posts) { let elements = []; - for (let i = 0; i < this.props.redux.postLimit && i < posts.length; i++) { + for (let i = 0; i < this.props.app.postLimit && i < posts.length; i++) { elements.push(
@@ -34,10 +34,10 @@ export default class Preview extends React.Component { } render() { - const posts = this.props.redux.preview.posts; - const postLimit = this.props.redux.postLimit; - const increasePostLimit = this.props.actions.increasePostLimit; - const fetched = this.props.redux.fetched; + const posts = this.props.app.preview.posts; + const postLimit = this.props.app.postLimit; + const fetched = this.props.app.fetched; + const increasePostLimit = this.props.appActions.increasePostLimit; return (
diff --git a/client/js/components/Sidebar.js b/client/js/components/Sidebar.js index 33cce28..ce12e27 100644 --- a/client/js/components/Sidebar.js +++ b/client/js/components/Sidebar.js @@ -63,7 +63,7 @@ export default class Sidebar extends React.Component {

Sensors


- + {this.props.sensor.fetchedList ? : null}
); } diff --git a/client/js/components/sensors/SensorInfo.js b/client/js/components/sensors/SensorInfo.js index 38c80fc..dcd0f3b 100644 --- a/client/js/components/sensors/SensorInfo.js +++ b/client/js/components/sensors/SensorInfo.js @@ -2,10 +2,13 @@ import React from 'react'; export default class SensorInfo extends React.Component{ - + componentDidMount(){ + this.props.sensorActions.fetchSensorInfoYear('Grand Meadow', '2016'); + this.props.sensorActions.fetchSensorInfoMonth('Grand Meadow', '2016', 'May'); + } render(){ return( -
Test123
+
Test123
); } } \ No newline at end of file diff --git a/client/js/components/sensors/SensorList.js b/client/js/components/sensors/SensorList.js index fe6a02e..d7b79eb 100644 --- a/client/js/components/sensors/SensorList.js +++ b/client/js/components/sensors/SensorList.js @@ -3,41 +3,6 @@ import 'whatwg-fetch'; export default class SensorList extends React.Component { - constructor() { - super(); - - this.state = { - sensors: {}, - fetching: false, - fetched: false - } - } - - componentDidMount() { - this.loadSensorData(); - } - - loadSensorData() { - this.setState({ - fetching: true - }); - - fetch('/api/allsensors') - .then((response) => { - return response.json() - }) - .then((json) => { - this.setState({ - sensors: json, - fetching: false, - fetched: true - }); - }) - .catch((e) => { - console.log('Loading sensors failed', e) - }); - } - insertSensorData = (sensor, index) => { const date = new Date(sensor.updated); @@ -50,9 +15,11 @@ export default class SensorList extends React.Component { ); } render() { + const list = this.props.list; + return (
- {this.state.fetched ? this.state.sensors.map(this.insertSensorData) : null} + {list.map(this.insertSensorData)}
) } diff --git a/client/js/pages/Index.js b/client/js/pages/Index.js index 33c1408..308d94c 100644 --- a/client/js/pages/Index.js +++ b/client/js/pages/Index.js @@ -12,14 +12,17 @@ import 'font-awesome/css/font-awesome.min.css'; import '../../assets/css/dracula.css'; export default class Index extends React.Component { - + + componentDidMount(){ + this.props.sensorActions.fetchSensorList(); + } render() { return (
{React.cloneElement(this.props.children, this.props)} - +
diff --git a/client/js/redux/actions.js b/client/js/redux/actions/app.js similarity index 96% rename from client/js/redux/actions.js rename to client/js/redux/actions/app.js index 77568f9..b1c9018 100644 --- a/client/js/redux/actions.js +++ b/client/js/redux/actions/app.js @@ -1,4 +1,4 @@ -import * as types from "./constants"; +import * as types from "../constants/app"; import marked from 'marked'; import 'whatwg-fetch'; diff --git a/client/js/redux/actions/sensor.js b/client/js/redux/actions/sensor.js new file mode 100644 index 0000000..e356e99 --- /dev/null +++ b/client/js/redux/actions/sensor.js @@ -0,0 +1,83 @@ +import * as types from "../constants/sensor"; +import 'whatwg-fetch'; + +function loadSensorList(sensor_list){ + return { + type: types.LOAD_SENSOR_LIST, + sensor_list + } +} + +function loadSensorInfoYear(sensor_info){ + return{ + type: types.LOAD_SENSOR_INFO_YEAR, + sensor_info + } +} + +function loadSensorInfoMonth(sensor_info){ + return{ + type: types.LOAD_SENSOR_INFO_MONTH, + sensor_info + } +} + +function fetchingList(){ + return { + type: types.FETCHING_LIST + } +} + +function fetchingInfoYear(){ + return { + type: types.FETCHING_INFO_YEAR + } +} + +function fetchingInfoMonth(){ + return { + type: types.FETCHING_INFO_MONTH + } +} + +export function fetchSensorList(){ + return (dispatch) => { + dispatch(fetchingList()); + return fetch('/api/allsensors') + .then(response => response.json()) + .then(json => { + dispatch(loadSensorList(json)); + }) + .catch(error => { + console.log(error); + }); + } +} + +export function fetchSensorInfoYear(location, year){ + return (dispatch) => { + dispatch(fetchingInfoYear()); + return fetch(`/api/sensor/${location}/${year}`) + .then(response => response.json()) + .then(json => { + dispatch(loadSensorInfoYear(json)); + }) + .catch(error => { + console.log(error); + }); + } +} + +export function fetchSensorInfoMonth(location, year, month){ + return (dispatch) => { + dispatch(fetchingInfoMonth()); + return fetch(`/api/sensor/${location}/${year}/${month}`) + .then(response => response.json()) + .then(json => { + dispatch(loadSensorInfoMonth(json)); + }) + .catch(error => { + console.log(error); + }); + } +} \ No newline at end of file diff --git a/client/js/redux/constants.js b/client/js/redux/constants/app.js similarity index 100% rename from client/js/redux/constants.js rename to client/js/redux/constants/app.js diff --git a/client/js/redux/constants/sensor.js b/client/js/redux/constants/sensor.js new file mode 100644 index 0000000..ae93469 --- /dev/null +++ b/client/js/redux/constants/sensor.js @@ -0,0 +1,10 @@ +//constants +export const LOAD_SENSOR_LIST = 'LOAD_SENSOR_LIST'; +export const LOAD_SENSOR_INFO_YEAR = 'LOAD_SENSOR_INFO_YEAR'; +export const LOAD_SENSOR_INFO_MONTH = 'LOAD_SENSOR_INFO_MONTH'; + + +//fetching +export const FETCHING_LIST = 'FETCHING_LIST'; +export const FETCHING_INFO_YEAR = 'FETCHING_INFO_YEAR'; +export const FETCHING_INFO_MONTH = 'FETCHING_INFO_MONTH'; \ No newline at end of file diff --git a/client/js/redux/reducers.js b/client/js/redux/reducers/app.js similarity index 75% rename from client/js/redux/reducers.js rename to client/js/redux/reducers/app.js index 79a76d2..5611138 100644 --- a/client/js/redux/reducers.js +++ b/client/js/redux/reducers/app.js @@ -1,9 +1,5 @@ -//just using one reducer - use combineReducers from redux to modularize things -import {combineReducers} from 'redux'; -import {routerReducer} from 'react-router-redux'; - //import typs -import * as types from './constants'; +import * as types from '../constants/app'; //defaults - const defaultState = { @@ -17,7 +13,7 @@ const defaultState = { }; //default reducer -function reducer(state = defaultState, action) { +export default function app(state = defaultState, action) { //every reducer gets called when an action is called - we check for the type to modify our state accordingly switch (action.type) { case types.INIT_PREVIEW: @@ -46,10 +42,3 @@ function reducer(state = defaultState, action) { //return present state if no actions get called return state; } - -const allReducers = combineReducers({ - reducer, - routing: routerReducer -}); - -export default allReducers; diff --git a/client/js/redux/reducers/reducers.js b/client/js/redux/reducers/reducers.js new file mode 100644 index 0000000..5e5d7bd --- /dev/null +++ b/client/js/redux/reducers/reducers.js @@ -0,0 +1,14 @@ +//just using one reducer - use combineReducers from redux to modularize things +import {combineReducers} from 'redux'; +import {routerReducer} from 'react-router-redux'; + +import app from './app'; +import sensor from './sensor'; + +const allReducers = combineReducers({ + app, + sensor, + routing: routerReducer +}); + +export default allReducers; \ No newline at end of file diff --git a/client/js/redux/reducers/sensor.js b/client/js/redux/reducers/sensor.js new file mode 100644 index 0000000..8d5a4af --- /dev/null +++ b/client/js/redux/reducers/sensor.js @@ -0,0 +1,59 @@ +//import typs +import * as types from '../constants/sensor'; + +//defaults - +const defaultState = { + list : [], + infoMonth: [], + infoYear: [], + + fetchingList: false, + fetchingInfoMonth: false, + fetchingInfoYear: false, + + fetchedList: false, + fetchedInfoMonth: false, + fetchedInfoYear: false +}; + +//default reducer +export default function app(state = defaultState, action) { + switch(action.type){ + case types.FETCHING_LIST: + return Object.assign({}, state, { + fetchingList: true, + fetchedList: false + }); + case types.FETCHING_INFO_MONTH: + return Object.assign({}, state, { + fetchingInfoMonth: true, + fetchedInfoMonth: false + }); + case types.FETCHING_INFO_YEAR: + return Object.assign({}, state, { + fetchingInfoYear: true, + fetchedInfoYear: false + }); + + case types.LOAD_SENSOR_LIST: + return Object.assign({}, state, { + list: action.sensor_list, + fetchingList: false, + fetchedList: true + }); + case types.LOAD_SENSOR_INFO_MONTH: + return Object.assign({}, state, { + infoMonth: action.sensor_info, + fetchingInfoMonth: false, + fetchedInfoMonth: true + }); + case types.LOAD_SENSOR_INFO_YEAR: + return Object.assign({}, state, { + infoYear: action.sensor_info, + fetchingInfoYear: false, + fetchedInfoYear: true + }); + } + //return present state if no actions get called + return state; +} diff --git a/client/js/redux/store.js b/client/js/redux/store.js index 4206e8e..b28f24c 100644 --- a/client/js/redux/store.js +++ b/client/js/redux/store.js @@ -4,7 +4,7 @@ import {applyMiddleware, createStore} from 'redux'; import {browserHistory} from 'react-router'; import {syncHistoryWithStore} from 'react-router-redux'; -import reducers from './reducers'; +import reducers from './reducers/reducers'; const middleware = applyMiddleware(thunk, logger());