Commit 4f84f7f4e989970feac071890089c4ec7a81a3a3
Exists in
master
and in
1 other branch
Merge branch 'master' of git.ucsd.edu:110swag/flashy-frontend
Showing 19 changed files Side-by-side Diff
- config.js
- home.html
- sass/feed_animations.scss
- sass/flashier.scss
- scripts/CardListController.js
- scripts/ClassAddController.js
- scripts/DeckController.js
- scripts/FeedController.js
- scripts/FlashcardDirective.js
- scripts/RequestResetController.js
- scripts/RootController.js
- scripts/UserService.js
- styles/feed_animations.css
- styles/flashier.css
- styles/flashy.css
- templates/deck.html
- templates/feed.html
- templates/flashcard.html
- templates/requestpasswordreset.html
config.js
View file @
4f84f7f
... | ... | @@ -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(); |
home.html
View file @
4f84f7f
... | ... | @@ -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 | - © 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 | + © 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
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> |