Skip to content

Commit 5c0f989

Browse files
committed
translate workspace
1 parent 3e741bc commit 5c0f989

File tree

7 files changed

+227
-19
lines changed

7 files changed

+227
-19
lines changed

django/gsmap/admin.py

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from django.contrib.gis import admin
2+
from django.contrib.admin import SimpleListFilter
23
from django.contrib.postgres import fields
34
from django.utils.translation import gettext as _
45
from django_json_widget.widgets import JSONEditorWidget
56
from django.utils.html import mark_safe
67
from django.contrib import messages
7-
from django.forms import ModelForm
88
from django.forms.widgets import Textarea, TextInput
99
import requests
1010
from parler.admin import TranslatableAdmin
@@ -118,7 +118,7 @@ def save_model(self, request, obj, form, change):
118118
)
119119

120120

121-
class WorkspaceAdmin(admin.OSMGeoAdmin):
121+
class WorkspaceAdmin(TranslatableAdmin):
122122
readonly_fields = ('id', 'created', 'modified', 'get_absolute_link')
123123
fieldsets = (
124124
(_('Meta'), {
@@ -127,7 +127,7 @@ class WorkspaceAdmin(admin.OSMGeoAdmin):
127127
)
128128
}),
129129
(_('Main'), {
130-
'fields': ('title', 'description', 'snapshots'),
130+
'fields': ('group', 'title', 'description', 'snapshots'),
131131
}),
132132
(_('Annotations'), {
133133
'fields': (
@@ -138,18 +138,61 @@ class WorkspaceAdmin(admin.OSMGeoAdmin):
138138
)
139139
}),
140140
)
141-
list_display = ('id', 'title', 'annotations_open', 'created', 'modified')
142-
search_fields = ['title']
141+
list_display = ('title', 'group', 'get_absolute_link', 'mode', 'annotations_contact_name', 'annotations_contact_email', 'findme_enabled', 'annotations_open', 'annotations_likes_enabled', 'polygon_open', 'polygon_likes_enabled', 'created', 'modified')
142+
list_filter = ['mode']
143+
search_fields = ['title', 'description']
143144

144145
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
145146
if db_field.name == 'snapshots' or db_field.name == 'categories' or db_field.name == 'usergroups':
146147
kwargs['widget'] = SortedFilteredSelectMultiple()
147148
return super().formfield_for_manytomany(db_field, request, **kwargs)
149+
150+
def get_queryset(self, request):
151+
qs = super().get_queryset(request)
152+
if not request.user.is_superuser:
153+
return qs.select_related('group').filter(group__in=request.user.groups.all())
154+
return qs
148155

149156
class AttachementInline(admin.TabularInline):
150157
model = Attachement
151158

152-
class AnnotationAdmin(admin.OSMGeoAdmin):
159+
class AnnotationWorkspaceFilter(SimpleListFilter):
160+
title = _('Workspace')
161+
parameter_name = 'workspace'
162+
163+
def lookups(self, request, model_admin):
164+
return [(x.id, x.title) for x in Workspace.objects.all() if request.user.is_superuser or x.group in request.user.groups.all()]
165+
166+
def queryset(self, request, queryset):
167+
if self.value():
168+
return queryset.filter(workspace__id=self.value())
169+
return queryset
170+
171+
class CategoryGroupFilter(SimpleListFilter):
172+
title = _('Category')
173+
parameter_name = 'category'
174+
175+
def lookups(self, request, model_admin):
176+
return [(x.id, f'{x.group.name}/{x.name}') for x in Category.objects.all() if request.user.is_superuser or x.group in request.user.groups.all()]
177+
178+
def queryset(self, request, queryset):
179+
if self.value():
180+
return queryset.filter(category__id=self.value())
181+
return queryset
182+
183+
class UsergroupGroupFilter(SimpleListFilter):
184+
title = _('Usergroup')
185+
parameter_name = 'usergroup'
186+
187+
def lookups(self, request, model_admin):
188+
return [(x.pk, f'{x.group.name}/{x.name}') for x in Usergroup.objects.all() if request.user.is_superuser or x.group in request.user.groups.all()]
189+
190+
def queryset(self, request, queryset):
191+
if self.value():
192+
return queryset.filter(usergroup__pk=self.value())
193+
return queryset
194+
195+
class AnnotationAdmin(admin.ModelAdmin):
153196
readonly_fields = ('id','created', 'modified')
154197
fieldsets = (
155198
(_('Meta'), {
@@ -175,9 +218,15 @@ class AnnotationAdmin(admin.OSMGeoAdmin):
175218
'workspace',
176219
)
177220
inlines = [ AttachementInline, ]
178-
list_filter = ('workspace', 'category', 'kind', 'usergroup')
221+
list_filter = (AnnotationWorkspaceFilter, CategoryGroupFilter, 'kind', UsergroupGroupFilter,)
179222
search_fields = ('id', 'data')
180223

224+
def get_queryset(self, request):
225+
queryset = super().get_queryset(request)
226+
if not request.user.is_superuser:
227+
return queryset.select_related('workspace__group').filter(workspace__group__in=request.user.groups.all())
228+
return queryset
229+
181230
class CategoryAdminForm(TranslatableModelForm):
182231
class Meta:
183232
model = Category
@@ -197,22 +246,28 @@ class CategoryAdmin(TranslatableAdmin): # admin.OSMGeoAdmin,
197246
readonly_fields = ('id', 'created', 'modified')
198247
fieldsets = (
199248
(_('Meta'), {
200-
'fields': ('deleted', 'hide_in_list', 'namespace'),
249+
'fields': ('deleted', 'hide_in_list'),
201250
}),
202251
(_('Category'), {
203-
'fields': ('name', 'icon', 'color'),
252+
'fields': ('group', 'name', 'icon', 'color'),
204253
}),
205254
)
206255

207256
list_display = (
208257
'name',
209-
'namespace',
258+
'group',
210259
'color',
211260
'hide_in_list'
212261
)
213262

214-
list_filter = ('namespace', 'hide_in_list', 'color')
215-
search_fields = ('id', 'translations__name', 'namespace')
263+
list_filter = (CategoryGroupFilter, 'hide_in_list', 'color')
264+
search_fields = ('id', 'translations__name')
265+
266+
def get_queryset(self, request):
267+
qs = super().get_queryset(request)
268+
if not request.user.is_superuser:
269+
return qs.select_related('group').filter(group__in=request.user.groups.all())
270+
return qs
216271

217272
class UsergroupAdmin(TranslatableAdmin): # admin.OSMGeoAdmin,
218273
readonly_fields = ('created', 'modified')
@@ -221,17 +276,32 @@ class UsergroupAdmin(TranslatableAdmin): # admin.OSMGeoAdmin,
221276
'fields': ('deleted', 'created', 'modified'),
222277
}),
223278
(_('Category'), {
224-
'fields': ('key', 'name'),
279+
'fields': ('group', 'key', 'name'),
225280
}),
226281
)
227282

228283
list_display = (
229284
'key',
285+
'group',
230286
'name',
231287
)
232288

233289
search_fields = ('id', 'name', 'key')
234290

291+
def get_queryset(self, request):
292+
qs = super().get_queryset(request)
293+
if not request.user.is_superuser:
294+
return qs.select_related('group').filter(group__in=request.user.groups.all())
295+
return qs
296+
297+
def _has_change_permission(needed, group, user_groups):
298+
for g in user_groups:
299+
if g == group:
300+
for p in g.permissions.all():
301+
if p.codename == needed:
302+
return True
303+
return False
304+
235305
admin.site.register(Municipality, MunicipalityAdmin)
236306
admin.site.register(Snapshot, SnapshotAdmin)
237307
admin.site.register(Workspace, WorkspaceAdmin)

django/gsmap/migrations/0013_auto_20200405_1555.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.db import migrations, models
44
import gsmap.models
55
import sortedm2m.fields
6+
import parler.models
67

78

89
class Migration(migrations.Migration):
@@ -30,5 +31,6 @@ class Migration(migrations.Migration):
3031
options={
3132
'ordering': ['-created'],
3233
},
34+
bases=(parler.models.TranslatableModelMixin, models.Model),
3335
),
3436
]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Generated by Django 3.1.13 on 2022-02-23 13:23
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
import parler.fields
6+
import parler.models
7+
import sortedm2m.fields
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('gsmap', '0036_auto_20220223_1048'),
14+
]
15+
16+
operations = [
17+
migrations.RenameField(
18+
model_name='workspace',
19+
old_name='title',
20+
new_name='_title',
21+
),
22+
migrations.RenameField(
23+
model_name='workspace',
24+
old_name='description',
25+
new_name='_description',
26+
),
27+
migrations.CreateModel(
28+
name='WorkspaceTranslation',
29+
fields=[
30+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31+
('language_code', models.CharField(db_index=True, max_length=15, verbose_name='Language')),
32+
('title', models.CharField(default='', max_length=150)),
33+
('description', models.TextField(default='')),
34+
('master', parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='gsmap.workspace')),
35+
],
36+
options={
37+
'verbose_name': 'workspace Translation',
38+
'db_table': 'gsmap_workspace_translation',
39+
'db_tablespace': '',
40+
'managed': True,
41+
'default_permissions': (),
42+
'unique_together': {('language_code', 'master')},
43+
},
44+
bases=(parler.models.TranslatedFieldsModelMixin, models.Model),
45+
),
46+
]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Generated by Django 3.1.13 on 2022-02-23 13:24
2+
3+
from django.db import migrations
4+
from django.conf import settings
5+
from django.core.exceptions import ObjectDoesNotExist
6+
7+
8+
def forwards_func(apps, schema_editor):
9+
Workspace = apps.get_model('gsmap', 'Workspace')
10+
WorkspaceTranslation = apps.get_model('gsmap', 'WorkspaceTranslation')
11+
12+
for object in Workspace.objects.all():
13+
WorkspaceTranslation.objects.create(
14+
master_id=object.pk,
15+
language_code=settings.PARLER_DEFAULT_LANGUAGE_CODE,
16+
title=object._title,
17+
description=object._description
18+
)
19+
20+
def backwards_func(apps, schema_editor):
21+
Workspace = apps.get_model('gsmap', 'Workspace')
22+
WorkspaceTranslation = apps.get_model('gsmap', 'WorkspaceTranslation')
23+
24+
for object in Workspace.objects.all():
25+
translation = _get_translation(object, WorkspaceTranslation)
26+
object._title = translation.title
27+
object._description = translation.description
28+
object.save() # Note this only calls Model.save()
29+
30+
def _get_translation(object, WorkspaceTranslation):
31+
translations = WorkspaceTranslation.objects.filter(master_id=object.pk)
32+
try:
33+
# Try default translation
34+
return translations.get(language_code=settings.PARLER_DEFAULT_LANGUAGE_CODE)
35+
except ObjectDoesNotExist:
36+
try:
37+
# Try default language
38+
return translations.get(language_code=settings.LANGUAGE_CODE)
39+
except ObjectDoesNotExist:
40+
# Maybe the object was translated only in a specific language?
41+
# Hope there is a single translation
42+
return translations.get()
43+
44+
class Migration(migrations.Migration):
45+
46+
dependencies = [
47+
('gsmap', '0037_add_translation_model'),
48+
]
49+
50+
operations = [
51+
migrations.RunPython(forwards_func, backwards_func),
52+
]
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Generated by Django 3.1.13 on 2022-02-23 16:00
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('gsmap', '0038_migrate_translatable_fields'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='workspace',
15+
name='_description',
16+
),
17+
migrations.RemoveField(
18+
model_name='workspace',
19+
name='_title',
20+
),
21+
]

