Skip to content

Commit

Permalink
Optimize logic to retrieve Resources in the Localization dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
mathjazz committed Feb 22, 2024
1 parent 1dcd738 commit d077b21
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 156 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@
{{ ResourceList.header(deadline, priority) }}

{% for resource in resources %}
{% if not loop.last %}
{% set main_link = url('pontoon.translate', locale.code, project.slug, resource.title) %}
{% set chart_link = main_link %}
{% set latest_activity = resource.latest_activity %}
{% set chart = resource.chart %}
{{ ResourceList.item(resource, main_link, chart_link, latest_activity, chart, deadline, priority) }}
{% endif %}
{% set main_link = url('pontoon.translate', locale.code, project.slug, resource.title) %}
{% set chart_link = main_link %}
{% set latest_activity = resource.latest_activity %}
{% set chart = resource.chart %}
{{ ResourceList.item(resource, main_link, chart_link, latest_activity, chart, deadline, priority) }}
{% endfor %}

{{ ResourceList.footer() }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ <h4>

{% if deadline %}
<td class="deadline">
{{ Deadline.deadline(resource.resource__deadline, chart.completion_percent == 100) }}
{{ Deadline.deadline(resource.deadline, chart.completion_percent == 100) }}
</td>
{% endif %}

{% if priority %}
<td class="priority">
{{ Priority.priority(resource.resource__priority) }}
{{ Priority.priority(resource.priority) }}
</td>
{% endif %}

Expand Down
118 changes: 30 additions & 88 deletions pontoon/localizations/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from django.urls import reverse
from django.shortcuts import render

from pontoon.base.models import Locale
from pontoon.base.tests import (
EntityFactory,
ResourceFactory,
TranslationFactory,
TranslatedResourceFactory,
Expand All @@ -16,44 +16,22 @@

@pytest.mark.django_db
@patch("pontoon.localizations.views.render", wraps=render)
@patch.object(Locale, "parts_stats")
def test_latest_activity(mock_parts_stats, mock_render, client, project_a, locale_a):
def test_ajax_resources(mock_render, client, project_a, locale_a):
"""Ensure that the latest_activity field is added to parts."""
ProjectLocaleFactory.create(locale=locale_a, project=project_a)

resource = ResourceFactory.create(project=project_a, path="has/stats.po")
resource2 = ResourceFactory.create(project=project_a, path="has/stats2.po")

translation = TranslationFactory.create(entity__resource=resource, locale=locale_a)
TranslatedResourceFactory.create(
entity = EntityFactory.create(resource=resource)
EntityFactory.create(resource=resource2)
translation = TranslationFactory.create(entity=entity, locale=locale_a)

tr = TranslatedResourceFactory.create(
resource=resource2, locale=locale_a, latest_translation=translation
)

mock_parts_stats.return_value = [
{
"title": "has/stats.po",
"resource__path": "has/stats.po",
"resource__total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 1,
"pretranslated_strings": 0,
"strings_with_warnings": 0,
"strings_with_errors": 0,
"resource__deadline": None,
"resource__priority": None,
},
{
"title": "no/stats.po",
"resource__path": "no/stats.po",
"resource__total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 0,
"pretranslated_strings": 0,
"strings_with_warnings": 0,
"strings_with_errors": 0,
"resource__deadline": None,
"resource__priority": None,
},
]
tr.total_strings = 1
tr.save()

client.get(
reverse(
Expand All @@ -65,59 +43,23 @@ def test_latest_activity(mock_parts_stats, mock_render, client, project_a, local

ctx = mock_render.call_args[0][2]

assert ctx["resources"] == [
{
"latest_activity": translation.latest_activity,
"title": "has/stats.po",
"resource__path": "has/stats.po",
"resource__deadline": None,
"resource__priority": None,
"resource__total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 1,
"pretranslated_strings": 0,
"strings_with_errors": 0,
"strings_with_warnings": 0,
"chart": {
"pretranslated_strings": 0,
"total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 1,
"strings_with_errors": 0,
"strings_with_warnings": 0,
"approved_share": 0.0,
"unreviewed_share": 100.0,
"pretranslated_share": 0.0,
"warnings_share": 0.0,
"errors_share": 0.0,
"completion_percent": 0,
},
},
{
"latest_activity": None,
"title": "no/stats.po",
"resource__path": "no/stats.po",
"resource__deadline": None,
"resource__priority": None,
"resource__total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 0,
"pretranslated_strings": 0,
"strings_with_errors": 0,
"strings_with_warnings": 0,
"chart": {
"pretranslated_strings": 0,
"total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 0,
"strings_with_errors": 0,
"strings_with_warnings": 0,
"approved_share": 0.0,
"unreviewed_share": 0.0,
"pretranslated_share": 0.0,
"warnings_share": 0.0,
"errors_share": 0.0,
"completion_percent": 0,
},
},
]
assert len(ctx["resources"]) == 2

assert ctx["resources"][0].title == "has/stats2.po"
assert ctx["resources"][0].deadline is None
assert ctx["resources"][0].priority is None
assert ctx["resources"][0].latest_activity == translation.latest_activity
assert ctx["resources"][0].chart == {
"pretranslated_strings": 0,
"total_strings": 1,
"approved_strings": 0,
"unreviewed_strings": 0,
"strings_with_errors": 0,
"strings_with_warnings": 0,
"approved_share": 0.0,
"unreviewed_share": 0.0,
"pretranslated_share": 0.0,
"warnings_share": 0.0,
"errors_share": 0.0,
"completion_percent": 0,
}
93 changes: 34 additions & 59 deletions pontoon/localizations/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import math
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Q
Expand Down Expand Up @@ -42,7 +41,15 @@ def localization(request, code, slug):
project=project,
)

resource_count = len(locale.parts_stats(project)) - 1
resource_count = (
TranslatedResource.objects.filter(
resource__project=project,
locale=locale,
resource__entities__obsolete=False,
)
.distinct()
.count()
)

return render(
request,
Expand Down Expand Up @@ -73,75 +80,43 @@ def ajax_resources(request, code, slug):
# Check if ProjectLocale exists
get_object_or_404(ProjectLocale, locale=locale, project=project)

# Amend the parts dict with latest activity info.
translatedresources_qs = TranslatedResource.objects.filter(
resource__project=project, locale=locale
).prefetch_related("resource", "latest_translation__user")
# Prefetch data needed for the latest activity column
translatedresources = (
TranslatedResource.objects.filter(
resource__project=project,
locale=locale,
resource__entities__obsolete=False,
)
.order_by("resource__path")
.prefetch_related(
"resource", "latest_translation__user", "latest_translation__approved_user"
)
.distinct()
)

if not len(translatedresources_qs):
if not len(translatedresources):
raise Http404

translatedresources = {s.resource.path: s for s in translatedresources_qs}
translatedresources = dict(list(translatedresources.items()))
parts = locale.parts_stats(project)

resource_priority_map = project.resource_priority_map()

for part in parts:
part["resource__priority"] = resource_priority_map.get(part["title"], None)

translatedresource = translatedresources.get(part["title"], None)
if translatedresource and translatedresource.latest_translation:
part[
"latest_activity"
] = translatedresource.latest_translation.latest_activity
else:
part["latest_activity"] = None

part["chart"] = {
"unreviewed_strings": part["unreviewed_strings"],
"pretranslated_strings": part["pretranslated_strings"],
"strings_with_errors": part["strings_with_errors"],
"strings_with_warnings": part["strings_with_warnings"],
"total_strings": part["resource__total_strings"],
"approved_strings": part["approved_strings"],
"approved_share": round(
part["approved_strings"] / part["resource__total_strings"] * 100
),
"unreviewed_share": round(
part["unreviewed_strings"] / part["resource__total_strings"] * 100
),
"pretranslated_share": round(
part["pretranslated_strings"] / part["resource__total_strings"] * 100
),
"errors_share": round(
part["strings_with_errors"] / part["resource__total_strings"] * 100
),
"warnings_share": round(
part["strings_with_warnings"] / part["resource__total_strings"] * 100
),
"completion_percent": int(
math.floor(
(
part["approved_strings"]
+ part["pretranslated_strings"]
+ part["strings_with_warnings"]
)
/ part["resource__total_strings"]
* 100
)
),
}
for tr in translatedresources:
tr.title = tr.resource.path
tr.deadline = tr.resource.deadline
tr.priority = resource_priority_map.get(tr.resource.path, None)
tr.latest_activity = (
tr.latest_translation.latest_activity if tr.latest_translation else None
)
tr.chart = TranslatedResource.get_chart_dict(tr)

return render(
request,
"localizations/includes/resources.html",
{
"locale": locale,
"project": project,
"resources": parts,
"deadline": any(part["resource__deadline"] for part in parts),
"priority": any(part["resource__priority"] for part in parts),
"resources": translatedresources,
"deadline": any(tr.resource.deadline for tr in translatedresources),
"priority": any(tr.priority for tr in translatedresources),
},
)

Expand Down

0 comments on commit d077b21

Please sign in to comment.