ipfabric_netbox 4.3.1b1__py3-none-any.whl → 4.3.1b3__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.

Potentially problematic release.


This version of ipfabric_netbox might be problematic. Click here for more details.

Files changed (40) hide show
  1. ipfabric_netbox/__init__.py +1 -1
  2. ipfabric_netbox/api/serializers.py +4 -2
  3. ipfabric_netbox/choices.py +56 -20
  4. ipfabric_netbox/filtersets.py +6 -2
  5. ipfabric_netbox/forms.py +24 -19
  6. ipfabric_netbox/graphql/enums.py +10 -3
  7. ipfabric_netbox/graphql/filters.py +4 -3
  8. ipfabric_netbox/jobs.py +6 -5
  9. ipfabric_netbox/models.py +46 -45
  10. ipfabric_netbox/navigation.py +10 -9
  11. ipfabric_netbox/tables.py +12 -10
  12. ipfabric_netbox/templates/ipfabric_netbox/inc/clone_form.html +7 -4
  13. ipfabric_netbox/templates/ipfabric_netbox/inc/diff.html +10 -8
  14. ipfabric_netbox/templates/ipfabric_netbox/inc/json.html +4 -2
  15. ipfabric_netbox/templates/ipfabric_netbox/inc/logs_pending.html +4 -3
  16. ipfabric_netbox/templates/ipfabric_netbox/inc/merge_form.html +7 -5
  17. ipfabric_netbox/templates/ipfabric_netbox/inc/site_topology_button.html +8 -6
  18. ipfabric_netbox/templates/ipfabric_netbox/inc/site_topology_modal.html +8 -4
  19. ipfabric_netbox/templates/ipfabric_netbox/inc/transform_map_field_map.html +2 -1
  20. ipfabric_netbox/templates/ipfabric_netbox/inc/transform_map_relationship_map.html +2 -1
  21. ipfabric_netbox/templates/ipfabric_netbox/ipfabric_table.html +4 -4
  22. ipfabric_netbox/templates/ipfabric_netbox/ipfabricingestion.html +12 -11
  23. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsnapshot.html +15 -14
  24. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsource.html +13 -12
  25. ipfabric_netbox/templates/ipfabric_netbox/ipfabricsync.html +16 -15
  26. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap.html +7 -6
  27. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap_list.html +2 -1
  28. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmap_restore.html +1 -1
  29. ipfabric_netbox/templates/ipfabric_netbox/ipfabrictransformmapgroup.html +4 -3
  30. ipfabric_netbox/templates/ipfabric_netbox/partials/ingestion_progress.html +5 -4
  31. ipfabric_netbox/templates/ipfabric_netbox/partials/ingestion_statistics.html +5 -4
  32. ipfabric_netbox/templates/ipfabric_netbox/partials/job_logs.html +10 -9
  33. ipfabric_netbox/tests/api/test_api.py +6 -5
  34. ipfabric_netbox/tests/test_forms.py +16 -15
  35. ipfabric_netbox/tests/test_views.py +24 -23
  36. ipfabric_netbox/utilities/ipfutils.py +2 -2
  37. ipfabric_netbox/views.py +8 -7
  38. {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b3.dist-info}/METADATA +1 -1
  39. {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b3.dist-info}/RECORD +40 -40
  40. {ipfabric_netbox-4.3.1b1.dist-info → ipfabric_netbox-4.3.1b3.dist-info}/WHEEL +0 -0
ipfabric_netbox/models.py CHANGED
@@ -7,7 +7,6 @@ from copy import deepcopy
7
7
  from uuid import uuid4
8
8
 
9
9
  import httpx
10
- from core.choices import DataSourceStatusChoices
11
10
  from core.choices import JobStatusChoices
12
11
  from core.exceptions import SyncError
13
12
  from core.models import Job
@@ -46,7 +45,9 @@ from utilities.request import NetBoxFakeRequest
46
45
 
47
46
  from .choices import IPFabricRawDataTypeChoices
48
47
  from .choices import IPFabricSnapshotStatusModelChoices
48
+ from .choices import IPFabricSourceStatusChoices
49
49
  from .choices import IPFabricSourceTypeChoices
50
+ from .choices import IPFabricSyncStatusChoices
50
51
  from .choices import IPFabricTransformMapSourceModelChoices
51
52
  from .choices import required_transform_map_contenttypes
52
53
  from .signals import clear_other_primary_ip
@@ -104,8 +105,8 @@ class IPFabricTransformMapGroup(NetBoxModel):
104
105
 
105
106
  class Meta:
106
107
  ordering = ("pk",)
