aa-structures 2.6.0__py3-none-any.whl → 2.6.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {aa_structures-2.6.0.dist-info → aa_structures-2.6.2.dist-info}/METADATA +1 -1
  2. {aa_structures-2.6.0.dist-info → aa_structures-2.6.2.dist-info}/RECORD +37 -38
  3. structures/__init__.py +1 -1
  4. structures/admin.py +208 -206
  5. structures/core/notification_embeds/billing_embeds.py +11 -10
  6. structures/core/notification_embeds/character_embeds.py +18 -17
  7. structures/core/notification_embeds/main.py +6 -6
  8. structures/core/notification_embeds/moonmining_embeds.py +25 -26
  9. structures/core/notification_embeds/orbital_embeds.py +8 -7
  10. structures/core/notification_embeds/sov_embeds.py +26 -35
  11. structures/core/notification_embeds/structures_embeds.py +67 -64
  12. structures/core/notification_embeds/tower_embeds.py +29 -22
  13. structures/core/notification_embeds/war_embeds.py +33 -44
  14. structures/core/serializers.py +1 -1
  15. structures/helpers.py +7 -1
  16. structures/locale/de/LC_MESSAGES/django.po +1036 -185
  17. structures/locale/django.pot +1054 -184
  18. structures/locale/en/LC_MESSAGES/django.po +1054 -184
  19. structures/locale/es/LC_MESSAGES/django.po +1035 -184
  20. structures/locale/fr_FR/LC_MESSAGES/django.po +1054 -184
  21. structures/locale/it_IT/LC_MESSAGES/django.po +1054 -184
  22. structures/locale/ja/LC_MESSAGES/django.po +1054 -184
  23. structures/locale/ko_KR/LC_MESSAGES/django.po +1035 -184
  24. structures/locale/ru/LC_MESSAGES/django.mo +0 -0
  25. structures/locale/ru/LC_MESSAGES/django.po +1144 -199
  26. structures/locale/uk/LC_MESSAGES/django.po +1035 -184
  27. structures/locale/zh_Hans/LC_MESSAGES/django.po +1036 -185
  28. structures/migrations/0004_improve_localization.py +401 -0
  29. structures/models/notifications.py +3 -3
  30. structures/models/owners.py +11 -11
  31. structures/models/structures_1.py +16 -16
  32. structures/templates/structures/base.html +1 -1
  33. structures/tests/test_helpers.py +13 -0
  34. structures/views.py +1 -2
  35. structures/webhooks/models.py +14 -5
  36. structures/locale/ko/LC_MESSAGES/django.mo +0 -0
  37. structures/locale/ko/LC_MESSAGES/django.po +0 -2221
  38. {aa_structures-2.6.0.dist-info → aa_structures-2.6.2.dist-info}/LICENSE +0 -0
  39. {aa_structures-2.6.0.dist-info → aa_structures-2.6.2.dist-info}/WHEEL +0 -0
structures/admin.py CHANGED
@@ -9,7 +9,8 @@ from django.db import models
9
9
  from django.db.models import Prefetch
10
10
  from django.db.models.functions import Lower
11
11
  from django.utils.html import format_html
12
- from django.utils.translation import gettext as _
12
+ from django.utils.text import format_lazy
13
+ from django.utils.translation import gettext_lazy as _
13
14
 
14
15
  from allianceauth.eveonline.models import EveAllianceInfo, EveCorporationInfo
15
16
  from allianceauth.services.hooks import get_extension_logger
@@ -58,6 +59,7 @@ class BaseFuelAlertAdmin(admin.ModelAdmin):
58
59
  )
59
60
  ordering = ("config", "structure")
60
61
 
62
+ @admin.display(description=_("owner"))
61
63
  def _owner(self, obj):
62
64
  return obj.structure.owner
63
65
 
@@ -90,18 +92,15 @@ class BaseFuelAlertConfigAdmin(admin.ModelAdmin):
90
92
  list_filter = ("is_enabled",)
91
93
  actions = ("send_fuel_notifications",)
92
94
  fieldsets = (
93
- (
94
- "Discord",
95
- {"fields": ("channel_ping_type", "color")},
96
- ),
97
- ("General", {"fields": ("is_enabled",)}),
95
+ (_("Discord"), {"fields": ("channel_ping_type", "color")}),
96
+ (_("General"), {"fields": ("is_enabled",)}),
98
97
  )
99
98
 
100
- @admin.display(ordering="pk")
99
+ @admin.display(ordering="pk", description=_("id"))
101
100
  def _id(self, obj):
102
101
  return f"#{obj.pk}"
103
102
 
104
- @admin.display(ordering="color")
103
+ @admin.display(ordering="color", description=_("color"))
105
104
  def _color(self, obj):
106
105
  color = Webhook.Color(obj.color)
107
106
  return format_html(
@@ -110,7 +109,7 @@ class BaseFuelAlertConfigAdmin(admin.ModelAdmin):
110
109
  color.label,
111
110
  )
112
111
 
113
- @admin.display(description=_("Sent fuel notifications for selected configuration"))
112
+ @admin.action(description=_("Sent fuel notifications for selected configuration"))
114
113
  def send_fuel_notifications(self, request, queryset):
115
114
  item_count = 0
116
115
  for obj in queryset:
@@ -119,7 +118,7 @@ class BaseFuelAlertConfigAdmin(admin.ModelAdmin):
119
118
  tasks.send_queued_messages_for_webhooks(Webhook.objects.filter(is_active=True))
120
119
  self.message_user(
121
120
  request,
122
- f"Started sending fuel notifications for {item_count} configurations",
121
+ _("Started sending fuel notifications for %d configurations") % item_count,
123
122
  )
124
123
 
125
124
 
@@ -133,7 +132,7 @@ class StructureFuelAlertConfigAdmin(BaseFuelAlertConfigAdmin):
133
132
  ) + tuple(BaseFuelAlertConfigAdmin.list_display)
134
133
  fieldsets = (
135
134
  (
136
- "Timing",
135
+ _("Timing"),
137
136
  {
138
137
  "description": _(
139
138
  "Timing configuration for sending fuel notifications. "
@@ -154,28 +153,22 @@ class JumpFuelAlertConfigAdmin(BaseFuelAlertConfigAdmin):
154
153
  "_threshold",
155
154
  ) + tuple(BaseFuelAlertConfigAdmin.list_display)
156
155
  fieldsets = (
157
- (
158
- "Fuel levels",
159
- {
160
- "description": ("tbd."),
161
- "fields": ("threshold",),
162
- },
163
- ),
156
+ ("Fuel levels", {"description": ("tbd."), "fields": ("threshold",)}),
164
157
  ) + tuple(BaseFuelAlertConfigAdmin.fieldsets)
165
158
 
166
- @admin.display(ordering="threshold")
159
+ @admin.display(ordering="threshold", description=_("threshold"))
167
160
  def _threshold(self, obj) -> str:
168
161
  return f"{obj.threshold:,}"
169
162
 
170
163
 
171
164
  class RenderableNotificationFilter(admin.SimpleListFilter):
172
- title = "can be send"
165
+ title = _("can be send")
173
166
  parameter_name = "notification_renderable"
174
167
 
175
168
  def lookups(self, request, model_admin):
176
169
  return (
177
- ("yes", "Yes"),
178
- ("no", "No"),
170
+ ("yes", _("yes")),
171
+ ("no", _("no")),
179
172
  )
180
173
 
181
174
  def queryset(self, request, queryset):
@@ -212,12 +205,6 @@ class NotificationBaseAdmin(admin.ModelAdmin):
212
205
  "add_or_remove_timer",
213
206
  )
214
207
 
215
- def has_add_permission(self, request):
216
- return False
217
-
218
- def has_change_permission(self, request, obj=None):
219
- return False
220
-
221
208
  def get_queryset(self, request):
222
209
  qs = super().get_queryset(request)
223
210
  return qs.prefetch_related(
@@ -233,9 +220,17 @@ class NotificationBaseAdmin(admin.ModelAdmin):
233
220
  ),
234
221
  ).select_related("owner", "owner__corporation")
235
222
 
223
+ def has_add_permission(self, request):
224
+ return False
225
+
226
+ def has_change_permission(self, request, obj=None):
227
+ return False
228
+
229
+ @admin.display(description=_("notification ID"))
236
230
  def _notification_id(self, obj):
237
231
  return obj.notification_id
238
232
 
233
+ @admin.display(description=_("webhooks"))
239
234
  def _webhooks(self, obj):
240
235
  if not obj.can_be_rendered:
241
236
  return format_html("<i>{}</i>", _("N/A"))
@@ -257,48 +252,55 @@ class NotificationBaseAdmin(admin.ModelAdmin):
257
252
  )
258
253
  return lines_sorted_html(names)
259
254
 
255
+ @admin.display(description=_("structures"))
260
256
  def _structures(self, obj) -> Optional[str]:
261
257
  if obj.is_structure_related:
262
258
  structures = [str(structure) for structure in obj.structures.all()]
263
259
  return lines_sorted_html(structures) if structures else "?"
264
260
  return None
265
261
 
262
+ @admin.display(description=_("is sent"))
266
263
  def _is_sent(self, obj):
267
264
  value = obj.is_sent if obj.can_be_rendered else None
268
265
  return admin_boolean_icon_html(value)
269
266
 
267
+ @admin.display(description=_("is timer added"))
270
268
  def _is_timer_added(self, obj):
271
269
  value = obj.is_timer_added if obj.can_have_timer else None
272
270
  return admin_boolean_icon_html(value)
273
271
 
274
- @admin.display(description=_("Mark selected notifications as sent"))
272
+ @admin.action(description=_("Mark selected notifications as sent"))
275
273
  def mark_as_sent(self, request, queryset):
276
274
  queryset.update(is_sent=True)
277
275
  notif_count = queryset.count()
278
- self.message_user(request, f"{notif_count} notifications marked as sent")
276
+ self.message_user(request, _("%d notifications marked as sent") % notif_count)
279
277
 
