Skip to content

Commit

Permalink
Merge pull request #1922 from laws-africa/perf-tasks
Browse files Browse the repository at this point in the history
improve task page performance by loading assignees on demand
  • Loading branch information
longhotsummer authored Jan 5, 2024
2 parents 61dccfd + 246dea8 commit 31c2389
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 55 deletions.
6 changes: 3 additions & 3 deletions indigo_api/models/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ def get_queryset(self):
from .documents import Document

return super(TaskManager, self).get_queryset() \
.select_related('created_by_user', 'updated_by_user', 'assigned_to', \
'submitted_by_user', 'reviewed_by_user', 'country', \
'country__country', 'locality') \
.select_related('created_by_user', 'updated_by_user', 'assigned_to',
'submitted_by_user', 'reviewed_by_user', 'country',
'country__country', 'locality', 'locality__country', 'locality__country__country') \
.prefetch_related(Prefetch('work', queryset=Work.objects.filter())) \
.prefetch_related(Prefetch('document', queryset=Document.objects.no_xml())) \
.prefetch_related('labels')
Expand Down
2 changes: 1 addition & 1 deletion indigo_app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ class TaskFilterForm(forms.Form):
assigned_to = forms.ModelMultipleChoiceField(queryset=User.objects)
submitted_by = forms.ModelMultipleChoiceField(queryset=User.objects)
type = forms.MultipleChoiceField(choices=Task.CODES)
country = forms.ModelMultipleChoiceField(queryset=Country.objects)
country = forms.ModelMultipleChoiceField(queryset=Country.objects.select_related('country'))
taxonomy_topic = forms.CharField()

def __init__(self, country, *args, **kwargs):
Expand Down
4 changes: 2 additions & 2 deletions indigo_app/static/javascript/indigo/views/task_bulk_update.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
const formData = this.$form.serialize() + '&unassign';
$.post(this.$form.data('assignees-url'), formData)
.then((resp) => {
const html = $.parseHTML(resp.trim())[0];
const html = $.parseHTML(resp.trim());
const $menu = this.$form.find('.dropdown-menu');
$menu.empty();
$menu.append(html.children);
$menu.append(html);
});
},
});
Expand Down
32 changes: 16 additions & 16 deletions indigo_app/templates/indigo_api/_task_assign_to_menu.html
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{% load account i18n %}

<div class="dropdown-menu">
{% if unassign %}
<button class="dropdown-item" type="submit" name="assigned_to" value="-1">{% trans 'Unassign' %}</button>
{% endif %}
{% if unassign %}
<button class="dropdown-item" type="submit" name="assigned_to" value="-1">{% trans 'Unassign' %}</button>
{% endif %}

{% for potential_assignee in potential_assignees %}
<button class="dropdown-item" type="submit" name="assigned_to"
{% if potential_assignee.too_many_tasks %}disabled{% endif %}
{% if task %}formaction="{% url 'assign_task' place=place.place_code pk=task.pk %}"{% endif %}
value="{{ potential_assignee.id }}">
{% user_display potential_assignee %}
{% if potential_assignee.too_many_tasks %}
– {% trans 'too many tasks' %} ({{ potential_assignee.assigned_tasks_count }})
{% endif %}
</button>
{% endfor %}
</div>
{% for potential_assignee in potential_assignees %}
<button class="dropdown-item" type="submit" name="assigned_to"
{% if potential_assignee.too_many_tasks %}disabled{% endif %}
{% if task %}formaction="{% url 'assign_task' place=place.place_code pk=task.pk %}"{% endif %}
value="{{ potential_assignee.id }}">
{% user_display potential_assignee %}
{% if potential_assignee.too_many_tasks %}
– {% trans 'too many tasks' %} ({{ potential_assignee.assigned_tasks_count }})
{% endif %}
</button>
{% empty %}
<div class="dropdown-item text-muted">{% trans "No users available" %}</div>
{% endfor %}
28 changes: 18 additions & 10 deletions indigo_app/templates/indigo_api/_task_card_single.html
Original file line number Diff line number Diff line change
Expand Up @@ -112,29 +112,37 @@
{% csrf_token %}

<div class="dropdown">
<button class="btn btn-outline-danger btn-sm mt-2 dropdown-toggle" type="button" id="unassignDropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button class="btn btn-outline-danger btn-sm mt-2 dropdown-toggle" type="button"
data-toggle="dropdown"
hx-trigger="click once"
hx-get="{% url 'assign_task_to' place=place.place_code pk=task.pk %}"
hx-target="next .dropdown-menu"
hx-swap="beforeend">
{% trans 'Reassign' %}
</button>
<div class="dropdown-menu" aria-labelledby="unassignDropdownMenuButton">
<button class="dropdown-item mb-1" type="submit" data-confirm="{% trans 'Are you sure you want to unassign this task?' %}" formaction="{% url 'unassign_task' place=task.place.place_code pk=task.pk %}?next={{ request.get_full_path|urlencode }}#task-{{ task.id }}">
{% trans 'Unassign' %}
</button>
<div class="dropdown-divider"></div>
{% include 'indigo_api/_task_assign_to_menu.html' with potential_assignees=task.potential_assignees %}
<div class="dropdown-menu">
<button class="dropdown-item mb-1" type="submit" data-confirm="{% trans 'Are you sure you want to unassign this task?' %}" formaction="{% url 'unassign_task' place=task.place.place_code pk=task.pk %}?next={{ request.get_full_path|urlencode }}#task-{{ task.id }}">
{% trans 'Unassign' %}
</button>
<div class="dropdown-divider"></div>
</div>
</div>
</form>
{% endif %}
</div>
{% elif task.state == 'open' or task.state == 'pending_review' %}
{% if perms.indigo_api.change_task and task.potential_assignees %}
{% if perms.indigo_api.change_task %}
<form method="POST" class="assign-task-form" action="{% url 'assign_task' place=task.place.place_code pk=task.pk %}?next={{ request.get_full_path|urlencode }}#task-{{ task.id }}">
{% csrf_token %}
<div class="dropdown">
<button class="btn btn-outline-primary mt-2 btn-sm dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<button class="btn btn-outline-primary btn-sm mt-2 dropdown-toggle" type="button"
data-toggle="dropdown"
hx-trigger="click once"
hx-get="{% url 'assign_task_to' place=place.place_code pk=task.pk %}"
hx-target="next .dropdown-menu">
{% trans 'Assign to' %}
</button>
{% include 'indigo_api/_task_assign_to_menu.html' with potential_assignees=task.potential_assignees %}
<div class="dropdown-menu"><div class="dropdown-item">...</div></div>
</div>
</form>
{% endif %}
Expand Down
29 changes: 10 additions & 19 deletions indigo_app/templates/indigo_api/_task_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -211,25 +211,16 @@ <h6>{% trans 'Assigned to' %}</h6>
</button>
{% endif %}

{% if task.potential_assignees %}
<div class="dropdown">
<button class="btn btn-outline-secondary mb-3 dropdown-toggle" type="button"
id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
{% trans 'Assign to' %}
</button>
{% include 'indigo_api/_task_assign_to_menu.html' with potential_assignees=task.potential_assignees %}
</div>

{% for potential_assignee in task.potential_assignees %}
{% if potential_assignee == request.user and potential_assignee.too_many_tasks %}
<div class="mb-3">
<i class="fa fa-exclamation-circle text-warning"></i>
{% trans 'Finish your other assigned tasks before assigning this task to yourself.' %}
</div>
{% endif %}
{% endfor %}
{% endif %}
<div class="dropdown">
<button class="btn btn-outline-secondary mb-3 dropdown-toggle" type="button"
data-toggle="dropdown"
hx-trigger="click once"
hx-get="{% url 'assign_task_to' place=place.place_code pk=task.pk %}"
hx-target="next .dropdown-menu">
{% trans 'Assign to' %}
</button>
<div class="dropdown-menu"><div class="dropdown-item">...</div></div>
</div>
</form>
{% endif %}

Expand Down
1 change: 1 addition & 0 deletions indigo_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
path('places/<str:place>/tasks/<int:pk>', tasks.TaskDetailView.as_view(), name='task_detail'),
path('places/<str:place>/tasks/<int:pk>/edit', tasks.TaskEditView.as_view(), name='task_edit'),
path('places/<str:place>/tasks/<int:pk>/assign', tasks.TaskAssignView.as_view(), name='assign_task'),
path('places/<str:place>/tasks/<int:pk>/assign-to', tasks.TaskAssignToView.as_view(), name='assign_task_to'),
path('places/<str:place>/tasks/<int:pk>/unassign', tasks.TaskAssignView.as_view(unassign=True), name='unassign_task'),
path('places/<str:place>/tasks/<int:pk>/projects', tasks.TaskChangeWorkflowsView.as_view(), name='task_workflows'),
path('places/<str:place>/tasks/<int:pk>/blocking-tasks', tasks.TaskChangeBlockingTasksView.as_view(), name='task_blocked_by'),
Expand Down
18 changes: 14 additions & 4 deletions indigo_app/views/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ def get_context_data(self, **kwargs):

# warn when submitting task on behalf of another user
Task.decorate_submission_message(context['tasks'], self)

Task.decorate_potential_assignees(context['tasks'], self.country, self.request.user)
Task.decorate_permissions(context['tasks'], self.request.user)

return context
Expand Down Expand Up @@ -144,8 +142,6 @@ def get_context_data(self, **kwargs):

# warn when submitting task on behalf of another user
Task.decorate_submission_message([task], self)

Task.decorate_potential_assignees([task], self.country, self.request.user)
Task.decorate_permissions([task], self.request.user)

# add work to context
Expand Down Expand Up @@ -348,6 +344,19 @@ def get_redirect_url(self):
return reverse('task_detail', kwargs={'place': self.kwargs['place'], 'pk': self.kwargs['pk']})


class TaskAssignToView(SingleTaskViewBase, DetailView):
template_name = "indigo_api/_task_assign_to_menu.html"

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Task.decorate_potential_assignees([self.object], self.country, self.request.user)
context["potential_assignees"] = self.object.potential_assignees
context["show"] = True
# prevent the form from being changed
context["task"] = None
return context


class TaskAssignView(SingleTaskViewBase, View, SingleObjectMixin):
# permissions
permission_required = ('indigo_api.change_task',)
Expand Down Expand Up @@ -552,6 +561,7 @@ def get(self, request, *args, **kwargs):
def get_queryset(self):
tasks = Task.objects \
.filter(assigned_to=None, country__in=self.request.user.editor.permitted_countries.all())\
.select_related('document__language', 'document__language__language') \
.defer('document__document_xml')\
.order_by('-updated_at')

Expand Down

0 comments on commit 31c2389

Please sign in to comment.