Commit c138ea0909d15d29e5bd617963e5c774786c9a85
Exists in
master
and in
1 other branch
Merge branch 'master' of https://git.ucsd.edu/110swag/flashy-frontend
Showing 16 changed files Side-by-side Diff
- config.js
- home.html
- scripts/CardListController.js
- scripts/ClassAddController.js
- scripts/FeedController.js
- scripts/HelpController.js
- scripts/RootController.js
- scripts/SelectDirective.js
- scripts/StudyController.js
- scripts/UserService.js
- styles/flashy.css
- templates/addclass.html
- templates/cardlist.html
- templates/help.html
- templates/login.html
- templates/study.html
config.js
View file @
c138ea0
... | ... | @@ -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) { |
home.html
View file @
c138ea0
... | ... | @@ -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 | - © 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 | + © 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
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 & 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
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> |