nautobot 3.0.0a2__py3-none-any.whl → 3.0.0a3__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 (420) hide show
  1. nautobot/apps/choices.py +0 -2
  2. nautobot/apps/filters.py +7 -9
  3. nautobot/apps/models.py +2 -2
  4. nautobot/apps/ui.py +9 -1
  5. nautobot/circuits/filters.py +3 -2
  6. nautobot/circuits/navigation.py +3 -2
  7. nautobot/circuits/templates/circuits/circuit.html +1 -1
  8. nautobot/circuits/templates/circuits/circuit_create.html +3 -3
  9. nautobot/circuits/templates/circuits/circuittermination.html +1 -1
  10. nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
  11. nautobot/circuits/templates/circuits/circuittype.html +1 -1
  12. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
  13. nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
  14. nautobot/circuits/templates/circuits/providernetwork.html +1 -1
  15. nautobot/circuits/tests/integration/test_circuit.py +10 -13
  16. nautobot/cloud/filters.py +1 -1
  17. nautobot/cloud/navigation.py +3 -2
  18. nautobot/core/api/schema.py +1 -1
  19. nautobot/core/api/serializers.py +6 -1
  20. nautobot/core/api/urls.py +1 -0
  21. nautobot/core/api/views.py +8 -0
  22. nautobot/core/apps/__init__.py +11 -10
  23. nautobot/core/celery/__init__.py +3 -5
  24. nautobot/core/checks.py +46 -0
  25. nautobot/core/cli/bootstrap_v3_to_v5.py +70 -1
  26. nautobot/core/cli/migrate_deprecated_templates.py +200 -0
  27. nautobot/core/constants.py +3 -0
  28. nautobot/core/context_processors.py +9 -1
  29. nautobot/core/forms/forms.py +1 -1
  30. nautobot/core/jobs/__init__.py +6 -3
  31. nautobot/core/jobs/groups.py +31 -1
  32. nautobot/core/management/commands/generate_test_data.py +28 -9
  33. nautobot/core/models/generics.py +9 -1
  34. nautobot/core/models/tree_queries.py +10 -5
  35. nautobot/core/settings.py +18 -12
  36. nautobot/core/settings.yaml +13 -7
  37. nautobot/core/signals.py +12 -1
  38. nautobot/core/tables.py +13 -6
  39. nautobot/core/templates/40x.html +1 -1
  40. nautobot/core/templates/500.html +2 -2
  41. nautobot/core/templates/admin/config/config.html +12 -12
  42. nautobot/core/templates/admin/index.html +3 -3
  43. nautobot/core/templates/buttons/export.html +1 -1
  44. nautobot/core/templates/components/button/dropdown.html +5 -3
  45. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  46. nautobot/core/templates/components/panel/panel.html +3 -3
  47. nautobot/core/templates/components/tab/content_wrapper.html +2 -3
  48. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
  49. nautobot/core/templates/echarts/echarts.html +1 -1
  50. nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
  51. nautobot/core/templates/generic/object_bulk_create.html +4 -3
  52. nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
  53. nautobot/core/templates/generic/object_bulk_remove.html +2 -2
  54. nautobot/core/templates/generic/object_bulk_update.html +5 -4
  55. nautobot/core/templates/generic/object_create.html +5 -4
  56. nautobot/core/templates/generic/object_import.html +2 -1
  57. nautobot/core/templates/generic/object_list.html +12 -4
  58. nautobot/core/templates/generic/object_notes.html +5 -3
  59. nautobot/core/templates/generic/object_retrieve.html +2 -3
  60. nautobot/core/templates/graphene/graphiql.html +7 -7
  61. nautobot/core/templates/home.html +1 -1
  62. nautobot/core/templates/import_success.html +2 -1
  63. nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
  64. nautobot/core/templates/inc/created_updated.html +7 -3
  65. nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
  66. nautobot/core/templates/inc/form_static_field.html +6 -0
  67. nautobot/core/templates/inc/header.html +1 -1
  68. nautobot/core/templates/inc/image_attachments.html +2 -1
  69. nautobot/core/templates/inc/nav_menu.html +2 -1
  70. nautobot/core/templates/inc/search_panel.html +4 -4
  71. nautobot/core/templates/login.html +4 -2
  72. nautobot/core/templates/nautobot_config.py.j2 +6 -5
  73. nautobot/core/templates/redoc_ui.html +7 -0
  74. nautobot/core/templates/search.html +1 -1
  75. nautobot/core/templates/swagger_ui.html +17 -3
  76. nautobot/core/templates/system_jobs/import_objects.html +1 -2
  77. nautobot/core/templates/utilities/confirmation_form.html +2 -2
  78. nautobot/core/templates/utilities/obj_table.html +10 -2
  79. nautobot/core/templates/utilities/render_field.html +7 -7
  80. nautobot/core/templates/utilities/render_jinja2.html +2 -2
  81. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +4 -4
  82. nautobot/core/templates/utilities/theme_preview.html +16 -3
  83. nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
  84. nautobot/core/templatetags/helpers.py +52 -6
  85. nautobot/core/testing/api.py +68 -9
  86. nautobot/core/testing/filters.py +0 -23
  87. nautobot/core/testing/integration.py +23 -10
  88. nautobot/core/testing/mixins.py +2 -0
  89. nautobot/core/testing/views.py +4 -0
  90. nautobot/core/tests/integration/test_app_home.py +34 -30
  91. nautobot/core/tests/integration/test_app_navbar.py +3 -0
  92. nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
  93. nautobot/core/tests/runner.py +9 -1
  94. nautobot/core/tests/test_api.py +5 -3
  95. nautobot/core/tests/test_breadcrumbs.py +6 -7
  96. nautobot/core/tests/test_checks.py +28 -0
  97. nautobot/core/tests/test_cli.py +40 -0
  98. nautobot/core/tests/test_config.py +2 -1
  99. nautobot/core/tests/test_forms.py +55 -13
  100. nautobot/core/tests/test_jobs.py +75 -1
  101. nautobot/core/tests/test_nautobot_server.py +2 -0
  102. nautobot/core/tests/test_navigations.py +76 -1
  103. nautobot/core/tests/test_patch_social_django.py +42 -0
  104. nautobot/core/tests/test_tables.py +3 -1
  105. nautobot/core/tests/test_templatetags_helpers.py +53 -13
  106. nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
  107. nautobot/core/tests/test_tree_queries.py +14 -1
  108. nautobot/core/tests/test_ui.py +1 -1
  109. nautobot/core/tests/test_utils.py +31 -4
  110. nautobot/core/tests/test_views.py +159 -31
  111. nautobot/core/ui/breadcrumbs.py +2 -12
  112. nautobot/core/ui/choices.py +142 -10
  113. nautobot/core/ui/constants.py +76 -12
  114. nautobot/core/ui/object_detail.py +92 -12
  115. nautobot/core/urls.py +12 -1
  116. nautobot/core/utils/cache.py +2 -1
  117. nautobot/core/utils/filtering.py +17 -17
  118. nautobot/core/utils/lookup.py +3 -8
  119. nautobot/core/utils/module_loading.py +21 -0
  120. nautobot/core/utils/patch_social_django.py +128 -0
  121. nautobot/core/views/__init__.py +38 -1
  122. nautobot/core/views/generic.py +3 -3
  123. nautobot/core/views/mixins.py +15 -3
  124. nautobot/core/views/renderers.py +2 -0
  125. nautobot/core/views/viewsets.py +2 -1
  126. nautobot/data_validation/apps.py +1 -5
  127. nautobot/data_validation/custom_validators.py +4 -4
  128. nautobot/data_validation/filters.py +1 -1
  129. nautobot/data_validation/forms.py +40 -0
  130. nautobot/data_validation/migrations/0001_initial.py +0 -7
  131. nautobot/data_validation/migrations/0002_data_migration_from_app.py +0 -12
  132. nautobot/data_validation/models.py +16 -7
  133. nautobot/data_validation/navigation.py +8 -1
  134. nautobot/data_validation/tables.py +12 -5
  135. nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
  136. nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
  137. nautobot/data_validation/tests/__init__.py +2 -2
  138. nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
  139. nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
  140. nautobot/data_validation/tests/test_filters.py +8 -6
  141. nautobot/data_validation/tests/test_models.py +15 -0
  142. nautobot/data_validation/tests/test_views.py +190 -32
  143. nautobot/data_validation/urls.py +2 -5
  144. nautobot/data_validation/views.py +73 -40
  145. nautobot/dcim/api/serializers.py +0 -13
  146. nautobot/dcim/apps.py +4 -0
  147. nautobot/dcim/choices.py +16 -0
  148. nautobot/dcim/custom_validators.py +84 -0
  149. nautobot/dcim/filter_mixins.py +353 -4
  150. nautobot/dcim/{filters/__init__.py → filters.py} +2 -35
  151. nautobot/dcim/forms.py +1 -1
  152. nautobot/dcim/migrations/0078_remove_device_location_tenant_name_uniqueness.py +16 -0
  153. nautobot/dcim/migrations/0079_device_name_data_migration.py +59 -0
  154. nautobot/dcim/models/device_components.py +81 -68
  155. nautobot/dcim/models/devices.py +13 -16
  156. nautobot/dcim/navigation.py +7 -6
  157. nautobot/dcim/tables/devices.py +3 -0
  158. nautobot/dcim/tables/template_code.py +14 -14
  159. nautobot/dcim/templates/dcim/cable.html +2 -61
  160. nautobot/dcim/templates/dcim/cable_connect.html +28 -112
  161. nautobot/dcim/templates/dcim/cable_edit.html +2 -5
  162. nautobot/dcim/templates/dcim/cable_retrieve.html +61 -0
  163. nautobot/dcim/templates/dcim/cable_trace.html +1 -3
  164. nautobot/dcim/templates/dcim/cable_update.html +5 -0
  165. nautobot/dcim/templates/dcim/consoleport.html +6 -5
  166. nautobot/dcim/templates/dcim/consoleserverport.html +6 -5
  167. nautobot/dcim/templates/dcim/device/config.html +2 -2
  168. nautobot/dcim/templates/dcim/device/consoleports.html +1 -1
  169. nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -1
  170. nautobot/dcim/templates/dcim/device/devicebays.html +1 -1
  171. nautobot/dcim/templates/dcim/device/frontports.html +1 -1
  172. nautobot/dcim/templates/dcim/device/interfaces.html +1 -1
  173. nautobot/dcim/templates/dcim/device/inventory.html +1 -1
  174. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
  175. nautobot/dcim/templates/dcim/device/modulebays.html +1 -1
  176. nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -1
  177. nautobot/dcim/templates/dcim/device/powerports.html +1 -1
  178. nautobot/dcim/templates/dcim/device/rearports.html +1 -1
  179. nautobot/dcim/templates/dcim/device/status.html +8 -8
  180. nautobot/dcim/templates/dcim/device/wireless.html +1 -1
  181. nautobot/dcim/templates/dcim/device.html +1 -1
  182. nautobot/dcim/templates/dcim/device_component_add.html +2 -2
  183. nautobot/dcim/templates/dcim/device_create.html +5 -3
  184. nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
  185. nautobot/dcim/templates/dcim/device_list.html +73 -10
  186. nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
  187. nautobot/dcim/templates/dcim/devicetype.html +1 -1
  188. nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
  189. nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
  190. nautobot/dcim/templates/dcim/frontport.html +9 -8
  191. nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
  192. nautobot/dcim/templates/dcim/interface.html +26 -6
  193. nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
  194. nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
  195. nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
  196. nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
  197. nautobot/dcim/templates/dcim/location_retrieve.html +1 -242
  198. nautobot/dcim/templates/dcim/module/base.html +49 -9
  199. nautobot/dcim/templates/dcim/module_list.html +57 -8
  200. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  201. nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
  202. nautobot/dcim/templates/dcim/platform_create.html +1 -1
  203. nautobot/dcim/templates/dcim/powerfeed.html +1 -1
  204. nautobot/dcim/templates/dcim/powerpanel.html +1 -1
  205. nautobot/dcim/templates/dcim/powerport.html +5 -4
  206. nautobot/dcim/templates/dcim/rack_elevation_list.html +16 -4
  207. nautobot/dcim/templates/dcim/rack_retrieve.html +33 -15
  208. nautobot/dcim/templates/dcim/rearport.html +7 -6
  209. nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
  210. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
  211. nautobot/dcim/templates/dcim/virtualchassis_update.html +14 -6
  212. nautobot/dcim/tests/integration/test_controller.py +1 -0
  213. nautobot/dcim/tests/test_api.py +8 -0
  214. nautobot/dcim/tests/test_custom_validators.py +229 -0
  215. nautobot/dcim/tests/test_filters.py +12 -6
  216. nautobot/dcim/tests/test_models.py +63 -4
  217. nautobot/dcim/tests/test_views.py +63 -22
  218. nautobot/dcim/urls.py +64 -21
  219. nautobot/dcim/utils.py +3 -3
  220. nautobot/dcim/views.py +547 -273
  221. nautobot/extras/api/views.py +9 -1
  222. nautobot/extras/choices.py +2 -13
  223. nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
  224. nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
  225. nautobot/extras/{filters/__init__.py → filters.py} +14 -46
  226. nautobot/extras/forms/forms.py +5 -13
  227. nautobot/extras/forms/mixins.py +0 -41
  228. nautobot/extras/management/__init__.py +9 -0
  229. nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
  230. nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
  231. nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
  232. nautobot/extras/models/__init__.py +1 -2
  233. nautobot/extras/models/approvals.py +22 -13
  234. nautobot/extras/models/contacts.py +2 -0
  235. nautobot/extras/models/groups.py +44 -5
  236. nautobot/extras/models/jobs.py +59 -1
  237. nautobot/extras/models/mixins.py +28 -0
  238. nautobot/extras/models/models.py +13 -0
  239. nautobot/extras/models/secrets.py +1 -0
  240. nautobot/extras/models/statuses.py +0 -15
  241. nautobot/extras/navigation.py +13 -9
  242. nautobot/extras/plugins/__init__.py +33 -55
  243. nautobot/extras/plugins/tables.py +3 -3
  244. nautobot/extras/plugins/urls.py +2 -21
  245. nautobot/extras/plugins/utils.py +1 -33
  246. nautobot/extras/plugins/views.py +0 -4
  247. nautobot/extras/signals.py +20 -19
  248. nautobot/extras/tables.py +52 -68
  249. nautobot/extras/templates/extras/approval_dashboard.html +7 -5
  250. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
  251. nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
  252. nautobot/extras/templates/extras/computedfield.html +1 -1
  253. nautobot/extras/templates/extras/configcontext.html +1 -1
  254. nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
  255. nautobot/extras/templates/extras/customfield.html +1 -1
  256. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
  257. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  258. nautobot/extras/templates/extras/gitrepository_result.html +0 -2
  259. nautobot/extras/templates/extras/graphqlquery_retrieve.html +1 -96
  260. nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
  261. nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
  262. nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
  263. nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
  264. nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
  265. nautobot/extras/templates/extras/inc/json_format.html +10 -3
  266. nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
  267. nautobot/extras/templates/extras/job.html +29 -12
  268. nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
  269. nautobot/extras/templates/extras/job_edit.html +52 -46
  270. nautobot/extras/templates/extras/job_list.html +29 -25
  271. nautobot/extras/templates/extras/marketplace.html +5 -9
  272. nautobot/extras/templates/extras/object_configcontext.html +1 -1
  273. nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
  274. nautobot/extras/templates/extras/objectchange_retrieve.html +19 -37
  275. nautobot/extras/templates/extras/plugin_detail.html +26 -21
  276. nautobot/extras/templates/extras/plugins_list.html +16 -26
  277. nautobot/extras/templates/extras/role_retrieve.html +64 -0
  278. nautobot/extras/templates/extras/scheduledjob.html +4 -2
  279. nautobot/extras/templates/extras/secretsgroup.html +1 -1
  280. nautobot/extras/templates/extras/tag.html +1 -1
  281. nautobot/extras/templatetags/custom_links.py +12 -12
  282. nautobot/extras/templatetags/job_buttons.py +14 -12
  283. nautobot/extras/test_jobs/invalid_import.py +9 -0
  284. nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
  285. nautobot/extras/test_jobs/missing_import.py +11 -0
  286. nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
  287. nautobot/extras/tests/integration/test_customfields.py +8 -7
  288. nautobot/extras/tests/integration/test_dynamicgroups.py +5 -1
  289. nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
  290. nautobot/extras/tests/integration/test_plugins.py +18 -6
  291. nautobot/extras/tests/test_api.py +27 -18
  292. nautobot/extras/tests/test_approvals.py +38 -38
  293. nautobot/extras/tests/test_changelog.py +35 -3
  294. nautobot/extras/tests/test_customfields.py +22 -13
  295. nautobot/extras/tests/test_customfields_filters.py +479 -0
  296. nautobot/extras/tests/test_dynamicgroups.py +39 -1
  297. nautobot/extras/tests/test_filters.py +21 -19
  298. nautobot/extras/tests/test_forms.py +18 -21
  299. nautobot/extras/tests/test_jobs.py +25 -4
  300. nautobot/extras/tests/test_migrations.py +1 -0
  301. nautobot/extras/tests/test_models.py +13 -31
  302. nautobot/extras/tests/test_plugins.py +36 -10
  303. nautobot/extras/tests/test_views.py +31 -30
  304. nautobot/extras/views.py +81 -19
  305. nautobot/ipam/factory.py +7 -0
  306. nautobot/ipam/filter_mixins.py +38 -0
  307. nautobot/ipam/filters.py +27 -38
  308. nautobot/ipam/formfields.py +1 -1
  309. nautobot/ipam/forms.py +6 -3
  310. nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
  311. nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
  312. nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
  313. nautobot/ipam/models.py +29 -2
  314. nautobot/ipam/navigation.py +3 -2
  315. nautobot/ipam/signals.py +71 -0
  316. nautobot/ipam/tables.py +13 -6
  317. nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
  318. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
  319. nautobot/ipam/templates/ipam/ipaddress.html +14 -0
  320. nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
  321. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
  322. nautobot/ipam/templates/ipam/namespace_update.html +15 -0
  323. nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
  324. nautobot/ipam/templates/ipam/prefix_list.html +14 -13
  325. nautobot/ipam/templates/ipam/service.html +1 -1
  326. nautobot/ipam/templates/ipam/vlan.html +1 -1
  327. nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
  328. nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
  329. nautobot/ipam/tests/migration/test_migrations.py +89 -0
  330. nautobot/ipam/tests/test_api.py +13 -6
  331. nautobot/ipam/tests/test_filters.py +10 -0
  332. nautobot/ipam/tests/test_forms.py +1 -1
  333. nautobot/ipam/tests/test_models.py +43 -1
  334. nautobot/ipam/tests/test_tables.py +1 -2
  335. nautobot/ipam/tests/test_utils.py +1 -1
  336. nautobot/ipam/tests/test_views.py +13 -14
  337. nautobot/ipam/ui.py +0 -17
  338. nautobot/ipam/utils/migrations.py +16 -2
  339. nautobot/ipam/utils/testing.py +9 -3
  340. nautobot/ipam/views.py +46 -6
  341. nautobot/project-static/dist/css/nautobot.css +1 -1
  342. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  343. nautobot/project-static/dist/js/nautobot.js +1 -1
  344. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  345. nautobot/project-static/js/cabletrace.js +1 -1
  346. nautobot/project-static/js/interface_filtering.js +20 -16
  347. nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
  348. nautobot/project-static/nautobot-icons/cloud.svg +1 -1
  349. nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
  350. nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
  351. nautobot/project-static/nautobot-icons/elements.svg +1 -1
  352. nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
  353. nautobot/project-static/nautobot-icons/hammer.svg +1 -1
  354. nautobot/project-static/nautobot-icons/organization.svg +3 -0
  355. nautobot/project-static/nautobot-icons/secrets.svg +1 -1
  356. nautobot/project-static/nautobot-icons/security.svg +3 -0
  357. nautobot/project-static/nautobot-icons/server.svg +1 -1
  358. nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
  359. nautobot/project-static/nautobot-icons/star.svg +1 -1
  360. nautobot/tenancy/api/serializers.py +1 -0
  361. nautobot/tenancy/api/views.py +2 -1
  362. nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
  363. nautobot/tenancy/navigation.py +3 -1
  364. nautobot/tenancy/tests/test_filters.py +0 -2
  365. nautobot/tenancy/views.py +2 -1
  366. nautobot/ui/src/js/collapse.js +3 -3
  367. nautobot/ui/src/js/nautobot.js +16 -0
  368. nautobot/ui/src/scss/colors.scss +1 -1
  369. nautobot/ui/src/scss/nautobot.scss +61 -28
  370. nautobot/users/templates/users/profile.html +45 -12
  371. nautobot/users/templates/users/sessionkey_delete.html +1 -1
  372. nautobot/users/tests/test_api.py +4 -0
  373. nautobot/users/views.py +4 -2
  374. nautobot/virtualization/models.py +1 -68
  375. nautobot/virtualization/navigation.py +3 -2
  376. nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
  377. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  378. nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
  379. nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
  380. nautobot/virtualization/tests/test_api.py +3 -0
  381. nautobot/virtualization/tests/test_models.py +44 -4
  382. nautobot/vpn/__init__.py +0 -0
  383. nautobot/vpn/api/serializers.py +113 -0
  384. nautobot/vpn/api/urls.py +19 -0
  385. nautobot/vpn/api/views.py +70 -0
  386. nautobot/vpn/apps.py +8 -0
  387. nautobot/vpn/choices.py +171 -0
  388. nautobot/vpn/factory.py +209 -0
  389. nautobot/vpn/filters.py +233 -0
  390. nautobot/vpn/forms.py +486 -0
  391. nautobot/vpn/homepage.py +19 -0
  392. nautobot/vpn/migrations/0001_initial.py +541 -0
  393. nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
  394. nautobot/vpn/migrations/__init__.py +0 -0
  395. nautobot/vpn/models.py +527 -0
  396. nautobot/vpn/navigation.py +98 -0
  397. nautobot/vpn/tables.py +380 -0
  398. nautobot/vpn/templates/vpn/vpnprofile.html +2 -0
  399. nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
  400. nautobot/vpn/tests/__init__.py +0 -0
  401. nautobot/vpn/tests/test_api.py +341 -0
  402. nautobot/vpn/tests/test_filters.py +139 -0
  403. nautobot/vpn/tests/test_forms.py +294 -0
  404. nautobot/vpn/tests/test_models.py +97 -0
  405. nautobot/vpn/tests/test_views.py +281 -0
  406. nautobot/vpn/urls.py +16 -0
  407. nautobot/vpn/views.py +437 -0
  408. nautobot/wireless/navigation.py +3 -2
  409. nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
  410. nautobot/wireless/tests/test_api.py +1 -1
  411. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/METADATA +14 -14
  412. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/RECORD +417 -366
  413. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/entry_points.txt +1 -0
  414. nautobot/data_validation/template_content.py +0 -42
  415. nautobot/dcim/filters/mixins.py +0 -354
  416. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
  417. /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
  418. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/LICENSE.txt +0 -0
  419. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/NOTICE +0 -0
  420. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/WHEEL +0 -0
