Clean up and other fixes for Survey modules.
authorDaniel Diniz <ajaksu@gmail.com>
Thu, 02 Jul 2009 10:33:58 +0200
changeset 2478 985fd974e095
parent 2477 e5629995d118
child 2479 b83c9b1ea0e1
Clean up and other fixes for Survey modules. Reviewed by: Lennard de Rijk
app/soc/logic/models/survey_record.py
app/soc/views/helper/surveys.py
app/soc/views/models/grading_project_survey.py
app/soc/views/models/project_survey.py
app/soc/views/models/survey.py
--- a/app/soc/logic/models/survey_record.py	Wed Jul 01 21:53:20 2009 +0200
+++ b/app/soc/logic/models/survey_record.py	Thu Jul 02 10:33:58 2009 +0200
@@ -111,25 +111,3 @@
 logic = Logic()
 project_logic = ProjectLogic()
 grading_logic = GradingProjectLogic()
-
-
-def updateSurveyRecord(user, survey, survey_record, fields):
-  """Create a new survey record, or get an existing one.
-
-  params:
-    user = user taking survey
-    survey = survey entity
-    survey_record = existing record, if one exists
-    fields = submitted responses to survey fields
-  """
-
-  # TODO(ajaksu) We should use class information here, but being careful about
-  # compatibility with existent records should the class change.
-  if hasattr(survey_record, 'grade'):
-    record_logic = grading_logic
-  elif hasattr(survey_record, 'project'):
-    record_logic = grading_logic
-  else:
-    record_logic = logic
-
-  return record_logic.updateSurveyRecord(user, survey, survey_record, fields)
--- a/app/soc/views/helper/surveys.py	Wed Jul 01 21:53:20 2009 +0200
+++ b/app/soc/views/helper/surveys.py	Thu Jul 02 10:33:58 2009 +0200
@@ -25,8 +25,10 @@
 
 
 from itertools import chain
+import csv
 import datetime
 import logging
+import StringIO
 
 from google.appengine.ext.db import djangoforms
 
@@ -666,3 +668,96 @@
     survey_form.fields.insert(field_count + 1, 'grade', gradeField)
 
   return survey_form
+
+
+class HelperForm(object):
+  """Thin wrapper for adding values to params['edit_form'].fields.
+  """
+
+  def __init__(self, form=None):
+    """Store the edit_form.
+    """
+
+    self.form = form
+
+  def __call__(self, instance=None):
+    """Transparently instantiate and add initial values to the edit_form.
+    """
+
+    form = self.form(instance=instance)
+    form.fields['created_by'].initial = instance.author.name
+    form.fields['last_modified_by'].initial = instance.modified_by.name
+    form.fields['doc_key_name'].initial = instance.key().id_or_name()
+    return form
+
+
+def _get_csv_header(sur):
+  """CSV header helper, needs support for comment lines in CSV.
+
+  Args:
+      sur: Survey entity
+  """
+
+  tpl = '# %s: %s\n'
+
+  # add static properties
+  fields = ['# Melange Survey export for \n#  %s\n#\n' % sur.title]
+  fields += [tpl % (k,v) for k,v in sur.toDict().items()]
+  fields += [tpl % (f, str(getattr(sur, f))) for f in PLAIN.split()]
+  fields += [tpl % (f, str(getattr(sur, f).link_id)) for f in FIELDS.split()]
+  fields.sort()
+
+  # add dynamic properties
+  fields += ['#\n#---\n#\n']
+  dynamic = sur.survey_content.dynamic_properties()
+  dynamic = [(prop, getattr(sur.survey_content, prop)) for prop in dynamic]
+  fields += [tpl % (k,v) for k,v in sorted(dynamic)]
+
+  # add schema
+  fields += ['#\n#---\n#\n']
+  schema =  sur.survey_content.schema
+  indent = '},\n#' + ' ' * 9
+  fields += [tpl % ('Schema', schema.replace('},', indent)) + '#\n']
+
+  return ''.join(fields).replace('\n', '\r\n')
+
+
+def _get_records(recs, props):
+  """Fetch properties from SurveyRecords for CSV export.
+  """
+
+  records = []
+  props = props[1:]
+  for rec in recs:
+    values = tuple(getattr(rec, prop, None) for prop in props)
+    leading = (rec.user.link_id,)
+    records.append(leading + values)
+  return records
+
+
+def to_csv(survey):
+  """CSV exporter.
+  """
+
+  # get header and properties
+  header = _get_csv_header(survey)
+  leading = ['user', 'created', 'modified']
+  properties = leading + survey.survey_content.orderedProperties()
+
+  try:
+    first = survey.getRecords().run().next()
+  except StopIteration:
+    # bail out early if survey_records.run() is empty
+    return header, survey.link_id
+
+  # generate results list
+  recs = survey.getRecords().run()
+  recs = _get_records(recs, properties)
+
+  # write results to CSV
+  output = StringIO.StringIO()
+  writer = csv.writer(output)
+  writer.writerow(properties)
+  writer.writerows(recs)
+
+  return header + output.getvalue(), survey.link_id
--- a/app/soc/views/models/grading_project_survey.py	Wed Jul 01 21:53:20 2009 +0200
+++ b/app/soc/views/models/grading_project_survey.py	Thu Jul 02 10:33:58 2009 +0200
@@ -23,6 +23,7 @@
 
 
 from soc.logic import dicts
+from soc.logic.models.survey import GRADES
 from soc.logic.models.survey import grading_logic as grading_survey_logic
 from soc.views.helper import access
 from soc.views.helper import decorators
@@ -60,6 +61,23 @@
 
     super(View, self).__init__(params=params)
 
+  # TODO: work on grade activation
+  def activate(self, request, **kwargs):
+    """This is a hack to support the 'Enable grades' button.
+    """
+    self.activateGrades(request)
+    redirect_path = request.path.replace('/activate/', '/edit/') + '?activate=1'
+    return http.HttpResponseRedirect(redirect_path)
+
+
+  def activateGrades(self, request, **kwargs):
+    """Updates SurveyRecord's grades for a given Survey.
+    """
+    survey_key_name = survey_logic.getKeyNameFromPath(request.path)
+    survey = Survey.get_by_key_name(survey_key_name)
+    survey_logic.activateGrades(survey)
+    return
+
 
 view = View()
 
@@ -71,6 +89,5 @@
 public = decorators.view(view.public)
 export = decorators.view(view.export)
 pick = decorators.view(view.pick)
-activate = decorators.view(view.activate)
 results = decorators.view(view.viewResults)
 json = decorators.view(view.exportSerialized)
--- a/app/soc/views/models/project_survey.py	Wed Jul 01 21:53:20 2009 +0200
+++ b/app/soc/views/models/project_survey.py	Thu Jul 02 10:33:58 2009 +0200
@@ -56,7 +56,7 @@
 
     new_params['name'] = "Project Survey"
 
-    new_params['extra_dynaexclude'] = ['prefix', 'taking_access']
+    new_params['extra_dynaexclude'] = ['taking_access']
 
     params = dicts.merge(params, new_params)
 
@@ -73,6 +73,5 @@
 public = decorators.view(view.public)
 export = decorators.view(view.export)
 pick = decorators.view(view.pick)
-activate = decorators.view(view.activate)
 results = decorators.view(view.viewResults)
 json = decorators.view(view.exportSerialized)
--- a/app/soc/views/models/survey.py	Wed Jul 01 21:53:20 2009 +0200
+++ b/app/soc/views/models/survey.py	Thu Jul 02 10:33:58 2009 +0200
@@ -23,10 +23,8 @@
   '"Lennard de Rijk" <ljvderijk@gmail.com>',
   ]
 
-import csv
 import datetime
 import re
-import StringIO
 import string
 
 from google.appengine.ext import db
@@ -37,7 +35,6 @@
 
 from soc.logic import cleaning
 from soc.logic import dicts
-from soc.logic.models.survey import GRADES
 from soc.logic.models.survey import logic as survey_logic
 from soc.logic.models.user import logic as user_logic
 from soc.models.survey import Survey
@@ -129,7 +126,7 @@
 
     new_params['export_content_type'] = 'text/text'
     new_params['export_extension'] = '.csv'
-    new_params['export_function'] = to_csv
+    new_params['export_function'] = surveys.to_csv
     new_params['delete_redirect'] = '/'
     new_params['list_key_order'] = [
         'link_id', 'scope_path', 'name', 'short_name', 'title',
@@ -137,6 +134,7 @@
 
     new_params['edit_template'] = 'soc/survey/edit.html'
     new_params['create_template'] = 'soc/survey/edit.html'
+    new_params['public_template'] = 'soc/survey/public.html'
     new_params['take_template'] = 'soc/survey/take.html'
 
     # TODO which one of these are leftovers from Document?
@@ -253,7 +251,8 @@
     if not entity:
       # new Survey
       if 'serialized' in request.POST:
-        fields, schema, survey_fields = self.importSerialized(request, fields, user)
+        fields, schema, survey_fields = self.importSerialized(request, fields,
+                                                              user)
       fields['author'] = user
     else:
       fields['author'] = entity.author
@@ -440,27 +439,6 @@
     Builds the SurveyForm that represents the Survey question contents.
     """
 
-    # TODO(ajaksu) Move CHOOSE_A_PROJECT_FIELD and CHOOSE_A_GRADE_FIELD
-    # to template.
-
-    CHOOSE_A_PROJECT_FIELD = """<tr class="role-specific">
-    <th><label>Choose Project:</label></th>
-    <td>
-      <select disabled="TRUE" id="id_survey__NA__selection__project"
-        name="survey__1__selection__see">
-          <option>Survey Taker's Projects For This Program</option></select>
-     </td></tr>
-     """
-
-    CHOOSE_A_GRADE_FIELD = """<tr class="role-specific">
-    <th><label>Assign Grade:</label></th>
-    <td>
-      <select disabled=TRUE id="id_survey__NA__selection__grade"
-       name="survey__1__selection__see">
-        <option>Pass/Fail</option>
-      </select></td></tr>
-    """
-
     self._entity = entity
     survey_content = entity.survey_content
     user = user_logic.getForCurrentAccount()
@@ -468,7 +446,6 @@
     project = None
     survey_record = None
 
-
     survey_form = surveys.SurveyForm(survey_content=survey_content,
                                      this_user=user, project=project,
                                      survey_logic=params['logic'],
@@ -476,16 +453,11 @@
                                      editing=True, read_only=False)
     survey_form.getFields()
 
-
-    # activate grades flag -- TODO: Can't configure notice on edit page
-    if request._get.get('activate'):
-      context['notice'] = "Evaluation Grades Have Been Activated"
-
     local = dict(survey_form=survey_form, question_types=QUESTION_TYPES,
                 survey_h=entity.survey_content)
     context.update(local)
 
-    params['edit_form'] = HelperForm(params['edit_form'])
+    params['edit_form'] = surveys.HelperForm(params['edit_form'])
     if entity.survey_end and datetime.datetime.now() > entity.survey_end:
       # are we already passed the survey_end?
       context["passed_survey_end"] = True
@@ -737,158 +709,6 @@
 
     return entity, context
 
-  def getMenusForScope(self, entity, params):
-    """List featured surveys if after the survey_start date and before survey_end.
-    """
-
-    # only list surveys for registered users
-    user = user_logic.getForCurrentAccount()
-    if not user:
-      return []
-
-    filter = {
-        'prefix' : params['url_name'],
-        'scope_path': entity.key().id_or_name(),
-        'is_featured': True,
-        }
-
-    entities = self._logic.getForFields(filter)
-    submenus = []
-    now = datetime.datetime.now()
-
-    # cache ACL
-    survey_rights = {}
-
-    # add a link to all featured documents
-    for entity in entities:
-
-      # only list those surveys the user can read
-      if entity.read_access not in survey_rights:
-
-        params = dict(prefix=entity.prefix, scope_path=entity.scope_path,
-                      link_id=entity.link_id, user=user)
-
-        # TODO(ajaksu) use access.Checker.checkIsSurveyReadable
-        checker = access.rights_logic.Checker(entity.prefix)
-        roles = checker.getMembership(entity.read_access)
-        rights = self._params['rights']
-        can_read = access.Checker.hasMembership(rights, roles, params)
-
-        # cache ACL for a given entity.read_access
-        survey_rights[entity.read_access] = can_read
-
-        if not can_read:
-          pass#continue
-
-      elif not survey_rights[entity.read_access]:
-        pass#continue
-
-      # omit if either before survey_start or after survey_end
-      if entity.survey_start and entity.survey_start > now:
-        pass#continue
-
-      if entity.survey_end and entity.survey_end < now:
-        pass#continue
-
-      taken_status = ""
-      taken_status = "(new)"
-      #TODO only if a document is readable it might be added
-      submenu = (redirects.getPublicRedirect(entity, self._params),
-      'Survey ' +  taken_status + ': ' + entity.short_name,
-      'show')
-
-      submenus.append(submenu)
-    return submenus
-
-class HelperForm(object):
-  """Thin wrapper for adding values to params['edit_form'].fields.
-  """
-
-  def __init__(self, form=None):
-    """Store the edit_form.
-    """
-
-    self.form = form
-
-  def __call__(self, instance=None):
-    """Transparently instantiate and add initial values to the edit_form.
-    """
-
-    form = self.form(instance=instance)
-    form.fields['created_by'].initial = instance.author.name
-    form.fields['last_modified_by'].initial = instance.modified_by.name
-    form.fields['doc_key_name'].initial = instance.key().id_or_name()
-    return form
-
-
-def _get_csv_header(sur):
-  """CSV header helper, needs support for comment lines in CSV.
-  """
-
-  tpl = '# %s: %s\n'
-
-  # add static properties
-  fields = ['# Melange Survey export for \n#  %s\n#\n' % sur.title]
-  fields += [tpl % (k,v) for k,v in sur.toDict().items()]
-  fields += [tpl % (f, str(getattr(sur, f))) for f in PLAIN.split()]
-  fields += [tpl % (f, str(getattr(sur, f).link_id)) for f in FIELDS.split()]
-  fields.sort()
-
-  # add dynamic properties
-  fields += ['#\n#---\n#\n']
-  dynamic = sur.survey_content.dynamic_properties()
-  dynamic = [(prop, getattr(sur.survey_content, prop)) for prop in dynamic]
-  fields += [tpl % (k,v) for k,v in sorted(dynamic)]
-
-  # add schema
-  fields += ['#\n#---\n#\n']
-  schema =  sur.survey_content.schema
-  indent = '},\n#' + ' ' * 9
-  fields += [tpl % ('Schema', schema.replace('},', indent)) + '#\n']
-
-  return ''.join(fields).replace('\n', '\r\n')
-
-
-def _get_records(recs, props):
-  """Fetch properties from SurveyRecords for CSV export.
-  """
-
-  records = []
-  props = props[1:]
-  for rec in recs:
-    values = tuple(getattr(rec, prop, None) for prop in props)
-    leading = (rec.user.link_id,)
-    records.append(leading + values)
-  return records
-
-
-def to_csv(survey):
-  """CSV exporter.
-  """
-
-  # get header and properties
-  header = _get_csv_header(survey)
-  leading = ['user', 'created', 'modified']
-  properties = leading + survey.survey_content.orderedProperties()
-
-  try:
-    first = survey.survey_records.run().next()
-  except StopIteration:
-    # bail out early if survey_records.run() is empty
-    return header, survey.link_id
-
-  # generate results list
-  recs = survey.survey_records.run()
-  recs = _get_records(recs, properties)
-
-  # write results to CSV
-  output = StringIO.StringIO()
-  writer = csv.writer(output)
-  writer.writerow(properties)
-  writer.writerows(recs)
-
-  return header + output.getvalue(), survey.link_id
-
 
 view = View()