Commit c138ea0909d15d29e5bd617963e5c774786c9a85

Authored by Tetranoir

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

Showing 16 changed files Side-by-side Diff

... ... @@ -9,10 +9,13 @@
9 9 'flashy.StudyController',
10 10 'flashy.UserService',
11 11 'flashy.FlashcardDirective',
  12 + //'flashy.SelectDirective',
  13 + // DOESNT WORK RN
12 14 'flashy.ResetPasswordController',
13 15 'flashy.VerifyEmailController',
14 16 'flashy.CardListController',
15   - 'flashy.SettingsController',
  17 + 'flashy.HelpController',
  18 + 'flashy.SettingsController',
16 19 'ngCookies']).
17 20 config(function($stateProvider, $urlRouterProvider, $resourceProvider, $httpProvider, $locationProvider) {
18 21 'use strict';
19 22  
20 23  
21 24  
... ... @@ -26,16 +29,22 @@
26 29 if (methodName !== 'length') {
27 30 NodeList.prototype[methodName] = Array.prototype[methodName];
28 31 }
29   - };
  32 + }
30 33  
31   - $httpProvider.interceptors.push(function($q) {
  34 + $httpProvider.interceptors.push(function($q, $rootScope) {
32 35 return {
33 36 'responseError': function(rejection) { // need a better redirect
34 37 if (rejection.status >= 500) {
35 38 console.log('got error');
36 39 console.log(rejection);
37   - $('body').html('<div class="card">Sorry, the server is not serving requests properly. Try again later</div>');
  40 + $rootScope.$broadcast('server_error', rejection);
38 41 }
  42 + if (rejection.status == 403) {
  43 + console.log(rejection);
  44 + if (rejection.data && rejection.data.detail == 'Please verify your email before continuing') {
  45 + $rootScope.$broadcast('account_locked');
  46 + }
  47 + }
39 48 return $q.reject(rejection);
40 49 }
41 50 };
... ... @@ -73,7 +82,7 @@
73 82 }).
74 83 state('root', {
75 84 resolve: auth_resolve,
76   - url: '/',
  85 + url: '',
77 86 controller: 'RootController'
78 87 }).
79 88 state('feed', {
... ... @@ -112,12 +121,12 @@
112 121 templateUrl: 'templates/flashcard.html',
113 122 controller: 'FlashcardController'
114 123 }).
115   - state('settings', {
116   - resolve: auth_resolve,
117   - url: '/settings',
118   - templateUrl: 'templates/settings.html',
119   - controller: 'SettingsController'
120   - }).
  124 + state('settings', {
  125 + resolve: auth_resolve,
  126 + url: '/settings',
  127 + templateUrl: 'templates/settings.html',
  128 + controller: 'SettingsController'
  129 + }).
121 130 state('requestpasswordreset', {
122 131 url: '/requestpasswordreset',
123 132 templateUrl: 'templates/requestpasswordreset.html',
... ... @@ -137,6 +146,12 @@
137 146 state('404', {
138 147 url: '/404',
139 148 template: "<h1>This page doesn't exist!</h1>"
  149 + }).
  150 + state('help', {
  151 + resolve: auth_resolve,
  152 + url: '/help',
  153 + templateUrl: 'templates/help.html',
  154 + controller: 'HelpController'
140 155 });
141 156 }).
142 157 run(function($rootScope, $state, $stateParams, $location, UserService) {
... ... @@ -19,6 +19,20 @@
19 19 <a ng-show="UserService.isLoggedIn()" href="#" data-activates="mobile-demo"
20 20 class="left button-collapse hide-on-med-and-up"><i
21 21 class="mdi-navigation-menu"></i></a>
  22 + <!-- User's classes dropdown -->
  23 + <ul id="classDropdown" class="dropdown-content">
  24 + <li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections">
  25 + <a ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
  26 + </li>
  27 + <li class="divider"></li>
  28 + <li><a ui-sref="addclass">Add Class</a></li>
  29 + </ul>
  30 + <ul>
  31 + <li><a style="font-size:20px; font-weight:700" class="dropdown-button ng-cloak hide-on-small-and-down"
  32 + href="#!"
  33 + data-activates="classDropdown">{{currentSection.id?currentSection.short_name:"Classes"}}<i
  34 + class="mdi-navigation-arrow-drop-down right"></i></a></li>
  35 + </ul>
22 36 <ul ng-show="currentSection.id && UserService.isLoggedIn()" class="left hide-on-small-and-down">
23 37 <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped"
24 38 data-position="bottom"
25 39  
26 40  
27 41  
28 42  
... ... @@ -36,53 +50,51 @@
36 50 <a href="#" class="brand-logo center">Flashy</a>
37 51  
38 52 <ul ng-show="UserService.isLoggedIn()" ng-cloak id="nav-mobile" class="right hide-on-small-and-down">
39   - <!-- User's classes dropdown -->
40   - <ul id="classDropdown" class="dropdown-content">
41   - <li ui-sref-active="active" ng-repeat="section in UserService.getUserData().sections">
42   - <a ui-sref="feed({sectionId:section.id})">{{section.short_name}}</a>
43   - </li>
44   - <li class="divider"></li>
45   - <li><a ui-sref="addclass">Add Class</a></li>
  53 +
  54 + <li ui-sref-active="active"><a ui-sref="study" class="tooltipped" data-position="bottom" data-delay="50"
  55 + data-tooltip="Study">
  56 + <i class="tiny mdi-action-pageview"></i></a></li>
  57 +
  58 + <!-- Settings Dropdown -->
  59 + <ul id="settingsDropdown" class="dropdown-content">
  60 + <li><a ui-sref="settings">Settings</a></li>
  61 + <li><a ui-sref="logout">Logout</a></li>
46 62 </ul>
47   -
48   - <li><a style="width:175px;" class="dropdown-button ng-cloak" href="#!" data-activates="classDropdown">{{currentSection.id?currentSection.short_name:"Classes"}}<i
49   - class="mdi-navigation-arrow-drop-down right"></i></a></li>
50   - <li><a ui-sref="study">Study</a></li>
51   -
52   - <!-- Settings Dropdown -->
53   - <ul id="settingsDropdown" class="dropdown-content">
54   - <li><a ui-sref="settings">Settings</a></li>
55   - <li><a ui-sref="logout">Logout</a></li>
56   - </ul>
57   -
58   - <li><a class="dropdown-button ng-cloak" href="#!" data-activates="settingsDropdown"><i class="tiny mdi-action-settings"></i></a></li>
59   -
60   -
61   -
62   -
  63 + <li ui-sref-active="active"><a ui-sref="help"><i class="tiny mdi-action-help tooltipped"
  64 + data-position="bottom"
  65 + data-delay="50" data-tooltip="Help"></i></a></li>
  66 +
  67 + <li><a class="dropdown-button ng-cloak" href="#!" data-activates="settingsDropdown"><i
  68 + class="tiny mdi-action-settings"></i></a></li>
  69 +
  70 +
63 71 </ul>
64 72  
65 73 <!-- Slide-in side-nav for small screens -->
66 74 <ul ng-show="UserService.isLoggedIn()" class="side-nav" id="mobile-demo">
67 75 <span ng-show="currentSection.id">
68   - <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped"
69   - ><i
70   - class="mdi-action-view-module left"></i>Feed</a></li>
71   - <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped"
72   - ><i
73   - class="mdi-action-view-carousel left"></i>Deck</a></li>
74   - <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped"
75   - ><i
76   - class="mdi-action-view-list left"></i>Card List</a>
  76 + <li ui-sref-active="active"><a ui-sref="feed({sectionId:currentSection.id})" class="tooltipped">
  77 + <i class="mdi-action-view-module left"></i>
  78 + Feed</a>
77 79 </li>
  80 + <li ui-sref-active="active"><a ui-sref="deck({sectionId:currentSection.id})" class="tooltipped">
  81 + <i class="mdi-action-view-carousel left"> </i>
  82 + Deck
  83 + </a>
  84 + </li>
  85 + <li ui-sref-active="active"><a ui-sref="cardlist({sectionId:currentSection.id})" class="tooltipped">
  86 + <i class="mdi-action-view-list left"></i>
  87 + Card List
  88 + </a>
  89 + </li>
78 90 <hr>
79 91 </span>
80 92 <!-- Collapsible menu for all the User's classes -->
81 93 <ul class="collapsible" data-collapsible="accordion">
82 94 <li class="bold">
83 95 <a class="collapsible-header black-text">
84   - Classes<i
85   - class="mdi-navigation-arrow-drop-down right"></i>
  96 + Classes
  97 + <i class="mdi-navigation-arrow-drop-down right"></i>
86 98 </a>
87 99 </li>
88 100 <div class="collapsible-body" style="display: block">
... ... @@ -96,7 +108,7 @@
96 108 </div>
97 109 </ul>
98 110 <li><a ui-sref="study">Study</a></li>
99   - <li><a ui-sref="settings">Settings</a></li>
  111 + <li><a ui-sref="settings">Settings</a></li>
100 112 <li><a ui-sref="logout">Logout</a></li>
101 113 </ul>
102 114 </div>
103 115  
104 116  
105 117  
... ... @@ -109,20 +121,19 @@
109 121  
110 122 <div class="wrapper">
111 123  
112   - <main ui-view></main>
113   -
114   - <div class="push"></div>
  124 + <main ui-view></main>
  125 +
  126 + <div class="push"></div>
115 127 </div>
116   -
117 128  
118 129  
119   -
120 130 <footer class="page-footer">
121 131 <div class="footer-copyright">
122   - <div class="container">
123   - &copy; 2015 Team Swag
124   - <a class="grey-text text-lighten-4 right" id="contact" href="mailto:halp@flashy.cards">Concerns? Contact us by email!</a>
125   - </div>
  132 + <div class="container">
  133 + &copy; 2015 Team Swag
  134 + <a class="grey-text text-lighten-4 right" id="contact" href="mailto:halp@flashy.cards">Concerns? Contact us by
  135 + email!</a>
  136 + </div>
126 137  
127 138 </div>
128 139 </footer>
129 140  
... ... @@ -156,13 +167,14 @@
156 167 <script src="scripts/ResetPasswordController.js"></script>
157 168 <script src="scripts/CardListController.js"></script>
158 169 <script src="scripts/VerifyEmailController.js"></script>
159   -<!--<script src="scripts/SidebarController.js"></script>-->
  170 +<script src="scripts/HelpController.js"></script>
160 171  
161 172 <!-- Services -->
162 173 <script src="scripts/UserService.js"></script>
163 174  
164 175 <!-- Directives -->
165 176 <script src="scripts/FlashcardDirective.js"></script>
  177 +<script src="scripts/SelectDirective.js"></script>
166 178  
167 179 <!-- Other -->
168 180 <!--<script src="scripts/StudyController.js"></script>-->
scripts/CardListController.js View file @ c138ea0
... ... @@ -105,8 +105,7 @@
105 105 $(document).off('keydown');
106 106 });
107 107  
108   - // Tooltips!
109   - $(document).ready(function(){
  108 + $(document).ready(function() {
110 109 $('.tooltipped').tooltip({delay: 50});
111 110  
112 111 //back to top
113 112  
114 113  
115 114  
116 115  
117 116  
118 117  
119 118  
120 119  
... ... @@ -124,27 +123,27 @@
124 123 event.preventDefault();
125 124 jQuery('html, body').animate({scrollTop: 0}, duration);
126 125 return false;
127   - })
  126 + });
128 127 });
129 128  
130 129 // to display day of the week badges
131 130 $scope.dayofweek = function(item) {
132 131 var date = new Date(item.material_date);
133   - switch(date.getDay()) {
  132 + switch (date.getDay()) {
134 133 case 0:
135   - return "Su";
  134 + return 'Su';
136 135 case 1:
137   - return "M";
  136 + return 'M';
138 137 case 2:
139   - return "T";
  138 + return 'T';
140 139 case 3:
141   - return "W";
  140 + return 'W';
142 141 case 4:
143   - return "R";
  142 + return 'R';
144 143 case 5:
145   - return "F";
  144 + return 'F';
146 145 case 6:
147   - return "Sa";
  146 + return 'Sa';
148 147 }
149 148 };
150 149  
scripts/ClassAddController.js View file @ c138ea0
... ... @@ -14,7 +14,7 @@
14 14 $scope.submit = function() {
15 15 $http.post('/api/sections/' + $scope.selectedItem.id + '/enroll/').
16 16 success(function(data) {
17   - UserService.getUserData().sections.push($scope.selectedItem);
  17 + UserService.addClass($scope.selectedItem);
18 18 $state.go('feed', {sectionId: $scope.selectedItem.id});
19 19 }).
20 20 error(function(data, status, header, config) {
scripts/FeedController.js View file @ c138ea0
... ... @@ -2,12 +2,17 @@
2 2  
3 3 controller('FeedController', function($scope, $rootScope, $stateParams, $state, $http, $window, $timeout, UserService) {
4 4 console.log('Hello from feed');
5   - sectionId = $stateParams.sectionId;
  5 + sectionId = parseInt($stateParams.sectionId);
  6 + if (!UserService.isInSection(sectionId)) {
  7 + console.log('user is not enrolled in ' + sectionId);
  8 + return $state.go('addclass');
  9 + }
6 10 $rootScope.currentSection = $rootScope.SectionResource.get({sectionId: sectionId});
7 11 $scope.cards = false;
8 12 $scope.cardCols = []; // organized data
9 13 $scope.numCols = 0;
10 14  
  15 +
11 16 function calculate_cols() {
12 17 var avail = $window.innerWidth - 17;
13 18 return Math.max(1, Math.floor(avail / 250));
... ... @@ -59,6 +64,7 @@
59 64 }).
60 65 error(function(err) {
61 66 console.log('refresh fail');
  67 + console.log(err);
62 68 });
63 69 };
64 70  
65 71  
66 72  
... ... @@ -132,20 +138,20 @@
132 138 ws.onclose = function(e) {
133 139 console.log('connection closed');
134 140 };
135   -
136   - var resetModal = function() {
137   - $('#new-card-input').html('');
  141 +
  142 + var resetModal = function() {
  143 + $('#new-card-input').html('');
138 144 $('#newCard').closeModal(modal_options);
139   - }
140   -
  145 + };
  146 +
141 147 $scope.pushCard = function() {
142 148 var i = 0;
143 149 var blanks = [];
144 150 $('#new-card-input')[0].childNodes.forEach(function(node) {
145   - if (typeof node.data == 'undefined') {
146   - console.log('undefined node');
147   - return resetModal();
148   - }
  151 + if (typeof node.data == 'undefined') {
  152 + console.log('undefined node');
  153 + return resetModal();
  154 + }
149 155 node = $(node)[0];
150 156 console.log(node);
151 157 if (node.tagName == 'B') {
... ... @@ -161,10 +167,10 @@
161 167 'mask': blanks,
162 168 section: sectionId
163 169 };
164   - if (myCard.text == '') {
165   - console.log('blank flashcard not pushed:' + myCard.text);
166   - return resetModal();
167   - }
  170 + if (myCard.text == '') {
  171 + console.log('blank flashcard not pushed:' + myCard.text);
  172 + return resetModal();
  173 + }
168 174 $http.post('/api/flashcards/', myCard).
169 175 success(function(data) {
170 176 console.log('flashcard pushed: ' + myCard.text);
... ... @@ -176,7 +182,7 @@
176 182 error(function(error) {
177 183 console.log('something went wrong pushing a card!');
178 184 });
179   - return resetModal();
  185 + return resetModal();
180 186 };
181 187  
182 188 /* Key bindings for the whole feed window. Hotkey it up! */
scripts/HelpController.js View file @ c138ea0
  1 +angular.module('flashy.HelpController', ['ui.router']).
  2 + controller('HelpController', ['$scope', '$state', '$http', '$timeout', 'UserService',
  3 + function($scope, $state, $http, $timeout, UserService) {
  4 +
  5 + }
  6 + ]);
scripts/RootController.js View file @ c138ea0
... ... @@ -3,9 +3,8 @@
3 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   - window.userservice = UserService;
7 6 $rootScope.currentSection = {};
8   - $scope.UserService = UserService;
  7 + $rootScope.UserService = UserService;
9 8  
10 9  
11 10 //UserService.getUserData().then(function(data) {
... ... @@ -20,7 +19,7 @@
20 19 );
21 20 var postlogin = function(data) {
22 21 $scope.user = data;
23   - UserService.redirectToDefaultState($state);
  22 + //UserService.redirectToDefaultState($state);
24 23 };
25 24 if (UserService.isLoggedIn()) {
26 25 postlogin(UserService.getUserData());
... ... @@ -43,7 +42,7 @@
43 42 console.log('got websocket message ' + e.data);
44 43 data = JSON.parse(e.data);
45 44 if (data.event_type == 'reload') {
46   - Materialize.toast('This page will refresh in 10 seconds. Sorry for the inconvenience!', 10000, function() {
  45 + Materialize.toast('This page will refresh in 10 seconds and clear the template cache.', 10000, '', function() {
47 46 $templateCache.removeAll();
48 47 $window.location.reload();
49 48 });
... ... @@ -58,6 +57,19 @@
58 57 ws.onclose = function(e) {
59 58 console.log('connection closed');
60 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 +
  70 + $rootScope.$on('server_error', function(error) {
  71 + Materialize.toast('A server error occurred! Proceed with caution', 4000);
  72 + });
61 73  
62 74 });
scripts/SelectDirective.js View file @ c138ea0
  1 +/* Credits to vinciciusmelquiades:
  2 +https://github.com/viniciusmelquiades/firstExample/blob/master/app/src/directive/directive.js */
  3 +(function () {
  4 + 'use strict';
  5 +
  6 + angular.module('flashy.SelectDirective', [])
  7 + .directive('select', materialSelect);
  8 + console.log("coming inside directive");
  9 + materialSelect.$inject = ['$timeout'];
  10 +
  11 + function materialSelect($timeout) {
  12 + var directive = {
  13 + link: link,
  14 + restrict: 'E',
  15 + require: '?ngModel'
  16 + };
  17 +
  18 + function link(scope, element, attrs, ngModel) {
  19 + $timeout(create);
  20 +
  21 + if (ngModel) {
  22 + ngModel.$render = create;
  23 + }
  24 +
  25 + function create() {
  26 + element.material_select();
  27 + }
  28 +
  29 + //if using materialize v0.96.0 use this
  30 + element.one('$destroy', function () {
  31 + element.material_select('destroy');
  32 + });
  33 + }
  34 +
  35 + return directive;
  36 + }
  37 +
  38 +})();
scripts/StudyController.js View file @ c138ea0
... ... @@ -6,13 +6,16 @@
6 6 sectionId = $stateParams.sectionId;
7 7  
8 8 $(document).ready(function() {
9   - $('.datepicker').pickadate({
10   - selectMonths: true, // Creates a dropdown to control month
11   - selectYears: 15 // Creates a dropdown of 15 years to control year
12   - });
  9 + $('.datepicker').pickadate({
  10 + selectMonths: true, // Creates a dropdown to control month
  11 + selectYears: 15 // Creates a dropdown of 15 years to control year
  12 + });
  13 +
  14 + $('select').material_select();
13 15 });
14 16  
15 17 $scope.UserService = UserService;
  18 + $scope.isParamOpen = true;
16 19  
17 20 console.log($scope.UserService.getUserData().sections);
18 21  
... ... @@ -20,6 +23,15 @@
20 23 console.log('toggle sect', id);
21 24 $scope.sectionToStudy = id;
22 25 };
  26 +
  27 + $scope.openParams = function() {
  28 + $scope.isParamOpen = !$scope.isParamOpen;
  29 + }
  30 +
  31 + $scope.fetchQuiz = function (a,b) {
  32 + //console.log($scope.startDate, $scope.endDate);
  33 + console.log(a,b);
  34 + }
23 35  
24 36 /*
25 37 $scope.fetchQuiz = function() {
scripts/UserService.js View file @ c138ea0
... ... @@ -5,7 +5,9 @@
5 5 var login = function(data) {
6 6 _user = data;
7 7 if (!data.is_confirmed) {
8   - Materialize.toast('Please verify your email address!', 4000);
  8 + Materialize.toast('Please verify your email address! ' +
  9 + '<a class="btn-flat cyan-text" ng-click="UserService.resendConfirmationEmail()">' +
  10 + 'Resend Verification Email</a>', 4000);
9 11 }
10 12 _user.sectionIdList = _user.sections.map(function(x) {
11 13 return x.id;
12 14  
13 15  
... ... @@ -37,11 +39,19 @@
37 39 _user = false;
38 40 deferred.resolve({});
39 41 };
  42 + this.addClass = function(section) {
  43 + _user.sections.push(section);
  44 + _user.sectionIdList.push(section.id);
  45 + };
40 46 this.isLoggedIn = function() {
41 47 rv = this.isResolved() && _user.email;
42 48 return rv;
43 49 };
  50 + this.isInSection = function(sectionId) {
  51 + return (_user.sectionIdList.indexOf(sectionId) >= 0);
  52 + };
44 53 this.redirectToDefaultState = function($state) {
  54 + console.log('redirecting user to their default state');
45 55 if (!this.isLoggedIn()) return $state.go('login');
46 56 if (!_user.sections.length) return $state.go('addclass');
47 57 last_state = localStorage.getItem('last_state');
... ... @@ -55,6 +65,13 @@
55 65 }
56 66 }
57 67 return true;
  68 + };
  69 + 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 + console.log('Requesting resend of confirmation email');
  72 + $http.post('/api/resend_confirmation_email/').success(function() {
  73 + Materialize.toast('Resent confirmation email! Check your spam folder too.', 4000);
  74 + });
58 75 };
59 76 });
styles/flashy.css View file @ c138ea0
... ... @@ -322,13 +322,13 @@
322 322 height: 100%;
323 323 }
324 324  
325   -.toast {
  325 +/*.toast {
326 326 height: 100px;
327 327 width: 300px;
328 328 line-height: 20px;
329 329 max-height: 100px;
330 330 word-wrap: normal;
331   -}
  331 +}*/
332 332  
333 333 [ng-cloak] {
334 334 display: none !important;
... ... @@ -372,6 +372,7 @@
372 372 opacity: 0;
373 373 }
374 374  
  375 +
375 376 /*.repeated-card.ng-move + div div {*/
376 377 /*background-color:blue;*/
377 378 /*top: -150px;*/
... ... @@ -404,7 +405,7 @@
404 405 }
405 406  
406 407  
407   -#resetPasswordForm{
  408 +#resetPasswordForm
408 409 display: block;
409 410 margin-left: auto;
410 411 margin-right: auto;
... ... @@ -416,5 +417,29 @@
416 417 margin-right: auto;
417 418 display: block;
418 419 width: 200px;
  420 +}
  421 +
  422 +.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;
  428 +}
  429 +.dropping.ng-enter {
  430 + height: 0%;
  431 + opacity: 0;
  432 +}
  433 +.dropping.ng-enter-active {
  434 + height: 100%;
  435 + opacity: 1;
  436 +}
  437 +.dropping.ng-leave {
  438 + height: 100%;
  439 + opacity: 1;
  440 +}
  441 +.dropping.ng-leave-active {
  442 + opacity: 0;
  443 + height: 0%;
419 444 }
templates/addclass.html View file @ c138ea0
... ... @@ -17,6 +17,9 @@
17 17 >
18 18 <md-item-template>
19 19 <div layout="row">
  20 + <i ng-show="!item.can_enroll" class="mdi-action-lock" style="margin-right:10px;"></i>
  21 + <i ng-show="item.is_enrolled" class="mdi-action-done" style="margin-right:10px;"></i>
  22 +
20 23 <div>{{item.short_name}}: {{item.course_title}}
21 24 ({{item.instructor}})
22 25 </div>
23 26  
... ... @@ -29,13 +32,25 @@
29 32 No classes match "{{searchText}}".
30 33 </md-not-found>
31 34 </md-autocomplete>
32   - <button class="btn waves-effect waves-light" type="submit" name="add" ng-click="submit()">Add
  35 + <button class="btn waves-effect waves-light"
  36 + ng-class="(selectedItem && !selectedItem.is_enrolled && selectedItem.can_enroll)?'':'disabled'"
  37 + type="submit" name="add"
  38 + ng-click="(selectedItem.can_enroll && !selectedItem.is_enrolled)?submit():0">Add
33 39 <i class="mdi-content-add right"></i>
34 40 </button>
35 41 </div>
36 42  
37 43 </form>
38 44 </md-content>
  45 + <div ng-show="(selectedItem && !selectedItem.can_enroll)">
  46 + <h4>Restricted Enrollment</h4>
  47 + Enrollment in this section has been restricted at the request of the instructor. Contact your instructor for
  48 + permission to add this section.
  49 + </div>
  50 + <div ng-show="(selectedItem && selectedItem.is_enrolled)">
  51 + <h4>Already Enrolled</h4>
  52 + You've already enrolled in this section! <a ui-sref="feed({sectionId:selectedItem.id})">Go to Feed</a>.
  53 + </div>
39 54 </div>
40 55 </div>
41 56 </div>
templates/cardlist.html View file @ c138ea0
... ... @@ -66,22 +66,16 @@
66 66 <div>{{card.text}}
67 67 <span class="badge">{{dayofweek(card)}}</span>
68 68 <p class="right-align" ng-show="expand">
69   - <a href="" class="tooltipped" data-position="bottom" data-delay="50" data-tooltip="Add to Deck" ng-click="pull(card)" ng-show="!card.is_in_deck">
70   - <i class="mdi-content-add-circle-outline small"></i></a>
71   - <a href="" ng-click="unpull(card)" ng-show="card.is_in_deck"><i
72   - class="mdi-content-remove-circle-outline small tooltipped"
73   - data-position="bottom" data-delay="50"
74   - data-tooltip="Remove from Deck"></i></a>
75   - <a href="" ng-click="hide(card)" ng-show="!card.is_hidden"><i
76   - class="mdi-action-delete small tooltipped"
77   - data-position="bottom" data-delay="50"
78   - data-tooltip="Hide"></i></a>
79   - <a href="" ng-click="unhide(card)" ng-show="card.is_hidden"><i
80   - class="mdi-image-remove-red-eye small tooltipped"
81   - data-position="bottom" data-delay="50"
82   - data-tooltip="Unhide"></i></a>
83   - <a href="" ng-click="flag(card)"><i
84   - class="mdi-content-flag small"></i></a>
  69 + <a href="" class="tooltipped" ng-click="pull(card)" ng-show="!card.is_in_deck" data-position="bottom" data-delay="50" data-tooltip="Add to Deck">
  70 + <i class="mdi-content-add-circle-outline small"></i></a>
  71 + <a href="" class="tooltipped" ng-click="unpull(card)" ng-show="card.is_in_deck" data-position="bottom" data-delay="50" data-tooltip="Add to Deck">
  72 + <i class="mdi-content-remove-circle-outline small"></i></a>
  73 + <a href="" class="tooltipped" ng-click="hide(card)" ng-show="!card.is_hidden" data-position="bottom" data-delay="50" data-tooltip="Hide">
  74 + <i class="mdi-action-visibility-off small"></i></a>
  75 + <a href="" class="tooltipped" ng-click="unhide(card)" ng-show="card.is_hidden" data-position="bottom" data-delay="50" data-tooltip="Unhide">
  76 + <i class="mdi-action-visibility small"></i></a>
  77 + <a href="" ng-click="flag(card)">
  78 + <i class="mdi-content-flag small"></i></a>
85 79 </p>
86 80 </div>
87 81 </li>
templates/help.html View file @ c138ea0
  1 +<div class="container">
  2 + <div class="row">
  3 + <h2>FAQ</h2>
  4 + <a id="whatis"></a>
  5 + <h4>What is Flashy?</h4>
  6 +
  7 + <p>Flashy is a service for creating, sharing, and reviewing flashcards for courses. We combine two solutions to
  8 + shortcomings of other flashcard services. </p>
  9 +
  10 + <p>Flashy is optimized for contributing cards in real time during lecture to a shared live feed. Don't want to
  11 + contribute cards? That's fine! By choosing others' cards to add to your deck, you help us identify high-quality
  12 + cards which should remain at the top of the feed.</p>
  13 +
  14 + <p>Based on the principles of spaced repetition, Flashy also intelligently determines which cards you are most at
  15 + risk of forgetting, based on your review history. You can also enable push notifications on Android in Chrome without
  16 + installing an app! We'll notify you when you have a few cards which need to be reviewed.</p>
  17 +
  18 + <h4>Does Flashy work outside of UCSD?</h4>
  19 +
  20 + <p>To simplify development, Flashy was configured only for courses at UCSD. If you'd like Flashy for your school,
  21 + please send us an email to let us know!</p>
  22 + <a id="verification"></a>
  23 + <h4>How do registration &amp; verification work? </h4>
  24 +
  25 + <p>An account is required to use Flashy. We store the cards you save to your deck with your account.
  26 + When you register, you'll be able to use the site immediately, but you must
  27 + verify ownership of your email address within 24 hours. After 24 hours have passed, you'll need to verify your
  28 + address before continuing to use the site. Don't worry, your cards and deck won't be deleted.</p>
  29 + </div>
  30 +</div>
templates/login.html View file @ c138ea0
... ... @@ -52,6 +52,7 @@
52 52 ng-click="signUp(registerEmail, registerPassword)">Register
53 53 </button>
54 54 </div>
  55 +
55 56 </form>
56 57 </div>
57 58 <div class="row offset-s1 col s12">
templates/study.html View file @ c138ea0
1 1 <!-- Parameters for the studying -->
2   -<div class="row">
3   - <div class="col s6 offset-s3">
4   - <h3>Choose what to study</h3>
5   - <!-- lots of difficulty with materializecss select and angularjs. If we want to
6   - refactor into a select(which prob looks better), maybe refer to this article:
7   - http://stackoverflow.com/questions/29402495/values-not-showing-up-in-select-button
8   - -->
9   - <!-- Also suffered huge casualties trying to do radios...let's just do buttons...
10   - -->
11   - <a class="waves-effect waves-light btn toggley"
12   - ng-init="sectionToStudy = null"
13   - ng-click="toggleSectionToStudy(null)"
14   - ng-class="{'pink white-text': sectionToStudy == null}">
15   - All classes</a>
16   - <div ng-repeat="section in UserService.getUserData().sections">
17   - <a class="waves-effect waves-light btn toggley"
18   - ng-click="toggleSectionToStudy(section.id)"
19   - ng-class="{'pink white-text': sectionToStudy == section.id}">
20   - {{section.short_name}}</a>
21   - </div>
22 2  
23   - <input type="date" class="datepicker">
  3 +<div class="collapsible-header param-header"
  4 + ng-click="openParams()">
  5 +<i class="mdi-image-filter-drama"></i>Choose study settings</div>
  6 +
  7 +<div class="study-params dropping" ng-init="isParamOpen = true" ng-if="isParamOpen">
  8 + <div class="row">
  9 + <h3>Choose what to study</h3>
  10 + <!-- lots of difficulty with materializecss select and angularjs. If we want to
  11 + refactor into a select(which prob looks better), maybe refer to this article:
  12 + http://stackoverflow.com/questions/29402495/values-not-showing-up-in-select-button
  13 + -->
  14 + <!-- Also suffered huge casualties trying to do radios...let's just do buttons...
  15 + -->
  16 + <a class="waves-effect waves-light btn toggley"
  17 + ng-init="sectionToStudy = null"
  18 + ng-click="toggleSectionToStudy(null)"
  19 + ng-class="{'pink white-text': sectionToStudy == null}">
  20 + All classes</a>
  21 + <div ng-repeat="section in UserService.getUserData().sections">
  22 + <a class="waves-effect waves-light btn toggley"
  23 + ng-click="toggleSectionToStudy(section.id)"
  24 + ng-class="{'pink white-text': sectionToStudy == section.id}">
  25 + {{section.short_name}}
  26 + </a>
  27 + </div>
  28 +
  29 +<!--
  30 + <div class="input-field col s12">
  31 + <select ng-model="selectedClass"
  32 + ng-options="section.short_name for section in UserService.getUserData().sections">
  33 + </select>
  34 + <label>Materialize Select</label>
  35 + </div>
  36 + -->
24 37 </div>
25   -</div>
26 38  
27   -<div class="row">
28   - <div class="col s6 offset-s3">
29   - <div class="card-action">
30   - <button class="btn waves-effect waves-light" ng-click="fetchQuiz()">
31   - Fetch!
32   - <i class="mdi-content-send right"></i>
33   - </button>
34   - </div>
  39 + <div class="row">
  40 + <div class="card">
  41 + <h3>Choose Date</h3>
  42 + <input type="date" class="datepicker" ng-model="startDate" placeholder="Start Date"/>
  43 + <input type="date" class="datepicker" ng-model"endDate" placeholder="End Date"/>
  44 + </div>
35 45 </div>
  46 +
  47 + <div class="row">
  48 + <div class="card-action">
  49 + <button class="btn waves-effect waves-light" ng-click="fetchQuiz()">
  50 + Fetch!
  51 + <i class="mdi-content-send right"></i>
  52 + </button>
  53 + </div>
  54 + </div>
36 55 </div>
37 56  
  57 +
38 58 <!-- Fetched card "quiz" -->
39 59 <div class="row">
40   - <div class="col s6 offset-s3">
41 60 <div class="card">
42 61 <div class="card-content">
43 62 <span ng-repeat="display in displayText">{{display}}<input ng-model="blank[displayText.indexOf(display)]" ng-show="displayText.indexOf(display) < blankText.length" class="" type="text"/></span>
... ... @@ -48,6 +67,5 @@
48 67 </button>
49 68 </div>
50 69 </div>
51   - </div>
52 70 </div>