Skip to content
Snippets Groups Projects
Commit bdd7fbfc authored by Alice Heaton's avatar Alice Heaton :speech_balloon:
Browse files

Implement the add&edit form. The actual action (add/edit/delete) are not yet wired in.

parent 32830701
No related branches found
No related tags found
2 merge requests!37Items can be edited when form is submitted,!36Edit item frontend
......@@ -43,6 +43,7 @@ python-dateutil==2.4.2
#django-recaptcha
#django-registration
django-tables2==1.0.4
django-widget-tweaks==1.4.1
## ---------Development
#django-extensions
......
from django import forms
import transport
from hid.constants import ITEM_TYPE_CATEGORY
class AddEditItemForm(forms.Form):
id = forms.CharField(
widget=forms.HiddenInput,
required=True
)
body = forms.CharField(
widget=forms.Textarea,
required=True
)
timestamp = forms.DateField(required=True)
next = forms.CharField(
widget=forms.HiddenInput,
required=True
)
def __init__(self, item_type, *args, **kwargs):
""" Add extra fields depending on item_type """
super(AddEditItemForm, self).__init__(*args, **kwargs)
if item_type in ITEM_TYPE_CATEGORY:
terms = transport.terms.list(
taxonomy=ITEM_TYPE_CATEGORY[item_type]
)
choices = (('', '-----'),)
choices += tuple((t['name'], t['name']) for t in terms)
self.fields['category'] = forms.ChoiceField(
choices=choices
)
# The template already has support for optional fields:
# 'region' (select)
# 'tags' (text input)
{% extends "base_side.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load widget_tweaks %}
{% block maincontent %}
<h1 class="page-header">
<span class="fa fa-pencil fa-fw"></span>
{% trans "View &amp; Edit: " %}
<span class="item-type">{{ item_type_label }}</span>
</h1>
<div class="col-lg-8 col-lg-offset-2">
<form id="single-item-form" role="form" method="POST">
{% csrf_token %}
{{ form.id }}
{{ form.next }}
<div class="panel panel-default"><div class="panel-body">
<div class="col-xs-12"><div class="row">
<div class="col-xs-12">
<p class="item-meta-info">
{% trans "Added on " %}
<span class="item-meta item-date-added">{{ item.created }}</span>
{% trans "Updated on " %}
<span class="item-meta item-date-updated">{{ item.last_modified }}</span>
</p>
</div>
<div class="col-xs-12">
<div class="col-xs-12 input-group form-group item-text">
<label>
{{ item_type_label }}
<span class="item-id">{{ item.id }}</span>
</label>
{{ form.body|add_class:'form-control'|attr:"rows:4"|attr:"placeholder:Type your question text here" }}
</div>
{% if form.tags %}
<div class="col-xs-12 form-group input-group item-tags">
<span class="input-group-addon"><span class="fa fa-tags fa-fw"></span> {% trans "Tags" %}</span>
{{ form.tags|add_class:'form-control'|attr:'placeholder:type and hit enter'|attr:'data-role:tagsinput' }}
</div>
{% endif %}
</div>
<div class="col-lg-12 col-md-12">
<div class="col-sm-{{ option_row_width }} col-xs-12 pull-left form-group input-group item-reported-date">
<label>{% trans "Reported date" %}</label>
{{ form.timestamp|add_class:'form-control'|attr:"placeholder:yyyy-mm-dd"|attr:"aria-describedby:basic-addon1" }}
</div>
{% if form.category %}
<div class="col-sm-{{ option_row_width }} col-xs-12 pull-left form-group input-group item-category">
<label>{{ item_type_label}} {% trans "type" %}</label>
<div class="selectContainer">
{{ form.category|add_class:'form-control' }}
</div>
</div>
{% endif %}
{% if form.region %}
<div class="col-sm-{{ option_row_width }} col-xs-12 pull-left form-group input-group item-region">
<label>{% trans "Region" %}</label>
<div class="selectContainer">
{{ form.region|add_class:'form-control' }}
</div>
</div>
{% endif %}
</div>
</div></div>
<div class="col-xs-12">
<div class="form-group btn-group pull-left">
{% bootstrap_button "Delete" button_type="submit" name="action" value="delete" button_class="btn btn-danger btn-sm" %}
</div>
<div class="form-group btn-group pull-right">
{% bootstrap_button "Cancel" button_type="submit" name="action" value="cancel" button_class="btn btn-sm" %}
{% bootstrap_button "Update" button_type="submit" name="action" value="update" button_class="btn btn-sm btn-success" %}
</div>
</div>
</div></div>
</form>
</div>
{% endblock maincontent %}
......@@ -5,7 +5,7 @@ from dashboard.views import DashboardView
from .views.upload_spreadsheet import UploadSpreadsheetView
from .views.list_sources import ListSources
from .views.item import AddEditItem
from .views.item import AddEditItemView
from hid.tabs.view_and_edit_table import view_and_edit_table_form_process_items
......@@ -14,7 +14,6 @@ urlpatterns = patterns('',
url(r'^sources/(?P<label>\w+)/$', login_required(ListSources.as_view()), name='sources-edit'),
url(r'^sources/$', login_required(ListSources.as_view()), name='sources'),
url(r'^process-items/$', login_required(view_and_edit_table_form_process_items), name="data-view-process"),
url(r'^item/(?P<id>\d+)/edit/$', login_required(AddEditItem.as_view())),
url(r'^item/new/$', login_required(AddEditItem.as_view())),
url(r'^item/(?P<item_id>\d+)/edit/$', login_required(AddEditItemView.as_view())),
url(r'^$', login_required(DashboardView.as_view()), name='dashboard'),
)
from django.views.generic.base import TemplateView
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from django.views.generic.edit import FormView
from transport.items import list
from ..forms.item import AddEditItemForm
from ..constants import ITEM_TYPE_CATEGORY
class AddEditItem(TemplateView):
template_name = "hid/item.html"
class AddEditItemView(FormView):
template_name = "hid/add_edit_item.html"
form_class = AddEditItemForm
def _initialize_item(self, item_id):
""" Initialize the view's item from the given item id.
This has a side effect of initializing:
self.item to the item object (or None)
self.item_type to the item type, if defined (None otherwise)
self.item_terms to a dictionary of taxonomy to list of terms
Args:
item_id (int): Item id
"""
self.item = None
self.item_type = None
self.item_terms = None
if not item_id:
return
# TODO: Use the single item get API when implemented
items = list(id=item_id)
if len(items) == 0:
return
self.item = items[0]
self.item_terms = {}
for term in self.item['terms']:
taxonomy = term['taxonomy']
if taxonomy == 'item-types':
self.item_type = term
if taxonomy not in self.item_terms:
self.item_terms[taxonomy] = []
self.item_terms[taxonomy].append(term)
def get(self, request, *args, **kwargs):
""" get request handler
If the URL defines an item_id, we load the corresponding item
to make it available for forms.
"""
self._initialize_item(kwargs.get('item_id'))
return super(AddEditItemView, self).get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
""" post request handler
If the URL defines an item_id, we load the corresponding item
to make it available for forms.
We handle cancel and delete here, as the form doesn't it to be
valid for those.
"""
self._initialize_item(kwargs.get('item_id'))
if 'cancel' in self.request.POST['action']:
return self._response(
self.request.POST['next'],
messages.INFO,
_('No action performed')
)
if 'delete' in self.request.POST['action']:
return self._response(
self.request.POST['next'],
messages.ERROR,
_('Delete item not implemented')
)
return super(AddEditItemView, self).post(request, *args, **kwargs)
def get_initial(self):
""" Return the form object's initial values for the current item """
if self.item is None:
return {
'id': 0
}
initial = {
'id': self.item['id'],
'body': self.item['body'],
'timestamp': self.item['timestamp'],
'next': self.request.GET.get('next', self.request.path)
}
taxonomy = ITEM_TYPE_CATEGORY.get(self.item_type['name'])
if (taxonomy and taxonomy in self.item_terms
and len(self.item_terms[taxonomy]) > 0):
initial['category'] = self.item_terms[taxonomy][0]['name']
return initial
def get_form(self, form_class):
""" Return the form object to be used """
if self.item_type:
item_type = self.item_type['name']
else:
# TODO: When implementing ADD mode, we'll need to use the URL to
# get the default
item_type = None
return form_class(item_type, **self.get_form_kwargs())
def get_context_data(self, **kwargs):
ctx = super(AddEditItem, self).get_context_data(**kwargs) or {}
return ctx
""" Get the form's context data
We invoke FormView's get_context_data and add the current
item.
"""
context = super(AddEditItemView, self).get_context_data(**kwargs)
# Add item to the context
context['item'] = self.item
# Add the type label to the context
# TODO: When implementing ADD mode, we'll need to use the URL to
# get the default.
context['item_type_label'] = '?'
if self.item_type:
context['item_type_label'] = self.item_type['long_name']
# Add the width of the option row to the context
option_row_widget_count = 1 # We always have 'created'
if 'category' in kwargs['form'].fields:
option_row_widget_count += 1
if 'region' in kwargs['form'].fields:
option_row_widget_count += 1
context['option_row_width'] = 12 / option_row_widget_count
return context
def form_valid(self, form):
""" Form submit handler """
# if self.item_type:
# item_type = self.item_type['long_name']
# else:
# item_type = 'Item'
# msg = _("%s %d successfully updated.") % (
# item_type,
# int(form.cleaned_data['id'])
# )
# return self._response(
# form.cleaned_data['next'],
# messages.SUCCESS,
# msg
# )
return self._response(
form.cleaned_data['next'],
messages.ERROR,
_('Update item not implemented')
)
def _response(self, url, message_type, message):
""" Log a message and return an HTTP Response
Args:
url (str): URL to redirect to
message_type (str): Message type to log (from message.INFO, etc.)
message (str): Message to log
Returns:
HttpResponseRedirect: Response object
"""
messages.add_message(self.request, message_type, message)
return HttpResponseRedirect(url)
......@@ -137,7 +137,8 @@ THIRD_PARTY_APPS = (
'rest_framework',
'django_tables2',
'djangojs',
'django_assets'
'django_assets',
'widget_tweaks'
)
LOCAL_APPS = (
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment