Commit 8842e1454be07c41e83f7433a900799414265705
Exists in
master
and in
8 other branches
Merge branch 'develop' into 'master'
Develop See merge request !2
Showing
227 changed files
with
11389 additions
and
1538 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 227 files displayed.
.editorconfig
.gitignore
... | ... | @@ -0,0 +1 @@ |
1 | +v0.12.7 | ... | ... |
README.md
1 | 1 | # Dialoga App |
2 | 2 | |
3 | -# Project Decisions | |
3 | +## Convenções (Dialoga x Noosfero) | |
4 | + | |
5 | +- Os *programas* são **topics**; | |
6 | +- Os *temas* são **categories**; | |
7 | +- Um *grupo de programas* é um **discussion** (um grupo de topics); | |
8 | +- As *propostas* são **proposals**; | |
9 | + | |
10 | + | |
11 | +## Desenvolvimento | |
12 | + | |
13 | +Para iniciar o desenvolvimento: | |
14 | + | |
15 | +```bash | |
16 | +# dev with staging data | |
17 | +gulp serve --staging | |
18 | + | |
19 | +# dev with production data | |
20 | +gulp serve --production | |
21 | +``` | |
22 | + | |
23 | +##### Tecnologias utilizadas | |
4 | 24 | |
5 | 25 | - [generator-gulp-angular](https://github.com/Swiip/generator-gulp-angular) |
6 | 26 | - Angular |
... | ... | @@ -9,8 +29,11 @@ |
9 | 29 | - angular-touch |
10 | 30 | - angular-sanitize |
11 | 31 | - angular-ui-router |
12 | - - restangular | |
13 | -- gulp (default task: serve) | |
14 | -- JS old style (no CoffeeScript or ES6 or ...) | |
15 | -- HTML pure (no JADE or HBS or ...) | |
16 | -- Bootstrap CSS only (without JS files) | |
32 | +- gulp | |
33 | +- JS old style (no CoffeeScript or ES6 or etc.) | |
34 | +- HTML pure (no JADE or HBS or etc.) | |
35 | +- Bootstrap 3 | |
36 | + | |
37 | +## Referências | |
38 | + | |
39 | +- Git ([Guia](http://rogerdudler.github.io/git-guide/index.pt_BR.html)) | ... | ... |
... | ... | @@ -0,0 +1,7 @@ |
1 | +- Erro com `lwip` ou `make: g++: Command not found` | |
2 | + - Solução: | |
3 | + 1. Instalar dependências do g++: `sudo apt-get install build-essential g++` | |
4 | + 2. Reinstalar o sprity: | |
5 | + 1. desinstalar: ``npm uninstall sprity`` | |
6 | + 2. limpar cache: ``npm cache clear`` | |
7 | + 3. instalar: ``npm install sprity`` | |
0 | 8 | \ No newline at end of file | ... | ... |
bower.json
... | ... | @@ -2,21 +2,28 @@ |
2 | 2 | "name": "dialoga", |
3 | 3 | "version": "0.0.0", |
4 | 4 | "dependencies": { |
5 | + "angular": "~1.4.0", | |
5 | 6 | "angular-animate": "~1.4.0", |
7 | + "angular-breadcrumb": "~0.4.1", | |
6 | 8 | "angular-cookies": "~1.4.0", |
7 | - "angular-touch": "~1.4.0", | |
9 | + "angular-messages": "ng-messages#*", | |
8 | 10 | "angular-sanitize": "~1.4.0", |
11 | + "angular-slugify": "~1.0.1", | |
12 | + "angular-socialshare": "angularjs-socialshare#~0.1.13", | |
13 | + "angular-touch": "~1.4.0", | |
9 | 14 | "angular-ui-router": "~0.2.15", |
10 | - "jquery": "~2.1.4", | |
11 | - "bootstrap-sass-official": "~3.3.4", | |
12 | 15 | "animate.css": "~3.3.0", |
13 | - "angular": "~1.4.0", | |
14 | - "modernizr": "~2.8.3" | |
16 | + "bootstrap-sass-official": "~3.3.4", | |
17 | + "jquery": "~2.1.4", | |
18 | + "modernizr": "~2.8.3", | |
19 | + "ngstorage": "~0.3.9", | |
20 | + "open-sans-fontface": "~1.4.2" | |
15 | 21 | }, |
16 | 22 | "devDependencies": { |
17 | 23 | "angular-mocks": "~1.4.0" |
18 | 24 | }, |
19 | 25 | "resolutions": { |
20 | - "angular": "~1.4.0" | |
26 | + "angular": "~1.4.0", | |
27 | + "angular-messages": "~1.4.5" | |
21 | 28 | } |
22 | 29 | } | ... | ... |
... | ... | @@ -0,0 +1,852 @@ |
1 | +/** | |
2 | + * Use https://github.com/typicode/json-server for fake endpoint server. | |
3 | + * Example: $ json-server data.js -p 9000 -w data.js | |
4 | + */ | |
5 | +module.exports = function () { | |
6 | + 'use strict'; | |
7 | + var data = {}; | |
8 | + | |
9 | + // add /api/v1/articles path | |
10 | + // data.api = {}; | |
11 | + // data.api.v1 = {}; | |
12 | + // data.api.v1.articles = []; | |
13 | + | |
14 | + // add data to articles path | |
15 | + // data.api.v1.articles.push({ | |
16 | + data.articles = []; | |
17 | + | |
18 | + // json get from hom on 26/08/2015 | |
19 | + var articleHome = { | |
20 | + id: 103358, | |
21 | + "article":{ | |
22 | + "id": 103358, | |
23 | + "abstract": "<p style=\"text-align: center;\"><iframe src=\"https://www.youtube.com/embed/kpAdrO-emV0?rel=0&showinfo=0&iv_load_policy=3&controls=1\" style=\"max-width: 1000px; left: 5%;\" width=\"275\" height=\"200\"></iframe></p>", | |
24 | + | |
25 | + "title": "Dialoga Brasil", | |
26 | + "categories": [ | |
27 | + { | |
28 | + "name": "Saúde", | |
29 | + "id": 180, | |
30 | + "slug": "saude", | |
31 | + "image": null | |
32 | + }, { | |
33 | + "name": "Segurança Pública", | |
34 | + "id": 182, | |
35 | + "slug": "seguranca-publica", | |
36 | + "image": null | |
37 | + }, { | |
38 | + "name": "Educação", | |
39 | + "id": 181, | |
40 | + "slug": "educacao", | |
41 | + "image": null | |
42 | + }, { | |
43 | + "name": "Redução da Pobreza", | |
44 | + "id": 183, | |
45 | + "slug": "reducao-da-pobreza", | |
46 | + "image": null | |
47 | + }, { | |
48 | + "name": "Cultura", | |
49 | + "id": 194, | |
50 | + "slug": "cultura", | |
51 | + "image": null | |
52 | + } | |
53 | + ], | |
54 | + "image": null, | |
55 | + "setting": { | |
56 | + "custom_body_label": "Corpo", | |
57 | + "phase": "proposals", | |
58 | + "allow_topics": true, | |
59 | + "moderate_comments": false, | |
60 | + "comment_paragraph_plugin_activate": false, | |
61 | + "author_name": "Leandro Nunes dos Santos", | |
62 | + "moderate_proposals": true, | |
63 | + "allow_members_to_edit": false | |
64 | + }, | |
65 | + "position": null, | |
66 | + "children": [ | |
67 | + { | |
68 | + "id": 103390, | |
69 | + "abstract": "<p>Prevenção, tratamento e enfrentamento ao tráfico.</p>", | |
70 | + "title": "Crack, é possível vencer!", | |
71 | + "categories": [ | |
72 | + { | |
73 | + "name": "Segurança Pública", | |
74 | + "id": 182, | |
75 | + "slug": "seguranca-publica", | |
76 | + "image": null | |
77 | + } | |
78 | + ], | |
79 | + "image": { | |
80 | + "url": "/image_uploads/dialoga/0000/0104/crack.jpg" | |
81 | + }, | |
82 | + "setting": { | |
83 | + "color": "#00ff00", | |
84 | + "moderate_comments": false, | |
85 | + "comment_paragraph_plugin_activate": false, | |
86 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
87 | + "allow_members_to_edit": false | |
88 | + }, | |
89 | + "position": 14 | |
90 | + }, { | |
91 | + "id": 103521, | |
92 | + "abstract": "<p>Mais atendimento nos municípios, mais saúde para quem mais precisa.</p>", | |
93 | + "title": "Mais Médicos", | |
94 | + "categories": [ | |
95 | + { | |
96 | + "name": "Saúde", | |
97 | + "id": 180, | |
98 | + "slug": "saude", | |
99 | + "image": null | |
100 | + } | |
101 | + ], | |
102 | + "image": { | |
103 | + "url": "/image_uploads/dialoga/0000/0025/Mais_M_dicos.jpg" | |
104 | + }, | |
105 | + "setting": { | |
106 | + "color": "#ffe599", | |
107 | + "moderate_comments": false, | |
108 | + "comment_paragraph_plugin_activate": false, | |
109 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
110 | + "allow_members_to_edit": false | |
111 | + }, | |
112 | + "position": 1 | |
113 | + }, { | |
114 | + "id": 103457, | |
115 | + "abstract": "<p>Ação conjunta e cooperação transfronteiriça.</p>", | |
116 | + "title": "Proteção das Fronteiras", | |
117 | + "categories": [ | |
118 | + { | |
119 | + "name": "Segurança Pública", | |
120 | + "id": 182, | |
121 | + "slug": "seguranca-publica", | |
122 | + "image": null | |
123 | + } | |
124 | + ], | |
125 | + "image": { | |
126 | + "url": "/image_uploads/dialoga/0000/0110/fronteira_redim.jpg" | |
127 | + }, | |
128 | + "setting": { | |
129 | + "color": "#a64d79", | |
130 | + "moderate_comments": false, | |
131 | + "comment_paragraph_plugin_activate": false, | |
132 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
133 | + "allow_members_to_edit": false | |
134 | + }, | |
135 | + "position": 15 | |
136 | + }, { | |
137 | + "id": 103612, | |
138 | + "abstract": "<p>Garantir água para beber e produzir.</p>", | |
139 | + "title": "Cisternas", | |
140 | + "categories": [ | |
141 | + { | |
142 | + "name": "Redução da Pobreza", | |
143 | + "id": 183, | |
144 | + "slug": "reducao-da-pobreza", | |
145 | + "image": null | |
146 | + } | |
147 | + ], | |
148 | + "image": { | |
149 | + "url": "/image_uploads/dialoga/0000/0039/cisterna_redim.jpg" | |
150 | + }, | |
151 | + "setting": { | |
152 | + "color": "#0000ff", | |
153 | + "moderate_comments": false, | |
154 | + "comment_paragraph_plugin_activate": false, | |
155 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
156 | + "allow_members_to_edit": false | |
157 | + }, | |
158 | + "position": 20 | |
159 | + }, { | |
160 | + "id": 103442, | |
161 | + "abstract": "<p>Complemento à renda e acompanhamento em educação e saúde.</p>", | |
162 | + "title": "Bolsa Família", | |
163 | + "categories": [ | |
164 | + { | |
165 | + "name": "Redução da Pobreza", | |
166 | + "id": 183, | |
167 | + "slug": "reducao-da-pobreza", | |
168 | + "image": null | |
169 | + } | |
170 | + ], | |
171 | + "image": { | |
172 | + "url": "/image_uploads/dialoga/0000/0013/bolsa_familia_redim.jpg" | |
173 | + }, | |
174 | + "setting": { | |
175 | + "color": "#ff9900", | |
176 | + "moderate_comments": false, | |
177 | + "comment_paragraph_plugin_activate": false, | |
178 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
179 | + "allow_members_to_edit": false | |
180 | + }, | |
181 | + "position": 17 | |
182 | + }, { | |
183 | + "id": 103673, | |
184 | + "abstract": "<p>A melhor escolha é se informar.</p>", | |
185 | + "title": "Incentivo ao Parto Normal", | |
186 | + "categories": [ | |
187 | + { | |
188 | + "name": "Saúde", | |
189 | + "id": 180, | |
190 | + "slug": "saude", | |
191 | + "image": null | |
192 | + } | |
193 | + ], | |
194 | + "image": { | |
195 | + "url": "/image_uploads/dialoga/0000/0092/parto-normal.jpg" | |
196 | + }, | |
197 | + "setting": { | |
198 | + "color": "#ff0000", | |
199 | + "moderate_comments": false, | |
200 | + "comment_paragraph_plugin_activate": false, | |
201 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
202 | + "allow_members_to_edit": false | |
203 | + }, | |
204 | + "position": 6 | |
205 | + }, { | |
206 | + "id": 103397, | |
207 | + "abstract": "<p>Renda, inclusão produtiva e acesso a serviços.</p>", | |
208 | + "title": "Brasil Sem Miséria", | |
209 | + "categories": [ | |
210 | + { | |
211 | + "name": "Redução da Pobreza", | |
212 | + "id": 183, | |
213 | + "slug": "reducao-da-pobreza", | |
214 | + "image": null | |
215 | + } | |
216 | + ], | |
217 | + "image": { | |
218 | + "url": "/image_uploads/dialoga/0000/0116/bsm_redim.jpg" | |
219 | + }, | |
220 | + "setting": { | |
221 | + "color": "", | |
222 | + "moderate_comments": false, | |
223 | + "comment_paragraph_plugin_activate": false, | |
224 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
225 | + "allow_members_to_edit": false | |
226 | + }, | |
227 | + "position": 18 | |
228 | + }, { | |
229 | + "id": 121505, | |
230 | + "abstract": "<p>Um novo jeito de ver e de fazer cultura</p>", | |
231 | + "title": "Agenda Seculo XXI", | |
232 | + "categories": [ | |
233 | + { | |
234 | + "name": "Cultura", | |
235 | + "id": 194, | |
236 | + "slug": "cultura", | |
237 | + "image": null | |
238 | + } | |
239 | + ], | |
240 | + "image": { | |
241 | + "url": "/image_uploads/dialoga/0000/0166/Abertura_AGENDA_SECULO_XXI-v4.jpg" | |
242 | + }, | |
243 | + "setting": { | |
244 | + "color": "", | |
245 | + "allow_members_to_edit": false, | |
246 | + "moderate_comments": false, | |
247 | + "comment_paragraph_plugin_activate": false, | |
248 | + "author_name": "leonardo.merlin" | |
249 | + }, | |
250 | + "position": null | |
251 | + }, { | |
252 | + "id": 121526, | |
253 | + "abstract": "<p>Cultura e arte como base para a educação integral</p>", | |
254 | + "title": "Cultura e Educação", | |
255 | + "categories": [ | |
256 | + { | |
257 | + "name": "Cultura", | |
258 | + "id": 194, | |
259 | + "slug": "cultura", | |
260 | + "image": null | |
261 | + } | |
262 | + ], | |
263 | + "image": { | |
264 | + "url": "/image_uploads/dialoga/0000/0177/Abertura-cultura-e-educacao-v2.jpg" | |
265 | + }, | |
266 | + "setting": { | |
267 | + "color": "", | |
268 | + "allow_members_to_edit": false, | |
269 | + "moderate_comments": false, | |
270 | + "comment_paragraph_plugin_activate": false, | |
271 | + "author_name": "leonardo.merlin" | |
272 | + }, | |
273 | + "position": null | |
274 | + }, { | |
275 | + "id": 103485, | |
276 | + "abstract": "<p>Caminho para uma educação de qualidade.</p>", | |
277 | + "title": "Valorização dos Professores", | |
278 | + "categories": [ | |
279 | + { | |
280 | + "name": "Educação", | |
281 | + "id": 181, | |
282 | + "slug": "educacao", | |
283 | + "image": null | |
284 | + } | |
285 | + ], | |
286 | + "image": { | |
287 | + "url": "/image_uploads/dialoga/0000/0140/valorizacao_professor.jpg" | |
288 | + }, | |
289 | + "setting": { | |
290 | + "color": "#ffff00", | |
291 | + "moderate_comments": false, | |
292 | + "comment_paragraph_plugin_activate": false, | |
293 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
294 | + "allow_members_to_edit": false | |
295 | + }, | |
296 | + "position": 11 | |
297 | + }, { | |
298 | + "id": 103663, | |
299 | + "abstract": "<p>Mais educação profissional e tecnológica, mais desenvolvimento</p>", | |
300 | + "title": "Ensino Técnico", | |
301 | + "categories": [ | |
302 | + { | |
303 | + "name": "Educação", | |
304 | + "id": 181, | |
305 | + "slug": "educacao", | |
306 | + "image": null | |
307 | + } | |
308 | + ], | |
309 | + "image": { | |
310 | + "url": "/image_uploads/dialoga/0000/0134/Ensino_tecnico.jpg" | |
311 | + }, | |
312 | + "setting": { | |
313 | + "color": "#d0e0e3", | |
314 | + "moderate_comments": false, | |
315 | + "comment_paragraph_plugin_activate": false, | |
316 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
317 | + "allow_members_to_edit": false | |
318 | + }, | |
319 | + "position": 10 | |
320 | + }, { | |
321 | + "id": 121514, | |
322 | + "abstract": "<p>Reconhecimento, fortalecimento e mobilização das comunidades que fazem cultura no Brasil</p>", | |
323 | + "title": "Cultura Viva", | |
324 | + "categories": [ | |
325 | + { | |
326 | + "name": "Cultura", | |
327 | + "id": 194, | |
328 | + "slug": "cultura", | |
329 | + "image": null | |
330 | + } | |
331 | + ], | |
332 | + "image": { | |
333 | + "url": "/image_uploads/dialoga/0000/0167/Abertura_Cultura_Viva.jpg" | |
334 | + }, | |
335 | + "setting": { | |
336 | + "color": "", | |
337 | + "allow_members_to_edit": false, | |
338 | + "moderate_comments": false, | |
339 | + "comment_paragraph_plugin_activate": false, | |
340 | + "author_name": "leonardo.merlin" | |
341 | + }, | |
342 | + "position": null | |
343 | + }, { | |
344 | + "id": 103592, | |
345 | + "abstract": "<p>Garantir acesso à proteção social.</p>", | |
346 | + "title": "Assistência Social", | |
347 | + "categories": [ | |
348 | + { | |
349 | + "name": "Redução da Pobreza", | |
350 | + "id": 183, | |
351 | + "slug": "reducao-da-pobreza", | |
352 | + "image": null | |
353 | + } | |
354 | + ], | |
355 | + "image": { | |
356 | + "url": "/image_uploads/dialoga/0000/0122/assistencia_social.jpg" | |
357 | + }, | |
358 | + "setting": { | |
359 | + "color": "#a61c00", | |
360 | + "moderate_comments": false, | |
361 | + "comment_paragraph_plugin_activate": false, | |
362 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
363 | + "allow_members_to_edit": false | |
364 | + }, | |
365 | + "position": 19 | |
366 | + }, { | |
367 | + "id": 103426, | |
368 | + "abstract": "<p>Da saúde se cuida todos os dias.</p>", | |
369 | + "title": "Vida saudável", | |
370 | + "categories": [ | |
371 | + { | |
372 | + "name": "Saúde", | |
373 | + "id": 180, | |
374 | + "slug": "saude", | |
375 | + "image": null | |
376 | + } | |
377 | + ], | |
378 | + "image": { | |
379 | + "url": "/image_uploads/dialoga/0000/0046/vida_saudavel.jpg" | |
380 | + }, | |
381 | + "setting": { | |
382 | + "color": "#d9d2e9", | |
383 | + "moderate_comments": false, | |
384 | + "comment_paragraph_plugin_activate": false, | |
385 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
386 | + "allow_members_to_edit": false | |
387 | + }, | |
388 | + "position": 7 | |
389 | + }, { | |
390 | + "id": 103507, | |
391 | + "abstract": "<p>Tecnologia a serviço da segurança do cidadão.</p>", | |
392 | + "title": "Sinesp", | |
393 | + "categories": [ | |
394 | + { | |
395 | + "name": "Segurança Pública", | |
396 | + "id": 182, | |
397 | + "slug": "seguranca-publica", | |
398 | + "image": null | |
399 | + } | |
400 | + ], | |
401 | + "image": { | |
402 | + "url": "/image_uploads/dialoga/0000/0098/sinesp.png" | |
403 | + }, | |
404 | + "setting": { | |
405 | + "color": "#00ff00", | |
406 | + "moderate_comments": false, | |
407 | + "comment_paragraph_plugin_activate": false, | |
408 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
409 | + "allow_members_to_edit": false | |
410 | + }, | |
411 | + "position": 12 | |
412 | + }, { | |
413 | + "id": 103359, | |
414 | + "abstract": "<p>Acesso a exames e consultas com especialistas.</p>", | |
415 | + "title": "Mais Especialidades", | |
416 | + "categories": [ | |
417 | + { | |
418 | + "name": "Saúde", | |
419 | + "id": 180, | |
420 | + "slug": "saude", | |
421 | + "image": null | |
422 | + } | |
423 | + ], | |
424 | + "image": { | |
425 | + "url": "/image_uploads/dialoga/0000/0083/mais_especialidades1.png" | |
426 | + }, | |
427 | + "setting": { | |
428 | + "color": "#ea9999", | |
429 | + "moderate_comments": false, | |
430 | + "comment_paragraph_plugin_activate": false, | |
431 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
432 | + "allow_members_to_edit": false | |
433 | + }, | |
434 | + "position": 2 | |
435 | + }, { | |
436 | + "id": 103683, | |
437 | + "abstract": "<p>Saúde não tem preço.</p>", | |
438 | + "title": "Aqui tem Farmácia Popular", | |
439 | + "categories": [ | |
440 | + { | |
441 | + "name": "Saúde", | |
442 | + "id": 180, | |
443 | + "slug": "saude", | |
444 | + "image": null | |
445 | + } | |
446 | + ], | |
447 | + "image": { | |
448 | + "url": "/image_uploads/dialoga/0000/0019/saude_nao_tem_preco.jpg" | |
449 | + }, | |
450 | + "setting": { | |
451 | + "color": "#e69138", | |
452 | + "moderate_comments": false, | |
453 | + "comment_paragraph_plugin_activate": false, | |
454 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
455 | + "allow_members_to_edit": false | |
456 | + }, | |
457 | + "position": 5 | |
458 | + }, { | |
459 | + "id": 103695, | |
460 | + "abstract": "<p>Novo modelo de atuação em Segurança Pública.</p>", | |
461 | + "title": "Segurança Pública Integrada", | |
462 | + "categories": [ | |
463 | + { | |
464 | + "name": "Segurança Pública", | |
465 | + "id": 182, | |
466 | + "slug": "seguranca-publica", | |
467 | + "image": null | |
468 | + } | |
469 | + ], | |
470 | + "image": { | |
471 | + "url": "/image_uploads/dialoga/0000/0152/policiaintegrada.jpg" | |
472 | + }, | |
473 | + "setting": { | |
474 | + "color": "#ff00ff", | |
475 | + "moderate_comments": false, | |
476 | + "comment_paragraph_plugin_activate": false, | |
477 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
478 | + "allow_members_to_edit": false | |
479 | + }, | |
480 | + "position": 13 | |
481 | + }, { | |
482 | + "id": 103379, | |
483 | + "abstract": "<p>Resgate e atendimento 24 horas, sete dias da semana.</p>", | |
484 | + "title": "SAMU 192 e UPAs", | |
485 | + "categories": [ | |
486 | + { | |
487 | + "name": "Saúde", | |
488 | + "id": 180, | |
489 | + "slug": "saude", | |
490 | + "image": null | |
491 | + } | |
492 | + ], | |
493 | + "image": { | |
494 | + "url": "/image_uploads/dialoga/0000/0060/SAMU.jpg" | |
495 | + }, | |
496 | + "setting": { | |
497 | + "color": "#45818e", | |
498 | + "moderate_comments": false, | |
499 | + "comment_paragraph_plugin_activate": false, | |
500 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
501 | + "allow_members_to_edit": false | |
502 | + }, | |
503 | + "position": 4 | |
504 | + }, { | |
505 | + "id": 103494, | |
506 | + "abstract": "<p>Da Educação Infantil ao Ensino Médio.</p>", | |
507 | + "title": "Educação Básica", | |
508 | + "categories": [ | |
509 | + { | |
510 | + "name": "Educação", | |
511 | + "id": 181, | |
512 | + "slug": "educacao", | |
513 | + "image": null | |
514 | + } | |
515 | + ], | |
516 | + "image": { | |
517 | + "url": "/image_uploads/dialoga/0000/0076/Educa__o_B_sica.jpg" | |
518 | + }, | |
519 | + "setting": { | |
520 | + "color": "#fce5cd", | |
521 | + "moderate_comments": false, | |
522 | + "comment_paragraph_plugin_activate": false, | |
523 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
524 | + "allow_members_to_edit": false | |
525 | + }, | |
526 | + "position": 8 | |
527 | + }, { | |
528 | + "id": 103644, | |
529 | + "abstract": "<p>Um caminho de oportunidades com o Enem: Sisu, Prouni, Fies, Ciência sem Fronteiras</p>", | |
530 | + "title": "Ensino Superior", | |
531 | + "categories": [ | |
532 | + { | |
533 | + "name": "Educação", | |
534 | + "id": 181, | |
535 | + "slug": "educacao", | |
536 | + "image": null | |
537 | + } | |
538 | + ], | |
539 | + "image": { | |
540 | + "url": "/image_uploads/dialoga/0000/0128/enem.jpg" | |
541 | + }, | |
542 | + "setting": { | |
543 | + "color": "#cfe2f3", | |
544 | + "moderate_comments": false, | |
545 | + "comment_paragraph_plugin_activate": false, | |
546 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
547 | + "allow_members_to_edit": false | |
548 | + }, | |
549 | + "position": 9 | |
550 | + }, { | |
551 | + "id": 121499, | |
552 | + "abstract": "<p>Valorização da arte e da cultura em suas múltiplas possibilidades</p>", | |
553 | + "title": "Política Nacional das Artes", | |
554 | + "categories": [ | |
555 | + { | |
556 | + "name": "Cultura", | |
557 | + "id": 194, | |
558 | + "slug": "cultura", | |
559 | + "image": null | |
560 | + } | |
561 | + ], | |
562 | + "image": { | |
563 | + "url": "/image_uploads/dialoga/0000/0159/Banner_Pol_tica_Nacional_das_Artes.jpg" | |
564 | + }, | |
565 | + "setting": { | |
566 | + "color": "", | |
567 | + "allow_members_to_edit": false, | |
568 | + "moderate_comments": false, | |
569 | + "comment_paragraph_plugin_activate": false, | |
570 | + "author_name": "leonardo.merlin" | |
571 | + }, | |
572 | + "position": null | |
573 | + }, { | |
574 | + "id": 103472, | |
575 | + "abstract": "<p>Polícia Federal, Polícia Rodoviária Federal e Força Nacional de Segurança Pública.</p>", | |
576 | + "title": "Forças Federais de Segurança", | |
577 | + "categories": [ | |
578 | + { | |
579 | + "name": "Segurança Pública", | |
580 | + "id": 182, | |
581 | + "slug": "seguranca-publica", | |
582 | + "image": null | |
583 | + } | |
584 | + ], | |
585 | + "image": { | |
586 | + "url": "/image_uploads/dialoga/0000/0031/federais2.png" | |
587 | + }, | |
588 | + "setting": { | |
589 | + "color": "", | |
590 | + "moderate_comments": false, | |
591 | + "comment_paragraph_plugin_activate": false, | |
592 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
593 | + "allow_members_to_edit": false | |
594 | + }, | |
595 | + "position": 16 | |
596 | + }, { | |
597 | + "id": 121492, | |
598 | + "abstract": "<p>Apoio ao audiovisual brasileiro: ampliação da produção, da difusão e do acesso</p>", | |
599 | + "title": "Brasil de Todas as Telas", | |
600 | + "categories": [ | |
601 | + { | |
602 | + "name": "Cultura", | |
603 | + "id": 194, | |
604 | + "slug": "cultura", | |
605 | + "image": null | |
606 | + } | |
607 | + ], | |
608 | + "image": { | |
609 | + "url": "/image_uploads/dialoga/0000/0165/brasil-de-todas-telas-banner.jpg" | |
610 | + }, | |
611 | + "setting": { | |
612 | + "color": "", | |
613 | + "allow_members_to_edit": false, | |
614 | + "moderate_comments": false, | |
615 | + "comment_paragraph_plugin_activate": false, | |
616 | + "author_name": "leonardo.merlin" | |
617 | + }, | |
618 | + "position": null | |
619 | + }, { | |
620 | + "id": 121521, | |
621 | + "abstract": "<p>Mais acesso a cultura para trabalhadores e trabalhadoras</p>", | |
622 | + "title": "Vale-Cultura", | |
623 | + "categories": [ | |
624 | + { | |
625 | + "name": "Cultura", | |
626 | + "id": 194, | |
627 | + "slug": "cultura", | |
628 | + "image": null | |
629 | + } | |
630 | + ], | |
631 | + "image": { | |
632 | + "url": "/image_uploads/dialoga/0000/0175/Abertura_Vale_cultura-v3.jpg" | |
633 | + }, | |
634 | + "setting": { | |
635 | + "color": "", | |
636 | + "allow_members_to_edit": false, | |
637 | + "moderate_comments": false, | |
638 | + "comment_paragraph_plugin_activate": false, | |
639 | + "author_name": "leonardo.merlin" | |
640 | + }, | |
641 | + "position": null | |
642 | + }, { | |
643 | + "id": 103416, | |
644 | + "abstract": "<p>Estrutura adequada para atender melhor a população na atenção básica.</p>", | |
645 | + "title": "Melhorar os Postos de Saúde", | |
646 | + "categories": [ | |
647 | + { | |
648 | + "name": "Saúde", | |
649 | + "id": 180, | |
650 | + "slug": "saude", | |
651 | + "image": null | |
652 | + } | |
653 | + ], | |
654 | + "image": { | |
655 | + "url": "/image_uploads/dialoga/0000/0053/requalif_redim.jpg" | |
656 | + }, | |
657 | + "setting": { | |
658 | + "color": "#cc4125", | |
659 | + "moderate_comments": false, | |
660 | + "comment_paragraph_plugin_activate": false, | |
661 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
662 | + "allow_members_to_edit": false | |
663 | + }, | |
664 | + "position": 3 | |
665 | + }, { | |
666 | + "id": 121501, | |
667 | + "abstract": "<p>Preservação do patrimônio e qualidade de vida para os cidadãos</p>", | |
668 | + "title": "PAC Cidades Históricas", | |
669 | + "categories": [ | |
670 | + { | |
671 | + "name": "Cultura", | |
672 | + "id": 194, | |
673 | + "slug": "cultura", | |
674 | + "image": null | |
675 | + } | |
676 | + ], | |
677 | + "image": { | |
678 | + "url": "/image_uploads/dialoga/0000/0168/Abertura__PAC_Cidades_Historicas-v3.JPG" | |
679 | + }, | |
680 | + "setting": { | |
681 | + "color": "", | |
682 | + "allow_members_to_edit": false, | |
683 | + "moderate_comments": false, | |
684 | + "comment_paragraph_plugin_activate": false, | |
685 | + "author_name": "leonardo.merlin" | |
686 | + }, | |
687 | + "position": null | |
688 | + } | |
689 | + ] | |
690 | + } | |
691 | + }; | |
692 | + data.articles.push(articleHome); | |
693 | + | |
694 | + data.articles.push({ | |
695 | + "id":103521, | |
696 | + "article":{"id":103521,"body":"\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch2\u003EMais M\u00e9dicos\u003Csmall\u003E Mais atendimento nos munic\u00edpios, mais sa\u00fade para quem mais precisa.\u003C/small\u003E\u003C/h2\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6\"\u003E\u003Cimg class=\"center-block img-responsive\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/mais-medicos-foto1.jpg\" alt=\"Foto colorida mostra um M\u00e9dico examinando uma menina. Ele est\u00e1 com uma lanterna na m\u00e3o e ela est\u00e1 com a l\u00edngua para fora.\" width=\"640\" height=\"373\" /\u003E\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6\"\u003E\r\n\u003Cp\u003EEste programa garante m\u00e9dicos nos postos de sa\u00fade de todo o Pa\u00eds. O\u00a0Mais M\u00e9dicos come\u00e7ou em 2013 e j\u00e1 mostra resultados positivos: \u00e9 muito bem avaliado por 95% dos usu\u00e1rios, segundo pesquisa feita pela UFMG / Ipespe, em 2014.\u003C/p\u003E\r\n\u003Cp\u003EO programa veio para enfrentar uma car\u00eancia hist\u00f3rica de m\u00e9dicos em muitos munic\u00edpios do Brasil. Antes do lan\u00e7amento do Mais M\u00e9dicos, 22 estados tinham um n\u00famero de m\u00e9dicos abaixo da m\u00e9dia nacional. Cinco desses estados tinham menos de 1 m\u00e9dico para cada mil habitantes.\u003C/p\u003E\r\n\u003Cp\u003EEntre 2013 e 2014, o governo federal selecionou e levou 14.462 m\u00e9dicos para 3.785 munic\u00edpios. Assim, garantiu atendimento para 50 milh\u00f5es de pessoas que precisavam se deslocar a outras cidades, nem sempre pr\u00f3ximas, para ter atendimento m\u00e9dico.\u003C/p\u003E\r\n\u003Cp\u003EEm 2015, chegamos a 18 mil vagas para m\u00e9dicos no programa. Beneficiamos 63 milh\u00f5es de pessoas, em mais de 4 mil munic\u00edpios. N\u00e3o h\u00e1 um \u00fanico munic\u00edpio brasileiro sem atendimento m\u00e9dico.\u003C/p\u003E\r\n\u003Cp\u003EOs m\u00e9dicos brasileiros se destacaram, em 2015: 92% dos m\u00e9dicos que aderiram ao programa s\u00e3o brasileiros.\u003C/p\u003E\r\n\u003Cp\u003ETodos os m\u00e9dicos rec\u00e9m-formados que participam do Mais M\u00e9dicos recebem um b\u00f4nus de 10% em sua nota na prova de resid\u00eancia, como incentivo a sua atua\u00e7\u00e3o nesta tarefa de levar atendimento \u00e0 sa\u00fade a nossa popula\u00e7\u00e3o.\u003C/p\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Cdiv class=\"text-center\"\u003E\u003Cimg class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/mais-medicos-foto2.jpg\" alt=\"Infogr\u00e1fico mostra a aceita\u00e7\u00e3o do Mais M\u00e9dico de 95% dos usu\u00e1rios.\" width=\"501\" height=\"135\" /\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch3\u003EEvolu\u00e7\u00e3o do programa\u003C/h3\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\u003Cimg class=\"center-block img-responsive\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/mais-medicos-foto3.jpg\" alt=\"Dois mapas do Brasil mostrando a evolu\u00e7\u00e3o do programa, um com o n\u00famero de m\u00e9dicos do programa em 2013 com 1.136 m\u00e9dicos e o outro em 2015 com 18.247 m\u00e9dicos.\" width=\"752\" height=\"548\" /\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row bloco-destaque\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch4\u003EForam criadas 4.600 vagas de gradua\u00e7\u00e3o e 2.586 vagas de resid\u00eancia\u003C/h4\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-5 col-sm-5\"\u003E\r\n\u003Cp\u003EO Programa Mais M\u00e9dicos leva para o interior novas vagas em cursos de medicina, investindo na qualidade da forma\u00e7\u00e3o de m\u00e9dicos no Brasil e aumentando o n\u00famero de novos profissionais.\u003C/p\u003E\r\n\u003Cp\u003ES\u00e3o oferecidas, tamb\u00e9m, mais vagas de resid\u00eancia m\u00e9dica na rede de sa\u00fade, para formar especialistas que atendam \u00e0s necessidades de todas as regi\u00f5es do pa\u00eds.\u003Cimg class=\"center-block img-responsive\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/mais-medicos-foto5.jpg\" alt=\"Gr\u00e1fico de barra, com duas colunas. Uma mostra o crescimento de bolsas em outras especialidades de sa\u00fade. Em 2010 o n\u00famero de 499 e 2.875 em 2015. A outra barra mostra o crescimento de bolsas em resid\u00eancia. 788 vagas de resid\u00eancia em 2010 e 4.952 bolsas em 2015. Ao lado do gr\u00e1fico tem o texto : A cada ano, o Minist\u00e9rio da Sa\u00fade financia um n\u00famero maior de bolsas para forma\u00e7\u00e3o e especializa\u00e7\u00e3o. Ao lado foto mostra quatro m\u00e9dicos, duas mulheres e dois homens de jaleco branco e estetosc\u00f3pio no pesco\u00e7o e sorrindo.\" width=\"756\" height=\"397\" /\u003E\u003C/p\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch3 class=\"titulo-destaque\"\u003EHoje, das 22.344 vagas em cursos de medicina, 52% est\u00e3o localizados no interior.\u003C/h3\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\u003Cimg class=\"center-block img-responsive\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/maismedicos-graficointeriorv3.jpg\" alt=\"Gr\u00e1fico de linha mostra a evolu\u00e7\u00e3o no n\u00famero de vagas nos cursos de medicina. A linha cinza mostra que em 1994 tinha 4.884 vagas na capital e 10.637 vagas em 2015. A linha azul mostra 3.878 vagas no interior em 1994 e 14.522 em 2015\" width=\"748\" height=\"435\" /\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch3\u003ECompromissos\u003C/h3\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\u003Cimg class=\"center-block img-responsive\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/mais-medicos/imagens/mais-medicos-foto7.png\" alt=\"Foto mostra uma m\u00e3o de mulher segurando um Estetosc\u00f3pio com a sigla do SUS (Sistema \u00danico de Sa\u00fade).\" width=\"327\" height=\"327\" /\u003E\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\r\n\u003Cul class=\"list-unstyled\"\u003E\r\n\u003Cli\u003ELevar atendimento m\u00e9dico a 70 milh\u00f5es de pessoas at\u00e9 2018.\u003C/li\u003E\r\n\u003Cli\u003EAt\u00e9 2017, criar mais 6,8 mil novas vagas em faculdades de medicina, chegando a 11,5 mil.\u003C/li\u003E\r\n\u003Cli\u003EAt\u00e9 2018, criar mais 9,8 mil vagas de resid\u00eancia m\u00e9dica chegando a 12,4 mil.\u003C/li\u003E\r\n\u003C/ul\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E"} | |
697 | + }); | |
698 | + data.articles.push({ | |
699 | + id: 103507, | |
700 | + "article": {"id":103507,"body":"\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch2\u003ESINESP\u003Csmall\u003ETecnologia a servi\u00e7o da seguran\u00e7a do cidad\u00e3o.\u003C/small\u003E\u003C/h2\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\u003Cimg class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/sinesp/imagens/grafico-sinesp-2.jpg\" alt=\"Infogr\u00e1fico com o mapa do Brasil ligado por pontilhados a um monitor com o texto: base de dados. Outro pontilhado liga o monitor a cinco pictogramas, o primeiro a figura de uma engrenagem com o texto: pain\u00e9is gerenciais; o segundo um gr\u00e1fico de barras com o texto: gr\u00e1ficos anal\u00edticos; o terceiro uma folha de papel com escrito e o texto: relat\u00f3rios; a quarta um mapa do Brasil com o texto: mapas estat\u00edsticos e o quinto com tr\u00eas pessoas e o texto: planos de a\u00e7\u00e3o. Ao lado desse infogr\u00e1fico o texto: Sinesp \u2013 Sistema Nacional de Informa\u00e7\u00f5es de Seguran\u00e7a P\u00fablica, Prisionais e sobre Drogas. Atendimentos a emerg\u00eancias municipais, estaduais e federais (190, 191, 192, 193 e 197). Dados centralizados e consolidados. Atualiza\u00e7\u00e3o em tempo real. Sincroniza\u00e7\u00e3o das bases. Boletins de ocorr\u00eancia. Inqu\u00e9ritos policiais civis estaduais e federais. \" width=\"784\" height=\"598\" /\u003E\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\r\n\u003Cp\u003EO \u003Cstrong\u003ESINESP - Sistema Nacional de Informa\u00e7\u00f5es de Seguran\u00e7a P\u00fablica, Prisionais e sobre Drogas\u003C/strong\u003E \u00e9 um servi\u00e7o in\u00e9dito no Brasil. Re\u00fane, sistematiza, analisa e coloca \u00e0 disposi\u00e7\u00e3o dos cidad\u00e3os informa\u00e7\u00f5es sobre seguran\u00e7a p\u00fablica, justi\u00e7a, drogas e sistema prisional.\u003C/p\u003E\r\n\u003Cp\u003EImplementado pelo governo federal, em parceria com os 26 estados e o Distrito Federal, o sistema est\u00e1 ajudando a \u003Cstrong\u003Emelhorar a qualidade dos servi\u00e7os prestados \u003C/strong\u003E pela seguran\u00e7a p\u00fablica.\u003C/p\u003E\r\n\u003Cp\u003EO SINESP ajuda gestores a planejar e executar a\u00e7\u00f5es integradas contra o crime e a viol\u00eancia. Al\u00e9m disso, d\u00e1 mais \u003Cstrong\u003Etranspar\u00eancia\u003C/strong\u003E aos \u00edndices de criminalidade para toda a sociedade, pois os relat\u00f3rios com todas as\u00a0 informa\u00e7\u00f5es dispon\u00edveis no SINESP podem ser lidos e consultados pela popula\u00e7\u00e3o via \u003Cem\u003Einternet\u003C/em\u003E.\u003C/p\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\r\n\u003Ch3\u003ESINESP Cidad\u00e3o\u003C/h3\u003E\r\n\u003Cp\u003EDispon\u00edvel para qualquer pessoa, \u00e9 um aplicativo de consulta r\u00e1pida via \u003Cem\u003Einternet \u003C/em\u003Eque oferece informa\u00e7\u00f5es sobre \u003Cstrong\u003Eve\u00edculos roubados ou furtados, pessoas desaparecidas ou com mandatos de pris\u00e3o expedidos contra elas.\u003C/strong\u003E\u003C/p\u003E\r\n\u003Cp\u003EA ferramenta pode ser acessada, \u003Cstrong\u003Egratuitamente\u003C/strong\u003E, pelo endere\u00e7o \u003Cstrong\u003Ewww.sinesp.gov.br\u003C/strong\u003E e nas lojas de aplicativos, tanto para IOS, Android e Windows Phone.\u003C/p\u003E\r\n\u003Cp\u003EEm breve, um novo m\u00f3dulo ser\u00e1 disponibilizado no aplicativo: a localiza\u00e7\u00e3o de unidades policiais pr\u00f3ximas do usu\u00e1rio.\u003C/p\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6\"\u003E\u003Cimg class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/sinesp/imagens/tecnologia-sinesp-imagem2.jpg\" alt=\"Foto mostra m\u00e3o de uma pessoa com celular na m\u00e3o acessando o aplicativo. Ao fundo carros passando na rua. \" width=\"326\" height=\"327\" /\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"container\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12 col-sm-12\"\u003E\u003Cimg class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/sinesp/imagens/tecnologia-sinesp-imagem3.jpg\" alt=\"Tr\u00eas pictogramas um ao lado do outro. O primeiro uma nuvem com uma seta para baixo com o texto: mais de 4,5 milh\u00f5es de downloads. O segundo uma lupa e o texto: mais de 150 milh\u00f5es de consulta. E o terceiro um carro com o texto: mais de 100 mil ve\u00edculos recuperados. \" width=\"773\" height=\"176\" /\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E"} | |
701 | + }); | |
702 | + data.articles.push({ | |
703 | + id: 121521, | |
704 | + "article":{"id":121521,"body":"\u003Cdiv class=\"col-xs-12\"\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch2\u003EVale-Cultura\u003Csmall\u003EMais acesso \u00e0 cultura para trabalhadores e trabalhadoras\u003C/small\u003E\u003C/h2\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch3\u003ELivros, shows e espet\u00e1culos para todos.\u003C/h3\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\u003Cimg class=\"img-responsive\" src=\"http://gestao.dialoga.gov.br/dialoga/dialoga-brasil/vale-cultura/imagens/vale-cultura1.jpg\" alt=\"\" /\u003E\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\r\n\u003Cp\u003EO Vale-Cultura incentiva as empresas a oferecer aos seus funcion\u00e1rios acesso a livros, revistas, ingressos para cinemas, teatros, shows, instrumentos musicais e cursos de arte e cultura.\u003C/p\u003E\r\n\u003Cp\u003EO benef\u00edcio \u00e9 garantido por meio de um cart\u00e3o magn\u00e9tico pr\u00e9-pago, v\u00e1lido em todo os pa\u00eds. Mensalmente, esse cart\u00e3o recebe cr\u00e9dito de R$ 50, que pode ser acumulado para despesas maiores.\u003C/p\u003E\r\n\u003Cp\u003EA ades\u00e3o das empresas \u00e9 facultativa e os custos s\u00e3o livres de encargos sociais e trabalhistas. Aquelas que t\u00eam lucro real podem deduzir at\u00e9 1% do Imposto de Renda devido.\u003C/p\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cbr /\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\r\n\u003Cblockquote\u003E\r\n\u003Cp class=\"text-center\"\u003EEm pouco mais de um ano, o Vale-Cultura j\u00e1 mobiliza mais de R$140 milh\u00f5es e beneficia cerca de 420 mil trabalhadores e trabalhadoras.\u003C/p\u003E\r\n\u003C/blockquote\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\r\n\u003Cdiv class=\"embed-responsive embed-responsive-16by9\"\u003E\u003Ciframe src=\"https://www.youtube.com/embed/KKmZh5T46g8?rel=0\" frameborder=\"0\" width=\"560\" height=\"315\"\u003E\u003C/iframe\u003E\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-12\"\u003E\r\n\u003Ch3\u003ECompromissos\u003C/h3\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003Cdiv class=\"row\"\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\u003Cimg class=\"img-responsive\" src=\"http://gestao.dialoga.gov.br/dialoga/dialoga-brasil/vale-cultura/imagens/vale-cultura3.jpg\" alt=\"\" /\u003E\u003C/div\u003E\r\n\u003Cdiv class=\"col-md-6 col-sm-6 vcenter\"\u003E\r\n\u003Cul class=\"list-unstyled\"\u003E\r\n\u003Cli class=\"bullet\"\u003E\u003Cstrong\u003EAmpliar a ades\u00e3o de empresas e trabalhadores\u003C/strong\u003E\u003C/li\u003E\r\n\u003Cli class=\"bullet\"\u003E\u003Cstrong\u003EAmpliar a rede de estabelecimentos que recebem o Vale-Cultura.\u003C/strong\u003E\u003C/li\u003E\r\n\u003C/ul\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E\r\n\u003C/div\u003E"} | |
705 | + }); | |
706 | + | |
707 | + | |
708 | + // Random topics / Programas aleatorios - 1 por tema | |
709 | + // path: /api/v1/dialoga_plugin/random_topics/103358 | |
710 | + // Like: http://hom.dialoga.gov.br/api/v1/dialoga_plugin/random_topics/103358 | |
711 | + // ?fields[]=id&fields[]=title&fields[]=slug&fields[]=abstract&fields[]=body&fields[]=categories&fields[]=setting&fields[]=ranking_position&fields[]=position&fields[]=children_count&fields[]=hits&fields[]=votes_for&fields[]=votes_against&fields[]=tag_list | |
712 | + data.dialoga_plugin = { | |
713 | + "articles": [ | |
714 | + { | |
715 | + "ranking_position": null, | |
716 | + "id": 116089, | |
717 | + "body": "<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h2>Cultura e Educação<small>Cultura e arte como base para a educação integral.</small></h2>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem1.jpg\" alt=\"\" /></div>\r\n</div>\r\n<br />\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>A aproximação entre cultura e educação é estratégica para o desenvolvimento cultural do país e para a qualificação da educação brasileira.</p>\r\n<p> </p>\r\n<h3>Mais Cultura nas Escolas promove ensino com criatividade</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>É mais fácil aprender quando as abordagens pedagógicas são criativas e têm relação com a realidade cultural das crianças e jovens. Com o Mais Cultura nas Escolas, o ensino de crianças, adolescentes e jovens vincula-se às experiências culturais e artísticas das comunidades em que vivem.</p>\r\n<blockquote>\r\n<p class=\"text-center\">São priorizadas as escolas que têm maior número de estudantes beneficiários do Bolsa Família</p>\r\n</blockquote>\r\n<img class=\"img-responsive center-block\" style=\"width: 100%;\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem3.jpg\" alt=\"Imagem de Vídeo\" /></div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem2.jpg\" alt=\"Conexão Felipe Camarão\" /> <br /> <img class=\"img-responsive center-block\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem4.jpg\" alt=\"Programa mais cultura nas escolas\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>União dos saberes científicos e populares</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-4 col-sm-4\"><img class=\"img-responsive center-block\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem5.jpg\" alt=\"\" /></div>\r\n<div class=\"col-md-8 col-sm-8\">\r\n<p>O Programa Mais Cultura nas Universidades utiliza os <em>campi</em> e os institutos federais de ensino como centros irradiadores de produção artística e cultural para as comunidades. São realizadas ações de extensão, pesquisa e inovação em conjunto com grupos artísticos locais.</p>\r\n<p>Um total de 28 universidades e institutos federais foram apoiados diretamente pelo programa e outras 73 instituições federais já apresentaram planos de cultura.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Pronatec Cultura fomenta a economia e amplia a renda</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>O Pronatec Cultura oferece qualificação profissional que fortalece as cadeias produtivas da cultura, promovendo a formalização do setor, inclusão profissional e aumento da renda.</p>\r\n<p>Está presente em 228 municípios de 19 estados brasileiros, com 7.702 pessoas formadas até o primeiro semestre de 2015.</p>\r\n<blockquote>\r\n<p class=\"text-center\">São 65 cursos de formação como fotógrafo, vitrinista, iluminador cênico, sonoplasta, ilustrador e assistente de produção, ofertados pelos Institutos Federais, Sistema S e escolas profissionalizantes</p>\r\n</blockquote>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://hom.gestao.dialoga.gov.br/dialoga/dialoga-brasil/cultura-e-educacao/imagens/cultura-educacao-imagem6.jpg\" alt=\"\" /></div>\r\n</div>\r\n</div>", | |
718 | + "abstract": "<p>Cultura e arte como base para a educação integral</p>", | |
719 | + "title": "Cultura e Educação", | |
720 | + "categories": [ | |
721 | + { | |
722 | + "name": "Cultura", | |
723 | + "id": 194, | |
724 | + "slug": "cultura" | |
725 | + } | |
726 | + ], | |
727 | + "votes_for": 0, | |
728 | + "votes_against": 0, | |
729 | + "setting": { | |
730 | + "color": "", | |
731 | + "allow_members_to_edit": false, | |
732 | + "moderate_comments": false, | |
733 | + "comment_paragraph_plugin_activate": false, | |
734 | + "author_name": "Admin DEDES" | |
735 | + }, | |
736 | + "position": null, | |
737 | + "hits": 17, | |
738 | + "tag_list": [], | |
739 | + "children_count": 2, | |
740 | + "slug": "cultura-e-educacao" | |
741 | + }, { | |
742 | + "ranking_position": null, | |
743 | + "id": 103644, | |
744 | + "body": "<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h2>Ensino Superior<small>Um caminho de oportunidades com o Enem: Sisu, Prouni, Fies, Ciência sem Fronteiras</small></h2>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Enem - Exame Nacional do Ensino Médio</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>O Exame Nacional do Ensino Médio (Enem) abre portas para que todos os brasileiros trilhem, em igualdade de condições e de acordo com seus méritos como estudantes, um <strong>caminho de oportunidades</strong> por meio dos ensinos técnico e superior.</p>\r\n<br />\r\n<h4>Cada vez mais estudantes realizam o Enem</h4>\r\n<p>Na edição de 2014, o Enem teve quase <strong>9 milhões de inscritos e se consolidou como o maior exame deste tipo no Brasil e o segundo maior no mundo.</strong></p>\r\n<blockquote>\r\n<p class=\"text-center\">Com o Enem, várias possibilidades se abrem para o estudante, de acordo com o seu desempenho nos exames.</p>\r\n</blockquote>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/foto-1.jpg\" alt=\"\" width=\"375\" height=\"417\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/infografico-1.jpg\" alt=\"\" width=\"305\" height=\"269\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>SISU - Sistema de Seleção Unificada</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>Em outros tempos, o jovem que quisesse ingressar no ensino superior fazia inscrição no vestibular para um único curso de uma única universidade. Apenas estudantes com melhores condições financeiras podiam se inscrever em mais instituições e em diferentes locais do país.</p>\r\n<p>Hoje, com o SISU, a realidade é outra. O jovem, independentemente de sua condição social, usando a nota de um único exame – o Enem, feito em um único local e em uma mesma data, tem direito de disputar <strong>milhares de vagas, em vários cursos</strong> das melhores Instituições públicas e privadas de ensino superior, de todo o país.</p>\r\n<p>Durante o período de inscrição, o aluno pode acompanhar diariamente, pela internet, como está a procura pelos cursos do seu interesse, para alinhar suas escolhas e seus planos de estudo com a nota que obteve no Enem.</p>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/infografico-2.jpg\" alt=\"\" width=\"546\" height=\"293\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>PROUNI: Universidade para Todos</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/enem-imagem4.jpg\" alt=\"\" /></div>\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>O Programa Universidade para Todos (Prouni) foi criado em 2004 para ampliar e democratizar o acesso de estudantes de baixa renda ao ensino superior no Brasil.</p>\r\n<p>O Prouni concede bolsas integrais e parciais de 50% em instituições privadas de ensino superior para estudantes que ainda não têm um diploma de nível superior. O programa já totaliza mais de 1,69 milhão de bolsas concedidas, desde a sua criação, em 2004.</p>\r\n<p>Para concorrer a uma das bolsas, o aluno tem que ter no mínimo 450 pontos no Enem, não ter tirado zero na redação, ter cursado todo o ensino médio em escola pública ou como bolsista integral em escola particular. A renda bruta da família também é considerada no acesso às bolsas: deve ser menor que 1 ½ salário mínimo por pessoa para bolsa integral e menor que 3 salários mínimos por pessoa para bolsa de 50%.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>FIES: Fundo de Financiamento Estudantil para acesso ao ensino superior</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens//infografico-3.jpg\" alt=\"\" width=\"281\" height=\"234\" /></div>\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>Com quase 2 milhões de contratos firmados e 1.770 instituições participantes, o Fies se tornou um importante instrumento para quem pretende ingressar em uma instituição privada de ensino superior.</p>\r\n<p>As adequações pelas quais o Fies está passando garantem a sua sustentabilidade, asseguram a qualidade dos cursos financiados e beneficiam diretamente o estudante que realmente precisa do financiamento. Nenhum estudante que participa do Fies deixará de receber o benefício e o governo vai zelar pelo bom funcionamento do programa.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>SISUTEC: mais opções para crescer</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>Criado em 2013, o Sistema de Seleção Unificada da Educação Profissional e Tecnológica é mais uma opção para o estudante que faz o Enem. O Sisutec faz parte do Programa Nacional de Acesso ao Ensino Técnico e Emprego (Pronatec) e oferece vagas gratuitas em cursos técnicos.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Ciência sem Fronteiras:<br />conhecimento avançado no exterior</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p>O Ciência sem Fronteiras proporciona aos estudantes brasileiros de graduação e de pós-graduação oportunidades de intercâmbio internacional, para estudar e pesquisar nas melhores universidades do mundo.</p>\r\n<p>Podem participar alunos de instituições públicas ou particulares de todo o país em áreas essenciais para o desenvolvimento científico e tecnológico.</p>\r\n<p>Na primeira fase do programa, mais de 100 mil estudantes se beneficiaram dessa importante oportunidade. Em breve novos editais serão publicados, com a abertura de novas vagas.</p>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/infografico-4.jpg\" alt=\"\" width=\"226\" height=\"191\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Lei das Cotas</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>Todas as universidades públicas federais e os institutos federais de tecnologia reservam uma parte das suas vagas para alunos que estudaram em escolas públicas. Desde 2012, as cotas estão sendo implantadas gradualmente, até atingir, em 2016, a metade das vagas existentes.</p>\r\n<p>Das vagas reservadas para egressos de escolas públicas, metade é destinada a estudantes de famílias com renda mensal de até um salario mínimo e meio.</p>\r\n<p>O preenchimento destas vagas também leva em conta critérios de cor ou raça de acordo com as estatísticas do IBGE para cada estado.</p>\r\n<p>Após dois anos da implantação de Lei das Cotas (Lei nº 12.711, de 29 de agosto de 2012), em 2014, todos os institutos federais atenderam ao percentual mínimo de 25%, previsto para aquele ano; 85% atingiram a meta de 2015; 78% já atingiram a meta prevista para 2016 - 50% das vagas.</p>\r\n<p>No caso das Universidades Federais, todas atenderam, em 2014, ao percentual mínimo previsto de 25%; 64% atingiram antecipadamente a meta de 2015; 56% atingiram, com antecedência, a meta prevista para 2016.</p>\r\n<p>Em 2014, nos institutos federais, 23% das vagas foram reservadas para pretos, pardos e indígenas e, nas Universidades Federais, foram 20%.</p>\r\n</div>\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/ensino-superior/imagens/infografico-5.jpg\" alt=\"\" width=\"749\" height=\"223\" /></div>\r\n</div>\r\n</div>", | |
745 | + "abstract": "<p>Um caminho de oportunidades com o Enem: Sisu, Prouni, Fies, Ciência sem Fronteiras</p>", | |
746 | + "title": "Ensino Superior", | |
747 | + "categories": [ | |
748 | + { | |
749 | + "name": "Educação", | |
750 | + "id": 181, | |
751 | + "slug": "educacao" | |
752 | + } | |
753 | + ], | |
754 | + "votes_for": 0, | |
755 | + "votes_against": 0, | |
756 | + "setting": { | |
757 | + "color": "#cfe2f3", | |
758 | + "moderate_comments": false, | |
759 | + "comment_paragraph_plugin_activate": false, | |
760 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
761 | + "allow_members_to_edit": false | |
762 | + }, | |
763 | + "position": 9, | |
764 | + "hits": 54, | |
765 | + "tag_list": [], | |
766 | + "children_count": 7, | |
767 | + "slug": "ensino-superior" | |
768 | + }, { | |
769 | + "ranking_position": null, | |
770 | + "id": 103442, | |
771 | + "body": "<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h2>Bolsa Família <small>Complemento à renda e acompanhamento em educação e saúde.</small></h2>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem1.png\" alt=\"\" width=\"748\" height=\"280\" /></div>\r\n<div class=\"col-md-12\"><br />\r\n<p>O Bolsa Família é um programa que complementa mensalmente a renda de 14 milhões de famílias pobres, garante que crianças e adolescentes permaneçam na escola e acompanha a saúde de crianças, de mulheres grávidas e daquelas que estão amamentando.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<h3>Educação no Bolsa Família</h3>\r\n<p>Na educação, o Bolsa Família faz o acompanhamento mensal da frequência escolar de 17 milhões de crianças e adolescentes de famílias de baixa renda. Também ajuda a identificar dificuldades de acesso e de permanência dos estudantes na escola.</p>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem2.jpg\" alt=\"\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem3.png\" alt=\"\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem4.png\" alt=\"\" /></div>\r\n<div class=\"col-md-6 col-sm-6\">\r\n<h3>Saúde no Bolsa Família</h3>\r\n<p>Na saúde, o Programa monitora a vacinação, o peso e a altura das crianças com menos de 7 anos. Também faz o acompanhamento do pré-natal das gestantes e orienta as mulheres em fase de amamentação.</p>\r\n<p>Mais de 9 milhões de famílias são atendidas na área da saúde pelo Bolsa Família e os efeitos do acompanhamento são percebidos na vida das pessoas, na comprovada redução da mortalidade infantil e no crescimento saudável das crianças.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\">\r\n<h3>Redução de quase 1 cm do déficit de altura das crianças de 5 anos do Bolsa Família</h3>\r\n<img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem5.jpg\" alt=\"\" /></div>\r\n<div class=\"col-md-6 col-sm-6\"> </div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12 col-sm-12\">\r\n<h3>As crianças estão mais saudáveis e altas</h3>\r\n<p>Com a redução da desnutrição crônica, o déficit de estatura entre as crianças do Bolsa Família diminui 51%, o equivalente a quase 1 centímetro. A queda foi verificada em pesquisa que acompanhou 360 mil crianças beneficiadas ao longo de cinco anos seguidos, em que foram medidas e pesadas.</p>\r\n<p> </p>\r\n<h3>Cadastro Único para acessar políticas públicas</h3>\r\n</div>\r\n<div class=\"col-md-12 col-sm-12\">\r\n<p>Para participar do Programa, a família faz um cadastro com informações sobre moradia, renda, escolaridade e condições de vida. Este é o Cadastro Único para Programas Sociais do Governo Federal, um mapa social que permite aos governos planejarem suas ações, a partir da identificação das necessidades básicas das famílias.</p>\r\n<p>A orientação e o encaminhamento das famílias são feitos pela rede de assistência social para que os beneficiários do Bolsa Família acessem também outros programas como o <strong>Pronatec, o </strong><strong>Luz para Todos e o</strong><strong> Minha Casa</strong>, <strong>Minha Vida</strong>.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12 col-sm-12\">\r\n<h3>Quem recebe o Bolsa Família</h3>\r\n</div>\r\n<div class=\"col-md-12 col-sm-12\">\r\n<p>Podem participar as famílias registradas no Cadastro Único, desde que:</p>\r\n<ul class=\"list-styled\">\r\n<li>Com renda mensal, por pessoa, de até R$ 77, mesmo que não tenham gestantes, crianças ou adolescentes;</li>\r\n<li>Com renda mensal, por pessoa, de até R$ 154, que tenham gestantes, crianças ou adolescentes na família.</li>\r\n</ul>\r\n<p>O valor repassado depende do <strong>tamanho da família</strong>, da <strong>idade dos seus membros</strong> e da sua <strong>renda</strong>. Há benefícios específicos para famílias com crianças, jovens até 17 anos, gestantes e mães que amamentam.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12 col-sm-12\">\r\n<h3>Você sabia?</h3>\r\n</div>\r\n<div class=\"col-md-12 col-sm-12\">\r\n<ul class=\"list-styled \">\r\n<li><strong>O valor médio pago aos beneficiários do Bolsa Família é de R$ 168,00 mensais.</strong></li>\r\n<li><strong>As famílias que participam do Programa têm, em média, 2 filhos.</strong></li>\r\n</ul>\r\n</div>\r\n<div class=\"col-md-12 col-sm-12\">\r\n<blockquote class=\"text-center\">\r\n<p>Em 11 anos, 3,1 milhões de famílias saíram voluntariamente do programa Bolsa Família.</p>\r\n</blockquote>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-clock\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem7.jpg\" alt=\"\" /></div>\r\n<div class=\"col-md-6 col-sm-6\">\r\n<h3>Trabalho no Bolsa Família</h3>\r\n<p>Os beneficiários do Bolsa Família trabalham e trabalham muito.</p>\r\n<p>A participação dos adultos beneficiários no mercado de trabalho formal e informal é igual à dos demais brasileiros.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12 col-sm-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem8.jpg\" alt=\"\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Controle e transparência</h3>\r\n<p>O governo está atento para que o benefício só chegue a quem realmente precisa. Há um trabalho contínuo e rigoroso para garantir o controle e a transparência do Programa Bolsa Família e o registro de irregularidades é muito baixo.</p>\r\n<ul class=\"list-styled \">\r\n<li>A lista dos beneficiários com o valor do benefício que recebem é mantida pública, no Portal da Transparência;</li>\r\n<li>Todos os beneficiários têm que atualizar o seu cadastro a cada dois anos;</li>\r\n<li>O governo realiza cruzamentos do Cadastro Único com outras bases de dados, rotineiramente.</li>\r\n</ul>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Acompanhe</h3>\r\n<p>Todo cidadão tem o direito de saber como o governo utiliza os recursos públicos. Para o Bolsa Família, existe um canal direto e gratuito para que qualquer pessoa possa obter informações ou fazer sugestões, reclamações e denúncias: <strong>0800 707 2003</strong>.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>A renda do Bolsa Família fortalece a economia local e o desenvolvimento do País</h3>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\">\r\n<p><strong>Com o Bolsa Família</strong> todos ganham. O programa beneficia diretamente mais de 50 milhões de pessoas pobres, mas seus resultados vão além do combate à pobreza.</p>\r\n<p>O dinheiro repassado para as famílias beneficiadas fica no município, circula na economia local e gera mais trabalho e renda para outras pessoas, contribuindo para o desenvolvimento do País.</p>\r\n</div>\r\n<div class=\"col-md-6 col-sm-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/bolsa-familia/imagens/educacao-bolsa-familia-imagem10.jpg\" alt=\"\" /></div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>O Bolsa Família faz tanto pelo Brasil que todos os brasileiros acabam sendo beneficiados por ele, direta ou indiretamente, com a movimentação da economia e com a inclusão social..</p>\r\n</div>\r\n</div>\r\n</div>", | |
772 | + "abstract": "<p>Complemento à renda e acompanhamento em educação e saúde.</p>", | |
773 | + "title": "Bolsa Família", | |
774 | + "categories": [ | |
775 | + { | |
776 | + "name": "Redução da Pobreza", | |
777 | + "id": 183, | |
778 | + "slug": "reducao-da-pobreza" | |
779 | + } | |
780 | + ], | |
781 | + "votes_for": 0, | |
782 | + "votes_against": 0, | |
783 | + "setting": { | |
784 | + "color": "#ff9900", | |
785 | + "moderate_comments": false, | |
786 | + "comment_paragraph_plugin_activate": false, | |
787 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
788 | + "allow_members_to_edit": false | |
789 | + }, | |
790 | + "position": 17, | |
791 | + "hits": 68, | |
792 | + "tag_list": [], | |
793 | + "children_count": 9, | |
794 | + "slug": "bolsa-familia" | |
795 | + }, { | |
796 | + "ranking_position": null, | |
797 | + "id": 103379, | |
798 | + "body": "<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h2>SAMU 192 e UPAs <small>Resgate e atendimento 24 horas, sete dias por semana.</small></h2>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p class=\"text-center\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/urgencia-e-emergencia/imagens/img-destaque-1.jpg\" alt=\"Ambulancha e SAMU 192\" /></p>\r\n<p>O SAMU 192 foi criado em 2003 e chega a 75% da população brasileira, garantindo socorro e transporte de emergência. São 3.300 ambulâncias (vans, motos, lanchas e helicópteros).</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>SAMU 192 já chega a 153,9 milhões de pessoas</h3>\r\n<p class=\"text-center\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/samu-192-e-upas/imagens/grafico-1.jpg\" alt=\"Em 2005 o SAMU chegou à 60 milhões de pessoas. Em 2015 o SAMU chegou à 153,9 milhões de pessoas.\" width=\"725\" height=\"138\" /></p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>UPA - Unidades de Pronto Atendimento</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/urgencia-e-emergencia/imagens/img-destaque-2.jpg\" alt=\"UPA 24h\" width=\"374\" height=\"346\" /></div>\r\n<div class=\"col-md-6\">\r\n<p>As Unidades de Pronto Atendimento podem resolver 90% das urgências e emergências de atendimento à saúde, como fraturas, problemas de pressão, derrames e infartos.</p>\r\n<p>As UPAs fazem parte de uma rede de atendimento, complementando as emergências dos hospitais e a internação domiciliar. Assim, as UPAs ajudam a diminuir a demanda sobre os pronto-socorros dos hospitais, que devem receber e atender rapidamente os casos mais graves e que exigem imediata internação.</p>\r\n<blockquote>\r\n<p class=\"text-center\">Há 400 UPAs em funcionamento no Brasil.</p>\r\n</blockquote>\r\n<p>Os serviços de atendimento para urgências e emergências estão sendo integrados e ampliados.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h3>Compromissos</h3>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-6\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/samu-192-e-upas/imagens/grafico-2.jpg\" alt=\"Imagem da rede de atenção as urgências e emergências. Posto de saúde, SAMU, UPA 24h, UBS e Hospital\" width=\"536\" height=\"402\" /></div>\r\n<div class=\"col-md-6\">\r\n<ul class=\"list-unstyled\">\r\n<li>Levar o atendimento do SAMU 192 para toda a população brasileira.</li>\r\n<li>Garantir a expansão das Unidades de Pronto Atendimento (UPAs) em todas as regiões do país.</li>\r\n<li>Garantir à população o atendimento em hospitais de referência para situações de urgência (cirurgias, internações e UTIs).</li>\r\n</ul>\r\n</div>\r\n</div>\r\n</div>", | |
799 | + "abstract": "<p>Resgate e atendimento 24 horas, sete dias da semana.</p>", | |
800 | + "title": "SAMU 192 e UPAs", | |
801 | + "categories": [ | |
802 | + { | |
803 | + "name": "Saúde", | |
804 | + "id": 180, | |
805 | + "slug": "saude" | |
806 | + } | |
807 | + ], | |
808 | + "votes_for": 0, | |
809 | + "votes_against": 0, | |
810 | + "setting": { | |
811 | + "color": "#45818e", | |
812 | + "moderate_comments": false, | |
813 | + "comment_paragraph_plugin_activate": false, | |
814 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
815 | + "allow_members_to_edit": false | |
816 | + }, | |
817 | + "position": 4, | |
818 | + "hits": 72, | |
819 | + "tag_list": [], | |
820 | + "children_count": 13, | |
821 | + "slug": "samu-192-e-upas" | |
822 | + }, { | |
823 | + "ranking_position": null, | |
824 | + "id": 103390, | |
825 | + "body": "<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<h2>Crack, é possível vencer!<small>Prevenção, tratamento e enfrentamento ao tráfico.</small></h2>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12\"><img class=\"img-responsive center-block\" src=\"http://dialoga.gov.br/dialoga/dialoga-brasil/crack-e-possivel-vencer/imagens/crack-img-1.jpg\" alt=\"\" /></div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12\">\r\n<p>O problema das drogas é um desafio ao mesmo tempo urgente e complexo. Requer medidas preventivas, de combate ao tráfico e, principalmente, oferta de serviços de saúde e assistência social.</p>\r\n<p>O programa “Crack, é possível vencer” envolve ações em três eixos: cuidado, autoridade e prevenção.</p>\r\n<p>O “<strong>cuidado</strong>” abrange a ampliação e a melhoria do atendimento para pessoas com problemas causados pelas drogas e para suas famílias, nas áreas de saúde e assistência social.</p>\r\n<p>No eixo “<strong>autoridade</strong>”, o foco é a integração de inteligência e cooperação entre forças policiais federais e estaduais. Envolve policiamento ostensivo nos pontos de uso e venda de drogas e a revitalização desses espaços, melhorando-os para toda a comunidade.</p>\r\n<p>Na área de “<strong>prevenção</strong>” são realizadas ações especiais em escolas e nas comunidades, assim como iniciativas de comunicação e informação para a população em geral.</p>\r\n<p><strong>Muitos resultados</strong> positivos <strong>foram</strong> alcançados <strong>de 2011 a 2014</strong>.</p>\r\n</div>\r\n</div>\r\n</div>\r\n<div class=\"container\">\r\n<div class=\"row\">\r\n<div class=\"col-md-12 list-container-border\">\r\n<h4>CUIDADO - Saúde e assistência</h4>\r\n<ul class=\"list-unstyled no-border\">\r\n<li>2.200 Centros de Atenção Psicossocial (CAPS)</li>\r\n<li>360 CAPS Álcool e Drogas</li>\r\n<li>60 Unidades de Acolhimento</li>\r\n<li>8.034 vagas em comunidades terapêuticas</li>\r\n</ul>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12 list-container-border\">\r\n<h4>AUTORIDADE - Combate ao tráfico</h4>\r\n<ul class=\"list-unstyled no-border\">\r\n<li>Intensificação das operações</li>\r\n<li>7.700 profissionais de segurança pública capacitados</li>\r\n<li>Instalação de 26 grupos de investigações sensíveis da Polícia Federal</li>\r\n</ul>\r\n</div>\r\n</div>\r\n<div class=\"row\">\r\n<div class=\"col-md-12 list-container-border\">\r\n<h4>PREVENÇÃO</h4>\r\n<ul class=\"list-unstyled no-border\">\r\n<li>367 mil funcionários capacitados na temática de drogas em todo o País</li>\r\n<li>4 mil ligações-dia e 230 mil atendimentos efetivos no ligue 132, serviço gratuito de atendimento telefônico para informações sobre drogas</li>\r\n</ul>\r\n</div>\r\n</div>\r\n</div>", | |
826 | + "abstract": "<p>Prevenção, tratamento e enfrentamento ao tráfico.</p>", | |
827 | + "title": "Crack, é possível vencer!", | |
828 | + "categories": [ | |
829 | + { | |
830 | + "name": "Segurança Pública", | |
831 | + "id": 182, | |
832 | + "slug": "seguranca-publica" | |
833 | + } | |
834 | + ], | |
835 | + "votes_for": 0, | |
836 | + "votes_against": 0, | |
837 | + "setting": { | |
838 | + "color": "#00ff00", | |
839 | + "moderate_comments": false, | |
840 | + "comment_paragraph_plugin_activate": false, | |
841 | + "author_name": "Ronald Emerson Scherolt da Costa", | |
842 | + "allow_members_to_edit": false | |
843 | + }, | |
844 | + "position": 14, | |
845 | + "hits": 44, | |
846 | + "tag_list": [], | |
847 | + "children_count": 7, | |
848 | + "slug": "crack-e-possivel-vencer" | |
849 | + } | |
850 | + ]}; | |
851 | + return data; | |
852 | +}; | ... | ... |
e2e/.jshintrc
e2e/main.po.js
... | ... | @@ -1,15 +0,0 @@ |
1 | -/** | |
2 | - * This file uses the Page Object pattern to define the main page for tests | |
3 | - * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ | |
4 | - */ | |
5 | - | |
6 | -'use strict'; | |
7 | - | |
8 | -var MainPage = function() { | |
9 | - this.jumbEl = element(by.css('.jumbotron')); | |
10 | - this.h1El = this.jumbEl.element(by.css('h1')); | |
11 | - this.imgEl = this.jumbEl.element(by.css('img')); | |
12 | - this.thumbnailEls = element(by.css('body')).all(by.repeater('awesomeThing in main.awesomeThings')); | |
13 | -}; | |
14 | - | |
15 | -module.exports = new MainPage(); |
e2e/main.spec.js
... | ... | @@ -1,21 +0,0 @@ |
1 | -'use strict'; | |
2 | - | |
3 | -describe('The main view', function () { | |
4 | - var page; | |
5 | - | |
6 | - beforeEach(function () { | |
7 | - browser.get('/index.html'); | |
8 | - page = require('./main.po'); | |
9 | - }); | |
10 | - | |
11 | - it('should include jumbotron with correct data', function() { | |
12 | - expect(page.h1El.getText()).toBe('\'Allo, \'Allo!'); | |
13 | - expect(page.imgEl.getAttribute('src')).toMatch(/assets\/images\/yeoman.png$/); | |
14 | - expect(page.imgEl.getAttribute('alt')).toBe('I\'m Yeoman'); | |
15 | - }); | |
16 | - | |
17 | - it('should list more than 5 awesome things', function () { | |
18 | - expect(page.thumbnailEls.count()).toBeGreaterThan(5); | |
19 | - }); | |
20 | - | |
21 | -}); |
... | ... | @@ -0,0 +1,16 @@ |
1 | +(function(){ | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('The index page', function () { | |
5 | + var page = browser.get('/'); | |
6 | + | |
7 | + // beforeEach(function () { | |
8 | + // browser.get('/'); | |
9 | + // }); | |
10 | + | |
11 | + describe('Common layout', function (){ | |
12 | + require('./layout.js')(); | |
13 | + }); | |
14 | + | |
15 | + }); | |
16 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,124 @@ |
1 | +/* global require */ | |
2 | +(function(){ | |
3 | + 'use strict'; | |
4 | + | |
5 | + describe('The index page', function () { | |
6 | + var page = require('./inicio.po.js'); | |
7 | + // beforeEach(function () { | |
8 | + // browser.get('/'); | |
9 | + // }); | |
10 | + | |
11 | + describe('Common layout', function (){ | |
12 | + require('./layout.js')(); | |
13 | + }); | |
14 | + | |
15 | + describe('Component: Main Video', function(){ | |
16 | + it('should have a thumb background image (for async)', function() { | |
17 | + expect(page.video.element(by.css('.video-thumbnail'))).toBeDefined(); | |
18 | + expect(page.video.element(by.css('.video-thumbnail')).getCssValue('background-image')).toContain('youtube-background.png'); | |
19 | + expect(page.video.element(by.css('.video-thumbnail')).getAttribute('aria-hidden')).toBe('true'); | |
20 | + }); | |
21 | + | |
22 | + it('should have a button play trigger', function() { | |
23 | + expect(page.video.element(by.css('.video-play-button'))).toBeDefined(); | |
24 | + expect(page.video.element(by.css('.video-play-button')).getAttribute('aria-label')).toBeDefined(); | |
25 | + }); | |
26 | + }); | |
27 | + | |
28 | + describe('Component: Agenda', function(){ | |
29 | + it('should have a tab-trigger', function() { | |
30 | + expect(page.agenda.element(by.css('.event-tab--trigger'))).toBeDefined(); | |
31 | + expect(page.agenda.element(by.css('.event-tab--title'))).toBeDefined(); | |
32 | + expect(page.agenda.element(by.css('.event-tab--icon'))).toBeDefined(); | |
33 | + expect(page.agenda.element(by.css('.event-tab--icon')).element(by.css('.glyphicon'))).toBeDefined(); | |
34 | + expect(page.agenda.element(by.css('.event-tab--icon')).element(by.css('.glyphicon')).getAttribute('aria-hidden')).toBe('true'); | |
35 | + expect(page.agenda.element(by.css('.event-tab--button'))).toBeDefined(); | |
36 | + expect(page.agenda.element(by.css('.event-tab--total-scheduled'))).toBeDefined(); | |
37 | + expect(page.agenda.element(by.css('.event-tab--total-scheduled'))).toMatch(/(\d)*/); | |
38 | + }); | |
39 | + | |
40 | + describe('Component: Agenda / Open-panel', function(){ | |
41 | + it('should have a header', function() { | |
42 | + // the 2 lines below need to open panel and make elements visibles | |
43 | + expect(page.agenda.element(by.model('eventListCtrl.isListVisible'))).toBeDefined(); | |
44 | + page.agenda.element(by.css('.event-tab--trigger')).click(); | |
45 | + | |
46 | + expect(page.agenda.element(by.css('.event-list--title'))).toBeDefined(); | |
47 | + expect(page.agenda.element(by.css('.event-list--title')).getText()).toEqual('Bate-papo com ministr@s'); | |
48 | + expect(page.agenda.element(by.css('.event-list--icon'))).toBeDefined(); | |
49 | + expect(page.agenda.element(by.css('.event-list--icon')).element(by.css('.glyphicon'))).toBeDefined(); | |
50 | + expect(page.agenda.element(by.css('.event-list--icon')).element(by.css('.glyphicon')).getAttribute('aria-hidden')).toBe('true'); | |
51 | + expect(page.agenda.element(by.css('.event-list--minimize'))).toBeDefined(); | |
52 | + expect(page.agenda.element(by.css('.event-list--minimize')).element(by.css('.glyphicon'))).toBeDefined(); | |
53 | + expect(page.agenda.element(by.css('.event-list--minimize')).element(by.css('.glyphicon')).getAttribute('aria-hidden')).toBe('true'); | |
54 | + }); | |
55 | + | |
56 | + it('should have a table with content', function() { | |
57 | + // date/time | |
58 | + expect(page.agenda.element(by.css('.event-list--minimize')).element(by.css('.glyphicon')).getAttribute('aria-hidden')).toBe('true'); | |
59 | + // title | |
60 | + // subscribe button | |
61 | + // total of subscribers | |
62 | + // show only 5 itens | |
63 | + }); | |
64 | + // it('should have the title of scheduled chat', function() {}); | |
65 | + // it('should have a subscribe button to scheduled chat', function() {}); | |
66 | + // it('should show the number of subscribers on each item', function() {}); | |
67 | + // it('should show 5 itens at most', function() {}); | |
68 | + // it('should be accessible', function() {}); | |
69 | + }); | |
70 | + | |
71 | + describe('Component: Agenda / with Hangout', function(){ | |
72 | + it('should have a title', function() {}); | |
73 | + it('should have a thumb background image (for async)', function() {}); | |
74 | + it('should have a button trigger to start the video', function() {}); | |
75 | + it('should have a description', function() { | |
76 | + // PATTERN: %DATETIME - %TITLE, %CATEGORY, ? | |
77 | + // Get it from the endpoint or assembly-it ? | |
78 | + }); | |
79 | + it('should have a open trigger', function() { | |
80 | + // with: | |
81 | + // - total of scheduled events | |
82 | + // - icon: arrow down | |
83 | + }); | |
84 | + }); | |
85 | + }); | |
86 | + | |
87 | + describe('Component: Category List', function(){ | |
88 | + it('should have a title', function() {}); | |
89 | + it('should have list of category', function() {}); | |
90 | + it('should have the icon of each category', function() {}); | |
91 | + it('should have the name of each category', function() {}); | |
92 | + it('should be accessible', function() {}); | |
93 | + // what expect on hover or focus? Material Desgn likes? | |
94 | + // | |
95 | + }); | |
96 | + | |
97 | + describe('Component: Article List | Box (each) ', function(){ | |
98 | + it('should have a category label', function() {}); | |
99 | + it('should have a banner image', function() {}); | |
100 | + it('should have a alternatve text for the banner image', function() {}); | |
101 | + it('should have a title', function() {}); | |
102 | + it('should have 50 letters at most on title', function() {}); | |
103 | + it('should have a abstract', function() {}); | |
104 | + it('should have 200 letters at most on abstract', function() {}); | |
105 | + it('should have the number of sent proposals', function() {}); | |
106 | + it('should have a call-to-action button', function() {}); | |
107 | + it('should have the same color of the category-color at call-to-action button', function() {}); | |
108 | + it('should be accessible', function() {}); | |
109 | + // what colors on what? | |
110 | + // what are links/clickable/focusable | |
111 | + }); | |
112 | + | |
113 | + describe('Component: Search ', function(){ | |
114 | + it('should have a hidden label', function() {}); | |
115 | + it('should have a html5 search input', function() {}); | |
116 | + it('should have be focusable by a11y link', function() {}); | |
117 | + it('should have a more filters?', function() {}); | |
118 | + it('should be accessible', function() {}); | |
119 | + // what behaviours? | |
120 | + // more filters? ordering by alphabet: name, category, random. | |
121 | + // show results at another page | |
122 | + }); | |
123 | + }); | |
124 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,80 @@ |
1 | +module.exports = function(){ | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('The common layout', function () { | |
5 | + | |
6 | + var page = require('./layout.po.js'); | |
7 | + | |
8 | + describe('Accessibility (a11y) top bar', function(){ | |
9 | + it('should have a "skip-to-content" anchor', function() { | |
10 | + expect(page.skipToContent.getText()).toEqual('Ir para o conteúdo 1'); | |
11 | + }); | |
12 | + it('should have a "skip-to-navigation" anchor', function() { | |
13 | + expect(page.skipToNavigation.getText()).toEqual('Ir para o menu 2'); | |
14 | + }); | |
15 | + it('should have a "skip-to-search" anchor', function() { | |
16 | + expect(page.skipToSearch.getText()).toEqual('Ir para a busca 3'); | |
17 | + }); | |
18 | + it('should have a "skip-to-footer" anchor', function() { | |
19 | + expect(page.skipToFooter.getText()).toEqual('Ir para o rodapé 4'); | |
20 | + }); | |
21 | + | |
22 | + it('should have a accessibility anchor', function() { | |
23 | + expect(page.actionAccessibility.getText()).toEqual('Acessibilidade'); | |
24 | + }); | |
25 | + it('should have a adjust contrast anchor', function() { | |
26 | + expect(page.actionContrast.getText()).toEqual('Alto Contraste'); | |
27 | + }); | |
28 | + it('should have a sitemap anchor', function() { | |
29 | + expect(page.actionSitemap.getText()).toEqual('Mapa do Site'); | |
30 | + }); | |
31 | + }); | |
32 | + | |
33 | + describe('Header', function(){ | |
34 | + it('should have a logo', function() {}); | |
35 | + it('should have a navigation', function() {}); | |
36 | + it('should have a social share area', function() {}); | |
37 | + it('should have a "CADASTRAR" anchor', function() {}); | |
38 | + it('should have a "ENTRAR" anchor', function() {}); | |
39 | + it('should have a "Veja mais" area', function() {}); | |
40 | + it('should have a valid ARIA', function() {}); | |
41 | + | |
42 | + describe('Header / Navigation', function(){ | |
43 | + it('should have a "SOBRE" anchor', function() {}); | |
44 | + it('should have a "PROGRAMAS" anchor', function() {}); | |
45 | + it('should have a "PROPOSTAS" anchor', function() {}); | |
46 | + it('should have a "DÚVIDAS" anchor', function() {}); | |
47 | + it('should be condensed on mobile', function() {}); | |
48 | + it('should have a valid ARIA', function() {}); | |
49 | + // it('should have a "ENTRAR?" anchor on MOBILE?', function() {}); | |
50 | + // it('should have a "RANKING?" anchor on MOBILE?', function() {}); | |
51 | + // it('should have a "RESPOSTAS?" anchor on MOBILE?', function() {}); | |
52 | + // it('should have a "PARTICIPE?" anchor on MOBILE?', function() {}); | |
53 | + }); | |
54 | + | |
55 | + describe('Header / Social Share', function(){ | |
56 | + it('should have a facebook share button', function() {}); | |
57 | + it('should have a twitter share button', function() {}); | |
58 | + it('should have a gplus share button', function() {}); | |
59 | + it('should have a whatsapp share button', function() {}); | |
60 | + it('should be condensed on mobile', function() {}); | |
61 | + it('should have a email share button', function() {}); | |
62 | + it('should have a valid ARIA', function() {}); | |
63 | + // what to do when on mobile? | |
64 | + // too small on mobile? point issues | |
65 | + }); | |
66 | + | |
67 | + describe('Header / "Veja mais"', function(){ | |
68 | + it('should have a youtube link', function() {}); | |
69 | + // it('should have a flicker? link', function() {}); | |
70 | + it('should have a valid ARIA', function() {}); | |
71 | + // what to do when on mobile? | |
72 | + }); | |
73 | + }); | |
74 | + | |
75 | + describe('Footer', function(){ | |
76 | + it('should have a ?', function() {}); | |
77 | + it('should have a valid ARIA', function() {}); | |
78 | + }); | |
79 | + }); | |
80 | +}; | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +module.exports = (function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + var PageObject = function() { | |
5 | + this.skipToContent = element(by.id('skip-to-content')); | |
6 | + this.skipToNavigation = element(by.id('skip-to-navigation')); | |
7 | + this.skipToSearch = element(by.id('skip-to-search')); | |
8 | + this.skipToFooter = element(by.id('skip-to-footer')); | |
9 | + | |
10 | + this.actionAccessibility = element(by.id('siteaction-accessibility')); | |
11 | + this.actionContrast = element(by.id('siteaction-contrast')); | |
12 | + this.actionSitemap = element(by.id('siteaction-sitemap')); | |
13 | + }; | |
14 | + | |
15 | + return (new PageObject()); | |
16 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,55 @@ |
1 | +(function(){ | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('The "Programa" page', function () { | |
5 | + var page = browser.get('/'); | |
6 | + | |
7 | + // beforeEach(function () { | |
8 | + // browser.get('/'); | |
9 | + // }); | |
10 | + | |
11 | + describe('Common layout', function (){ | |
12 | + require('./layout.js')(); | |
13 | + }); | |
14 | + | |
15 | + describe('Component: article-preview', function (){}); | |
16 | + | |
17 | + describe('Component: article-content', function (){}); | |
18 | + | |
19 | + // describe('Component: article-template-1', function (){}); | |
20 | + | |
21 | + describe('Component: proposal-random', function (){ | |
22 | + it('should have a loading state', function() {}); | |
23 | + it('should have a breadcrumb', function() {}); | |
24 | + it('should have the text-content of proposal', function() {}); | |
25 | + it('should have a vote up button', function() {}); | |
26 | + it('should have a vote skip button', function() {}); | |
27 | + it('should have a vote down button', function() {}); | |
28 | + it('should have a social share area', function() {}); | |
29 | + it('should have the ranking position', function() {}); | |
30 | + it('should have a ranking button trigger', function() {}); | |
31 | + it('should be accessible', function() {}); | |
32 | + }); | |
33 | + | |
34 | + describe('Component: proposal-ranking', function (){ | |
35 | + it('should have a loading state', function() {}); | |
36 | + it('should have a close button trigger', function() {}); | |
37 | + it('should have the ranking position of proposal', function() {}); | |
38 | + it('should have the text-content of proposal', function() {}); | |
39 | + it('should have the number of views', function() {}); | |
40 | + it('should have the number of votes up', function() {}); | |
41 | + it('should have the number of votes down', function() {}); | |
42 | + it('should have a link to proposal', function() {}); | |
43 | + it('should have a link to all proposals', function() {}); | |
44 | + it('should be accessible', function() {}); | |
45 | + }); | |
46 | + | |
47 | + describe('Component: proposal-maker', function (){ | |
48 | + it('should be accessible', function() {}); | |
49 | + }); | |
50 | + | |
51 | + describe('Component: proposal-ranking', function (){ | |
52 | + it('should be accessible', function() {}); | |
53 | + }); | |
54 | + }); | |
55 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,29 @@ |
1 | +(function(){ | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('The "Sobre" page', function () { | |
5 | + var page = browser.get('/'); | |
6 | + | |
7 | + // beforeEach(function () { | |
8 | + // browser.get('/'); | |
9 | + // }); | |
10 | + | |
11 | + describe('Common layout', function (){ | |
12 | + require('./layout.js')(); | |
13 | + }); | |
14 | + | |
15 | + describe('Breadcrumb', function(){ | |
16 | + it('should have two itens', function() {}); | |
17 | + }); | |
18 | + | |
19 | + describe('Content', function(){ | |
20 | + it('should have a main video', function() {}); | |
21 | + it('should have a main video thumb image', function() {}); | |
22 | + it('should have a main video thumb image alternative text', function() {}); | |
23 | + | |
24 | + it('should have a "Programas" description', function() {}); | |
25 | + it('should have a "Propostas" tutorial', function() {}); | |
26 | + it('should be accessible', function() {}); | |
27 | + }); | |
28 | + }); | |
29 | +})(); | ... | ... |
gulp/build.js
... | ... | @@ -43,11 +43,19 @@ gulp.task('html', ['inject', 'partials'], function () { |
43 | 43 | .pipe(assets = $.useref.assets()) |
44 | 44 | .pipe($.rev()) |
45 | 45 | .pipe(jsFilter) |
46 | + // production | |
47 | + .pipe($.if($.util.env.production, $.replace('$logProvider.debugEnabled(true);', '$logProvider.debugEnabled(false);'))) | |
48 | + .pipe($.if($.util.env.production, $.replace('http://hom.dialoga.gov.br', 'http://login.dialoga.gov.br'))) | |
49 | + .pipe($.if($.util.env.production, $.replace('http://hom.login.dialoga.gov.br', 'http://login.dialoga.gov.br'))) | |
50 | + // staging | |
51 | + .pipe($.if($.util.env.staging, $.replace('http://dialoga.gov.br', 'http://hom.dialoga.gov.br'))) | |
52 | + .pipe($.if($.util.env.staging, $.replace('http://login.dialoga.gov.br', 'http://hom.login.dialoga.gov.br'))) | |
46 | 53 | .pipe($.ngAnnotate()) |
47 | 54 | .pipe($.uglify({ preserveComments: $.uglifySaveLicense })).on('error', conf.errorHandler('Uglify')) |
48 | 55 | .pipe(jsFilter.restore()) |
49 | 56 | .pipe(cssFilter) |
50 | 57 | .pipe($.replace('../../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/', '../fonts/')) |
58 | + .pipe($.replace('../../bower_components/open-sans-fontface/fonts/', '../fonts/')) | |
51 | 59 | .pipe($.csso()) |
52 | 60 | .pipe(cssFilter.restore()) |
53 | 61 | .pipe(assets.restore()) |
... | ... | @@ -67,13 +75,26 @@ gulp.task('html', ['inject', 'partials'], function () { |
67 | 75 | |
68 | 76 | // Only applies for fonts from bower dependencies |
69 | 77 | // Custom fonts are handled by the "other" task |
70 | -gulp.task('fonts', function () { | |
71 | - return gulp.src($.mainBowerFiles().concat('bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*')) | |
78 | +gulp.task('fonts', ['fonts-bootstrap', 'fonts-opensans']); | |
79 | + | |
80 | +gulp.task('fonts-bootstrap', function () { | |
81 | + return gulp.src([ | |
82 | + 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/**/*' | |
83 | + ]) | |
72 | 84 | .pipe($.filter('**/*.{eot,svg,ttf,woff,woff2}')) |
73 | 85 | .pipe($.flatten()) |
74 | 86 | .pipe(gulp.dest(path.join(conf.paths.dist, '/fonts/'))); |
75 | 87 | }); |
76 | 88 | |
89 | +gulp.task('fonts-opensans', function () { | |
90 | + return gulp.src([ | |
91 | + 'bower_components/open-sans-fontface/fonts/**/*' | |
92 | + ]) | |
93 | + .pipe($.filter('**/*.{eot,svg,ttf,woff,woff2}')) | |
94 | + // .pipe($.flatten()) | |
95 | + .pipe(gulp.dest(path.join(conf.paths.dist, '/styles/fonts/'))); | |
96 | +}); | |
97 | + | |
77 | 98 | gulp.task('other', function () { |
78 | 99 | var fileFilter = $.filter(function (file) { |
79 | 100 | return file.stat.isFile(); | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var gulpif = require('gulp-if'); | |
8 | +var sprity = require('sprity'); | |
9 | + | |
10 | +gulp.task('sprites', function () { | |
11 | + var src = [ | |
12 | + path.join(conf.paths.src, '/assets/images/icons/*.png'), | |
13 | + path.join('!' + conf.paths.src, '/assets/images/icons/sprite.png') | |
14 | + ]; | |
15 | + var destCss = path.join(conf.paths.tmp, '/serve/app/'); | |
16 | + var destImg = path.join(conf.paths.src, '/assets/images/icons'); | |
17 | + | |
18 | + return sprity.src({ | |
19 | + src: src, | |
20 | + style: 'sprite.css', | |
21 | + cssPath: '../assets/images/icons/', | |
22 | + cachebuster: true | |
23 | + }) | |
24 | + .pipe(gulpif('*.png', gulp.dest(destImg), gulp.dest(destCss))); | |
25 | +}); | ... | ... |
gulp/inject.js
... | ... | @@ -9,7 +9,7 @@ var $ = require('gulp-load-plugins')(); |
9 | 9 | var wiredep = require('wiredep').stream; |
10 | 10 | var _ = require('lodash'); |
11 | 11 | |
12 | -gulp.task('inject', ['scripts', 'styles'], function () { | |
12 | +gulp.task('inject', ['scripts', 'styles', 'sprites'], function () { | |
13 | 13 | var injectStyles = gulp.src([ |
14 | 14 | path.join(conf.paths.tmp, '/serve/app/**/*.css'), |
15 | 15 | path.join('!' + conf.paths.tmp, '/serve/app/vendor.css') | ... | ... |
gulp/scripts.js
... | ... | @@ -9,9 +9,9 @@ var browserSync = require('browser-sync'); |
9 | 9 | var $ = require('gulp-load-plugins')(); |
10 | 10 | |
11 | 11 | gulp.task('scripts', function () { |
12 | - return gulp.src(path.join(conf.paths.src, '/app/**/*.js')) | |
13 | - .pipe($.jshint()) | |
14 | - .pipe($.jshint.reporter('jshint-stylish')) | |
15 | - .pipe(browserSync.reload({ stream: true })) | |
16 | - .pipe($.size()) | |
12 | + return gulp.src(path.join(conf.paths.src, '/app/**/*.js')) | |
13 | + .pipe($.jshint()) | |
14 | + .pipe($.jshint.reporter('jshint-stylish')) | |
15 | + .pipe(browserSync.reload({ stream: true })) | |
16 | + .pipe($.size()); | |
17 | 17 | }); | ... | ... |
gulp/server.js
... | ... | @@ -8,6 +8,7 @@ var browserSync = require('browser-sync'); |
8 | 8 | var browserSyncSpa = require('browser-sync-spa'); |
9 | 9 | |
10 | 10 | var util = require('util'); |
11 | +var gutil = require('gulp-util'); | |
11 | 12 | |
12 | 13 | var proxyMiddleware = require('http-proxy-middleware'); |
13 | 14 | |
... | ... | @@ -15,7 +16,7 @@ function browserSyncInit(baseDir, browser) { |
15 | 16 | browser = browser === undefined ? 'default' : browser; |
16 | 17 | |
17 | 18 | var routes = null; |
18 | - if(baseDir === conf.paths.src || (util.isArray(baseDir) && baseDir.indexOf(conf.paths.src) !== -1)) { | |
19 | + if (baseDir === conf.paths.src || (util.isArray(baseDir) && baseDir.indexOf(conf.paths.src) !== -1)) { | |
19 | 20 | routes = { |
20 | 21 | '/bower_components': 'bower_components' |
21 | 22 | }; |
... | ... | @@ -33,12 +34,57 @@ function browserSyncInit(baseDir, browser) { |
33 | 34 | * |
34 | 35 | * For more details and option, https://github.com/chimurai/http-proxy-middleware/blob/v0.0.5/README.md |
35 | 36 | */ |
36 | - // server.middleware = proxyMiddleware('/users', {target: 'http://jsonplaceholder.typicode.com', proxyHost: 'jsonplaceholder.typicode.com'}); | |
37 | + if (gutil.env.local) { | |
38 | + // no target env. Point to localhost | |
39 | + server.middleware = proxyMiddleware('/api', { | |
40 | + target: 'http://0.0.0.0:9000/', | |
41 | + pathRewrite: { | |
42 | + // rewrite paths | |
43 | + '^/api/v1/articles': '/articles' | |
44 | + }, | |
45 | + proxyTable: { | |
46 | + // when request.headers.host == 'dev.localhost:3000', | |
47 | + // override target 'http://www.example.org' to 'http://localhost:8000' | |
48 | + // 'dev.localhost:3000' : 'http://localhost:8000' | |
49 | + 'hom.dialoga.gov.br': 'http://localhost:9000', | |
50 | + 'login.dialoga.gov.br': 'http://localhost:9000' | |
51 | + } | |
52 | + }); | |
53 | + } | |
54 | + | |
55 | + if (gutil.env.production) { | |
56 | + var host_production = 'http://login.dialoga.gov.br/'; | |
57 | + server.middleware = proxyMiddleware([ | |
58 | + '/api/**', | |
59 | + '/image_uploads/**' | |
60 | + ], { | |
61 | + target: host_production, | |
62 | + changeOrigin: true, | |
63 | + proxyTable: { | |
64 | + 'localhost:3000': host_production | |
65 | + } | |
66 | + }); | |
67 | + } | |
68 | + | |
69 | + if (gutil.env.staging) { | |
70 | + var host_staging = 'http://hom.login.dialoga.gov.br/'; | |
71 | + server.middleware = proxyMiddleware([ | |
72 | + '/api/**', | |
73 | + '/image_uploads/**' | |
74 | + ], { | |
75 | + target: host_staging, | |
76 | + changeOrigin: true, | |
77 | + proxyTable: { | |
78 | + 'localhost:3000': host_staging | |
79 | + } | |
80 | + }); | |
81 | + } | |
37 | 82 | |
38 | 83 | browserSync.instance = browserSync.init({ |
39 | 84 | startPath: '/', |
40 | 85 | server: server, |
41 | - browser: browser | |
86 | + browser: browser, | |
87 | + ghostMode: false | |
42 | 88 | }); |
43 | 89 | } |
44 | 90 | |
... | ... | @@ -46,18 +92,18 @@ browserSync.use(browserSyncSpa({ |
46 | 92 | selector: '[ng-app]'// Only needed for angular apps |
47 | 93 | })); |
48 | 94 | |
49 | -gulp.task('serve', ['watch'], function () { | |
95 | +gulp.task('serve', ['watch'], function() { | |
50 | 96 | browserSyncInit([path.join(conf.paths.tmp, '/serve'), conf.paths.src]); |
51 | 97 | }); |
52 | 98 | |
53 | -gulp.task('serve:dist', ['build'], function () { | |
99 | +gulp.task('serve:dist', ['build'], function() { | |
54 | 100 | browserSyncInit(conf.paths.dist); |
55 | 101 | }); |
56 | 102 | |
57 | -gulp.task('serve:e2e', ['inject'], function () { | |
103 | +gulp.task('serve:e2e', ['inject'], function() { | |
58 | 104 | browserSyncInit([conf.paths.tmp + '/serve', conf.paths.src], []); |
59 | 105 | }); |
60 | 106 | |
61 | -gulp.task('serve:e2e-dist', ['build'], function () { | |
107 | +gulp.task('serve:e2e-dist', ['build'], function() { | |
62 | 108 | browserSyncInit(conf.paths.dist, []); |
63 | 109 | }); | ... | ... |
gulp/styles.js
... | ... | @@ -39,7 +39,10 @@ gulp.task('styles', function () { |
39 | 39 | .pipe(wiredep(_.extend({}, conf.wiredep))) |
40 | 40 | .pipe($.sourcemaps.init()) |
41 | 41 | .pipe($.sass(sassOptions)).on('error', conf.errorHandler('Sass')) |
42 | - .pipe($.autoprefixer()).on('error', conf.errorHandler('Autoprefixer')) | |
42 | + .pipe($.autoprefixer({ | |
43 | + browsers: ['last 3 versions', 'ie >= 9', 'ff > 20', 'Chrome > 30', 'Opera > 25', 'Safari > 6', 'iOS > 6'], | |
44 | + cascade: false | |
45 | + })).on('error', conf.errorHandler('Autoprefixer')) | |
43 | 46 | .pipe($.sourcemaps.write()) |
44 | 47 | .pipe(gulp.dest(path.join(conf.paths.tmp, '/serve/app/'))) |
45 | 48 | .pipe(browserSync.reload({ stream: true })); | ... | ... |
gulp/unit-tests.js
gulp/watch.js
... | ... | @@ -25,6 +25,16 @@ gulp.task('watch', ['inject'], function () { |
25 | 25 | } |
26 | 26 | }); |
27 | 27 | |
28 | + gulp.watch([ | |
29 | + path.join(conf.paths.src, '/assets/images/icons/*.png') | |
30 | + ], function(event) { | |
31 | + if(isOnlyChange(event)) { | |
32 | + gulp.start('sprites'); | |
33 | + } else { | |
34 | + gulp.start('inject'); | |
35 | + } | |
36 | + }); | |
37 | + | |
28 | 38 | gulp.watch(path.join(conf.paths.src, '/app/**/*.js'), function(event) { |
29 | 39 | if(isOnlyChange(event)) { |
30 | 40 | gulp.start('scripts'); | ... | ... |
package.json
... | ... | @@ -6,47 +6,49 @@ |
6 | 6 | "test": "gulp test" |
7 | 7 | }, |
8 | 8 | "devDependencies": { |
9 | + "browser-sync": "~2.7.12", | |
10 | + "browser-sync-spa": "~1.0.2", | |
11 | + "chalk": "~1.0.0", | |
12 | + "concat-stream": "~1.5.0", | |
13 | + "del": "~1.2.0", | |
9 | 14 | "gulp": "~3.9.0", |
10 | - "gulp-autoprefixer": "~2.3.1", | |
15 | + "gulp-angular-filesort": "~1.1.1", | |
11 | 16 | "gulp-angular-templatecache": "~1.6.0", |
12 | - "del": "~1.2.0", | |
13 | - "lodash": "~3.9.3", | |
17 | + "gulp-autoprefixer": "~2.3.1", | |
14 | 18 | "gulp-csso": "~1.0.0", |
15 | 19 | "gulp-filter": "~2.0.2", |
16 | 20 | "gulp-flatten": "~0.0.4", |
21 | + "gulp-if": "^1.2.5", | |
22 | + "gulp-inject": "~1.3.1", | |
17 | 23 | "gulp-jshint": "~1.11.0", |
18 | 24 | "gulp-load-plugins": "~0.10.0", |
19 | - "gulp-size": "~1.2.1", | |
20 | - "gulp-uglify": "~1.2.0", | |
21 | - "gulp-useref": "~1.2.0", | |
22 | - "gulp-util": "~3.0.5", | |
25 | + "gulp-minify-html": "~1.0.3", | |
23 | 26 | "gulp-ng-annotate": "~1.0.0", |
24 | - "gulp-replace": "~0.5.3", | |
27 | + "gulp-protractor": "~1.0.0", | |
25 | 28 | "gulp-rename": "~1.2.2", |
29 | + "gulp-replace": "~0.5.3", | |
26 | 30 | "gulp-rev": "~5.0.0", |
27 | 31 | "gulp-rev-replace": "~0.4.2", |
28 | - "gulp-minify-html": "~1.0.3", | |
29 | - "gulp-inject": "~1.3.1", | |
30 | - "gulp-protractor": "~1.0.0", | |
31 | - "gulp-sourcemaps": "~1.5.2", | |
32 | 32 | "gulp-sass": "~2.0.1", |
33 | - "gulp-angular-filesort": "~1.1.1", | |
34 | - "main-bower-files": "~2.8.0", | |
35 | - "merge-stream": "~0.1.7", | |
33 | + "gulp-size": "~1.2.1", | |
34 | + "gulp-sourcemaps": "~1.5.2", | |
35 | + "gulp-uglify": "~1.2.0", | |
36 | + "gulp-useref": "~1.2.0", | |
37 | + "gulp-util": "~3.0.5", | |
38 | + "http-proxy-middleware": "^0.7.0", | |
36 | 39 | "jshint-stylish": "~2.0.0", |
37 | - "wiredep": "~2.2.2", | |
38 | 40 | "karma": "~0.12.36", |
39 | - "karma-jasmine": "~0.3.5", | |
40 | - "karma-phantomjs-launcher": "~0.2.0", | |
41 | 41 | "karma-angular-filesort": "~0.1.0", |
42 | + "karma-jasmine": "~0.3.5", | |
42 | 43 | "karma-ng-html2js-preprocessor": "~0.1.2", |
43 | - "concat-stream": "~1.5.0", | |
44 | + "karma-phantomjs-launcher": "~0.2.0", | |
45 | + "lodash": "~3.10.1", | |
46 | + "main-bower-files": "~2.8.0", | |
47 | + "merge-stream": "^1.0.0", | |
44 | 48 | "require-dir": "~0.3.0", |
45 | - "browser-sync": "~2.7.12", | |
46 | - "browser-sync-spa": "~1.0.2", | |
47 | - "http-proxy-middleware": "~0.0.5", | |
48 | - "chalk": "~1.0.0", | |
49 | + "sprity": "^1.0.7", | |
49 | 50 | "uglify-save-license": "~0.4.1", |
51 | + "wiredep": "~2.2.2", | |
50 | 52 | "wrench": "~1.5.8" |
51 | 53 | }, |
52 | 54 | "engines": { | ... | ... |
protractor.conf.js
1 | -'use strict'; | |
2 | - | |
3 | -var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths; | |
4 | - | |
5 | -// An example configuration file. | |
6 | -exports.config = { | |
7 | - // The address of a running selenium server. | |
8 | - //seleniumAddress: 'http://localhost:4444/wd/hub', | |
9 | - //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json | |
10 | - | |
11 | - // Capabilities to be passed to the webdriver instance. | |
12 | - capabilities: { | |
13 | - 'browserName': 'chrome' | |
14 | - }, | |
15 | - | |
16 | - baseUrl: 'http://localhost:3000', | |
17 | - | |
18 | - // Spec patterns are relative to the current working directly when | |
19 | - // protractor is called. | |
20 | - specs: [paths.e2e + '/**/*.js'], | |
21 | - | |
22 | - // Options to be passed to Jasmine-node. | |
23 | - jasmineNodeOpts: { | |
24 | - showColors: true, | |
25 | - defaultTimeoutInterval: 30000 | |
26 | - } | |
27 | -}; | |
1 | +/* globals require, exports*/ | |
2 | +(function(){ | |
3 | + 'use strict'; | |
4 | + | |
5 | + var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths; | |
6 | + | |
7 | + // An example configuration file. | |
8 | + exports.config = { | |
9 | + // The address of a running selenium server. | |
10 | + //seleniumAddress: 'http://0.0.0.0:4444/wd/hub', | |
11 | + //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json | |
12 | + | |
13 | + // Capabilities to be passed to the webdriver instance. | |
14 | + // | |
15 | + // Ref.: https://github.com/angular/protractor/blob/master/docs/browser-setup.md | |
16 | + // chrome, phantomjs, firefox | |
17 | + | |
18 | + // capabilities: { | |
19 | + // 'browserName': 'phantomjs' | |
20 | + // }, | |
21 | + | |
22 | + multiCapabilities: [ | |
23 | + // {'browserName': 'firefox'}, | |
24 | + // {'browserName': 'chrome'} | |
25 | + {'browserName': 'phantomjs'} | |
26 | + ], | |
27 | + | |
28 | + chromeOnly: true, | |
29 | + | |
30 | + onPrepare: function() { | |
31 | + /* global angular: false, browser: false */ | |
32 | + | |
33 | + // Disable animations so e2e tests run more quickly | |
34 | + var disableNgAnimate = function() { | |
35 | + angular.module('disableNgAnimate', []).run(['$animate', function($animate) { | |
36 | + $animate.enabled(false); | |
37 | + }]); | |
38 | + }; | |
39 | + | |
40 | + browser.addMockModule('disableNgAnimate', disableNgAnimate); | |
41 | + | |
42 | + // Disable debug info | |
43 | + // var disableDebugInfo = function() { | |
44 | + // angular.module('disableDebugInfo', []).run(['$compileProvider', function($compileProvider) { | |
45 | + // $compileProvider.debugInfoEnabled(false); | |
46 | + // }]); | |
47 | + // }; | |
48 | + // browser.addMockModule('disableDebugInfo', disableDebugInfo); | |
49 | + | |
50 | + // Store the name of the browser that's currently being used. | |
51 | + browser.getCapabilities().then(function(caps) { | |
52 | + browser.params.browser = caps.get('browserName'); | |
53 | + }); | |
54 | + | |
55 | + browser.driver.manage().window().setSize(1400, 400); | |
56 | + }, | |
57 | + | |
58 | + baseUrl: 'http://0.0.0.0:3000', | |
59 | + | |
60 | + rootElement: '[ng-app]', | |
61 | + | |
62 | + // The timeout in milliseconds for each script run on the browser. This should | |
63 | + // be longer than the maximum time your application needs to stabilize between | |
64 | + // tasks. | |
65 | + allScriptsTimeout: 15000, | |
66 | + | |
67 | + // How long to wait for a page to load. | |
68 | + getPageTimeout: 12000, | |
69 | + | |
70 | + // Spec patterns are relative to the current working directly when | |
71 | + // protractor is called. | |
72 | + specs: [paths.e2e + '/**/*.js'], | |
73 | + | |
74 | + // Options to be passed to Jasmine-node. | |
75 | + 'framework': 'jasmine2', | |
76 | + jasmineNodeOpts: { | |
77 | + showColors: true, | |
78 | + defaultTimeoutInterval: 30000 | |
79 | + }, | |
80 | + | |
81 | + plugins: [{ | |
82 | + path: 'node_modules/gulp-protractor/node_modules/protractor/plugins/accessibility', | |
83 | + chromeA11YDevTools: { | |
84 | + treatWarningsAsFailures: true | |
85 | + } | |
86 | + }, { | |
87 | + path: 'node_modules/gulp-protractor/node_modules/protractor/plugins/ngHint' | |
88 | + }] | |
89 | + }; | |
90 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,6 @@ |
1 | +#!/bin/bash | |
2 | + | |
3 | +gulp clean && gulp build --staging | |
4 | +git add --all -f dist/ | |
5 | +git commit -m "Update dist" | |
6 | +git push origin staging && wget -qO- --no-check-certificate 'ci.serpro/view/Noosfero/job/DialogaApp-Deploy-Homologa%C3%A7%C3%A3o/build?token=DIALOGA_TOKEN' &> /dev/null | ... | ... |
... | ... | @@ -0,0 +1,48 @@ |
1 | +<div class="a11y-bar hidden-xs"> | |
2 | + <div class="container"> | |
3 | + <div class="row"> | |
4 | + <div class="col-sm-6"> | |
5 | + <ul class="skip-links list-inline list-unstyled"> | |
6 | + <li> | |
7 | + <a class="color-theme-common-fg" accesskey="1" href="#content" id="skip-to-content" ng-click="focusOn('#content', $event)"> | |
8 | + Ir para o conteúdo | |
9 | + <span class="color-theme-common-bg">1</span> | |
10 | + </a> | |
11 | + </li> | |
12 | + <li> | |
13 | + <a class="color-theme-common-fg" accesskey="2" href="#navigation" id="skip-to-navigation" ng-click="focusOn('#navigation', $event)"> | |
14 | + Ir para o menu | |
15 | + <span class="color-theme-common-bg">2</span> | |
16 | + </a> | |
17 | + </li> | |
18 | + <li> | |
19 | + <a class="color-theme-common-fg" accesskey="3" href="#search" id="skip-to-search" ng-click="focusOn('#search', $event)"> | |
20 | + Ir para a busca | |
21 | + <span class="color-theme-common-bg">3</span> | |
22 | + </a> | |
23 | + </li> | |
24 | + <!-- <li> | |
25 | + <a class="color-theme-common-fg" accesskey="4" href="#footer" id="skip-to-footer" ng-click="focusOn('#footer', $event)"> | |
26 | + Ir para o rodapé | |
27 | + <span class="color-theme-common-bg">4</span> | |
28 | + </a> | |
29 | + </li> --> | |
30 | + </ul> | |
31 | + </div> | |
32 | + | |
33 | + <div class="col-sm-6"> | |
34 | + <ul class="action-links list-inline list-unstyled pull-right"> | |
35 | + <li> | |
36 | + <a id="siteaction-accessibility" class="color-theme-common-fg" href="#" title="Acessibilidade" accesskey="5" ng-click="actionAccessibility()">Acessibilidade</a> | |
37 | + </li> | |
38 | + <li> | |
39 | + <a id="siteaction-contrast" class="color-theme-common-fg" href="#" title="Alto Contraste" accesskey="6" ng-click="actionContrast()">Alto Contraste</a> | |
40 | + </li> | |
41 | + <li> | |
42 | + <a id="siteaction-sitemap" class="color-theme-common-fg" ui-sref="mapa-do-site" title="Mapa do Site" accesskey="7" ng-click="actionSitemap()">Mapa do Site</a> | |
43 | + </li> | |
44 | + </ul> | |
45 | + </div> | |
46 | + </div> | |
47 | + </div> | |
48 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,18 @@ |
1 | +.a11y-bar { | |
2 | + font-size: 12px; | |
3 | + padding: 5px 0; | |
4 | + | |
5 | + @media (max-width: $screen-md) { | |
6 | + font-size: 11px; | |
7 | + } | |
8 | + | |
9 | + span { | |
10 | + color: #fff; | |
11 | + padding: 0 5px; | |
12 | + } | |
13 | + | |
14 | + .action-links { | |
15 | + text-transform: uppercase; | |
16 | + border-bottom: 1px dotted #262626; | |
17 | + } | |
18 | +} | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('a11yBar', a11yBar); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function a11yBar() { | |
10 | + var directive = { | |
11 | + restrict: 'E', | |
12 | + templateUrl: 'app/components/a11y-bar/a11y-bar.html' | |
13 | + }; | |
14 | + | |
15 | + return directive; | |
16 | + | |
17 | + } | |
18 | + | |
19 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,17 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('appFooter', appFooter); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function appFooter() { | |
10 | + var directive = { | |
11 | + restrict: 'E', | |
12 | + templateUrl: 'app/components/app-footer/app-footer.html' | |
13 | + }; | |
14 | + | |
15 | + return directive; | |
16 | + } | |
17 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<div id="footer"> | |
2 | + <div class="container"> | |
3 | + <div class="row"> | |
4 | + <div class="col-xs-12 text-center"> | |
5 | + <a href="#header" style="position:absolute;right:0;top:-10px;" ng-click="scrollTo('#header')">Voltar para o topo</a> | |
6 | + </div> | |
7 | + </div> | |
8 | + </div> | |
9 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +$barra-theme: ("green": #00420c, "yellow": #2c66ce, "blue": #0042b1); | |
2 | + | |
3 | +#footer-brasil { | |
4 | + background: none repeat scroll 0% 0% map-get($barra-theme, "blue"); | |
5 | + padding: 1em 0px; | |
6 | + max-width: 100%; | |
7 | +} | |
8 | + | |
9 | +#footer { | |
10 | + padding: 20px 0; | |
11 | + a { | |
12 | + margin: 10px auto; | |
13 | + } | |
14 | + | |
15 | + .contraste & { | |
16 | + background-color: #000; | |
17 | + a { | |
18 | + color: #fff; | |
19 | + } | |
20 | + } | |
21 | +} | ... | ... |
... | ... | @@ -0,0 +1,17 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('appHeader', appHeader); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function appHeader() { | |
10 | + var directive = { | |
11 | + restrict: 'E', | |
12 | + templateUrl: 'app/components/app-header/app-header.html' | |
13 | + }; | |
14 | + | |
15 | + return directive; | |
16 | + } | |
17 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +<header id="header" class="container"> | |
2 | + | |
3 | + <div class="row hidden-xs"> | |
4 | + <div class="col-sm-12"> | |
5 | + <auth-user></auth-user> | |
6 | + </div> | |
7 | + </div> | |
8 | + | |
9 | + <div class="row"> | |
10 | + <div class="col-sm-12"> | |
11 | + <app-navbar></app-navbar> | |
12 | + </div> | |
13 | + </div> | |
14 | + | |
15 | +</header> | ... | ... |
src/app/components/app-paginator/app-paginator.directive.js
0 → 100644
... | ... | @@ -0,0 +1,71 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('appPaginator', appPaginator); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function appPaginator() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function AppPaginatorController($log) { | |
13 | + var vm = this; | |
14 | + | |
15 | + vm.$log = $log; | |
16 | + | |
17 | + vm.init(); | |
18 | + | |
19 | + $log.debug('AppPaginatorController'); | |
20 | + } | |
21 | + | |
22 | + AppPaginatorController.prototype.init = function() { | |
23 | + var vm = this; | |
24 | + | |
25 | + vm.page = vm.page || 1; | |
26 | + vm.perPage = vm.perPage || 20; | |
27 | + vm.total = vm.total || 0; | |
28 | + | |
29 | + if ((vm.total % vm.perPage) === 0) { | |
30 | + vm.pages = vm.total / vm.perPage; | |
31 | + } else { | |
32 | + vm.pages = (vm.total / vm.perPage) + 1; | |
33 | + } | |
34 | + | |
35 | + vm.arraypages = new Array(Math.floor(vm.pages)); | |
36 | + }; | |
37 | + | |
38 | + AppPaginatorController.prototype.showPage = function(pageIndex) { | |
39 | + var vm = this; | |
40 | + | |
41 | + if (pageIndex < 1) { | |
42 | + pageIndex = 1; | |
43 | + } | |
44 | + | |
45 | + if (pageIndex > vm.pages) { | |
46 | + pageIndex = vm.pages; | |
47 | + } | |
48 | + | |
49 | + if (vm.changePage) { | |
50 | + vm.changePage({pageIndex: pageIndex}); | |
51 | + } | |
52 | + }; | |
53 | + | |
54 | + var directive = { | |
55 | + restrict: 'E', | |
56 | + templateUrl: 'app/components/app-paginator/app-paginator.html', | |
57 | + scope: { | |
58 | + page: '=', | |
59 | + perPage: '=', | |
60 | + total: '=', | |
61 | + changePage: '&' | |
62 | + }, | |
63 | + controller: AppPaginatorController, | |
64 | + controllerAs: 'vm', | |
65 | + bindToController: true | |
66 | + }; | |
67 | + | |
68 | + return directive; | |
69 | + } | |
70 | + | |
71 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,17 @@ |
1 | +<nav class="app-paginator" ng-if="vm.arraypages.length > 1"> | |
2 | + <ul class="pagination"> | |
3 | + <li ng-style="{'visibility': (vm.page === 1) ? 'hidden' : 'visible'}"> | |
4 | + <a class="btn-pagination" href="#" aria-label="Previous" ng-click="vm.showPage(vm.page-1)"> | |
5 | + <span aria-hidden="true" class="glyphicon glyphicon-chevron-left pagination-icon"></span> | |
6 | + </a> | |
7 | + </li> | |
8 | + <li ng-repeat="paginas in vm.arraypages track by $index" ng-class="{ 'active' : ($index) === (vm.page - 1) }" > | |
9 | + <a class="btn-pagination" href="#" ng-click="vm.showPage($index + 1)">{{::($index)+1}}</a> | |
10 | + </li> | |
11 | + <li ng-style="{'visibility': (vm.page === vm.arraypages.length) ? 'hidden' : 'visible'}"> | |
12 | + <a class="btn-pagination" href="#" aria-label="Next" ng-click="vm.showPage(vm.page+1)"> | |
13 | + <span aria-hidden="true" class="glyphicon glyphicon-chevron-right pagination-icon"></span> | |
14 | + </a> | |
15 | + </li> | |
16 | + </ul> | |
17 | +</nav> | ... | ... |
... | ... | @@ -0,0 +1,40 @@ |
1 | +.app-paginator { | |
2 | + text-align: center; | |
3 | + | |
4 | + .btn-pagination { | |
5 | + background-color: transparent; | |
6 | + border: none; | |
7 | + border-radius: 100%; | |
8 | + font-weight: bold; | |
9 | + font-size: 20px; | |
10 | + padding: 0px 8px; | |
11 | + width: 28px; | |
12 | + height: 28px; | |
13 | + text-decoration: underline; | |
14 | + color: $defaultblue; | |
15 | + } | |
16 | + | |
17 | + .pagination-icon { | |
18 | + color: $defaultblue; | |
19 | + } | |
20 | + | |
21 | + .pagination > .active > a, | |
22 | + .pagination > .active > a:hover, | |
23 | + .pagination > .active > a:focus, | |
24 | + .pagination > .active > span, | |
25 | + .pagination > .active > span:hover, | |
26 | + .pagination > .active > span:focus { | |
27 | + background-color: $defaultblue; | |
28 | + text-decoration: none; | |
29 | + | |
30 | + } | |
31 | + | |
32 | + .pagination > .disabled > span, | |
33 | + .pagination > .disabled > span:hover, | |
34 | + .pagination > .disabled > span:focus, | |
35 | + .pagination > .disabled > a, | |
36 | + .pagination > .disabled > a:hover, | |
37 | + .pagination > .disabled > a:focus { | |
38 | + background-color: transparent; | |
39 | + } | |
40 | +} | ... | ... |
... | ... | @@ -0,0 +1,68 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('articleBar', articleBar); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function articleBar() { | |
10 | + var directive = { | |
11 | + restrict: 'E', | |
12 | + templateUrl: 'app/components/article-bar/article-bar.html', | |
13 | + scope: { | |
14 | + category: '=', | |
15 | + categories: '=' | |
16 | + }, | |
17 | + controller: ArticleBarController, | |
18 | + controllerAs: 'vm', | |
19 | + bindToController: true | |
20 | + }; | |
21 | + | |
22 | + return directive; | |
23 | + | |
24 | + /** @ngInject */ | |
25 | + function ArticleBarController($scope, $rootScope, $state, $log) { | |
26 | + $log.debug('ArticleBarController'); | |
27 | + | |
28 | + var vm = this; | |
29 | + | |
30 | + vm.$scope = $scope; | |
31 | + vm.$rootScope = $rootScope; | |
32 | + vm.$state = $state; | |
33 | + vm.theme = 'blue'; | |
34 | + | |
35 | + // if(!vm.category) { | |
36 | + // throw 'article bar without category'; | |
37 | + // } | |
38 | + | |
39 | + // if(!vm.categories) { | |
40 | + // throw 'article bar without categories list'; | |
41 | + // } | |
42 | + | |
43 | + vm.currentCategory = vm.category; | |
44 | + | |
45 | + vm.$scope.$watch('vm.currentCategory', function(newValue, oldValue){ | |
46 | + if(newValue !== oldValue){ | |
47 | + vm.$state.go('inicio', { | |
48 | + tema: newValue.slug | |
49 | + }, { | |
50 | + location: true | |
51 | + }); | |
52 | + } | |
53 | + }); | |
54 | + | |
55 | + vm.goBack = function (){ | |
56 | + var vm = this; | |
57 | + var prevState = vm.$rootScope.$previousState; | |
58 | + if(prevState && prevState.state.name){ | |
59 | + vm.$state.go(prevState.state.name, prevState.params); | |
60 | + } else { | |
61 | + vm.$state.go('inicio'); | |
62 | + } | |
63 | + }; | |
64 | + } | |
65 | + | |
66 | + } | |
67 | + | |
68 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +<div class="article-bar" ng-class="vm.theme"> | |
2 | + <div class="navbar"> | |
3 | + <div class="navbar-header"> | |
4 | + <button class="article-bar--item btn btn-link" ng-click="vm.goBack()"> | |
5 | + <!-- <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> --> | |
6 | + <span class="glyphicon glyphicon-arrow-left" aria-hidden="true"></span> | |
7 | + Voltar | |
8 | + </button> | |
9 | + </div> | |
10 | + <div class="navbar-left" ng-if="vm.category"> | |
11 | + <button class="article-bar--item article-bar--category-button btn btn-link"> | |
12 | + <span class="icon" ng-class="'icon-tema-' + vm.category.slug"></span> | |
13 | + <span class="category-name">{{::vm.category.name}}</span> | |
14 | + </button> | |
15 | + </div> | |
16 | + <div class="navbar-right" ng-if="vm.categories"> | |
17 | + <label for="selectCategory" class="control-label sr-only" title="Selecione uma opção para acessar os programas do tema">Temas:</label> | |
18 | + <select id="selectCategory" name="selectCategory" class="article-bar--item form-control" ng-model="vm.currentCategory" ng-options="category.name for category in vm.categories track by category.slug"> | |
19 | + </select> | |
20 | + </div> | |
21 | + </div> | |
22 | + </div> | |
23 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,52 @@ |
1 | +.article-bar { | |
2 | + position: relative; | |
3 | + background-color: #0042b1; | |
4 | + | |
5 | + .btn { | |
6 | + color: #fff; | |
7 | + font-weight: bold; | |
8 | + } | |
9 | + | |
10 | + &--item { | |
11 | + margin: 8px 0; | |
12 | + | |
13 | + @media (max-width: $screen-xs) { | |
14 | + margin: 8px; | |
15 | + } | |
16 | + | |
17 | + } | |
18 | + | |
19 | + &--category-button { | |
20 | + position: relative; | |
21 | + width: 125px; | |
22 | + text-align: right; | |
23 | + margin-left: 10px; | |
24 | + font-size: 24px; | |
25 | + line-height: 20px; | |
26 | + font-family: 'Open Sans'; | |
27 | + | |
28 | + .icon { | |
29 | + display: inline-block; | |
30 | + margin: -40px -35px -40px -50px; | |
31 | + transform: scale(.37); | |
32 | + } | |
33 | + } | |
34 | + | |
35 | + .navbar { | |
36 | + margin-bottom: 0; | |
37 | + } | |
38 | + | |
39 | + .navbar-right { | |
40 | + margin-right: 15px; | |
41 | + } | |
42 | + | |
43 | + @each $category, $color in $categories { | |
44 | + &.#{$category} { | |
45 | + background-color: $color; | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + .contraste & { | |
50 | + background-color: #262626; | |
51 | + } | |
52 | +} | ... | ... |
... | ... | @@ -0,0 +1,68 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('articleBox', articleBox); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function articleBox() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ArticleBoxController($state, PATH, $log) { | |
13 | + $log.debug('ArticleBoxController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$state = $state; | |
17 | + vm.PATH = PATH; | |
18 | + vm.$log = $log; | |
19 | + | |
20 | + vm.init(); | |
21 | + } | |
22 | + | |
23 | + ArticleBoxController.prototype.init = function () { | |
24 | + var vm = this; | |
25 | + | |
26 | + if(!vm.article.slug){ | |
27 | + throw { name: 'NotDefined', message: 'The attribute "slug" is undefined.'}; | |
28 | + } | |
29 | + | |
30 | + if(!vm.category){ | |
31 | + throw { name: 'NotDefined', message: 'The attribute "category" is undefined.'}; | |
32 | + } | |
33 | + | |
34 | + if(!vm.image && vm.article.image){ | |
35 | + vm.image = { | |
36 | + src: vm.PATH.image + vm.article.image.url, | |
37 | + alt: 'Imagem de destaque do conteúdo' | |
38 | + }; | |
39 | + } | |
40 | + }; | |
41 | + | |
42 | + ArticleBoxController.prototype.showContent = function () { | |
43 | + var vm = this; | |
44 | + | |
45 | + vm.$state.go('programa', { | |
46 | + slug: vm.article.slug | |
47 | + }, { | |
48 | + location: true | |
49 | + }); | |
50 | + }; | |
51 | + | |
52 | + var directive = { | |
53 | + restrict: 'E', | |
54 | + templateUrl: 'app/components/article-box/article-box.html', | |
55 | + scope: { | |
56 | + article: '=', | |
57 | + category: '=' | |
58 | + }, | |
59 | + controller: ArticleBoxController, | |
60 | + controllerAs: 'vm', | |
61 | + bindToController: true | |
62 | + }; | |
63 | + | |
64 | + | |
65 | + return directive; | |
66 | + } | |
67 | + | |
68 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,17 @@ |
1 | +<article class="article-box" ng-click="vm.showContent()" ng-class="vm.category.slug"> | |
2 | + <div> | |
3 | + <h2 class="article-box--category">{{ ::vm.category.name }}</h2> | |
4 | + <div class="article-box--image-wrapper"> | |
5 | + <div class="article-box--image" ng-style="{ 'background-image' : 'url({{ vm.image.src }})' }"></div> | |
6 | + </div> | |
7 | + <div class="article-box--title"> | |
8 | + <h1>{{::vm.article.title}}</h1> | |
9 | + </div> | |
10 | + <div class="article-box--abstract" ng-bind-html="vm.article.summary"></div> | |
11 | + <div class="button--themed"> | |
12 | + <button class="btn btn-block"> | |
13 | + Participe | |
14 | + </button> | |
15 | + </div> | |
16 | + </div> | |
17 | +</article> | ... | ... |
... | ... | @@ -0,0 +1,150 @@ |
1 | +$article-box-space: 20px; | |
2 | + | |
3 | +.article-box { | |
4 | + cursor: pointer; | |
5 | + background-color: #fff; | |
6 | + margin-top: $article-box-space; | |
7 | + margin-bottom: $article-box-space; | |
8 | + border-radius: 3px; | |
9 | + overflow: hidden; | |
10 | + | |
11 | + .contraste & { | |
12 | + color: #fff; | |
13 | + background-color: #262626; | |
14 | + } | |
15 | + | |
16 | + &--category { | |
17 | + font-size: 14px; | |
18 | + font-weight: bold; | |
19 | + text-transform: uppercase; | |
20 | + line-height: 22px; | |
21 | + display: block; | |
22 | + height: 30px; | |
23 | + margin: 0; | |
24 | + padding: 5px $article-box-space; | |
25 | + color: #ffffff; | |
26 | + | |
27 | + @each $category, $color in $categories { | |
28 | + .#{$category} & { | |
29 | + background-color: $color; | |
30 | + } | |
31 | + } | |
32 | + | |
33 | + .contraste & { | |
34 | + background-color: #262626; | |
35 | + } | |
36 | + } | |
37 | + | |
38 | + &--title { | |
39 | + | |
40 | + padding: 0 $article-box-space; | |
41 | + | |
42 | + h1 { | |
43 | + font-size: 18px; | |
44 | + font-weight: bold; | |
45 | + margin: 0 0 $article-box-space 0; | |
46 | + display: table-cell; | |
47 | + vertical-align: middle; | |
48 | + | |
49 | + // Altura das linhas do abstract | |
50 | + $hLine: 20px; | |
51 | + // default | |
52 | + height: $hLine * 2; | |
53 | + | |
54 | + @media (max-width: $screen-xs) { | |
55 | + // height: $hLine * 3; | |
56 | + height: auto; | |
57 | + } | |
58 | + | |
59 | + @media (min-width: $screen-xs + 1) { | |
60 | + // height: $hLine * 2; | |
61 | + height: auto; | |
62 | + } | |
63 | + | |
64 | + @media (min-width: $screen-sm + 1) { | |
65 | + height: $hLine * 2; | |
66 | + } | |
67 | + | |
68 | + @media (min-width: $screen-md + 1) { | |
69 | + height: $hLine * 2; | |
70 | + } | |
71 | + } | |
72 | + } | |
73 | + | |
74 | + &--abstract { | |
75 | + padding: 0 $article-box-space; | |
76 | + display: table-cell; | |
77 | + vertical-align: middle; | |
78 | + | |
79 | + // Altura das linhas do abstract | |
80 | + $pLine: 20px; | |
81 | + // 1 linha: 19px -> 20 | |
82 | + // 2 linhas: 38px -> 40 | |
83 | + // 3 linhas: 57px -> 60 | |
84 | + // 4 linhas: 76px -> 80 | |
85 | + | |
86 | + height: $pLine * 2; // default | |
87 | + | |
88 | + @media (max-width: $screen-xs) { | |
89 | + // height: $pLine * 4; | |
90 | + height: auto; | |
91 | + } | |
92 | + | |
93 | + @media (min-width: $screen-xs + 1) { | |
94 | + // height: $pLine * 3; | |
95 | + height: auto; | |
96 | + } | |
97 | + | |
98 | + @media (min-width: $screen-sm + 1) { | |
99 | + height: $pLine * 4; | |
100 | + } | |
101 | + | |
102 | + @media (min-width: $screen-md + 1) { | |
103 | + height: $pLine * 3; | |
104 | + } | |
105 | + | |
106 | + p { margin: 0; } | |
107 | + } | |
108 | + | |
109 | + &--image-wrapper { | |
110 | + position: relative; | |
111 | + // width: 100%; | |
112 | + // width: 370px; | |
113 | + // height: 170px; | |
114 | + | |
115 | + overflow: hidden; | |
116 | + // text-align: center; | |
117 | + min-height: 170px; | |
118 | + } | |
119 | + | |
120 | + &--image { | |
121 | + min-height: 170px; | |
122 | + background-position: center; | |
123 | + background-size: cover; | |
124 | + background-repeat: no-repeat; | |
125 | + | |
126 | + -webkit-transition: all $time ease-in-out; | |
127 | + -moz-transition: all $time ease-in-out; | |
128 | + -o-transition: all $time ease-in-out; | |
129 | + transition: all $time ease-in-out; | |
130 | + } | |
131 | + | |
132 | + .button--themed { | |
133 | + padding: 20px; | |
134 | + } | |
135 | + | |
136 | + &:hover { | |
137 | + background-color: #d9d9d9; | |
138 | + | |
139 | + .article-box--image { | |
140 | + -webkit-transform: scale($scale); /* prefixo para browsers webkit */ | |
141 | + -moz-transform: scale($scale); /* prefixo para browsers gecko */ | |
142 | + -o-transform: scale($scale); /* prefixo para opera */ | |
143 | + transform: scale($scale); | |
144 | + } | |
145 | + | |
146 | + .contraste & { | |
147 | + background-color: #262626; | |
148 | + } | |
149 | + } | |
150 | +} | ... | ... |
src/app/components/article-grid/article-grid.directive.js
0 → 100644
... | ... | @@ -0,0 +1,54 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('articleGrid', articleGrid); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function articleGrid() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ArticleGridController($scope, $rootScope, $element, $location, $filter, $log) { | |
13 | + $log.debug('ArticleGridController'); | |
14 | + | |
15 | + // alias | |
16 | + var vm = this; | |
17 | + | |
18 | + // dependencies | |
19 | + vm.$scope = $scope; | |
20 | + vm.$rootScope = $rootScope; | |
21 | + vm.$element = $element; | |
22 | + vm.$location = $location; | |
23 | + vm.$filter = $filter; | |
24 | + vm.$log = $log; | |
25 | + vm.defaultLimit = 6; | |
26 | + | |
27 | + // initialization | |
28 | + vm.init(); | |
29 | + vm.attachListeners(); | |
30 | + } | |
31 | + | |
32 | + ArticleGridController.prototype.init = function() { | |
33 | + // var vm = this; | |
34 | + // vm.programs = null; // scope var | |
35 | + }; | |
36 | + | |
37 | + ArticleGridController.prototype.attachListeners = function() { | |
38 | + // var vm = this; | |
39 | + }; | |
40 | + | |
41 | + var directive = { | |
42 | + restrict: 'E', | |
43 | + templateUrl: 'app/components/article-grid/article-grid.html', | |
44 | + scope: { | |
45 | + articles: '=' | |
46 | + }, | |
47 | + controller: ArticleGridController, | |
48 | + controllerAs: 'vm', | |
49 | + bindToController: true | |
50 | + }; | |
51 | + | |
52 | + return directive; | |
53 | + } | |
54 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<div class="article-grid row"> | |
2 | + <div ng-repeat="article in vm.articles as results"> | |
3 | + <article-box article="article" category="article.categories[0]" class="col-xs-12 col-sm-6"></article-box> | |
4 | + <div ng-if="$odd" class="clearfix"></div> | |
5 | + </div> | |
6 | + <div class="animate-repeat" ng-if="results.length == 0"> | |
7 | + Nenhum programa encontrado. | |
8 | + </div> | |
9 | +</div> | ... | ... |
src/app/components/article-preview/article-preview.directive.js
0 → 100644
... | ... | @@ -0,0 +1,67 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('articlePreview', articlePreview); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function articlePreview() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ArticlePreviewController($state, PATH, $log) { | |
13 | + $log.debug('ArticlePreviewController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$state = $state; | |
17 | + vm.PATH = PATH; | |
18 | + vm.$log = $log; | |
19 | + | |
20 | + vm.init(); | |
21 | + } | |
22 | + | |
23 | + ArticlePreviewController.prototype.init = function () { | |
24 | + var vm = this; | |
25 | + | |
26 | + if(!vm.article.slug){ | |
27 | + throw { name: 'NotDefined', message: 'The attribute "slug" is undefined.'}; | |
28 | + } | |
29 | + | |
30 | + if(!vm.category){ | |
31 | + vm.category = vm.article.categories[0]; | |
32 | + } | |
33 | + | |
34 | + if(!vm.banner){ | |
35 | + vm.banner = { | |
36 | + src: vm.PATH.image + vm.article.image.url, | |
37 | + alt: 'Imagem de destaque do programa' | |
38 | + }; | |
39 | + } | |
40 | + }; | |
41 | + | |
42 | + ArticlePreviewController.prototype.showContent = function () { | |
43 | + var vm = this; | |
44 | + | |
45 | + vm.$state.go('conheca-o-programa', { | |
46 | + slug: vm.article.slug | |
47 | + }, { | |
48 | + location: true | |
49 | + }); | |
50 | + }; | |
51 | + | |
52 | + var directive = { | |
53 | + restrict: 'E', | |
54 | + templateUrl: 'app/components/article-preview/article-preview.html', | |
55 | + scope: { | |
56 | + article: '=' | |
57 | + }, | |
58 | + controller: ArticlePreviewController, | |
59 | + controllerAs: 'vm', | |
60 | + bindToController: true | |
61 | + }; | |
62 | + | |
63 | + | |
64 | + return directive; | |
65 | + } | |
66 | + | |
67 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,101 @@ |
1 | +<article class="article-preview" ng-class="vm.category.slug"> | |
2 | + <header class="article-banner"> | |
3 | + <img class="article-banner--image" ng-src="{{vm.banner.src}}" alt="{{vm.banner.alt}}"> | |
4 | + <div class="article-banner--strip"> | |
5 | + <h1 class="article-banner--title">{{::vm.article.title}}</h1> | |
6 | + <p class="article-banner--abstract" ng-bind-html="vm.article.abstract"></p> | |
7 | + </div> | |
8 | + </header> | |
9 | + | |
10 | + <section class="call-to-action--section"> | |
11 | + <div class="row show-content-row"> | |
12 | + <div class="col-xs-10 col-xs-offset-1 col-md-8 col-md-offset-2 col-lg-6 col-lg-offset-3"> | |
13 | + <div class="button--themed"> | |
14 | + <button class="btn btn-block" ng-click="vm.showContent()">Conheça o programa</button> | |
15 | + </div> | |
16 | + </div> | |
17 | + </div> | |
18 | + <div class="row proposal-row"> | |
19 | + <div class="row-height"> | |
20 | + <div class="col-md-6 col-height"> | |
21 | + <div class="inside-full-height"> | |
22 | + <div class="proposal-box make-proposal"> | |
23 | + <h2 class="proposal-box--title">Faça uma proposta</h2> | |
24 | + <p class="proposal-box--text">Qual a sua sugestão para melhorar este programa?</p> | |
25 | + <div class="row"> | |
26 | + <div class="col-xs-8 col-xs-offset-2"> | |
27 | + <div class="button--themed"> | |
28 | + <button class="btn btn-block" ng-click="vm.goSendProposal()"> | |
29 | + Envie sua proposta | |
30 | + </button> | |
31 | + </div> | |
32 | + </div> | |
33 | + </div> | |
34 | + </div> | |
35 | + </div> | |
36 | + </div> | |
37 | + <div class="col-md-6 col-height"> | |
38 | + <div class="inside-full-height"> | |
39 | + <div class="proposal-box support-proposal"> | |
40 | + <h2 class="proposal-box--title">Apoie outras propostas</h2> | |
41 | + <p class="proposal-box--text"> | |
42 | + Lorem qual a sua sugestão para melhorar este programa | |
43 | + Lorem qual a sua sugestão para melhorar este programa | |
44 | + Lorem qual a sua sugestão para melhorar este programa | |
45 | + Lorem qual a sua sugestão para melhorar este programa | |
46 | + Lorem qual a sua sugestão para melhorar este programa | |
47 | + Lorem qual a sua sugestão para melhorar este programa? | |
48 | + </p> | |
49 | + <div class="col-lg-12"> | |
50 | + <div class="col-xs-8 col-xs-offset-2 col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2"> | |
51 | + <div class="button--themed vote-buttons"> | |
52 | + <button class="btn btn-circle vote-buttons-up" ng-click="vm.vote(1)"> | |
53 | + <span class="sr-only">Eu <b>apoio</b> esta proposta.</span> | |
54 | + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> | |
55 | + </button> | |
56 | + | |
57 | + <button class="btn btn-circle vote-buttons-down" ng-click="vm.vote(-1)"> | |
58 | + <span class="sr-only">Eu <b>não apoio</b> esta proposta.</span> | |
59 | + <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> | |
60 | + </button> | |
61 | + | |
62 | + <button class="btn btn-block vote-buttons-skip" ng-click="vm.vote(0)"> | |
63 | + <span class="sr-only">Pular esta proposta.</span> | |
64 | + <span class="icon" aria-hidden="true"></span> | |
65 | + Pular | |
66 | + </button> | |
67 | + </div> | |
68 | + </div> | |
69 | + </div> | |
70 | + <div class="col-lg-12"> | |
71 | + <div class="col-xs-8 col-xs-offset-2 col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2"> | |
72 | + <div class="text-center"> | |
73 | + <button class="btn btn-link" ng-click="vm.showResults()">Resultados</button> | |
74 | + </div> | |
75 | + </div> | |
76 | + </div> | |
77 | + <div class="col-md-12"> | |
78 | + <div class="col-xs-12"> | |
79 | + <div class="text-center"> | |
80 | + <span>Compartilhe esta proposta</span> | |
81 | + <social-share></social-share> | |
82 | + </div> | |
83 | + </div> | |
84 | + </div> | |
85 | + <div class="clearfix"></div> | |
86 | + </div> | |
87 | + </div> | |
88 | + </div> | |
89 | + </div> | |
90 | + </div> | |
91 | + <div class="talk-proposal row proposal-row"> | |
92 | + <div class="row-height"> | |
93 | + <div class="col-md-12 col-height"> | |
94 | + <div class=""> | |
95 | + <h2>Bate-papo virtual com ministr@s</h2> | |
96 | + </div> | |
97 | + </div> | |
98 | + </div> | |
99 | + </div> | |
100 | + </section> | |
101 | +</article> | ... | ... |
... | ... | @@ -0,0 +1,111 @@ |
1 | +.article-preview { | |
2 | + .article-banner { | |
3 | + position: relative; | |
4 | + } | |
5 | + | |
6 | + .article-banner--image { | |
7 | + width: 100%; | |
8 | + } | |
9 | + | |
10 | + .article-banner--strip { | |
11 | + color: #fff; | |
12 | + position: absolute; | |
13 | + bottom: 15%; | |
14 | + right: 0; | |
15 | + width: 50%; | |
16 | + text-align: center; | |
17 | + | |
18 | + @each $category, $color in $categories { | |
19 | + .#{$category} & { | |
20 | + background-color: $color; | |
21 | + } | |
22 | + } | |
23 | + | |
24 | + @media (max-width: $screen-sm){ | |
25 | + position: relative; | |
26 | + width: 100%; | |
27 | + } | |
28 | + } | |
29 | + | |
30 | + .article-banner--title { | |
31 | + font-size: 32px; | |
32 | + text-transform: uppercase; | |
33 | + margin-top: 0; | |
34 | + padding-top: 20px; | |
35 | + } | |
36 | + .article-banner--title, | |
37 | + .article-banner--abstract { | |
38 | + font-weight: bold; | |
39 | + } | |
40 | + .article-banner--abstract { | |
41 | + padding-bottom: 10px; | |
42 | + } | |
43 | + | |
44 | + .show-content-row { | |
45 | + .button--themed { | |
46 | + .btn { | |
47 | + font-size: 38px; | |
48 | + | |
49 | + @media (max-width: $screen-sm){ | |
50 | + font-size: 20px; | |
51 | + } | |
52 | + } | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + .talk-proposal { | |
57 | + margin-top: -20px; | |
58 | + } | |
59 | + | |
60 | + .proposal-box { | |
61 | + | |
62 | + // padding: 10px 20px; | |
63 | + | |
64 | + .proposal-box--title { | |
65 | + font-size: 38px; | |
66 | + font-weight: 400; | |
67 | + text-align: center; | |
68 | + | |
69 | + margin-bottom: 20px; | |
70 | + } | |
71 | + | |
72 | + .proposal-box--text { | |
73 | + font-size: 24px; | |
74 | + font-weight: 700; | |
75 | + line-height: 1.2; | |
76 | + margin-bottom: 20px; | |
77 | + } | |
78 | + | |
79 | + @each $category, $color in $categories { | |
80 | + .#{$category} & { | |
81 | + border-color: $color; | |
82 | + | |
83 | + .proposal-box--title { | |
84 | + color: $color; | |
85 | + } | |
86 | + } | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + .row-height { | |
91 | + border-spacing: 20px; | |
92 | + } | |
93 | + | |
94 | + .col-height { | |
95 | + | |
96 | + border: 1px solid #000; | |
97 | + border-radius: 3px; | |
98 | + | |
99 | + @each $category, $color in $categories { | |
100 | + .#{$category} & { | |
101 | + border-color: $color; | |
102 | + } | |
103 | + } | |
104 | + | |
105 | + @media (max-width: $screen-sm){ | |
106 | + display: block; | |
107 | + border: none; | |
108 | + } | |
109 | + | |
110 | + } | |
111 | +} | ... | ... |
... | ... | @@ -0,0 +1,306 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .factory('ArticleService', ArticleService); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function ArticleService($http, $q, $rootScope, API, UtilService, Slug, GUID, $log) { | |
10 | + $log.debug('ArticleService'); | |
11 | + | |
12 | + var service = { | |
13 | + apiArticles: $rootScope.basePath + '/api/v1/articles/', | |
14 | + apiCommunities: $rootScope.basePath + '/api/v1/communities/', | |
15 | + apiProposals: $rootScope.basePath + '/api/v1/proposals_discussion_plugin/', | |
16 | + getArticleById: getArticleById, | |
17 | + getArticleBySlug: getArticleBySlug, | |
18 | + getCategories: getCategories, | |
19 | + getCategoryBySlug: getCategoryBySlug, | |
20 | + getTopics: getTopics, | |
21 | + getTopicById: getTopicById, | |
22 | + getProposals: getProposals, | |
23 | + getProposalById: getProposalById, | |
24 | + getProposalsByTopicId: getProposalsByTopicId, | |
25 | + createProposal: createProposal, | |
26 | + voteProposal: voteProposal, | |
27 | + getEvents: getEvents, | |
28 | + subscribeToEvent: subscribeToEvent, | |
29 | + searchTopics: searchTopics, | |
30 | + searchProposals: searchProposals | |
31 | + }; | |
32 | + | |
33 | + return service; | |
34 | + | |
35 | + function _getArticleById (articleId, params, cbSuccess, cbError) { | |
36 | + | |
37 | + var url = service.apiArticles + articleId; | |
38 | + var paramsExtended = angular.extend({}, params); | |
39 | + | |
40 | + UtilService.get(url, {params: paramsExtended}) | |
41 | + .then(function(data){ | |
42 | + cbSuccess(data); | |
43 | + }).catch(function(error){ | |
44 | + cbError(error); | |
45 | + }); | |
46 | + } | |
47 | + | |
48 | + function getArticleById (articleId, params, cbSuccess, cbError) { | |
49 | + _getArticleById(articleId, params, cbSuccess, cbError); | |
50 | + } | |
51 | + | |
52 | + function getArticleBySlug (/*slug, params, cbSuccess, cbError*/) { | |
53 | + throw { name: 'NotImplementedYet', message: 'The service "getArticleBySlug" is not implemented yet.'}; | |
54 | + } | |
55 | + | |
56 | + function getCategories (articleId, params, cbSuccess, cbError) { | |
57 | + // Ex.: /api/v1/articles/103358?fields= | |
58 | + | |
59 | + var url = service.apiArticles + articleId; | |
60 | + var paramsExtended = angular.extend({ | |
61 | + 'fields[]': ['id', 'categories'] | |
62 | + }, params); | |
63 | + | |
64 | + UtilService.get(url, {params: paramsExtended}) | |
65 | + .then(function(data){ | |
66 | + cbSuccess(data); | |
67 | + }).catch(function(error){ | |
68 | + cbError(error); | |
69 | + }); | |
70 | + } | |
71 | + | |
72 | + function getCategoryBySlug (/*slug, params, cbSuccess, cbError*/) { | |
73 | + throw { name: 'NotImplementedYet', message: 'The service "getArticleBySlug" is not implemented yet.'}; | |
74 | + } | |
75 | + | |
76 | + function getTopics (params, cbSuccess, cbError) { | |
77 | + // Ex.: /api/v1/articles/103358/children?fields= | |
78 | + getTopicById(API.articleId.home, params, cbSuccess, cbError); | |
79 | + } | |
80 | + | |
81 | + function getTopicById (topicId, params, cbSuccess, cbError) { | |
82 | + // Ex.: /api/v1/articles/103358/children?fields= | |
83 | + | |
84 | + var url = service.apiArticles + topicId + '/children'; | |
85 | + var paramsExtended = angular.extend({ | |
86 | + 'fields[]': ['id', 'categories'] | |
87 | + // 'fields[]': ['id', 'title', 'body', 'slug', 'abstract', 'categories', 'setting', 'children_count', 'hits'] | |
88 | + }, params); | |
89 | + | |
90 | + UtilService.get(url, {params: paramsExtended}) | |
91 | + .then(function(data){ | |
92 | + cbSuccess(data); | |
93 | + }).catch(function(error){ | |
94 | + cbError(error); | |
95 | + }); | |
96 | + } | |
97 | + | |
98 | + function getProposals (params, cbSuccess, cbError) { | |
99 | + var paramsExtended = angular.extend({ | |
100 | + query: '' | |
101 | + }, params); | |
102 | + | |
103 | + searchProposals(paramsExtended, cbSuccess, cbError); | |
104 | + } | |
105 | + | |
106 | + function getProposalById (proposalId, params, cbSuccess, cbError) { | |
107 | + var url = service.apiArticles + proposalId; | |
108 | + | |
109 | + var paramsExtended = angular.extend({ | |
110 | + // 'fields[]': ['id', 'title', 'abstract', 'children', 'children_count', 'ranking_position', 'hits', 'votes_for', 'votes_against'], | |
111 | + // 'per_page':'1', | |
112 | + 'limit':'1', | |
113 | + 'content_type':'ProposalsDiscussionPlugin::Proposal' | |
114 | + }, params); | |
115 | + | |
116 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
117 | + _pipeInjectSlugIntoParentProgram(data); | |
118 | + _pipeSortByRankinPosition(data); | |
119 | + cbSuccess(data); | |
120 | + }).catch(function(error){ | |
121 | + cbError(error); | |
122 | + }); | |
123 | + | |
124 | + } | |
125 | + | |
126 | + /** | |
127 | + * Ex.: /api/v1/articles/[article_id]/children?[params]content_type=ProposalsDiscussionPlugin::Proposal | |
128 | + * Ex.: /api/v1/articles/103644/children?limit=20&fields=id,name,slug,abstract,created_by&content_type=ProposalsDiscussionPlugin::Proposal | |
129 | + * | |
130 | + * @param {Integer} topicId topic where has those proposals | |
131 | + * @param {Object} params params for pagination ant others | |
132 | + * @param {Function} cbSuccess callback for success | |
133 | + * @param {Function} cbError callback for error | |
134 | + * @return {Array} [description] | |
135 | + */ | |
136 | + function getProposalsByTopicId (topicId, params, cbSuccess, cbError) { | |
137 | + getProposalById(topicId + '/children', params, cbSuccess, cbError); | |
138 | + } | |
139 | + | |
140 | + function createProposal (proposal, targetId, cbSuccess, cbError){ | |
141 | + | |
142 | + if(!$rootScope.currentUser){ | |
143 | + cbError({message: 'Usuário não logado.'}); | |
144 | + }else{ | |
145 | + // /api/v1/proposals_discussion_plugin/' + targetId + '/propose | |
146 | + var url = service.apiProposals + targetId + '/propose'; | |
147 | + | |
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'); | |
152 | + encodedParams.push('private_token=' + $rootScope.currentUser.private_token); | |
153 | + encodedParams.push('fields=id'); | |
154 | + encodedParams.push('article[name]=article_' + GUID.generate()); | |
155 | + encodedParams = encodedParams.join('&'); | |
156 | + | |
157 | + UtilService.post(url, encodedParams).then(function(response){ | |
158 | + cbSuccess(response); | |
159 | + }).catch(function(error){ | |
160 | + cbError(error); | |
161 | + }); | |
162 | + } | |
163 | + } | |
164 | + | |
165 | + function voteProposal (proposal_id, params, cbSuccess, cbError){ | |
166 | + var url = service.apiArticles + proposal_id + '/vote'; | |
167 | + var paramsExtended = angular.extend({ | |
168 | + private_token: $rootScope.currentUser.private_token | |
169 | + // private_token: 'e2198fdbcc20409f082829b4b5c0848e' | |
170 | + }, params); | |
171 | + | |
172 | + var encodedParams = angular.element.param(paramsExtended); | |
173 | + | |
174 | + UtilService.post(url, encodedParams).then(function(response){ | |
175 | + cbSuccess(response); | |
176 | + }).catch(function(error){ | |
177 | + cbError(error); | |
178 | + }); | |
179 | + } | |
180 | + | |
181 | + function getEvents (community_id, params, cbSuccess, cbError) { | |
182 | + // Ex.: /api/v1/communities/19195/articles?categories_ids[]=' + cat_id + '&content_type=Event'; | |
183 | + // Ex.: /api/v1/communities/' + community_id + '/articles?categories_ids[]=' + cat_id + '&content_type=Event'; | |
184 | + | |
185 | + var url = service.apiCommunities + community_id + '/articles'; | |
186 | + var paramsExtended = angular.extend({ | |
187 | + // 'fields[]': ['id', 'title', 'abstract', 'body', 'categories', 'created_at', 'start_date', 'end_date', 'followers_count', 'image', 'url'], | |
188 | + 'content_type':'Event' | |
189 | + }, params); | |
190 | + | |
191 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
192 | + _pipeIsInThePast(data); | |
193 | + cbSuccess(data.articles); | |
194 | + }).catch(function(error){ | |
195 | + cbError(error); | |
196 | + }); | |
197 | + } | |
198 | + | |
199 | + // function getSubscribers (event_id, params, cbSuccess, cbError) { | |
200 | + // var url = service.apiArticles + event_id + '/followers?_=' + new Date().getTime(); | |
201 | + // var paramsExtended = angular.extend({ | |
202 | + // // 'fields[]': ['id', 'slug', 'title', 'abstract', 'body', 'categories', 'created_at', 'start_date', 'end_date', 'hits'], | |
203 | + // 'content_type':'Event' | |
204 | + // }, params); | |
205 | + | |
206 | + // UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
207 | + // cbSuccess(data.articles); | |
208 | + // }).catch(function(error){ | |
209 | + // cbError(error); | |
210 | + // }); | |
211 | + // } | |
212 | + | |
213 | + function subscribeToEvent (event_id, params, cbSuccess, cbError) { | |
214 | + | |
215 | + if(!$rootScope.currentUser){ | |
216 | + cbError({message: 'Usuário não logado.'}); | |
217 | + | |
218 | + }else{ | |
219 | + var url = service.apiArticles + event_id + '/follow'; | |
220 | + var encodedParams = 'private_token=' + $rootScope.currentUser.private_token; | |
221 | + | |
222 | + UtilService.post(url, encodedParams).then(function(response){ | |
223 | + cbSuccess(response); | |
224 | + }).catch(function(error){ | |
225 | + cbError(error); | |
226 | + }); | |
227 | + } | |
228 | + } | |
229 | + | |
230 | + function searchTopics (params, cbSuccess, cbError) { | |
231 | + // Ex.: /api/v1/search/article?type=ProposalsDiscussionPlugin::Topic&query=cisternas | |
232 | + var url = '/api/v1/search/article'; | |
233 | + var paramsExtended = angular.extend({ | |
234 | + // 'fields[]': ['id', 'title', 'slug', 'abstract', 'categories', 'setting', 'children_count', 'hits'], | |
235 | + 'type': 'ProposalsDiscussionPlugin::Topic' | |
236 | + }, params); | |
237 | + | |
238 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
239 | + cbSuccess(data); | |
240 | + }).catch(function(error){ | |
241 | + cbError(error); | |
242 | + }); | |
243 | + } | |
244 | + | |
245 | + function searchProposals (params, cbSuccess, cbError) { | |
246 | + // Ex.: /api/v1/search/article?type=ProposalsDiscussionPlugin::Proposal&query=cisternas | |
247 | + var url = '/api/v1/search/article'; | |
248 | + var paramsExtended = angular.extend({ | |
249 | + page: 1, | |
250 | + per_page: 20, | |
251 | + type: 'ProposalsDiscussionPlugin::Proposal' | |
252 | + }, params); | |
253 | + | |
254 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
255 | + _pipeInjectSlugIntoParentProgram(data); | |
256 | + _pipeSortByRankinPosition(data); | |
257 | + cbSuccess(data); | |
258 | + }).catch(function(error){ | |
259 | + cbError(error); | |
260 | + }); | |
261 | + } | |
262 | + | |
263 | + function _pipeInjectSlugIntoParentProgram(data){ | |
264 | + if(!data.articles && data.article){ | |
265 | + data.articles = [data.article]; | |
266 | + } | |
267 | + var proposals = data.articles; | |
268 | + for (var i = proposals.length - 1; i >= 0; i--) { | |
269 | + var proposal = proposals[i]; | |
270 | + if(proposal.parent && !proposal.parent.slug){ | |
271 | + proposal.parent.slug = Slug.slugify(proposal.parent.title); | |
272 | + } | |
273 | + } | |
274 | + } | |
275 | + | |
276 | + function _pipeSortByRankinPosition(data){ | |
277 | + if(!data.articles && data.article){ | |
278 | + data.articles = [data.article]; | |
279 | + } | |
280 | + data.articles = data.articles.sort(function(pA, pB){ | |
281 | + return pA.ranking_position - pB.ranking_position; | |
282 | + }); | |
283 | + } | |
284 | + | |
285 | + function _pipeIsInThePast(data){ | |
286 | + if(!data.articles && data.article){ | |
287 | + data.articles = [data.article]; | |
288 | + } | |
289 | + var now = (new Date()).getTime(); | |
290 | + var eventDate = null; | |
291 | + var events = data.articles; | |
292 | + | |
293 | + for (var i = events.length - 1; i >= 0; i--) { | |
294 | + var event = events[i]; | |
295 | + | |
296 | + if(event.end_date){ | |
297 | + eventDate = new Date(event.end_date); | |
298 | + } | |
299 | + | |
300 | + if(eventDate.getTime() < now){ | |
301 | + event.isOld = true; | |
302 | + } | |
303 | + } | |
304 | + } | |
305 | + } | |
306 | +})(); | ... | ... |
src/app/components/article-service/article.service.spec.js
0 → 100644
... | ... | @@ -0,0 +1,67 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('article services', function() { | |
5 | + var ArticleService, httpBackend; | |
6 | + | |
7 | + beforeEach(module('dialoga')); | |
8 | + | |
9 | + beforeEach(inject(function(_ArticleService_, $httpBackend) { | |
10 | + ArticleService = _ArticleService_; | |
11 | + httpBackend = $httpBackend; | |
12 | + })); | |
13 | + | |
14 | + it('should return the main article', function() { | |
15 | + var url = 'http://login.dialoga.gov.br/api/v1/articles/103358?fields=id,children,categories,abstract,title,image,url,setting,position&private_token=null'; | |
16 | + httpBackend.whenGET(url).respond({ | |
17 | + 'article':{'id':103358,'abstract':'\u003Cp style=\"text-align: center;\"\u003E\u003Ciframe src=\"https://www.youtube.com/embed/kpAdrO-emV0?rel=0\u0026amp;showinfo=0\u0026amp;iv_load_policy=3\u0026amp;controls=1\" style=\"max-width: 1000px; left: 5%;\" width=\"275\" height=\"200\"\u003E\u003C/iframe\u003E\u003C/p\u003E','title':'Dialoga Brasil','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null},{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null},{'name':'Educa\u00e7\u00e3o','id':181,'slug':'educacao','image':null},{'name':'Redu\u00e7\u00e3o da Pobreza','id':183,'slug':'reducao-da-pobreza','image':null}],'image':null,'setting':{'custom_body_label':'Corpo','phase':'proposals','allow_topics':true,'moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Leandro Nunes dos Santos','moderate_proposals':true,'allow_members_to_edit':false},'position':null,'children':[{'id':103644,'abstract':'\u003Cp\u003EUm caminho de oportunidades com o Enem: Sisu, Prouni, Fies, Ci\u00eancia sem Fronteiras\u003C/p\u003E','title':'Ensino Superior','categories':[{'name':'Educa\u00e7\u00e3o','id':181,'slug':'educacao','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0128/enem.jpg'},'setting':{'color':'#cfe2f3','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':9},{'id':103673,'abstract':'\u003Cp\u003EA melhor escolha \u00e9 se informar.\u003C/p\u003E','title':'Incentivo ao Parto Normal','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0092/parto-normal.jpg'},'setting':{'color':'#ff0000','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':6},{'id':103397,'abstract':'\u003Cp\u003ERenda, inclus\u00e3o produtiva e acesso a servi\u00e7os.\u003C/p\u003E','title':'Brasil Sem Mis\u00e9ria','categories':[{'name':'Redu\u00e7\u00e3o da Pobreza','id':183,'slug':'reducao-da-pobreza','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0116/bsm_redim.jpg'},'setting':{'color':'','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':18},{'id':103379,'abstract':'\u003Cp\u003EResgate e atendimento 24 horas, sete dias da semana.\u003C/p\u003E','title':'SAMU 192 e UPAs','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0060/SAMU.jpg'},'setting':{'color':'#45818e','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':4},{'id':103521,'abstract':'\u003Cp\u003EMais atendimento nos munic\u00edpios, mais sa\u00fade para quem mais precisa.\u003C/p\u003E','title':'Mais M\u00e9dicos','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0025/Mais_M_dicos.jpg'},'setting':{'color':'#ffe599','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':1},{'id':103390,'abstract':'\u003Cp\u003EPreven\u00e7\u00e3o, tratamento e enfrentamento ao tr\u00e1fico.\u003C/p\u003E','title':'Crack, \u00e9 poss\u00edvel vencer!','categories':[{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0104/crack.jpg'},'setting':{'color':'#00ff00','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':14},{'id':103592,'abstract':'\u003Cp\u003EGarantir acesso \u00e0 prote\u00e7\u00e3o social.\u003C/p\u003E','title':'Assist\u00eancia Social','categories':[{'name':'Redu\u00e7\u00e3o da Pobreza','id':183,'slug':'reducao-da-pobreza','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0122/assistencia_social.jpg'},'setting':{'color':'#a61c00','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':19},{'id':103426,'abstract':'\u003Cp\u003EDa sa\u00fade se cuida todos os dias.\u003C/p\u003E','title':'Vida saud\u00e1vel','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0046/vida_saudavel.jpg'},'setting':{'color':'#d9d2e9','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':7},{'id':103695,'abstract':'\u003Cp\u003ENovo modelo de atua\u00e7\u00e3o em Seguran\u00e7a P\u00fablica.\u003C/p\u003E','title':'Seguran\u00e7a P\u00fablica Integrada','categories':[{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0152/policiaintegrada.jpg'},'setting':{'color':'#ff00ff','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':13},{'id':103663,'abstract':'\u003Cp\u003EMais educa\u00e7\u00e3o profissional e tecnol\u00f3gica, mais desenvolvimento\u003C/p\u003E','title':'Ensino T\u00e9cnico','categories':[{'name':'Educa\u00e7\u00e3o','id':181,'slug':'educacao','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0134/Ensino_tecnico.jpg'},'setting':{'color':'#d0e0e3','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':10},{'id':103472,'abstract':'\u003Cp\u003EPol\u00edcia Federal, Pol\u00edcia Rodovi\u00e1ria Federal e For\u00e7a Nacional de Seguran\u00e7a P\u00fablica.\u003C/p\u003E','title':'For\u00e7as Federais de Seguran\u00e7a','categories':[{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0031/federais2.png'},'setting':{'color':'','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':16},{'id':103612,'abstract':'\u003Cp\u003EGarantir \u00e1gua para beber e produzir.\u003C/p\u003E','title':'Cisternas','categories':[{'name':'Redu\u00e7\u00e3o da Pobreza','id':183,'slug':'reducao-da-pobreza','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0039/cisterna_redim.jpg'},'setting':{'color':'#0000ff','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':20},{'id':103442,'abstract':'\u003Cp\u003EComplemento \u00e0 renda e acompanhamento em educa\u00e7\u00e3o e sa\u00fade.\u003C/p\u003E','title':'Bolsa Fam\u00edlia','categories':[{'name':'Redu\u00e7\u00e3o da Pobreza','id':183,'slug':'reducao-da-pobreza','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0013/bolsa_familia_redim.jpg'},'setting':{'color':'#ff9900','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':17},{'id':103507,'abstract':'\u003Cp\u003ETecnologia a servi\u00e7o da seguran\u00e7a do cidad\u00e3o.\u003C/p\u003E','title':'Sinesp','categories':[{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0098/sinesp.png'},'setting':{'color':'#00ff00','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':12},{'id':103683,'abstract':'\u003Cp\u003ESa\u00fade n\u00e3o tem pre\u00e7o.\u003C/p\u003E','title':'Aqui tem Farm\u00e1cia Popular','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0019/saude_nao_tem_preco.jpg'},'setting':{'color':'#e69138','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':5},{'id':103457,'abstract':'\u003Cp\u003EA\u00e7\u00e3o conjunta e coopera\u00e7\u00e3o transfronteiri\u00e7a.\u003C/p\u003E','title':'Prote\u00e7\u00e3o das Fronteiras','categories':[{'name':'Seguran\u00e7a P\u00fablica','id':182,'slug':'seguranca-publica','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0110/fronteira_redim.jpg'},'setting':{'color':'#a64d79','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':15},{'id':103494,'abstract':'\u003Cp\u003EDa Educa\u00e7\u00e3o Infantil ao Ensino M\u00e9dio.\u003C/p\u003E','title':'Educa\u00e7\u00e3o B\u00e1sica','categories':[{'name':'Educa\u00e7\u00e3o','id':181,'slug':'educacao','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0076/Educa__o_B_sica.jpg'},'setting':{'color':'#fce5cd','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':8},{'id':103359,'abstract':'\u003Cp\u003EAcesso a exames e consultas com especialistas.\u003C/p\u003E','title':'Mais Especialidades','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0083/mais_especialidades1.png'},'setting':{'color':'#ea9999','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':2},{'id':103485,'abstract':'\u003Cp\u003ECaminho para uma educa\u00e7\u00e3o de qualidade.\u003C/p\u003E','title':'Valoriza\u00e7\u00e3o dos Professores','categories':[{'name':'Educa\u00e7\u00e3o','id':181,'slug':'educacao','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0140/valorizacao_professor.jpg'},'setting':{'color':'#ffff00','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':11},{'id':103416,'abstract':'\u003Cp\u003EEstrutura adequada para atender melhor a popula\u00e7\u00e3o na aten\u00e7\u00e3o b\u00e1sica.\u003C/p\u003E','title':'Melhorar os Postos de Sa\u00fade','categories':[{'name':'Sa\u00fade','id':180,'slug':'saude','image':null}],'image':{'url':'/image_uploads/dialoga/0000/0053/requalif_redim.jpg'},'setting':{'color':'#cc4125','moderate_comments':false,'comment_paragraph_plugin_activate':false,'author_name':'Ronald Emerson Scherolt da Costa','allow_members_to_edit':false},'position':3}]}}); | |
18 | + | |
19 | + ArticleService.getHome(function(result){ | |
20 | + expect(result.article).toBeDefined(); | |
21 | + expect(result.article.title).toEqual('Dialoga Brasil'); | |
22 | + expect(result.article.categories).toBeDefined(); | |
23 | + }); | |
24 | + | |
25 | + httpBackend.flush(); | |
26 | + }); | |
27 | + | |
28 | + // it('should return a list of articles', function() { | |
29 | + | |
30 | + // httpBackend.whenGET('http://login.dialoga.gov.br/api/v1/articles').respond({ | |
31 | + // "articles": [ | |
32 | + // { | |
33 | + // abstract: "Que exista educação continuada permanente dos profissionais!!", | |
34 | + // author: null, | |
35 | + // body: "", | |
36 | + // categories: [], | |
37 | + // children: [], | |
38 | + // created_at: "2015/08/04 16:36:13", | |
39 | + // end_date: null, | |
40 | + // hits: 0, | |
41 | + // id: 120568, | |
42 | + // image: null, | |
43 | + // parent: {id: 103379,…}, | |
44 | + // position: null, | |
45 | + // profile: {identifier: "dialoga", name: "dialoga", id: 19195, created_at: "2015/04/15 09:38:36", image: null}, | |
46 | + // setting: {comment_paragraph_plugin_activate: false, author_name: "estacio"}, | |
47 | + // start_date: null, | |
48 | + // tag_list: [], | |
49 | + // title: "article_f4f4601c-0f36-e90e-d01a-9871f0bd126b", | |
50 | + // votes_against: 0, | |
51 | + // votes_for: 0, | |
52 | + // } | |
53 | + // ] | |
54 | + // }); | |
55 | + | |
56 | + // ArticleService.getList().then(function(result) { | |
57 | + // console.log('result', result); | |
58 | + | |
59 | + // expect(result.data.article).toBeDefined(); | |
60 | + // expect(result.data.article.title).toEqual('Dialoga Brasil'); | |
61 | + | |
62 | + // }); | |
63 | + | |
64 | + // httpBackend.flush(); | |
65 | + // }); | |
66 | + }); | |
67 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,60 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('authUser', authUser); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function authUser() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function AuthUserController($scope, AuthService, Session, AUTH_EVENTS, $log) { | |
13 | + $log.debug('AuthUserController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + | |
17 | + vm.$scope = $scope; | |
18 | + vm.AuthService = AuthService; | |
19 | + vm.Session = Session; | |
20 | + vm.AUTH_EVENTS = AUTH_EVENTS; | |
21 | + vm.$log = $log; | |
22 | + | |
23 | + vm.init(); | |
24 | + } | |
25 | + | |
26 | + AuthUserController.prototype.init = function (){ | |
27 | + var vm = this; | |
28 | + | |
29 | + vm.currentUser = vm.Session.getCurrentUser(); | |
30 | + | |
31 | + // handle login | |
32 | + vm.$scope.$on(vm.AUTH_EVENTS.loginSuccess, function () { | |
33 | + vm.currentUser = vm.Session.getCurrentUser(); | |
34 | + }); | |
35 | + | |
36 | + // handle logout | |
37 | + vm.$scope.$on(vm.AUTH_EVENTS.logoutSuccess, function () { | |
38 | + vm.currentUser = vm.Session.getCurrentUser(); | |
39 | + }); | |
40 | + }; | |
41 | + | |
42 | + AuthUserController.prototype.onClickLogout = function (){ | |
43 | + var vm = this; | |
44 | + | |
45 | + vm.AuthService.logout(); | |
46 | + }; | |
47 | + | |
48 | + var directive = { | |
49 | + restrict: 'E', | |
50 | + templateUrl: 'app/components/auth-user/auth-user.html', | |
51 | + controller: AuthUserController, | |
52 | + controllerAs: 'vm', | |
53 | + bindToController: true | |
54 | + }; | |
55 | + | |
56 | + return directive; | |
57 | + | |
58 | + } | |
59 | + | |
60 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +<div class="auth-user"> | |
2 | + <div ng-if="vm.currentUser" class="pull-right"> | |
3 | + <span ng-if="vm.currentUser.person">{{::vm.currentUser.person.name}}</span> | |
4 | + <span ng-if="!vm.currentUser.person">{{::vm.currentUser.login}}</span> | |
5 | + <span>|</span> | |
6 | + <button type="button" class="btn btn-link" ng-click="vm.onClickLogout()">Sair</button> | |
7 | + </div> | |
8 | + | |
9 | + <div ng-if="!vm.currentUser"> | |
10 | + <button type="button" class="btn btn-link pull-right" ui-sref="entrar">Entrar</button> | |
11 | + </div> | |
12 | +</div> | ... | ... |
src/app/components/auth/auth.service.js
... | ... | @@ -8,20 +8,129 @@ |
8 | 8 | .factory('AuthInterceptor', AuthInterceptor); |
9 | 9 | |
10 | 10 | /** @ngInject */ |
11 | - function AuthService($http, $rootScope, Session, AUTH_EVENTS, api, $log) { | |
11 | + function AuthService($q, $http, $rootScope, Session, AUTH_EVENTS, API, PATH, $log) { | |
12 | 12 | |
13 | - var service = { | |
14 | - login: login, | |
15 | - logout: logout, | |
16 | - isAuthenticated: isAuthenticated, | |
17 | - isAuthorized: isAuthorized | |
18 | - }; | |
13 | + function register (data){ | |
14 | + var url = PATH.host + '/api/v1/register'; | |
15 | + $log.debug('data', data); | |
16 | + // var encodedData = data; | |
17 | + var encodedData = ''; | |
18 | + encodedData += 'name=' + data.name; | |
19 | + encodedData += '&email=' + data.email; | |
20 | + encodedData += '&login=' + data.email.substr(0, data.email.indexOf('@')).toLowerCase().replace(/\W+/g,'').substr(0,25) + '-' + Date.now(); | |
21 | + encodedData += '&email=' + data.email; | |
22 | + encodedData += '&password=' + data.password; | |
23 | + encodedData += '&password_confirmation=' + data.password_confirmation; | |
24 | + encodedData += '&user_terms_accepted=' + data.user_terms_accepted; | |
25 | + encodedData += '&captcha_text=' + data.captcha_text; | |
26 | + encodedData += '&txtToken_captcha_serpro_gov_br=' + data.txtToken_captcha_serpro_gov_br; | |
19 | 27 | |
20 | - $log.debug('AuthService', service); | |
21 | - return service; | |
28 | + // var encodedData = _encodeObj(data); | |
29 | + // var encodedData = angular.element.param(data); | |
30 | + // '&email=&login=&name=&password=&password_confirmation'; | |
31 | + // oauth_providers | |
32 | + // oauth_signup_token | |
33 | + // captcha_text | |
34 | + // user_terms_accepted | |
35 | + | |
36 | + return $http.post(url, encodedData) | |
37 | + .then(function(response) { | |
38 | + $log.debug('AuthService.register [SUCCESS] response', response); | |
39 | + | |
40 | + var currentUser = Session.create(response.data); | |
41 | + | |
42 | + $rootScope.currentUser = currentUser; | |
43 | + $rootScope.$broadcast(AUTH_EVENTS.registerSuccess, currentUser); | |
44 | + $rootScope.$broadcast(AUTH_EVENTS.loginSuccess, currentUser); | |
45 | + | |
46 | + return response; | |
47 | + }, function(response) { | |
48 | + $log.debug('AuthService.register [FAIL] response', response); | |
49 | + | |
50 | + $rootScope.$broadcast(AUTH_EVENTS.registerFailed, response); | |
51 | + return $q.reject(response); | |
52 | + }); | |
53 | + } | |
54 | + | |
55 | + function activate (code) { | |
56 | + var url = '/api/v1/activate'; | |
57 | + // var data = { | |
58 | + // private_token: API.token, | |
59 | + // activation_code: code | |
60 | + // }; | |
61 | + var encodedData = 'private_token=' + API.token; | |
62 | + encodedData += '&activation_code=' + code; | |
63 | + | |
64 | + return $http | |
65 | + .patch(url, encodedData) | |
66 | + .then(function(response) { | |
67 | + $log.debug('AuthService.activate [SUCCESS] response', response); | |
68 | + | |
69 | + // 'Usuário ativado com sucesso' | |
70 | + $rootScope.$broadcast(AUTH_EVENTS.activateSuccess, response); | |
71 | + return response; | |
72 | + }, function(response) { | |
73 | + // 'Erro: O código de ativação é inválido.' | |
74 | + $log.debug('AuthService.activate [FAIL] response', response); | |
75 | + $rootScope.$broadcast(AUTH_EVENTS.activateFailed); | |
76 | + }); | |
77 | + } | |
78 | + | |
79 | + function changePassword (code, newPassword, newPasswordConfirmation){ | |
80 | + var url = '/api/v1/new_password'; | |
81 | + // var data = { | |
82 | + // code: code, | |
83 | + // password: newPassword, | |
84 | + // password_confirmation: newPasswordConfirmation | |
85 | + // }; | |
86 | + var encodedData = 'code=' + code; | |
87 | + encodedData += '&password=' + newPassword; | |
88 | + encodedData += '&password_confirmation=' + newPasswordConfirmation; | |
89 | + | |
90 | + return $http | |
91 | + .patch(url, encodedData) | |
92 | + .then(function(response) { | |
93 | + $log.debug('AuthService.changePassword [SUCCESS] response', response); | |
94 | + | |
95 | + // 'Senha alterada com sucesso.' | |
96 | + $rootScope.$broadcast(AUTH_EVENTS.changePasswordSuccess, response); | |
97 | + return response; | |
98 | + }, function(response) { | |
99 | + // 'Não foi possível trocar a senha com os dados informados.' | |
100 | + $log.debug('AuthService.changePassword [FAIL] response', response); | |
101 | + $rootScope.$broadcast(AUTH_EVENTS.changePasswordFailed); | |
102 | + }); | |
103 | + } | |
104 | + | |
105 | + function forgotPassword (data){ | |
106 | + var url = 'http://hom.login.dialoga.gov.br/api/v1/forgot_password'; | |
107 | + var encodedData = ([ | |
108 | + 'value=' + data.login, | |
109 | + 'captcha_text=' + data.captcha_text, | |
110 | + 'txtToken_captcha_serpro_gov_br=' + data.txtToken_captcha_serpro_gov_br | |
111 | + ]).join('&'); | |
112 | + | |
113 | + return $http | |
114 | + .post(url, encodedData) | |
115 | + .then(function(response) { | |
116 | + $log.debug('AuthService.forgotPassword [SUCCESS] response', response); | |
117 | + | |
118 | + // 'Verifique seu email para efetuar a troca da senha.' | |
119 | + $rootScope.$broadcast(AUTH_EVENTS.forgotPasswordSuccess, response); | |
120 | + | |
121 | + return response; | |
122 | + }, function(response) { | |
123 | + // 'Não foi possível requisitar a troca de senha para os dados informados.' | |
124 | + $log.debug('AuthService.forgotPassword [FAIL] response', response); | |
125 | + $rootScope.$broadcast(AUTH_EVENTS.forgotPasswordFailed); | |
126 | + | |
127 | + return response; | |
128 | + }); | |
129 | + } | |
22 | 130 | |
23 | 131 | function login (credentials) { |
24 | - var url = api.host + '/api/v1/login'; | |
132 | + var hostProd = 'http://login.dialoga.gov.br'; | |
133 | + var url = hostProd + '/api/v1/login'; | |
25 | 134 | var encodedData = 'login=' + credentials.username + '&password=' + credentials.password; |
26 | 135 | |
27 | 136 | return $http |
... | ... | @@ -30,6 +139,7 @@ |
30 | 139 | $log.debug('AuthService.login [SUCCESS] response', response); |
31 | 140 | |
32 | 141 | var currentUser = Session.create(response.data); |
142 | + $rootScope.currentUser = currentUser; | |
33 | 143 | |
34 | 144 | $rootScope.$broadcast(AUTH_EVENTS.loginSuccess, currentUser); |
35 | 145 | return currentUser; |
... | ... | @@ -40,7 +150,10 @@ |
40 | 150 | } |
41 | 151 | |
42 | 152 | function logout () { |
153 | + | |
43 | 154 | Session.destroy(); |
155 | + $rootScope.currentUser = null; | |
156 | + $rootScope.$broadcast(AUTH_EVENTS.logoutSuccess); | |
44 | 157 | } |
45 | 158 | |
46 | 159 | function isAuthenticated () { |
... | ... | @@ -54,42 +167,62 @@ |
54 | 167 | |
55 | 168 | return (service.isAuthenticated() && authorizedRoles.indexOf(Session.userRole) !== -1); |
56 | 169 | } |
170 | + | |
171 | + // function _encodeObj(obj){ | |
172 | + // var result = []; | |
173 | + // var str = null; | |
174 | + // var p = null; | |
175 | + | |
176 | + // for (p in obj) { | |
177 | + // if (obj.hasOwnProperty(p)) { | |
178 | + // // str = encodeURIComponent(p) + '=' + obj[p]; | |
179 | + // str = p + '=' + obj[p]; | |
180 | + // result.push(str); | |
181 | + // } | |
182 | + // } | |
183 | + | |
184 | + // return result.join('&'); | |
185 | + // } | |
186 | + | |
187 | + var service = { | |
188 | + register: register, | |
189 | + activate: activate, | |
190 | + changePassword: changePassword, | |
191 | + forgotPassword: forgotPassword, | |
192 | + login: login, | |
193 | + logout: logout, | |
194 | + isAuthenticated: isAuthenticated, | |
195 | + isAuthorized: isAuthorized | |
196 | + }; | |
197 | + | |
198 | + $log.debug('AuthService', service); | |
199 | + return service; | |
57 | 200 | } |
58 | 201 | |
59 | 202 | /** @ngInject */ |
60 | - function Session($cookies, $log) { | |
203 | + function Session($localStorage, $log) { | |
61 | 204 | |
62 | 205 | var service = {}; |
63 | 206 | |
64 | - var currentUser = $cookies.getObject('currentUser') || {}; | |
207 | + // $localStorage.currentUser = $localStorage.currentUser || null; | |
65 | 208 | |
66 | 209 | service.create = function(data) { |
67 | 210 | |
68 | - currentUser.id = data.id; | |
69 | - currentUser.email = data.email; | |
70 | - currentUser.login = data.login; | |
71 | - currentUser.permissions = data.permissions; | |
72 | - currentUser.person = data.person; | |
73 | - currentUser.private_token = data.private_token; | |
74 | - currentUser.activated = data.activated; | |
211 | + $localStorage.currentUser = data; | |
212 | + $log.debug('User session created.', $localStorage.currentUser); | |
75 | 213 | |
76 | - $cookies.putObject('currentUser', currentUser); | |
77 | - | |
78 | - $log.debug('User session created.', currentUser); | |
79 | - return currentUser; | |
214 | + return $localStorage.currentUser; | |
80 | 215 | }; |
81 | 216 | |
82 | 217 | service.destroy = function() { |
83 | 218 | |
84 | - currentUser = {}; | |
85 | - | |
86 | - $cookies.remove('currentUser'); | |
219 | + delete $localStorage.currentUser; | |
87 | 220 | |
88 | 221 | $log.debug('User session destroyed.'); |
89 | 222 | }; |
90 | 223 | |
91 | 224 | service.getCurrentUser = function () { |
92 | - return currentUser; | |
225 | + return $localStorage.currentUser; | |
93 | 226 | }; |
94 | 227 | |
95 | 228 | return service; |
... | ... | @@ -110,26 +243,26 @@ |
110 | 243 | }; |
111 | 244 | } |
112 | 245 | |
113 | - /** @ngInject */ | |
114 | - function AuthResolver($q, $rootScope, $state){ | |
115 | - return { | |
116 | - resolve: function () { | |
117 | - var deferred = $q.defer(); | |
118 | - var unwatch = $rootScope.$watch('currentUser', function (currentUser) { | |
119 | - if (angular.isDefined(currentUser)) { | |
120 | - if (currentUser) { | |
121 | - deferred.resolve(currentUser); | |
122 | - } else { | |
123 | - deferred.reject(); | |
124 | - // TODO: too many responsibilities? | |
125 | - $state.go('login'); | |
126 | - } | |
127 | - unwatch(); | |
128 | - } | |
129 | - }); | |
130 | - return deferred.promise; | |
131 | - } | |
132 | - }; | |
133 | - } | |
246 | + // /** @ngInject */ | |
247 | + // function AuthResolver($q, $rootScope, $state){ | |
248 | + // return { | |
249 | + // resolve: function () { | |
250 | + // var deferred = $q.defer(); | |
251 | + // var unwatch = $rootScope.$watch('currentUser', function (currentUser) { | |
252 | + // if (angular.isDefined(currentUser)) { | |
253 | + // if (currentUser) { | |
254 | + // deferred.resolve(currentUser); | |
255 | + // } else { | |
256 | + // deferred.reject(); | |
257 | + // // TODO: too many responsibilities? | |
258 | + // $state.go('login'); | |
259 | + // } | |
260 | + // unwatch(); | |
261 | + // } | |
262 | + // }); | |
263 | + // return deferred.promise; | |
264 | + // } | |
265 | + // }; | |
266 | + // } | |
134 | 267 | |
135 | 268 | })(); | ... | ... |
... | ... | @@ -0,0 +1,27 @@ |
1 | +.custom-breadcrumb { | |
2 | + | |
3 | + .breadcrumb { | |
4 | + background: none; | |
5 | + padding: 0; | |
6 | + margin: 10px 0; | |
7 | + } | |
8 | + | |
9 | + .glyphicon { | |
10 | + color: #1E3E65;; | |
11 | + border: 1px solid #1E3E65; | |
12 | + border-radius: 100%; | |
13 | + width: 23px; | |
14 | + height: 23px; | |
15 | + margin: 0; | |
16 | + padding: 2px 0 0 3px; | |
17 | + } | |
18 | + | |
19 | + .breadcrumb > li + li:before { | |
20 | + content: '\00BB'; | |
21 | + } | |
22 | + | |
23 | + .contraste & .breadcrumb { | |
24 | + background-color: #000; | |
25 | + border: 1px solid #fff; | |
26 | + } | |
27 | +} | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +<div class="custom-breadcrumb"> | |
2 | + <ol class="breadcrumb"> | |
3 | + <li ng-repeat="step in steps | limitTo:(steps.length-1)"> | |
4 | + <a href="{{step.ncyBreadcrumbLink}}" ng-if="$index === 0" ng-class="{'item-home': $index === 0}"> | |
5 | + <span class="glyphicon glyphicon-home" aria-hidden="true"></span> | |
6 | + </a> | |
7 | + <a href="{{step.ncyBreadcrumbLink}}" ng-if="$index !== 0" ng-class="{'item-home': $index === 0}" ng-bind-html="step.ncyBreadcrumbLabel"></a> | |
8 | + </li> | |
9 | + <li ng-repeat="step in steps | limitTo:-1" class="active"> | |
10 | + <span ng-bind-html="step.ncyBreadcrumbLabel"></span> | |
11 | + </li> | |
12 | + </ol> | |
13 | +</div> | ... | ... |
src/app/components/cadastro-proposta/cadastro-proposta.directive.js
0 → 100644
... | ... | @@ -0,0 +1,68 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('cadastroProposta', cadastroProposta); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function cadastroProposta() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function CadastroPropostaController ($scope, $element, $timeout, $log) { | |
13 | + $log.debug('cadastroPropostaController'); | |
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 | + CadastroPropostaController.prototype.init = function () { | |
25 | + // async values | |
26 | + var vm = this; | |
27 | + | |
28 | + // requeue to wait until DOM be created | |
29 | + vm.$timeout(function(){ | |
30 | + attachPopover.call(vm); | |
31 | + }, 200); | |
32 | + }; | |
33 | + | |
34 | + CadastroPropostaController.prototype.sendProposal = function (proposal) { | |
35 | + var vm = this; | |
36 | + | |
37 | + // notify parents - handled by parents | |
38 | + vm.$scope.$emit('cadastro-proposa:startSendProposal', proposal); | |
39 | + }; | |
40 | + | |
41 | + function attachPopover(){ | |
42 | + var vm = this; | |
43 | + | |
44 | + vm.popover = angular.element(vm.$element.find('.btn-question')); | |
45 | + vm.popover.popover({ | |
46 | + html: true, | |
47 | + placement: 'bottom', | |
48 | + animation: true, | |
49 | + title: 'Regra de posição das propostas', | |
50 | + content: '<p>Poderia escrever a sua proposta em um texto simples e breve?</p><br><p>Sua proposta passará pela fase de moderação. Assim que ela estiver pronta para compartilhar, avisaremos você.' | |
51 | + }); | |
52 | + } | |
53 | + | |
54 | + var directive = { | |
55 | + restrict: 'E', | |
56 | + templateUrl: 'app/components/cadastro-proposta/cadastro-proposta.html', | |
57 | + scope: { | |
58 | + program: '=' | |
59 | + }, | |
60 | + controller: CadastroPropostaController, | |
61 | + controllerAs: 'vm', | |
62 | + bindToController: true | |
63 | + }; | |
64 | + | |
65 | + return directive; | |
66 | + } | |
67 | + | |
68 | +})(); | ... | ... |
src/app/components/cadastro-proposta/cadastro-proposta.html
0 → 100644
... | ... | @@ -0,0 +1,46 @@ |
1 | +<div id="message" class="envio-proposta"> | |
2 | + <div class="row linha-proposta"> | |
3 | + <div class="col-sm-8"> | |
4 | + <span class="titulo-envio-proposta">Faça sua proposta</span> | |
5 | + <p> | |
6 | + Aqui você cadastra sua proposta e ajuda a construir um Brasil melhor. | |
7 | + </p> | |
8 | + </div> | |
9 | + </div> | |
10 | + <div class="row linha-proposta"> | |
11 | + <div class="col-sm-8"> | |
12 | + <p>Você está fazendo uma proposta para o programa:</p> | |
13 | + <div class="bloco-programa"> | |
14 | + <span class="texto-programa">{{::vm.program.title}}</span> | |
15 | + </div> | |
16 | + </div> | |
17 | + </div> | |
18 | + <form role="form" name="formPropostas" ng-submit="vm.sendProposal(proposta)" novalidate> | |
19 | + <div class="form-group"> | |
20 | + <div class="row linha-proposta"> | |
21 | + <div class="col-sm-8"> | |
22 | + <label for="proposta-textarea">Descrição da proposta*</label> | |
23 | + <a tabindex="0" class="btn btn-link btn-question" role="button" data-toggle="popover" data-trigger="focus">?</a> | |
24 | + <textarea id="proposta-textarea" name="proposta" class="texto-proposta form-control" | |
25 | + ng-class="{ 'has-error' : formPropostas.proposta.$invalid && formPropostas.proposta.$touched }" | |
26 | + ng-model="proposta" | |
27 | + required ng-maxlength="200" ></textarea> | |
28 | + <validation-messages field="formPropostas.proposta" maxlength="'Ops, esse campo não pode ser maior que 200 caracteres.'"></validation-messages> | |
29 | + <div class="row"> | |
30 | + <div class="col-xs-6"> | |
31 | + <span>*Dados obrigatórios</span> | |
32 | + </div> | |
33 | + <div class="col-xs-6 text-right"> | |
34 | + <span>Máx. 200 caracteres</span> | |
35 | + </div> | |
36 | + </div> | |
37 | + </div> | |
38 | + </div> | |
39 | + </div> | |
40 | + <div class="form-group"> | |
41 | + <div class="col-sm-4"> | |
42 | + <button class="btn btn-lg btn-block btn-submit" type="submit">Enviar Proposta</button> | |
43 | + </div> | |
44 | + </div> | |
45 | + </form> | |
46 | +</div> | ... | ... |
src/app/components/cadastro-proposta/cadastro-proposta.scss
0 → 100644
... | ... | @@ -0,0 +1,49 @@ |
1 | +.envio-proposta { | |
2 | + | |
3 | + .titulo-envio-proposta{ | |
4 | + color: #2D7B66; | |
5 | + font-size: 30px | |
6 | + } | |
7 | + | |
8 | + .bloco-programa { | |
9 | + border-color: gray; | |
10 | + border-width: 1px; | |
11 | + border-style: solid; | |
12 | + border-radius: 5px; | |
13 | + padding: 15px; | |
14 | + } | |
15 | + | |
16 | + .texto-programa { | |
17 | + font-weight: 600; | |
18 | + } | |
19 | + | |
20 | + .linha-proposta { | |
21 | + margin-bottom: 40px; | |
22 | + } | |
23 | + | |
24 | + .texto-proposta { | |
25 | + width: 100%; | |
26 | + height: 200px; | |
27 | + resize: none; | |
28 | + } | |
29 | + | |
30 | + .popover .fade .right .in { | |
31 | + top: 0px!important; | |
32 | + } | |
33 | + | |
34 | + .popover-content { | |
35 | + width: 300px; | |
36 | + } | |
37 | + | |
38 | + .popover-title { | |
39 | + display: none; | |
40 | + } | |
41 | + | |
42 | + .link-popover { | |
43 | + font-size: 15px; | |
44 | + color: gray; | |
45 | + padding: 0px 7px; | |
46 | + border-style: none; | |
47 | + } | |
48 | + | |
49 | +} | ... | ... |
src/app/components/category-list/category-list.directive.js
0 → 100644
... | ... | @@ -0,0 +1,95 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('categoryList', categoryList); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function categoryList() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function CategoryListController($rootScope, $element, $log) { | |
13 | + $log.debug('CategoryListController'); | |
14 | + | |
15 | + // alias | |
16 | + var vm = this; | |
17 | + | |
18 | + // dependencies | |
19 | + vm.$rootScope = $rootScope; | |
20 | + vm.$element = $element; | |
21 | + vm.$log = $log; | |
22 | + | |
23 | + // initialization | |
24 | + vm.init(); | |
25 | + } | |
26 | + | |
27 | + CategoryListController.prototype.init = function() { | |
28 | + var vm = this; | |
29 | + | |
30 | + if(!vm.isCollapsed){ | |
31 | + vm.isCollapsed = false; | |
32 | + } | |
33 | + }; | |
34 | + | |
35 | + CategoryListController.prototype._disableUnselect = function() { | |
36 | + var vm = this; | |
37 | + | |
38 | + if(vm.disableUnselect && vm.disableUnselect === 'true'){ | |
39 | + return true; | |
40 | + } | |
41 | + | |
42 | + return false; | |
43 | + }; | |
44 | + | |
45 | + | |
46 | + CategoryListController.prototype.selectCategory = function(category, $event) { | |
47 | + var vm = this; | |
48 | + | |
49 | + // prevent glitch | |
50 | + $event.stopPropagation(); | |
51 | + | |
52 | + if (category !== vm.selectedCategory) { | |
53 | + vm.selectedCategory = category; | |
54 | + }else{ | |
55 | + | |
56 | + if(vm._disableUnselect()){ | |
57 | + vm.$log.info('Unselect is disabled.'); | |
58 | + return; | |
59 | + } | |
60 | + | |
61 | + vm.selectedCategory = null; | |
62 | + } | |
63 | + | |
64 | + // send event to all controllers | |
65 | + vm.$rootScope.$broadcast('change-selectedCategory', vm.selectedCategory); | |
66 | + }; | |
67 | + | |
68 | + | |
69 | + CategoryListController.prototype.toogleList = function() { | |
70 | + var vm = this; | |
71 | + | |
72 | + if(!vm._listGroup){ | |
73 | + vm._listGroup = vm.$element.find('.list-group'); | |
74 | + } | |
75 | + | |
76 | + vm._listGroup.slideToggle(); | |
77 | + }; | |
78 | + | |
79 | + var directive = { | |
80 | + restrict: 'E', | |
81 | + templateUrl: 'app/components/category-list/category-list.html', | |
82 | + scope: { | |
83 | + categories: '=', | |
84 | + selectedCategory: '=', | |
85 | + disableUnselect: '@' | |
86 | + }, | |
87 | + controller: CategoryListController, | |
88 | + controllerAs: 'vm', | |
89 | + bindToController: true | |
90 | + }; | |
91 | + | |
92 | + return directive; | |
93 | + } | |
94 | + | |
95 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +<div class="category-list"> | |
2 | + <nav class="navigation"> | |
3 | + <h3 class="category-list--title" ng-click="vm.toogleList()"> | |
4 | + <span class="hidden-xs"><b>Programas</b> por Tema</span> | |
5 | + <span class="visible-xs"><b>Filtrar</b> por Tema <span class="glyphicon glyphicon-filter pull-right"></span></span> | |
6 | + </h3> | |
7 | + | |
8 | + <!-- <div class="list-group ng-hide" ng-show="!vm.isCollapsed" ng-class="vm.selectedCategory.slug"> --> | |
9 | + <div class="list-group" ng-class="vm.selectedCategory.slug"> | |
10 | + <button type="button" class="list-group-item category-list--item" | |
11 | + ng-repeat="category in vm.categories" | |
12 | + ng-class="{active: vm.selectedCategory.slug === category.slug}" | |
13 | + ng-click="vm.selectCategory(category, $event)"> | |
14 | + | |
15 | + <span class="category-list--icon-circle" aria-hidden="true" ng-class="category.slug"></span> | |
16 | + <span class="category-list--icon icon" aria-hidden="true" ng-class="'icon-tema-' + category.slug + '-small'"></span> | |
17 | + <span class="category-list--label">{{::category.name}}</span> | |
18 | + <span class="category-list--icon--right glyphicon glyphicon-chevron-right hidden-xs" ng-hide="vm.selectedCategory.slug === category.slug"></span> | |
19 | + <span class="category-list--icon--right glyphicon glyphicon-remove hidden-xs" ng-show="vm.selectedCategory.slug === category.slug"></span> | |
20 | + </button> | |
21 | + </div> | |
22 | + </nav> | |
23 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,116 @@ |
1 | +.category-list { | |
2 | + &--title { | |
3 | + color: #ffffff; | |
4 | + font-size: 16px; | |
5 | + margin: 0; | |
6 | + padding: 20px; | |
7 | + background-color: #484848; | |
8 | + border-top-left-radius: 5px; | |
9 | + border-top-right-radius: 5px; | |
10 | + overflow: hidden; | |
11 | + cursor: pointer; | |
12 | + } | |
13 | + | |
14 | + .category-list--item { | |
15 | + position: relative; | |
16 | + text-transform: uppercase; | |
17 | + font-weight: bold; | |
18 | + padding: 0; | |
19 | + height: 68px; | |
20 | + overflow: hidden; | |
21 | + } | |
22 | + | |
23 | + | |
24 | + | |
25 | + .category-list--label { | |
26 | + margin-left: 70px; | |
27 | + margin-right: 30px; | |
28 | + display: inline-block; | |
29 | + z-index: 99999; | |
30 | + } | |
31 | + | |
32 | + &--icon-circle { | |
33 | + width: 48px; | |
34 | + height: 48px; | |
35 | + position: absolute; | |
36 | + top: 10px; | |
37 | + left: 10px; | |
38 | + // border: 1px solid #fff; | |
39 | + border-radius: 100%; | |
40 | + | |
41 | + -webkit-transition: -webkit-transform 0.2s ease-in-out; | |
42 | + -moz-transition: -moz-transform 0.2s ease-in-out; | |
43 | + -o-transition: -o-transform 0.2s ease-in-out; | |
44 | + transition: transform 0.2s ease-in-out; | |
45 | + | |
46 | + // -webkit-transition: all 0.2s ease-in-out; | |
47 | + // -moz-transition: all 0.2s ease-in-out; | |
48 | + // -o-transition: all 0.2s ease-in-out; | |
49 | + // transition: all 0.2s ease-in-out; | |
50 | + | |
51 | + z-index: 0; | |
52 | + | |
53 | + .active & { | |
54 | + z-index: -1; | |
55 | + | |
56 | + @media (max-width: $screen-xs) { | |
57 | + transform: scale(20); | |
58 | + } | |
59 | + | |
60 | + @media (min-width: $screen-xs + 1) { | |
61 | + transform: scale(40); | |
62 | + } | |
63 | + | |
64 | + @media (min-width: $screen-sm + 1) { | |
65 | + transform: scale(20); | |
66 | + } | |
67 | + | |
68 | + // @media (min-width: $screen-md + 1) { | |
69 | + // transform: scale(20); | |
70 | + // } | |
71 | + } | |
72 | + | |
73 | + @each $category, $color in $categories { | |
74 | + &.#{$category} { | |
75 | + background-color: $color; | |
76 | + } | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + .category-list--icon { | |
81 | + position: absolute; | |
82 | + top: 6px; | |
83 | + left: 6px; | |
84 | + // transform: scale(0.4); | |
85 | + } | |
86 | + | |
87 | + .category-list--icon--right { | |
88 | + position: absolute; | |
89 | + right: 9px; | |
90 | + top: 50%; | |
91 | + margin-top: -9px; | |
92 | + transform: scale(1.4); | |
93 | + } | |
94 | + | |
95 | + .list-group { | |
96 | + | |
97 | + -webkit-transition: -webkit-transform .3s ease-in-out; | |
98 | + -moz-transition: -moz-transform .3s ease-in-out; | |
99 | + -o-transition: -o-transform .3s ease-in-out; | |
100 | + transition: transform .3s ease-in-out; | |
101 | + | |
102 | + opacity: 1; | |
103 | + | |
104 | + &.ng-hide { | |
105 | + opacity: 0; | |
106 | + // height: 0; | |
107 | + // line-height: 0; | |
108 | + } | |
109 | + } | |
110 | + | |
111 | + .list-group-item.active, | |
112 | + .list-group-item.active:hover, | |
113 | + .list-group-item.active:focus { | |
114 | + background-color: #f5f5f5; | |
115 | + } | |
116 | +} | ... | ... |
... | ... | @@ -0,0 +1,435 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .factory('DialogaService', DialogaService); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function DialogaService($rootScope, $sce, API, ArticleService, UtilService, Slug, $log) { | |
10 | + $log.debug('DialogaService'); | |
11 | + | |
12 | + var extendedService = angular.extend({}, ArticleService); | |
13 | + | |
14 | + extendedService.serviceDialoga = $rootScope.basePath + '/api/v1/dialoga_plugin/'; | |
15 | + extendedService.getHome = getHome; | |
16 | + extendedService.getAbout = getAbout; | |
17 | + extendedService.getTerms = getTerms; | |
18 | + extendedService.getThemes = getThemes; | |
19 | + extendedService.getThemeBySlug = getThemeBySlug; | |
20 | + extendedService.getPrograms = getPrograms; | |
21 | + extendedService.getProgramBySlug = getProgramBySlug; | |
22 | + extendedService.getProgramsByThemeId = getProgramsByThemeId; | |
23 | + extendedService.getProgramsRandom = getProgramsRandom; | |
24 | + extendedService.getEvents = getEvents; // override | |
25 | + extendedService.getQuestions = getQuestions; | |
26 | + extendedService.searchPrograms = searchPrograms; | |
27 | + extendedService.searchProposals = searchProposals; | |
28 | + extendedService.filterProposalsByCategorySlug = filterProposalsByCategorySlug; | |
29 | + extendedService.filterProposalsByProgramId = filterProposalsByProgramId; | |
30 | + | |
31 | + var CACHE = {}; | |
32 | + | |
33 | + return extendedService; | |
34 | + | |
35 | + function getHome (cbSuccess, cbError) { | |
36 | + if( !!CACHE.home ){ | |
37 | + cbSuccess(CACHE.home); | |
38 | + }else{ | |
39 | + // load main content | |
40 | + ArticleService.getArticleById(API.articleId.home, { | |
41 | + 'fields[]': ['id','abstract','body','categories','children','children_count','title','slug','image','url'], | |
42 | + 'content_type':'ProposalsDiscussionPlugin::DiscussionTopic' | |
43 | + }, function (data){ | |
44 | + CACHE.home = data; | |
45 | + | |
46 | + _pipeHandleYoutube(data); | |
47 | + _pipeHandleSlug(data); | |
48 | + _pipeSetThemes(data); | |
49 | + _pipeSetPrograms(data); | |
50 | + | |
51 | + cbSuccess(data); | |
52 | + }, cbError); | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + function getAbout (cbSuccess, cbError) { | |
57 | + if( !!CACHE.about ){ | |
58 | + cbSuccess(CACHE.about); | |
59 | + }else{ | |
60 | + // load article content | |
61 | + ArticleService.getArticleById(API.articleId.about, {}, function (article){ | |
62 | + CACHE.about = article; | |
63 | + | |
64 | + cbSuccess(CACHE.about); | |
65 | + }, cbError); | |
66 | + } | |
67 | + } | |
68 | + | |
69 | + function getTerms (cbSuccess, cbError) { | |
70 | + if( !!CACHE.terms ){ | |
71 | + cbSuccess(CACHE.terms); | |
72 | + }else{ | |
73 | + // load article content | |
74 | + ArticleService.getArticleById(API.articleId.terms, {}, function (article){ | |
75 | + CACHE.terms = article; | |
76 | + | |
77 | + cbSuccess(CACHE.terms); | |
78 | + }, cbError); | |
79 | + } | |
80 | + } | |
81 | + | |
82 | + function getThemes (cbSuccess, cbError) { | |
83 | + if( !!CACHE.themes ){ | |
84 | + cbSuccess(CACHE.themes); | |
85 | + }else{ | |
86 | + // load main content | |
87 | + getHome(function(){ | |
88 | + if(!CACHE.hasOwnProperty('themes')){ | |
89 | + throw { name: 'NotFound', message: '"themes" is not defined. "article.categories" was loaded?'}; | |
90 | + } | |
91 | + cbSuccess(CACHE.themes); | |
92 | + },cbError); | |
93 | + } | |
94 | + } | |
95 | + | |
96 | + function getThemeBySlug (slug, cbSuccess, cbError) { | |
97 | + if( !!CACHE.themes ){ | |
98 | + _getThemeBySlug(CACHE.themes); | |
99 | + }else{ | |
100 | + getThemes(_getThemeBySlug, cbError); | |
101 | + } | |
102 | + | |
103 | + function _getThemeBySlug () { | |
104 | + var result = null; | |
105 | + | |
106 | + for (var i = CACHE.themes.length - 1; i >= 0; i--) { | |
107 | + var theme = CACHE.themes[i]; | |
108 | + | |
109 | + if(theme && theme.slug && theme.slug === slug){ | |
110 | + result = theme; | |
111 | + break; | |
112 | + } | |
113 | + } | |
114 | + | |
115 | + cbSuccess(result); | |
116 | + } | |
117 | + } | |
118 | + | |
119 | + function getPrograms (cbSuccess, cbError) { | |
120 | + if( !!CACHE.programs ){ | |
121 | + cbSuccess(CACHE.programs); | |
122 | + }else{ | |
123 | + // load main content | |
124 | + getHome(function(){ | |
125 | + if(!CACHE.hasOwnProperty('programs')){ | |
126 | + throw { name: 'NotFound', message: '"programs" is not defined. "article.children" was handled?'}; | |
127 | + } | |
128 | + cbSuccess(CACHE.programs); | |
129 | + },cbError); | |
130 | + } | |
131 | + } | |
132 | + | |
133 | + function getProgramBySlug (slug, cbSuccess, cbError) { | |
134 | + | |
135 | + if( !CACHE.programs ){ | |
136 | + getPrograms(_getProgramBySlug, cbError); | |
137 | + } else { | |
138 | + _getProgramBySlug(); | |
139 | + } | |
140 | + | |
141 | + function _getProgramBySlug(){ | |
142 | + var result = CACHE.programs.filter(function filterProgramBySlug (program) { | |
143 | + if(angular.equals(program.slug, slug)) { | |
144 | + return true; | |
145 | + } | |
146 | + return false; | |
147 | + }); | |
148 | + | |
149 | + cbSuccess(result[0]); | |
150 | + } | |
151 | + } | |
152 | + | |
153 | + function getProgramsByThemeId (themeId, cbSuccess, cbError) { | |
154 | + | |
155 | + if( !CACHE.programs ){ | |
156 | + getPrograms(_getProgramsByThemeId, cbError); | |
157 | + } else { | |
158 | + _getProgramsByThemeId(); | |
159 | + } | |
160 | + | |
161 | + function _getProgramsByThemeId(){ | |
162 | + var result = CACHE.programs.filter(function filterProgramBySlug (program) { | |
163 | + var category = program.categories[0]; | |
164 | + | |
165 | + if(category && angular.equals(category.id, themeId)) { | |
166 | + return true; | |
167 | + } | |
168 | + return false; | |
169 | + }); | |
170 | + | |
171 | + cbSuccess(result); | |
172 | + } | |
173 | + } | |
174 | + | |
175 | + // Ex.: /api/v1/dialoga_plugin/random_topics/103358 | |
176 | + // TODO: get endpoint for production | |
177 | + // TODO: put at cache? | |
178 | + function getProgramsRandom(params, cbSuccess, cbError) { | |
179 | + | |
180 | + if( !!CACHE.programsRandom ){ | |
181 | + cbSuccess(CACHE.programsRandom); | |
182 | + }else{ | |
183 | + var mapFromCache = !!CACHE.programs; | |
184 | + | |
185 | + var url = extendedService.serviceDialoga + 'random_topics/' + API.articleId.home; | |
186 | + var fields = null; | |
187 | + | |
188 | + if (mapFromCache){ | |
189 | + // get only references | |
190 | + fields = ['id', 'title', 'slug']; | |
191 | + }else{ | |
192 | + // get all content | |
193 | + fields = []; | |
194 | + } | |
195 | + | |
196 | + var paramsExtended = angular.extend({ | |
197 | + 'fields[]': fields | |
198 | + }, params); | |
199 | + | |
200 | + UtilService.get(url, {params: paramsExtended}).then(function(data){ | |
201 | + _pipeHandleProgramsRandomFromCache(mapFromCache, data, cbSuccess); | |
202 | + }).catch(function(error){ | |
203 | + cbError(error); | |
204 | + }); | |
205 | + } | |
206 | + } | |
207 | + | |
208 | + function getEvents (params, cbSuccess, cbError) { | |
209 | + var paramsExtended = angular.extend({}, params); | |
210 | + | |
211 | + ArticleService.getEvents(API.communityId, paramsExtended, cbSuccess, cbError); | |
212 | + } | |
213 | + | |
214 | + // TODO: implement | |
215 | + function getQuestions (cbSuccess/*, cbError*/) { | |
216 | + if( !!CACHE.questions ){ | |
217 | + cbSuccess(CACHE.questions); | |
218 | + }else{ | |
219 | + // load content | |
220 | + var questions = []; | |
221 | + | |
222 | + CACHE.questions = questions; | |
223 | + cbSuccess(CACHE.questions); | |
224 | + } | |
225 | + } | |
226 | + | |
227 | + function searchPrograms (query, cbSuccess, cbError) { | |
228 | + ArticleService.searchTopics({query: query}, cbSuccess, cbError); | |
229 | + } | |
230 | + | |
231 | + function searchProposals (params, cbSuccess, cbError) { | |
232 | + ArticleService.searchProposals(params, cbSuccess, cbError); | |
233 | + } | |
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 | + | |
280 | + function _pipeHandleYoutube (data) { | |
281 | + var abstract = data.article.abstract; | |
282 | + | |
283 | + abstract = forceIframeParams(abstract); | |
284 | + abstract = removeStylefromIframe(abstract); | |
285 | + | |
286 | + data.article.abstract = abstract; | |
287 | + | |
288 | + data.article.abstractTrusted = $sce.trustAsHtml(abstract); | |
289 | + } | |
290 | + | |
291 | + function _pipeHandleSlug (data) { | |
292 | + // set slug to article | |
293 | + if(!data.article.slug){ | |
294 | + data.article.slug = Slug.slugify(data.article.title); | |
295 | + } | |
296 | + | |
297 | + // set slug to programs | |
298 | + for (var i = data.article.children.length - 1; i >= 0; i--) { | |
299 | + var program = data.article.children[i]; | |
300 | + if(!program.slug){ | |
301 | + program.slug = Slug.slugify(program.title); | |
302 | + } | |
303 | + } | |
304 | + } | |
305 | + | |
306 | + function _pipeSetThemes (data) { | |
307 | + if(!CACHE.hasOwnProperty('themes')){ | |
308 | + CACHE.themes = data.article.categories; | |
309 | + } | |
310 | + | |
311 | + _pipeCalcColors(data); | |
312 | + } | |
313 | + | |
314 | + function _pipeSetPrograms (data) { | |
315 | + if(!CACHE.hasOwnProperty('programs')){ | |
316 | + CACHE.programs = data.article.children; | |
317 | + CACHE.programs_count = data.article.children_count; | |
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 | + } | |
344 | + } | |
345 | + | |
346 | + // Calculate color pallet | |
347 | + function _pipeCalcColors (data) { | |
348 | + // var darkFactor = 0.15; | |
349 | + if(data.article.categories){ | |
350 | + // var categories = data.article.categories; | |
351 | + | |
352 | + // Handle Category Data | |
353 | + | |
354 | + // Handle Category Colors | |
355 | + // for (var i = categories.length - 1; i >= 0; i--) { | |
356 | + // var category = categories[i]; | |
357 | + // if(category.color && !category.bgColor){ | |
358 | + // category.colorDarker = $window.ColorLuminance(category.color, 0.15); | |
359 | + // } | |
360 | + // }; | |
361 | + } | |
362 | + } | |
363 | + | |
364 | + function _pipeHandleProgramsRandomFromCache (mapFromCache, data, cbSuccess){ | |
365 | + | |
366 | + if(mapFromCache){ | |
367 | + var result = []; | |
368 | + var refPrograms = data.articles; | |
369 | + | |
370 | + for (var i = CACHE.programs.length - 1; i >= 0; i--) { | |
371 | + var cachedProgram = CACHE.programs[i]; | |
372 | + | |
373 | + for (var j = refPrograms.length - 1; j >= 0; j--) { | |
374 | + var refProgram = refPrograms[j]; | |
375 | + | |
376 | + if(refProgram.id === cachedProgram.id){ | |
377 | + result.push(cachedProgram); | |
378 | + } | |
379 | + } | |
380 | + } | |
381 | + | |
382 | + data.articles = result; | |
383 | + } | |
384 | + | |
385 | + cbSuccess(data); | |
386 | + } | |
387 | + | |
388 | + function forceIframeParams(abstract) { | |
389 | + var patternIframe = '<iframe src="'; | |
390 | + var indexOfIframe = abstract.indexOf(patternIframe); | |
391 | + | |
392 | + if (indexOfIframe === -1) { | |
393 | + return abstract; | |
394 | + } | |
395 | + | |
396 | + var startSrcUrl = indexOfIframe + patternIframe.length; | |
397 | + var endSrcUrl = abstract.indexOf('"', startSrcUrl); | |
398 | + var srcUrl = abstract.substring(startSrcUrl , endSrcUrl); | |
399 | + var resultUrl = srcUrl; | |
400 | + var c = (srcUrl.indexOf('?') !== -1) ? '&' : ''; // already have url params. So, append-it | |
401 | + | |
402 | + // enable js api | |
403 | + if (srcUrl.indexOf('enablejsapi=1') === -1) { | |
404 | + resultUrl += c + 'enablejsapi=1'; | |
405 | + c = '&'; // force to always use '&' after here | |
406 | + } | |
407 | + | |
408 | + // set opaque mode | |
409 | + if (srcUrl.indexOf('wmode=opaque') === -1) { | |
410 | + resultUrl += c + 'wmode=opaque'; | |
411 | + // c = '&'; // force to always use '&' after here | |
412 | + } | |
413 | + | |
414 | + abstract = abstract.replace(srcUrl, resultUrl); | |
415 | + | |
416 | + return abstract; | |
417 | + } | |
418 | + | |
419 | + function removeStylefromIframe (abstract) { | |
420 | + var patternIframe = 'style="'; | |
421 | + var indexOfIframe = abstract.indexOf('<iframe'); | |
422 | + var indexOfStyleOnIframe = abstract.indexOf('style="', indexOfIframe); | |
423 | + | |
424 | + if (indexOfStyleOnIframe === -1) { | |
425 | + return abstract; | |
426 | + } | |
427 | + | |
428 | + var startStyleContent = indexOfStyleOnIframe + patternIframe.length; | |
429 | + var endStyleContent = abstract.indexOf('"', startStyleContent); | |
430 | + var style = abstract.substring(startStyleContent , endStyleContent); | |
431 | + | |
432 | + return abstract.replace(style, ''); | |
433 | + } | |
434 | + } | |
435 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,84 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('eventList', eventList); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function eventList() { | |
10 | + /** @ngInject */ | |
11 | + function EventListController(ArticleService, $scope, $rootScope, $state, $log) { | |
12 | + $log.debug('EventListController'); | |
13 | + | |
14 | + var vm = this; | |
15 | + | |
16 | + vm.ArticleService = ArticleService; | |
17 | + vm.$scope = $scope; | |
18 | + vm.$rootScope = $rootScope; | |
19 | + vm.$state = $state; | |
20 | + vm.$log = $log; | |
21 | + | |
22 | + vm.init(); | |
23 | + // vm.attachListeners(); | |
24 | + } | |
25 | + | |
26 | + EventListController.prototype.init = function () { | |
27 | + var vm = this; | |
28 | + | |
29 | + if(!vm.events){ | |
30 | + throw { name: 'NotDefined', message: 'The attribute "events" is undefined.'}; | |
31 | + } | |
32 | + | |
33 | + if(!vm.isCollapsed){ | |
34 | + vm.isCollapsed = true; | |
35 | + } | |
36 | + }; | |
37 | + | |
38 | + EventListController.prototype.toggleView = function () { | |
39 | + var vm = this; | |
40 | + vm.isCollapsed = !vm.isCollapsed; | |
41 | + }; | |
42 | + | |
43 | + EventListController.prototype.subscribe = function (event) { | |
44 | + var vm = this; | |
45 | + | |
46 | + if(event.isOld){ | |
47 | + vm.$log.debug('Event already happened. Abort.'); | |
48 | + return; | |
49 | + } | |
50 | + | |
51 | + var event_id = event.id; | |
52 | + vm.$log.debug('event_id', event_id); | |
53 | + | |
54 | + if(!vm.$rootScope.currentUser){ | |
55 | + vm.$log.info('User is not logged in. Redirect to Auth page.'); | |
56 | + vm.$state.go('entrar',{ | |
57 | + redirect_uri: 'state=inicio&task=subscribe&event_id=' + event_id | |
58 | + },{ | |
59 | + location: true | |
60 | + }); | |
61 | + }else{ | |
62 | + vm.ArticleService.subscribeToEvent(event_id, {}, function(response){ | |
63 | + vm.$log.debug('response', response); | |
64 | + }, function(error){ | |
65 | + vm.$log.debug('error', error); | |
66 | + }); | |
67 | + } | |
68 | + }; | |
69 | + | |
70 | + var directive = { | |
71 | + restrict: 'E', | |
72 | + templateUrl: 'app/components/event-list/event-list.html', | |
73 | + scope: { | |
74 | + events: '=', | |
75 | + isCollapsed: '=' | |
76 | + }, | |
77 | + controller: EventListController, | |
78 | + controllerAs: 'vm', | |
79 | + bindToController: true | |
80 | + }; | |
81 | + | |
82 | + return directive; | |
83 | + } | |
84 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,82 @@ |
1 | +<div class="event-list"> | |
2 | + | |
3 | + <section class="color-theme-common-bg"> | |
4 | + | |
5 | + <div class="container"> | |
6 | + <div class="event-bar--trigger" ng-click="vm.toggleView()"> | |
7 | + <div class="event-bar--trigger-top"> | |
8 | + <div class="col-sm-6"> | |
9 | + <h1 class="title"> | |
10 | + <span class="glyphicon glyphicon-calendar icon-circle color-theme-common-fg"></span> | |
11 | + Agenda <b>Dialoga Brasil</b> | |
12 | + </h1> | |
13 | + </div> | |
14 | + <div class="col-sm-6 text-right"> | |
15 | + <h2 class="event-bar--trigger-toggle text-right"> | |
16 | + <span><b>{{vm.events.length}}</b> bate papos <b>agendados</b></span> | |
17 | + <span ng-if="vm.isCollapsed" class="glyphicon glyphicon-menu-down" aria-hidden="true"></span> | |
18 | + <span ng-if="!vm.isCollapsed" class="glyphicon glyphicon-menu-up" aria-hidden="true"></span> | |
19 | + </h2> | |
20 | + </div> | |
21 | + </div> | |
22 | + <div class="clearfix"></div> | |
23 | + </div> | |
24 | + </div> | |
25 | + </section> | |
26 | + | |
27 | + <section class="section-table"> | |
28 | + <div class="container"> | |
29 | + <div class="event-list--panel ng-hide" ng-show="!vm.isCollapsed"> | |
30 | + <div class="event-list--table-wrapper"> | |
31 | + <div class="row row-level-1" ng-repeat="event in vm.events | orderBy:'start_date':false"> | |
32 | + <div class="col-xs-12 col-sm-4 col-md-3 vcenter"> | |
33 | + <span class="date-wrapper"> | |
34 | + <span class="glyphicon glyphicon-calendar"></span> | |
35 | + <span class="date">{{event.start_date | date : "dd/MM/yyyy"}}</span> | |
36 | + </span> | |
37 | + <span class="time-wrapper"> | |
38 | + <span class="glyphicon glyphicon-time"></span> | |
39 | + <span class="time">{{event.start_date | date : "HH:mm"}}</span> | |
40 | + </span> | |
41 | + </div> | |
42 | + <div class="col-xs-12 col-sm-4 col-md-5 vcenter"> | |
43 | + <span class="description">{{::event.title.split('-')[0]}}</span> | |
44 | + </div> | |
45 | + <!-- <div class="col-xs-12 col-sm-4 col-md-3 text-center vcenter"> | |
46 | + <span class="theme">{{::event.categories[0].name}}</span> | |
47 | + </div> --> | |
48 | + <div class="col-xs-12 col-sm-4 col-md-4 text-right vcenter" style="padding-right: 20px;"> | |
49 | + <div class="row"> | |
50 | + <div class="col-xs-6 text-right"> | |
51 | + <div ng-if="event.followers_count > 50"> | |
52 | + <b>{{::event.followers_count}}</b> | |
53 | + <br/> | |
54 | + <span>Inscritos</span> | |
55 | + </div> | |
56 | + </div> | |
57 | + <div class="col-xs-6"> | |
58 | + <button type="button" class="btn color-theme-common-bg btn-disabled" disabled ng-click="vm.subscribe(event)"> | |
59 | + Inscreva-se | |
60 | + <span class="sr-only">no bate-papo com (ministro) no dia {event.start_date | date : "dd/MM/yyyy"}} as {{event.start_date | date : "HH:mm"}} horas</span> | |
61 | + </button> | |
62 | + </div> | |
63 | + </div> | |
64 | + </div> | |
65 | + </div> | |
66 | + </div> | |
67 | + </div> | |
68 | + </div> | |
69 | + <div class="container visible-xs" ng-show="!vm.isCollapsed"> | |
70 | + <div class="minimize" ng-click="vm.toggleView()"> | |
71 | + <div class="row color-theme-common-bg"> | |
72 | + <div class="col-xs-6"> | |
73 | + <button type="button" class="btn btn-link" ng-click="">MINIMIZAR</button> | |
74 | + </div> | |
75 | + <div class="col-xs-5 text-right"> | |
76 | + <span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span> | |
77 | + </div> | |
78 | + </div> | |
79 | + </div> | |
80 | + </div> | |
81 | + </section> | |
82 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,148 @@ |
1 | +.event-list { | |
2 | + position: relative; | |
3 | + | |
4 | + .contraste & { | |
5 | + background-color: #262626; | |
6 | + } | |
7 | + | |
8 | + .section-table { | |
9 | + background-color: #e1e1e1; | |
10 | + } | |
11 | + | |
12 | + .event-list--panel { | |
13 | + width: 100%; | |
14 | + height: 240px; | |
15 | + margin: 8px 0; | |
16 | + padding: 0 20px; | |
17 | + overflow-x: hidden; | |
18 | + overflow-y: scroll; | |
19 | + transition: .3s linear all; | |
20 | + | |
21 | + &.ng-hide { | |
22 | + height: 0; | |
23 | + line-height: 0; | |
24 | + } | |
25 | + | |
26 | + .btn { | |
27 | + color: #e1e1e1; | |
28 | + text-transform: uppercase; | |
29 | + font-weight: bold; | |
30 | + } | |
31 | + | |
32 | + .row-level-1 { | |
33 | + // height: 48px; | |
34 | + line-height: 20px; | |
35 | + padding: 5px 0; | |
36 | + border-bottom: 1px solid #ccc; | |
37 | + } | |
38 | + | |
39 | + .row-level-1:last-child { | |
40 | + border-bottom: none; | |
41 | + } | |
42 | + | |
43 | + | |
44 | + @media screen and (max-width: $screen-sm) { | |
45 | + height: auto; | |
46 | + overflow: visible; | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + &--table{ | |
51 | + margin-bottom: 0; | |
52 | + } | |
53 | + | |
54 | + .event-tab--trigger { | |
55 | + $event-tab-height: 130px; | |
56 | + width: 150px; | |
57 | + height: $event-tab-height; | |
58 | + position: absolute; | |
59 | + right: 0; | |
60 | + top: $event-tab-height * (-1); | |
61 | + padding: 5px; | |
62 | + background-color: #eeeeee; | |
63 | + border: 1px solid #333333; | |
64 | + text-align: center; | |
65 | + line-height: 20px; | |
66 | + cursor: pointer; | |
67 | + | |
68 | + transition: all 0.3s linear all; | |
69 | + | |
70 | + overflow: hidden; | |
71 | + z-index: 100; | |
72 | + | |
73 | + &.ng-hide { | |
74 | + height: 0px; | |
75 | + line-height: 0px; | |
76 | + top: -1px; | |
77 | + } | |
78 | + | |
79 | + .contraste & { | |
80 | + background-color: #262626; | |
81 | + } | |
82 | + } | |
83 | + | |
84 | + .event-bar--trigger { | |
85 | + color: #fff; | |
86 | + cursor: pointer; | |
87 | + | |
88 | + h1 { | |
89 | + margin-bottom: 20px; | |
90 | + } | |
91 | + | |
92 | + .icon-circle { | |
93 | + font-size: 28px; | |
94 | + line-height: 33px; | |
95 | + border-radius: 100%; | |
96 | + padding: 8px 8px 8px 10px; | |
97 | + background-color: #fff; | |
98 | + } | |
99 | + | |
100 | + &-toggle { | |
101 | + display: inline-block; | |
102 | + text-transform: uppercase; | |
103 | + font-size: 16px; | |
104 | + | |
105 | + .glyphicon { | |
106 | + position: relative; | |
107 | + top: 5px; | |
108 | + font-size: 30px; | |
109 | + } | |
110 | + } | |
111 | + } | |
112 | + | |
113 | + .event-list--panel { | |
114 | + .date-wrapper {margin-left: 16px; } | |
115 | + .time-wrapper {margin-left: 22px; } | |
116 | + // .description {margin-left: 22px; } | |
117 | + } | |
118 | + | |
119 | + .event-tab--icon { | |
120 | + font-size: 25px; | |
121 | + } | |
122 | + | |
123 | + .event-tab--title { | |
124 | + font-weight: bold; | |
125 | + } | |
126 | + | |
127 | + .event-tab--button { | |
128 | + font-size: 12px; | |
129 | + margin: 10px 0 0 0; | |
130 | + padding: 0; | |
131 | + width: 100%; | |
132 | + white-space: normal; | |
133 | + } | |
134 | + | |
135 | + .minimize { | |
136 | + cursor: pointer; | |
137 | + | |
138 | + .btn, | |
139 | + .glyphicon { | |
140 | + color: #fff; | |
141 | + font-weight: bold; | |
142 | + } | |
143 | + | |
144 | + .glyphicon { | |
145 | + line-height: 32px; | |
146 | + } | |
147 | + } | |
148 | +} | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .factory('GUID', GUID); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function GUID(){ | |
10 | + var service = {}; | |
11 | + | |
12 | + service.generate = function (){ | |
13 | + function s4() { | |
14 | + return Math.floor((1 + Math.random()) * 0x10000) | |
15 | + .toString(16) | |
16 | + .substring(1); | |
17 | + } | |
18 | + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + | |
19 | + s4() + '-' + s4() + s4() + s4(); | |
20 | + }; | |
21 | + | |
22 | + return service; | |
23 | + } | |
24 | +})(); | ... | ... |
src/app/components/navbar/navbar.directive.js
... | ... | @@ -7,11 +7,24 @@ |
7 | 7 | |
8 | 8 | /** @ngInject */ |
9 | 9 | function appNavbar() { |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function NavbarController($log) { | |
13 | + $log.debug('NavbarController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + | |
17 | + vm.scrollTo = function(hash) { | |
18 | + var $el = angular.element('#' + hash); | |
19 | + angular.element('body').animate({scrollTop: $el.offset().top}, 'slow'); | |
20 | + }; | |
21 | + } | |
22 | + | |
10 | 23 | var directive = { |
11 | 24 | restrict: 'E', |
12 | 25 | templateUrl: 'app/components/navbar/navbar.html', |
13 | 26 | scope: { |
14 | - creationDate: '=' | |
27 | + creationDate: '=' | |
15 | 28 | }, |
16 | 29 | controller: NavbarController, |
17 | 30 | controllerAs: 'vm', |
... | ... | @@ -19,15 +32,6 @@ |
19 | 32 | }; |
20 | 33 | |
21 | 34 | return directive; |
22 | - | |
23 | - /** @ngInject */ | |
24 | - function NavbarController($log) { | |
25 | - $log.debug('NavbarController'); | |
26 | - // var vm = this; | |
27 | - | |
28 | - // "vm.creation" is avaible by directive option "bindToController: true" | |
29 | - // vm.relativeDate = moment(vm.creationDate).fromNow(); | |
30 | - } | |
31 | 35 | } |
32 | 36 | |
33 | 37 | })(); | ... | ... |
src/app/components/navbar/navbar.html
1 | -<nav class="navbar navbar-static-top"> | |
2 | - <div class="container-fluid"> | |
1 | +<div class="app-navbar"> | |
2 | + <nav id="navigation" class="header-navbar navbar navbar-static-top" role="navigation"> | |
3 | 3 | <div class="navbar-header"> |
4 | - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false"> | |
5 | - <span class="sr-only">Alternar menu de navegação</span> | |
6 | - <span class="icon-bar"></span> | |
7 | - <span class="icon-bar"></span> | |
8 | - <span class="icon-bar"></span> | |
9 | - </button> | |
10 | - <a class="navbar-brand" ui-sref="inicio"> | |
11 | - <img src="/assets/images/logo.png" alt="Dialoga Brasil | O país fica melhor quando você participa" /> | |
12 | - <!-- <span class="glyphicon glyphicon-home"></span> Início --> | |
13 | - </a> | |
4 | + <div class="row"> | |
5 | + <div class="row-height"> | |
6 | + <div class="col-xs-10 col-xs-height col-middle"> | |
7 | + <a class="navbar-brand" ui-sref="inicio"> | |
8 | + <img src="/assets/images/logo.png" class="img-responsive" alt="Dialoga Brasil | O país fica melhor quando você participa" /> | |
9 | + </a> | |
10 | + </div> | |
11 | + <div class="col-xs-2 col-xs-height col-middle"> | |
12 | + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false"> | |
13 | + <span class="sr-only">Alternar menu de navegação</span> | |
14 | + <span class="icon-bar" aria-hidden="true"></span> | |
15 | + <span class="icon-bar" aria-hidden="true"></span> | |
16 | + <span class="icon-bar" aria-hidden="true"></span> | |
17 | + </button> | |
18 | + </div> | |
19 | + </div> | |
20 | + </div> | |
14 | 21 | </div> |
15 | 22 | |
16 | 23 | <div id="navbar-collapse" class="collapse navbar-collapse"> |
17 | - <ul class="nav navbar-nav"> | |
18 | - <li><a ui-sref="sobre">Sobre</a></li> | |
19 | - <li><a ui-sref="programas">Programas</a></li> | |
20 | - <!-- <li><a ui-sref="ranking">Ranking</a></li> --> | |
21 | - <!-- <li><a ui-sref="duvidas">Dúvidas</a></li> --> | |
22 | - <!-- <li><a ui-sref="respostas">Respostas</a></li> --> | |
24 | + <ul class="nav navbar-nav navbar-right"> | |
25 | + <li ui-sref-active="active"><a ui-sref="sobre">Sobre</a></li> | |
26 | + <li ui-sref-active="active"><a ui-sref="programas">Programas</a></li> | |
27 | + <li ui-sref-active="active"><a ui-sref="propostas">Propostas</a></li> | |
28 | + <li ui-sref-active="active"><a ui-sref="ranking">Ranking</a></li> | |
29 | + <li ui-sref-active="active"><a ui-sref="duvidas">Dúvidas</a></li> | |
30 | + <li role="separator" class="divider hidden-xs hidden-sm"><span>|</span></li> | |
31 | + <li class="dropdown"> | |
32 | + <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Compartilhar <span aria-hidden="true" class="icon icon-social-share-small"></span></a> | |
33 | + <social-share class="dropdown-menu dropdown-menu-right" arrow-class="social-share--arrow"></social-share> | |
34 | + </li> | |
23 | 35 | </ul> |
24 | 36 | </div> |
37 | + </nav> | |
38 | + | |
39 | + <div id="dialoga-nas-redes" class="hidden-xs"> | |
40 | + <div class="text text-right"> | |
41 | + <p>DIALOGA<br><b>NAS REDES</b></p> | |
42 | + </div> | |
43 | + <ul class="social-share list-inline"> | |
44 | + <li> | |
45 | + <a href="https://www.facebook.com/DialogaBrasil" target="_blank"> | |
46 | + <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-facebook"><span class="icon icon-social-facebook"></span></span> | |
47 | + <span class="sr-only">Visitar perfil no Facebook</span> | |
48 | + </a> | |
49 | + </li> | |
50 | + <li> | |
51 | + <a href="https://twitter.com/dialogabrasil" target="_blank"> | |
52 | + <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-twitter"><span class="icon icon-social-twitter"></span></span> | |
53 | + <span class="sr-only">Visitar perfil no Twitter</span> | |
54 | + </a> | |
55 | + </li> | |
56 | + <li> | |
57 | + <a href="https://www.youtube.com/channel/UCtjaJwOWwGu2legqFVAzhIA" target="_blank"> | |
58 | + <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-youtube"><span class="icon icon-social-youtube"></span></span> | |
59 | + <span class="sr-only">Visitar canal no Youtube</span> | |
60 | + </a> | |
61 | + </li> | |
62 | + <li> | |
63 | + <a href="https://www.flickr.com/photos/dialogabrasil" target="_blank"> | |
64 | + <span aria-hidden="true" class="icon-circle icon-small icon-circle-social-flickr"><span class="icon icon-social-flickr"></span></span> | |
65 | + <span class="sr-only">Visitar canal no Flickr</span> | |
66 | + </a> | |
67 | + </li> | |
68 | + </ul> | |
25 | 69 | </div> |
26 | -</nav> | |
70 | +</div> | ... | ... |
src/app/components/navbar/navbar.scss
1 | -.navbar-brand { | |
2 | - height: auto; | |
3 | -} | |
1 | +.app-navbar { | |
2 | + | |
3 | + border-bottom: 2px solid #f1f1f1; | |
4 | + | |
5 | + .navbar { | |
6 | + margin-bottom: 0; | |
7 | + border: none; | |
8 | + } | |
9 | + | |
10 | + .navbar-brand { | |
11 | + height: auto; | |
12 | + padding-bottom: 0; | |
13 | + padding-left: 0; | |
14 | + | |
15 | + @media screen and (max-width: $screen-md) { | |
16 | + padding: 20px 0; | |
17 | + margin: 20px 0; | |
18 | + } | |
19 | + } | |
20 | + | |
21 | + .navbar-toggle { | |
22 | + border-radius: 100%; | |
23 | + background-color: #5e749d; | |
24 | + | |
25 | + .icon-bar { | |
26 | + height: 3px; | |
27 | + background-color: #fff; | |
28 | + } | |
29 | + | |
30 | + @media screen and (max-width: $screen-md) { | |
31 | + padding: 12px 10px; | |
32 | + margin: 0; | |
33 | + } | |
34 | + } | |
35 | + | |
36 | + .navbar-nav .divider span { | |
37 | + display: block; | |
38 | + | |
39 | + @media screen and (max-width: $screen-md) { | |
40 | + display: none; | |
41 | + } | |
42 | + } | |
43 | + | |
44 | + .dropdown-menu { | |
45 | + padding: 0; | |
46 | + } | |
47 | + | |
48 | + .navbar-nav { | |
49 | + | |
50 | + li > a { | |
51 | + text-transform: uppercase; | |
52 | + color: #616161; | |
53 | + font-weight: bold; | |
54 | + | |
55 | + &:hover, | |
56 | + &:focus { | |
57 | + background: none; | |
58 | + } | |
59 | + | |
60 | + .contraste & { | |
61 | + color: #fff; | |
62 | + } | |
63 | + } | |
64 | + | |
65 | + li.active > a { | |
66 | + border-bottom: 2px solid #77BB34; | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + .contraste & { | |
71 | + .nav > li > a:hover, | |
72 | + .nav > li > a:focus { | |
73 | + color: #fff; | |
74 | + } | |
75 | + | |
76 | + .active a { | |
77 | + border-bottom-color: #fff; | |
78 | + } | |
79 | + } | |
80 | + | |
81 | + // <= Mobile | |
82 | + @media screen and (max-width: ($screen-sm - 1)) { | |
83 | + .navbar-collapse { | |
84 | + margin: 0 -15px; | |
85 | + } | |
86 | + | |
87 | + .navbar-nav { | |
88 | + background-color: #eee; | |
4 | 89 | |
5 | -.navbar-nav > li > a { | |
6 | - padding-top: 30px; | |
7 | - padding-bottom: 30px; | |
90 | + & > li { | |
91 | + // border-top: 1px solid #ccc; | |
92 | + -moz-border-image: -moz-linear-gradient(left, #eee 0%, #ccc 100%); | |
93 | + -webkit-border-image: -webkit-linear-gradient(left, #eee 0%, #ccc 100%); | |
94 | + border-image: linear-gradient(to right, #eee 0%, #ccc 100%); | |
95 | + border-image-slice: 1; | |
96 | + | |
97 | + border-top: 1px solid #ccc; | |
98 | + border-bottom: 0px solid #ccc; | |
99 | + border-left: 0px solid #ccc; | |
100 | + border-right: 0px solid #ccc; | |
101 | + &:last-child { | |
102 | + border-bottom: 1px solid #ccc; | |
103 | + } | |
104 | + } | |
105 | + | |
106 | + & > li > a { | |
107 | + padding: 12px 20px; | |
108 | + margin: 0; | |
109 | + text-align: right; | |
110 | + } | |
111 | + | |
112 | + & > li.active > a { | |
113 | + border-bottom: none; | |
114 | + border-right: 4px solid #77BB34; | |
115 | + } | |
116 | + | |
117 | + .dropdown-toggle { | |
118 | + margin-top: 0px; | |
119 | + | |
120 | + } | |
121 | + .dropdown-menu { | |
122 | + position: relative; | |
123 | + margin-right: 10px; | |
124 | + } | |
125 | + | |
126 | + .social-share { | |
127 | + float: right; | |
128 | + } | |
129 | + } | |
130 | + | |
131 | + } | |
132 | + | |
133 | + // >= Table, < Destop | |
134 | + @media screen and (min-width: $screen-sm) and (max-width: ($screen-md - 1)) { | |
135 | + .navbar-brand { | |
136 | + padding-top: 0; | |
137 | + margin-top: 0; | |
138 | + margin-bottom: 60px; | |
139 | + } | |
140 | + | |
141 | + .navbar-collapse { | |
142 | + position: absolute; | |
143 | + left: 0; | |
144 | + bottom: 0; | |
145 | + width: 100%; | |
146 | + | |
147 | + ul.navbar-nav { | |
148 | + width: 100%; | |
149 | + float: none; | |
150 | + } | |
151 | + | |
152 | + li > a { | |
153 | + margin: 0 10px; | |
154 | + padding: 0 0 10px 0; | |
155 | + } | |
156 | + | |
157 | + li.dropdown { | |
158 | + position: absolute; | |
159 | + right: 0; | |
160 | + bottom: 0; | |
161 | + | |
162 | + .dropdown-toggle { | |
163 | + position: relative; | |
164 | + width: 160px; | |
165 | + margin: 0 5px 5px 0; | |
166 | + padding: 0; | |
167 | + } | |
168 | + } | |
169 | + } | |
170 | + } | |
171 | + // >= Desktop | |
172 | + @media screen and (min-width: $screen-md) { | |
173 | + | |
174 | + li > a { | |
175 | + padding: 15px 0; | |
176 | + margin: 0 9px; | |
177 | + } | |
178 | + | |
179 | + li.divider span{ | |
180 | + padding: 12px 0; | |
181 | + line-height: 20px; | |
182 | + } | |
183 | + | |
184 | + li.dropdown { | |
185 | + .dropdown-toggle { | |
186 | + padding: 6px 10px; | |
187 | + margin: 0; | |
188 | + } | |
189 | + } | |
190 | + } | |
191 | + | |
192 | + // > Desktop Large | |
193 | + @media screen and (min-width: $screen-lg) { | |
194 | + .navbar-brand { | |
195 | + margin-bottom: 30px; | |
196 | + } | |
197 | + | |
198 | + ul.navbar-nav { | |
199 | + position: absolute; | |
200 | + right: 0; | |
201 | + bottom: 0; | |
202 | + } | |
203 | + | |
204 | + li.divider span{ | |
205 | + padding: 12px 6px; | |
206 | + } | |
207 | + } | |
8 | 208 | } |
9 | 209 | |
10 | -.navbar-toggle .icon-bar { | |
11 | - background-color: #333; | |
210 | +#dialoga-nas-redes { | |
211 | + position: absolute; | |
212 | + right: 0; | |
213 | + top: 0; | |
214 | + z-index: 1000; | |
215 | + | |
216 | + .text { | |
217 | + position: absolute; | |
218 | + top: 5px; | |
219 | + right: 210px; | |
220 | + width: 100px; | |
221 | + } | |
12 | 222 | } | ... | ... |
src/app/components/programa/programa.directive.js
... | ... | @@ -1,73 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - angular | |
5 | - .module('dialoga') | |
6 | - .directive('programaBox', programaBox); | |
7 | - | |
8 | - /** @ngInject */ | |
9 | - function programaBox(api) { | |
10 | - | |
11 | - /** @ngInject */ | |
12 | - function ProgramaController($log) { | |
13 | - $log.debug('ProgramaController'); | |
14 | - | |
15 | - var vm = this; | |
16 | - vm.$log = $log; | |
17 | - | |
18 | - vm.init(); | |
19 | - } | |
20 | - | |
21 | - ProgramaController.prototype.init = function () { | |
22 | - | |
23 | - }; | |
24 | - | |
25 | - ProgramaController.prototype.getCategory = function () { | |
26 | - var vm = this; | |
27 | - | |
28 | - return vm.program.categories[0]; | |
29 | - }; | |
30 | - | |
31 | - ProgramaController.prototype.getCategoryName = function () { | |
32 | - return this.getCategory().name; | |
33 | - }; | |
34 | - | |
35 | - ProgramaController.prototype.getCategorySlug = function () { | |
36 | - return this.getCategory().slug; | |
37 | - }; | |
38 | - | |
39 | - ProgramaController.prototype.getImageUrl = function () { | |
40 | - var vm = this; | |
41 | - | |
42 | - return api.host + vm.program.image.url; | |
43 | - }; | |
44 | - | |
45 | - ProgramaController.prototype.getImageAlt = function () { | |
46 | - var vm = this; | |
47 | - | |
48 | - vm.$log.warn('image is not accessible.'); | |
49 | - return 'TODO: create image alt on server-side.'; | |
50 | - }; | |
51 | - | |
52 | - ProgramaController.prototype.showContent = function () { | |
53 | - var vm = this; | |
54 | - | |
55 | - vm.$log.debug('TODO: showContent()', vm.program); | |
56 | - }; | |
57 | - | |
58 | - var directive = { | |
59 | - restrict: 'E', | |
60 | - templateUrl: 'app/components/programa/programa.html', | |
61 | - scope: { | |
62 | - program: '=' | |
63 | - }, | |
64 | - controller: ProgramaController, | |
65 | - controllerAs: 'vm', | |
66 | - bindToController: true | |
67 | - }; | |
68 | - | |
69 | - | |
70 | - return directive; | |
71 | - } | |
72 | - | |
73 | -})(); |
src/app/components/programa/programa.html
... | ... | @@ -1,8 +0,0 @@ |
1 | -<article class="program-box {{::vm.getCategorySlug()}}" ng-if="vm.program" ng-click="vm.showContent()"> | |
2 | - <h2 class="category-name">{{::vm.getCategoryName()}}</h2> | |
3 | - <div class="image-wrapper"> | |
4 | - <img class="img-responsive" ng-src="{{::vm.getImageUrl()}}" alt="{{::vm.getImageAlt()}}" /> | |
5 | - </div> | |
6 | - <h1 class="program-title">{{::vm.program.title}}</h1> | |
7 | - <div class="program-abstract" ng-bind-html="vm.program.abstract"></div> | |
8 | -</article> |
src/app/components/programa/programa.scss
... | ... | @@ -1,39 +0,0 @@ |
1 | -// Variables | |
2 | -$scale: 1.1; | |
3 | -$time: .3s; | |
4 | - | |
5 | -// sandbox | |
6 | -.program-box { | |
7 | - cursor: pointer; | |
8 | - .category-name { | |
9 | - font-size: 14px; | |
10 | - font-weight: bold; | |
11 | - line-height: 30px; | |
12 | - display: block; | |
13 | - height: 30px; | |
14 | - margin-bottom: 0; | |
15 | - color: #ffffff; | |
16 | - background-color: #000000; | |
17 | - } | |
18 | - .image-wrapper { | |
19 | - position: relative; | |
20 | - // width: 100%; | |
21 | - // width: 370px; | |
22 | - // height: 170px; | |
23 | - | |
24 | - overflow: hidden; | |
25 | - text-align: center; | |
26 | - } | |
27 | - .img-responsive { | |
28 | - -webkit-transition: all $time ease-in-out; | |
29 | - -moz-transition: all $time ease-in-out; | |
30 | - -o-transition: all $time ease-in-out; | |
31 | - transition: all $time ease-in-out; | |
32 | - } | |
33 | - &:hover .img-responsive { | |
34 | - -webkit-transform: scale($scale); /* prefixo para browsers webkit */ | |
35 | - -moz-transform: scale($scale); /* prefixo para browsers gecko */ | |
36 | - -o-transform: scale($scale); /* prefixo para opera */ | |
37 | - transform: scale($scale); | |
38 | - } | |
39 | -} |
src/app/components/programas/programas.directive.js
... | ... | @@ -1,212 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - angular | |
5 | - .module('dialoga') | |
6 | - .filter('filterByCategory', filterByCategory) | |
7 | - .filter('filterByCriteria', filterByCriteria) | |
8 | - .directive('programaList', programaList); | |
9 | - | |
10 | - /** @ngInject */ | |
11 | - function programaList() { | |
12 | - | |
13 | - /** @ngInject */ | |
14 | - function ProgramaListController($scope, $location, $log) { | |
15 | - $log.debug('ProgramaListController'); | |
16 | - | |
17 | - // alias | |
18 | - var vm = this; | |
19 | - | |
20 | - // dependencies | |
21 | - vm.$scope = $scope; | |
22 | - vm.$location = $location; | |
23 | - vm.$log = $log; | |
24 | - | |
25 | - // initialization | |
26 | - vm.init(); | |
27 | - } | |
28 | - | |
29 | - ProgramaListController.prototype.init = function () { | |
30 | - var vm = this; | |
31 | - | |
32 | - if(!vm.article){ | |
33 | - vm.$log.warn('no article to display. Tip: use a ng-if before use this directive'); | |
34 | - return; | |
35 | - } | |
36 | - | |
37 | - vm.categories = vm.article.categories; | |
38 | - vm.programs = vm.article.children; | |
39 | - vm.filtredProgramList = []; | |
40 | - vm.orderCriteries = [ | |
41 | - { label: 'Título', name: 'title' }, | |
42 | - { label: 'Tema', name: 'category' } | |
43 | - // , { label: 'Mais participações', name: 'more_participants' } | |
44 | - ]; | |
45 | - | |
46 | - vm.search = vm.$location.search(); | |
47 | - | |
48 | - // Add initial values for the filter | |
49 | - vm.query = (vm.search && vm.search.filtro) ? vm.search.filtro : null; | |
50 | - vm.limitTo = (vm.search && vm.search.limite) ? parseInt(vm.search.limite, 10) : 4; | |
51 | - vm.categoryFilter = (vm.search && vm.search.tema) ? vm.filterByCategorySlug(vm.search.tema) : null; | |
52 | - | |
53 | - // update window location params | |
54 | - vm.$scope.$watch('vm.query', function(newValue, oldValue){ | |
55 | - vm.search.filtro = newValue; | |
56 | - vm.$location.search(vm.search); | |
57 | - }); | |
58 | - | |
59 | - vm.$scope.$watch('vm.limitTo', function(newValue, oldValue){ | |
60 | - vm.search.limite = newValue; | |
61 | - vm.$location.search(vm.search); | |
62 | - }); | |
63 | - | |
64 | - vm.$scope.$watch('vm.categoryFilter', function(newValue, oldValue){ | |
65 | - vm.search.tema = newValue ? newValue.slug : ''; | |
66 | - vm.$location.search(vm.search); | |
67 | - }); | |
68 | - | |
69 | - }; | |
70 | - | |
71 | - ProgramaListController.prototype.resetFilterValues = function () { | |
72 | - var vm = this; | |
73 | - | |
74 | - vm.query = null; | |
75 | - vm.limitTo = 4; | |
76 | - vm.categoryFilter = null; | |
77 | - }; | |
78 | - | |
79 | - ProgramaListController.prototype.getIconClasses = function (category) { | |
80 | - var vm = this; | |
81 | - | |
82 | - vm.$log.debug('[TODO] getIconClasses of category:', category); | |
83 | - return 'glyphicon glyphicon-exclamation-sign'; | |
84 | - }; | |
85 | - | |
86 | - ProgramaListController.prototype.filterByCategorySlug = function (categorySlug) { | |
87 | - var vm = this; | |
88 | - var result = null; | |
89 | - | |
90 | - angular.forEach(vm.categories, function (value, key){ | |
91 | - if(value.slug === categorySlug){ | |
92 | - result = value; | |
93 | - } | |
94 | - }) | |
95 | - return result; | |
96 | - } | |
97 | - | |
98 | - ProgramaListController.prototype.filterByCategory = function (category, $event) { | |
99 | - var vm = this; | |
100 | - | |
101 | - $event.stopPropagation(); | |
102 | - | |
103 | - if(category !== vm.categoryFilter){ | |
104 | - | |
105 | - // selected new filter | |
106 | - vm.categoryFilter = category; | |
107 | - }else{ | |
108 | - // already selected. Unselect. | |
109 | - vm.showAll(); | |
110 | - } | |
111 | - }; | |
112 | - | |
113 | - ProgramaListController.prototype.showAll = function ($event) { | |
114 | - var vm = this; | |
115 | - | |
116 | - $event.stopPropagation(); | |
117 | - | |
118 | - vm.resetFilterValues(); | |
119 | - }; | |
120 | - | |
121 | - // function ProgramaListLinker (scope, element, attrs) { | |
122 | - | |
123 | - // scope.$watch('article', function(newValue, oldValue){ | |
124 | - // if(!newValue){ | |
125 | - // return; | |
126 | - // } | |
127 | - // scope.vm.categories = scope.vm.article.categories; | |
128 | - // scope.vm.programs = scope.vm.article.children; | |
129 | - // }); | |
130 | - // } | |
131 | - | |
132 | - var directive = { | |
133 | - restrict: 'E', | |
134 | - templateUrl: 'app/components/programas/programas.html', | |
135 | - scope: { | |
136 | - article: '=' | |
137 | - }, | |
138 | - controller: ProgramaListController, | |
139 | - controllerAs: 'vm', | |
140 | - bindToController: true, | |
141 | - // link: ProgramaListLinker | |
142 | - }; | |
143 | - | |
144 | - | |
145 | - return directive; | |
146 | - } | |
147 | - | |
148 | - function filterByCategory(){ | |
149 | - return function (input, category){ | |
150 | - input = input || []; | |
151 | - | |
152 | - if(!category){ | |
153 | - // no filter | |
154 | - return input; | |
155 | - } | |
156 | - | |
157 | - var out = []; | |
158 | - for (var i = 0; i < input.length; i++) { | |
159 | - var program = input[i]; | |
160 | - if(program.categories[0].slug === category.slug){ | |
161 | - out.push(program); | |
162 | - } | |
163 | - } | |
164 | - | |
165 | - return out; | |
166 | - }; | |
167 | - } | |
168 | - | |
169 | - /** @ngInject */ | |
170 | - function filterByCriteria($filter, $log){ | |
171 | - var orderBy = $filter('orderBy'); | |
172 | - | |
173 | - return function (input, criteria, reverse){ | |
174 | - input = input || []; | |
175 | - criteria = criteria || {}; | |
176 | - reverse = reverse || false; | |
177 | - | |
178 | - var out = []; | |
179 | - // for (var i = 0; i < input.length; i++) { | |
180 | - // var program = input[i]; | |
181 | - | |
182 | - // // todo ordering | |
183 | - // out.push(program); | |
184 | - // } | |
185 | - | |
186 | - switch(criteria.name){ | |
187 | - case 'title': | |
188 | - out = orderBy(input, 'title', reverse); | |
189 | - break; | |
190 | - case 'category': | |
191 | - out = orderBy(input, 'categories[0].name', reverse); | |
192 | - break; | |
193 | - case 'more_participants': | |
194 | - // break; | |
195 | - default: | |
196 | - $log.info('Criteria not handled yet: ', criteria); | |
197 | - | |
198 | - if(reverse){ | |
199 | - out = input.slice().reverse(); | |
200 | - }else{ | |
201 | - out = input; | |
202 | - } | |
203 | - break; | |
204 | - } | |
205 | - | |
206 | - | |
207 | - return out; | |
208 | - }; | |
209 | - } | |
210 | - | |
211 | - | |
212 | -})(); |
src/app/components/programas/programas.html
... | ... | @@ -1,68 +0,0 @@ |
1 | -<div class="row"> | |
2 | - <div class="col-sm-3"> | |
3 | - <div class="category-list"> | |
4 | - <nav class="navigation"> | |
5 | - <h3 class="title"><b>Programas</b> por Tema</h3> | |
6 | - <div class="list-group category-list"> | |
7 | - <button type="button" class="list-group-item category-item" | |
8 | - ng-repeat="category in vm.categories" | |
9 | - ng-class="{active: vm.categoryFilter.slug === category.slug}" | |
10 | - ng-click="vm.filterByCategory(category, $event)"> | |
11 | - | |
12 | - <span ng-class="[category.iconClass]"></span> | |
13 | - <span>{{::category.name}}</span> | |
14 | - <span class="glyphicon glyphicon-chevron-right pull-right"></span> | |
15 | - | |
16 | - </button> | |
17 | - </div> | |
18 | - </nav> | |
19 | - </div> | |
20 | - </div> | |
21 | - | |
22 | - <div class="col-sm-9"> | |
23 | - <article class="program-list"> | |
24 | - <header class="header"> | |
25 | - <h2>Programas</h2> | |
26 | - <button type="button" class="btn btn-link" ng-click="vm.showAll($event)"> | |
27 | - <span class="glyphicon glyphicon-chevron-right"></span> Ver todos os programas | |
28 | - </button> | |
29 | - </header> | |
30 | - <div> | |
31 | - <div class="col-sm-12"> | |
32 | - <aside class="form-inline"> | |
33 | - <div class="form-group"> | |
34 | - <label for="programListFilter" class="control-label sr-only">Filtrar programas:</label> | |
35 | - <input id="programListFilter" type="search" class="form-control" ng-model="vm.query" placeholder="Filtrar programas" aria-label="Filtrar programas" > | |
36 | - | |
37 | - <select class="form-control" ng-model="vm.categoryFilter" ng-options="category.name for category in vm.categories track by category.slug"> | |
38 | - <option value="">-- Filtrar por tema --</option> | |
39 | - </select> | |
40 | - | |
41 | - <select class="form-control" ng-model="vm.orderCriteria" ng-options="orderCriteria.label for orderCriteria in vm.orderCriteries"> | |
42 | - <option value="">-- Ordernar por: --</option> | |
43 | - </select> | |
44 | - | |
45 | - <div class="checkbox"> | |
46 | - <label> | |
47 | - <input type="checkbox" ng-model="orderReverse"> | |
48 | - Reverso | |
49 | - </label> | |
50 | - </div> | |
51 | - | |
52 | - <input id="programListLimit" type="number" class="form-control input-sm" size="4" step="2" ng-model="vm.limitTo" aria-label="Limitar" > | |
53 | - <label for="programListLimit" class="control-label">Limite</label> | |
54 | - | |
55 | - </div> | |
56 | - </aside> | |
57 | - </div> | |
58 | - <div ng-repeat="program in vm.programs | filterByCategory:vm.categoryFilter | filterByCriteria:vm.orderCriteria:orderReverse | filter:vm.query | limitTo:vm.limitTo as results"> | |
59 | - <programa-box program="program" class="col-sm-12 col-md-6"></programa-box> | |
60 | - <div ng-if="$odd" class="clearfix"></div> | |
61 | - </div> | |
62 | - <div class="animate-repeat" ng-if="results.length == 0"> | |
63 | - Nenhum programa encontrado. | |
64 | - </div> | |
65 | - </div> | |
66 | - </article> | |
67 | - </div> | |
68 | -</div> |
src/app/components/programas/programas.scss
src/app/components/proposal-box/proposal-box.directive.js
0 → 100644
... | ... | @@ -0,0 +1,152 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('proposalBox', proposalBox); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function proposalBox() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ProposalBoxController($scope, $rootScope, $state, VOTE_STATUS, VOTE_OPTIONS, $log) { | |
13 | + $log.debug('ProposalBoxController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$scope = $scope; | |
17 | + vm.$rootScope = $rootScope; | |
18 | + vm.$state = $state; | |
19 | + vm.VOTE_STATUS = VOTE_STATUS; | |
20 | + vm.VOTE_OPTIONS = VOTE_OPTIONS; | |
21 | + vm.$log = $log; | |
22 | + | |
23 | + vm.init(); | |
24 | + vm.addListeners(); | |
25 | + } | |
26 | + | |
27 | + ProposalBoxController.prototype.init = function () { | |
28 | + | |
29 | + var vm = this; | |
30 | + | |
31 | + vm.canVote = vm.canVote || false; | |
32 | + vm.focus = vm.focus || false; | |
33 | + vm.STATE = null; | |
34 | + vm.errorOnSkip = false; | |
35 | + vm.showAuthMessage = null; | |
36 | + vm.voteProposalRedirectURI = null; | |
37 | + | |
38 | + var slug = vm.topic.slug; | |
39 | + var proposal_id = vm.proposal.id; | |
40 | + vm.voteProposalRedirectURI = 'state=programa&task=vote-proposal&slug=' + slug + '&proposal_id=' + proposal_id; | |
41 | + }; | |
42 | + | |
43 | + ProposalBoxController.prototype.addListeners = function () { | |
44 | + var vm = this; | |
45 | + | |
46 | + vm.$scope.$on('proposal-box:proposal-loaded', function(event, data){ | |
47 | + if(data.success){ | |
48 | + vm.STATE = null; | |
49 | + } | |
50 | + | |
51 | + if(data.error){ | |
52 | + vm.errorOnSkip = data.error; | |
53 | + } | |
54 | + }); | |
55 | + | |
56 | + vm.$scope.$on('proposal-box:vote-response', function(event, data){ | |
57 | + vm.$log.debug('proposal-box:vote-response'); | |
58 | + vm.$log.debug('event', event); | |
59 | + vm.$log.debug('data', data); | |
60 | + | |
61 | + if(data.success) { | |
62 | + vm.STATE = vm.VOTE_STATUS.SUCCESS; | |
63 | + } | |
64 | + | |
65 | + if(data.error) { | |
66 | + vm.STATE = vm.VOTE_STATUS.ERROR; | |
67 | + } | |
68 | + | |
69 | + vm.message = data.message; | |
70 | + }); | |
71 | + }; | |
72 | + | |
73 | + ProposalBoxController.prototype.showContent = function (slug) { | |
74 | + var vm = this; | |
75 | + | |
76 | + vm.$state.go('programa', { | |
77 | + slug: slug, | |
78 | + proposal_id: vm.proposal.id | |
79 | + }, { | |
80 | + location: true | |
81 | + }); | |
82 | + }; | |
83 | + | |
84 | + ProposalBoxController.prototype.vote = function (value) { | |
85 | + var vm = this; | |
86 | + | |
87 | + if(vm.$rootScope.currentUser){ | |
88 | + vm.$scope.$emit('proposal-box:vote', { | |
89 | + OPTION: value, | |
90 | + proposal_id: vm.proposal.id | |
91 | + }); | |
92 | + vm.$log.debug('Sending vote', value); | |
93 | + }else{ | |
94 | + vm.$log.info('Must be logged in...'); | |
95 | + vm.showAuthMessage = true; | |
96 | + } | |
97 | + }; | |
98 | + | |
99 | + ProposalBoxController.prototype.voteDown = function () { | |
100 | + var vm = this; | |
101 | + | |
102 | + vm.STATE = vm.VOTE_STATUS.LOADING; | |
103 | + vm.$scope.$emit('proposal-box:vote', { | |
104 | + OPTION: vm.VOTE_OPTIONS.DOWN, | |
105 | + proposal_id: vm.proposal.id | |
106 | + }); | |
107 | + vm.$log.debug('Sending vote'); | |
108 | + }; | |
109 | + | |
110 | + ProposalBoxController.prototype.skip = function () { | |
111 | + var vm = this; | |
112 | + | |
113 | + vm.errorOnSkip = false; | |
114 | + vm.STATE = vm.VOTE_STATUS.LOADING; | |
115 | + vm.$scope.$emit('proposal-box:vote', { | |
116 | + OPTION: vm.VOTE_OPTIONS.SKIP, | |
117 | + proposal_id: vm.proposal.id | |
118 | + }); | |
119 | + vm.$log.debug('Sending vote'); | |
120 | + }; | |
121 | + | |
122 | + ProposalBoxController.prototype.getSocialUrl = function () { | |
123 | + var vm = this; | |
124 | + | |
125 | + return vm.$state.href('programa', { | |
126 | + slug: vm.topic.slug, | |
127 | + proposal_id: vm.proposal.id, | |
128 | + }); | |
129 | + }; | |
130 | + | |
131 | + var directive = { | |
132 | + restrict: 'E', | |
133 | + templateUrl: 'app/components/proposal-box/proposal-box.html', | |
134 | + scope: { | |
135 | + proposal: '=', | |
136 | + topic: '=', | |
137 | + category: '=', | |
138 | + canVote: '=', | |
139 | + focus: '@' | |
140 | + // @ -> Text binding / one-way binding | |
141 | + // = -> Direct model binding / two-way binding | |
142 | + // & -> Behaviour binding / Method binding | |
143 | + }, | |
144 | + controller: ProposalBoxController, | |
145 | + controllerAs: 'vm', | |
146 | + bindToController: true | |
147 | + }; | |
148 | + | |
149 | + return directive; | |
150 | + } | |
151 | + | |
152 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,165 @@ |
1 | +<div class="proposal-box" ng-class="[{'focus': (vm.focus || (vm.STATE === vm.VOTE_STATUS.LOADING) )}, vm.category.slug]"> | |
2 | + <div ng-show="(vm.STATE === vm.VOTE_STATUS.SUCCESS) || (vm.STATE === vm.VOTE_STATUS.ERROR)"> | |
3 | + <div class="proposal-message-panel"> | |
4 | + <div class="row"> | |
5 | + <div class="row-height"> | |
6 | + <div class="col-sm-12 col-height col-middle"> | |
7 | + <div class="inside inside-full-height"> | |
8 | + <div class="content text-center show-message"> | |
9 | + <div class="row"> | |
10 | + <div class="col-xs-12"> | |
11 | + <div class="message-icon color-fg-white" ng-class="{'success': (vm.STATE === vm.VOTE_STATUS.SUCCESS), 'error': vm.STATE === vm.VOTE_STATUS.ERROR}"> | |
12 | + <span ng-if="vm.STATE === vm.VOTE_STATUS.SUCCESS" class="glyphicon glyphicon-ok" aria-hidden="true"></span> | |
13 | + <span ng-if="vm.STATE === vm.VOTE_STATUS.ERROR" class="glyphicon glyphicon-remove" aria-hidden="true"></span> | |
14 | + </div> | |
15 | + </div> | |
16 | + </div> | |
17 | + <div class="row"> | |
18 | + <div class="col-xs-12"> | |
19 | + <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.SUCCESS"> | |
20 | + <p class="feedback--title">Obrigado por apoiar<br/>esta proposta!</p> | |
21 | + | |
22 | + <!-- actions --> | |
23 | + <div class="row feedback--message"> | |
24 | + <div class="col-xs-6 feedback--share"> | |
25 | + <div class="row"> | |
26 | + <span>Compartilhe<br/>esta proposta</span> | |
27 | + </div> | |
28 | + <div class="row"> | |
29 | + <button class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" aria-label="Mostrar ou esconder a lista redes sociais para compartilhamento"> | |
30 | + <span class="icon icon-social-share" aria-hidden="true"></span> | |
31 | + </button> | |
32 | + <social-share | |
33 | + url="vm.getSocialUrl()" | |
34 | + text="vm.getSocialText()" | |
35 | + image="vm.getSocialImage()" | |
36 | + class="dropdown-menu dropdown-menu-right ng-isolate-scope"></social-share> | |
37 | + </div> | |
38 | + </div> | |
39 | + <div class="col-xs-6 feedback--next"> | |
40 | + <div class="row"> | |
41 | + <span>Próxima<br/>proposta</span> | |
42 | + </div> | |
43 | + <div class="row"> | |
44 | + <button class="btn btn-link" aria-label="Ir para próxima proposta" ng-click="vm.skip()"> | |
45 | + <div class="icon-circle play"> | |
46 | + <span class="glyphicon glyphicon-play" aria-hidden="true"></span> | |
47 | + </div> | |
48 | + </button> | |
49 | + </div> | |
50 | + </div> | |
51 | + </div> | |
52 | + </div> | |
53 | + <div class="feedback" ng-if="vm.STATE === vm.VOTE_STATUS.ERROR"> | |
54 | + <p class="feedback--title">Erro!</p> | |
55 | + <p class="feedback--message" ng-if="vm.message"> | |
56 | + Motivo: {{vm.message}} | |
57 | + </p> | |
58 | + </div> | |
59 | + </div> | |
60 | + </div> | |
61 | + </div> | |
62 | + </div> | |
63 | + </div> | |
64 | + </div> | |
65 | + </div> | |
66 | + </div> | |
67 | + </div> | |
68 | + <div ng-show="vm.showAuthMessage"> | |
69 | + <div class="proposal-message-panel"> | |
70 | + <div class="row"> | |
71 | + <div class="row-height"> | |
72 | + <div class="col-sm-12 col-height col-middle"> | |
73 | + <div class="inside inside-full-height"> | |
74 | + <div class="content text-center"> | |
75 | + <p>Você precisa estar logado para votar na proposta</p> | |
76 | + <br> | |
77 | + <p> | |
78 | + <a ui-sref="entrar({redirect_uri: vm.voteProposalRedirectURI})">Clique aqui para ir para a página de login</a> | |
79 | + </p> | |
80 | + </div> | |
81 | + </div> | |
82 | + </div> | |
83 | + </div> | |
84 | + </div> | |
85 | + </div> | |
86 | + </div> | |
87 | + <div ng-show="vm.STATE === vm.VOTE_STATUS.LOADING"> | |
88 | + <div class="proposal-message-panel"> | |
89 | + <div class="row"> | |
90 | + <div class="row-height"> | |
91 | + <div class="col-sm-12 col-height col-middle"> | |
92 | + <div class="inside inside-full-height"> | |
93 | + <div class="content text-center"> | |
94 | + <div ng-show="!vm.errorOnSkip"> | |
95 | + <p>Carregando...</p> | |
96 | + </div> | |
97 | + <div ng-show="vm.errorOnSkip"> | |
98 | + <p>Erro ao carregar nova proposta proposta.</p> | |
99 | + </div> | |
100 | + </div> | |
101 | + </div> | |
102 | + </div> | |
103 | + </div> | |
104 | + </div> | |
105 | + </div> | |
106 | + </div> | |
107 | + <div class="proposal-box--top"> | |
108 | + <div class="proposal-box--theme color-theme-bg-complementar-2">{{vm.category.name}}</div> | |
109 | + <div class="proposal-box--program color-theme-bg">{{vm.topic.title}}</div> | |
110 | + </div> | |
111 | + <div class="proposal-box--middle"> | |
112 | + <div class="proposal-box--content"> | |
113 | + <div class="proposal-box--content-inner">{{vm.proposal.abstract}}</div> | |
114 | + </div> | |
115 | + <div ng-hide="vm.canVote" class="proposal-box--join"> | |
116 | + <button class="btn btn-link color-theme-common-fg" ng-click="vm.showContent(vm.topic.slug)"> | |
117 | + Participe | |
118 | + </button> | |
119 | + </div> | |
120 | + <div ng-show="vm.canVote" class="proposal-box--actions text-center"> | |
121 | + <div class="row"> | |
122 | + <div class="col-xs-4"> | |
123 | + <div class="action vote_for" ng-click="vm.vote(vm.VOTE_OPTIONS.UP)"> | |
124 | + <div class="icon-circle"> | |
125 | + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> | |
126 | + </div> | |
127 | + <div class="action-label">Apoio</div> | |
128 | + </div> | |
129 | + </div> | |
130 | + <div class="col-xs-4"> | |
131 | + <div class="action skip" ng-click="vm.skip()"> | |
132 | + <div class="icon-circle"> | |
133 | + <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> | |
134 | + </div> | |
135 | + <div class="action-label">Pular</div> | |
136 | + </div> | |
137 | + </div> | |
138 | + <div class="col-xs-4"> | |
139 | + <div class="action vote_against" ng-click="vm.vote(vm.VOTE_OPTIONS.DOWN)"> | |
140 | + <div class="icon-circle"> | |
141 | + <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> | |
142 | + </div> | |
143 | + <div class="action-label">Não Apoio</div> | |
144 | + </div> | |
145 | + </div> | |
146 | + </div> | |
147 | + </div> | |
148 | + </div> | |
149 | + <div class="proposal-box--bottom text-center"> | |
150 | + <div class="proposal-box--share"> | |
151 | + <span>COMPARTILHE ESTA <b>PROPOSTA</b></span> | |
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> | |
154 | + <social-share class="dropdown-menu dropdown-menu-right"></social-share> | |
155 | + </div> | |
156 | + </div> | |
157 | + <div class="proposal-box--ranking"> | |
158 | + <div class="proposal-box--ranking-inner"> | |
159 | + <span class="icon icon-small icon-ranking" aria-hidden="true"></span> | |
160 | + <span>Colocação nos resultados:</span> | |
161 | + <span>{{vm.proposal.ranking_position}}º</span> | |
162 | + </div> | |
163 | + </div> | |
164 | + </div> | |
165 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,173 @@ |
1 | +.proposal-box { | |
2 | + background-color: #f1f1f1; | |
3 | + border-radius: 5px; | |
4 | + // overflow: hidden; | |
5 | + margin-bottom: 20px; | |
6 | + position: relative; | |
7 | + | |
8 | + &.focus { | |
9 | + border: 7px solid #000; | |
10 | + border-radius: 12px; | |
11 | + border-color: #5E769C; | |
12 | + } | |
13 | + | |
14 | + &--top { | |
15 | + color: #fff; | |
16 | + font-weight: bold; | |
17 | + | |
18 | + border-top-left-radius: 5px; | |
19 | + border-top-right-radius: 5px; | |
20 | + overflow: hidden; | |
21 | + } | |
22 | + | |
23 | + &--middle { | |
24 | + padding: 30px; | |
25 | + min-height: 180px; | |
26 | + | |
27 | + // position: relative; | |
28 | + // .proposal-box--join { | |
29 | + // position: absolute; | |
30 | + // bottom: 10px; | |
31 | + // left: 30px; | |
32 | + // } | |
33 | + } | |
34 | + | |
35 | + &--bottom { | |
36 | + border-bottom-left-radius: 5px; | |
37 | + border-bottom-right-radius: 5px; | |
38 | + // overflow: hidden; | |
39 | + border-bottom: 5px solid #dadada; | |
40 | + } | |
41 | + | |
42 | + &--theme { | |
43 | + padding: 10px 15px 5px 15px; | |
44 | + } | |
45 | + | |
46 | + &--program { | |
47 | + padding: 20px 15px; | |
48 | + } | |
49 | + | |
50 | + &--content { | |
51 | + padding-bottom: 20px; | |
52 | + } | |
53 | + | |
54 | + &--share { | |
55 | + padding: 15px 0; | |
56 | + background-color: #e8e8e8; | |
57 | + } | |
58 | + | |
59 | + &--ranking { | |
60 | + font-weight: bold; | |
61 | + padding: 10px 0; | |
62 | + background-color: #dadada; | |
63 | + } | |
64 | + | |
65 | + .action-label { | |
66 | + margin-top: 10px; | |
67 | + } | |
68 | + | |
69 | + .proposal-box--join { | |
70 | + .btn { | |
71 | + font-weight: bold; | |
72 | + padding: 6px 0; | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + .proposal-message-panel { | |
77 | + position: absolute; | |
78 | + width: 100%; | |
79 | + height: 100%; | |
80 | + top: 0; | |
81 | + left: 0; | |
82 | + z-index: 1000; | |
83 | + background-color: #f5f5f5; | |
84 | + background-color: rgba(245, 245, 245, 0.9); | |
85 | + border: 7px solid #5E769C; | |
86 | + border-radius: 5px; | |
87 | + | |
88 | + .row { height: 100%; } | |
89 | + .inside { position: relative; } | |
90 | + | |
91 | + .content { | |
92 | + color: #262626; | |
93 | + font-size: 24px; | |
94 | + font-weight: bold; | |
95 | + line-height: 24px; | |
96 | + padding: 10px 30px; | |
97 | + } | |
98 | + | |
99 | + .message-icon { | |
100 | + .glyphicon { | |
101 | + top: 8px; | |
102 | + } | |
103 | + } | |
104 | + } | |
105 | + | |
106 | + .feedback { | |
107 | + padding: 20px; | |
108 | + | |
109 | + &--title { | |
110 | + font-size: 22px; | |
111 | + font-weight: bold; | |
112 | + } | |
113 | + | |
114 | + &--message { | |
115 | + font-size: 14px; | |
116 | + font-weight: normal; | |
117 | + line-height: 20px; | |
118 | + margin-top: 48px; | |
119 | + } | |
120 | + | |
121 | + .icon-circle { | |
122 | + &.play { | |
123 | + background-color: #5e769c; | |
124 | + } | |
125 | + | |
126 | + .glyphicon { | |
127 | + top: 12px; | |
128 | + color: #fff; | |
129 | + } | |
130 | + } | |
131 | + } | |
132 | + | |
133 | + | |
134 | + .action { | |
135 | + .glyphicon { | |
136 | + color: #fff; | |
137 | + } | |
138 | + } | |
139 | + | |
140 | + .dropdown { | |
141 | + display: inline-block; | |
142 | + } | |
143 | + | |
144 | + .dropdown-menu { | |
145 | + padding: 0; | |
146 | + margin: 0; | |
147 | + } | |
148 | + | |
149 | + .icon-circle { | |
150 | + cursor: pointer; | |
151 | + | |
152 | + -webkit-box-shadow: inset 0px -2px 2px 0px rgba(0,0,0,0.3); | |
153 | + -moz-box-shadow: inset 0px -2px 2px 0px rgba(0,0,0,0.3); | |
154 | + box-shadow: inset 0px -2px 2px 0px rgba(0,0,0,0.3); | |
155 | + | |
156 | + -webkit-transition: all 0.3s ease; | |
157 | + -moz-transition: all 0.3s ease; | |
158 | + transition: all 0.3s ease; | |
159 | + | |
160 | + &:hover { | |
161 | + -webkit-box-shadow: none; | |
162 | + -moz-box-shadow: none; | |
163 | + box-shadow: none; | |
164 | + } | |
165 | + | |
166 | + &:active, | |
167 | + &:focus { | |
168 | + -webkit-box-shadow: inset 0px 2px 2px 0px rgba(0,0,0,0.3); | |
169 | + -moz-box-shadow: inset 0px 2px 2px 0px rgba(0,0,0,0.3); | |
170 | + box-shadow: inset 0px 2px 2px 0px rgba(0,0,0,0.3); | |
171 | + } | |
172 | + } | |
173 | +} | ... | ... |
src/app/components/proposal-carousel/proposal-carousel.directive.js
0 → 100644
... | ... | @@ -0,0 +1,94 @@ |
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, $state, $element, $timeout, $log) { | |
13 | + $log.debug('ProposalCarouselController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$scope = $scope; | |
17 | + vm.$state = $state; | |
18 | + vm.$element = $element; | |
19 | + vm.$timeout = $timeout; | |
20 | + vm.$log = $log; | |
21 | + | |
22 | + vm.init(); | |
23 | + } | |
24 | + | |
25 | + ProposalCarouselController.prototype.init = function () { | |
26 | + // initial values | |
27 | + var vm = this; | |
28 | + | |
29 | + if(!vm.proposals){ | |
30 | + throw { name: 'NotDefined', message: 'The attribute "proposals" is undefined.'}; | |
31 | + } | |
32 | + | |
33 | + vm.activeIndex = 0; | |
34 | + vm.loading = false; | |
35 | + vm.proposalsLength = vm.proposals.length; | |
36 | + }; | |
37 | + | |
38 | + ProposalCarouselController.prototype.swipeLeft = function () { | |
39 | + var vm = this; | |
40 | + | |
41 | + vm.activeIndex = (vm.activeIndex < vm.proposalsLength - 1) ? ++vm.activeIndex : 0; | |
42 | + }; | |
43 | + | |
44 | + ProposalCarouselController.prototype.swipeRight = function () { | |
45 | + var vm = this; | |
46 | + | |
47 | + vm.activeIndex = (vm.activeIndex > 0) ? --vm.activeIndex : vm.proposalsLength - 1; | |
48 | + }; | |
49 | + | |
50 | + ProposalCarouselController.prototype.switchProposal = function (index) { | |
51 | + var vm = this; | |
52 | + | |
53 | + if(index >= 0 && index < vm.proposalsLength) { | |
54 | + vm.activeIndex = index; | |
55 | + }else{ | |
56 | + vm.$log.warn('[switchProposal] "index" not handled:', index); | |
57 | + } | |
58 | + }; | |
59 | + | |
60 | + ProposalCarouselController.prototype.showProposalsList = function () { | |
61 | + var vm = this; | |
62 | + | |
63 | + // notify parents - handled by parents | |
64 | + vm.$scope.$emit('proposal-carousel:showProposalsList'); | |
65 | + }; | |
66 | + | |
67 | + ProposalCarouselController.prototype.showContent = function (proposal) { | |
68 | + var vm = this; | |
69 | + | |
70 | + vm.$state.go('programa', { | |
71 | + slug: proposal.parent.slug, | |
72 | + proposal_id: proposal.id | |
73 | + }, { | |
74 | + location: true, | |
75 | + reload: true | |
76 | + }); | |
77 | + }; | |
78 | + | |
79 | + var directive = { | |
80 | + restrict: 'E', | |
81 | + templateUrl: 'app/components/proposal-carousel/proposal-carousel.html', | |
82 | + scope: { | |
83 | + proposals: '=' | |
84 | + }, | |
85 | + controller: ProposalCarouselController, | |
86 | + controllerAs: 'vm', | |
87 | + bindToController: true | |
88 | + }; | |
89 | + | |
90 | + | |
91 | + return directive; | |
92 | + } | |
93 | + | |
94 | +})(); | ... | ... |
src/app/components/proposal-carousel/proposal-carousel.html
0 → 100644
... | ... | @@ -0,0 +1,41 @@ |
1 | +<div class="proposal-carousel"> | |
2 | + <div ng-if="vm.proposals"> | |
3 | + <div class="proposal-carousel-top color-theme-bg-complementar-2"> | |
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"> | |
20 | + <div class="inner">{{::proposal.abstract}}</div> | |
21 | + </div> | |
22 | + </div> | |
23 | + <div class="join" ng-show="vm.activeIndex === $index"> | |
24 | + <button type="button" class="btn btn-link btn-rate color-theme-common-fg" ng-click="vm.showContent(proposal)"> | |
25 | + Participe | |
26 | + <span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span> | |
27 | + </button> | |
28 | + </div> | |
29 | + <div class="proposal-carousel-middle-watermark" ng-show="vm.activeIndex === $index"> | |
30 | + <span>{{::($index+1)}}º</span> | |
31 | + </div> | |
32 | + </div> | |
33 | + </div> | |
34 | + <div class="proposal-carousel-bottom color-theme-common-bg" ng-click="vm.showProposalsList()"> | |
35 | + <div>Veja as propostas mais votadas</div> | |
36 | + <div class="proposal-carousel-bottom-icon"> | |
37 | + <span class="glyphicon glyphicon-chevron-down pull-right color-theme-common-fg" aria-hidden="true"></span> | |
38 | + </div> | |
39 | + </div> | |
40 | + </div> | |
41 | +</div> | ... | ... |
src/app/components/proposal-carousel/proposal-carousel.scss
0 → 100644
... | ... | @@ -0,0 +1,106 @@ |
1 | +.proposal-carousel { | |
2 | + background-color: #f1f1f1; | |
3 | + border-radius: 5px; | |
4 | + overflow: hidden; | |
5 | + margin-bottom: 30px; | |
6 | + | |
7 | + &-top { | |
8 | + position: relative; | |
9 | + color: #fff; | |
10 | + font-weight: bold; | |
11 | + font-size: 25px; | |
12 | + padding: 10px 15px; | |
13 | + | |
14 | + &-triggers { | |
15 | + position: absolute; | |
16 | + right: 15px; | |
17 | + top: 8px; | |
18 | + | |
19 | + li { | |
20 | + padding-left: 15px; | |
21 | + | |
22 | + &:first-child { | |
23 | + padding-left: 0; | |
24 | + } | |
25 | + } | |
26 | + | |
27 | + button { | |
28 | + border: 1px solid #fff; | |
29 | + border-radius: 100%; | |
30 | + width: 15px; | |
31 | + height: 15px; | |
32 | + margin-right: 5px; | |
33 | + background-color: transparent; | |
34 | + | |
35 | + cursor: pointer; | |
36 | + | |
37 | + &.active { | |
38 | + background-color: #fff; | |
39 | + } | |
40 | + } | |
41 | + } | |
42 | + } | |
43 | + | |
44 | + &-middle { | |
45 | + position: relative; | |
46 | + padding: 25px 30px; | |
47 | + min-height: 200px; | |
48 | + // cursor: pointer; | |
49 | + -webkit-user-select: none; | |
50 | + -khtml-user-select: none; | |
51 | + -moz-user-select: none; | |
52 | + -ms-user-select: none; | |
53 | + user-select: none; | |
54 | + | |
55 | + .content { | |
56 | + position: relative; | |
57 | + z-index: 10; | |
58 | + } | |
59 | + | |
60 | + .join { | |
61 | + position: absolute; | |
62 | + bottom: 32px; | |
63 | + z-index: 10; | |
64 | + | |
65 | + .btn { | |
66 | + padding: 0; | |
67 | + font-weight: bold; | |
68 | + font-size: 16px; | |
69 | + } | |
70 | + } | |
71 | + | |
72 | + &-watermark { | |
73 | + position: absolute; | |
74 | + bottom: 1px; | |
75 | + left: -5px; | |
76 | + color: #e6e6e6; | |
77 | + font-size: 150px; | |
78 | + font-weight: bold; | |
79 | + line-height: 116px; | |
80 | + z-index: 1; | |
81 | + } | |
82 | + } | |
83 | + | |
84 | + &-bottom { | |
85 | + position: relative; | |
86 | + color: #fff; | |
87 | + padding: 15px 30px; | |
88 | + font-weight: bold; | |
89 | + cursor: pointer; | |
90 | + z-index: 10; | |
91 | + | |
92 | + &-icon { | |
93 | + position: absolute; | |
94 | + top: 15px; | |
95 | + right: 15px; | |
96 | + | |
97 | + .glyphicon { | |
98 | + position: relative; | |
99 | + top: -2px; | |
100 | + background-color: #fff; | |
101 | + padding: 6px 5px 5px 6px; | |
102 | + border-radius: 100%; | |
103 | + } | |
104 | + } | |
105 | + } | |
106 | +} | ... | ... |
src/app/components/proposal-grid/proposal-grid.directive.js
0 → 100644
... | ... | @@ -0,0 +1,52 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('proposalGrid', proposalGrid); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function proposalGrid() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ProposalGridController($scope, $rootScope, $element, $location, $filter, $log) { | |
13 | + $log.debug('ProposalGridController'); | |
14 | + | |
15 | + // alias | |
16 | + var vm = this; | |
17 | + | |
18 | + // dependencies | |
19 | + vm.$scope = $scope; | |
20 | + vm.$rootScope = $rootScope; | |
21 | + vm.$element = $element; | |
22 | + vm.$location = $location; | |
23 | + vm.$filter = $filter; | |
24 | + vm.$log = $log; | |
25 | + | |
26 | + // initialization | |
27 | + vm.init(); | |
28 | + vm.attachListeners(); | |
29 | + } | |
30 | + | |
31 | + ProposalGridController.prototype.init = function() { | |
32 | + // var vm = this; | |
33 | + }; | |
34 | + | |
35 | + ProposalGridController.prototype.attachListeners = function() { | |
36 | + // var vm = this; | |
37 | + }; | |
38 | + | |
39 | + var directive = { | |
40 | + restrict: 'E', | |
41 | + templateUrl: 'app/components/proposal-grid/proposal-grid.html', | |
42 | + scope: { | |
43 | + proposals: '=' | |
44 | + }, | |
45 | + controller: ProposalGridController, | |
46 | + controllerAs: 'vm', | |
47 | + bindToController: true | |
48 | + }; | |
49 | + | |
50 | + return directive; | |
51 | + } | |
52 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<div class="proposal-grid row"> | |
2 | + <div ng-repeat="proposal in vm.proposals as results"> | |
3 | + <proposal-box proposal="proposal" topic="proposal.parent" category="proposal.parent.categories[0]" class="col-xs-12 col-sm-6"></proposal-box> | |
4 | + <div ng-if="$odd" class="clearfix"></div> | |
5 | + </div> | |
6 | + <div class="animate-repeat" ng-if="results.length == 0"> | |
7 | + Nenhum programa encontrado. | |
8 | + </div> | |
9 | +</div> | ... | ... |
src/app/components/proposal-list/proposal-list.directive.js
0 → 100644
... | ... | @@ -0,0 +1,77 @@ |
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($state, $element, $timeout, $log) { | |
13 | + $log.debug('ProposalListController'); | |
14 | + | |
15 | + var vm = this; | |
16 | + vm.$state = $state; | |
17 | + vm.$element = $element; | |
18 | + vm.$timeout = $timeout; | |
19 | + vm.$log = $log; | |
20 | + | |
21 | + vm.init(); | |
22 | + } | |
23 | + | |
24 | + ProposalListController.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.$timeout(function(){ | |
33 | + attachPopover.call(vm); | |
34 | + }, 1000); | |
35 | + }; | |
36 | + | |
37 | + ProposalListController.prototype.showContent = function (proposal) { | |
38 | + var vm = this; | |
39 | + | |
40 | + vm.$state.go('programa', { | |
41 | + slug: proposal.parent.slug, | |
42 | + proposal_id: proposal.id | |
43 | + }, { | |
44 | + location: true, | |
45 | + reload: true | |
46 | + }); | |
47 | + }; | |
48 | + | |
49 | + function attachPopover(){ | |
50 | + var vm = this; | |
51 | + | |
52 | + vm.popover = angular.element(vm.$element.find('.btn-question')); | |
53 | + vm.popover.popover({ | |
54 | + html: true, | |
55 | + placement: 'bottom', | |
56 | + animation: true, | |
57 | + title: 'Regra de posição das propostas', | |
58 | + 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>' | |
59 | + }); | |
60 | + } | |
61 | + | |
62 | + var directive = { | |
63 | + restrict: 'E', | |
64 | + templateUrl: 'app/components/proposal-list/proposal-list.html', | |
65 | + scope: { | |
66 | + proposals: '=' | |
67 | + }, | |
68 | + controller: ProposalListController, | |
69 | + controllerAs: 'vm', | |
70 | + bindToController: true | |
71 | + }; | |
72 | + | |
73 | + | |
74 | + return directive; | |
75 | + } | |
76 | + | |
77 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,39 @@ |
1 | +<div class="proposal-list"> | |
2 | + <div class="" ng-if="vm.proposals"> | |
3 | + <table class="table table-striped"> | |
4 | + <thead> | |
5 | + <tr> | |
6 | + <th> | |
7 | + Colocação | |
8 | + <a tabindex="0" class="btn btn-link btn-question" role="button" data-toggle="popover" data-trigger="focus">?</a> | |
9 | + </th> | |
10 | + <th>{{vm.proposals.length}} PROPOSTAS</th> | |
11 | + </tr> | |
12 | + </thead> | |
13 | + <tbody> | |
14 | + <tr ng-repeat="proposal in vm.proposals"> | |
15 | + <td class="color-theme-fg"> | |
16 | + <span class="position">{{::proposal.ranking_position}}º</span> | |
17 | + </td> | |
18 | + <td> | |
19 | + <div class="row"> | |
20 | + <div class="col-xs-12"> | |
21 | + <div class="abstract" ng-bind-html="proposal.abstract"></div> | |
22 | + </div> | |
23 | + </div> | |
24 | + <div class="row row-actions"> | |
25 | + <div class="col-sm-8"> | |
26 | + <button type="button" class="btn btn-link btn-rate color-theme-common-fg" ng-click="vm.showContent(proposal)"> | |
27 | + Participe | |
28 | + </button> | |
29 | + </div> | |
30 | + <div class="col-sm-4"> | |
31 | + <proposal-stats class="text-right" views="{{::proposal.hits}}" up="{{::proposal.votes_for}}" down="{{::proposal.votes_against}}"></proposal-stats> | |
32 | + </div> | |
33 | + </div> | |
34 | + </td> | |
35 | + </tr> | |
36 | + </tbody> | |
37 | + </table> | |
38 | + </div> | |
39 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,83 @@ |
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 | + .popover { | |
20 | + color: #484848; | |
21 | + } | |
22 | + } | |
23 | + | |
24 | + tbody { | |
25 | + tr { | |
26 | + background-color: #fff; | |
27 | + } | |
28 | + | |
29 | + td { | |
30 | + &:first-child { | |
31 | + font-size: 22px; | |
32 | + font-weight: bold; | |
33 | + padding: 0; | |
34 | + text-align: right; | |
35 | + } | |
36 | + } | |
37 | + | |
38 | + .position { | |
39 | + display: block; | |
40 | + width: 100%; | |
41 | + margin: 20px 0; | |
42 | + padding: 5px 20px; | |
43 | + border-top-right-radius: 4px; | |
44 | + border-bottom-right-radius: 4px; | |
45 | + } | |
46 | + } | |
47 | + | |
48 | + .abstract { | |
49 | + color: #393939; | |
50 | + font-size: 18px; | |
51 | + } | |
52 | + | |
53 | + .row-actions { | |
54 | + padding-top: 20px; | |
55 | + } | |
56 | + | |
57 | + .btn-rate { | |
58 | + padding: 0; | |
59 | + font-size: 20px; | |
60 | + font-weight: bold; | |
61 | + text-decoration: blink; | |
62 | + } | |
63 | + | |
64 | + // override bootstrap | |
65 | + .table-striped > tbody > tr:nth-of-type(odd) { | |
66 | + // impar | |
67 | + background-color: #eaeaea; | |
68 | + | |
69 | + .position { | |
70 | + background-color: #fff; | |
71 | + } | |
72 | + } | |
73 | + | |
74 | + .table-striped > tbody > tr:nth-of-type(even) { | |
75 | + // par | |
76 | + background-color: #fff; | |
77 | + | |
78 | + .position { | |
79 | + background-color: #eaeaea; | |
80 | + } | |
81 | + } | |
82 | + | |
83 | +} | ... | ... |
src/app/components/proposal-stats/proposal-stats.directive.js
0 → 100644
... | ... | @@ -0,0 +1,20 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('proposalStats', proposalStats); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function proposalStats() { | |
10 | + | |
11 | + var directive = { | |
12 | + restrict: 'E', | |
13 | + templateUrl: 'app/components/proposal-stats/proposal-stats.html' | |
14 | + // no scope. Use the parent scope. | |
15 | + }; | |
16 | + | |
17 | + return directive; | |
18 | + } | |
19 | + | |
20 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,16 @@ |
1 | +<div class="proposal-stats"> | |
2 | + <ul class="list-inline"> | |
3 | + <li class="proposal-stats-up"> | |
4 | + <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> | |
5 | + <span>{{proposal.votes_for}}</span> | |
6 | + </li> | |
7 | + <li class="proposal-stats-down"> | |
8 | + <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> | |
9 | + <span>{{proposal.votes_against}}</span> | |
10 | + </li> | |
11 | + <li class="proposal-stats-views"> | |
12 | + <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span> | |
13 | + <span>{{proposal.hits}}</span> | |
14 | + </li> | |
15 | + </ul> | |
16 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,20 @@ |
1 | +.proposal-stats { | |
2 | + font-weight: bold; | |
3 | + | |
4 | + .list-inline { | |
5 | + margin: 10px 0; | |
6 | + } | |
7 | + | |
8 | + li { | |
9 | + margin: 0 5px; | |
10 | + padding-left: 15px; | |
11 | + | |
12 | + &:first-child { | |
13 | + padding-left: 0px; | |
14 | + } | |
15 | + } | |
16 | + | |
17 | + &-views {} | |
18 | + &-up .glyphicon {color: #4ac97a; } | |
19 | + &-down .glyphicon {color: #ef4a68; } | |
20 | +} | ... | ... |
src/app/components/service/utils.service.js
... | ... | @@ -1,78 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - angular | |
5 | - .module('dialoga') | |
6 | - .factory('UtilService', UtilService); | |
7 | - | |
8 | - /** @ngInject */ | |
9 | - function UtilService($http, $q, $log) { | |
10 | - $log.debug('UtilService'); | |
11 | - | |
12 | - var service = { | |
13 | - get: get, | |
14 | - post: post, | |
15 | - // put: put, | |
16 | - // delete: delete, | |
17 | - // head: head, | |
18 | - handleSuccess: handleSuccess, | |
19 | - handleError: handleError | |
20 | - }; | |
21 | - | |
22 | - return service; | |
23 | - | |
24 | - function get (url, config) { | |
25 | - return $http.get(url, config) | |
26 | - .then(handleSuccess) | |
27 | - .catch(handleError); | |
28 | - } | |
29 | - | |
30 | - function post (url, config) { | |
31 | - return $http.post(url, config) | |
32 | - .then(handleSuccess) | |
33 | - .catch(handleError); | |
34 | - } | |
35 | - | |
36 | - /** | |
37 | - * Transform the successful response, unwrapping the application data | |
38 | - * from the API response payload. | |
39 | - * | |
40 | - * @param {Object} response from the server. | |
41 | - * data – {string|Object} – The response body transformed with the transform functions. | |
42 | - * status – {number} – HTTP status code of the response. | |
43 | - * headers – {function([headerName])} – Header getter function. | |
44 | - * config – {Object} – The configuration object that was used to generate the request. | |
45 | - * statusText – {string} – HTTP status text of the response. | |
46 | - * | |
47 | - * @return {Object} the data unwrapped. | |
48 | - */ | |
49 | - function handleSuccess (response) { | |
50 | - $log.debug('[SUCCESS]', response); | |
51 | - return response.data; | |
52 | - } | |
53 | - | |
54 | - /** | |
55 | - * Transform the error response, unwrapping the application data from | |
56 | - * the API response payload. | |
57 | - * | |
58 | - * @param {Object} error from the server. | |
59 | - * @return {Promise} promise rejection called. | |
60 | - */ | |
61 | - function handleError (error) { | |
62 | - $log.debug('[ERROR]', error); | |
63 | - | |
64 | - $log.error('XHR Failed on Service.\n' + angular.toJson(error.data, true)); | |
65 | - | |
66 | - // The API response from the server should be returned in a | |
67 | - // nomralized format. However, if the request was not handled by the | |
68 | - // server (or what not handles properly - ex. server error), then we | |
69 | - // may have to normalize it on our end, as best we can. | |
70 | - if (!angular.isObject(error.data) || !error.data.message) { | |
71 | - return $q.reject('An unknown error occurred.'); | |
72 | - } | |
73 | - | |
74 | - // Otherwise, use expected error message. | |
75 | - return $q.reject(error.data.message); | |
76 | - } | |
77 | - } | |
78 | -})(); |
src/app/components/service/utils.service.spec.js
... | ... | @@ -1,28 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - describe('util services', function() { | |
5 | - // var UtilService, httpBackend; | |
6 | - | |
7 | - // beforeEach(module('dialoga')); | |
8 | - | |
9 | - // beforeEach(inject(function(_UtilService_, $httpBackend) { | |
10 | - // UtilService = _UtilService_; | |
11 | - // httpBackend = $httpBackend; | |
12 | - // })); | |
13 | - | |
14 | - // it('should do something', function() { | |
15 | - // var url = 'http://example.com/api/v1/data/103358'; | |
16 | - // httpBackend.whenGET(url).respond({}); | |
17 | - | |
18 | - // UtilService.getData().then(function(result) { | |
19 | - | |
20 | - // expect(result.data).toBeDefined(); | |
21 | - // expect(result.data.title).toEqual('My Title'); | |
22 | - | |
23 | - // }); | |
24 | - | |
25 | - // httpBackend.flush(); | |
26 | - // }); | |
27 | - }); | |
28 | -})(); |
src/app/components/show-message/show-message.directive.js
0 → 100644
... | ... | @@ -0,0 +1,33 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('showMessage', showMessage); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function showMessage() { | |
10 | + | |
11 | + /** @ngInject */ | |
12 | + function ShowMessageController($log) { | |
13 | + // var vm = this; | |
14 | + $log.debug('ShowMessageController'); | |
15 | + } | |
16 | + | |
17 | + var directive = { | |
18 | + restrict: 'E', | |
19 | + templateUrl: 'app/components/show-message/show-message.html', | |
20 | + scope: { | |
21 | + type: '=', | |
22 | + message: '=', | |
23 | + description: '=' | |
24 | + }, | |
25 | + controller: ShowMessageController, | |
26 | + controllerAs: 'vm', | |
27 | + bindToController: true | |
28 | + }; | |
29 | + | |
30 | + return directive; | |
31 | + } | |
32 | + | |
33 | +})(); | ... | ... |
... | ... | @@ -0,0 +1,15 @@ |
1 | +<div id="message" class="show-message"> | |
2 | + <div class="row"> | |
3 | + <div class="col-sm-2 col-sm-offset-2 message-icon-wrapper text-right text-center-sm"> | |
4 | + <div class="message-icon text-center color-fg-white" ng-class="[vm.type]"> | |
5 | + <span ng-if="vm.type === 'success'" class="glyphicon glyphicon-ok" aria-hidden="true"></span> | |
6 | + <span ng-if="vm.type === 'alert'" class="glyphicon glyphicon-alert" aria-hidden="true"></span> | |
7 | + <span ng-if="vm.type === 'error'" class="glyphicon glyphicon-remove" aria-hidden="true"></span> | |
8 | + </div> | |
9 | + </div> | |
10 | + <div class="col-sm-8 message-content text-center-sm"> | |
11 | + <h3>{{ ::vm.message }}</h3> | |
12 | + <div ng-bind-html="vm.description"></div> | |
13 | + </div> | |
14 | + </div> | |
15 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +.show-message { | |
2 | + | |
3 | + .message-icon { | |
4 | + background-color: #ccc; | |
5 | + border-radius: 100%; | |
6 | + padding: 20px 7px; | |
7 | + width: 80px; | |
8 | + height: 80px; | |
9 | + display: inline-block; | |
10 | + | |
11 | + font-size: 26px; | |
12 | + | |
13 | + &.alert { | |
14 | + background-color: #EEB453; | |
15 | + } | |
16 | + | |
17 | + &.success { | |
18 | + background-color: #8AB34D; | |
19 | + } | |
20 | + | |
21 | + &.error { | |
22 | + background-color: #C93E55; | |
23 | + } | |
24 | + } | |
25 | +} | ... | ... |
src/app/components/social-share/social-share.directive.js
0 → 100644
... | ... | @@ -0,0 +1,34 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('dialoga') | |
6 | + .directive('socialShare', socialShare); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function socialShare() { | |
10 | + var directive = { | |
11 | + restrict: 'E', | |
12 | + templateUrl: 'app/components/social-share/social-share.html', | |
13 | + scope: { | |
14 | + url: '=', | |
15 | + image: '=', | |
16 | + text: '=', | |
17 | + arrowClass: '@', | |
18 | + }, | |
19 | + controller: SocialShareController, | |
20 | + controllerAs: 'vm', | |
21 | + bindToController: true | |
22 | + }; | |
23 | + | |
24 | + return directive; | |
25 | + | |
26 | + /** @ngInject */ | |
27 | + function SocialShareController($log) { | |
28 | + $log.debug('SocialShareController'); | |
29 | + | |
30 | + // var vm = this; | |
31 | + } | |
32 | + } | |
33 | + | |
34 | +})(); | ... | ... |