@@ -0,0 +1,61 @@
1
+ {% extends 'generic/object_retrieve.html' %}
2
+ {% load helpers %}
3
+
4
+ {% block content_left_page %}
5
+ <div class="card">
6
+ <div class="card-header">
7
+ <strong>Cable</strong>
8
+ </div>
9
+ <table class="table table-hover card-body attr-table">
10
+ <tr>
11
+ <td>Type</td>
12
+ <td>{{ object.get_type_display|placeholder }}</td>
13
+ </tr>
14
+ <tr>
15
+ <td>Status</td>
16
+ <td>
17
+ {{ object.status| hyperlinked_object_with_color }}
18
+ </td>
19
+ </tr>
20
+ <tr>
21
+ <td>Label</td>
22
+ <td>{{ object.label|placeholder }}</td>
23
+ </tr>
24
+ <tr>
25
+ <td>Color</td>
26
+ <td>
27
+ {% if object.color %}
28
+ <span class="label nb-color-block" style="background-color: #{{ object.color }}">&nbsp;</span>
29
+ {% else %}
30
+ <span class="text-secondary">&mdash;</span>
31
+ {% endif %}
32
+ </td>
33
+ </tr>
34
+ <tr>
35
+ <td>Length</td>
36
+ <td>
37
+ {% if object.length %}
38
+ {{ object.length }} {{ object.get_length_unit_display }}
39
+ {% else %}
40
+ <span class="text-secondary">&mdash;</span>
41
+ {% endif %}
42
+ </td>
43
+ </tr>
44
+ </table>
45
+ </div>
46
+ {% endblock content_left_page %}
47
+
48
+ {% block content_right_page %}
49
+ <div class="card">
50
+ <div class="card-header">
51
+ <strong>Termination A</strong>
52
+ </div>
53
+ {% include 'dcim/inc/cable_termination.html' with termination=object.termination_a %}
54
+ </div>
55
+ <div class="card">
56
+ <div class="card-header">
57
+ <strong>Termination B</strong>
58
+ </div>
59
+ {% include 'dcim/inc/cable_termination.html' with termination=object.termination_b %}
60
+ </div>
61
+ {% endblock content_right_page %}
@@ -1,9 +1,7 @@
1
1
  {% extends 'base.html' %}
