app/soc/views/helper/surveys.py
changeset 2502 2e096acc8720
parent 2501 d612b48e6e12
child 2506 c98bf890156e
--- a/app/soc/views/helper/surveys.py	Fri Jul 03 14:19:23 2009 +0200
+++ b/app/soc/views/helper/surveys.py	Fri Jul 03 14:35:03 2009 +0200
@@ -46,6 +46,26 @@
 from soc.models.survey import SurveyContent
 
 
+# TODO(ajaksu) add this to template
+REQUIRED_COMMENT_TPL = """
+  <label for="required_for_{{ name }}">Required</label>
+  <select id="required_for_{{ name }}" name="required_for_{{ name }}">
+    <option value="True" {% if is_required %} selected='selected' {% endif %}
+     >True</option>
+    <option value="False" {% if not is_required %} selected='selected'
+     {% endif %}>False</option>
+  </select><br/>
+
+  <label for="comment_for_{{ name }}">Allow Comments</label>
+  <select id="comment_for_{{ name }}" name="comment_for_{{ name }}">
+    <option value="True" {% if has_comment %} selected='selected' {% endif %}
+     >True</option>
+    <option value="False" {% if not has_comment %} selected='selected'
+     {% endif %}>False</option>
+  </select><br/>
+"""
+
+
 class SurveyForm(djangoforms.ModelForm):
   """Main SurveyContent form.
 
@@ -161,12 +181,17 @@
 
       # find correct field type
       addField = self.fields_map[schema.getType(field)]
-      addField(field, value, extra_attrs, schema, label=label, comment=comment)
+
+      # check if question is required, it's never required when editing
+      required = not self.editing and schema.getRequired(field)
+      kwargs = dict(label=label, req=required)
 
-      # handle comments
-      comment_name = COMMENT_PREFIX + field
-      if comment_name in post_dict or hasattr(self.survey_record, comment_name):
-        self.data[comment_name] = comment
+      # add new field
+      addField(field, value, extra_attrs, schema, **kwargs)
+
+      # handle comments if question allows them
+      if schema.getHasComment(field):
+        self.data[COMMENT_PREFIX + field] = comment
         self.addCommentField(field, comment, extra_attrs, tip='Add a comment.')
 
     return self.insertFields()
@@ -189,7 +214,7 @@
                              self.survey_fields[property])
     return self.fields
 
-  def addLongField(self, field, value, attrs, schema, req=False, label='',
+  def addLongField(self, field, value, attrs, schema, req=True, label='',
                    tip='', comment=''):
     """Add a long answer fields to this form.
 
@@ -204,7 +229,11 @@
       comment: initial comment value for field
     """
 
-    widget = widgets.Textarea(attrs=attrs)
+    # use a widget that allows setting required and comments
+    has_comment = schema.getHasComment(field)
+    is_required = schema.getRequired(field)
+    widget = LongTextarea(is_required, has_comment, attrs=attrs,
+                          editing=self.editing)
 
     if not tip:
       tip = 'Please provide a long answer to this question.'
@@ -230,7 +259,12 @@
     """
 
     attrs['class'] = "text_question"
-    widget = widgets.TextInput(attrs=attrs)
+
+    # use a widget that allows setting required and comments
+    has_comment = schema.getHasComment(field)
+    is_required = schema.getRequired(field)
+    widget = ShortTextInput(is_required, has_comment, attrs=attrs,
+                          editing=self.editing)
 
     if not tip:
       tip = 'Please provide a short answer to this question.'
@@ -298,8 +332,6 @@
     if self.survey_record and isinstance(value, basestring):
       # pass value as 'initial' so MultipleChoiceField renders checked boxes
       value = value.split(',')
-    else:
-      value = None
 
     these_choices = [(v,v) for v in getattr(self.survey_content, field)]
     if not tip:
@@ -365,6 +397,18 @@
   def getType(self, field):
     return self.schema[field]["type"]
 
+  def getRequired(self, field):
+    """Check whether survey question is required.
+    """
+
+    return self.schema[field]["required"]
+
+  def getHasComment(self, field):
+    """Check whether survey question allows adding a comment.
+    """
+
+    return self.schema[field]["has_comment"]
+
   def getRender(self, field):
     return self.schema[field]["render"]
 
@@ -375,7 +419,9 @@
     if editing:
       kind = self.getType(field)
       render = self.getRender(field)
-      widget = UniversalChoiceEditor(kind, render)
+      is_required = self.getRequired(field)
+      has_comment = self.getHasComment(field)
+      widget = UniversalChoiceEditor(kind, render, is_required, has_comment)
     else:
       widget = WIDGETS[self.schema[field]['render']](attrs=attrs)
     return widget
