def context(self): """Returns the context for this view. """ task = self.data.task context = { 'page_name': '%s - %s' %(task.title, task.org.name), 'task': task, 'is_mentor': self.data.mentorFor(task.org), 'task_info': TaskInformation(self.data), } if task.deadline: context['complete_percentage'] = timeline_helper.completePercentage( end=task.deadline, duration=(task.time_to_complete*3600)) if self.data.is_visible: context['work_submissions'] = WorkSubmissions(self.data) context['comment_ids'] = [i.key().id() for i in self.data.comments] context['comments'] = CommentsTemplate(self.data) if not context['is_mentor']: # Programmatically change css for non-mentors, to for instance show # the open cog when a task can be claimed. if task.status == 'Closed': block_type = 'completed' elif task_logic.isOwnerOfTask(task, self.data.profile): block_type = 'owned' elif task.status in ACTIVE_CLAIMED_TASK: block_type = 'claimed' else: block_type = 'open' context['block_task_type'] = block_type return context
def context(self): """Returns the context for the current template. """ task = self.data.task mentors = [m.public_name for m in db.get(task.mentors)] profile = self.data.profile # We count everyone from the org as a mentor, the mentors property # is just who best to contact about this task context = { 'task': task, 'mentors': mentors, 'is_mentor': self.data.mentorFor(task.org), 'is_task_mentor': profile.key() in task.mentors if profile else None, 'is_owner': task_logic.isOwnerOfTask(task, self.data.profile), 'is_claimed': task.status in ACTIVE_CLAIMED_TASK, 'profile': self.data.profile, } if task.deadline: rdays, rhrs, rmins = timeline_helper.remainingTimeSplit(task.deadline) context['remaining_days'] = rdays context['remaining_hours'] = rhrs context['remaining_minutes'] = rmins self.setButtonControls(context) return context
def checkAccess(self): """Checks whether this task is visible to the public and any other checks if it is a POST request. """ self.mutator.taskFromKwargs(comments=True, work_submissions=True) self.data.is_visible = self.check.isTaskVisible() if task_logic.updateTaskStatus(self.data.task): # The task logic updated the status of the task since the deadline passed # and the GAE task was late to run. Reload the page. raise RedirectRequest('') if self.request.method == 'POST': # Access checks for the different forms on this page. Note that there # are no elif clauses because one could add multiple GET params :). self.check.isProfileActive() if 'reply' in self.data.GET: # checks for posting comments # valid tasks and profile are already checked. self.check.isBeforeAllWorkStopped() self.check.isCommentingAllowed() if 'submit_work' in self.data.GET: self.check.isBeforeAllWorkStopped() if not task_logic.canSubmitWork(self.data.task, self.data.profile): self.check.fail(DEF_NOT_ALLOWED_TO_UPLOAD_WORK) if 'button' in self.data.GET: # check for any of the buttons button_name = self._buttonName() buttons = {} TaskInformation(self.data).setButtonControls(buttons) if not buttons.get(button_name): self.check.fail(DEF_NOT_ALLOWED_TO_OPERATE_BUTTON % button_name) if 'send_for_review' in self.data.GET: self.check.isBeforeAllWorkStopped() if not task_logic.isOwnerOfTask(self.data.task, self.data.profile) or \ not self.data.work_submissions: self.check.fail(DEF_CANT_SEND_FOR_REVIEW) if 'delete_submission' in self.data.GET: self.check.isBeforeAllWorkStopped() id = self._submissionId() work = GCIWorkSubmission.get_by_id(id, parent=self.data.task) if not work: self.check.fail(DEF_NO_WORK_FOUND %id) time_expired = work.submitted_on - datetime.datetime.now() if work.user.key() != self.data.user.key() or \ time_expired > task_logic.DELETE_EXPIRATION: self.check.fail(DEF_NOT_ALLOWED_TO_DELETE)
def context(self): """Returns the context for the current template. """ context = { 'submissions': self._buildWorkSubmissionContext(), 'download_url': self.data.redirect.id().urlOf('gci_download_work') } task = self.data.task is_owner = task_logic.isOwnerOfTask(task, self.data.ndb_profile) if is_owner: context['send_for_review'] = self.data.work_submissions and \ task.status in SEND_FOR_REVIEW_ALLOWED deleteable = [] if self.data.ndb_user: for work in self.data.work_submissions: work_key = ndb.Key.from_old_key( task_model.GCIWorkSubmission.user.get_value_for_datastore( work)) if work_key == self.data.ndb_user.key: # Ensure that it is the work from the current user in case the task # got re-assigned. time_expired = work.submitted_on - datetime.datetime.now() if time_expired < task_logic.DELETE_EXPIRATION: deleteable.append(work) context['deleteable'] = deleteable if task_logic.canSubmitWork(task, self.data.ndb_profile): if self.data.POST and 'submit_work' in self.data.GET: # File form doesn't have any POST parameters so it should not be # passed while reconstructing the form. So only URL form is # constructed from POST data context['work_url_form'] = WorkSubmissionURLForm( data=self.data.POST) else: context['work_url_form'] = WorkSubmissionURLForm() # As mentioned in the comment above since there is no POST data to # be passed to the file form, it is constructed in the same way # in either cases. context['work_file_form'] = WorkSubmissionFileForm() if self.data.GET.get('file', None) == '0': context['work_file_form'].addFileRequiredError() if self.data.GET.get('ws_error', None) == '1': context['ws_error'] = True url = '%s?submit_work' % (self.data.redirect.id().urlOf( url_names.GCI_VIEW_TASK)) context['direct_post_url'] = url return context
def context(self): """Returns the context for the current template. """ context = { 'submissions': self._buildWorkSubmissionContext(), 'download_url': self.data.redirect.id().urlOf('gci_download_work') } task = self.data.task is_owner = task_logic.isOwnerOfTask(task, self.data.ndb_profile) if is_owner: context['send_for_review'] = self.data.work_submissions and \ task.status in SEND_FOR_REVIEW_ALLOWED deleteable = [] if self.data.ndb_user: for work in self.data.work_submissions: work_key = ndb.Key.from_old_key( task_model.GCIWorkSubmission.user.get_value_for_datastore(work)) if work_key == self.data.ndb_user.key: # Ensure that it is the work from the current user in case the task # got re-assigned. time_expired = work.submitted_on - datetime.datetime.now() if time_expired < task_logic.DELETE_EXPIRATION: deleteable.append(work) context['deleteable'] = deleteable if task_logic.canSubmitWork(task, self.data.ndb_profile): if self.data.POST and 'submit_work' in self.data.GET: # File form doesn't have any POST parameters so it should not be # passed while reconstructing the form. So only URL form is # constructed from POST data context['work_url_form'] = WorkSubmissionURLForm(data=self.data.POST) else: context['work_url_form'] = WorkSubmissionURLForm() # As mentioned in the comment above since there is no POST data to # be passed to the file form, it is constructed in the same way # in either cases. context['work_file_form'] = WorkSubmissionFileForm() if self.data.GET.get('file', None) == '0': context['work_file_form'].addFileRequiredError() if self.data.GET.get('ws_error', None) == '1': context['ws_error'] = True url = '%s?submit_work' % ( self.data.redirect.id().urlOf(url_names.GCI_VIEW_TASK)) context['direct_post_url'] = url return context
def setButtonControls(self, context): """Enables buttons on the TaskInformation block based on status and the user. Args: context: Context dictionary which to write to. """ profile = self.data.profile if not profile: # no buttons for someone without a profile return if self.data.timeline.allReviewsStopped(): # no buttons after all reviews has stopped return task = self.data.task is_org_admin = self.data.orgAdminFor(task.org) is_mentor = self.data.mentorFor(task.org) is_student = self.data.is_student is_owner = task_logic.isOwnerOfTask(task, profile) if is_org_admin: can_unpublish = (task.status in CLAIMABLE) and not task.student context['button_unpublish'] = can_unpublish context['button_delete'] = not task.student if is_mentor: context['button_edit'] = task.status in \ UNPUBLISHED + CLAIMABLE + ACTIVE_CLAIMED_TASK context['button_assign'] = task.status == 'ClaimRequested' context['button_unassign'] = task.status in ACTIVE_CLAIMED_TASK context['button_close'] = task.status == 'NeedsReview' context['button_needs_work'] = task.status == 'NeedsReview' context['button_extend_deadline'] = task.status in TASK_IN_PROGRESS if is_student: if not self.data.timeline.tasksClaimEnded(): context['button_claim'] = task_logic.canClaimRequestTask( task, profile) if is_owner: if not self.data.timeline.tasksClaimEnded(): context['button_unclaim'] = task.status in ACTIVE_CLAIMED_TASK if task.status != 'Closed': context['button_subscribe'] = not profile.key() in task.subscribers context['button_unsubscribe'] = profile.key() in task.subscribers
def context(self): """Returns the context for the current template. """ task = self.data.task mentors = [ mentor.public_name for mentor in ndb.get_multi( map(ndb.Key.from_old_key, task.mentors)) ] profile = self.data.ndb_profile # We count everyone from the org as a mentor, the mentors property # is just who best to contact about this task context = { 'task': task, 'mentors': mentors, 'is_mentor': self.data.mentorFor( task_model.GCITask.org.get_value_for_datastore(task)), 'is_task_mentor': profile.key.to_old_key() in task.mentors if profile else None, 'is_owner': task_logic.isOwnerOfTask(task, self.data.ndb_profile), 'is_claimed': task.status in ACTIVE_CLAIMED_TASK, 'profile': self.data.ndb_profile, } if task.deadline: rdays, rhrs, rmins = timeline_helper.remainingTimeSplit( task.deadline) context['remaining_days'] = rdays context['remaining_hours'] = rhrs context['remaining_minutes'] = rmins self.setButtonControls(context) return context
def context(self, data, check, mutator): """Returns the context for this view.""" task = data.task context = { 'page_name': '%s - %s' % (task.title, task.org.name), 'task': task, 'is_mentor': data.mentorFor(task.org.key()), 'task_info': TaskInformation(data), } if task.deadline: # TODO(nathaniel): This is math - move it to a helper function. context[ 'complete_percentage'] = timeline_helper.completePercentage( end=task.deadline, duration=(task.time_to_complete * 3600)) if data.is_visible: context['work_submissions'] = WorkSubmissions(data) context['comment_ids'] = [i.key().id() for i in data.comments] context['comments'] = CommentsTemplate(data) if not context['is_mentor']: # Programmatically change css for non-mentors, to for instance show # the open cog when a task can be claimed. if task.status == 'Closed': block_type = 'completed' elif task_logic.isOwnerOfTask(task, data.ndb_profile): block_type = 'owned' elif task.status in ACTIVE_CLAIMED_TASK: block_type = 'claimed' else: block_type = 'open' context['block_task_type'] = block_type return context
def setButtonControls(self, context): """Enables buttons on the TaskInformation block based on status and the user. Args: context: Context dictionary which to write to. """ if not self.data.ndb_profile: # no buttons for someone without a profile return if self.data.timeline.allReviewsStopped(): # no buttons after all reviews has stopped return task = self.data.task is_org_admin = self.data.orgAdminFor(task.org.key()) is_mentor = self.data.mentorFor(task.org.key()) is_student = self.data.ndb_profile.is_student is_owner = task_logic.isOwnerOfTask(task, self.data.ndb_profile) if is_org_admin: can_unpublish = task.status == task_model.OPEN and not task.student context['button_unpublish'] = can_unpublish can_publish = task.status in task_model.UNAVAILABLE context['button_publish'] = can_publish context['button_delete'] = not task.student if is_mentor: context['button_edit'] = task.status in \ task_model.UNAVAILABLE + CLAIMABLE + ACTIVE_CLAIMED_TASK context['button_assign'] = task.status == 'ClaimRequested' context['button_unassign'] = task.status in ACTIVE_CLAIMED_TASK context['button_close'] = task.status == 'NeedsReview' context['button_needs_work'] = task.status == 'NeedsReview' context['button_extend_deadline'] = task.status in TASK_IN_PROGRESS if is_student: if not self.data.timeline.tasksClaimEnded(): if not profile_logic.hasStudentFormsUploaded( self.data.ndb_profile): # TODO(nathaniel): make this .program() call unnecessary. self.data.redirect.program() context['student_forms_link'] = self.data.redirect.urlOf( url_names.GCI_STUDENT_FORM_UPLOAD) # TODO(lennie): Separate the access check out in to different # methods and add a context variable to show separate messages.' context['button_claim'] = task_logic.canClaimRequestTask( task, self.data.ndb_profile) if is_owner: if not self.data.timeline.tasksClaimEnded(): context['button_unclaim'] = task.status in ACTIVE_CLAIMED_TASK if task.status != 'Closed': task_subscribers_keys = map(ndb.Key.from_old_key, task.subscribers) context['button_subscribe'] = (not self.data.ndb_profile.key in task_subscribers_keys) context['button_unsubscribe'] = (not self.data.ndb_profile.key in task.subscribers)
def checkAccess(self, data, check, mutator): """Checks whether this task is visible to the public and any other checks if it is a POST request. """ mutator.taskFromKwargs(comments=True, work_submissions=True) data.is_visible = check.isTaskVisible() if task_logic.updateTaskStatus(data.task): # The task logic updated the status of the task since the deadline passed # and the GAE task was late to run. Reload the page. raise exception.Redirect('') if data.request.method == 'POST': # Access checks for the different forms on this page. Note that there # are no elif clauses because one could add multiple GET params :). check.isProfileActive() # Tasks for non-active organizations cannot be touched check.isOrganizationActive(data.task.org) if 'reply' in data.GET: # checks for posting comments # valid tasks and profile are already checked. check.isBeforeAllWorkStopped() check.isCommentingAllowed() if 'submit_work' in data.GET: check.isBeforeAllWorkStopped() if not task_logic.canSubmitWork(data.task, data.ndb_profile): check.fail(DEF_NOT_ALLOWED_TO_UPLOAD_WORK) if 'button' in data.GET: # check for any of the buttons button_name = self._buttonName(data) buttons = {} TaskInformation(data).setButtonControls(buttons) if not buttons.get(button_name): check.fail(DEF_NOT_ALLOWED_TO_OPERATE_BUTTON % button_name) if 'send_for_review' in data.GET: check.isBeforeAllWorkStopped() if not task_logic.isOwnerOfTask(data.task, data.ndb_profile) or \ not data.work_submissions or \ data.task.status not in TASK_IN_PROGRESS: check.fail(DEF_CANT_SEND_FOR_REVIEW) if 'delete_submission' in data.GET: check.isBeforeAllWorkStopped() task_id = self._submissionId(data) work = work_submission_model.GCIWorkSubmission.get_by_id( task_id, parent=data.task) if not work: check.fail(DEF_NO_WORK_FOUND % id) user_key = ndb.Key.from_old_key( task_model.GCIWorkSubmission.user.get_value_for_datastore( work)) time_expired = work.submitted_on - datetime.datetime.now() if (user_key != data.ndb_user.key or time_expired > task_logic.DELETE_EXPIRATION): check.fail(DEF_NOT_ALLOWED_TO_DELETE)
def setButtonControls(self, context): """Enables buttons on the TaskInformation block based on status and the user. Args: context: Context dictionary which to write to. """ if not self.data.ndb_profile: # no buttons for someone without a profile return if self.data.timeline.allReviewsStopped(): # no buttons after all reviews has stopped return task = self.data.task is_org_admin = self.data.orgAdminFor(task.org.key()) is_mentor = self.data.mentorFor(task.org.key()) is_student = self.data.ndb_profile.is_student is_owner = task_logic.isOwnerOfTask(task, self.data.ndb_profile) if is_org_admin: can_unpublish = task.status == task_model.OPEN and not task.student context['button_unpublish'] = can_unpublish can_publish = task.status in task_model.UNAVAILABLE context['button_publish'] = can_publish context['button_delete'] = not task.student if is_mentor: context['button_edit'] = task.status in \ task_model.UNAVAILABLE + CLAIMABLE + ACTIVE_CLAIMED_TASK context['button_assign'] = task.status == 'ClaimRequested' context['button_unassign'] = task.status in ACTIVE_CLAIMED_TASK context['button_close'] = task.status == 'NeedsReview' context['button_needs_work'] = task.status == 'NeedsReview' context['button_extend_deadline'] = task.status in TASK_IN_PROGRESS if is_student: if not self.data.timeline.tasksClaimEnded(): if not profile_logic.hasStudentFormsUploaded(self.data.ndb_profile): # TODO(nathaniel): make this .program() call unnecessary. self.data.redirect.program() context['student_forms_link'] = self.data.redirect.urlOf( url_names.GCI_STUDENT_FORM_UPLOAD) # TODO(lennie): Separate the access check out in to different # methods and add a context variable to show separate messages.' context['button_claim'] = task_logic.canClaimRequestTask( task, self.data.ndb_profile) if is_owner: if not self.data.timeline.tasksClaimEnded(): context['button_unclaim'] = task.status in ACTIVE_CLAIMED_TASK if task.status != 'Closed': task_subscribers_keys = map(ndb.Key.from_old_key, task.subscribers) context['button_subscribe'] = ( not self.data.ndb_profile.key in task_subscribers_keys) context['button_unsubscribe'] = ( not self.data.ndb_profile.key in task.subscribers)
def checkAccess(self, data, check, mutator): """Checks whether this task is visible to the public and any other checks if it is a POST request. """ mutator.taskFromKwargs(comments=True, work_submissions=True) data.is_visible = check.isTaskVisible() if task_logic.updateTaskStatus(data.task): # The task logic updated the status of the task since the deadline passed # and the GAE task was late to run. Reload the page. raise exception.Redirect('') if data.request.method == 'POST': # Access checks for the different forms on this page. Note that there # are no elif clauses because one could add multiple GET params :). check.isProfileActive() # Tasks for non-active organizations cannot be touched check.isOrganizationActive(data.task.org) if 'reply' in data.GET: # checks for posting comments # valid tasks and profile are already checked. check.isBeforeAllWorkStopped() check.isCommentingAllowed() if 'submit_work' in data.GET: check.isBeforeAllWorkStopped() if not task_logic.canSubmitWork(data.task, data.ndb_profile): check.fail(DEF_NOT_ALLOWED_TO_UPLOAD_WORK) if 'button' in data.GET: # check for any of the buttons button_name = self._buttonName(data) buttons = {} TaskInformation(data).setButtonControls(buttons) if not buttons.get(button_name): check.fail(DEF_NOT_ALLOWED_TO_OPERATE_BUTTON % button_name) if 'send_for_review' in data.GET: check.isBeforeAllWorkStopped() if not task_logic.isOwnerOfTask(data.task, data.ndb_profile) or \ not data.work_submissions or \ data.task.status not in TASK_IN_PROGRESS: check.fail(DEF_CANT_SEND_FOR_REVIEW) if 'delete_submission' in data.GET: check.isBeforeAllWorkStopped() task_id = self._submissionId(data) work = work_submission_model.GCIWorkSubmission.get_by_id( task_id, parent=data.task) if not work: check.fail(DEF_NO_WORK_FOUND % id) user_key = ndb.Key.from_old_key( task_model.GCIWorkSubmission.user.get_value_for_datastore(work)) time_expired = work.submitted_on - datetime.datetime.now() if (user_key != data.ndb_user.key or time_expired > task_logic.DELETE_EXPIRATION): check.fail(DEF_NOT_ALLOWED_TO_DELETE)