├── .gitignore ├── LICENSE ├── Makefile ├── README.rst ├── __init__.py ├── apps ├── __init__.py ├── home_page │ ├── __init__.py │ ├── features │ │ ├── resources │ │ │ ├── erp5.png │ │ │ ├── nsi.png │ │ │ └── x.png │ │ ├── show_index.feature │ │ └── steps.py │ ├── templates │ │ └── index.html │ ├── tests.py │ └── views.py ├── members │ ├── __init__.py │ ├── admin.py │ ├── features │ │ ├── manage_members.feature │ │ ├── resources │ │ │ ├── batata_photo.png │ │ │ ├── pedro_photo.png │ │ │ └── pluck_photo.png │ │ └── steps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto__chg_field_member_current_team.py │ │ ├── 0003_auto__del_field_member_current_team.py │ │ ├── 0004_auto__add_participation__del_field_member_project_memberships.py │ │ ├── 0005_auto__add_field_member_function__chg_field_member_slideshare__chg_fiel.py │ │ ├── 0006_auto__add_field_member_is_renegade.py │ │ ├── 0007_auto__add_field_member_slug__chg_field_member_photo.py │ │ ├── 0008_auto__del_unique_member_slug.py │ │ ├── 0009_add_nickname.py │ │ ├── 0010_auto__add_field_member_phone.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── show_all_current_members.html │ │ ├── show_all_former_members.html │ │ └── show_member.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── news │ ├── __init__.py │ ├── admin.py │ ├── features │ │ ├── manage_news.feature │ │ ├── resources │ │ │ ├── erp5.png │ │ │ ├── nsi.png │ │ │ └── x.png │ │ └── steps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto.py │ │ ├── 0003_auto__del_new__add_news.py │ │ ├── 0004_auto__chg_field_news_image.py │ │ ├── 0005_auto__del_field_news_datetime__add_field_news_date_and_time.py │ │ ├── 0006_add_slug.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── detail_news.html │ │ └── show_news.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── nsi_info │ ├── __init__.py │ ├── admin.py │ ├── features │ │ ├── manage_history.feature │ │ └── steps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ └── show_about.html │ ├── tests.py │ └── views.py ├── projects │ ├── __init__.py │ ├── admin.py │ ├── features │ │ ├── link_documents_to_project.feature │ │ ├── manage_projects.feature │ │ ├── resources │ │ │ ├── erp5.png │ │ │ └── nsi.png │ │ └── steps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto__chg_field_project_end_date.py │ │ ├── 0003_auto__add_document.py │ │ ├── 0004_add_slug.py │ │ ├── 0005_auto__add_field_project_github.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── show_all_projects.html │ │ └── show_project.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── tools │ ├── __init__.py │ ├── admin.py │ ├── features │ │ ├── manage_tools.feature │ │ ├── resources │ │ │ ├── ludibrio.png │ │ │ ├── ricks.png │ │ │ └── should-dsl.png │ │ └── steps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto__add_field_tool_logo.py │ │ ├── 0003_auto__add_field_tool_status.py │ │ ├── 0004_auto__add_field_tool_short_description.py │ │ ├── 0005_add_slug.py │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── show_all.html │ │ └── show_tool.html │ ├── tests.py │ ├── urls.py │ └── views.py └── wiki │ ├── __init__.py │ ├── features │ ├── manage_wiki.feature │ └── steps.py │ ├── forms.py │ ├── models.py │ ├── templates │ ├── add_wiki_item.html │ ├── delete_wiki_item.html │ ├── edit_wiki_item.html │ ├── wiki_item.html │ ├── wiki_item_successfully_added.html │ ├── wiki_item_successfully_deleted.html │ ├── wiki_item_successfully_updated.html │ └── wiki_items.html │ ├── tests │ ├── test_forms.py │ ├── test_models.py │ └── test_views.py │ ├── urls.py │ └── views.py ├── manage.py ├── paths.py ├── settings.py ├── settings_test.py ├── setup_on_debian_like.sh ├── site_media ├── css │ ├── base.css │ ├── index.css │ ├── members.css │ ├── news.css │ ├── nsi_info.css │ ├── projects.css │ ├── tools.css │ └── wiki.css ├── files │ └── projects │ │ └── .gitignore ├── images │ ├── base │ │ ├── background_head.jpg │ │ ├── favicon.ico │ │ ├── feed.32x32.png │ │ ├── github.32x32.png │ │ ├── icon_github.png │ │ ├── icon_lattes.png │ │ ├── icon_site.png │ │ ├── icon_slideshare.png │ │ ├── icon_twitter.png │ │ ├── logo.png │ │ ├── news.png │ │ ├── planetaNSI.png │ │ ├── projects.32x32.png │ │ ├── projects.png │ │ ├── tools.32x32.png │ │ └── tools.png │ ├── members │ │ └── .gitignore │ ├── news │ │ └── .gitignore │ ├── projects │ │ └── .gitignore │ └── wiki │ │ ├── add.png │ │ ├── add_hover.png │ │ ├── back.png │ │ ├── delete.png │ │ ├── delete_hover.png │ │ ├── edit.png │ │ └── edit_hover.png └── javascripts │ ├── coderwall.js │ ├── github_activities.js │ └── jquery-1.7.1.min.js ├── templates └── base.html ├── terrain.py ├── thumbs.py ├── urls.py └── web_steps.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.db 3 | *.swp 4 | *.komodoproject 5 | .komodotools 6 | build/ 7 | site_media/files 8 | site_media/images/members 9 | site_media/images/news 10 | site_media/images/projects 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by NSI-IFF_Campos-Brazil 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PYTHON=python 2 | PIP=pip 3 | 4 | export DJANGO_SETTINGS_MODULE=settings 5 | 6 | all: deps test_database test remove_test_database 7 | 8 | database: 9 | @$(PYTHON) manage.py syncdb 10 | @$(PYTHON) manage.py migrate 11 | 12 | test_database: 13 | @echo ============================================== 14 | @echo ========== Creating test database ============ 15 | @echo 16 | @$(PYTHON) manage.py syncdb --settings=settings_test 17 | @$(PYTHON) manage.py migrate --settings=settings_test 18 | 19 | 20 | remove_test_database: 21 | @echo Deleting test database... 22 | @rm nsi_site-test.db 23 | 24 | deps: app_deps functional_deps unit_deps 25 | 26 | app_deps: django pil south docutils django-pagination linaro_django_pagination 27 | 28 | functional_deps: selenium lettuce splinter should-dsl nose lxml 29 | 30 | unit_deps: should-dsl model_mommy specloud nosedjango 31 | 32 | selenium: 33 | @$(PYTHON) -c 'import selenium' 2>/dev/null || $(PIP) install selenium==2.0rc3 34 | 35 | should-dsl: 36 | @$(PYTHON) -c 'import should_dsl' 2>/dev/null || $(PIP) install http://github.com/hugobr/should-dsl/tarball/master 37 | 38 | django: 39 | @$(PYTHON) -c 'import django' 2>/dev/null || $(PIP) install django 40 | 41 | splinter: 42 | @$(PYTHON) -c 'import splinter' 2>/dev/null || $(PIP) install http://github.com/cobrateam/splinter/tarball/master 43 | 44 | pil: 45 | @$(PYTHON) -c 'import pil' 2>/dev/null || $(PIP) install PIL 46 | 47 | south: 48 | @$(PYTHON) -c 'import south' 2>/dev/null || $(PIP) install South 49 | 50 | docutils: 51 | @$(PYTHON) -c 'import docutils' 2>/dev/null || $(PIP) install docutils 52 | 53 | lettuce: 54 | @$(PYTHON) -c 'import lettuce' 2>/dev/null || $(PIP) install lettuce 55 | 56 | nose: 57 | @$(PYTHON) -c 'import nose' 2>/dev/null || $(PIP) install nose 58 | 59 | lxml: 60 | @$(PYTHON) -c 'import lxml' 2>/dev/null || $(PIP) install lxml 61 | 62 | specloud: 63 | @$(PYTHON) -c 'import specloud' 2>/dev/null || $(PIP) install specloud --no-deps -r http://github.com/hugobr/specloud/raw/master/requirements.txt 64 | 65 | nosedjango: 66 | @$(PYTHON) -c 'import nosedjango' 2>/dev/null || $(PIP) install -U nosedjango nose 67 | 68 | model_mommy: 69 | @$(PYTHON) -c 'import model_mommy' 2>/dev/null || $(PIP) install http://github.com/vandersonmota/model_mommy/tarball/master 70 | 71 | django-pagination: 72 | @$(PYTHON) -c 'import pagination' 2>/dev/null || $(PIP) install -e git+https://github.com/tiagosc/django-pagination.git#egg=pagination 73 | 74 | linaro_django_pagination: 75 | @$(PYTHON) -c 'import linaro_django_pagination' 2>/dev/null || $(PIP) install -U linaro_django_pagination 76 | 77 | test: functional unit 78 | 79 | functional: functional_deps deps 80 | @echo ============================================== 81 | @echo ========= Running acceptance specs =========== 82 | @python manage.py harvest --settings=settings_test 83 | @echo 84 | 85 | unit: unit_deps deps 86 | @echo ============================================== 87 | @echo ============ Running unit specs ============== 88 | @specloud --with-django --nocapture 89 | @echo 90 | 91 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | NSI Site 2 | ======== 3 | 4 | How to Install 5 | -------------- 6 | 7 | On Debian like 8 | ~~~~~~~~~~~~~~ 9 | Just run:: 10 | 11 | ./setup_on_debian_like.sh 12 | 13 | On Windows 14 | ~~~~~~~~~~ 15 | I don't know, sorry. 16 | 17 | 18 | Python dependencies 19 | ~~~~~~~~~~~~~~~~~~~ 20 | Run:: 21 | 22 | make deps 23 | 24 | How to create the databases 25 | --------------------------- 26 | Just run:: 27 | 28 | make database 29 | 30 | For test database, run:: 31 | 32 | make test_database 33 | 34 | Note: after you run functional tests, the admin user on test database will be "admin" with password "admin". 35 | 36 | How to Run Tests 37 | ---------------- 38 | Run `make test` to install all Python dependencies (if they are not installed) and run all tests. Depending on your environment, this script may need root permissions in order to install the dependencies. 39 | 40 | You can run `make functional` for executing only acceptance tests, and `make unit` to execute only unit tests. 41 | 42 | Remember to install all dependencies and create the test database before run any test. 43 | 44 | How to Contribute 45 | ----------------- 46 | Please: 47 | - Fork the project and submit pull request 48 | - Create an issue 49 | - Close an issue 50 | 51 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/__init__.py -------------------------------------------------------------------------------- /apps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/__init__.py -------------------------------------------------------------------------------- /apps/home_page/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/home_page/__init__.py -------------------------------------------------------------------------------- /apps/home_page/features/resources/erp5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/home_page/features/resources/erp5.png -------------------------------------------------------------------------------- /apps/home_page/features/resources/nsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/home_page/features/resources/nsi.png -------------------------------------------------------------------------------- /apps/home_page/features/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/home_page/features/resources/x.png -------------------------------------------------------------------------------- /apps/home_page/features/show_index.feature: -------------------------------------------------------------------------------- 1 | Feature: User visitor 2 | As a visitor NSI Site 3 | I want see home index data 4 | 5 | Scenario: showing News in index home 6 | Given exist a author: 7 | | name | 8 | | herman | 9 | | ronaldo | 10 | Given exist a news: 11 | | title | image | author | date_and_time | 12 | | Notícia sobre o NSI Site | test/images/news/nsi.png | herman | 15/01/2011 20:00 | 13 | | Notícia sobre o ERP5 Lek | test/images/news/erp5.png | herman | 05/04/2011 20:00 | 14 | | Notícia sobre o ERP5 e o NSI Site | test/images/news/x.png | ronaldo | 01/01/2010 20:00 | 15 | 16 | When I go to "the NSI home page" 17 | And I should see "Notícia sobre o NSI Site" 18 | And I should see an image called "nsi.png" 19 | And I should see "Postado por: herman" 20 | And I should see "15/01/2011" 21 | 22 | And I should see "Notícia sobre o ERP5 Lek" 23 | And I should see an image called "erp5.png" 24 | And I should see "Postado por: herman" 25 | And I should see "05/04/2011" 26 | 27 | And I should see "Notícia sobre o ERP5 e o NSI Site" 28 | And I should see an image called "x.png" 29 | And I should see "Postado por: ronaldo" 30 | And I should see "01/01/2010" 31 | 32 | Scenario: showing a open Projects in index home 33 | Given exist a project: 34 | | name | status | 35 | | NSI Site | aberto | 36 | | ERP5 Lek | aberto | 37 | | Abodorock | aberto | 38 | | Batata Ricks | finalizado | 39 | 40 | When I go to "the NSI home page" 41 | And I should see "NSI Site" 42 | And I should see "ERP5 Lek" 43 | And I should see "Abodorock" 44 | 45 | Scenario: showing a highlight Tools in index home 46 | Given exist a tool: 47 | | name | highlight | 48 | | Should-dsl | True | 49 | | Ludibrio | True | 50 | | rock-py | False | 51 | | Restful-py | True | 52 | 53 | When I go to "the NSI home page" 54 | And I should see "Should-dsl" 55 | And I should see "Ludibrio" 56 | And I should see "Restful-py" 57 | -------------------------------------------------------------------------------- /apps/home_page/features/steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import shutil 4 | from datetime import datetime 5 | from django.conf import settings 6 | from lettuce import step 7 | from model_mommy import mommy 8 | from apps.news.models import News 9 | from apps.projects.models import Project 10 | from apps.tools.models import Tool 11 | from django.contrib.auth.models import User 12 | 13 | 14 | @step(u'exist a author:') 15 | def exist_a_author(step): 16 | for user in step.hashes: 17 | mommy.make_one(User, username=user.get('name'), email='a@a.com') 18 | 19 | @step(u'exist a news:') 20 | def exist_a_news(step): 21 | for news_hashes in step.hashes: 22 | author = User.objects.get(username__exact=news_hashes.get('author')) 23 | date, hour = news_hashes.get('date_and_time').split() 24 | day, month, year = date.split('/') 25 | hours, minutes = hour.split(':') 26 | date_time = datetime(int(year), int(month), int(day), int(hours), int(minutes)) 27 | news = mommy.make_one(News, title=news_hashes.get('title'), image=news_hashes.get('image'), author=author, date_and_time=date_time).save() 28 | file_name = news_hashes.get('image').split('/')[-1] 29 | shutil.copy2(os.path.join(settings.PROJECT_ROOT_PATH, 'apps', 'home_page', 30 | 'features', 'resources', file_name), 31 | os.path.join(settings.MEDIA_ROOT, 'test', 'images', 'news')) 32 | 33 | @step(u'exist a project:') 34 | def exist_a_project(step): 35 | for project_hashes in step.hashes: 36 | project = mommy.make_one(Project, name=project_hashes.get('name'), status=project_hashes.get('status')) 37 | 38 | @step(u'exist a tool:') 39 | def exist_a_tool(step): 40 | for tool_hashes in step.hashes: 41 | tool = mommy.make_one(Tool, name=tool_hashes.get('name'), highlight=tool_hashes.get('highlight')) 42 | 43 | -------------------------------------------------------------------------------- /apps/home_page/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | 9 | {% block content %} 10 |
11 |
12 |
13 | Projetos 14 |
15 | {% for project_obj in projects %} 16 |
17 | 18 |
19 | {{ project_obj.name }} 20 |
21 |
22 | {% endfor %} 23 |
24 | 25 |
26 |
27 | Notícias 28 |
29 | {% for news_obj in news %} 30 |
31 | {% if news_obj.image %} 32 |
33 | 34 | {{ news_obj.title }} 35 |
36 |
37 | {% else %} 38 |
39 | {% endif %} 40 |

{{ news_obj.title }}

41 |
42 | Postado por: {{ news_obj.author }} 43 | {{ news_obj.date_and_time|date:"d/m/Y" }} 44 |
45 | {% endfor %} 46 |
47 |

Leia mais +

