diff --git a/client/demo/todo-list-controller/todo-list.controller.js b/client/demo/todo-list-controller/todo-list.controller.js
index cb4b63b..99518b9 100644
--- a/client/demo/todo-list-controller/todo-list.controller.js
+++ b/client/demo/todo-list-controller/todo-list.controller.js
@@ -3,7 +3,7 @@
// Create module and controller
angular
- .module('todoListDemo', [])
+ .module('todoListControllerDemo', [])
.controller('TodoListController', TodoListController);
diff --git a/client/demo/todo-list-controller/todo-list.controller.spec.js b/client/demo/todo-list-controller/todo-list.controller.spec.js
index e69de29..7d21948 100644
--- a/client/demo/todo-list-controller/todo-list.controller.spec.js
+++ b/client/demo/todo-list-controller/todo-list.controller.spec.js
@@ -0,0 +1,29 @@
+describe('Controller: todo-list', function() {
+ 'use strict';
+ var controller,
+ scope;
+ // Refresh the $filter every time.
+ beforeEach(module('todoListControllerDemo'));
+ beforeEach(inject(function(_$rootScope_, $controller) {
+ scope = _$rootScope_.$new();
+ controller = $controller('TodoListController',
+ {$scope: scope});
+ })
+ );
+
+ it('should start empty', function() {
+ expect(controller.list.length).to.equal(0);
+ });
+
+ it('should add items', function() {
+ controller.itemText = 'First item';
+ controller.add(controller.itemText);
+ expect(controller.list.length).to.equal(1);
+ controller.itemText = 'Second item';
+ controller.add(controller.itemText);
+ expect(controller.list.length).to.equal(2);
+ controller.remove(1);
+ expect(controller.list.length).to.equal(1);
+ });
+
+});
diff --git a/client/demo/validation/customValidation.module.js b/client/demo/validation/customValidation.module.js
new file mode 100644
index 0000000..9510880
--- /dev/null
+++ b/client/demo/validation/customValidation.module.js
@@ -0,0 +1,4 @@
+(function() {
+ 'use strict';
+ angular.module('customValidation', []);
+})();
\ No newline at end of file
diff --git a/client/demo/validation/emailCom.directive.js b/client/demo/validation/emailCom.directive.js
new file mode 100644
index 0000000..a6f21da
--- /dev/null
+++ b/client/demo/validation/emailCom.directive.js
@@ -0,0 +1,31 @@
+(function() {
+ 'use strict';
+
+ angular
+ .module('customValidation')
+ .directive('emailCom', emailComDirective);
+
+ emailComDirective.$inject = [];
+
+ function emailComDirective() {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: emailComLink
+ };
+
+ function emailComLink(scope, element, attributes, ngModelController) {
+ var oldEmail;
+ oldEmail = ngModelController.$validators.email;
+
+ ngModelController.$validators.email = validateEmail;
+
+ scope.modelController = ngModelController;
+
+ function validateEmail(viewValue, modelValue) {
+
+ return modelValue === undefined || oldEmail(viewValue, modelValue) && modelValue.endsWith('.com');
+ }
+ }
+ }
+})();
diff --git a/client/demo/validation/index.html b/client/demo/validation/index.html
new file mode 100644
index 0000000..eeb4dd8
--- /dev/null
+++ b/client/demo/validation/index.html
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/demo/validation/same-letters.directive.js b/client/demo/validation/same-letters.directive.js
new file mode 100644
index 0000000..2091599
--- /dev/null
+++ b/client/demo/validation/same-letters.directive.js
@@ -0,0 +1,29 @@
+(function() {
+ 'use strict';
+
+ angular
+ .module('customValidation')
+ .directive('sameLettersNumbers', sameLettersNumbersDirective);
+
+ sameLettersNumbersDirective.$inject = [];
+
+ function sameLettersNumbersDirective() {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: sameLettersNumbersLink
+ };
+
+ function sameLettersNumbersLink(scope, element, attributes, ngModelController) {
+
+ ngModelController.$validators.sameLettersNumbers = validateSameNumbers;
+
+ function validateSameNumbers(viewValue, modelValue) {
+ var letters = (viewValue || ' ').match(/[A-Za-z]/g) || [],
+ numbers = (viewValue || ' ').match(/[0-9]/g) || [];
+
+ return letters.length === numbers.length;
+ }
+ }
+ }
+})();
diff --git a/client/index.html b/client/index.html
index 687cba4..2f82e12 100644
--- a/client/index.html
+++ b/client/index.html
@@ -13,6 +13,7 @@
+
@@ -53,12 +54,13 @@
-
+
+
+
-
-
+
@@ -70,6 +72,7 @@
+
@@ -82,6 +85,11 @@
+
+
+
+
+
diff --git a/e2e/expenses/main.spec.js b/e2e/expenses/main.spec.js
new file mode 100644
index 0000000..7763a18
--- /dev/null
+++ b/e2e/expenses/main.spec.js
@@ -0,0 +1,30 @@
+'use strict';
+
+describe('Expenses', function() {
+ var page;
+
+ beforeEach(function() {
+ browser.get('/demo/expenses/');
+ page = {};
+ });
+
+ it('should add an expense', function() {
+ page.date = element(by.id('date'));
+ page.type = element(by.id('type'));
+ page.description = element(by.id('description'));
+ page.amount = element(by.id('amount'));
+ page.button = element(by.id('add-button'));
+
+ page.date.sendKeys('11/25/2015');
+ page.type.sendKeys('financial');
+ page.description.sendKeys('credit');
+ page.amount.sendKeys('21000');
+ page.button.click();
+
+ var todoList = element.all(by.repeater('expense in expensesVm.list'));
+ expect(todoList.count()).to.eventually.equal(1);
+ var total = $('.row.total .ng-binding').getText();
+ expect(total).to.eventually.equal('21000');
+
+ });
+});
diff --git a/karma.conf.js b/karma.conf.js
index 4bdbd2b..0d22131 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -23,6 +23,7 @@ module.exports = function(config) {
'client/app/app.js',
'client/app/**/*.js',
'client/components/**/*.js',
+ 'client/demo/**/*.js',
//'client/app/**/*.jade',
//'client/components/**/*.jade',
'client/app/**/*.html',
@@ -35,7 +36,8 @@ module.exports = function(config) {
'**/*.jade': 'ng-jade2js',
'**/*.html': 'html2js',
'**/*.coffee': 'coffee',
- 'client/app/**/*.js' : ['coverage']
+ 'client/app/**/*.js' : ['coverage'],
+ 'client/demo/**/*.js' : ['coverage']
},
ngHtml2JsPreprocessor: {
diff --git a/package.json b/package.json
index 27a310f..fdb2256 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"method-override": "~1.0.0",
"morgan": "~1.0.0",
"moviedb": "^0.2.2",
+ "nedb": "^1.4.0",
"omdb-client": "^1.0.6",
"serve-favicon": "~2.0.1",
"serve-index": "^1.7.2"
@@ -61,6 +62,8 @@
"jit-grunt": "^0.5.0",
"jshint-stylish": "~0.1.5",
"karma": "~0.12.9",
+ "karma-chai": "^0.1.0",
+ "karma-chai-as-promised": "^0.1.2",
"karma-chrome-launcher": "~0.1.3",
"karma-coverage": "^0.5.3",
"karma-firefox-launcher": "~0.1.3",
diff --git a/server/api/movies/index.js b/server/api/movies/index.js
index 8300a18..7fd0291 100644
--- a/server/api/movies/index.js
+++ b/server/api/movies/index.js
@@ -3,18 +3,20 @@
var express = require('express');
var router = express.Router();
-if (!process.env.MOVIEDB_API) {
- router.get('/', function(req, res){
- res.status({status: 404});
- res.json({error: 404})
- });
-} else {
- var controller = require('./movies.controller');
- router.get('/', controller.index);
- router.get('/:movieId', controller.get);
- router.get('/configuration', controller.configuration);
- router.get('/playing', controller.nowPlaying);
- router.get('/search/:query', controller.search);
+function createRouter(app) {
+ if (!process.env.MOVIEDB_API) {
+ router.get('/', function(req, res){
+ res.status({status: 404});
+ res.json({error: 404})
+ });
+ } else {
+ var controller = require('./movies.controller')(app) ;
+ router.get('/', controller.index);
+ router.get('/info/:movieId', controller.get);
+ router.get('/configuration', controller.configuration);
+ router.get('/playing', controller.nowPlaying);
+ router.get('/search/:query', controller.search);
+ }
+ return router;
}
-
-module.exports = router;
+module.exports = createRouter;
diff --git a/server/api/movies/movies.controller.js b/server/api/movies/movies.controller.js
index 662489a..3da7f5a 100644
--- a/server/api/movies/movies.controller.js
+++ b/server/api/movies/movies.controller.js
@@ -9,121 +9,83 @@
'use strict';
+
var _ = require('lodash'),
MovieDB = require('moviedb')(process.env.MOVIEDB_API);
// Get list of things
-exports.get = get;
-exports.index = index;
-exports.search = search;
-exports.configuration = configuration;
-exports.nowPlaying = nowPlaying;
+function createRouteConfigs(app) {
+ var routeConfigs = {};
+ routeConfigs.get = get;
+ routeConfigs.index = index;
+ routeConfigs.search = search;
+ routeConfigs.configuration = configuration;
+ routeConfigs.nowPlaying = nowPlaying;
-function configuration(req, res){
- MovieDB.configuration(function(err, movies){
- console.log(err);
- console.log(movies);
- if (movies === null) {
- res.json({
- "images": {
- "base_url": "http://image.tmdb.org/t/p/",
- "secure_base_url": "https://image.tmdb.org/t/p/",
- "backdrop_sizes": [
- "w300",
- "w780",
- "w1280",
- "original"
- ],
- "logo_sizes": [
- "w45",
- "w92",
- "w154",
- "w185",
- "w300",
- "w500",
- "original"
- ],
- "poster_sizes": [
- "w92",
- "w154",
- "w185",
- "w342",
- "w500",
- "w780",
- "original"
- ],
- "profile_sizes": [
- "w45",
- "w185",
- "h632",
- "original"
- ],
- "still_sizes": [
- "w92",
- "w185",
- "w300",
- "original"
- ]
- },
- "change_keys": [
- "adult",
- "also_known_as",
- "alternative_titles",
- "biography",
- "birthday",
- "budget",
- "cast",
- "character_names",
- "crew",
- "deathday",
- "general",
- "genres",
- "homepage",
- "images",
- "imdb_id",
- "name",
- "original_title",
- "overview",
- "plot_keywords",
- "production_companies",
- "production_countries",
- "releases",
- "revenue",
- "runtime",
- "spoken_languages",
- "status",
- "tagline",
- "title",
- "trailers",
- "translations"
- ]
-})
- }
- res.json(movies);
+ function configuration(req, res){
+ app.db.findOne({configuration: 1}, function (err, result) {
+ if (result) {
+ res.json(result.configurationData);
+ } else{
+ MovieDB.configuration(function(err, config){
+ app.db.insert({configuration: 1, configurationData: config});
+ res.json(config);
+ });
+ }
});
-}
+ }
-function get(req, res) {
- MovieDB.movieInfo({id: req.params.id}, function(err, response){
- res.json(response);
+ function get(req, res) {
+ app.db.findOne({movieId: req.params.movieId}, function (err, result) {
+ if (result) {
+ res.json(result.movie)
+ } else{
+ MovieDB.movieInfo({id: req.params.movieId}, function(err, response){
+ MovieDB.movieSimilar({id: req.params.movieId}, function (errSimilar, responseSimilar) {
+ response.similar = responseSimilar;
+ app.db.insert({movieId: req.params.movieId, movie: response});
+ res.json(response);
+ })
+
+ });
+ }
});
-}
+ }
-function search(req, res) {
- MovieDB.searchMovie({query: req.params.query}, function(err, response){
- res.json(response);
- });
-}
-function nowPlaying(req, res) {
- MovieDB.miscPopularMovies(function(err, movies){
- res.json(movies);
- });
+ function search(req, res) {
+ app.db.findOne({searchQuery: req.params.query}, function (err, result) {
+ if (result) {
+ res.json(result.searchResults)
+ } else{
+ MovieDB.searchMovie({query: req.params.query}, function(err, response){
+ app.db.insert({searchQuery: req.params.query, searchResults: response});
+ res.json(response);
+ });
+ }
+ })
+
+ }
-}
-function index(req, res) {
+ function nowPlaying(req, res) {
+ MovieDB.miscPopularMovies(function(err, movies){
+ res.json(movies);
+ });
- MovieDB.miscTopRatedMovies(function(err, movies){
- res.json(movies);
- });
+ }
+ function index(req, res) {
+ app.db.findOne({topRated: 1}, function (err, result) {
+ if (result) {
+ res.json(result.movies);
+ } else{
+ MovieDB.miscTopRatedMovies(function(err, movies){
+ app.db.insert({topRated: 1, movies: movies});
+ res.json(movies);
+ });
+ }
+ });
+ }
+ return routeConfigs;
}
+
+module.exports = createRouteConfigs;
\ No newline at end of file
diff --git a/server/api/random/random.controller.js b/server/api/random/random.controller.js
index 0150d2e..2781440 100644
--- a/server/api/random/random.controller.js
+++ b/server/api/random/random.controller.js
@@ -9,8 +9,6 @@
'use strict';
-var _ = require('lodash'),
- MovieDB = require('moviedb')(process.env.MOVIEDB_API);
// Get list of things
exports.fast = fast;
@@ -24,7 +22,7 @@ function fast(req, res) {
function slow(req, res) {
setTimeout(function() {
res.json({value: Math.random()});
- }, 1000);
+ }, Math.floor(2000 * Math.random()));
}
function faulty(req, res) {
@@ -36,5 +34,5 @@ function faulty(req, res) {
res.status(status);
}
res.json({value: value});
- }, 1000);
+ }, Math.floor(1000 * Math.random()));
}
diff --git a/server/app.js b/server/app.js
index 1dcd147..b1719aa 100644
--- a/server/app.js
+++ b/server/app.js
@@ -12,9 +12,14 @@ var config = require('./config/environment');
// Setup server
var app = express();
var server = require('http').createServer(app);
+var Datastore = require('nedb');
+app.db = new Datastore({ filename: './cache.nedb', autoload: true });
+
require('./config/express')(app);
require('./routes')(app);
+//Open database
+
// Start server
server.listen(config.port, config.ip, function () {
console.log('Express server listening on %d, in %s mode', config.port, app.get('env'));
diff --git a/server/routes.js b/server/routes.js
index f7db227..37675a9 100644
--- a/server/routes.js
+++ b/server/routes.js
@@ -14,7 +14,7 @@ module.exports = function(app) {
// Insert routes below
app.use('/api/things', require('./api/thing'));
- app.use('/api/movies', require('./api/movies'));
+ app.use('/api/movies', require('./api/movies')(app));
app.use('/api/random', require('./api/random'));
// Serve demo directory
app.use('/demo/', serveIndex(demoDir, {'icons': true}));