107
- verbose_name = "IP Fabric Transform Map Group"
108
- verbose_name_plural = "IP Fabric Transform Map Groups"
108
+ verbose_name = _("IP Fabric Transform Map Group")
109
+ verbose_name_plural = _("IP Fabric Transform Map Groups")
109
110
 
110
111
  def __str__(self):
111
112
  return self.name
@@ -124,7 +125,7 @@ class IPFabricTransformMap(NetBoxModel):
124
125
  target_model = models.ForeignKey(
125
126
  to=ContentType,
126
127
  related_name="+",
127
- verbose_name="Target Model",
128
+ verbose_name=_("Target Model"),
128
129
  limit_choices_to=IPFabricSupportedSyncModels,
129
130
  help_text=_("The object(s) to which transform map target applies."),
130
131
  on_delete=models.PROTECT,
@@ -141,8 +142,8 @@ class IPFabricTransformMap(NetBoxModel):
141
142
 
142
143
  class Meta:
143
144
  ordering = ("pk",)
144
- verbose_name = "IP Fabric Transform Map"
145
- verbose_name_plural = "IP Fabric Transform Maps"
145
+ verbose_name = _("IP Fabric Transform Map")
146
+ verbose_name_plural = _("IP Fabric Transform Maps")
146
147
 
147
148
  def __str__(self):
148
149
  if self.source_model and self.target_model:
@@ -336,7 +337,7 @@ class IPFabricRelationshipField(models.Model):
336
337
  ContentType,
337
338
  related_name="ipfabric_transform_fields",
338
339
  limit_choices_to=IPFabricRelationshipFieldSourceModels,
339
- verbose_name="Source Model",
340
+ verbose_name=_("Source Model"),
340
341
  on_delete=models.PROTECT,
341
342
  blank=False,
342
343
  null=False,
@@ -355,8 +356,8 @@ class IPFabricRelationshipField(models.Model):
355
356
 
356
357
  class Meta:
357
358
  ordering = ("transform_map",)
358
- verbose_name = "IP Fabric Relationship Field"
359
- verbose_name_plural = "IP Fabric Relationship Fields"
359
+ verbose_name = _("IP Fabric Relationship Field")
360
+ verbose_name_plural = _("IP Fabric Relationship Fields")
360
361
 
361
362
  @property
362
363
  def docs_url(self):
@@ -385,8 +386,8 @@ class IPFabricTransformField(models.Model):
385
386
 
386
387
  class Meta:
387
388
  ordering = ("transform_map",)
388
- verbose_name = "IP Fabric Transform Field"
389
- verbose_name_plural = "IP Fabric Transform Fields"
389
+ verbose_name = _("IP Fabric Transform Field")
390
+ verbose_name_plural = _("IP Fabric Transform Fields")
390
391
 
391
392
  @property
392
393
  def docs_url(self):
@@ -418,7 +419,7 @@ class IPFabricClient:
418
419
  self.handle_sync_failure("Error", e)
419
420
 
420
421
  def handle_sync_failure(self, failure_type, exception, message=None):
421
- self.status = DataSourceStatusChoices.FAILED
422
+ self.status = IPFabricSyncStatusChoices.FAILED
422
423
 
423
424
  if message:
424
425
  self.logger.log_failure(
@@ -439,8 +440,8 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
439
440
  url = models.CharField(max_length=200, verbose_name=_("URL"))
440
441
  status = models.CharField(
441
442
  max_length=50,
442
- choices=DataSourceStatusChoices,
443
- default=DataSourceStatusChoices.NEW,
443
+ choices=IPFabricSourceStatusChoices,
444
+ default=IPFabricSourceStatusChoices.NEW,
444
445
  editable=False,
445
446
  )
446
447
  parameters = models.JSONField(blank=True, null=True)
@@ -448,8 +449,8 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
448
449
 
449
450
  class Meta:
450
451
  ordering = ("name",)
451
- verbose_name = "IP Fabric Source"
452
- verbose_name_plural = "IP Fabric Sources"
452
+ verbose_name = _("IP Fabric Source")
453
+ verbose_name_plural = _("IP Fabric Sources")
453
454
 
454
455
  def __str__(self):
455
456
  return f"{self.name}"
@@ -460,8 +461,8 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
460
461
  @property
461
462
  def ready_for_sync(self):
462
463
  return self.status not in (
463
- DataSourceStatusChoices.QUEUED,
464
- DataSourceStatusChoices.SYNCING,
464
+ IPFabricSourceStatusChoices.QUEUED,
465
+ IPFabricSourceStatusChoices.SYNCING,
465
466
  )
466
467
 
467
468
  @property
@@ -476,7 +477,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
476
477
 
477
478
  def enqueue_sync_job(self, request):
478
479
  # Set the status to "syncing"
479
- self.status = DataSourceStatusChoices.QUEUED
480
+ self.status = IPFabricSourceStatusChoices.QUEUED
480
481
  IPFabricSource.objects.filter(pk=self.pk).update(status=self.status)
481
482
 
482
483
  # Enqueue a sync job
@@ -489,7 +490,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
489
490
 
490
491
  def sync(self, job):
491
492
  self.logger = SyncLogging(job=job.pk)
492
- if self.status == DataSourceStatusChoices.SYNCING:
493
+ if self.status == IPFabricSourceStatusChoices.SYNCING:
493
494
  self.logger.log_failure(
494
495
  "Cannot initiate sync; syncing already in progress.", obj=self
495
496
  )
@@ -497,7 +498,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
497
498
 
498
499
  pre_sync.send(sender=self.__class__, instance=self)
499
500
 
500
- self.status = DataSourceStatusChoices.SYNCING
501
+ self.status = IPFabricSourceStatusChoices.SYNCING
501
502
  IPFabricSource.objects.filter(pk=self.pk).update(status=self.status)
502
503
 
503
504
  # Begin Sync
@@ -542,7 +543,7 @@ class IPFabricSource(IPFabricClient, JobsMixin, PrimaryModel):
542
543
  f"Created/Updated Snapshot {snapshot.name} ({snapshot.snapshot_id})",
543
544
  obj=snapshot, # noqa E225
544
545
  )
545
- self.status = DataSourceStatusChoices.COMPLETED
546
+ self.status = IPFabricSourceStatusChoices.COMPLETED
546
547
  self.logger.log_success(f"Completed syncing snapshots from {self.name}")
547
548
  logger.debug(f"Completed syncing snapshots from {self.url}")
548
549
  except Exception as e:
@@ -587,8 +588,8 @@ class IPFabricSnapshot(TagsMixin, ChangeLoggedModel):
587
588
 
588
589
  class Meta:
589
590
  ordering = ("source", "-date")
590
- verbose_name = "IP Fabric Snapshot"
591
- verbose_name_plural = "IP Fabric Snapshots"
591
+ verbose_name = _("IP Fabric Snapshot")
592
+ verbose_name_plural = _("IP Fabric Snapshots")
592
593
 
593
594
  def __str__(self):
594
595
  return f"{self.name} - {self.snapshot_id}"
@@ -621,8 +622,8 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
621
622
  )
622
623
  status = models.CharField(
623
624
  max_length=50,
624
- choices=DataSourceStatusChoices,
625
- default=DataSourceStatusChoices.NEW,
625
+ choices=IPFabricSyncStatusChoices,
626
+ default=IPFabricSyncStatusChoices.NEW,
626
627
  editable=False,
627
628
  )
628
629
  parameters = models.JSONField(blank=True, null=True)
@@ -646,7 +647,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
646
647
 
647
648
  class Meta:
648
649
  ordering = ["pk"]
649
- verbose_name = "IP Fabric Sync"
650
+ verbose_name = _("IP Fabric Sync")
650
651
 
651
652
  def __str__(self):
652
653
  return f"{self.name}"
@@ -668,7 +669,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
668
669
  return reverse("plugins:ipfabric_netbox:ipfabricsync", args=[self.pk])
669
670
 
670
671
  def get_status_color(self):
671
- return DataSourceStatusChoices.colors.get(self.status)
672
+ return IPFabricSyncStatusChoices.colors.get(self.status)
672
673
 
673
674
  def save(self, *args, **kwargs):
674
675
  super().save(*args, **kwargs)
@@ -677,7 +678,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
677
678
 
678
679
  @property
679
680
  def ready_for_sync(self):
680
- if self.status not in (DataSourceStatusChoices.SYNCING,):
681
+ if self.status not in (IPFabricSyncStatusChoices.SYNCING,):
681
682
  if self.snapshot_data.source.type == "remote":
682
683
  if self.snapshot_data.ipf_data.count() > 0:
683
684
  return True
@@ -723,7 +724,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
723
724
 
724
725
  def enqueue_sync_job(self, adhoc=False, user=None) -> Job | None:
725
726
  def set_syncing_status():
726
- self.status = DataSourceStatusChoices.QUEUED
727
+ self.status = IPFabricSyncStatusChoices.QUEUED
727
728
  IPFabricSync.objects.filter(pk=self.pk).update(status=self.status)
728
729
 
729
730
  def sync_snapshots():
@@ -794,12 +795,12 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
794
795
  f"Combination of these transform map groups failed validation. Missing maps: {missing}."
795
796
  )
796
797
 
