Skip to content
This repository was archived by the owner on Aug 25, 2018. It is now read-only.

Commit d21939d

Browse files
committed
Fixes #61 - upgrade to recommended angular project structure
1 parent 2db3f70 commit d21939d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+587
-1002
lines changed

README.md

+1-6
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,8 @@ Now browse to the app at `http://localhost:8000/app/index.html`.
8989
js/ --> javascript files
9090
app.js --> application
9191
config.js --> where you configure Firebase and auth options
92-
controllers.js --> application controllers
93-
directives.js --> application directives
94-
decorators.js --> decorator functions
95-
filters.js --> custom angular filters
9692
firebase.utils.js --> some DRY methods for interacting with Firebase and AngularFire
97-
routes.js --> routing and route security for the app
98-
services.js --> custom angular services
93+
security.js --> routing and route security for the app
9994
auth.js --> some DRY methods for interacting with Firebase authentication
10095
partials/ --> angular view partials (partial html templates)
10196
account.html
File renamed without changes.

app/account/account.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
(function (angular) {
2+
"use strict";
3+
4+
var app = angular.module('myApp.account', ['firebase', 'firebase.utils', 'firebase.auth', 'ngRoute']);
5+
6+
app.controller('AccountCtrl', ['$scope', 'Auth', 'fbutil', 'user', '$location', '$firebaseObject',
7+
function($scope, Auth, fbutil, user, $location, $firebaseObject) {
8+
var unbind;
9+
// create a 3-way binding with the user profile object in Firebase
10+
var profile = $firebaseObject(fbutil.ref('users', user.uid));
11+
profile.$bindTo($scope, 'profile').then(function(ub) { unbind = ub; });
12+
13+
// expose logout function to scope
14+
$scope.logout = function() {
15+
if( unbind ) { unbind(); }
16+
profile.$destroy();
17+
Auth.$unauth();
18+
$location.path('/login');
19+
};
20+
21+
$scope.changePassword = function(pass, confirm, newPass) {
22+
resetMessages();
23+
if( !pass || !confirm || !newPass ) {
24+
$scope.err = 'Please fill in all password fields';
25+
}
26+
else if( newPass !== confirm ) {
27+
$scope.err = 'New pass and confirm do not match';
28+
}
29+
else {
30+
Auth.$changePassword({email: profile.email, oldPassword: pass, newPassword: newPass})
31+
.then(function() {
32+
$scope.msg = 'Password changed';
33+
}, function(err) {
34+
$scope.err = err;
35+
})
36+
}
37+
};
38+
39+
$scope.clear = resetMessages;
40+
41+
$scope.changeEmail = function(pass, newEmail) {
42+
resetMessages();
43+
var oldEmail = profile.email;
44+
Auth.$changeEmail({oldEmail: oldEmail, newEmail: newEmail, password: pass})
45+
.then(function() {
46+
// store the new email address in the user's profile
47+
return fbutil.handler(function(done) {
48+
fbutil.ref('users', user.uid, 'email').set(newEmail, done);
49+
});
50+
})
51+
.then(function() {
52+
$scope.emailmsg = 'Email changed';
53+
}, function(err) {
54+
$scope.emailerr = err;
55+
});
56+
};
57+
58+
function resetMessages() {
59+
$scope.err = null;
60+
$scope.msg = null;
61+
$scope.emailerr = null;
62+
$scope.emailmsg = null;
63+
}
64+
}
65+
]);
66+
67+
app.config(['$routeProvider', function($routeProvider) {
68+
// require user to be authenticated before they can access this page
69+
// this is handled by the .whenAuthenticated method declared in
70+
// components/router/router.js
71+
$routeProvider.whenAuthenticated('/account', {
72+
templateUrl: 'account/account.html',
73+
controller: 'AccountCtrl'
74+
})
75+
}]);
76+
77+
})(angular);

app/account/account_test.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
describe('myApp.account', function() {
3+
beforeEach(function() {
4+
module('myApp');
5+
module('myApp.account');
6+
});
7+
8+
describe('AccountCtrl', function() {
9+
var accountCtrl, $scope;
10+
beforeEach(function() {
11+
module(function($provide) {
12+
// comes from routes.js in the resolve: {} attribute
13+
$provide.value('user', {uid: 'test123'});
14+
});
15+
16+
inject(function($controller) {
17+
$scope = {};
18+
accountCtrl = $controller('AccountCtrl', {$scope: $scope});
19+
});
20+
});
21+
22+
it('should define logout method', function() {
23+
expect(typeof $scope.logout).toBe('function');
24+
});
25+
26+
it('should define changePassword method', function() {
27+
expect(typeof $scope.changePassword).toBe('function');
28+
});
29+
30+
it('should define changeEmail method', function() {
31+
expect(typeof $scope.changeEmail).toBe('function');
32+
});
33+
34+
it('should define clear method', function() {
35+
expect(typeof $scope.clear).toBe('function');
36+
});
37+
});
38+
});

app/css/app.css app/app.css

File renamed without changes.

app/app.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
// Declare app level module which depends on filters, and services
4+
angular.module('myApp', [
5+
'myApp.config',
6+
'myApp.security',
7+
'myApp.home',
8+
'myApp.account',
9+
'myApp.chat',
10+
'myApp.login'
11+
])
12+
13+
.run(['$rootScope', 'Auth', function($rootScope, Auth) {
14+
// track status of authentication
15+
Auth.$onAuth(function(user) {
16+
$rootScope.loggedIn = !!user;
17+
});
18+
}]);

app/partials/chat.html app/chat/chat.html

