pytask/taskapp/views/task.py
author Madhusudan.C.S <madhusudancs@gmail.com>
Tue, 01 Feb 2011 19:38:41 +0530
changeset 550 a606a40584f7
parent 545 3a86d85333a3
child 556 a0e57ca7cf56
permissions -rwxr-xr-x
Base views should take keyword arguments and should use them for URLs.

"""Module containing the views for all the task related activities.

If there is something common to all other views. They sit here, here
even if there nothing relevant to tasks alone since task is the basis
for everything else.
"""


__authors__ = [
    '"Nishanth Amuluru" <nishanth@fossee.in>',
    '"Madhusudan.C.S" <madhusudancs@fossee.in>',
    ]


from datetime import datetime

from django import shortcuts
from django import http
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.utils import simplejson as json
from django.utils.translation import ugettext

from tagging.models import Tag
from tagging.models import TaggedItem

from pytask.helpers import exceptions
from pytask.views import show_msg

from pytask.profile import models as profile_models

from pytask.taskapp import forms as taskapp_forms
from pytask.taskapp import models as taskapp_models


DONT_CLAIM_TASK_MSG = ugettext(
  "Please don't submit any claims for the tasks until you get an email "
  "to start claiming tasks. Please be warned that the task claim work-"
  "flow may change. So all the claims submitted before the workshop may "
  "not be valid.")

NO_EDIT_RIGHT = ugettext(
  "You are not authorized to edit this page.")


@login_required
def create_task(request):

    user = request.user
    profile = user.get_profile()

    context = {"user": user,
               "profile": profile,
              }

    context.update(csrf(request))

    can_create_task = False if (
      profile.role == profile_models.ROLES_CHOICES[3][0]) else True
    if can_create_task:
        if request.method == "POST":
            form = taskapp_forms.CreateTaskForm(request.POST)
            if form.is_valid():
                data = form.cleaned_data.copy()
                data.update({"created_by": user,
                             "creation_datetime": datetime.now(),
                            })

                task = taskapp_models.Task(**data)
                task.save()

                task_url = reverse('view_task', kwargs={'task_id': task.id})
                return shortcuts.redirect(task_url)
            else:
                context.update({'form':form})
                return shortcuts.render_to_response(
                  'task/edit.html', RequestContext(request, context))
        else:
            form = taskapp_forms.CreateTaskForm()
            context.update({'form': form})
            return shortcuts.render_to_response(
              'task/edit.html', RequestContext(request, context))
    else:
        return show_msg(user, 'You are not authorised to create a task.')

def browse_tasks(request):

    context = {}

    # TODO(disable): Disable once the tasks can be claimed
    context['uberbar_message'] = DONT_CLAIM_TASK_MSG

    open_tasks = taskapp_models.Task.objects.filter(
      status=taskapp_models.TASK_STATUS_CHOICES[1][0])
    working_tasks = taskapp_models.Task.objects.filter(
      status=taskapp_models.TASK_STATUS_CHOICES[3][0])
    comp_tasks = taskapp_models.Task.objects.filter(
      status=taskapp_models.TASK_STATUS_CHOICES[6][0])

    context.update({
      'open_tasks': open_tasks,
      'working_tasks': working_tasks,
      'comp_tasks': comp_tasks,
      })

    user = request.user
    if not user.is_authenticated():
        return shortcuts.render_to_response('task/browse.html',
                                            RequestContext(request, context))

    profile = user.get_profile()


    if profile.role in [profile_models.ROLES_CHOICES[0][0],
                        profile_models.ROLES_CHOICES[1][0]]:
        can_approve = True
    else:
        can_approve = False

    unpub_tasks = taskapp_models.Task.objects.filter(
      status=taskapp_models.TASK_STATUS_CHOICES[0][0]).exclude(
        status=taskapp_models.TASK_STATUS_CHOICES[5][0])

    if can_approve:
        context.update({'unpub_tasks': unpub_tasks})

    context.update({'user': user,
                    'profile': profile,
                   })

    return shortcuts.render_to_response('task/browse.html',
                                        RequestContext(request, context))


