Commit 8820112c1f81765063ceabea284abbac6ec6004e

Authored by Leonardo Merlin
2 parents 9cc7a83a 3b946930

Merge branch 'merlin' into rafael

Conflicts:
	src/app/layout.scss
Showing 41 changed files with 385 additions and 248 deletions   Show diff stats
gulp/images.js
@@ -18,7 +18,8 @@ gulp.task('sprites', function () { @@ -18,7 +18,8 @@ gulp.task('sprites', function () {
18 return sprity.src({ 18 return sprity.src({
19 src: src, 19 src: src,
20 style: 'sprite.css', 20 style: 'sprite.css',
21 - cssPath: '../assets/images/icons/' 21 + cssPath: '../assets/images/icons/',
  22 + cachebuster: true
22 }) 23 })
23 .pipe(gulpif('*.png', gulp.dest(destImg), gulp.dest(destCss))); 24 .pipe(gulpif('*.png', gulp.dest(destImg), gulp.dest(destCss)));
24 }); 25 });
src/app/components/article-box/article-box.html
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 <div class="article-box--title"> 7 <div class="article-box--title">
8 <h1>{{::vm.article.title}}</h1> 8 <h1>{{::vm.article.title}}</h1>
9 </div> 9 </div>
10 - <div class="article-box--abstract" ng-bind-html="vm.article.abstract"></div> 10 + <div class="article-box--abstract" ng-bind-html="vm.article.summary"></div>
11 <div class="button--themed"> 11 <div class="button--themed">
12 <button class="btn btn-block"> 12 <button class="btn btn-block">
13 Participe 13 Participe
src/app/components/article-service/article.service.js
@@ -146,6 +146,9 @@ @@ -146,6 +146,9 @@
146 var url = service.apiProposals + targetId + '/propose'; 146 var url = service.apiProposals + targetId + '/propose';
147 147
148 var encodedParams = []; 148 var encodedParams = [];
  149 + encodedParams.push('article%5Babstract%5D=' + proposal);
  150 + encodedParams.push('article%5Btype%5D=ProposalsDiscussionPlugin%3A%3AProposal');
  151 + encodedParams.push('content_type=ProposalsDiscussionPlugin%3A%3AProposal');
149 encodedParams.push('private_token=' + $rootScope.currentUser.private_token); 152 encodedParams.push('private_token=' + $rootScope.currentUser.private_token);
150 encodedParams.push('fields=id'); 153 encodedParams.push('fields=id');
151 encodedParams.push('article[name]=article_' + GUID.generate()); 154 encodedParams.push('article[name]=article_' + GUID.generate());
src/app/components/dialoga-service/dialoga.service.js
@@ -25,6 +25,8 @@ @@ -25,6 +25,8 @@
25 extendedService.getQuestions = getQuestions; 25 extendedService.getQuestions = getQuestions;
26 extendedService.searchPrograms = searchPrograms; 26 extendedService.searchPrograms = searchPrograms;
27 extendedService.searchProposals = searchProposals; 27 extendedService.searchProposals = searchProposals;
  28 + extendedService.filterProposalsByCategorySlug = filterProposalsByCategorySlug;
  29 + extendedService.filterProposalsByProgramId = filterProposalsByProgramId;
28 30
29 var CACHE = {}; 31 var CACHE = {};
30 32
@@ -230,6 +232,51 @@ @@ -230,6 +232,51 @@
230 ArticleService.searchProposals(params, cbSuccess, cbError); 232 ArticleService.searchProposals(params, cbSuccess, cbError);
231 } 233 }
232 234
  235 + function filterProposalsByCategorySlug (input, categorySlug) {
  236 +
  237 + if(!angular.isArray(input)){
  238 + $log.error('Input is not a Array.');
  239 + return [];
  240 + }
  241 +
  242 + // Use native array filter
  243 + return input.filter(function(value/*, index, arr*/) {
  244 +
  245 + if (!value.parent) {
  246 + $log.warn('Proposal without a parent.');
  247 + return false;
  248 + }
  249 +
  250 + if (!value.parent.categories || value.parent.categories.length === 0) {
  251 + $log.warn('Proposal parent has no categories.');
  252 + return false;
  253 + }
  254 +
  255 + // match?!
  256 + return value.parent.categories[0].slug === categorySlug;
  257 + });
  258 + }
  259 +
  260 + function filterProposalsByProgramId (input, program_id) {
  261 +
  262 + if(!angular.isArray(input)){
  263 + $log.error('Input is not a Array.');
  264 + return [];
  265 + }
  266 +
  267 + // Use native array filter
  268 + return input.filter(function(value) {
  269 + if (!value.parent || !value.parent.id) {
  270 + $log.warn('Proposal has no parent.');
  271 +
  272 + return false;
  273 + }
  274 +
  275 + // match?!
  276 + return value.parent.id === program_id;
  277 + });
  278 + }
  279 +
233 function _pipeHandleYoutube (data) { 280 function _pipeHandleYoutube (data) {
234 var abstract = data.article.abstract; 281 var abstract = data.article.abstract;
235 282
@@ -269,6 +316,31 @@ @@ -269,6 +316,31 @@
269 CACHE.programs = data.article.children; 316 CACHE.programs = data.article.children;
270 CACHE.programs_count = data.article.children_count; 317 CACHE.programs_count = data.article.children_count;
271 } 318 }
  319 +
  320 + _pipeHackPrograms(CACHE.programs);
  321 + }
  322 +
  323 + function _pipeHackPrograms (programs) {
  324 +
  325 + if(!angular.isArray(programs)){
  326 + return;
  327 + }
  328 +
  329 + var program = null;
  330 + var parts = null;
  331 + for (var i = programs.length - 1; i >= 0; i--) {
  332 + program = programs[i];
  333 +
  334 + if(!program.summary){
  335 + parts = program.abstract.split('<hr />');
  336 +
  337 + program.summary = $rootScope.stripHtml(parts[0]).trim();
  338 +
  339 + if(parts.length > 1){
  340 + program.summaryExtended = parts[1].trim();
  341 + }
  342 + }
  343 + }
272 } 344 }
273 345
274 // Calculate color pallet 346 // Calculate color pallet
src/app/components/proposal-box/proposal-box.html
@@ -148,7 +148,7 @@ @@ -148,7 +148,7 @@
148 </div> 148 </div>
149 <div class="proposal-box--bottom text-center"> 149 <div class="proposal-box--bottom text-center">
150 <div class="proposal-box--share"> 150 <div class="proposal-box--share">
151 - <span>COMPARTILHE ESSA <b>PROPOSTA</b></span> 151 + <span>COMPARTILHE ESTA <b>PROPOSTA</b></span>
152 <div class="dropdown"> 152 <div class="dropdown">
153 <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> 153 <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>
154 <social-share class="dropdown-menu dropdown-menu-right"></social-share> 154 <social-share class="dropdown-menu dropdown-menu-right"></social-share>
src/app/components/show-message/show-message.directive.js
@@ -19,8 +19,8 @@ @@ -19,8 +19,8 @@
19 templateUrl: 'app/components/show-message/show-message.html', 19 templateUrl: 'app/components/show-message/show-message.html',
20 scope: { 20 scope: {
21 type: '=', 21 type: '=',
22 - title: '=',  
23 - message: '=' 22 + message: '=',
  23 + description: '='
24 }, 24 },
25 controller: ShowMessageController, 25 controller: ShowMessageController,
26 controllerAs: 'vm', 26 controllerAs: 'vm',
src/app/components/show-message/show-message.html
@@ -8,8 +8,8 @@ @@ -8,8 +8,8 @@
8 </div> 8 </div>
9 </div> 9 </div>
10 <div class="col-sm-8 message-content text-center-sm"> 10 <div class="col-sm-8 message-content text-center-sm">
11 - <h3>{{ ::vm.title }}</h3>  
12 - <p>{{ ::vm.message }}</p> 11 + <h3>{{ ::vm.message }}</h3>
  12 + <div ng-bind-html="vm.description"></div>
13 </div> 13 </div>
14 </div> 14 </div>
15 </div> 15 </div>
src/app/components/util-service/utils.service.js
@@ -68,7 +68,7 @@ @@ -68,7 +68,7 @@
68 // nomralized format. However, if the request was not handled by the 68 // nomralized format. However, if the request was not handled by the
69 // server (or what not handles properly - ex. server error), then we 69 // server (or what not handles properly - ex. server error), then we
70 // may have to normalize it on our end, as best we can. 70 // may have to normalize it on our end, as best we can.
71 - if (!angular.isObject(error.data) || !error.data.message) { 71 + if (!angular.isObject(error.data)) {
72 return $q.reject('An unknown error occurred.'); 72 return $q.reject('An unknown error occurred.');
73 } 73 }
74 74
src/app/layout.scss
@@ -293,38 +293,39 @@ a.link-black { @@ -293,38 +293,39 @@ a.link-black {
293 color: black; 293 color: black;
294 } 294 }
295 295
296 -article.program-content {  
297 - margin-top: 40px;  
298 -}  
299 -  
300 -article.program-content div.ng-binding div.container div.row {  
301 - margin-bottom: 40px;  
302 -}  
303 -  
304 -article.program-content h3 {  
305 - margin-bottom: 15px;  
306 -}  
307 -  
308 .inline-block { 296 .inline-block {
309 display: inline-block; 297 display: inline-block;
310 } 298 }
311 299
  300 +// Sobreescreve a classe do bootstrap
  301 +.close {
  302 + color: white;
  303 + opacity: 1;
  304 + font-weight: normal;
  305 +}
  306 +