280
- @admin.display(description=_("Mark selected notifications as unsent"))
278
+ @admin.action(description=_("Mark selected notifications as unsent"))
281
279
  def mark_as_unsent(self, request, queryset):
282
280
  queryset.update(is_sent=False)
283
281
  notif_count = queryset.count()
284
- self.message_user(request, f"{notif_count} notifications marked as unsent")
282
+ self.message_user(request, _("%d notifications marked as unsent") % notif_count)
285
283
 
286
- @admin.display(description=_("Send selected notifications to configured webhooks"))
284
+ @admin.action(description=_("Send selected notifications to configured webhooks"))
287
285
  def send_to_configured_webhooks(self, request, queryset):
288
286
  notifs_queued = 0
289
287
  for obj in queryset:
290
288
  if obj.can_be_rendered and obj.relevant_webhooks().exists():
291
289
  if obj.send_to_configured_webhooks():
292
290
  notifs_queued += 1
291
+
293
292
  if notifs_queued:
294
293
  tasks.send_queued_messages_for_webhooks(
295
294
  Webhook.objects.filter(is_active=True)
296
295
  )
296
+
297
297
  self.message_user(
298
- request, f"Sent {notifs_queued}/{queryset.count()} generated messages."
298
+ request,
299
+ _("Sent %(sent_count)d/%(selected_count)d generated messages.")
300
+ % {"sent_count": notifs_queued, "selected_count": queryset.count()},
299
301
  )
300
302
 
301
- @admin.display(description=_("Process selected notifications for timerboard"))
303
+ @admin.action(description=_("Process selected notifications for timerboard"))
302
304
  def add_or_remove_timer(self, request, queryset):
303
305
  notifications_count = 0
304
306
  ignored_count = 0
@@ -307,11 +309,19 @@ class NotificationBaseAdmin(admin.ModelAdmin):
307
309
  notifications_count += 1
308
310
  else:
309
311
  ignored_count += 1
310
- message = (
311
- f"Added timers from {notifications_count} notifications to timerboard."
312
+
313
+ first = (
314
+ _("Added timers from %d notifications to timerboard.") % notifications_count
315
+ )
316
+ second = (
317
+ _("Ignored %d notification(s), which has no relation to timers.")
318
+ % ignored_count
312
319
  )
313
320
  if ignored_count:
314
- message += f" Ignored {ignored_count} notification(s), which has no relation to timers."
321
+ message = format_lazy("{first} {second}", first=first, second=second)
322
+ else:
323
+ message = first
324
+ message = format_lazy({first})
315
325
  self.message_user(request, message)
316
326
 
317
327
 
@@ -384,7 +394,7 @@ class OwnerAdmin(admin.ModelAdmin):
384
394
  },
385
395
  ),