797
- if self.status == DataSourceStatusChoices.SYNCING:
798
+ if self.status == IPFabricSyncStatusChoices.SYNCING:
798
799
  raise SyncError("Cannot initiate sync; ingestion already in progress.")
799
800
 
800
801
  pre_sync.send(sender=self.__class__, instance=self)
801
802
 
802
- self.status = DataSourceStatusChoices.SYNCING
803
+ self.status = IPFabricSyncStatusChoices.SYNCING
803
804
  IPFabricSync.objects.filter(pk=self.pk).update(status=self.status)
804
805
 
805
806
  # Begin Sync
@@ -875,11 +876,11 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
875
876
  current_request.set(token.old_value)
876
877
  active_branch.set(current_branch)
877
878
 
878
- if self.status != DataSourceStatusChoices.FAILED:
879
- self.status = DataSourceStatusChoices.COMPLETED
879
+ if self.status != IPFabricSyncStatusChoices.FAILED:
880
+ self.status = IPFabricSyncStatusChoices.READY_TO_MERGE
880
881
 
881
882
  except Exception as e:
882
- self.status = DataSourceStatusChoices.FAILED
883
+ self.status = IPFabricSyncStatusChoices.FAILED
883
884
  self.logger.log_failure(f"Ingestion Failed: `{e}`", obj=ingestion)
884
885
  self.logger.log_failure(
885
886
  f"Stack Trace: `{traceback.format_exc()}`", obj=ingestion
@@ -893,7 +894,7 @@ class IPFabricSync(IPFabricClient, JobsMixin, TagsMixin, ChangeLoggedModel):
893
894
 
894
895
  self.last_synced = timezone.now()
895
896
 
896
- if self.auto_merge and self.status == DataSourceStatusChoices.COMPLETED:
897
+ if self.auto_merge and self.status == IPFabricSyncStatusChoices.READY_TO_MERGE:
897
898
  self.logger.log_info("Auto Merging Ingestion", obj=ingestion)
898
899
  logger.info("Auto Merging Ingestion")
899
900
  try:
@@ -927,8 +928,8 @@ class IPFabricIngestion(JobsMixin, models.Model):
927
928
 
928
929
  class Meta:
929
930
  ordering = ("pk",)
930
- verbose_name = "IP Fabric Ingestion"
931
- verbose_name_plural = "IP Fabric Ingestions"
931
+ verbose_name = _("IP Fabric Ingestion")
932
+ verbose_name_plural = _("IP Fabric Ingestions")
932
933
 
933
934
  def __str__(self):
934
935
  return self.name
@@ -947,7 +948,7 @@ class IPFabricIngestion(JobsMixin, models.Model):
947
948
 
948
949
  def enqueue_merge_job(self, user, remove_branch=False):
949
950
  # Set the status to "queued"
950
- self.status = DataSourceStatusChoices.QUEUED
951
+ self.status = IPFabricSyncStatusChoices.QUEUED
951
952
  IPFabricSync.objects.filter(ipfabricingestion=self.pk).update(
952
953
  status=self.status
953
954
  )
@@ -988,12 +989,12 @@ class IPFabricIngestion(JobsMixin, models.Model):
988
989
 
989
990
  def sync_merge(self):
990
991
  ipfabricsync = self.sync
991
- if ipfabricsync.status == DataSourceStatusChoices.SYNCING:
992
+ if ipfabricsync.status == IPFabricSyncStatusChoices.MERGING:
992
993
  raise SyncError("Cannot initiate merge; merge already in progress.")
993
994
 
994
995
  pre_sync.send(sender=self.__class__, instance=self)
995
996
 
996
- ipfabricsync.status = DataSourceStatusChoices.SYNCING
997
+ ipfabricsync.status = IPFabricSyncStatusChoices.MERGING
997
998
  IPFabricSync.objects.filter(ipfabricingestion=self.pk).update(
998
999
  status=self.sync.status
999
1000
  )
@@ -1010,9 +1011,9 @@ class IPFabricIngestion(JobsMixin, models.Model):
1010
1011
  assign_virtualchassis_master, sender=VirtualChassis
1011
1012
  )
1012
1013
  signals.pre_save.disconnect(clear_other_primary_ip, sender=Device)
1013
- ipfabricsync.status = DataSourceStatusChoices.COMPLETED
1014
+ ipfabricsync.status = IPFabricSyncStatusChoices.COMPLETED
1014
1015
  except Exception as e:
1015
- ipfabricsync.status = DataSourceStatusChoices.FAILED
1016
+ ipfabricsync.status = IPFabricSyncStatusChoices.FAILED
1016
1017
  logger.debug(f"Merging {self.name} Failed: `{e}`")
1017
1018
 
