nautobot 3.0.0rc1__py3-none-any.whl → 3.0.1__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 nautobot might be problematic. Click here for more details.

Files changed (103) hide show
  1. nautobot/apps/forms.py +8 -0
  2. nautobot/apps/templatetags.py +231 -0
  3. nautobot/apps/testing.py +11 -1
  4. nautobot/apps/ui.py +21 -1
  5. nautobot/apps/utils.py +26 -1
  6. nautobot/core/celery/__init__.py +46 -1
  7. nautobot/core/cli/bootstrap_v3_to_v5.py +185 -44
  8. nautobot/core/cli/bootstrap_v3_to_v5_changes.yaml +314 -0
  9. nautobot/core/graphql/generators.py +2 -2
  10. nautobot/core/jobs/bulk_actions.py +12 -6
  11. nautobot/core/jobs/cleanup.py +13 -1
  12. nautobot/core/settings.py +13 -0
  13. nautobot/core/settings.yaml +22 -0
  14. nautobot/core/settings_funcs.py +11 -1
  15. nautobot/core/tables.py +19 -1
  16. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  17. nautobot/core/templates/components/panel/header_extra_content_table.html +9 -3
  18. nautobot/core/templates/generic/object_create.html +1 -1
  19. nautobot/core/templates/inc/header.html +9 -10
  20. nautobot/core/templates/login.html +16 -1
  21. nautobot/core/templates/nautobot_config.py.j2 +14 -1
  22. nautobot/core/templates/redoc_ui.html +3 -0
  23. nautobot/core/templatetags/helpers.py +3 -3
  24. nautobot/core/testing/views.py +3 -1
  25. nautobot/core/tests/test_graphql.py +13 -0
  26. nautobot/core/tests/test_jobs.py +118 -0
  27. nautobot/core/tests/test_views.py +24 -0
  28. nautobot/core/ui/bulk_buttons.py +2 -3
  29. nautobot/core/utils/lookup.py +2 -3
  30. nautobot/core/utils/permissions.py +1 -1
  31. nautobot/core/views/generic.py +1 -0
  32. nautobot/core/views/mixins.py +37 -10
  33. nautobot/core/views/renderers.py +1 -0
  34. nautobot/core/views/utils.py +3 -3
  35. nautobot/data_validation/views.py +1 -9
  36. nautobot/dcim/forms.py +9 -9
  37. nautobot/dcim/models/devices.py +3 -3
  38. nautobot/dcim/tables/power.py +3 -0
  39. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +1 -1
  40. nautobot/dcim/views.py +30 -44
  41. nautobot/extras/api/views.py +14 -3
  42. nautobot/extras/choices.py +3 -0
  43. nautobot/extras/jobs.py +48 -2
  44. nautobot/extras/migrations/0132_approval_workflow_seed_data.py +127 -0
  45. nautobot/extras/models/approvals.py +11 -1
  46. nautobot/extras/models/models.py +19 -0
  47. nautobot/extras/models/relationships.py +3 -1
  48. nautobot/extras/tables.py +35 -18
  49. nautobot/extras/templates/extras/approval_workflow/approve.html +9 -2
  50. nautobot/extras/templates/extras/approval_workflow/deny.html +9 -3
  51. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +1 -1
  52. nautobot/extras/templates/extras/customfield_update.html +1 -1
  53. nautobot/extras/templates/extras/dynamicgroup_update.html +2 -2
  54. nautobot/extras/templates/extras/inc/approval_buttons_column.html +10 -2
  55. nautobot/extras/templates/extras/inc/job_tiles.html +2 -2
  56. nautobot/extras/templates/extras/inc/jobresult.html +1 -1
  57. nautobot/extras/templates/extras/metadatatype_create.html +1 -1
  58. nautobot/extras/templates/extras/object_approvalworkflow.html +2 -3
  59. nautobot/extras/templates/extras/secretsgroup_update.html +1 -1
  60. nautobot/extras/tests/test_api.py +57 -3
  61. nautobot/extras/tests/test_customfields_filters.py +84 -4
  62. nautobot/extras/tests/test_views.py +323 -6
  63. nautobot/extras/views.py +114 -39
  64. nautobot/ipam/constants.py +2 -2
  65. nautobot/ipam/tables.py +7 -6
  66. nautobot/load_balancers/constants.py +6 -0
  67. nautobot/load_balancers/migrations/0001_initial.py +14 -3
  68. nautobot/load_balancers/models.py +5 -4
  69. nautobot/load_balancers/tables.py +5 -0
  70. nautobot/project-static/dist/css/nautobot.css +1 -1
  71. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  72. nautobot/project-static/dist/js/graphql-libraries.js +1 -1
  73. nautobot/project-static/dist/js/graphql-libraries.js.map +1 -1
  74. nautobot/project-static/dist/js/libraries.js +1 -1
  75. nautobot/project-static/dist/js/libraries.js.LICENSE.txt +38 -2
  76. nautobot/project-static/dist/js/libraries.js.map +1 -1
  77. nautobot/project-static/dist/js/nautobot-graphiql.js +1 -1
  78. nautobot/project-static/dist/js/nautobot-graphiql.js.map +1 -1
  79. nautobot/project-static/dist/js/nautobot.js +1 -1
  80. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  81. nautobot/project-static/img/dark-theme.png +0 -0
  82. nautobot/project-static/img/light-theme.png +0 -0
  83. nautobot/project-static/img/system-theme.png +0 -0
  84. nautobot/project-static/js/forms.js +1 -85
  85. nautobot/tenancy/tables.py +3 -2
  86. nautobot/tenancy/views.py +3 -2
  87. nautobot/ui/package-lock.json +553 -569
  88. nautobot/ui/package.json +10 -10
  89. nautobot/ui/src/js/checkbox.js +132 -0
  90. nautobot/ui/src/js/nautobot.js +6 -0
  91. nautobot/ui/src/js/select2.js +69 -73
  92. nautobot/ui/src/js/theme.js +129 -39
  93. nautobot/ui/src/scss/nautobot.scss +11 -1
  94. nautobot/vpn/templates/vpn/vpnprofile_create.html +2 -2
  95. nautobot/wireless/filters.py +15 -1
  96. nautobot/wireless/tables.py +18 -14
  97. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +1 -1
  98. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/METADATA +2 -2
  99. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/RECORD +103 -98
  100. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/LICENSE.txt +0 -0
  101. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/NOTICE +0 -0
  102. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/WHEEL +0 -0
  103. {nautobot-3.0.0rc1.dist-info → nautobot-3.0.1.dist-info}/entry_points.txt +0 -0
@@ -21,72 +21,6 @@ function slugify(s, num_chars) {
21
21
  * JS-ify Inputs
22
22
  */
23
23
 
24
- // Static choice selection
25
- function initializeCheckboxes(context){
26
- // Track last selected checkbox for range selection
27
- let lastSelectedIndex = null;
28
-
29
- // "Toggle" checkbox for object lists (PK column)
30
- document.querySelectorAll('input[type="checkbox"].toggle').forEach(toggleCheckbox => {
31
- toggleCheckbox.addEventListener('click', function () {
32
- const isChecked = this.checked;
33
- // Check/uncheck all pk column checkboxes in the table
34
- this.closest('table')
35
- .querySelectorAll('input[type="checkbox"][name="pk"]:not([visually-hidden])')
36
- .forEach(checkbox => checkbox.checked = isChecked);
37
-
38
- // Show the "select all" box if present
39
- const selectAllBox = document.getElementById('select_all_box');
40
- if (selectAllBox) {
41
- if (isChecked) {
42
- // unhide the select all objects form that contains the bulk action buttons
43
- selectAllBox.classList.remove('visually-hidden');
44
- } else {
45
- const selectAll = document.getElementById('select_all');
46
- if (selectAll) selectAll.checked = false;
47
- }
48
- }
49
- });
50
-
51
- // Reset last selected index when using toggle all
52
- lastSelectedIndex = null;
53
- });
54
-
55
- // Uncheck the "toggle" and "select all" checkboxes if an item is unchecked
56
- document.querySelectorAll('input[type="checkbox"][name="pk"]').forEach((itemCheckbox) => {
57
- itemCheckbox.addEventListener('click', function () {
58
- const table = this.closest('table');
59
- const allCheckboxes = Array.from(table.querySelectorAll('input[type="checkbox"][name="pk"]:not([visually-hidden])'));
60
- const currentIndex = allCheckboxes.indexOf(this);
61
-
62
- // Handle shift-click for range selection/deselection
63
- if (event.shiftKey && lastSelectedIndex !== null) {
64
- // Create range from previous click to current click
65
- const startIndex = Math.min(lastSelectedIndex, currentIndex);
66
- const endIndex = Math.max(lastSelectedIndex, currentIndex);
67
-
68
- // Use the clicked item's new state for entire range
69
- const shouldSelect = this.checked;
70
-
71
- // Apply to entire range
72
- for (let i = startIndex; i <= endIndex; i++) {
73
- allCheckboxes[i].checked = shouldSelect;
74
- }
75
- }
76
-
77
- // Always update anchor to current click (normal click or shift+click)
78
- lastSelectedIndex = currentIndex;
79
-
80
- // Uncheck the "toggle" and "select all" checkboxes if any item is unchecked
81
- const hasUnchecked = allCheckboxes.some(checkbox => !checkbox.checked);
82
- if (hasUnchecked) {
83
- document.querySelectorAll('input[type="checkbox"].toggle, #select_all')
84
- .forEach(checkbox => checkbox.checked = false);
85
- }
86
- });
87
- });
88
- }
89
-
90
24
  function repopulateAutoField(context, targetField, sourceFields, maxLength, transformValue = null){
91
25
  const newValues = sourceFields.map(function(sourceFieldName){
92
26
  const sourceFieldId = `id_${sourceFieldName}`;
@@ -333,23 +267,6 @@ function initializeImagePreview(context){
333
267
  });
334
268
  }
335
269
 
336
- function initializeSelectAllForm(context){
337
- // selectAll is the checkbox that selects all objects
338
- const selectAll = document.querySelector('#select_all');
339
- // selectAllBox is the div that contains the form bulk action buttons
340
- const selectAllBox = document.querySelector('#select_all_box');
341
-
342
- if (selectAll && selectAllBox) {
343
- selectAll.addEventListener('click', function () {
344
- // If the selectAll checkbox is checked, enable all form bulk action buttons
345
- const isChecked = this.checked;
346
- selectAllBox.querySelectorAll('button').forEach(button => {
347
- button.disabled = !isChecked;
348
- });
349
- });
350
- }
351
- }
352
-
353
270
  function initializeResultPerPageSelection(context){
354
271
  this_context = $(context);
355
272
  this_context.find('select#per_page').change(function() {
@@ -359,7 +276,6 @@ function initializeResultPerPageSelection(context){
359
276
 
360
277
  function initializeInputs(context) {
361
278
  const this_context = $(context);
362
- initializeCheckboxes(this_context)
363
279
  initializeSlugField(this_context)
364
280
  initializeAutoPopulateField(this_context)
365
281
  initializeFormActionClick(this_context)
@@ -368,8 +284,8 @@ function initializeInputs(context) {
368
284
  initializeVLANModeSelection(this_context)
369
285
  initializeSortableList(this_context)
370
286
  initializeImagePreview(this_context)
371
- initializeSelectAllForm(this_context)
372
287
 
288
+ window.nb.checkbox.initializeCheckboxes()
373
289
  window.nb.select2.initializeSelect2Fields(this_context)
374
290
  }
375
291
 
@@ -77,8 +77,9 @@ class TenantTable(BaseTable):
77
77
  name = tables.Column(linkify=True)
78
78
  tenant_group = tables.Column(linkify=True)
79
79
  tags = TagColumn(url_name="tenancy:tenant_list")
80
+ actions = ButtonsColumn(Tenant)
80
81
 
81
82
  class Meta(BaseTable.Meta):
82
83
  model = Tenant
83
- fields = ("pk", "name", "tenant_group", "description", "tags")
84
- default_columns = ("pk", "name", "tenant_group", "description")
84
+ fields = ("pk", "name", "tenant_group", "description", "tags", "actions")
85
+ default_columns = ("pk", "name", "tenant_group", "description", "actions")
nautobot/tenancy/views.py CHANGED
@@ -42,8 +42,9 @@ class TenantGroupUIViewSet(NautobotUIViewSet):
42
42
  ObjectsTablePanel(
43
43
  weight=100,
44
44
  section=SectionChoices.RIGHT_HALF,
45
- context_table_key="tenant_table",
46
45
  exclude_columns=["tenant_group"],
46
+ context_table_key="tenant_table",
47
+ related_field_name="tenant_group",
47
48
  ),
48
49
  )
49
50
  )
@@ -59,7 +60,7 @@ class TenantGroupUIViewSet(NautobotUIViewSet):
59
60
  tenant_group__in=instance.descendants(include_self=True)
60
61
  )
61
62
 
62
- tenant_table = tables.TenantTable(tenants)
63
+ tenant_table = tables.TenantTable(tenants, configurable=True)
63
64
  tenant_table.columns.hide("tenant_group")
64
65
 
65
66
  paginate = {