django/gsmap/models.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
from parler.models import TranslatableModel, TranslatedFields
3333

34-
34+
from django.contrib.auth.models import Group
3535
from gsuser.models import User
3636
from main.utils import get_website
3737

@@ -376,9 +376,6 @@ class Meta:
376376
created = models.DateTimeField(auto_now_add=True)
377377
modified = models.DateTimeField(auto_now=True)
378378

379-
title = models.CharField(max_length=150, default='')
380-
description = models.TextField(default='')
381-
382379
snapshots = SortedManyToManyField(Snapshot)
383380

384381
categories = SortedManyToManyField(Category)
@@ -402,6 +399,11 @@ class Meta:
402399

403400
findme_enabled = models.BooleanField(default=False, help_text="Enable 'Find Me'", verbose_name="Find me enabled")
404401

402+
translations = TranslatedFields(
403+
title = models.CharField(max_length=150, default=''),
404+
description = models.TextField(default=''),
405+
)
406+
405407
def get_absolute_link(self):
406408
website = get_website(Site.objects.get_current())
407409
return format_html(
@@ -430,7 +432,7 @@ def test_exists(pk):
430432
super().save(*args, **kwargs)
431433

432434
def __str__(self):
433-
return f'{self.id} {self.title}'
435+
return f'{self.id}'
434436

435437
class Annotation(models.Model):
436438
class Meta:
@@ -457,7 +459,7 @@ class Meta:
457459
)
458460
author_email = models.EmailField(max_length=254)
459461
rating = models.DecimalField(default=0, decimal_places=2, max_digits=6)
460-
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
462+
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
461463

462464
def save(self, *args, **kwargs):
463465
if self.data['properties']['description']:

django/gsmap/schema.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ class Meta:
182182
interfaces = [graphene.relay.Node]
183183

184184
pk = graphene.String(source='id')
185+
title = graphene.String(
186+
language_code=graphene.Argument(Q_LANGUAGE, default_value=Q_LANGUAGE[settings.PARLER_DEFAULT_LANGUAGE_CODE]),
187+
)
188+
189+
description = graphene.String(
190+
language_code=graphene.Argument(Q_LANGUAGE, default_value=Q_LANGUAGE[settings.PARLER_DEFAULT_LANGUAGE_CODE]),
191+
)
185192
snapshots = graphene.List(SnapshotNode)
186193

187194
annotations = graphene.List(AnnotationNode)
@@ -192,6 +199,14 @@ class Meta:
192199
)
193200

194201
usergroups = graphene.List(UsergroupNode)
202+
203+
def resolve_title(self, info, language_code=None):
204+
lang = Q_LANGUAGE.get(language_code).name
205+
return self.safe_translation_getter("title", language_code=lang)
206+
207+
def resolve_description(self, info, language_code=None):
208+
lang = Q_LANGUAGE.get(language_code).name
209+
return self.safe_translation_getter("description", language_code=lang)
195210

196211
def resolve_snapshots(self, info):
197212
return gql_optimizer.query(self.snapshots.all(), info)

0 commit comments

Comments
 (0)