Skip to content

Commit f2fc978

Browse files
committed
Add new fields to project admin form
1 parent 5946e9f commit f2fc978

5 files changed

Lines changed: 137 additions & 37 deletions

File tree

pontoon/administration/forms.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ class ProjectForm(forms.ModelForm):
3838

3939
def clean(self):
4040
cleaned_data = super().clean()
41+
set_locales_from_repo = cleaned_data.get("set_locales_from_repo")
4142
locales_readonly = cleaned_data.get("locales_readonly")
4243
locales = cleaned_data.get("locales")
43-
if not (locales or locales_readonly):
44+
if not (set_locales_from_repo or locales or locales_readonly):
4445
raise ValidationError("At least one locale must be selected.")
4546

4647
class Meta:
@@ -61,6 +62,8 @@ class Meta:
6162
"sync_disabled",
6263
"tags_enabled",
6364
"pretranslation_enabled",
65+
"set_locales_from_repo",
66+
"set_translated_resources_from_repo",
6467
"visibility",
6568
)
6669

pontoon/administration/static/css/admin_project.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ form a:visited {
184184
text-transform: uppercase;
185185
}
186186

187+
.locales {
188+
margin-top: 40px;
189+
}
190+
187191
.double-list-selector .locale.select .menu {
188192
background: transparent;
189193
border-bottom: 1px solid var(--main-border-1);

pontoon/administration/static/js/admin_project.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ $(function () {
7676

7777
button.addClass('in-progress').html('Syncing...');
7878

79+
const slug = $('#id_slug').val();
7980
$.ajax({
80-
url: '/admin/projects/' + $('#id_slug').val() + '/sync/',
81+
url: `/admin/projects/${slug}/sync/`,
8182
success: function () {
8283
button.html('Started');
8384
},
@@ -105,8 +106,9 @@ $(function () {
105106

106107
button.addClass('in-progress').html('Pretranslating...');
107108

109+
const slug = $('#id_slug').val();
108110
$.ajax({
109-
url: '/admin/projects/' + $('#id_slug').val() + '/pretranslate/',
111+
url: `/admin/projects/${slug}/pretranslate/`,
110112
success: function () {
111113
button.html('Started');
112114
},
@@ -166,6 +168,51 @@ $(function () {
166168
});
167169
});
168170

171+
const setLocalesCheckbox = $('#id_set_locales_from_repo');
172+
const configFileInput = $('#id_configuration_file');
173+
function setLocalesUpdate() {
174+
const configFile = configFileInput.val();
175+
let reqSync = configFile !== configFileInput.data('init');
176+
177+
const controls = $('.repo-locale-control');
178+
if ($('#id_data_source').val() === 'repository') {
179+
controls.show();
180+
} else {
181+
controls.hide();
182+
setLocalesCheckbox.prop('checked', false);
183+
reqSync = false;
184+
}
185+
186+
const label = $('#id_set_locales_from_repo + span');
187+
const hint = $('#hint_set_locales_from_repo');
188+
if (configFile) {
189+
label.text('Read locales from configuration file');
190+
hint.hide();
191+
} else {
192+
label.text('Set locales from repository');
193+
hint.show();
194+
}
195+
196+
const setLocalesFromRepo = setLocalesCheckbox.prop('checked');
197+
const trDiv = $('#translated_resources_from_repo');
198+
const locales = $('.locales, .locales-toolbar');
199+
if (setLocalesFromRepo) {
200+
trDiv.toggle(!configFile);
201+
locales.hide();
202+
reqSync ||= setLocalesFromRepo !== setLocalesCheckbox.data('init');
203+
} else {
204+
trDiv.hide();
205+
locales.show();
206+
}
207+
208+
$('button.save').text(reqSync ? 'Save & sync project' : 'Save project');
209+
}
210+
setLocalesCheckbox.data('init', setLocalesCheckbox.prop('checked'));
211+
setLocalesCheckbox.on('change', setLocalesUpdate);
212+
configFileInput.data('init', configFileInput.val());
213+
configFileInput.on('change', setLocalesUpdate);
214+
setLocalesUpdate();
215+
169216
self.NProgressUnbind();
170217

171218
// Set locales to existing projects to be copied to the current project

pontoon/administration/templates/admin_project.html

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,29 @@ <h1>
5454

5555
<h3>Locales</h3>
5656

57-
<div class="locales clearfix">
57+
<div class="repo-locale-control checkbox clearfix">
58+
<label for="id_set_locales_from_repo">
59+
{{ form.set_locales_from_repo }}
60+
<span></span>
61+
</label>
62+
<span id="hint_set_locales_from_repo"
63+
>Locale is available if target directory is present.</span
64+
>
65+
</div>
66+
67+
<div
68+
class="repo-locale-control checkbox clearfix"
69+
id="translated_resources_from_repo"
70+
style="display: none"
71+
>
72+
<label for="id_set_translated_resources_from_repo">
73+
{{ form.set_translated_resources_from_repo }} Set per-resource
74+
localizability from repository
75+
</label>
76+
Resource is available if target file is present in locale directory.
77+
</div>
78+
79+
<div class="locales clearfix" style="display: none">
5880
{{ admin_team_selector.render(locales_available, locales_selected, locales_readonly) }}
5981
{{ form.locales }}
6082
{{ form.locales.errors }}

pontoon/administration/views.py

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import csv
22
import logging
33

4+
from typing import cast
5+
46
from django.conf import settings
57
from django.contrib.auth.decorators import login_required
68
from django.core.exceptions import PermissionDenied
@@ -33,6 +35,8 @@
3335
from pontoon.pretranslation.tasks import pretranslate_task
3436
from pontoon.sync.tasks import sync_project_task
3537

38+
from ..base.models.project import ProjectQuerySet
39+
3640

3741
log = logging.getLogger(__name__)
3842

@@ -127,6 +131,8 @@ def manage_project(request, slug=None, template="admin_project.html"):
127131
subtitle = "Add project"
128132
pk = None
129133
project = None
134+
prev_config_file = None
135+
prev_set_locales_from_repo = False
130136

131137
# Save project
132138
if request.method == "POST":
@@ -143,7 +149,11 @@ def manage_project(request, slug=None, template="admin_project.html"):
143149
# Update existing project
144150
try:
145151
pk = request.POST["pk"]
146-
project = Project.objects.visible_for(request.user).get(pk=pk)
152+
project = (
153+
cast(ProjectQuerySet, Project.objects)
154+
.visible_for(request.user)
155+
.get(pk=pk)
156+
)
147157
form = ProjectForm(request.POST, instance=project)
148158
# Needed if form invalid
149159
repo_formset = RepositoryInlineFormSet(request.POST, instance=project)
@@ -156,6 +166,8 @@ def manage_project(request, slug=None, template="admin_project.html"):
156166
request.POST, instance=project
157167
)
158168
subtitle = "Edit project"
169+
prev_config_file = project.configuration_file
170+
prev_set_locales_from_repo = project.set_locales_from_repo
159171

160172
# Add a new project
161173
except MultiValueDictKeyError:
@@ -166,7 +178,7 @@ def manage_project(request, slug=None, template="admin_project.html"):
166178
tag_formset = None
167179

168180
if form.is_valid():
169-
project = form.save(commit=False)
181+
project = cast(Project, form.save(commit=False))
170182
repo_formset = RepositoryInlineFormSet(request.POST, instance=project)
171183
external_resource_formset = ExternalResourceInlineFormSet(
172184
request.POST, instance=project
@@ -180,38 +192,43 @@ def manage_project(request, slug=None, template="admin_project.html"):
180192
)
181193
if formsets_valid:
182194
project.save()
183-
184-
# Manually save ProjectLocales due to intermediary model
185-
locales_form = form.cleaned_data.get("locales", [])
186-
locales_readonly_form = form.cleaned_data.get("locales_readonly", [])
187-
locales = locales_form | locales_readonly_form
188-
189-
(
190-
ProjectLocale.objects.filter(project=project)
191-
.exclude(locale__pk__in=[loc.pk for loc in locales])
192-
.delete()
193-
)
194-
195-
for locale in locales:
196-
# The implicit pre_save and post_save signals sent here are required
197-
# to maintain django-guardian permissions.
198-
ProjectLocale.objects.get_or_create(project=project, locale=locale)
199-
200-
project_locales = ProjectLocale.objects.filter(project=project)
201-
202-
# Update readonly flags
203-
locales_readonly_pks = [loc.pk for loc in locales_readonly_form]
204-
project_locales.filter(readonly=True).exclude(
205-
locale__pk__in=locales_readonly_pks
206-
).update(readonly=False)
207-
project_locales.filter(
208-
locale__pk__in=locales_readonly_pks, readonly=False
209-
).update(readonly=True)
195+
pk = project.pk
196+
data = form.cleaned_data
197+
198+
set_locales_from_repo = data.get("set_locales_from_repo", False)
199+
200+
if set_locales_from_repo:
201+
project_locales = ProjectLocale.objects.filter(project=project)
202+
else:
203+
# Manually save ProjectLocales due to intermediary model
204+
locales_form = data.get("locales", set())
205+
locales_readonly_form = data.get("locales_readonly", set())
206+
locales = locales_form | locales_readonly_form
207+
208+
ProjectLocale.objects.filter(project=project).exclude(
209+
locale__pk__in=[loc.pk for loc in locales]
210+
).delete()
211+
212+
for locale in locales:
213+
# The implicit pre_save and post_save signals sent here are required
214+
# to maintain django-guardian permissions.
215+
ProjectLocale.objects.get_or_create(
216+
project=project, locale=locale
217+
)
218+
219+
project_locales = ProjectLocale.objects.filter(project=project)
220+
221+
# Update readonly flags
222+
locales_readonly_pks = [loc.pk for loc in locales_readonly_form]
223+
project_locales.filter(readonly=True).exclude(
224+
locale__pk__in=locales_readonly_pks
225+
).update(readonly=False)
226+
project_locales.filter(
227+
locale__pk__in=locales_readonly_pks, readonly=False
228+
).update(readonly=True)
210229

211230
# Update pretranslate flags
212-
locales_pretranslate_form = form.cleaned_data.get(
213-
"locales_pretranslate", []
214-
)
231+
locales_pretranslate_form = data.get("locales_pretranslate", [])
215232
locales_pretranslate_pks = [loc.pk for loc in locales_pretranslate_form]
216233
project_locales.filter(pretranslation_enabled=True).exclude(
217234
locale__pk__in=locales_pretranslate_pks,
@@ -239,7 +256,14 @@ def manage_project(request, slug=None, template="admin_project.html"):
239256
if project.tags_enabled:
240257
tag_formset = TagInlineFormSet(instance=project)
241258
subtitle += ". Saved."
242-
pk = project.pk
259+
260+
if project.data_source == Project.DataSource.REPOSITORY and (
261+
set_locales_from_repo
262+
and not prev_set_locales_from_repo
263+
or data.get("configuration_file") != prev_config_file
264+
):
265+
sync_project_task.delay(project.pk)
266+
subtitle += " Sync started."
243267
else:
244268
subtitle += ". Error."
245269
else:

0 commit comments

Comments
 (0)