Commit 6c43d39c7ccec7028709ff36197cd564c8dc0fb0
Exists in
master
and in
7 other branches
Merge branch 'feature-proposal-vote'
Showing
15 changed files
with
283 additions
and
136 deletions
Show diff stats
src/app/components/article-service/article.service.js
@@ -162,20 +162,15 @@ | @@ -162,20 +162,15 @@ | ||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | - function voteProposal (proposal_id, params, cbSuccess, cbError){ | 165 | + function voteProposal (proposal_id, params){ |
166 | var url = service.apiArticles + proposal_id + '/vote'; | 166 | var url = service.apiArticles + proposal_id + '/vote'; |
167 | var paramsExtended = angular.extend({ | 167 | var paramsExtended = angular.extend({ |
168 | - private_token: $rootScope.currentUser.private_token | ||
169 | - // private_token: 'e2198fdbcc20409f082829b4b5c0848e' | 168 | + private_token: $rootScope.temporaryToken |
170 | }, params); | 169 | }, params); |
171 | 170 | ||
172 | var encodedParams = angular.element.param(paramsExtended); | 171 | var encodedParams = angular.element.param(paramsExtended); |
173 | 172 | ||
174 | - UtilService.post(url, encodedParams).then(function(response){ | ||
175 | - cbSuccess(response); | ||
176 | - }).catch(function(error){ | ||
177 | - cbError(error); | ||
178 | - }); | 173 | + return UtilService.post(url, encodedParams); |
179 | } | 174 | } |
180 | 175 | ||
181 | function getEvents (community_id, params) { | 176 | function getEvents (community_id, params) { |
src/app/components/auth/auth.service.js
@@ -53,11 +53,7 @@ | @@ -53,11 +53,7 @@ | ||
53 | } | 53 | } |
54 | 54 | ||
55 | function activate (code) { | 55 | function activate (code) { |
56 | - var url = PATH.host +'/api/v1/activate'; | ||
57 | - // var data = { | ||
58 | - // private_token: API.token, | ||
59 | - // activation_code: code | ||
60 | - // }; | 56 | + var url = PATH.host + '/api/v1/activate'; |
61 | var encodedData = 'private_token=' + API.token; | 57 | var encodedData = 'private_token=' + API.token; |
62 | encodedData += '&activation_code=' + code; | 58 | encodedData += '&activation_code=' + code; |
63 | 59 | ||
@@ -77,12 +73,7 @@ | @@ -77,12 +73,7 @@ | ||
77 | } | 73 | } |
78 | 74 | ||
79 | function changePassword (code, newPassword, newPasswordConfirmation){ | 75 | function changePassword (code, newPassword, newPasswordConfirmation){ |
80 | - var url = PATH.host +'/api/v1/new_password'; | ||
81 | - // var data = { | ||
82 | - // code: code, | ||
83 | - // password: newPassword, | ||
84 | - // password_confirmation: newPasswordConfirmation | ||
85 | - // }; | 76 | + var url = PATH.host + '/api/v1/new_password'; |
86 | var encodedData = 'code=' + code; | 77 | var encodedData = 'code=' + code; |
87 | encodedData += '&password=' + newPassword; | 78 | encodedData += '&password=' + newPassword; |
88 | encodedData += '&password_confirmation=' + newPasswordConfirmation; | 79 | encodedData += '&password_confirmation=' + newPasswordConfirmation; |
@@ -103,7 +94,7 @@ | @@ -103,7 +94,7 @@ | ||
103 | } | 94 | } |
104 | 95 | ||
105 | function forgotPassword (data){ | 96 | function forgotPassword (data){ |
106 | - var url = PATH.host +'/api/v1/forgot_password'; | 97 | + var url = PATH.host + '/api/v1/forgot_password'; |
107 | var encodedData = ([ | 98 | var encodedData = ([ |
108 | 'value=' + data.login, | 99 | 'value=' + data.login, |
109 | 'captcha_text=' + data.captcha_text, | 100 | 'captcha_text=' + data.captcha_text, |
@@ -145,9 +136,28 @@ | @@ -145,9 +136,28 @@ | ||
145 | }, function(response) { | 136 | }, function(response) { |
146 | $log.debug('AuthService.login [FAIL] response', response); | 137 | $log.debug('AuthService.login [FAIL] response', response); |
147 | $rootScope.$broadcast(AUTH_EVENTS.loginFailed); | 138 | $rootScope.$broadcast(AUTH_EVENTS.loginFailed); |
139 | + | ||
140 | + return $q.reject(response); | ||
148 | }); | 141 | }); |
149 | } | 142 | } |
150 | 143 | ||
144 | + function loginCaptcha (data) { | ||
145 | + var url = PATH.host + '/api/v1/login-captcha'; | ||
146 | + var encodedData = angular.element.param(data); | ||
147 | + | ||
148 | + return $http.post(url, encodedData).then(function(response){ | ||
149 | + // SUCCESS | ||
150 | + $log.debug('AuthService.loginCaptcha [SUCCESS] response', response); | ||
151 | + | ||
152 | + var temporaryToken = response.data.private_token; | ||
153 | + Session.setTemporaryToken(temporaryToken); | ||
154 | + $rootScope.temporaryToken = temporaryToken; | ||
155 | + return temporaryToken; | ||
156 | + }, function(response){ | ||
157 | + return $q.reject(response.data); | ||
158 | + }); | ||
159 | + } | ||
160 | + | ||
151 | function logout () { | 161 | function logout () { |
152 | 162 | ||
153 | Session.destroy(); | 163 | Session.destroy(); |
@@ -167,28 +177,13 @@ | @@ -167,28 +177,13 @@ | ||
167 | return (service.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1); | 177 | return (service.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1); |
168 | } | 178 | } |
169 | 179 | ||
170 | - // function _encodeObj(obj){ | ||
171 | - // var result = []; | ||
172 | - // var str = null; | ||
173 | - // var p = null; | ||
174 | - | ||
175 | - // for (p in obj) { | ||
176 | - // if (obj.hasOwnProperty(p)) { | ||
177 | - // // str = encodeURIComponent(p) + '=' + obj[p]; | ||
178 | - // str = p + '=' + obj[p]; | ||
179 | - // result.push(str); | ||
180 | - // } | ||
181 | - // } | ||
182 | - | ||
183 | - // return result.join('&'); | ||
184 | - // } | ||
185 | - | ||
186 | var service = { | 180 | var service = { |
187 | register: register, | 181 | register: register, |
188 | activate: activate, | 182 | activate: activate, |
189 | changePassword: changePassword, | 183 | changePassword: changePassword, |
190 | forgotPassword: forgotPassword, | 184 | forgotPassword: forgotPassword, |
191 | login: login, | 185 | login: login, |
186 | + loginCaptcha: loginCaptcha, | ||
192 | logout: logout, | 187 | logout: logout, |
193 | isAuthenticated: isAuthenticated, | 188 | isAuthenticated: isAuthenticated, |
194 | isAuthorized: isAuthorized | 189 | isAuthorized: isAuthorized |
@@ -207,7 +202,7 @@ | @@ -207,7 +202,7 @@ | ||
207 | 202 | ||
208 | service.create = function(data) { | 203 | service.create = function(data) { |
209 | 204 | ||
210 | - $localStorage.currentUser = data; | 205 | + $localStorage.currentUser = data.user; |
211 | $log.debug('User session created.', $localStorage.currentUser); | 206 | $log.debug('User session created.', $localStorage.currentUser); |
212 | 207 | ||
213 | return $localStorage.currentUser; | 208 | return $localStorage.currentUser; |
@@ -224,6 +219,14 @@ | @@ -224,6 +219,14 @@ | ||
224 | return $localStorage.currentUser; | 219 | return $localStorage.currentUser; |
225 | }; | 220 | }; |
226 | 221 | ||
222 | + service.setTemporaryToken = function (private_token) { | ||
223 | + $localStorage.temporaryToken = private_token; | ||
224 | + }; | ||
225 | + | ||
226 | + service.getTemporaryToken = function () { | ||
227 | + return $localStorage.temporaryToken; | ||
228 | + }; | ||
229 | + | ||
227 | return service; | 230 | return service; |
228 | } | 231 | } |
229 | 232 |
src/app/components/proposal-box/proposal-box.directive.js
@@ -9,30 +9,34 @@ | @@ -9,30 +9,34 @@ | ||
9 | function proposalBox() { | 9 | function proposalBox() { |
10 | 10 | ||
11 | /** @ngInject */ | 11 | /** @ngInject */ |
12 | - function ProposalBoxController($scope, $rootScope, $state, VOTE_STATUS, VOTE_OPTIONS, $log) { | 12 | + function ProposalBoxController($scope, $rootScope, $state, $timeout, $interval, $window, VOTE_STATUS, VOTE_OPTIONS, AuthService, DialogaService, $log) { |
13 | $log.debug('ProposalBoxController'); | 13 | $log.debug('ProposalBoxController'); |
14 | 14 | ||
15 | var vm = this; | 15 | var vm = this; |
16 | vm.$scope = $scope; | 16 | vm.$scope = $scope; |
17 | vm.$rootScope = $rootScope; | 17 | vm.$rootScope = $rootScope; |
18 | vm.$state = $state; | 18 | vm.$state = $state; |
19 | + vm.$timeout = $timeout; | ||
20 | + vm.$interval = $interval; | ||
21 | + vm.$window = $window; | ||
19 | vm.VOTE_STATUS = VOTE_STATUS; | 22 | vm.VOTE_STATUS = VOTE_STATUS; |
20 | vm.VOTE_OPTIONS = VOTE_OPTIONS; | 23 | vm.VOTE_OPTIONS = VOTE_OPTIONS; |
24 | + vm.AuthService = AuthService; | ||
21 | vm.$log = $log; | 25 | vm.$log = $log; |
22 | 26 | ||
23 | vm.init(); | 27 | vm.init(); |
24 | vm.addListeners(); | 28 | vm.addListeners(); |
25 | } | 29 | } |
26 | 30 | ||
27 | - ProposalBoxController.prototype.init = function () { | 31 | + ProposalBoxController.prototype.init = function() { |
28 | 32 | ||
29 | var vm = this; | 33 | var vm = this; |
30 | 34 | ||
31 | - vm.canVote = vm.canVote || false; | 35 | + vm.showVote = vm.showVote || false; |
32 | vm.focus = vm.focus || false; | 36 | vm.focus = vm.focus || false; |
33 | vm.STATE = null; | 37 | vm.STATE = null; |
34 | vm.errorOnSkip = false; | 38 | vm.errorOnSkip = false; |
35 | - vm.showAuthMessage = null; | 39 | + vm.showCaptchaForm = null; |
36 | vm.voteProposalRedirectURI = null; | 40 | vm.voteProposalRedirectURI = null; |
37 | 41 | ||
38 | var slug = vm.topic.slug; | 42 | var slug = vm.topic.slug; |
@@ -40,37 +44,52 @@ | @@ -40,37 +44,52 @@ | ||
40 | vm.voteProposalRedirectURI = 'state=programa&task=vote-proposal&slug=' + slug + '&proposal_id=' + proposal_id; | 44 | vm.voteProposalRedirectURI = 'state=programa&task=vote-proposal&slug=' + slug + '&proposal_id=' + proposal_id; |
41 | }; | 45 | }; |
42 | 46 | ||
43 | - ProposalBoxController.prototype.addListeners = function () { | 47 | + ProposalBoxController.prototype.addListeners = function() { |
44 | var vm = this; | 48 | var vm = this; |
45 | 49 | ||
46 | - vm.$scope.$on('proposal-box:proposal-loaded', function(event, data){ | ||
47 | - if(data.success){ | 50 | + vm.$scope.$on('proposal-box:proposal-loaded', function(event, data) { |
51 | + if (data.success) { | ||
48 | vm.STATE = null; | 52 | vm.STATE = null; |
49 | } | 53 | } |
50 | 54 | ||
51 | - if(data.error){ | 55 | + if (data.error) { |
52 | vm.errorOnSkip = data.error; | 56 | vm.errorOnSkip = data.error; |
53 | } | 57 | } |
54 | }); | 58 | }); |
55 | 59 | ||
56 | - vm.$scope.$on('proposal-box:vote-response', function(event, data){ | ||
57 | - vm.$log.debug('proposal-box:vote-response'); | ||
58 | - vm.$log.debug('event', event); | ||
59 | - vm.$log.debug('data', data); | ||
60 | - | ||
61 | - if(data.success) { | 60 | + vm.$scope.$on('proposal-box:vote-response', function(event, data) { |
61 | + if (data.success) { | ||
62 | vm.STATE = vm.VOTE_STATUS.SUCCESS; | 62 | vm.STATE = vm.VOTE_STATUS.SUCCESS; |
63 | } | 63 | } |
64 | 64 | ||
65 | - if(data.error) { | 65 | + if (data.error) { |
66 | vm.STATE = vm.VOTE_STATUS.ERROR; | 66 | vm.STATE = vm.VOTE_STATUS.ERROR; |
67 | } | 67 | } |
68 | 68 | ||
69 | - vm.message = data.message; | 69 | + if (data.code === 401) { |
70 | + vm.message = 'Não autorizado.'; | ||
71 | + } | ||
72 | + | ||
73 | + vm.messageCode = data.code; | ||
70 | }); | 74 | }); |
75 | + | ||
76 | + // Load captcha | ||
77 | + var stop = null; | ||
78 | + stop = vm.$interval(function() { | ||
79 | + var $el = angular.element('#serpro_captcha'); | ||
80 | + | ||
81 | + if ($el && $el.length > 0) { | ||
82 | + vm.$window.initCaptcha($el[0]); | ||
83 | + vm.$interval.cancel(stop); | ||
84 | + stop = undefined; | ||
85 | + }else { | ||
86 | + vm.$log.debug('captcha element not found.'); | ||
87 | + } | ||
88 | + | ||
89 | + }, 10); | ||
71 | }; | 90 | }; |
72 | 91 | ||
73 | - ProposalBoxController.prototype.showContent = function (slug) { | 92 | + ProposalBoxController.prototype.showContent = function(slug) { |
74 | var vm = this; | 93 | var vm = this; |
75 | 94 | ||
76 | vm.$state.go('programa', { | 95 | vm.$state.go('programa', { |
@@ -81,45 +100,106 @@ | @@ -81,45 +100,106 @@ | ||
81 | }); | 100 | }); |
82 | }; | 101 | }; |
83 | 102 | ||
84 | - ProposalBoxController.prototype.vote = function (value) { | 103 | + ProposalBoxController.prototype.canVote = function() { |
85 | var vm = this; | 104 | var vm = this; |
86 | 105 | ||
87 | - if(vm.$rootScope.currentUser){ | ||
88 | - vm.$scope.$emit('proposal-box:vote', { | ||
89 | - OPTION: value, | ||
90 | - proposal_id: vm.proposal.id | ||
91 | - }); | ||
92 | - vm.$log.debug('Sending vote', value); | ||
93 | - }else{ | ||
94 | - vm.$log.info('Must be logged in...'); | ||
95 | - vm.showAuthMessage = true; | ||
96 | - } | 106 | + return !!vm.$rootScope.temporaryToken; |
97 | }; | 107 | }; |
98 | 108 | ||
99 | - ProposalBoxController.prototype.voteDown = function () { | 109 | + ProposalBoxController.prototype.submitCaptcha = function($event, captchaForm) { |
100 | var vm = this; | 110 | var vm = this; |
101 | 111 | ||
102 | - vm.STATE = vm.VOTE_STATUS.LOADING; | ||
103 | - vm.$scope.$emit('proposal-box:vote', { | ||
104 | - OPTION: vm.VOTE_OPTIONS.DOWN, | ||
105 | - proposal_id: vm.proposal.id | 112 | + var target = $event.target; |
113 | + var $target = angular.element(target); | ||
114 | + var $captcha = $target.find('[name="txtToken_captcha_serpro_gov_br"]'); | ||
115 | + | ||
116 | + vm.sendingCaptcha = true; | ||
117 | + vm.AuthService.loginCaptcha({ | ||
118 | + captcha_text: captchaForm.captcha_text.$modelValue, | ||
119 | + txtToken_captcha_serpro_gov_br: $captcha.val() | ||
120 | + }).then(function(data) { | ||
121 | + // SUCCESS | ||
122 | + vm.$log.debug('register success.data', data); | ||
123 | + | ||
124 | + // SEND VOTE | ||
125 | + if (vm._oldVoteValue) { | ||
126 | + vm.vote(vm._oldVoteValue); | ||
127 | + vm._oldVoteValue = null; | ||
128 | + } | ||
129 | + // hide captcha form | ||
130 | + vm.showCaptchaForm = false; | ||
131 | + | ||
132 | + }, function(data) { | ||
133 | + // ERROR | ||
134 | + vm.$log.debug('register error.data', data); | ||
135 | + | ||
136 | + vm.sendingCaptchaError = { | ||
137 | + code: data.status, | ||
138 | + message: data.message || ('Erro (' + data.status + '). Já estamos trabalhando para resolver o problema.<br/>Por favor, tente novamente mais tarde') | ||
139 | + }; | ||
140 | + | ||
141 | + if (angular.equals(vm.sendingCaptchaError.message, 'Internal captcha validation error')) { | ||
142 | + vm.sendingCaptchaError.message = 'Erro interno ao tentar validar captcha.<br/><br/>Já estamos trabalhando para resolver o problema.<br/>Por favor, tente novamente mais tarde.'; | ||
143 | + } | ||
144 | + | ||
145 | + }, function(data) { | ||
146 | + // UPDATE | ||
147 | + vm.$log.debug('register update.data', data); | ||
148 | + }).finally(function() { | ||
149 | + vm.sendingCaptcha = false; | ||
106 | }); | 150 | }); |
107 | - vm.$log.debug('Sending vote'); | ||
108 | }; | 151 | }; |
109 | 152 | ||
110 | - ProposalBoxController.prototype.skip = function () { | 153 | + ProposalBoxController.prototype.captchaTryAgain = function() { |
154 | + var vm = this; | ||
155 | + | ||
156 | + vm.showCaptchaForm = true; | ||
157 | + vm.sendingCaptcha = false; | ||
158 | + vm.sendingCaptchaError = false; | ||
159 | + vm.message = null; | ||
160 | + | ||
161 | + // reload new captcha | ||
162 | + var $el = angular.element('#serpro_captcha'); | ||
163 | + vm.$window.reloadCaptcha($el[0]); | ||
164 | + | ||
165 | + // focus on input | ||
166 | + angular.element('#captcha_text').val('').focus(); | ||
167 | + }; | ||
168 | + | ||
169 | + ProposalBoxController.prototype.vote = function(value) { | ||
170 | + var vm = this; | ||
171 | + | ||
172 | + vm._oldVoteValue = value; | ||
173 | + if (vm.canVote()) { | ||
174 | + if (vm.doVote) { | ||
175 | + vm.doVote({ | ||
176 | + proposal_id: vm.proposal.id, | ||
177 | + value: value | ||
178 | + }); | ||
179 | + }else { | ||
180 | + vm.$log.error('No vote function to handler votes'); | ||
181 | + } | ||
182 | + }else { | ||
183 | + vm.$log.debug('You cannot vote.'); | ||
184 | + vm.showCaptchaForm = true; | ||
185 | + | ||
186 | + angular.element('#captcha_text').focus(); | ||
187 | + } | ||
188 | + }; | ||
189 | + | ||
190 | + ProposalBoxController.prototype.skip = function() { | ||
111 | var vm = this; | 191 | var vm = this; |
112 | 192 | ||
113 | vm.errorOnSkip = false; | 193 | vm.errorOnSkip = false; |
114 | vm.STATE = vm.VOTE_STATUS.LOADING; | 194 | vm.STATE = vm.VOTE_STATUS.LOADING; |
115 | - vm.$scope.$emit('proposal-box:vote', { | ||
116 | - OPTION: vm.VOTE_OPTIONS.SKIP, | ||
117 | - proposal_id: vm.proposal.id | 195 | + vm.doVote({ |
196 | + proposal_id: vm.proposal.id, | ||
197 | + value: vm.VOTE_OPTIONS.SKIP | ||
118 | }); | 198 | }); |
119 | vm.$log.debug('Sending vote'); | 199 | vm.$log.debug('Sending vote'); |
120 | }; | 200 | }; |
121 | 201 | ||
122 | - ProposalBoxController.prototype.getSocialUrl = function () { | 202 | + ProposalBoxController.prototype.getSocialUrl = function() { |
123 | var vm = this; | 203 | var vm = this; |
124 | 204 | ||
125 | return vm.$state.href('programa', { | 205 | return vm.$state.href('programa', { |
@@ -135,8 +215,9 @@ | @@ -135,8 +215,9 @@ | ||
135 | proposal: '=', | 215 | proposal: '=', |
136 | topic: '=', | 216 | topic: '=', |
137 | category: '=', | 217 | category: '=', |
138 | - canVote: '=', | ||
139 | - focus: '@' | 218 | + showVote: '=', |
219 | + focus: '@', | ||
220 | + doVote: '&' | ||
140 | // @ -> Text binding / one-way binding | 221 | // @ -> Text binding / one-way binding |
141 | // = -> Direct model binding / two-way binding | 222 | // = -> Direct model binding / two-way binding |
142 | // & -> Behaviour binding / Method binding | 223 | // & -> Behaviour binding / Method binding |
src/app/components/proposal-box/proposal-box.html
@@ -52,8 +52,10 @@ | @@ -52,8 +52,10 @@ | ||
52 | </div> | 52 | </div> |
53 | <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.ERROR"> | 53 | <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.ERROR"> |
54 | <p class="feedback--title">Erro!</p> | 54 | <p class="feedback--title">Erro!</p> |
55 | - <p class="feedback--message" ng-if="vm.message"> | ||
56 | - Motivo: {{vm.message}} | 55 | + <p class="feedback--message" ng-if="vm.messageCode === 401"> |
56 | + Não autorizado. Insira um novo captcha. | ||
57 | + <br> | ||
58 | + <button type="button" class="btn btn-link" ng-click="vm.captchaTryAgain()">Gerar novo captcha</button> | ||
57 | </p> | 59 | </p> |
58 | </div> | 60 | </div> |
59 | </div> | 61 | </div> |
@@ -65,18 +67,48 @@ | @@ -65,18 +67,48 @@ | ||
65 | </div> | 67 | </div> |
66 | </div> | 68 | </div> |
67 | </div> | 69 | </div> |
68 | - <div ng-show="vm.showAuthMessage"> | 70 | + <div ng-show="vm.showCaptchaForm"> |
69 | <div class="proposal-message-panel"> | 71 | <div class="proposal-message-panel"> |
70 | <div class="row"> | 72 | <div class="row"> |
71 | <div class="row-height"> | 73 | <div class="row-height"> |
72 | <div class="col-sm-12 col-height col-middle"> | 74 | <div class="col-sm-12 col-height col-middle"> |
73 | <div class="inside inside-full-height"> | 75 | <div class="inside inside-full-height"> |
74 | <div class="content text-center"> | 76 | <div class="content text-center"> |
75 | - <p>Você precisa estar logado para votar na proposta</p> | ||
76 | - <br> | ||
77 | - <p> | ||
78 | - <a ui-sref="entrar({redirect_uri: vm.voteProposalRedirectURI})">Clique aqui para ir para a página de login</a> | ||
79 | - </p> | 77 | + <div ng-show="vm.sendingCaptcha"> |
78 | + <p>Enviando captcha...</p> | ||
79 | + </div> | ||
80 | + <div ng-hide="vm.sendingCaptcha"> | ||
81 | + <div class="row feedback-message" ng-show="vm.sendingCaptchaError"> | ||
82 | + <div class="col-sm-12"> | ||
83 | + <div class="feedback--title alert alert-danger">Erro!</div> | ||
84 | + <div class="feedback--message" ng-if="!vm.message"> | ||
85 | + <p ng-bind-html="vm.sendingCaptchaError.message"></p> | ||
86 | + </div> | ||
87 | + <div> | ||
88 | + <button type="reset" class="btn btn-link" ng-click="vm.captchaTryAgain()">Tentar novamente</button> | ||
89 | + <button type="reset" class="btn btn-link" ng-click="vm.showCaptchaForm = false">Voltar</button> | ||
90 | + </div> | ||
91 | + </div> | ||
92 | + </div> | ||
93 | + <div ng-hide="vm.sendingCaptchaError"> | ||
94 | + <form name="captchaForm" ng-submit="vm.submitCaptcha($event, captchaForm)"> | ||
95 | + <div class="form-group"> | ||
96 | + <div id="serpro_captcha" class="captcha"></div> | ||
97 | + <div class="captcha">Digite os caracteres acima:</div> | ||
98 | + <div class="captcha"> | ||
99 | + <input type="text" name="captcha_text" id="captcha_text" aria-label="Escreva os caracteres do captcha aqui" ng-model="vm._captcha_text" ng-minlength="" ng-maxlength="" required> | ||
100 | + <validation-messages field="captchaForm.captcha_text"></validation-messages> | ||
101 | + </div> | ||
102 | + </div> | ||
103 | + <div class="form-group"> | ||
104 | + <button type="submit" class="btn btn-lg btn-block btn-submit">Enviar</button> | ||
105 | + </div> | ||
106 | + <div class="form-group"> | ||
107 | + <button type="reset" class="btn btn-link" ng-click="vm.showCaptchaForm = false">Voltar</button> | ||
108 | + </div> | ||
109 | + </form> | ||
110 | + </div> | ||
111 | + </div> | ||
80 | </div> | 112 | </div> |
81 | </div> | 113 | </div> |
82 | </div> | 114 | </div> |
@@ -112,12 +144,12 @@ | @@ -112,12 +144,12 @@ | ||
112 | <div class="proposal-box--content"> | 144 | <div class="proposal-box--content"> |
113 | <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div> | 145 | <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div> |
114 | </div> | 146 | </div> |
115 | - <div ng-hide="vm.canVote" class="proposal-box--join"> | 147 | + <div ng-hide="vm.showVote" class="proposal-box--join"> |
116 | <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)"> | 148 | <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)"> |
117 | Participe | 149 | Participe |
118 | </button> | 150 | </button> |
119 | </div> | 151 | </div> |
120 | - <div ng-show="vm.canVote" class="proposal-box--actions text-center"> | 152 | + <div ng-show="vm.showVote" class="proposal-box--actions text-center"> |
121 | <div class="row"> | 153 | <div class="row"> |
122 | <div class="col-xs-4"> | 154 | <div class="col-xs-4"> |
123 | <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)"> | 155 | <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)"> |
src/app/components/proposal-box/proposal-box.scss
@@ -91,9 +91,15 @@ | @@ -91,9 +91,15 @@ | ||
91 | .content { | 91 | .content { |
92 | color: #262626; | 92 | color: #262626; |
93 | font-size: 24px; | 93 | font-size: 24px; |
94 | + font-size: 2.4rem; | ||
94 | font-weight: bold; | 95 | font-weight: bold; |
95 | line-height: 24px; | 96 | line-height: 24px; |
96 | padding: 10px 30px; | 97 | padding: 10px 30px; |
98 | + | ||
99 | + form { | ||
100 | + font-size: 18px; | ||
101 | + font-size: 1.8rem; | ||
102 | + } | ||
97 | } | 103 | } |
98 | 104 | ||
99 | .message-icon { | 105 | .message-icon { |
@@ -108,11 +114,13 @@ | @@ -108,11 +114,13 @@ | ||
108 | 114 | ||
109 | &--title { | 115 | &--title { |
110 | font-size: 22px; | 116 | font-size: 22px; |
117 | + font-size: 2.2rem; | ||
111 | font-weight: bold; | 118 | font-weight: bold; |
112 | } | 119 | } |
113 | 120 | ||
114 | &--message { | 121 | &--message { |
115 | font-size: 14px; | 122 | font-size: 14px; |
123 | + font-size: 1.4rem; | ||
116 | font-weight: normal; | 124 | font-weight: normal; |
117 | line-height: 20px; | 125 | line-height: 20px; |
118 | margin-top: 48px; | 126 | margin-top: 48px; |
src/app/components/proposal-grid/proposal-grid.html
1 | <div class="proposal-grid row"> | 1 | <div class="proposal-grid row"> |
2 | <div ng-repeat="proposal in vm.proposals as results"> | 2 | <div ng-repeat="proposal in vm.proposals as results"> |
3 | - <proposal-box proposal="proposal" topic="proposal.parent" category="proposal.parent.categories[0]" class="col-xs-12 col-sm-6"></proposal-box> | 3 | + <proposal-box proposal="proposal" topic="proposal.parent" category="proposal.parent.categories[0]" show-vote="false" class="col-xs-12 col-sm-6"></proposal-box> |
4 | <div ng-if="$odd" class="clearfix"></div> | 4 | <div ng-if="$odd" class="clearfix"></div> |
5 | </div> | 5 | </div> |
6 | <div class="animate-repeat" ng-if="results.length == 0"> | 6 | <div class="animate-repeat" ng-if="results.length == 0"> |
src/app/components/proposal-list/proposal-list.directive.js
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | 31 | ||
32 | vm.$timeout(function(){ | 32 | vm.$timeout(function(){ |
33 | attachPopover.call(vm); | 33 | attachPopover.call(vm); |
34 | - }, 1000); | 34 | + }, 0); |
35 | }; | 35 | }; |
36 | 36 | ||
37 | ProposalListController.prototype.showContent = function (proposal) { | 37 | ProposalListController.prototype.showContent = function (proposal) { |
src/app/index.run.js
@@ -41,6 +41,7 @@ | @@ -41,6 +41,7 @@ | ||
41 | }); | 41 | }); |
42 | 42 | ||
43 | $rootScope.currentUser = $localStorage.currentUser; | 43 | $rootScope.currentUser = $localStorage.currentUser; |
44 | + $rootScope.temporaryToken = $localStorage.temporaryToken; | ||
44 | 45 | ||
45 | $log.debug('[RUN] Auth end.'); | 46 | $log.debug('[RUN] Auth end.'); |
46 | } | 47 | } |
src/app/layout.scss
@@ -9,7 +9,6 @@ | @@ -9,7 +9,6 @@ | ||
9 | display: table-cell; | 9 | display: table-cell; |
10 | float: none; | 10 | float: none; |
11 | height: 100%; | 11 | height: 100%; |
12 | - background-color: #181e21; | ||
13 | } | 12 | } |
14 | 13 | ||
15 | .col-top { | 14 | .col-top { |
@@ -206,6 +205,13 @@ | @@ -206,6 +205,13 @@ | ||
206 | margin-left: 10px; | 205 | margin-left: 10px; |
207 | padding: 0; | 206 | padding: 0; |
208 | border-radius: 100%; | 207 | border-radius: 100%; |
208 | + | ||
209 | + &:hover, | ||
210 | + &:focus, | ||
211 | + &:active { | ||
212 | + color: #fff; | ||
213 | + border-color: #fff; | ||
214 | + } | ||
209 | } | 215 | } |
210 | 216 | ||
211 | ul.list-color { | 217 | ul.list-color { |
@@ -224,7 +230,7 @@ ul.list-color li:before { | @@ -224,7 +230,7 @@ ul.list-color li:before { | ||
224 | } | 230 | } |
225 | 231 | ||
226 | ul.list-color li:before { | 232 | ul.list-color li:before { |
227 | - content: "• "; | 233 | + content: "\2022"; |
228 | font-weight: bold; | 234 | font-weight: bold; |
229 | font-size: 20px; | 235 | font-size: 20px; |
230 | position: relative; | 236 | position: relative; |
@@ -333,7 +339,7 @@ blockquote { | @@ -333,7 +339,7 @@ blockquote { | ||
333 | position: relative; | 339 | position: relative; |
334 | margin: 0px; | 340 | margin: 0px; |
335 | border-left: none; | 341 | border-left: none; |
336 | - // line-height: 28px; | 342 | + |
337 | &:before { | 343 | &:before { |
338 | content: "\231C"; | 344 | content: "\231C"; |
339 | font-size: 300px; | 345 | font-size: 300px; |
src/app/pages/programas/programa.controller.js
@@ -82,7 +82,10 @@ | @@ -82,7 +82,10 @@ | ||
82 | } | 82 | } |
83 | 83 | ||
84 | vm.loadingTopProposals = true; | 84 | vm.loadingTopProposals = true; |
85 | - vm.DialogaService.getProposalsByTopicId(vm.article.id, {}, function(data) { | 85 | + vm.DialogaService.getProposalsByTopicId(vm.article.id, { |
86 | + 'limit': 5 | ||
87 | + }, function(data) { | ||
88 | + vm.total_proposals = parseInt(data._obj.headers('total')); | ||
86 | vm.proposals = data.articles; | 89 | vm.proposals = data.articles; |
87 | vm.proposalsTopFive = vm.proposals.slice(0, 5); | 90 | vm.proposalsTopFive = vm.proposals.slice(0, 5); |
88 | vm.proposalsTopRated = vm.proposals.slice(0, 3); | 91 | vm.proposalsTopRated = vm.proposals.slice(0, 3); |
@@ -142,24 +145,6 @@ | @@ -142,24 +145,6 @@ | ||
142 | vm.proposalStatus = vm.PROPOSAL_STATUS.ERROR; | 145 | vm.proposalStatus = vm.PROPOSAL_STATUS.ERROR; |
143 | }); | 146 | }); |
144 | }); | 147 | }); |
145 | - | ||
146 | - vm.$scope.$on('proposal-box:vote', function(event, params) { | ||
147 | - // vm.$log.debug('event', event); | ||
148 | - // vm.$log.debug('params', params); | ||
149 | - var proposal_id = params.proposal_id; | ||
150 | - var OPTION = params.OPTION; | ||
151 | - | ||
152 | - switch (OPTION){ | ||
153 | - case vm.VOTE_OPTIONS.UP: | ||
154 | - case vm.VOTE_OPTIONS.DOWN: | ||
155 | - case vm.VOTE_OPTIONS.SKIP: | ||
156 | - vm.vote(proposal_id, OPTION); | ||
157 | - break; | ||
158 | - default: | ||
159 | - vm.$log.error('Vote option not handled:', OPTION); | ||
160 | - break; | ||
161 | - } | ||
162 | - }); | ||
163 | }; | 148 | }; |
164 | 149 | ||
165 | ProgramaPageController.prototype.loadProposalById = function(proposal_id) { | 150 | ProgramaPageController.prototype.loadProposalById = function(proposal_id) { |
@@ -219,31 +204,28 @@ | @@ -219,31 +204,28 @@ | ||
219 | return; | 204 | return; |
220 | } | 205 | } |
221 | 206 | ||
222 | - if (!vm.$rootScope.currentUser) { | ||
223 | - // vm.$state.go('entrar', { | ||
224 | - // redirect_uri: vm.sendProposalRedirectURI, | ||
225 | - // message: 'Você precisa estar logado para votar em uma proposta.' | ||
226 | - // }, { | ||
227 | - // location: true | ||
228 | - // }); | 207 | + if (!vm.$rootScope.temporaryToken) { |
208 | + vm.$log.debug('"temporaryToken" not defined. Abort.'); | ||
229 | return; | 209 | return; |
230 | } | 210 | } |
231 | 211 | ||
232 | vm.DialogaService.voteProposal(proposal_id, { | 212 | vm.DialogaService.voteProposal(proposal_id, { |
233 | value: value | 213 | value: value |
234 | - }, function(response) { | ||
235 | - vm.$log.debug('response', response); | 214 | + }).then(function(response) { |
215 | + vm.$log.debug('voteProposal response', response); | ||
236 | 216 | ||
237 | response.success = true; | 217 | response.success = true; |
238 | vm.$scope.$broadcast('proposal-box:vote-response', response); | 218 | vm.$scope.$broadcast('proposal-box:vote-response', response); |
239 | - }, function(error) { | ||
240 | - vm.$log.error('error', error); | 219 | + }, function(response) { |
220 | + vm.$log.debug('voteProposal error', response); | ||
221 | + | ||
222 | + response.error = true; | ||
223 | + vm.$scope.$broadcast('proposal-box:vote-response', response); | ||
224 | + }).finally(function(response){ | ||
225 | + vm.$log.debug('voteProposal finally', response); | ||
241 | 226 | ||
242 | - error.error = true; | ||
243 | - vm.$scope.$broadcast('proposal-box:vote-response', error); | ||
244 | }); | 227 | }); |
245 | }; | 228 | }; |
246 | - ProgramaPageController.prototype.voteHasBeenComputed = function() {}; | ||
247 | 229 | ||
248 | ProgramaPageController.prototype.showProposalsList = function() { | 230 | ProgramaPageController.prototype.showProposalsList = function() { |
249 | var vm = this; | 231 | var vm = this; |
src/app/pages/programas/programa.html
@@ -90,7 +90,14 @@ | @@ -90,7 +90,14 @@ | ||
90 | <div> | 90 | <div> |
91 | <div class="col-xs-12" ng-if="!pagePrograma.loadingProposalBox && pagePrograma.randomProposal" ng-class="{'focused-proposal': !!pagePrograma.search.proposal_id}"> | 91 | <div class="col-xs-12" ng-if="!pagePrograma.loadingProposalBox && pagePrograma.randomProposal" ng-class="{'focused-proposal': !!pagePrograma.search.proposal_id}"> |
92 | <h3 class="color-theme-fg">Apoie outras propostas</h3> | 92 | <h3 class="color-theme-fg">Apoie outras propostas</h3> |
93 | - <proposal-box proposal="pagePrograma.randomProposal" topic="pagePrograma.article" category="pagePrograma.category" can-vote="true" focus="{{pagePrograma.search.proposal_id}}" ></proposal-box> | 93 | + <proposal-box |
94 | + proposal="pagePrograma.randomProposal" | ||
95 | + topic="pagePrograma.article" | ||
96 | + category="pagePrograma.category" | ||
97 | + show-vote="true" | ||
98 | + focus="{{pagePrograma.search.proposal_id}}" | ||
99 | + do-vote="pagePrograma.vote(proposal_id, value)" | ||
100 | + ></proposal-box> | ||
94 | </div> | 101 | </div> |
95 | 102 | ||
96 | <!-- Loading Proposal Box --> | 103 | <!-- Loading Proposal Box --> |
@@ -133,7 +140,7 @@ | @@ -133,7 +140,7 @@ | ||
133 | <div class="row"> | 140 | <div class="row"> |
134 | <div class="col-xs-12"> | 141 | <div class="col-xs-12"> |
135 | <a ui-sref="ranking({tema: pagePrograma.category.slug, programa: pagePrograma.article.slug})" class="btn btn-link"> | 142 | <a ui-sref="ranking({tema: pagePrograma.category.slug, programa: pagePrograma.article.slug})" class="btn btn-link"> |
136 | - <span ng-if="pagePrograma.proposals.length > 1">Veja todas as {{pagePrograma.proposals.length}} propostas</span> | 143 | + <span ng-if="pagePrograma.proposals.length > 1">Veja todas as {{pagePrograma.total_proposals}} propostas</span> |
137 | <span ng-if="pagePrograma.proposals.length === 1">Ir para a página de ranking</span> | 144 | <span ng-if="pagePrograma.proposals.length === 1">Ir para a página de ranking</span> |
138 | </a> | 145 | </a> |
139 | </div> | 146 | </div> |
src/app/pages/programas/programas.controller.js
@@ -139,6 +139,21 @@ | @@ -139,6 +139,21 @@ | ||
139 | 139 | ||
140 | }; | 140 | }; |
141 | 141 | ||
142 | + ProgramasPageController.prototype.submitSearch = function() { | ||
143 | + var vm = this; | ||
144 | + | ||
145 | + vm.loadingFilter = true; | ||
146 | + | ||
147 | + // scroll to result grid | ||
148 | + var $searchResult = angular.element('#search-result'); | ||
149 | + if ($searchResult && $searchResult.length > 0) { | ||
150 | + angular.element('body').animate({scrollTop: $searchResult.offset().top}, 'fast'); | ||
151 | + vm.filtredPrograms = vm.getFiltredPrograms(); | ||
152 | + }else { | ||
153 | + vm.$log.warn('#search-result element not found.'); | ||
154 | + } | ||
155 | + }; | ||
156 | + | ||
142 | ProgramasPageController.prototype.showAllPrograms = function($event) { | 157 | ProgramasPageController.prototype.showAllPrograms = function($event) { |
143 | var vm = this; | 158 | var vm = this; |
144 | $event.stopPropagation(); | 159 | $event.stopPropagation(); |
src/app/pages/programas/programas.html
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | <label for="articleQueryFilter" class="control-label sr-only">Buscar programas:</label> | 26 | <label for="articleQueryFilter" class="control-label sr-only">Buscar programas:</label> |
27 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pageProgramas.query" placeholder="Buscar programas" aria-label="Buscar programas" > | 27 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pageProgramas.query" placeholder="Buscar programas" aria-label="Buscar programas" > |
28 | <span class="input-group-btn"> | 28 | <span class="input-group-btn"> |
29 | - <button type="button" class="btn btn-default" ng-click="pageProgramas.search()"> | 29 | + <button type="button" class="btn btn-default" ng-click="pageProgramas.submitSearch()"> |
30 | <span class="icon-circle icon-small color-theme-common-bg"> | 30 | <span class="icon-circle icon-small color-theme-common-bg"> |
31 | <span class="glyphicon glyphicon-search"></span> | 31 | <span class="glyphicon glyphicon-search"></span> |
32 | </span> | 32 | </span> |
@@ -58,7 +58,7 @@ | @@ -58,7 +58,7 @@ | ||
58 | <label for="articleQueryFilter" class="control-label sr-only">Buscar programas:</label> | 58 | <label for="articleQueryFilter" class="control-label sr-only">Buscar programas:</label> |
59 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pageProgramas.query" placeholder="Buscar programas" aria-label="Buscar programas" > | 59 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pageProgramas.query" placeholder="Buscar programas" aria-label="Buscar programas" > |
60 | <span class="input-group-btn"> | 60 | <span class="input-group-btn"> |
61 | - <button type="button" class="btn btn-default" ng-click="pageProgramas.search()"> | 61 | + <button type="button" class="btn btn-default" ng-click="pageProgramas.submitSearch()"> |
62 | <span class="icon-circle icon-small color-theme-common-bg"> | 62 | <span class="icon-circle icon-small color-theme-common-bg"> |
63 | <span class="glyphicon glyphicon-search"></span> | 63 | <span class="glyphicon glyphicon-search"></span> |
64 | </span> | 64 | </span> |
@@ -68,7 +68,7 @@ | @@ -68,7 +68,7 @@ | ||
68 | </div> | 68 | </div> |
69 | </div> | 69 | </div> |
70 | </div> | 70 | </div> |
71 | - <div class="row"> | 71 | + <div id="search-result" class="row"> |
72 | <div class="col-sm-12"> | 72 | <div class="col-sm-12"> |
73 | <header class="header"> | 73 | <header class="header"> |
74 | <h2>Conheça os programas</h2> | 74 | <h2>Conheça os programas</h2> |
src/app/pages/propostas/propostas.controller.js
@@ -6,11 +6,12 @@ | @@ -6,11 +6,12 @@ | ||
6 | .controller('PropostasPageController', PropostasPageController); | 6 | .controller('PropostasPageController', PropostasPageController); |
7 | 7 | ||
8 | /** @ngInject */ | 8 | /** @ngInject */ |
9 | - function PropostasPageController(DialogaService, $scope, $location, $filter, $log) { | 9 | + function PropostasPageController(DialogaService, $scope, $rootScope, $location, $filter, $log) { |
10 | var vm = this; | 10 | var vm = this; |
11 | 11 | ||
12 | vm.DialogaService = DialogaService; | 12 | vm.DialogaService = DialogaService; |
13 | vm.$scope = $scope; | 13 | vm.$scope = $scope; |
14 | + vm.$rootScope = $rootScope; | ||
14 | vm.$location = $location; | 15 | vm.$location = $location; |
15 | vm.$filter = $filter; | 16 | vm.$filter = $filter; |
16 | vm.$log = $log; | 17 | vm.$log = $log; |
@@ -18,6 +19,7 @@ | @@ -18,6 +19,7 @@ | ||
18 | vm.init(); | 19 | vm.init(); |
19 | vm.loadData(); | 20 | vm.loadData(); |
20 | // vm.attachListeners(); // attach listeners after load data (SYNC) | 21 | // vm.attachListeners(); // attach listeners after load data (SYNC) |
22 | + vm.$rootScope.focusMainContent(); | ||
21 | 23 | ||
22 | $log.debug('PropostasPageController'); | 24 | $log.debug('PropostasPageController'); |
23 | } | 25 | } |
@@ -156,4 +158,19 @@ | @@ -156,4 +158,19 @@ | ||
156 | return output; | 158 | return output; |
157 | }; | 159 | }; |
158 | 160 | ||
161 | + PropostasPageController.prototype.submitSearch = function() { | ||
162 | + var vm = this; | ||
163 | + | ||
164 | + vm.loadingFilter = true; | ||
165 | + | ||
166 | + // scroll to result grid | ||
167 | + var $searchResult = angular.element('#search-result'); | ||
168 | + if ($searchResult && $searchResult.length > 0) { | ||
169 | + angular.element('body').animate({scrollTop: $searchResult.offset().top}, 'fast'); | ||
170 | + vm.filtredProposals = vm.getFiltredProposals(); | ||
171 | + }else { | ||
172 | + vm.$log.warn('#search-result element not found.'); | ||
173 | + } | ||
174 | + }; | ||
175 | + | ||
159 | })(); | 176 | })(); |
src/app/pages/propostas/propostas.html
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | </div> | 6 | </div> |
7 | </div> | 7 | </div> |
8 | 8 | ||
9 | -<div class="page--propostas"> | 9 | +<div class="page--propostas" role="main"> |
10 | 10 | ||
11 | <section class="section-info" ng-if="pagePropostas.loading || pagePropostas.error"> | 11 | <section class="section-info" ng-if="pagePropostas.loading || pagePropostas.error"> |
12 | <div class="container"> | 12 | <div class="container"> |
@@ -46,7 +46,7 @@ | @@ -46,7 +46,7 @@ | ||
46 | <label for="articleQueryFilter" class="control-label sr-only">Buscar propostas:</label> | 46 | <label for="articleQueryFilter" class="control-label sr-only">Buscar propostas:</label> |
47 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pagePropostas.query" placeholder="Buscar propostas" aria-label="Buscar propostas" > | 47 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pagePropostas.query" placeholder="Buscar propostas" aria-label="Buscar propostas" > |
48 | <span class="input-group-btn"> | 48 | <span class="input-group-btn"> |
49 | - <button type="button" class="btn btn-default" ng-click="pagePropostas.search()"> | 49 | + <button type="button" class="btn btn-default" ng-click="pagePropostas.submitSearch()"> |
50 | <span class="icon-circle icon-small color-theme-common-bg"> | 50 | <span class="icon-circle icon-small color-theme-common-bg"> |
51 | <span class="glyphicon glyphicon-search"></span> | 51 | <span class="glyphicon glyphicon-search"></span> |
52 | </span> | 52 | </span> |
@@ -78,7 +78,7 @@ | @@ -78,7 +78,7 @@ | ||
78 | <label for="articleQueryFilter" class="control-label sr-only">Buscar propostas:</label> | 78 | <label for="articleQueryFilter" class="control-label sr-only">Buscar propostas:</label> |
79 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pagePropostas.query" placeholder="Buscar propostas" aria-label="Buscar propostas" > | 79 | <input id="articleQueryFilter" type="search" class="form-control input-search" ng-model="pagePropostas.query" placeholder="Buscar propostas" aria-label="Buscar propostas" > |
80 | <span class="input-group-btn"> | 80 | <span class="input-group-btn"> |
81 | - <button type="button" class="btn btn-default" ng-click="pagePropostas.search()"> | 81 | + <button type="button" class="btn btn-default" ng-click="pagePropostas.submitSearch()"> |
82 | <span class="icon-circle icon-small color-theme-common-bg"> | 82 | <span class="icon-circle icon-small color-theme-common-bg"> |
83 | <span class="glyphicon glyphicon-search"></span> | 83 | <span class="glyphicon glyphicon-search"></span> |
84 | </span> | 84 | </span> |
@@ -89,7 +89,7 @@ | @@ -89,7 +89,7 @@ | ||
89 | </div> | 89 | </div> |
90 | </div> | 90 | </div> |
91 | 91 | ||
92 | - <div class="row" ng-if="pagePropostas.proposals"> | 92 | + <div id="search-result" class="row" ng-if="pagePropostas.proposals"> |
93 | <div class="col-sm-12"> | 93 | <div class="col-sm-12"> |
94 | <header class="header"> | 94 | <header class="header"> |
95 | <h2>Total de Propostas: "<b>{{pagePropostas.filtredProposals.length}} propostas</b>"</h2> | 95 | <h2>Total de Propostas: "<b>{{pagePropostas.filtredProposals.length}} propostas</b>"</h2> |