Commit 621fc7521ac2f9695b79162b5920b377e35f2f6a

Authored by Leonardo Merlin
2 parents a6b79c31 b3e7d5cb

Merge branch 'merlin' of gitlab.com:participa/discussion-app into merlin

gulp/build.js
... ... @@ -43,9 +43,9 @@ gulp.task('html', ['inject', 'partials'], function () {
43 43 .pipe(assets = $.useref.assets())
44 44 .pipe($.rev())
45 45 .pipe(jsFilter)
46   - .pipe($.replace('$logProvider.debugEnabled(true);', '$logProvider.debugEnabled(false);'))
47   - .pipe($.replace('http://hom.dialoga.gov.br', 'http://login.dialoga.gov.br'))
48   - .pipe($.replace('http://hom.login.dialoga.gov.br', 'http://login.dialoga.gov.br'))
  46 + .pipe($.if($.util.env.server === 'production', $.replace('$logProvider.debugEnabled(true);', '$logProvider.debugEnabled(false);')))
  47 + .pipe($.if($.util.env.server === 'production', $.replace('http://hom.dialoga.gov.br', 'http://login.dialoga.gov.br')))
  48 + .pipe($.if($.util.env.server === 'production', $.replace('http://hom.login.dialoga.gov.br', 'http://login.dialoga.gov.br')))
49 49 .pipe($.ngAnnotate())
50 50 .pipe($.uglify({ preserveComments: $.uglifySaveLicense })).on('error', conf.errorHandler('Uglify'))
51 51 .pipe(jsFilter.restore())
... ...
src/app/components/article-service/article.service.js
... ... @@ -177,9 +177,12 @@
177 177 var url = service.apiArticles + proposal_id + '/vote';
178 178 var paramsExtended = angular.extend({
179 179 private_token: $rootScope.currentUser.private_token
  180 + // private_token: 'e2198fdbcc20409f082829b4b5c0848e'
180 181 }, params);
181 182  
182   - UtilService.post(url, paramsExtended).then(function(response){
  183 + var encodedParams = angular.element.param(paramsExtended);
  184 +
  185 + UtilService.post(url, encodedParams).then(function(response){
183 186 cbSuccess(response);
184 187 }).catch(function(error){
185 188 cbError(error);
... ... @@ -197,6 +200,7 @@
197 200 }, params);
198 201  
199 202 UtilService.get(url, {params: paramsExtended}).then(function(data){
  203 + _pipeIsInThePast(data);
200 204 cbSuccess(data.articles);
201 205 }).catch(function(error){
202 206 cbError(error);
... ... @@ -287,5 +291,26 @@
287 291 return pA.ranking_position - pB.ranking_position;
288 292 });
289 293 }
  294 +
  295 + function _pipeIsInThePast(data){
  296 + if(!data.articles && data.article){
  297 + data.articles = [data.article];
  298 + }
  299 + var now = (new Date()).getTime();
  300 + var eventDate = null;
  301 + var events = data.articles;
  302 +
  303 + for (var i = events.length - 1; i >= 0; i--) {
  304 + var event = events[i];
  305 +
  306 + if(event.end_date){
  307 + eventDate = new Date(event.end_date);
  308 + }
  309 +
  310 + if(eventDate.getTime() < now){
  311 + event.isOld = true;
  312 + }
  313 + }
  314 + }
290 315 }
291 316 })();
... ...
src/app/components/auth/auth.service.js
... ... @@ -8,10 +8,10 @@
8 8 .factory('AuthInterceptor', AuthInterceptor);
9 9  
10 10 /** @ngInject */
11   - function AuthService($http, $rootScope, Session, AUTH_EVENTS, API, $log) {
  11 + function AuthService($q, $http, $rootScope, Session, AUTH_EVENTS, API, PATH, $log) {
12 12  
13 13 function register (data){
14   - var url = API.host + '/api/v1/register';
  14 + var url = PATH.host + '/api/v1/register';
15 15 $log.debug('data', data);
16 16 // var encodedData = data;
17 17 var encodedData = '';
... ... @@ -22,6 +22,8 @@
22 22 encodedData += '&password=' + data.password;
23 23 encodedData += '&password_confirmation=' + data.password_confirmation;
24 24 encodedData += '&user_terms_accepted=' + data.user_terms_accepted;
  25 + encodedData += '&captcha_text=' + data.captcha_text;
  26 + encodedData += '&txtToken_captcha_serpro_gov_br=' + data.txtToken_captcha_serpro_gov_br;
25 27  
26 28 // var encodedData = _encodeObj(data);
27 29 // var encodedData = angular.element.param(data);
... ... @@ -44,8 +46,8 @@
44 46 }, function(response) {
45 47 $log.debug('AuthService.register [FAIL] response', response);
46 48  
47   - $rootScope.$broadcast(AUTH_EVENTS.registerFailed);
48   - return response;
  49 + $rootScope.$broadcast(AUTH_EVENTS.registerFailed, response);
  50 + return $q.reject(response);
49 51 });
50 52 }
51 53  
... ...
src/app/components/event-list/event-list.html
... ... @@ -54,16 +54,16 @@
54 54 <div class="col-xs-12 col-sm-4 col-md-3 text-center vcenter">
55 55 <span class="theme">{{::event.categories[0].name}}</span>
56 56 </div>
57   - <div class="col-xs-12 col-sm-4 col-md-3 text-right vcenter">
  57 + <div class="col-xs-12 col-sm-4 col-md-3 text-right vcenter" style="padding-right: 20px;">
58 58 <div class="row">
59   - <div class="col-xs-6 text-right">
60   - <div ng-if="event.followers_count > 0">
  59 + <div class="col-xs-6 text-right" ng-class="{'col-xs-12': event.isOld}">
  60 + <div ng-if="event.followers_count > 50">
61 61 <b>{{::event.followers_count}}</b>
62 62 <br/>
63 63 <span>Inscritos</span>
64 64 </div>
65 65 </div>
66   - <div class="col-xs-6">
  66 + <div class="col-xs-6" ng-if="!event.isOld">
