Commit 4c3a5e272ef1b27284ca56e5bd28286a3234450d

Authored by Andrew Buss
1 parent dc71f53b15

cleanup; redirect away from login if already logged in

Showing 7 changed files with 227 additions and 228 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',
'ngCookies']). 15 15 'ngCookies']).
config(['$stateProvider', '$urlRouterProvider', '$httpProvider', 16 16 config(function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) {
'$locationProvider', 17 17 'use strict';
function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) { 18 18 $httpProvider.defaults.withCredentials = true;
'use strict'; 19 19 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.withCredentials = true; 20 20 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; 21
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; 22
23 21
var arrayMethods = Object.getOwnPropertyNames(Array.prototype); 24 22 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
arrayMethods.forEach(attachArrayMethodsToNodeList); 25 23 arrayMethods.forEach(attachArrayMethodsToNodeList);
function attachArrayMethodsToNodeList(methodName) { 26 24 function attachArrayMethodsToNodeList(methodName) {
if (methodName !== 'length') { 27 25 if (methodName !== 'length') {
NodeList.prototype[methodName] = Array.prototype[methodName]; 28 26 NodeList.prototype[methodName] = Array.prototype[methodName];
} 29 27 }
}; 30 28 };
31 29
$httpProvider.interceptors.push(function($q) { 32 30 $httpProvider.interceptors.push(function($q) {
return { 33 31 return {
'responseError': function(rejection) { 34 32 'responseError': function(rejection) {
if (rejection.status >= 500) { 35 33 if (rejection.status >= 500) {
console.log('got error'); 36 34 console.log('got error');
console.log(rejection); 37 35 console.log(rejection);
$('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>'); 38 36 $('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>');
} 39
return $q.reject(rejection); 40
} 41 37 }
}; 42 38 return $q.reject(rejection);
}); 43 39 }
$locationProvider.html5Mode(true); 44
$urlRouterProvider.otherwise('/login'); 45
var auth_resolve = { 46
authorize: ['$q', 'UserService', 47
function($q, UserService) { 48
console.log('resolving user before continuing'); 49
return UserService.getUserData(); 50
} 51
] 52
}; 53 40 };
$stateProvider. 54 41 });
state('login', { 55 42 $locationProvider.html5Mode(true);
url: '/login', 56 43 $urlRouterProvider.otherwise('/login');
templateUrl: 'templates/login.html', 57 44 var auth_resolve = {
controller: 'LoginController' 58 45 authorize: function($q, UserService) {
}). 59 46 console.log('resolving user before continuing');
state('logout', { 60 47 return UserService.getUserData();
resolve: auth_resolve, 61 48 }
url: '/logout', 62 49 };
templateUrl: 'templates/logout.html', 63 50 $stateProvider.
controller: 'LogoutController' 64 51 state('login', {
}). 65 52 url: '/login',
state('root', { 66 53 templateUrl: 'templates/login.html',
resolve: auth_resolve, 67 54 controller: 'LoginController'
url: '', 68 55 }).
templateUrl: 'templates/root.html', 69 56 state('logout', {
controller: 'RootController' 70 57 resolve: auth_resolve,
}). 71 58 url: '/logout',
state('feed', { 72 59 templateUrl: 'templates/logout.html',
resolve: auth_resolve, 73 60 controller: 'LogoutController'
url: '/feed/{sectionId}', 74 61 }).
templateUrl: 'templates/feed.html', 75 62 state('root', {
controller: 'FeedController' 76 63 resolve: auth_resolve,
}). 77 64 url: '',
state('cardlist', { 78 65 templateUrl: 'templates/root.html',
resolve: auth_resolve, 79 66 controller: 'RootController'
url: '/cards/{sectionId}', 80 67 }).
templateUrl: 'templates/cardlist.html', 81 68 state('feed', {
controller: 'CardListController' 82 69 resolve: auth_resolve,
}). 83 70 url: '/feed/{sectionId}',
state('addclass', { 84 71 templateUrl: 'templates/feed.html',
resolve: auth_resolve, 85 72 controller: 'FeedController'
url: '/addclass', 86 73 }).
templateUrl: 'templates/addclass.html', 87 74 state('cardlist', {
controller: 'ClassAddController' 88 75 resolve: auth_resolve,
}). 89 76 url: '/cards/{sectionId}',
state('deck', { 90 77 templateUrl: 'templates/cardlist.html',
resolve: auth_resolve, 91 78 controller: 'CardListController'
url: '/deck/{sectionId}', 92 79 }).
templateUrl: 'templates/deck.html', 93 80 state('addclass', {
controller: 'DeckController' 94 81 resolve: auth_resolve,
}). 95 82 url: '/addclass',
state('study', { 96 83 templateUrl: 'templates/addclass.html',
resolve: auth_resolve, 97 84 controller: 'ClassAddController'
url: '/study', 98 85 }).
templateUrl: 'templates/study.html', 99 86 state('deck', {
controller: 'StudyController' 100 87 resolve: auth_resolve,
}). 101 88 url: '/deck/{sectionId}',
state('flashcard', { 102 89 templateUrl: 'templates/deck.html',
resolve: auth_resolve, 103 90 controller: 'DeckController'
url: '/flashcard', 104 91 }).
templateUrl: 'templates/flashcard.html', 105 92 state('study', {
controller: 'FlashcardController' 106 93 resolve: auth_resolve,
}). 107 94 url: '/study',
state('requestpasswordreset', { 108 95 templateUrl: 'templates/study.html',
url: '/requestpasswordreset', 109 96 controller: 'StudyController'
templateUrl: 'templates/requestpasswordreset.html', 110 97 }).
controller: 'RequestResetController' 111 98 state('flashcard', {
}). 112 99 resolve: auth_resolve,
state('resetpassword', { 113 100 url: '/flashcard',
url: '/resetpassword/{uid}/{token}', 114 101 templateUrl: 'templates/flashcard.html',
templateUrl: 'templates/resetpassword.html', 115 102 controller: 'FlashcardController'
controller: 'ResetPasswordController' 116 103 }).
}). 117 104 state('requestpasswordreset', {
state('verifyemail', { 118 105 url: '/requestpasswordreset',
resolve: auth_resolve, 119 106 templateUrl: 'templates/requestpasswordreset.html',
url: '/verifyemail/{key}', 120 107 controller: 'RequestResetController'
templateUrl: 'templates/verifyemail.html', 121 108 }).
controller: 'VerifyEmailController' 122 109 state('resetpassword', {
}); 123 110 url: '/resetpassword/{uid}/{token}',
} 124 111 templateUrl: 'templates/resetpassword.html',
]). 125 112 controller: 'ResetPasswordController'
run(['$rootScope', '$state', '$stateParams', '$location', 'UserService', 126 113 }).
function($rootScope, $state, $stateParams, $location, UserService) { 127 114 state('verifyemail', {
$rootScope.$on('$stateChangeStart', function(event, toState, toStateParams) { 128 115 resolve: auth_resolve,
if (UserService.isLoggedIn()) return console.log('no login required; going straight to ' + toState.name); 129 116 url: '/verifyemail/{key}',
if (toState.name == 'login') return console.log('we are going to login anyway; just let it happen :)'); 130 117 templateUrl: 'templates/verifyemail.html',
if (!UserService.isUserResolved()) return console.log('user not yet resolved; hold off'); 131 118 controller: 'VerifyEmailController'
$rootScope.returnToState = toState; 132
$rootScope.returnToStateParams = toStateParams; 133
console.log('going to ' + toState.name + ' after login'); 134
$state.go('login'); 135
}); 136 119 });
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) { 137 120 }).
console.log('failed to change state: ' + error); 138 121 run(function($rootScope, $state, $stateParams, $location, UserService) {
$state.go('login'); 139 122 $rootScope.$on('$stateChangeStart', function(event, toState, toStateParams) {
}); 140 123 if (toState.name == 'login') {
} 141 124 if (UserService.isLoggedIn()) return console.log('already logged in') + $state.go('addclass');
]); 142 125 else return console.log('we are going to login anyway');
126 }
127 if (UserService.isLoggedIn()) return console.log('no login required; going straight to ' + toState.name);
128
129 if (!UserService.isUserResolved()) return console.log('user not yet resolved; hold off');
130 $rootScope.returnToState = toState;
131 $rootScope.returnToStateParams = toStateParams;
132 console.log('going to ' + toState.name + ' after login');
133
134 });
135 $rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error) {
136 console.log('failed to change state: ' + error);
137 $state.go('login');
138 });
139 });
143 140
<!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>
<header> 15 15 <header>
16 <nav>
17 <div class="nav-wrapper">
18 <a href="#" data-activates="mobile-demo" class="left button-collapse"><i class="mdi-navigation-menu"></i></a>
19 <ul ng-show="currentSection.id && isLoggedIn" class="left hide-on-small-and-down">
20 <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped"
21 data-position="bottom"
22 data-delay="50" data-tooltip="Feed"><i
23 class="mdi-action-view-module"></i></a></li>
24 <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped"
25 data-position="bottom"
26 data-delay="50" data-tooltip="Deck"><i
27 class="mdi-action-view-carousel"></i></a></li>
28 <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped"
29 data-position="bottom"
30 data-delay="50" data-tooltip="Card List"><i
31 class="mdi-action-view-list"></i></a></li>
32 </ul>
33 <a href="#" class="brand-logo center">Flashy</a>
16 34
35 <ul ng-show="isLoggedIn" id="nav-mobile" class="right hide-on-small-and-down">
36 <!-- User's classes dropdown -->
37 <ul id="dropdown1" class="dropdown-content">
38 <li ui-sref-active="active" ng-repeat="section in sections">
39 <a class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
40 </li>
41 <li class="divider"></li>
42 <li><a ui-sref="addclass">Add Class</a></li>
43 </ul>
44 <li><a class="dropdown-button ng-cloak" href="#!" data-activates="dropdown1">{{currentSection.id?currentSection.short_name:"Classes"}}<i
45 class="mdi-navigation-arrow-drop-down right"></i></a></li>
46 <li><a ui-sref="study">Study</a></li>
47 <li><a ui-sref="logout">Logout</a></li>
48 </ul>
49
50 <!-- Slide-in side-nav for small screens -->
51 <ul class="side-nav" id="mobile-demo">
52 <!-- Collapsible menu for all the User's classes -->
53 <ul class="collapsible" data-collapsible="accordion">
54 <li class="bold">
55 <a class="collapsible-header black-text">
56 Classes<i class="mdi-navigation-arrow-drop-down right"></i>
57 </a>
58 </li>
59 <div class="collapsible-body" style="display: block">
60 <ul>
61 <li ng-repeat="section in sections">
62 <a ui-sref-active="active" class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
63 </li>
64 <hr>
65 <li><a ui-sref="addclass"><i class="tiny mdi-content-add"> Add Class</i></a></li>
66 </ul>
67 </div>
68 </ul>
69 <li><a ui-sref="study">Study</a></li>
70 <li><a ui-sref="logout">Logout</a></li>
71 </ul>
72 </div>
73 </nav>
74
</header> 17 75 </header>
<body ng-controller="RootController"> 18 76 <body ng-controller="RootController">
19 77
<!-- Menu Bar --> 20 78 <!-- Menu Bar -->
<nav> 21
<div class="nav-wrapper"> 22
<a href="#" data-activates="mobile-demo" class="left button-collapse"><i class="mdi-navigation-menu"></i></a> 23
<ul ng-show="currentSection.id && isLoggedIn" class="left hide-on-small-and-down"> 24
<li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped" data-position="bottom" 25
data-delay="50" data-tooltip="Feed"><i 26
class="mdi-action-view-module"></i></a></li> 27
<li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped" data-position="bottom" 28
data-delay="50" data-tooltip="Deck"><i 29
class="mdi-action-view-carousel"></i></a></li> 30
<li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped" data-position="bottom" 31
data-delay="50" data-tooltip="Card List"><i 32
class="mdi-action-view-list"></i></a></li> 33
</ul> 34
<a href="#" class="brand-logo center">Flashy</a> 35
36
<ul ng-show="isLoggedIn" id="nav-mobile" class="right hide-on-small-and-down"> 37
<!-- User's classes dropdown --> 38
<ul id="dropdown1" class="dropdown-content"> 39
<li ui-sref-active="active" ng-repeat="section in sections"> 40
<a class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a> 41
</li> 42
<li class="divider"></li> 43
<li><a ui-sref="addclass">Add Class</a></li> 44
</ul> 45
<li><a class="dropdown-button ng-cloak" href="#!" data-activates="dropdown1">{{currentSection.id?currentSection.short_name:"Classes"}}<i 46
class="mdi-navigation-arrow-drop-down right"></i></a></li> 47
<li><a ui-sref="study">Study</a></li> 48
<li><a ui-sref="logout">Logout</a></li> 49
</ul> 50
51
<!-- Slide-in side-nav for small screens --> 52
<ul class="side-nav" id="mobile-demo"> 53
<!-- Collapsible menu for all the User's classes --> 54
<ul class="collapsible" data-collapsible="accordion"> 55
<li class="bold"> 56
<a class="collapsible-header black-text"> 57
Classes<i class="mdi-navigation-arrow-drop-down right"></i> 58
</a> 59
</li> 60
<div class="collapsible-body" style="display: block"> 61
<ul> 62
<li ng-repeat="section in sections"> 63
<a ui-sref-active="active" class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a> 64
</li> 65
<hr> 66
<li><a ui-sref="addclass"><i class="tiny mdi-content-add"> Add Class</i></a></li> 67
</ul> 68
</div> 69
</ul> 70
<li><a ui-sref="study">Study</a></li> 71
<li><a ui-sref="logout">Logout</a></li> 72
</ul> 73
</div> 74
</nav> 75
<main ui-view></main> 76 79 <main ui-view></main>
<footer class="page-footer"> 77 80 <footer class="page-footer">
<div class="footer-copyright"> 78 81 <div class="footer-copyright">
<div class="container"> 79 82 <div class="container">
Concerns? Contact us by <a class="grey-text text-lighten-4" href="mailto:halp@flashy.cards">email</a>! 80 83 Concerns? Contact us by <a class="grey-text text-lighten-4" href="mailto:halp@flashy.cards">email</a>!
</div> 81 84 </div>
</div> 82 85 </div>
</footer> 83 86 </footer>
</body> 84 87 </body>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script> 85 88 <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> 86 89 <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> 87 90 <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> 88 91 <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="scripts/materialize.js"></script> 89 92 <script type="text/javascript" src="scripts/materialize.js"></script>
<script type="text/javascript" src="scripts/jquery.collapsible.js"></script> 90 93 <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> 91 94 <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> 92 95 <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> 93 96 <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> 94 97 <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> 95 98 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.4/angular-filter.js"></script>
96 99
97 100
<script src="config.js"></script> 98 101 <script src="config.js"></script>
99 102
<!-- Controllers --> 100 103 <!-- Controllers -->
<script src="scripts/FeedController.js"></script> 101 104 <script src="scripts/FeedController.js"></script>
<script src="scripts/RootController.js"></script> 102 105 <script src="scripts/RootController.js"></script>
<script src="scripts/LoginController.js"></script> 103 106 <script src="scripts/LoginController.js"></script>
<script src="scripts/LogoutController.js"></script> 104 107 <script src="scripts/LogoutController.js"></script>
<script src="scripts/DeckController.js"></script> 105 108 <script src="scripts/DeckController.js"></script>
<script src="scripts/RequestResetController.js"></script> 106 109 <script src="scripts/RequestResetController.js"></script>
<script src="scripts/ClassAddController.js"></script> 107 110 <script src="scripts/ClassAddController.js"></script>
<script src="scripts/StudyController.js"></script> 108 111 <script src="scripts/StudyController.js"></script>
<script src="scripts/ResetPasswordController.js"></script> 109 112 <script src="scripts/ResetPasswordController.js"></script>
<script src="scripts/CardListController.js"></script> 110 113 <script src="scripts/CardListController.js"></script>
<script src="scripts/VerifyEmailController.js"></script> 111 114 <script src="scripts/VerifyEmailController.js"></script>
scripts/CardListController.js View file @ 4c3a5e2
angular.module('flashy.CardListController', ['ui.router']). 1 1 angular.module('flashy.CardListController', ['ui.router']).
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/'). 8 8 $http.get('/api/sections/' + sectionId + '/flashcards/').
success(function (data) { 9 9 success(function(data) {
console.log(data); 10 10 console.log(data);
$scope.cards = data; 11 11 $scope.cards = data;
}). 12 12 }).
error(function (err) { 13 13 error(function(err) {
console.log('pulling feed failed'); 14 14 console.log('pulling feed failed');
}); 15 15 });
16 16
$scope.viewFeed = function () { 17 17 $scope.viewFeed = function() {
$state.go('feed', {sectionId: sectionId}); 18 18 $state.go('feed', {sectionId: sectionId});
console.log('go to feed'); 19 19 console.log('go to feed');
}; 20 20 };
21 21
// unhide card (dunno if it works yet) 22 22 // unhide card (dunno if it works yet)
$scope.unhide = function (card) { 23 23 $scope.unhide = function(card) {
$http.post('/api/flashcards/' + card.id + '/unhide'). 24 24 $http.post('/api/flashcards/' + card.id + '/unhide').
success(function (data) { 25 25 success(function(data) {
console.log(card.text + " unhidden"); 26 26 console.log(card.text + ' unhidden');
}). 27 27 }).
error(function (err) { 28 28 error(function(err) {
console.log('no unhide for you'); 29 29 console.log('no unhide for you');
}); 30 30 });
}; 31 31 };
32 32
// toggle button text from show to hide 33 33 // toggle button text from show to hide
$(function () { 34 34 $(function() {
$("#showHidden").click(function () { 35 35 $('#showHidden').click(function() {
$(this).text(function (i, text) { 36 36 $(this).text(function(i, text) {
return text === "Show Hidden" ? "Hide Hidden" : "Show Hidden"; 37 37 return text === 'Show Hidden' ? 'Hide Hidden' : 'Show Hidden';
}) 38 38 });
}); 39 39 });
}); 40 40 });
$scope.$on('$destroy', function () { 41 41 $scope.$on('$destroy', function() {
$rootScope.currentSection = {}; 42 42 $rootScope.currentSection = {};
$(document).off('keydown'); 43 43 $(document).off('keydown');
}); 44 44 });
45 45
} 46 46 }
); 47 47 );
48 48
scripts/DeckController.js View file @ 4c3a5e2
angular.module('flashy.DeckController', ['ui.router']). 1 1 angular.module('flashy.DeckController', ['ui.router']).
2 2
controller('DeckController', function ($scope, $rootScope, $state, $http, $stateParams) { 3 3 controller('DeckController', function($scope, $rootScope, $state, $http, $stateParams) {
// cards array 4 4 // cards array
sectionId = $stateParams.sectionId; 5 5 sectionId = $stateParams.sectionId;
$rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId}); 6 6 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
$scope.sectionId = sectionId; 7 7 $scope.sectionId = sectionId;
$scope.cards = []; 8 8 $scope.cards = [];
9 9
// Populate our page with cards. 10 10 // Populate our page with cards.
$http.get('/api/sections/' + sectionId + '/deck/'). 11 11 $http.get('/api/sections/' + sectionId + '/deck/').
success(function (data) { 12 12 success(function(data) {
console.log(data); 13 13 console.log(data);
$scope.cards = data; 14 14 $scope.cards = data;
}). 15 15 }).
error(function (err) { 16 16 error(function(err) {
console.log('pulling feed failed'); 17 17 console.log('pulling feed failed');
}); 18 18 });
19 19
/* Lets page refresh the cards shown on the page. */ 20 20 /* Lets page refresh the cards shown on the page. */
$scope.refreshCards = function () { 21 21 $scope.refreshCards = function() {
var myDelay = 200; // ms 22 22 var myDelay = 200; // ms
23 23
setTimeout(function () { 24 24 setTimeout(function() {
$http.get('/api/sections/' + sectionId + '/deck/'). 25 25 $http.get('/api/sections/' + sectionId + '/deck/').
success(function (data) { 26 26 success(function(data) {
console.log(data); 27 27 console.log(data);
$scope.cards = data; 28 28 $scope.cards = data;
console.log('success in refresh cards...'); 29 29 console.log('success in refresh cards...');
}). 30 30 }).
error(function (err) { 31 31 error(function(err) {
console.log('refresh fail'); 32 32 console.log('refresh fail');
}); 33 33 });
}, myDelay); 34 34 }, myDelay);
}; 35 35 };
$scope.$on('$destroy', function () { 36 36 $scope.$on('$destroy', function() {
$rootScope.currentSection = {}; 37 37 $rootScope.currentSection = {};
}); 38 38 });
} 39 39 }
); 40 40 );
41 41
scripts/FeedController.js View file @ 4c3a5e2
angular.module('flashy.FeedController', ['ui.router']). 1 1 angular.module('flashy.FeedController', ['ui.router']).
controller('FeedController', function ($scope, $rootScope, $stateParams, $state, $http) { 2 2 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http) {
console.log('Hello from feed'); 3 3 console.log('Hello from feed');
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
var loc = window.location, new_uri; 8 8 var loc = window.location, new_uri;
if (loc.protocol === 'https:') { 9 9 if (loc.protocol === 'https:') {
new_uri = 'wss:'; 10 10 new_uri = 'wss:';
} else { 11 11 } else {
new_uri = 'ws:'; 12 12 new_uri = 'ws:';
} 13 13 }
new_uri += '//' + loc.host; 14 14 new_uri += '//' + loc.host;
var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast'); 15 15 var ws = new WebSocket(new_uri + '/ws/feed/' + sectionId + '?subscribe-broadcast');
16 16
ws.onopen = function () { 17 17 ws.onopen = function() {
console.log('websocket connected'); 18 18 console.log('websocket connected');
}; 19 19 };
ws.onmessage = function (e) { 20 20 ws.onmessage = function(e) {
console.log('got websocket message ' + e.data); 21 21 console.log('got websocket message ' + e.data);
$scope.refreshCards(); 22 22 $scope.refreshCards();
}; 23 23 };
ws.onerror = function (e) { 24 24 ws.onerror = function(e) {
console.error(e); 25 25 console.error(e);
}; 26 26 };
ws.onclose = function (e) { 27 27 ws.onclose = function(e) {
console.log('connection closed'); 28 28 console.log('connection closed');
}; 29 29 };
30 30
$http.get('/api/sections/' + sectionId + '/feed/'). 31 31 $http.get('/api/sections/' + sectionId + '/feed/').
success(function (data) { 32 32 success(function(data) {
console.log(data); 33 33 console.log(data);
$scope.cards = data; 34 34 $scope.cards = data;
}). 35 35 }).
error(function (err) { 36 36 error(function(err) {
console.log('pulling feed failed'); 37 37 console.log('pulling feed failed');
}); 38 38 });
39 39
$scope.viewDeck = function () { 40 40 $scope.viewDeck = function() {
$state.go('deck', {sectionId: sectionId}); 41 41 $state.go('deck', {sectionId: sectionId});
console.log('go to deck'); 42 42 console.log('go to deck');
}; 43 43 };
44 44
$scope.pushCard = function () { 45 45 $scope.pushCard = function() {
var pushed = new Date(Date.now()); 46 46 var pushed = new Date(Date.now());
var i = 0; 47 47 var i = 0;
var blanks = []; 48 48 var blanks = [];
$('#new-card-input')[0].childNodes.forEach(function (node) { 49 49 $('#new-card-input')[0].childNodes.forEach(function(node) {
node = $(node)[0]; 50 50 node = $(node)[0];
console.log(node); 51 51 console.log(node);
if (node.tagName == 'B') { 52 52 if (node.tagName == 'B') {
text = $(node).text(); 53 53 text = $(node).text();
blanks.push([i, i + text.length]); 54 54 blanks.push([i, i + text.length]);
i += text.length; 55 55 i += text.length;
} else { 56 56 } else {
i += node.data.length; 57 57 i += node.data.length;
} 58 58 }
}); 59 59 });
console.log(blanks); 60 60 console.log(blanks);
text = $('#new-card-input').text(); 61 61 text = $('#new-card-input').text();
var myCard = { 62 62 var myCard = {
'text': text, 63 63 'text': text,
'material_date': pushed, 64 64 'material_date': pushed,
'mask': JSON.stringify(blanks), 65 65 'mask': JSON.stringify(blanks),
section: sectionId 66 66 section: sectionId
}; 67 67 };
$http.post('/api/flashcards/', myCard). 68 68 $http.post('/api/flashcards/', myCard).
success(function (data) { 69 69 success(function(data) {
console.log('pushed a card!'); 70 70 console.log('pushed a card!');
listenForC = true; 71 71 listenForC = true;
}). 72 72 }).
error(function (error) { 73 73 error(function(error) {
console.log('something went wrong pushing a card!'); 74 74 console.log('something went wrong pushing a card!');
}); 75 75 });
76 76
$('#new-card-input').html(''); 77 77 $('#new-card-input').html('');
}; 78 78 };
79 79
$scope.refreshCards = function () { 80 80 $scope.refreshCards = function() {
$http.get('/api/sections/' + sectionId + '/feed/'). 81 81 $http.get('/api/sections/' + sectionId + '/feed/').
success(function (data) { 82 82 success(function(data) {
console.log(data); 83 83 console.log(data);
$scope.cards = data; 84 84 $scope.cards = data;
console.log('success in refresh cards...'); 85 85 console.log('success in refresh cards...');
}). 86 86 }).
error(function (err) { 87 87 error(function(err) {
console.log('refresh fail'); 88 88 console.log('refresh fail');
}); 89 89 });
}; 90 90 };
91 91
/* Key bindings for the whole feed window. Hotkey it up! */ 92 92 /* Key bindings for the whole feed window. Hotkey it up! */
var listenForC = true; 93 93 var listenForC = true;
94 94
// Need to pass these options into openmodal and leanmodal, 95 95 // Need to pass these options into openmodal and leanmodal,
// otherwise the ready handler doesn't get called 96 96 // otherwise the ready handler doesn't get called
97 97
modal_options = { 98 98 modal_options = {
dismissible: true, // Modal can be dismissed by clicking outside of the modal 99 99 dismissible: true, // Modal can be dismissed by clicking outside of the modal
opacity: 0, // Opacity of modal background 100 100 opacity: 0, // Opacity of modal background
in_duration: 300, // Transition in duration 101 101 in_duration: 300, // Transition in duration
out_duration: 200, // Transition out duration 102 102 out_duration: 200, // Transition out duration
ready: function () { 103 103 ready: function() {
listenForC = false; 104 104 listenForC = false;
console.log('modal OPENING'); 105 105 console.log('modal OPENING');
$('#new-card-input').focus(); 106 106 $('#new-card-input').focus();
}, 107 107 },
complete: function () { 108 108 complete: function() {
listenForC = true; 109 109 listenForC = true;
console.log('modal done, closing'); 110 110 console.log('modal done, closing');
$('#new-card-input').blur(); 111 111 $('#new-card-input').blur();
} 112 112 }
}; 113 113 };
114 114
$(document).keydown(function (e) { 115 115 $(document).keydown(function(e) {
console.log(e.which); 116 116 console.log(e.which);
var keyed = e.which; 117 117 var keyed = e.which;
if (keyed == 67 && listenForC) { // "c" or "C" for compose 118 118 if (keyed == 67 && listenForC) { // "c" or "C" for compose
$('#newCard').openModal(modal_options); 119 119 $('#newCard').openModal(modal_options);
e.preventDefault(); 120 120 e.preventDefault();
listenForC = false; 121 121 listenForC = false;
return false; 122 122 return false;
} else if (keyed == 27) { // enter or esc, respectively 123 123 } else if (keyed == 27) { // enter or esc, respectively
listenForC = true; 124 124 listenForC = true;
document.getElementById('new-card-input').value = ''; 125 125 document.getElementById('new-card-input').value = '';
} 126 126 }
}); 127 127 });
$scope.flashcard = ''; 128 128 $scope.flashcard = '';
$scope.text = ''; 129 129 $scope.text = '';
var selected_start = 0; 130 130 var selected_start = 0;
var selected_end = 0; 131 131 var selected_end = 0;
$(document).ready(function () { 132 132 $(document).ready(function() {
// the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered 133 133 // the "href" attribute of .modal-trigger must specify the modal ID that wants to be triggered
$('.modal-trigger').leanModal(modal_options); 134 134 $('.modal-trigger').leanModal(modal_options);
$('#new-card-input').on('keydown', function (e) { 135 135 $('#new-card-input').on('keydown', function(e) {
if (e.which == 13) { 136 136 if (e.which == 13) {
e.preventDefault(); 137 137 e.preventDefault();
$scope.pushCard(); 138 138 $scope.pushCard();
$('#newCard').closeModal(modal_options); 139 139 $('#newCard').closeModal(modal_options);
return false; 140 140 return false;
} 141 141 }
}); 142 142 });
$('#new-card-input').on('mouseup', function () { 143 143 $('#new-card-input').on('mouseup', function() {
console.log('got selection: ' + selected_start); 144 144 console.log('got selection: ' + selected_start);
}); 145 145 });
$('button#blank-selected').click(function () { 146 146 $('button#blank-selected').click(function() {
console.log(window.getSelection()); 147 147 console.log(window.getSelection());
document.execCommand('bold'); 148 148 document.execCommand('bold');
}); 149 149 });
}); 150 150 });
151 151
$scope.$on('$destroy', function () { 152 152 $scope.$on('$destroy', function() {
ws.close(); 153 153 ws.close();
$rootScope.currentSection = {}; 154 154 $rootScope.currentSection = {};
$(document).off('keydown'); 155 155 $(document).off('keydown');
}); 156 156 });
157 157
}); 158 158 });
159 159
scripts/RootController.js View file @ 4c3a5e2
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) { 3 3 controller('RootController', function($rootScope, $resource, $scope, $state, UserService) {
$rootScope.SectionResource = $resource('/api/sections/:sectionId/'); 4 4 $rootScope.SectionResource = $resource('/api/sections/:sectionId/');
window.rootscope = $rootScope; 5 5 window.rootscope = $rootScope;
$rootScope.isLoggedIn = false; 6 6 $rootScope.isLoggedIn = false;
$rootScope.currentSection = {}; 7 7 $rootScope.currentSection = {};
UserService.getUserData().then(function (data) { 8 8 UserService.getUserData().then(function(data) {
console.log(data); 9 9 console.log(data);
$rootScope.user = data; 10 10 $rootScope.user = data;
}); 11 11 });
$('.button-collapse').sideNav({ 12 12 $('.button-collapse').sideNav({
menuWidth: 240, // Default is 240 13 13 menuWidth: 240, // Default is 240
edge: 'left', // Choose the horizontal origin 14 14 edge: 'left', // Choose the horizontal origin
closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor 15 15 closeOnClick: true // Closes side-nav on <a> clicks, useful for Angular/Meteor
} 16 16 }
); 17 17 );
}); 18 18 });
19 19
styles/flashy.css View file @ 4c3a5e2
.no-user-select { 1 1 .no-user-select {
-moz-user-select: none; 2 2 -moz-user-select: none;
-webkit-user-select: none; 3 3 -webkit-user-select: none;
-ms-user-select: none; 4 4 -ms-user-select: none;
user-select: none; 5 5 user-select: none;
} 6 6 }
7 7
.angucomplete-dropdown { 8 8 .angucomplete-dropdown {
border-color: #ececec; 9 9 border-color: #ececec;
border-width: 1px; 10 10 border-width: 1px;
border-style: solid; 11 11 border-style: solid;
border-radius: 2px; 12 12 border-radius: 2px;
/*width: 250px;*/ 13 13 /*width: 250px;*/
padding: 6px; 14 14 padding: 6px;
cursor: pointer; 15 15 cursor: pointer;
z-index: 9999; 16 16 z-index: 9999;
position: absolute; 17 17 position: absolute;
/*top: 32px; 18 18 /*top: 32px;
left: 0px; 19 19 left: 0px;
*/ 20 20 */
margin-top: -6px; 21 21 margin-top: -6px;
background-color: #ffffff; 22 22 background-color: #ffffff;
} 23 23 }
24 24
.angucomplete-description { 25 25 .angucomplete-description {
font-size: 14px; 26 26 font-size: 14px;
} 27 27 }
28 28
.angucomplete-row { 29 29 .angucomplete-row {
padding: 5px; 30 30 padding: 5px;
color: #000000; 31 31 color: #000000;
margin-bottom: 4px; 32 32 margin-bottom: 4px;
clear: both; 33 33 clear: both;
} 34 34 }
35 35
.angucomplete-selected-row { 36 36 .angucomplete-selected-row {
background-color: #aaaaff; 37 37 background-color: #aaaaff;
} 38 38 }
39 39
/*.container .row {*/ 40 40 /*.container .row {*/
/*margin-left: 0;*/ 41 41 /*margin-left: 0;*/
/*margin-right: 0;*/ 42 42 /*margin-right: 0;*/
/*}*/ 43 43 /*}*/
44 44
/* Flashcard directive css */ 45 45 /* Flashcard directive css */
.card { 46 46 .card {
word-wrap: break-word; 47 47 word-wrap: break-word;
} 48 48 }
49 49
.card.flashy { 50 50 .card.flashy {
background-color: #fff; 51 51 background-color: #fff;
font-family: 'Titillium Web', sans-serif; 52 52 font-family: 'Titillium Web', sans-serif;
float: left; 53 53 float: left;
text-align: center; 54 54 text-align: center;
margin: 6px; 55 55 margin: 6px;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1); 56 56 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1);
} 57 57 }
58 58
.card.flashy.shrinky { 59 59 .card.flashy.shrinky {
height: 0; 60 60 height: 0;
opacity: 0; 61 61 opacity: 0;
overflow: hidden; 62 62 overflow: hidden;
} 63 63 }
64 64
.card-overlay { 65 65 .card-overlay {
cursor: pointer; 66 66 cursor: pointer;
left: 0; 67 67 left: 0;
opacity: 0; 68 68 opacity: 0;
position: absolute; 69 69 position: absolute;
top: 0; 70 70 top: 0;
transition: visibility 0s cubic-bezier(0, 0, 0.6, 1) 0.2s, 71 71 transition: visibility 0s cubic-bezier(0, 0, 0.6, 1) 0.2s,
opacity 0.2s cubic-bezier(0, 0, 0.6, 1); 72 72 opacity 0.2s cubic-bezier(0, 0, 0.6, 1);
/* animation effect to appear on off-hover */ 73 73 /* animation effect to appear on off-hover */
visibility: hidden; 74 74 visibility: hidden;
height: 100%; 75 75 height: 100%;
width: 100%; 76 76 width: 100%;
} 77 77 }
78 78
.card-overlay i { 79 79 .card-overlay i {
color: #FFF; 80 80 color: #FFF;
left: 50%; 81 81 left: 50%;
position: absolute; 82 82 position: absolute;
top: 50%; 83 83 top: 50%;
transform: translate(-50%, -50%); 84 84 transform: translate(-50%, -50%);
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 85 85 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
} 86 86 }
87 87
.center-me:hover i { 88 88 .center-me:hover i {
text-shadow: 0 0 15px rgba(255, 255, 255, 0.9); 89 89 text-shadow: 0 0 15px rgba(255, 255, 255, 0.9);
} 90 90 }
91 91
.card:hover .card-overlay { 92 92 .card:hover .card-overlay {
opacity: 1.0; 93 93 opacity: 1.0;
transition-delay: 0s; /* animation effect to appear on hover */ 94 94 transition-delay: 0s; /* animation effect to appear on hover */
visibility: visible; 95 95 visibility: visible;
} 96 96 }
97 97
.top-box { 98 98 .top-box {
background-color: rgba(0, 184, 76, 0.5); 99 99 background-color: rgba(0, 184, 76, 0.5);
height: 65%; 100 100 height: 65%;
position: relative; 101 101 position: relative;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 102 102 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 100%; 103 103 width: 100%;
} 104 104 }
105 105
.top-box:hover { 106 106 .top-box:hover {
background-color: rgba(0, 184, 76, 0.6); 107 107 background-color: rgba(0, 184, 76, 0.6);
} 108 108 }
109 109
.bottom-box { 110 110 .bottom-box {
height: 35%; 111 111 height: 35%;
width: 100%; 112 112 width: 100%;
} 113 113 }
114 114
.left-box { 115 115 .left-box {
background-color: rgba(119, 146, 255, 0.5); 116 116 background-color: rgba(119, 146, 255, 0.5);
float: left; 117 117 float: left;
position: relative; 118 118 position: relative;
height: 100%; 119 119 height: 100%;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 120 120 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 50%; 121 121 width: 50%;
} 122 122 }
123 123
.left-box:hover { 124 124 .left-box:hover {
background-color: rgba(119, 146, 255, 0.6); 125 125 background-color: rgba(119, 146, 255, 0.6);
} 126 126 }
127 127
.right-box { 128 128 .right-box {
background-color: rgba(255, 62, 76, 0.5); 129 129 background-color: rgba(255, 62, 76, 0.5);
float: right; 130 130 float: right;
height: 100%; 131 131 height: 100%;
position: relative; 132 132 position: relative;
transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s; 133 133 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
width: 50%; 134 134 width: 50%;
} 135 135 }
136 136
.right-box:hover { 137 137 .right-box:hover {
background-color: rgba(255, 62, 76, 0.6); 138 138 background-color: rgba(255, 62, 76, 0.6);
} 139 139 }
140 140
.center-me { 141 141 .center-me {
height: 100%; 142 142 height: 100%;
margin: 0 auto; 143 143 margin: 0 auto;
text-align: center; 144 144 text-align: center;
vertical-align: middle; 145 145 vertical-align: middle;
width: 100%; 146 146 width: 100%;
} 147 147 }
148 148
.modal.bottom-sheet { 149 149 .modal.bottom-sheet {
max-width: 600px; 150 150 max-width: 600px;
margin-left: auto; 151 151 margin-left: auto;
margin-right: auto; 152 152 margin-right: auto;
} 153 153 }
154 154
#newCard input[type=text] { 155 155 #newCard input[type=text] {
height: 3rem !important; 156 156 height: 3rem !important;
} 157 157 }
158 158
.input-field label { 159 159 .input-field label {
color: #00b3c2; 160 160 color: #00b3c2;
} 161 161 }
162 162
/* label focus color */ 163 163 /* label focus color */
.input-field input[type]:focus + label { 164 164 .input-field input[type]:focus + label {
color: #00b3c2; 165 165 color: #00b3c2;
} 166 166 }
167 167
/* label underline focus color */ 168 168 /* label underline focus color */
.input-field input[type]:focus { 169 169 .input-field input[type]:focus {
border-bottom: 1px solid #00b3c2; 170 170 border-bottom: 1px solid #00b3c2;
box-shadow: 0 1px 0 0 #b388ff; 171 171 box-shadow: 0 1px 0 0 #b388ff;
} 172 172 }
173 173
/* valid color */ 174 174 /* valid color */
.input-field input[type].valid { 175 175 .input-field input[type].valid {
border-bottom: 1px solid #00c28f; 176 176 border-bottom: 1px solid #00c28f;
box-shadow: 0 1px 0 0 #673ab7; 177 177 box-shadow: 0 1px 0 0 #673ab7;
} 178 178 }
179 179
/* invalid color */ 180 180 /* invalid color */
.input-field input[type].invalid { 181 181 .input-field input[type].invalid {
border-bottom: 1px solid #673ab7; 182 182 border-bottom: 1px solid #673ab7;
box-shadow: 0 1px 0 0 #673ab7; 183 183 box-shadow: 0 1px 0 0 #673ab7;
} 184 184 }
185 185
/* icon prefix focus color */ 186 186 /* icon prefix focus color */
.input-field .prefix.active { 187 187 .input-field .prefix.active {
color: #b388ff; 188 188 color: #b388ff;
} 189 189 }
190 190
/* label focus color */ 191 191 /* label focus color */
.input-field textarea[type]:focus + label { 192 192 .input-field textarea[type]:focus + label {
color: #b388ff; 193 193 color: #b388ff;
} 194 194 }
195 195
/* label underline focus color */ 196 196 /* label underline focus color */
.input-field textarea[type]:focus { 197 197 .input-field textarea[type]:focus {
border-bottom: 1px solid #00b3c2; 198 198 border-bottom: 1px solid #00b3c2;
box-shadow: 0 1px 0 0 #b388ff; 199 199 box-shadow: 0 1px 0 0 #b388ff;
} 200 200 }
201 201
body { 202 202 body {
background-color: #e8e8e8; 203 203 background-color: #e8e8e8;
overflow-x: hidden; 204 204 overflow-x: hidden;
font-family: 'Titillium Web', sans-serif; 205 205 font-family: 'Titillium Web', sans-serif;
} 206 206 }
207 207
html { 208 208 html {
background: transparent; 209 209 background: transparent;
} 210 210 }
211 211
.btn { 212 212 .btn {
background-color: #00b3c2; 213 213 background-color: #00b3c2;
} 214 214 }
215 215
.btn:hover { 216 216 .btn:hover {
background-color: #0097cb; 217 217 background-color: #0097cb;
} 218 218 }
219 219
.btn-floating { 220 220 .btn-floating {
background-color: #00b3c2; 221 221 background-color: #00b3c2;
} 222 222 }
223 223
.btn-floating:hover { 224 224 .btn-floating:hover {
background-color: #0097cb; 225 225 background-color: #0097cb;
} 226 226 }
227 227
#logo-container { 228 228 #logo-container {
margin-bottom: 18px; 229 229 margin-bottom: 18px;
} 230 230 }
231 231
#lean-overlay { 232 232 #lean-overlay {
display: none !important; 233 233 display: none !important;