2
2
  {% load helpers %}
3
3
 
4
- {% block header %}
5
- <h1>{% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}</h1>
6
- {% endblock %}
4
+ {% block title %}Cable Trace for {{ object|meta:"verbose_name"|bettertitle }} {{ object }}{% endblock %}
7
5
 
8
6
  {% block content %}
9
7
  <div class="row">
@@ -0,0 +1,5 @@
1
+ {% extends 'generic/object_create.html' %}
2
+
3
+ {% block form %}
4
+ {% include 'dcim/inc/cable_form.html' %}
5
+ {% endblock %}
@@ -91,13 +91,14 @@
91
91
  Not connected
92
92
  {% if perms.dcim.add_cable %}
93
93
  <span class="dropdown float-end">
94
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
94
+ {# comment The "fixed" strategy allows the dropdown to break out of the containing card #}
95
+ <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-bs-popper-config='{"strategy": "fixed"}'>
95
96
  <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
96
97
  </button>
97
- <ul class="dropdown-menu dropdown-menu-right">
98
- <li><a href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='console-server-port' %}?return_url={{ object.get_absolute_url }}">Console Server Port</a></li>
99
- <li><a href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
100
- <li><a href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
98
+ <ul class="dropdown-menu dropdown-menu-end">
99
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='console-server-port' %}?return_url={{ object.get_absolute_url }}">Console Server Port</a></li>
100
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
101
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
101
102
  </ul>