67 67 <button type="button" class="btn color-theme-common-bg" ng-click="vm.subscribe(event.id)">
68 68 Inscreva-se
69 69 <span class="sr-only">no bate-papo com (ministro) no dia {event.start_date | date : "dd/MM/yyyy"}} as {{event.start_date | date : "HH:mm"}} horas</span>
... ...
src/app/components/proposal-box/proposal-box.directive.js
... ... @@ -41,7 +41,7 @@
41 41  
42 42 vm.$scope.$on('proposal-box:proposal-loaded', function(event, data){
43 43 if(data.success){
44   - vm.STATE = null;
  44 + vm.STATE = null;
45 45 }
46 46  
47 47 if(data.error){
... ... @@ -57,11 +57,11 @@
57 57 if(data.success) {
58 58 vm.STATE = vm.VOTE_STATUS.SUCCESS;
59 59 }
60   -
  60 +
61 61 if(data.error) {
62 62 vm.STATE = vm.VOTE_STATUS.ERROR;
63 63 }
64   -
  64 +
65 65 vm.message = data.message;
66 66 });
67 67  
... ... @@ -123,6 +123,15 @@
123 123 vm.$log.debug('Sending vote');
124 124 };
125 125  
  126 + ProposalBoxController.prototype.getSocialUrl = function () {
  127 + var vm = this;
  128 +
  129 + return vm.$state.href('programa', {
  130 + slug: vm.topic.slug,
  131 + proposal_id: vm.proposal.id,
  132 + });
  133 + };
  134 +
126 135 var directive = {
127 136 restrict: 'E',
128 137 templateUrl: 'app/components/proposal-box/proposal-box.html',
... ... @@ -141,7 +150,6 @@
141 150 bindToController: true
142 151 };
143 152  
144   -
145 153 return directive;
146 154 }
147 155  
... ...
src/app/components/proposal-box/proposal-box.html
1 1 <div class="proposal-box" ng-class="[{'focus': (vm.focus || (vm.STATE === vm.VOTE_STATUS.LOADING) )}, vm.category.slug]">
2   - <!-- <div ng-hide="(vm.STATE === vm.VOTE_STATUS.SUCCESS) || (vm.STATE === vm.VOTE_STATUS.ERROR)"> -->
3   - <div>
4   - <div ng-show="(vm.STATE === vm.VOTE_STATUS.SUCCESS) || (vm.STATE === vm.VOTE_STATUS.ERROR)">
5   - <div class="proposal-message-panel">
6   - <div class="row">
7   - <div class="row-height">
8   - <div class="col-sm-12 col-sm-height col-middle">
9   - <div class="inside inside-full-height">
10   - <div class="content text-center show-message">
11   - <div class="row">
12   - <div class="col-xs-12">
13   - <div class="message-icon color-fg-white" ng-class="{'success': (vm.STATE === vm.VOTE_STATUS.SUCCESS), 'error': vm.STATE === vm.VOTE_STATUS.ERROR}">
14   - <span ng-if="vm.STATE === vm.VOTE_STATUS.SUCCESS" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
15   - <span ng-if="vm.STATE === vm.VOTE_STATUS.ERROR" class="glyphicon glyphicon-remove" aria-hidden="true"></span>
16   - </div>
  2 + <div ng-show="(vm.STATE === vm.VOTE_STATUS.SUCCESS) || (vm.STATE === vm.VOTE_STATUS.ERROR)">
  3 + <div class="proposal-message-panel">
  4 + <div class="row">
  5 + <div class="row-height">
  6 + <div class="col-sm-12 col-height col-middle">
  7 + <div class="inside inside-full-height">
  8 + <div class="content text-center show-message">
  9 + <div class="row">
  10 + <div class="col-xs-12">
  11 + <div class="message-icon color-fg-white" ng-class="{'success': (vm.STATE === vm.VOTE_STATUS.SUCCESS), 'error': vm.STATE === vm.VOTE_STATUS.ERROR}">
  12 + <span ng-if="vm.STATE === vm.VOTE_STATUS.SUCCESS" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
  13 + <span ng-if="vm.STATE === vm.VOTE_STATUS.ERROR" class="glyphicon glyphicon-remove" aria-hidden="true"></span>
17 14 </div>
18 15 </div>
19   - <div class="row">
20   - <div class="col-xs-12">
21   - <p style="padding-top:20px;">{{vm.message}}</p>
  16 + </div>
  17 + <div class="row">
  18 + <div class="col-xs-12">
  19 + <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.SUCCESS">
  20 + <p class="feedback--title">Obrigado por apoiar<br/>esta proposta!</p>
  21 +
  22 + <!-- actions -->
  23 + <div class="row feedback--message">
  24 + <div class="col-xs-6 feedback--share">
  25 + <div class="row">
  26 + <span>Compartilhe<br/>esta proposta</span>
  27 + </div>
  28 + <div class="row">
  29 + <button class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Mostrar ou esconder a lista redes sociais para compartilhamento">
  30 + <span class="icon icon-social-share" aria-hidden="true"></span>
  31 + </button>
  32 + <social-share
  33 + url="vm.getSocialUrl()"
  34 + text="vm.getSocialText()"
  35 + image="vm.getSocialImage()"
  36 + class="dropdown-menu dropdown-menu-right ng-isolate-scope"></social-share>
  37 + </div>
  38 + </div>
  39 + <div class="col-xs-6 feedback--next">
  40 + <div class="row">
  41 + <span>Próxima<br/>proposta</span>
  42 + </div>
  43 + <div class="row">
  44 + <button class="btn btn-link" aria-label="Ir para próxima proposta" ng-click="vm.skip()">
  45 + <div class="icon-circle play">
  46 + <span class="glyphicon glyphicon-play" aria-hidden="true"></span>
  47 + </div>
  48 + </button>
  49 + </div>
  50 + </div>
  51 + </div>
  52 + </div>
  53 + <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.ERROR">
  54 + <p class="feedback--title">Erro!</p>
  55 + <p class="feedback--message" ng-if="vm.message">
  56 + Motivo: {{vm.message}}
  57 + </p>
22 58 </div>
23 59 </div>
24 60 </div>
... ... @@ -28,40 +64,40 @@
28 64 </div>
29 65 </div>
30 66 </div>
31   - <div ng-show="vm.showAuthMessage">
32   - <div class="proposal-message-panel">
33   - <div class="row">
34   - <div class="row-height">
35   - <div class="col-sm-12 col-sm-height col-middle">
36   - <div class="inside inside-full-height">
37   - <div class="content text-center">
38   - <p>Você precisa estar logado para votar na proposta</p>
39   - <br>
40   - <p>
41   - <!-- <a ui-sref="entrar({redirect_uri: vm.voteProposalRedirectURI})">Clique aqui</a> para ir para a página de login. -->
42   - <a ui-sref="entrar({redirect_uri: vm.voteProposalRedirectURI})">Clique aqui para ir para a página de login</a>
43   - </p>
44   - </div>
  67 + </div>
  68 + <div ng-show="vm.showAuthMessage">
  69 + <div class="proposal-message-panel">
  70 + <div class="row">
  71 + <div class="row-height">
  72 + <div class="col-sm-12 col-height col-middle">
  73 + <div class="inside inside-full-height">
  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</a> para ir para a página de login. -->
  79 + <a ui-sref="entrar({redirect_uri: vm.voteProposalRedirectURI})">Clique aqui para ir para a página de login</a>
  80 + </p>
45 81 </div>
46 82 </div>
47 83 </div>
48 84 </div>
49 85 </div>
50 86 </div>
51   - <div ng-show="vm.STATE === vm.VOTE_STATUS.LOADING">
52   - <div class="proposal-message-panel">
53   - <div class="row">
54   - <div class="row-height">
55   - <div class="col-sm-12 col-sm-height col-middle">
56   - <div class="inside inside-full-height">
57   - <div class="content text-center">
58   - <div ng-show="!vm.errorOnSkip">
59   - <p>Carregando...</p>
60   - </div>
61   - <div ng-show="!vm.errorOnSkip">
62   - <p>Erro ao carregar nova proposta proposta.</p>
63   - <p>{{vm.errorOnSkip}}</p>
64   - </div>
  87 + </div>
  88 + <div ng-show="vm.STATE === vm.VOTE_STATUS.LOADING">
  89 + <div class="proposal-message-panel">
  90 + <div class="row">
  91 + <div class="row-height">
  92 + <div class="col-sm-12 col-height col-middle">
  93 + <div class="inside inside-full-height">
  94 + <div class="content text-center">
  95 + <div ng-show="!vm.errorOnSkip">
  96 + <p>Carregando...</p>
  97 + </div>
  98 + <div ng-show="!vm.errorOnSkip">
  99 + <p>Erro ao carregar nova proposta proposta.</p>
  100 + <p>{{vm.errorOnSkip}}</p>
65 101 </div>
66 102 </div>
67 103 </div>
... ... @@ -69,63 +105,63 @@
69 105 </div>
70 106 </div>
71 107 </div>
72   - <div class="proposal-box--top">
73   - <div class="proposal-box--theme color-theme-bg-complementar-2">{{vm.category.name}}</div>
74   - <div class="proposal-box--program color-theme-bg">{{vm.topic.title}}</div>
  108 + </div>
  109 + <div class="proposal-box--top">
  110 + <div class="proposal-box--theme color-theme-bg-complementar-2">{{vm.category.name}}</div>
  111 + <div class="proposal-box--program color-theme-bg">{{vm.topic.title}}</div>
  112 + </div>
  113 + <div class="proposal-box--middle">
  114 + <div class="proposal-box--content">
  115 + <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div>
  116 + </div>
  117 + <div ng-hide="vm.canVote" class="proposal-box--join">
  118 + <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)">
  119 + Participe
  120 + <span class="glyphicon glyphicon-menu-right color-theme-common-fg" aria-hidde="true"></span>
  121 + </button>
75 122 </div>
76   - <div class="proposal-box--middle">
77   - <div class="proposal-box--content">
78   - <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div>
79   - </div>
80   - <div ng-hide="vm.canVote" class="proposal-box--join">
81   - <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)">
82   - Participe
83   - <span class="glyphicon glyphicon-menu-right color-theme-common-fg" aria-hidde="true"></span>
84   - </button>
85   - </div>
86   - <div ng-show="vm.canVote" class="proposal-box--actions text-center">
87   - <div class="row">
88   - <div class="col-xs-4">
89   - <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)">
90   - <div class="icon-circle">
91   - <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
92   - </div>
93   - <div class="action-label">Apoio</div>
  123 + <div ng-show="vm.canVote" class="proposal-box--actions text-center">
  124 + <div class="row">
  125 + <div class="col-xs-4">
  126 + <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)">
  127 + <div class="icon-circle">
  128 + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
94 129 </div>
  130 + <div class="action-label">Apoio</div>
95 131 </div>
96   - <div class="col-xs-4">
97   - <div class="action skip" ng-click="vm.skip()">
98   - <div class="icon-circle">
99   - <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
100   - </div>
101   - <div class="action-label">Pular</div>
  132 + </div>
  133 + <div class="col-xs-4">
  134 + <div class="action skip" ng-click="vm.skip()">
  135 + <div class="icon-circle">
  136 + <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span>
102 137 </div>
  138 + <div class="action-label">Pular</div>
103 139 </div>
104   - <div class="col-xs-4">
105   - <div class="action vote_against" ng-click="vm.vote(vm.VOTE_OPTIONS.DOWN)">
106   - <div class="icon-circle">
107   - <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
108   - </div>
109   - <div class="action-label">Não Apoio</div>
  140 + </div>
  141 + <div class="col-xs-4">
  142 + <div class="action vote_against" ng-click="vm.vote(vm.VOTE_OPTIONS.DOWN)">
  143 + <div class="icon-circle">
  144 + <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
110 145 </div>
  146 + <div class="action-label">Não Apoio</div>
111 147 </div>
112 148 </div>
113 149 </div>
114 150 </div>
115   - <div class="proposal-box--bottom text-center">
116   - <div class="proposal-box--share">
117   - <span>COMPARTILHE ESSA <b>PROPOSTA</b></span>
118   - <div class="dropdown">
119   - <button id="dropdown-share-btn" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Mostrar ou esconder a lista redes sociais para compartilhamento"><span class="icon icon-social-share-small" aria-hidden="true"></span></button>
120   - <social-share class="dropdown-menu dropdown-menu-right"></social-share>
121   - </div>
  151 + </div>
  152 + <div class="proposal-box--bottom text-center">
  153 + <div class="proposal-box--share">
  154 + <span>COMPARTILHE ESSA <b>PROPOSTA</b></span>
  155 + <div class="dropdown">
  156 + <button id="dropdown-share-btn" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Mostrar ou esconder a lista redes sociais para compartilhamento"><span class="icon icon-social-share-small" aria-hidden="true"></span></button>
  157 + <social-share class="dropdown-menu dropdown-menu-right"></social-share>
122 158 </div>
123   - <div class="proposal-box--ranking">
124   - <div class="proposal-box--ranking-inner">
125   - <span class="icon icon-small icon-ranking" aria-hidden="true"></span>
126   - <span>Colocação nos resultados:</span>
127   - <span>{{vm.proposal.ranking_position}}º</span>
128   - </div>
  159 + </div>
  160 + <div class="proposal-box--ranking">
  161 + <div class="proposal-box--ranking-inner">
  162 + <span class="icon icon-small icon-ranking" aria-hidden="true"></span>
  163 + <span>Colocação nos resultados:</span>
  164 + <span>{{vm.proposal.ranking_position}}º</span>
129 165 </div>
130 166 </div>
131 167 </div>
... ...
src/app/components/proposal-box/proposal-box.scss
... ... @@ -81,6 +81,8 @@
81 81 z-index: 1000;
82 82 background-color: #f5f5f5;
83 83 background-color: rgba(245, 245, 245, 0.9);
  84 + border: 7px solid #5E769C;
  85 + border-radius: 5px;
84 86  
85 87 .row { height: 100%; }
86 88 .inside { position: relative; }
... ... @@ -92,8 +94,42 @@
92 94 line-height: 24px;
93 95 padding: 10px 30px;
94 96 }
  97 +
  98 + .message-icon {
  99 + .glyphicon {
  100 + top: 8px;
  101 + }
  102 + }
95 103 }
96 104  
  105 + .feedback {
  106 + padding: 20px;
  107 +
  108 + &--title {
  109 + font-size: 22px;
  110 + font-weight: bold;
  111 + }
  112 +
  113 + &--message {
  114 + font-size: 14px;
  115 + font-weight: normal;
  116 + line-height: 20px;
  117 + margin-top: 48px;
  118 + }
  119 +
  120 + .icon-circle {
  121 + &.play {
  122 + background-color: #5e769c;
  123 + }
  124 +
  125 + .glyphicon {
  126 + top: 12px;
  127 + color: #fff;
  128 + }
  129 + }
  130 + }
  131 +
  132 +
97 133 .action {
98 134 .glyphicon {
99 135 color: #fff;
... ...
src/app/components/proposal-list/proposal-list.scss
... ... @@ -117,4 +117,8 @@
117 117 background-color: transparent;
118 118 }
119 119  
  120 + nav {
  121 + text-align: center;
  122 + }
  123 +
120 124 }
... ...
src/app/components/social-share/social-share.directive.js
... ... @@ -11,6 +11,9 @@
11 11 restrict: 'E',
12 12 templateUrl: 'app/components/social-share/social-share.html',
13 13 scope: {
  14 + url: '=',
  15 + image: '=',
  16 + text: '=',
14 17 },
15 18 controller: SocialShareController,
16 19 controllerAs: 'vm',
... ...
src/app/index.run.js
... ... @@ -4,12 +4,13 @@
4 4  
5 5 angular
6 6 .module('dialoga')
7   - .run(runAuth)
8   - .run(runSocialAuth)
9 7 .run(runAccessibility)
  8 + .run(runAuth)
  9 + .run(runCaptcha)
  10 + .run(runColorUtils)
10 11 .run(runHistory)
11 12 .run(runPath)
12   - .run(runColorUtils)
  13 + .run(runSocialAuth)
13 14 .run(runUtils)
14 15 .run(runBlock);
15 16  
... ... @@ -45,18 +46,53 @@
45 46 }
46 47  
47 48 /** @ngInject */
  49 + function runCaptcha($window, $log, GUID) {
  50 + var serpro_captcha_clienteId = 'fdbcdc7a0b754ee7ae9d865fda740f17';
  51 +
  52 + $window.initCaptcha = function(element) {
  53 + var $element = angular.element(element);
  54 +
  55 + // already have a started captcha
  56 + if ($element.data('captcha')) {
  57 + $log.info('Captcha already initialized. Abort.');
  58 + return;
  59 + }
  60 +
  61 + // Create a new instance of Captcha
  62 + var oCaptcha_serpro_gov_br = new $window.captcha_serpro_gov_br();
  63 +
  64 + // Set the initial data
  65 + $element.val('');
  66 + $element.data('captcha', oCaptcha_serpro_gov_br);
  67 + oCaptcha_serpro_gov_br.clienteId = serpro_captcha_clienteId;
  68 + // oCaptcha_serpro_gov_br.url = "/serprocaptcha";
  69 + oCaptcha_serpro_gov_br.criarUI(element, 'css', 'serpro_captcha_component_', GUID.generate());
  70 + };
  71 +
  72 + $window.reloadCaptcha = function(element) {
  73 + var $element = angular.element(element);
  74 +
  75 + if ($element.data('captcha')) {
  76 + $element.data('captcha').recarregar();
  77 + }
  78 + };
  79 +
  80 + $log.debug('runCaptcha');
  81 + }
  82 +
  83 + /** @ngInject */
