Commit 4c0183630bda780eb58e93cb1f3a1ec7e9d67dcd
1 parent
105102b0
Exists in
master
and in
8 other branches
proposal-box: vote with captch (initial commit)
Showing
5 changed files
with
123 additions
and
30 deletions
Show diff stats
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 = '/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 = '/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 = 'http://hom.login.dialoga.gov.br/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, |
| @@ -129,8 +120,7 @@ | @@ -129,8 +120,7 @@ | ||
| 129 | } | 120 | } |
| 130 | 121 | ||
| 131 | function login (credentials) { | 122 | function login (credentials) { |
| 132 | - var hostProd = 'http://login.dialoga.gov.br'; | ||
| 133 | - var url = hostProd + '/api/v1/login'; | 123 | + var url = PATH.host + '/api/v1/login'; |
| 134 | var encodedData = 'login=' + credentials.username + '&password=' + credentials.password; | 124 | var encodedData = 'login=' + credentials.username + '&password=' + credentials.password; |
| 135 | 125 | ||
| 136 | return $http | 126 | return $http |
| @@ -149,6 +139,13 @@ | @@ -149,6 +139,13 @@ | ||
| 149 | }); | 139 | }); |
| 150 | } | 140 | } |
| 151 | 141 | ||
| 142 | + function loginCaptcha (data) { | ||
| 143 | + var url = PATH.host + '/api/v1/login-captcha'; | ||
| 144 | + var encodedData = angular.element.param(data); | ||
| 145 | + | ||
| 146 | + return $http.post(url, encodedData); | ||
| 147 | + } | ||
| 148 | + | ||
| 152 | function logout () { | 149 | function logout () { |
| 153 | 150 | ||
| 154 | Session.destroy(); | 151 | Session.destroy(); |
| @@ -190,6 +187,7 @@ | @@ -190,6 +187,7 @@ | ||
| 190 | changePassword: changePassword, | 187 | changePassword: changePassword, |
| 191 | forgotPassword: forgotPassword, | 188 | forgotPassword: forgotPassword, |
| 192 | login: login, | 189 | login: login, |
| 190 | + loginCaptcha: loginCaptcha, | ||
| 193 | logout: logout, | 191 | logout: logout, |
| 194 | isAuthenticated: isAuthenticated, | 192 | isAuthenticated: isAuthenticated, |
| 195 | isAuthorized: isAuthorized | 193 | isAuthorized: isAuthorized |
src/app/components/proposal-box/proposal-box.directive.js
| @@ -9,15 +9,19 @@ | @@ -9,15 +9,19 @@ | ||
| 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, $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(); |
| @@ -28,11 +32,11 @@ | @@ -28,11 +32,11 @@ | ||
| 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; |
| @@ -68,6 +72,21 @@ | @@ -68,6 +72,21 @@ | ||
| 68 | 72 | ||
| 69 | vm.message = data.message; | 73 | vm.message = data.message; |
| 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) { |
| @@ -81,18 +100,56 @@ | @@ -81,18 +100,56 @@ | ||
| 81 | }); | 100 | }); |
| 82 | }; | 101 | }; |
| 83 | 102 | ||
| 103 | + ProposalBoxController.prototype.canVote = function () { | ||
| 104 | + return false; | ||
| 105 | + }; | ||
| 106 | + | ||
| 107 | + ProposalBoxController.prototype.submitCaptcha = function ($event, captchaForm) { | ||
| 108 | + var vm = this; | ||
| 109 | + | ||
| 110 | + var target = $event.target; | ||
| 111 | + var $target = angular.element(target); | ||
| 112 | + var $captcha = $target.find('[name="txtToken_captcha_serpro_gov_br"]'); | ||
| 113 | + | ||
| 114 | + vm.sendingCaptcha = true; | ||
| 115 | + vm.AuthService.loginCaptcha({ | ||
| 116 | + captcha_text: captchaForm.captcha_text.$modelValue, | ||
| 117 | + txtToken_captcha_serpro_gov_br: $captcha.val() | ||
| 118 | + }).then(function(data) { | ||
| 119 | + // SUCCESS | ||
| 120 | + vm.$log.debug('register success.data', data); | ||
| 121 | + | ||
| 122 | + // get captcha_token | ||
| 123 | + }, function(data) { | ||
| 124 | + // ERROR | ||
| 125 | + vm.$log.debug('register error.data', data); | ||
| 126 | + | ||
| 127 | + vm.sendingCaptchaError = {code: data.status }; | ||
| 128 | + | ||
| 129 | + if(data.status === 404){ | ||
| 130 | + vm.$log.error('The api service is out!?'); | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + }, function(data){ | ||
| 134 | + // UPDATE | ||
| 135 | + vm.$log.debug('register update.data', data); | ||
| 136 | + }).finally(function(){ | ||
| 137 | + vm.sendingCaptcha = false; | ||
| 138 | + }); | ||
| 139 | + }; | ||
| 140 | + | ||
| 84 | ProposalBoxController.prototype.vote = function (value) { | 141 | ProposalBoxController.prototype.vote = function (value) { |
| 85 | var vm = this; | 142 | var vm = this; |
| 86 | 143 | ||
| 87 | - if(vm.$rootScope.currentUser){ | 144 | + if(vm.canVote()){ |
| 88 | vm.$scope.$emit('proposal-box:vote', { | 145 | vm.$scope.$emit('proposal-box:vote', { |
| 89 | OPTION: value, | 146 | OPTION: value, |
| 90 | proposal_id: vm.proposal.id | 147 | proposal_id: vm.proposal.id |
| 91 | }); | 148 | }); |
| 92 | vm.$log.debug('Sending vote', value); | 149 | vm.$log.debug('Sending vote', value); |
| 93 | }else{ | 150 | }else{ |
| 94 | - vm.$log.info('Must be logged in...'); | ||
| 95 | - vm.showAuthMessage = true; | 151 | + vm.$log.debug('You cannot vote.'); |
| 152 | + vm.showCaptchaForm = true; | ||
| 96 | } | 153 | } |
| 97 | }; | 154 | }; |
| 98 | 155 | ||
| @@ -135,7 +192,7 @@ | @@ -135,7 +192,7 @@ | ||
| 135 | proposal: '=', | 192 | proposal: '=', |
| 136 | topic: '=', | 193 | topic: '=', |
| 137 | category: '=', | 194 | category: '=', |
| 138 | - canVote: '=', | 195 | + showVote: '=', |
| 139 | focus: '@' | 196 | focus: '@' |
| 140 | // @ -> Text binding / one-way binding | 197 | // @ -> Text binding / one-way binding |
| 141 | // = -> Direct model binding / two-way binding | 198 | // = -> Direct model binding / two-way binding |
src/app/components/proposal-box/proposal-box.html
| @@ -65,18 +65,48 @@ | @@ -65,18 +65,48 @@ | ||
| 65 | </div> | 65 | </div> |
| 66 | </div> | 66 | </div> |
| 67 | </div> | 67 | </div> |
| 68 | - <div ng-show="vm.showAuthMessage"> | 68 | + <div ng-show="vm.showCaptchaForm"> |
| 69 | <div class="proposal-message-panel"> | 69 | <div class="proposal-message-panel"> |
| 70 | <div class="row"> | 70 | <div class="row"> |
| 71 | <div class="row-height"> | 71 | <div class="row-height"> |
| 72 | <div class="col-sm-12 col-height col-middle"> | 72 | <div class="col-sm-12 col-height col-middle"> |
| 73 | <div class="inside inside-full-height"> | 73 | <div class="inside inside-full-height"> |
| 74 | <div class="content text-center"> | 74 | <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> | 75 | + <div ng-if="vm.sendingCaptcha"> |
| 76 | + <p>Enviando captcha...</p> | ||
| 77 | + </div> | ||
| 78 | + <div ng-if="!vm.sendingCaptcha"> | ||
| 79 | + | ||
| 80 | + <div class="row" class="feedback-message" ng-if="vm.sendingCaptchaError"> | ||
| 81 | + <div class="col-sm-12"> | ||
| 82 | + <div class="feedback--title alert alert-danger">Erro!</div> | ||
| 83 | + <div class="feedback--message" ng-if="vm.sendingCaptchaError.code === 404"> | ||
| 84 | + <p> | ||
| 85 | + Houve uma falha. Já estamos trabalhando para resolver o problema. | ||
| 86 | + <br/> Por favor, tente novamente mais tarde | ||
| 87 | + </p> | ||
| 88 | + </div> | ||
| 89 | + </div> | ||
| 90 | + </div> | ||
| 91 | + <div ng-if="!vm.sendingCaptchaError"> | ||
| 92 | + <form name="captchaForm" ng-submit="vm.submitCaptcha($event, captchaForm)"> | ||
| 93 | + <div class="form-group"> | ||
| 94 | + <div id="serpro_captcha" class="captcha"></div> | ||
| 95 | + <div class="captcha">Digite os caracteres acima:</div> | ||
| 96 | + <div class="captcha"> | ||
| 97 | + <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> | ||
| 98 | + <validation-messages field="captchaForm.captcha_text"></validation-messages> | ||
| 99 | + </div> | ||
| 100 | + </div> | ||
| 101 | + <div class="form-group"> | ||
| 102 | + <button type="submit" class="btn btn-lg btn-block btn-submit">Enviar</button> | ||
| 103 | + </div> | ||
| 104 | + <div class="form-group"> | ||
| 105 | + <button class="btn btn-link" ng-click="vm.showCaptchaForm = false">Voltar</button> | ||
| 106 | + </div> | ||
| 107 | + </form> | ||
| 108 | + </div> | ||
| 109 | + </div> | ||
| 80 | </div> | 110 | </div> |
| 81 | </div> | 111 | </div> |
| 82 | </div> | 112 | </div> |
| @@ -112,12 +142,12 @@ | @@ -112,12 +142,12 @@ | ||
| 112 | <div class="proposal-box--content"> | 142 | <div class="proposal-box--content"> |
| 113 | <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div> | 143 | <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div> |
| 114 | </div> | 144 | </div> |
| 115 | - <div ng-hide="vm.canVote" class="proposal-box--join"> | 145 | + <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)"> | 146 | <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)"> |
| 117 | Participe | 147 | Participe |
| 118 | </button> | 148 | </button> |
| 119 | </div> | 149 | </div> |
| 120 | - <div ng-show="vm.canVote" class="proposal-box--actions text-center"> | 150 | + <div ng-show="vm.showVote" class="proposal-box--actions text-center"> |
| 121 | <div class="row"> | 151 | <div class="row"> |
| 122 | <div class="col-xs-4"> | 152 | <div class="col-xs-4"> |
| 123 | <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)"> | 153 | <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"> |