from datetime import datetime
from django.http import HttpResponse, Http404
from django.shortcuts import render_to_response, redirect
from pytask.taskapp.models import User, Task, Comment, Request, Notification, WorkReport
from pytask.taskapp.utilities.task import getTask
from pytask.taskapp.forms.task import TaskCreateForm, AddReviewerForm, AddTaskForm, ChoiceForm, AssignPyntForm, RemoveUserForm, EditTaskForm, ClaimTaskForm, WorkReportForm
from pytask.taskapp.events.task import createTask, reqReviewer, publishTask, addSubTask, addDep, addClaim, assignTask, updateTask, removeTask, removeUser, assignPynts, completeTask, closeTask, addReviewer, deleteTask
from pytask.taskapp.views.user import show_msg
from pytask.taskapp.utilities.user import get_user
## everywhere if there is no task, django should display 500 message.. but take care of that in sensitive views like add reviewer and all
## do not create su user thro syncdb
def browse_tasks(request):
""" display all the tasks """
user = get_user(request.user) if request.user.is_authenticated() else request.user
task_list = Task.objects.exclude(status="UP").exclude(status="DL").order_by('published_datetime').reverse()
task_list = task_list.exclude(tags_field__icontains="textbook")
context = {'user':user,
'task_list':task_list,
}
return render_to_response('task/browse.html', context)
def show_textbooks(request):
""" display all the tasks """
user = get_user(request.user) if request.user.is_authenticated() else request.user
task_list = Task.objects.exclude(status="UP").exclude(status="DL").order_by('published_datetime').reverse()
task_list = task_list.filter(tags_field__icontains="textbook")
context = {'user':user,
'task_list':task_list,
}
return render_to_response('task/browse.html', context)
def upload_work(request, tid):
""" Check if the work is in WR state and the user is in assigned_users.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
if not task.status == "WR":
return show_msg(user, "The task is not in a stage to upload content", task_url, "view the task")
can_upload = True if user in task.assigned_users.all() else False
old_reports = task.workreport_report.all()
context = {
'user': user,
'task': task,
'old_reports': old_reports,
'can_upload': can_upload,
}
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 = WorkReportForm(request.POST, request.FILES)
if form.is_valid():
r = WorkReport(attachment = form.cleaned_data['attachment'],
remarks = form.cleaned_data['remarks'],
revision = old_reports.count(),
task = task,
submitted_by = user,
created_at = datetime.now(),
)
r.save()
return redirect(task_url)
else:
context.update({"form":form})
return render_to_response('task/report.html', context)
else:
form = WorkReportForm()
context.update({"form":form})
return render_to_response('task/report.html', context)
def publish_task(request, tid):
""" check if user is the reviewer and also if the task status is UP.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
if user == task.created_by:
context = {
'user':user,
}
if task.status == "UP":
if request.method == "POST":
publishTask(task)
return show_msg(user, "The task has been published", task_url, "view the task")
else:
return render_to_response('task/publish.html', context)
else:
return show_msg(user, "The task is already published", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to do this", '/task/browse/', "browse tasks")
def view_task(request, tid):
""" get the task depending on its tid and display accordingly if it is a get.
check for authentication and add a comment if it is a post request.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
if task.status == "DL":
return show_msg(user, 'This task no longer exists', '/task/browse/','browse the tasks')
comments = task.comment_set.filter(is_deleted=False).order_by('creation_datetime')
reviewers = task.reviewers.all()
deps, subs = task.deps, task.subs
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
context = {'user':user,
'task':task,
'comments':comments,
'reviewers':reviewers,
'subs':subs,
'deps':deps,
'is_guest':is_guest,
'is_reviewer':is_reviewer,
}
claimed_users = task.claimed_users.all()
is_requested_reviewer = True if user.is_authenticated() and user.request_sent_to.filter(is_valid=True,is_replied=False,role="MT",task=task) else False
task_viewable = True if ( task.status != "UP" ) or is_reviewer or is_requested_reviewer else False
if not task_viewable:
return show_msg(user, "You are not authorised to view this task", "/task/browse/", "browse the tasks")
context['is_requested_reviewer'] = is_requested_reviewer
context['can_publish'] = True if task.status == "UP" and user == task.created_by else False
context['can_edit'] = True if task.status == "UP" and is_reviewer else False
context['can_close'] = True if task.status not in ["UP", "CD", "CM"] and is_reviewer else False
context['can_delete'] = True if task.status == "UP" and user == task.created_by else False
context['can_mod_reviewers'] = True if task.status in ["UP", "OP", "LO", "WR"] and is_reviewer else False
context['can_mod_tasks'] = True if task.status in ["UP", "OP", "LO"] and is_reviewer else False
context['can_assign_pynts'] = True if task.status in ["OP", "WR"] and is_reviewer else False
context['task_claimable'] = True if task.status in ["OP", "WR"] and not is_guest else False
if task.status == "CD":
context['closing_notification'] = Notification.objects.filter(task=task,role="CD")[0]
elif task.status == "CM":
context['completed_notification'] = Notifications.objects.filter(task=task,role="CM")[0]
elif task.status == "WR":
context['assigned_users'] = task.assigned_users.all()
if request.method == 'POST':
if not is_guest:
data = request.POST.get("data", "").strip()
if not data:
context['error_msg'] = "Enter some message to comment"
return render_to_response('task/view.html', context)
new_comment = Comment(task=task, data=data, created_by=user, creation_datetime=datetime.now())
new_comment.save()
return redirect(task_url)
else:
errors.append("You must be logged in to post a comment")
return render_to_response('task/view.html', context)
else:
return render_to_response('task/view.html', context)
def create_task(request):
""" check for rights and create a task if applicable.
if user cannot create a task, redirect to homepage.
"""
user = get_user(request.user) if request.user.is_authenticated() else request.user
is_guest = True if not user.is_authenticated() else False
if not is_guest:
user_profile = user.get_profile()
can_create_task = False if user_profile.rights == "CT" else True
if can_create_task:
if request.method == "POST":
form = TaskCreateForm(request.POST)
if form.is_valid():
data = form.cleaned_data
title = data['title']
desc = data['desc']
pynts = data['pynts']
#publish = data['publish'] # just in case if we have to show the option
task = createTask(title,desc,user,pynts)
addReviewer(task, user)
updateTask(task,tags_field=data['tags_field'])
# if publish: publishTask(task)
task_url = '/task/view/tid=%s'%task.id
return redirect(task_url)
else:
return render_to_response('task/create.html',{'user':user, 'form':form})
else:
form = TaskCreateForm()
return render_to_response('task/create.html',{'user':user, 'form':form})
else:
return show_msg(user, 'You are not authorised to create a task.')
else:
return show_msg(user, 'You are not authorised to create a task.', "/", "home page")
def add_reviewer(request, tid):
""" check if the current user has the rights to edit the task and add him.
if user is not authenticated, redirect him to concerned page. """
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
errors = []
is_guest = True if not user.is_authenticated() else False
if (not is_guest) and user in task.reviewers.all():
pending_requests = Request.objects.filter(is_replied=False,is_valid=True,role="MT",task=task).order_by('creation_date').reverse()
user_pending_requests = pending_requests.filter(sent_by=user)
## now iam going for a brute force method
user_list = list(User.objects.filter(is_active=True))
for reviewer in task.reviewers.all():
user_list.remove(reviewer)
for a_user in task.claimed_users.all():
user_list.remove(a_user)
for a_user in task.assigned_users.all():
user_list.remove(a_user)
for req in user_pending_requests:
user_list.remove(req.sent_to.all()[0])
non_reviewers = ((_.id, _.username) for _ in user_list)
non_reviewer_ids = [ str(a_user.id) for a_user in user_list ]
## code till must be made elegant and not brute force like above
form = AddReviewerForm(non_reviewers)
context = {
'user':user,
'task':task,
'pending_requests':pending_requests,
'form':form,
}
if request.method == "POST":
data = request.POST
uid = data.get('reviewer', None)
if uid in non_reviewer_ids:
new_reviewer = User.objects.get(id=int(uid))
reqReviewer(task, new_reviewer, user)
return redirect('/task/addreviewer/tid=%s'%task.id)
else:
## bogus post request
raise Http404
else:
return render_to_response('task/addreviewer.html', context)
else:
return show_msg(user, 'You are not authorised to add reviewers for this task', task_url, 'view the task')
def add_tasks(request, tid):
""" first display tasks which can be subtasks for the task and do the rest.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
deps, subs = task.deps, task.subs
is_plain = False if deps or subs else True
## again a brute force method
valid_tasks = []
for a_task in Task.objects.all():
if not ( a_task in deps or a_task in subs or a_task.status=="CD" or a_task==task ):
valid_tasks.append(a_task)
task_choices = [ (_.id,_.title) for _ in valid_tasks ]
errors = []
is_guest = True if not user.is_authenticated() else False
if (not is_guest) and user in task.reviewers.all():
if task.status in ["UP", "OP", "LO"]:
form = AddTaskForm(task_choices, is_plain)
if request.method == "POST":
## first decide if adding subs and deps can be in same page
## only exclude tasks with status deleted
data = request.POST
if is_plain and not data.get('type', None): errors.append('Please choose which type of task(s) do you want to add.')
if not data.get('task', None): errors.append('Please choose a one task')
if not errors:
if is_plain:
update_method = addDep if data['type'] == "D" else addSubTask
elif deps:
update_method = addDep
elif subs:
update_method = addSubTask
else:
print "Screw you"
## we might iterate over a task list later on
task_id = data['task']
sub_or_dep = getTask(task_id)
update_method(task, sub_or_dep)
return redirect(task_url)
else:
return render_to_response('task/addtask.html', {'user':user, 'form':form, 'errors':errors})
else:
return render_to_response('task/addtask.html', {'user':user, 'form':form, 'errors':errors})
else:
errors = ["The task cannot be added subtasks or dependencies in this state"]
# return render_to_response('task/add.html', {'form':form, 'errors':errors})
return show_msg(user, 'The task cannot be added subtasks or dependencies now', task_url, 'view the task')
else:
return show_msg(user, 'You are not authorised to add subtasks or dependencies for this task', task_url, 'view the task')
def remove_task(request, tid):
""" display a list of tasks and remove the selectes ones.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
if (not is_guest) and user in task.reviewers.all():
if task.status in ["UP", "LO", "OP"]:
deps, subs = task.deps, task.subs
task_list = deps if task.sub_type == "D" else subs
if task_list:
choices = [(_.id,_.title) for _ in task_list ]
form = ChoiceForm(choices)
errors = []
context = {
'user':user,
'task':task,
'form':form,
}
if request.method == "POST":
data = request.POST
if not data.get('choice', None):
errors.append("Please choose a task to remove.")
context['errors'] = errors
if not errors:
tid = data['choice']
sub_task = getTask(tid)
removeTask(task, sub_task)
return redirect(task_url)
else:
return render_to_response('task/removetask.html', context)
else:
return render_to_response('task/removetask.html', context)
else:
return show_msg(user, "The task has no subtasks/dependencies to be removed", task_url, "view the task")
else:
return show_msg(user, "subtasks/dependencies cannot be removed at this stage", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to do this", task_url, "view the task")
def claim_task(request, tid):
""" display a list of claims for get and display submit only if claimable """
## create claims model and create a new database with required tables for it
## see if that "one to n" or "n to one" relationship has a special field
task_url = "/task/view/tid=%s"%tid
claim_url = "/task/claim/tid=%s"%tid
errors = []
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
#claims = task.notifications_task.filter(role="CL",sent_to=task.created_by)
# this is what the next line should be when i re sync the db
claims = Notification.objects.filter(task=task, sent_to=task.created_by, role="CL")
reviewers = task.reviewers.all()
claimed_users = task.claimed_users.all()
assigned_users = task.assigned_users.all()
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in reviewers else False
task_claimable = True if task.status in ["OP", "WR"] else False
user_can_claim = True if task_claimable and not ( is_guest or is_reviewer ) and ( user not in claimed_users ) and ( user not in assigned_users ) else False
task_claimed = True if claimed_users else False
context = {'user':user,
'is_reviewer':is_reviewer,
'task':task,
'claims':claims,
'user_can_claim':user_can_claim,
'task_claimable':task_claimable,
'task_claimed':task_claimed,
'errors':errors}
if not is_guest:
form = ClaimTaskForm()
context['form'] = form
if request.method == "POST":
form = ClaimTaskForm(request.POST)
context['form'] = form
if form.is_valid():
claim_proposal = form.cleaned_data['message']
addClaim(task, claim_proposal, user)
return redirect(claim_url)
else:
return render_to_response('task/claim.html', context)
else:
return render_to_response('task/claim.html', context)
else:
return show_msg(user, 'You are not logged in to view claims for this task', task_url, 'view the task')
def rem_user(request, tid):
""" show a list of working users and ask for a message/reason for removing user.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
if (not is_guest) and is_reviewer:
assigned_users = task.assigned_users.all()
choices = [ (_.id,_.username) for _ in assigned_users ]
context = {
'user':user,
'task':task,
}
if task.status in ["WR"]:
if assigned_users:
form = RemoveUserForm(choices)
context['form'] = form
if request.method == "POST":
data = request.POST
form = RemoveUserForm(choices, data)
if form.is_valid():
data = form.cleaned_data
uid = data['user']
reason = data['reason']
rem_user = User.objects.get(id=uid)
removeUser(task, rem_user, user, reason)
return redirect(task_url)
else:
context['form'] = form
return render_to_response('task/remove_user.html', context)
else:
return render_to_response('task/remove_user.html',context)
else:
return show_msg(user, "There is no one working on this task to be kicked off", task_url, "view the task")
else:
return show_msg(user, "This is not the stage to remove users", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to do this", task_url, "view the task")
def assign_task(request, tid):
""" first get the status of the task and then assign it to one of claimed users
generate list of claimed users by passing it as an argument to a function.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
claimed_users = task.claimed_users.all()
assigned_users = task.assigned_users.all()
task_claimed = True if claimed_users else False
if (not is_guest) and is_reviewer:
if task.status in ["OP", "WR"]:
if task_claimed:
user_list = ((user.id,user.username) for user in claimed_users)
form = ChoiceForm(user_list)
if request.method == "POST":
uid = request.POST['choice']
assigned_user = User.objects.get(id=uid)
assignTask(task, assigned_user, user)
return redirect(task_url)
else:
return render_to_response('task/assign.html',{'user':user, 'task':task,'form':form})
elif assigned_users:
return show_msg(user, 'When the no of users you need for the task is more than the no of users willing to do the task, I\'d say please re consider the task :P',task_url, 'view the task')
else:
return show_msg(user, 'Wait for ppl to claim dude... slow and steady wins the race :)', task_url, 'view the task')
else:
return show_msg(user, "The task cannot be assigned to users at this stage", task_url, 'view the task')
else:
return show_msg(user, 'You are not authorised to perform this action', task_url, 'view the task')
def assign_pynts(request, tid):
""" Check if the user is a reviewer and pynts can be assigned.
Then display all the approved pynts.
Then see if reviewer can assign pynts to users also or only reviewers.
Then put up a form for reviewer to assign pynts accordingly.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
## the moment we see that user had requested pynts, it means he had worked and hence we change the status to WR
## we have to discuss on this since, pynts may also be given to reviewer
task.status = "WR"
task.save()
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if (not is_guest) and user in task.reviewers.all() else False
if is_reviewer:
if task.status in ["OP", "WR"]:
choices = [(_.id,_.username) for _ in task.reviewers.all()]
if task.status == "WR":
choices.extend([(_.id, _.username) for _ in task.assigned_users.all() ])
prev_pynts = task.request_task.filter(role="PY",is_valid=True,is_replied=True,reply=True).count()
pynt_requests = task.request_task.filter(role="PY",is_valid=True).order_by('creation_date').reverse()
form = AssignPyntForm(choices)
context = {
'user':user,
'task':task,
'prev_pynts':prev_pynts,
'pynt_requests':pynt_requests,
'form':form,
}
if request.method == "POST":
data = request.POST
form = AssignPyntForm(choices, data)
if form.is_valid():
data = form.cleaned_data
uid = data['user']
points = data['pynts']
given_to = User.objects.get(id=uid)
assignPynts(task=task, given_by=user, given_to=given_to, points=points)
return redirect('/task/assignpynts/tid=%s'%task.id)
else:
context['form'] = form
return render_to_response('task/assignpynts.html', context)
else:
return render_to_response('task/assignpynts.html', context)
else:
return show_msg(user, "Pynts cannot be assigned at this stage", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to perform this action", task_url, "view the task")
def edit_task(request, tid):
""" see what are the attributes that can be edited depending on the current status
and then give the user fields accordingly.
"""
task = getTask(tid)
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
is_reviewer = True if user in task.reviewers.all() else False
can_edit = True if is_reviewer and task.status == "UP" else False
if can_edit:
form = EditTaskForm(instance=task)
if request.method=="POST":
data = request.POST
form = EditTaskForm(data, instance=task)
if form.is_valid():
form.save()
return redirect(task_url)
else:
return render_to_response('task/edittask.html',{'user':user, 'form':form})
else:
return render_to_response('task/edittask.html',{'user':user, 'form':form})
else:
return show_msg(user, "You cannot edit the task at this stage", task_url, "view the task")
def complete_task(request, tid):
""" call the event called complete task.
and also pass it the current user to know who marked it as complete.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
claimed_users = task.claimed_users.all()
assigned_users = task.assigned_users.all()
assign_pynts_url = '/task/assignpynts/tid=%s'%task.id
task_assigned_pynts = task.pynt_set.all()
if is_reviewer:
if task.status in ["OP", "WR"]:
context = {
'user':user,
'task':task,
}
if task_assigned_pynts:
if request.method=="POST":
completeTask(task, user)
return redirect(task_url)
else:
return render_to_response('task/complete.html', context)
else:
return show_msg(user, "Nobody has been pynted for doing this task.", assign_pynts_url, "assign pynts")
else:
return show_msg(user, "The task cannot be marked as completed at this stage", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to do this", task_url, "view the task")
def close_task(request, tid):
""" task can be closed only if task is published.
call the event close task if everything is fine.
"""
task_url = "/task/view/tid=%s"%tid
user = get_user(request.user) if request.user.is_authenticated() else request.user
task = getTask(tid)
is_guest = True if not user.is_authenticated() else False
is_reviewer = True if user in task.reviewers.all() else False
if is_reviewer:
context = {
'user':user,
'task':task,
}
if not task.status in ["UP", "CD", "DL", "CM"]:
if request.method == "POST":
data = request.POST
if not data.get("reason", None):
context["error"] = "Please enter a reason for closing the task"
return render_to_response('task/close.html', context)
else:
closeTask(task, user, data['reason'])
return show_msg(user, "The task has been closed.", task_url, "view the task.")
else:
return render_to_response('task/close.html', context)
else:
return show_msg(user, "The task is either already closed or cannot be closed at this stage", task_url, "view the task")
else:
return show_msg(user, "You are not authorised to do this", task_url, "view the task")
def delete_task(request, tid):
""" mark the task status as DL.
take a reason from the user and pass on to all the other reviewers.
"""
task_url = "/task/view/tid=%s"%tid
task = getTask(tid)
user = get_user(request.user) if request.user.is_authenticated() else request.user
if task.status == "DL":
return show_msg(user, "This task no longer exists", '/task/browse/', "to browse other tasks")
can_delete = True if task.status == "UP" and task.created_by == user else False
if can_delete:
if request.method == "POST":
data = request.POST
reason = data.get('reason', None)
deleteTask(task, user, reason)
return show_msg(user, "The task is deleted", '/', "to return to home page")
else:
return render_to_response('task/delete.html',{'user':user,})
else:
return show_msg(user, "You are not authorised to do this at this stage", task_url, "view the task")