48 84 function runSocialAuth($window, $rootScope, $interval, $log) {
49 85  
50   - $window.oauthClientAction = function (url){
  86 + $window.oauthClientAction = function(url) {
51 87 var child = $window.open(url, '_blank');
52 88 var interval = $interval(function() {
53 89 try {
54   - if(!child.closed) {
  90 + if (!child.closed) {
55 91 child.postMessage({
56 92 message: 'requestOauthClientPluginResult'
57 93 }, '*');
58 94 }
59   - } catch(e) {
  95 + } catch (e) {
60 96 // we're here when the child window has been navigated away or closed
61 97 if (child.closed) {
62 98 $interval.cancel(interval);
... ... @@ -118,7 +154,7 @@
118 154 // prevent skip link from redirecting
119 155 if ($event) { $event.preventDefault(); }
120 156  
121   - if(angular.isString(target)){
  157 + if (angular.isString(target)) {
122 158 target = angular.element(target);
123 159 }
124 160  
... ... @@ -137,7 +173,7 @@
137 173 $rootScope.$previousState.splice(-MAX_HISTORY, MAX_HISTORY);
138 174 });
139 175  
140   - $rootScope.goBack = $rootScope.goBack || function () {
  176 + $rootScope.goBack = $rootScope.goBack || function() {
141 177 return $rootScope.$previousState.pop();
142 178 };
143 179 }
... ... @@ -178,7 +214,7 @@
178 214  
179 215 /** @ngInject */
180 216 function runUtils($rootScope) {
181   - $rootScope.stripHtml = function (text) {
  217 + $rootScope.stripHtml = function(text) {
182 218 return String(text).replace(/<[^>]+>/gm, '');
183 219 };
184 220 }
... ...
src/app/index.scss
... ... @@ -272,3 +272,18 @@ $common-color: #5E739E;
272 272 */
273 273 // injector
274 274 // endinjector
  275 +
  276 +
  277 +// blockquote {
  278 +// position:relative;
  279 +// }
  280 +
  281 +// blockquote:before {
  282 +// content:"\0393";
  283 +// font-size: 50px;
  284 +// display: block;
  285 +// position: absolute;
  286 +// top: 0;
  287 +// left: 0.
  288 +// }
  289 +
... ...
src/app/layout.scss
... ... @@ -29,21 +29,21 @@
29 29 table-layout: fixed;
30 30 height: 100%;
31 31 width: 100%;
32   - }
33   - .col-xs-height {
  32 +}
  33 +.col-xs-height {
34 34 display: table-cell;
35 35 float: none;
36 36 height: 100%;
37   - }
38   - .col-xs-top {
  37 +}
  38 +.col-xs-top {
39 39 vertical-align: top;
40   - }
41   - .col-xs-middle {
  40 +}
  41 +.col-xs-middle {
42 42 vertical-align: middle;
43   - }
44   - .col-xs-bottom {
  43 +}
  44 +.col-xs-bottom {
45 45 vertical-align: bottom;
46   - }
  46 +}
47 47 }
48 48  
49 49 @media (min-width: 768px) {
... ... @@ -52,21 +52,21 @@
52 52 table-layout: fixed;
53 53 height: 100%;
54 54 width: 100%;
55   - }
56   - .col-sm-height {
  55 +}
  56 +.col-sm-height {
57 57 display: table-cell;
58 58 float: none;
59 59 height: 100%;
60   - }
61   - .col-sm-top {
  60 +}
  61 +.col-sm-top {
62 62 vertical-align: top;
63   - }
64   - .col-sm-middle {
  63 +}
  64 +.col-sm-middle {
65 65 vertical-align: middle;
66   - }
67   - .col-sm-bottom {
  66 +}
  67 +.col-sm-bottom {
68 68 vertical-align: bottom;
69   - }
  69 +}
70 70 }
71 71  
72 72 @media (min-width: 992px) {
... ... @@ -75,21 +75,21 @@
75 75 table-layout: fixed;
76 76 height: 100%;
77 77 width: 100%;
78   - }
79   - .col-md-height {
  78 +}
  79 +.col-md-height {
80 80 display: table-cell;
81 81 float: none;
82 82 height: 100%;
83   - }
84   - .col-md-top {
  83 +}
  84 +.col-md-top {
85 85 vertical-align: top;
86   - }
87   - .col-md-middle {
  86 +}
  87 +.col-md-middle {
88 88 vertical-align: middle;
89   - }
90   - .col-md-bottom {
  89 +}
  90 +.col-md-bottom {
91 91 vertical-align: bottom;
92   - }
  92 +}
93 93 }
94 94  
95 95 @media (min-width: 1200px) {
... ... @@ -98,21 +98,21 @@
98 98 table-layout: fixed;
99 99 height: 100%;
100 100 width: 100%;
101   - }
102   - .col-lg-height {
  101 +}
  102 +.col-lg-height {
103 103 display: table-cell;
104 104 float: none;
105 105 height: 100%;
106   - }
107   - .col-lg-top {
  106 +}
  107 +.col-lg-top {
108 108 vertical-align: top;
109   - }
110   - .col-lg-middle {
  109 +}
  110 +.col-lg-middle {
111 111 vertical-align: middle;
112   - }
113   - .col-lg-bottom {
  112 +}
  113 +.col-lg-bottom {
114 114 vertical-align: bottom;
115   - }
  115 +}
116 116 }
117 117  
118 118 .vcenter {
... ... @@ -133,17 +133,17 @@
133 133 }
134 134  
135 135 .btn-submit {
136   - background-color: $defaultblue;
137   - color: #fff;
138   - font-weight: bold;
  136 + background-color: $defaultblue;
  137 + color: #fff;
  138 + font-weight: bold;
139 139  
140   - &:hover,
141   - &:focus {color: #fff;}
  140 + &:hover,
  141 + &:focus {color: #fff;}
142 142 }
143 143  
144 144 .has-error {
145   - border-color: #FF0000;
146   - border-width: 1px;
  145 + border-color: #FF0000;
  146 + border-width: 1px;
147 147 }
148 148  
149 149 // Está com o nome do termos de uso. Deixas genérico ou apenas aqui? Ver como vão ficar esses modais
... ... @@ -157,9 +157,9 @@
157 157 position: relative;
158 158 top: -30px;
159 159 right: 0px;
160   - }
  160 +}
161 161  
162   - &-body {
  162 +&-body {
163 163 padding: 25px 35px;
164 164 height: 500px;
165 165  
... ... @@ -168,9 +168,9 @@
168 168 overflow-y: auto;
169 169 padding: 15px;
170 170 height: 440px;
171   - }
172 171 }
173 172 }
  173 +}
174 174  
175 175 .modal-fechar-pequeno {
176 176 font-size: 15px;
... ... @@ -182,29 +182,11 @@
182 182  
183 183 // Sobreescreve a classe do bootstrap
184 184 .close {
185   - // position: absolute;
186 185 color: white;
187 186 opacity: 1;
188 187 font-weight: normal;
189 188 }
190 189  
191   -// Cria uma barra de rolagem parecida com a pedida, mas aplica pro site todo
192   -// ::-webkit-scrollbar {
193   -// width: 12px;
194   -// background-color: gray;
195   -// }
196   -
197   -// ::-webkit-scrollbar-track {
198   -// -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
199   -// border-radius: 10px;
200   -// }
201   -
202   -// ::-webkit-scrollbar-thumb {
203   -// border-radius: 10px;
204   -// -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);
205   -// background-color: black;
206   -// }
207   -
208 190 .btn-question {
209 191 color: #484848;
210 192 background-color: #fff;
... ... @@ -216,3 +198,105 @@
216 198 padding: 0;
217 199 border-radius: 100%;
218 200 }
  201 +
  202 +.destaque-cinza {
  203 + background-color: #F1F1F1;
  204 + padding: 30px;
  205 +}
  206 +
  207 +.gray-block {
  208 + background-color: #F1F1F1;
  209 +}
  210 +
  211 +.destaque-cinza-claro {
  212 + background-color: #F8F8F8;
  213 + padding: 30px;
  214 +}
  215 +
  216 +.left-border-gray {
  217 + border-left: 3px solid #eeeeee;
  218 +
  219 + @media (max-width: 768px) {
  220 + border: none;
  221 +}
  222 +}
  223 +
  224 +// .img-responsive-100 {
  225 +// width: 100%;
  226 +// }
  227 +
  228 +// .vcenter {
  229 +// display: inline-block;
  230 +// vertical-align: middle;
  231 +// float: none;
  232 +// margin-right: -2px;
  233 +// margin-left: -2px;
  234 +// }
  235 +
  236 +
  237 +ul.list-color {
  238 + list-style: none;
  239 + padding: 0;
  240 + margin: 0;
  241 +}
  242 +
  243 +ul.list-color li:before {
  244 +
  245 + @each $category, $color in $categories {
  246 + .#{$category} & {
  247 + color: $color;
  248 + }
  249 +}
  250 +
  251 +}
  252 +
  253 +ul.list-color li:before {
  254 + content: "• ";
  255 + font-weight: bold;
  256 + font-size: 20px;
  257 + position: relative;
  258 + top: 2px;
  259 +}
  260 +
  261 +ul.list-color li {
  262 + padding-left: 2em;
  263 + padding-bottom: 20px;
  264 + text-indent: -0.7em;
  265 +}
  266 +
  267 +.right-block {
  268 + float: right;
  269 +}
  270 +
  271 +// .margin-bottom {
  272 +// margin-bottom: 40px;
  273 +// }
  274 +
  275 +// .no-space-right {
  276 +// padding-right: 0px;
  277 +// }
  278 +
  279 +// .no-space-left {
  280 +// padding-left: 0px;
  281 +// }
  282 +
  283 +a.link-black {
  284 + color: black;
  285 +}
  286 +
  287 +.font-white {
  288 + color: white;
  289 +}
  290 +
  291 +// .padding-top-50{
  292 +// padding-top: 50px;
  293 +// }
  294 +
  295 +// .padding-bottom-20{
  296 +// padding-bottom: 20px;
  297 +// }
  298 +
  299 +
  300 +.inline-block {
  301 + display: inline-block;
  302 +}
