├── .bowerrc ├── .gitignore ├── LICENSE ├── README.md ├── app ├── app.css ├── app.js ├── common │ ├── datepicker-directive.js │ ├── footer-directive.html │ ├── footer-directive.js │ ├── main-controller.js │ └── validate-english-directive.js ├── home │ ├── home-controller.js │ └── home.html ├── news-feed │ ├── feed.js │ ├── news-feed-controller.js │ └── news-feed.html └── users │ ├── authentication.js │ └── identity.js ├── bower.json ├── index.html └── package.json /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs/* 2 | !.gitkeep 3 | node_modules/ 4 | bower_components/ 5 | tmp 6 | .DS_Store 7 | .idea 8 | .vscode -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010-2014 Google, Inc. http://angularjs.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Social Network - Angular JS demo project -------------------------------------------------------------------------------- /app/app.css: -------------------------------------------------------------------------------- 1 | /* app css stylesheet */ 2 | 3 | body { 4 | margin-top: 60px; 5 | } 6 | 7 | .border { 8 | border: 1px solid black; 9 | padding: 15px; 10 | } 11 | 12 | .margin-bottom-100 { 13 | margin-bottom: 100px; 14 | } 15 | 16 | .menu { 17 | list-style: none; 18 | border-bottom: 0.1em solid black; 19 | margin-bottom: 2em; 20 | padding: 0 0 0.5em; 21 | } 22 | 23 | .hidden-element { 24 | display: none; 25 | } 26 | 27 | .disabled-button { 28 | opacity: 0.5; 29 | } 30 | 31 | .small-image { 32 | width: 250px; 33 | } 34 | 35 | input.ng-invalid.ng-dirty { 36 | background-color: pink; 37 | } 38 | 39 | .menu:before { 40 | content: "["; 41 | } 42 | 43 | .menu:after { 44 | content: "]"; 45 | } 46 | 47 | .menu > li { 48 | display: inline; 49 | } 50 | 51 | .menu > li:before { 52 | content: "|"; 53 | padding-right: 0.3em; 54 | } 55 | 56 | .menu > li:nth-child(1):before { 57 | content: ""; 58 | padding: 0; 59 | } 60 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('socialNetwork', [ 4 | 'ngRoute', 5 | 'ngCookies', 6 | 'socialNetwork.common', 7 | 'socialNetwork.common.footer', 8 | 'socialNetwork.common.validation', 9 | 'socialNetwork.common.datepicker', 10 | 'socialNetwork.home', 11 | 'socialNetwork.newsFeed', 12 | 'socialNetwork.users.identity' 13 | ]) 14 | .config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) { 15 | $routeProvider.otherwise({redirectTo: '/'}); 16 | 17 | $httpProvider.interceptors.push(['$q','toastr', function($q, toastr) { 18 | return { 19 | 'responseError': function(rejection) { 20 | if (rejection.data && rejection.data['error_description']) { 21 | toastr.error(rejection.data['error_description']); 22 | } 23 | else if (rejection.data && rejection.data.modelState && rejection.data.modelState['']){ 24 | var errors = rejection.data.modelState['']; 25 | if (errors.length > 0) { 26 | toastr.error(errors[0]); 27 | } 28 | } 29 | 30 | return $q.reject(rejection); 31 | } 32 | } 33 | }]); 34 | }]) 35 | .run(['$rootScope', '$location', 'authentication', function($rootScope, $location, authentication) { 36 | $rootScope.$on('$routeChangeError', function(ev, current, previous, rejection) { 37 | if (rejection == 'Unauthorized Access') { 38 | $location.path('/'); 39 | } 40 | }); 41 | 42 | authentication.refreshCookie(); 43 | }]) 44 | .constant('jQuery', $) 45 | .constant('toastr', toastr) 46 | .constant('BASE_URL', 'http://softuni-social-network.azurewebsites.net/api/'); 47 | -------------------------------------------------------------------------------- /app/common/datepicker-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.common.datepicker', []) 2 | .directive('datePicker', [function() { 3 | return { 4 | restrict: 'A', 5 | link: function(scope, element, attrs) { 6 | var minDate = attrs['minDate'] || '-20'; 7 | var maxDate = attrs['maxDate'] || '+1M +10D'; 8 | 9 | element.datepicker({ 10 | minDate: parseInt(minDate), 11 | maxDate: maxDate 12 | }); 13 | } 14 | } 15 | }]); -------------------------------------------------------------------------------- /app/common/footer-directive.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/common/footer-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.common.footer', []) 2 | .directive('footer', [function() { 3 | return { 4 | restrict: 'A', 5 | templateUrl: 'app/common/footer-directive.html', 6 | link: function (scope, element) { 7 | 8 | } 9 | }; 10 | }]); 11 | -------------------------------------------------------------------------------- /app/common/main-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.common', []) 2 | .controller('MainCtrl', [ 3 | '$scope', 4 | 'identity', 5 | function($scope, identity) { 6 | identity.getCurrentUser() 7 | .then(function(user) { 8 | $scope.currentUser = user; 9 | $scope.isAuthenticated = true; 10 | }); 11 | }]); -------------------------------------------------------------------------------- /app/common/validate-english-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.common.validation', []) 2 | .directive('validateEnglish', [function() { 3 | return { 4 | restrict: 'A', 5 | link: function(scope, element) { 6 | 7 | } 8 | } 9 | }]); -------------------------------------------------------------------------------- /app/home/home-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.home', [ 2 | 'socialNetwork.users.authentication' 3 | ]) 4 | .config(['$routeProvider', function($routeProvider) { 5 | $routeProvider.when('/', { 6 | templateUrl: 'app/home/home.html', 7 | controller: 'HomeCtrl' 8 | }); 9 | }]) 10 | .controller('HomeCtrl', [ 11 | '$scope', 12 | '$location', 13 | 'authentication', 14 | function($scope, $location, authentication) { 15 | if (authentication.isAuthenticated()) { 16 | $location.path('/newsFeed'); 17 | } 18 | 19 | $scope.login = function (user) { 20 | authentication.loginUser(user) 21 | .then(function(loggedInUser){ 22 | $location.path('/newsFeed'); 23 | }); 24 | }; 25 | 26 | $scope.register = function (user) { 27 | authentication.registerUser(user) 28 | .then(function(registeredUser) { 29 | $location.path('/newsFeed'); 30 | }); 31 | }; 32 | }]); -------------------------------------------------------------------------------- /app/home/home.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 |
7 | 8 | 9 |
10 | 11 |
12 |
13 | 14 |
15 |
16 | 17 | 18 |
19 | 20 | 21 |
22 | 23 | 24 |
25 | 26 | 27 |
28 | 29 | 30 |
31 | 32 | Male 33 | Female 34 | Other 35 |
36 | 37 |
38 |
39 |
-------------------------------------------------------------------------------- /app/news-feed/feed.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.newsFeed.feed', []) 2 | .factory('feed', [ 3 | '$http', 4 | '$q', 5 | 'BASE_URL', 6 | function($http, $q, BASE_URL) { 7 | function latest(pageSize) { 8 | pageSize = pageSize || 10; 9 | 10 | var deferred = $q.defer(); 11 | 12 | $http.get(BASE_URL + 'me/feed?PageSize=' + pageSize) 13 | .then(function(feed) { 14 | deferred.resolve(feed); 15 | }); 16 | 17 | return deferred.promise; 18 | } 19 | 20 | return { 21 | latest: latest 22 | } 23 | }]); -------------------------------------------------------------------------------- /app/news-feed/news-feed-controller.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.newsFeed', [ 2 | 'socialNetwork.newsFeed.feed' 3 | ]) 4 | .config(['$routeProvider', function($routeProvider) { 5 | var routeChecks = { 6 | authenticated: ['$q', 'authentication', function($q, authentication) { 7 | if (authentication.isAuthenticated()) { 8 | return $q.when(true); 9 | } 10 | 11 | return $q.reject('Unauthorized Access'); 12 | }] 13 | } 14 | 15 | $routeProvider.when('/newsFeed', { 16 | templateUrl: 'app/news-feed/news-feed.html', 17 | controller: 'NewsFeedCtrl', 18 | resolve: routeChecks.authenticated 19 | }) 20 | }]) 21 | .controller('NewsFeedCtrl', [ 22 | '$scope', 23 | 'feed', 24 | function($scope, feed) { 25 | 26 | feed.latest() 27 | .then(function(latestFeed) { 28 | $scope.latestFeed = latestFeed; 29 | }); 30 | }]); -------------------------------------------------------------------------------- /app/news-feed/news-feed.html: -------------------------------------------------------------------------------- 1 |

