Commit df5215d6528a61305f0630bfc534d49cad12e01e

Authored by Rohan Rangray

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

Mergin conflicts after delayed pull

Showing 12 changed files Side-by-side Diff

... ... @@ -42,7 +42,8 @@
42 42 if (rejection.status == 403) {
43 43 console.log(rejection);
44 44 if (rejection.data && rejection.data.detail == 'Please verify your email before continuing') {
45   - $rootScope.$broadcast('account_locked');
  45 + UserService.showLockedMessage();
  46 + UserService.logout();
46 47 }
47 48 }
48 49 return $q.reject(rejection);
... ... @@ -53,7 +54,10 @@
53 54 $urlRouterProvider.otherwise('/404');
54 55 var auth_resolve = {
55 56 authorize: function($q, $state, $stateParams, UserService) {
56   - console.log('resolving user before continuing');
  57 + if (UserService.noAuthRequired($state)) {
  58 + return console.log('no auth state ' + $state.name);
  59 + }
  60 + console.log('resolving user before continuing for ' + $state.name);
57 61 var redirectAsNeeded = function() {
58 62 if (!UserService.isLoggedIn()) {
59 63 console.log(UserService.getUserData());
... ... @@ -61,6 +65,7 @@
61 65 $state.go('login');
62 66 }
63 67 if (!UserService.authorizedFor($state, $stateParams)) {
  68 + console.log('user not authorized for ' + $state.name);
64 69 $state.go('addclass');
65 70 }
66 71 };
... ... @@ -138,7 +143,6 @@
138 143 controller: 'ResetPasswordController'
139 144 }).
140 145 state('verifyemail', {
141   - resolve: auth_resolve,
142 146 url: '/verifyemail/{key}',
143 147 templateUrl: 'templates/verifyemail.html',
144 148 controller: 'VerifyEmailController'
... ... @@ -30,24 +30,25 @@
30 30 <li class="divider"></li>
31 31 <li><a ui-sref="addclass">Add Class</a></li>
32 32 </ul>
33   - <ul>
  33 + <ul ng-show="UserService.isLoggedIn()" class="left hide-on-small-and-down">
34 34 <li><a style="font-size:20px; font-weight:700" class="dropdown-button ng-cloak hide-on-small-and-down"
35 35 href="#!"
36 36 data-activates="classDropdown">{{currentSection.id?currentSection.short_name:"Classes"}}<i
37 37 class="mdi-navigation-arrow-drop-down right"></i></a></li>
38   - </ul>
39   - <ul ng-show="currentSection.id && UserService.isLoggedIn()" class="left hide-on-small-and-down">
40   - <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped"
41   - data-position="bottom"
42   - data-delay="50" data-tooltip="Feed"><i
  38 + <li ng-show="currentSection.id" ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})"
  39 + class="tooltipped"
  40 + data-position="bottom"
  41 + data-delay="50" data-tooltip="Feed"><i
43 42 class="mdi-action-view-module"></i></a></li>
44   - <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped"
45   - data-position="bottom"
46   - data-delay="50" data-tooltip="Deck"><i
  43 + <li ng-show="currentSection.id" ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})"
  44 + class="tooltipped"
  45 + data-position="bottom"
  46 + data-delay="50" data-tooltip="Deck"><i
47 47 class="mdi-action-view-carousel"></i></a></li>
48   - <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped"
49   - data-position="bottom"
50   - data-delay="50" data-tooltip="Card List"><i
  48 + <li ng-show="currentSection.id" ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})"
  49 + class="tooltipped"
  50 + data-position="bottom"
  51 + data-delay="50" data-tooltip="Card List"><i
51 52 class="mdi-action-view-list"></i></a></li>
52 53 </ul>
53 54 <a href="#" class="brand-logo center">Flashy</a>
54 55  
55 56  
... ... @@ -60,15 +61,18 @@
60 61  
61 62 <!-- Settings Dropdown -->
62 63 <ul id="settingsDropdown" class="dropdown-content">
63   - <li><a ui-sref="settings">Settings</a></li>
64   - <li><a ui-sref="logout">Logout</a></li>
  64 +
  65 +
65 66 </ul>
  67 +
66 68 <li ui-sref-active="active"><a ui-sref="help"><i class="tiny mdi-action-help tooltipped"
67 69 data-position="bottom"
68 70 data-delay="50" data-tooltip="Help"></i></a></li>
69   -
70   - <li><a class="dropdown-button ng-cloak" href="#!" data-activates="settingsDropdown"><i
71   - class="tiny mdi-action-settings"></i></a></li>
  71 + <li ui-sref-active="active"><a ui-sref="settings"><i data-position="bottom" data-delay="50"
  72 + data-tooltip="Settings"
  73 + class="mdi-action-settings tooltipped"></i></a></li>
  74 + <li><a ui-sref="logout"><i data-position="bottom" data-delay="50" data-tooltip="Logout"
  75 + class="mdi-content-forward tooltipped"></i></a></li>