... ...
src/app/pages/auth/auth.controller.js
... ... @@ -6,7 +6,7 @@
6 6 .controller('AuthPageController', AuthPageController);
7 7  
8 8 /** @ngInject */
9   - function AuthPageController($scope, $rootScope, $window, $location, $state, $timeout, AUTH_EVENTS, AuthService, DialogaService, Session, $log) {
  9 + function AuthPageController($scope, $rootScope, $window, $location, $state, $timeout, $interval, AUTH_EVENTS, AuthService, DialogaService, Session, $log) {
10 10 var vm = this;
11 11  
12 12 vm.$scope = $scope;
... ... @@ -15,6 +15,7 @@
15 15 vm.$location = $location;
16 16 vm.$state = $state;
17 17 vm.$timeout = $timeout;
  18 + vm.$interval = $interval;
18 19 vm.AUTH_EVENTS = AUTH_EVENTS;
19 20 vm.AuthService = AuthService;
20 21 vm.DialogaService = DialogaService;
... ... @@ -78,14 +79,38 @@
78 79 AuthPageController.prototype.attachListeners = function() {
79 80 var vm = this;
80 81  
  82 + vm.$scope.$on(vm.AUTH_EVENTS.registerSuccess, function(event, response) {
  83 + vm.$log.debug('TODO: handle register success');
  84 + vm.$log.debug('[register success] response', response);
  85 + });
  86 +
  87 + vm.$scope.$on(vm.AUTH_EVENTS.registerFailed, function(event, response) {
  88 + vm.$log.debug('TODO: handle register error');
  89 + vm.$log.debug('[register error] response', response);
  90 +
  91 + var reason = response.data.message;
  92 + vm.errorMessage = reason;
  93 + });
  94 +
81 95 vm.$scope.$on('oauthClientPluginResult', function(event, response) {
82 96 vm.$log.debug('response', response);
83 97  
84 98 // var logged_id = response.data.logged_id;
85 99 // var private_token = response.data.private_token;
86 100 // var user = response.data.user;
87   -
88 101 });
  102 +
  103 + var stop = null;
  104 + stop = vm.$interval(function(){
  105 + var $el = angular.element('#serpro_captcha');
  106 +
  107 + if ($el && $el.length > 0 ){
  108 + vm.$window.initCaptcha($el[0]);
  109 + vm.$interval.cancel(stop);
  110 + stop = undefined;
  111 + }
  112 +
  113 + }, 200);
89 114 };
90 115  
91 116 AuthPageController.prototype.onClickLogout = function() {
... ... @@ -94,7 +119,7 @@
94 119 vm.AuthService.logout();
95 120 };
96 121  
97   - AuthPageController.prototype.submitSigup = function(credentials) {
  122 + AuthPageController.prototype.submitSingup = function(credentials) {
98 123 var vm = this;
99 124  
100 125 vm.AuthService.register(credentials).then(function(response) {
... ... @@ -108,8 +133,19 @@
108 133 }, function(response) {
109 134 vm.$log.debug('register error.response', response);
110 135  
  136 + var message = response.data.message;
  137 + vm.errorMessage = message;
  138 +
  139 + if(response.data.code === 500){
  140 + vm.internalError = true;
  141 + }
  142 +
  143 +
111 144 // TODO: mensagens de erro
112 145 // TODO: tratar multiplos erros
  146 +
  147 + // javascript_console_message: "Unable to reach Serpro's Captcha validation service"
  148 + // message: "Internal captcha validation error"
113 149 });
114 150 };
115 151  
... ... @@ -137,15 +173,14 @@
137 173  
138 174 // start countdown
139 175 vm.countdown = vm.delay;
140   - (function countdown() {
141   - vm.$timeout(function() {
142   - vm.countdown--;
143   - vm.$log.debug('vm.countdown', vm.countdown);
144   - if (vm.countdown > 0) {
145   - countdown();
146   - }
147   - }, 1000);
148   - })();
  176 + var stop = null;
  177 + stop = vm.$interval(function() {
  178 + vm.countdown--;
  179 + if (vm.countdown <= 0) {
  180 + vm.$interval.cancel(stop);
  181 + stop = undefined;
  182 + }
  183 + }, 1000);
149 184  
150 185 vm.$timeout(function() {
151 186 var state = vm.params.state;
... ...
src/app/pages/auth/signin.html
... ... @@ -82,92 +82,87 @@
82 82 </p>
83 83 </div>
84 84 </div>
85   - <div class="row">
86   - <div class="col-xs-6">
87   - <button type="button" ng-click="pageSignin.authWithFacebook()" class="btn btn-lg btn-block btn-social btn-facebook">
88   - <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-facebook">
89   - <span class="icon icon-social-facebook"></span>
90   - </span>
91   - <span class="text">Entrar com Facebook</span>
92   - </button>
93   - </div>
94   - <div class="col-xs-6">
95   - <button type="button" ng-click="pageSignin.authWithGooglePlus()" class="btn btn-lg btn-block btn-social btn-google-plus">
96   - <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-googleplus">
97   - <span class="icon icon-social-googleplus"></span>
98   - </span>
99   - <span class="text">Entrar com Google+</span>
100   - </button>
  85 + <div class="row" ng-if="pageSignin.errorMessage">
  86 + <div class="col-sm-12">
  87 + <div class="alert alert-danger">
  88 + {{pageSignin.errorMessage}}
  89 + </div>
  90 + <div ng-if="vm.internalError">
  91 + <p>Este erro parece ser um problema interno.<br/>Por favor, tente novamente mais tarde.</p>
  92 + <p>Caso o problema persista, entre em contato!</p>
  93 + <p><a ui-sref="duvidas">Ir para página de contato</a></p>
  94 + </div>
101 95 </div>
102 96 </div>
103 97 <div class="row">
104 98 <div class="col-sm-12">
105   - <hr class="separator separator-cadastro"></hr>
106   - </div>
107   - <div class="row">
108   - <div class="col-sm-12">
109   - <form name="signupForm" ng-submit="pageSignin.submitSigup(pageSignin.signup)">
110   - <div class="form-group">
111   - <label for="signup-form--name">Nome*:</label>
112   - <span class="pull-right">*Dados obrigatórios</span>
113   - <input type="text" id="signup-form--name" name="name" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.name.$invalid && signupForm.name.$touched }" ng-model="pageSignin.signup.name" ng-minlength="" ng-maxlength="" required>
114   - <validation-messages field="signupForm.name"/>
115   - </div>
116   - <div class="form-group">
117   - <label for="signup-form--email">E-mail*:</label>
118   - <input type="email" id="signup-form--email" name="email" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.email.$invalid && signupForm.email.$touched }" ng-model="pageSignin.signup.email" ng-minlength="" ng-maxlength="" required>
119   - <validation-messages field="signupForm.email"/>
  99 + <form name="signupForm" ng-submit="pageSignin.submitSigup(pageSignin.signup)">
  100 + <div class="form-group">
  101 + <label for="signup-form--name">Nome*:</label>
  102 + <span class="pull-right">*Dados obrigatórios</span>
  103 + <input type="text" id="signup-form--name" name="name" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.name.$invalid && signupForm.name.$touched }" ng-model="pageSignin.signup.name" ng-minlength="" ng-maxlength="" required>
  104 + <validation-messages field="signupForm.name"/>
  105 + </div>
  106 + <div class="form-group">
  107 + <label for="signup-form--email">E-mail*:</label>
  108 + <input type="email" id="signup-form--email" name="email" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.email.$invalid && signupForm.email.$touched }" ng-model="pageSignin.signup.email" ng-minlength="" ng-maxlength="" required>
  109 + <validation-messages field="signupForm.email"/>
  110 + </div>
  111 + <div class="row">
  112 + <div class="col-sm-6">
  113 + <div class="form-group">
  114 + <label for="signup-form--password">Senha*:</label>
  115 + <input type="password" id="signup-form--password" name="password" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.password.$invalid && signupForm.password.$touched }" ng-model="pageSignin.signup.password" ng-minlength="" ng-maxlength="" required>
  116 + <validation-messages field="signupForm.password"/>
  117 + </div>
120 118 </div>
121   - <div class="row">
122   - <div class="col-sm-6">
123   - <div class="form-group">
124   - <label for="signup-form--password">Senha*:</label>
125   - <input type="password" id="signup-form--password" name="password" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.password.$invalid && signupForm.password.$touched }" ng-model="pageSignin.signup.password" ng-minlength="" ng-maxlength="" required>
126   - <validation-messages field="signupForm.password"/>
127   - </div>
  119 + <div class="col-sm-6">
  120 + <div class="form-group">
  121 + <label for="signup-form--password-confirmation">Confirmar Senha*:</label>
  122 + <input type="password" id="signup-form--password-confirmation" name="password_confirmation" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.password_confirmation.$invalid && signupForm.password_confirmation.$touched }" ng-model="pageSignin.signup.password_confirmation" ng-minlength="" ng-maxlength="" required>
  123 + <validation-messages field="signupForm.password_confirmation"/>