48 |
49 |
50 | 51 |
52 |
53 | Ferramentas 54 |
55 | {% for tool_obj in tools %} 56 |
57 | 58 |
59 | {{ tool_obj.name }} 60 |
61 |
62 | {% endfor %} 63 |
64 | 65 |
66 |
67 | Planeta NSI 68 |
69 |
70 | 71 |
72 | Feeds 73 |
74 |
75 |
76 | 77 |
78 | GitHub 79 |
80 |
81 |
82 |
83 | 84 |
85 | {% endblock content %} 86 | -------------------------------------------------------------------------------- /apps/home_page/tests.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | 3 | from django.test import TestCase 4 | 5 | 6 | class HomePageTest(TestCase): 7 | pass 8 | 9 | -------------------------------------------------------------------------------- /apps/home_page/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.news.models import News 4 | from apps.projects.models import Project 5 | from apps.tools.models import Tool 6 | 7 | def show_index(request): 8 | news = News.objects.all()[:3] 9 | projects = Project.objects.filter(status='aberto') 10 | tools = Tool.objects.filter(highlight=True) 11 | return render_to_response( 12 | 'index.html', 13 | {'news': news, 'projects': projects, 'tools': tools}, 14 | context_instance=RequestContext(request) 15 | ) 16 | -------------------------------------------------------------------------------- /apps/members/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/members/__init__.py -------------------------------------------------------------------------------- /apps/members/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from apps.members.models import Member 3 | from apps.members.models import Participation 4 | 5 | 6 | class ParticipationInline(admin.TabularInline): 7 | model = Participation 8 | extra = 1 9 | 10 | class MemberAdmin(admin.ModelAdmin): 11 | list_display = ('name', 'function', 'site','github', 'twitter','slideshare','lattes','phone','started_nsi_date', 'is_renegade') 12 | list_filter = ('function','started_nsi_date','is_renegade') 13 | inlines = [ParticipationInline] 14 | 15 | 16 | admin.site.register(Member, MemberAdmin) 17 | admin.site.register(Participation) 18 | -------------------------------------------------------------------------------- /apps/members/features/resources/batata_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/members/features/resources/batata_photo.png -------------------------------------------------------------------------------- /apps/members/features/resources/pedro_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/members/features/resources/pedro_photo.png -------------------------------------------------------------------------------- /apps/members/features/resources/pluck_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/members/features/resources/pluck_photo.png -------------------------------------------------------------------------------- /apps/members/features/steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import shutil 4 | from lettuce import step, world 5 | from django.conf import settings 6 | from lettuce.django import django_url 7 | from should_dsl import should 8 | from model_mommy import mommy 9 | from apps.members.models import Member 10 | from apps.members.models import Participation 11 | from apps.projects.models import Project 12 | 13 | @step(u'exist a project:') 14 | def given_exist_a_project(step): 15 | for project in step.hashes: 16 | mommy.make_one(Project, name=project.get('name'), logo=None) 17 | 18 | @step(u'exist a member:') 19 | def exist_a_member(step): 20 | for member in step.hashes: 21 | Member(**member).save() 22 | file_name = member.get('photo').split('/')[-1] 23 | shutil.copy2(os.path.join(settings.PROJECT_ROOT_PATH, 'apps', 'members', 24 | 'features', 'resources', file_name), 25 | os.path.join(settings.MEDIA_ROOT, 'test', 'images', 'members')) 26 | 27 | @step(r'"(.*)" member started participation the "(.*)" project in "(.*)"') 28 | def and_member_participation_the_project_in(step, member_name, project_name, start_participation_date): 29 | member = Member.objects.get(name=member_name) 30 | project = Project.objects.get(name=project_name) 31 | Participation(member=member, project=project, start_date=start_participation_date).save() 32 | 33 | @step(r'"(.*)" member participated on "(.*)" project between "(.*)" and "(.*)"') 34 | def and_member_participated_on_project_between(step, member_name, project_name, start_participation_date, end_participation_date): 35 | member = Member.objects.get(name=member_name) 36 | project = Project.objects.get(name=project_name) 37 | Participation(member=member, project=project, start_date=start_participation_date, end_date=end_participation_date).save() 38 | 39 | @step(r'I go to the "(.+)" member page') 40 | def i_go_to_member_page(step, member_name): 41 | member_obj = Member.objects.get(name=member_name) 42 | world.browser.visit(django_url('/membro/%s' % member_obj.slug)) 43 | 44 | @step(r'I go to the "(.+)" former member page') 45 | def i_go_to_former_member_page(step, member_name): 46 | member_obj = Member.objects.get(name=member_name) 47 | world.browser.visit(django_url('/ex-membro/%s' % member_obj.slug)) 48 | 49 | @step(u'I should see a label "(.*)" with the link to "(.*)"') 50 | def i_should_see_a_label_with_link(step, link_text, link_href): 51 | links = world.browser.find_link_by_href(link_href) 52 | links |should| have_at_least(1).item 53 | link_value = links[0].value 54 | link_label, link_value_text = link_value.split(': ') 55 | link_value_text |should| equal_to(link_text) 56 | 57 | @step(r'I should see the following members') 58 | def i_should_see_the_following_members(step): 59 | 60 | for member_data in step.hashes: 61 | member = Member.objects.get(name=member_data['name']) 62 | 63 | container_photo = world.browser.find_by_css('#member%s .avatar' % member.id) 64 | container_image_name = container_photo[0]['src'].split("/")[-1] 65 | container_image_name |should| equal_to(member_data['photo']) 66 | 67 | title_text = world.browser.find_by_css('#member%s h1' % member.id) 68 | title_text[0].value |should| equal_to(member_data['name']) 69 | 70 | function_text = world.browser.find_by_css('#member%s span' % member.id) 71 | function_text[0].value |should| equal_to(member_data['function']) 72 | 73 | currently_does_text = world.browser.find_by_css('#member%s p' % member.id) 74 | currently_does_text[0].value |should| equal_to(member_data['currently_does']) 75 | 76 | container_links = world.browser.find_by_css('#member%s .links a' % member.id) 77 | container_links_href = [x['href'] for x in container_links] 78 | 79 | member_data['site'] |should| be_into(container_links_href) 80 | member_data['github'] |should| be_into(container_links_href) 81 | member_data['twitter'] |should| be_into(container_links_href) 82 | member_data['slideshare'] |should| be_into(container_links_href) 83 | -------------------------------------------------------------------------------- /apps/members/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Member' 12 | db.create_table('members_member', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('name', self.gf('django.db.models.fields.CharField')(max_length=100)), 15 | ('current_team', self.gf('django.db.models.fields.CharField')(max_length=100)), 16 | ('currently_does', self.gf('django.db.models.fields.TextField')()), 17 | ('life_and_work', self.gf('django.db.models.fields.TextField')()), 18 | ('site', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)), 19 | ('github', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)), 20 | ('twitter', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)), 21 | ('slideshare', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)), 22 | ('lattes', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)), 23 | ('photo', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), 24 | ('project_memberships', self.gf('django.db.models.fields.CharField')(max_length=100)), 25 | ('started_nsi_date', self.gf('django.db.models.fields.DateField')()), 26 | ('desertion_nsi_date', self.gf('django.db.models.fields.DateField')(null=True)), 27 | )) 28 | db.send_create_signal('members', ['Member']) 29 | 30 | 31 | def backwards(self, orm): 32 | 33 | # Deleting model 'Member' 34 | db.delete_table('members_member') 35 | 36 | 37 | models = { 38 | 'members.member': { 39 | 'Meta': {'object_name': 'Member'}, 40 | 'current_team': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 41 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 42 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 43 | 'github': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 44 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 45 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 46 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 47 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 48 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 49 | 'project_memberships': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 50 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 51 | 'slideshare': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 52 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 53 | 'twitter': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}) 54 | } 55 | } 56 | 57 | complete_apps = ['members'] 58 | -------------------------------------------------------------------------------- /apps/members/migrations/0002_auto__chg_field_member_current_team.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Changing field 'Member.current_team' 12 | db.alter_column('members_member', 'current_team', self.gf('django.db.models.fields.CharField')(max_length=100, null=True)) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # User chose to not deal with backwards NULL issues for 'Member.current_team' 18 | raise RuntimeError("Cannot reverse this migration. 'Member.current_team' and its values cannot be restored.") 19 | 20 | 21 | models = { 22 | 'members.member': { 23 | 'Meta': {'object_name': 'Member'}, 24 | 'current_team': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}), 25 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 26 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 27 | 'github': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 30 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 31 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 32 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 33 | 'project_memberships': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 34 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 35 | 'slideshare': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 36 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 37 | 'twitter': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}) 38 | } 39 | } 40 | 41 | complete_apps = ['members'] 42 | -------------------------------------------------------------------------------- /apps/members/migrations/0003_auto__del_field_member_current_team.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Deleting field 'Member.current_team' 12 | db.delete_column('members_member', 'current_team') 13 | 14 | # Adding M2M table for field current_team on 'Member' 15 | db.create_table('members_member_current_team', ( 16 | ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), 17 | ('member', models.ForeignKey(orm['members.member'], null=False)), 18 | ('team', models.ForeignKey(orm['teams.team'], null=False)) 19 | )) 20 | db.create_unique('members_member_current_team', ['member_id', 'team_id']) 21 | 22 | 23 | def backwards(self, orm): 24 | 25 | # Adding field 'Member.current_team' 26 | db.add_column('members_member', 'current_team', self.gf('django.db.models.fields.CharField')(max_length=100, null=True), keep_default=False) 27 | 28 | # Removing M2M table for field current_team on 'Member' 29 | db.delete_table('members_member_current_team') 30 | 31 | 32 | models = { 33 | 'members.member': { 34 | 'Meta': {'object_name': 'Member'}, 35 | 'current_team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['teams.Team']", 'symmetrical': 'False'}), 36 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 37 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 38 | 'github': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 39 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 40 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 41 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 42 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 43 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 44 | 'project_memberships': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 45 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 46 | 'slideshare': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 47 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 48 | 'twitter': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}) 49 | }, 50 | 'teams.team': { 51 | 'Meta': {'object_name': 'Team'}, 52 | 'description': ('django.db.models.fields.TextField', [], {}), 53 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 54 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 55 | } 56 | } 57 | 58 | complete_apps = ['members'] 59 | -------------------------------------------------------------------------------- /apps/members/migrations/0004_auto__add_participation__del_field_member_project_memberships.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Participation' 12 | db.create_table('members_participation', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('member', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['members.Member'])), 15 | ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['projects.Project'])), 16 | ('start_date', self.gf('django.db.models.fields.DateField')()), 17 | ('end_date', self.gf('django.db.models.fields.DateField')(null=True)), 18 | )) 19 | db.send_create_signal('members', ['Participation']) 20 | 21 | # Deleting field 'Member.project_memberships' 22 | db.delete_column('members_member', 'project_memberships') 23 | 24 | # Removing M2M table for field current_team on 'Member' 25 | db.delete_table('members_member_current_team') 26 | 27 | 28 | def backwards(self, orm): 29 | 30 | # Deleting model 'Participation' 31 | db.delete_table('members_participation') 32 | 33 | # User chose to not deal with backwards NULL issues for 'Member.project_memberships' 34 | raise RuntimeError("Cannot reverse this migration. 'Member.project_memberships' and its values cannot be restored.") 35 | 36 | # Adding M2M table for field current_team on 'Member' 37 | db.create_table('members_member_current_team', ( 38 | ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), 39 | ('member', models.ForeignKey(orm['members.member'], null=False)), 40 | ('team', models.ForeignKey(orm['teams.team'], null=False)) 41 | )) 42 | db.create_unique('members_member_current_team', ['member_id', 'team_id']) 43 | 44 | 45 | models = { 46 | 'members.member': { 47 | 'Meta': {'object_name': 'Member'}, 48 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 49 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 50 | 'github': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 51 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 52 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 53 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 54 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 55 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 56 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 57 | 'slideshare': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), 58 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 59 | 'twitter': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}) 60 | }, 61 | 'members.participation': { 62 | 'Meta': {'object_name': 'Participation'}, 63 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 64 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 65 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 66 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 67 | 'start_date': ('django.db.models.fields.DateField', [], {}) 68 | }, 69 | 'projects.project': { 70 | 'Meta': {'object_name': 'Project'}, 71 | 'description': ('django.db.models.fields.TextField', [], {}), 72 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 73 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 74 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 75 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 76 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 77 | 'start_date': ('django.db.models.fields.DateField', [], {}), 78 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 79 | } 80 | } 81 | 82 | complete_apps = ['members'] 83 | -------------------------------------------------------------------------------- /apps/members/migrations/0005_auto__add_field_member_function__chg_field_member_slideshare__chg_fiel.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Member.function' 12 | db.add_column('members_member', 'function', self.gf('django.db.models.fields.CharField')(default='nao informado', max_length=100), keep_default=False) 13 | 14 | # Changing field 'Member.slideshare' 15 | db.alter_column('members_member', 'slideshare', self.gf('django.db.models.fields.CharField')(max_length=50, null=True)) 16 | 17 | # Changing field 'Member.twitter' 18 | db.alter_column('members_member', 'twitter', self.gf('django.db.models.fields.CharField')(max_length=50, null=True)) 19 | 20 | # Changing field 'Member.github' 21 | db.alter_column('members_member', 'github', self.gf('django.db.models.fields.CharField')(max_length=50, null=True)) 22 | 23 | 24 | def backwards(self, orm): 25 | 26 | # Deleting field 'Member.function' 27 | db.delete_column('members_member', 'function') 28 | 29 | # Changing field 'Member.slideshare' 30 | db.alter_column('members_member', 'slideshare', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)) 31 | 32 | # Changing field 'Member.twitter' 33 | db.alter_column('members_member', 'twitter', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)) 34 | 35 | # Changing field 'Member.github' 36 | db.alter_column('members_member', 'github', self.gf('django.db.models.fields.URLField')(max_length=200, null=True)) 37 | 38 | 39 | models = { 40 | 'members.member': { 41 | 'Meta': {'object_name': 'Member'}, 42 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 43 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 44 | 'function': ('django.db.models.fields.CharField', [], {'default': "'nao informado'", 'max_length': '100'}), 45 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 46 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 47 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 48 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 49 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 50 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 51 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 52 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 53 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 54 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 55 | }, 56 | 'members.participation': { 57 | 'Meta': {'object_name': 'Participation'}, 58 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 59 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 60 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 61 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 62 | 'start_date': ('django.db.models.fields.DateField', [], {}) 63 | }, 64 | 'projects.project': { 65 | 'Meta': {'object_name': 'Project'}, 66 | 'description': ('django.db.models.fields.TextField', [], {}), 67 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 68 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 69 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 70 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 71 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 72 | 'start_date': ('django.db.models.fields.DateField', [], {}), 73 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 74 | } 75 | } 76 | 77 | complete_apps = ['members'] 78 | -------------------------------------------------------------------------------- /apps/members/migrations/0006_auto__add_field_member_is_renegade.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Member.is_renegade' 12 | db.add_column('members_member', 'is_renegade', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Member.is_renegade' 18 | db.delete_column('members_member', 'is_renegade') 19 | 20 | 21 | models = { 22 | 'members.member': { 23 | 'Meta': {'object_name': 'Member'}, 24 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 25 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'function': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 27 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_renegade': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 31 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 32 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 33 | 'photo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 34 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 35 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 36 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 37 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 38 | }, 39 | 'members.participation': { 40 | 'Meta': {'object_name': 'Participation'}, 41 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 42 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 43 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 44 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 45 | 'start_date': ('django.db.models.fields.DateField', [], {}) 46 | }, 47 | 'projects.project': { 48 | 'Meta': {'object_name': 'Project'}, 49 | 'description': ('django.db.models.fields.TextField', [], {}), 50 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 51 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 52 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 53 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 54 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 55 | 'start_date': ('django.db.models.fields.DateField', [], {}), 56 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 57 | } 58 | } 59 | 60 | complete_apps = ['members'] 61 | -------------------------------------------------------------------------------- /apps/members/migrations/0007_auto__add_field_member_slug__chg_field_member_photo.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Member.slug' 12 | db.add_column('members_member', 'slug', self.gf('django.db.models.fields.SlugField')(db_index=True, default='', unique=True, max_length=100, blank=True), keep_default=False) 13 | 14 | # Changing field 'Member.photo' 15 | db.alter_column('members_member', 'photo', self.gf('thumbs.ImageWithThumbsField')(max_length=100, name='photo', sizes=((100, 100),))) 16 | 17 | 18 | def backwards(self, orm): 19 | 20 | # Deleting field 'Member.slug' 21 | db.delete_column('members_member', 'slug') 22 | 23 | # Changing field 'Member.photo' 24 | db.alter_column('members_member', 'photo', self.gf('django.db.models.fields.files.ImageField')(max_length=100)) 25 | 26 | 27 | models = { 28 | 'members.member': { 29 | 'Meta': {'object_name': 'Member'}, 30 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 31 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 32 | 'function': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 33 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 34 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 35 | 'is_renegade': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 36 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 37 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 38 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 39 | 'photo': ('thumbs.ImageWithThumbsField', [], {'max_length': '100', 'name': "'photo'", 'sizes': '((100, 100),)'}), 40 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 41 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 42 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'unique': 'True', 'max_length': '100', 'blank': 'True'}), 43 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 44 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 45 | }, 46 | 'members.participation': { 47 | 'Meta': {'object_name': 'Participation'}, 48 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 49 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 50 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 51 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 52 | 'start_date': ('django.db.models.fields.DateField', [], {}) 53 | }, 54 | 'projects.project': { 55 | 'Meta': {'object_name': 'Project'}, 56 | 'description': ('django.db.models.fields.TextField', [], {}), 57 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 58 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 59 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 60 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 61 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 62 | 'start_date': ('django.db.models.fields.DateField', [], {}), 63 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 64 | } 65 | } 66 | 67 | complete_apps = ['members'] 68 | -------------------------------------------------------------------------------- /apps/members/migrations/0008_auto__del_unique_member_slug.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Removing unique constraint on 'Member', fields ['slug'] 12 | db.delete_unique('members_member', ['slug']) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Adding unique constraint on 'Member', fields ['slug'] 18 | db.create_unique('members_member', ['slug']) 19 | 20 | 21 | models = { 22 | 'members.member': { 23 | 'Meta': {'object_name': 'Member'}, 24 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 25 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'function': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 27 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_renegade': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 31 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 32 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 33 | 'photo': ('thumbs.ImageWithThumbsField', [], {'max_length': '100', 'name': "'photo'", 'sizes': '((100, 100),)'}), 34 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 35 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 36 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 37 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 38 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 39 | }, 40 | 'members.participation': { 41 | 'Meta': {'object_name': 'Participation'}, 42 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 43 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 44 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 45 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 46 | 'start_date': ('django.db.models.fields.DateField', [], {}) 47 | }, 48 | 'projects.project': { 49 | 'Meta': {'object_name': 'Project'}, 50 | 'description': ('django.db.models.fields.TextField', [], {}), 51 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 52 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 53 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 54 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 55 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 56 | 'start_date': ('django.db.models.fields.DateField', [], {}), 57 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 58 | } 59 | } 60 | 61 | complete_apps = ['members'] 62 | -------------------------------------------------------------------------------- /apps/members/migrations/0009_add_nickname.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Member.nickname' 12 | db.add_column('members_member', 'nickname', self.gf('django.db.models.fields.CharField')(max_length=100, null=True, blank=True), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Member.nickname' 18 | db.delete_column('members_member', 'nickname') 19 | 20 | 21 | models = { 22 | 'members.member': { 23 | 'Meta': {'object_name': 'Member'}, 24 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 25 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'function': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 27 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_renegade': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 31 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 32 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 33 | 'nickname': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 34 | 'photo': ('thumbs.ImageWithThumbsField', [], {'max_length': '100', 'name': "'photo'", 'sizes': '((100, 100),)'}), 35 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 36 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 37 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 38 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 39 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 40 | }, 41 | 'members.participation': { 42 | 'Meta': {'object_name': 'Participation'}, 43 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 44 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 45 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 46 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 47 | 'start_date': ('django.db.models.fields.DateField', [], {}) 48 | }, 49 | 'projects.project': { 50 | 'Meta': {'object_name': 'Project'}, 51 | 'description': ('django.db.models.fields.TextField', [], {}), 52 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 53 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 54 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 55 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 56 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 57 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 58 | 'start_date': ('django.db.models.fields.DateField', [], {}), 59 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 60 | } 61 | } 62 | 63 | complete_apps = ['members'] 64 | -------------------------------------------------------------------------------- /apps/members/migrations/0010_auto__add_field_member_phone.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Member.phone' 12 | db.add_column('members_member', 'phone', self.gf('django.db.models.fields.CharField')(max_length=13, null=True, blank=True), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Member.phone' 18 | db.delete_column('members_member', 'phone') 19 | 20 | 21 | models = { 22 | 'members.member': { 23 | 'Meta': {'object_name': 'Member'}, 24 | 'currently_does': ('django.db.models.fields.TextField', [], {}), 25 | 'desertion_nsi_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'function': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 27 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 28 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 29 | 'is_renegade': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 30 | 'lattes': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 31 | 'life_and_work': ('django.db.models.fields.TextField', [], {}), 32 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 33 | 'nickname': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 34 | 'phone': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True', 'blank': 'True'}), 35 | 'photo': ('thumbs.ImageWithThumbsField', [], {'max_length': '100', 'name': "'photo'", 'sizes': '((100, 100),)'}), 36 | 'site': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 37 | 'slideshare': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), 38 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 39 | 'started_nsi_date': ('django.db.models.fields.DateField', [], {}), 40 | 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) 41 | }, 42 | 'members.participation': { 43 | 'Meta': {'object_name': 'Participation'}, 44 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 45 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 46 | 'member': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['members.Member']"}), 47 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 48 | 'start_date': ('django.db.models.fields.DateField', [], {}) 49 | }, 50 | 'projects.project': { 51 | 'Meta': {'object_name': 'Project'}, 52 | 'description': ('django.db.models.fields.TextField', [], {}), 53 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 54 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 55 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 56 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 57 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 58 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 59 | 'start_date': ('django.db.models.fields.DateField', [], {}), 60 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 61 | } 62 | } 63 | 64 | complete_apps = ['members'] 65 | -------------------------------------------------------------------------------- /apps/members/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/members/migrations/__init__.py -------------------------------------------------------------------------------- /apps/members/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.template.defaultfilters import slugify 3 | from thumbs import ImageWithThumbsField 4 | from apps.projects.models import Project 5 | 6 | 7 | MEMBER_FUNCTIONS = ( 8 | ('0', 'gerente'), 9 | ('1', 'coordenador'), 10 | ('2', 'pesquisador'), 11 | ('3', 'bolsista'), 12 | ('4', 'colaborador')) 13 | 14 | 15 | class Participation(models.Model): 16 | member = models.ForeignKey('Member') 17 | project = models.ForeignKey(Project) 18 | start_date = models.DateField() 19 | end_date = models.DateField(null=True, blank=True) 20 | 21 | def __unicode__(self): 22 | return self.member.name + ' - ' + self.project.name 23 | 24 | class Member(models.Model): 25 | name = models.CharField(max_length=100) 26 | nickname = models.CharField(max_length=100, null=True, blank=True) 27 | phone = models.CharField(max_length=13, null=True, blank=True) 28 | currently_does = models.TextField() 29 | life_and_work = models.TextField() 30 | function = models.CharField(max_length=100, choices=MEMBER_FUNCTIONS) 31 | site = models.URLField(null=True, blank=True) 32 | github = models.CharField(max_length=50, null=True, blank=True) 33 | twitter = models.CharField(max_length=50, null=True, blank=True) 34 | slideshare = models.CharField(max_length=50, null=True, blank=True) 35 | lattes = models.URLField(null=True, blank=True) 36 | photo = ImageWithThumbsField(upload_to='images/members', sizes=((100, 100), )) 37 | started_nsi_date = models.DateField() 38 | desertion_nsi_date = models.DateField(null=True, blank=True) 39 | is_renegade = models.BooleanField(editable=False) 40 | slug = models.SlugField(max_length=100, blank=True) 41 | 42 | def github_link(self): 43 | return "http://github.com/" + self.github 44 | 45 | def twitter_link(self): 46 | return "http://twitter.com/" + self.twitter 47 | 48 | def slideshare_link(self): 49 | return "http://www.slideshare.net/" + self.slideshare 50 | 51 | def github_feed(self): 52 | return self.github_link() + '.atom' 53 | 54 | def __unicode__(self): 55 | return self.name 56 | 57 | def save(self, *args, **kwargs): 58 | self.slug = slugify(self.name) 59 | if self.desertion_nsi_date is not None: 60 | self.is_renegade = True 61 | super(Member, self).save(*args, **kwargs) 62 | else: 63 | self.is_renegade = False 64 | super(Member, self).save(*args, **kwargs) 65 | 66 | -------------------------------------------------------------------------------- /apps/members/templates/show_all_current_members.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 |
10 | {% for member in members %} 11 |
12 | 13 | {{ member.name }} 14 | 15 |
16 |