1018
1019
  logger.debug(f"Completed merge {self.name}")
@@ -1039,8 +1040,8 @@ class IPFabricIngestionIssue(models.Model):
1039
1040
 
1040
1041
  class Meta:
1041
1042
  ordering = ["timestamp"]
1042
- verbose_name = "IP Fabric Ingestion Issue"
1043
- verbose_name_plural = "IP Fabric Ingestion Issues"
1043
+ verbose_name = _("IP Fabric Ingestion Issue")
1044
+ verbose_name_plural = _("IP Fabric Ingestion Issues")
1044
1045
 
1045
1046
  def __str__(self):
1046
1047
  return f"[{self.timestamp}] {self.message}"
@@ -1,3 +1,4 @@
1
+ from django.utils.translation import gettext as _
1
2
  from netbox.plugins import PluginMenu
2
3
  from netbox.plugins import PluginMenuButton
3
4
  from netbox.plugins import PluginMenuItem
@@ -6,7 +7,7 @@ from netbox.plugins import PluginMenuItem
6
7
  sync_buttons = [
7
8
  PluginMenuButton(
8
9
  link="plugins:ipfabric_netbox:ipfabricsync_add",
9
- title="Add",
10
+ title=_("Add"),
10
11
  icon_class="mdi mdi-plus-thick",
11
12
  permissions=["ipfabric_netbox.add_ipfabricsync"],
12
13
  )
@@ -15,7 +16,7 @@ sync_buttons = [
15
16
  source_buttons = [
16
17
  PluginMenuButton(
17
18
  link="plugins:ipfabric_netbox:ipfabricsource_add",
18
- title="Add",
19
+ title=_("Add"),
19
20
  icon_class="mdi mdi-plus-thick",
20
21
  permissions=["ipfabric_netbox.add_ipfabricsource"],
21
22
  )
@@ -23,33 +24,33 @@ source_buttons = [
23
24
 
24
25
  source = PluginMenuItem(
25
26
  link="plugins:ipfabric_netbox:ipfabricsource_list",
26
- link_text="Sources",
27
+ link_text=_("Sources"),
27
28
  buttons=source_buttons,
28
29
  permissions=["ipfabric_netbox.view_ipfabricsource"],
29
30
  )
30
31
 
31
32
  snapshot = PluginMenuItem(
32
33
  link="plugins:ipfabric_netbox:ipfabricsnapshot_list",
33
- link_text="Snapshots",
34
+ link_text=_("Snapshots"),
34
35
  permissions=["ipfabric_netbox.view_ipfabricsnapshot"],
35
36
  )
36
37
 
37
38
 
38
39
  ingestion = PluginMenuItem(
39
40
  link="plugins:ipfabric_netbox:ipfabricsync_list",
40
- link_text="Syncs",
41
+ link_text=_("Syncs"),
41
42
  buttons=sync_buttons,
42
43
  permissions=["ipfabric_netbox.view_ipfabricsync"],
43
44
  )
44
45
 
45
46
  tmg = PluginMenuItem(
46
47
  link="plugins:ipfabric_netbox:ipfabrictransformmapgroup_list",
47
- link_text="Transform Map Groups",
48
+ link_text=_("Transform Map Groups"),
48
49
  permissions=["ipfabric_netbox.view_ipfabrictransformmapgroup"],
49
50
  buttons=[
50
51
  PluginMenuButton(
51
52
  link="plugins:ipfabric_netbox:ipfabrictransformmapgroup_add",
52
- title="Add",
53
+ title=_("Add"),
53
54
  icon_class="mdi mdi-plus-thick",
54
55
  permissions=["ipfabric_netbox.add_ipfabrictransformmapgroup"],
55
56
  )
@@ -58,12 +59,12 @@ tmg = PluginMenuItem(
58
59
 
59
60
  tm = PluginMenuItem(
60
61
  link="plugins:ipfabric_netbox:ipfabrictransformmap_list",
61
- link_text="Transform Maps",
62
+ link_text=_("Transform Maps"),
62
63
  permissions=["ipfabric_netbox.view_ipfabrictransformmap"],
63
64
  buttons=[
64
65
  PluginMenuButton(
65
66
  link="plugins:ipfabric_netbox:ipfabrictransformmap_add",
66
- title="Add",
67
+ title=_("Add"),
67
68
  icon_class="mdi mdi-plus-thick",
68
69
  permissions=["ipfabric_netbox.add_ipfabrictransformmap"],
69
70
  )
ipfabric_netbox/tables.py CHANGED
@@ -68,7 +68,7 @@ class IPFabricTransformMapGroupTable(NetBoxTable):
68
68
  maps_count = columns.LinkedCountColumn(
69
69
  viewname="plugins:ipfabric_netbox:ipfabrictransformmap_list",
70
70
  url_params={"group_id": "pk"},
71
- verbose_name="Transform Maps",
71
+ verbose_name=_("Transform Maps"),
72
72
  )
73
73
 
74
74
  class Meta(NetBoxTable.Meta):
@@ -90,9 +90,11 @@ class IPFabricTransformMapTable(NetBoxTable):
90
90
 
91
91
  class IPFabricIngestionTable(NetBoxTable):
92
92
  name = tables.Column(linkify=True)
93
- sync = tables.Column(verbose_name="IP Fabric Sync", linkify=True)
93
+ sync = tables.Column(verbose_name=_("IP Fabric Sync"), linkify=True)
94
94
  branch = tables.Column(linkify=True)
95
- changes = tables.Column(accessor="staged_changes", verbose_name="Number of Changes")
95
+ changes = tables.Column(
96
+ accessor="staged_changes", verbose_name=_("Number of Changes")
97
+ )
96
98
  actions = columns.ActionsColumn(actions=("delete",))
97
99
 
98
100
  class Meta(NetBoxTable.Meta):
@@ -126,7 +128,7 @@ class IPFabricSnapshotTable(NetBoxTable):
126
128
  class IPFabricSourceTable(NetBoxTable):
127
129
  name = tables.Column(linkify=True)
128
130
  status = columns.ChoiceFieldColumn()
129
- snapshot_count = tables.Column(verbose_name="Snapshots")
131
+ snapshot_count = tables.Column(verbose_name=_("Snapshots"))
130
132
  tags = columns.TagColumn(url_name="core:datasource_list")
131
133
 
132
134
  class Meta(NetBoxTable.Meta):
@@ -148,13 +150,13 @@ class IPFabricSyncTable(NetBoxTable):
148
150
  name = tables.Column(linkify=True)
149
151
  status = columns.ChoiceFieldColumn()
150
152
  snapshot_name = tables.Column(
151
- verbose_name="Snapshot Name",
153
+ verbose_name=_("Snapshot Name"),
152
154
  accessor="snapshot_data",
153
155
  linkify=True,
154
156
  )
155
157
  last_ingestion = tables.Column(
156
158
  accessor="last_ingestion",
157
- verbose_name="Last Ingestion",
159
+ verbose_name=_("Last Ingestion"),
158
160
  linkify=True,
159
161
  )
160
162
 
@@ -186,9 +188,9 @@ class IPFabricIngestionChangesTable(NetBoxTable):
186
188
  id = tables.Column(verbose_name=_("ID"))
187
189
  pk = None
188
190
  object_type = tables.Column(
189
- accessor="object_type.model", verbose_name="Object Type"
191
+ accessor="object_type.model", verbose_name=_("Object Type")
190
192
  )
191
- object = tables.Column(verbose_name="Object")
193
+ object = tables.Column(verbose_name=_("Object"))
192
194
  actions = columns.TemplateColumn(template_code=DIFF_BUTTON)
193
195
 
194
196
  def render_object(self, value, record):
@@ -225,8 +227,8 @@ class IPFabricIngestionChangesTable(NetBoxTable):
225
227
 
226
228
  class IPFabricIngestionIssuesTable(NetBoxTable):
227
229
  id = tables.Column(verbose_name=_("ID"))
228
- exception = tables.Column(verbose_name="Exception Type")
229
- message = tables.Column(verbose_name="Error Message")
230
+ exception = tables.Column(verbose_name=_("Exception Type"))
231
+ message = tables.Column(verbose_name=_("Error Message"))
230
232
  actions = None
231
233
 
232
234
  class Meta(NetBoxTable.Meta):
@@ -1,13 +1,16 @@
1
1
  {% load form_helpers %}
2
+ {% load i18n %}
2
3
 
3
4
  <form action="{{ form_url }}" method="post">
4
5
  {% csrf_token %}
5
6
 
6
7
  <div class="modal-header">
7
- <h5 class="modal-title">Confirm Clone</h5>
8
+ <h5 class="modal-title">{% trans "Confirm Clone" %}</h5>
8
9
  </div>
9
10
  <div class="modal-body">
11
+ {% blocktrans trimmed with count=selected_objects|length %}
10
12
  <p>Are you sure you want to <strong class="text-danger">clone</strong> {{ object_type }} <strong>{{ object }}</strong>?</p>
13
+ {% endblocktrans %}
11
14
  {% if form.non_field_errors %}
12
15
  <div class="form-text text-danger">
13
16
  {{ form.non_field_errors }}
@@ -17,11 +20,11 @@
17
20
  </div>
18
21
  <div class="modal-footer">
19
22
  {% if return_url %}
20
- <a href="{{ return_url }}" class="btn btn-outline-secondary">Cancel</a>
23
+ <a href="{{ return_url }}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
21
24
  {% else %}
22
- <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
25
+ <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
23
26
  {% endif %}
24
- <button hx-post="{% url 'plugins:ipfabric_netbox:ipfabrictransformmap_clone' pk=pk %}" hx-target="#htmx-modal-content" type="submit" class="btn btn-danger">Clone</button>
27
+ <button hx-post="{% url 'plugins:ipfabric_netbox:ipfabrictransformmap_clone' pk=pk %}" hx-target="#htmx-modal-content" type="submit" class="btn btn-danger">{% trans "Clone" %}</button>
25
28
  </div>
26
29
  </div>
27
30
  </form>
@@ -1,13 +1,15 @@
1
+ {% load i18n %}
1
2
  <div class="modal-content" id="htmx-modal-content">
2
3
  <div class="modal-header">
3
- <h5 class="modal-title">Change Diff {{ change }}</h5>
4
+ <h5 class="modal-title">
5
+ {% blocktrans %}Change Diff {{ change }}{% endblocktrans %}</h5>
4
6
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
5
7
  </div>
6
8
  <div class="modal-body">
7
9
  <div class="row mb-3">
8
10
  <div class="col-6">
9
11
  <div class="card">
10
- <h5 class="card-header">Pre-Change Data</h5>
12
+ <h5 class="card-header">%{ trans "Pre-Change Data" %}</h5>
11
13
  <div class="card-body">
12
14
  {% if prechange_data %}
13
15
  <pre class="change-data">{% for k, v in prechange_data.items %}{% spaceless %}
@@ -15,14 +17,14 @@
15
17
  {% endspaceless %}{% endfor %}
16
18
  </pre>
17
19
  {% else %}
18
- <span class="text-muted">None</span>
20
+ <span class="text-muted">%{ trans "None" %}</span>
19
21
  {% endif %}
20
22
  </div>
21
23
  </div>
22
24
  </div>
23
25
  <div class="col-6">
24
26
  <div class="card">
25
- <h5 class="card-header">Post-Change Data</h5>
27
+ <h5 class="card-header">%{ trans "Post-Change Data" %}</h5>
26
28
  <div class="card-body">
27
29
  {% if postchange_data %}
28
30
  <pre class="change-data">{% for k, v in postchange_data.items %}{% spaceless %}
@@ -36,7 +38,7 @@
36
38
  <div class="col">
37
39
  <div class="card">
38
40
  <div class="card-header">
39
- <h5 class="d-inline">Difference</h5>
41
+ <h5 class="d-inline">%{ trans "Difference" %}</h5>
40
42
  <!-- <div class="btn-group btn-group-sm float-end noprint">
41
43
  <a {% if prev_change %}href="{% url 'extras:objectchange' pk=prev_change.pk %}"{% else %}disabled{% endif %} class="btn btn-outline-secondary">
42
44
  <i class="mdi mdi-chevron-left" aria-hidden="true"></i> Previous
@@ -50,11 +52,11 @@
50
52
  {% if diff_added == diff_removed %}
51
53
  <span class="text-muted" style="margin-left: 10px;">
52
54
  {% if object.action == 'create' %}
53
- Object Created
55
+ %{ trans "Object Created" %}
54
56
  {% elif object.action == 'delete' %}
55
- Object Deleted
57
+ %{ trans "Object Deleted" %}
56
58
  {% else %}
57
- No Changes
59
+ %{ trans "No Changes" %}
58
60
  {% endif %}
59
61
  </span>
60
62
  {% else %}
@@ -1,12 +1,14 @@
1
+ {% load i18n %}
2
+
1
3
  <div class="modal-header">
2
- <h5 class="modal-title">Raw Data {{ object.pk }}</h5>
4
+ <h5 class="modal-title">{% blocktrans %}Raw Data {{ object.pk }}{% endblocktrans %}</h5>
3
5
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
4
6
  </div>
5
7
  <div class="modal-body">
6
8
  <div class="row mb-3">
7
9
  <div class="col-12">
8
10
  <div class="card">
9
- <h5 class="card-header">JSON Output</h5>
11
+ <h5 class="card-header">{% trans "JSON Output" %}</h5>
10
12
  <div class="card-body">
11
13
  <pre>{{ object.data | json }}</pre>
12
14
  </div>
@@ -1,6 +1,7 @@
1
+ {% load i18n %}
1
2
  {# Indicates that a job result is still pending; used for HTMX requests #}
2
3
  <div class="spinner-border float-start me-1" id="spinner" role="status">
3
- <span class="visually-hidden">Loading...</span>
4
+ <span class="visually-hidden">{% trans "Loading..." %}</span>
4
5
  </div>
5
- <h3>Logs pending...</h3>
6
- <small class="text-muted">Last updated {% now "H:i:s" %}</small>
6
+ <h3>{% trans "Logs pending..." %}</h3>
7
+ <small class="text-muted">{% trans "Last updated" %} {% now "H:i:s" %}</small>
@@ -1,22 +1,24 @@
1
1
  {% load form_helpers %}
2
-
2
+ {% load i18n %}
3
3
  <form action="{{ form_url }}" method="post">
4
4
  {% csrf_token %}
5
5
 
6
6
  <div class="modal-header">
7
- <h5 class="modal-title">Confirm Merge</h5>
7
+ <h5 class="modal-title">{% trans "Confirm Merge" %}</h5>
8
8
  </div>
9
9
  <div class="modal-body">
10
+ {% blocktrans %}
10
11
  <p>Are you sure you want to <strong class="text-danger">merge</strong> {{ object_type }} <strong>{{ object }}</strong>?</p>
12
+ {% endblocktrans %}
11
13
  {% render_form form %}
12
14
  </div>
13
15
  <div class="modal-footer">
14
16
  {% if return_url %}
15
- <a href="{{ return_url }}" class="btn btn-outline-secondary">Cancel</a>
17
+ <a href="{{ return_url }}" class="btn btn-outline-secondary">{% trans "Cancel" %}</a>
16
18
  {% else %}
17
- <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
19
+ <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
18
20
  {% endif %}
19
- <button type="submit" class="btn btn-danger">Merge</button>
21
+ <button type="submit" class="btn btn-danger">{% trans "Merge" %}</button>
20
22
  </div>
21
23
  </div>
22
24
  </form>
@@ -1,8 +1,10 @@
1
+ {% load i18n %}
2
+
1
3
  <div class="btn-group" role="group" aria-label="Button group with nested dropdown">
2
4
  <div class="btn-group" role="group">
3
5
  <button id="btnGroupDrop1" type="button" class="btn btn-sm btn-success dropdown-toggle" data-bs-toggle="dropdown"
4
6
  aria-expanded="false">
5
- IP Fabric Topology
7
+ {% trans "IP Fabric Topology" %}
6
8
  </button>
7
9
  <ul class="dropdown-menu" aria-labelledby="btnGroupDrop1">
8
10
  {% if source is not None %}
@@ -10,19 +12,19 @@
10
12
  hx-get="{% url 'plugins:ipfabric_netbox:ipfabricsource_topology' pk=source.pk site=object.pk %}?snapshot=$last&source={{ source.id }}"
11
13
  hx-target="#topology-modal-content" data-bs-toggle="modal" data-bs-target="#topology-modal"
12
14
  class="dropdown-item">
13
- Last Snapshot
15
+ {% trans "Last Snapshot" %}
14
16
  </a>
15
17
  </li>
16
18
  <li><a href="#"
17
19
  hx-get="{% url 'plugins:ipfabric_netbox:ipfabricsource_topology' pk=source.pk site=object.pk %}?snapshot=$prev&source={{ source.id }}"
18
20
  hx-target="#topology-modal-content" data-bs-toggle="modal" data-bs-target="#topology-modal"
19
21
  class="dropdown-item">
20
- Previous Snapshot
22
+ {% trans "Previous Snapshot" %}
21
23
  </a>
22
24
  </li>
23
25
  {% else %}
24
26
  <li>
25
- <span class="dropdown-item text-danger">No IP Fabric Source Found for this Site</span>
27
+ <span class="dropdown-item text-danger">{% trans "No IP Fabric Source Found for this Site" %}</span>
26
28
  </li>
27
29
  {% endif %}
28
30
  </ul>
@@ -33,13 +35,13 @@
33
35
  <div class="modal-dialog modal-xl">
34
36
  <div class="modal-content">
35
37
  <div class="modal-header">
36
- <h5 class="modal-title">{{ object.name }} Topology</h5>
38
+ <h5 class="modal-title">{{ object.name }} {% trans "Topology" %}</h5>
37
39
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
38
40
  </div>
39
41
  <div id="topology-modal-content">
40
42
  <div class="modal-body">
41
43
  <div class="d-flex align-items-center">
42
- <strong role="status">Loading...</strong>
44
+ <strong role="status">{% trans "Loading..." %}</strong>
43
45
  <div class="spinner-border ms-auto" aria-hidden="true"></div>
44
46
  </div>
45
47
  </div>