Commit c07e7c4b42e81fc477a1ce00108867a1dd7e3723
1 parent
e80daf58
Exists in
master
and in
8 other branches
Sync
Showing
27 changed files
with
893 additions
and
864 deletions
Show diff stats
src/app/components/article-grid/article-grid.directive.js
... | ... | @@ -26,7 +26,6 @@ |
26 | 26 | |
27 | 27 | // initialization |
28 | 28 | vm.init(); |
29 | - vm.loadData(); | |
30 | 29 | vm.attachListeners(); |
31 | 30 | } |
32 | 31 | |
... | ... | @@ -35,10 +34,6 @@ |
35 | 34 | // vm.programs = null; // scope var |
36 | 35 | }; |
37 | 36 | |
38 | - ArticleGridController.prototype.loadData = function() { | |
39 | - // var vm = this; | |
40 | - }; | |
41 | - | |
42 | 37 | ArticleGridController.prototype.attachListeners = function() { |
43 | 38 | // var vm = this; |
44 | 39 | }; | ... | ... |
src/app/components/article-service/article.service.js
... | ... | @@ -17,6 +17,8 @@ |
17 | 17 | getCategoryBySlug: getCategoryBySlug, |
18 | 18 | getTopics: getTopics, |
19 | 19 | getTopicById: getTopicById, |
20 | + getProposals: getProposals, | |
21 | + getProposalsByTopicId: getProposalsByTopicId, | |
20 | 22 | searchTopics: searchTopics, |
21 | 23 | searchProposals: searchProposals |
22 | 24 | }; |
... | ... | @@ -90,6 +92,40 @@ |
90 | 92 | }); |
91 | 93 | } |
92 | 94 | |
95 | + function getProposals (params, cbSuccess, cbError) { | |
96 | + // Ex.: /api/v1/articles/103358?fields= | |
97 | + | |
98 | + var url = service.apiArticles + API.articleId.home; | |
99 | + | |
100 | + var paramsExtended = angular.extend({ | |
101 | + 'fields[]': ['id', 'title', 'slug', 'abstract', 'categories', 'setting', 'children_count', 'hits'], | |
102 | + 'content_type':'ProposalsDiscussionPlugin::Proposals' | |
103 | + }, params); | |
104 | + | |
105 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
106 | + cbSuccess(data); | |
107 | + }).catch(function(error){ | |
108 | + cbError(error); | |
109 | + }); | |
110 | + } | |
111 | + | |
112 | + function getProposalsByTopicId (topicId, params, cbSuccess, cbError) { | |
113 | + var url = service.apiArticles + topicId; | |
114 | + | |
115 | + var paramsExtended = angular.extend({ | |
116 | + 'fields[]': ['id', 'title', 'abstract', 'children', 'children_count'], | |
117 | + 'content_type':'ProposalsDiscussionPlugin::Proposals' | |
118 | + }, params); | |
119 | + | |
120 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
121 | + cbSuccess(data); | |
122 | + }).catch(function(error){ | |
123 | + cbError(error); | |
124 | + }); | |
125 | + } | |
126 | + | |
127 | + function getRandomProposal (cbSuccess, cbError) {} | |
128 | + | |
93 | 129 | function searchTopics (params, cbSuccess, cbError) { |
94 | 130 | // Ex.: /api/v1/search/article?type=ProposalsDiscussionPlugin::Topic&query=cisternas |
95 | 131 | var url = '/api/v1/search/article'; | ... | ... |
src/app/components/dialoga-service/dialoga.service.js
... | ... | @@ -17,6 +17,7 @@ |
17 | 17 | getProgramBySlug: getProgramBySlug, |
18 | 18 | getProgramsRandom: getProgramsRandom, |
19 | 19 | getProposals: getProposals, |
20 | + getProposalsByTopicId: getProposalsByTopicId, | |
20 | 21 | getEvents: getEvents, |
21 | 22 | getQuestions: getQuestions, |
22 | 23 | searchProgram: searchProgram, |
... | ... | @@ -131,18 +132,20 @@ |
131 | 132 | // } |
132 | 133 | } |
133 | 134 | |
134 | - function getProposals (cbSuccess, cbError) { | |
135 | - if( !!CACHE.proposals ){ | |
135 | + function getProposals (param, cbSuccess, cbError) { | |
136 | + ArticleService.getProposals(param, function (data){ | |
137 | + CACHE.proposals = data; | |
138 | + | |
136 | 139 | cbSuccess(CACHE.proposals); |
137 | - }else{ | |
138 | - // load main content | |
139 | - getHome(function(){ | |
140 | - if(!CACHE.hasOwnProperty('proposals')){ | |
141 | - throw { name: 'NotFound', message: '"proposals" is not defined. "article.categories" was loaded?'}; | |
142 | - } | |
143 | - cbSuccess(CACHE.proposals); | |
144 | - },cbError); | |
145 | - } | |
140 | + }, cbError); | |
141 | + } | |
142 | + | |
143 | + function getProposalsByTopicId (topicId, params, cbSuccess, cbError) { | |
144 | + ArticleService.getProposalsByTopicId(topicId, params, function (data){ | |
145 | + CACHE.proposals = data; | |
146 | + | |
147 | + cbSuccess(CACHE.proposals); | |
148 | + }, cbError); | |
146 | 149 | } |
147 | 150 | |
148 | 151 | function getEvents (cbSuccess, cbError) { | ... | ... |
src/app/components/programas/programas.directive.js
... | ... | @@ -1,316 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - angular | |
5 | - .module('dialoga') | |
6 | - .directive('programaList', programaList); | |
7 | - | |
8 | - /** @ngInject */ | |
9 | - function programaList() { | |
10 | - | |
11 | - /** @ngInject */ | |
12 | - function ProgramaListController($scope, $element, $location, $filter, $log) { | |
13 | - $log.debug('ProgramaListController'); | |
14 | - | |
15 | - // alias | |
16 | - var vm = this; | |
17 | - | |
18 | - // dependencies | |
19 | - vm.$scope = $scope; | |
20 | - vm.$element = $element; | |
21 | - vm.$location = $location; | |
22 | - vm.$filter = $filter; | |
23 | - vm.$log = $log; | |
24 | - vm.defaultLimit = 6; | |
25 | - | |
26 | - // initialization | |
27 | - vm.init(); | |
28 | - } | |
29 | - | |
30 | - ProgramaListController.prototype.init = function() { | |
31 | - var vm = this; | |
32 | - | |
33 | - if (!vm.article) { | |
34 | - vm.$log.warn('no article to display. Tip: use a ng-if before use this directive'); | |
35 | - return; | |
36 | - } | |
37 | - | |
38 | - vm.categories = vm.article.categories; | |
39 | - vm.programs = vm.article.children; | |
40 | - vm.orderCriteries = [ | |
41 | - { label: 'Título', name: 'titulo' }, | |
42 | - { label: 'Tema', name: 'tema' }, | |
43 | - { label: 'Aleatório', name: 'aleatorio' } | |
44 | - ]; | |
45 | - | |
46 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
47 | - vm.search = vm.$location.search(); | |
48 | - | |
49 | - // Add initial values for the filter | |
50 | - vm.query = (vm.search && vm.search.filtro) ? vm.search.filtro : null; | |
51 | - vm.limitTo = (vm.search && vm.search.limite) ? parseInt(vm.search.limite, 10) : vm.defaultLimit; | |
52 | - vm.categoryFilter = (vm.search && vm.search.tema) ? vm.getCategoryBySlug(vm.search.tema) : null; | |
53 | - vm.orderCriteria = (vm.search && vm.search.ordem) ? { name: vm.search.ordem } : null; | |
54 | - vm.reverse = (vm.search && vm.search.reverso) ? true : false; | |
55 | - | |
56 | - if (!angular.equals({}, vm.search)) { | |
57 | - var $el = vm.$element; | |
58 | - angular.element('body').animate({scrollTop: $el.offset().top}, 'slow'); | |
59 | - } | |
60 | - | |
61 | - // update window location params | |
62 | - vm.$scope.$watch('vm.query', function(newValue/*, oldValue*/) { | |
63 | - vm.search.filtro = newValue ? newValue : null; | |
64 | - vm.$location.search('filtro', vm.search.filtro); | |
65 | - if(vm.search.filtro){ | |
66 | - vm.limitTo = vm.programs.length; | |
67 | - }else{ | |
68 | - vm.limitTo = vm.defaultLimit; | |
69 | - } | |
70 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
71 | - }); | |
72 | - | |
73 | - vm.$scope.$watch('vm.limitTo', function(newValue/*, oldValue*/) { | |
74 | - vm.search.limite = (newValue && newValue !== vm.defaultLimit) ? newValue : null; | |
75 | - vm.$location.search('limite', vm.search.limite); | |
76 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
77 | - }); | |
78 | - | |
79 | - vm.$scope.$watch('vm.categoryFilter', function(newValue/*, oldValue*/) { | |
80 | - vm.search.tema = newValue ? newValue.slug : null; | |
81 | - vm.$location.search('tema', vm.search.tema); | |
82 | - if(vm.search.tema){ | |
83 | - vm.limitTo = vm.programs.length; | |
84 | - } | |
85 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
86 | - }); | |
87 | - | |
88 | - vm.$scope.$watch('vm.orderCriteria', function(newValue/*, oldValue*/) { | |
89 | - vm.search.ordem = (newValue && newValue.name) ? newValue.name : null; | |
90 | - vm.$location.search('ordem', vm.search.ordem); | |
91 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
92 | - }); | |
93 | - | |
94 | - vm.$scope.$watch('vm.reverse', function(newValue/*, oldValue*/) { | |
95 | - vm.search.reverso = newValue ? newValue : null; | |
96 | - vm.$location.search('reverso', vm.search.reverso); | |
97 | - vm.filtredProgramList = vm.getFiltredPrograms(); | |
98 | - }); | |
99 | - | |
100 | - }; | |
101 | - | |
102 | - ProgramaListController.prototype.resetFilterValues = function() { | |
103 | - var vm = this; | |
104 | - | |
105 | - vm.query = null; | |
106 | - vm.limitTo = vm.defaultLimit; | |
107 | - vm.categoryFilter = null; | |
108 | - vm.orderCriteria = null; | |
109 | - }; | |
110 | - | |
111 | - ProgramaListController.prototype.getIconClasses = function(category) { | |
112 | - var vm = this; | |
113 | - | |
114 | - vm.$log.debug('[TODO] getIconClasses of category:', category); | |
115 | - return 'glyphicon glyphicon-exclamation-sign'; | |
116 | - }; | |
117 | - | |
118 | - ProgramaListController.prototype.getCategoryBySlug = function(categorySlug) { | |
119 | - var vm = this; | |
120 | - var result = null; | |
121 | - | |
122 | - angular.forEach(vm.categories, function(value/*, key*/) { | |
123 | - if (value.slug === categorySlug) { | |
124 | - result = value; | |
125 | - } | |
126 | - }); | |
127 | - | |
128 | - return result; | |
129 | - }; | |
130 | - | |
131 | - ProgramaListController.prototype.filterByCategory = function(category, $event) { | |
132 | - var vm = this; | |
133 | - | |
134 | - $event.stopPropagation(); | |
135 | - | |
136 | - if (category !== vm.categoryFilter) { | |
137 | - | |
138 | - // selected new filter | |
139 | - vm.categoryFilter = category; | |
140 | - } else { | |
141 | - vm.categoryFilter = null; | |
142 | - } | |
143 | - }; | |
144 | - | |
145 | - ProgramaListController.prototype.showAll = function($event) { | |
146 | - var vm = this; | |
147 | - | |
148 | - $event.stopPropagation(); | |
149 | - | |
150 | - vm.resetFilterValues(); | |
151 | - vm.limitTo = vm.programs.length; | |
152 | - }; | |
153 | - | |
154 | - ProgramaListController.prototype.getFiltredPrograms = function() { | |
155 | - var vm = this; | |
156 | - | |
157 | - var input = vm.programs; | |
158 | - var output = input; | |
159 | - var query = vm.query; | |
160 | - var categoryFilter = vm.categoryFilter; | |
161 | - var orderCriteria = vm.orderCriteria ? vm.orderCriteria : { name : 'aleatorio'}; | |
162 | - var filter = vm.$filter('filter'); | |
163 | - var orderBy = vm.$filter('orderBy'); | |
164 | - var limitTo = vm.$filter('limitTo'); | |
165 | - var limit = vm.limitTo ? vm.limitTo : 4; | |
166 | - | |
167 | - if (categoryFilter) { | |
168 | - output = _filterByCategory(output, categoryFilter); | |
169 | - } | |
170 | - | |
171 | - if (query) { | |
172 | - output = filter(output, query, false); | |
173 | - } | |
174 | - | |
175 | - switch (orderCriteria.name) { | |
176 | - case 'titulo': | |
177 | - output = orderBy(output, 'title', vm.reverse); | |
178 | - break; | |
179 | - case 'tema': | |
180 | - output = orderBy(output, 'categories[0].name', vm.reverse); | |
181 | - break; | |
182 | - case 'more_participants': | |
183 | - vm.$log.info('Criteria not handled yet: ', orderCriteria); | |
184 | - break; | |
185 | - case 'aleatorio': | |
186 | - // shuffling | |
187 | - // if (!vm._isShuffled){ | |
188 | - output = vm.filterShuffle(output); | |
189 | - // vm._isShuffled = true; | |
190 | - // } | |
191 | - | |
192 | - if (vm.reverse) { | |
193 | - output = output.slice().reverse(); | |
194 | - } | |
195 | - | |
196 | - break; | |
197 | - default: | |
198 | - vm.$log.warn('Criteria not matched: ', orderCriteria); | |
199 | - break; | |
200 | - } | |
201 | - | |
202 | - output = limitTo(output, limit); | |
203 | - | |
204 | - return output; | |
205 | - }; | |
206 | - | |
207 | - ProgramaListController.prototype.filterShuffle = function(input) { | |
208 | - var result = []; | |
209 | - var resultByCategory = {}; | |
210 | - | |
211 | - // divide by categories | |
212 | - for (var i = 0; i < input.length; i++) { | |
213 | - var program = input[i]; | |
214 | - var categorySlug = program.categories[0].slug; | |
215 | - | |
216 | - if (!resultByCategory[categorySlug]) { | |
217 | - resultByCategory[categorySlug] = []; | |
218 | - } | |
219 | - | |
220 | - resultByCategory[categorySlug].push(program); | |
221 | - } | |
222 | - | |
223 | - // shuffle each array | |
224 | - var prop = null; | |
225 | - var categoryWithPrograms = null; | |
226 | - for (prop in resultByCategory) { | |
227 | - if (resultByCategory.hasOwnProperty(prop)) { | |
228 | - categoryWithPrograms = resultByCategory[prop]; | |
229 | - resultByCategory[prop] = shuffle(categoryWithPrograms); | |
230 | - } | |
231 | - } | |
232 | - | |
233 | - // Concat all into result array | |
234 | - // > while has program at Lists on resultByCategory | |
235 | - var hasProgram = true; | |
236 | - while (hasProgram) { | |
237 | - | |
238 | - var foundProgram = false; | |
239 | - // each categoryList with array of program | |
240 | - prop = null; | |
241 | - categoryWithPrograms = null; | |
242 | - for (prop in resultByCategory) { | |
243 | - | |
244 | - if (resultByCategory.hasOwnProperty(prop)) { | |
245 | - categoryWithPrograms = resultByCategory[prop]; | |
246 | - | |
247 | - if (categoryWithPrograms.length > 0) { | |
248 | - var pivotProgram = categoryWithPrograms.pop(); | |
249 | - result.push(pivotProgram); | |
250 | - foundProgram = true; | |
251 | - } | |
252 | - } | |
253 | - } | |
254 | - | |
255 | - if (!foundProgram) { | |
256 | - hasProgram = false; | |
257 | - } | |
258 | - } | |
259 | - | |
260 | - return result; | |
261 | - }; | |
262 | - | |
263 | - var directive = { | |
264 | - restrict: 'E', | |
265 | - templateUrl: 'app/components/programas/programas.html', | |
266 | - scope: { | |
267 | - article: '=' | |
268 | - }, | |
269 | - controller: ProgramaListController, | |
270 | - controllerAs: 'vm', | |
271 | - bindToController: true | |
272 | - }; | |
273 | - | |
274 | - return directive; | |
275 | - } | |
276 | - | |
277 | - function _filterByCategory (input, category) { | |
278 | - input = input || []; | |
279 | - | |
280 | - if (!category) { | |
281 | - // no filter | |
282 | - return input; | |
283 | - } | |
284 | - | |
285 | - var out = []; | |
286 | - for (var i = 0; i < input.length; i++) { | |
287 | - var program = input[i]; | |
288 | - if (program.categories[0].slug === category.slug) { | |
289 | - out.push(program); | |
290 | - } | |
291 | - } | |
292 | - | |
293 | - return out; | |
294 | - } | |
295 | - | |
296 | - // -> Fisher–Yates shuffle algorithm | |
297 | - function shuffle (array) { | |
298 | - var currentIndex = array.length, temporaryValue, randomIndex ; | |
299 | - | |
300 | - // While there remain elements to shuffle... | |
301 | - while (0 !== currentIndex) { | |
302 | - | |
303 | - // Pick a remaining element... | |
304 | - randomIndex = Math.floor(Math.random() * currentIndex); | |
305 | - currentIndex -= 1; | |
306 | - | |
307 | - // And swap it with the current element. | |
308 | - temporaryValue = array[currentIndex]; | |
309 | - array[currentIndex] = array[randomIndex]; | |
310 | - array[randomIndex] = temporaryValue; | |
311 | - } | |
312 | - | |
313 | - return array; | |
314 | - } | |
315 | - | |
316 | -})(); |
src/app/components/programas/programas.directive.spec.js
... | ... | @@ -1,32 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - describe('program directive', function() { | |
5 | - var compile, scope, directiveElem; | |
6 | - | |
7 | - beforeEach(function(){ | |
8 | - module('dialoga'); | |
9 | - | |
10 | - inject(function($compile, $rootScope){ | |
11 | - compile = $compile; | |
12 | - scope = $rootScope.$new(); | |
13 | - // mock article | |
14 | - scope.article = {}; | |
15 | - }); | |
16 | - | |
17 | - directiveElem = getCompiledElement(); | |
18 | - }); | |
19 | - | |
20 | - function getCompiledElement(){ | |
21 | - var element = compile(angular.element('<programa-list></programa-list>'))(scope); | |
22 | - var compiledElement = compile(element)(scope); | |
23 | - scope.$digest(); | |
24 | - return compiledElement; | |
25 | - } | |
26 | - | |
27 | - it('ensure exist only one id "lista-de-programas"', function() {}); | |
28 | - | |
29 | - it('should show default programs, one each category', function() {}); | |
30 | - | |
31 | - }); | |
32 | -})(); |
src/app/components/proposal-carousel/proposal-carousel.directive.js
0 → 100644
... | ... | @@ -0,0 +1,71 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('proposalCarousel', proposalCarousel); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function proposalCarousel() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ProposalCarouselController($scope, $element, $timeout, $log) { | |
13 | + $log.debug('ProposalCarouselController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$scope = $scope; | |
17 | + vm.$element = $element; | |
18 | + vm.$timeout = $timeout; | |
19 | + vm.$log = $log; | |
20 | + | |
21 | + vm.init(); | |
22 | + } | |
23 | + | |
24 | + ProposalCarouselController.prototype.init = function () { | |
25 | + // initial values | |
26 | + var vm = this; | |
27 | + | |
28 | + if(!vm.proposals){ | |
29 | + throw { name: 'NotDefined', message: 'The attribute "proposals" is undefined.'}; | |
30 | + } | |
31 | + | |
32 | + vm.activeIndex = 0; | |
33 | + vm.loading = false; | |
34 | + vm.proposalsLength = vm.proposals.length; | |
35 | + }; | |
36 | + | |
37 | + ProposalCarouselController.prototype.swipeLeft = function () { | |
38 | + var vm = this; | |
39 | + | |
40 | + vm.activeIndex = (vm.activeIndex < vm.proposalsLength - 1) ? ++vm.activeIndex : 0; | |
41 | + }; | |
42 | + | |
43 | + ProposalCarouselController.prototype.swipeRight = function () { | |
44 | + var vm = this; | |
45 | + | |
46 | + vm.activeIndex = (vm.activeIndex > 0) ? --vm.activeIndex : vm.proposalsLength - 1; | |
47 | + }; | |
48 | + | |
49 | + ProposalCarouselController.prototype.showProposals = function () { | |
50 | + var vm = this; | |
51 | + | |
52 | + // notify parents - handled by parents | |
53 | + vm.$scope.$emit('proposal-carousel:toProposals'); | |
54 | + }; | |
55 | + | |
56 | + var directive = { | |
57 | + restrict: 'E', | |
58 | + templateUrl: 'app/components/proposal-carousel/proposal-carousel.html', | |
59 | + scope: { | |
60 | + proposals: '=' | |
61 | + }, | |
62 | + controller: ProposalCarouselController, | |
63 | + controllerAs: 'vm', | |
64 | + bindToController: true | |
65 | + }; | |
66 | + | |
67 | + | |
68 | + return directive; | |
69 | + } | |
70 | + | |
71 | +})(); | ... | ... |
src/app/components/proposal-carousel/proposal-carousel.html
0 → 100644
... | ... | @@ -0,0 +1,33 @@ |
1 | +<div class="proposal-carousel"> | |
2 | + <div ng-if="vm.proposals"> | |
3 | + <div class="proposal-carousel-top color-theme-bg"> | |
4 | + <div class="proposal-carousel-position" ng-repeat="proposal in vm.proposals"> | |
5 | + <span ng-show="vm.activeIndex === $index">{{::($index+1)}}º</span> | |
6 | + <span ng-show="vm.activeIndex === $index">Lugar</span> | |
7 | + </div> | |
8 | + <div class="proposal-carousel-top-triggers" ng-if="vm.proposals"> | |
9 | + <ul class="list-inline"> | |
10 | + <li class="item-dot" ng-repeat="proposal in vm.proposals"> | |
11 | + <button type="button" ng-class="{'active': vm.activeIndex === $index}" ng-click="vm.switchProposal($index)" title="Apersentar proposta na posição {{$index}}"></button> | |
12 | + </li> | |
13 | + </ul> | |
14 | + </div> | |
15 | + </div> | |
16 | + <div class="proposal-carousel-middle" ng-swipe-left="vm.swipeLeft()" ng-swipe-right="vm.swipeRight()"> | |
17 | + <div ng-repeat="proposal in vm.proposals" class="animation-swipe"> | |
18 | + <div class="content"> | |
19 | + <div ng-show="vm.activeIndex === $index">{{::proposal.abstract}}</div> | |
20 | + </div> | |
21 | + <div class="proposal-carousel-middle-watermark" ng-show="vm.activeIndex === $index"> | |
22 | + <span>{{::($index+1)}}º</span> | |
23 | + </div> | |
24 | + </div> | |
25 | + </div> | |
26 | + <div class="proposal-carousel-bottom color-theme-common-bg" ng-click="vm.showProposals()"> | |
27 | + <div>Veja as propostas mais vortadas</div> | |
28 | + <div class="proposal-carousel-bottom-icon"> | |
29 | + <span class="glyphicon glyphicon-chevron-down pull-right color-theme-common-fg"></span> | |
30 | + </div> | |
31 | + </div> | |
32 | + </div> | |
33 | +</div> | ... | ... |
src/app/components/proposal-carousel/proposal-carousel.scss
0 → 100644
... | ... | @@ -0,0 +1,86 @@ |
1 | +.proposal-carousel { | |
2 | + background-color: #f1f1f1; | |
3 | + border-radius: 5px; | |
4 | + overflow: hidden; | |
5 | + | |
6 | + &-top { | |
7 | + position: relative; | |
8 | + color: #fff; | |
9 | + font-weight: bold; | |
10 | + font-size: 25px; | |
11 | + padding: 20px 15px; | |
12 | + | |
13 | + &-triggers { | |
14 | + position: absolute; | |
15 | + right: 15px; | |
16 | + top: 20px; | |
17 | + | |
18 | + button { | |
19 | + border: 1px solid #fff; | |
20 | + border-radius: 100%; | |
21 | + width: 15px; | |
22 | + height: 15px; | |
23 | + margin-right: 5px; | |
24 | + background-color: transparent; | |
25 | + | |
26 | + cursor: pointer; | |
27 | + | |
28 | + &.active { | |
29 | + background-color: #fff; | |
30 | + } | |
31 | + } | |
32 | + } | |
33 | + } | |
34 | + | |
35 | + &-middle { | |
36 | + position: relative; | |
37 | + padding: 25px 30px; | |
38 | + min-height: 200px; | |
39 | + // cursor: pointer; | |
40 | + -webkit-user-select: none; | |
41 | + -khtml-user-select: none; | |
42 | + -moz-user-select: none; | |
43 | + -ms-user-select: none; | |
44 | + user-select: none; | |
45 | + | |
46 | + .content { | |
47 | + position: relative; | |
48 | + z-index: 2; | |
49 | + } | |
50 | + | |
51 | + &-watermark { | |
52 | + position: absolute; | |
53 | + bottom: 1px; | |
54 | + left: -5px; | |
55 | + color: #ddd; | |
56 | + font-size: 150px; | |
57 | + font-weight: bold; | |
58 | + line-height: 116px; | |
59 | + z-index: 1; | |
60 | + | |
61 | + } | |
62 | + } | |
63 | + | |
64 | + &-bottom { | |
65 | + position: relative; | |
66 | + color: #fff; | |
67 | + padding: 10px; | |
68 | + font-weight: bold; | |
69 | + cursor: pointer; | |
70 | + z-index: 10; | |
71 | + | |
72 | + &-icon { | |
73 | + position: absolute; | |
74 | + top: 10px; | |
75 | + right: 15px; | |
76 | + | |
77 | + .glyphicon { | |
78 | + position: relative; | |
79 | + top: -2px; | |
80 | + background-color: #fff; | |
81 | + padding: 6px 5px 5px 6px; | |
82 | + border-radius: 100%; | |
83 | + } | |
84 | + } | |
85 | + } | |
86 | +} | ... | ... |
src/app/components/proposal-list/proposal-list.directive.js
0 → 100644
... | ... | @@ -0,0 +1,81 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('proposalList', proposalList); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function proposalList() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ProposalListController(ArticleService, $scope, $element, $timeout, $log) { | |
13 | + $log.debug('ProposalListController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.ArticleService = ArticleService; | |
17 | + vm.$scope = $scope; | |
18 | + vm.$element = $element; | |
19 | + vm.$timeout = $timeout; | |
20 | + vm.$log = $log; | |
21 | + | |
22 | + vm.init(); | |
23 | + | |
24 | + vm.loadData(); | |
25 | + } | |
26 | + | |
27 | + ProposalListController.prototype.init = function () { | |
28 | + // initial values | |
29 | + var vm = this; | |
30 | + | |
31 | + if(!vm.proposals){ | |
32 | + throw { name: 'NotDefined', message: 'The attribute "proposals" is undefined.'}; | |
33 | + } | |
34 | + | |
35 | + if(!vm.per_page){ | |
36 | + vm.per_page = 5; | |
37 | + } | |
38 | + | |
39 | + vm.proposalsLength = vm.proposals.length; | |
40 | + }; | |
41 | + | |
42 | + ProposalListController.prototype.loadData = function () { | |
43 | + // async values | |
44 | + var vm = this; | |
45 | + | |
46 | + // requeue to wait until DOM be created | |
47 | + vm.$timeout(function(){ | |
48 | + attachPopover.call(vm); | |
49 | + }, 100); | |
50 | + }; | |
51 | + | |
52 | + function attachPopover(){ | |
53 | + var vm = this; | |
54 | + | |
55 | + vm.popover = angular.element(vm.$element.find('.btn-question')); | |
56 | + vm.popover.popover({ | |
57 | + html: true, | |
58 | + placement: 'bottom', | |
59 | + animation: true, | |
60 | + title: 'Regra de posição das propostas', | |
61 | + content: '<p>É calculada pelo saldo de interações das propostas (curtidas - não curtidas) dividido pela diferença de exibições entre elas.</p><p>O objetivo dessa correção é compensar o saldo de interações e a diferença de exibições das propostas que não tiveram muitas oportunidades de visualização ou das propostas que tiveram mais oportunidades de visualização que a média.</p><p>Com essa correção, é possível comparar propostas que entraram em diferentes momentos, durante todo o período da consulta.</p>' | |
62 | + }); | |
63 | + } | |
64 | + | |
65 | + var directive = { | |
66 | + restrict: 'E', | |
67 | + templateUrl: 'app/components/proposal-list/proposal-list.html', | |
68 | + scope: { | |
69 | + proposals: '=', | |
70 | + per_page: '=' | |
71 | + }, | |
72 | + controller: ProposalListController, | |
73 | + controllerAs: 'vm', | |
74 | + bindToController: true | |
75 | + }; | |
76 | + | |
77 | + | |
78 | + return directive; | |
79 | + } | |
80 | + | |
81 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,45 @@ |
1 | +<div class="proposal-list"> | |
2 | + | |
3 | + <div class="table-responsive" ng-if="vm.loading"> | |
4 | + <div class="table-responsive">Carregando...</div> | |
5 | + </div> | |
6 | + <div class="table-responsive" ng-if="!vm.loading && vm.proposals"> | |
7 | + <table class="table table-striped"> | |
8 | + <thead> | |
9 | + <tr> | |
10 | + <th> | |
11 | + Colocação | |
12 | + <button type="button" class="btn btn-link btn-question">?</button> | |
13 | + </th> | |
14 | + <th>123 PROPOSTAS</th> | |
15 | + </tr> | |
16 | + </thead> | |
17 | + <tbody> | |
18 | + <tr ng-repeat="proposal in vm.proposals"> | |
19 | + | |
20 | + <td class="color-theme-fg"> | |
21 | + <span class="position">{{::($index+1)}}º</span> | |
22 | + </td> | |
23 | + <td> | |
24 | + <div class="row"> | |
25 | + <div class="col-xs-12"> | |
26 | + <span class="abstract">{{proposal.abstract}}</span> | |
27 | + </div> | |
28 | + </div> | |
29 | + <div class="row row-actions"> | |
30 | + <div class="col-md-9"> | |
31 | + <button type="button" class="btn btn-link btn-rate color-theme-common-fg"> | |
32 | + Avalie esta proposta | |
33 | + <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> | |
34 | + </button> | |
35 | + </div> | |
36 | + <div class="col-md-3"> | |
37 | + <proposal-stats views="{{::proposal.hits}}" up="{{::proposal.votes_for}}" down="{{::proposal.votes_against}}"></proposal-stats> | |
38 | + </div> | |
39 | + </div> | |
40 | + </td> | |
41 | + </tr> | |
42 | + </tbody> | |
43 | + </table> | |
44 | + </div> | |
45 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,94 @@ |
1 | +.proposal-list { | |
2 | + table { | |
3 | + border-radius: 4px; | |
4 | + overflow: hidden; | |
5 | + } | |
6 | + | |
7 | + thead { | |
8 | + th{ | |
9 | + color: #fff; | |
10 | + background-color: #606060; | |
11 | + &:first-child { | |
12 | + background-color: #484848; | |
13 | + text-align: right; | |
14 | + width: 160px; | |
15 | + padding-right: 20px; | |
16 | + } | |
17 | + } | |
18 | + | |
19 | + .btn-question { | |
20 | + color: #484848; | |
21 | + background-color: #fff; | |
22 | + display: inline-block; | |
23 | + text-align: center; | |
24 | + width: 22px; | |
25 | + height: 22px; | |
26 | + margin-left: 10px; | |
27 | + padding: 0; | |
28 | + border-radius: 100%; | |
29 | + } | |
30 | + | |
31 | + .popover { | |
32 | + color: #484848; | |
33 | + } | |
34 | + } | |
35 | + | |
36 | + tbody { | |
37 | + tr { | |
38 | + background-color: #fff; | |
39 | + } | |
40 | + | |
41 | + td { | |
42 | + &:first-child { | |
43 | + font-size: 22px; | |
44 | + font-weight: bold; | |
45 | + padding: 0; | |
46 | + text-align: right; | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + .position { | |
51 | + display: block; | |
52 | + width: 100%; | |
53 | + margin: 20px 0; | |
54 | + padding: 5px 20px; | |
55 | + border-top-right-radius: 4px; | |
56 | + border-bottom-right-radius: 4px; | |
57 | + } | |
58 | + } | |
59 | + | |
60 | + .abstract { | |
61 | + color: #393939; | |
62 | + font-size: 18px; | |
63 | + } | |
64 | + | |
65 | + .row-actions { | |
66 | + padding-top: 20px; | |
67 | + } | |
68 | + | |
69 | + .btn-rate { | |
70 | + padding: 0; | |
71 | + font-size: 20px; | |
72 | + font-weight: bold; | |
73 | + text-decoration: blink; | |
74 | + } | |
75 | + | |
76 | + // override bootstrap | |
77 | + .table-striped > tbody > tr:nth-of-type(odd) { | |
78 | + // impar | |
79 | + background-color: #eaeaea; | |
80 | + | |
81 | + .position { | |
82 | + background-color: #fff; | |
83 | + } | |
84 | + } | |
85 | + | |
86 | + .table-striped > tbody > tr:nth-of-type(even) { | |
87 | + // par | |
88 | + background-color: #fff; | |
89 | + | |
90 | + .position { | |
91 | + background-color: #eaeaea; | |
92 | + } | |
93 | + } | |
94 | +} | ... | ... |
src/app/components/proposal-ranking/proposal-ranking-carousel.scss
... | ... | @@ -1,90 +0,0 @@ |
1 | -.proposal-ranking { | |
2 | - // both: carousel and list | |
3 | -} | |
4 | - | |
5 | -.proposal-ranking--carousel { | |
6 | - background-color: #f1f1f1; | |
7 | - border-radius: 5px; | |
8 | - overflow: hidden; | |
9 | - | |
10 | - &-top { | |
11 | - position: relative; | |
12 | - color: #fff; | |
13 | - font-weight: bold; | |
14 | - font-size: 25px; | |
15 | - padding: 20px 15px; | |
16 | - | |
17 | - | |
18 | - &-triggers { | |
19 | - position: absolute; | |
20 | - right: 15px; | |
21 | - top: 20px; | |
22 | - | |
23 | - button { | |
24 | - border: 1px solid #fff; | |
25 | - border-radius: 100%; | |
26 | - width: 15px; | |
27 | - height: 15px; | |
28 | - margin-right: 5px; | |
29 | - background-color: transparent; | |
30 | - | |
31 | - cursor: pointer; | |
32 | - | |
33 | - &.active { | |
34 | - background-color: #fff; | |
35 | - } | |
36 | - } | |
37 | - } | |
38 | - } | |
39 | - | |
40 | - &-middle { | |
41 | - position: relative; | |
42 | - padding: 25px 30px; | |
43 | - cursor: pointer; | |
44 | - -webkit-user-select: none; | |
45 | - -khtml-user-select: none; | |
46 | - -moz-user-select: none; | |
47 | - -ms-user-select: none; | |
48 | - user-select: none; | |
49 | - | |
50 | - .content { | |
51 | - position: relative; | |
52 | - z-index: 2; | |
53 | - } | |
54 | - | |
55 | - &-watermark { | |
56 | - position: absolute; | |
57 | - bottom: 1px; | |
58 | - left: -5px; | |
59 | - color: #ddd; | |
60 | - font-size: 150px; | |
61 | - font-weight: bold; | |
62 | - line-height: 116px; | |
63 | - z-index: 1; | |
64 | - | |
65 | - } | |
66 | - } | |
67 | - | |
68 | - &-bottom { | |
69 | - position: relative; | |
70 | - color: #fff; | |
71 | - padding: 10px; | |
72 | - font-weight: bold; | |
73 | - cursor: pointer; | |
74 | - z-index: 10; | |
75 | - | |
76 | - &-icon { | |
77 | - position: absolute; | |
78 | - top: 10px; | |
79 | - right: 15px; | |
80 | - | |
81 | - .glyphicon { | |
82 | - position: relative; | |
83 | - top: -2px; | |
84 | - background-color: #fff; | |
85 | - padding: 6px 5px 5px 6px; | |
86 | - border-radius: 100%; | |
87 | - } | |
88 | - } | |
89 | - } | |
90 | -} |
src/app/components/proposal-ranking/proposal-ranking-list.scss
... | ... | @@ -1,98 +0,0 @@ |
1 | -.proposal-ranking { | |
2 | - // both: carousel and list | |
3 | -} | |
4 | - | |
5 | -.proposal-ranking--list { | |
6 | - table { | |
7 | - border-radius: 4px; | |
8 | - overflow: hidden; | |
9 | - } | |
10 | - | |
11 | - thead { | |
12 | - th{ | |
13 | - color: #fff; | |
14 | - background-color: #606060; | |
15 | - &:first-child { | |
16 | - background-color: #484848; | |
17 | - text-align: right; | |
18 | - width: 160px; | |
19 | - padding-right: 20px; | |
20 | - } | |
21 | - } | |
22 | - | |
23 | - .btn-question { | |
24 | - color: #484848; | |
25 | - background-color: #fff; | |
26 | - display: inline-block; | |
27 | - text-align: center; | |
28 | - width: 22px; | |
29 | - height: 22px; | |
30 | - margin-left: 10px; | |
31 | - padding: 0; | |
32 | - border-radius: 100%; | |
33 | - } | |
34 | - | |
35 | - .popover { | |
36 | - color: #484848; | |
37 | - } | |
38 | - } | |
39 | - | |
40 | - tbody { | |
41 | - tr { | |
42 | - background-color: #fff; | |
43 | - } | |
44 | - | |
45 | - td { | |
46 | - &:first-child { | |
47 | - font-size: 22px; | |
48 | - font-weight: bold; | |
49 | - padding: 0; | |
50 | - text-align: right; | |
51 | - } | |
52 | - } | |
53 | - | |
54 | - .position { | |
55 | - display: block; | |
56 | - width: 100%; | |
57 | - margin: 20px 0; | |
58 | - padding: 5px 20px; | |
59 | - border-top-right-radius: 4px; | |
60 | - border-bottom-right-radius: 4px; | |
61 | - } | |
62 | - } | |
63 | - | |
64 | - .abstract { | |
65 | - color: #393939; | |
66 | - font-size: 18px; | |
67 | - } | |
68 | - | |
69 | - .row-actions { | |
70 | - padding-top: 20px; | |
71 | - } | |
72 | - | |
73 | - .btn-rate { | |
74 | - padding: 0; | |
75 | - font-size: 20px; | |
76 | - font-weight: bold; | |
77 | - text-decoration: blink; | |
78 | - } | |
79 | - | |
80 | - // override bootstrap | |
81 | - .table-striped > tbody > tr:nth-of-type(odd) { | |
82 | - // impar | |
83 | - background-color: #eaeaea; | |
84 | - | |
85 | - .position { | |
86 | - background-color: #fff; | |
87 | - } | |
88 | - } | |
89 | - | |
90 | - .table-striped > tbody > tr:nth-of-type(even) { | |
91 | - // par | |
92 | - background-color: #fff; | |
93 | - | |
94 | - .position { | |
95 | - background-color: #eaeaea; | |
96 | - } | |
97 | - } | |
98 | -} |
src/app/components/proposal-ranking/proposal-ranking.directive.js
... | ... | @@ -1,143 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - angular | |
5 | - .module('dialoga') | |
6 | - .directive('proposalRanking', proposalRanking); | |
7 | - | |
8 | - /** @ngInject */ | |
9 | - function proposalRanking() { | |
10 | - | |
11 | - /** @ngInject */ | |
12 | - function ProposalRankingController(ArticleService, $scope, $element, $timeout, $log) { | |
13 | - $log.debug('ProposalRankingController'); | |
14 | - | |
15 | - var vm = this; | |
16 | - vm.ArticleService = ArticleService; | |
17 | - vm.$scope = $scope; | |
18 | - vm.$element = $element; | |
19 | - vm.$timeout = $timeout; | |
20 | - vm.$log = $log; | |
21 | - | |
22 | - vm.init(); | |
23 | - } | |
24 | - | |
25 | - ProposalRankingController.prototype.init = function () { | |
26 | - // initial values | |
27 | - var vm = this; | |
28 | - | |
29 | - vm.activeIndex = 0; | |
30 | - vm.loading = false; | |
31 | - | |
32 | - if(angular.isDefined(vm.limit) && angular.isString(vm.limit)){ | |
33 | - vm.limit = parseInt(vm.limit); | |
34 | - }else{ | |
35 | - vm.limit = 3; | |
36 | - } | |
37 | - | |
38 | - vm.loadData(); | |
39 | - }; | |
40 | - | |
41 | - ProposalRankingController.prototype.loadData = function () { | |
42 | - // async values | |
43 | - var vm = this; | |
44 | - | |
45 | - vm.loading = true; | |
46 | - | |
47 | - // simulate delay | |
48 | - vm.$timeout(function(){ | |
49 | - vm.loading = false; | |
50 | - | |
51 | - // Fake Data | |
52 | - // vm.proposals = vm.ArticleService.getProposals(); | |
53 | - vm.proposals = [{ | |
54 | - id: 4159, | |
55 | - abstract: 'Ut odio unde porro in. Aut fuga magni adipisci. Recusandae ipsum distinctio omnis ut illum.', | |
56 | - effective_support: 0.1572052401746725, | |
57 | - hits: 4159, | |
58 | - votes_against: 3779, | |
59 | - votes_for: 1780 | |
60 | - },{ | |
61 | - id: 935, | |
62 | - abstract: 'Aut fuga magni adipisci. Recusandae ipsum distinctio omnis ut illum. Magni sunt ut molestiae.', | |
63 | - effective_support: 0.1572052401746725, | |
64 | - hits: 8602, | |
65 | - votes_against: 7005, | |
66 | - votes_for: 8728 | |
67 | - },{ | |
68 | - id: 1008, | |
69 | - abstract: 'Recusandae ipsum distinctio omnis ut illum. Magni sunt ut molestiae. Aut fuga magni adipisci.', | |
70 | - effective_support: 0.1572052401746725, | |
71 | - hits: 9181, | |
72 | - votes_against: 612, | |
73 | - votes_for: 1786 | |
74 | - }]; | |
75 | - | |
76 | - if(vm.display === 'list'){ | |
77 | - // wait until DOM be created | |
78 | - vm.$timeout(function(){ | |
79 | - attachPopover.call(vm); | |
80 | - }, 20); | |
81 | - } | |
82 | - }, 2000); | |
83 | - }; | |
84 | - | |
85 | - ProposalRankingController.prototype.swipeLeft = function () { | |
86 | - var vm = this; | |
87 | - | |
88 | - vm.activeIndex = (vm.activeIndex < vm.limit - 1) ? ++vm.activeIndex : 0; | |
89 | - }; | |
90 | - | |
91 | - ProposalRankingController.prototype.swipeRight = function () { | |
92 | - var vm = this; | |
93 | - | |
94 | - vm.activeIndex = (vm.activeIndex > 0) ? --vm.activeIndex : vm.limit - 1; | |
95 | - }; | |
96 | - | |
97 | - ProposalRankingController.prototype.switchProposal = function (index) { | |
98 | - var vm = this; | |
99 | - | |
100 | - if(index >= 0 && index < vm.limit) { | |
101 | - vm.activeIndex = index; | |
102 | - }else{ | |
103 | - vm.$log.warn('[switchProposal] "index" not handled:', index); | |
104 | - } | |
105 | - }; | |
106 | - | |
107 | - ProposalRankingController.prototype.showProposals = function () { | |
108 | - var vm = this; | |
109 | - | |
110 | - // notify parents - handled by parents | |
111 | - vm.$scope.$emit('see-proposals'); | |
112 | - }; | |
113 | - | |
114 | - function attachPopover(){ | |
115 | - var vm = this; | |
116 | - | |
117 | - vm.popover = angular.element(vm.$element.find('.btn-question')); | |
118 | - vm.popover.popover({ | |
119 | - html: true, | |
120 | - placement: 'top', | |
121 | - animation: true, | |
122 | - title: 'Regra de posição das propostas', | |
123 | - content: '<p>É calculada pelo saldo de interações das propostas (curtidas - não curtidas) dividido pela diferença de exibições entre elas.</p><p>O objetivo dessa correção é compensar o saldo de interações e a diferença de exibições das propostas que não tiveram muitas oportunidades de visualização ou das propostas que tiveram mais oportunidades de visualização que a média.</p><p>Com essa correção, é possível comparar propostas que entraram em diferentes momentos, durante todo o período da consulta.</p>' | |
124 | - }); | |
125 | - } | |
126 | - | |
127 | - var directive = { | |
128 | - restrict: 'E', | |
129 | - templateUrl: 'app/components/proposal-ranking/proposal-ranking.html', | |
130 | - scope: { | |
131 | - limit: '&', | |
132 | - display: '=' | |
133 | - }, | |
134 | - controller: ProposalRankingController, | |
135 | - controllerAs: 'vm', | |
136 | - bindToController: true | |
137 | - }; | |
138 | - | |
139 | - | |
140 | - return directive; | |
141 | - } | |
142 | - | |
143 | -})(); |
src/app/components/proposal-ranking/proposal-ranking.html
... | ... | @@ -1,84 +0,0 @@ |
1 | -<div class="proposal-ranking contraste-box"> | |
2 | - <div class="proposal-ranking--carousel" ng-if="vm.display === 'carousel'"> | |
3 | - <div ng-if="!vm.proposals"> | |
4 | - Carregando... | |
5 | - </div> | |
6 | - <div ng-if="vm.proposals"> | |
7 | - <div class="proposal-ranking--carousel-top color-theme-bg"> | |
8 | - <div class="proposal-ranking--carousel-position" ng-repeat="proposal in vm.proposals"> | |
9 | - <span ng-show="vm.activeIndex === $index">{{::($index+1)}}º</span> | |
10 | - <span ng-show="vm.activeIndex === $index">Lugar</span> | |
11 | - </div> | |
12 | - <div class="proposal-ranking--carousel-top-triggers" ng-if="vm.proposals"> | |
13 | - <ul class="list-inline"> | |
14 | - <li class="item-dot" ng-repeat="proposal in vm.proposals"> | |
15 | - <button type="button" ng-class="{'active': vm.activeIndex === $index}" ng-click="vm.switchProposal($index)" title="Apersentar proposta na posição {{$index}}"></button> | |
16 | - </li> | |
17 | - </ul> | |
18 | - </div> | |
19 | - </div> | |
20 | - <div class="proposal-ranking--carousel-middle" ng-swipe-left="vm.swipeLeft()" ng-swipe-right="vm.swipeRight()"> | |
21 | - <div ng-repeat="proposal in vm.proposals" class="animation-swipe"> | |
22 | - <div class="content"> | |
23 | - <div ng-show="vm.activeIndex === $index">{{::proposal.abstract}}</div> | |
24 | - </div> | |
25 | - <div class="proposal-ranking--carousel-middle-watermark" ng-show="vm.activeIndex === $index"> | |
26 | - <span>{{::($index+1)}}º</span> | |
27 | - </div> | |
28 | - </div> | |
29 | - </div> | |
30 | - <div class="proposal-ranking--carousel-bottom color-theme-common-bg" ng-click="vm.showProposals()"> | |
31 | - <div>Veja as propostas mais vortadas</div> | |
32 | - <div class="proposal-ranking--carousel-bottom-icon"> | |
33 | - <span class="glyphicon glyphicon-chevron-down pull-right color-theme-common-fg"></span> | |
34 | - </div> | |
35 | - </div> | |
36 | - </div> | |
37 | - </div> | |
38 | - | |
39 | - <div class="proposal-ranking--list" ng-if="vm.display==='list'"> | |
40 | - | |
41 | - <div class="table-responsive" ng-if="vm.loading"> | |
42 | - <div class="table-responsive">Carregando...</div> | |
43 | - </div> | |
44 | - <div class="table-responsive" ng-if="!vm.loading && vm.proposals"> | |
45 | - <table class="table table-striped"> | |
46 | - <thead> | |
47 | - <tr> | |
48 | - <th> | |
49 | - Colocação | |
50 | - <button type="button" class="btn btn-link btn-question">?</button> | |
51 | - </th> | |
52 | - <th>123 PROPOSTAS</th> | |
53 | - </tr> | |
54 | - </thead> | |
55 | - <tbody> | |
56 | - <tr ng-repeat="proposal in vm.proposals"> | |
57 | - | |
58 | - <td class="color-theme-fg"> | |
59 | - <span class="position">{{::($index+1)}}º</span> | |
60 | - </td> | |
61 | - <td> | |
62 | - <div class="row"> | |
63 | - <div class="col-xs-12"> | |
64 | - <span class="abstract">{{proposal.abstract}}</span> | |
65 | - </div> | |
66 | - </div> | |
67 | - <div class="row row-actions"> | |
68 | - <div class="col-md-9"> | |
69 | - <button type="button" class="btn btn-link btn-rate color-theme-common-fg"> | |
70 | - Avalie esta proposta | |
71 | - <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> | |
72 | - </button> | |
73 | - </div> | |
74 | - <div class="col-md-3"> | |
75 | - <proposal-stats views="{{::proposal.hits}}" up="{{::proposal.votes_for}}" down="{{::proposal.votes_against}}"></proposal-stats> | |
76 | - </div> | |
77 | - </div> | |
78 | - </td> | |
79 | - </tr> | |
80 | - </tbody> | |
81 | - </table> | |
82 | - </div> | |
83 | - </div> | |
84 | -</div> |
... | ... | @@ -0,0 +1,316 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('topicList', topicList); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function topicList() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function TopicListController($scope, $element, $location, $filter, $log) { | |
13 | + $log.debug('TopicListController'); | |
14 | + | |
15 | + // alias | |
16 | + var vm = this; | |
17 | + | |
18 | + // dependencies | |
19 | + vm.$scope = $scope; | |
20 | + vm.$element = $element; | |
21 | + vm.$location = $location; | |
22 | + vm.$filter = $filter; | |
23 | + vm.$log = $log; | |
24 | + vm.defaultLimit = 6; | |
25 | + | |
26 | + // initialization | |
27 | + vm.init(); | |
28 | + } | |
29 | + | |
30 | + TopicListController.prototype.init = function() { | |
31 | + var vm = this; | |
32 | + | |
33 | + if (!vm.article) { | |
34 | + vm.$log.warn('no article to display. Tip: use a ng-if before use this directive'); | |
35 | + return; | |
36 | + } | |
37 | + | |
38 | + vm.categories = vm.article.categories; | |
39 | + vm.programs = vm.article.children; | |
40 | + vm.orderCriteries = [ | |
41 | + { label: 'Título', name: 'titulo' }, | |
42 | + { label: 'Tema', name: 'tema' }, | |
43 | + { label: 'Aleatório', name: 'aleatorio' } | |
44 | + ]; | |
45 | + | |
46 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
47 | + vm.search = vm.$location.search(); | |
48 | + | |
49 | + // Add initial values for the filter | |
50 | + vm.query = (vm.search && vm.search.filtro) ? vm.search.filtro : null; | |
51 | + vm.limitTo = (vm.search && vm.search.limite) ? parseInt(vm.search.limite, 10) : vm.defaultLimit; | |
52 | + vm.categoryFilter = (vm.search && vm.search.tema) ? vm.getCategoryBySlug(vm.search.tema) : null; | |
53 | + vm.orderCriteria = (vm.search && vm.search.ordem) ? { name: vm.search.ordem } : null; | |
54 | + vm.reverse = (vm.search && vm.search.reverso) ? true : false; | |
55 | + | |
56 | + if (!angular.equals({}, vm.search)) { | |
57 | + var $el = vm.$element; | |
58 | + angular.element('body').animate({scrollTop: $el.offset().top}, 'slow'); | |
59 | + } | |
60 | + | |
61 | + // update window location params | |
62 | + vm.$scope.$watch('vm.query', function(newValue/*, oldValue*/) { | |
63 | + vm.search.filtro = newValue ? newValue : null; | |
64 | + vm.$location.search('filtro', vm.search.filtro); | |
65 | + if(vm.search.filtro){ | |
66 | + vm.limitTo = vm.programs.length; | |
67 | + }else{ | |
68 | + vm.limitTo = vm.defaultLimit; | |
69 | + } | |
70 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
71 | + }); | |
72 | + | |
73 | + vm.$scope.$watch('vm.limitTo', function(newValue/*, oldValue*/) { | |
74 | + vm.search.limite = (newValue && newValue !== vm.defaultLimit) ? newValue : null; | |
75 | + vm.$location.search('limite', vm.search.limite); | |
76 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
77 | + }); | |
78 | + | |
79 | + vm.$scope.$watch('vm.categoryFilter', function(newValue/*, oldValue*/) { | |
80 | + vm.search.tema = newValue ? newValue.slug : null; | |
81 | + vm.$location.search('tema', vm.search.tema); | |
82 | + if(vm.search.tema){ | |
83 | + vm.limitTo = vm.programs.length; | |
84 | + } | |
85 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
86 | + }); | |
87 | + | |
88 | + vm.$scope.$watch('vm.orderCriteria', function(newValue/*, oldValue*/) { | |
89 | + vm.search.ordem = (newValue && newValue.name) ? newValue.name : null; | |
90 | + vm.$location.search('ordem', vm.search.ordem); | |
91 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
92 | + }); | |
93 | + | |
94 | + vm.$scope.$watch('vm.reverse', function(newValue/*, oldValue*/) { | |
95 | + vm.search.reverso = newValue ? newValue : null; | |
96 | + vm.$location.search('reverso', vm.search.reverso); | |
97 | + vm.filtredProgramList = vm.getFiltredPrograms(); | |
98 | + }); | |
99 | + | |
100 | + }; | |
101 | + | |
102 | + TopicListController.prototype.resetFilterValues = function() { | |
103 | + var vm = this; | |
104 | + | |
105 | + vm.query = null; | |
106 | + vm.limitTo = vm.defaultLimit; | |
107 | + vm.categoryFilter = null; | |
108 | + vm.orderCriteria = null; | |
109 | + }; | |
110 | + | |
111 | + TopicListController.prototype.getIconClasses = function(category) { | |
112 | + var vm = this; | |
113 | + | |
114 | + vm.$log.debug('[TODO] getIconClasses of category:', category); | |
115 | + return 'glyphicon glyphicon-exclamation-sign'; | |
116 | + }; | |
117 | + | |
118 | + TopicListController.prototype.getCategoryBySlug = function(categorySlug) { | |
119 | + var vm = this; | |
120 | + var result = null; | |
121 | + | |
122 | + angular.forEach(vm.categories, function(value/*, key*/) { | |
123 | + if (value.slug === categorySlug) { | |
124 | + result = value; | |
125 | + } | |
126 | + }); | |
127 | + | |
128 | + return result; | |
129 | + }; | |
130 | + | |
131 | + TopicListController.prototype.filterByCategory = function(category, $event) { | |
132 | + var vm = this; | |
133 | + | |
134 | + $event.stopPropagation(); | |
135 | + | |
136 | + if (category !== vm.categoryFilter) { | |
137 | + | |
138 | + // selected new filter | |
139 | + vm.categoryFilter = category; | |
140 | + } else { | |
141 | + vm.categoryFilter = null; | |
142 | + } | |
143 | + }; | |
144 | + | |
145 | + TopicListController.prototype.showAll = function($event) { | |
146 | + var vm = this; | |
147 | + | |
148 | + $event.stopPropagation(); | |
149 | + | |
150 | + vm.resetFilterValues(); | |
151 | + vm.limitTo = vm.programs.length; | |
152 | + }; | |
153 | + | |
154 | + TopicListController.prototype.getFiltredPrograms = function() { | |
155 | + var vm = this; | |
156 | + | |
157 | + var input = vm.programs; | |
158 | + var output = input; | |
159 | + var query = vm.query; | |
160 | + var categoryFilter = vm.categoryFilter; | |
161 | + var orderCriteria = vm.orderCriteria ? vm.orderCriteria : { name : 'aleatorio'}; | |
162 | + var filter = vm.$filter('filter'); | |
163 | + var orderBy = vm.$filter('orderBy'); | |
164 | + var limitTo = vm.$filter('limitTo'); | |
165 | + var limit = vm.limitTo ? vm.limitTo : 4; | |
166 | + | |
167 | + if (categoryFilter) { | |
168 | + output = _filterByCategory(output, categoryFilter); | |
169 | + } | |
170 | + | |
171 | + if (query) { | |
172 | + output = filter(output, query, false); | |
173 | + } | |
174 | + | |
175 | + switch (orderCriteria.name) { | |
176 | + case 'titulo': | |
177 | + output = orderBy(output, 'title', vm.reverse); | |
178 | + break; | |
179 | + case 'tema': | |
180 | + output = orderBy(output, 'categories[0].name', vm.reverse); | |
181 | + break; | |
182 | + case 'more_participants': | |
183 | + vm.$log.info('Criteria not handled yet: ', orderCriteria); | |
184 | + break; | |
185 | + case 'aleatorio': | |
186 | + // shuffling | |
187 | + // if (!vm._isShuffled){ | |
188 | + output = vm.filterShuffle(output); | |
189 | + // vm._isShuffled = true; | |
190 | + // } | |
191 | + | |
192 | + if (vm.reverse) { | |
193 | + output = output.slice().reverse(); | |
194 | + } | |
195 | + | |
196 | + break; | |
197 | + default: | |
198 | + vm.$log.warn('Criteria not matched: ', orderCriteria); | |
199 | + break; | |
200 | + } | |
201 | + | |
202 | + output = limitTo(output, limit); | |
203 | + | |
204 | + return output; | |
205 | + }; | |
206 | + | |
207 | + TopicListController.prototype.filterShuffle = function(input) { | |
208 | + var result = []; | |
209 | + var resultByCategory = {}; | |
210 | + | |
211 | + // divide by categories | |
212 | + for (var i = 0; i < input.length; i++) { | |
213 | + var program = input[i]; | |
214 | + var categorySlug = program.categories[0].slug; | |
215 | + | |
216 | + if (!resultByCategory[categorySlug]) { | |
217 | + resultByCategory[categorySlug] = []; | |
218 | + } | |
219 | + | |
220 | + resultByCategory[categorySlug].push(program); | |
221 | + } | |
222 | + | |
223 | + // shuffle each array | |
224 | + var prop = null; | |
225 | + var categoryWithPrograms = null; | |
226 | + for (prop in resultByCategory) { | |
227 | + if (resultByCategory.hasOwnProperty(prop)) { | |
228 | + categoryWithPrograms = resultByCategory[prop]; | |
229 | + resultByCategory[prop] = shuffle(categoryWithPrograms); | |
230 | + } | |
231 | + } | |
232 | + | |
233 | + // Concat all into result array | |
234 | + // > while has program at Lists on resultByCategory | |
235 | + var hasProgram = true; | |
236 | + while (hasProgram) { | |
237 | + | |
238 | + var foundProgram = false; | |
239 | + // each categoryList with array of program | |
240 | + prop = null; | |
241 | + categoryWithPrograms = null; | |
242 | + for (prop in resultByCategory) { | |
243 | + | |
244 | + if (resultByCategory.hasOwnProperty(prop)) { | |
245 | + categoryWithPrograms = resultByCategory[prop]; | |
246 | + | |
247 | + if (categoryWithPrograms.length > 0) { | |
248 | + var pivotProgram = categoryWithPrograms.pop(); | |
249 | + result.push(pivotProgram); | |
250 | + foundProgram = true; | |
251 | + } | |
252 | + } | |
253 | + } | |
254 | + | |
255 | + if (!foundProgram) { | |
256 | + hasProgram = false; | |
257 | + } | |
258 | + } | |
259 | + | |
260 | + return result; | |
261 | + }; | |
262 | + | |
263 | + var directive = { | |
264 | + restrict: 'E', | |
265 | + templateUrl: 'app/components/programas/programas.html', | |
266 | + scope: { | |
267 | + article: '=' | |
268 | + }, | |
269 | + controller: TopicListController, | |
270 | + controllerAs: 'vm', | |
271 | + bindToController: true | |
272 | + }; | |
273 | + | |
274 | + return directive; | |
275 | + } | |
276 | + | |
277 | + function _filterByCategory (input, category) { | |
278 | + input = input || []; | |
279 | + | |
280 | + if (!category) { | |
281 | + // no filter | |
282 | + return input; | |
283 | + } | |
284 | + | |
285 | + var out = []; | |
286 | + for (var i = 0; i < input.length; i++) { | |
287 | + var program = input[i]; | |
288 | + if (program.categories[0].slug === category.slug) { | |
289 | + out.push(program); | |
290 | + } | |
291 | + } | |
292 | + | |
293 | + return out; | |
294 | + } | |
295 | + | |
296 | + // -> Fisher–Yates shuffle algorithm | |
297 | + function shuffle (array) { | |
298 | + var currentIndex = array.length, temporaryValue, randomIndex ; | |
299 | + | |
300 | + // While there remain elements to shuffle... | |
301 | + while (0 !== currentIndex) { | |
302 | + | |
303 | + // Pick a remaining element... | |
304 | + randomIndex = Math.floor(Math.random() * currentIndex); | |
305 | + currentIndex -= 1; | |
306 | + | |
307 | + // And swap it with the current element. | |
308 | + temporaryValue = array[currentIndex]; | |
309 | + array[currentIndex] = array[randomIndex]; | |
310 | + array[randomIndex] = temporaryValue; | |
311 | + } | |
312 | + | |
313 | + return array; | |
314 | + } | |
315 | + | |
316 | +})(); | ... | ... |
src/app/components/topic-list/topic-list.directive.spec.js
0 → 100644
... | ... | @@ -0,0 +1,32 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('topic directive', function() { | |
5 | + var compile, scope, directiveElem; | |
6 | + | |
7 | + beforeEach(function(){ | |
8 | + module('dialoga'); | |
9 | + | |
10 | + inject(function($compile, $rootScope){ | |
11 | + compile = $compile; | |
12 | + scope = $rootScope.$new(); | |
13 | + // mock topics | |
14 | + scope.topics = []; | |
15 | + }); | |
16 | + | |
17 | + directiveElem = getCompiledElement(); | |
18 | + }); | |
19 | + | |
20 | + function getCompiledElement(){ | |
21 | + var element = compile(angular.element('<topic-list></topic-list>'))(scope); | |
22 | + var compiledElement = compile(element)(scope); | |
23 | + scope.$digest(); | |
24 | + return compiledElement; | |
25 | + } | |
26 | + | |
27 | + // it('ensure exist only one id "topic-list"', function() {}); | |
28 | + | |
29 | + // it('should show default topics, one each category', function() {}); | |
30 | + | |
31 | + }); | |
32 | +})(); | ... | ... |
src/app/pages/programas/programa-content.controller.js
... | ... | @@ -18,28 +18,27 @@ |
18 | 18 | vm.$log = $log; |
19 | 19 | |
20 | 20 | vm.init(); |
21 | + vm.loadData(); | |
22 | + vm.attachListeners(); | |
21 | 23 | } |
22 | 24 | |
23 | 25 | ProgramaContentPageController.prototype.init = function() { |
24 | 26 | var vm = this; |
25 | 27 | |
26 | - var params = vm.$state.params; | |
27 | - | |
28 | 28 | vm.article = null; |
29 | 29 | vm.category = null; |
30 | - vm.loading = true; | |
31 | - vm.error = false; | |
32 | - vm.slug = params.slug; | |
33 | 30 | |
34 | - vm.loadData(); | |
35 | - vm.attachListeners(); | |
31 | + vm.error = false; | |
36 | 32 | }; |
37 | 33 | |
38 | 34 | ProgramaContentPageController.prototype.loadData = function() { |
39 | 35 | var vm = this; |
40 | 36 | |
41 | - // Get initial data of Program | |
42 | - vm.DialogaService.getProgramBySlug(vm.slug, function(article) { | |
37 | + vm.loading = true; | |
38 | + | |
39 | + // Get program by slug | |
40 | + var slug = vm.$state.params.slug; | |
41 | + vm.DialogaService.getProgramBySlug(slug, function(article) { | |
43 | 42 | vm.article = article; |
44 | 43 | vm.category = vm.article.categories[0]; |
45 | 44 | |
... | ... | @@ -54,41 +53,37 @@ |
54 | 53 | }; |
55 | 54 | } |
56 | 55 | |
57 | - // Get full data content of Program | |
58 | - vm.loadContent(); | |
59 | - | |
56 | + vm.DialogaService.getProposalsByTopicId(vm.article.id, {}, function(data){ | |
57 | + vm.proposals = data.children; | |
58 | + vm.proposalsTopRated = [ | |
59 | + {abstract: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tristique consectetur neque, at tincidunt enim volutpat sit amet. Integer sed cursus metus, non luctus risus. Mauris elementum est quis vehicula ullamcorper.'}, | |
60 | + {abstract: 'Mauris elementum est quis vehicula ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tristique consectetur neque, at tincidunt enim volutpat sit amet. Integer sed cursus metus, non luctus risus.'}, | |
61 | + {abstract: 'Integer sed cursus metus, non luctus risus. Mauris elementum est quis vehicula ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec tristique consectetur neque, at tincidunt enim volutpat sit amet.'}, | |
62 | + ]; | |
63 | + }, function (error) { | |
64 | + vm.$log.error(error); | |
65 | + }); | |
66 | + | |
67 | + vm.loading = false; | |
60 | 68 | }, function(error) { |
61 | 69 | vm.$log.error(error); |
62 | - vm.$log.info('Rollback to home page.'); | |
63 | - vm.$state.go('inicio', {}, {location: true}); | |
70 | + vm.error = error; | |
71 | + vm.loading = false; | |
72 | + | |
73 | + // vm.$log.info('Rollback to home page.'); | |
74 | + // vm.$state.go('inicio', {}, {location: true}); | |
64 | 75 | }); |
76 | + | |
65 | 77 | }; |
66 | 78 | |
67 | 79 | ProgramaContentPageController.prototype.attachListeners = function() { |
68 | 80 | var vm = this; |
69 | 81 | |
70 | - vm.$scope.$on('see-proposals', function() { | |
82 | + vm.$scope.$on('proposal-carousel:toProposals', function() { | |
71 | 83 | vm.$log.warn('TODO: handle see proposals / ranking'); |
72 | 84 | }); |
73 | 85 | }; |
74 | 86 | |
75 | - // Get full data content of Program | |
76 | - ProgramaContentPageController.prototype.loadContent = function() { | |
77 | - var vm = this; | |
78 | - | |
79 | - vm.loading = true; | |
80 | - if (!vm.article.body) { | |
81 | - vm.DialogaService.getContentById(vm.article.id, function(data) { | |
82 | - vm.article.body = data.article.body; | |
83 | - vm.loading = false; | |
84 | - }, function(error) { | |
85 | - vm.loading = false; | |
86 | - vm.error = error; | |
87 | - }); | |
88 | - } | |
89 | - vm.loading = false; | |
90 | - }; | |
91 | - | |
92 | 87 | ProgramaContentPageController.prototype.makeProposal = function() { |
93 | 88 | var vm = this; |
94 | 89 | ... | ... |
src/app/pages/programas/programa.html
... | ... | @@ -9,9 +9,11 @@ |
9 | 9 | <div class="page--conheca-o-programa"> |
10 | 10 | <section> |
11 | 11 | <div class="container"> |
12 | - <div ng-if="!pageProgramaContent.article.body"> | |
13 | - <div ng-if="!pageProgramaContent.error" class="alert alert-info" role="alert">Carregando detalhes sobre o progama...</div> | |
14 | - <div ng-if="pageProgramaContent.error" class="alert alert-warning" role="alert">{{pageProgramaContent}}</div> | |
12 | + <div class="row"> | |
13 | + <div class="col-sm-12"> | |
14 | + <div ng-if="!pageProgramaContent.article && pageProgramaContent.loading" class="alert alert-info" role="alert">Carregando detalhes sobre o progama...</div> | |
15 | + <div ng-if="!pageProgramaContent.article && pageProgramaContent.error" class="alert alert-warning" role="alert">Erro ao carregar o programa.</div> | |
16 | + </div> | |
15 | 17 | </div> |
16 | 18 | </div> |
17 | 19 | </section> |
... | ... | @@ -19,56 +21,59 @@ |
19 | 21 | <div ng-if="pageProgramaContent.article.body" ng-class="pageProgramaContent.category.slug"> |
20 | 22 | <section> |
21 | 23 | <div class="container"> |
22 | - <article class="program-preview"> | |
23 | - <div class="row"> | |
24 | - <div class="col-md-12"> | |
25 | - <h1 class="program-preview--title color-theme-fg">{{::pageProgramaContent.article.title}}</h1> | |
26 | - </div> | |
27 | - <div class="col-md-8"> | |
28 | - <div class="program-preview--box contraste-box"> | |
29 | - <div class="program-preview--banner" ng-style="{'background-image':'url( {{::pageProgramaContent.banner.src}} )'}"></div> | |
30 | - <div class="program-preview--box--content-wrapper"> | |
31 | - <div class="program-preview--icon icon-wrapper-rounded color-theme-bg" ng-class="pageProgramaContent.category.slug"> | |
32 | - <span class="icon" ng-class="'icon-tema-' + pageProgramaContent.category.slug"></span> | |
33 | - </div> | |
34 | - <div class="program-preview--abstract color-theme-fg"> | |
35 | - <h2>{{::stripHtml(pageProgramaContent.article.abstract)}}</h2> | |
36 | - </div> | |
37 | - <div class="program-preview--abstract-details"> | |
38 | - <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> | |
39 | - </div> | |
40 | - <div class="program-preview--share"> | |
41 | - <ul class="list-inline"> | |
42 | - <li>Compartilhe este programa:</li> | |
43 | - <li><social-share class="program-preview--share-directive"></social-share></li> | |
44 | - </ul> | |
45 | - </div> | |
46 | - <div class="program-preview--make-proposal"> | |
47 | - <div class="row"> | |
48 | - <div class="col-sm-6"> | |
49 | - <div class="button--themed"> | |
50 | - <button type="button" class="btn btn-block" ng-click="pageProgramaContent.makeProposal()">Faça uma proposta</button> | |
24 | + <div class="row"> | |
25 | + <article class="program-preview"> | |
26 | + | |
27 | + <div class="col-md-12"> | |
28 | + <h1 class="program-preview--title color-theme-fg">{{::pageProgramaContent.article.title}}</h1> | |
29 | + </div> | |
30 | + <div class="col-md-8"> | |
31 | + <div class="program-preview--box contraste-box"> | |
32 | + <div class="program-preview--banner" ng-style="{'background-image':'url( {{::pageProgramaContent.banner.src}} )'}"></div> | |
33 | + <div class="program-preview--box--content-wrapper"> | |
34 | + <div class="program-preview--icon icon-wrapper-rounded color-theme-bg" ng-class="pageProgramaContent.category.slug"> | |
35 | + <span class="icon" ng-class="'icon-tema-' + pageProgramaContent.category.slug"></span> | |
36 | + </div> | |
37 | + <div class="program-preview--abstract color-theme-fg"> | |
38 | + <h2>{{::stripHtml(pageProgramaContent.article.abstract)}}</h2> | |
39 | + </div> | |
40 | + <div class="program-preview--abstract-details"> | |
41 | + <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> | |
42 | + </div> | |
43 | + <div class="program-preview--share"> | |
44 | + <ul class="list-inline"> | |
45 | + <li>Compartilhe este programa:</li> | |
46 | + <li><social-share class="program-preview--share-directive"></social-share></li> | |
47 | + </ul> | |
48 | + </div> | |
49 | + <div class="program-preview--make-proposal"> | |
50 | + <div class="row"> | |
51 | + <div class="col-sm-6"> | |
52 | + <div class="button--themed"> | |
53 | + <button type="button" class="btn btn-block" ng-click="pageProgramaContent.makeProposal()">Faça uma proposta</button> | |
54 | + </div> | |
51 | 55 | </div> |
52 | 56 | </div> |
53 | 57 | </div> |
54 | 58 | </div> |
55 | 59 | </div> |
56 | 60 | </div> |
57 | - </div> | |
58 | - <div class="col-md-4"> | |
59 | - <div class="row"> | |
60 | - <div class="col-xs-12"> | |
61 | - <h3 class="color-theme-fg">Propostas mais votadas</h3> | |
62 | - <proposal-ranking limit="'3'" display="'carousel'"></proposal-ranking> | |
63 | - </div> | |
64 | - <div class="col-xs-12"> | |
65 | - <h3 class="color-theme-fg">Propostas nesse programa</h3> | |
66 | - <proposal-related article="pageProgramaContent.article"></proposal-related> | |
61 | + <div class="col-md-4"> | |
62 | + <div class="row"> | |
63 | + <div class="col-xs-12"> | |
64 | + <h3 class="color-theme-fg">Propostas mais votadas</h3> | |
65 | + <div ng-if="pageProgramaContent.proposalsTopRated"> | |
66 | + <proposal-carousel proposals="pageProgramaContent.proposalsTopRated"></proposal-carousel> | |
67 | + </div> | |
68 | + </div> | |
69 | + <div class="col-xs-12"> | |
70 | + <h3 class="color-theme-fg">Propostas nesse programa</h3> | |
71 | + <proposal-related article="pageProgramaContent.article"></proposal-related> | |
72 | + </div> | |
67 | 73 | </div> |
68 | 74 | </div> |
69 | - </div> | |
70 | - </div> | |
71 | - </article> | |
75 | + </article> | |
76 | + </div> | |
72 | 77 | </div> |
73 | 78 | </section> |
74 | 79 | |
... | ... | @@ -77,16 +82,16 @@ |
77 | 82 | <div class="proposal-ranking-section-header"> |
78 | 83 | <h3 class="color-theme-fg">Resultados de propostas mais votadas</h3> |
79 | 84 | </div> |
80 | - <div class="proposal-ranking-section-table"> | |
81 | - <proposal-ranking limit="'5'" display="'list'"></proposal-ranking> | |
85 | + <div class="proposal-ranking-section-table" ng-if="pageProgramaContent.proposals"> | |
86 | + <proposal-list proposals="pageProgramaContent.proposals"></proposal-list> | |
82 | 87 | </div> |
83 | 88 | </div> |
84 | 89 | </section> |
85 | - | |
86 | - <article class="program-content"> | |
87 | - <div class="row"> | |
88 | - <section ng-bind-html="pageProgramaContent.article.body"></section> | |
89 | - </div> | |
90 | - </article> | |
90 | + | |
91 | + <section class="section-content"> | |
92 | + <article class="program-content" ng-if="pageProgramaContent.article"> | |
93 | + <div ng-bind-html="pageProgramaContent.article.body"></div> | |
94 | + </article> | |
95 | + </section> | |
91 | 96 | </div> |
92 | 97 | </div> | ... | ... |
src/assets/images/icons/social-facebook.png
src/assets/images/icons/social-flickr.png
src/assets/images/icons/social-googleplus.png
src/assets/images/icons/social-share.png
src/assets/images/icons/social-twitter.png
src/assets/images/icons/social-whatsapp.png
src/assets/images/icons/social-youtube.png
src/assets/images/icons/sprite.png