17 | {{ member.name }} 18 |

19 | {{ member.get_function_display }} 20 |

{{ member.currently_does }}

21 |
22 | 59 |
60 | {% endfor %} 61 |
62 | {% endblock content %} 63 | 64 | -------------------------------------------------------------------------------- /apps/members/templates/show_all_former_members.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 |
10 | {% for member in members %} 11 |
12 | 13 | {{ member.name }} 14 | 15 |
16 |

17 | {{ member.name }} 18 |

19 | {{ member.get_function_display }} 20 |

{{ member.currently_does }}

21 |
22 | 59 |
60 | {% endfor %} 61 |
62 | {% endblock content %} 63 | 64 | -------------------------------------------------------------------------------- /apps/members/templates/show_member.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block styles %} 3 | {{ block.super }} 4 | {% endblock styles %} 5 | 6 | {% block scripts %} 7 | {{ block.super }} 8 | 9 | 10 | {% endblock scripts %} 11 | 12 | {% block content %} 13 |
14 | {{ member.name }} 15 |
16 |

{{ member.name }}

17 | {% if member.nickname %} 18 |
({{ member.nickname }}) 19 | {% endif %} 20 | {% if user.is_authenticated %} 21 | {% if member.phone %} 22 |

{{ member.phone }} 23 | {% endif %} 24 | {% endif %} 25 |

{{ member.currently_does }}

26 |

{{ member.life_and_work }}

27 |

Função: {{ member.get_function_display }}

28 | 60 | {% if member.desertion_nsi_date %} 61 | Data de início no NSI: {{ member.started_nsi_date|date:"d/m/Y" }} 62 |
63 | Data de saída do NSI: {{ member.desertion_nsi_date|date:"d/m/Y" }} 64 | {% else %} 65 | Membro desde: {{ member.started_nsi_date|date:"d/m/Y" }} 66 | {% endif %} 67 | {% if participation_list %} 68 |

69 |

Participações:

70 | 82 |

83 | {% endif %} 84 | {% if member.github %} 85 |
86 |

87 | 88 | 89 |
    90 |
91 |
92 | {% endif %} 93 |
94 |
95 |
96 |
97 | {% endblock content %} 98 | 99 | -------------------------------------------------------------------------------- /apps/members/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from should_dsl import should 3 | from model_mommy import mommy 4 | from apps.members.models import Member 5 | 6 | 7 | class MemberTest(TestCase): 8 | def test_github_link(self): 9 | m = mommy.make_one(Member, github="pluck", photo="ricks_sunshine.png") 10 | m.github_link() |should| equal_to("http://github.com/pluck") 11 | 12 | def test_twitter_link(self): 13 | m = mommy.make_one(Member, twitter="pluck", photo="ricks_sunshine.png") 14 | m.twitter_link() |should| equal_to("http://twitter.com/pluck") 15 | 16 | def test_slideshare_link(self): 17 | m = mommy.make_one(Member, slideshare="pluck", photo="ricks_sunshine.png") 18 | m.slideshare_link() |should| equal_to("http://www.slideshare.net/pluck") 19 | 20 | -------------------------------------------------------------------------------- /apps/members/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.views.generic.simple import direct_to_template 3 | from django.conf import settings 4 | 5 | from django.contrib import admin 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | (r'^membros/$', 'apps.members.views.show_all_current_members'), 10 | (r'^membro/(?P[\w_-]+)$', 'apps.members.views.show_member'), 11 | 12 | (r'^ex-membros/$', 'apps.members.views.show_all_former_members'), 13 | (r'^ex-membro/(?P[\w_-]+)$', 'apps.members.views.show_member'), 14 | 15 | ) 16 | -------------------------------------------------------------------------------- /apps/members/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.members.models import Member 4 | 5 | 6 | def show_all_current_members(request): 7 | members = Member.objects.filter(is_renegade=False).order_by('function', 'started_nsi_date') 8 | return render_to_response( 9 | 'show_all_current_members.html', 10 | {'members': members}, 11 | context_instance=RequestContext(request) 12 | ) 13 | 14 | def show_member(request, slug): 15 | member = Member.objects.get(slug=slug) 16 | participation_list = member.participation_set.all() 17 | members = Member.objects.all() 18 | return render_to_response( 19 | 'show_member.html', 20 | {'member': member, 'participation_list': participation_list, 'members': members}, 21 | context_instance=RequestContext(request) 22 | ) 23 | 24 | def show_all_former_members(request): 25 | members = Member.objects.filter(is_renegade=True) 26 | return render_to_response( 27 | 'show_all_former_members.html', 28 | {'members': members}, 29 | context_instance=RequestContext(request) 30 | ) 31 | -------------------------------------------------------------------------------- /apps/news/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/news/__init__.py -------------------------------------------------------------------------------- /apps/news/admin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | from django.contrib.admin import site 4 | 5 | from apps.news.models import News 6 | 7 | site.register(News) 8 | -------------------------------------------------------------------------------- /apps/news/features/manage_news.feature: -------------------------------------------------------------------------------- 1 | Feature: News maintenance 2 | As a NSI site administrator 3 | I want to handle news data 4 | In order to know details about whats happening at NSI 5 | 6 | Scenario: showing a news 7 | Given exist a author: 8 | | name | 9 | | rogerio | 10 | And exist a project: 11 | | name | 12 | | NSI Site | 13 | And exist a news: 14 | | title | summary | body | image | author | date_and_time | 15 | | Notícia sobre o NSI Site | O site do NSI está no ar | Já está no ar o site do NSI! | test/images/news/nsi.png | rogerio | 15/01/2011 20:00 | 16 | And the news "Notícia sobre o NSI Site" is related with project "NSI Site" 17 | When I go to "the news page" 18 | Then I should see "Notícia sobre o NSI Site" 19 | And I should see "O site do NSI está no ar" 20 | And I should see "Já está no ar o site do NSI!" 21 | And I should see an image called "nsi.png" 22 | And I should see "Postado por: rogerio" 23 | And I should see "Data: 15/01/2011 às 20:00" 24 | 25 | Scenario: showing many news 26 | Given exist a author: 27 | | name | 28 | | rogerio | 29 | | ronaldo | 30 | | herman | 31 | And exist a project: 32 | | name | 33 | | NSI Site | 34 | | ERP5 | 35 | 36 | And exist a news: 37 | | title | summary | body | image | author | date_and_time | 38 | | Notícia sobre o NSI Site | O site do NSI está no ar | Já está no ar o site do NSI! | test/images/news/nsi.png | rogerio | 15/01/2011 20:00 | NSI Site | 39 | | Notícia sobre o ERP5 Lek | Rick Rock Sunshine Project | ERP5 Lek, muita coisa pronta | test/images/news/erp5.png | ronaldo | 16/01/2011 20:00 | ERP5 | 40 | | Notícia sobre o ERP5 e o NSI Site | Rick Rock Sunshine Project NSI e ERP5 | NSI power site e ERP5 Lek, muita coisa pronta | test/images/news/x.png | herman | 16/01/2011 23:00 | ERP5 NSI Site | 41 | 42 | And the news "Notícia sobre o NSI Site" is related with project "NSI Site" 43 | And the news "Notícia sobre o ERP5 Lek" is related with project "ERP5" 44 | And the news "Notícia sobre o ERP5 e o NSI Site" is related with project "ERP5" 45 | And the news "Notícia sobre o ERP5 e o NSI Site" is related with project "NSI Site" 46 | When I go to "the news page" 47 | Then I should see "Notícia sobre o NSI Site" 48 | And I should see "O site do NSI está no ar" 49 | And I should see "Já está no ar o site do NSI!" 50 | And I should see an image called "nsi.png" 51 | And I should see "Postado por: rogerio" 52 | And I should see "Data: 15/01/2011 às 20:00" 53 | 54 | And I should see "Notícia sobre o ERP5 Lek" 55 | And I should see "Rick Rock Sunshine Project" 56 | And I should see "ERP5 Lek, muita coisa pronta" 57 | And I should see an image called "erp5.png" 58 | And I should see "Postado por: ronaldo" 59 | And I should see "Data: 16/01/2011 às 20:00" 60 | 61 | And I should see "Notícia sobre o ERP5 e o NSI Site" 62 | And I should see "Rick Rock Sunshine Project NSI e ERP5" 63 | And I should see "NSI power site e ERP5 Lek, muita coisa pronta" 64 | And I should see an image called "x.png" 65 | And I should see "Postado por: herman" 66 | And I should see "Data: 16/01/2011 às 23:00" 67 | 68 | Scenario: showing a especific news 69 | Given exist a author: 70 | | name | 71 | | herman | 72 | 73 | And exist a project: 74 | | name | 75 | | NSI Site | 76 | 77 | And exist a news: 78 | | title | summary | body | image | author | date_and_time | 79 | | Notícia sobre o NSI Site | O site do NSI está no ar | Já está no ar o site do NSI! | test/images/news/nsi.png | herman | 15/01/2011 20:00 | 80 | 81 | And the news "Notícia sobre o NSI Site" is related with project "NSI Site" 82 | When I go to "the news page" 83 | And I click "Notícia sobre o NSI Site" 84 | Then I should see "Notícia sobre o NSI Site" 85 | And I should see "O site do NSI está no ar" 86 | And I should see "Já está no ar o site do NSI!" 87 | And I should see an image called "nsi.png" 88 | And I should see "Postado por: herman" 89 | And I should see "Data: 15/01/2011 às 20:00" 90 | And I should see "NSI Site" 91 | 92 | 93 | Scenario: News are rendered as RST 94 | Given exist a author: 95 | | name | 96 | | herman | 97 | And exist a project: 98 | | name | 99 | | NSI Site | 100 | And exist a news: 101 | | title | summary | body | image | author | date_and_time | 102 | | Notícia sobre o NSI Site | O site do NSI está no ar | Já está no ar o *site do NSI*! | test/images/news/nsi.png | herman | 15/01/2011 20:00 | 103 | When I go to "the news page" 104 | And I click "Notícia sobre o NSI Site" 105 | Then I should have "Já está no ar o site do NSI!" as HTML 106 | 107 | -------------------------------------------------------------------------------- /apps/news/features/resources/erp5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/news/features/resources/erp5.png -------------------------------------------------------------------------------- /apps/news/features/resources/nsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/news/features/resources/nsi.png -------------------------------------------------------------------------------- /apps/news/features/resources/x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/news/features/resources/x.png -------------------------------------------------------------------------------- /apps/news/features/steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import shutil 4 | from lettuce import step 5 | from datetime import datetime 6 | from django.conf import settings 7 | from model_mommy import mommy 8 | from django.contrib.auth.models import User 9 | from apps.projects.models import Project 10 | from apps.news.models import News 11 | 12 | 13 | @step(u'exist a author:') 14 | def exist_a_author(step): 15 | for user in step.hashes: 16 | mommy.make_one(User, username=user.get('name'), email='a@a.com') 17 | 18 | @step(u'exist a project:') 19 | def exist_a_project(step): 20 | for project in step.hashes: 21 | mommy.make_one(Project, name=project.get('name'), logo=None) 22 | 23 | @step(u'the news "(.*)" is related with project "(.*)"') 24 | def the_news_is_related_with_project(step, news_title, project_name): 25 | project_obj = Project.objects.get(name=project_name) 26 | news_obj = News.objects.get(title=news_title) 27 | news_obj.projects_relateds.add(project_obj) 28 | news_obj.save() 29 | 30 | @step(u'exist a news:') 31 | def exist_a_news(step): 32 | for news_hashes in step.hashes: 33 | author = User.objects.get(username__exact=news_hashes.get('author')) 34 | date, hour = news_hashes.get('date_and_time').split() 35 | day, month, year = date.split('/') 36 | hours, minutes = hour.split(':') 37 | date_time = datetime(int(year), int(month), int(day), int(hours), int(minutes)) 38 | News(title=news_hashes.get('title'), summary=news_hashes.get('summary'), body=news_hashes.get('body'), image=news_hashes.get('image'), author=author, date_and_time=date_time).save() 39 | file_name = news_hashes.get('image').split('/')[-1] 40 | shutil.copy2(os.path.join(settings.PROJECT_ROOT_PATH, 'apps', 'news', 41 | 'features', 'resources', file_name), 42 | os.path.join(settings.MEDIA_ROOT, 'test', 'images', 'news')) 43 | -------------------------------------------------------------------------------- /apps/news/migrations/0004_auto__chg_field_news_image.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Changing field 'News.image' 12 | db.alter_column('news_news', 'image', self.gf('thumbs.ImageWithThumbsField')(name='image', sizes=((300, 300), (90, 90)), max_length=100, null=True)) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Changing field 'News.image' 18 | db.alter_column('news_news', 'image', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True)) 19 | 20 | 21 | models = { 22 | 'auth.group': { 23 | 'Meta': {'object_name': 'Group'}, 24 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 25 | 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), 26 | 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) 27 | }, 28 | 'auth.permission': { 29 | 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, 30 | 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 31 | 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), 32 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 33 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) 34 | }, 35 | 'auth.user': { 36 | 'Meta': {'object_name': 'User'}, 37 | 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 38 | 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 39 | 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 40 | 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), 41 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 42 | 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), 43 | 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 44 | 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 45 | 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 46 | 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), 47 | 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), 48 | 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 49 | 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) 50 | }, 51 | 'contenttypes.contenttype': { 52 | 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, 53 | 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 54 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 55 | 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 56 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 57 | }, 58 | 'news.news': { 59 | 'Meta': {'object_name': 'News'}, 60 | 'author': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), 61 | 'body': ('django.db.models.fields.TextField', [], {}), 62 | 'datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 3, 24, 19, 16, 47, 662542)'}), 63 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 64 | 'image': ('thumbs.ImageWithThumbsField', [], {'name': "'image'", 'sizes': '((300, 300), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 65 | 'projects_relateds': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 66 | 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}), 67 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) 68 | }, 69 | 'projects.project': { 70 | 'Meta': {'object_name': 'Project'}, 71 | 'description': ('django.db.models.fields.TextField', [], {}), 72 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 73 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 74 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 75 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 76 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 77 | 'start_date': ('django.db.models.fields.DateField', [], {}), 78 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 79 | } 80 | } 81 | 82 | complete_apps = ['news'] 83 | -------------------------------------------------------------------------------- /apps/news/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/news/migrations/__init__.py -------------------------------------------------------------------------------- /apps/news/models.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime as dt 2 | from django.db import models 3 | from django.template.defaultfilters import slugify 4 | from django.contrib.auth.models import User 5 | from thumbs import ImageWithThumbsField 6 | from docutils.core import publish_parts 7 | from apps.projects.models import Project 8 | 9 | 10 | class News(models.Model): 11 | 12 | class Meta: 13 | verbose_name_plural = 'News' 14 | ordering = ['-date_and_time'] 15 | 16 | title = models.CharField(max_length=200) 17 | summary = models.CharField(max_length=200, null=True, blank=True) 18 | body = models.TextField() 19 | image = ImageWithThumbsField(null=True, blank=True, upload_to='images/news', sizes=((150, 150), (90, 90), )) 20 | author = models.ForeignKey(User) 21 | date_and_time = models.DateTimeField(default=dt.now()) 22 | projects_relateds = models.ManyToManyField(Project, null=True, blank=True) 23 | slug = models.SlugField(max_length=200, blank=True) 24 | 25 | def __unicode__(self): 26 | return self.title 27 | 28 | def body_as_html(self): 29 | parts = publish_parts(source=self.body, writer_name="html4css1") 30 | return parts['fragment'] 31 | 32 | def save(self, *args, **kwargs): 33 | self.slug = slugify(self.title) 34 | super(News, self).save(*args, **kwargs) 35 | 36 | -------------------------------------------------------------------------------- /apps/news/templates/detail_news.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block scripts %} 4 | {{ bloc.super }} 5 | 6 | {% endblock scripts %} 7 | 8 | {% block content %} 9 |
10 | {% if news_obj.image %} 11 |
12 | {{ news_obj.title }} 13 |
14 | {% endif %} 15 |

{{ news_obj.title }}

16 |

{{ news_obj.summary }}

17 |

{{ news_obj.body_as_html|safe }}

18 |

Postado por: {{ news_obj.author }}

19 |

Data: {{ news_obj.date_and_time|date:"d/m/Y à\s H:i" }}

20 | {% if news_obj.projects_relateds.all %} 21 |

Projetos relacionados:

22 |
    23 | {% for project in news_obj.projects_relateds.all %} 24 |
  • {{ project.name }}
  • 25 | {% endfor %} 26 |
27 | {% endif %} 28 |
29 | {% endblock content %} 30 | 31 | -------------------------------------------------------------------------------- /apps/news/templates/show_news.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load pagination_tags %} 4 | 5 | {% block styles %} 6 | {{ block.super }} 7 | 8 | {% endblock styles %} 9 | 10 | {% block content %} 11 |
12 | {% autopaginate news 5 %} 13 | {% for new in news %} 14 |
15 | {% if new.image %} 16 | 17 | {{ new.title }} 18 | 19 | {% endif %} 20 |

{{ new.title }}

21 |

{{ new.summary }}

22 |

{{ new.body|slice:"200" }} ...

23 |

24 | Data: {{ new.date_and_time|date:"d/m/Y à\s H:i" }} - Postado por: {{ new.author }} 25 | Leia mais + 26 |

27 |
28 | {% endfor %} 29 |
30 | {% paginate %} 31 | {% endblock content %} 32 | -------------------------------------------------------------------------------- /apps/news/tests.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | from django.test import TestCase 3 | from should_dsl import should 4 | from apps.news.models import News 5 | 6 | 7 | class TestNews(TestCase): 8 | 9 | def test_convert_its_RST_body_to_HTML(self): 10 | h = News(body="*NSI* site rulz!") 11 | h.body_as_html() |should| contain('NSI site rulz!') 12 | 13 | -------------------------------------------------------------------------------- /apps/news/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.views.generic.simple import direct_to_template 3 | from django.conf import settings 4 | 5 | from django.contrib import admin 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | 10 | (r'^noticias/$', 'apps.news.views.show_news'), 11 | (r'^noticia/(?P[\w_-]+)$', 'apps.news.views.detail_news'), 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /apps/news/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.news.models import News 4 | 5 | 6 | def show_news(request): 7 | news = News.objects.all() 8 | return render_to_response( 9 | 'show_news.html', 10 | {'news': news}, 11 | context_instance=RequestContext(request) 12 | ) 13 | 14 | def detail_news(request, news_slug): 15 | news_obj = News.objects.get(slug=news_slug) 16 | return render_to_response( 17 | 'detail_news.html', 18 | {'news_obj':news_obj}, 19 | context_instance=RequestContext(request) 20 | ) 21 | -------------------------------------------------------------------------------- /apps/nsi_info/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/nsi_info/__init__.py -------------------------------------------------------------------------------- /apps/nsi_info/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from apps.nsi_info.models import NSIInfo 3 | 4 | 5 | admin.site.register(NSIInfo) 6 | 7 | -------------------------------------------------------------------------------- /apps/nsi_info/features/manage_history.feature: -------------------------------------------------------------------------------- 1 | Feature: NSI info maintenance 2 | As a NSI site administrator 3 | I want to maintain NSI-related data 4 | In order to keep people informed about the glorious NSI 5 | 6 | Scenario Outline: Info page 7 | Given current is "Hello, we are the glorious NSI." 8 | When I go to "the page" 9 | Then I should see "Hello, we are the glorious NSI." 10 | 11 | Examples: 12 | | field | 13 | | about | 14 | 15 | Scenario Outline: Accepts restructuredText format input 16 | Given current is "*NSI* rules!" 17 | When I go to "the page" 18 | Then I should have "NSI rules!" as HTML 19 | 20 | Examples: 21 | | field | 22 | | about | 23 | -------------------------------------------------------------------------------- /apps/nsi_info/features/steps.py: -------------------------------------------------------------------------------- 1 | from lettuce import step 2 | from apps.nsi_info.models import NSIInfo 3 | 4 | 5 | @step(u'current about is "(.*)"') 6 | def current_about_is(step, about_text): 7 | if len(NSIInfo.objects.all()) == 0: 8 | NSIInfo(about=about_text).save() 9 | else: 10 | info = NSIInfo.objects.all()[0] 11 | info.about = about_text 12 | info.save() 13 | 14 | -------------------------------------------------------------------------------- /apps/nsi_info/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'NSIInfo' 12 | db.create_table('nsi_info_nsiinfo', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('about', self.gf('django.db.models.fields.TextField')()), 15 | ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), 16 | )) 17 | db.send_create_signal('nsi_info', ['NSIInfo']) 18 | 19 | 20 | def backwards(self, orm): 21 | 22 | # Deleting model 'NSIInfo' 23 | db.delete_table('nsi_info_nsiinfo') 24 | 25 | 26 | models = { 27 | 'nsi_info.nsiinfo': { 28 | 'Meta': {'object_name': 'NSIInfo'}, 29 | 'about': ('django.db.models.fields.TextField', [], {}), 30 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 31 | 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) 32 | } 33 | } 34 | 35 | complete_apps = ['nsi_info'] 36 | -------------------------------------------------------------------------------- /apps/nsi_info/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/nsi_info/migrations/__init__.py -------------------------------------------------------------------------------- /apps/nsi_info/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from docutils.core import publish_parts 3 | 4 | 5 | class NSIInfo(models.Model): 6 | about = models.TextField(blank=False) 7 | updated_at = models.DateTimeField(auto_now=True) 8 | 9 | class Meta: 10 | verbose_name_plural = 'nsi_info' 11 | 12 | def about_as_html(self): 13 | return self._to_html(self.about) 14 | 15 | def _to_html(self, rst_source): 16 | parts = publish_parts(source=rst_source, writer_name="html4css1") 17 | return parts['fragment'] 18 | 19 | -------------------------------------------------------------------------------- /apps/nsi_info/templates/show_about.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block styles %} 3 | {{ block.super }} 4 | {% endblock styles %} 5 | {% block content %} 6 | 7 |
8 |

{{ nsi_info.about_as_html|safe }}

9 |
10 | 11 | {% endblock content %} 12 | -------------------------------------------------------------------------------- /apps/nsi_info/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from should_dsl import should 3 | from apps.nsi_info.models import NSIInfo 4 | 5 | 6 | class HistoryTest(TestCase): 7 | 8 | def test_convert_its_RST_text_to_HTML(self): 9 | h = NSIInfo(about="*NSI* site rulz!") 10 | h.about_as_html() |should| contain('NSI site rulz!') 11 | 12 | -------------------------------------------------------------------------------- /apps/nsi_info/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.nsi_info.models import NSIInfo 4 | 5 | 6 | def show_about(request): 7 | if len(NSIInfo.objects.all()): 8 | nsi_info = NSIInfo.objects.latest('updated_at') 9 | else: 10 | nsi_info = list() 11 | return render_to_response( 12 | 'show_about.html', 13 | {'nsi_info': nsi_info}, 14 | context_instance=RequestContext(request) 15 | ) 16 | -------------------------------------------------------------------------------- /apps/projects/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/projects/__init__.py -------------------------------------------------------------------------------- /apps/projects/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from apps.projects.models import Project, Document 3 | 4 | 5 | class DocumentInline(admin.StackedInline): 6 | model = Document 7 | extra = 1 8 | 9 | 10 | class ProjectAdmin(admin.ModelAdmin): 11 | inlines = [DocumentInline] 12 | 13 | 14 | admin.site.register(Project, ProjectAdmin) 15 | 16 | -------------------------------------------------------------------------------- /apps/projects/features/link_documents_to_project.feature: -------------------------------------------------------------------------------- 1 | Feature: Link documents to project 2 | As a NSI site administrator 3 | I want to link documents to projects 4 | In order to provide additional information on our projects 5 | 6 | Scenario: Show documents related to a project 7 | Given exist a project: 8 | | name | description | logo | sponsor | status | start_date | end_date | 9 | | NSI Site | The terrific site of NSI | test/images/projects/nsi.png | NSI | aberto | 2010-11-10 | 2011-02-01 | 10 | And "NSI Site" project has attached the following documents: 11 | | title | description | file | 12 | | UML model | UML detailed diagrams for project documentation | test/files/projects/nsi.png | 13 | When I go to "the projects page" 14 | And I click "NSI Site" 15 | Then I should see "UML model" 16 | And I should see "UML detailed diagrams for project documentation" 17 | And I should see a link to "nsi.png" with label "Download" 18 | 19 | -------------------------------------------------------------------------------- /apps/projects/features/manage_projects.feature: -------------------------------------------------------------------------------- 1 | Feature: Project maintenance 2 | As a NSI site administrator 3 | I want to handle project data 4 | In order to know what we are doing and what we did 5 | 6 | Scenario: Projects page 7 | Given exist a project: 8 | | name | description | github | logo | sponsor | status | start_date | end_date | 9 | | NSI Site | The terrific site of NSI | nsi-iff/nsi_site | test/images/projects/nsi.png | NSI | finalizado | 2010-11-10 | 2011-02-01 | 10 | 11 | When I go to "the projects page" 12 | Then I should see "1 projeto" 13 | And I should see "NSI Site" 14 | And I should see "The terrific site of NSI" 15 | And I should see an image called "nsi.png" 16 | 17 | When I go to the "NSI Site" project page 18 | 19 | Then I should see a label "nsi-iff/nsi_site" with the link to "http://github.com/nsi-iff/nsi_site" 20 | 21 | 22 | Scenario: Projects page for non-closed projects 23 | Given exist a project: 24 | | name | description | logo | sponsor | status | start_date | 25 | | NSI Site | The terrific site of NSI | test/images/projects/nsi.png | NSI | aberto | 2010-11-10 | 26 | When I go to "the projects page" 27 | Then I should see "1 projeto" 28 | And I should see "NSI Site" 29 | And I should see "The terrific site of NSI" 30 | And I should see an image called "nsi.png" 31 | 32 | 33 | Scenario: Showing a especific project 34 | Given exist a project: 35 | | name | description | logo | sponsor | status | start_date | end_date | 36 | | NSI Site | The terrific site of NSI | test/images/projects/nsi.png | NSI | finalizado | 2010-11-10 | 2011-02-01 | 37 | | ERP5 | ERP5, lek | test/images/projects/erp5.png | NSI | finalizado | 2010-11-10 | 2011-02-01 | 38 | 39 | And exist a member: 40 | | name | 41 | | Pluck | 42 | | Batata | 43 | | Pedro | 44 | 45 | And "Pluck" member started participation on "NSI Site" project 46 | And "Batata" member started participation on "NSI Site" project 47 | And "Pedro" member started participation on "ERP5" project 48 | 49 | When I go to the "NSI Site" project page 50 | And I should see "NSI Site" 51 | And I should see "The terrific site of NSI" 52 | And I should see "Patrocinador: NSI" 53 | And I should see "Status: finalizado" 54 | And I should see "Duração: 10/11/2010 a 01/02/2011" 55 | And I should see an image called "nsi.png" 56 | And I should see "Pluck" 57 | And I should see "Batata" 58 | 59 | -------------------------------------------------------------------------------- /apps/projects/features/resources/erp5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/projects/features/resources/erp5.png -------------------------------------------------------------------------------- /apps/projects/features/resources/nsi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/projects/features/resources/nsi.png -------------------------------------------------------------------------------- /apps/projects/features/steps.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from django.conf import settings 4 | from lettuce import step, world 5 | from lettuce.django import django_url 6 | from should_dsl import should 7 | from model_mommy import mommy 8 | from apps.members.models import Member 9 | from apps.members.models import Participation 10 | from apps.projects.models import Project, Document 11 | 12 | @step(u'exist a project:') 13 | def exist_a_project(step): 14 | for project in step.hashes: 15 | Project(**project).save() 16 | file_name = project['logo'].split('/')[-1] 17 | shutil.copy2(os.path.join(settings.PROJECT_ROOT_PATH, 'apps', 'projects', 18 | 'features', 'resources', file_name), 19 | os.path.join(settings.MEDIA_ROOT, 'test', 'images', 'projects')) 20 | 21 | @step(u'exist a member:') 22 | def exist_a_member(step): 23 | for member in step.hashes: 24 | mommy.make_one(Member, name=member.get('name'), site=None, lattes=None, photo=None) 25 | 26 | @step(r'"(.*)" member started participation on "(.*)" project') 27 | def member_started_participation_on_project(step, member_name, project_name): 28 | member_obj = Member.objects.get(name=member_name) 29 | project_obj = Project.objects.get(name=project_name) 30 | mommy.make_one(Participation, member=member_obj, project=project_obj) 31 | 32 | @step(r'I go to the "(.+)" project page') 33 | def i_go_to_project_page(step, project_name): 34 | project_obj = Project.objects.get(name=project_name) 35 | world.browser.visit(django_url('/projeto/%s' % project_obj.slug)) 36 | 37 | @step(u'"(.*)" project has attached the following documents:') 38 | def project_has_attached_the_following_documents(step, project_name): 39 | project = Project.objects.get(name=project_name) 40 | document = Document(**step.hashes[0]) 41 | document.project = project 42 | document.save() 43 | 44 | @step(u'I should see a label "(.*)" with the link to "(.*)"') 45 | def i_should_see_a_label_with_link(step, link_text, link_href): 46 | links = world.browser.find_link_by_href(link_href) 47 | links |should| have_at_least(1).item 48 | link_value = links[0].value 49 | link_value |should| equal_to(link_text) 50 | -------------------------------------------------------------------------------- /apps/projects/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Project' 12 | db.create_table('projects_project', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('name', self.gf('django.db.models.fields.CharField')(max_length=100)), 15 | ('description', self.gf('django.db.models.fields.TextField')()), 16 | ('logo', self.gf('django.db.models.fields.files.ImageField')(max_length=100)), 17 | ('sponsor', self.gf('django.db.models.fields.CharField')(max_length=100)), 18 | ('status', self.gf('django.db.models.fields.CharField')(max_length=100)), 19 | ('start_date', self.gf('django.db.models.fields.DateField')()), 20 | ('end_date', self.gf('django.db.models.fields.DateField')()), 21 | )) 22 | db.send_create_signal('projects', ['Project']) 23 | 24 | 25 | def backwards(self, orm): 26 | 27 | # Deleting model 'Project' 28 | db.delete_table('projects_project') 29 | 30 | 31 | models = { 32 | 'projects.project': { 33 | 'Meta': {'object_name': 'Project'}, 34 | 'description': ('django.db.models.fields.TextField', [], {}), 35 | 'end_date': ('django.db.models.fields.DateField', [], {}), 36 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 37 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 38 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 39 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 40 | 'start_date': ('django.db.models.fields.DateField', [], {}), 41 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 42 | } 43 | } 44 | 45 | complete_apps = ['projects'] 46 | -------------------------------------------------------------------------------- /apps/projects/migrations/0002_auto__chg_field_project_end_date.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Changing field 'Project.end_date' 12 | db.alter_column('projects_project', 'end_date', self.gf('django.db.models.fields.DateField')(null=True)) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Changing field 'Project.end_date' 18 | db.alter_column('projects_project', 'end_date', self.gf('django.db.models.fields.DateField')(default=datetime.date(2011, 2, 1))) 19 | 20 | 21 | models = { 22 | 'projects.project': { 23 | 'Meta': {'object_name': 'Project'}, 24 | 'description': ('django.db.models.fields.TextField', [], {}), 25 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 28 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 29 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 30 | 'start_date': ('django.db.models.fields.DateField', [], {}), 31 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 32 | } 33 | } 34 | 35 | complete_apps = ['projects'] 36 | -------------------------------------------------------------------------------- /apps/projects/migrations/0003_auto__add_document.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Document' 12 | db.create_table('projects_document', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('title', self.gf('django.db.models.fields.CharField')(max_length=100)), 15 | ('description', self.gf('django.db.models.fields.TextField')()), 16 | ('file', self.gf('django.db.models.fields.files.FileField')(max_length=100)), 17 | ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['projects.Project'])), 18 | ('uploaded_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), 19 | )) 20 | db.send_create_signal('projects', ['Document']) 21 | 22 | 23 | def backwards(self, orm): 24 | 25 | # Deleting model 'Document' 26 | db.delete_table('projects_document') 27 | 28 | 29 | models = { 30 | 'projects.document': { 31 | 'Meta': {'object_name': 'Document'}, 32 | 'description': ('django.db.models.fields.TextField', [], {}), 33 | 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 34 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 35 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 36 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 37 | 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) 38 | }, 39 | 'projects.project': { 40 | 'Meta': {'object_name': 'Project'}, 41 | 'description': ('django.db.models.fields.TextField', [], {}), 42 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True'}), 43 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 44 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100'}), 45 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 46 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 47 | 'start_date': ('django.db.models.fields.DateField', [], {}), 48 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 49 | } 50 | } 51 | 52 | complete_apps = ['projects'] 53 | -------------------------------------------------------------------------------- /apps/projects/migrations/0004_add_slug.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | from django.template.defaultfilters import slugify 7 | 8 | class Migration(SchemaMigration): 9 | 10 | def forwards(self, orm): 11 | 12 | # Adding field 'Project.slug' 13 | db.add_column('projects_project', 'slug', self.gf('django.db.models.fields.SlugField')(db_index=True, default='', max_length=100, blank=True), keep_default=False) 14 | 15 | # Changing field 'Project.logo' 16 | db.alter_column('projects_project', 'logo', self.gf('thumbs.ImageWithThumbsField')(name='logo', sizes=((200, 200), (90, 90)), max_length=100, null=True)) 17 | 18 | for project in orm.Project.objects.all(): 19 | project.slug = slugify(project.name) 20 | project.save() 21 | 22 | def backwards(self, orm): 23 | 24 | # Deleting field 'Project.slug' 25 | db.delete_column('projects_project', 'slug') 26 | 27 | # User chose to not deal with backwards NULL issues for 'Project.logo' 28 | raise RuntimeError("Cannot reverse this migration. 'Project.logo' and its values cannot be restored.") 29 | 30 | 31 | models = { 32 | 'projects.document': { 33 | 'Meta': {'object_name': 'Document'}, 34 | 'description': ('django.db.models.fields.TextField', [], {}), 35 | 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 36 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 37 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 38 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 39 | 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) 40 | }, 41 | 'projects.project': { 42 | 'Meta': {'object_name': 'Project'}, 43 | 'description': ('django.db.models.fields.TextField', [], {}), 44 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 45 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 46 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 47 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 48 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 49 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 50 | 'start_date': ('django.db.models.fields.DateField', [], {}), 51 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 52 | } 53 | } 54 | 55 | complete_apps = ['projects'] 56 | -------------------------------------------------------------------------------- /apps/projects/migrations/0005_auto__add_field_project_github.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Project.github' 12 | db.add_column('projects_project', 'github', self.gf('django.db.models.fields.CharField')(max_length=80, null=True, blank=True), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Project.github' 18 | db.delete_column('projects_project', 'github') 19 | 20 | 21 | models = { 22 | 'projects.document': { 23 | 'Meta': {'object_name': 'Document'}, 24 | 'description': ('django.db.models.fields.TextField', [], {}), 25 | 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['projects.Project']"}), 28 | 'title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 29 | 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}) 30 | }, 31 | 'projects.project': { 32 | 'Meta': {'object_name': 'Project'}, 33 | 'description': ('django.db.models.fields.TextField', [], {}), 34 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 35 | 'github': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}), 36 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 37 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 38 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 39 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 40 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 41 | 'start_date': ('django.db.models.fields.DateField', [], {}), 42 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 43 | } 44 | } 45 | 46 | complete_apps = ['projects'] 47 | -------------------------------------------------------------------------------- /apps/projects/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/projects/migrations/__init__.py -------------------------------------------------------------------------------- /apps/projects/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.template.defaultfilters import slugify 3 | from thumbs import ImageWithThumbsField 4 | 5 | 6 | PROJECT_STATES = ( 7 | ('0', 'aberto'), 8 | ('1', 'finalizado'), 9 | ('2', 'paralisado'), 10 | ('3', 'cancelado')) 11 | 12 | 13 | class Project(models.Model): 14 | name = models.CharField(max_length=100) 15 | description = models.TextField() 16 | logo = ImageWithThumbsField(upload_to='images/projects', null=True, blank=True, sizes=((200, 200), (90, 90), )) 17 | sponsor = models.CharField(max_length=100) 18 | github = models.CharField(max_length=80, null=True, blank=True) 19 | status = models.CharField(max_length=100, choices=PROJECT_STATES) 20 | start_date = models.DateField() 21 | end_date = models.DateField(null=True, blank=True) 22 | slug = models.SlugField(max_length=100, blank=True) 23 | 24 | def github_link(self): 25 | return "http://github.com/" + self.github 26 | 27 | def github_feed(self): 28 | return self.github_link() + "/commits/master.atom" 29 | 30 | 31 | def finished(self): 32 | return self.end_date is not None 33 | 34 | def __unicode__(self): 35 | return self.name 36 | 37 | def save(self, *args, **kwargs): 38 | self.slug = slugify(self.name) 39 | if self.finished(): 40 | self.status = 'finalizado' 41 | super(Project, self).save(*args, **kwargs) 42 | else: 43 | super(Project, self).save(*args, **kwargs) 44 | 45 | 46 | class Document(models.Model): 47 | title = models.CharField(max_length=100) 48 | description = models.TextField() 49 | file = models.FileField(upload_to='files/projects') 50 | project = models.ForeignKey(Project) 51 | uploaded_at = models.DateTimeField(auto_now_add=True) 52 | 53 | def __unicode__(self): 54 | return self.title + ' - ' + self.description 55 | -------------------------------------------------------------------------------- /apps/projects/templates/show_all_projects.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load pagination_tags %} 4 | 5 | {% block scripts %} 6 | {{ block.super }} 7 | 8 | {% endblock scripts %} 9 | 10 | {% block content %} 11 | 12 |

{{ project_count }} projeto{{ project_count|pluralize }}

13 | 14 |
15 | {% autopaginate projects 5 %} 16 | {% for project in projects %} 17 |
18 | {% if project.logo %} 19 | {{ project.name }} 20 | {% endif %} 21 |

{{ project.name }}

22 |

{{ project.description|slice:"250"}} ...

23 | Saiba mais + 24 |
25 | {% endfor %} 26 |
27 | {% paginate %} 28 | {% endblock content %} 29 | -------------------------------------------------------------------------------- /apps/projects/templates/show_project.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block scripts %} 4 | {{ block.super }} 5 | 6 | 7 | 8 | {% endblock scripts %} 9 | 10 | {% block content %} 11 |
12 | {% if project.logo %} 13 | 16 | {% endif %} 17 |
18 |

