mirror of
https://github.com/Febbweiss/CloudBudget-AngularJS.git
synced 2026-03-04 22:35:38 +00:00
Feature: get user's accounts
This commit is contained in:
@@ -7,7 +7,8 @@
|
|||||||
"angular-route": "~1.4.1",
|
"angular-route": "~1.4.1",
|
||||||
"animate.css": "~3.3.0",
|
"animate.css": "~3.3.0",
|
||||||
"bootstrap": "~3.3.5",
|
"bootstrap": "~3.3.5",
|
||||||
"font-awesome": "~4.4.0"
|
"font-awesome": "~4.4.0",
|
||||||
|
"angular-xeditable": "~0.1.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-mocks": "~1.4.4"
|
"angular-mocks": "~1.4.4"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ module.exports = function(config) {
|
|||||||
'public/libs/angular/angular.js',
|
'public/libs/angular/angular.js',
|
||||||
'public/libs/angular-route/angular-route.js',
|
'public/libs/angular-route/angular-route.js',
|
||||||
'public/libs/angular-cookies/angular-cookies.js',
|
'public/libs/angular-cookies/angular-cookies.js',
|
||||||
|
'public/libs/angular-xeditable/dist/js/xeditable.min.js',
|
||||||
'public/libs/angular-mocks/angular-mocks.js',
|
'public/libs/angular-mocks/angular-mocks.js',
|
||||||
'public/js/**/*.js',
|
'public/js/**/*.js',
|
||||||
'public/**/*.controller.js',
|
'public/**/*.controller.js',
|
||||||
|
|||||||
83
public/accounts/accounts.controller.js
Normal file
83
public/accounts/accounts.controller.js
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
(function(){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('cloudbudget')
|
||||||
|
.controller('AccountsController', AccountsController);
|
||||||
|
|
||||||
|
AccountsController.$inject = ['$scope', '$location', '$rootScope', 'FlashService', 'AccountsService'];
|
||||||
|
|
||||||
|
function AccountsController($scope, $location, $rootScope, FlashService, AccountsService) {
|
||||||
|
var vm = this;
|
||||||
|
|
||||||
|
vm.dataLoading = false;
|
||||||
|
vm.accounts = [];
|
||||||
|
vm.create = create;
|
||||||
|
vm.drop = drop;
|
||||||
|
vm.edit = edit;
|
||||||
|
vm.consult = consult;
|
||||||
|
|
||||||
|
(function init() {
|
||||||
|
vm.dataLoading = true;
|
||||||
|
AccountsService.list()
|
||||||
|
.then(function(response) {
|
||||||
|
if( response.success ) {
|
||||||
|
vm.accounts = response.accounts;
|
||||||
|
} else {
|
||||||
|
FlashService.error(response.message);
|
||||||
|
}
|
||||||
|
vm.dataLoading = false;
|
||||||
|
})
|
||||||
|
})();
|
||||||
|
|
||||||
|
function create() {
|
||||||
|
vm.dataLoading = true;
|
||||||
|
AccountsService.create(vm.account)
|
||||||
|
.then( function(response) {
|
||||||
|
if( response.success) {
|
||||||
|
vm.accounts.push(response.account);
|
||||||
|
} else {
|
||||||
|
FlashService.error(response.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.dataLoading = false;
|
||||||
|
});
|
||||||
|
vm.account = angular.copy({});
|
||||||
|
$scope.form.$setPristine();
|
||||||
|
};
|
||||||
|
|
||||||
|
function drop(account) {
|
||||||
|
vm.dataLoading = true;
|
||||||
|
AccountsService.drop(account)
|
||||||
|
.then(function(response) {
|
||||||
|
if( response.success ) {
|
||||||
|
var index = vm.accounts.indexOf(account);
|
||||||
|
vm.accounts.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
FlashService.error( response.message );
|
||||||
|
}
|
||||||
|
vm.dataLoading = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function edit(altered, origin) {
|
||||||
|
vm.dataLoading = true;
|
||||||
|
return AccountsService.edit(origin._id, altered)
|
||||||
|
.then( function(response) {
|
||||||
|
if( response.success ) {
|
||||||
|
var index = vm.accounts.map(function (item) {
|
||||||
|
return item._id;
|
||||||
|
}).indexOf(origin._id);
|
||||||
|
vm.accounts[index] = response.account;
|
||||||
|
} else {
|
||||||
|
FlashService.error( response.message );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
function consult(account) {
|
||||||
|
$location.path('/account/' + account._id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})();
|
||||||
49
public/accounts/accounts.view.html
Normal file
49
public/accounts/accounts.view.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<form name="form" ng-submit="vm.create()" role="form">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<input name="reference" id="reference" class="form-control" placeholder="Reference" ng-model="vm.account.reference" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div class="form-group" ng-class="{'has-error': form.name.$dirty && form.name.$error.required}">
|
||||||
|
<input name="name" id="name" class="form-control" ng-model="vm.account.name" placeholder="name" required/>
|
||||||
|
<span ng-show="form.name.$dirty && form.name.$error.required" class="help-block">name is required</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<button type="submit" class="btn btn-primary" ng-disabled="form.$invalid || vm.dataLoading">
|
||||||
|
<i class="fa fa-fw fa-floppy-o"></i>
|
||||||
|
</button>
|
||||||
|
<img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row" ng-repeat="account in vm.accounts">
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<span e-form="rowform" e-name="reference" editable-text="account.reference">{{account.reference}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4"><span e-form="rowform" e-name="name" editable-text="account.name" e-required>{{account.name}}</span></div>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<form editable-form name="rowform" onbeforesave="vm.edit($data, account)" ng-show="rowform.$visible" xclass="form-buttons form-inline" shown="inserted == account">
|
||||||
|
<button type="submit" ng-disabled="rowForm.$invalid || rowform.$waiting" title="Edit" class="btn btn-success">
|
||||||
|
<i class="fa fa-fw fa-floppy-o"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" ng-disabled="rowform.$waiting" title="Cancel" ng-click="rowform.$cancel()" class="btn btn-default">
|
||||||
|
<i class="fa fa-fw fa-ban"></i>
|
||||||
|
</button>
|
||||||
|
<a class="btn btn-danger" title="Delete" ng-disabled="rowForm.$waiting" ng-click="vm.drop(account)">
|
||||||
|
<i class="fa fa-fw fa-trash"></i>
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
<a class="btn btn-success" ng-click="rowform.$show()" ng-show="!rowform.$visible">
|
||||||
|
<i class="fa fa-fw fa-pencil"></i>
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-primary" ng-click="vm.consult(account)" ng-show="!rowform.$visible">
|
||||||
|
<i class="fa fa-fw fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
<base href="/" />
|
<base href="/" />
|
||||||
|
|
||||||
<title>CloudBudget</title>
|
<title>CloudBudget</title>
|
||||||
<link rel="stylesheet" href="/libs/bootstrap/dist/css/bootstrap.min.css" />
|
<link rel="stylesheet" href="/libs/bootstrap/dist/css/bootstrap.min.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css" type="text/css"/>
|
||||||
|
<link rel="stylesheet" href="/libs/angular-xeditable/dist/css/xeditable.css" type="text/css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -19,14 +21,9 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<div class="jumbotron">
|
|
||||||
<div class="container">
|
<div ng-class="{ 'alert': flash, 'alert-success' : flash.type === 'success', 'alert-danger': flash.type === 'error'}" ng-if="flash" ng-bind="flash.message"></div>
|
||||||
<div class="col-sm-8 col-sm-offset-2">
|
<div ng-view></div>
|
||||||
<div ng-class="{ 'alert': flash, 'alert-success' : flash.type === 'success', 'alert-danger': flash.type === 'error'}" ng-if="flash" ng-bind="flash.message"></div>
|
|
||||||
<div ng-view></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="credits text-center">
|
<div class="credits text-center">
|
||||||
<p>
|
<p>
|
||||||
@@ -37,18 +34,21 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/libs/angular/angular.js" ></script>
|
<script type="text/javascript" src="/libs/angular/angular.js" ></script>
|
||||||
<script src="/libs/angular-route/angular-route.min.js"></script>
|
<script type="text/javascript" src="/libs/angular-route/angular-route.min.js"></script>
|
||||||
<script src="/libs/angular-cookies/angular-cookies.min.js"></script>
|
<script type="text/javascript" src="/libs/angular-cookies/angular-cookies.min.js"></script>
|
||||||
|
<script type="text/javascript" src="/libs/angular-xeditable/dist/js/xeditable.min.js"></script>
|
||||||
|
|
||||||
<script src="/js/app.js"></script>
|
<script type="text/javascript" src="/js/app.js"></script>
|
||||||
<script src="/js/routes.js"></script>
|
<script type="text/javascript" src="/js/routes.js"></script>
|
||||||
<script src="/js/services/authentication.service.js"></script>
|
<script type="text/javascript" src="/js/services/authentication.service.js"></script>
|
||||||
<script src="/js/services/flash.service.js"></script>
|
<script type="text/javascript" src="/js/services/flash.service.js"></script>
|
||||||
<script src="/js/services/user.service.js"></script>
|
<script type="text/javascript" src="/js/services/user.service.js"></script>
|
||||||
|
<script type="text/javascript" src="/js/services/accounts.service.js"></script>
|
||||||
|
|
||||||
<script src="/home/home.controller.js"></script>
|
<script type="text/javascript" src="/home/home.controller.js"></script>
|
||||||
<script src="/login/login.controller.js"></script>
|
<script type="text/javascript" src="/login/login.controller.js"></script>
|
||||||
<script src="/register/register.controller.js"></script>
|
<script type="text/javascript" src="/register/register.controller.js"></script>
|
||||||
|
<script type="text/javascript" src="/accounts/accounts.controller.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,21 +1,27 @@
|
|||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var HOST = 'http://cloudbudget.pavnay.fr/api';
|
var HOST = 'http://cloudbudget-febbweiss.c9.io/api';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
.module('cloudbudget', ['ngRoute', 'routes', 'ngCookies'])
|
.module('cloudbudget', ['ngRoute', 'routes', 'ngCookies', 'xeditable'])
|
||||||
.constant('apiRoutes', {
|
.constant('apiRoutes', {
|
||||||
'host': HOST,
|
'host' : HOST,
|
||||||
'port': "80",
|
'port' : "80",
|
||||||
'login': HOST + '/users/login',
|
'login' : HOST + '/users/login',
|
||||||
'register': HOST + '/users',
|
'register' : HOST + '/users',
|
||||||
'unregister': HOST + '/users/'
|
'unregister' : HOST + '/users/',
|
||||||
|
'accounts' : HOST + '/accounts/'
|
||||||
})
|
})
|
||||||
.run(run);
|
.run(run);
|
||||||
|
|
||||||
run.$inject = ['$rootScope', '$location', '$cookieStore', '$http', '$filter'];
|
run.$inject = ['$rootScope', '$location', '$cookieStore', '$http', '$filter', 'editableThemes', 'editableOptions'];
|
||||||
function run( $rootScope, $location, $cookieStore, $http, $filter) {
|
function run( $rootScope, $location, $cookieStore, $http, $filter, editableThemes, editableOptions) {
|
||||||
|
|
||||||
|
editableThemes.bs3.inputClass = 'input-sm';
|
||||||
|
editableThemes.bs3.buttonsClass = 'btn-sm';
|
||||||
|
editableOptions.theme = 'bs3';
|
||||||
|
|
||||||
$rootScope.globals = $cookieStore.get('globals') || {};
|
$rootScope.globals = $cookieStore.get('globals') || {};
|
||||||
if( $rootScope.globals.user && $rootScope.globals.user.token) {
|
if( $rootScope.globals.user && $rootScope.globals.user.token) {
|
||||||
$http.defaults.headers.common['Authorization'] = 'JWT ' + $rootScope.globals.user.token;
|
$http.defaults.headers.common['Authorization'] = 'JWT ' + $rootScope.globals.user.token;
|
||||||
|
|||||||
@@ -27,6 +27,12 @@
|
|||||||
controllerAs: 'vm'
|
controllerAs: 'vm'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.when('/accounts', {
|
||||||
|
controller: 'AccountsController',
|
||||||
|
templateUrl: 'accounts/accounts.view.html',
|
||||||
|
controllerAs: 'vm'
|
||||||
|
})
|
||||||
|
|
||||||
.otherwise({redirectTo: '/login'});
|
.otherwise({redirectTo: '/login'});
|
||||||
|
|
||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
|
|||||||
52
public/js/services/accounts.service.js
Normal file
52
public/js/services/accounts.service.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('cloudbudget')
|
||||||
|
.factory('AccountsService', AccountsService);
|
||||||
|
|
||||||
|
AccountsService.$inject =['$http', 'apiRoutes'];
|
||||||
|
|
||||||
|
function AccountsService($http, apiRoute) {
|
||||||
|
|
||||||
|
var service = {};
|
||||||
|
service.list = list;
|
||||||
|
service.create = create;
|
||||||
|
service.drop = drop;
|
||||||
|
service.edit = edit;
|
||||||
|
|
||||||
|
return service;
|
||||||
|
|
||||||
|
function list() {
|
||||||
|
return $http.get( apiRoute.accounts)
|
||||||
|
.then(function handleSuccess(response) {
|
||||||
|
return {success: true, accounts: response.data};
|
||||||
|
}, handleError('Error during accounts listing'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function create(account) {
|
||||||
|
return $http.post( apiRoute.accounts, account)
|
||||||
|
.then(handleSuccess, handleError('Error creating account'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function drop(account) {
|
||||||
|
return $http.delete(apiRoute.accounts + account._id)
|
||||||
|
.then(handleSuccess, handleError('Error deleting account'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function edit(id, account) {
|
||||||
|
return $http.put(apiRoute.accounts + id, account)
|
||||||
|
.then(handleSuccess, handleError('Error updating account'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSuccess(response) {
|
||||||
|
return {success: true, account: response.data};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(error) {
|
||||||
|
return function() {
|
||||||
|
return {success: false, message: error};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
$http.defaults.headers.common['Authorization'] = 'JWT ' + user.token;
|
$http.defaults.headers.common['Authorization'] = 'JWT ' + user.token;
|
||||||
$cookieStore.put('globals', $rootScope.globals);
|
$cookieStore.put('globals', $rootScope.globals);
|
||||||
console.log( $cookieStore.get('globals'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearCredentials() {
|
function clearCredentials() {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
AuthenticationService.login(vm.username, vm.password).then( function(response) {
|
AuthenticationService.login(vm.username, vm.password).then( function(response) {
|
||||||
if( response.success ) {
|
if( response.success ) {
|
||||||
AuthenticationService.setCredentials(response.user);
|
AuthenticationService.setCredentials(response.user);
|
||||||
$location.path('/');
|
$location.path('/accounts');
|
||||||
} else {
|
} else {
|
||||||
FlashService.error(response.message);
|
FlashService.error(response.message);
|
||||||
vm.dataLoading = false;
|
vm.dataLoading = false;
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="jumbotron">
|
||||||
<h2>Login</h2>
|
<div class="container">
|
||||||
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
|
<div class="col-sm-8 col-sm-offset-2">
|
||||||
<form name="form" ng-submit="vm.login()" role="form">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<div class="form-group" ng-class="{'has-error': form.username.$dirty && form.username.$error.required}">
|
<h2>Login</h2>
|
||||||
<label for="username">Username</label>
|
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
|
||||||
<input type="text" name="username" id="username" class="form-control" ng-model="vm.username" required />
|
<form name="form" ng-submit="vm.login()" role="form">
|
||||||
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
|
<div class="form-group" ng-class="{'has-error': form.username.$dirty && form.username.$error.required}">
|
||||||
</div>
|
<label for="username">Username</label>
|
||||||
<div class="form-group" ng-class="{'has-error': form.password.$dirty && form.password.$error.required}">
|
<input type="text" name="username" id="username" class="form-control" ng-model="vm.username" required />
|
||||||
<label for="password">Password</label>
|
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
|
||||||
<input type="password" name="password" id="password" class="form-control" ng-model="vm.password" required />
|
</div>
|
||||||
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
|
<div class="form-group" ng-class="{'has-error': form.password.$dirty && form.password.$error.required}">
|
||||||
</div>
|
<label for="password">Password</label>
|
||||||
<div class="form-actions">
|
<input type="password" name="password" id="password" class="form-control" ng-model="vm.password" required />
|
||||||
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Login</button>
|
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
|
||||||
<i ng-if="vm.dataLoading" class="fa fa-spinner fa-spin"></i>
|
</div>
|
||||||
<a href="/register" class="btn btn-link">Register</a>
|
<div class="form-actions">
|
||||||
|
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Login</button>
|
||||||
|
<i ng-if="vm.dataLoading" class="fa fa-spinner fa-spin"></i>
|
||||||
|
<a href="/register" class="btn btn-link">Register</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
if( response.success ) {
|
if( response.success ) {
|
||||||
AuthenticationService.setCredentials(response.user);
|
AuthenticationService.setCredentials(response.user);
|
||||||
FlashService.success('Registration successful', true);
|
FlashService.success('Registration successful', true);
|
||||||
$location.path('/');
|
$location.path('/accounts');
|
||||||
} else {
|
} else {
|
||||||
FlashService.error(response.message);
|
FlashService.error(response.message);
|
||||||
vm.dataLoading = false;
|
vm.dataLoading = false;
|
||||||
|
|||||||
@@ -1,29 +1,35 @@
|
|||||||
<div class="col-md-6 col-md-offset-3">
|
<div class="jumbotron">
|
||||||
<h2>Register</h2>
|
<div class="container">
|
||||||
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
|
<div class="col-sm-8 col-sm-offset-2">
|
||||||
<form name="form" ng-submit="vm.register()" role="form">
|
<div class="col-md-6 col-md-offset-3">
|
||||||
<div class="form-group" ng-class="{'has-error': form.username.$dirty && form.username.$error.required}">
|
<h2>Register</h2>
|
||||||
<label for="username">Username</label>
|
<div ng-show="vm.error" class="alert alert-danger">{{vm.error}}</div>
|
||||||
<input type="text" name="username" id="username" class="form-control" ng-model="vm.user.username" required />
|
<form name="form" ng-submit="vm.register()" role="form">
|
||||||
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
|
<div class="form-group" ng-class="{'has-error': form.username.$dirty && form.username.$error.required}">
|
||||||
</div>
|
<label for="username">Username</label>
|
||||||
<div class="form-group" ng-class="{'has-error': form.password.$dirty && form.password.$error.required}">
|
<input type="text" name="username" id="username" class="form-control" ng-model="vm.user.username" required />
|
||||||
<label for="password">Password</label>
|
<span ng-show="form.username.$dirty && form.username.$error.required" class="help-block">Username is required</span>
|
||||||
<input type="password" name="password" id="password" class="form-control" ng-model="vm.user.password" required />
|
</div>
|
||||||
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
|
<div class="form-group" ng-class="{'has-error': form.password.$dirty && form.password.$error.required}">
|
||||||
</div>
|
<label for="password">Password</label>
|
||||||
<div class="form-group" ng-class="{'has-error': form.language.$dirty && form.language.$error.required}">
|
<input type="password" name="password" id="password" class="form-control" ng-model="vm.user.password" required />
|
||||||
<label for="language">Language</label>
|
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
|
||||||
<select id="language" name="language" ng-model="vm.user.language" required>
|
</div>
|
||||||
<option value="en">English</option>
|
<div class="form-group" ng-class="{'has-error': form.language.$dirty && form.language.$error.required}">
|
||||||
<option value="fr">Français</option>
|
<label for="language">Language</label>
|
||||||
</select>
|
<select id="language" name="language" class="form-control" ng-model="vm.user.language" required>
|
||||||
<span ng-show="form.language.$dirty && form.language.$error.required" class="help-block">Language is required</span>
|
<option value="en">English</option>
|
||||||
|
<option value="fr">Français</option>
|
||||||
|
</select>
|
||||||
|
<span ng-show="form.language.$dirty && form.language.$error.required" class="help-block">Language is required</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Register</button>
|
||||||
|
<img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
|
||||||
|
<a href="/login" class="btn btn-link">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-actions">
|
</div>
|
||||||
<button type="submit" ng-disabled="form.$invalid || vm.dataLoading" class="btn btn-primary">Register</button>
|
|
||||||
<img ng-if="vm.dataLoading" src="data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" />
|
|
||||||
<a href="/login" class="btn btn-link">Cancel</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
@@ -10,7 +10,8 @@ router.get('*', function(req, res, next) {
|
|||||||
var dotIndex = req.path.lastIndexOf('.'),
|
var dotIndex = req.path.lastIndexOf('.'),
|
||||||
extension = dotIndex === - 1 ? '' : req.path.substr(dotIndex);
|
extension = dotIndex === - 1 ? '' : req.path.substr(dotIndex);
|
||||||
|
|
||||||
if( ['.js','.css','.html'].indexOf(extension) > -1 ) {
|
if( ['.js','.css','.html',
|
||||||
|
'.woff', '.woff2', '.ttf', '.svg', '.eot', '.otf'].indexOf(extension) > -1 ) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
res.sendfile('./public/index.html');
|
res.sendfile('./public/index.html');
|
||||||
|
|||||||
184
test/accounts.controller.spec.js
Normal file
184
test/accounts.controller.spec.js
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
describe('AccountsController', function() {
|
||||||
|
|
||||||
|
var $location,
|
||||||
|
$rootScope,
|
||||||
|
$scope,
|
||||||
|
$timeout,
|
||||||
|
$httpBackend,
|
||||||
|
AccountsService,
|
||||||
|
FlashService,
|
||||||
|
createController,
|
||||||
|
apiRoutes,
|
||||||
|
shouldPass,
|
||||||
|
DEFAULT_ACCOUNT = {
|
||||||
|
"name": "test",
|
||||||
|
"reference": "1234567890",
|
||||||
|
"user_id": "55b78934d2a706265ea28e9c",
|
||||||
|
"_id": "560aa0e79633cd7c1495ff21"
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(module('cloudbudget'));
|
||||||
|
|
||||||
|
beforeEach(inject(function ( _$rootScope_, _$httpBackend_, $controller, _$location_, _$timeout_, _AccountsService_, _FlashService_, _apiRoutes_) {
|
||||||
|
$location = _$location_;
|
||||||
|
$httpBackend = $httpBackend;
|
||||||
|
$rootScope = _$rootScope_.$new();
|
||||||
|
$scope = _$rootScope_.$new();
|
||||||
|
$scope.form = {
|
||||||
|
$valid: true,
|
||||||
|
$setPristine: function() {}
|
||||||
|
};
|
||||||
|
$timeout = _$timeout_;
|
||||||
|
AccountsService = _AccountsService_;
|
||||||
|
FlashService = _FlashService_;
|
||||||
|
apiRoutes = _apiRoutes_;
|
||||||
|
|
||||||
|
createController = function() {
|
||||||
|
return $controller('AccountsController', {
|
||||||
|
'$scope': $scope,
|
||||||
|
'$location': $location,
|
||||||
|
'$rootScope': $rootScope,
|
||||||
|
FlashService: _FlashService_,
|
||||||
|
AccountsService: _AccountsService_,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('init()', function() {
|
||||||
|
it('should create successfully', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([DEFAULT_ACCOUNT]);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(1);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('* create()', function() {
|
||||||
|
it('should create successfully', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([]);
|
||||||
|
|
||||||
|
$httpBackend.expect('POST', apiRoutes.accounts)
|
||||||
|
.respond(DEFAULT_ACCOUNT);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.account = {
|
||||||
|
name: 'test',
|
||||||
|
reference: '1234567890'
|
||||||
|
};
|
||||||
|
|
||||||
|
accountsController.create();
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
var account = accountsController.accounts[0];
|
||||||
|
account.name.should.be.equal('test');
|
||||||
|
account.reference.should.be.equal('1234567890');
|
||||||
|
should.exist(account._id);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fail to create account', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([]);
|
||||||
|
|
||||||
|
$httpBackend.expect('POST', apiRoutes.accounts)
|
||||||
|
.respond(400, [{"field":"name","rule":"required","message":"Path `name` is required."}]);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.account = {
|
||||||
|
reference: '1234567890'
|
||||||
|
};
|
||||||
|
|
||||||
|
accountsController.create();
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(0);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('* delete()', function() {
|
||||||
|
it('should delete successfully', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([DEFAULT_ACCOUNT]);
|
||||||
|
|
||||||
|
$httpBackend.expect('DELETE', apiRoutes.accounts + '560aa0e79633cd7c1495ff21')
|
||||||
|
.respond(204);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.drop({_id: '560aa0e79633cd7c1495ff21'});
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fail to delete unknown account', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([DEFAULT_ACCOUNT]);
|
||||||
|
|
||||||
|
$httpBackend.expect('DELETE', apiRoutes.accounts + 'fake_id')
|
||||||
|
.respond(404);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.drop({_id: 'fake_id'});
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(1);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('* edit()', function() {
|
||||||
|
it('should edit successfully', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([DEFAULT_ACCOUNT]);
|
||||||
|
|
||||||
|
$httpBackend.expect('PUT', apiRoutes.accounts + '560aa0e79633cd7c1495ff21')
|
||||||
|
.respond(200, {
|
||||||
|
"name": "test updated",
|
||||||
|
"reference": "1234567890",
|
||||||
|
"user_id": "55b78934d2a706265ea28e9c",
|
||||||
|
"_id": "560aa0e79633cd7c1495ff21"
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.edit({ name:"test updated"}, DEFAULT_ACCOUNT);
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(1);
|
||||||
|
var account = accountsController.accounts[0];
|
||||||
|
account.name.should.be.equal('test updated');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should fail to edit unknown account', inject(function($controller, $httpBackend) {
|
||||||
|
$httpBackend.expect('GET', apiRoutes.accounts)
|
||||||
|
.respond([DEFAULT_ACCOUNT]);
|
||||||
|
|
||||||
|
$httpBackend.expect('PUT', apiRoutes.accounts + 'fake_id')
|
||||||
|
.respond(404);
|
||||||
|
|
||||||
|
|
||||||
|
var accountsController = createController();
|
||||||
|
accountsController.edit({name:"test updated"}, {_id: 'fake_id'});
|
||||||
|
$httpBackend.flush();
|
||||||
|
$timeout.flush();
|
||||||
|
|
||||||
|
accountsController.accounts.should.be.instanceof(Array).and.have.lengthOf(1);
|
||||||
|
var account = accountsController.accounts[0];
|
||||||
|
account.name.should.be.equal('test');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -78,7 +78,7 @@ describe('LoginController', function() {
|
|||||||
loginController.login();
|
loginController.login();
|
||||||
$timeout.flush();
|
$timeout.flush();
|
||||||
|
|
||||||
$location.path().should.be.equal('/');
|
$location.path().should.be.equal('/accounts');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fail to log', inject(function($controller, $location) {
|
it('should fail to log', inject(function($controller, $location) {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ describe('RegisterController', function() {
|
|||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
$timeout.flush();
|
$timeout.flush();
|
||||||
|
|
||||||
$location.path().should.be.equal('/');
|
$location.path().should.be.equal('/accounts');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fail to register on bad parameter', inject(function($controller, $httpBackend, $location) {
|
it('should fail to register on bad parameter', inject(function($controller, $httpBackend, $location) {
|
||||||
|
|||||||
Reference in New Issue
Block a user