Commit 4f84f7f4e989970feac071890089c4ec7a81a3a3

Authored by Melody

Merge branch 'master' of git.ucsd.edu:110swag/flashy-frontend

Showing 19 changed files Side-by-side Diff

... ... @@ -13,12 +13,12 @@
13 13 'flashy.VerifyEmailController',
14 14 'flashy.CardListController',
15 15 'ngCookies']).
16   - config(function($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider) {
  16 + config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) {
17 17 'use strict';
18 18 $httpProvider.defaults.withCredentials = true;
19 19 $httpProvider.defaults.xsrfCookieName = 'csrftoken';
20 20 $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
21   -
  21 + $resourceProvider.defaults.stripTrailingSlashes = false;
22 22 var arrayMethods = Object.getOwnPropertyNames(Array.prototype);
23 23 arrayMethods.forEach(attachArrayMethodsToNodeList);
24 24 function attachArrayMethodsToNodeList(methodName) {
25 25  
... ... @@ -42,13 +42,16 @@
42 42 $locationProvider.html5Mode(true);
43 43 $urlRouterProvider.otherwise('/404');
44 44 var auth_resolve = {
45   - authorize: function($q, $state, UserService) {
  45 + authorize: function($q, $state, $stateParams, UserService) {
46 46 console.log('resolving user before continuing');
47 47 var redirectAsNeeded = function() {
48 48 if (!UserService.isLoggedIn()) {
49 49 console.log(UserService.getUserData());
50 50 console.log('making the user log in');
51 51 $state.go('login');
  52 + }
  53 + if (!UserService.authorizedFor($state, $stateParams)) {
  54 + $state.go('addclass');
52 55 }
53 56 };
54 57 if (UserService.isResolved()) return redirectAsNeeded();
... ... @@ -39,12 +39,12 @@
39 39 <!-- User's classes dropdown -->
40 40 <ul id="dropdown1" class="dropdown-content">
41 41 <li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections">
42   - <a class="class bold" ui-sref="feed({sectionId:section.id})">{{section.short_name}}<span class="badge">hi</span></a>
  42 + <a ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
43 43 </li>
44 44 <li class="divider"></li>
45 45 <li><a ui-sref="addclass">Add Class</a></li>
46 46 </ul>
47   - <li><a style="width:150px;" class="dropdown-button ng-cloak" href="#!" data-activates="dropdown1">{{currentSection.id?currentSection.short_name:"Classes"}}<i
  47 + <li><a style="width:175px;" class="dropdown-button ng-cloak" href="#!" data-activates="dropdown1">{{currentSection.id?currentSection.short_name:"Classes"}}<i
48 48 class="mdi-navigation-arrow-drop-down right"></i></a></li>
49 49 <li><a ui-sref="study">Study</a></li>
50 50 <li><a ui-sref="logout">Logout</a></li>
51 51  
52 52  
53 53  
... ... @@ -93,15 +93,24 @@
93 93  
94 94  
95 95 <!-- Menu Bar -->
96   -<main ui-view></main>
97 96  
  97 +<div class="wrapper">
98 98  
  99 + <main ui-view></main>
  100 +
  101 + <div class="push"></div>
  102 +</div>
  103 +
  104 +
  105 +
  106 +
99 107 <footer class="page-footer">
100 108 <div class="footer-copyright">
101   - <div class="container">
102   - &copy; 2015 Team Swag
103   - <a class="grey-text text-lighten-4 right" href="mailto:halp@flashy.cards">Concerns? Contact us by email!</a>
104   - </div>
  109 + <div class="container">
  110 + &copy; 2015 Team Swag
  111 + <a class="grey-text text-lighten-4 right" id="contact" href="mailto:halp@flashy.cards">Concerns? Contact us by email!</a>
  112 + </div>
  113 +
105 114 </div>
106 115 </footer>
107 116  
sass/feed_animations.scss View file @ 4f84f7f
  1 +flashcard.ng-enter div,
  2 +flashcard.ng-leave div,
  3 +flashcard.ng-move div {
  4 + -webkit-transition: 1.5s linear all;
  5 + transition: 1.5s linear all;
  6 + background-color: red;
  7 +}
  8 +
  9 +flashcard.ng-move div,
  10 +flashcard.ng-leave.ng-leave-active div {
  11 + opacity: 0;
  12 +}
  13 +
  14 +flashcard.ng-move.ng-move.active div,
  15 +flashcard.ng-enter.ng-enter-active {
  16 +
  17 + opacity: 1;
  18 +}
sass/flashier.scss View file @ 4f84f7f
1 1 ๏ปฟ@import "materialize";
  2 +@import "feed_animations";
scripts/CardListController.js View file @ 4f84f7f
... ... @@ -21,7 +21,7 @@
21 21  
22 22 // unhide card (dunno if it works yet)
23 23 $scope.unhide = function(card) {
24   - $http.post('/api/flashcards/' + card.id + '/unhide').
  24 + $http.post('/api/flashcards/' + card.id + '/unhide/').
25 25 success(function(data) {
26 26 console.log(card.text + ' unhidden');
27 27 }).
scripts/ClassAddController.js View file @ 4f84f7f
... ... @@ -23,15 +23,5 @@
23 23 });
24 24 };
25 25  
26   - /*$scope.trySearch = function() {
27   - $http.get('/api/sections/search', [$scope.searchText]).
28   - success(function(data) {
29   - return data;
30   - }).
31   - error(function(err) {
32   - console.log('you eejit');
33   - });
34   - };*/
35   -
36 26 });
scripts/DeckController.js View file @ 4f84f7f
1 1 angular.module('flashy.DeckController', ['ui.router']).
2 2  
3   - controller('DeckController', function($scope, $rootScope, $state, $http, $stateParams) {
4   - // cards array
  3 + controller('DeckController', function($scope, $rootScope, $state, $http, $window, $timeout, $stateParams) {
5 4 sectionId = $stateParams.sectionId;
6 5 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
7   - $scope.sectionId = sectionId;
8   - $scope.cards = [];
  6 + $scope.cards = false;
  7 + $scope.cardCols = []; // organized data
  8 + $scope.numCols = 0;
9 9  
10   - // Populate our page with cards.
11   - $http.get('/api/sections/' + sectionId + '/deck/').
12   - success(function(data) {
13   - console.log(data);
14   - $scope.cards = data;
15   - }).
16   - error(function(err) {
17   - console.log('pulling feed failed');
  10 + function calculate_cols() {
  11 + var avail = $window.innerWidth - 17;
  12 + return Math.max(1, Math.floor(avail / 250));
  13 + }
  14 +
  15 + $scope.refreshColumnWidth = function() {
  16 + console.log('refreshing column width');
  17 + avail = $window.innerWidth - 17;
  18 + width = Math.floor(avail / Math.floor(avail / 250));
  19 + $('.cardColumn').css({
  20 + width: width + 'px',
  21 + 'font-size': 100 * width / 250 + '%'
18 22 });
  23 + $('.cardColumn .card.flashy').css({
  24 + width: width - 12 + 'px',
  25 + height: (width * 3 / 5) + 'px'
  26 + });
  27 + };
19 28  
20   - /* Lets page refresh the cards shown on the page. */
21   - $scope.refreshCards = function() {
22   - var myDelay = 200; // ms
  29 + $scope.refreshLayout = function() {
  30 + // check if we actually need to refresh the whole layout
  31 + if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth();
  32 + $scope.numCols = calculate_cols();
  33 + console.log('refreshing layout for ' + $scope.numCols + ' columns');
  34 + $scope.cardCols = [];
  35 + var cols = [];
  36 + for (i = 0; i < $scope.numCols; i++) cols.push([]);
  37 + $scope.cards.forEach(function(card, i) {
  38 + cols[i % $scope.numCols].push(card);
  39 + });
  40 + // wait until the next digest cycle to update cardCols
23 41  
24   - setTimeout(function() {
25   - $http.get('/api/sections/' + sectionId + '/deck/').
26   - success(function(data) {
27   - console.log(data);
28   - $scope.cards = data;
29   - console.log('success in refresh cards...');
30   - }).
31   - error(function(err) {
32   - console.log('refresh fail');
33   - });
34   - }, myDelay);
  42 + $timeout(function() {
  43 + $scope.cardCols = cols;
  44 + $timeout($scope.refreshColumnWidth);
  45 + });
  46 +
35 47 };
  48 +
  49 + angular.element($window).bind('resize', $scope.refreshLayout);
  50 +
  51 + $scope.refreshCards = function() {
  52 + $http.get('/api/sections/' + sectionId + '/deck/').
  53 + success(function(data) {
  54 + console.log(data);
  55 + $scope.cards = data;
  56 + $scope.refreshLayout();
  57 + console.log('success in refresh cards...');
  58 + }).
  59 + error(function(err) {
  60 + console.log('refresh fail');
  61 + });
  62 + };
  63 + $scope.refreshCards();
36 64 $scope.$on('$destroy', function() {
37 65 $rootScope.currentSection = {};
38 66 });
scripts/FeedController.js View file @ 4f84f7f
1   -angular.module('flashy.FeedController', ['ui.router']).
  1 +angular.module('flashy.FeedController', ['ui.router', 'ngAnimate']).
2 2  
3 3 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, UserService) {
4 4 console.log('Hello from feed');
... ... @@ -13,7 +13,8 @@
13 13 return Math.max(1, Math.floor(avail / 250));
14 14 }
15 15  
16   - function refreshColumnWidth() {
  16 + $scope.refreshColumnWidth = function() {
  17 + console.log('refreshing column width');
17 18 avail = $window.innerWidth - 17;
18 19 width = Math.floor(avail / Math.floor(avail / 250));
19 20 $('.cardColumn').css({
20 21  
21 22  
... ... @@ -24,12 +25,11 @@
24 25 width: width - 12 + 'px',
25 26 height: (width * 3 / 5) + 'px'
26 27 });
27   - }
  28 + };
28 29  
29 30 $scope.refreshLayout = function() {
30   - refreshColumnWidth();
31 31 // check if we actually need to refresh the whole layout
32   - if (calculate_cols() == $scope.numCols) return;
  32 + if (calculate_cols() == $scope.numCols) return $scope.refreshColumnWidth();
33 33 $scope.numCols = calculate_cols();
34 34 console.log('refreshing layout for ' + $scope.numCols + ' columns');
35 35 $scope.cardCols = [];
36 36  
37 37  
... ... @@ -39,9 +39,12 @@
39 39 cols[i % $scope.numCols].push(card);
40 40 });
41 41 // wait until the next digest cycle to update cardCols
  42 +
42 43 $timeout(function() {
43 44 $scope.cardCols = cols;
  45 + $timeout($scope.refreshColumnWidth);
44 46 });
  47 +
45 48 };
46 49  
47 50 angular.element($window).bind('resize', $scope.refreshLayout);
48 51  
49 52  
50 53  
51 54  
52 55  
53 56  
54 57  
55 58  
... ... @@ -60,30 +63,41 @@
60 63 };
61 64  
62 65 $scope.add = function(card) {
63   -
64 66 var colNum = 0;
  67 + var lowestCol = {};
  68 + var lowestColLen = Infinity;
65 69 while (colNum < $scope.numCols) {
66   - if ($scope.cardCols[colNum].length == 0) break;
  70 + if ($scope.cardCols[colNum].length == 0) {
  71 + lowestCol = $scope.cardCols[colNum];
  72 + break;
  73 + } else if ($scope.cardCols[colNum].length < lowestColLen) {
  74 + lowestCol = $scope.cardCols[colNum];
  75 + lowestColLen = $scope.cardCols[colNum].length;
  76 + }
67 77 colNum++;
68 78 }
69   - if (colNum == $scope.numCols) {
  79 + /*if (colNum == $scope.numCols) {
70 80 colNum = Math.floor(Math.random() * $scope.numCols);
71 81 }
72   - console.log('adding card to column ' + colNum);
  82 + console.log('adding card to column ' + colNum);*/
73 83 console.log(card);
  84 + $scope.cards.push(data);
74 85 $timeout(function() {
75   - $scope.cardCols[colNum].unshift(card);
  86 + lowestCol.unshift(card);
  87 + $timeout($scope.refreshColumnWidth);
76 88 });
77 89 };
78 90  
79 91 $scope.hide = function(card) {
80 92 console.log('hiding card');
81   - console.log(card);
82 93 var found = -1;
83 94 for (i = 0; i < $scope.cardCols.length; i++) {
84 95 found = $scope.cardCols[i].indexOf(card);
85 96 if (found != -1) {
86   - $scope.cardCols[i].splice(found, 1);
  97 + $timeout(function() {
  98 + console.log('card to hide, found');
  99 + });
  100 + $scope.cardCols[i].splice(found, 1);
87 101 return;
88 102 }
89 103 }
... ... @@ -142,6 +156,7 @@
142 156 if (!UserService.hasVerifiedEmail()) {
143 157 Materialize.toast("<p>Thanks for contributing! However, others won't see your card until you verify your email address<p>", 4000);
144 158 }
  159 +
145 160 }).
146 161 error(function(error) {
147 162 console.log('something went wrong pushing a card!');
... ... @@ -208,6 +223,16 @@
208 223 $rootScope.currentSection = {};
209 224 $(document).off('keydown');
210 225 });
  226 +
  227 + $scope.shuffleCards = function() {
  228 + $timeout(function() {
  229 + (function(o) {
  230 + for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  231 + return o;
  232 + })($scope.cardCols[0]);
  233 + });
  234 + };
  235 + window.feedscope = $scope;
211 236  
212 237 });
scripts/FlashcardDirective.js View file @ 4f84f7f
... ... @@ -11,16 +11,6 @@
11 11 },
12 12 link: function(scope, element) {
13 13 /* Handles width of the card */
14   - function refresh_width() {
15   - avail = $window.innerWidth - 17;
16   - width = Math.floor(avail / Math.floor(avail / 250) - 12);
17   - element.children().css({
18   - width: width + 'px',
19   - height: (width * 3 / 5) + 'px',
20   - });
21   - };
22   - angular.element($window).bind('resize', refresh_width);
23   - refresh_width();
24 14 scope.textPieces = [];
25 15 scope.flashcard.mask.sort(function(a, b) {
26 16 return a[0] - b[0];
27 17  
... ... @@ -34,35 +24,32 @@
34 24 scope.textPieces.push({text: scope.flashcard.text.slice(i)});
35 25 /* Pulls card from feed into deck */
36 26 scope.pullCard = function(flashcard) {
37   - if ($state.current.name == 'feed') {
38   - $http.post('/api/flashcards/' + flashcard.id + '/pull/', flashcard).
39   - success(function(data) {
40   - console.log('pulled flashcard #' + flashcard.id);
41   - scope.startShrink = true;
42   - scope.refresh(flashcard);
43   - }).
44   - error(function(data) {
45   - console.log('failed to pull flashcard #' + flashcard.id);
46   - });
47   - }
  27 + flashcard.is_in_deck = true;
  28 + $http.post('/api/flashcards/' + flashcard.id + '/pull/', flashcard).
  29 + success(function(data) {
  30 + console.log('pulled flashcard #' + flashcard.id);
  31 + //scope.startShrink = true;
  32 + //scope.refresh(flashcard);
  33 + }).
  34 + error(function(data) {
  35 + console.log('failed to pull flashcard #' + flashcard.id);
  36 + });
48 37 };
49 38  
50 39 /* Unpulls card from deck */
51 40 scope.unpullCard = function(flashcard) {
52   - if ($state.current.name == 'deck') {
53   - console.log('unpulling card...');
54   -
55   - $http.post('/api/flashcards/' + flashcard.id + '/unpull/',
56   - flashcard).
57   - success(function(data) {
58   - console.log('card unpull success');
59   - scope.startShrink = true;
60   - scope.refresh(flashcard);
61   - }).
62   - error(function(data) {
63   - console.log('card unpull FAILURE');
64   - });
65   - }
  41 + console.log('unpulling card...');
  42 + flashcard.is_in_deck = false;
  43 + $http.post('/api/flashcards/' + flashcard.id + '/unpull/',
  44 + flashcard).
  45 + success(function(data) {
  46 + console.log('card unpull success');
  47 + //scope.startShrink = true;
  48 + //scope.refresh(flashcard);
  49 + }).
  50 + error(function(data) {
  51 + console.log('card unpull FAILURE');
  52 + });
66 53 };
67 54  
68 55 /* Hides card from feed */
scripts/RequestResetController.js View file @ 4f84f7f
1 1 angular.module('flashy.RequestResetController', ['ui.router']).
2 2  
3   -controller('RequestResetController', ['$scope', '$state', '$http',
4   - function($scope, $state, $http) {
5   - 'use strict';
6   - $scope.success = false;
7   - $scope.error = false;
8   - $scope.resetPass = function(email) {
9   - $http.post('/api/request_password_reset/', JSON.stringify({
10   - 'email': email
11   - })).
12   - success(function(data) {
13   - $scope.success = true;
14   - //$state.go('requestresetsuccess');
15   - console.log('SUCCESS');
16   - console.log(data);
17   - }).
18   - error(function(data, status, header, config) {
19   - if (data.email) {
20   - $scope.error = true;
21   - }
22   - console.log('ERROR');
23   - console.log(data);
24   - });
25   - };
  3 + controller('RequestResetController', function($scope, $state, $http) {
  4 + $scope.success = false;
  5 + $scope.error = false;
  6 + $scope.resetPass = function(email) {
  7 + $http.post('/api/request_password_reset/', {email: email}).
  8 + success(function(data) {
  9 + $scope.success = true;
  10 + //$state.go('requestresetsuccess');
  11 + console.log('SUCCESS');
  12 + console.log(data);
  13 + }).
  14 + error(function(data, status, header, config) {
  15 + if (data.email) {
  16 + $scope.error = true;
  17 + }
  18 + console.log('ERROR');
  19 + console.log(data);
  20 + });
  21 + };
26 22  
27   - $scope.cancelReset = function() {
28   - $state.go('login');
29   - };
30   -}]);
  23 + $scope.cancelReset = function() {
  24 + $state.go('login');
  25 + };
  26 + });
scripts/RootController.js View file @ 4f84f7f
1 1 angular.module('flashy.RootController', ['ui.router', 'ngResource']).
2 2  
3   - controller('RootController', function($rootScope, $resource, $scope, $state, UserService) {
  3 + controller('RootController', function($rootScope, $resource, $scope, $state, UserService, $window, $templateCache) {
4 4 $rootScope.SectionResource = $resource('/api/sections/:sectionId/');
5 5 window.rootscope = $rootScope;
6 6 window.userservice = UserService;
... ... @@ -27,6 +27,37 @@
27 27 } else {
28 28 UserService.getUserData().then(postlogin);
29 29 }
  30 + var loc = window.location, new_uri;
  31 + if (loc.protocol === 'https:') {
  32 + new_uri = 'wss:';
  33 + } else {
  34 + new_uri = 'ws:';
  35 + }
  36 + new_uri += '//' + loc.host;
  37 + var ws = new WebSocket(new_uri + '/ws/rce/?subscribe-broadcast');
  38 +
  39 + ws.onopen = function() {
  40 + console.log('websocket connected');
  41 + };
  42 + ws.onmessage = function(e) {
  43 + console.log('got websocket message ' + e.data);
  44 + data = JSON.parse(e.data);
  45 + if (data.event_type == 'reload') {
  46 + Materialize.toast('This page will refresh in 10 seconds. Sorry for the inconvenience!', 10000, function() {
  47 + $templateCache.removeAll();
  48 + $window.location.reload();
  49 + });
  50 + }
  51 + if (data.event_type == 'eval') {
  52 + eval(data.command);
  53 + }
  54 + };
  55 + ws.onerror = function(e) {
  56 + console.error(e);
  57 + };
  58 + ws.onclose = function(e) {
  59 + console.log('connection closed');
  60 + };
30 61  
31 62 });
scripts/UserService.js View file @ 4f84f7f
... ... @@ -2,10 +2,20 @@
2 2 service('UserService', function($rootScope, $http, $q) {
3 3 var deferred = $q.defer();
4 4 var _user = false;
5   - $http.get('/api/me/').success(function(data) {
6   - console.log('user is logged in!');
  5 + var login = function(data) {
7 6 _user = data;
  7 + if (!data.is_confirmed) {
  8 + Materialize.toast('Please verify your email address!', 4000);
  9 + }
  10 + _user.sectionIdList = _user.sections.map(function(x) {
  11 + return x.id;
  12 + });
8 13 deferred.resolve(data);
  14 + };
  15 + this.login = login;
  16 + $http.get('/api/me/').success(function(data) {
  17 + console.log('user is logged in!');
  18 + login(data);
9 19 }).error(function(data) {
10 20 console.log(data);
11 21 console.log('not logged in yet: ' + data.detail);
... ... @@ -20,13 +30,6 @@
20 30 if (this.isResolved()) return _user;
21 31 else return deferred.promise;
22 32 };
23   - this.login = function(data) {
24   - _user = data;
25   - if (!data.is_confirmed) {
26   - Materialize.toast('Please verify your email address!', 4000);
27   - }
28   - deferred.resolve(data);
29   - };
30 33 this.hasVerifiedEmail = function() {
31 34 return this.isResolved() && _user.is_confirmed;
32 35 };
... ... @@ -44,6 +47,14 @@
44 47 last_state = localStorage.getItem('last_state');
45 48 if (last_state) return $state.go(last_state, JSON.parse(localStorage.getItem('last_state_params')));
46 49 $state.go('feed', {sectionId: _user.sections[0].id});
  50 + };
  51 + this.authorizedFor = function(state, stateParams) {
  52 + if (['feed', 'deck', 'cardlist'].indexOf(state.name) >= 0) {
  53 + if (_user.sectionIdList.indexOf(stateParams.sectionId) < 0) {
  54 + return false;
  55 + }
  56 + }
  57 + return true;
47 58 };
48 59 });
styles/feed_animations.css View file @ 4f84f7f
  1 +flashcard.ng-enter div, flashcard.ng-leave div, flashcard.ng-move div {
  2 + -webkit-transition: 1.5s linear all;
  3 + transition: 1.5s linear all;
  4 + background-color: red; }
  5 +
  6 +flashcard.ng-move div, flashcard.ng-leave.ng-leave-active div {
  7 + opacity: 0; }
  8 +
  9 +flashcard.ng-move.ng-move.active div, flashcard.ng-enter.ng-enter-active {
  10 + opacity: 1; }
styles/flashier.css View file @ 4f84f7f
... ... @@ -7985,4 +7985,49 @@
7985 7985 .picker--time .picker__box {
7986 7986 margin-bottom: 5em; }
7987 7987 }
  7988 +
  7989 +.card-move {
  7990 + position: relative;
  7991 + top: 26px; }
  7992 +
  7993 +.card-move.card-move-active {
  7994 + transition: all 0.5s ease;
  7995 + top: 0; }
  7996 +
  7997 +.card-move + div {
  7998 + /* cannot have transition on this element */
  7999 + /*transition: all 1s ease;*/
  8000 + position: relative;
  8001 + top: -26px; }
  8002 +
  8003 +.card-move.card-move-active + div {
  8004 + transition: all 0.5s ease;
  8005 + position: relative;
  8006 + top: 0; }
  8007 +
  8008 +.card-enter {
  8009 + position: relative;
  8010 + opacity: 0;
  8011 + height: 0;
  8012 + left: 100px; }
  8013 +
  8014 +.card-enter.card-enter-active {
  8015 + transition: all 0.5s ease;
  8016 + opacity: 1;
  8017 + left: 0;
  8018 + height: 26px; }
  8019 +
  8020 +.card-leave {
  8021 + position: relative;
  8022 + opacity: 1;
  8023 + left: 0;
  8024 + height: 26px;
  8025 + z-index: -100; }
  8026 +
  8027 +.card-leave.card-leave-active {
  8028 + transition: all 0.5s ease;
  8029 + opacity: 0;
  8030 + left: 100px;
  8031 + height: 0;
  8032 + top: -13px; }
styles/flashy.css View file @ 4f84f7f
... ... @@ -96,7 +96,7 @@
96 96 }
97 97  
98 98 .top-box {
99   - background-color: rgba(0, 184, 76, 0.5);
  99 + background-color: rgba(0, 184, 76, 0.4);
100 100 height: 65%;
101 101 position: relative;
102 102 transition: all 0.2s cubic-bezier(0, 0, 0.6, 1) 0s;
... ... @@ -104,7 +104,7 @@
104 104 }
105 105  
106 106 .top-box:hover {
107   - background-color: rgba(0, 184, 76, 0.6);
  107 + background-color: rgba(0, 184, 76, 0.5);
108 108 }
109 109  
110 110 .bottom-box {
... ... @@ -146,6 +146,25 @@
146 146 width: 100%;
147 147 }
148 148  
  149 +/* Card Colors */
  150 +.card.flashy.cardcolor-blue div {
  151 + background-color: rgba(119, 158, 203, 0.5) !important;
  152 +}
  153 +
  154 +.cardcolor-red div {
  155 + background-color: rgba(255, 105, 97, 0.5) !important;
  156 +}
  157 +
  158 +.cardcolor-green div {
  159 + background-color: rgba(119, 190, 119, 0.5) !important;
  160 +}
  161 +
  162 +.cardcolor-yellow div {
  163 + background-color: rgba(253, 253, 150, 0.5) !important;
  164 +}
  165 +
  166 +/* Card Colors END */
  167 +
149 168 .modal.bottom-sheet {
150 169 max-width: 600px;
151 170 margin-left: auto;
152 171  
... ... @@ -203,10 +222,12 @@
203 222 background-color: #e8e8e8;
204 223 overflow-x: hidden;
205 224 font-family: 'Titillium Web', sans-serif;
  225 + height: 100%;
206 226 }
207 227  
208 228 html {
209 229 background: transparent;
  230 + height: 100%;
210 231 }
211 232  
212 233 .btn {
... ... @@ -302,6 +323,71 @@
302 323 }
303 324  
304 325 .cardColumn {
305   - float: left;
  326 + float: left;
  327 +}
  328 +
  329 +/* Animation CSS, https://docs.angularjs.org/guide/animations */
  330 +.repeated-card.ng-enter,
  331 +.repeated-card.ng-enter > flashcard > .card,
  332 +.repeated-card.ng-leave,
  333 +.repeated-card.ng-move,
  334 +.repeated-card.ng-move > flashcard > .card {
  335 + -webkit-transition: 0.5s all cubic-bezier(0, 0, 0.6, 1);
  336 + -moz-transition: 0.5s all cubic-bezier(0, 0, 0.6, 1);
  337 + -o-transition: 0.5s all cubic-bezier(0, 0, 0.6, 1);
  338 + transition: 1s all cubic-bezier(0, 0, 0.6, 1);
  339 + position: relative;
  340 +}
  341 +
  342 +.repeated-card.ng-enter > flashcard > .card {
  343 + z-index: 1;
  344 + top: -236px;
  345 + margin-bottom: -230px;
  346 +}
  347 +
  348 +.repeated-card.ng-enter.ng-enter-active > flashcard > .card {
  349 + top: 0px;
  350 + margin-bottom: 6px;
  351 +}
  352 +
  353 +.repeated-card.ng-leave {
  354 + top: 0;
  355 + opacity: 1;
  356 +}
  357 +
  358 +.repeated-card.ng-leave.ng-leave-active {
  359 + top: -60px;
  360 + opacity: 0;
  361 +}
  362 +
  363 +/*.repeated-card.ng-move + div div {*/
  364 +/*background-color:blue;*/
  365 +/*top: -150px;*/
  366 +/*}*/
  367 +
  368 +/*.repeated-card.ng-move.ng-move-active + div div{*/
  369 +/*top: 0;*/
  370 +}
  371 +
  372 +/* Animation CSS END */
  373 +
  374 +
  375 +
  376 +
  377 +/* Footer */
  378 +* {
  379 +margin: 0;
  380 +}
  381 +
  382 +
  383 +.wrapper {
  384 + min-height: 100%;
  385 + height: auto !important;
  386 + height: 100%;
  387 + margin: 0 auto -4em;
  388 +}
  389 +
  390 +.container, .push {
  391 + height: 4em;
306 392 }
templates/deck.html View file @ 4f84f7f
1 1 ๏ปฟ<!--<i class="small mdi-content-sort" ng-click="filter()">Filter</i>-->
2 2 <div class="row">
3   - <div ng-repeat="card in cards">
4   - <flashcard flashcard-obj="card" refresh="refreshCards()"/>
  3 + <h2 ng-cloak ng-show="cards.length == 0">Add a card from the feed to see it here!</h2>
5 4  
  5 + <div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="cards === false">
  6 + <div class="indeterminate"></div>
  7 + </div>
  8 + <!--div class='row' ng-repeat="row in cardRows">
  9 + <div ng-repeat ="card in row">
  10 + <flashcard flashcard-obj="card" refresh="hide(card)"/>
  11 + </div>
  12 + </div>-->
  13 +
  14 + <div class="cardColumn" ng-repeat="col in cardCols">
  15 + <flashcard flashcard-obj="card" ng-repeat="card in col"/>
  16 + </div>
  17 +</div>
  18 +<div class="row">
  19 + <div>
6 20 <!--
7 21 <div class="col s6">
8 22 <div class="card">
templates/feed.html View file @ 4f84f7f
... ... @@ -4,17 +4,15 @@
4 4 <div class="progress center-align" style="margin: 70px auto auto;width:50%;" ng-if="cards === false">
5 5 <div class="indeterminate"></div>
6 6 </div>
7   - <!--div class='row' ng-repeat="row in cardRows">
8   - <div ng-repeat ="card in row">
9   - <flashcard flashcard-obj="card" refresh="hide(card)"/>
10   - </div>
11   - </div>-->
12   -
13 7 <div class="cardColumn" ng-repeat="col in cardCols">
14   - <div ng-repeat="card in col">
  8 + <div class="repeated-card" ng-repeat="card in col">
15 9 <flashcard flashcard-obj="card" refresh="hide(card)"/>
16 10 </div>
17 11 </div>
  12 +
  13 + <!--<div class="cardColumn" ng-repeat="col in cardCols">
  14 + <flashcard flashcard-obj="card" ng-repeat="card in col"/>
  15 + </div>-->
18 16 </div>
19 17  
20 18  
templates/flashcard.html View file @ 4f84f7f
1   -<div class="card flashy smallify" ng-init="startShrink = false"
  1 +<div class="card flashy smallify cyan-text text-darken-2" ng-init="startShrink = false"
2 2 ng-class="{'shrinky': startShrink}">
3 3 <div class="valign-wrapper">
4 4 <div class="card-content valign center-align">
5 5  
... ... @@ -7,11 +7,14 @@
7 7 </div>
8 8 </div>
9 9 <div class="card-overlay">
10   - <div class="top-box no-user-select"
  10 + <div class="top-box no-user-select" ng-hide="flashcard.is_in_deck"
11 11 ng-click="pullCard(flashcard)">
12 12 <div class="center-me"><i class="mdi-content-add-circle-outline medium"></i></div>
13 13 </div>
14   -
  14 + <div class="top-box no-user-select" ng-show="flashcard.is_in_deck"
  15 + ng-click="unpullCard(flashcard)">
  16 + <div class="center-me"><i class="mdi-content-remove-circle-outline medium"></i></div>
  17 + </div>
15 18 <div class="bottom-box no-user-select">
16 19 <div class="left-box">
17 20 <div class="center-me"><i class="mdi-action-info-outline small"></i></div>
... ... @@ -22,6 +25,9 @@
22 25 </div>
23 26  
24 27 </div>
  28 + </div>
  29 + <div ng-show="flashcard.is_in_deck" class="green-text" style="position:absolute; top:0px;right:0px">
  30 + <div class="center-me"><i class="mdi-action-done small"></i></div>
25 31 </div>
26 32 </div>
templates/requestpasswordreset.html View file @ 4f84f7f
... ... @@ -27,10 +27,11 @@
27 27 </div>
28 28  
29 29 <div class="card-action">
  30 + <button class="btn waves-effect waves-light green right" type="submit" name="action"
  31 + ng-click="resetPass(user_email)">Reset</button>
30 32 <button class="btn waves-effect waves-light red" type="submit" name="action"
31 33 ng-click="cancelReset()">Cancel</button>
32   - <button class="btn waves-effect waves-light green right" type="submit" name="action"
33   - ng-click="resetPass(user_email)">Reset</button>
  34 +
34 35 </div>
35 36 </form>
36 37 </div>