{{ project.name }}

19 | 20 |

{{ project.description }}

21 | 22 |

Patrocinador: {{ project.sponsor }}

23 | 24 | {% if project.github %} 25 | Github: 26 | 27 | {{ project.github }} 28 | 29 | {% endif %} 30 | 31 |

Status: {{ project.get_status_display }}

32 | {% if project.finished %} 33 |

Duração: {{ project.start_date|date:"d/m/Y" }} a {{ project.end_date|date:"d/m/Y" }}

34 | {% else %} 35 |

Início: {{ project.start_date|date:"d/m/Y" }}

36 | {% endif %} 37 | 38 | {% if project.document_set.all %} 39 |

Documentos relacionados:

40 | 41 | 42 | 43 | 44 | 45 | {% for document in project.document_set.all %} 46 | 47 | 48 | 49 | 50 | 51 | 52 | {% endfor %} 53 | 54 |
NomeDescriçãoEnviado
{{ document.title }}{{ document.description }}{{ document.uploaded_at|date:"d/m/Y à\s H:i" }}Download
55 | {% endif %} 56 | 57 | {% if participations %} 58 |

Membros:

59 |
    60 | {% for participation in participations %} 61 | {% if participation.project.name == project.name %} 62 |
  • {{ participation.member.name }}
  • 63 | {% endif %} 64 | {% endfor %} 65 |
66 | {% endif %} 67 | 68 | {% if project.github %} 69 |
70 | 71 | 72 |

73 |
74 |
    75 |
76 |
77 | {% endif %} 78 | 79 |
80 |
81 | {% endblock content %} 82 | -------------------------------------------------------------------------------- /apps/projects/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from should_dsl import should, should_not 3 | from apps.projects.models import Project 4 | 5 | 6 | class ProjectTest(TestCase): 7 | 8 | def test_finishing(self): 9 | project = Project(start_date='2011-01-01', end_date=None) 10 | project |should_not| be_finished 11 | project.end_date = '2011-01-31' 12 | project |should| be_finished 13 | 14 | def test_change_status_to_finished(self): 15 | project = Project(start_date='2011-01-01', end_date=None) 16 | project |should_not| be_finished 17 | project.end_date = '2011-01-31' 18 | project.save() 19 | project.status |should| equal_to('finalizado') 20 | -------------------------------------------------------------------------------- /apps/projects/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.views.generic.simple import direct_to_template 3 | from django.conf import settings 4 | 5 | from django.contrib import admin 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | 10 | (r'^projetos/$', 'apps.projects.views.show_all'), 11 | (r'^projeto/(?P[\w_-]+)/$', 'apps.projects.views.show_project'), 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /apps/projects/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.projects.models import Project 4 | from apps.members.models import Participation 5 | 6 | 7 | def show_all(request): 8 | projects = Project.objects.all().order_by('status', 'start_date') 9 | return render_to_response( 10 | 'show_all_projects.html', 11 | {'projects': projects, 'project_count': len(projects)}, 12 | context_instance=RequestContext(request) 13 | ) 14 | 15 | def show_project(request, project_slug): 16 | project = Project.objects.get(slug=project_slug) 17 | participations = Participation.objects.all() 18 | return render_to_response( 19 | 'show_project.html', 20 | {'project': project, 'participations': participations}, 21 | context_instance=RequestContext(request) 22 | ) 23 | 24 | 25 | -------------------------------------------------------------------------------- /apps/tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/tools/__init__.py -------------------------------------------------------------------------------- /apps/tools/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from apps.tools.models import Tool 3 | 4 | admin.site.register(Tool) 5 | -------------------------------------------------------------------------------- /apps/tools/features/manage_tools.feature: -------------------------------------------------------------------------------- 1 | Feature: Tool maintenance 2 | As a NSI site administrator 3 | I want to handle tools data 4 | In order to keep tools information up to date 5 | 6 | Scenario: showing a tool 7 | Given exist a tool: 8 | | name | description | repository | site | logo | status | highlight | 9 | | Should DSL| A tool to write should expectations | http://github.com/hugobr/should-dsl | http://www.should-dsl.info | test/images/tools/should-dsl.png | ativo | True | 10 | 11 | And given there exist a project: 12 | | name | 13 | | NSI Site | 14 | 15 | And "Should DSL" has related projects: 16 | | name | 17 | | NSI Site | 18 | 19 | When I go to the "Should DSL" tool page 20 | Then I should see an image called "should-dsl.png" 21 | And I should see "Should DSL" 22 | And I should see "A tool to write should expectations" 23 | And I should see "http://github.com/hugobr/should-dsl" 24 | And I should see "http://www.should-dsl.info" 25 | And I should see "Status: ativo" 26 | And I should see "Projetos relacionados:" 27 | And I should see "NSI Site" 28 | 29 | Scenario: showing all tools 30 | Given exist a tool: 31 | | name | short_description | logo | status | 32 | | Should DSL | A tool to write should expectations | test/images/tools/should-dsl.png | ativo | 33 | | Ludibrio | A tool for mock | test/images/tools/ludibrio.png | descontinuado | 34 | | Ricks | A tool for sunshine | test/images/tools/ricks.png | ativo | 35 | 36 | When I go to "the tools page" 37 | Then I should see an image called "should-dsl.png" 38 | And I should see "Should DSL" 39 | And I should see "A tool to write should expectations" 40 | And I should see "Status: ativo" 41 | And I should see an image called "ludibrio.png" 42 | And I should see "Ludibrio" 43 | And I should see "A tool for mock" 44 | And I should see "Status: descontinuado" 45 | And I should see an image called "ricks.png" 46 | And I should see "Ricks" 47 | And I should see "A tool for sunshine" 48 | And I should see "Status: ativo" 49 | -------------------------------------------------------------------------------- /apps/tools/features/resources/ludibrio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/tools/features/resources/ludibrio.png -------------------------------------------------------------------------------- /apps/tools/features/resources/ricks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/tools/features/resources/ricks.png -------------------------------------------------------------------------------- /apps/tools/features/resources/should-dsl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/tools/features/resources/should-dsl.png -------------------------------------------------------------------------------- /apps/tools/features/steps.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | from lettuce import step 4 | from model_mommy import mommy 5 | from apps.projects.models import Project 6 | from apps.tools.models import Tool 7 | 8 | @step(u'exist a tool:') 9 | def there_exist_a_tool(step): 10 | for tool_hashes in step.hashes: 11 | Tool.objects.create(**tool_hashes) 12 | if tool_hashes.get('logo'): 13 | file_name = tool_hashes['logo'].split('/')[-1] 14 | shutil.copy2(os.path.join(settings.PROJECT_ROOT_PATH, 'apps', 'tools', 15 | 'features', 'resources', file_name), 16 | os.path.join(settings.MEDIA_ROOT, 'test', 'images', 'tools')) 17 | 18 | @step(u'exist a project:') 19 | def exist_a_project(step): 20 | for project_hashes in step.hashes: 21 | project = mommy.make_one(Project, name=project_hashes.get('name')) 22 | 23 | 24 | @step(u'And "(.*)" has related projects:') 25 | def and_tool_has_related_projects(step, tool_name): 26 | tool = Tool.objects.get(name=tool_name) 27 | for project_hashes in step.hashes: 28 | project = Project.objects.get(name=project_hashes.get('name')) 29 | tool.relateds_projects.add(project) 30 | tool.save() 31 | 32 | 33 | @step(r'I go to the "(.+)" tool page') 34 | def i_go_to_tool_page(step, tool_name): 35 | tool_obj = Tool.objects.get(name=tool_name) 36 | world.browser.visit(django_url('/ferramenta/%s' % tool_obj.slug)) 37 | -------------------------------------------------------------------------------- /apps/tools/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding model 'Tool' 12 | db.create_table('tools_tool', ( 13 | ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), 14 | ('name', self.gf('django.db.models.fields.CharField')(max_length=100)), 15 | ('description', self.gf('django.db.models.fields.TextField')()), 16 | ('repository', self.gf('django.db.models.fields.CharField')(max_length=100)), 17 | ('site', self.gf('django.db.models.fields.CharField')(max_length=100)), 18 | ('highlight', self.gf('django.db.models.fields.BooleanField')(default=False)), 19 | )) 20 | db.send_create_signal('tools', ['Tool']) 21 | 22 | # Adding M2M table for field relateds_projects on 'Tool' 23 | db.create_table('tools_tool_relateds_projects', ( 24 | ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), 25 | ('tool', models.ForeignKey(orm['tools.tool'], null=False)), 26 | ('project', models.ForeignKey(orm['projects.project'], null=False)) 27 | )) 28 | db.create_unique('tools_tool_relateds_projects', ['tool_id', 'project_id']) 29 | 30 | 31 | def backwards(self, orm): 32 | 33 | # Deleting model 'Tool' 34 | db.delete_table('tools_tool') 35 | 36 | # Removing M2M table for field relateds_projects on 'Tool' 37 | db.delete_table('tools_tool_relateds_projects') 38 | 39 | 40 | models = { 41 | 'projects.project': { 42 | 'Meta': {'object_name': 'Project'}, 43 | 'description': ('django.db.models.fields.TextField', [], {}), 44 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 45 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 46 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 47 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 48 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 49 | 'start_date': ('django.db.models.fields.DateField', [], {}), 50 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 51 | }, 52 | 'tools.tool': { 53 | 'Meta': {'object_name': 'Tool'}, 54 | 'description': ('django.db.models.fields.TextField', [], {}), 55 | 'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 56 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 57 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 58 | 'relateds_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 59 | 'repository': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 60 | 'site': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 61 | } 62 | } 63 | 64 | complete_apps = ['tools'] 65 | -------------------------------------------------------------------------------- /apps/tools/migrations/0002_auto__add_field_tool_logo.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Tool.logo' 12 | db.add_column('tools_tool', 'logo', self.gf('django.db.models.fields.files.ImageField')(max_length=100, null=True, blank=True), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Tool.logo' 18 | db.delete_column('tools_tool', 'logo') 19 | 20 | 21 | models = { 22 | 'projects.project': { 23 | 'Meta': {'object_name': 'Project'}, 24 | 'description': ('django.db.models.fields.TextField', [], {}), 25 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 28 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 29 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 30 | 'start_date': ('django.db.models.fields.DateField', [], {}), 31 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 32 | }, 33 | 'tools.tool': { 34 | 'Meta': {'object_name': 'Tool'}, 35 | 'description': ('django.db.models.fields.TextField', [], {}), 36 | 'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 37 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 38 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 39 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 40 | 'relateds_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 41 | 'repository': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 42 | 'site': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 43 | } 44 | } 45 | 46 | complete_apps = ['tools'] 47 | -------------------------------------------------------------------------------- /apps/tools/migrations/0003_auto__add_field_tool_status.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Tool.status' 12 | db.add_column('tools_tool', 'status', self.gf('django.db.models.fields.CharField')(default='ativo', max_length=100), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Tool.status' 18 | db.delete_column('tools_tool', 'status') 19 | 20 | 21 | models = { 22 | 'projects.project': { 23 | 'Meta': {'object_name': 'Project'}, 24 | 'description': ('django.db.models.fields.TextField', [], {}), 25 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 28 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 29 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 30 | 'start_date': ('django.db.models.fields.DateField', [], {}), 31 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 32 | }, 33 | 'tools.tool': { 34 | 'Meta': {'object_name': 'Tool'}, 35 | 'description': ('django.db.models.fields.TextField', [], {}), 36 | 'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 37 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 38 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 39 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 40 | 'relateds_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 41 | 'repository': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 42 | 'site': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 43 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 44 | } 45 | } 46 | 47 | complete_apps = ['tools'] 48 | -------------------------------------------------------------------------------- /apps/tools/migrations/0004_auto__add_field_tool_short_description.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Tool.short_description' 12 | db.add_column('tools_tool', 'short_description', self.gf('django.db.models.fields.TextField')(default='N\xc3\xa3o Informado', max_length=200), keep_default=False) 13 | 14 | 15 | def backwards(self, orm): 16 | 17 | # Deleting field 'Tool.short_description' 18 | db.delete_column('tools_tool', 'short_description') 19 | 20 | 21 | models = { 22 | 'projects.project': { 23 | 'Meta': {'object_name': 'Project'}, 24 | 'description': ('django.db.models.fields.TextField', [], {}), 25 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 26 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 27 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 28 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 29 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 30 | 'start_date': ('django.db.models.fields.DateField', [], {}), 31 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 32 | }, 33 | 'tools.tool': { 34 | 'Meta': {'object_name': 'Tool'}, 35 | 'description': ('django.db.models.fields.TextField', [], {}), 36 | 'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 37 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 38 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 39 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 40 | 'relateds_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 41 | 'repository': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 42 | 'short_description': ('django.db.models.fields.TextField', [], {'max_length': '200'}), 43 | 'site': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 44 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 45 | } 46 | } 47 | 48 | complete_apps = ['tools'] 49 | -------------------------------------------------------------------------------- /apps/tools/migrations/0005_add_slug.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import datetime 3 | from south.db import db 4 | from south.v2 import SchemaMigration 5 | from django.db import models 6 | 7 | class Migration(SchemaMigration): 8 | 9 | def forwards(self, orm): 10 | 11 | # Adding field 'Tool.slug' 12 | db.add_column('tools_tool', 'slug', self.gf('django.db.models.fields.SlugField')(db_index=True, default='', max_length=100, blank=True), keep_default=False) 13 | 14 | for tool in orm.Tool.objects.all(): 15 | tool.slug = slugify(tool.name) 16 | tool.save() 17 | 18 | def backwards(self, orm): 19 | 20 | # Deleting field 'Tool.slug' 21 | db.delete_column('tools_tool', 'slug') 22 | 23 | 24 | models = { 25 | 'projects.project': { 26 | 'Meta': {'object_name': 'Project'}, 27 | 'description': ('django.db.models.fields.TextField', [], {}), 28 | 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}), 29 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 30 | 'logo': ('thumbs.ImageWithThumbsField', [], {'name': "'logo'", 'sizes': '((200, 200), (90, 90))', 'max_length': '100', 'blank': 'True', 'null': 'True'}), 31 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 32 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 33 | 'sponsor': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 34 | 'start_date': ('django.db.models.fields.DateField', [], {}), 35 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 36 | }, 37 | 'tools.tool': { 38 | 'Meta': {'object_name': 'Tool'}, 39 | 'description': ('django.db.models.fields.TextField', [], {}), 40 | 'highlight': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 41 | 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 42 | 'logo': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), 43 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 44 | 'relateds_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'blank': 'True'}), 45 | 'repository': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 46 | 'short_description': ('django.db.models.fields.TextField', [], {'max_length': '200'}), 47 | 'site': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 48 | 'slug': ('django.db.models.fields.SlugField', [], {'db_index': 'True', 'max_length': '100', 'blank': 'True'}), 49 | 'status': ('django.db.models.fields.CharField', [], {'max_length': '100'}) 50 | } 51 | } 52 | 53 | complete_apps = ['tools'] 54 | -------------------------------------------------------------------------------- /apps/tools/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/tools/migrations/__init__.py -------------------------------------------------------------------------------- /apps/tools/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.template.defaultfilters import slugify 3 | from apps.projects.models import Project 4 | 5 | 6 | TOOLS_STATES = ( 7 | ('ativo', 'ativo'), 8 | ('descontinuado', 'descontinuado')) 9 | 10 | class Tool(models.Model): 11 | name = models.CharField(max_length=100) 12 | short_description = models.TextField(max_length=200) 13 | description = models.TextField() 14 | repository = models.CharField(max_length=100) 15 | site = models.CharField(max_length=100) 16 | logo = models.ImageField(upload_to='images/tools', null=True, blank=True) 17 | status = models.CharField(max_length=100, choices=TOOLS_STATES) 18 | highlight = models.BooleanField() 19 | relateds_projects = models.ManyToManyField(Project, null=True, blank=True) 20 | slug = models.SlugField(max_length=100, blank=True) 21 | 22 | def __unicode__(self): 23 | return self.name 24 | 25 | def save(self, *args, **kwargs): 26 | self.slug = slugify(self.name) 27 | super(Tool, self).save(*args, **kwargs) 28 | 29 | -------------------------------------------------------------------------------- /apps/tools/templates/show_all.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load pagination_tags %} 4 | 5 | {% block styles %} 6 | {{ block.super }} 7 | 8 | {% endblock styles %} 9 | 10 | {% block content %} 11 | {% autopaginate tools 5 %} 12 | {% for tool in tools %} 13 |
14 |
15 | {% if tool.logo %} 16 | 17 | {{ tool.name }} 18 | 19 | {% endif %} 20 |
21 |

{{ tool.name }}

22 |

{{ tool.short_description }}

23 |

Status: 24 | {{ tool.status }} 25 |

26 |

Leia mais +

27 |
28 |
29 |
30 | {% endfor %} 31 | {% paginate %} 32 | {% endblock content %} 33 | 34 | -------------------------------------------------------------------------------- /apps/tools/templates/show_tool.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block scripts %} 4 | {{ block.super }} 5 | 6 | {% endblock scripts %} 7 | 8 | {% block content %} 9 |
10 | {% if tool.logo %} 11 | {{ tool.name }} 12 | {% endif %} 13 |
14 |

{{ tool.name }}

15 | 16 |

{{ tool.description }}

17 | 18 |

Repositório: 19 | {{ tool.repository }} 20 |

21 |

Site: 22 | {{ tool.site }} 23 |

24 |

Status: 25 | {{ tool.status }} 26 |

27 | {% if tool.relateds_projects.all %} 28 |

Projetos relacionados:

29 |
    30 | {% for project in tool.relateds_projects.all %} 31 |
  • {{ project.name }}
  • 32 | {% endfor %} 33 |
34 | {% endif %} 35 |
36 |
37 | {% endblock content %} 38 | -------------------------------------------------------------------------------- /apps/tools/tests.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | 3 | from django.test import TestCase 4 | 5 | 6 | class ToolsTest(TestCase): 7 | pass 8 | 9 | -------------------------------------------------------------------------------- /apps/tools/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.views.generic.simple import direct_to_template 3 | from django.conf import settings 4 | 5 | from django.contrib import admin 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | 10 | (r'^ferramentas/$', 'apps.tools.views.show_all'), 11 | (r'^ferramenta/(?P[\w_-]+)$', 'apps.tools.views.show_tool'), 12 | 13 | ) 14 | -------------------------------------------------------------------------------- /apps/tools/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render_to_response 2 | from django.template import RequestContext 3 | from apps.tools.models import Tool 4 | 5 | 6 | def show_tool(request, tool_slug): 7 | tool = Tool.objects.get(slug=tool_slug) 8 | return render_to_response( 9 | 'show_tool.html', 10 | {'tool': tool}, 11 | context_instance=RequestContext(request) 12 | ) 13 | 14 | def show_all(request): 15 | tools = Tool.objects.all().order_by('status') 16 | return render_to_response( 17 | 'show_all.html', 18 | {'tools': tools}, 19 | context_instance=RequestContext(request) 20 | ) 21 | -------------------------------------------------------------------------------- /apps/wiki/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/apps/wiki/__init__.py -------------------------------------------------------------------------------- /apps/wiki/features/manage_wiki.feature: -------------------------------------------------------------------------------- 1 | Feature: Wiki maintenance 2 | As a visitor NSI Site 3 | I want see home wiki data 4 | In order to learn more about Plone 5 | 6 | 7 | Scenario: listing all wiki items without be logged in 8 | 9 | Given exist a wiki item: 10 | | id | title | content | 11 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 12 | | 2 | Installing Plone 4 | Run "install.sh" | 13 | 14 | When I go to "the NSI home page" 15 | And I click "Wiki" 16 | 17 | Then I should see a link with text "Adding a Plone Site" 18 | And I should see a link with text "Installing Plone 4" 19 | 20 | 21 | Scenario: listing all wiki items logged in 22 | 23 | Given exist a wiki item: 24 | | id | title | content | 25 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 26 | | 2 | Installing Plone 4 | Run "install.sh" | 27 | And that i'm logged in 28 | 29 | When I go to "the NSI home page" 30 | And I click "Wiki" 31 | 32 | Then I should see a link with text "Adding a Plone Site" 33 | And I should have a link that ends in "adding-a-plone-site/editar/" 34 | And I should have a link that ends in "adding-a-plone-site/excluir/" 35 | And I should see a link with text "Installing Plone 4" 36 | And I should have a link that ends in "installing-plone-4/editar/" 37 | And I should have a link that ends in "installing-plone-4/excluir/" 38 | 39 | 40 | Scenario: adding some item to the wiki 41 | 42 | Given that i'm logged in 43 | 44 | When I go to "the NSI home page" 45 | And I click "Wiki" 46 | And I click "Adicionar um item" 47 | And I fill in "title" with "Teste" 48 | And I fill in "nicEdit-main" with "Conteúdo do teste" 49 | And I press "send" 50 | Then I should see "Item salvo com sucesso!" 51 | And I should see a link with text "Voltar para a wiki" 52 | 53 | 54 | Scenario: viewing a wiki item 55 | 56 | Given exist a wiki item: 57 | | id | title | content | 58 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 59 | 60 | When I go to "the NSI home page" 61 | And I click "Wiki" 62 | And I should have a link that ends in "adding-a-plone-site/" 63 | And I click "Adding a Plone Site" 64 | 65 | Then I should see "Adding a Plone Site" 66 | And I should see "Just click in 'Add Plone Site'" 67 | 68 | 69 | Scenario: editing some wiki item 70 | 71 | Given exist a wiki item: 72 | | id | title | content | 73 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 74 | And that i'm logged in 75 | 76 | When I go to "the NSI home page" 77 | And I click "Wiki" 78 | And I click on link that ends in "adding-a-plone-site/editar/" 79 | And I fill in "title" with "How to install django" 80 | And I fill in "nicEdit-main" with "Run: pip install django" 81 | And I press "send" 82 | 83 | Then I should see "Item editado com sucesso!" 84 | And I should see a link with text "Voltar para a wiki" 85 | 86 | 87 | Scenario: deleting some wiki item 88 | 89 | Given exist a wiki item: 90 | | id | title | content | 91 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 92 | And that i'm logged in 93 | 94 | When I go to "the NSI home page" 95 | And I click "Wiki" 96 | And I click on link that ends in "adding-a-plone-site/excluir/" 97 | And I should see "Deseja excluir o item 'Adding a Plone Site'?" 98 | And I press "yes" 99 | 100 | Then I should see "Item excluído com sucesso!" 101 | And I should see a link with text "Voltar para a wiki" 102 | 103 | 104 | Scenario: giving up of deleting some wiki item 105 | 106 | Given exist a wiki item: 107 | | id | title | content | 108 | | 1 | Adding a Plone Site | Just click in 'Add Plone Site' | 109 | And that i'm logged in 110 | 111 | When I go to "the NSI home page" 112 | And I click "Wiki" 113 | And I click on link that ends in "adding-a-plone-site/excluir/" 114 | And I should see "Deseja excluir o item 'Adding a Plone Site'?" 115 | And I press "no" 116 | 117 | Then I should see a link with text "Adding a Plone Site" 118 | And I should have a link that ends in "adding-a-plone-site/editar/" 119 | And I should have a link that ends in "adding-a-plone-site/excluir/" 120 | -------------------------------------------------------------------------------- /apps/wiki/features/steps.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django.contrib.auth.models import User 4 | 5 | from lettuce import step, world 6 | from lettuce.django import django_url 7 | from should_dsl import should 8 | 9 | from apps.wiki.models import WikiItem 10 | 11 | 12 | @step(u'exist a wiki item:') 13 | def exist_a_wiki_item(step): 14 | for wiki_item in step.hashes: 15 | WikiItem(id=wiki_item['id'], title=wiki_item['title'], content=wiki_item['content']).save() 16 | 17 | @step(u'I should have a link that ends in "(.*)"') 18 | def i_should_have_a_link_with_ends_in(step, url): 19 | links = world.browser.find_by_tag('a') 20 | end_links = [end_link for end_link in links if end_link['href'].endswith(url)] 21 | end_links |should| have_at_least(1).end_link 22 | 23 | @step(u'I click on link that ends in "(.*)"') 24 | def i_click_on_link_that_ends_in(step, url): 25 | links = world.browser.find_by_tag('a') 26 | end_link = [end_link for end_link in links if end_link['href'].endswith(url)] 27 | end_link |should| have(1).end_link 28 | end_link[0].click() 29 | 30 | @step(u"that i'm logged in") 31 | def that_i_m_logged_in(step): 32 | user = User.objects.create_user('test', 'test@test.com', 'test') 33 | user.is_staff = True 34 | user.save() 35 | world.browser.visit(django_url('/admin')) 36 | world.browser.fill('username', 'test') 37 | world.browser.fill('password', 'test') 38 | world.browser.find_by_value('Acessar').first.click() 39 | -------------------------------------------------------------------------------- /apps/wiki/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms import ModelForm 2 | 3 | from models import WikiItem 4 | 5 | 6 | class WikiItemForm(ModelForm): 7 | 8 | class Meta: 9 | model = WikiItem 10 | exclude = ('slug', ) 11 | -------------------------------------------------------------------------------- /apps/wiki/models.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | from django.db import models 4 | from django.db.models import signals 5 | from django.template.defaultfilters import slugify 6 | 7 | 8 | class WikiItem(models.Model): 9 | title = models.CharField(verbose_name='Título',max_length=100) 10 | content = models.TextField(verbose_name='Conteúdo') 11 | slug = models.SlugField(max_length=100, blank=True, unique=True) 12 | 13 | 14 | def wiki_item_pre_save(signal, instance, sender, **kwargs): 15 | slug = slugify(instance.title) 16 | new_slug = slug 17 | counter = 0 18 | 19 | while WikiItem.objects.filter(slug=new_slug).exclude(id=instance.id).count() > 0: 20 | counter += 1 21 | new_slug = '%s-%d' % (slug, counter) 22 | 23 | instance.slug = new_slug 24 | 25 | 26 | signals.pre_save.connect(wiki_item_pre_save, sender=WikiItem) 27 | -------------------------------------------------------------------------------- /apps/wiki/templates/add_wiki_item.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block scripts %} 9 | {{ block.super }} 10 | 11 | 17 | {% endblock scripts %} 18 | 19 | {% block content %} 20 | 21 |
22 | {{ wiki_item_form.as_p }} 23 | 24 |
25 | 26 | {% endblock content %} 27 | 28 | -------------------------------------------------------------------------------- /apps/wiki/templates/delete_wiki_item.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 | 10 |

Deseja excluir o item '{{ object.title }}'?

11 |
12 | 13 | 14 |
15 | 16 | {% endblock content %} 17 | -------------------------------------------------------------------------------- /apps/wiki/templates/edit_wiki_item.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block scripts %} 9 | {{ block.super }} 10 | 11 | 17 | {% endblock scripts %} 18 | 19 | {% block content %} 20 | 21 |
22 |

23 | {{ form.title.errors }} 24 | 25 | {{ form.title }} 26 |

27 |

28 | {{ form.title.errors }} 29 | 30 | {{ form.content }} 31 |

32 | 33 |
34 | 35 | {% endblock content %} 36 | -------------------------------------------------------------------------------- /apps/wiki/templates/wiki_item.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 | 10 |
11 |
12 |   13 |
14 | 19 | 20 |
21 |


22 |
23 |

{{ wiki_item.title }}

24 | 25 | {{ wiki_item.content|safe }} 26 |
27 | 28 | {% endblock content %} 29 | -------------------------------------------------------------------------------- /apps/wiki/templates/wiki_item_successfully_added.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 | 10 |

Item salvo com sucesso!

11 | 12 | Voltar para a wiki 13 | 14 | {% endblock content %} 15 | 16 | -------------------------------------------------------------------------------- /apps/wiki/templates/wiki_item_successfully_deleted.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 | 10 |

Item excluído com sucesso!

11 | 12 | Voltar para a wiki 13 | 14 | {% endblock content %} 15 | 16 | -------------------------------------------------------------------------------- /apps/wiki/templates/wiki_item_successfully_updated.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block styles %} 4 | {{ block.super }} 5 | 6 | {% endblock styles %} 7 | 8 | {% block content %} 9 | 10 |

Item editado com sucesso!

11 | 12 | Voltar para a wiki 13 | 14 | {% endblock content %} 15 | 16 | -------------------------------------------------------------------------------- /apps/wiki/templates/wiki_items.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load pagination_tags %} 4 | 5 | {% block styles %} 6 | {{ block.super }} 7 | 8 | {% endblock styles %} 9 | 10 | {% block content %} 11 | 12 | {% if user.is_authenticated %} 13 |
14 |
15 |   16 |
17 | 22 | 23 |
24 | {% endif %} 25 | 26 | {% autopaginate wiki_items 5 %} 27 | {% for wiki_item in wiki_items %} 28 |
29 | {{ wiki_item.title }} 30 | {% if user.is_authenticated %} 31 |
32 |   33 |   34 |
35 | {% endif %} 36 |
37 | {% endfor %} 38 | {% paginate %} 39 | 40 | {% endblock content %} 41 | -------------------------------------------------------------------------------- /apps/wiki/tests/test_forms.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from should_dsl import should 4 | 5 | from apps.wiki.forms import WikiItemForm 6 | from apps.wiki.models import WikiItem 7 | 8 | 9 | class WikiFormsTests(TestCase): 10 | 11 | def setUp(self): 12 | self.wiki_item_form = WikiItemForm() 13 | 14 | def test_it_is_an_instance_of_WikiItem(self): 15 | self.wiki_item_form.instance |should| be_instance_of(WikiItem) 16 | 17 | def test_it_has_title_and_content(self): 18 | self.wiki_item_form.fields.keys() |should| equal_to(['title', 'content']) 19 | self.wiki_item_form.fields.keys() |should| have(2).fields 20 | -------------------------------------------------------------------------------- /apps/wiki/tests/test_models.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | from apps.wiki.models import WikiItem 4 | 5 | from should_dsl import should, should_not 6 | 7 | 8 | class WikiModelsTests(TestCase): 9 | 10 | def test_it_has_title_and_content_and_slug(self): 11 | self.wiki_item = WikiItem( 12 | title='Add Plone Site', 13 | content='Click on "Add Plone Site"', 14 | slug='add-plone-site' 15 | ) 16 | self.wiki_item.title |should| equal_to('Add Plone Site') 17 | self.wiki_item.content |should| equal_to('Click on "Add Plone Site"') 18 | self.wiki_item.slug |should| equal_to('add-plone-site') 19 | 20 | def test_it_can_has_a_blank_slug(self): 21 | self.wiki_item = WikiItem( 22 | title='Install Django', 23 | content='Run "pip install django".', 24 | ) 25 | self.wiki_item.full_clean() |should_not| throw('ValidationError') 26 | 27 | def test_it_fills_slug_with_title_when_pre_save_wiki_item(self): 28 | self.wiki_item = WikiItem( 29 | title='Add Plone Site', content='Click on "Add Plone Site"').save() 30 | self.wiki_item = WikiItem.objects.get(title='Add Plone Site') 31 | self.wiki_item.slug |should| equal_to('add-plone-site') 32 | 33 | def test_it_can_adds_many_wiki_items_with_same_title(self): 34 | self.first_wiki_item = WikiItem( 35 | id=1, title='Add Plone Site', content='Click on "Add Plone Site"').save() 36 | self.first_wiki_item = WikiItem.objects.get(id=1) 37 | self.first_wiki_item.slug |should| equal_to('add-plone-site') 38 | self.second_wiki_item = WikiItem( 39 | id=2, title='Add Plone Site', content='Second way to add Plone Site').save() 40 | self.second_wiki_item = WikiItem.objects.get(id=2) 41 | self.second_wiki_item.slug |should| equal_to('add-plone-site-1') 42 | -------------------------------------------------------------------------------- /apps/wiki/tests/test_views.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase, Client 2 | from django.contrib.auth.models import User 3 | 4 | from should_dsl import should 5 | 6 | from apps.wiki.models import WikiItem 7 | 8 | 9 | class WikiViewsTests(TestCase): 10 | 11 | def setUp(self): 12 | self.client = Client() 13 | user = User.objects.create_user('test', 'test@test.com', 'test').save() 14 | 15 | def test_it_shows_all_wiki_items(self): 16 | response = self.client.get('/wiki/') 17 | response.status_code |should| equal_to(200) 18 | response.template[0].name |should| equal_to('wiki_items.html') 19 | response.context[0].has_key('wiki_items') |should| equal_to(True) 20 | 21 | def test_it_can_add_a_wiki_item(self): 22 | self.client.login(username='test', password='test') 23 | response = self.client.get('/wiki/novo_item/') 24 | response.status_code |should| equal_to(200) 25 | response.template[0].name |should| equal_to('add_wiki_item.html') 26 | response.context[0].has_key('wiki_item_form') |should| equal_to(True) 27 | 28 | def test_it_adds_a_wiki_item(self): 29 | response = self.client.post( 30 | '/wiki/novo_item/', 31 | {'title':'Adding a Plone Site', 'content': 'Just clik "Add Plone Site"'}) 32 | response.status_code |should| equal_to(302) 33 | 34 | def test_it_can_view_a_wiki_item(self): 35 | wiki_item = WikiItem(id=3, title='Add Plone Site', content='Click on "Add Plone Site"').save() 36 | response = self.client.get('/wiki/add-plone-site/') 37 | response.status_code |should| equal_to(200) 38 | response.template[0].name |should| equal_to('wiki_item.html') 39 | response.context[0].has_key('wiki_item') |should| be(True) 40 | 41 | def test_it_can_edit_a_wiki_item(self): 42 | self.client.login(username='test', password='test') 43 | WikiItem(id=3, title='Add Plone Site', content='Click on "Add Plone Site"').save() 44 | wiki_item = WikiItem.objects.get(pk=3) 45 | response = self.client.get('/wiki/add-plone-site/editar/') 46 | response.status_code |should| equal_to(200) 47 | response.template[0].name |should| equal_to('edit_wiki_item.html') 48 | response.context[0].has_key('form') |should| be(True) 49 | 50 | def test_it_can_delete_a_wiki_item(self): 51 | self.client.login(username='test', password='test') 52 | WikiItem(id=3, title='Add Plone Site', content='Click on "Add Plone Site"').save() 53 | wiki_item = WikiItem.objects.get(pk=3) 54 | response = self.client.get('/wiki/add-plone-site/excluir/') 55 | response.status_code |should| equal_to(200) 56 | response.template[0].name |should| equal_to('delete_wiki_item.html') 57 | response.context[0].has_key('object') |should| be(True) 58 | -------------------------------------------------------------------------------- /apps/wiki/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import patterns 2 | from django.views.generic.simple import direct_to_template 3 | from django.views.generic.create_update import update_object, delete_object 4 | 5 | from apps.wiki.models import WikiItem 6 | 7 | 8 | urlpatterns = patterns('apps.wiki.views', 9 | (r'^$', 'show_all_wiki_items'), 10 | (r'^novo_item/$', 'add_wiki_item'), 11 | (r'^item_editado_com_sucesso/$', 12 | direct_to_template, {'template': 'wiki_item_successfully_updated.html'} 13 | ), 14 | (r'^item_excluido_com_sucesso/$', 15 | direct_to_template, {'template': 'wiki_item_successfully_deleted.html'} 16 | ), 17 | (r'^novo_item/adicionado_com_sucesso/$', 18 | direct_to_template, {'template': 'wiki_item_successfully_added.html'} 19 | ), 20 | (r'^(?P[\w_-]+)/$', 'view_wiki_item'), 21 | (r'^(?P[\w_-]+)/editar/$', update_object, 22 | {'model': WikiItem, 'template_name': 'edit_wiki_item.html', 23 | 'post_save_redirect': '/wiki/item_editado_com_sucesso/', 24 | 'login_required': True} 25 | ), 26 | (r'^(?P[\w_-]+)/excluir/$', delete_object, 27 | {'model': WikiItem, 'template_name': 'delete_wiki_item.html', 28 | 'post_delete_redirect': '/wiki/item_excluido_com_sucesso/', 29 | 'login_required': True} 30 | ), 31 | ) 32 | -------------------------------------------------------------------------------- /apps/wiki/views.py: -------------------------------------------------------------------------------- 1 | from django.template import RequestContext 2 | from django.shortcuts import render_to_response, get_object_or_404 3 | from django.http import HttpResponseRedirect 4 | from django.contrib.auth.decorators import login_required 5 | 6 | from models import WikiItem 7 | from forms import WikiItemForm 8 | 9 | 10 | def show_all_wiki_items(request): 11 | wiki_items = WikiItem.objects.all() 12 | 13 | return render_to_response( 14 | 'wiki_items.html', 15 | {'wiki_items': wiki_items}, 16 | context_instance=RequestContext(request) 17 | ) 18 | 19 | @login_required 20 | def add_wiki_item(request): 21 | wiki_item_form = WikiItemForm() 22 | if request.method == 'POST': 23 | wiki_item_form = WikiItemForm(request.POST) 24 | if wiki_item_form.is_valid(): 25 | wiki_item_form.save() 26 | return HttpResponseRedirect('/wiki/novo_item/adicionado_com_sucesso/') 27 | 28 | return render_to_response( 29 | 'add_wiki_item.html', 30 | {'wiki_item_form': wiki_item_form}, 31 | context_instance=RequestContext(request) 32 | ) 33 | 34 | def view_wiki_item(request, wiki_item_slug): 35 | wiki_item = get_object_or_404(WikiItem, slug=wiki_item_slug) 36 | 37 | return render_to_response( 38 | 'wiki_item.html', 39 | {'wiki_item': wiki_item}, 40 | context_instance=RequestContext(request) 41 | ) 42 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from django.core.management import execute_manager 3 | 4 | try: 5 | import settings # Assumed to be in the same directory. 6 | except ImportError: 7 | import sys 8 | sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__) 9 | sys.exit(1) 10 | 11 | if __name__ == "__main__": 12 | execute_manager(settings) 13 | -------------------------------------------------------------------------------- /paths.py: -------------------------------------------------------------------------------- 1 | from lettuce.django import django_url 2 | 3 | 4 | def path_to(page_name): 5 | return django_url( 6 | { 7 | 'the NSI home page': '/', 8 | 'the about page': '/sobre', 9 | 'the projects page': '/projetos', 10 | 'the page list all current members': '/membros', 11 | 'the news page': '/noticias', 12 | 'the tools page': '/ferramentas', 13 | 'the tool page': '/ferramenta', 14 | 'page that list all former members': '/ex-membros', 15 | }[page_name]) 16 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | PROJECT_ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) 5 | 6 | DEBUG = True 7 | TEMPLATE_DEBUG = DEBUG 8 | 9 | ADMINS = ( 10 | # ('Your Name', 'your_email@domain.com'), 11 | ) 12 | 13 | MANAGERS = ADMINS 14 | 15 | DATABASES = { 16 | 'default': { 17 | 'ENGINE': 'django.db.backends.sqlite3', 18 | 'NAME': os.path.join(PROJECT_ROOT_PATH, 'nsi_site.db'), 19 | 'USER': '', 20 | 'PASSWORD': '', 21 | 'HOST': '', 22 | 'PORT': '', 23 | } 24 | } 25 | 26 | TIME_ZONE = 'America/Sao_Paulo' 27 | LANGUAGE_CODE = 'pt-br' 28 | 29 | SITE_ID = 1 30 | USE_I18N = True 31 | USE_L10N = True 32 | 33 | MEDIA_ROOT = os.path.join(PROJECT_ROOT_PATH, 'site_media') 34 | MEDIA_URL = '/site_media' 35 | #ADMIN_MEDIA_PREFIX = '/admin_media/' 36 | 37 | SECRET_KEY = 'orv%lcr5o-_@#uq+)@^krb)fh*_p$v*!xtayj4sly@d1s)r^1+' 38 | 39 | TEMPLATE_LOADERS = ( 40 | 'django.template.loaders.filesystem.Loader', 41 | 'django.template.loaders.app_directories.Loader', 42 | # 'django.template.loaders.eggs.Loader', 43 | ) 44 | 45 | TEMPLATE_CONTEXT_PROCESSORS = ( 46 | "django.core.context_processors.auth", 47 | "django.core.context_processors.debug", 48 | "django.core.context_processors.i18n", 49 | "django.core.context_processors.media", 50 | "django.core.context_processors.request" 51 | ) 52 | 53 | MIDDLEWARE_CLASSES = ( 54 | 'django.middleware.common.CommonMiddleware', 55 | 'django.contrib.sessions.middleware.SessionMiddleware', 56 | 'django.middleware.csrf.CsrfViewMiddleware', 57 | 'django.middleware.csrf.CsrfResponseMiddleware', 58 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 59 | 'django.contrib.messages.middleware.MessageMiddleware', 60 | 'linaro_django_pagination.middleware.PaginationMiddleware', 61 | ) 62 | 63 | ROOT_URLCONF = 'urls' 64 | 65 | TEMPLATE_DIRS = ( 66 | os.path.join(PROJECT_ROOT_PATH, 'templates'), 67 | ) 68 | 69 | LETTUCE_AVOID_APPS = ( 70 | 'south', 71 | 'linaro_django_pagination', 72 | ) 73 | 74 | INSTALLED_APPS = ( 75 | 'django.contrib.auth', 76 | 'django.contrib.contenttypes', 77 | 'django.contrib.sessions', 78 | 'django.contrib.sites', 79 | 'django.contrib.messages', 80 | 'django.contrib.admin', 81 | 'lettuce.django', 82 | 'south', 83 | 'linaro_django_pagination', 84 | 'apps.home_page', 85 | 'apps.nsi_info', 86 | 'apps.projects', 87 | 'apps.news', 88 | 'apps.tools', 89 | 'apps.members', 90 | 'apps.wiki', 91 | ) 92 | 93 | PAGINATION_DEFAULT_WINDOW = 1 94 | -------------------------------------------------------------------------------- /settings_test.py: -------------------------------------------------------------------------------- 1 | from settings import * 2 | 3 | DEBUG = True 4 | 5 | DATABASES = { 6 | 'default': { 7 | 'ENGINE': 'django.db.backends.sqlite3', 8 | 'NAME': os.path.join(PROJECT_ROOT_PATH, 'nsi_site-test.db'), 9 | 'USER': '', 10 | 'PASSWORD': '', 11 | 'HOST': '', 12 | 'PORT': '', 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /setup_on_debian_like.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get install python-dev libxml2 libxslt1.1 libxslt1-dev libjpeg62-dev 2 | sudo apt-get install python-setuptools 3 | easy_install pip 4 | 5 | -------------------------------------------------------------------------------- /site_media/css/base.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: verdana,arial,sans-serif; 5 | font-size: 0.625em; 6 | } 7 | 8 | #main { 9 | font-size: 1em; 10 | } 11 | 12 | #header { 13 | height: 100px; 14 | background-color: #E6E6E6; 15 | font-family: "trebuchet ms",arial,sans-serif; 16 | } 17 | 18 | #header #center_header { 19 | background: url("/site_media/images/base/background_head.jpg") repeat scroll 0px 0px transparent; 20 | height: 100px; 21 | width: 900px; 22 | margin: 0 auto; 23 | } 24 | 25 | #header #center_header #logo_nsi { 26 | margin-top: 17px; 27 | margin-left: 10px; 28 | border: none; 29 | } 30 | 31 | #header #menu { 32 | height: 40px; 33 | width: 898px; 34 | margin: 0 auto; 35 | color: #4B4B4B; 36 | font-size: 1.3em; 37 | border-left: 1px solid #AFAFAF; 38 | border-right: 1px solid #AFAFAF; 39 | border-bottom: 1px solid #AFAFAF; 40 | -moz-border-radius-bottomleft: 5px; 41 | -moz-border-radius-bottomright: 5px; 42 | -webkit-border-bottom-right-radius: 5px; 43 | -webkit-border-bottom-left-radius: 5px; 44 | -khtml-border-bottom-right-radius: 5px; 45 | -khtml-border-bottom-left-radius: 5px; 46 | border-bottom-right-radius: 5px; 47 | border-bottom-left-radius: 5px; 48 | } 49 | 50 | #header #menu ul { 51 | list-style-type: none; 52 | margin: 0; 53 | padding: 0; 54 | width: 900px; 55 | } 56 | 57 | #header #menu ul li { 58 | border-right: 1px solid #AFAFAF; 59 | float: left; 60 | position: relative; 61 | z-index: auto !important; 62 | width: 128px; 63 | } 64 | 65 | #header #menu ul li#last { 66 | border-right: none; 67 | width: 126px; 68 | color: #646464; 69 | font-weight: bold; 70 | line-height: 3.1em; 71 | text-align: center; 72 | } 73 | 74 | #header #menu ul li#last:hover { 75 | background-color: #d2d2d2; 76 | -webkit-border-bottom-right-radius: 5px; 77 | -khtml-border-bottom-right-radius: 5px; 78 | border-bottom-right-radius: 5px; 79 | } 80 | 81 | #header #menu ul li a { 82 | color: #646464; 83 | display: block; 84 | float: none !important; 85 | font-weight: bold; 86 | height: 3.1em; 87 | line-height: 3.1em; 88 | text-align: center; 89 | text-decoration: none; 90 | } 91 | 92 | #header #menu ul li:hover a { 93 | background-color: #d2d2d2; 94 | text-decoration:none; 95 | } 96 | 97 | #header #menu ul li ul { 98 | border: medium none; 99 | display: none; 100 | } 101 | 102 | #header #menu ul li:hover ul { 103 | display: block; 104 | position: absolute; 105 | width: auto; 106 | } 107 | 108 | #header #menu ul li:hover ul li { 109 | width: 126px; 110 | } 111 | 112 | #header #menu ul li:hover ul li a { 113 | border-left:solid 1px #AFAFAF; 114 | border-bottom: solid 1px #AFAFAF; 115 | background-color:#ededed; 116 | } 117 | 118 | #header #menu ul li:hover ul li a:hover { 119 | background-color:#d2d2d2; 120 | } 121 | 122 | #content { 123 | clear: both; 124 | width: 900px; 125 | margin: 60px auto 25px; 126 | } 127 | 128 | #footer { 129 | clear: both; 130 | margin: 0 auto; 131 | padding: 5px; 132 | background-color: #E6E6E6; 133 | text-align: center; 134 | } 135 | 136 | .floated_image { 137 | max-width: 100px; 138 | max-height: 100px; 139 | } 140 | 141 | .pagination { 142 | text-align: center; 143 | } 144 | 145 | .pagination .current { 146 | border-radius: 10px; 147 | -moz-border-radius: 10px; 148 | background-color: lightGrey; 149 | padding: 3px; 150 | } 151 | 152 | .pagination a, .pagination a:visited { 153 | color: black; 154 | -------------------------------------------------------------------------------- /site_media/css/index.css: -------------------------------------------------------------------------------- 1 | #content #highlights { 2 | width: 900px; 3 | } 4 | 5 | #content #highlights .title_highlights { 6 | font-size: 1.8em; 7 | margin-left: 5px; 8 | height: 64px; 9 | padding-left: 70px; 10 | line-height: 65px; 11 | } 12 | 13 | #content #highlights #projects, 14 | #content #highlights #news, 15 | #content #highlights #tools, 16 | #content #highlights #planetaNSI { 17 | float: left; 18 | margin-left: 5px; 19 | margin-right: 5px; 20 | margin-bottom: 5px; 21 | padding: 10px; 22 | background-color: #EEEEEE; 23 | -moz-border-radius: 10px; 24 | -webkit-border-radius: 10px; 25 | -khtml-border-radius: 10px; 26 | border-radius: 10px; 27 | border: thin solid #9BCD9B; 28 | } 29 | 30 | #content #highlights #projects { 31 | width: 187px; 32 | } 33 | #content #highlights #news { 34 | width: 430px; 35 | } 36 | #content #highlights #tools { 37 | width: 187px; 38 | } 39 | 40 | #content #highlights #planetaNSI { 41 | width: 187px; 42 | } 43 | 44 | #content #highlights #projects #title_projects { 45 | background: transparent url("/site_media/images/base/projects.png") no-repeat; 46 | margin-bottom: 15px; 47 | } 48 | 49 | #content #highlights #projects .entry { 50 | margin-bottom: 10px; 51 | } 52 | 53 | #content #highlights #projects img { 54 | float: left; 55 | margin-right: 10px; 56 | } 57 | 58 | .text_entry { 59 | height: 32px; 60 | display: table-cell; 61 | vertical-align: middle; 62 | } 63 | 64 | .text_entry a { 65 | font-size: 14px; 66 | } 67 | 68 | .text_entry a:link, .text_entry a:visited { 69 | color: black; 70 | text-decoration: none; 71 | } 72 | 73 | .text_entry a:hover { 74 | color: gray; 75 | text-decoration: underline; 76 | } 77 | 78 | #content #highlights #news #title_news { 79 | background: transparent url("/site_media/images/base/news.png") 140px 0px no-repeat; 80 | padding-left: 210px; 81 | margin-bottom: 15px; 82 | } 83 | 84 | #content #highlights #tools #title_tools { 85 | background: transparent url("/site_media/images/base/tools.png") no-repeat; 86 | margin-bottom: 15px; 87 | } 88 | 89 | #content #highlights #news .entry { 90 | border-bottom: 1px dotted #000; 91 | margin-bottom: 20px; 92 | overflow: hidden; 93 | 94 | } 95 | 96 | #content #highlights #planetaNSI #title_planetaNSI { 97 | background: transparent url("/site_media/images/base/planetaNSI.png") no-repeat; 98 | 99 | margin-bottom: 15px; 100 | } 101 | 102 | #content #highlights #planetaNSI .entry img { 103 | float: left; 104 | margin-right: 10px; 105 | } 106 | 107 | #content #highlights #planetaNSI #feed, 108 | #content #highlights #planetaNSI #github { 109 | height: 32px; 110 | vertical-align: middle; 111 | } 112 | 113 | #content #highlights #news .entry .image_news { 114 | float: left; 115 | margin-right: 7px; 116 | } 117 | 118 | #content #highlights #news .entry .image_news img { 119 | border: none; 120 | } 121 | 122 | #content #highlights #news .entry .text_news { 123 | clear: both; 124 | } 125 | 126 | #content #highlights #news .entry .news_title_without_image { 127 | margin-bottom: 20px; 128 | } 129 | 130 | #content #highlights #news .entry .news_title_with_image a, 131 | #content #highlights #news .entry .news_title_without_image a{ 132 | text-decoration: none; 133 | color: black; 134 | font-size: 1.4em; 135 | } 136 | 137 | #content #highlights #news .entry .news_title_with_image a p, 138 | #content #highlights #news .entry .news_title_without_image a p { 139 | text-align: justify; 140 | } 141 | 142 | #content #highlights #news .entry .news_title_with_image { 143 | display: table-cell; 144 | height: 75px; 145 | vertical-align: middle; 146 | } 147 | 148 | #content #highlights #news .entry .news_title_with_image a:hover, 149 | #content #highlights #news .entry .news_title_without_image a:hover { 150 | color: gray; 151 | text-decoration: underline; 152 | } 153 | 154 | #content #highlights #news #read_more { 155 | float: right; 156 | } 157 | 158 | #content #highlights #news #read_more a, 159 | #content #highlights #news #read_more a:visited { 160 | color: black; 161 | font-size: 14px; 162 | } 163 | 164 | #content #highlights #news #read_more a:hover p { 165 | text-decoration: underline; 166 | } 167 | 168 | #content #highlights #news #read_more p span { 169 | color: green; 170 | font-weight: bold; 171 | font-size: 18px; 172 | } 173 | 174 | #content #highlights #tools .entry { 175 | margin-bottom: 10px; 176 | } 177 | 178 | #content #highlights #tools .entry img { 179 | float: left; 180 | margin-right: 10px; 181 | } 182 | 183 | .text_highlight { 184 | font-weight: bold; 185 | } 186 | 187 | .text_data { 188 | font-weight: bold; 189 | float: right; 190 | } 191 | 192 | .index_image { 193 | max-width: 100px; 194 | max-height: 100px; 195 | } 196 | -------------------------------------------------------------------------------- /site_media/css/members.css: -------------------------------------------------------------------------------- 1 | .member { 2 | padding: 10px 0px 15px 10px; 3 | float: left; 4 | height: 140px; 5 | width: 270px; 6 | margin-right: 9px; 7 | margin-left: 9px; 8 | margin-bottom: 15px; 9 | background-color: #E6E6E6; 10 | border-width: thin; 11 | border-color: #9BCD9B; 12 | border-style: solid; 13 | border-radius: 7px; 14 | -moz-border-radius: 7px; 15 | } 16 | 17 | 18 | .members_content { 19 | display: table; 20 | border-collapse: collapse; 21 | table-layout:fixed; 22 | } 23 | 24 | .avatar { 25 | float: left; 26 | border: none; 27 | border: 2px solid white; 28 | max-width: 100px; 29 | max-height: 100px; 30 | } 31 | 32 | .member_data { 33 | float: left; 34 | margin-left: 15px; 35 | width: 145px; 36 | } 37 | 38 | .member_data h1 { 39 | font-size: 14px; 40 | margin: 0; 41 | } 42 | 43 | .member_data h1 a { 44 | text-decoration: none; 45 | } 46 | 47 | .member_data h1 a:link, .member_data h1 a:visited { 48 | color: black; 49 | } 50 | 51 | .member_data h1 a:hover { 52 | color: gray; 53 | } 54 | 55 | .member_data span { 56 | font-style: italic; 57 | } 58 | 59 | .links{ 60 | clear: left; 61 | padding: 7px 0 0 0; 62 | 63 | position: absolute; 64 | margin-top: 110px; 65 | list-style: none; 66 | } 67 | 68 | .links li { 69 | display: inline; 70 | } 71 | 72 | ul.links li a { 73 | text-decoration: none; 74 | } 75 | 76 | .links a img { 77 | border: none; 78 | width: 22px; 79 | } 80 | 81 | .member_details { 82 | padding: 10px; 83 | border-radius: 15px; 84 | -moz-border-radius: 15px; 85 | margin-bottom: 20px; 86 | overflow: hidden; 87 | border: thin solid #9BCD9B; 88 | } 89 | 90 | .member_details h2 { 91 | text-align: justify; 92 | } 93 | 94 | .member_details img { 95 | float: left; 96 | margin: 0 10px 0 0; 97 | position: relative; 98 | top: -4px; 99 | } 100 | 101 | .member_details a { 102 | display: block; 103 | clear: both; 104 | text-decoration: none; 105 | color: black; 106 | } 107 | 108 | .member_details a h3 { 109 | display: inline; 110 | margin-left: -6px; 111 | } 112 | 113 | .member_details .data{ 114 | margin-left: 150px; 115 | } 116 | 117 | .member_details a img { 118 | margin-bottom: 4px; 119 | position: relative; 120 | top: -10px; 121 | border: none 122 | } 123 | 124 | .member_details .avatar { 125 | float: left; 126 | border: 2px solid white; 127 | margin-left: 15px; 128 | margin-top: 20px; 129 | } 130 | 131 | .member_links { 132 | margin-left: -2px; 133 | padding-top: 15px; 134 | overflow: hidden; 135 | } 136 | 137 | .member_details .text_highlight { 138 | font-size: 12px; 139 | font-weight: bold; 140 | } 141 | 142 | #coderwall_link { 143 | font-size: 12px; 144 | font-weight: bold; 145 | } 146 | 147 | div.github_activities ul.activities li { 148 | padding: 3px 0 3px 0; 149 | } 150 | 151 | div.github_activities ul.activities a:hover { 152 | text-decoration: underline; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /site_media/css/news.css: -------------------------------------------------------------------------------- 1 | .new { 2 | background-color: #E6E6E6; 3 | padding: 10px; 4 | border-radius: 10px; 5 | -moz-border-radius: 10px; 6 | margin-bottom: 20px; 7 | overflow: hidden; 8 | border: thin solid #9BCD9B; 9 | } 10 | 11 | .new img { 12 | float: left; 13 | margin-right: 20px; 14 | margin-bottom: 10px; 15 | border: 3px solid white; 16 | } 17 | 18 | .new #new_image { 19 | float: left; 20 | } 21 | 22 | .new h1 { 23 | margin: 0; 24 | } 25 | 26 | .new h1 a, .new h1 a:visited { 27 | color: black; 28 | text-decoration: none; 29 | } 30 | 31 | .new h1 a:hover { 32 | text-decoration: underline; 33 | } 34 | 35 | .new p span { 36 | font-weight: bold; 37 | } 38 | 39 | .new ul li a, .new ul li a:visited { 40 | color: black; 41 | text-decoration: none; 42 | } 43 | 44 | .new ul li a:hover { 45 | text-decoration: underline; 46 | } 47 | 48 | .new p a { 49 | float: right; 50 | } 51 | 52 | .new p a, .new p a:visited { 53 | color: black; 54 | text-decoration: none; 55 | } 56 | 57 | .new p a:hover { 58 | text-decoration: underline; 59 | } 60 | 61 | .new p a span { 62 | color: green; 63 | font-weight: bold; 64 | font-size: 18px; 65 | } 66 | 67 | .new h3 { 68 | text-align: justify; 69 | font-weight: normal; 70 | } 71 | 72 | .pagination { 73 | text-align: center; 74 | } 75 | 76 | .pagination .current { 77 | border-radius: 10px; 78 | -moz-border-radius: 10px; 79 | background-color: lightGrey; 80 | padding: 3px; 81 | } 82 | 83 | .pagination a, .pagination a:visited { 84 | color: black; 85 | } 86 | -------------------------------------------------------------------------------- /site_media/css/nsi_info.css: -------------------------------------------------------------------------------- 1 | .nsi_info { 2 | text-align: justify; 3 | font-size: 1.2em; 4 | background-color: #E6E6E6; 5 | padding: 10px; 6 | border-radius: 10px; 7 | -moz-border-radius: 10px; 8 | overflow: hidden; 9 | border: thin solid #9BCD9B; 10 | } 11 | -------------------------------------------------------------------------------- /site_media/css/projects.css: -------------------------------------------------------------------------------- 1 | .project { 2 | background-color: #E6E6E6; 3 | padding: 10px; 4 | border-radius: 5px; 5 | -moz-border-radius: 5px; 6 | margin-bottom: 20px; 7 | overflow: hidden; 8 | border: thin solid #9BCD9B; 9 | } 10 | 11 | .project h2 { 12 | margin: 0; 13 | } 14 | 15 | .project h2 a:link, .project h2 a:visited { 16 | color: black; 17 | text-decoration: none; 18 | } 19 | 20 | .project h2 a:hover { 21 | text-decoration: underline; 22 | } 23 | 24 | .project img { 25 | float: left; 26 | margin-right: 20px; 27 | border: 3px solid white; 28 | } 29 | 30 | .project p { 31 | font-size: 12px; 32 | text-align: justify; 33 | } 34 | 35 | .project #know_more:link, .project #know_more:visited { 36 | float: right; 37 | color: black; 38 | text-decoration: none; 39 | } 40 | 41 | .project #know_more:hover { 42 | text-decoration: underline; 43 | } 44 | 45 | .project #know_more span { 46 | font-size: 18px; 47 | color: green; 48 | } 49 | 50 | #project_details { 51 | background-color: #E6E6E6; 52 | padding: 10px; 53 | border-radius: 10px; 54 | -moz-border-radius: 10px; 55 | overflow: hidden; 56 | border: thin solid #9BCD9B; 57 | } 58 | 59 | #project_details img { 60 | border: 3px solid white; 61 | float: left; 62 | margin-right: 20px; 63 | margin-bottom: 10px; 64 | } 65 | 66 | #project_details #project_logo { 67 | float: left; 68 | } 69 | 70 | #project_details #data p { 71 | text-align: justify; 72 | font-size: 1.2em; 73 | } 74 | 75 | #project_details #data h1 { 76 | margin: 0; 77 | } 78 | 79 | #project_details #data .text_highlight { 80 | font-size: 12px; 81 | font-weight: bold; 82 | } 83 | 84 | #project_details #data #documents { 85 | border: 1px solid #BDBDBD; 86 | border-collapse: collapse; 87 | } 88 | 89 | #project_details #data #documents tr th, #project_details #documents tr td { 90 | padding: 5px; 91 | } 92 | 93 | #project_details #data #documents tr th, #project_details #documents tr td { 94 | border: 1px solid #BDBDBD; 95 | } 96 | 97 | #project_details #data ul li a:link, #project_details #data ul li a:visited, span#github_project { 98 | color: black; 99 | text-decoration: none; 100 | } 101 | 102 | #project_details #data ul li a:hover, span#github_project a { 103 | text-decoration: underline; 104 | } 105 | 106 | #project_details a { 107 | clear: both; 108 | color: black; 109 | text-decoration:none; 110 | } 111 | 112 | #project_details #data ul a:hover, span#github_project a { 113 | text-decoration: underline; 114 | } 115 | 116 | div.github_activities ul.activities li { 117 | padding: 3px 0 3px 0; 118 | } 119 | -------------------------------------------------------------------------------- /site_media/css/tools.css: -------------------------------------------------------------------------------- 1 | .tool { 2 | background-color: #E6E6E6; 3 | padding: 10px; 4 | border-radius: 5px; 5 | -moz-border-radius: 5px; 6 | margin-bottom: 20px; 7 | overflow: hidden; 8 | border: thin solid #9BCD9B; 9 | } 10 | 11 | .tool img { 12 | border: 3px solid white; 13 | float: left; 14 | margin-bottom: 10px; 15 | margin-right: 20px; 16 | } 17 | 18 | .tool h1 { 19 | margin: 0; 20 | } 21 | 22 | .tool p { 23 | font-size: 12px; 24 | } 25 | 26 | .tool p span { 27 | font-weight: bold; 28 | } 29 | 30 | .tool a:link, .tool a:visited { 31 | color: black; 32 | text-decoration: none; 33 | } 34 | 35 | .more_info { 36 | float: right; 37 | } 38 | 39 | .tool p a span { 40 | color: green; 41 | font-size: 18px; 42 | font-weight: bold; 43 | -------------------------------------------------------------------------------- /site_media/css/wiki.css: -------------------------------------------------------------------------------- 1 | .edit { 2 | background-image: url("/site_media/images/wiki/edit.png"); 3 | display: block; 4 | width: 24px; 5 | height: 24px; 6 | float: left; 7 | text-decoration: none; 8 | } 9 | 10 | .edit:hover { 11 | background-image: url("/site_media/images/wiki/edit_hover.png"); 12 | } 13 | 14 | .delete { 15 | background-image: url("/site_media/images/wiki/delete.png"); 16 | display: block; 17 | width: 24px; 18 | height: 24px; 19 | float: left; 20 | text-decoration: none; 21 | } 22 | 23 | .delete:hover { 24 | background-image: url("/site_media/images/wiki/delete_hover.png"); 25 | } 26 | 27 | .wiki_item { 28 | clear: both; 29 | background-color: #ECECEC; 30 | height: 30px; 31 | margin-bottom: 15px; 32 | border-radius: 10px; 33 | box-shadow: black 1px 1px 1px; 34 | } 35 | 36 | .wiki_item .wiki_item_title { 37 | color: black; 38 | font-size: 2em; 39 | font-weight: bold; 40 | margin-left: 10px; 41 | text-decoration: none; 42 | } 43 | 44 | .wiki_item .wiki_item_title:hover { 45 | text-decoration: underline; 46 | } 47 | 48 | .manage_wiki_item { 49 | float: right; 50 | margin-top: 4px; 51 | margin-right: 5px; 52 | } 53 | 54 | #new_item { 55 | float: right; 56 | margin-bottom: 20px; 57 | } 58 | 59 | #new_item a { 60 | text-decoration: none; 61 | color: black; 62 | } 63 | 64 | #new_item a:hover { 65 | text-decoration: underline; 66 | } 67 | 68 | #new_item_image { 69 | float: left; 70 | margin-right: 5px; 71 | } 72 | 73 | #new_item_image a { 74 | background-image: url("/site_media/images/wiki/add.png"); 75 | display: block; 76 | width: 24px; 77 | height: 24px; 78 | } 79 | 80 | #new_item_image a:hover { 81 | background-image: url("/site_media/images/wiki/add_hover.png"); 82 | text-decoration: none; 83 | } 84 | 85 | #new_item_text { 86 | display: table-cell; 87 | font-size: 1.5em; 88 | height: 24px; 89 | vertical-align: middle; 90 | width: 167px; 91 | } 92 | 93 | label { 94 | font-size: 1.3em; 95 | } 96 | input[type=text] { 97 | padding-top: 10px; 98 | padding-bottom: 10px; 99 | padding-left: 10px; 100 | width: 890px; 101 | } 102 | textarea { 103 | width: 900px; 104 | height: 300px; 105 | } 106 | 107 | #back_to_wiki_page { 108 | float: right; 109 | } 110 | 111 | #back_to_wiki_page a { 112 | text-decoration: none; 113 | color: black; 114 | } 115 | 116 | #back_to_wiki_page a:hover { 117 | text-decoration: underline; 118 | } 119 | 120 | #back_to_wiki_page_image { 121 | float: left; 122 | margin-right: 5px; 123 | } 124 | 125 | #back_to_wiki_page_image a { 126 | background-image: url("/site_media/images/wiki/back.png"); 127 | display: block; 128 | width: 24px; 129 | height: 24px; 130 | } 131 | 132 | #back_to_wiki_page_text { 133 | display: table-cell; 134 | font-size: 1.5em; 135 | height: 24px; 136 | vertical-align: middle; 137 | width: 200px; 138 | } 139 | 140 | #wiki_item_page { 141 | text-align: justify; 142 | font-size: 1.2em; 143 | background-color: #E6E6E6; 144 | padding: 10px; 145 | border-radius: 10px; 146 | -moz-border-radius: 10px; 147 | overflow: hidden; 148 | border: thin solid #9BCD9B; 149 | } 150 | 151 | .pagination { 152 | text-align: center; 153 | } 154 | 155 | .pagination .current { 156 | border-radius: 10px; 157 | -moz-border-radius: 10px; 158 | background-color: lightGrey; 159 | padding: 3px; 160 | } 161 | 162 | .pagination a, .pagination a:visited { 163 | color: black; 164 | } 165 | -------------------------------------------------------------------------------- /site_media/files/projects/.gitignore: -------------------------------------------------------------------------------- 1 | DON'T DELETE THIS FILE!! 2 | 3 | -------------------------------------------------------------------------------- /site_media/images/base/background_head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/background_head.jpg -------------------------------------------------------------------------------- /site_media/images/base/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/favicon.ico -------------------------------------------------------------------------------- /site_media/images/base/feed.32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/feed.32x32.png -------------------------------------------------------------------------------- /site_media/images/base/github.32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/github.32x32.png -------------------------------------------------------------------------------- /site_media/images/base/icon_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/icon_github.png -------------------------------------------------------------------------------- /site_media/images/base/icon_lattes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/icon_lattes.png -------------------------------------------------------------------------------- /site_media/images/base/icon_site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/icon_site.png -------------------------------------------------------------------------------- /site_media/images/base/icon_slideshare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/icon_slideshare.png -------------------------------------------------------------------------------- /site_media/images/base/icon_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/icon_twitter.png -------------------------------------------------------------------------------- /site_media/images/base/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/logo.png -------------------------------------------------------------------------------- /site_media/images/base/news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/news.png -------------------------------------------------------------------------------- /site_media/images/base/planetaNSI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/planetaNSI.png -------------------------------------------------------------------------------- /site_media/images/base/projects.32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/projects.32x32.png -------------------------------------------------------------------------------- /site_media/images/base/projects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/projects.png -------------------------------------------------------------------------------- /site_media/images/base/tools.32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/tools.32x32.png -------------------------------------------------------------------------------- /site_media/images/base/tools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/base/tools.png -------------------------------------------------------------------------------- /site_media/images/members/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/members/.gitignore -------------------------------------------------------------------------------- /site_media/images/news/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/news/.gitignore -------------------------------------------------------------------------------- /site_media/images/projects/.gitignore: -------------------------------------------------------------------------------- 1 | DON'T DELETE THIS FILE!! 2 | 3 | -------------------------------------------------------------------------------- /site_media/images/wiki/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/add.png -------------------------------------------------------------------------------- /site_media/images/wiki/add_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/add_hover.png -------------------------------------------------------------------------------- /site_media/images/wiki/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/back.png -------------------------------------------------------------------------------- /site_media/images/wiki/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/delete.png -------------------------------------------------------------------------------- /site_media/images/wiki/delete_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/delete_hover.png -------------------------------------------------------------------------------- /site_media/images/wiki/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/edit.png -------------------------------------------------------------------------------- /site_media/images/wiki/edit_hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsi-iff/nsi_site/a70056d227ea7404364583221b21e83498405b29/site_media/images/wiki/edit_hover.png -------------------------------------------------------------------------------- /site_media/javascripts/coderwall.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Code to display coderwall.com badges 3 | */ 4 | 5 | $(document).ready(function(){ 6 | var member = $('#github_user').text(); 7 | var coderwallJSONurl ="http://www.coderwall.com/" + member + ".json?callback=?"; 8 | var height = 75; 9 | var width = 75; 10 | 11 | $.getJSON(coderwallJSONurl, function(data) { 12 | $("

