├── .gitignore ├── users ├── .gitignore ├── src │ ├── post.js │ ├── comment.js │ ├── blogPost.js │ └── user.js ├── package.json └── test │ ├── create_test.js │ ├── virtual_type_test.js │ ├── test_helper.js │ ├── middleware_test.js │ ├── validation_test.js │ ├── reading_test.js │ ├── delete_test.js │ ├── subdocument_test.js │ ├── update_test.js │ └── association_test.js ├── UpStarMusic ├── .gitignore ├── src │ ├── components │ │ ├── filters │ │ │ ├── index.js │ │ │ ├── Picker.js │ │ │ ├── Switch.js │ │ │ └── Range.js │ │ ├── Home.js │ │ ├── artists │ │ │ ├── ArtistMain.js │ │ │ ├── ArtistCreate.js │ │ │ ├── Paginator.js │ │ │ ├── ArtistEdit.js │ │ │ ├── ArtistIndex.js │ │ │ ├── ArtistDetail.js │ │ │ └── ArtistFilter.js │ │ └── Header.js │ ├── reducers │ │ ├── ErrorReducer.js │ │ ├── SelectionReducer.js │ │ ├── FilterCriteriaReducer.js │ │ ├── index.js │ │ └── ArtistsReducer.js │ ├── actions │ │ ├── types.js │ │ └── index.js │ ├── constants.js │ ├── router.js │ ├── main.js │ └── seeds.js ├── .eslintrc ├── index.js ├── database │ ├── models │ │ ├── album.js │ │ └── artist.js │ └── queries │ │ ├── DeleteArtist.js │ │ ├── FindArtist.js │ │ ├── SetRetired.js │ │ ├── SetNotRetired.js │ │ ├── CreateArtist.js │ │ ├── EditArtist.js │ │ ├── GetAgeRange.js │ │ ├── GetYearsActiveRange.js │ │ └── SearchArtists.js ├── index.html ├── tasks │ └── validator.js ├── package.json ├── webpack.config.js ├── style │ └── style.css ├── npm-debug.log └── bundle.js ├── .DS_Store ├── muber ├── index.js ├── routes │ └── routes.js ├── test │ ├── app_test.js │ ├── test_helper.js │ └── controllers │ │ └── drivers_controller_test.js ├── package.json ├── app.js ├── models │ └── Driver.js └── controllers │ └── drivers_controller.js ├── README.md └── promises └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /users/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | -------------------------------------------------------------------------------- /UpStarMusic/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/MongoCasts/master/.DS_Store -------------------------------------------------------------------------------- /UpStarMusic/src/components/filters/index.js: -------------------------------------------------------------------------------- 1 | export * from './Picker'; 2 | export * from './Range'; 3 | export * from './Switch'; 4 | -------------------------------------------------------------------------------- /muber/index.js: -------------------------------------------------------------------------------- 1 | const app = require('./app'); 2 | 3 | app.listen(3050, () => { 4 | console.log('Running on port 3050'); 5 | }); 6 | -------------------------------------------------------------------------------- /UpStarMusic/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "rallycoding", 3 | "rules": { 4 | "arrow-body-style": 0, 5 | "no-underscore-dangle": 0, 6 | "radix": 0 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /users/src/post.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const PostSchema = new Schema({ 5 | title: String 6 | }); 7 | 8 | module.exports = PostSchema; 9 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/filters/Picker.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Picker = () => { 4 | return ( 5 |
6 | Picker 7 |
8 | ); 9 | }; 10 | 11 | export { Picker }; 12 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/filters/Switch.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Switch = () => { 4 | return ( 5 |
6 | Switch 7 |
8 | ); 9 | }; 10 | 11 | export { Switch }; 12 | -------------------------------------------------------------------------------- /UpStarMusic/index.js: -------------------------------------------------------------------------------- 1 | const {app, BrowserWindow} = require('electron'); 2 | let win 3 | 4 | app.on('ready', function() { 5 | win = new BrowserWindow({width: 800, height: 600}); 6 | 7 | win.loadURL(`file://${__dirname}/index.html`); 8 | }); 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MongoCasts 2 | 3 | Each example from the course can be found within this repo. You can either look at the files in a completed state, or check out the changes that were made in a particular section by clicking on one of the links below. 4 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/Home.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from './Header'; 3 | 4 | const Home = ({ children }) => { 5 | return ( 6 |
7 |
8 | {children} 9 |
10 | ); 11 | }; 12 | 13 | export default Home; 14 | -------------------------------------------------------------------------------- /users/src/comment.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const CommentSchema = new Schema({ 5 | content: String, 6 | user: { type: Schema.Types.ObjectId, ref: 'user' } 7 | }); 8 | 9 | const Comment = mongoose.model('comment', CommentSchema); 10 | 11 | module.exports = Comment; 12 | -------------------------------------------------------------------------------- /UpStarMusic/database/models/album.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const AlbumSchema = new Schema({ 5 | title: String, 6 | date: Date, 7 | copiesSolid: Number, 8 | numberTracks: Number, 9 | image: String, 10 | revenue: Number 11 | }); 12 | 13 | module.exports = AlbumSchema; 14 | -------------------------------------------------------------------------------- /muber/routes/routes.js: -------------------------------------------------------------------------------- 1 | const DriversController = require('../controllers/drivers_controller'); 2 | 3 | module.exports = (app) => { 4 | app.post('/api/drivers', DriversController.create); 5 | app.put('/api/drivers/:id', DriversController.edit); 6 | app.delete('/api/drivers/:id', DriversController.delete); 7 | app.get('/api/drivers', DriversController.index); 8 | }; 9 | -------------------------------------------------------------------------------- /users/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "users", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "nodemon --exec 'mocha -R min'" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "mocha": "^3.1.2", 13 | "mongoose": "^4.6.6", 14 | "nodemon": "^1.11.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/DeleteArtist.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Deletes a single artist from the Artists collection 5 | * @param {string} _id - The ID of the artist to delete. 6 | * @return {promise} A promise that resolves when the record is deleted 7 | */ 8 | module.exports = (_id) => { 9 | return Artist.remove({ _id }); 10 | }; 11 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/FindArtist.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Finds a single artist in the artist collection. 5 | * @param {string} _id - The ID of the record to find. 6 | * @return {promise} A promise that resolves with the Artist that matches the id 7 | */ 8 | module.exports = (_id) => { 9 | return Artist.findById(_id); 10 | }; 11 | -------------------------------------------------------------------------------- /UpStarMusic/src/reducers/ErrorReducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | CREATE_ERROR, 3 | CLEAR_ERROR 4 | } from '../actions/types'; 5 | 6 | export default (state = '', action) => { 7 | switch (action.type) { 8 | case CREATE_ERROR: 9 | return 'There was an error inserting this record'; 10 | case CLEAR_ERROR: 11 | return ''; 12 | default: 13 | return state; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /users/src/blogPost.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const BlogPostSchema = new Schema({ 5 | title: String, 6 | content: String, 7 | comments: [{ 8 | type: Schema.Types.ObjectId, 9 | ref: 'comment' 10 | }] 11 | }); 12 | 13 | const BlogPost = mongoose.model('blogPost', BlogPostSchema); 14 | 15 | module.exports = BlogPost; 16 | -------------------------------------------------------------------------------- /users/test/create_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Creating records', () => { 5 | it('saves a user', (done) => { 6 | const joe = new User({ name: 'Joe' }); 7 | 8 | joe.save() 9 | .then(() => { 10 | // Has joe been saved successfully? 11 | assert(!joe.isNew); 12 | done(); 13 | }); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/SetRetired.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Sets a group of Artists as retired 5 | * @param {array} _ids - An array of the _id's of of artists to update 6 | * @return {promise} A promise that resolves after the update 7 | */ 8 | module.exports = (_ids) => { 9 | return Artist.update( 10 | { _id: { $in: _ids } }, 11 | { retired: true }, 12 | { multi: true } 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /muber/test/app_test.js: -------------------------------------------------------------------------------- 1 | // const assert = require('assert'); 2 | // const request = require('supertest'); 3 | // const app = require('../app'); 4 | // 5 | // describe('the express App', () => { 6 | // it('handles a request to root route', (done) => { 7 | // request(app) 8 | // .get('/') 9 | // .end((err, response) => { 10 | // assert(response.body.hi === 'there'); 11 | // done(); 12 | // }); 13 | // }); 14 | // }); 15 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/SetNotRetired.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Sets a group of Artists as not retired 5 | * @param {array} _ids - An array of the _id's of of artists to update 6 | * @return {promise} A promise that resolves after the update 7 | */ 8 | module.exports = (_ids) => { 9 | return Artist.update( 10 | { _id: { $in: _ids } }, 11 | { retired: false }, 12 | { multi: true } 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /muber/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "muber", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "NODE_ENV=test nodemon --exec 'mocha --recursive -R min'" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "body-parser": "^1.15.2", 13 | "express": "^4.14.0", 14 | "mocha": "^3.2.0", 15 | "mongoose": "^4.7.1", 16 | "supertest": "^2.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/CreateArtist.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Finds a single artist in the artist collection. 5 | * @param {object} artistProps - Object containing a name, age, yearsActive, and genre 6 | * @return {promise} A promise that resolves with the Artist that was created 7 | */ 8 | module.exports = (artistProps) => { 9 | const artist = new Artist(artistProps); 10 | 11 | return artist.save(); 12 | }; 13 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/EditArtist.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Edits a single artist in the Artists collection 5 | * @param {string} _id - The ID of the artist to edit. 6 | * @param {object} artistProps - An object with a name, age, yearsActive, and genre 7 | * @return {promise} A promise that resolves when the record is edited 8 | */ 9 | module.exports = (_id, artistProps) => { 10 | return Artist.update({ _id }, artistProps); 11 | }; 12 | -------------------------------------------------------------------------------- /users/test/virtual_type_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Virtual types', () => { 5 | it('postCount returns number of posts', (done) => { 6 | const joe = new User({ 7 | name: 'Joe', 8 | posts: [{ title: 'PostTitle' }] 9 | }); 10 | 11 | joe.save() 12 | .then(() => User.findOne({ name: 'Joe' })) 13 | .then((user) => { 14 | assert(joe.postCount === 1); 15 | done(); 16 | }); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /UpStarMusic/src/reducers/SelectionReducer.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import { 3 | SELECT_ARTIST, 4 | DESELECT_ARTIST, 5 | RESET_SELECTION 6 | } from '../actions/types'; 7 | 8 | export default (state = [], action) => { 9 | switch (action.type) { 10 | case SELECT_ARTIST: 11 | return [...state, action.payload]; 12 | case DESELECT_ARTIST: 13 | return _.without(state, action.payload); 14 | case RESET_SELECTION: 15 | return []; 16 | default: 17 | return state; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /UpStarMusic/src/reducers/FilterCriteriaReducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | SET_AGE_RANGE, 3 | SET_YEARS_ACTIVE_RANGE 4 | } from '../actions/types'; 5 | 6 | const INITIAL_STATE = { 7 | age: { min: 0, max: 100 } 8 | }; 9 | 10 | export default (state = INITIAL_STATE, action) => { 11 | switch (action.type) { 12 | case SET_AGE_RANGE: 13 | return { ...state, age: action.payload }; 14 | case SET_YEARS_ACTIVE_RANGE: 15 | return { ...state, yearsActive: action.payload }; 16 | default: 17 | return state; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /UpStarMusic/database/models/artist.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const AlbumSchema = require('./album'); 3 | const Schema = mongoose.Schema; 4 | 5 | const ArtistSchema = new Schema({ 6 | name: String, 7 | age: Number, 8 | yearsActive: Number, 9 | image: String, 10 | genre: String, 11 | website: String, 12 | netWorth: Number, 13 | labelName: String, 14 | retired: Boolean, 15 | albums: [AlbumSchema] 16 | }); 17 | 18 | const Artist = mongoose.model('artist', ArtistSchema); 19 | 20 | module.exports = Artist; 21 | -------------------------------------------------------------------------------- /UpStarMusic/src/actions/types.js: -------------------------------------------------------------------------------- 1 | export const SET_AGE_RANGE = 'set_age_range'; 2 | export const SET_YEARS_ACTIVE_RANGE = 'SET_YEARS_ACTIVE_RANGE'; 3 | export const SEARCH_ARTISTS = 'SEARCH_ARTISTS'; 4 | export const FIND_ARTIST = 'FIND_ARTIST'; 5 | export const RESET_ARTIST = 'RESET_ARTIST'; 6 | export const CREATE_ERROR = 'CREATE_ERROR'; 7 | export const CLEAR_ERROR = 'CLEAR_ERROR'; 8 | export const SELECT_ARTIST = 'SELECT_ARTIST'; 9 | export const DESELECT_ARTIST = 'DESELECT_ARTIST'; 10 | export const RESET_SELECTION = 'RESET_SELECTION'; 11 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistMain.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ArtistFilter from './ArtistFilter'; 3 | import ArtistIndex from './ArtistIndex'; 4 | 5 | class ArtistMain extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 | ); 17 | } 18 | } 19 | 20 | export default ArtistMain; 21 | -------------------------------------------------------------------------------- /muber/app.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const mongoose = require('mongoose'); 3 | const bodyParser = require('body-parser'); 4 | const routes = require('./routes/routes'); 5 | 6 | const app = express(); 7 | 8 | mongoose.Promise = global.Promise; 9 | if (process.env.NODE_ENV !== 'test') { 10 | mongoose.connect('mongodb://localhost/muber'); 11 | } 12 | 13 | app.use(bodyParser.json()); 14 | routes(app); 15 | 16 | app.use((err, req, res, next) => { 17 | res.status(422).send({ error: err.message }); 18 | }); 19 | 20 | module.exports = app; 21 | -------------------------------------------------------------------------------- /UpStarMusic/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { reducer as formReducer } from 'redux-form'; 3 | import filterCriteriaReducer from './FilterCriteriaReducer'; 4 | import ArtistsReducer from './ArtistsReducer'; 5 | import ErrorReducer from './ErrorReducer'; 6 | import SelectionReducer from './SelectionReducer'; 7 | 8 | export default combineReducers({ 9 | form: formReducer, 10 | filterCriteria: filterCriteriaReducer, 11 | artists: ArtistsReducer, 12 | errors: ErrorReducer, 13 | selection: SelectionReducer 14 | }); 15 | -------------------------------------------------------------------------------- /muber/test/test_helper.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | before(done => { 4 | mongoose.connect('mongodb://localhost/muber_test'); 5 | mongoose.connection 6 | .once('open', () => done()) 7 | .on('error', error => { 8 | console.warn('Warning', error); 9 | }); 10 | }); 11 | 12 | beforeEach(done => { 13 | const { drivers } = mongoose.connection.collections; 14 | drivers.drop() 15 | .then(() => drivers.ensureIndex({ 'geometry.coordinates': '2dsphere' })) 16 | .then(() => done()) 17 | .catch(() => done()); 18 | }); 19 | -------------------------------------------------------------------------------- /UpStarMusic/src/constants.js: -------------------------------------------------------------------------------- 1 | export const GENRES = [ 2 | 'Acceptable Country', 3 | 'Acceptable Emo', 4 | 'Acceptable Pop', 5 | 'Acceptable Pop-Punk', 6 | 'Alt-Country', 7 | 'Alt-Rap', 8 | 'Bloghaus', 9 | 'Blog Rap', 10 | 'Blog Rock', 11 | 'Cold Wave', 12 | 'Cool Jazz', 13 | 'Digital Punk', 14 | 'Doom Metal', 15 | 'Freak Folk', 16 | 'Garage Rock', 17 | 'Hypnagogic Pop', 18 | 'Noise Pop', 19 | 'Power Electronics', 20 | 'Serialism', 21 | 'Witch House', 22 | 'Ye Olde Timey Rock And Roll Music of Indeterminate Hipster Variety' 23 | ]; 24 | -------------------------------------------------------------------------------- /muber/models/Driver.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const PointSchema = new Schema({ 5 | coordinates: { type: [Number], index: '2dsphere' }, 6 | type: { type: String, default: 'Point' } 7 | }); 8 | 9 | const DriverSchema = new Schema({ 10 | email: { 11 | type: String, 12 | required: true 13 | }, 14 | driving: { 15 | type: Boolean, 16 | default: false 17 | }, 18 | geometry: PointSchema 19 | }); 20 | 21 | const Driver = mongoose.model('driver', DriverSchema); 22 | 23 | module.exports = Driver; 24 | -------------------------------------------------------------------------------- /UpStarMusic/src/reducers/ArtistsReducer.js: -------------------------------------------------------------------------------- 1 | import { 2 | SEARCH_ARTISTS, 3 | FIND_ARTIST, 4 | RESET_ARTIST 5 | } from '../actions/types'; 6 | 7 | const INITIAL_STATE = { 8 | all: [], 9 | offset: 0, 10 | limit: 20 11 | }; 12 | 13 | export default (state = INITIAL_STATE, action) => { 14 | switch (action.type) { 15 | case SEARCH_ARTISTS: 16 | return action.payload; 17 | case FIND_ARTIST: 18 | return { ...state, artist: action.payload }; 19 | case RESET_ARTIST: 20 | return { ...state, artist: null }; 21 | default: 22 | return state; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /users/test/test_helper.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | mongoose.Promise = global.Promise; 4 | 5 | before((done) => { 6 | mongoose.connect('mongodb://localhost/users_test'); 7 | mongoose.connection 8 | .once('open', () => { done(); }) 9 | .on('error', (error) => { 10 | console.warn('Warning', error); 11 | }); 12 | }); 13 | 14 | beforeEach((done) => { 15 | const { users, comments, blogposts } = mongoose.connection.collections; 16 | users.drop(() => { 17 | comments.drop(() => { 18 | blogposts.drop(() => { 19 | done(); 20 | }); 21 | }); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /UpStarMusic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Upstar Music 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /promises/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 29 | 30 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/GetAgeRange.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Finds the lowest and highest age of artists in the Artist collection 5 | * @return {promise} A promise that resolves with an object 6 | * containing the min and max ages, like { min: 16, max: 45 }. 7 | */ 8 | module.exports = () => { 9 | const minQuery = Artist 10 | .find({}) 11 | .sort({ age: 1 }) 12 | .limit(1) 13 | .then(artists => artists[0].age); 14 | 15 | const maxQuery = Artist 16 | .find({}) 17 | .sort({ age: -1 }) 18 | .limit(1) 19 | .then(artists => artists[0].age); 20 | 21 | return Promise.all([minQuery, maxQuery]) 22 | .then((result) => { 23 | return { min: result[0], max: result[1] }; 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /UpStarMusic/tasks/validator.js: -------------------------------------------------------------------------------- 1 | const Mongo = require('mongodb'); 2 | 3 | const { Db, Server } = Mongo; 4 | 5 | const db = new Db('artists', new Server('localhost', 27017)); 6 | db.open() 7 | .then(() => { 8 | db.command({ 9 | collMod: 'artists', 10 | validator: { 11 | $and: [ 12 | { age: { $gte: 15, $lte: 45, $type: 'number' } }, 13 | { yearsActive: { $gte: 0, $lte: 15, $type: 'number' } }, 14 | { name: { $type: 'string' } }, 15 | { genre: { $type: 'string' } } 16 | ] 17 | } 18 | }) 19 | .then(() => { 20 | console.log('Mod Success'); 21 | process.exit(0); 22 | }) 23 | .catch((e) => { 24 | console.log('Mod Failed', e); 25 | process.exit(1); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /users/test/middleware_test.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const assert = require('assert'); 3 | const User = require('../src/user'); 4 | const BlogPost = require('../src/blogPost'); 5 | 6 | describe('Middlware', () => { 7 | let joe, blogPost; 8 | 9 | beforeEach((done) => { 10 | joe = new User({ name: 'Joe' }); 11 | blogPost = new BlogPost({ title: 'JS is Great', content: 'Yep it really is' }); 12 | 13 | joe.blogPosts.push(blogPost); 14 | 15 | Promise.all([joe.save(), blogPost.save()]) 16 | .then(() => done()); 17 | }); 18 | 19 | it('users clean up dangling blogposts on remove', (done) => { 20 | joe.remove() 21 | .then(() => BlogPost.count()) 22 | .then((count) => { 23 | assert(count === 0); 24 | done(); 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/GetYearsActiveRange.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Finds the lowest and highest yearsActive of artists in the Artist collection 5 | * @return {promise} A promise that resolves with an object 6 | * containing the min and max yearsActive, like { min: 0, max: 14 }. 7 | */ 8 | module.exports = () => { 9 | const minQuery = Artist 10 | .find({}) 11 | .sort({ yearsActive: 1 }) 12 | .limit(1) 13 | .then(artists => artists[0].yearsActive); 14 | 15 | const maxQuery = Artist 16 | .find({}) 17 | .sort({ yearsActive: -1 }) 18 | .limit(1) 19 | .then(artists => artists[0].yearsActive); 20 | 21 | return Promise.all([minQuery, maxQuery]) 22 | .then((result) => { 23 | return { min: result[0], max: result[1] }; 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/filters/Range.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Slider from 'react-input-range'; 3 | 4 | class Range extends Component { 5 | onChange(component, values) { 6 | const { input: { onChange } } = this.props; 7 | 8 | onChange(values); 9 | } 10 | 11 | render() { 12 | const { input: { value } } = this.props; 13 | 14 | return ( 15 |
16 | 17 | 23 |
24 | ); 25 | } 26 | }; 27 | 28 | Range.defaultProps = { 29 | range: { min: 0, max: 100 } 30 | }; 31 | 32 | export { Range }; 33 | -------------------------------------------------------------------------------- /UpStarMusic/src/router.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Router, Route, IndexRoute, hashHistory } from 'react-router'; 3 | 4 | import Home from './components/Home'; 5 | import ArtistMain from './components/artists/ArtistMain'; 6 | import ArtistDetail from './components/artists/ArtistDetail'; 7 | import ArtistCreate from './components/artists/ArtistCreate'; 8 | import ArtistEdit from './components/artists/ArtistEdit'; 9 | 10 | const Routes = () => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | }; 22 | 23 | export default Routes; 24 | -------------------------------------------------------------------------------- /users/src/user.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const PostSchema = require('./post'); 3 | const Schema = mongoose.Schema; 4 | 5 | const UserSchema = new Schema({ 6 | name: { 7 | type: String, 8 | validate: { 9 | validator: (name) => name.length > 2, 10 | message: 'Name must be longer than 2 characters.' 11 | }, 12 | required: [true, 'Name is required.'] 13 | }, 14 | posts: [PostSchema], 15 | likes: Number, 16 | blogPosts: [{ 17 | type: Schema.Types.ObjectId, 18 | ref: 'blogPost' 19 | }] 20 | }); 21 | 22 | UserSchema.virtual('postCount').get(function() { 23 | return this.posts.length; 24 | }); 25 | 26 | UserSchema.pre('remove', function(next) { 27 | const BlogPost = mongoose.model('blogPost'); 28 | // this === joe 29 | 30 | BlogPost.remove({ _id: { $in: this.blogPosts } }) 31 | .then(() => next()); 32 | }); 33 | 34 | const User = mongoose.model('user', UserSchema); 35 | 36 | module.exports = User; 37 | -------------------------------------------------------------------------------- /users/test/validation_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Validating records', () => { 5 | it('requires a user name', () => { 6 | const user = new User({ name: undefined }); 7 | const validationResult = user.validateSync(); 8 | const { message } = validationResult.errors.name; 9 | 10 | assert(message === 'Name is required.'); 11 | }); 12 | 13 | it('requires a user\'s name longer than 2 characters', () => { 14 | const user = new User({ name: 'Al' }); 15 | const validationResult = user.validateSync(); 16 | const { message } = validationResult.errors.name; 17 | 18 | assert(message === 'Name must be longer than 2 characters.'); 19 | }); 20 | 21 | it('disallows invalid records from being saved', (done) => { 22 | const user = new User({ name: 'Al' }); 23 | user.save() 24 | .catch((validationResult) => { 25 | const { message } = validationResult.errors.name; 26 | 27 | assert(message === 'Name must be longer than 2 characters.'); 28 | done(); 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /UpStarMusic/src/main.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { createStore, applyMiddleware } from 'redux'; 4 | import { Provider } from 'react-redux'; 5 | import ReduxThunk from 'redux-thunk'; 6 | import { Db, Server } from 'mongodb'; 7 | import reducers from './reducers'; 8 | import Routes from './router'; 9 | import mongoose from 'mongoose'; 10 | import './seeds'; 11 | 12 | mongoose.Promise = Promise; 13 | 14 | const App = () => { 15 | const store = createStore(reducers, {}, applyMiddleware(ReduxThunk)); 16 | 17 | return ( 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | const db = new Db('upstar_music', new Server('localhost', 27017)); 25 | db.open() 26 | .then(() => { 27 | window.db = db; 28 | mongoose.connect('mongodb://localhost/upstar_music'); 29 | mongoose.connection 30 | .once('open', () => { 31 | ReactDOM.render(, document.getElementById('root')); 32 | }) 33 | .on('error', (error) => { 34 | console.warn('Warning', error); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /UpStarMusic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "upstar_music", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "electron . & webpack-dev-server" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "babel-core": "^6.17.0", 13 | "babel-loader": "^6.2.0", 14 | "babel-preset-es2015": "^6.1.18", 15 | "babel-preset-react": "^6.1.18", 16 | "babel-preset-stage-1": "^6.1.18", 17 | "electron": "^1.4.5", 18 | "eslint-config-rallycoding": "^3.1.0", 19 | "faker": "^3.1.0", 20 | "json-loader": "^0.5.4", 21 | "lodash": "^3.10.1", 22 | "markdown-loader": "^0.1.7", 23 | "mongodb": "^2.2.11", 24 | "mongoose": "^4.6.6", 25 | "node-sass": "^3.10.1", 26 | "react": "^0.14.3", 27 | "react-dom": "^0.14.3", 28 | "react-input-range": "^0.9.2", 29 | "react-redux": "^4.4.5", 30 | "react-router": "^3.0.0", 31 | "redux": "^3.6.0", 32 | "redux-form": "^6.1.1", 33 | "redux-thunk": "^2.1.0", 34 | "sass-loader": "^4.0.2", 35 | "webpack": "^1.12.9", 36 | "webpack-dev-server": "^1.14.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /muber/controllers/drivers_controller.js: -------------------------------------------------------------------------------- 1 | const Driver = require('../models/Driver'); 2 | 3 | module.exports = { 4 | index(req, res, next) { 5 | const { lng, lat } = req.query; 6 | 7 | Driver.geoNear( 8 | { type: 'Point', coordinates: [parseFloat(lng), parseFloat(lat)] }, 9 | { spherical: true, maxDistance: 200000 } 10 | ) 11 | .then(drivers => res.send(drivers)) 12 | .catch(next); 13 | }, 14 | 15 | create(req, res, next) { 16 | const driverProps = req.body; 17 | 18 | Driver.create(driverProps) 19 | .then(driver => res.send(driver)) 20 | .catch(next) 21 | }, 22 | 23 | edit(req, res, next) { 24 | const driverId = req.params.id; 25 | const driverProps = req.body; 26 | 27 | Driver.findByIdAndUpdate({ _id: driverId }, driverProps) 28 | .then(() => Driver.findById({ _id: id })) 29 | .then(driver => res.send(driver)) 30 | .catch(next); 31 | }, 32 | 33 | delete(req, res, next) { 34 | const driverId = req.params.id; 35 | 36 | Driver.findByIdAndRemove({ _id: driverId }) 37 | .then(driver => res.status(204).send(driver)) 38 | .catch(next); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /users/test/reading_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Reading users out of the database', () => { 5 | let joe, maria, alex, zach; 6 | 7 | beforeEach((done) => { 8 | alex = new User({ name: 'Alex' }); 9 | joe = new User({ name: 'Joe' }); 10 | maria = new User({ name: 'Maria' }); 11 | zach = new User({ name: 'Zach' }); 12 | 13 | Promise.all([joe.save(), alex.save(), maria.save(), zach.save()]) 14 | .then(() => done()); 15 | }); 16 | 17 | it('finds all users with a name of joe', (done) => { 18 | User.find({ name: 'Joe' }) 19 | .then((users) => { 20 | assert(users[0]._id.toString() === joe._id.toString()); 21 | done(); 22 | }); 23 | }); 24 | 25 | it('find a user with a particular id', (done) => { 26 | User.findOne({ _id: joe._id }) 27 | .then((user) => { 28 | assert(user.name === 'Joe'); 29 | done(); 30 | }); 31 | }); 32 | 33 | it('can skip and limit the result set', (done) => { 34 | User.find({}) 35 | .sort({ name: 1 }) 36 | .skip(1) 37 | .limit(2) 38 | .then((users) => { 39 | assert(users.length === 2); 40 | assert(users[0].name === 'Joe'); 41 | assert(users[1].name === 'Maria'); 42 | done(); 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /UpStarMusic/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | var fs = require('fs'); 4 | 5 | var nodeModules = {}; 6 | fs.readdirSync('node_modules') 7 | .filter(function(x) { 8 | return ['.bin'].indexOf(x) === -1; 9 | }) 10 | .forEach(function(mod) { 11 | nodeModules[mod] = 'commonjs ' + mod; 12 | }); 13 | 14 | module.exports = { 15 | externals: nodeModules, 16 | entry: [ 17 | './src/main.js' 18 | ], 19 | target: 'node', 20 | output: { 21 | path: __dirname, 22 | publicPath: '/', 23 | filename: 'bundle.js' 24 | }, 25 | sassLoader: { 26 | includePaths: [path.resolve(__dirname, './sass')] 27 | }, 28 | module: { 29 | loaders: [ 30 | { 31 | exclude: /node_modules/, 32 | loader: 'babel', 33 | query: { 34 | presets: ['react', 'es2015', 'stage-1'] 35 | } 36 | }, 37 | { 38 | test: /\.sass$/, 39 | loaders: ['style', 'css', 'sass'] 40 | }, 41 | { 42 | test: /\.json$/, 43 | loader: 'json' 44 | }, 45 | { 46 | test: /\.md$/, 47 | loader: 'html!markdown' 48 | } 49 | ] 50 | }, 51 | resolve: { 52 | extensions: ['', '.js', '.jsx'] 53 | }, 54 | devServer: { 55 | historyApiFallback: true, 56 | contentBase: './', 57 | port: 4172 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /users/test/delete_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Deleting a user', () => { 5 | let joe; 6 | 7 | beforeEach((done) => { 8 | joe = new User({ name: 'Joe' }); 9 | joe.save() 10 | .then(() => done()); 11 | }); 12 | 13 | it('model instance remove', (done) => { 14 | joe.remove() 15 | .then(() => User.findOne({ name: 'Joe' })) 16 | .then((user) => { 17 | assert(user === null); 18 | done(); 19 | }); 20 | }); 21 | 22 | it('class method remove', (done) => { 23 | // Remove a bunch of records with some given criteria 24 | User.remove({ name: 'Joe' }) 25 | .then(() => User.findOne({ name: 'Joe' })) 26 | .then((user) => { 27 | assert(user === null); 28 | done(); 29 | }); 30 | }); 31 | 32 | it('class method findOneAndRemove', (done) => { 33 | User.findOneAndRemove({ name: 'Joe' }) 34 | .then(() => User.findOne({ name: 'Joe' })) 35 | .then((user) => { 36 | assert(user === null); 37 | done(); 38 | }); 39 | }); 40 | 41 | it('class method findByIdAndRemove', (done) => { 42 | User.findByIdAndRemove(joe._id) 43 | .then(() => User.findOne({ name: 'Joe' })) 44 | .then((user) => { 45 | assert(user === null); 46 | done(); 47 | }); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /UpStarMusic/style/style.css: -------------------------------------------------------------------------------- 1 | .input-field label { 2 | left: 0; 3 | } 4 | 5 | .range-slider { 6 | margin: 65px 0 30px; 7 | } 8 | 9 | .range-slider label { 10 | top: -37px; 11 | } 12 | 13 | label { 14 | color: white !important; 15 | } 16 | 17 | .pagination li > a { 18 | cursor: pointer; 19 | } 20 | 21 | .pagination { 22 | margin-bottom: 5px; 23 | } 24 | 25 | a.secondary-content { 26 | position: relative !important; 27 | flex: 1; 28 | text-align: right; 29 | top: 0px !important; 30 | right: 0px !important; 31 | } 32 | 33 | .secondary-content .material-icons { 34 | font-size: 36px; 35 | } 36 | 37 | .artist-detail .header { 38 | display: flex; 39 | justify-content: space-between; 40 | } 41 | 42 | .flex { 43 | display: flex; 44 | justify-content: space-around; 45 | } 46 | 47 | .wrap { 48 | flex-wrap: wrap; 49 | } 50 | 51 | .album img { 52 | width: 250px !important; 53 | } 54 | 55 | .has-error { 56 | color: red; 57 | } 58 | 59 | .spacer a { 60 | margin: 0px 10px; 61 | cursor: pointer; 62 | } 63 | 64 | li.collection-item.avatar { 65 | display: flex; 66 | align-items: center; 67 | padding-left: 10px !important; 68 | } 69 | 70 | li.collection-item.avatar img { 71 | position: relative !important; 72 | left: 0px !important; 73 | margin: 0px 10px !important; 74 | } 75 | 76 | .retired { 77 | background-color: #ddd !important; 78 | } 79 | 80 | .select { 81 | font-size: 1rem; 82 | } 83 | 84 | select { 85 | display: block !important; 86 | margin-bottom: 10px; 87 | height: 30px; 88 | color: black; 89 | } 90 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistCreate.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { reduxForm, Field } from 'redux-form'; 4 | import * as actions from '../../actions'; 5 | 6 | class ArtistCreate extends Component { 7 | componentWillUnmount() { 8 | this.props.clearError(); 9 | } 10 | 11 | onSubmit(formProps) { 12 | this.props.createArtist(formProps); 13 | } 14 | 15 | render() { 16 | const { handleSubmit } = this.props; 17 | 18 | return ( 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | {this.props.errorMessage} 34 |
35 | 36 |
37 | ); 38 | } 39 | } 40 | 41 | const mapStateToProps = (state) => { 42 | return { 43 | errorMessage: state.errors 44 | }; 45 | }; 46 | 47 | export default connect(mapStateToProps, actions)(reduxForm({ 48 | form: 'create' 49 | })(ArtistCreate)); 50 | -------------------------------------------------------------------------------- /UpStarMusic/database/queries/SearchArtists.js: -------------------------------------------------------------------------------- 1 | const Artist = require('../models/artist'); 2 | 3 | /** 4 | * Searches through the Artist collection 5 | * @param {object} criteria An object with a name, age, and yearsActive 6 | * @param {string} sortProperty The property to sort the results by 7 | * @param {integer} offset How many records to skip in the result set 8 | * @param {integer} limit How many records to return in the result set 9 | * @return {promise} A promise that resolves with the artists, count, offset, and limit 10 | * like this: { all: [artists], count: count, offset: offset, limit: limit } 11 | */ 12 | module.exports = (criteria, sortProperty, offset = 0, limit = 20) => { 13 | const query = Artist.find(buildQuery(criteria)) 14 | .sort({ [sortProperty]: 1 }) 15 | .skip(offset) 16 | .limit(limit); 17 | 18 | return Promise.all([query, Artist.find(buildQuery(criteria)).count()]) 19 | .then((results) => { 20 | return { 21 | all: results[0], 22 | count: results[1], 23 | offset: offset, 24 | limit: limit 25 | }; 26 | }); 27 | }; 28 | 29 | const buildQuery = (criteria) => { 30 | const query = {}; 31 | 32 | if (criteria.name) { 33 | query.$text = { $search: criteria.name }; 34 | } 35 | 36 | if (criteria.age) { 37 | query.age = { 38 | $gte: criteria.age.min, 39 | $lte: criteria.age.max 40 | }; 41 | } 42 | 43 | if (criteria.yearsActive) { 44 | query.yearsActive = { 45 | $gte: criteria.yearsActive.min, 46 | $lte: criteria.yearsActive.max 47 | }; 48 | } 49 | 50 | return query; 51 | }; 52 | -------------------------------------------------------------------------------- /users/test/subdocument_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Subdocuments', () => { 5 | it('can create a subdocument', (done) => { 6 | const joe = new User({ 7 | name: 'Joe', 8 | posts: [{ title: 'PostTitle' }] 9 | }); 10 | 11 | joe.save() 12 | .then(() => User.findOne({ name: 'Joe' })) 13 | .then((user) => { 14 | assert(user.posts[0].title === 'PostTitle'); 15 | done(); 16 | }); 17 | }); 18 | 19 | it('Can add subdocuments to an existing record', (done) => { 20 | const joe = new User({ 21 | name: 'Joe', 22 | posts: [] 23 | }); 24 | 25 | joe.save() 26 | .then(() => User.findOne({ name: 'Joe' })) 27 | .then((user) => { 28 | user.posts.push({ title: 'New Post' }); 29 | return user.save(); 30 | }) 31 | .then(() => User.findOne({ name: 'Joe' })) 32 | .then((user) => { 33 | assert(user.posts[0].title === 'New Post'); 34 | done(); 35 | }); 36 | }); 37 | 38 | it('can remove an existing subdocument', (done) => { 39 | const joe = new User({ 40 | name: 'Joe', 41 | posts: [{ title: 'New Title' }] 42 | }); 43 | 44 | joe.save() 45 | .then(() => User.findOne({ name: 'Joe' })) 46 | .then((user) => { 47 | const post = user.posts[0]; 48 | post.remove(); 49 | return user.save(); 50 | }) 51 | .then(() => User.findOne({ name: 'Joe' })) 52 | .then((user) => { 53 | assert(user.posts.length === 0); 54 | done(); 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link } from 'react-router'; 3 | 4 | class Header extends Component { 5 | constructor(props) { 6 | super(props); 7 | 8 | this.state = { id: null }; 9 | } 10 | 11 | componentWillMount() { 12 | this.setLink(); 13 | } 14 | 15 | setLink() { 16 | window.db.collection('artists') 17 | .aggregate({ $sample: { size: 100 } }) 18 | .toArray() 19 | .then((artists) => { 20 | const artist = artists[~~(Math.random() * artists.length)]; 21 | 22 | if (artist) { 23 | this.setState({ id: artist._id.toString() }); 24 | } 25 | }); 26 | } 27 | 28 | render() { 29 | return ( 30 |
31 | 53 |
54 | ); 55 | } 56 | }; 57 | 58 | export default Header; 59 | -------------------------------------------------------------------------------- /users/test/update_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const User = require('../src/user'); 3 | 4 | describe('Updating records', () => { 5 | let joe; 6 | 7 | beforeEach((done) => { 8 | joe = new User({ name: 'Joe', likes: 0 }); 9 | joe.save() 10 | .then(() => done()); 11 | }); 12 | 13 | function assertName(operation, done) { 14 | operation 15 | .then(() => User.find({})) 16 | .then((users) => { 17 | assert(users.length === 1); 18 | assert(users[0].name === 'Alex'); 19 | done(); 20 | }); 21 | } 22 | 23 | it('instance type using set n save', (done) => { 24 | joe.set('name', 'Alex'); 25 | assertName(joe.save(), done); 26 | }); 27 | 28 | it('A model instance can update', (done) => { 29 | assertName(joe.update({ name: 'Alex' }), done); 30 | }); 31 | 32 | it('A model class can update', (done) => { 33 | assertName( 34 | User.update({ name: 'Joe' }, { name: 'Alex' }), 35 | done 36 | ); 37 | }); 38 | 39 | it('A model class can update one record', (done) => { 40 | assertName( 41 | User.findOneAndUpdate({ name: 'Joe' }, { name: 'Alex' }), 42 | done 43 | ); 44 | }); 45 | 46 | it('A model class can find a record with an Id and update', (done) => { 47 | assertName( 48 | User.findByIdAndUpdate(joe._id, { name: 'Alex' }), 49 | done 50 | ); 51 | }); 52 | 53 | it('A user can have their postcount incremented by 1', (done) => { 54 | User.update({ name: 'Joe' }, { $inc: { likes: 10 } }) 55 | .then(() => User.findOne({ name: 'Joe' })) 56 | .then((user) => { 57 | assert(user.likes === 10); 58 | done(); 59 | }); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /UpStarMusic/npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ '/usr/local/Cellar/node/7.0.0/bin/node', 3 | 1 verbose cli '/usr/local/bin/npm', 4 | 1 verbose cli 'run', 5 | 1 verbose cli 'dev' ] 6 | 2 info using npm@3.10.8 7 | 3 info using node@v7.0.0 8 | 4 verbose stack Error: missing script: dev 9 | 4 verbose stack at run (/usr/local/lib/node_modules/npm/lib/run-script.js:151:19) 10 | 4 verbose stack at /usr/local/lib/node_modules/npm/lib/run-script.js:61:5 11 | 4 verbose stack at /usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:356:5 12 | 4 verbose stack at checkBinReferences_ (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:320:45) 13 | 4 verbose stack at final (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:354:3) 14 | 4 verbose stack at then (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:124:5) 15 | 4 verbose stack at ReadFileContext. (/usr/local/lib/node_modules/npm/node_modules/read-package-json/read-json.js:295:20) 16 | 4 verbose stack at ReadFileContext.callback (/usr/local/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:78:16) 17 | 4 verbose stack at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:335:13) 18 | 5 verbose cwd /Users/stephengrider/workspace/MongoWorkspace/prod/UpStarMusic 19 | 6 error Darwin 15.2.0 20 | 7 error argv "/usr/local/Cellar/node/7.0.0/bin/node" "/usr/local/bin/npm" "run" "dev" 21 | 8 error node v7.0.0 22 | 9 error npm v3.10.8 23 | 10 error missing script: dev 24 | 11 error If you need help, you may report this error at: 25 | 11 error 26 | 12 verbose exit [ 1, true ] 27 | -------------------------------------------------------------------------------- /users/test/association_test.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const assert = require('assert'); 3 | const User = require('../src/user'); 4 | const Comment = require('../src/comment'); 5 | const BlogPost = require('../src/blogPost'); 6 | 7 | describe('Assocations', () => { 8 | let joe, blogPost, comment; 9 | 10 | beforeEach((done) => { 11 | joe = new User({ name: 'Joe' }); 12 | blogPost = new BlogPost({ title: 'JS is Great', content: 'Yep it really is' }); 13 | comment = new Comment({ content: 'Congrats on great post' }); 14 | 15 | joe.blogPosts.push(blogPost); 16 | blogPost.comments.push(comment); 17 | comment.user = joe; 18 | 19 | Promise.all([joe.save(), blogPost.save(), comment.save()]) 20 | .then(() => done()); 21 | }); 22 | 23 | it('saves a relation between a user and a blogpost', (done) => { 24 | User.findOne({ name: 'Joe' }) 25 | .populate('blogPosts') 26 | .then((user) => { 27 | assert(user.blogPosts[0].title === 'JS is Great'); 28 | done(); 29 | }); 30 | }); 31 | 32 | it('saves a full relation graph', (done) => { 33 | User.findOne({ name: 'Joe' }) 34 | .populate({ 35 | path: 'blogPosts', 36 | populate: { 37 | path: 'comments', 38 | model: 'comment', 39 | populate: { 40 | path: 'user', 41 | model: 'user' 42 | } 43 | } 44 | }) 45 | .then((user) => { 46 | assert(user.name === 'Joe'); 47 | assert(user.blogPosts[0].title === 'JS is Great'); 48 | assert(user.blogPosts[0].comments[0].content === 'Congrats on great post'); 49 | assert(user.blogPosts[0].comments[0].user.name === 'Joe'); 50 | 51 | done(); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/Paginator.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../../actions'; 4 | 5 | class Paginator extends Component { 6 | back() { 7 | const { offset, limit, form: { filters: { values } } } = this.props; 8 | 9 | if (offset === 0 ) { return; } 10 | 11 | this.props.searchArtists(values, offset - 10, limit); 12 | } 13 | 14 | advance() { 15 | const { offset, limit, count, form: { filters: { values } } } = this.props; 16 | 17 | if ((offset + limit) > count) { return; } 18 | 19 | this.props.searchArtists(values, offset + 10, limit); 20 | } 21 | 22 | left() { 23 | return ( 24 |
  • 25 | 26 | chevron_left 27 | 28 |
  • 29 | ); 30 | } 31 | 32 | right() { 33 | const { offset, limit, count } = this.props; 34 | 35 | const end = ((offset + limit) >= count) ? true : false; 36 | 37 | return ( 38 |
  • 39 | 40 | chevron_right 41 | 42 |
  • 43 | ); 44 | } 45 | 46 | render() { 47 | return ( 48 |
    49 | 54 | {this.props.count} Records Found 55 |
    56 | ); 57 | } 58 | } 59 | 60 | const mapStateToProps = ({ artists, form }) => { 61 | const { limit, offset, count } = artists; 62 | 63 | return { limit, offset, count, form}; 64 | }; 65 | 66 | export default connect(mapStateToProps, actions)(Paginator); 67 | -------------------------------------------------------------------------------- /UpStarMusic/bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | 29 | 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = "/"; 38 | 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ([ 44 | /* 0 */ 45 | /***/ function(module, exports, __webpack_require__) { 46 | 47 | module.exports = __webpack_require__(1); 48 | 49 | 50 | /***/ }, 51 | /* 1 */ 52 | /***/ function(module, exports, __webpack_require__) { 53 | 54 | 'use strict'; 55 | 56 | var _mongodb = __webpack_require__(2); 57 | 58 | var url = 'mongodb://localhost:27017/auth'; 59 | 60 | /***/ }, 61 | /* 2 */ 62 | /***/ function(module, exports) { 63 | 64 | module.exports = require("mongodb"); 65 | 66 | /***/ } 67 | /******/ ]); -------------------------------------------------------------------------------- /UpStarMusic/src/seeds.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import faker from 'faker'; 3 | import { Db, Server } from 'mongodb'; 4 | import { GENRES } from './constants'; 5 | 6 | const MINIMUM_ARTISTS = 200; 7 | const ARTISTS_TO_ADD = 15000; 8 | 9 | let artistsCollection; 10 | const db = new Db('upstar_music', new Server('localhost', 27017)); 11 | db.open() 12 | .then(() => { 13 | artistsCollection = db.collection('artists'); 14 | return artistsCollection.count({}); 15 | }) 16 | .then(count => { 17 | if (count < MINIMUM_ARTISTS) { 18 | const artists = _.times(ARTISTS_TO_ADD, () => createArtist()); 19 | 20 | artistsCollection.insertMany(artists); 21 | } 22 | }) 23 | .catch(e => console.log(e)); 24 | 25 | 26 | function createArtist() { 27 | return { 28 | name: faker.name.findName(), 29 | age: randomBetween(15, 45), 30 | yearsActive: randomBetween(0, 15), 31 | image: faker.image.avatar(), 32 | genre: getGenre(), 33 | website: faker.internet.url(), 34 | netWorth: randomBetween(0, 5000000), 35 | labelName: faker.company.companyName(), 36 | retired: faker.random.boolean(), 37 | albums: getAlbums() 38 | }; 39 | } 40 | 41 | function getAlbums() { 42 | return _.times(randomBetween(0, 5), () => { 43 | const copiesSold = randomBetween(0, 1000000); 44 | 45 | return { 46 | title: _.capitalize(faker.random.words()), 47 | date: faker.date.past(), 48 | copiesSold, 49 | numberTracks: randomBetween(1, 20), 50 | image: getAlbumImage(), 51 | revenue: copiesSold * 12.99 52 | }; 53 | }); 54 | } 55 | 56 | function getAlbumImage() { 57 | const types = _.keys(faker.image); 58 | const method = randomEntry(types); 59 | 60 | return faker.image[method](); 61 | } 62 | 63 | function getGenre() { 64 | return randomEntry(GENRES); 65 | } 66 | 67 | function randomEntry(array) { 68 | return array[~~(Math.random() * array.length)]; 69 | } 70 | 71 | function randomBetween(min, max) { 72 | return ~~(Math.random() * (max-min)) + min; 73 | } 74 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistEdit.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../../actions'; 4 | 5 | class ArtistEdit extends Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = {}; 10 | } 11 | 12 | componentWillMount() { 13 | this.props.findArtist(this.props.params.id); 14 | } 15 | 16 | componentWillReceiveProps({ artist }) { 17 | if (artist) { 18 | const { name, age, yearsActive, genre } = artist; 19 | 20 | this.setState({ name, age, yearsActive, genre }); 21 | } 22 | } 23 | 24 | componentWillUpdate(nextProps) { 25 | if (nextProps.params.id !== this.props.params.id) { 26 | this.props.findArtist(nextProps.params.id); 27 | } 28 | } 29 | 30 | componentWillUnmount() { 31 | this.props.clearError(); 32 | } 33 | 34 | onSubmit(event) { 35 | event.preventDefault(); 36 | event.stopPropagation(); 37 | 38 | this.props.editArtist(this.props.params.id, this.state); 39 | } 40 | 41 | render() { 42 | return ( 43 |
    44 |
    45 | this.setState({ name: e.target.value })} 48 | placeholder="Name" 49 | /> 50 |
    51 |
    52 | this.setState({ age: e.target.value })} 55 | placeholder="Age" 56 | /> 57 |
    58 |
    59 | this.setState({ yearsActive: e.target.value })} 62 | placeholder="Years Active" 63 | /> 64 |
    65 |
    66 | this.setState({ genre: e.target.value })} 69 | placeholder="Genre" 70 | /> 71 |
    72 |
    73 | {this.props.errorMessage} 74 |
    75 | 76 |
    77 | ); 78 | } 79 | } 80 | 81 | const mapStateToProps = (state) => { 82 | return { 83 | artist: state.artists.artist, 84 | errorMessage: state.errors 85 | }; 86 | }; 87 | 88 | export default connect(mapStateToProps, actions)(ArtistEdit); 89 | -------------------------------------------------------------------------------- /muber/test/controllers/drivers_controller_test.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | const request = require('supertest'); 3 | const mongoose = require('mongoose'); 4 | const app = require('../../app'); 5 | 6 | const Driver = mongoose.model('driver'); 7 | 8 | describe('Drivers controller', () => { 9 | it('Post to /api/drivers creates a new driver', (done) => { 10 | Driver.count().then(count => { 11 | request(app) 12 | .post('/api/drivers') 13 | .send({ email: 'test@test.com' }) 14 | .end(() => { 15 | Driver.count().then(newCount => { 16 | assert(count + 1 === newCount); 17 | done(); 18 | }); 19 | }); 20 | }); 21 | }); 22 | 23 | it('Post to /api/drivers requires an email', (done) => { 24 | request(app) 25 | .post('/api/drivers') 26 | .send({}) 27 | .end((err, res) => { 28 | assert(res.body.error); 29 | done(); 30 | }); 31 | }); 32 | 33 | it('Put to /api/drivers/id can update a record', done => { 34 | const driver = new Driver({ email: 'test@test.com', driving: false }); 35 | 36 | driver.save().then(() => { 37 | request(app) 38 | .put(`/api/drivers/${driver._id}`) 39 | .send({ driving: true }) 40 | .end(() => { 41 | Driver.findOne({ email: 'test@test.com' }) 42 | .then(driver => { 43 | assert(driver.driving === true); 44 | done(); 45 | }); 46 | }); 47 | }); 48 | }); 49 | 50 | it('Delete to /api/drivers/:id can delete a record', done => { 51 | const driver = new Driver({ email: 'test@test.com' }); 52 | 53 | driver.save().then(() => { 54 | request(app) 55 | .delete(`/api/drivers/${driver._id}`) 56 | .end(() => { 57 | Driver.count().then(count => { 58 | assert(count === 0); 59 | done(); 60 | }); 61 | }); 62 | }); 63 | }); 64 | 65 | it('Get to /api/drivers finds drivers in a location', done => { 66 | const seattleDriver = new Driver({ 67 | email: 'seattle@test.com', 68 | geometry: { type: 'Point', coordinates: [-122.4759902, 47.6147628] } 69 | }); 70 | const miamiDriver = new Driver({ 71 | email: 'miami@test.com', 72 | geometry: { type: 'Point', coordinates: [-80.2534507, 25.791581] } 73 | }); 74 | 75 | Promise.all([seattleDriver.save(), miamiDriver.save()]) 76 | .then(() => { 77 | request(app) 78 | .get('/api/drivers?lng=-80&lat=25') 79 | .end((err, response) => { 80 | assert(response.body.length === 1); 81 | assert(response.body[0].obj.email === 'miami@test.com'); 82 | done(); 83 | }); 84 | }); 85 | }) 86 | }); 87 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistIndex.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React, { Component } from 'react'; 3 | import { Link } from 'react-router'; 4 | import { connect } from 'react-redux'; 5 | import Paginator from './Paginator'; 6 | import * as actions from '../../actions'; 7 | 8 | class ArtistIndex extends Component { 9 | onChange(_id) { 10 | if (_.contains(this.props.selection, _id)) { 11 | this.props.deselectArtist(_id); 12 | } else { 13 | this.props.selectArtist(_id); 14 | } 15 | } 16 | 17 | renderList(artist) { 18 | const { _id } = artist; 19 | const classes = `collection-item avatar ${artist.retired && 'retired'}`; 20 | 21 | return ( 22 |
  • 23 |
    24 | this.onChange(_id)} 29 | /> 30 |
    32 | 33 |
    34 | 35 | {artist.name} 36 | 37 |

    38 | {artist.age} years old 39 |
    40 | {artist.yearsActive} years active 41 |

    42 |
    43 | 44 | play_arrow 45 | 46 |
  • 47 | ); 48 | } 49 | 50 | renderPaginator() { 51 | if (this.props.artists.all.length) { 52 | return ; 53 | } 54 | } 55 | 56 | renderEmptyCollection() { 57 | if (this.props.artists.all.length) { return; } 58 | 59 | return ( 60 |
    61 |
    No records found!
    62 |
    Try searching again
    63 |
    64 | ); 65 | } 66 | 67 | renderRetire() { 68 | if (this.props.selection.length) { 69 | return ( 70 |
    71 | 77 | 83 |
    84 | ); 85 | } 86 | } 87 | 88 | render() { 89 | return ( 90 |
    91 | {this.renderRetire()} 92 |
      93 | {this.props.artists.all.map(this.renderList.bind(this))} 94 | {this.renderEmptyCollection()} 95 |
    96 | 97 | {this.renderPaginator()} 98 |
    99 | ); 100 | } 101 | } 102 | 103 | const mapStateToProps = ({ artists, selection }) => ({ artists, selection }); 104 | 105 | export default connect(mapStateToProps, actions)(ArtistIndex); 106 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistDetail.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import { Link } from 'react-router'; 4 | import * as actions from '../../actions'; 5 | 6 | class ArtistDetail extends Component { 7 | componentWillMount() { 8 | this.props.findArtist(this.props.params.id); 9 | } 10 | 11 | componentWillReceiveProps(nextProps) { 12 | if (nextProps.params.id !== this.props.params.id) { 13 | this.props.findArtist(nextProps.params.id); 14 | } 15 | } 16 | 17 | componentWillUnmount() { 18 | this.props.resetArtist(); 19 | } 20 | 21 | onDeleteClick() { 22 | this.props.deleteArtist(this.props.params.id); 23 | } 24 | 25 | renderAlbums() { 26 | const { albums } = this.props.artist; 27 | 28 | if (!albums || !albums.map) { return; } 29 | 30 | return albums.map(album => { 31 | return ( 32 |
    33 |
    34 | 35 | 36 |

    {album.title}

    37 |
    38 |
    39 |
    40 |
    41 |
    {album.copiesSold}
    42 | copies sold 43 |
    44 |
    45 |
    {album.numberTracks}
    46 | tracks 47 |
    48 |
    49 |
    50 | ); 51 | }); 52 | } 53 | 54 | render() { 55 | if (!this.props.artist) { return
    Todo: implement "FindArtist" query
    ; } 56 | 57 | const { artist: { name, age, genre, image, yearsActive, netWorth, labelName, _id } } = this.props; 58 | 59 | return ( 60 |
    61 |
    62 | Back 63 | Edit 64 | Delete 65 |
    66 |
      67 |
    • 68 |
      69 |

      {name}

      70 |
      Master of {genre}
      71 |
      72 | 73 |
    • 74 |
    • 75 |
      {yearsActive}
      76 |

      Years Active

      77 |
    • 78 |
    • 79 |
      {age}
      80 |

      Years Old

      81 |
    • 82 |
    • 83 |
      ${netWorth}
      84 |

      Net Worth

      85 |
    • 86 |
    • 87 |
      {labelName}
      88 |

      Label

      89 |
    • 90 |
    • 91 | {this.renderAlbums()} 92 |
    • 93 |
    94 |
    95 | ); 96 | } 97 | } 98 | 99 | const mapStateToProps = ({ artists }) => { 100 | return { artist: artists.artist }; 101 | }; 102 | 103 | export default connect(mapStateToProps, actions)(ArtistDetail); 104 | -------------------------------------------------------------------------------- /UpStarMusic/src/components/artists/ArtistFilter.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Field, reduxForm } from 'redux-form'; 3 | import { connect } from 'react-redux'; 4 | import { Range } from '../filters'; 5 | import * as actions from '../../actions'; 6 | 7 | const TEXT_FIELDS = [ 8 | { label: 'Name', prop: 'name' } 9 | ]; 10 | 11 | class ArtistFilter extends Component { 12 | componentWillMount() { 13 | if (this.props.filters) { 14 | this.props.searchArtists({ 15 | name: '', 16 | ...this.props.filters 17 | }); 18 | } else { 19 | this.props.searchArtists({ 20 | name: '', 21 | sort: 'name' 22 | }); 23 | } 24 | } 25 | 26 | componentDidMount() { 27 | this.props.setAgeRange(); 28 | this.props.setYearsActiveRange(); 29 | } 30 | 31 | handleSubmit(formProps) { 32 | this.props.searchArtists({ 33 | name: '', 34 | ...formProps 35 | }); 36 | } 37 | 38 | renderInputs() { 39 | return TEXT_FIELDS.map(({ label, prop }) => 40 |
    41 | 48 |
    49 | ); 50 | } 51 | 52 | render() { 53 | const { handleSubmit } = this.props; 54 | 55 | return ( 56 |
    57 |
    58 |
    59 |
    60 | Search 61 |
    62 | 63 | {this.renderInputs()} 64 | 65 |
    66 | 74 |
    75 | 76 |
    77 | 85 |
    86 | 87 |
    88 | 89 | 90 | 91 | 92 | 93 | 94 |
    95 | 96 |
    97 | 98 |
    99 |
    100 |
    101 |
    102 | ); 103 | } 104 | } 105 | 106 | const mapStateToProps = (state) => { 107 | const { filterCriteria } = state; 108 | 109 | return { 110 | yearsActive: filterCriteria.yearsActive, 111 | ageRange: filterCriteria.age, 112 | filters: state.form.filters && state.form.filters.values 113 | }; 114 | }; 115 | 116 | export default connect(mapStateToProps, actions)(reduxForm({ 117 | destroyOnUnmount: false, 118 | form: 'filters', 119 | initialValues: { sort: 'name' } 120 | })(ArtistFilter)); 121 | -------------------------------------------------------------------------------- /UpStarMusic/src/actions/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import { hashHistory } from 'react-router'; 3 | import { 4 | SET_AGE_RANGE, 5 | SET_YEARS_ACTIVE_RANGE, 6 | SEARCH_ARTISTS, 7 | FIND_ARTIST, 8 | RESET_ARTIST, 9 | CREATE_ERROR, 10 | CLEAR_ERROR, 11 | DESELECT_ARTIST, 12 | SELECT_ARTIST, 13 | RESET_SELECTION 14 | } from './types'; 15 | 16 | import GetAgeRange from '../../database/queries/GetAgeRange'; 17 | import GetYearsActiveRange from '../../database/queries/GetYearsActiveRange'; 18 | import SearchArtists from '../../database/queries/SearchArtists'; 19 | import FindArtist from '../../database/queries/FindArtist'; 20 | import CreateArtist from '../../database/queries/CreateArtist'; 21 | import EditArtist from '../../database/queries/EditArtist'; 22 | import DeleteArtist from '../../database/queries/DeleteArtist'; 23 | import SetRetired from '../../database/queries/SetRetired'; 24 | import SetNotRetired from '../../database/queries/SetNotRetired'; 25 | 26 | export const resetArtist = () => { 27 | return { type: RESET_ARTIST }; 28 | }; 29 | 30 | export const clearError = () => { 31 | return { type: CLEAR_ERROR }; 32 | }; 33 | 34 | export const selectArtist = id => { 35 | return { type: SELECT_ARTIST, payload: id }; 36 | }; 37 | 38 | export const deselectArtist = id => { 39 | return { type: DESELECT_ARTIST, payload: id }; 40 | }; 41 | 42 | export const setRetired = ids => (dispatch, getState) => 43 | SetRetiredProxy(ids.map(id => id.toString())) 44 | .then(() => dispatch({ type: RESET_SELECTION })) 45 | .then(() => refreshSearch(dispatch, getState)); 46 | 47 | export const setNotRetired = ids => (dispatch, getState) => 48 | SetNotRetiredProxy(ids.map(id => id.toString())) 49 | .then(() => dispatch({ type: RESET_SELECTION })) 50 | .then(() => refreshSearch(dispatch, getState)); 51 | 52 | export const setAgeRange = () => dispatch => 53 | GetAgeRangeProxy() 54 | .then(result => 55 | dispatch({ type: SET_AGE_RANGE, payload: result }) 56 | ); 57 | 58 | export const setYearsActiveRange = () => dispatch => 59 | GetYearsActiveRangeProxy() 60 | .then(result => 61 | dispatch({ type: SET_YEARS_ACTIVE_RANGE, payload: result }) 62 | ); 63 | 64 | export const searchArtists = (...criteria) => dispatch => 65 | SearchArtistsProxy(...criteria) 66 | .then((result = []) => 67 | dispatch({ type: SEARCH_ARTISTS, payload: result }) 68 | ); 69 | 70 | export const findArtist = id => dispatch => 71 | FindArtistProxy(id) 72 | .then(artist => 73 | dispatch({ type: FIND_ARTIST, payload: artist }) 74 | ); 75 | 76 | export const createArtist = props => dispatch => 77 | CreateArtistProxy(props) 78 | .then(artist => { 79 | hashHistory.push(`artists/${artist.id}`); 80 | }) 81 | .catch(error => { 82 | console.log(error); 83 | dispatch({ type: CREATE_ERROR, payload: error }); 84 | }); 85 | 86 | export const editArtist = (id, props) => dispatch => 87 | EditArtistProxy(id, props) 88 | .then(() => hashHistory.push(`artists/${id}`)) 89 | .catch(error => { 90 | console.log(error); 91 | dispatch({ type: CREATE_ERROR, payload: error }); 92 | }); 93 | 94 | export const deleteArtist = (id) => dispatch => 95 | DeleteArtistProxy(id) 96 | .then(() => hashHistory.push('/')) 97 | .catch(error => { 98 | console.log(error); 99 | dispatch({ type: CREATE_ERROR, payload: error }); 100 | }); 101 | 102 | 103 | // 104 | // Faux Proxies 105 | 106 | const GetAgeRangeProxy = (...args) => { 107 | const result = GetAgeRange(...args); 108 | if (!result || !result.then) { 109 | return new Promise(() => {}); 110 | } 111 | return result; 112 | }; 113 | 114 | const GetYearsActiveRangeProxy = (...args) => { 115 | const result = GetYearsActiveRange(...args); 116 | if (!result || !result.then) { 117 | return new Promise(() => {}); 118 | } 119 | return result; 120 | }; 121 | 122 | const SearchArtistsProxy = (criteria, offset, limit) => { 123 | const result = SearchArtists(_.omit(criteria, 'sort'), criteria.sort, offset, limit); 124 | if (!result || !result.then) { 125 | return new Promise(() => {}); 126 | } 127 | return result; 128 | }; 129 | 130 | const FindArtistProxy = (...args) => { 131 | const result = FindArtist(...args); 132 | if (!result || !result.then) { 133 | return new Promise(() => {}); 134 | } 135 | return result; 136 | }; 137 | 138 | const CreateArtistProxy = (...args) => { 139 | const result = CreateArtist(...args); 140 | if (!result || !result.then) { 141 | return new Promise(() => {}); 142 | } 143 | return result; 144 | }; 145 | 146 | const EditArtistProxy = (...args) => { 147 | const result = EditArtist(...args); 148 | if (!result || !result.then) { 149 | return new Promise(() => {}); 150 | } 151 | return result; 152 | }; 153 | 154 | const DeleteArtistProxy = (...args) => { 155 | const result = DeleteArtist(...args); 156 | if (!result || !result.then) { 157 | return new Promise(() => {}); 158 | } 159 | return result; 160 | }; 161 | 162 | const SetRetiredProxy = (_ids) => { 163 | const result = SetRetired(_ids); 164 | if (!result || !result.then) { 165 | return new Promise(() => {}); 166 | } 167 | return result; 168 | }; 169 | 170 | const SetNotRetiredProxy = (_ids) => { 171 | const result = SetNotRetired(_ids); 172 | if (!result || !result.then) { 173 | return new Promise(() => {}); 174 | } 175 | return result; 176 | }; 177 | 178 | // 179 | // Helpers 180 | 181 | const refreshSearch = (dispatch, getState) => { 182 | const { artists: { offset, limit } } = getState(); 183 | const criteria = getState().form.filters.values; 184 | 185 | dispatch(searchArtists({ name: '', ...criteria }, offset, limit)); 186 | }; 187 | --------------------------------------------------------------------------------