From d583ad3bb14734c7b48debbdadad00dbc6d846e5 Mon Sep 17 00:00:00 2001 From: Harman Singh Date: Mon, 14 Nov 2016 09:49:31 -0800 Subject: [PATCH 01/11] Update README.md --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2fbf185..c1988ef 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,17 @@ A mongodb database named lizardboard must be created prior to starting the appli - Ensure `mongo` is running - yarn install +### Specs +- [x] Setup Api for getting json responses of various dashboard queries following: + - [x] GET /dashboards - get all dashboards + - [x] POST /dashboards { data } - create a new dashboard entry + - [x] GET /dashboards/:id - get single dashboard entry + - [x] PUT /dashboards/:id { data } - update single dashboard entry + - [x] DELETE /dashboards/:id - delete single dashboard entry + - [x] POST /dashboards/:id/widgets - create widgets for single dashboard entry +- [x] [Create New Dashboard #23](https://github.com/GuildCrafts/lizardboard/issues/23) +- [x] [Delete Dashboard #25](https://github.com/GuildCrafts/lizardboard/issues/25) + ## Technical Stack ### Back End @@ -24,11 +35,11 @@ A mongodb database named lizardboard must be created prior to starting the appli ### Database - [Mongodb](https://docs.mongodb.com/) - -[Mongoose](http://mongoosejs.com/docs/guide.html) - -[Migrate-Mongoose](https://github.com/balmasi/migrate-mongoose) +- [Mongoose](http://mongoosejs.com/docs/guide.html) +- [Migrate-Mongoose](https://github.com/balmasi/migrate-mongoose) ## Front End - [React](https://facebook.github.io/react/) ## Testing -TBD \ No newline at end of file +TBD From a231f16f3da33cf75502f740fdf5b6fa34f28168 Mon Sep 17 00:00:00 2001 From: Harman Singh Date: Mon, 14 Nov 2016 09:50:55 -0800 Subject: [PATCH 02/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c1988ef..996a3ed 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Lizardboard +# Lizardboard Team Name: #Shaggy-Sheatbill An open source clone of [geckoboard](https://www.geckoboard.com/). Interested in contributing? Take a look at the [project page](https://github.com/GuildCrafts/lizardboard/projects) and [issues page](https://github.com/GuildCrafts/lizardboard/issues) for outstanding issues. From f20a10cf544e3cc0c58c269a2b2453d55eb4b7f8 Mon Sep 17 00:00:00 2001 From: Harman Singh Date: Mon, 14 Nov 2016 09:51:08 -0800 Subject: [PATCH 03/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 996a3ed..7bc2394 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Lizardboard Team Name: #Shaggy-Sheatbill +# Lizardboard Team Name: #Shaggy-Sheathbill An open source clone of [geckoboard](https://www.geckoboard.com/). Interested in contributing? Take a look at the [project page](https://github.com/GuildCrafts/lizardboard/projects) and [issues page](https://github.com/GuildCrafts/lizardboard/issues) for outstanding issues. From 1334ea500769e4b0ad36710b45bff011dbcce6ca Mon Sep 17 00:00:00 2001 From: Harman Singh Date: Mon, 14 Nov 2016 10:06:25 -0800 Subject: [PATCH 04/11] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7bc2394..049687f 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ A mongodb database named lizardboard must be created prior to starting the appli - [x] GET /dashboards/:id - get single dashboard entry - [x] PUT /dashboards/:id { data } - update single dashboard entry - [x] DELETE /dashboards/:id - delete single dashboard entry + - [x] GET /dashboards/:id/widgets - get all widgets for single dashboard entry - [x] POST /dashboards/:id/widgets - create widgets for single dashboard entry - [x] [Create New Dashboard #23](https://github.com/GuildCrafts/lizardboard/issues/23) - [x] [Delete Dashboard #25](https://github.com/GuildCrafts/lizardboard/issues/25) From 7391a5d6119cf7bad3d07c250f049a867dc7dc21 Mon Sep 17 00:00:00 2001 From: Harman Singh Date: Mon, 7 Nov 2016 16:53:15 -0800 Subject: [PATCH 05/11] Create User API(Closes #39) * Deleted routes/api/v1/widgets file, added creation of widgets to routes/api/v1/dashboards file * Converted widgets post to promises from callbacks * Created GET / POST / GET /:id PUT /:id and DELETE /:id routes for Users * Wrote error codes for different error types and required the errorResponse file in our dashboard routes file * Updated Users routes to handle errors with http error code responses --- routes/api/v1/errorResponse.js | 13 +++++++ server/app.js | 66 ++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 routes/api/v1/errorResponse.js create mode 100644 server/app.js diff --git a/routes/api/v1/errorResponse.js b/routes/api/v1/errorResponse.js new file mode 100644 index 0000000..2a6f4b5 --- /dev/null +++ b/routes/api/v1/errorResponse.js @@ -0,0 +1,13 @@ +const errorResponse = response => error => { + if( error.name === 'CastError' ) { + response.status( 404 ).json({}) + } + else if( error.name === 'ValidationError' ) { + response.status( 400 ).json({}) + } + else { + response.status( 500 ).json({}) + } +} + +module.exports = errorResponse diff --git a/server/app.js b/server/app.js new file mode 100644 index 0000000..03a89d6 --- /dev/null +++ b/server/app.js @@ -0,0 +1,66 @@ +const express = require( 'express' ) +const path = require( 'path' ) +const favicon = require( 'serve-favicon' ) +const logger = require( 'morgan' ) +const cookieParser = require( 'cookie-parser' ) +const bodyParser = require( 'body-parser' ) + +const api = require( '../routes/api/manifest' ).v1 + +const app = express() + +app.set( 'env', process.env.PORT || '3000' ) +if( process.env.NODE_ENV !== 'test' ) app.use( logger( 'dev' )) +// app.use( cookieSession({ +// name: 'session', +// keys: [[ process.env.SESSION_KEY ]] +// })) +// app.use(express.static(buildpath+'/public')) +app.use(bodyParser.json()) + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))) +app.use( logger( 'dev' )) +app.use( bodyParser.json()) +app.use( bodyParser.urlencoded({ extended: false })) +app.use( cookieParser()) + +app.use( express.static( path.join( __dirname, '../front_end/public' ))) + +app.use( express.static( path.join( __dirname, 'public' ))) + +app.use( '/api/v1/dashboards', api.dashboards ) +app.use( '/api/v1/users', api.users ) + +// catch 404 and forward to error handler +app.use( function( req, res, next ) { + var err = new Error( 'Not Found' ) + err.status = 404 + next( err ) +}) + +// error handlers + +// development error handler +// will print stacktrace +if ( app.get( 'env' ) === 'development' ) { + app.use( function( err, req, res, next ) { + res.status( err.status || 500 ) + res.send({ + message: err.message, + error: err + }) + }) +} + +// production error handler +// no stacktraces leaked to user +app.use( function( err, req, res, next ) { + res.status( err.status || 500 ) + res.send({ + message: err.message, + error: {} + }) +}) + +module.exports = app From b8014823b3da444a6cf41ac3400546ca05f05adf Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Wed, 16 Nov 2016 11:46:18 -0800 Subject: [PATCH 06/11] WIP, partially defined potential widget schema ideas --- models/widgets.js | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/models/widgets.js b/models/widgets.js index 0953b97..80b77c0 100644 --- a/models/widgets.js +++ b/models/widgets.js @@ -11,3 +11,72 @@ const WidgetSchema = new Schema ({ const Widget = mongoose.model( 'Widget', WidgetSchema ) module.exports = { WidgetSchema, Widget } + +const dashboard = { + /* ... */ + widgets: [ + { type: 'Clock', title: 'Clock', size: '1x1', fields: { + format: { value: '24 hour' }, + location: { value: 'United Kingdom', fields: { + timezone: { value: 'London' } + }} + }, + { type: 'Facebook', title: 'Likes Today', size: '2x3', oauthToken: 'uh2498tyhjghfdjkb' } + ] +} + +const clockWidgetSchema = { + type: 'Clock', + title: { + type: 'text', + value: 'Clock' + }, + size: { + type: 'dropdown', + value: '1x1', + options: [ '1x1', '2x1', '2x2' ] + }, + fields: { + format: { + type: 'radio', + value: '24 hour', + options: [ '24 hour', '12 hour' ] + }, + location: { + type: 'dropdown', + value: 'United Kingdom', + options: [ '...' ] + fields: { + timezone: { + type: 'dropdown', + value: 'London', + options: [ '...' ] + } + } + } + } +} + +const textWidgetSchema = { + type: 'Text', + title: { + type: 'text', + value: 'Text' + }, + size: { + type: 'dropdown', + value: '1x1', + options: [ '1x1', '2x1', '2x2' ] + }, + fields: { + + } +} + + +//first, define all individual widget types and what data they have. Start with simple and well known ones. +//then, put those individual widgets into the widget collection. +//at some point, write logic that allows a user to insert a specific widget type into their dashboard +//we probably do not need the WidgetSchema any more, since we are not defining what a widget looks like, so we can have flexibility +//how do we sync our widgets that we write in atom and send them to the database? +//should we define each individual widget in a new file? From dd8ede0b270262892eb327e5f081deb0fa8fb8dd Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Wed, 16 Nov 2016 17:18:45 -0800 Subject: [PATCH 07/11] WIP generalizing addWidget function --- models/widgets.js | 71 ------------------------------------- routes/api/v1/dashboards.js | 2 +- 2 files changed, 1 insertion(+), 72 deletions(-) diff --git a/models/widgets.js b/models/widgets.js index 80b77c0..e9e5b9d 100644 --- a/models/widgets.js +++ b/models/widgets.js @@ -8,75 +8,4 @@ const WidgetSchema = new Schema ({ contents: String }) -const Widget = mongoose.model( 'Widget', WidgetSchema ) - module.exports = { WidgetSchema, Widget } - -const dashboard = { - /* ... */ - widgets: [ - { type: 'Clock', title: 'Clock', size: '1x1', fields: { - format: { value: '24 hour' }, - location: { value: 'United Kingdom', fields: { - timezone: { value: 'London' } - }} - }, - { type: 'Facebook', title: 'Likes Today', size: '2x3', oauthToken: 'uh2498tyhjghfdjkb' } - ] -} - -const clockWidgetSchema = { - type: 'Clock', - title: { - type: 'text', - value: 'Clock' - }, - size: { - type: 'dropdown', - value: '1x1', - options: [ '1x1', '2x1', '2x2' ] - }, - fields: { - format: { - type: 'radio', - value: '24 hour', - options: [ '24 hour', '12 hour' ] - }, - location: { - type: 'dropdown', - value: 'United Kingdom', - options: [ '...' ] - fields: { - timezone: { - type: 'dropdown', - value: 'London', - options: [ '...' ] - } - } - } - } -} - -const textWidgetSchema = { - type: 'Text', - title: { - type: 'text', - value: 'Text' - }, - size: { - type: 'dropdown', - value: '1x1', - options: [ '1x1', '2x1', '2x2' ] - }, - fields: { - - } -} - - -//first, define all individual widget types and what data they have. Start with simple and well known ones. -//then, put those individual widgets into the widget collection. -//at some point, write logic that allows a user to insert a specific widget type into their dashboard -//we probably do not need the WidgetSchema any more, since we are not defining what a widget looks like, so we can have flexibility -//how do we sync our widgets that we write in atom and send them to the database? -//should we define each individual widget in a new file? diff --git a/routes/api/v1/dashboards.js b/routes/api/v1/dashboards.js index 54765fb..86d2249 100644 --- a/routes/api/v1/dashboards.js +++ b/routes/api/v1/dashboards.js @@ -36,7 +36,7 @@ router.delete( '/:id',( request, response ) => { .catch( errorResponse( response )) }) -router.post( '/:id/widgets', ( request, response ) => { +router.post( '/:id/widgets/', ( request, response ) => { Dashboard.findById( request.params.id ).exec() .then( addWidget( request.body )) .then( dashboard => response.status( 201 ).json( dashboard )) From 95a6d13fea4aeadb5da5928bd6ca4a876125c564 Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Wed, 16 Nov 2016 17:26:25 -0800 Subject: [PATCH 08/11] WIP can send in widget type to addWidget function --- routes/api/v1/dashboards.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/api/v1/dashboards.js b/routes/api/v1/dashboards.js index 86d2249..54765fb 100644 --- a/routes/api/v1/dashboards.js +++ b/routes/api/v1/dashboards.js @@ -36,7 +36,7 @@ router.delete( '/:id',( request, response ) => { .catch( errorResponse( response )) }) -router.post( '/:id/widgets/', ( request, response ) => { +router.post( '/:id/widgets', ( request, response ) => { Dashboard.findById( request.params.id ).exec() .then( addWidget( request.body )) .then( dashboard => response.status( 201 ).json( dashboard )) From aa85c48d5f9d960f6e04c593a9f0313363580a6c Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Thu, 17 Nov 2016 09:27:22 -0800 Subject: [PATCH 09/11] WIP POST route working for widgets --- models/widgets.js | 2 +- routes/api/v1/dashboard/addWidget.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/models/widgets.js b/models/widgets.js index e9e5b9d..25093a1 100644 --- a/models/widgets.js +++ b/models/widgets.js @@ -8,4 +8,4 @@ const WidgetSchema = new Schema ({ contents: String }) -module.exports = { WidgetSchema, Widget } +module.exports = { WidgetSchema } diff --git a/routes/api/v1/dashboard/addWidget.js b/routes/api/v1/dashboard/addWidget.js index bfa3790..dfef539 100644 --- a/routes/api/v1/dashboard/addWidget.js +++ b/routes/api/v1/dashboard/addWidget.js @@ -4,5 +4,4 @@ const addWidget = widgetData => dashboard => { dashboard.widgets.push( new Widget( widgetData )) return dashboard.save() } - module.exports = addWidget From ba29ce8f5211fff015dd338c4d59f0eea95abf75 Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Thu, 17 Nov 2016 11:18:18 -0800 Subject: [PATCH 10/11] jrob gave us examples --- models/widgets.js | 4 +++- routes/api/v1/dashboards.js | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/models/widgets.js b/models/widgets.js index 25093a1..0953b97 100644 --- a/models/widgets.js +++ b/models/widgets.js @@ -8,4 +8,6 @@ const WidgetSchema = new Schema ({ contents: String }) -module.exports = { WidgetSchema } +const Widget = mongoose.model( 'Widget', WidgetSchema ) + +module.exports = { WidgetSchema, Widget } diff --git a/routes/api/v1/dashboards.js b/routes/api/v1/dashboards.js index 54765fb..c4294d9 100644 --- a/routes/api/v1/dashboards.js +++ b/routes/api/v1/dashboards.js @@ -43,4 +43,16 @@ router.post( '/:id/widgets', ( request, response ) => { .catch( errorResponse( response )) }) +router.put( '/:id/widgets/:widgetId', ( request, response ) => { + Widget.findByIdAndUpdate( request.params.widgetId, request.body ).exec() + .then( widget => response.json( widget )) + .catch( errorResponse( response )) +}) + +router.delete( '/:id/widgets/:widgetId', ( request, response ) => { + Widget.findByIdAndRemove( request.params.widgetId ).exec() + .then( widget => response.json( widget )) + .catch( errorResponse( response )) +}) + module.exports = router From 3b135e32da5f0a62b3e5ef2a849d22d9e356fa69 Mon Sep 17 00:00:00 2001 From: Monica Williams Date: Fri, 18 Nov 2016 09:21:08 -0800 Subject: [PATCH 11/11] WIP --- models/widgets.js | 69 +++++++++++++++++++++++++++---- routes/api/v1/widgetDescriptor.js | 3 ++ 2 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 routes/api/v1/widgetDescriptor.js diff --git a/models/widgets.js b/models/widgets.js index 0953b97..dfa38b6 100644 --- a/models/widgets.js +++ b/models/widgets.js @@ -1,13 +1,68 @@ const mongoose = require('mongoose') const { Schema } = mongoose -const WidgetSchema = new Schema ({ - type: String, - title: String, - size: { type: Number, required: true }, - contents: String +const WidgetDescriptorSchema = new Schema({ + category: { type: String, required: true }, + source: { type: String, required: true }, + type: { type: String, required: true }, // GithubPullRequest + title: { type: String, required: true }, + size: { type: String, required: true, default: '1x1' }, + fields: [ ] }) -const Widget = mongoose.model( 'Widget', WidgetSchema ) +const WidgetDescriptor = mongoose.model( + 'WidgetDescriptor', WidgetDescriptorSchema +) -module.exports = { WidgetSchema, Widget } + + + +// { +// type: 'GithubPullRequest', +// title: 'Github Pull Requests', +// fields: [ { title: 'Github ID', key: 'githubId', type: 'Text' } ] +// } + +// const newWidget = new WidgetDescriptor({ request.body }) + + +WidgetDescriptor.create({ + category: 'Dashboard Tools', + source: 'Geckoboard', + type: 'Clock', + title: 'Clock', + size: '1x1', + fields: [ + Field.create({ title: 'Format', key: 'format', type: 'Dropdown', defaultValue: '12 hour', options: [ '12 hour', '24 hour' ] }), + Field.create({ + title: 'Location', + key: 'location', + type: 'Dropdown', + options: [ 'All', 'the', 'countries' ], + fields: [ + Field.create({ title: 'Timezone', key: 'timezone', type: 'Dropdown', options: [ 'all', 'timezones' ]}) + ] + }) + ] +}) + +WidgetDescriptor.create({ + type: 'QR', + title: 'QR Code', + fields: [ Field.create({ title: 'url', key: 'url', type: 'Text' }) ] +}) + +WidgetDescriptor.create({ + type: 'Text', + title: 'Text', + fields: [ + Field.create({ title: 'Message one', key: 'messageOne', type: 'Text'}) + Field.create({ title: 'Message one type', key: 'messageOneType', type: 'Dropdown', defaultValue: 'Text', options: [ 'Text', 'Alert', 'Info' ]}) + Field.create({ title: 'Message two', key: 'messageTwo', type: 'Text'}) + Field.create({ title: 'Message two type', key: 'messageTwoType', type: 'Dropdown', defaultValue: 'Text', options: [ 'Text', 'Alert', 'Info' ]}) + Field.create({ title: 'Message three', key: 'messageThree', type: 'Text'}) + Field.create({ title: 'Message three type', key: 'messageThreeType', type: 'Dropdown', defaultValue: 'Text', options: [ 'Text', 'Alert', 'Info' ]}) + Field.create({ title: 'Message four', key: 'messageFour', type: 'Text'}) + Field.create({ title: 'Message four type', key: 'messageFourType', type: 'Dropdown', defaultValue: 'Text', options: [ 'Text', 'Alert', 'Info' ]}) + ] +}) diff --git a/routes/api/v1/widgetDescriptor.js b/routes/api/v1/widgetDescriptor.js new file mode 100644 index 0000000..feb4808 --- /dev/null +++ b/routes/api/v1/widgetDescriptor.js @@ -0,0 +1,3 @@ +// GET / all widgets, group by different categories +// GET /:type +// document API Trossello