72 76  
73 77  
74 78 </ul>
scripts/FeedController.js View file @ df5215d
... ... @@ -8,11 +8,12 @@
8 8 return $state.go('addclass');
9 9 }
10 10 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
  11 + $rootScope.debug_flashcard = false;
11 12 $scope.cards = false;
12 13 $scope.cardCols = []; // organized data
13 14 $scope.numCols = 0;
  15 + $scope.cardTable = {}; // look up table of cards, {'colNum':col, 'obj':card}
14 16  
15   -
16 17 function calculate_cols() {
17 18 var avail = $window.innerWidth - 17;
18 19 return Math.max(1, Math.floor(avail / 250));
... ... @@ -42,6 +43,7 @@
42 43 for (i = 0; i < $scope.numCols; i++) cols.push([]);
43 44 $scope.cards.forEach(function(card, i) {
44 45 cols[i % $scope.numCols].push(card);
  46 + $scope.cardTable[card.id] = {'colNum': (i % $scope.numCols), 'obj': card};
45 47 });
46 48 // wait until the next digest cycle to update cardCols
47 49  
48 50  
49 51  
50 52  
51 53  
52 54  
53 55  
54 56  
55 57  
... ... @@ -70,47 +72,74 @@
70 72  
71 73 $scope.add = function(card) {
72 74 var colNum = 0;
73   - var lowestCol = {};
74   - var lowestColLen = Infinity;
  75 + var lowestCol = $scope.cardCols[0];
  76 + var lowestColNum = 0;
75 77 while (colNum < $scope.numCols) {
76 78 if ($scope.cardCols[colNum].length == 0) {
77 79 lowestCol = $scope.cardCols[colNum];
78 80 break;
79   - } else if ($scope.cardCols[colNum].length < lowestColLen) {
  81 + } else if ($scope.cardCols[colNum].length < lowestCol.length) {
80 82 lowestCol = $scope.cardCols[colNum];
  83 + lowestColNum = colNum;
81 84 lowestColLen = $scope.cardCols[colNum].length;
82 85 }
83 86 colNum++;
84 87 }
85   - /*if (colNum == $scope.numCols) {
86   - colNum = Math.floor(Math.random() * $scope.numCols);
87   - }
88   - console.log('adding card to column ' + colNum);*/
89 88 console.log(card);
90 89 $scope.cards.push(data);
91 90 $timeout(function() {
92 91 lowestCol.unshift(card);
  92 + $scope.cardTable[card.id] = {'colNum': lowestColNum, 'obj': card};
93 93 $timeout($scope.refreshColumnWidth);
94 94 });
95 95 };
96 96  
  97 + $scope.sortAdd = function(card, array) {
  98 + console.log('sort add');
  99 + array.forEach(function(ele, i, ary) {
  100 + if (ele.score <= card.score) {
  101 + ary.splice(i, 0, card);
  102 + return;
  103 + }
  104 + });
  105 + };
  106 +
97 107 $scope.hide = function(card) {
98 108 console.log('hiding card');
99 109 var found = -1;
100   - for (i = 0; i < $scope.cardCols.length; i++) {
101   - found = $scope.cardCols[i].indexOf(card);
102   - if (found != -1) {
103   - $timeout(function() {
104   - console.log('card to hide, found');
105   - });
106   - $scope.cardCols[i].splice(found, 1);
107   - return;
108   - }
  110 + col = $scope.cardTable[card.id].colNum;
  111 + found = $scope.cardCols[col].indexOf(card);
  112 + if (found != -1) {
  113 + $scope.cardCols[col].splice(found, 1);
  114 + console.log('card hidden');
  115 + return col;
109 116 }
110 117 console.log('Error finding card to hide:');
111 118 console.log(card);
  119 + return -1;
112 120 };
113 121  
  122 + $scope.update = function(id, new_score) {
  123 + card = $scope.cardTable[id].obj;
  124 + if (Math.abs(new_score - card.score) < .0001) {
  125 + console.log('score same, no update required');
  126 + return;
  127 + }
  128 + console.log('updating');
  129 + console.log(card);
  130 + var column = $scope.cardCols[$scope.cardTable[id].colNum];
  131 + var found = column.indexOf(card);
  132 + var i = 0;
  133 + for (; i < column.length; i++)
  134 + if (column[i].score <= new_score) break;
  135 + card.score = new_score;
  136 + if ($scope.$$phase) { // most of the time it is "$digest"
  137 + column.splice(i, 0, column.splice(found, 1)[0]);
  138 + } else {
  139 + $scope.$apply(column.splice(i, 0, column.splice(found, 1)[0]));
  140 + }
  141 + };
  142 +
114 143 var loc = window.location, new_uri;
115 144 if (loc.protocol === 'https:') {
116 145 new_uri = 'wss:';
117 146  
118 147  
... ... @@ -124,13 +153,14 @@
124 153 console.log('websocket connected');
125 154 };
126 155 ws.onmessage = function(e) {
127   - console.log('got websocket message ' + e.data);
128 156 data = JSON.parse(e.data);
  157 + console.log('got websocket message ' + e.data);
  158 + console.log(data);
129 159 if (data.event_type == 'new_card') {
130 160 $scope.add(data.flashcard);
131 161 } else if (data.event_type == 'score_change') {
132   - //
133   - }
  162 + $scope.update(data.flashcard_id, data.new_score);
  163 + }
134 164 };
135 165 ws.onerror = function(e) {
136 166 console.error(e);
scripts/RootController.js View file @ df5215d
... ... @@ -57,15 +57,6 @@
57 57 ws.onclose = function(e) {
58 58 console.log('connection closed');
59 59 };
60   - $rootScope.$on('account_locked', function() {
61   - UserService.logout();
62   - if ($rootScope.locked_toast_active) return;
63   - $rootScope.locked_toast_active = true;
64   - Materialize.toast('Thanks for trying Flashy! To ensure quality content, we ask that you verify your email before continuing', 4000, '', function() {
65   - $rootScope.locked_toast_active = undefined;
66   - });
67   - $state.go('login');
68   - });
69 60  
70 61 $rootScope.$on('server_error', function(error) {
71 62 Materialize.toast('A server error occurred! Proceed with caution', 4000);
scripts/SelectDirective.js View file @ df5215d
1 1 /* Credits to vinciciusmelquiades:
2 2 https://github.com/viniciusmelquiades/firstExample/blob/master/app/src/directive/directive.js */
3   -(function () {
  3 +(function() {
4 4 'use strict';
5 5  
6 6 angular.module('flashy.SelectDirective', [])
7 7 .directive('select', materialSelect);
8   - console.log("coming inside directive");
  8 + console.log('coming inside directive');
9 9 materialSelect.$inject = ['$timeout'];
10 10  
11 11 function materialSelect($timeout) {
... ... @@ -27,7 +27,7 @@
27 27 }
28 28  
29 29 //if using materialize v0.96.0 use this
30   - element.one('$destroy', function () {
  30 + element.one('$destroy', function() {
31 31 element.material_select('destroy');
32 32 });
33 33 }
scripts/StudyController.js View file @ df5215d
... ... @@ -4,7 +4,8 @@
4 4 function($scope, $stateParams, $state, $http, UserService) {
5 5 console.log('Flashy study controller content in this file. also hell0');
6 6 sectionId = $stateParams.sectionId;
7   -
  7 + $scope.isParamOpen = true;
  8 +
8 9 $(document).ready(function() {
9 10 $('.datepicker').pickadate({
10 11 selectMonths: true, // Creates a dropdown to control month
11 12  
12 13  
... ... @@ -26,12 +27,12 @@
26 27  
27 28 $scope.openParams = function() {
28 29 $scope.isParamOpen = !$scope.isParamOpen;
29   - }
  30 + };
30 31  
31   - $scope.fetchQuiz = function (a,b) {
  32 + $scope.fetchQuiz = function(a, b) {
32 33 //console.log($scope.startDate, $scope.endDate);
33   - console.log(a,b);
34   - }
  34 + console.log(a, b);
  35 + };
35 36  
36 37 /*
37 38 $scope.fetchQuiz = function() {
scripts/UserService.js View file @ df5215d
... ... @@ -3,12 +3,16 @@
3 3 var deferred = $q.defer();
4 4 var _user = false;
5 5 var login = function(data) {
6   - _user = data;
  6 + if (data.locked) {
  7 + $rootScope.UserService.showLockedMessage();
  8 + return deferred.reject('account locked');
  9 + }
7 10 if (!data.is_confirmed) {
8 11 Materialize.toast('Please verify your email address! ' +
9   - '<a class="btn-flat cyan-text" ng-click="UserService.resendConfirmationEmail()">' +
  12 + '<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' +
10 13 'Resend Verification Email</a>', 4000);
11 14 }
  15 + _user = data;
12 16 _user.sectionIdList = _user.sections.map(function(x) {
13 17 return x.id;
14 18 });
15 19  
... ... @@ -66,8 +70,18 @@
66 70 }
67 71 return true;
68 72 };
  73 + this.showLockedMessage = function(){
  74 + Materialize.toast('You must verify your email address before continuing.' +
  75 + '<a class="btn-flat cyan-text" onclick="rootscope.UserService.resendConfirmationEmail()">' +
  76 + 'Resend Verification Email</a>', 4000);
  77 + }
  78 + this.noAuthRequired = function(state) {
  79 + if (['verifyemail'].indexOf(state.name) >= 0) {
  80 + return true;
  81 + }
  82 + return false;
  83 + };
69 84 this.resendConfirmationEmail = function() {
70   - if (!this.isLoggedIn()) return console.log("Can't request resending a confirmation email since the user is not logged in.");
71 85 console.log('Requesting resend of confirmation email');
72 86 $http.post('/api/resend_confirmation_email/').success(function() {
73 87 Materialize.toast('Resent confirmation email! Check your spam folder too.', 4000);
scripts/VerifyEmailController.js View file @ df5215d
... ... @@ -8,15 +8,15 @@
8 8 $scope.success = false;
9 9 $scope.error = false;
10 10  
11   - $http.patch('/api/me/', JSON.stringify({
  11 + $http.post('/api/verify_email/', JSON.stringify({
12 12 'confirmation_key': key
13 13 }))
14 14 .success(function(data) {
15 15 $scope.success = true;
16 16 console.log('SUCCESS');
17 17 console.log(data);
18   - $timeout(function($state) {
19   - $state.go('feed');
  18 + $timeout(function() {
  19 + $state.go('login');
20 20 }, 2000);
21 21 })
22 22 .error(function(data, status, header, config) {
styles/flashy.css View file @ df5215d
... ... @@ -172,11 +172,11 @@
172 172 }
173 173  
174 174 .feed-modal-input {
175   - background-color: #D3D3D3;
176   - //border-style: solid;
177   - //border-width: 1px;
178   - box-shadow: 2px 2px 5px #888888;
179   - height: 24px;
  175 + background-color: #D3D3D3;
  176 +/ / border-style : solid;
  177 +/ / border-width : 1 px;
  178 + box-shadow: 2px 2px 5px #888888;
  179 + height: 24px;
180 180 }
181 181  
182 182 #newCard input[type=text] {
183 183  
184 184  
... ... @@ -230,11 +230,12 @@
230 230 background-color: #e8e8e8;
231 231 overflow-x: hidden;
232 232 font-family: 'Titillium Web', sans-serif;
233   - height: 100%;
  233 + height: 100%;
234 234 }
  235 +
235 236 html {
236 237 background: transparent;
237   - height: 100%;
  238 + height: 100%;
238 239 }
239 240  
240 241 .btn {
241 242  
242 243  
243 244  
244 245  
245 246  
246 247  
247 248  
248 249  
249 250  
250 251  
251 252  
252 253  
253 254  
254 255  
255 256  
256 257  
... ... @@ -373,73 +374,62 @@
373 374 }
374 375  
375 376  
376   -/*.repeated-card.ng-move + div div {*/
377   -/*background-color:blue;*/
378   -/*top: -150px;*/
379   -/*}*/
380   -
381   -/*.repeated-card.ng-move.ng-move-active + div div{*/
382   -/*top: 0;*/
383   -}
384   -
385 377 /* Animation CSS END */
386 378  
387   -
388   -
389   -
390 379 /* Footer */
391 380 * {
392   -margin: 0;
  381 + margin: 0;
393 382 }
394 383  
395   -
396 384 .wrapper {
397   - min-height: 100%;
398   - height: auto !important;
399   - height: 100%;
400   - margin: 0 auto -4em;
  385 + min-height: 100%;
  386 + height: 100%;
  387 + margin: 0 auto -4em;
401 388 }
402 389  
403 390 .container, .push {
404   - height: 4em;
  391 + height: 4em;
405 392 }
406 393  
407   -
408   -#resetPasswordForm
409   - display: block;
410   - margin-left: auto;
411   - margin-right: auto;
412   - width: 500px;
  394 +#resetPasswordForm {
  395 + display: block;
  396 + margin-left: auto;
  397 + margin-right: auto;
  398 + width: 500px;
413 399 }
414 400  
415   -#resetPWButton{
416   - margin-left: auto;
417   - margin-right: auto;
418   - display: block;
419   - width: 200px;
  401 +#resetPWButton {
  402 + margin-left: auto;
  403 + margin-right: auto;
  404 + display: block;
  405 + width: 200px;
420 406 }
421 407  
422 408 .study-params {
423   - background-color: #f6f6f6;
424   - height: 100%;
425   - overflow: hidden;
426   - transition: all 1.2s cubic-bezier(0, 0, 0.6, 1);
427   - will-change: opacity;
  409 + background-color: #f6f6f6;
  410 + height: 100%;
  411 + overflow: hidden;
  412 + transition: all 1.2s cubic-bezier(0, 0, 0.6, 1);
  413 + will-change: opacity;
428 414 }
  415 +
429 416 .dropping.ng-enter {
430   - height: 0%;
431   - opacity: 0;
  417 + height: 0%;
  418 + opacity: 0;
432 419 }
  420 +
433 421 .dropping.ng-enter-active {
434   - height: 100%;
435   - opacity: 1;
  422 + height: 100%;
  423 + opacity: 1;
436 424 }
  425 +
437 426 .dropping.ng-leave {
438   - height: 100%;
439   - opacity: 1;
  427 + height: 100%;
  428 + opacity: 1;
440 429 }
  430 +
441 431 .dropping.ng-leave-active {
442   - opacity: 0;
443   - height: 0%;
  432 + opacity: 0;
  433 + height: 0;
444 434 }
templates/flashcard.html View file @ df5215d
... ... @@ -29,5 +29,8 @@
29 29 <div ng-show="flashcard.is_in_deck" class="green-text" style="position:absolute; top:0px;right:0px">
30 30 <div class="center-me"><i class="mdi-action-done small"></i></div>
31 31 </div>
  32 + <div ng-show="$root.debug_flashcard" style="position:absolute; bottom:0px; right:5px;">
  33 + <span class="center-me">score:{{flashcard.score}}</span>
  34 + </div>
32 35 </div>
templates/settings.html View file @ df5215d
1 1 <div class="card" id="resetPasswordForm">
2 2  
3   - <h2>Change Password</h2>
  3 + <h2>Change Password</h2>
4 4  
5   - <div class="row">
6   - <form class="col s12">
  5 + <div class="row">
  6 + <form class="col s12">
7 7  
8 8  
9   - <div class="row">
10   - <div class="input-field col s12">
11   - <input id="password" type="password" ng-model="oldPassword" class="validate">
12   - <label for="password">Old Password</label>
13   - </div>
14   - </div>
15   -
16   - <div class="row">
17   - <div class="input-field col s12">
18   - <input id="password" type="password" ng-model="newPassword" class="validate">
19   - <label for="password">New Password</label>
20   - </div>
21   - </div>
22   -
23   - <div class="row">
24   - <div class="input-field col s12">
25   - <input id="password" type="password" ng-model="confirmedNewPassword" class="validate">
26   - <label for="password">Confirm New Password</label>
27   - </div>
28   - </div>
29   -
30   -
31   - </form>
32   -
33   - <a class="waves-effect waves-light btn" id="resetPWButton" ng-click="changePassword(oldPassword, newPassword, confirmedNewPassword)">Reset Password</a>
34   -
35   - </div>
  9 + <div class="row">
  10 + <div class="input-field col s12">
  11 + <input id="password" type="password" ng-model="oldPassword" class="validate">
  12 + <label for="password">Old Password</label>
  13 + </div>
  14 + </div>
  15 +
  16 + <div class="row">
  17 + <div class="input-field col s12">
  18 + <input id="password" type="password" ng-model="newPassword" class="validate">
  19 + <label for="password">New Password</label>
  20 + </div>
  21 + </div>
  22 +
  23 + <div class="row">
  24 + <div class="input-field col s12">
  25 + <input id="password" type="password" ng-model="confirmedNewPassword" class="validate">
  26 + <label for="password">Confirm New Password</label>
  27 + </div>
  28 + </div>
  29 +
  30 +
  31 + </form>
  32 +
  33 + <a class="waves-effect waves-light btn" id="resetPWButton"
  34 + ng-click="changePassword(oldPassword, newPassword, confirmedNewPassword)">Reset Password</a>
  35 +
  36 + </div>
36 37 </div>
templates/study.html View file @ df5215d
... ... @@ -4,7 +4,7 @@
4 4 ng-click="openParams()">
5 5 <i class="mdi-image-filter-drama"></i>Choose study settings</div>
6 6  
7   -<div class="study-params dropping" ng-init="isParamOpen = true" ng-if="isParamOpen">
  7 +<div class="study-params dropping" ng-show="isParamOpen">
8 8 <div class="row">
9 9 <h3>Choose what to study</h3>
10 10 <!-- lots of difficulty with materializecss select and angularjs. If we want to