386
396
  (
387
- "Sync Status",
397
+ _("Sync Status"),
388
398
  {
389
399
  "classes": ("collapse",),
390
400
  "fields": (
@@ -402,6 +412,13 @@ class OwnerAdmin(admin.ModelAdmin):
402
412
  ),
403
413
  )
404
414
 
415
+ def formfield_for_manytomany(self, db_field, request, **kwargs):
416
+ """only show custom tags in dropdown"""
417
+ if db_field.name == "webhooks":
418
+ kwargs["queryset"] = Webhook.objects.filter(is_active=True)
419
+
420
+ return super().formfield_for_manytomany(db_field, request, **kwargs)
421
+
405
422
  def get_queryset(self, request):
406
423
  qs = super().get_queryset(request)
407
424
  return (
@@ -410,32 +427,94 @@ class OwnerAdmin(admin.ModelAdmin):
410
427
  .annotate_characters_count()
411
428
  )
412
429
 
413
- @admin.display(ordering="x_characters_count")
430
+ def get_form(self, *args, **kwargs):
431
+ """Add help text to custom field."""
432
+ help_texts = {
433
+ "_avg_turnaround_time": (
434
+ "For last %d | %d | %d notifications"
435
+ % (
436
+ app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_SHORT,
437
+ app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_MEDIUM,
438
+ app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_LONG,
439
+ )
440
+ ),
441
+ "_are_all_syncs_ok": (
442
+ "True when all of the last successful syncs were within grace periods."
443
+ ),
444
+ "_structures_last_update_fresh": (
445
+ "True when last sync within %s minutes."
446
+ % app_settings.STRUCTURES_STRUCTURE_SYNC_GRACE_MINUTES
447
+ ),
448
+ "_notifications_last_update_fresh": (
449
+ "True when last sync within %s minutes."
450
+ % app_settings.STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES
451
+ ),
452
+ "_forwarding_last_update_fresh": (
453
+ "True when last sync within %s minutes."
454
+ % app_settings.STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES
455
+ ),
456
+ "_assets_last_update_fresh": (
457
+ "True when last sync within %s minutes."
458
+ % app_settings.STRUCTURES_STRUCTURE_SYNC_GRACE_MINUTES
459
+ ),
460
+ }
461
+ kwargs.update({"help_texts": help_texts})
462
+ return super().get_form(*args, **kwargs)
463
+
464
+ def get_readonly_fields(self, request, obj=None):
465
+ if obj: # editing an existing object
466
+ return tuple(self.readonly_fields) + (
467
+ "assets_last_update_at",
468
+ "corporation",
469
+ "forwarding_last_update_at",
470
+ "notifications_last_update_at",
471
+ "structures_last_update_at",
472
+ "_avg_turnaround_time",
473
+ "_are_all_syncs_ok",
474
+ "_structures_last_update_fresh",
475
+ "_notifications_last_update_fresh",
476
+ "_forwarding_last_update_fresh",
477
+ "_assets_last_update_fresh",
478
+ "_structures_count",
479
+ )
480
+ return self.readonly_fields
481
+
482
+ def has_add_permission(self, request):
483
+ return False
484
+
485
+ @admin.display(ordering="x_characters_count", description=_("characters"))
414
486
  def _characters(self, obj) -> int:
415
487
  return obj.x_characters_count
416
488
 
417
- @admin.display(description="default pings", boolean=True)
489
+ @admin.display(description=_("default pings"), boolean=True)
418
490
  def _has_default_pings_enabled(self, obj):
419
491
  return obj.has_default_pings_enabled
420
492
 
493
+ @admin.display(description=_("ping groups"))
421
494
  def _ping_groups(self, obj):
422
495
  ping_groups = [ping_group.name for ping_group in obj.ping_groups.all()]
423
496
  return lines_sorted_html(ping_groups) if ping_groups else None
424
497
 
425
- @admin.display(ordering="corporation__corporation_name")
498
+ @admin.display(
499
+ ordering="corporation__corporation_name", description=_("corporation")
500
+ )
426
501
  def _corporation(self, obj):
427
502
  return obj.corporation.corporation_name
428
503
 
429
- @admin.display(ordering="corporation__alliance__alliance_name")
504
+ @admin.display(
505
+ ordering="corporation__alliance__alliance_name", description=_("alliance")
506
+ )
430
507
  def _alliance(self, obj):
431
508
  if obj.corporation.alliance:
432
509
  return obj.corporation.alliance.alliance_name
433
510
  return None
434
511
 
512
+ @admin.display(description=_("webhooks"))
435
513
  def _webhooks(self, obj):
436
514
  names = [webhook.name for webhook in obj.webhooks.all()]
437
515
  if names:
438
516
  return lines_sorted_html(names)
517
+
439
518
  return format_html(
440
519
  '<span style="color: red">⚠ {}</span>',
441
520
  _(
@@ -444,101 +523,72 @@ class OwnerAdmin(admin.ModelAdmin):
444
523
  ),
445
524
  )
446
525
 
447
- @admin.display(description="active", boolean=True)
526
+ @admin.display(description=_("active"), boolean=True)
448
527
  def _is_active(self, obj):
449
528
  return obj.is_active
450
529
 
451
- @admin.display(description="alliance main")
530
+ @admin.display(description=_("alliance main"))
452
531
  def _is_alliance_main(self, obj):
453
532
  value = True if obj.is_alliance_main else None
454
533
  return admin_boolean_icon_html(value)
455
534
 
456
- @admin.display(description="services up", boolean=True)
535
+ @admin.display(description=_("services up"), boolean=True)
457
536
  def _is_sync_ok(self, obj):
458
- if not obj.is_active:
459
- return None
460
- return obj.is_up
537
+ return obj.is_up if obj.is_active else None
461
538
 
462
- @admin.display(description=_("Activate selected owners"))
539
+ @admin.action(description=_("Activate selected owners"))
463
540
  def activate_owners(self, request, queryset):
464
541
  queryset.update(is_active=True)
465
- self.message_user(request, f"Activated {queryset.count()} owners")
542
+ self.message_user(request, _("Activated %d owners") % queryset.count())
466
543
 
467
- @admin.display(description=_("Deactivate selected owner"))
544
+ @admin.action(description=_("Deactivate selected owner"))
468
545
  def deactivate_owners(self, request, queryset):
469
546
  queryset.update(is_active=False)
470
- self.message_user(request, f"Deactivated {queryset.count()} owners")
547
+ self.message_user(request, _("Deactivated %d owners") % queryset.count())
471
548
 
472
- @admin.display(description=_("Update all from EVE server for selected owners"))
549
+ @admin.action(description=_("Update all from EVE server for selected owners"))
473
550
  def update_all(self, request, queryset):
474
551
  for obj in queryset:
475
552
  tasks.update_all_for_owner.delay(obj.pk, user_pk=request.user.pk) # type: ignore
476
- text = (
477
- _(
478
- "Started updating structures and notifications for %s. "
479
- "You will receive a notification once it is completed."
480
- )
481
- % obj
553
+
554
+ text = format_lazy(
555
+ "{first} {second}",
556
+ first=_("Started updating structures and notifications for %s.") % obj,
557
+ second=_("You will receive a notification once it is completed."),
482
558
  )
483
559
  self.message_user(request, text)
484
560
 
485
- @admin.display(
561
+ @admin.action(
486
562
  description=_("Update structures from EVE server for selected owners")
487
563
  )
488
564
  def update_structures(self, request, queryset):
489
565
  for obj in queryset:
490
566
  tasks.update_structures_for_owner.delay(obj.pk, user_pk=request.user.pk) # type: ignore
491
- text = (
492
- f"Started updating structures for {obj}. "
493
- "You will receive a notification once it is completed."
567
+ text = format_lazy(
568
+ "{first} {second}",
569
+ first=_("Started updating structures for %s.") % obj,
570
+ second=_("You will receive a notification once it is completed."),
494
571
  )
495
572
  self.message_user(request, text)
496
573
 
497
- @admin.display(
574
+ @admin.action(
498
575
  description=_("Fetch notifications from EVE server for selected owners")
499
576
  )
500
577
  def fetch_notifications(self, request, queryset):
501
578
  for obj in queryset:
502
579
  tasks.process_notifications_for_owner.delay(obj.pk, user_pk=request.user.pk) # type: ignore
503
- text = (
504
- f"Started fetching notifications for {obj}. "
505
- "You will receive a notification once it is completed."
580
+ text = format_lazy(
581
+ "{first} {second}",
582
+ first=_("Started fetching notifications for %s.") % obj,
583
+ second=_("You will receive a notification once it is completed."),
506
584
  )
507
585
  self.message_user(request, text)
508
586
 
509
- def has_add_permission(self, request):
510
- return False
511
-
512
- def get_readonly_fields(self, request, obj=None):
513
- if obj: # editing an existing object
514
- return tuple(self.readonly_fields) + (
515
- "assets_last_update_at",
516
- "corporation",
517
- "forwarding_last_update_at",
518
- "notifications_last_update_at",
519
- "structures_last_update_at",
520
- "_avg_turnaround_time",
521
- "_are_all_syncs_ok",
522
- "_structures_last_update_fresh",
523
- "_notifications_last_update_fresh",
524
- "_forwarding_last_update_fresh",
525
- "_assets_last_update_fresh",
526
- "_structures_count",
527
- )
528
- return self.readonly_fields
529
-
530
- def formfield_for_manytomany(self, db_field, request, **kwargs):
531
- """only show custom tags in dropdown"""
532
- if db_field.name == "webhooks":
533
- kwargs["queryset"] = Webhook.objects.filter(is_active=True)
534
-
535
- return super().formfield_for_manytomany(db_field, request, **kwargs)
536
-
537
- @admin.display(description="All syncs OK", boolean=True)
587
+ @admin.display(description=_("all syncs OK"), boolean=True)
538
588
  def _are_all_syncs_ok(self, obj):
539
589
  return obj.are_all_syncs_ok
540
590
 
541
- @admin.display(description="Avg. turnaround time")
591
+ @admin.display(description=_("avg. turnaround time"))
542
592
  def _avg_turnaround_time(self, obj) -> str:
543
593
  """Average time between timestamp of notifications an when they are received."""
544
594
 
@@ -562,60 +612,26 @@ class OwnerAdmin(admin.ModelAdmin):
562
612
  long = statistics.mean(data[:max_long]) if len(data) >= max_long else None
563
613
  return f"{my_format(short)} | {my_format(medium)} | {my_format(long)}"
564
614
 
565
- @admin.display(description="Structures update fresh", boolean=True)
615
+ @admin.display(description=_("structures update fresh"), boolean=True)
566
616
  def _structures_last_update_fresh(self, obj) -> bool:
567
617
  return obj.is_structure_sync_fresh
568
618
 
569
- @admin.display(description="Notifications update fresh", boolean=True)
619
+ @admin.display(description=_("notifications update fresh"), boolean=True)
570
620
  def _notifications_last_update_fresh(self, obj) -> bool:
571
621
  return obj.is_notification_sync_fresh
572
622
 
573
- @admin.display(description="Forwarding update fresh", boolean=True)
623
+ @admin.display(description=_("forwarding update fresh"), boolean=True)
574
624
  def _forwarding_last_update_fresh(self, obj) -> bool:
575
625
  return obj.is_forwarding_sync_fresh
576
626
 
577
- @admin.display(description="Assets update fresh", boolean=True)
627
+ @admin.display(description=_("assets update fresh"), boolean=True)
578
628
  def _assets_last_update_fresh(self, obj) -> bool:
579
629
  return obj.is_assets_sync_fresh
580
630
 
581
- @admin.display(description="Structures Count")
631
+ @admin.action(description=_("structures Count"))
582
632
  def _structures_count(self, obj) -> int:
583
633
  return obj.structures.count()
584
634
 
585
- def get_form(self, *args, **kwargs):
586
- """Add help text to custom field."""
587
- help_texts = {
588
- "_avg_turnaround_time": (
589
- "For last %d | %d | %d notifications"
590
- % (
591
- app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_SHORT,
592
- app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_MEDIUM,
593
- app_settings.STRUCTURES_NOTIFICATION_TURNAROUND_LONG,
594
- )
595
- ),
596
- "_are_all_syncs_ok": (
597
- "True when all of the last successful syncs were within grace periods."
598
- ),
599
- "_structures_last_update_fresh": (
600
- "True when last sync within %s minutes."
601
- % app_settings.STRUCTURES_STRUCTURE_SYNC_GRACE_MINUTES
602
- ),
603
- "_notifications_last_update_fresh": (
604
- "True when last sync within %s minutes."
605
- % app_settings.STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES
606
- ),
607
- "_forwarding_last_update_fresh": (
608
- "True when last sync within %s minutes."
609
- % app_settings.STRUCTURES_NOTIFICATION_SYNC_GRACE_MINUTES
610
- ),
611
- "_assets_last_update_fresh": (
612
- "True when last sync within %s minutes."
613
- % app_settings.STRUCTURES_STRUCTURE_SYNC_GRACE_MINUTES
614
- ),
615
- }
616
- kwargs.update({"help_texts": help_texts})
617
- return super().get_form(*args, **kwargs)
618
-
619
635
 
620
636
  @admin.register(StructureTag)
621
637
  class StructureTagAdmin(admin.ModelAdmin):
@@ -627,11 +643,7 @@ class StructureTagAdmin(admin.ModelAdmin):
627
643
  "is_default",
628
644
  "is_user_managed",
629
645
  )
630
- list_filter = (
631
- "is_default",
632
- "style",
633
- "is_user_managed",
634
- )
646
+ list_filter = ("is_default", "style", "is_user_managed")
635
647
  readonly_fields = ("is_user_managed",)
636
648
 
637
649
  def has_delete_permission(self, request, obj: Optional[StructureTag] = None):
@@ -670,7 +682,7 @@ class StructureItemAdminInline(admin.TabularInline):
670
682
  class OwnerCorporationsFilter(admin.SimpleListFilter):
671
683
  """Custom filter to filter on corporations from owners only"""
672
684
 
673
- title = "owner corporation"
685
+ title = _("owner corporation")
674
686
  parameter_name = "owner_corporation_id__exact"
675
687
 
676
688
  def lookups(self, request, model_admin):
@@ -692,7 +704,7 @@ class OwnerCorporationsFilter(admin.SimpleListFilter):
692
704
  class OwnerAllianceFilter(admin.SimpleListFilter):
693
705
  """Custom filter to filter on alliances from owners only"""
694
706
 
695
- title = "owner alliance"
707
+ title = _("owner alliance")
696
708
  parameter_name = "owner_alliance_id__exact"
697
709
 
698
710
  def lookups(self, request, model_admin):
@@ -714,13 +726,13 @@ class OwnerAllianceFilter(admin.SimpleListFilter):
714
726
 
715
727
 
716
728
  class HasWebhooksListFilter(admin.SimpleListFilter):
717
- title = "has webhooks"
729
+ title = _("has webhooks")
718
730
  parameter_name = "has_webhooks"
719
731
 
720
732
  def lookups(self, request, model_admin):
721
733
  return (
722
- ("y", "yes"),
723
- ("n", "no"),
734
+ ("y", _("yes")),
735
+ ("n", _("no")),
724
736
  )
725
737
 
726
738
  def queryset(self, request, queryset):
@@ -779,9 +791,10 @@ class StructureAdmin(admin.ModelAdmin):
779
791
  actions = ("add_default_tags", "remove_user_tags", "update_generated_tags")
780
792
  readonly_fields = tuple(
781
793
  (
782
- x.name
783
- for x in Structure._meta.get_fields()
784
- if isinstance(x, models.fields.Field) and x.name not in ["tags", "webhooks"]
794
+ obj.name
795
+ for obj in Structure._meta.get_fields()
796
+ if isinstance(obj, models.fields.Field)
797
+ and obj.name not in ["tags", "webhooks"]
785
798
  )
786
799
  )
787
800
  fieldsets = (
@@ -799,7 +812,7 @@ class StructureAdmin(admin.ModelAdmin):
799
812
  },
800
813
  ),
801
814
  (
802
- "Status",
815
+ _("Status"),
803
816
  {
804
817
  "classes": ("collapse",),
805
818
  "fields": (
@@ -817,20 +830,17 @@ class StructureAdmin(admin.ModelAdmin):
817
830
  },
818
831
  ),
819
832
  (
820
- "Reinforcement",
833
+ _("Reinforcement"),
821
834
  {
822
835
  "classes": ("collapse",),
823
836
  "fields": (
824
837
  ("reinforce_hour",),
825
- (
826
- "next_reinforce_hour",
827
- "next_reinforce_apply",
828
- ),
838
+ ("next_reinforce_hour", "next_reinforce_apply"),
829
839
  ),
830
840
  },
831
841
  ),
832
842
  (
833
- "Position",
843
+ _("Position"),
834
844
  {
835
845
  "classes": ("collapse",),
836
846
  "fields": ("position_x", "position_y", "position_z"),
@@ -838,33 +848,34 @@ class StructureAdmin(admin.ModelAdmin):
838
848
  ),
839
849
  (
840
850
  None,
841
- {
842
- "fields": (
843
- (
844
- "id",
845
- "last_updated_at",
846
- )
847
- )
848
- },
851
+ {"fields": (("id", "last_updated_at"))},
849
852
  ),
850
853
  )
851
854
  filter_horizontal = ("tags", "webhooks")
852
855
  inlines = (StructureServiceAdminInline, StructureItemAdminInline)
853
856
 
854
- def has_add_permission(self, request):
855
- return False
857
+ def formfield_for_manytomany(self, db_field, request, **kwargs):
858
+ if db_field.name == "tags":
859
+ kwargs["queryset"] = StructureTag.objects.filter(is_user_managed=True)
860
+
861
+ return super().formfield_for_manytomany(db_field, request, **kwargs)
856
862
 
857
863
  def get_queryset(self, request):
858
864
  qs = super().get_queryset(request)
859
865
  return qs.prefetch_related("tags", "webhooks")
860
866
 
861
- @admin.display(ordering="name")
867
+ def has_add_permission(self, request):
868
+ return False
869
+
870
+ @admin.display(ordering="name", description=_("name"))
862
871
  def _name(self, structure) -> str:
863
872
  if structure.name:
864
873
  return structure.name
865
874
  return structure.location_name
866
875
 
867
- @admin.display(ordering="owner__corporation__corporation_name")
876
+ @admin.display(
877
+ ordering="owner__corporation__corporation_name", description=_("owner")
878
+ )
868
879
  def _owner(self, structure) -> str:
869
880
  alliance = structure.owner.corporation.alliance
870
881
  return format_html(
@@ -873,7 +884,7 @@ class StructureAdmin(admin.ModelAdmin):
873
884
  alliance if alliance else "",
874
885
  )
875
886
 
876
- @admin.display(ordering="eve_solar_system__name")
887
+ @admin.display(ordering="eve_solar_system__name", description=_("location"))
877
888
  def _location(self, structure) -> str:
878
889
  return format_html(
879
890
  "{}<br>{}",
@@ -881,22 +892,24 @@ class StructureAdmin(admin.ModelAdmin):
881
892
  structure.eve_solar_system.eve_constellation.eve_region,
882
893
  )
883
894
 
884
- @admin.display(ordering="eve_type__name")
895
+ @admin.display(ordering="eve_type__name", description=_("type"))
885
896
  def _type(self, structure):
886
897
  return format_html("{}<br>{}", structure.eve_type, structure.eve_type.eve_group)
887
898
 
899
+ @admin.display(description=_("power mode"))
888
900
  def _power_mode(self, structure) -> str:
889
901
  return structure.get_power_mode_display()
890
902
 
891
- @admin.display(description="Tags")
903
+ @admin.display(description=_("tags"))
892
904
  def _tags(self, structure) -> list:
893
905
  return sorted([tag.name for tag in structure.tags.all()])
894
906
 
907
+ @admin.display(description=_("webhooks"))
895
908
  def _webhooks(self, obj):
896
909
  names = [webhook.name for webhook in obj.webhooks.all()]
897
910
  return lines_sorted_html(names) if names else None
898
911
 
899
- @admin.display(description="Add default tags to selected structures")
912
+ @admin.action(description=_("Add default tags to selected structures"))
900
913
  def add_default_tags(self, request, queryset):
901
914
  structure_count = 0
902
915
  tags = StructureTag.objects.filter(is_default=True)
@@ -907,10 +920,11 @@ class StructureAdmin(admin.ModelAdmin):
907
920
  tags_count = tags.count()
908
921
  self.message_user(
909
922
  request,
910
- f"Added {tags_count:,} default tags to {structure_count:,} structures",
923
+ _("Added %(tags_count)d default tags to %(structure_count)d structures")
924
+ % {"tags_count": tags_count, "structure_count": structure_count},
911
925
  )
912
926
 
913
- @admin.display(description=_("Remove user tags for selected structures"))
927
+ @admin.action(description=_("Remove user tags for selected structures"))
914
928
  def remove_user_tags(self, request, queryset):
915
929
  structure_count = 0
916
930
  for structure in queryset:
@@ -918,32 +932,22 @@ class StructureAdmin(admin.ModelAdmin):
918
932
  structure.tags.remove(tag)
919
933
  structure_count += 1
920
934
  self.message_user(
921
- request,
922
- f"Removed all user tags from {structure_count:,} structures",
935
+ request, _("Removed all user tags from %d structures") % structure_count
923
936
  )
924
937
 
925
- @admin.display(description=_("Update generated tags for selected structures"))
938
+ @admin.action(description=_("Update generated tags for selected structures"))
926
939
  def update_generated_tags(self, request, queryset):
927
940
  structure_count = 0
928
941
  for structure in queryset:
929
942
  structure.update_generated_tags(recreate_tags=True)
930
943
  structure_count += 1
931
944
  self.message_user(
932
- request,
933
- f"Updated all generated tags for {structure_count:,} structures",
945
+ request, _("Updated all generated tags for %d structures") % structure_count
934
946
  )
935
947
 
936
- def formfield_for_manytomany(self, db_field, request, **kwargs):
937
- """only show custom tags in dropdown"""
938
- if db_field.name == "tags":
939
- kwargs["queryset"] = StructureTag.objects.filter(is_user_managed=True)
940
-
941
- return super().formfield_for_manytomany(db_field, request, **kwargs)
942
-
943
948
 
944
949
  @admin.register(Webhook)
945
950
  class WebhookAdmin(admin.ModelAdmin):
946
- ordering = ["name"]
947
951
  list_display = (
948
952
  "name",
949
953
  "_ping_groups",
@@ -953,6 +957,7 @@ class WebhookAdmin(admin.ModelAdmin):
953
957
  "_messages_in_queue",
954
958
  )
955
959
  list_filter = ("is_active",)
960
+ ordering = ["name"]
956
961
  save_as = True
957
962
  actions = (
958
963
  "test_notification",
@@ -978,7 +983,7 @@ class WebhookAdmin(admin.ModelAdmin):
978
983
  },
979
984
  ),
980
985
  (
981
- "Advanced Options",
986
+ _("Advanced Options"),
982
987
  {
983
988
  "classes": ("collapse",),
984
989
  "fields": (
@@ -1015,15 +1020,12 @@ class WebhookAdmin(admin.ModelAdmin):
1015
1020
  ),
1016
1021
  )
1017
1022
 
1018
- @admin.display(boolean=True)
1019
- def _default_pings(self, obj):
1020
- return obj.has_default_pings_enabled
1021
-
1023
+ @admin.display(description=_("ping groups"))
1022
1024
  def _ping_groups(self, obj):
1023
1025
  ping_groups = [ping_group.name for ping_group in obj.ping_groups.all()]
1024
1026
  return lines_sorted_html(ping_groups) if ping_groups else None
1025
1027
 
1026
- @admin.display(description="Enabled for Owners/Structures")
1028
+ @admin.display(description=_("enabled for owners or structures"))
1027
1029
  def _owners(self, obj):
1028
1030
  configurations = [str(owner) for owner in obj.owners.all()]
1029
1031
  configurations += [
@@ -1036,43 +1038,43 @@ class WebhookAdmin(admin.ModelAdmin):
1036
1038
  )
1037
1039
  return lines_sorted_html(configurations)
1038
1040
 
1041
+ @admin.display(description=_("is default"))
1039
1042
  def _is_default(self, obj):
1040
1043
  value = True if obj.is_default else None
1041
1044
  return admin_boolean_icon_html(value)
1042
1045
 
1046
+ @admin.display(description=_("messages in queue"))
1043
1047
  def _messages_in_queue(self, obj):
1044
1048
  return obj.queue_size()
1045
1049
 
1046
- @admin.display(description=_("Send test notification to selected webhook"))
1050
+ @admin.action(description=_("Send test notification to selected webhook"))
1047
1051
  def test_notification(self, request, queryset):
1048
1052
  for obj in queryset:
1049
1053
  tasks.send_test_notifications_to_webhook.delay(
1050
1054
  obj.pk, user_pk=request.user.pk
1051
1055
  ) # type: ignore
1052
- self.message_user(
1053
- request,
1054
- _(
1055
- "Initiated sending test notification to webhook %s. "
1056
- "You will receive a report on completion."
1057
- )
1058
- % obj,
1056
+ text = format_lazy(
1057
+ "{first} {second}",
1058
+ first=_("Initiated sending test notification to webhook %s.") % obj,
1059
+ second=_("You will receive a notification once it is completed."),
1059
1060
  )
1061
+ self.message_user(request, text)
1060
1062
 
1061
- @admin.display(description=_("Activate selected webhook"))
1063
+ @admin.action(description=_("Activate selected webhook"))
1062
1064
  def activate(self, request, queryset):
1063
1065
  for obj in queryset:
1064
1066
  obj.is_active = True
1065
1067
  obj.save()
1066
1068
  self.message_user(request, _("You have activated webhook %s") % obj)
1067
1069
 
1068
- @admin.display(description=_("Deactivate selected webhook"))
1070
+ @admin.action(description=_("Deactivate selected webhook"))
1069
1071
  def deactivate(self, request, queryset):
1070
1072
  for obj in queryset:
1071
1073
  obj.is_active = False
1072
1074
  obj.save()
1073
1075
  self.message_user(request, _("You have de-activated webhook %s") % obj)
1074
1076
 
1075
- @admin.display(description=_("Purge queued messages from selected webhooks"))
1077
+ @admin.action(description=_("Purge queued messages from selected webhooks"))
1076
1078
  def purge_messages(self, request, queryset):
1077
1079
  actions_count = 0
1078
1080
  killmails_deleted = 0
@@ -1088,7 +1090,7 @@ class WebhookAdmin(admin.ModelAdmin):
1088
1090
  % {"actions_count": actions_count, "killmails_deleted": killmails_deleted},
1089
1091
  )
1090
1092
 
1091
- @admin.display(description=_("Send queued messages from selected webhooks"))
1093
+ @admin.action(description=_("Send queued messages from selected webhooks"))
1092
1094
  def send_messages(self, request, queryset):
1093
1095
  items_count = 0
1094
1096
  for webhook in queryset: