Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
 def get(self, request, *args, **kwargs):
     self.form = TaskFilterForm(None, request.GET)
     self.form.is_valid()
     return super(AvailableTasksView, self).get(request, *args, **kwargs)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
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