102
103
  </span>
103
104
  {% endif %}
@@ -91,13 +91,14 @@
91
91
  Not connected
92
92
  {% if perms.dcim.add_cable %}
93
93
  <span class="dropdown float-end">
94
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
94
+ {# comment The "fixed" strategy allows the dropdown to break out of the containing card #}
95
+ <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-bs-popper-config='{"strategy": "fixed"}'>
95
96
  <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
96
97
  </button>
97
- <ul class="dropdown-menu dropdown-menu-right">
98
- <li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='console-port' %}?return_url={{ object.get_absolute_url }}">Console Port</a></li>
99
- <li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
100
- <li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
98
+ <ul class="dropdown-menu dropdown-menu-end">
99
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='console-port' %}?return_url={{ object.get_absolute_url }}">Console Port</a></li>
100
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
101
+ <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
101
102
  </ul>
102
103
  </span>
103
104
  {% endif %}
@@ -1,11 +1,11 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
 
3
3
  {% block title %}{{ object }} - Config{% endblock %}
4
4
 
5
5
  {% block content %}
6
6
  {% include 'inc/ajax_loader.html' %}
7
7
  <div class="row">
8
- <div class="col-lg-10 offset-md-1">
8
+ <div class="col-lg-10 offset-lg-1">
9
9
  <div class="card">
