class AvailableTasksView(AbstractAuthedIndigoView, ListView): authentication_required = True template_name = 'indigo_app/tasks/available_tasks.html' context_object_name = 'tasks' paginate_by = 50 paginate_orphans = 4 tab = 'available_tasks' def get(self, request, *args, **kwargs): self.form = TaskFilterForm(None, request.GET) self.form.is_valid() return super(AvailableTasksView, self).get(request, *args, **kwargs) def get_queryset(self): tasks = Task.objects \ .filter(assigned_to=None)\ .defer('document__document_xml', 'document__search_text', 'document__search_vector') \ .order_by('-updated_at') if not self.form.cleaned_data.get('state'): tasks = tasks.filter(state__in=Task.OPEN_STATES) return self.form.filter_queryset(tasks) def get_context_data(self, **kwargs): context = super(AvailableTasksView, self).get_context_data(**kwargs) context['form'] = self.form context['tab_count'] = context['paginator'].count return context
def get(self, request, *args, **kwargs): # allows us to set defaults on the form params = QueryDict(mutable=True) params.update(request.GET) # initial state if not params.get('state'): params.setlist('state', ['open', 'assigned', 'pending_review']) params.setdefault('format', 'columns') self.form = TaskFilterForm(self.country, params) self.form.is_valid() return super(TaskListView, self).get(request, *args, **kwargs)
class TaskListView(TaskViewBase, ListView): context_object_name = 'tasks' model = Task js_view = 'TaskListView TaskBulkUpdateView' def get(self, request, *args, **kwargs): # allows us to set defaults on the form params = QueryDict(mutable=True) params.update(request.GET) # initial state if not params.get('state'): params.setlist('state', ['open', 'assigned', 'pending_review']) params.setdefault('format', 'columns') self.form = TaskFilterForm(self.country, params) self.form.is_valid() return super(TaskListView, self).get(request, *args, **kwargs) def get_queryset(self): tasks = Task.objects\ .filter(country=self.country, locality=self.locality)\ .select_related('document__language', 'document__language__language') \ .defer('document__document_xml', 'document__search_text', 'document__search_vector')\ .order_by('-updated_at') return self.form.filter_queryset(tasks) def get_context_data(self, **kwargs): context = super(TaskListView, self).get_context_data(**kwargs) context['task_labels'] = TaskLabel.objects.all() context['form'] = self.form context['frbr_uri'] = self.request.GET.get('frbr_uri') context['task_groups'] = Task.task_columns( self.form.cleaned_data['state'], context['tasks']) # warn when submitting task on behalf of another user Task.decorate_submission_message(context['tasks'], self) Task.decorate_potential_assignees(context['tasks'], self.country) Task.decorate_permissions(context['tasks'], self) return context
class TaskListView(TaskViewBase, ListView): context_object_name = 'tasks' paginate_by = 20 paginate_orphans = 4 model = Task def get(self, request, *args, **kwargs): # allows us to set defaults on the form params = QueryDict(mutable=True) params.update(request.GET) # initial state if not params.get('state'): params.setlist('state', ['open', 'assigned', 'pending_review']) params.setdefault('format', 'columns') self.form = TaskFilterForm(params) self.form.is_valid() if self.form.cleaned_data['format'] == 'columns': self.paginate_by = 40 return super(TaskListView, self).get(request, *args, **kwargs) def get_queryset(self): tasks = Task.objects.filter( country=self.country, locality=self.locality).order_by('-updated_at') return self.form.filter_queryset( tasks, frbr_uri=self.request.GET.get('frbr_uri')) def get_context_data(self, **kwargs): context = super(TaskListView, self).get_context_data(**kwargs) context['task_labels'] = TaskLabel.objects.all() context['form'] = self.form context['frbr_uri'] = self.request.GET.get('frbr_uri') context['task_groups'] = Task.task_columns( self.form.cleaned_data['state'], context['tasks']) return context
def get(self, request, *args, **kwargs): self.form = TaskFilterForm(None, request.GET) self.form.is_valid() return super(AvailableTasksView, self).get(request, *args, **kwargs)
class WorkflowDetailView(WorkflowViewBase, DetailView): context_object_name = 'workflow' model = Workflow threshold = timedelta(seconds=3) js_view = 'WorkflowDetailView TaskBulkUpdateView' def get(self, request, *args, **kwargs): # allows us to set defaults on the form params = QueryDict(mutable=True) params.update(request.GET) # initial state if not params.get('state'): params.setlist( 'state', ['open', 'assigned', 'pending_review', 'done', 'cancelled']) params.setdefault('format', 'columns') self.form = TaskFilterForm(self.country, params) self.form.is_valid() return super(WorkflowDetailView, self).get(request, *args, **kwargs) def get_context_data(self, *args, **kwargs): context = super(WorkflowDetailView, self).get_context_data(**kwargs) # stats self.object.n_tasks = self.object.tasks.count() self.object.n_done = self.object.tasks.closed().count() self.object.pct_done = self.object.n_done / (self.object.n_tasks or 1) * 100.0 context['form'] = self.form tasks = self.form.filter_queryset(self.object.tasks) \ .select_related('document__language', 'document__language__language')\ .defer('document__document_xml', 'document__search_text', 'document__search_vector')\ .all() context['tasks'] = tasks context['has_tasks'] = self.object.n_tasks > 0 context['task_groups'] = Task.task_columns( ['open', 'pending_review', 'assigned'], tasks) context['possible_tasks'] = self.place.tasks\ .unclosed()\ .exclude(workflows=self.object) \ .select_related('document__language', 'document__language__language') \ .defer('document__document_xml', 'document__search_text', 'document__search_vector')\ .all() # warn when submitting task on behalf of another user Task.decorate_submission_message(tasks, self) Task.decorate_potential_assignees(tasks, self.country) Task.decorate_permissions(tasks, self) context[ 'may_close'] = not self.object.closed and self.object.n_tasks == self.object.n_done context['may_reopen'] = self.object.closed stream = any_stream(self.object) context['activity_stream'] = self.coalesce_entries(stream) return context def coalesce_entries(self, stream): """ If more than 1 task were added to the workflow at once, rather display something like '<User> added <n> tasks to this workflow at <time>' """ activity_stream = [] added_stash = [] for i, action in enumerate(stream): if i == 0: # is the first action an addition? if getattr(action, 'verb', None) == 'added': added_stash.append(action) else: activity_stream.append(action) else: # is a subsequent action an addition? if getattr(action, 'verb', None) == 'added': # if yes, was the previous action also an addition? prev = stream[i - 1] if getattr(prev, 'verb', None) == 'added': # if yes, did the two actions happen close together? if prev.timestamp - action.timestamp < self.threshold: # if yes, the previous action was added to the stash and # this action should also be added to the stash added_stash.append(action) else: # if not, this action should start a new stash, # but first squash, add and delete the existing stash stash = self.combine(added_stash) activity_stream.append(stash) added_stash = [] added_stash.append(action) else: # the previous action wasn't an addition # so this action should start a new stash added_stash.append(action) else: # this action isn't an addition, so squash and add the existing stash first # (if it exists) and then add this action if len(added_stash) > 0: stash = self.combine(added_stash) activity_stream.append(stash) added_stash = [] activity_stream.append(action) return activity_stream def combine(self, stash): first = stash[0] if len(stash) == 1: return first else: action = Action(actor=first.actor, verb='added %d tasks to' % len(stash), action_object=self.object) action.timestamp = first.timestamp return action
class AvailableTasksView(AbstractAuthedIndigoView, ListView): authentication_required = True template_name = 'indigo_app/tasks/available_tasks.html' context_object_name = 'tasks' paginate_by = 50 paginate_orphans = 4 tab = 'available_tasks' priority = False def get(self, request, *args, **kwargs): self.form = TaskFilterForm(None, request.GET) self.form.is_valid() return super(AvailableTasksView, self).get(request, *args, **kwargs) def get_queryset(self): tasks = Task.objects \ .filter(assigned_to=None)\ .defer('document__document_xml')\ .order_by('-updated_at') if not self.form.cleaned_data.get('state'): tasks = tasks.filter(state__in=Task.OPEN_STATES) if self.priority: tasks = tasks.filter(workflows__priority=True) return self.form.filter_queryset(tasks) def get_context_data(self, **kwargs): context = super(AvailableTasksView, self).get_context_data(**kwargs) context['form'] = self.form context['tab_count'] = context['paginator'].count if self.priority: workflows = Workflow.objects\ .unclosed()\ .filter(priority=True)\ .select_related('country', 'locality')\ .annotate( n_tasks_open=Subquery( Task.objects.filter(workflows=OuterRef('pk'), state=Task.OPEN, assigned_to=None) .values('workflows__pk') .annotate(cnt=Count(1)) .values('cnt'), output_field=IntegerField()), n_tasks_assigned=Subquery( Task.objects.filter(workflows=OuterRef('pk'), state=Task.OPEN) .exclude(assigned_to=None) .values('workflows__pk') .annotate(cnt=Count(1)) .values('cnt'), output_field=IntegerField()), n_tasks_pending_review=Subquery( Task.objects.filter(workflows=OuterRef('pk'), state=Task.PENDING_REVIEW) .values('workflows__pk') .annotate(cnt=Count(1)) .values('cnt'), output_field=IntegerField()), n_tasks_done=Subquery( Task.objects.filter(workflows=OuterRef('pk'), state=Task.DONE) .values('workflows__pk') .annotate(cnt=Count(1)) .values('cnt'), output_field=IntegerField()), n_tasks_cancelled=Subquery( Task.objects.filter(workflows=OuterRef('pk'), state=Task.CANCELLED) .values('workflows__pk') .annotate(cnt=Count(1)) .values('cnt'), output_field=IntegerField()), ).all() # sort by due date (desc + nulls last), then by id (asc) def key(x): return [-x.due_date.toordinal() if x.due_date else math.inf, x.pk] context['priority_workflows'] = sorted(workflows, key=key) for w in context['priority_workflows']: w.task_counts = [ (state, getattr(w, f'n_tasks_{state}') or 0, state.replace('_', ' ')) for state in ['open', 'assigned', 'pending_review', 'done', 'cancelled'] ] w.n_tasks = sum(n for s, n, l in w.task_counts) w.n_tasks_complete = (w.n_tasks_done or 0) + (w.n_tasks_cancelled or 0) w.pct_complete = (w.n_tasks_complete or 0) / (w.n_tasks or 1) * 100.0 return context