312 blockquote { 307 blockquote {
313 - border-left: medium none;  
314 - font-size: 140%; 308 + border-left: none;
  309 + font-size: 24px;
  310 + line-height: 28px;
315 padding: 50px 0 0 50px; 311 padding: 50px 0 0 50px;
316 position: relative; 312 position: relative;
  313 +
  314 + @each $category, $color in $categories {
  315 + .#{$category} & {
  316 + color: $color;
  317 + }
  318 + }
  319 +
317 &:before { 320 &:before {
318 content: "⌜"; 321 content: "⌜";
319 font-size: 200px; 322 font-size: 200px;
320 - left: -2px; 323 + line-height: 200px;
321 position: absolute; 324 position: absolute;
322 - top: -50px; 325 + top: -10px;
  326 + left: -10px;
323 font-weight: bolder; 327 font-weight: bolder;
324 - left: -17px;  
325 - top: -68px;  
326 - @each $category,  
327 - $color in $categories { 328 + @each $category, $color in $categories {
328 .#{$category} & { 329 .#{$category} & {
329 color: $color; 330 color: $color;
330 } 331 }
@@ -332,26 +333,6 @@ blockquote { @@ -332,26 +333,6 @@ blockquote {
332 } 333 }
333 } 334 }
334 335
335 -// .cultura blockquote::before {  
336 -// color: #cd999b;  
337 -// }  
338 -// Sobreescreve a classe do bootstrap  
339 -.close {  
340 - color: white;  
341 - opacity: 1;  
342 - font-weight: normal;  
343 -}  
344 -  
345 -// .img-responsive {  
346 -// width: 100%;  
347 -// }  
348 -//strong {  
349 -// @each $category, $color in $categories {  
350 -// .#{$category} & {  
351 -// color: $color;  
352 -// }  
353 -// }  
354 -//}  
355 .top-border-theme { 336 .top-border-theme {
356 @each $category, 337 @each $category,
357 $color in $categories { 338 $color in $categories {
src/app/pages/auth/recover.html
@@ -17,8 +17,8 @@ @@ -17,8 +17,8 @@
17 <div class="feedback-message"> 17 <div class="feedback-message">
18 <show-message 18 <show-message
19 type="'success'" 19 type="'success'"
20 - title="pageSignin.successRecoverMessageTitle || 'Pronto!'"  
21 - message="pageSignin.successRecoverMessage" 20 + message="pageSignin.successRecoverMessageTitle || 'Pronto!'"
  21 + description="pageSignin.successRecoverMessage"
22 ></show-message> 22 ></show-message>
23 <div class="row"> 23 <div class="row">
24 <div class="col-sm-8 col-sm-offset-4"> 24 <div class="col-sm-8 col-sm-offset-4">
src/app/pages/auth/signin.html
@@ -14,21 +14,21 @@ @@ -14,21 +14,21 @@
14 <div class="feedback-message"> 14 <div class="feedback-message">
15 <show-message 15 <show-message
16 type="'success'" 16 type="'success'"
17 - title="pageSignin.messageTitle || 'Você está logado!'"  
18 - message="pageSignin.successMessage" 17 + message="pageSignin.messageTitle || 'Você está logado!'"
  18 + description="pageSignin.successMessage"
19 ></show-message> 19 ></show-message>
20 20
21 <div class="row"> 21 <div class="row">
22 <div class="col-sm-4"></div> 22 <div class="col-sm-4"></div>
23 <div class="col-sm-8 text-center-sm"> 23 <div class="col-sm-8 text-center-sm">
24 - <!-- <div ng-if="pageSignin.redirect > 0">  
25 - </div> -->  
26 <div ng-if="pageSignin.countdown > 0"> 24 <div ng-if="pageSignin.countdown > 0">
27 <p> 25 <p>
28 Você será redirecionado em menos de <b>{{pageSignin.countdown}} segundos</b>... 26 Você será redirecionado em menos de <b>{{pageSignin.countdown}} segundos</b>...
29 </p> 27 </p>
30 </div> 28 </div>
31 - <button type="button" ng-click="pageSignin.onClickLogout()" class="btn btn-primary">Sair</button> 29 + <div ng-if="!pageSignin.hasRedirect">
  30 + <a ui-sref="inicio" class="btn btn-primary">Ir para a Página Inicial</a>
  31 + </div>
32 </div> 32 </div>
33 </div> 33 </div>
34 </div> 34 </div>
src/app/pages/inicio/inicio.controller.js
@@ -160,6 +160,21 @@ @@ -160,6 +160,21 @@
160 vm.article.videoIsLoaded = true; 160 vm.article.videoIsLoaded = true;
161 }; 161 };
162 162
  163 + InicioPageController.prototype.submitSearch = function() {
  164 + var vm = this;
  165 +
  166 + vm.loadingFilter = true;
  167 +
  168 + // scroll to result grid
  169 + var $searchResult = angular.element('#search-result');
  170 + if($searchResult && $searchResult.length > 0){
  171 + angular.element('body').animate({scrollTop: $searchResult.offset().top}, 'fast');
  172 + vm.filtredPrograms = vm.getFiltredPrograms();
  173 + }else{
  174 + vm.$log.warn('#search-result element not found.');
  175 + }
  176 + };
  177 +
163 InicioPageController.prototype.filter = function() { 178 InicioPageController.prototype.filter = function() {
164 var vm = this; 179 var vm = this;
165 180
@@ -218,6 +233,7 @@ @@ -218,6 +233,7 @@
218 var selectedTheme = vm.selectedTheme; 233 var selectedTheme = vm.selectedTheme;
219 234
220 var filter = vm.$filter('filter'); 235 var filter = vm.$filter('filter');
  236 + vm.loadingFilter = true;
221 237
222 if (selectedTheme) { 238 if (selectedTheme) {
223 output = vm._filterByCategory(output, selectedTheme); 239 output = vm._filterByCategory(output, selectedTheme);
@@ -231,6 +247,7 @@ @@ -231,6 +247,7 @@
231 output = _balanceByCategory(output); 247 output = _balanceByCategory(output);
232 } 248 }
233 249
  250 + vm.loadingFilter = false;
234 return output; 251 return output;
235 }; 252 };
236 253
@@ -259,7 +276,7 @@ @@ -259,7 +276,7 @@
259 } 276 }
260 277
261 return out; 278 return out;
262 - } 279 + };
263 280
264 function _balanceByCategory (input) { 281 function _balanceByCategory (input) {
265 var result = []; 282 var result = [];
src/app/pages/inicio/inicio.html
@@ -88,7 +88,7 @@ @@ -88,7 +88,7 @@
88 <label for="articleQueryFilter1" class="control-label sr-only">Buscar programas:</label> 88 <label for="articleQueryFilter1" class="control-label sr-only">Buscar programas:</label>
89 <input id="articleQueryFilter1" type="search" class="form-control input-search" ng-model="pageInicio.query" placeholder="Buscar programas" aria-label="Buscar programas" > 89 <input id="articleQueryFilter1" type="search" class="form-control input-search" ng-model="pageInicio.query" placeholder="Buscar programas" aria-label="Buscar programas" >
90 <span class="input-group-btn"> 90 <span class="input-group-btn">
91 - <button type="button" class="btn btn-default" ng-click="pageInicio.search()"> 91 + <button type="button" class="btn btn-default" ng-click="pageInicio.submitSearch()">
92 <span class="icon-circle icon-small color-theme-common-bg"> 92 <span class="icon-circle icon-small color-theme-common-bg">
93 <span class="glyphicon glyphicon-search"></span> 93 <span class="glyphicon glyphicon-search"></span>
94 </span> 94 </span>
@@ -120,7 +120,7 @@ @@ -120,7 +120,7 @@
120 <label for="articleQueryFilter2" class="control-label sr-only">Buscar programas:</label> 120 <label for="articleQueryFilter2" class="control-label sr-only">Buscar programas:</label>
121 <input id="articleQueryFilter2" type="search" class="form-control input-search" ng-model="pageInicio.query" placeholder="Buscar programas" aria-label="Buscar programas" > 121 <input id="articleQueryFilter2" type="search" class="form-control input-search" ng-model="pageInicio.query" placeholder="Buscar programas" aria-label="Buscar programas" >
122 <span class="input-group-btn"> 122 <span class="input-group-btn">
123 - <button type="button" class="btn btn-default" ng-click="pageInicio.search()"> 123 + <button type="button" class="btn btn-default" ng-click="pageInicio.submitSearch()">
124 <span class="icon-circle icon-small color-theme-common-bg"> 124 <span class="icon-circle icon-small color-theme-common-bg">
125 <span class="glyphicon glyphicon-search"></span> 125 <span class="glyphicon glyphicon-search"></span>
126 </span> 126 </span>
@@ -130,12 +130,12 @@ @@ -130,12 +130,12 @@
130 </div> 130 </div>
131 </div> 131 </div>
132 </div> 132 </div>
133 - <div class="row"> 133 + <div id="search-result" class="row">
134 <div class="col-sm-12"> 134 <div class="col-sm-12">
135 <header class="header"> 135 <header class="header">
136 <h2>Programas</h2> 136 <h2>Programas</h2>
137 <button type="button" class="btn btn-link" ng-click="pageInicio.showAllPrograms($event)"> 137 <button type="button" class="btn btn-link" ng-click="pageInicio.showAllPrograms($event)">
138 - <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> Ver todos os programas 138 + <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> Ver todos os {{::pageInicio.programs.length}} programas
139 </button> 139 </button>
140 </header> 140 </header>
141 </div> 141 </div>
src/app/pages/programas/programa.controller.js
@@ -122,10 +122,22 @@ @@ -122,10 +122,22 @@
122 122
123 vm.DialogaService.createProposal(proposal, vm.article.id, function(response) { 123 vm.DialogaService.createProposal(proposal, vm.article.id, function(response) {
124 vm.$log.debug('response', response); 124 vm.$log.debug('response', response);
  125 + // vm.message =
125 // vm.proposalStatus = vm.PROPOSAL_STATUS.SENT | vm.PROPOSAL_STATUS.SUCCESS; 126 // vm.proposalStatus = vm.PROPOSAL_STATUS.SENT | vm.PROPOSAL_STATUS.SUCCESS;
126 vm.proposalStatus = vm.PROPOSAL_STATUS.SUCCESS; 127 vm.proposalStatus = vm.PROPOSAL_STATUS.SUCCESS;
127 }, function(error) { 128 }, function(error) {
128 vm.$log.error(error); 129 vm.$log.error(error);
  130 +
  131 + vm.error = error;
  132 +
  133 + if (vm.error.code === 400){
  134 + // Bad Request
  135 + vm.error.message = '';
  136 + vm.error.message += 'Não foi possível enviar a proposta.<br>';
  137 + vm.error.message += 'Este problema já foi registrado em nossos servidores.<br>';
  138 + vm.error.message += 'Por favor, tente novamente mais tarde.';
  139 + }
  140 +
129 // vm.proposalStatus = vm.PROPOSAL_STATUS.SENT | vm.PROPOSAL_STATUS.ERROR; 141 // vm.proposalStatus = vm.PROPOSAL_STATUS.SENT | vm.PROPOSAL_STATUS.ERROR;
130 vm.proposalStatus = vm.PROPOSAL_STATUS.ERROR; 142 vm.proposalStatus = vm.PROPOSAL_STATUS.ERROR;
131 }); 143 });
src/app/pages/programas/programa.html
@@ -18,94 +18,104 @@ @@ -18,94 +18,104 @@
18 </div> 18 </div>
19 </section> 19 </section>
20 20
21 - <div role="main">  
22 - <section ng-if="pagePrograma.article.body" ng-class="pagePrograma.category.slug"> 21 + <div role="main" ng-class="pagePrograma.category.slug">
  22 + <section ng-if="pagePrograma.article.body">
23 <div class="container"> 23 <div class="container">
24 <div class="row"> 24 <div class="row">
25 <article class="program-preview"> 25 <article class="program-preview">
26 - <!-- Preview > Titulo -->  
27 - <div class="col-md-12">  
28 - <h1 class="program-preview--title color-theme-fg">{{::pagePrograma.article.title}}</h1>  
29 - </div>  
30 - <!-- Preview > coluna da esquerda -->  
31 - <div class="col-md-8">  
32 - <div class="program-preview--box contraste-box">  
33 - <div class="program-preview--banner" ng-style="{'background-image':'url( {{::pagePrograma.banner.src}} )'}"></div>  
34 - <div class="program-preview--box--content-wrapper">  
35 - <div class="program-preview--icon icon-wrapper-rounded color-theme-bg" ng-class="pagePrograma.category.slug">  
36 - <span class="icon" ng-class="'icon-tema-' + pagePrograma.category.slug"></span>  
37 - </div>  
38 - <div class="program-preview--abstract color-theme-fg">  
39 - <h2>{{::stripHtml(pagePrograma.article.abstract)}}</h2>  
40 - </div>  
41 - <div class="program-preview--abstract-details">  
42 - <p>Lorem ipsum dolor sit amet, ea veniam mucius ocurreret vix, ius ex nisl vidisse partiendo. Blandit nominavi cum ei, paulo quaestio his ei, eum minim salutandi in. Civibus albucius in quo, et eam posse facilisis. Debet suavitate sea ut, his ei feugiat fastidii eleifend. Quo ex quando maiestatis voluptatum, mel te perpetua maiestatis, sit ceteros legendos deserunt ea. Enim dolores moderatius eu pro, ad quo ignota aliquid meliore.</p>  
43 - </div>  
44 - <div class="program-preview--share">  
45 - <div class="program-preview--share-label">Compartilhe este programa:</div>  
46 - <social-share class="program-preview--share-directive"></social-share> 26 + <!-- Preview > Titulo -->
  27 + <div class="col-md-12">
  28 + <h1 class="program-preview--title color-theme-fg">{{::pagePrograma.article.title}}</h1>
  29 + </div>
  30 + <!-- Preview > coluna da esquerda -->
  31 + <div class="col-md-8">
  32 + <div class="program-preview--box contraste-box">
  33 + <div class="program-preview--banner" ng-style="{'background-image':'url( {{::pagePrograma.banner.src}} )'}"></div>
  34 + <div class="program-preview--box--content-wrapper">
  35 + <div class="program-preview--icon icon-wrapper-rounded color-theme-bg" ng-class="pagePrograma.category.slug">
  36 + <span class="icon" ng-class="'icon-tema-' + pagePrograma.category.slug"></span>
  37 + </div>
  38 + <div class="program-preview--abstract color-theme-fg">
  39 + <h2>{{::stripHtml(pagePrograma.article.summary)}}</h2>
  40 + </div>
  41 + <div class="program-preview--abstract-details">
  42 + <div ng-bind-html="pagePrograma.article.summaryExtended"></div>
  43 + <p>Lorem ipsum dolor sit amet, ea veniam mucius ocurreret vix, ius ex nisl vidisse partiendo. Blandit nominavi cum ei, paulo quaestio his ei, eum minim salutandi in. Civibus albucius in quo, et eam posse facilisis. Debet suavitate sea ut, his ei feugiat fastidii eleifend. Quo ex quando maiestatis voluptatum, mel te perpetua maiestatis, sit ceteros legendos deserunt ea. Enim dolores moderatius eu pro, ad quo ignota aliquid meliore.</p>
  44 + </div>
  45 + <div class="program-preview--share">
  46 + <div class="program-preview--share-label">COMPARTILHE ESTE <b>PROGRAMA</b></div>
  47 + <div class="dropdown">
  48 + <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>
  49 + <social-share
  50 + url=""
  51 + text=""
  52 + image=""
  53 + arrow-class="social-share--arrow"
  54 + class="dropdown-menu dropdown-menu-right"
  55 + ></social-share>
47 </div> 56 </div>
48 - <div class="program-preview--make-proposal">  
49 - <div class="row">  
50 - <div class="col-sm-6">  
51 - <div class="button--themed">  
52 - <button type="button" class="btn btn-block" ng-click="pagePrograma.showProposalForm()">Faça uma proposta</button>  
53 - </div> 57 + </div>
  58 + <div class="program-preview--make-proposal">
  59 + <div class="row">
  60 + <div class="col-sm-6">
  61 + <div class="button--themed">
  62 + <button type="button" class="btn btn-block" ng-click="pagePrograma.showProposalForm()">Faça uma proposta</button>
54 </div> 63 </div>
55 </div> 64 </div>
56 </div> 65 </div>
57 </div> 66 </div>
58 </div> 67 </div>
59 </div> 68 </div>
60 - <!-- Preview > coluna da direita -->  
61 - <div class="col-md-4">  
62 - <div class="row"> 69 + </div>
  70 + <!-- Preview > coluna da direita -->
  71 + <div class="col-md-4">
  72 + <div class="row">
63 73
64 - <!-- Top Proposals -->  
65 - <div>  
66 - <!-- Loading Top Proposals -->  
67 - <div ng-if="pagePrograma.loadingTopProposals">  
68 - <div class="alert alert-info" role="alert">  
69 - Carregando propostas mais votadas...  
70 - </div> 74 + <!-- Top Proposals -->
  75 + <div>
  76 + <!-- Loading Top Proposals -->
  77 + <div ng-if="pagePrograma.loadingTopProposals">
  78 + <div class="alert alert-info" role="alert">
  79 + Carregando propostas mais votadas...
71 </div> 80 </div>
  81 + </div>
72 82
73 - <!-- Top Proposals > Carousel -->  
74 - <div class="col-xs-12" ng-if="!pagePrograma.loadingTopProposals && pagePrograma.proposalsTopRated && pagePrograma.proposalsTopRated.length > 0">  
75 - <h3 class="color-theme-fg">Propostas mais votadas</h3>  
76 - <proposal-carousel proposals="pagePrograma.proposalsTopRated"></proposal-carousel>  
77 - </div> 83 + <!-- Top Proposals > Carousel -->
  84 + <div class="col-xs-12" ng-if="!pagePrograma.loadingTopProposals && pagePrograma.proposalsTopRated && pagePrograma.proposalsTopRated.length > 0">
  85 + <h3 class="color-theme-fg">Propostas mais votadas</h3>
  86 + <proposal-carousel proposals="pagePrograma.proposalsTopRated"></proposal-carousel>
78 </div> 87 </div>
  88 + </div>
79 89
80 - <!-- Proposal Box -->  
81 - <div>  
82 - <div class="col-xs-12" ng-if="!pagePrograma.loadingProposalBox && pagePrograma.randomProposal" ng-class="{'focused-proposal': !!pagePrograma.search.proposal_id}">  
83 - <h3 class="color-theme-fg">Apoie outras propostas</h3>  
84 - <proposal-box proposal="pagePrograma.randomProposal" topic="pagePrograma.article" category="pagePrograma.category" can-vote="true" focus="{{pagePrograma.search.proposal_id}}" ></proposal-box>  
85 - </div> 90 + <!-- Proposal Box -->
  91 + <div>
  92 + <div class="col-xs-12" ng-if="!pagePrograma.loadingProposalBox && pagePrograma.randomProposal" ng-class="{'focused-proposal': !!pagePrograma.search.proposal_id}">
  93 + <h3 class="color-theme-fg">Apoie outras propostas</h3>
  94 + <proposal-box proposal="pagePrograma.randomProposal" topic="pagePrograma.article" category="pagePrograma.category" can-vote="true" focus="{{pagePrograma.search.proposal_id}}" ></proposal-box>
  95 + </div>
86 96
87 - <!-- Loading Proposal Box -->  
88 - <div ng-if="pagePrograma.loadingProposalBox">  
89 - <div class="alert alert-info" role="alert">  
90 - Carregando propostas nesse programa...  
91 - </div> 97 + <!-- Loading Proposal Box -->
  98 + <div ng-if="pagePrograma.loadingProposalBox">
  99 + <div class="alert alert-info" role="alert">
  100 + Carregando propostas nesse programa...
92 </div> 101 </div>
93 </div> 102 </div>
  103 + </div>
94 104
95 - <!-- No Proposals? okay! -->  
96 - <div ng-if="!pagePrograma.loadingTopProposals && !pagePrograma.loadingProposalBox">  
97 - <div class="col-xs-12" ng-if="!pagePrograma.randomProposal && !(pagePrograma.proposalsTopRated && pagePrograma.proposalsTopRated.length > 0)">  
98 - <h3>Programas sem propostas</h3>  
99 - <p>  
100 - Este programa ainda não possui nenhuma proposta.  
101 - <div class="button--themed">  
102 - <button type="button" class="btn btn-block" ng-click="pagePrograma.showProposalForm()">Faça uma proposta</button>  
103 - </div>  
104 - </p>  
105 - </div> 105 + <!-- No Proposals? okay! -->
  106 + <div ng-if="!pagePrograma.loadingTopProposals && !pagePrograma.loadingProposalBox">
  107 + <div class="col-xs-12" ng-if="!pagePrograma.randomProposal && !(pagePrograma.proposalsTopRated && pagePrograma.proposalsTopRated.length > 0)">
  108 + <h3>Programas sem propostas</h3>
  109 + <p>
  110 + Este programa ainda não possui nenhuma proposta.
  111 + <div class="button--themed">
  112 + <button type="button" class="btn btn-block" ng-click="pagePrograma.showProposalForm()">Faça uma proposta</button>
  113 + </div>
  114 + </p>
106 </div> 115 </div>
107 </div> 116 </div>
108 </div> 117 </div>
  118 + </div>
109 </article> 119 </article>
110 </div> 120 </div>
111 </div> 121 </div>
@@ -143,8 +153,8 @@ @@ -143,8 +153,8 @@
143 <div ng-if="!pagePrograma.$rootScope.currentUser"> 153 <div ng-if="!pagePrograma.$rootScope.currentUser">
144 <show-message 154 <show-message
145 type="'alert'" 155 type="'alert'"
146 - title="'Você não está logado!'"  
147 - message="'Você precisa estar logado para enviar uma proposta.'" 156 + message="'Você não está logado!'"
  157 + description="'Você precisa estar logado para enviar uma proposta.'"
148 ></show-message> 158 ></show-message>
149 <div class="row"> 159 <div class="row">
150 <div class="col-sm-4"></div> 160 <div class="col-sm-4"></div>
@@ -158,8 +168,26 @@ @@ -158,8 +168,26 @@
158 <div ng-if="pagePrograma.proposalStatus === pagePrograma.PROPOSAL_STATUS.SUCCESS"> 168 <div ng-if="pagePrograma.proposalStatus === pagePrograma.PROPOSAL_STATUS.SUCCESS">
159 <show-message 169 <show-message
160 type="'success'" 170 type="'success'"
161 - title="'Proposta enviada com sucesso!'"  
162 - message="'Sua proposta foi enviada para a nossa equipe de moderação. Em aproximadamente 72 horas você receberá em seu endereço de e-mail uma resposta sobre a sua proposta.'" 171 + message="'Proposta enviada com sucesso!'"
  172 + description="'Sua proposta foi enviada para a nossa equipe de moderação. Em aproximadamente 72 horas você receberá em seu endereço de e-mail uma resposta sobre a sua proposta.'"
  173 + ></show-message>
  174 + <div class="row">
  175 + <div class="col-sm-4"></div>
  176 + <div class="col-sm-8 text-center-sm">
  177 + <button type="button" class="btn btn-link" ng-click="pagePrograma.sendAnotherProposal()">
  178 + Clique aqui para enviar outra proposta
  179 + </button>
  180 + </div>
  181 + </div>
  182 + </div>
  183 + <div ng-if="pagePrograma.proposalStatus === pagePrograma.PROPOSAL_STATUS.SENDING">
  184 + Enviando...
  185 + </div>
  186 + <div ng-if="pagePrograma.proposalStatus === pagePrograma.PROPOSAL_STATUS.ERROR">
  187 + <show-message
  188 + type="'error'"
  189 + message="'Erro ' + pagePrograma.error.code + '!'"
  190 + description="pagePrograma.error.message"
163 ></show-message> 191 ></show-message>
164 <div class="row"> 192 <div class="row">
165 <div class="col-sm-4"></div> 193 <div class="col-sm-4"></div>
@@ -170,7 +198,6 @@ @@ -170,7 +198,6 @@
170 </div> 198 </div>
171 </div> 199 </div>
172 </div> 200 </div>
173 - <div ng-if="pagePrograma.proposalStatus === pagePrograma.PROPOSAL_STATUS.ERROR"></div>  
174 <div ng-if="!pagePrograma.proposalStatus"> 201 <div ng-if="!pagePrograma.proposalStatus">
175 <cadastro-proposta program="pagePrograma.article" status="pagePrograma.proposalStatus"></cadastro-proposta> 202 <cadastro-proposta program="pagePrograma.article" status="pagePrograma.proposalStatus"></cadastro-proposta>
176 </div> 203 </div>
src/app/pages/programas/programas.controller.js
@@ -212,7 +212,7 @@ @@ -212,7 +212,7 @@
212 } 212 }
213 213
214 return out; 214 return out;
215 - } 215 + };
216 216
217 ProgramasPageController.prototype._balanceByCategory = function (input) { 217 ProgramasPageController.prototype._balanceByCategory = function (input) {
218 var vm = this; 218 var vm = this;
@@ -276,5 +276,5 @@ @@ -276,5 +276,5 @@
276 } 276 }
277 277
278 return result; 278 return result;
279 - } 279 + };
280 })(); 280 })();
src/app/pages/programas/programas.scss
@@ -7,81 +7,151 @@ @@ -7,81 +7,151 @@
7 } 7 }
8 } 8 }
9 9
10 -.program-preview { 10 +.page--program {
11 11
12 - .program-preview--box {  
13 - position: relative;  
14 - background-color: #f1f1f1;  
15 - } 12 + .program-preview {
16 13
17 - .program-preview--banner {  
18 - width: 100%;  
19 - height: 400px; 14 + .program-preview--box {
  15 + position: relative;
  16 + background-color: #f1f1f1;
  17 + }
  18 +
  19 + .program-preview--banner {
  20 + width: 100%;
  21 + height: 400px;
20 22
21 - background-position: center;  
22 - background-size: cover;  
23 - background-repeat: no-repeat; 23 + background-position: center;
  24 + background-size: cover;
  25 + background-repeat: no-repeat;
24 26
25 27
26 28
27 - @media screen and (max-width: $screen-xs) {  
28 - // height: 15px; 29 + @media screen and (max-width: $screen-xs) {
  30 + // height: 15px;
29 31
30 - // .video {  
31 - // height: 290px;  
32 - // } 32 + // .video {
  33 + // height: 290px;
  34 + // }
  35 + }
33 } 36 }
34 - }  
35 37
36 - .program-preview--icon {  
37 - $icon-size: 98px;  
38 - $icon-scale: 0.7;  
39 - position: absolute;  
40 - top: (-1) * ($icon-size / 2);  
41 - left: 40px; 38 + .program-preview--icon {
  39 + $icon-size: 80px;
  40 + $icon-scale: 0.7;
  41 + position: absolute;
  42 + top: (-1) * ($icon-size / 2);
  43 + left: 40px;
  44 +
  45 + width: $icon-size * $icon-scale + 25px;
  46 + height: $icon-size * $icon-scale + 25px;
  47 +
  48 + .icon {
  49 + display: block;
  50 + position: relative;
  51 + top: -2px;
  52 + left: -2px;
  53 + }
  54 +
  55 + .contraste & {
  56 + border: 1px solid #fff;
  57 + }
  58 + }
42 59
43 - width: $icon-size * $icon-scale + 20px;  
44 - height: $icon-size * $icon-scale + 20px; 60 + .program-preview--box--content-wrapper {
  61 + padding: 48px;
  62 + position: relative;
  63 + }
  64 +
  65 + .program-preview--abstract {
  66 + h2 {
  67 + margin-top: 22px; // parent.margin + this.margin = 48 + 22 = 72px;
  68 + margin-bottom: 32px;
  69 + }
  70 + }
45 71
46 - .icon {  
47 - display: block; 72 + .program-preview--abstract-details {
  73 + p {
  74 + color: #484848;
  75 + font-size: 14px;
  76 + line-height: 18px;
  77 + margin-bottom: 25px;
  78 + }
  79 + }
  80 +
  81 + .program-preview--share {
  82 + margin-bottom: 20px;
48 position: relative; 83 position: relative;
49 - top: -8px;  
50 - left: -8px;  
51 - // transform: scale($icon-scale); 84 + .dropdown {
  85 + display: inline-block;
  86 + position: relative;
  87 + }
  88 +
  89 + .dropdown-menu {
  90 + padding: 0;
  91 + margin: 0;
  92 + }
  93 +
  94 + .social-share {
  95 + background-color: #fff;
  96 + }
  97 +
  98 + .social-share--arrow {
  99 + border-bottom-color: #fff;
  100 + }
52 } 101 }
53 102
54 - .contraste & {  
55 - border: 1px solid #fff; 103 + .program-preview--share-label,
  104 + .program-preview--share-directive {
  105 + display: inline-block;
  106 + vertical-align: middle;
56 } 107 }
57 - }  
58 108
59 - .program-preview--box--content-wrapper {  
60 - padding: 40px;  
61 - position: relative;  
62 - } 109 + h1 {
  110 + font-size: 38px;
  111 + line-height: 40px;
  112 + font-weight: 900;
  113 + }
63 114
64 - .program-preview--share-label,  
65 - .program-preview--share-directive {  
66 - display: inline-block;  
67 - vertical-align: middle; 115 + h2 {
  116 + font-size: 32px;
  117 + line-height: 36px;
  118 + font-weight: bold;
  119 + }
68 } 120 }
69 121
70 - .program-preview--abstract h2 {  
71 - font-size: 40px;  
72 - } 122 + .program-content {
73 123
74 - h2,  
75 - h3{  
76 - font-weight: bold;  
77 - } 124 + margin-top: 40px;
78 125
79 - h3 {  
80 - margin-top: 0;  
81 - }  
82 -} 126 + h3 {
  127 + font-size: 22px;
  128 + line-height: 26px;
  129 + font-weight: bold;
83 130
84 -.page--program { 131 + margin-top: 0;
  132 + margin-bottom: 15px;
  133 + }
  134 +
  135 + h4 {
  136 + font-size: 18px;
  137 + line-height: 24px;
  138 + font-weight: bold;
  139 + }
  140 +
  141 + h5 {
  142 + font-size: 16px;
  143 + line-height: 22px;
  144 + }
  145 +
  146 + p {
  147 + font-size: 14px;
  148 + line-height: 18px;
  149 + }
  150 +
  151 + .container > .row {
  152 + margin-bottom: 40px;
  153 + }
  154 + }
