Skip to content

Commit

Permalink
Merge main into branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Harmit Goswami committed Dec 3, 2024
2 parents ed2e37e + 6273ecb commit 27cd4e1
Show file tree
Hide file tree
Showing 78 changed files with 2,885 additions and 813 deletions.
10 changes: 10 additions & 0 deletions docs/admin/deployment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ you create:
It allows to explain what type of communication to expect and to link to
deployment-specific privacy notices among other things.

``EMAIL_COMMUNICATIONS_FOOTER_PRE_TEXT``
Optional. Text to be shown in the footer of the non-transactional emails sent
using the Messaging Center, just above the unsubscribe text.

``ENABLE_BUGS_TAB``
Optional. Enables Bugs tab on team pages, which pulls team data from
bugzilla.mozilla.org. Specific for Mozilla deployments.
Expand Down Expand Up @@ -296,6 +300,12 @@ you create:
Optional. Set your `SYSTRAN Translate API key` to use machine translation
by SYSTRAN.

``TBX_DESCRIPTION``
Optional. Description to be used in the header of the Terminology (.TBX) files.

``TBX_TITLE``
Optional. Title to be used in the header of the Terminology (.TBX) files.

``THROTTLE_ENABLED``
Optional. Enables traffic throttling based on IP address (default: ``False``).

Expand Down
1 change: 1 addition & 0 deletions pontoon/actionlog/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class ActionLogAdmin(admin.ModelAdmin):
"performed_by",
"entity",
"translation",
"tm_entries",
)
readonly_fields = ("created_at",)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 4.2.16 on 2024-11-14 00:18

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("base", "0067_remove_userprofile_community_builder_level_and_more"),
("actionlog", "0005_migrate_old_translations_to_actionlog"),
]

operations = [
migrations.AddField(
model_name="actionlog",
name="tm_entries",
field=models.ManyToManyField(blank=True, to="base.translationmemoryentry"),
),
migrations.AlterField(
model_name="actionlog",
name="action_type",
field=models.CharField(
choices=[
("translation:created", "Translation created"),
("translation:deleted", "Translation deleted"),
("translation:approved", "Translation approved"),
("translation:unapproved", "Translation unapproved"),
("translation:rejected", "Translation rejected"),
("translation:unrejected", "Translation unrejected"),
("comment:added", "Comment added"),
("tm_entry:deleted", "TranslationMemoryEntry deleted"),
("tm_entries:edited", "TranslationMemoryEntries edited"),
("tm_entries:uploaded", "TranslationMemoryEntries uploaded"),
],
max_length=50,
),
),
]
80 changes: 60 additions & 20 deletions pontoon/actionlog/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,28 @@ class ActionType(models.TextChoices):
TRANSLATION_UNREJECTED = "translation:unrejected", "Translation unrejected"
# A comment has been added.
COMMENT_ADDED = "comment:added", "Comment added"
# A TranslationMemoryEntry has been deleted.
TM_ENTRY_DELETED = "tm_entry:deleted", "TranslationMemoryEntry deleted"
# TranslationMemoryEntries have been edited.
TM_ENTRIES_EDITED = "tm_entries:edited", "TranslationMemoryEntries edited"
# TranslationMemoryEntries have been uploaded.
TM_ENTRIES_UPLOADED = "tm_entries:uploaded", "TranslationMemoryEntries uploaded"

action_type = models.CharField(max_length=50, choices=ActionType.choices)
created_at = models.DateTimeField(default=timezone.now)
performed_by = models.ForeignKey(
"auth.User", models.SET_NULL, related_name="actions", null=True
)

# Used to track on what translation related actions apply.
# Used to track translation-related actions.
translation = models.ForeignKey(
"base.Translation",
models.CASCADE,
blank=True,
null=True,
)

# Used when a translation has been deleted or a team comment has been added.
# Used when a translation or TM entry has been deleted, or a team comment has been added.
entity = models.ForeignKey(
"base.Entity",
models.CASCADE,
Expand All @@ -48,6 +54,12 @@ class ActionType(models.TextChoices):
null=True,
)

# Used to track actions related to TM entries.
tm_entries = models.ManyToManyField(
"base.TranslationMemoryEntry",
blank=True,
)

def validate_action_type_choice(self):
valid_types = self.ActionType.values
if self.action_type not in valid_types:
Expand All @@ -58,31 +70,59 @@ def validate_action_type_choice(self):
)

