diff --git a/client/app/components/movies-connector/connector.module.js b/client/app/components/movies-connector/connector.module.js index d5698e3..46f3838 100644 --- a/client/app/components/movies-connector/connector.module.js +++ b/client/app/components/movies-connector/connector.module.js @@ -1,5 +1,8 @@ 'use strict'; -angular.module('movies.connector', [ - -]); +angular + .module('movies.connector', []) + .constant('cache_calls', { + SEARCH_MOVIES: 100, + INFO_MOVIES: 100 + }); diff --git a/client/app/components/movies-connector/movieConnectorCache.factory.js b/client/app/components/movies-connector/movieConnectorCache.factory.js new file mode 100644 index 0000000..6bf5c3d --- /dev/null +++ b/client/app/components/movies-connector/movieConnectorCache.factory.js @@ -0,0 +1,73 @@ +(function() { + 'use strict'; + angular + .module('movies.connector') + .factory('moviesConnectorCache', moviesConnectorCacheFactory); + + /** + * @ngInject + */ + moviesConnectorCacheFactory.$inject = [ + 'cache_calls' + ]; + + function moviesConnectorCacheFactory( + cache_calls + ) { + var service = { + catchedInfo: [], + catchedSearch : [], + getCacheInfo: getCacheInfo, + addCacheInfo: addCacheInfo, + getCacheSearch: getCacheSearch, + addCacheSearch: addCacheSearch + }; + + function getCacheInfo(movieId) { + var result = {}; + result.hasCache = false; + result.data = {}; + angular.forEach(service.catchedInfo, function(obj){ + if (movieId == obj.movieId){ + result.hasCache = true; + result.data = obj; + console.log('cache INFO found!'); + } + }); + return result; + } + + function addCacheInfo(movieId, result){ + if (service.catchedInfo.length > cache_calls.INFO_MOVIES){ + console.log('Cleaning INFO cache'); + service.catchedInfo = []; + } + service.catchedInfo.push({ movieId: movieId, result: result}); + } + + function getCacheSearch(query) { + var result = {}; + result.hasCache = false; + result.data = {}; + angular.forEach(service.catchedSearch, function(obj){ + if (query == obj.query){ + result.hasCache = true; + result.data = obj; + console.log('cache MOVIES found!'); + } + }); + return result; + } + + function addCacheSearch(query, result){ + if (service.catchedSearch.length > cache_calls.SEARCH_MOVIES){ + console.log('Cleaning MOVIES cache'); + service.catchedSearch = []; + } + service.catchedSearch.push({ query: query, result: result}); + } + + return service; + } + +})(); diff --git a/client/app/components/movies-connector/moviesConnector.factory.js b/client/app/components/movies-connector/moviesConnector.factory.js index 5cd3886..6136bdb 100644 --- a/client/app/components/movies-connector/moviesConnector.factory.js +++ b/client/app/components/movies-connector/moviesConnector.factory.js @@ -9,29 +9,80 @@ */ moviesConnectorFactory.$inject = [ '$q', - '$http' + '$http', + 'moviesConnectorCache' ]; function moviesConnectorFactory( $q, - $http + $http, + moviesConnectorCache ) { var service = { cachedConfiguration: null, topRatedMovies: topRatedMovies, configuration: configuration, search: search, - movieInfo: movieInfo + movieInfo: movieInfo, + topRatedMoviesCompleteInfo: topRatedMoviesCompleteInfo }; function topRatedMovies() { return $http.get('/api/movies/'); } + + function topRatedMoviesCompleteInfo(){ + topRatedMovies() + .then(function(response){ + angular.forEach(response.results, function(obj){ + movieInfo(obj.id) + .then(function(response){ + console.log(response) + }); + }); + }); + + + } + function movieInfo(movieId) { - return $http.get('/api/movies/info/' + movieId); + var result = {}; + var deferred = $q.defer(); + + var cacheResult = moviesConnectorCache.getCacheInfo(movieId); + if (cacheResult.hasCache === true){ //the query has been catched: + result.data = cacheResult.data.result; + deferred.resolve(result); + } else { //that query has NOT been catched: + $http.get('/api/movies/info/' + movieId) + .then(function(response){ + result.data = response.data; + moviesConnectorCache.addCacheInfo(movieId, result.data); + deferred.resolve(result); + }); + } + + return deferred.promise; } + function search(query) { - return $http.get('/api/movies/search/' + query); + var result = {}; + var deferred = $q.defer(); + + var cacheResult = moviesConnectorCache.getCacheSearch(query); + if (cacheResult.hasCache === true){ //the query has been catched: + result.data = cacheResult.data.result; + deferred.resolve(result); + } else { //that query has NOT been catched: + $http.get('/api/movies/search/' + query) + .then(function(response){ + result.data = response.data; + moviesConnectorCache.addCacheSearch(query, result.data); + deferred.resolve(result); + }); + } + + return deferred.promise; } function configuration() { diff --git a/client/demo/ex/assignment1/index.html b/client/demo/ex/assignment1/index.html new file mode 100644 index 0000000..ed960e4 --- /dev/null +++ b/client/demo/ex/assignment1/index.html @@ -0,0 +1,117 @@ + + + + + + + + Expense App Assignment1 + + +
+

Expenses

+
+ +
+

Create Expense

+
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
DateTypeDescriptionAmount
{{ exp.date | date: 'dd/MM/yy'}}{{ exp.type }}{{ exp.description }}{{ exp.amount }} + + +
+
+
+

Totals by Type

+
+ + + + + + + + + + + +
TypeTotal
{{type}}{{ exp.amount + total }} +
+
+
+

Total All Types

+
+
+

{{ exp.amount + total}}

+
+
+
+
+ + diff --git a/client/demo/ex/assignment1/index2.html b/client/demo/ex/assignment1/index2.html new file mode 100644 index 0000000..fac60cd --- /dev/null +++ b/client/demo/ex/assignment1/index2.html @@ -0,0 +1,118 @@ + + + + + + + + + + +
+
+

Todo List #{{list.length}}

+
+ +
+
+ Date: +
+
+ +
+
+ Type: +
+
+ +
+
+ Description: +
+
+ +
+
+ Amount: +
+
+ +
+
+
+
+ + + + + +
+
+ + + + + + + + + + + + + + + + + + + +
DateTypeDescriptionAmountAction
{{item.date}}{{item.type}}{{item.description}}{{item.amount}} + + + +
+ + + + + + + + + + + + + +
TypeTotal
{{type}}{{total + item.amout * 1}}
+ +
+
+
+ + \ No newline at end of file diff --git a/client/demo/ex/assignment2/app.js b/client/demo/ex/assignment2/app.js new file mode 100644 index 0000000..954b27e --- /dev/null +++ b/client/demo/ex/assignment2/app.js @@ -0,0 +1,2 @@ +angular + .module('expensesApp', []); \ No newline at end of file diff --git a/client/demo/ex/assignment2/expensesController.js b/client/demo/ex/assignment2/expensesController.js new file mode 100644 index 0000000..b474c08 --- /dev/null +++ b/client/demo/ex/assignment2/expensesController.js @@ -0,0 +1,101 @@ +angular + .module('expensesApp') + .controller('ExpenseController', ExpenseController); + + +ExpenseController.$inject = ['$filter']; + +function ExpenseController($filter){ + vm = this; + + vm.expenses = []; + vm.expense = {}; + vm.types = ['food', 'transportation', 'lodging', 'financial', 'sales', 'other.']; + vm.isEditing = false; + + vm.total = 0; + + vm.newExpense = function(){ + vm.expense.id = vm.expenses.length + 1; + vm.expenses.push(vm.expense); + //console.debug(vm.expense); + vm.expense = {}; + }; + + vm.delete = function(exp){ + vm.expenses.splice(vm.expenses.indexOf(exp),1); + }; + + vm.edit = function(exp){ + vm.expense = angular.copy(exp); + vm.isEditing = true; + }; + + vm.update = function(exp){ + var selectedExpense = $filter('filter')(vm.expenses, {id: exp.id})[0]; + selectedExpense.date = exp.date; + selectedExpense.type = exp.type; + selectedExpense.description = exp.description; + selectedExpense.amount = exp.amount; + + vm.isEditing = false; + vm.expense = {}; + }; + + vm.cancel = function(){ + vm.expense = {}; + vm.isEditing = false; + }; + + vm.getTotal = getTotal; + vm.getTotalByType = getTotalByType; + vm.setColor = setColor; + + function getTotal(){ + var totals = 0; + angular.forEach(vm.expenses, function(key, value){ + totals += key.amount; + }); + return totals; + } + + function getTotalByType(type){ + var totals = 0; + angular.forEach(vm.expenses, function(key, value){ + if (key.type == type){ + totals += key.amount; + } + }); + return totals; + } + + function setColor(type){ + console.log(type); + switch (type){ + case 'food': + return { 'background-color': "lightblue" }; + case 'transportation': + return { 'background-color': "lightcoral" }; + case 'lodging': + return { 'background-color': "lightgray" }; + case 'financial': + return { 'background-color': "lightgreen" }; + case 'sales': + return { 'background-color': "lightskyblue" }; + case 'other.': + return { 'background-color': "lightsalmon" }; + } + } +} + + + + + + + + + + + + diff --git a/client/demo/ex/assignment2/expensesController.spec.js b/client/demo/ex/assignment2/expensesController.spec.js new file mode 100644 index 0000000..539eaf8 --- /dev/null +++ b/client/demo/ex/assignment2/expensesController.spec.js @@ -0,0 +1,44 @@ +describe('Controller: expensesController', function () { + 'use strict'; + var controller, + scope; + // Refresh the $filter every time. + beforeEach(module('expensesApp')); + beforeEach(inject(function (_$rootScope_, $controller) { + scope = _$rootScope_.$new(); + controller = $controller('ExpenseController', + {$scope: scope}); + }) + ); + + it('should start empty', function () { + expect(controller.expenses.length).to.equal(0); + }); + + it('should add/remove items', function () { + //Create + //First expense + controller.expense.date = '09/06/1988'; + controller.expense.type = 'transportation'; + controller.expense.description = 'Testing Expense'; + controller.expense.amount = 1000; + controller.newExpense(); + + expect(controller.expenses.length).to.equal(1); + + //Second expense + controller.expense.date = '01/01/2015'; + controller.expense.type = 'food'; + controller.expense.description = 'Testing Expense 2'; + controller.expense.amount = 10000; + + controller.newExpense(); + + expect(controller.expenses.length).to.equal(2); + + //Delete: + controller.delete(controller.expense); + expect(controller.expenses.length).to.equal(1); + }); + +}); diff --git a/client/demo/ex/assignment2/index.html b/client/demo/ex/assignment2/index.html new file mode 100644 index 0000000..7a49fc6 --- /dev/null +++ b/client/demo/ex/assignment2/index.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + + Expense App Assignment2 + + +
+

Expenses

+
+
+

Create Expense

+
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
DateTypeDescriptionAmount
{{ expen.date | date: 'MM/dd/yy'}}{{ expen.type }}{{ expen.description }}{{ expen.amount }} + + +
+
+
+
+
+ Totals by Type +
+
+
+ + + + + + + + + + + +
TypeTotal
{{ type }}{{ exp.getTotalByType(type) }}
+
+
+
+
+
+
+
+ Total All Types +
+
+
+

Total: {{ exp.getTotal() }}

+
+
+
+
+
+
+ + diff --git a/client/index.html b/client/index.html index 2f82e12..e20b97c 100644 --- a/client/index.html +++ b/client/index.html @@ -75,6 +75,7 @@ + diff --git a/e2e/ex/main.spec.js b/e2e/ex/main.spec.js new file mode 100644 index 0000000..a3715cf --- /dev/null +++ b/e2e/ex/main.spec.js @@ -0,0 +1,76 @@ +'use strict'; + +describe('Expenses app', function () { + var page; + beforeEach(function () { + browser.get('/demo/ex/assignment2/'); + page = {}; + }); + + it('should include H1 title', function () { + expect(element(by.tagName('h1')).getText()).to.eventually.equal('Expenses'); + }); + + it('should add/edit/delete an item from/to the table', function () { + page.date = element(by.model('exp.expense.date')); + page.date.sendKeys('09/06/1988'); + + page.type = element(by.cssContainingText('option', 'transportation')).click(); + page.description = element(by.model('exp.expense.description')).sendKeys('Testing Expense'); + page.amount = element(by.model('exp.expense.amount')).sendKeys('1000'); + + page.button = element(by.id('create-button')); + page.button.click(); + + //Quantity + var items = element.all(by.repeater('expen in exp.expenses track by expen.id')); + expect(items.count()).to.eventually.equal(1); + + //Check content + element(by.css('.table.items')).all(by.css('tbody tr')).then(function (rows) { + return rows[0].$$('td').then(function (cols) { + expect(cols[0].getText()).to.eventually.equal('09/06/88'); + expect(cols[1].getText()).to.eventually.equal('transportation'); + expect(cols[2].getText()).to.eventually.equal('Testing Expense'); + expect(cols[3].getText()).to.eventually.equal('1000'); + }); + }); + + //Check if fields were cleaned + expect(page.date.getAttribute('value')).to.eventually.equal(''); + expect(page.description.getAttribute('value')).to.eventually.equal(''); + expect(page.amount.getAttribute('value')).to.eventually.equal(''); + + //Edit + var items = element.all(by.repeater('expen in exp.expenses track by expen.id')); + items.first().then(function () { + page.button = element(by.css('.edit-expense')); + page.button.click(); + }); + + page.date = element(by.model('exp.expense.date')); + page.date.sendKeys('01/01/2015'); + + page.button = element(by.id('update-button')); + page.button.click(); + + element(by.css('.table.items')).all(by.css('tbody tr')).then(function (rows) { + return rows[0].$$('td').then(function (cols) { + expect(cols[0].getText()).to.eventually.equal('01/01/15'); + expect(cols[1].getText()).to.eventually.equal('transportation'); + expect(cols[2].getText()).to.eventually.equal('Testing Expense'); + expect(cols[3].getText()).to.eventually.equal('1000'); + }); + }); + + //Delete + var items = element.all(by.repeater('expen in exp.expenses track by expen.id')); + items.first().then(function () { + page.button = element(by.css('.delete-expense')); + page.button.click(); + }); + + expect(element.all(by.repeater('expen in exp.expenses track by expen.id')).count()).to.eventually.equal(0); + }); + +});