@@ -401,7 +447,15 @@
   Allows adding and removing options, re-ordering and editing option text.
   """
 
-  def __init__(self, kind, render, attrs=None, choices=()):
+  def __init__(self, kind, render, is_required, has_comment, attrs=None,
+               choices=()):
+    """
+    params:
+      kind: question kind (one of selection, pick_multi or pick_quant)
+      render: question widget (single_select, multi_checkbox or quant_radio)
+      is_required: bool, controls selection in the required_for field
+      has_comments: bool, controls selection in the has_comments field
+    """
 
     self.attrs = attrs or {}
 
@@ -411,9 +465,14 @@
     self.choices = list(choices)
     self.kind = kind
     self.render_as = render
+    self.is_required = is_required
+    self.has_comment = has_comment
+
 
   def render(self, name, value, attrs=None, choices=()):
-    """ renders UCE widget
+    """Render UCE widget.
+
+    Option reordering, editing, addition and deletion are added here.
     """
 
     if value is None:
@@ -433,6 +492,12 @@
         is_radio_buttons=selected * (self.render_as == 'quant_radio'),
         )
 
+    # set required and has_comment selects
+    context.update(dict(
+        is_required = self.is_required,
+        has_comment = self.has_comment,
+        ))
+
     str_value = forms.util.smart_unicode(value) # normalize to string.
     chained_choices = enumerate(chain(self.choices, choices))
     choices = {}
@@ -472,6 +537,86 @@
     super(PickQuantField, self).__init__(*args, **kwargs)
 
 
+class LongTextarea(widgets.Textarea):
+  """Set whether long question is required or allows comments.
+  """
+
+  def __init__(self, is_required, has_comment, attrs=None, editing=False):
+    """Initialize widget and store editing mode.
+
+    params:
+      is_required: bool, controls selection in the 'required' extra field
+      has_comments: bool, controls selection in the 'has_comment' extra field
+      editing: bool, controls rendering as plain textarea or with extra fields
+    """
+
+    self.editing = editing
+    self.is_required = is_required
+    self.has_comment = has_comment
+
+    super(LongTextarea, self).__init__(attrs)
+
+  def render(self, name, value, attrs=None):
+    """Render plain textarea or widget with extra fields.
+
+    Extra fields are 'required' and 'has_comment'.
+    """
+
+    # plain text area
+    output = super(LongTextarea, self).render(name, value, attrs)
+
+    if self.editing:
+      # add 'required' and 'has_comment' fields
+      context = dict(name=name, is_required=self.is_required,
+                     has_comment=self.has_comment)
+      template = loader.get_template_from_string(REQUIRED_COMMENT_TPL)
+      rendered = template.render(context=loader.Context(dict_=context))
+      output =  rendered + output
+
+      output = '<fieldset>' + output + '</fieldset>'
+    return output
+
+
+class ShortTextInput(widgets.TextInput):
+  """Set whether short answer question is required or allows comments.
+  """
+
+  def __init__(self, is_required, has_comment, attrs=None, editing=False):
+    """Initialize widget and store editing mode.
+
+    params:
+      is_required: bool, controls selection in the 'required' extra field
+      has_comments: bool, controls selection in the 'has_comment' extra field
+      editing: bool, controls rendering as plain text input or with extra fields
+    """
+
+    self.editing = editing
+    self.is_required = is_required
+    self.has_comment = has_comment
+
+    super(ShortTextInput, self).__init__(attrs)
+
+  def render(self, name, value, attrs=None):
+    """Render plain text input or widget with extra fields.
+
+    Extra fields are 'required' and 'has_comment'.
+    """
+
+    # plain text area
+    output = super(ShortTextInput, self).render(name, value, attrs)
+
+    if self.editing:
+      # add 'required' and 'has_comment' fields
+      context = dict(name=name, is_required=self.is_required,
+                     has_comment=self.has_comment)
+      template = loader.get_template_from_string(REQUIRED_COMMENT_TPL)
+      rendered = template.render(context=loader.Context(dict_=context))
+      output =  rendered + output
+
+      output = '<fieldset>' + output + '</fieldset>'
+    return output
+
+
 class PickOneSelect(forms.Select):
   """Stub for customizing the single choice select widget.
   """
@@ -664,8 +809,8 @@
     response_dict[name] = value
 
     # handle comments
-    comment_name = COMMENT_PREFIX + name
-    if comment_name in post_dict:
+    if schema.getHasComment(name):
+      comment_name = COMMENT_PREFIX + name
       comment = post_dict.get(comment_name)
       if comment:
         response_dict[comment_name] = comment