def validate_foreign_keys_per_action(self):
if self.action_type == self.ActionType.TRANSLATION_DELETED and (
self.translation or not self.entity or not self.locale
if self.action_type in (
self.ActionType.TRANSLATION_DELETED,
self.ActionType.TM_ENTRY_DELETED,
):
raise ValidationError(
f'For action type "{self.action_type}", `entity` and `locale` are required'
)
if self.translation or not self.entity or not self.locale:
raise ValidationError(
f'For action type "{self.action_type}", only `entity` and `locale` are accepted'
)

elif self.action_type == self.ActionType.COMMENT_ADDED:
if not (
(self.translation and not self.locale and not self.entity)
or (not self.translation and self.locale and self.entity)
):
raise ValidationError(
f'For action type "{self.action_type}", either `translation` or `entity` and `locale` are accepted'
)

if self.action_type == self.ActionType.COMMENT_ADDED and not (
(self.translation and not self.locale and not self.entity)
or (not self.translation and self.locale and self.entity)
elif self.action_type in (
self.ActionType.TRANSLATION_CREATED,
self.ActionType.TRANSLATION_APPROVED,
self.ActionType.TRANSLATION_UNAPPROVED,
self.ActionType.TRANSLATION_REJECTED,
self.ActionType.TRANSLATION_UNREJECTED,
):
raise ValidationError(
f'For action type "{self.action_type}", either `translation` or `entity` and `locale` are required'
)
if not self.translation or self.entity or self.locale:
raise ValidationError(
f'For action type "{self.action_type}", only `translation` is accepted'
)

if (
self.action_type != self.ActionType.TRANSLATION_DELETED
and self.action_type != self.ActionType.COMMENT_ADDED
) and (not self.translation or self.entity or self.locale):
raise ValidationError(
f'For action type "{self.action_type}", only `translation` is accepted'
)
elif self.action_type in (
self.ActionType.TM_ENTRIES_EDITED,
self.ActionType.TM_ENTRIES_UPLOADED,
):
if self.translation or self.entity or self.locale:
raise ValidationError(
f'For action type "{self.action_type}", only `tm_entries` is accepted'
)

def validate_many_to_many_relationships_per_action(self):
if self.action_type in (
self.ActionType.TM_ENTRIES_EDITED,
self.ActionType.TM_ENTRIES_UPLOADED,
):
if not self.tm_entries or self.translation or self.entity or self.locale:
raise ValidationError(
f'For action type "{self.action_type}", only `tm_entries` is accepted'
)

def save(self, *args, **kwargs):
self.validate_action_type_choice()
self.validate_foreign_keys_per_action()

super().save(*args, **kwargs)

self.validate_many_to_many_relationships_per_action()
42 changes: 42 additions & 0 deletions pontoon/actionlog/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pontoon.actionlog import utils
from pontoon.actionlog.models import ActionLog
from pontoon.test.factories import TranslationMemoryFactory


@pytest.mark.django_db
Expand Down Expand Up @@ -88,3 +89,44 @@ def test_log_action_valid_with_entity_locale(user_a, entity_a, locale_a):
)
assert len(log) == 1
assert log[0].action_type == ActionLog.ActionType.TRANSLATION_DELETED


@pytest.mark.django_db
def test_log_action_valid_with_tm_entry_deleted(user_a, entity_a, locale_a):
utils.log_action(
ActionLog.ActionType.TM_ENTRY_DELETED,
user_a,
entity=entity_a,
locale=locale_a,
)

log = ActionLog.objects.filter(
performed_by=user_a,
entity=entity_a,
locale=locale_a,
)
assert len(log) == 1
assert log[0].action_type == ActionLog.ActionType.TM_ENTRY_DELETED


@pytest.mark.django_db
def test_log_action_valid_with_tm_entries_edited(user_a, entity_a, locale_a):
tm_entry = TranslationMemoryFactory.create(
entity=entity_a,
source=entity_a.string,
target="tm_translation",
locale=locale_a,
)

utils.log_action(
ActionLog.ActionType.TM_ENTRIES_EDITED,
user_a,
tm_entries=[tm_entry],
)

log = ActionLog.objects.filter(
performed_by=user_a,
tm_entries=tm_entry.pk,
)
assert len(log) == 1
assert log[0].action_type == ActionLog.ActionType.TM_ENTRIES_EDITED
9 changes: 7 additions & 2 deletions pontoon/actionlog/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ def log_action(
translation=None,
entity=None,
locale=None,
tm_entries=None,
):
"""Save a new action in the database.
Expand All @@ -17,10 +18,11 @@ def log_action(
:arg Translation translation: The Translation the action was performed on.
:arg Entity entity:
The Entity the action was performed on.
Only used for the "translation:deleted" action.
Only used for the "translation:deleted", "tm_entries:deleted" and "comment:added" actions.
:arg Locale locale:
The Locale the action was performed on.
Only used for the "translation:deleted" action.
Only used for the "translation:deleted", "tm_entries:deleted" and "comment:added" actions.
:arg list tm_entries: A list of TranslationMemoryEntries the action was performed on.
:returns: None
"""
Expand All @@ -32,3 +34,6 @@ def log_action(
locale=locale,
)
action.save()

if tm_entries:
action.tm_entries.set(tm_entries)
25 changes: 24 additions & 1 deletion pontoon/api/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from graphene_django.views import GraphQLView

from django.urls import re_path
from django.urls import include, path, re_path

from pontoon.api import views
from pontoon.api.schema import schema
from pontoon.settings import DEV

Expand All @@ -13,4 +14,26 @@
r"^graphql/?$",
GraphQLView.as_view(schema=schema, graphiql=DEV),
),
# API v1
path(
"api/v1/",
include(
[
path(
# User actions
"user-actions/",
include(
[
# In a given project
path(
"<str:date>/project/<slug:slug>/",
views.get_user_actions,
name="pontoon.api.get_user_actions.project",
),
]
),
),
]
),
),
]
Loading

0 comments on commit 27cd4e1

Please sign in to comment.