128 124 </div>
129   - <div class="col-sm-6">
130   - <div class="form-group">
131   - <label for="signup-form--password-confirmation">Confirmar Senha*:</label>
132   - <input type="password" id="signup-form--password-confirmation" name="password_confirmation" class="form-control input-lg" ng-class="{ 'has-error' : signupForm.password_confirmation.$invalid && signupForm.password_confirmation.$touched }" ng-model="pageSignin.signup.password_confirmation" ng-minlength="" ng-maxlength="" required>
133   - <validation-messages field="signupForm.password_confirmation"/>
134   - </div>
  125 + </div>
  126 + </div>
  127 + <div class="row">
  128 + <div class="col-sm-12" ng-show="(signupForm.password.$viewValue.length > 0 && signupForm.password_confirmation.$viewValue.length > 0) && (signupForm.password.$viewValue !== signupForm.password_confirmation.$viewValue)">
  129 + <div class="error-message">
  130 + As senhas estão diferentes.
135 131 </div>
136 132 </div>
137   - <div class="row">
138   - <div class="col-sm-12" ng-show="(signupForm.password.$viewValue.length > 0 && signupForm.password_confirmation.$viewValue.length > 0) && (signupForm.password.$viewValue !== signupForm.password_confirmation.$viewValue)">
  133 + <div class="col-sm-12">
  134 + <span class="text" ng-show="signupForm.password.$viewValue.length > 0 && signupForm.password.$viewValue.length < 6">
139 135 <div class="error-message">
140   - As senhas estão diferentes.
  136 + A senha deve ter 6 ou mais caracteres e conter números e letras.
141 137 </div>
142   - </div>
143   - <div class="col-sm-12">
144   - <span class="text" ng-show="signupForm.password.$viewValue.length > 0 && signupForm.password.$viewValue.length < 6">
145   - <div class="error-message">
146   - A senha deve ter 6 ou mais caracteres e conter números e letras.
147   - </div>
148   - </span>
149   - </div>
  138 + </span>
150 139 </div>
151   - <div class="form-group">
152   - <div class="checkbox">
153   - <label for="user_terms_accepted">
154   - <input type="checkbox" id="user_terms_accepted" name="user_terms_accepted" value="aceito" ng-model="pageSignin.signup.user_terms_accepted" required>
155   - Já li e concordo com os
156   - <button type="button" class="btn btn-link" style="padding:0 0 4px 0;" data-toggle="modal" data-target="#modalTermosDeUso">Termos de Uso</button>
157   - </label>
158   - </div>
159   - </input>
160   - <validation-messages field="signupForm.user_terms_accepted"/>
161 140 </div>
162 141 <div class="form-group">
163   - <span>Digite o texto da imagem</span>
164   - <p>O Captcha vai aqui</p>
  142 + <div class="checkbox">
  143 + <label for="user_terms_accepted">
  144 + <input type="checkbox" id="user_terms_accepted" name="user_terms_accepted" value="aceito" ng-model="pageSignin.signup.user_terms_accepted" required>
  145 + Já li e concordo com os
  146 + <button type="button" class="btn btn-link" style="padding:0 0 4px 0;" data-toggle="modal" data-target="#modalTermosDeUso">Termos de Uso</button>
  147 + </label>
  148 + </div>
  149 + </input>
  150 + <validation-messages field="signupForm.user_terms_accepted"/>
  151 + </div>
  152 + <div class="form-group">
  153 + <div id="serpro_captcha" class="captcha">
165 154 </div>
166   - <div class="form-group">
167   - <button class="btn btn-lg btn-block btn-submit" ng-class=" {'disabled' : !pageSignin.signup.user_terms_accepted }" type="submit">Cadastrar</button>
  155 + <div class="captcha">
  156 + Digite os caracteres acima:
168 157 </div>
169   - </form>
170   - </div>
  158 + <div class="captcha">
  159 + <input type="text" name="captcha_text" id="captcha_text" aria-label="Escreva os caracteres do captcha aqui" ng-model="pageSignin.signup.captcha_text">
  160 + </div>
  161 + </div>
  162 + <div class="form-group">
  163 + <button class="btn btn-lg btn-block btn-submit" ng-class=" {'disabled' : !pageSignin.signup.user_terms_accepted }" type="submit">Cadastrar</button>
  164 + </div>
  165 + </form>
171 166 </div>
172 167 </div>
173 168 </div>
... ...
src/app/pages/programas/programa.controller.js
... ... @@ -66,7 +66,7 @@
66 66 vm.$rootScope.contentTitle = vm.article.title;
67 67  
68 68 // set the banner image with full image path
69   - if (!vm.banner) {
  69 + if (!vm.banner && vm.article.image) {
70 70 vm.banner = {
71 71 src: vm.PATH.image + vm.article.image.url,
72 72 alt: 'Imagem de destaque do conteúdo'
... ... @@ -209,12 +209,12 @@
209 209 value: value
210 210 }, function(response) {
211 211 vm.$log.debug('response', response);
212   -
  212 +
213 213 response.success = true;
214 214 vm.$scope.$broadcast('proposal-box:vote-response', response);
215 215 }, function(error) {
216 216 vm.$log.error('error', error);
217   -
  217 +
218 218 error.error = true;
219 219 vm.$scope.$broadcast('proposal-box:vote-response', error);
220 220 });
... ...
src/index.html
... ... @@ -60,5 +60,6 @@
60 60 <!-- endinject -->
61 61 <!-- endbuild -->
62 62 <script defer="defer" src="http://barra.brasil.gov.br/barra.js" type="text/javascript"></script>
  63 + <script defer="defer" src="http://captcha2.servicoscorporativos.serpro.gov.br/js/captcha.serpro.gov.br.js"></script>
63 64 </body>
64 65 </html>
... ...