-5
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ <h2>Chat</h2>
88
<ul id="messages" ng-show="messages.length">
99
<li ng-repeat="message in messages | reverse">{{message.text}}</li>
1010
</ul>
11-
12-
<p>
13-
Running the 'interpolate' filter:
14-
{{ 'Current version is v%VERSION%.' | interpolate }}
15-
</p>

app/chat/chat.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
(function (angular) {
2+
"use strict";
3+
4+
var app = angular.module('myApp.chat', ['ngRoute', 'firebase.utils', 'firebase']);
5+
6+
app.controller('ChatCtrl', ['$scope', 'messageList', function($scope, messageList) {
7+
$scope.messages = messageList;
8+
$scope.addMessage = function(newMessage) {
9+
if( newMessage ) {
10+
$scope.messages.$add({text: newMessage});
11+
}
12+
};
13+
}]);
14+
15+
app.factory('messageList', ['fbutil', '$firebaseArray', function(fbutil, $firebaseArray) {
16+
var ref = fbutil.ref('messages').limitToLast(10);
17+
return $firebaseArray(ref);
18+
}]);
19+
20+
app.config(['$routeProvider', function($routeProvider) {
21+
$routeProvider.when('/chat', {
22+
templateUrl: 'chat/chat.html',
23+
controller: 'ChatCtrl'
24+
});
25+
}]);
26+
27+
})(angular);

app/chat/chat_test.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
describe('myApp.chat', function() {
3+
beforeEach(module('myApp.chat'));
4+
5+
describe('ChatCtrl', function() {
6+
var chatCtrl, $scope;
7+
beforeEach(function() {
8+
inject(function($controller) {
9+
$scope = {};
10+
chatCtrl = $controller('ChatCtrl', {$scope: $scope});
11+
});
12+
});
13+
14+
it('creates messages array in scope', function() {
15+
expect(Object.prototype.toString.call($scope.messages)).toBe('[object Array]');
16+
});
17+
});
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
/* Directives */
4+
5+
6+
angular.module('myApp')
7+
8+
.directive('appVersion', ['version', function(version) {
9+
return function(scope, elm) {
10+
elm.text(version);
11+
};
12+
}]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'use strict';
2+
3+
/* jasmine specs for directives go here */
4+
5+
describe('app-version directive', function() {
6+
beforeEach(function() {
7+
module('mock.firebase');
8+
module('myApp');
9+
});
10+
11+
it('should print current version', function() {
12+
module(function($provide) {
13+
$provide.constant('version', 'TEST_VER');
14+
});
15+
inject(function($compile, $rootScope) {
16+
var element = $compile('<span app-version></span>')($rootScope);
17+
expect(element.text()).toEqual('TEST_VER');
18+
});
19+
});
20+
21+
});

app/components/auth/auth.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
angular.module('firebase.auth', ['firebase', 'firebase.utils'])
2+
.factory('Auth', ['$firebaseAuth', 'fbutil', function($firebaseAuth, fbutil) {
3+
return $firebaseAuth(fbutil.ref());
4+
}]);

app/components/auth/auth_test.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"use strict";
2+
describe('Auth', function() {
3+
beforeEach(function() {
4+
module('mock.firebase');
5+
module('firebase.auth');
6+
});
7+
8+
it('should return $firebaseAuth instance', function() {
9+
inject(function (Auth, $firebaseAuth) {
10+
var ref = new MockFirebase();
11+
var testInst = $firebaseAuth(ref);
12+
expect(Auth.prototype === testInst.prototype).toBe(true);
13+
});
14+
});
15+
});
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use strict";
2+
describe('fbutil', function() {
3+
beforeEach(function() {
4+
module('mock.firebase');
5+
module('firebase.utils');
6+
});
7+
8+
describe('handler', function() {
9+
it('should have tests');
10+
});
11+
12+
describe('defer', function() {
13+
it('should have tests');
14+
});
15+
16+
describe('ref', function() {
17+
it('should have tests');
18+
});
19+
});

app/js/decorators.js app/components/ngcloak/ngcloak-decorator.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
12
/**
2-
* Wraps ng-cloak so that, instead of simply waiting for Angular to compile, it waits until
3-
* Auth resolves with the remote Firebase services.
4-
*
5-
* <code>
6-
* <div ng-cloak>Authentication has resolved.</div>
7-
* </code>
8-
*/
9-
angular.module('myApp.decorators', ['firebase.utils', 'firebase.auth'])
3+
* Wraps ng-cloak so that, instead of simply waiting for Angular to compile, it waits until
4+
* Auth resolves with the remote Firebase services.
5+
*
6+
* <code>
7+
* <div ng-cloak>Authentication has resolved.</div>
8+
* </code>
9+
*/
10+
angular.module('myApp')
1011
.config(['$provide', function($provide) {
1112
// adapt ng-cloak to wait for auth before it does its magic
1213
$provide.decorator('ngCloakDirective', ['$delegate', 'Auth',
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
/* Filters */
4+
5+
angular.module('myApp')
6+
.filter('reverse', function() {
7+
return function(items) {
8+
return items.slice().reverse();
9+
};
10+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
describe('reverse', function() {
2+
var reverse;
3+
beforeEach(function() {
4+
module('myApp');
5+
inject(function (reverseFilter) {
6+
reverse = reverseFilter;
7+
});
8+
});
9+
10+
it('should reverse contents of an array', function() {
11+
expect(reverse([3,2,1])).toEqual([1,2,3]);
12+
});
13+
});

0 commit comments

Comments
 (0)