10
10
  <div class="card-header"><strong>Device Configuration</strong></div>
11
11
  <ul class="nav nav-tabs mt-16" role="tablist">
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,4 +1,4 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% load helpers %}
3
3
 
4
4
  {% block title %}{{ object }} - LLDP Neighbors{% endblock %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,4 +1,4 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% load helpers %}
3
3
 
4
4
  {% block title %}{{ object }} - Status{% endblock %}
@@ -101,11 +101,11 @@
101
101
  memory.after("<tr><td>Available</td><td>" + json['get_environment']['memory']['available_ram'] + "</td></tr>");
102
102
  }
103
103
  $.each(json['get_environment']['temperature'], function(name, obj) {
104
- var style = "success";
104
+ var style = "table-success";
105
105
  if (obj['is_alert']) {
106
- style = "warning";
106
+ style = "table-warning";
107
107
  } else if (obj['is_critical']) {
108
- style = "danger";
108
+ style = "table-danger";
109
109
  }
110
110
  var row="<tr class=\"" + style +"\"><td>" + name + "</td><td>" + obj['temperature'] + "°C</td></tr>";
111
111
  $("#temperature").after(row)
@@ -113,18 +113,18 @@
113
113
  $.each(json['get_environment']['fans'], function(name, obj) {
114
114
  var row;
115
115
  if (obj['status']) {
116
- row = `<tr class="success"><td>${name}</td><td>{{ True | render_boolean }}</td></tr>`;
116
+ row = `<tr class="table-success"><td>${name}</td><td>{{ True | render_boolean }}</td></tr>`;
117
117
  } else {
118
- row = `<tr class="error"><td>${name}</td><td>{{ False | render_boolean }}</td></tr>`;
118
+ row = `<tr class="table-danger"><td>${name}</td><td>{{ False | render_boolean }}</td></tr>`;
119
119
  }
120
120
  $("#fans").after(row)
121
121
  });
122
122
  $.each(json['get_environment']['power'], function(name, obj) {
123
123
  var row;
124
124
  if (obj['status']) {
125
- row = `<tr class="success"><td>${name}</td><td>{{ True | render_boolean }}</td></tr>`;
125
+ row = `<tr class="table-success"><td>${name}</td><td>{{ True | render_boolean }}</td></tr>`;
126
126
  } else {
127
- row = `<tr class="danger"><td>${name}</td><td>{{ False | render_boolean }}</td></tr>`;
127
+ row = `<tr class="table-danger"><td>${name}</td><td>{{ False | render_boolean }}</td></tr>`;
128
128
  }
129
129
  $("#power").after(row)
130
130
  });
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,4 +1,4 @@
1
- {% extends 'dcim/device/base.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% load helpers %}
3
3
 
4
4
  {% block javascript %}
@@ -6,8 +6,8 @@
6
6
  {% block content %}
7
7
  <form action="" method="post" class="h-100 vstack">
8
8
  {% csrf_token %}
9
- <div class="row align-content-start flex-fill">
10
- <div class="col-xl-8 offset-lg-2 col-lg-10 offset-md-1">
9
+ <div class="row justify-content-center align-content-start flex-fill">
10
+ <div class="col-xl-8 col-lg-10">
11
11
  {% if form.non_field_errors %}
12
12
  <div class="card border-danger">
13
13
  <div class="card-header bg-danger-subtle border-danger text-body">
@@ -61,7 +61,9 @@
61
61
  <div class="card-body">
62
62
  {% render_field form.platform %}
63
63
  {% render_field form.software_version %}
64
- <div class="mb-10 d-flex justify-content-center" id="software_version_image_container" style="display:none">
64
+ <div class="mb-10 d-flex justify-content-center"
65
+ id="software_version_image_container"
66
+ style="display:none !important">{# !important is required to override d-flex #}
65
67
  <div class="col-lg-3"></div>
66
68
  <div class="col-lg-9">
67
69
  <span class="form-text">
@@ -185,7 +187,7 @@
185
187
  }
186
188
 
187
189
  function hide_software_image_container(){
188
- software_version_image_container.style.display = 'none';
190
+ software_version_image_container.style.setProperty('display', 'none', 'important');
189
191
  software_version_image_description.innerHTML = '';
190
192
  clear_software_image_list();
191
193
  }
@@ -194,7 +196,7 @@
194
196
  clear_software_image_list();
195
197
  software_version_image_description.innerHTML = '<img src="{% static 'img/ajax-loader.gif' %}">';
196
198
  software_version_image_list.style.visibility = 'hidden'; // prevent flicker when changing values
197
- software_version_image_container.style.display = 'block';
199
+ software_version_image_container.style.setProperty('display', 'flex', 'important');
198
200
  let device_type_id = $('select#id_device_type').find(':selected')[0].value;
199
201
  if (!device_type_id) {
200
202
  software_version_image_description.innerHTML = '<b>Unable to display software image list. Select a device type first.</b>';
@@ -1,3 +1,3 @@
1
- {% extends 'generic/object_delete.html' %}
1
+ {% extends 'generic/object_destroy.html' %}
2
2
 
3
3
  {% block message_extra %}This would also delete any/all child interfaces of this interface.{% endblock %}
@@ -2,20 +2,83 @@
2
2
 
3
3
  {% block bulk_buttons %}
4
4
  {% if perms.dcim.change_device %}
5
- <div class="btn-group dropup">
5
+ <div class="dropdown dropup d-inline-flex">
6
6
  <button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="device-bulk-add-components-button">
7
7
  <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Components <span class="mdi mdi-chevron-down"></span>
8
8
  </button>
9
9
  <ul class="dropdown-menu">
10
- {% if perms.dcim.add_consoleport %}<li><a href="{% url 'dcim:device_bulk_add_consoleport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Console Ports</a></li>{% endif %}
11
- {% if perms.dcim.add_consoleserverport %}<li><a href="{% url 'dcim:device_bulk_add_consoleserverport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Console Server Ports</a></li>{% endif %}
12
- {% if perms.dcim.add_powerport %}<li><a href="{% url 'dcim:device_bulk_add_powerport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Power Ports</a></li>{% endif %}
13
- {% if perms.dcim.add_poweroutlet %}<li><a href="{% url 'dcim:device_bulk_add_poweroutlet' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Power Outlets</a></li>{% endif %}
14
- {% if perms.dcim.add_interface %}<li><a href="{% url 'dcim:device_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Interfaces</a></li>{% endif %}
15
- {% if perms.dcim.add_rearport %}<li><a href="{% url 'dcim:device_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Rear Ports</a></li>{% endif %}
16
- {% if perms.dcim.add_devicebay %}<li><a href="{% url 'dcim:device_bulk_add_devicebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Device Bays</a></li>{% endif %}
17
- {% if perms.dcim.add_modulebay %}<li><a href="{% url 'dcim:device_bulk_add_modulebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Module Bays</a></li>{% endif %}
18
- {% if perms.dcim.add_inventoryitem %}<li><a href="{% url 'dcim:device_bulk_add_inventoryitem' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction dropdown-item">Inventory Items</a></li>{% endif %}
10
+ {% if perms.dcim.add_consoleport %}
11
+ <li>
12
+ <a href="{% url 'dcim:device_bulk_add_consoleport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
13
+ class="formaction dropdown-item">
14
+ <span class="mdi mdi-console" aria-hidden="true"></span> Console Ports
15
+ </a>
16
+ </li>
17
+ {% endif %}
18
+ {% if perms.dcim.add_consoleserverport %}
19
+ <li>
20
+ <a href="{% url 'dcim:device_bulk_add_consoleserverport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
21
+ class="formaction dropdown-item">
22
+ <span class="mdi mdi-console-network-outline" aria-hidden="true"></span> Console Server Ports
23
+ </a>
24
+ </li>
25
+ {% endif %}
26
+ {% if perms.dcim.add_powerport %}
27
+ <li>
28
+ <a href="{% url 'dcim:device_bulk_add_powerport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
29
+ class="formaction dropdown-item">
30
+ <span class="mdi mdi-power-plug-outline" aria-hidden="true"></span> Power Ports
31
+ </a>
32
+ </li>
33
+ {% endif %}
34
+ {% if perms.dcim.add_poweroutlet %}
35
+ <li>
36
+ <a href="{% url 'dcim:device_bulk_add_poweroutlet' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
37
+ class="formaction dropdown-item">
38
+ <span class="mdi mdi-power-socket" aria-hidden="true"></span> Power Outlets
39
+ </a>
40
+ </li>
41
+ {% endif %}
42
+ {% if perms.dcim.add_interface %}
43
+ <li>
44
+ <a href="{% url 'dcim:device_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
45
+ class="formaction dropdown-item">
46
+ <span class="mdi mdi-ethernet" aria-hidden="true"></span> Interfaces
47
+ </a>
48
+ </li>
49
+ {% endif %}
50
+ {% if perms.dcim.add_rearport %}
51
+ <li>
52
+ <a href="{% url 'dcim:device_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
53
+ class="formaction dropdown-item">
54
+ <span class="mdi mdi-square-rounded-outline" aria-hidden="true"></span> Rear Ports
55
+ </a>
56
+ </li>
57
+ {% endif %}
58
+ {% if perms.dcim.add_devicebay %}
59
+ <li>
60
+ <a href="{% url 'dcim:device_bulk_add_devicebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
61
+ class="formaction dropdown-item">
62
+ <span class="mdi mdi-circle-outline" aria-hidden="true"></span> Device Bays
63
+ </a>
64
+ </li>
65
+ {% endif %}
66
+ {% if perms.dcim.add_modulebay %}
67
+ <li>
68
+ <a href="{% url 'dcim:device_bulk_add_modulebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
69
+ class="formaction dropdown-item">
70
+ <span class="mdi mdi-tray" aria-hidden="true"></span> Module Bays
71
+ </a>
72
+ </li>
73
+ {% endif %}
74
+ {% if perms.dcim.add_inventoryitem %}
75
+ <li>
76
+ <a href="{% url 'dcim:device_bulk_add_inventoryitem' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
77
+ class="formaction dropdown-item">
78
+ <span class="mdi mdi-invoice-list-outline" aria-hidden="true"></span> Inventory Items
79
+ </a>
80
+ </li>
81
+ {% endif %}
19
82
  </ul>
20
83
  </div>
21
84
  {% endif %}
@@ -4,8 +4,8 @@
4
4
  {% block content %}
5
5
  <form action="." method="post" class="h-100 vstack">
6
6
  {% csrf_token %}
7
- <div class="row align-content-start flex-fill">
8
- <div class="col-lg-6 offset-md-3">
7
+ <div class="row justify-content-center align-content-start flex-fill">
8
+ <div class="col-lg-6">
9
9
  {% if form.non_field_errors %}
10
10
  <div class="card border-danger">
11
11
  <div class="card-header bg-danger-subtle border-danger text-body">
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/devicetype_retrieve.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -6,8 +6,8 @@
6
6
  {% block content %}
7
7
  <form action="." method="post" class="h-100 vstack">
8
8
  {% csrf_token %}
9
- <div class="row align-content-start flex-fill">
10
- <div class="col-lg-6 offset-md-3">
9
+ <div class="row justify-content-center align-content-start flex-fill">
10
+ <div class="col-xl-8 col-lg-10">
11
11
  {% if form.non_field_errors %}
12
12
  <div class="card border-danger">
13
13
  <div class="card-header bg-danger-subtle border-danger text-body">
@@ -0,0 +1,14 @@
1
+ {% load perms %}
2
+ {% load helpers %}
3
+ {% if perms.dcim.contact_association %}
4
+ {% if object.contact_name or object.contact_phone or object.contact_email %}
5
+ {% with request.path|add:"?tab=contacts"|urlencode as return_url %}
6
+ <div class="float-end d-print-none">
7
+ <a href="{% url 'dcim:location_migrate_data_to_contact' pk=object.pk %}?return_url={{ return_url }}" class="btn btn-primary btn-sm">
8
+ <span class="mdi mdi-account-edit" aria-hidden="true"></span>
9
+ Convert to contact/team record
10
+ </a>
11
+ </div>
12
+ {% endwith %}
13
+ {% endif %}
14
+ {% endif %}
@@ -76,16 +76,17 @@
76
76
  Not connected
77
77
  {% if perms.dcim.add_cable %}
78
78
  <span class="dropdown float-end">
79
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
79
+ {# comment The "fixed" strategy allows the dropdown to break out of the containing card #}
80
+ <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-bs-popper-config='{"strategy": "fixed"}'>
80
81
  <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
81
82
  </button>
82
- <ul class="dropdown-menu dropdown-menu-right">
83
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
84
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='console-server-port' %}?return_url={{ object.get_absolute_url }}">Console Server Port</a></li>
85
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='console-port' %}?return_url={{ object.get_absolute_url }}">Console Port</a></li>
86
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
87
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
88
- <li><a href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
83
+ <ul class="dropdown-menu dropdown-menu-end">
84
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
85
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='console-server-port' %}?return_url={{ object.get_absolute_url }}">Console Server Port</a></li>
86
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='console-port' %}?return_url={{ object.get_absolute_url }}">Console Port</a></li>
87
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
88
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
89
+ <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
89
90
  </ul>
90
91
  </span>
91
92
  {% endif %}
@@ -46,7 +46,7 @@
46
46
  }