85 155
86 .btn-close { 156 .btn-close {
87 position: absolute; 157 position: absolute;
src/app/pages/propostas/propostas.controller.js
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 $log.debug('PropostasPageController'); 22 $log.debug('PropostasPageController');
23 } 23 }
24 24
25 - PropostasPageController.prototype.init = function () { 25 + PropostasPageController.prototype.init = function() {
26 var vm = this; 26 var vm = this;
27 27
28 vm.themes = null; 28 vm.themes = null;
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 vm.error = null; 38 vm.error = null;
39 }; 39 };
40 40
41 - PropostasPageController.prototype.loadData = function () { 41 + PropostasPageController.prototype.loadData = function() {
42 var vm = this; 42 var vm = this;
43 43
44 vm.loading = true; 44 vm.loading = true;
@@ -50,15 +50,15 @@ @@ -50,15 +50,15 @@
50 50
51 // 1. Load themes 51 // 1. Load themes
52 vm.loadingThemes = true; 52 vm.loadingThemes = true;
53 - vm.DialogaService.getThemes(function(themes){ 53 + vm.DialogaService.getThemes(function(themes) {
54 vm.themes = themes; 54 vm.themes = themes;
55 vm.loadingThemes = false; 55 vm.loadingThemes = false;
56 vm.loading = false; 56 vm.loading = false;
57 57
58 - vm.loadProposals(function (){ 58 + vm.loadProposals(function() {
59 vm.attachListeners(); 59 vm.attachListeners();
60 }); 60 });
61 - }, function (error) { 61 + }, function(error) {
62 vm.error = error; 62 vm.error = error;
63 vm.$log.error(error); 63 vm.$log.error(error);
64 vm.loadingThemes = false; 64 vm.loadingThemes = false;
@@ -66,21 +66,21 @@ @@ -66,21 +66,21 @@
66 }); 66 });
67 }; 67 };
68 68
69 - PropostasPageController.prototype.loadProposals = function (cb) { 69 + PropostasPageController.prototype.loadProposals = function(cb) {
70 var vm = this; 70 var vm = this;
71 71
72 // load Proposals 72 // load Proposals
73 vm.loadingProposals = true; 73 vm.loadingProposals = true;
74 - vm.DialogaService.getProposals({}, function(data){ 74 + vm.DialogaService.getProposals({}, function(data) {
75 vm.proposals = data.articles; 75 vm.proposals = data.articles;
76 vm.filtredProposals = vm.proposals; 76 vm.filtredProposals = vm.proposals;
77 vm.loadingProposals = false; 77 vm.loadingProposals = false;
78 vm.loading = false; 78 vm.loading = false;
79 79
80 - if(cb){ 80 + if (cb) {
81 cb(); 81 cb();
82 } 82 }
83 - }, function (error) { 83 + }, function(error) {
84 vm.error = error; 84 vm.error = error;
85 vm.$log.error(error); 85 vm.$log.error(error);
86 vm.loadingProposals = false; 86 vm.loadingProposals = false;
@@ -91,21 +91,21 @@ @@ -91,21 +91,21 @@
91 PropostasPageController.prototype.attachListeners = function() { 91 PropostasPageController.prototype.attachListeners = function() {
92 var vm = this; 92 var vm = this;
93 93
94 - vm.$scope.$on('change-selectedCategory', function (event, selectedCategory) { 94 + vm.$scope.$on('change-selectedCategory', function(event, selectedCategory) {
95 vm.selectedTheme = selectedCategory; 95 vm.selectedTheme = selectedCategory;
96 }); 96 });
97 97
98 - vm.$scope.$watch('pagePropostas.selectedTheme', function(newValue, oldValue) { 98 + vm.$scope.$watch('pagePropostas.selectedTheme', function(newValue/*, oldValue*/) {
99 vm.search.tema = newValue ? newValue.slug : null; 99 vm.search.tema = newValue ? newValue.slug : null;
100 vm.$location.search('tema', vm.search.tema); 100 vm.$location.search('tema', vm.search.tema);
101 vm.filtredProposals = vm.getFiltredProposals(); 101 vm.filtredProposals = vm.getFiltredProposals();
102 }); 102 });
103 103
104 - vm.$scope.$on('change-selectedTopic', function (event, selectedTopic) { 104 + vm.$scope.$on('change-selectedTopic', function(event, selectedTopic) {
105 vm.selectedProgram = selectedTopic; 105 vm.selectedProgram = selectedTopic;
106 }); 106 });
107 107
108 - vm.$scope.$watch('pagePropostas.selectedProgram', function(newValue, oldValue) { 108 + vm.$scope.$watch('pagePropostas.selectedProgram', function(newValue/*, oldValue*/) {
109 vm.search.programa = newValue ? newValue.slug : null; 109 vm.search.programa = newValue ? newValue.slug : null;
110 vm.$location.search('programa', vm.search.programa); 110 vm.$location.search('programa', vm.search.programa);
111 vm.filtredProposals = vm.getFiltredProposals(); 111 vm.filtredProposals = vm.getFiltredProposals();
@@ -128,7 +128,7 @@ @@ -128,7 +128,7 @@
128 PropostasPageController.prototype.getFiltredProposals = function() { 128 PropostasPageController.prototype.getFiltredProposals = function() {
129 var vm = this; 129 var vm = this;
130 130
131 - if(!vm.proposals){ 131 + if (!vm.proposals) {
132 vm.$log.info('No proposals loaded yet. Abort.'); 132 vm.$log.info('No proposals loaded yet. Abort.');
133 return null; 133 return null;
134 } 134 }
@@ -142,64 +142,18 @@ @@ -142,64 +142,18 @@
142 var filter = vm.$filter('filter'); 142 var filter = vm.$filter('filter');
143 143
144 if (selectedTheme) { 144 if (selectedTheme) {
145 - output = vm._filterByCategory(output, selectedTheme); 145 + output = vm.DialogaService.filterProposalsByCategorySlug(output, selectedTheme.slug);
146 } 146 }
147 147
148 if (selectedProgram) { 148 if (selectedProgram) {
149 - output = vm._filterByProgram(output, selectedProgram); 149 + output = vm.DialogaService.filterProposalsByProgramId(output, selectedProgram.id);
150 } 150 }
151 151
152 if (query) { 152 if (query) {
153 output = filter(output, query, false); 153 output = filter(output, query, false);
154 } 154 }
155 155
156 - // if(!query && !selectedTheme && vm._showAllFlag){  
157 - // output = _balanceByCategory(output);  
158 - // }  
159 -  
160 return output; 156 return output;
161 }; 157 };
162 158
163 - PropostasPageController.prototype._filterByCategory = function (input, category) {  
164 - var vm = this;  
165 -  
166 - input = input || [];  
167 -  
168 - if (!category) {  
169 - // no filter  
170 - return input;  
171 - }  
172 -  
173 - var out = [];  
174 - for (var i = 0; i < input.length; i++) {  
175 - var proposal = input[i];  
176 - if (proposal.parent.categories[0].slug === category.slug) {  
177 - out.push(proposal);  
178 - }  
179 - }  
180 -  
181 - return out;  
182 - }  
183 -  
184 - PropostasPageController.prototype._filterByProgram = function (input, program) {  
185 - var vm = this;  
186 -  
187 - input = input || [];  
188 -  
189 - if (!program) {  
190 - // no filter  
191 - return input;  
192 - }  
193 -  
194 - var out = [];  
195 - for (var i = 0; i < input.length; i++) {  
196 - var proposal = input[i];  
197 - if (proposal.parent.id === program.id) {  
198 - out.push(proposal);  
199 - }  
200 - }  
201 -  
202 - return out;  
203 - }  
204 -  
205 })(); 159 })();
src/assets/images/icons/feedback-login-success-blue.png

4.29 KB

src/assets/images/icons/feedback-login-success-green.png

4.4 KB

src/assets/images/icons/feedback-login-success-red.png

4.33 KB

src/assets/images/icons/feedback-login-success-yellow.png

3.86 KB

src/assets/images/icons/feedback-proposal-sent-blue.png

3.53 KB

src/assets/images/icons/feedback-proposal-sent-green.png

3.63 KB

src/assets/images/icons/feedback-proposal-sent-red.png

3.53 KB

src/assets/images/icons/feedback-proposal-sent-yellow.png

3.15 KB

src/assets/images/icons/feedback-user-created.png

3.2 KB

src/assets/images/icons/tema-agricultura.png

3.1 KB | W: | H:

2.83 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-cidades.png

2.45 KB | W: | H:

2.16 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-cultura.png

2.24 KB | W: | H:

2.26 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-desenvolvimento-produtivo.png

2.88 KB | W: | H:

2.57 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-educacao.png

2.74 KB | W: | H:

2.48 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-esporte.png

2.21 KB | W: | H:

2.2 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-gestao-publica.png

2.1 KB | W: | H:

2.04 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-igualdade.png

2.73 KB | W: | H:

2.37 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-infraestrutura.png

2.99 KB | W: | H:

2.75 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-meio-ambiente.png

1.9 KB | W: | H:

1.88 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-reducao-da-pobreza.png

2.55 KB | W: | H:

2.36 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-saude.png

2.07 KB | W: | H:

1.95 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-seguranca-publica.png

2.47 KB | W: | H:

2.29 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/images/icons/tema-trabalho-emprego-e-renda.png

2.38 KB | W: | H:

2.15 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin