mirror of https://github.com/interlegis/sigi.git
22 changed files with 413 additions and 0 deletions
@ -0,0 +1,15 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from django.contrib import admin |
|||
from sigi.forms_builder.forms.admin import FieldAdmin, FormAdmin |
|||
from sigi.apps.pesquisas.models import Pesquisa, Pergunta, Formulario, Resposta |
|||
|
|||
class PerguntaAdmin(FieldAdmin): |
|||
model = Pergunta |
|||
|
|||
class PesquisaAdmin(FormAdmin): |
|||
formentry_model = Formulario |
|||
fieldentry_model = Resposta |
|||
inlines = (PerguntaAdmin,) |
|||
|
|||
admin.site.register(Pesquisa, PesquisaAdmin) |
@ -0,0 +1,11 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from sigi.forms_builder.forms.forms import FormForForm |
|||
from sigi.apps.pesquisas.models import Formulario, Resposta |
|||
|
|||
class PesquisaForm(FormForForm): |
|||
field_entry_model = Resposta |
|||
|
|||
class Meta(FormForForm.Meta): |
|||
model = Formulario |
|||
fields = ['casa_legislativa',] |
@ -0,0 +1,44 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from django.db import models |
|||
from django.utils.translation import ungettext, ugettext_lazy as _ |
|||
from sigi.forms_builder.forms.models import AbstractForm, AbstractField, AbstractFormEntry, AbstractFieldEntry |
|||
from sigi.apps.casas.models import CasaLegislativa |
|||
from sigi.apps.servidores.models import Servidor |
|||
|
|||
class Pesquisa(AbstractForm): |
|||
class Meta: |
|||
verbose_name = _("Pesquisa") |
|||
verbose_name_plural = _("Pesquisas") |
|||
|
|||
class Pergunta(AbstractField): |
|||
""" |
|||
Implements automated field ordering. |
|||
""" |
|||
|
|||
form = models.ForeignKey("Pesquisa", related_name="fields") |
|||
order = models.IntegerField(_("Order"), null=True, blank=True) |
|||
|
|||
class Meta(AbstractField.Meta): |
|||
ordering = ("order",) |
|||
|
|||
def save(self, *args, **kwargs): |
|||
if self.order is None: |
|||
self.order = self.form.fields.count() |
|||
super(Pergunta, self).save(*args, **kwargs) |
|||
|
|||
def delete(self, *args, **kwargs): |
|||
fields_after = self.form.fields.filter(order__gte=self.order) |
|||
fields_after.update(order=models.F("order") - 1) |
|||
super(Pergunta, self).delete(*args, **kwargs) |
|||
|
|||
class Formulario(AbstractFormEntry): |
|||
form = models.ForeignKey("Pesquisa", related_name="entries") |
|||
casa_legislativa = models.ForeignKey(CasaLegislativa, verbose_name=u"Casa legislativa") |
|||
#operador = models.ForeignKey(Servidor, verbose_name=u"Operador") |
|||
|
|||
class Meta(AbstractFormEntry.Meta): |
|||
unique_together = ('form', 'casa_legislativa') |
|||
|
|||
class Resposta(AbstractFieldEntry): |
|||
entry = models.ForeignKey("Formulario", related_name="fields") |
@ -0,0 +1,30 @@ |
|||
{% extends "admin/change_form.html" %} |
|||
|
|||
{% load i18n %} |
|||
{% load url from future %} |
|||
|
|||
{% block object-tools %} |
|||
{% if change %}{% if not is_popup %} |
|||
<ul class="object-tools"> |
|||
<li> |
|||
<a href="{% url "admin:form_entries" object_id %}">{% trans "View entries" %}</a> |
|||
</li> |
|||
<li> |
|||
<a href="history/" class="historylink">{% trans "History" %}</a> |
|||
</li> |
|||
{% if has_absolute_url %} |
|||
<li> |
|||
<a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a> |
|||
</li> |
|||
{% endif%} |
|||
</ul> |
|||
<style> |
|||
#fields-group .vTextField {width: 13.5em;} |
|||
#fields-group .vIntegerField {width: 2em;} |
|||
#fields-group .field-required, |
|||
#fields-group .field-visible, |
|||
#fields-group .delete {text-align: center;} |
|||
form .aligned p.help {padding-left: 24px;} |
|||
</style> |
|||
{% endif %}{% endif %} |
|||
{% endblock %} |
@ -0,0 +1,167 @@ |
|||
{% extends "admin/base_site.html" %} |
|||
|
|||
{% load i18n %} |
|||
|
|||
{% block extrahead %} |
|||
{{ block.super }} |
|||
<style> |
|||
#content-main table {margin:10px 0 20px 0;} |
|||
#content-main ul, #content-main li {display:inline; padding:0;} |
|||
#content-main label {cursor:pointer;} |
|||
h1 {margin-top:20px;} |
|||
#content-main h1 {margin:30px 0 0 0;} |
|||
table {border:1px solid #ddd; width:100%;} |
|||
th, td {border-right:1px solid #ddd; padding:5px 15px;} |
|||
.last {border-right:0;} |
|||
td.include, th.include-all, td.include-all {text-align:center; width:10px;} |
|||
.empty {margin-top:10px;} |
|||
.field {padding-top:8px;} |
|||
.filter select {width:140px;} |
|||
.options {vertical-align:middle; white-space:nowrap;} |
|||
.options label {margin:0 10px; font-weight:normal; vertical-align:middle;} |
|||
.options-div {visibility:hidden;} |
|||
.options select {min-width:0;} |
|||
.on {background:#eee;} |
|||
.off {background:#fff;} |
|||
.button {float:left !important; margin-right:10px; cursor:pointer;} |
|||
</style> |
|||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script> |
|||
<script> |
|||
$(function() { |
|||
// Show the filter criteria fields when a filter option is selected. |
|||
$('.filter select').change(function() { |
|||
var filtering = this.selectedIndex > 0; |
|||
var options = $(this).parent().parent().find('.options-div'); |
|||
options.css('visibility', filtering ? 'visible' : 'hidden'); |
|||
// Focus the first field. |
|||
if (filtering) { |
|||
var input = options.find('input:first'); |
|||
if (input.length === 1) { |
|||
input.focus(); |
|||
} else { |
|||
options.find('select:first').focus(); |
|||
} |
|||
} |
|||
}).change(); |
|||
// Toggle the include `All` checkboxes - grouped within table tags. |
|||
$('#content-main table').each(function(i, table) { |
|||
table = $(table); |
|||
var all = table.find('.include-all :checkbox'); |
|||
var others = table.find('.include :checkbox'); |
|||
others.change(function() { |
|||
var len = table.find('.include :checkbox:not(:checked)').length; |
|||
all.attr('checked', len === 0); |
|||
}); |
|||
all.change(function() { |
|||
others.attr('checked', !!all.attr('checked')); |
|||
}); |
|||
}); |
|||
// Add a confirmation prompt for deleting entries. |
|||
$('input[name="delete"]').click(function() { |
|||
if ( $('input[name="selected"]:checked').length === 0 ) { |
|||
alert('{% trans "No entries selected" %}'); |
|||
return false; |
|||
} else { |
|||
return confirm('{% trans "Delete selected entries?" %}'); |
|||
} |
|||
}); |
|||
}); |
|||
</script> |
|||
{% endblock %} |
|||
|
|||
{% block breadcrumbs %} |
|||
<div class="breadcrumbs"> |
|||
<a href="../../../../">{% trans "Home" %}</a> › |
|||
<a href="../../../">{{ opts.app_label|capfirst|escape }}</a> › |
|||
<a href="../../">{{ opts.verbose_name_plural|capfirst }}</a> › |
|||
<a href="../">{{ original|truncatewords:"18" }}</a> › |
|||
{{ title }} |
|||
</div> |
|||
{% endblock %} |
|||
|
|||
{% block content %} |
|||
<div id="content-main"> |
|||
<form method="post"> |
|||
{% csrf_token %} |
|||
<table> |
|||
<tr> |
|||
<th>{% trans "Field" %}</th> |
|||
<th>{% trans "Include" %}</th> |
|||
<th class="last" colspan="2">{% trans "Filter by" %}</th> |
|||
</tr> |
|||
{% for include_field, filter_field, filter_option_fields in entries_form %} |
|||
<tr class="{% cycle on,off as row %}"> |
|||
<td class="field">{{ include_field.label_tag }}</td> |
|||
<td class="include">{{ include_field }}</td> |
|||
<td class="filter last">{{ filter_field }}</td> |
|||
<td class="options last"> |
|||
<div class="options-div"> |
|||
{% for option_field in filter_option_fields %} |
|||
{{ option_field.label_tag }} {{ option_field }} |
|||
{% endfor %} |
|||
</div> |
|||
</td> |
|||
</tr> |
|||
{% endfor %} |
|||
<tr class="{% cycle row %}"> |
|||
<td class="field" style="text-align:right;"> |
|||
<label for="include-all">{% trans "All" %}</label> |
|||
</td> |
|||
<td class="include-all"> |
|||
<input type="checkbox" id="include-all" class="include-all" checked="checked"> |
|||
</td> |
|||
<td class="last" colspan="2"> </td> |
|||
</tr> |
|||
</table> |
|||
<input type="submit" name="back" class="button" value="{% trans "Back to form" %}"> |
|||
<input type="submit" class="button default" value="{% trans "View entries" %}"> |
|||
<input type="submit" class="button default" name="export" value="{% trans "Export CSV" %}"> |
|||
{% if xlwt_installed %} |
|||
<input type="submit" class="button default" name="export_xls" value="{% trans "Export XLS" %}"> |
|||
{% endif %} |
|||
{% if submitted %} |
|||
<br clear="both" /> |
|||
<h1 id="entries-title">{% trans "Entries" %}</h1> |
|||
{% for row in entries_form.rows %} |
|||
{% if forloop.first %} |
|||
<table id="entries-table"> |
|||
<tr> |
|||
{% if can_delete_entries %} |
|||
<th class="include-all"><input type="checkbox"></th> |
|||
{% endif %} |
|||
{% for column in entries_form.columns %} |
|||
<th{% if forloop.last %} class="last"{% endif %}>{{ column }}</th> |
|||
{% endfor %} |
|||
</tr> |
|||
{% endif %} |
|||
<tr class="{% cycle on,off %}"> |
|||
{% if can_delete_entries %} |
|||
<td class="include"> |
|||
<input type="checkbox" name="selected" value="{{ row.0 }}"> |
|||
</td> |
|||
{% endif %} |
|||
{% for field in row %} |
|||
{% if not forloop.first %} |
|||
<td{% if forloop.last %} class="last"{% endif %}>{{ field }}</td> |
|||
{% endif %} |
|||
{% endfor %} |
|||
</tr> |
|||
{% if forloop.last %} |
|||
</table> |
|||
<!-- |
|||
count is injected into the title here with the :after selector |
|||
to avoid calling the expensive "entries_form.rows" twice. |
|||
--> |
|||
<style>#entries-title:after {content: ' ({{ forloop.counter }})';}</style> |
|||
{% if can_delete_entries %} |
|||
<input type="submit" name="back" class="button" value="{% trans "Back to form" %}"> |
|||
<input type="submit" name="delete" class="button default" value="{% trans "Delete selected" %}"> |
|||
{% endif %} |
|||
{% endif %} |
|||
{% empty %} |
|||
<p class="empty">{% trans "No entries to display" %}</p> |
|||
{% endfor %} |
|||
{% endif %} |
|||
</form> |
|||
</div> |
|||
{% endblock %} |
@ -0,0 +1,3 @@ |
|||
{% block main %}{% endblock %} |
|||
|
|||
<br><a href="http://{{ request.get_host }}">http://{{ request.get_host }}</a> |
@ -0,0 +1,3 @@ |
|||
{% block main %}{% endblock %} |
|||
|
|||
http://{{ request.get_host }} |
@ -0,0 +1,13 @@ |
|||
{% extends "email_extras/base.html" %} |
|||
|
|||
{% block main %} |
|||
{% if message %}<p>{{ message }}</p>{% endif %} |
|||
<table border="0"> |
|||
{% for field, value in fields %} |
|||
<tr> |
|||
<td><b>{{ field }}:</b></td> |
|||
<td>{{ value|linebreaks }}</td> |
|||
</tr> |
|||
{% endfor %} |
|||
</table> |
|||
{% endblock %} |
@ -0,0 +1,9 @@ |
|||
{% extends "email_extras/base.txt" %} |
|||
|
|||
{% block main %}{% if message %} |
|||
{{ message }} |
|||
|
|||
{% endif %}{% for field, value in fields %} |
|||
{{ field }}: {{ value|safe }} |
|||
{% endfor %} |
|||
{% endblock %} |
@ -0,0 +1,5 @@ |
|||
{% extends "email_extras/form_response.html" %} |
|||
|
|||
{% block main %} |
|||
{{ block.super }} |
|||
{% endblock %} |
@ -0,0 +1,5 @@ |
|||
{% extends "email_extras/form_response.txt" %} |
|||
|
|||
{% block main %} |
|||
{{ block.super }} |
|||
{% endblock %} |
@ -0,0 +1,17 @@ |
|||
<!doctype html> |
|||
{% load forms_builder_tags %} |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>{{ form.title }}</title> |
|||
<style> |
|||
body {font-family:sans-serif; padding:1em 2em;} |
|||
p {width:50em; clear:both;} |
|||
label {display:block; float:left; width:8em; margin:0 1.2em 1.2em 0;} |
|||
li {list-style-type:none;} |
|||
li label {width:auto; cursor:pointer;} |
|||
.errorlist {color:#f00;} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
{% render_built_form form %} |
|||
</body> |
@ -0,0 +1,17 @@ |
|||
<!doctype html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<title>{{ form.title }}</title> |
|||
<style> |
|||
body {font-family:sans-serif; padding:1em 2em;} |
|||
p {width:50em;} |
|||
label {display:block; float:left; width:10em;} |
|||
.errorlist {color:#f00;} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<h1>{{ form.title }}</h1> |
|||
{% if form.response %} |
|||
<p>{{ form.response }}</p> |
|||
{% endif %} |
|||
</body> |
@ -0,0 +1,11 @@ |
|||
<h1>{{ form.title }}</h1> |
|||
{% if form.intro %} |
|||
<p>{{ form.intro }}</p> |
|||
{% endif %} |
|||
<form action="{{ form.get_absolute_url }}" method="post" |
|||
{% if form_for_form.is_multipart %}enctype="multipart/form-data"{% endif %}> |
|||
{% csrf_token %} |
|||
{{ form_for_form.as_p }} |
|||
<div style="clear:left;"> </div> |
|||
<input type="submit" value="{{ form.button_text }}"> |
|||
</form> |
@ -0,0 +1,33 @@ |
|||
from django import template |
|||
from sigi.forms_builder.forms.templatetags.forms_builder_tags import BuiltFormNode |
|||
from sigi.apps.pesquisas.models import Pesquisa |
|||
from sigi.apps.pesquisas.forms import PesquisaForm |
|||
|
|||
register = template.Library() |
|||
|
|||
class BuiltPesquisaNode(BuiltFormNode): |
|||
form_class = Pesquisa |
|||
form_for_form_class = PesquisaForm |
|||
|
|||
@register.tag |
|||
def render_built_form(parser, token): |
|||
""" |
|||
render_build_form takes one argument in one of the following formats: |
|||
|
|||
{% render_build_form form_instance %} |
|||
{% render_build_form form=form_instance %} |
|||
{% render_build_form id=form_instance.id %} |
|||
{% render_build_form slug=form_instance.slug %} |
|||
|
|||
""" |
|||
try: |
|||
_, arg = token.split_contents() |
|||
if "=" not in arg: |
|||
arg = "form=" + arg |
|||
name, value = arg.split("=", 1) |
|||
if name not in ("form", "id", "slug"): |
|||
raise ValueError |
|||
except ValueError: |
|||
e = () |
|||
raise template.TemplateSyntaxError(render_built_form.__doc__) |
|||
return BuiltPesquisaNode(name, value) |
@ -0,0 +1,3 @@ |
|||
from django.test import TestCase |
|||
|
|||
# Create your tests here. |
@ -0,0 +1,9 @@ |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.conf.urls import patterns, url |
|||
|
|||
|
|||
urlpatterns = patterns("apps.pesquisas.views", |
|||
url(r"(?P<slug>.*)/sent/$", "form_sent", name="form_sent"), |
|||
url(r"(?P<slug>.*)/$", "form_detail", name="form_detail"), |
|||
) |
@ -0,0 +1,15 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
from sigi.forms_builder.forms.views import FormDetail, FormSent |
|||
from sigi.apps.pesquisas.models import Pesquisa |
|||
from sigi.apps.pesquisas.forms import PesquisaForm |
|||
|
|||
class PesquisaDetail(FormDetail): |
|||
form_class = Pesquisa |
|||
form_for_form_class = PesquisaForm |
|||
|
|||
class PesquisaSent(FormSent): |
|||
form_class = Pesquisa |
|||
|
|||
form_detail = PesquisaDetail.as_view() |
|||
form_sent = PesquisaSent.as_view() |
Loading…
Reference in new issue