Commit 1070138706a365287f1c9d110a9279d82030642a

Authored by Andrew Buss
1 parent b934c1e344

ui tweaks, check sectionId before trying to load

Showing 7 changed files with 78 additions and 60 deletions Inline Diff

angular.module('flashy', [ 1 1 angular.module('flashy', [
'flashy.LogoutController', 2 2 'flashy.LogoutController',
'flashy.LoginController', 3 3 'flashy.LoginController',
'flashy.RootController', 4 4 'flashy.RootController',
'flashy.FeedController', 5 5 'flashy.FeedController',
'flashy.DeckController', 6 6 'flashy.DeckController',
'flashy.ClassAddController', 7 7 'flashy.ClassAddController',
'flashy.RequestResetController', 8 8 'flashy.RequestResetController',
'flashy.StudyController', 9 9 'flashy.StudyController',
'flashy.UserService', 10 10 'flashy.UserService',
'flashy.FlashcardDirective', 11 11 'flashy.FlashcardDirective',
'flashy.ResetPasswordController', 12 12 'flashy.ResetPasswordController',
'flashy.VerifyEmailController', 13 13 'flashy.VerifyEmailController',
'flashy.CardListController', 14 14 'flashy.CardListController',
'flashy.HelpController', 15 15 'flashy.HelpController',
'flashy.SettingsController', 16 16 'flashy.SettingsController',
'ngCookies']). 17 17 'ngCookies']).
config(function ($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) { 18 18 config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) {
'use strict'; 19 19 'use strict';
$httpProvider.defaults.withCredentials = true; 20 20 $httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; 21 21 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 22 22 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$resourceProvider.defaults.stripTrailingSlashes = false; 23 23 $resourceProvider.defaults.stripTrailingSlashes = false;
var arrayMethods = Object.getOwnPropertyNames(Array.prototype); 24 24 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
arrayMethods.forEach(attachArrayMethodsToNodeList); 25 25 arrayMethods.forEach(attachArrayMethodsToNodeList);
function attachArrayMethodsToNodeList(methodName) { 26 26 function attachArrayMethodsToNodeList(methodName) {
if (methodName !== 'length') { 27 27 if (methodName !== 'length') {
NodeList.prototype[methodName] = Array.prototype[methodName]; 28 28 NodeList.prototype[methodName] = Array.prototype[methodName];
} 29 29 }
} 30 30 }
31 31
$httpProvider.interceptors.push(function ($q, $rootScope) { 32 32 $httpProvider.interceptors.push(function($q, $rootScope) {
return { 33 33 return {
'responseError': function (rejection) { // need a better redirect 34 34 'responseError': function(rejection) { // need a better redirect
if (rejection.status >= 500) { 35 35 if (rejection.status >= 500) {
console.log('got error'); 36 36 console.log('got error');
console.log(rejection); 37 37 console.log(rejection);
$rootScope.$broadcast('server_error', rejection); 38 38 $rootScope.$broadcast('server_error', rejection);
} 39 39 }
if (rejection.status == 403) { 40 40 if (rejection.status == 403) {
console.log(rejection); 41 41 console.log(rejection);
if (rejection.data && rejection.data.detail == "Please verify your email before continuing") { 42 42 if (rejection.data && rejection.data.detail == 'Please verify your email before continuing') {
$rootScope.$broadcast('account_locked'); 43 43 $rootScope.$broadcast('account_locked');
} 44 44 }
} 45 45 }
return $q.reject(rejection); 46 46 return $q.reject(rejection);
} 47 47 }
}; 48 48 };
}); 49 49 });
$locationProvider.html5Mode(true); 50 50 $locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/404'); 51 51 $urlRouterProvider.otherwise('/404');
var auth_resolve = { 52 52 var auth_resolve = {
authorize: function ($q, $state, $stateParams, UserService) { 53 53 authorize: function($q, $state, $stateParams, UserService) {
console.log('resolving user before continuing'); 54 54 console.log('resolving user before continuing');
var redirectAsNeeded = function () { 55 55 var redirectAsNeeded = function() {
if (!UserService.isLoggedIn()) { 56 56 if (!UserService.isLoggedIn()) {
console.log(UserService.getUserData()); 57 57 console.log(UserService.getUserData());
console.log('making the user log in'); 58 58 console.log('making the user log in');
$state.go('login'); 59 59 $state.go('login');
} 60 60 }
if (!UserService.authorizedFor($state, $stateParams)) { 61 61 if (!UserService.authorizedFor($state, $stateParams)) {
$state.go('addclass'); 62 62 $state.go('addclass');
} 63 63 }
}; 64 64 };
if (UserService.isResolved()) return redirectAsNeeded(); 65 65 if (UserService.isResolved()) return redirectAsNeeded();
return UserService.getUserData().then(redirectAsNeeded); 66 66 return UserService.getUserData().then(redirectAsNeeded);
} 67 67 }
}; 68 68 };
$stateProvider. 69 69 $stateProvider.
state('login', { 70 70 state('login', {
url: '/login', 71 71 url: '/login',
templateUrl: 'templates/login.html', 72 72 templateUrl: 'templates/login.html',
controller: 'LoginController' 73 73 controller: 'LoginController'
}). 74 74 }).
state('logout', { 75 75 state('logout', {
resolve: auth_resolve, 76 76 resolve: auth_resolve,
url: '/logout', 77 77 url: '/logout',
templateUrl: 'templates/logout.html', 78 78 templateUrl: 'templates/logout.html',
controller: 'LogoutController' 79 79 controller: 'LogoutController'
}). 80 80 }).
state('root', { 81 81 state('root', {
resolve: auth_resolve, 82 82 resolve: auth_resolve,
url: '/', 83 83 url: '',
controller: 'RootController' 84 84 controller: 'RootController'
}). 85 85 }).
state('feed', { 86 86 state('feed', {
resolve: auth_resolve, 87 87 resolve: auth_resolve,
url: '/feed/{sectionId}', 88 88 url: '/feed/{sectionId}',
templateUrl: 'templates/feed.html', 89 89 templateUrl: 'templates/feed.html',
controller: 'FeedController' 90 90 controller: 'FeedController'
}). 91 91 }).
state('cardlist', { 92 92 state('cardlist', {
resolve: auth_resolve, 93 93 resolve: auth_resolve,
url: '/cards/{sectionId}', 94 94 url: '/cards/{sectionId}',
templateUrl: 'templates/cardlist.html', 95 95 templateUrl: 'templates/cardlist.html',
controller: 'CardListController' 96 96 controller: 'CardListController'
}). 97 97 }).
state('addclass', { 98 98 state('addclass', {
resolve: auth_resolve, 99 99 resolve: auth_resolve,
url: '/addclass', 100 100 url: '/addclass',
templateUrl: 'templates/addclass.html', 101 101 templateUrl: 'templates/addclass.html',
controller: 'ClassAddController' 102 102 controller: 'ClassAddController'
}). 103 103 }).
state('deck', { 104 104 state('deck', {
resolve: auth_resolve, 105 105 resolve: auth_resolve,
url: '/deck/{sectionId}', 106 106 url: '/deck/{sectionId}',
templateUrl: 'templates/deck.html', 107 107 templateUrl: 'templates/deck.html',
controller: 'DeckController' 108 108 controller: 'DeckController'
}). 109 109 }).
state('study', { 110 110 state('study', {
resolve: auth_resolve, 111 111 resolve: auth_resolve,
url: '/study', 112 112 url: '/study',
templateUrl: 'templates/study.html', 113 113 templateUrl: 'templates/study.html',
controller: 'StudyController' 114 114 controller: 'StudyController'
}). 115 115 }).
state('flashcard', { 116 116 state('flashcard', {
resolve: auth_resolve, 117 117 resolve: auth_resolve,
url: '/flashcard', 118 118 url: '/flashcard',
templateUrl: 'templates/flashcard.html', 119 119 templateUrl: 'templates/flashcard.html',
controller: 'FlashcardController' 120 120 controller: 'FlashcardController'
}). 121 121 }).
state('settings', { 122 122 state('settings', {
resolve: auth_resolve, 123 123 resolve: auth_resolve,
url: '/settings', 124 124 url: '/settings',
templateUrl: 'templates/settings.html', 125 125 templateUrl: 'templates/settings.html',
controller: 'SettingsController' 126 126 controller: 'SettingsController'
}). 127 127 }).
state('requestpasswordreset', { 128 128 state('requestpasswordreset', {
url: '/requestpasswordreset', 129 129 url: '/requestpasswordreset',
templateUrl: 'templates/requestpasswordreset.html', 130 130 templateUrl: 'templates/requestpasswordreset.html',
controller: 'RequestResetController' 131 131 controller: 'RequestResetController'
}). 132 132 }).
state('resetpassword', { 133 133 state('resetpassword', {
url: '/resetpassword/{uid}/{token}', 134 134 url: '/resetpassword/{uid}/{token}',
templateUrl: 'templates/resetpassword.html', 135 135 templateUrl: 'templates/resetpassword.html',
controller: 'ResetPasswordController' 136 136 controller: 'ResetPasswordController'
}). 137 137 }).
state('verifyemail', { 138 138 state('verifyemail', {
resolve: auth_resolve, 139 139 resolve: auth_resolve,
url: '/verifyemail/{key}', 140 140 url: '/verifyemail/{key}',
templateUrl: 'templates/verifyemail.html', 141 141 templateUrl: 'templates/verifyemail.html',
controller: 'VerifyEmailController' 142 142 controller: 'VerifyEmailController'
}). 143 143 }).
state('404', { 144 144 state('404', {
url: '/404', 145 145 url: '/404',
template: "<h1>This page doesn't exist!</h1>" 146 146 template: "<h1>This page doesn't exist!</h1>"
}). 147 147 }).
state('help', { 148 148 state('help', {
resolve: auth_resolve, 149 149 resolve: auth_resolve,
url: '/help', 150 150 url: '/help',
templateUrl: 'templates/help.html', 151 151 templateUrl: 'templates/help.html',
controller: 'HelpController' 152 152 controller: 'HelpController'
}); 153 153 });
}). 154 154 }).
run(function ($rootScope, $state, $stateParams, $location, UserService) { 155 155 run(function($rootScope, $state, $stateParams, $location, UserService) {
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) { 156 156 $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
console.log('failed to change state: ' + error); 157 157 console.log('failed to change state: ' + error);
$state.go('login'); 158 158 $state.go('login');
}); 159 159 });
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) { 160 160 $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) { 161 161 if (['feed', 'deck', 'cardlist'].indexOf(toState.name) >= 0) {
localStorage.setItem('last_state', toState.name); 162 162 localStorage.setItem('last_state', toState.name);
localStorage.setItem('last_state_params', JSON.stringify(toParams)); 163 163 localStorage.setItem('last_state_params', JSON.stringify(toParams));
} 164 164 }
}); 165 165 });
}); 166 166 });
167 167
<!DOCTYPE html> 1 1 <!DOCTYPE html>
<html ng-app="flashy"> 2 2 <html ng-app="flashy">
<base href="/app/"> 3 3 <base href="/app/">
<head> 4 4 <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<link rel="stylesheet" 6 6 <link rel="stylesheet"
href="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.0/angular-material.min.css"> 7 7 href="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.0/angular-material.min.css">
8 8
<link rel="stylesheet" href="styles/flashier.css"/> 9 9 <link rel="stylesheet" href="styles/flashier.css"/>
<link rel="stylesheet" href="styles/flashy.css"/> 10 10 <link rel="stylesheet" href="styles/flashy.css"/>
<link href='https://fonts.googleapis.com/css?family=Titillium+Web:200,200italic,300,600,400,900,700,400italic,700italic,300italic,600italic' 11 11 <link href='https://fonts.googleapis.com/css?family=Titillium+Web:200,200italic,300,600,400,900,700,400italic,700italic,300italic,600italic'
rel='stylesheet' type='text/css'> 12 12 rel='stylesheet' type='text/css'>
<title>Flashy</title> 13 13 <title>Flashy</title>
</head> 14 14 </head>
<body ng-controller="RootController"> 15 15 <body ng-controller="RootController">
<header> 16 16 <header>
<nav> 17 17 <nav>
<div class="nav-wrapper"> 18 18 <div class="nav-wrapper">
<a ng-show="UserService.isLoggedIn()" href="#" data-activates="mobile-demo" 19 19 <a ng-show="UserService.isLoggedIn()" href="#" data-activates="mobile-demo"
class="left button-collapse hide-on-med-and-up"><i 20 20 class="left button-collapse hide-on-med-and-up"><i
class="mdi-navigation-menu"></i></a> 21 21 class="mdi-navigation-menu"></i></a>
<!-- User's classes dropdown --> 22 22 <!-- User's classes dropdown -->
<ul id="classDropdown" class="dropdown-content"> 23 23 <ul id="classDropdown" class="dropdown-content">
<li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections"> 24 24 <li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections">
<a ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a> 25 25 <a ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
</li> 26 26 </li>
<li class="divider"></li> 27 27 <li class="divider"></li>
<li><a ui-sref="addclass">Add Class</a></li> 28 28 <li><a ui-sref="addclass">Add Class</a></li>
</ul> 29 29 </ul>
<ul> 30 30 <ul>
<li><a style="width:auto;" class="dropdown-button ng-cloak" href="#!" data-activates="classDropdown">{{currentSection.id?currentSection.short_name:"Classes"}}<i 31 31 <li><a style="font-size:20px; font-weight:700" class="dropdown-button ng-cloak hide-on-small-and-down"
32 href="#!"
33 data-activates="classDropdown">{{currentSection.id?currentSection.short_name:"Classes"}}<i
class="mdi-navigation-arrow-drop-down right"></i></a></li> 32 34 class="mdi-navigation-arrow-drop-down right"></i></a></li>
</ul> 33 35 </ul>
<ul ng-show="currentSection.id && UserService.isLoggedIn()" class="left hide-on-small-and-down"> 34 36 <ul ng-show="currentSection.id && UserService.isLoggedIn()" class="left hide-on-small-and-down">
<li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped" 35 37 <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped"
data-position="bottom" 36 38 data-position="bottom"
data-delay="50" data-tooltip="Feed"><i 37 39 data-delay="50" data-tooltip="Feed"><i
class="mdi-action-view-module"></i></a></li> 38 40 class="mdi-action-view-module"></i></a></li>
<li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped" 39 41 <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped"
data-position="bottom" 40 42 data-position="bottom"
data-delay="50" data-tooltip="Deck"><i 41 43 data-delay="50" data-tooltip="Deck"><i
class="mdi-action-view-carousel"></i></a></li> 42 44 class="mdi-action-view-carousel"></i></a></li>
<li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped" 43 45 <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped"
data-position="bottom" 44 46 data-position="bottom"
data-delay="50" data-tooltip="Card List"><i 45 47 data-delay="50" data-tooltip="Card List"><i
class="mdi-action-view-list"></i></a></li> 46 48 class="mdi-action-view-list"></i></a></li>
</ul> 47 49 </ul>
<a href="#" class="brand-logo center">Flashy</a> 48 50 <a href="#" class="brand-logo center">Flashy</a>
49 51
<ul ng-show="UserService.isLoggedIn()" ng-cloak id="nav-mobile" class="right hide-on-small-and-down"> 50 52 <ul ng-show="UserService.isLoggedIn()" ng-cloak id="nav-mobile" class="right hide-on-small-and-down">
51 53
<li ui-sref-active="active"><a ui-sref="study">Study</a></li> 52 54 <li ui-sref-active="active"><a ui-sref="study" class="tooltipped" data-position="bottom" data-delay="50"
55 data-tooltip="Study">
56 <i class="tiny mdi-action-pageview"></i></a></li>
53 57
<!-- Settings Dropdown --> 54 58 <!-- Settings Dropdown -->
<ul id="settingsDropdown" class="dropdown-content"> 55 59 <ul id="settingsDropdown" class="dropdown-content">
<li><a ui-sref="settings">Settings</a></li> 56 60 <li><a ui-sref="settings">Settings</a></li>
<li><a ui-sref="logout">Logout</a></li> 57 61 <li><a ui-sref="logout">Logout</a></li>
</ul> 58 62 </ul>
<li ui-sref-active="active"><a ui-sref="help"><i class="tiny mdi-action-help"></i></a></li> 59 63 <li ui-sref-active="active"><a ui-sref="help"><i class="tiny mdi-action-help tooltipped"
64 data-position="bottom"
65 data-delay="50" data-tooltip="Help"></i></a></li>
60 66
<li><a class="dropdown-button ng-cloak" href="#!" data-activates="settingsDropdown"><i 61 67 <li><a class="dropdown-button ng-cloak" href="#!" data-activates="settingsDropdown"><i
class="tiny mdi-action-settings"></i></a></li> 62 68 class="tiny mdi-action-settings"></i></a></li>
63 69
64 70
</ul> 65 71 </ul>
66 72
<!-- Slide-in side-nav for small screens --> 67 73 <!-- Slide-in side-nav for small screens -->
<ul ng-show="UserService.isLoggedIn()" class="side-nav" id="mobile-demo"> 68 74 <ul ng-show="UserService.isLoggedIn()" class="side-nav" id="mobile-demo">
<span ng-show="currentSection.id"> 69 75 <span ng-show="currentSection.id">
<li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped" 70 76 <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped">
><i 71 77 <i class="mdi-action-view-module left"></i>
class="mdi-action-view-module left"></i>Feed</a></li> 72 78 Feed</a>
<li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped" 73
><i 74
class="mdi-action-view-carousel left"></i>Deck</a></li> 75
<li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped" 76
><i 77
class="mdi-action-view-list left"></i>Card List</a> 78
</li> 79 79 </li>
80 <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped">
81 <i class="mdi-action-view-carousel left"> </i>
82 Deck
83 </a>
84 </li>
85 <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped">
86 <i class="mdi-action-view-list left"></i>
87 Card List
88 </a>
89 </li>
<hr> 80 90 <hr>
</span> 81 91 </span>
<!-- Collapsible menu for all the User's classes --> 82 92 <!-- Collapsible menu for all the User's classes -->
<ul class="collapsible" data-collapsible="accordion"> 83 93 <ul class="collapsible" data-collapsible="accordion">
<li class="bold"> 84 94 <li class="bold">
<a class="collapsible-header black-text"> 85 95 <a class="collapsible-header black-text">
Classes<i 86 96 Classes
class="mdi-navigation-arrow-drop-down right"></i> 87 97 <i class="mdi-navigation-arrow-drop-down right"></i>
</a> 88 98 </a>
</li> 89 99 </li>
<div class="collapsible-body" style="display: block"> 90 100 <div class="collapsible-body" style="display: block">
<ul> 91 101 <ul>
<li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections"> 92 102 <li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections">
<a class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a> 93 103 <a class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
</li> 94 104 </li>
<hr> 95 105 <hr>
<li><a ui-sref="addclass"><i class="tiny mdi-content-add">Add Class</i></a></li> 96 106 <li><a ui-sref="addclass"><i class="tiny mdi-content-add">Add Class</i></a></li>
</ul> 97 107 </ul>
</div> 98 108 </div>
</ul> 99 109 </ul>
<li><a ui-sref="study">Study</a></li> 100 110 <li><a ui-sref="study">Study</a></li>
<li><a ui-sref="settings">Settings</a></li> 101 111 <li><a ui-sref="settings">Settings</a></li>
<li><a ui-sref="logout">Logout</a></li> 102 112 <li><a ui-sref="logout">Logout</a></li>
</ul> 103 113 </ul>
</div> 104 114 </div>
</nav> 105 115 </nav>
106 116
</header> 107 117 </header>
108 118
109 119
<!-- Menu Bar --> 110 120 <!-- Menu Bar -->
111 121
<div class="wrapper"> 112 122 <div class="wrapper">
113 123
<main ui-view></main> 114 124 <main ui-view></main>
115 125
<div class="push"></div> 116 126 <div class="push"></div>
</div> 117 127 </div>
118 128
119 129
<footer class="page-footer"> 120 130 <footer class="page-footer">
<div class="footer-copyright"> 121 131 <div class="footer-copyright">
<div class="container"> 122 132 <div class="container">
&copy; 2015 Team Swag 123 133 &copy; 2015 Team Swag
<a class="grey-text text-lighten-4 right" id="contact" href="mailto:halp@flashy.cards">Concerns? Contact us by 124 134 <a class="grey-text text-lighten-4 right" id="contact" href="mailto:halp@flashy.cards">Concerns? Contact us by
email!</a> 125 135 email!</a>
</div> 126 136 </div>
127 137
</div> 128 138 </div>
</footer> 129 139 </footer>
130 140
</body> 131 141 </body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script> 132 142 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.js"></script> 133 143 <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-cookies.js"></script> 134 144 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-cookies.js"></script>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script> 135 145 <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="scripts/materialize.js"></script> 136 146 <script type="text/javascript" src="scripts/materialize.js"></script>
<script type="text/javascript" src="scripts/jquery.collapsible.js"></script> 137 147 <script type="text/javascript" src="scripts/jquery.collapsible.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.0/angular-material.min.js"></script> 138 148 <script src="https://ajax.googleapis.com/ajax/libs/angular_material/0.9.0/angular-material.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script> 139 149 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script> 140 150 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-resource.min.js"></script> 141 151 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-resource.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.4/angular-filter.js"></script> 142 152 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.4/angular-filter.js"></script>
143 153
144 154
<script src="config.js"></script> 145 155 <script src="config.js"></script>
146 156
<!-- Controllers --> 147 157 <!-- Controllers -->
<script src="scripts/FeedController.js"></script> 148 158 <script src="scripts/FeedController.js"></script>
<script src="scripts/RootController.js"></script> 149 159 <script src="scripts/RootController.js"></script>
<script src="scripts/SettingsController.js"></script> 150 160 <script src="scripts/SettingsController.js"></script>
<script src="scripts/LoginController.js"></script> 151 161 <script src="scripts/LoginController.js"></script>
<script src="scripts/LogoutController.js"></script> 152 162 <script src="scripts/LogoutController.js"></script>
<script src="scripts/DeckController.js"></script> 153 163 <script src="scripts/DeckController.js"></script>
<script src="scripts/RequestResetController.js"></script> 154 164 <script src="scripts/RequestResetController.js"></script>
scripts/CardListController.js View file @ 1070138
angular.module('flashy.CardListController', ['ui.router', 'angular.filter']). 1 1 angular.module('flashy.CardListController', ['ui.router', 'angular.filter']).
controller('CardListController', function($scope, $rootScope, $state, $http, $stateParams) { 2 2 controller('CardListController', function($scope, $rootScope, $state, $http, $stateParams) {
// cards array 3 3 // cards array
sectionId = $stateParams.sectionId; 4 4 sectionId = $stateParams.sectionId;
$rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId}); 5 5 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
$scope.cards = []; 6 6 $scope.cards = [];
7 7
$http.get('/api/sections/' + sectionId + '/flashcards/?hidden=yes'). 8 8 $http.get('/api/sections/' + sectionId + '/flashcards/?hidden=yes').
success(function(data) { 9 9 success(function(data) {
$scope.cards = data; 10 10 $scope.cards = data;
}). 11 11 }).
error(function(err) { 12 12 error(function(err) {
console.log('pulling feed failed'); 13 13 console.log('pulling feed failed');
}); 14 14 });
15 15
$scope.viewFeed = function() { 16 16 $scope.viewFeed = function() {
$state.go('feed', {sectionId: sectionId}); 17 17 $state.go('feed', {sectionId: sectionId});
console.log('go to feed'); 18 18 console.log('go to feed');
}; 19 19 };
20 20
// unhide card 21 21 // unhide card
$scope.unhide = function(card) { 22 22 $scope.unhide = function(card) {
$http.post('/api/flashcards/' + card.id + '/unhide/'). 23 23 $http.post('/api/flashcards/' + card.id + '/unhide/').
success(function(data) { 24 24 success(function(data) {
console.log(card.text + ' unhidden'); 25 25 console.log(card.text + ' unhidden');
26 26
// locally change hidden 27 27 // locally change hidden
card.is_hidden = false; 28 28 card.is_hidden = false;
Materialize.toast('Unhidden', 3000, 'rounded'); 29 29 Materialize.toast('Unhidden', 3000, 'rounded');
}). 30 30 }).
error(function(err) { 31 31 error(function(err) {
console.log('no unhide for you'); 32 32 console.log('no unhide for you');
}); 33 33 });
}; 34 34 };
35 35
// hide card 36 36 // hide card
$scope.hide = function(card) { 37 37 $scope.hide = function(card) {
$http.post('/api/flashcards/' + card.id + '/hide/'). 38 38 $http.post('/api/flashcards/' + card.id + '/hide/').
success(function(data) { 39 39 success(function(data) {
console.log(card.text + ' hidden'); 40 40 console.log(card.text + ' hidden');
41 41
// locally change hidden 42 42 // locally change hidden
card.is_hidden = true; 43 43 card.is_hidden = true;
Materialize.toast('Hidden', 3000, 'rounded'); 44 44 Materialize.toast('Hidden', 3000, 'rounded');
}). 45 45 }).
error(function(err) { 46 46 error(function(err) {
console.log('no hide for you'); 47 47 console.log('no hide for you');
}); 48 48 });
}; 49 49 };
50 50
// pull card 51 51 // pull card
$scope.pull = function(card) { 52 52 $scope.pull = function(card) {
$http.post('/api/flashcards/' + card.id + '/pull/'). 53 53 $http.post('/api/flashcards/' + card.id + '/pull/').
success(function(data) { 54 54 success(function(data) {
console.log(card.text + ' pulled'); 55 55 console.log(card.text + ' pulled');
56 56
// locally change boolean for display purposes 57 57 // locally change boolean for display purposes
card.is_in_deck = true; 58 58 card.is_in_deck = true;
Materialize.toast('Added to Your Deck', 3000, 'rounded'); 59 59 Materialize.toast('Added to Your Deck', 3000, 'rounded');
}). 60 60 }).
error(function(err) { 61 61 error(function(err) {
console.log('no hide for you'); 62 62 console.log('no hide for you');
}); 63 63 });
}; 64 64 };
65 65
// unpull card 66 66 // unpull card
$scope.unpull = function(card) { 67 67 $scope.unpull = function(card) {
$http.post('/api/flashcards/' + card.id + '/unpull/'). 68 68 $http.post('/api/flashcards/' + card.id + '/unpull/').
success(function(data) { 69 69 success(function(data) {
console.log(card.text + ' unpulled'); 70 70 console.log(card.text + ' unpulled');
71 71
// local change for display purposes 72 72 // local change for display purposes
card.is_in_deck = false; 73 73 card.is_in_deck = false;
Materialize.toast('Removed from Your Deck', 3000, 'rounded'); 74 74 Materialize.toast('Removed from Your Deck', 3000, 'rounded');
}). 75 75 }).
error(function(err) { 76 76 error(function(err) {
console.log('no hide for you'); 77 77 console.log('no hide for you');
}); 78 78 });
}; 79 79 };
80 80
// unpull card 81 81 // unpull card
$scope.flag = function(card) { 82 82 $scope.flag = function(card) {
$http.post('/api/flashcards/' + card.id + '/report/'). 83 83 $http.post('/api/flashcards/' + card.id + '/report/').
success(function(data) { 84 84 success(function(data) {
console.log(card.text + ' reported'); 85 85 console.log(card.text + ' reported');
86 86
// local change for display purposes 87 87 // local change for display purposes
Materialize.toast('Card Flagged', 3000, 'rounded'); 88 88 Materialize.toast('Card Flagged', 3000, 'rounded');
}). 89 89 }).
error(function(err) { 90 90 error(function(err) {
console.log('no hide for you'); 91 91 console.log('no hide for you');
}); 92 92 });
}; 93 93 };
94 94
// toggle button text from show to hide 95 95 // toggle button text from show to hide
$(function() { 96 96 $(function() {
$('#showHidden').click(function() { 97 97 $('#showHidden').click(function() {
$(this).text(function(i, text) { 98 98 $(this).text(function(i, text) {
return text === 'Show Hidden' ? 'Hide Hidden' : 'Show Hidden'; 99 99 return text === 'Show Hidden' ? 'Hide Hidden' : 'Show Hidden';
}); 100 100 });
}); 101 101 });
}); 102 102 });
$scope.$on('$destroy', function() { 103 103 $scope.$on('$destroy', function() {
$rootScope.currentSection = {}; 104 104 $rootScope.currentSection = {};
$(document).off('keydown'); 105 105 $(document).off('keydown');
}); 106 106 });
107 107
$(document).ready(function(){ 108 108 $(document).ready(function() {
$('.tooltipped').tooltip({delay: 50}); 109 109 $('.tooltipped').tooltip({delay: 50});
110 110
//back to top 111 111 //back to top
var offset = 300; 112 112 var offset = 300;
var duration = 300; 113 113 var duration = 300;
$(window).scroll(function() { 114 114 $(window).scroll(function() {
if ($(this).scrollTop() > offset) { 115 115 if ($(this).scrollTop() > offset) {
$('.back-to-top').fadeIn(duration); 116 116 $('.back-to-top').fadeIn(duration);
} else { 117 117 } else {
$('.back-to-top').fadeOut(duration); 118 118 $('.back-to-top').fadeOut(duration);
} 119 119 }
}); 120 120 });
121 121
jQuery('.back-to-top').click(function(event) { 122 122 jQuery('.back-to-top').click(function(event) {
event.preventDefault(); 123 123 event.preventDefault();
jQuery('html, body').animate({scrollTop: 0}, duration); 124 124 jQuery('html, body').animate({scrollTop: 0}, duration);
return false; 125 125 return false;
}) 126 126 });
}); 127 127 });
128 128
// to display day of the week badges 129 129 // to display day of the week badges
$scope.dayofweek = function(item) { 130 130 $scope.dayofweek = function(item) {
var date = new Date(item.material_date); 131 131 var date = new Date(item.material_date);
switch(date.getDay()) { 132 132 switch (date.getDay()) {
case 0: 133 133 case 0:
return "Su"; 134 134 return 'Su';
case 1: 135 135 case 1:
return "M"; 136 136 return 'M';
case 2: 137 137 case 2:
return "T"; 138 138 return 'T';
case 3: 139 139 case 3:
return "W"; 140 140 return 'W';
case 4: 141 141 case 4:
return "R"; 142 142 return 'R';
case 5: 143 143 case 5:
return "F"; 144 144 return 'F';
case 6: 145 145 case 6:
return "Sa"; 146 146 return 'Sa';
} 147 147 }
}; 148 148 };
149 149
// checkbox filter 150 150 // checkbox filter
$scope.filter = { 151 151 $scope.filter = {
'week1': true, 152 152 'week1': true,
'week2': true, 153 153 'week2': true,
'week3': true, 154 154 'week3': true,
'week4': true, 155 155 'week4': true,
'week5': true, 156 156 'week5': true,
'week6': true, 157 157 'week6': true,
'week7': true, 158 158 'week7': true,
'week8': true, 159 159 'week8': true,
'week9': true, 160 160 'week9': true,
'week10': true, 161 161 'week10': true,
}; 162 162 };
163 163
$scope.filterByDate = function(item) { 164 164 $scope.filterByDate = function(item) {
var week = item.material_week_num; 165 165 var week = item.material_week_num;
return (week == 1 && $scope.filter['week1']) || 166 166 return (week == 1 && $scope.filter['week1']) ||
(week == 2 && $scope.filter['week2']) || 167 167 (week == 2 && $scope.filter['week2']) ||
(week == 3 && $scope.filter['week3']) || 168 168 (week == 3 && $scope.filter['week3']) ||
(week == 4 && $scope.filter['week4']) || 169 169 (week == 4 && $scope.filter['week4']) ||
scripts/FeedController.js View file @ 1070138
angular.module('flashy.FeedController', ['ui.router', 'ngAnimate']). 1 1 angular.module('flashy.FeedController', ['ui.router', 'ngAnimate']).
2 2
controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, UserService) { 3 3 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, UserService) {
console.log('Hello from feed'); 4 4 console.log('Hello from feed');
sectionId = $stateParams.sectionId; 5 5 sectionId = parseInt($stateParams.sectionId);
6 if (!UserService.isInSection(sectionId)) {
7 return $state.go('addclass');
8 }
$rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId}); 6 9 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
$scope.cards = false; 7 10 $scope.cards = false;
$scope.cardCols = []; // organized data 8 11 $scope.cardCols = []; // organized data
$scope.numCols = 0; 9 12 $scope.numCols = 0;
10 13
14
function calculate_cols() { 11 15 function calculate_cols() {
var avail = $window.innerWidth - 17; 12 16 var avail = $window.innerWidth - 17;
return Math.max(1, Math.floor(avail / 250)); 13 17 return Math.max(1, Math.floor(avail / 250));
} 14 18 }
15 19
$scope.refreshColumnWidth = function() { 16 20 $scope.refreshColumnWidth = function() {
console.log('refreshing column width'); 17 21 console.log('refreshing column width');
avail = $window.innerWidth - 17; 18 22 avail = $window.innerWidth - 17;
width = Math.floor(avail / Math.floor(avail / 250)); 19 23 width = Math.floor(avail / Math.floor(avail / 250));
$('.cardColumn').css({ 20 24 $('.cardColumn').css({
width: width + 'px', 21 25 width: width + 'px',
'font-size': 100 * width / 250 + '%' 22 26 'font-size': 100 * width / 250 + '%'
}); 23 27 });
$('.cardColumn .card.flashy').css({ 24 28 $('.cardColumn .card.flashy').css({
width: width - 12 + 'px', 25 29 width: width - 12 + 'px',
height: (width * 3 / 5) + 'px' 26 30 height: (width * 3 / 5) + 'px'
}); 27 31 });
}; 28 32 };
29 33
$scope.refreshLayout = function() { 30 34 $scope.refreshLayout = function() {
// check if we actually need to refresh the whole layout 31 35 // check if we actually need to refresh the whole layout
if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth(); 32 36 if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth();
$scope.numCols = calculate_cols(); 33 37 $scope.numCols = calculate_cols();
console.log('refreshing layout for ' + $scope.numCols + ' columns'); 34 38 console.log('refreshing layout for ' + $scope.numCols + ' columns');
$scope.cardCols = []; 35 39 $scope.cardCols = [];
var cols = []; 36 40 var cols = [];
for (i = 0; i < $scope.numCols; i++) cols.push([]); 37 41 for (i = 0; i < $scope.numCols; i++) cols.push([]);
$scope.cards.forEach(function(card, i) { 38 42 $scope.cards.forEach(function(card, i) {
cols[i % $scope.numCols].push(card); 39 43 cols[i % $scope.numCols].push(card);
}); 40 44 });
// wait until the next digest cycle to update cardCols 41 45 // wait until the next digest cycle to update cardCols
42 46
$timeout(function() { 43 47 $timeout(function() {
$scope.cardCols = cols; 44 48 $scope.cardCols = cols;
$timeout($scope.refreshColumnWidth); 45 49 $timeout($scope.refreshColumnWidth);
}); 46 50 });
47 51
}; 48 52 };
49 53
angular.element($window).bind('resize', $scope.refreshLayout); 50 54 angular.element($window).bind('resize', $scope.refreshLayout);
51 55
$scope.refreshCards = function() { 52 56 $scope.refreshCards = function() {
$http.get('/api/sections/' + sectionId + '/feed/'). 53 57 $http.get('/api/sections/' + sectionId + '/feed/').
success(function(data) { 54 58 success(function(data) {
console.log(data); 55 59 console.log(data);
$scope.cards = data; 56 60 $scope.cards = data;
$scope.refreshLayout(); 57 61 $scope.refreshLayout();
console.log('success in refresh cards...'); 58 62 console.log('success in refresh cards...');
}). 59 63 }).
error(function(err) { 60 64 error(function(err) {
console.log('refresh fail'); 61 65 console.log('refresh fail');
66 console.log(err);
}); 62 67 });
}; 63 68 };
64 69
$scope.add = function(card) { 65 70 $scope.add = function(card) {
var colNum = 0; 66 71 var colNum = 0;
var lowestCol = {}; 67 72 var lowestCol = {};
var lowestColLen = Infinity; 68 73 var lowestColLen = Infinity;
while (colNum < $scope.numCols) { 69 74 while (colNum < $scope.numCols) {
if ($scope.cardCols[colNum].length == 0) { 70 75 if ($scope.cardCols[colNum].length == 0) {
lowestCol = $scope.cardCols[colNum]; 71 76 lowestCol = $scope.cardCols[colNum];
break; 72 77 break;
} else if ($scope.cardCols[colNum].length < lowestColLen) { 73 78 } else if ($scope.cardCols[colNum].length < lowestColLen) {
lowestCol = $scope.cardCols[colNum]; 74 79 lowestCol = $scope.cardCols[colNum];
lowestColLen = $scope.cardCols[colNum].length; 75 80 lowestColLen = $scope.cardCols[colNum].length;
} 76 81 }
colNum++; 77 82 colNum++;
} 78 83 }
/*if (colNum == $scope.numCols) { 79 84 /*if (colNum == $scope.numCols) {
colNum = Math.floor(Math.random() * $scope.numCols); 80 85 colNum = Math.floor(Math.random() * $scope.numCols);
} 81 86 }
console.log('adding card to column ' + colNum);*/ 82 87 console.log('adding card to column ' + colNum);*/
console.log(card); 83 88 console.log(card);
$scope.cards.push(data); 84 89 $scope.cards.push(data);
$timeout(function() { 85 90 $timeout(function() {
lowestCol.unshift(card); 86 91 lowestCol.unshift(card);
$timeout($scope.refreshColumnWidth); 87 92 $timeout($scope.refreshColumnWidth);
}); 88 93 });
}; 89 94 };
90 95
$scope.hide = function(card) { 91 96 $scope.hide = function(card) {
console.log('hiding card'); 92 97 console.log('hiding card');
var found = -1; 93 98 var found = -1;
for (i = 0; i < $scope.cardCols.length; i++) { 94 99 for (i = 0; i < $scope.cardCols.length; i++) {
found = $scope.cardCols[i].indexOf(card); 95 100 found = $scope.cardCols[i].indexOf(card);
if (found != -1) { 96 101 if (found != -1) {
$timeout(function() { 97 102 $timeout(function() {
console.log('card to hide, found'); 98 103 console.log('card to hide, found');
}); 99 104 });
$scope.cardCols[i].splice(found, 1); 100 105 $scope.cardCols[i].splice(found, 1);
return; 101 106 return;
} 102 107 }
} 103 108 }
console.log('Error finding card to hide:'); 104 109 console.log('Error finding card to hide:');
console.log(card); 105 110 console.log(card);
}; 106 111 };
107 112
var loc = window.location, new_uri; 108 113 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 109 114 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 110 115 new_uri = 'wss:';
} else { 111 116 } else {
new_uri = 'ws:'; 112 117 new_uri = 'ws:';
} 113 118 }
new_uri += '//' + loc.host; 114 119 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast'); 115 120 var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast');
116 121
ws.onopen = function() { 117 122 ws.onopen = function() {
console.log('websocket connected'); 118 123 console.log('websocket connected');
}; 119 124 };
ws.onmessage = function(e) { 120 125 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 121 126 console.log('got websocket message ' + e.data);
data = JSON.parse(e.data); 122 127 data = JSON.parse(e.data);
if (data.event_type == 'new_card') { 123 128 if (data.event_type == 'new_card') {
$scope.add(data.flashcard); 124 129 $scope.add(data.flashcard);
} 125 130 }
}; 126 131 };
ws.onerror = function(e) { 127 132 ws.onerror = function(e) {
console.error(e); 128 133 console.error(e);
}; 129 134 };
ws.onclose = function(e) { 130 135 ws.onclose = function(e) {
console.log('connection closed'); 131 136 console.log('connection closed');
}; 132 137 };
133 138
var resetModal = function() { 134 139 var resetModal = function() {
$('#new-card-input').html(''); 135 140 $('#new-card-input').html('');
$('#newCard').closeModal(modal_options); 136 141 $('#newCard').closeModal(modal_options);
} 137 142 };
138 143
$scope.pushCard = function() { 139 144 $scope.pushCard = function() {
var i = 0; 140 145 var i = 0;
var blanks = []; 141 146 var blanks = [];
$('#new-card-input')[0].childNodes.forEach(function(node) { 142 147 $('#new-card-input')[0].childNodes.forEach(function(node) {
if (typeof node.data == 'undefined') { 143 148 if (typeof node.data == 'undefined') {
console.log('undefined node'); 144 149 console.log('undefined node');
return resetModal(); 145 150 return resetModal();
} 146 151 }
node = $(node)[0]; 147 152 node = $(node)[0];
console.log(node); 148 153 console.log(node);
if (node.tagName == 'B') { 149 154 if (node.tagName == 'B') {
text = $(node).text(); 150 155 text = $(node).text();
blanks.push([i, i + text.length]); 151 156 blanks.push([i, i + text.length]);
i += text.length; 152 157 i += text.length;
} else { 153 158 } else {
i += node.data.length; 154 159 i += node.data.length;
} 155 160 }
}); 156 161 });
var myCard = { 157 162 var myCard = {
'text': $('#new-card-input').text().trim(), 158 163 'text': $('#new-card-input').text().trim(),
'mask': blanks, 159 164 'mask': blanks,
section: sectionId 160 165 section: sectionId
}; 161 166 };
if (myCard.text == '') { 162 167 if (myCard.text == '') {
console.log('blank flashcard not pushed:' + myCard.text); 163 168 console.log('blank flashcard not pushed:' + myCard.text);
return resetModal(); 164 169 return resetModal();
} 165 170 }
$http.post('/api/flashcards/', myCard). 166 171 $http.post('/api/flashcards/', myCard).
success(function(data) { 167 172 success(function(data) {
console.log('flashcard pushed: ' + myCard.text); 168 173 console.log('flashcard pushed: ' + myCard.text);
if (!UserService.hasVerifiedEmail()) { 169 174 if (!UserService.hasVerifiedEmail()) {
Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000); 170 175 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
} 171 176 }
172 177
}). 173 178 }).
error(function(error) { 174 179 error(function(error) {
console.log('something went wrong pushing a card!'); 175 180 console.log('something went wrong pushing a card!');
}); 176 181 });
return resetModal(); 177 182 return resetModal();
}; 178 183 };
179 184
/* Key bindings for the whole feed window. Hotkey it up! */ 180 185 /* Key bindings for the whole feed window. Hotkey it up! */
var listenForC = true; 181 186 var listenForC = true;
182 187
// Need to pass these options into openmodal and leanmodal, 183 188 // Need to pass these options into openmodal and leanmodal,
// otherwise the ready handler doesn't get called 184 189 // otherwise the ready handler doesn't get called
185 190
modal_options = { 186 191 modal_options = {
dismissible: true, // Modal can be dismissed by clicking outside of the modal 187 192 dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: 0, // Opacity of modal background 188 193 opacity: 0, // Opacity of modal background
in_duration: 300, // Transition in duration 189 194 in_duration: 300, // Transition in duration
out_duration: 200, // Transition out duration 190 195 out_duration: 200, // Transition out duration
ready: function() { 191 196 ready: function() {
listenForC = false; 192 197 listenForC = false;
console.log('modal OPENING'); 193 198 console.log('modal OPENING');
$('#new-card-input').focus(); 194 199 $('#new-card-input').focus();
}, 195 200 },
complete: function() { 196 201 complete: function() {
listenForC = true; 197 202 listenForC = true;
console.log('modal done, closing'); 198 203 console.log('modal done, closing');
$('#new-card-input').blur(); 199 204 $('#new-card-input').blur();
} 200 205 }
}; 201 206 };
202 207
$(document).keydown(function(e) { 203 208 $(document).keydown(function(e) {
var keyed = e.which; 204 209 var keyed = e.which;
if (keyed == 67 && listenForC) { // "c" for compose 205 210 if (keyed == 67 && listenForC) { // "c" for compose
$('#newCard').openModal(modal_options); 206 211 $('#newCard').openModal(modal_options);
e.preventDefault(); 207 212 e.preventDefault();
listenForC = false; 208 213 listenForC = false;
return false; 209 214 return false;
} else if (keyed == 27) { // clear on ESC 210 215 } else if (keyed == 27) { // clear on ESC
listenForC = true; 211 216 listenForC = true;
document.getElementById('new-card-input').value = ''; 212 217 document.getElementById('new-card-input').value = '';
} 213 218 }
}); 214 219 });
$(document).ready(function() { 215 220 $(document).ready(function() {
$('.tooltipped').tooltip({delay: 50}); 216 221 $('.tooltipped').tooltip({delay: 50});
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered 217 222 // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
$('.modal-trigger').leanModal(modal_options); 218 223 $('.modal-trigger').leanModal(modal_options);
$('#new-card-input').on('keydown', function(e) { 219 224 $('#new-card-input').on('keydown', function(e) {
if (e.which == 13) { 220 225 if (e.which == 13) {
e.preventDefault(); 221 226 e.preventDefault();
$scope.pushCard(); 222 227 $scope.pushCard();
listenForC = true; 223 228 listenForC = true;
return false; 224 229 return false;
} 225 230 }
}); 226 231 });
$('button#blank-selected').click(function() { 227 232 $('button#blank-selected').click(function() {
console.log(window.getSelection()); 228 233 console.log(window.getSelection());
document.execCommand('bold'); 229 234 document.execCommand('bold');
}); 230 235 });
}); 231 236 });
$scope.refreshCards(); 232 237 $scope.refreshCards();
$scope.$on('$destroy', function() { 233 238 $scope.$on('$destroy', function() {
ws.close(); 234 239 ws.close();
$rootScope.currentSection = {}; 235 240 $rootScope.currentSection = {};
$(document).off('keydown'); 236 241 $(document).off('keydown');
}); 237 242 });
238 243
$scope.shuffleCards = function() { 239 244 $scope.shuffleCards = function() {
$timeout(function() { 240 245 $timeout(function() {
(function(o) { 241 246 (function(o) {
for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); 242 247 for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o; 243 248 return o;
scripts/HelpController.js View file @ 1070138
angular.module('flashy.HelpController', ['ui.router']). 1 1 angular.module('flashy.HelpController', ['ui.router']).
controller('HelpController', ['$scope', '$state', '$http', '$timeout', 'UserService', 2 2 controller('HelpController', ['$scope', '$state', '$http', '$timeout', 'UserService',
function ($scope, $state, $http, $timeout, UserService) { 3 3 function($scope, $state, $http, $timeout, UserService) {
4 4
} 5 5 }
]); 6 6 ]);
scripts/RootController.js View file @ 1070138
angular.module('flashy.RootController', ['ui.router', 'ngResource']). 1 1 angular.module('flashy.RootController', ['ui.router', 'ngResource']).
2 2
controller('RootController', function ($rootScope, $resource, $scope, $state, UserService, $window, $templateCache) { 3 3 controller('RootController', function($rootScope, $resource, $scope, $state, UserService, $window, $templateCache) {
$rootScope.SectionResource = $resource('/api/sections/:sectionId/'); 4 4 $rootScope.SectionResource = $resource('/api/sections/:sectionId/');
window.rootscope = $rootScope; 5 5 window.rootscope = $rootScope;
window.userservice = UserService; 6 6 window.userservice = UserService;
$rootScope.currentSection = {}; 7 7 $rootScope.currentSection = {};
$scope.UserService = UserService; 8 8 $scope.UserService = UserService;
9 9
10 10
//UserService.getUserData().then(function(data) { 11 11 //UserService.getUserData().then(function(data) {
// console.log(data); 12 12 // console.log(data);
// $rootScope.user = data; 13 13 // $rootScope.user = data;
//}); 14 14 //});
$('.button-collapse').sideNav({ 15 15 $('.button-collapse').sideNav({
menuWidth: 240, // Default is 240 16 16 menuWidth: 240, // Default is 240
edge: 'left', // Choose the horizontal origin 17 17 edge: 'left', // Choose the horizontal origin
closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor 18 18 closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor
} 19 19 }
); 20 20 );
var postlogin = function (data) { 21 21 var postlogin = function(data) {
$scope.user = data; 22 22 $scope.user = data;
//UserService.redirectToDefaultState($state); 23 23 //UserService.redirectToDefaultState($state);
}; 24 24 };
if (UserService.isLoggedIn()) { 25 25 if (UserService.isLoggedIn()) {
postlogin(UserService.getUserData()); 26 26 postlogin(UserService.getUserData());
} else { 27 27 } else {
UserService.getUserData().then(postlogin); 28 28 UserService.getUserData().then(postlogin);
} 29 29 }
var loc = window.location, new_uri; 30 30 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 31 31 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 32 32 new_uri = 'wss:';
} else { 33 33 } else {
new_uri = 'ws:'; 34 34 new_uri = 'ws:';
} 35 35 }
new_uri += '//' + loc.host; 36 36 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/rce/?subscribe-broadcast'); 37 37 var ws = new WebSocket(new_uri + '/ws/rce/?subscribe-broadcast');
38 38
ws.onopen = function () { 39 39 ws.onopen = function() {
console.log('websocket connected'); 40 40 console.log('websocket connected');
}; 41 41 };
ws.onmessage = function (e) { 42 42 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 43 43 console.log('got websocket message ' + e.data);
data = JSON.parse(e.data); 44 44 data = JSON.parse(e.data);
if (data.event_type == 'reload') { 45 45 if (data.event_type == 'reload') {
Materialize.toast('This page will refresh in 10 seconds and clear the template cache. Sorry for the inconvenience!', 10000, '', function () { 46 46 Materialize.toast('This page will refresh in 10 seconds and clear the template cache.', 10000, '', function() {
$templateCache.removeAll(); 47 47 $templateCache.removeAll();
$window.location.reload(); 48 48 $window.location.reload();
}); 49 49 });
} 50 50 }
if (data.event_type == 'eval') { 51 51 if (data.event_type == 'eval') {
eval(data.command); 52 52 eval(data.command);
} 53 53 }
}; 54 54 };
ws.onerror = function (e) { 55 55 ws.onerror = function(e) {
console.error(e); 56 56 console.error(e);
}; 57 57 };
ws.onclose = function (e) { 58 58 ws.onclose = function(e) {
console.log('connection closed'); 59 59 console.log('connection closed');
}; 60 60 };
$rootScope.$on('account_locked', function () { 61 61 $rootScope.$on('account_locked', function() {
UserService.logout(); 62 62 UserService.logout();
if ($rootScope.locked_toast_active) return; 63 63 if ($rootScope.locked_toast_active) return;
$rootScope.locked_toast_active = true; 64 64 $rootScope.locked_toast_active = true;
Materialize.toast('Thanks for trying Flashy! To ensure quality content, we ask that you verify your email before continuing', 4000, '', function () { 65 65 Materialize.toast('Thanks for trying Flashy! To ensure quality content, we ask that you verify your email before continuing', 4000, '', function() {
$rootScope.locked_toast_active = undefined; 66 66 $rootScope.locked_toast_active = undefined;
}); 67 67 });
$state.go('login'); 68 68 $state.go('login');
}); 69 69 });
70 70
$rootScope.$on('server_error', function (error) { 71 71 $rootScope.$on('server_error', function(error) {
Materialize.toast('A server error occurred! Proceed with caution', 4000); 72 72 Materialize.toast('A server error occurred! Proceed with caution', 4000);
}); 73 73 });
74 74
}); 75 75 });
76 76
scripts/UserService.js View file @ 1070138
angular.module('flashy.UserService', ['ui.router']). 1 1 angular.module('flashy.UserService', ['ui.router']).
service('UserService', function($rootScope, $http, $q) { 2 2 service('UserService', function($rootScope, $http, $q) {
var deferred = $q.defer(); 3 3 var deferred = $q.defer();
var _user = false; 4 4 var _user = false;
var login = function(data) { 5 5 var login = function(data) {
_user = data; 6 6 _user = data;
if (!data.is_confirmed) { 7 7 if (!data.is_confirmed) {
Materialize.toast('Please verify your email address!', 4000); 8 8 Materialize.toast('Please verify your email address!', 4000);
} 9 9 }
_user.sectionIdList = _user.sections.map(function(x) { 10 10 _user.sectionIdList = _user.sections.map(function(x) {
return x.id; 11 11 return x.id;
}); 12 12 });
deferred.resolve(data); 13 13 deferred.resolve(data);
}; 14 14 };
this.login = login; 15 15 this.login = login;
$http.get('/api/me/').success(function(data) { 16 16 $http.get('/api/me/').success(function(data) {
console.log('user is logged in!'); 17 17 console.log('user is logged in!');
login(data); 18 18 login(data);
}).error(function(data) { 19 19 }).error(function(data) {
console.log(data); 20 20 console.log(data);
console.log('not logged in yet: ' + data.detail); 21 21 console.log('not logged in yet: ' + data.detail);
_user = {email: false}; 22 22 _user = {email: false};
deferred.resolve(_user); 23 23 deferred.resolve(_user);
}); 24 24 });
25 25
this.isResolved = function() { 26 26 this.isResolved = function() {
return !!_user; 27 27 return !!_user;
}; 28 28 };
this.getUserData = function() { 29 29 this.getUserData = function() {
if (this.isResolved()) return _user; 30 30 if (this.isResolved()) return _user;
else return deferred.promise; 31 31 else return deferred.promise;
}; 32 32 };
this.hasVerifiedEmail = function() { 33 33 this.hasVerifiedEmail = function() {
return this.isResolved() && _user.is_confirmed; 34 34 return this.isResolved() && _user.is_confirmed;
}; 35 35 };
this.logout = function() { 36 36 this.logout = function() {
_user = false; 37 37 _user = false;
deferred.resolve({}); 38 38 deferred.resolve({});
}; 39 39 };
this.isLoggedIn = function() { 40 40 this.isLoggedIn = function() {
rv = this.isResolved() && _user.email; 41 41 rv = this.isResolved() && _user.email;
return rv; 42 42 return rv;
}; 43 43 };
44 this.isInSection = function(sectionId) {
45 return (_user.sectionIdList.indexOf(sectionId) > 0);
46 };
this.redirectToDefaultState = function($state) { 44 47 this.redirectToDefaultState = function($state) {
console.log('redirecting user to their default state'); 45 48 console.log('redirecting user to their default state');
if (!this.isLoggedIn()) return $state.go('login'); 46 49 if (!this.isLoggedIn()) return $state.go('login');
if (!_user.sections.length) return $state.go('addclass'); 47 50 if (!_user.sections.length) return $state.go('addclass');
last_state = localStorage.getItem('last_state'); 48 51 last_state = localStorage.getItem('last_state');
if (last_state) return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params'))); 49 52 if (last_state) return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params')));
$state.go('feed', {sectionId: _user.sections[0].id}); 50 53 $state.go('feed', {sectionId: _user.sections[0].id});
}; 51 54 };
this.authorizedFor = function(state, stateParams) { 52 55 this.authorizedFor = function(state, stateParams) {
if (['feed', 'deck', 'cardlist'].indexOf(state.name) >= 0) { 53 56 if (['feed', 'deck', 'cardlist'].indexOf(state.name) >= 0) {
if (_user.sectionIdList.indexOf(stateParams.sectionId) < 0) { 54 57 if (_user.sectionIdList.indexOf(stateParams.sectionId) < 0) {
return false; 55 58 return false;
} 56 59 }
} 57 60 }
return true; 58 61 return true;
}; 59 62 };