47
47
 
48
48
  function hide_software_image_container(){
49
- software_version_image_container.style.display = 'none';
49
+ software_version_image_container.style.setProperty('display', 'none', 'important');
50
50
  software_version_image_description.innerHTML = '';
51
51
  clear_software_image_list();
52
52
  }
@@ -55,7 +55,7 @@
55
55
  clear_software_image_list();
56
56
  software_version_image_description.innerHTML = '<img src="{% static 'img/ajax-loader.gif' %}">';
57
57
  software_version_image_list.style.visibility = 'hidden'; // prevent flicker when changing values
58
- software_version_image_container.style.display = 'block';
58
+ software_version_image_container.style.setProperty('display', 'flex', 'important');
59
59
  retrieve_software_images(software_image_url, {'software_version': version_id});
60
60
  software_version_image_list.style.visibility = 'visible';
61
61
  }
@@ -177,14 +177,15 @@
177
177
  Not connected
178
178
  {% if perms.dcim.add_cable %}
179
179
  <span class="dropdown float-end">
180
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
180
+ {# comment The "fixed" strategy allows the dropdown to break out of the containing card #}
181
+ <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-bs-popper-config='{"strategy": "fixed"}'>
181
182
  <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
182
183
  </button>
183
- <ul class="dropdown-menu dropdown-menu-right">
184
- <li><a href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
185
- <li><a href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
186
- <li><a href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
187
- <li><a href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
184
+ <ul class="dropdown-menu dropdown-menu-end">
185
+ <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='interface' %}?return_url={{ object.get_absolute_url }}">Interface</a></li>
186
+ <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='front-port' %}?return_url={{ object.get_absolute_url }}">Front Port</a></li>
187
+ <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?return_url={{ object.get_absolute_url }}">Rear Port</a></li>
188
+ <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
188
189
  </ul>
189
190
  </span>
190
191
  {% endif %}
@@ -221,6 +222,25 @@
221
222
  </table>
222
223
  </div>
223
224
  {% endif %}
225
+ {% if object.vpn_tunnel_endpoints_src_int %}
226
+ <div class="card">
227
+ <div class="card-header"><strong>VPN Endpoints</strong></div>
228
+ <table class="table table-hover nb-table-headings card-body">
229
+ <thead>
230
+ <tr>
231
+ <th>Name</th>
232
+ <th>Role</th>
233
+ </tr>
234
+ </thead>
235
+ <tbody>
236
+ <tr>
237
+ <td>{{ object.vpn_tunnel_endpoints_src_int|hyperlinked_object }}</td>
238
+ <td>{{ object.vpn_tunnel_endpoints_src_int.role|placeholder }}</td>
239
+ </tr>
240
+ </tbody>
241
+ </table>
242
+ </div>
243
+ {% endif %}
224
244
  {% endblock content_right_page %}
225
245
 
226
246
  {% block content_full_width_page %}
@@ -1,3 +1,3 @@
1
- {% extends 'generic/object_bulk_delete.html' %}
1
+ {% extends 'generic/object_bulk_destroy.html' %}
2
2
 
3
3
  {% block message_extra %}This would also delete any/all child interfaces of these interfaces.{% endblock %}
@@ -17,7 +17,9 @@
17
17
  {% render_field form.label_pattern %}
18
18
  {% render_field form.manufacturer %}
19
19
  {% render_field form.software_version %}
20
- <div class="mb-10 d-flex justify-content-center" id="software_version_image_container" style="display:none">
20
+ <div class="mb-10 d-flex justify-content-center"
21
+ id="software_version_image_container"
22
+ style="display:none !important">{# !important is required to override d-flex #}
21
23
  <div class="col-lg-3"></div>
22
24
  <div class="col-lg-9">
23
25
  <span class="form-text">
@@ -1,4 +1,4 @@
1
- {% extends 'generic/object_bulk_delete.html' %}
1
+ {% extends 'generic/object_bulk_destroy.html' %}
2
2
 
3
3
  {% block message_extra %}
4
4
  <p class="text-center text-danger"><span class="mdi mdi-alert"></span> This will also delete all child inventory items of those listed.</p>
@@ -10,7 +10,9 @@
10
10
  {% render_field form.label %}
11
11
  {% render_field form.manufacturer %}
12
12
  {% render_field form.software_version %}
13
- <div class="mb-10 d-flex justify-content-center" id="software_version_image_container" style="display:none">
13
+ <div class="mb-10 d-flex justify-content-center"
14
+ id="software_version_image_container"
15
+ style="display:none !important">{# !important is required to override d-flex #}
14
16
  <div class="col-lg-3"></div>
15
17
  <div class="col-lg-9">
16
18
  <span class="form-text">