News Feed

2 |
3 |
4 |
5 |
6 |
7 |
-------------------------------------------------------------------------------- /app/users/authentication.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.users.authentication', []) 2 | .factory('authentication', [ 3 | '$http', 4 | '$cookies', 5 | '$q', 6 | '$location', 7 | 'identity', 8 | 'BASE_URL', 9 | function($http, $cookies, $q, $location, identity, BASE_URL) { 10 | 11 | var AUTHENTICATION_COOKIE_KEY = '!__Authentication_Cookie_Key__!'; 12 | 13 | function preserveUserData(data) { 14 | var accessToken = data.access_token; 15 | $http.defaults.headers.common.Authorization = 'Bearer ' + accessToken; 16 | $cookies.put(AUTHENTICATION_COOKIE_KEY, accessToken); 17 | } 18 | 19 | function registerUser(user) { 20 | var deferred = $q.defer(); 21 | 22 | $http.post(BASE_URL + 'Users/Register', user) 23 | .then(function(response) { 24 | preserveUserData(response.data); 25 | 26 | identity.requestUserProfile() 27 | .then(function() { 28 | deferred.resolve(response.data); 29 | }); 30 | }); 31 | 32 | return deferred.promise; 33 | } 34 | 35 | function loginUser(user) { 36 | var deferred = $q.defer(); 37 | 38 | $http.post(BASE_URL + 'Users/Login', user) 39 | .then(function(response) { 40 | preserveUserData(response.data); 41 | 42 | identity.requestUserProfile() 43 | .then(function() { 44 | deferred.resolve(response.data); 45 | }); 46 | }); 47 | 48 | return deferred.promise; 49 | } 50 | 51 | function isAuthenticated() { 52 | return !!$cookies.get(AUTHENTICATION_COOKIE_KEY); 53 | } 54 | 55 | function logout() { 56 | $cookies.remove(AUTHENTICATION_COOKIE_KEY); 57 | $http.defaults.headers.common.Authorization = undefined; 58 | identity.removeUserProfile(); 59 | $location.path('/'); 60 | } 61 | 62 | function refreshCookie() { 63 | if (isAuthenticated()) { 64 | $http.defaults.headers.common.Authorization = 'Bearer ' + $cookies.get(AUTHENTICATION_COOKIE_KEY); 65 | identity.requestUserProfile(); 66 | } 67 | } 68 | 69 | return { 70 | registerUser: registerUser, 71 | loginUser: loginUser, 72 | isAuthenticated: isAuthenticated, 73 | refreshCookie: refreshCookie, 74 | logout: logout 75 | } 76 | }]); -------------------------------------------------------------------------------- /app/users/identity.js: -------------------------------------------------------------------------------- 1 | angular.module('socialNetwork.users.identity', []) 2 | .factory('identity', [ 3 | '$http', 4 | '$q', 5 | 'BASE_URL', 6 | function($http, $q, BASE_URL) { 7 | 8 | var deferred = $q.defer(); 9 | 10 | var currentUser = undefined; 11 | 12 | return { 13 | getCurrentUser: function () { 14 | if (currentUser) { 15 | return $q.when(currentUser); 16 | } 17 | else { 18 | return deferred.promise; 19 | } 20 | }, 21 | removeUserProfile: function() { 22 | currentUser = undefined; 23 | }, 24 | requestUserProfile: function() { 25 | var userProfileDeferred = $q.defer(); 26 | 27 | $http.get(BASE_URL + 'me') 28 | .then(function(response) { 29 | currentUser = response.data; 30 | deferred.resolve(currentUser); 31 | userProfileDeferred.resolve(); 32 | }); 33 | 34 | return userProfileDeferred.promise; 35 | } 36 | }; 37 | }]); -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed", 3 | "description": "A starter project for AngularJS", 4 | "version": "0.0.0", 5 | "homepage": "https://github.com/angular/angular-seed", 6 | "license": "MIT", 7 | "private": true, 8 | "dependencies": { 9 | "angular": "~1.4.0", 10 | "angular-route": "~1.4.0", 11 | "angular-loader": "~1.4.0", 12 | "angular-mocks": "~1.4.0", 13 | "html5-boilerplate": "~5.2.0", 14 | "bootstrap": "~3.3.6", 15 | "angular-sanitize": "~1.5.3", 16 | "angular-cookies": "~1.5.5", 17 | "jquery": "~2.2.2", 18 | "toastr": "~2.1.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Social Network 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 49 | 50 |
51 |
52 |
53 | 54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-seed", 3 | "private": true, 4 | "version": "0.0.0", 5 | "description": "A starter project for AngularJS", 6 | "repository": "https://github.com/angular/angular-seed", 7 | "license": "MIT", 8 | "devDependencies": { 9 | "bower": "^1.3.1", 10 | "http-server": "^0.6.1" 11 | }, 12 | "scripts": { 13 | "postinstall": "bower install", 14 | 15 | "prestart": "npm install", 16 | "start": "http-server -a localhost -p 8000 -c-1" 17 | } 18 | } 19 | --------------------------------------------------------------------------------