Skip to content
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lizardboard
# 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.

Expand All @@ -14,6 +14,18 @@ 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] 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)

## Technical Stack

### Back End
Expand All @@ -24,11 +36,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
TBD
69 changes: 62 additions & 7 deletions models/widgets.js
Original file line number Diff line number Diff line change
@@ -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' ]})
]
})
1 change: 0 additions & 1 deletion routes/api/v1/dashboard/addWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ const addWidget = widgetData => dashboard => {
dashboard.widgets.push( new Widget( widgetData ))
return dashboard.save()
}

module.exports = addWidget
12 changes: 12 additions & 0 deletions routes/api/v1/dashboards.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
13 changes: 13 additions & 0 deletions routes/api/v1/errorResponse.js
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions routes/api/v1/widgetDescriptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// GET / all widgets, group by different categories
// GET /:type
// document API Trossello
66 changes: 66 additions & 0 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -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