Coderwall Achievements



").appendTo("#coderwall"); 13 | $.each(data.data.badges, function(i, item) { 14 | $("").attr("src", item.badge) 15 | .attr("float", "left") 16 | .attr("title", item.name + ": " + item.description) 17 | .attr("alt", item.name) 18 | .attr("height", height) 19 | .attr("width", width) 20 | .appendTo("#coderwall") 21 | .hover( 22 | function(){ 23 | $(this).css("opacity","0.6"); 24 | }, 25 | function(){ 26 | $(this).css("opacity","1.0"); 27 | } 28 | ) 29 | }); 30 | }); 31 | }); 32 | 33 | -------------------------------------------------------------------------------- /site_media/javascripts/github_activities.js: -------------------------------------------------------------------------------- 1 | // jQuery plugin to show github user's activities 2 | // https://github.com/bernardofire/github-activities 3 | 4 | (function($) { 5 | function parse(feed, container, settings) { 6 | if (feed.entries.length > 0) { 7 | $(feed.entries).each(function(key, entry){ 8 | var content = entry.contentSnippet; 9 | //convert special chars and remove unnecessary " ..." from content 10 | var description = $('').html(content).text().trim().replace(new RegExp("[\n ]+...$"),''); 11 | var title = entry.title; 12 | if (settings.hide_username) 13 | title = title.replace(new RegExp('^' + entry.author + ' '), ''); 14 | var li_entry = $('
  • ').text(title); 15 | var div_entry = $('').append(li_entry); 16 | div_entry.attr({ 17 | 'href': entry.link, 18 | 'target': '_blank', 19 | 'title': description 20 | }); 21 | $(container).append(div_entry); 22 | }); 23 | } 24 | } 25 | 26 | $.fn.extend({ 27 | activities: 28 | function(options) { 29 | var defaults = { 30 | 'username': '', 31 | 'hide_username': false, 32 | } 33 | 34 | var settings = $.extend(defaults, options); 35 | 36 | return this.each(function() { 37 | var container = $(this) 38 | $.ajax({ 39 | url: 'http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent('http://github.com/' + settings.username + '.atom'), 40 | async: true, 41 | dataType: 'json', 42 | success: function(data) { 43 | parse(data.responseData.feed, container, settings); 44 | } 45 | }); 46 | }); 47 | } 48 | }); 49 | })(jQuery); 50 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}NSI - Núcleo de Pesquisa em Sistemas de Informação{% endblock title %} 6 | 7 | 8 | {% block styles %} 9 | 10 | {% endblock styles %} 11 | 12 | {% block scripts %} 13 | 14 | {% endblock scripts %} 15 | 16 | 17 | 18 |
    19 | 63 |
    64 | {% block content %} 65 | {% endblock content %} 66 |
    67 | 71 |
    72 | 73 | 74 | -------------------------------------------------------------------------------- /terrain.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import shutil 4 | from django.core.management import call_command 5 | from django.conf import settings 6 | from splinter.browser import Browser 7 | from lettuce import after, before, world 8 | from web_steps import * 9 | 10 | 11 | PROJECT_ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) 12 | 13 | @before.harvest 14 | def initial_run_time(variables): 15 | world.time_before_harvest = time.time() 16 | test_directories_list = [ 17 | os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test', 'files', 'projects'), 18 | os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test', 'images', 'members'), 19 | os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test', 'images', 'news'), 20 | os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test', 'images', 'projects'), 21 | os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test', 'images', 'tools'), 22 | ] 23 | 24 | for directory in test_directories_list: 25 | if not os.path.exists(directory): 26 | os.makedirs(directory) 27 | 28 | @before.all 29 | def set_browser(): 30 | world.browser = Browser() 31 | 32 | @before.each_scenario 33 | def clean_database(scenario): 34 | clean_data() 35 | clean_media() 36 | 37 | def clean_data(): 38 | call_command('flush', interactive=False) 39 | call_command('loaddata', 'all') 40 | 41 | def clean_media(): 42 | clean_media_by_kind('images') 43 | clean_media_by_kind('files') 44 | 45 | def clean_media_by_kind(kind, skip_dir=None): 46 | images_dir = os.path.join(settings.MEDIA_ROOT, 'test', kind) 47 | for file_name in os.listdir(images_dir): 48 | clean_all(os.path.join(images_dir, file_name)) 49 | 50 | def clean_all(directory, skip_dir=None): 51 | for file_name in os.listdir(directory): 52 | absname = os.path.join(directory, file_name) 53 | if skip_dir and skip_dir in absname: 54 | pass 55 | elif os.path.isdir(absname) and file_name not in ['.', '..']: 56 | clean_all(absname) 57 | elif not file_name.startswith('.'): 58 | os.unlink(absname) 59 | 60 | @after.all 61 | def finish_him(total_result): 62 | world.browser.quit() 63 | clean_media() 64 | 65 | @after.harvest 66 | def run_time(results): 67 | shutil.rmtree(os.path.join(PROJECT_ROOT_PATH, 'site_media', 'test')) 68 | time_after_harvest = time.time() 69 | time_before_harvest = world.time_before_harvest 70 | total_time = int(time_after_harvest - time_before_harvest) 71 | minutes = total_time / 60 72 | seconds = total_time % 60 73 | total_features_ran = 0 74 | total_scenarios_ran = 0 75 | total_scenarios_passed = 0 76 | total_scenarios_failed = dict() 77 | for app in results: 78 | total_features_ran += app.features_ran 79 | total_scenarios_ran += app.scenarios_ran 80 | total_scenarios_passed += app.scenarios_passed 81 | for result in app.scenario_results: 82 | if result.passed == False: 83 | total_scenarios_failed.update({result.scenario.name: result.scenario.feature}) 84 | 85 | print '\n================================================' 86 | print '=========== Acceptance tests results ===========\n' 87 | print '\033[32m\033[1m%i features ran.\033[0;0m' % total_features_ran 88 | print '\033[32m\033[1m%i scenarios ran.\033[0;0m' % total_scenarios_ran 89 | print '\033[32m\033[1m%i scenarios passed.\033[0;0m' % total_scenarios_passed 90 | if total_scenarios_failed: 91 | print '\033[31m\033[1mError in:\033[0;0m' 92 | for scenario, feature in total_scenarios_failed.iteritems(): 93 | print '\033[31m\033[1m' + feature.name + ' ~> ' + scenario + '\033[0;0m' 94 | else: 95 | print '\033[32m\033[1mNo errors! Congratulations!\033[0;0m' 96 | print '----------------------------------------------------------------------' 97 | print 'Everything ran in %i minute(s) and %i second(s).' % (minutes, seconds) 98 | 99 | -------------------------------------------------------------------------------- /urls.py: -------------------------------------------------------------------------------- 1 | from django.conf.urls.defaults import * 2 | from django.conf import settings 3 | from django.contrib import admin 4 | 5 | 6 | admin.autodiscover() 7 | 8 | urlpatterns = patterns('', 9 | (r'^admin/', include(admin.site.urls)), 10 | 11 | (r'^$', 'apps.home_page.views.show_index'), 12 | 13 | url(r'^', include('apps.news.urls')), 14 | 15 | (r'^sobre/$', 'apps.nsi_info.views.show_about'), 16 | 17 | url(r'^', include('apps.projects.urls')), 18 | 19 | url(r'^', include('apps.members.urls')), 20 | 21 | url(r'^', include('apps.tools.urls')), 22 | 23 | (r'^wiki/', include('apps.wiki.urls')), 24 | 25 | (r'^site_media/(.*)$', 'django.views.static.serve', {"document_root": settings.MEDIA_ROOT}), 26 | ) 27 | -------------------------------------------------------------------------------- /web_steps.py: -------------------------------------------------------------------------------- 1 | import re 2 | from lettuce import world, step 3 | from should_dsl import should 4 | from paths import path_to 5 | 6 | 7 | @step(r'I fill in "(.*)" with "(.*)"') 8 | def fill_field(step, label, value): 9 | world.browser.fill(label, value) 10 | 11 | @step(r'I go to "(.+)"') 12 | def i_go_to(step, page_name): 13 | world.browser.visit(path_to(page_name)) 14 | 15 | @step(r'I press "(.*)"') 16 | def press_button(step, name): 17 | world.browser.find_by_name(name.lower()).click() 18 | 19 | @step(u'I click "(.*)"') 20 | def i_click(step, link): 21 | world.browser.find_link_by_text(link).first.click() 22 | 23 | # a "little" help from http://love-python.blogspot.com/2008/07/strip-html-tags-using-python.html 24 | def remove_html_tags(data): 25 | p = re.compile(r'<.*?>') 26 | return p.sub('', data) 27 | 28 | def remove_extra_spaces(data): 29 | p = re.compile(r'\s+') 30 | return p.sub(' ', data) 31 | 32 | @step(r'I should see "(.*)"$') 33 | def i_should_see(step, content): 34 | page_content = remove_extra_spaces(remove_html_tags(world.browser.html)) 35 | page_content |should| contain(content) 36 | 37 | @step(u'I should have "(.*)" as HTML') 38 | def i_should_have_as_html(step, html_output): 39 | world.browser.html |should| contain(html_output) 40 | 41 | @step(u'I should see an image called "(.*)"') 42 | def and_i_should_see_an_image_called_group1(step, image_name): 43 | images = world.browser.find_by_css('img') 44 | found_image = [image for image in images if image['src'].endswith(image_name)] 45 | found_image |should| have_at_least(1).image 46 | 47 | @step(u'I should see a link to "(.*)" with label "(.*)"') 48 | def i_should_see_a_link_to_with_label(step, link_href, link_text): 49 | links = world.browser.find_link_by_text(link_text) 50 | links |should| have_at_least(1).item 51 | link = links[0] 52 | link['href'] |should| end_with(link_href) 53 | 54 | @step(u'I should see a link with text "(.*)"') 55 | def i_should_see_a_link_with_text(step, link_text): 56 | world.browser.find_link_by_text(link_text) |should| have(1).item 57 | 58 | --------------------------------------------------------------------------------