def view_task(request, task_id, **kwargs):
    """View to get the requested.

    Checks for authentication and add a comment if it is a post request.
    """

    context = {}

    if 'context' in kwargs:
        context.update(kwargs['context'])

    # TODO(disable): Disable once the tasks can be claimed
    context['uberbar_message'] = DONT_CLAIM_TASK_MSG

    task_url = kwargs.get(
      'task_url', reverse('view_task', kwargs={'task_id': task_id}))

    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    user = request.user

    if not user.is_authenticated():
        return shortcuts.render_to_response('task/view.html', {'task': task})

    profile = user.get_profile()

    context.update({
      'user': user,
      'profile': profile,
      'task': task,
      })

    context.update(csrf(request))

    if task.status == taskapp_models.TASK_STATUS_CHOICES[5][0]:
        return show_msg(user, 'This task no longer exists',
                        reverse('browse_tasks'), 'browse the tasks')

    if ((task.status != taskapp_models.TASK_STATUS_CHOICES[0][0] )
      or profile.role != profile_models.ROLES_CHOICES[3][0]):
        task_viewable = True
    else:
        task_viewable = False

    if not task_viewable:
        return show_msg(user, 'You are not authorised to view this task',
                        reverse('browse_tasks'), 'browse the tasks')

    reviewers = task.reviewers.all()
    is_reviewer = True if user in task.reviewers.all() else False
    comments = task.comments.filter(
      is_deleted=False).order_by('comment_datetime')

    context.update({'is_reviewer':is_reviewer,
                    'comments':comments,
                    'reviewers':reviewers,
                   })

    selected_users = task.selected_users.all()

    user_role = user.get_profile().role
    is_creator = True if user == task.created_by else False

    context['selected_users'] = selected_users

    context['is_selected'] = True if user in selected_users else False

    if (task.status == taskapp_models.TASK_STATUS_CHOICES[0][0] and
      profile.role in [profile_models.ROLES_CHOICES[0][0],
      profile_models.ROLES_CHOICES[1][0]]):
        context['can_approve'] = True
    else:
        context['can_approve'] = False

    if ((is_creator or user_role != profile_models.ROLES_CHOICES[3][0])
      and task.status in [taskapp_models.TASK_STATUS_CHOICES[0][0],
      taskapp_models.TASK_STATUS_CHOICES[1][0]]):
        context['can_edit'] = True
    else:
        context['can_edit'] = False

    if (task.status not in [taskapp_models.TASK_STATUS_CHOICES[0][0],
      taskapp_models.TASK_STATUS_CHOICES[4][0],
      taskapp_models.TASK_STATUS_CHOICES[6][0]] and is_reviewer):
        context['can_close'] = True
    else:
        context['can_close'] = False

    if task.status == taskapp_models.TASK_STATUS_CHOICES[0][0] and is_creator:
        context['can_delete'] = True
    else:
        context['can_delete'] = False

    if (task.status in [taskapp_models.TASK_STATUS_CHOICES[1][0],
      taskapp_models.TASK_STATUS_CHOICES[3][0]] and is_reviewer):
        context['can_assign_pynts'] = True
    else:
        context['can_assign_pynts'] = False

    if (task.status in [taskapp_models.TASK_STATUS_CHOICES[1][0],
      taskapp_models.TASK_STATUS_CHOICES[3][0]]):
        context['task_claimable'] = True
    else:
        context['task_claimable'] = False

    if (task.status != taskapp_models.TASK_STATUS_CHOICES[0][0] or\
      profile.role != profile_models.ROLES_CHOICES[3][0]):
        context['can_comment'] = True
    else:
        context['can_comment'] = False

    if (profile.role in [profile_models.ROLES_CHOICES[0][0],
      profile_models.ROLES_CHOICES[1][0]]):
        context['can_mod_reviewers'] = True
    else:
        context['can_mod_reviewers'] = False

    if request.method == 'POST':
        form = taskapp_forms.TaskCommentForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data['data']
            new_comment = taskapp_forms.TaskComment(
              task=task, data=data, commented_by=user,
              comment_datetime=datetime.now())
            new_comment.save()
            return shortcuts.redirect(task_url)
        else:
            context['form'] = form
            return shortcuts.render_to_response(
              'task/view.html', RequestContext(request, context))
    else:
        form = taskapp_forms.TaskCommentForm()
        context['form'] = form
        return shortcuts.render_to_response(
          'task/view.html', RequestContext(request, context))

@login_required
def edit_task(request, task_id, **kwargs):
    """ only creator gets to edit the task and that too only before it gets
    approved.
    """

    user = request.user
    profile = user.get_profile()

    task_url = kwargs.get(
      'task_url', reverse('view_task', kwargs={'task_id': task_id}))
    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    is_creator = True if user == task.created_by else False

    if ((is_creator or profile.role != profile_models.ROLES_CHOICES[3][0])
      and task.status in [taskapp_models.TASK_STATUS_CHOICES[0][0],
      taskapp_models.TASK_STATUS_CHOICES[1][0]]):
        can_edit = True 
    else:
        can_edit = False

    if not can_edit:
        raise exceptions.UnauthorizedAccess(NO_EDIT_RIGHT)

    context = {"user": user,
               "profile": profile,
               "task": task,
              }

    context.update(csrf(request))

    if request.method == "POST":
        form = taskapp_forms.EditTaskForm(request.POST, instance=task)
        if form.is_valid():
            form.save()
            return shortcuts.redirect(task_url)
        else:
            context.update({"form": form})
            return shortcuts.render_to_response(
              "task/edit.html", RequestContext(request, context))
    else:
        form = taskapp_forms.EditTaskForm(instance=task)
        context.update({"form": form})
        return shortcuts.render_to_response("task/edit.html",
                                            RequestContext(request, context))

@login_required
def approve_task(request, task_id):

    user = request.user
    profile = user.get_profile()

    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    if profile.role not in [profile_models.ROLES_CHOICES[0][0], profile_models.ROLES_CHOICES[1][0]] or task.status != taskapp_models.TASK_STATUS_CHOICES[0][0]:
        raise http.Http404

    context = {"user": user,
               "profile": profile,
               "task": task,
              }

    return shortcuts.render_to_response(
      "task/confirm_approval.html", RequestContext(request, context))

@login_required
def approved_task(request, task_id):

    user = request.user
    profile = user.get_profile()

    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    if profile.role not in [profile_models.ROLES_CHOICES[0][0], profile_models.ROLES_CHOICES[1][0]] or task.status != taskapp_models.TASK_STATUS_CHOICES[0][0]:
        raise http.Http404

    task.approved_by = user
    task.approval_datetime = datetime.now()
    task.status = taskapp_models.TASK_STATUS_CHOICES[1][0]
    task.save()

    context = {"user": user,
               "profile": profile,
               "task": task,
              }

    return shortcuts.render_to_response(
      "task/approved_task.html", RequestContext(request, context))

@login_required
def addreviewer(request, task_id):

    user = request.user
    profile = user.get_profile()

    task_url = reverse('view_task', kwargs={'task_id': task_id})
    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    can_mod_reviewers = True if profile.role in [profile_models.ROLES_CHOICES[0][0], profile_models.ROLES_CHOICES[1][0]] else False
    if not can_mod_reviewers:
        raise http.Http404

    context = {"user": user,
               "profile": profile,
               "task": task,
              }

    context.update(csrf(request))


    # This part has to be made better
    reviewer_choices = User.objects.filter(is_active=True).\
                                           exclude(reviewing_tasks__id=task_id).\
                                           exclude(claimed_tasks__id=task_id).\
                                           exclude(selected_tasks__id=task_id).\
                                           exclude(created_tasks__id=task_id)

    choices = ((a_user.id,a_user.username) for a_user in reviewer_choices)
    label = "Reviewer"

    if request.method == "POST":
        form = taskapp_forms.ChoiceForm(choices, data=request.POST, label=label)
        if form.is_valid():
            data = form.cleaned_data.copy()
            uid = data['choice']
            reviewer = User.objects.get(id=uid)

            task.reviewers.add(reviewer)
            return shortcuts.redirect(task_url)
        else:
            context.update({"form": form})
            return shortcuts.render_to_response(
              "task/addreviewer.html", RequestContext(request, context))
    else:
        form = taskapp_forms.ChoiceForm(choices, label=label)
        context.update({"form": form})
        return shortcuts.render_to_response(
          "task/addreviewer.html", RequestContext(request, context))

def view_work(request, task_id):

    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    user = request.user
    old_reports = task.reports.all()

    context = {
      'task': task,
      'old_reports': old_reports,
      }

    if not user.is_authenticated():
        return shortcuts.render_to_response(
          "task/view_work.html", RequestContext(request, context))

    profile = user.get_profile()

    context.update({"user": user,
                    "profile": profile,
                   })

    context.update(csrf(request))

    working_users = task.selected_users.all()
    is_working = True if user in working_users else False

    context.update({"is_working": is_working})

    return shortcuts.render_to_response("task/view_work.html",
                                        RequestContext(request, context))

@login_required
def view_report(request, report_id):

    report = shortcuts.get_object_or_404(taskapp_models.WorkReport,
                                         pk=report_id)

    user = request.user
    context = {"report": report,
               "user": user,
              }

    if not user.is_authenticated():
        return shortcuts.render_to_response(
          "task/view_report.html", RequestContext(request, context))

    profile = user.get_profile()

    context.update({"profile": profile})
    return shortcuts.render_to_response("task/view_report.html",
                                        RequestContext(request, context))

@login_required
def submit_report(request, task_id):
    """ Check if the work is in WR state and the user is in assigned_users.
    """
    task_url = reverse('view_task', kwargs={'task_id': task_id})
    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    user = request.user
    old_reports = task.reports.all()

    if not task.status == taskapp_models.TASK_STATUS_CHOICES[3][0]:
        raise http.Http404

    can_upload = True if user in task.selected_users.all() else False

    context = {
        'user': user,
        'task': task,
        'can_upload': can_upload,
    }

    context.update(csrf(request))

    if request.method == "POST":
        if not can_upload:
            return show_msg(user, "You are not authorised to upload data to this task", task_url, "view the task")

        form = taskapp_forms.WorkReportForm(request.POST, request.FILES)

        if form.is_valid():
            data = form.cleaned_data.copy()
            data.update({"task":task,
                         "revision": old_reports.count(),
                         "submitted_by": user,
                         "submitted_at": datetime.now(),
                        })
            r = taskapp_models.WorkReport(**data)
            r.save()

            report_url = reverse('view_report', kwargs={'report_id': r.id})
            return shortcuts.redirect(report_url)

        else:
            context.update({"form":form})
            return shortcuts.render_to_response(
              'task/submit_report.html', RequestContext(request, context))

    else:
        form = taskapp_forms.WorkReportForm()
        context.update({"form":form})
        return shortcuts.render_to_response(
          'task/submit_report.html', RequestContext(request, context))

@login_required
def claim_task(request, task_id):

    context = {}

    # TODO(disable): Disable once the tasks can be claimed
    context['uberbar_message'] = DONT_CLAIM_TASK_MSG

    claim_url = reverse('claim_task', kwargs={'task_id': task_id})
    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    if task.status == taskapp_models.TASK_STATUS_CHOICES[0][0]:
        raise http.Http404

    user = request.user
    profile = user.get_profile()

    context.update({
      'user': user,
      'profile': profile,
      'task': task,
      })

    context.update(csrf(request))

    reviewers = task.reviewers.all()
    claimed_users = task.claimed_users.all()

    is_creator = True if user == task.created_by else False
    is_reviewer = True if user in reviewers else False
    has_claimed = True if user in claimed_users else False

    task_claimable = True if task.status in [taskapp_models.TASK_STATUS_CHOICES[1][0], taskapp_models.TASK_STATUS_CHOICES[3][0]] else False
    can_claim = True if task_claimable and ( not has_claimed )\
                        and ( not is_reviewer ) and (not is_creator ) \
                        else False

    old_claims = task.claims.all()

    context.update({"is_creator": is_creator,
                    "task_claimable": task_claimable,
                    "can_claim": can_claim,
                    "old_claims": old_claims})

    if request.method == "POST" and can_claim:
        form = taskapp_forms.ClaimTaskForm(request.POST)
        if form.is_valid():
            data = form.cleaned_data.copy()
            data.update({"task": task,
                         "claim_datetime": datetime.now(),
                         "claimed_by": user,})
            new_claim = taskapp_models.TaskClaim(**data)
            new_claim.save()

            task.claimed_users.add(user)
            task.save()

            return shortcuts.redirect(claim_url)

        else:
            context.update({"form": form})
            return shortcuts.render_to_response(
              "task/claim.html", RequestContext(request, context))
    else:
        form = taskapp_forms.ClaimTaskForm()
        context.update({"form": form})
        return shortcuts.render_to_response(
          "task/claim.html", RequestContext(request, context))

@login_required
def select_user(request, task_id):
    """ first get the status of the task and then select one of claimed users
    generate list of claimed users by passing it as an argument to a function.
    """

    task_url = reverse('view_task', kwargs={'task_id': task_id})

    user = request.user
    profile = user.get_profile()
    task = shortcuts.get_object_or_404(taskapp_models.Task, pk=task_id)

    context = {"user": user,
               "profile": profile,
               "task": task,
              }

    context.update(csrf(request))

    claimed_users = task.claimed_users.all()
    task_claimed = True if claimed_users else False
    
    is_creator = True if user == task.created_by else False

    if (is_creator or profile.role in [profile_models.ROLES_CHOICES[1][0], profile_models.ROLES_CHOICES[2][0]]) and \
       task.status in [taskapp_models.TASK_STATUS_CHOICES[1][0], taskapp_models.TASK_STATUS_CHOICES[3][0]]:

        if task_claimed:

            user_list = ((user.id,user.username) for user in claimed_users)

            if request.method == "POST":
                form = taskapp_forms.ChoiceForm(user_list, request.POST)
                if form.is_valid():
                    uid = form.cleaned_data['choice']
                    selected_user = User.objects.get(id=uid)

                    task.selected_users.add(selected_user)
                    task.claimed_users.remove(selected_user)
                    task.status = taskapp_models.TASK_STATUS_CHOICES[3][0]
                    task.save()

                    return shortcuts.redirect(task_url)
                else:
                    context.update({"form": form})
                    return shortcuts.render_to_response(
                      'task/select_user.html',
                      RequestContext(request, context))
            else:
                form = taskapp_forms.ChoiceForm(user_list)
                context.update({"form": form})
                return shortcuts.render_to_response(
                  'task/select_user.html',
                  RequestContext(request, context))
        else:
            return show_msg(user, 'There are no pending claims for this task',
                            task_url, 'view the task')
    else:
        raise http.Http404

def suggest_task_tags(request):
    """Returns the tags matching the query for the AJAXy autocomplete
    to get tags related to tasks.
    """

    term = request.GET.get('term', None)
    response = []

    if term:
      tag_entities = Tag.objects.filter(name__icontains=term)
      response = [tag.name for tag in tag_entities]

    json_response = json.dumps(response)
    return http.HttpResponse(json_response)

def view_tag(request, tag_name, template='task/view_tag.html'):
    """View that displays all the tasks tagged with the given name
    """

    tag = Tag.objects.filter(name=tag_name)
    tasks = TaggedItem.objects.get_by_model(taskapp_models.Task, tag)

    context = {
      'tag_name': tag_name,
      'tasks': tasks,
      }

    return shortcuts.render_to_response(
      template, RequestContext(request, context))