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
@@ -1,243 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load buttons %}
3
- {% load plugins %}
4
- {% load helpers %}
5
- {% load tz %}
6
-
7
- {% block content_left_page %}
8
- <div class="card">
9
- <div class="card-header">
10
- <strong>Location</strong>
11
- </div>
12
- <table class="table table-hover card-body attr-table">
13
- <tr>
14
- <td>Location Type</td>
15
- <td>{{ object.location_type|hyperlinked_object:"name" }}</td>
16
- </tr>
17
- <tr>
18
- <td>Status</td>
19
- <td>
20
- {{ object.status| hyperlinked_object_with_color }}
21
- </td>
22
- </tr>
23
- <tr>
24
- <td>Hierarchy</td>
25
- <td>
26
- {% include 'dcim/inc/location_hierarchy.html' with location=object %}
27
- </td>
28
- </tr>
29
- {% include 'inc/tenant_table_row.html' %}
30
- <tr>
31
- <td>Facility</td>
32
- <td>{{ object.facility|placeholder }}</td>
33
- </tr>
34
- <tr>
35
- <td>AS Number</td>
36
- <td>{{ object.asn|placeholder }}</td>
37
- </tr>
38
- <tr>
39
- <td>Time Zone</td>
40
- <td>
41
- {% if object.time_zone %}
42
- {{ object.time_zone }} (UTC {{ object.time_zone|tzoffset }})<br />
43
- <small class="text-secondary">Local time: {% timezone object.time_zone %}{% now "SHORT_DATETIME_FORMAT" %}{% endtimezone %}</small>
44
- {% else %}
45
- <span class="text-secondary">&mdash;</span>
46
- {% endif %}
47
- </td>
48
- </tr>
49
- <tr>
50
- <td>Description</td>
51
- <td>{{ object.description|placeholder }}</td>
52
- </tr>
53
- <tr>
54
- <td>Children</td>
55
- <td>
56
- {% if object.children.all %}
57
- <a href="{% url 'dcim:location_list' %}?parent={{ object.pk }}">{{ children_table.rows|length }}</a>
58
- {% else %}
59
- {{ None|placeholder }}
60
- {% endif %}
61
- </td>
62
- </tr>
63
- </table>
64
- </div>
65
- <div class="card">
66
- <div class="card-header">
67
- <strong>Geographical Info</strong>
68
- </div>
69
- <table class="table table-hover card-body attr-table">
70
- <tr>
71
- <td>Physical Address</td>
72
- <td>
73
- {% if object.physical_address %}
74
- <div class="float-end d-print-none">
75
- <a href="https://maps.google.com/?q={{ object.physical_address|urlencode }}" target="_blank" class="btn btn-primary btn-sm">
76
- <span class="mdi mdi-map-marker"></span> Map it
77
- </a>
78
- </div>
79
- <span>{{ object.physical_address|linebreaksbr }}</span>
80
- {% else %}
81
- <span class="text-secondary">&mdash;</span>
82
- {% endif %}
83
- </td>
84
- </tr>
85
- <tr>
86
- <td>Shipping Address</td>
87
- <td>{{ object.shipping_address|linebreaksbr|placeholder }}</td>
88
- </tr>
89
- <tr>
90
- <td>GPS Coordinates</td>
91
- <td>
92
- {% if object.latitude and object.longitude %}
93
- <div class="float-end d-print-none">
94
- <a href="https://maps.google.com/?q={{ object.latitude }},{{ object.longitude }}" target="_blank" class="btn btn-primary btn-sm">
95
- <span class="mdi mdi-map-marker"></span> Map it
96
- </a>
97
- </div>
98
- <span>{{ object.latitude }}, {{ object.longitude }}</span>
99
- {% else %}
100
- <span class="text-secondary">&mdash;</span>
101
- {% endif %}
102
- </td>
103
- </tr>
104
- </table>
105
- </div>
106
- {% if show_convert_to_contact_button %}
107
- <div class="card">
108
- <div class="card-header">
109
- <strong>Contact Info</strong>
110
- </div>
111
- <table class="table table-hover card-body attr-table">
112
- <tr>
113
- <td>Contact Name</td>
114
- <td>{{ object.contact_name|placeholder }}</td>
115
- </tr>
116
- <tr>
117
- <td>Contact Phone</td>
118
- <td>{{ object.contact_phone|hyperlinked_phone_number }}</td>
119
- </tr>
120
- <tr>
121
- <td>Contact E-Mail</td>
122
- <td>{{ object.contact_email|hyperlinked_email }}</td>
123
- </tr>
124
- </table>
125
- {% if request.user|has_perms:contact_association_permission %}
126
- {% with request.path|add:"?tab=contacts"|urlencode as return_url %}
127
- <div class="card-footer text-end d-print-none">
128
- <a href="{% url 'dcim:location_migrate_data_to_contact' pk=object.pk %}?return_url={{return_url}}" class="btn btn-primary btn-sm">
129
- <span class="mdi mdi-account-edit" aria-hidden="true"></span>
130
- Convert to contact/team record
131
- </a>
132
- </div>
133
- {% endwith %}
134
- {% endif %}
135
- </div>
136
- {% endif %}
137
- <div class="card">
138
- <div class="card-header">
139
- <strong>Comments</strong>
140
- </div>
141
- <div class="card-body nb-rendered-markdown">
142
- {% if object.comments %}
143
- {{ object.comments|render_markdown }}
144
- {% else %}
145
- <span class="text-secondary">None</span>
146
- {% endif %}
147
- </div>
148
- </div>
149
- {% endblock content_left_page %}
150
-
151
- {% block content_right_page %}
152
- <div class="card">
153
- <div class="card-header">
154
- <strong>Stats</strong>
155
- </div>
156
- <div class="card-body row">
157
- <div class="col-lg-4 text-center">
158
- <h2><a href="{% url 'dcim:rack_list' %}?location={{ object.pk }}" class="btn {% if stats.rack_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.rack_count }}</a></h2>
159
- <p>Racks</p>
160
- </div>
161
- <div class="col-lg-4 text-center">
162
- <h2><a href="{% url 'dcim:device_list' %}?location={{ object.pk }}" class="btn {% if stats.device_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.device_count }}</a></h2>
163
- <p>Devices</p>
164
- </div>
165
- <div class="col-lg-4 text-center">
166
- <h2><a href="{% url 'ipam:prefix_list' %}?locations={{ object.pk }}" class="btn {% if stats.prefix_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.prefix_count }}</a></h2>
167
- <p>Prefixes</p>
168
- </div>
169
- <div class="col-lg-4 text-center">
170
- <h2><a href="{% url 'ipam:vlan_list' %}?locations={{ object.pk }}" class="btn {% if stats.vlan_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.vlan_count }}</a></h2>
171
- <p>VLANs</p>
172
- </div>
173
- <div class="col-lg-4 text-center">
174
- <h2><a href="{% url 'circuits:circuit_list' %}?location={{ object.pk }}" class="btn {% if stats.circuit_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.circuit_count }}</a></h2>
175
- <p>Circuits</p>
176
- </div>
177
- <div class="col-lg-4 text-center">
178
- <h2><a href="{% url 'virtualization:virtualmachine_list' %}?location={{ object.pk }}" class="btn {% if stats.vm_count %}btn-primary{% else %}btn-secondary{% endif %} btn-lg">{{ stats.vm_count }}</a></h2>
179
- <p>Virtual Machines</p>
180
- </div>
181
- </div>
182
- </div>
183
- <div class="card">
184
- <div class="card-header">
185
- <strong>Rack Groups</strong>
186
- </div>
187
- <table class="table table-hover card-body">
188
- {% for rg in rack_groups %}
189
- <tr>
190
- <td style="padding-left: {{ rg.tree_depth }}8px"><span class="mdi mdi-folder-open"></span> <a href="{{ rg.get_absolute_url }}">{{ rg }}</a></td>
191
- <td>{{ rg.rack_count }}</td>
192
- <td class="text-end d-print-none">
193
- <a href="{% url 'dcim:rack_elevation_list' %}?rack_group={{ rg.pk }}" class="btn btn-sm btn-primary" title="View elevations">
194
- <span class="mdi mdi-server"></span>
195
- </a>
196
- </td>
197
- </tr>
198
- {% endfor %}
199
- <tr>
200
- <td><span class="mdi mdi-folder-open"></span> All racks</td>
201
- <td>{{ stats.rack_count }}</td>
202
- <td class="text-end d-print-none">
203
- <a href="{% url 'dcim:rack_elevation_list' %}?location={{ object.pk }}" class="btn btn-sm btn-primary" title="View elevations">
204
- <span class="mdi mdi-server"></span>
205
- </a>
206
- </td>
207
- </tr>
208
- </table>
209
- </div>
210
- <div class="card">
211
- <div class="card-header">
212
- <strong>Images</strong>
213
- </div>
214
- {% include 'inc/image_attachments.html' with images=object.images.all %}
215
- {% if perms.extras.add_imageattachment %}
216
- <div class="card-footer text-end d-print-none">
217
- <a href="{% url 'dcim:location_add_image' object_id=object.pk %}" class="btn btn-primary btn-sm">
218
- <span class="mdi mdi-plus-thick" aria-hidden="true"></span>
219
- Attach an image
220
- </a>
221
- </div>
222
- {% endif %}
223
- </div>
224
- {% endblock content_right_page %}
225
-
226
- {% block content_full_width_page %}
227
- {% if object.children.all %}
228
- <div class="card">
229
- <div class="card-header">
230
- <strong>Children</strong>
231
- </div>
232
- {% include 'inc/table.html' with table=children_table %}
233
- {% if perms.dcim.add_location %}
234
- <div class="card-footer text-end d-print-none">
235
- <a href="{% url 'dcim:location_add' %}?parent={{ object.pk }}" class="btn btn-sm btn-primary">
236
- <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add child
237
- </a>
238
- </div>
239
- {% endif %}
240
- </div>
241
- {% include 'inc/paginator.html' with paginator=children_table.paginator page=children_table.page %}
242
- {% endif %}
243
- {% endblock content_full_width_page %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -4,34 +4,74 @@
4
4
 
5
5
  {% block extra_buttons %}
6
6
  {% if perms.dcim.change_module %}
7
- <div class="btn-group">
7
+ <div class="dropdown d-inline-flex">
8
8
  <button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
9
9
  <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Components <span class="mdi mdi-chevron-down"></span>
10
10
  </button>
11
11
  <ul class="dropdown-menu">
12
12
  {% if perms.dcim.add_consoleport %}
13
- <li><a href="{% url 'dcim:consoleport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_consoleports' pk=object.pk %}">Console Ports</a></li>
13
+ <li>
14
+ <a class="dropdown-item"
15
+ href="{% url 'dcim:consoleport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_consoleports' pk=object.pk %}">
16
+ <span class="mdi mdi-console" aria-hidden="true"></span> Console Ports
17
+ </a>
18
+ </li>
14
19
  {% endif %}
15
20
  {% if perms.dcim.add_consoleserverport %}
16
- <li><a href="{% url 'dcim:consoleserverport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_consoleserverports' pk=object.pk %}">Console Server Ports</a></li>
21
+ <li>
22
+ <a class="dropdown-item"
23
+ href="{% url 'dcim:consoleserverport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_consoleserverports' pk=object.pk %}">
24
+ <span class="mdi mdi-console-network-outline" aria-hidden="true"></span> Console Server Ports
25
+ </a>
26
+ </li>
17
27
  {% endif %}
18
28
  {% if perms.dcim.add_powerport %}
19
- <li><a href="{% url 'dcim:powerport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_powerports' pk=object.pk %}">Power Ports</a></li>
29
+ <li>
30
+ <a class="dropdown-item"
31
+ href="{% url 'dcim:powerport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_powerports' pk=object.pk %}">
32
+ <span class="mdi mdi-power-plug-outline" aria-hidden="true"></span> Power Ports
33
+ </a>
34
+ </li>
20
35
  {% endif %}
21
36
  {% if perms.dcim.add_poweroutlet %}
22
- <li><a href="{% url 'dcim:poweroutlet_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_poweroutlets' pk=object.pk %}">Power Outlets</a></li>
37
+ <li>
38
+ <a class="dropdown-item"
39
+ href="{% url 'dcim:poweroutlet_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_poweroutlets' pk=object.pk %}">
40
+ <span class="mdi mdi-power-socket" aria-hidden="true"></span> Power Outlets
41
+ </a>
42
+ </li>
23
43
  {% endif %}
24
44
  {% if perms.dcim.add_interface %}
25
- <li><a href="{% url 'dcim:interface_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_interfaces' pk=object.pk %}">Interfaces</a></li>
45
+ <li>
46
+ <a class="dropdown-item"
47
+ href="{% url 'dcim:interface_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_interfaces' pk=object.pk %}">
48
+ <span class="mdi mdi-ethernet" aria-hidden="true"></span> Interfaces
49
+ </a>
50
+ </li>
26
51
  {% endif %}
27
52
  {% if perms.dcim.add_frontport %}
28
- <li><a href="{% url 'dcim:frontport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_frontports' pk=object.pk %}">Front Ports</a></li>
53
+ <li>
54
+ <a class="dropdown-item"
55
+ href="{% url 'dcim:frontport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_frontports' pk=object.pk %}">
56
+ <span class="mdi mdi-square-rounded-outline" aria-hidden="true"></span> Front Ports
57
+ </a>
58
+ </li>
29
59
  {% endif %}
30
60
  {% if perms.dcim.add_rearport %}
31
- <li><a href="{% url 'dcim:rearport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_rearports' pk=object.pk %}">Rear Ports</a></li>
61
+ <li>
62
+ <a class="dropdown-item"
63
+ href="{% url 'dcim:rearport_add' %}?module={{ object.pk }}&return_url={% url 'dcim:module_rearports' pk=object.pk %}">
64
+ <span class="mdi mdi-square-rounded-outline" aria-hidden="true"></span> Rear Ports
65
+ </a>
66
+ </li>
32
67
  {% endif %}
33
68
  {% if perms.dcim.add_modulebay %}
34
- <li><a href="{% url 'dcim:modulebay_add' %}?parent_module={{ object.pk }}&return_url={% url 'dcim:module_modulebays' pk=object.pk %}">Module Bays</a></li>
69
+ <li>
70
+ <a class="dropdown-item"
71
+ href="{% url 'dcim:modulebay_add' %}?parent_module={{ object.pk }}&return_url={% url 'dcim:module_modulebays' pk=object.pk %}">
72
+ <span class="mdi mdi-tray" aria-hidden="true"></span> Module Bays
73
+ </a>
74
+ </li>
35
75
  {% endif %}
36
76
  </ul>
37
77
  </div>
@@ -2,18 +2,67 @@
2
2
 
3
3
  {% block bulk_buttons %}
4
4
  {% if perms.dcim.change_module %}
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="module-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:module_bulk_add_consoleport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Console Ports</a></li>{% endif %}
11
- {% if perms.dcim.add_consoleserverport %}<li><a href="{% url 'dcim:module_bulk_add_consoleserverport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Console Server Ports</a></li>{% endif %}
12
- {% if perms.dcim.add_powerport %}<li><a href="{% url 'dcim:module_bulk_add_powerport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Power Ports</a></li>{% endif %}
13
- {% if perms.dcim.add_poweroutlet %}<li><a href="{% url 'dcim:module_bulk_add_poweroutlet' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Power Outlets</a></li>{% endif %}
14
- {% if perms.dcim.add_interface %}<li><a href="{% url 'dcim:module_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Interfaces</a></li>{% endif %}
15
- {% if perms.dcim.add_rearport %}<li><a href="{% url 'dcim:module_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Rear Ports</a></li>{% endif %}
16
- {% if perms.dcim.add_modulebay %}<li><a href="{% url 'dcim:module_bulk_add_modulebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Module Bays</a></li>{% endif %}
10
+ {% if perms.dcim.add_consoleport %}
11
+ <li>
12
+ <a href="{% url 'dcim:module_bulk_add_consoleport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
13
+ class="dropdown-item formaction">
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:module_bulk_add_consoleserverport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
21
+ class="dropdown-item formaction">
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:module_bulk_add_powerport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
29
+ class="dropdown-item formaction">
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:module_bulk_add_poweroutlet' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
37
+ class="dropdown-item formaction">
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:module_bulk_add_interface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
45
+ class="dropdown-item formaction">
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:module_bulk_add_rearport' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
53
+ class="dropdown-item formaction">
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_modulebay %}
59
+ <li>
60
+ <a href="{% url 'dcim:module_bulk_add_modulebay' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}"
61
+ class="dropdown-item formaction">
62
+ <span class="mdi mdi-tray" aria-hidden="true"></span> Module Bays
63
+ </a>
64
+ </li>
65
+ {% endif %}
17
66
  </ul>
18
67
  </div>
19
68
  {% endif %}
@@ -1,4 +1,4 @@
1
- {% extends 'generic/object_detail.html' %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
2
  {% load helpers %}
3
3
 
4
4
  {% block content_left_page %}
@@ -4,34 +4,74 @@
4
4
 
5
5
  {% block extra_buttons %}
6
6
  {% if perms.dcim.change_moduletype %}
7
- <div class="btn-group">
7
+ <div class="dropdown d-inline-flex">
8
8
  <button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" id="module-type-add-components-button">
9
9
  <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Components <span class="mdi mdi-chevron-down"></span>
10
10
  </button>
11
11
  <ul class="dropdown-menu">
12
12
  {% if perms.dcim.add_consoleporttemplate %}
13
- <li><a href="{% url 'dcim:consoleporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=consoleports">Console Ports</a></li>
13
+ <li>
14
+ <a class="dropdown-item"
15
+ href="{% url 'dcim:consoleporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=consoleports">
16
+ <span class="mdi mdi-console" aria-hidden="true"></span> Console Ports
17
+ </a>
18
+ </li>
14
19
  {% endif %}
15
20
  {% if perms.dcim.add_consoleserverporttemplate %}
16
- <li><a href="{% url 'dcim:consoleserverporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=consoleserverports">Console Server Ports</a></li>
21
+ <li>
22
+ <a class="dropdown-item"
23
+ href="{% url 'dcim:consoleserverporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=consoleserverports">
24
+ <span class="mdi mdi-console-network-outline" aria-hidden="true"></span>Console Server Ports
25
+ </a>
26
+ </li>
17
27
  {% endif %}
18
28
  {% if perms.dcim.add_powerporttemplate %}
19
- <li><a href="{% url 'dcim:powerporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=powerports">Power Ports</a></li>
29
+ <li>
30
+ <a class="dropdown-item"
31
+ href="{% url 'dcim:powerporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=powerports">
32
+ <span class="mdi mdi-power-plug-outline" aria-hidden="true"></span> Power Ports
33
+ </a>
34
+ </li>
20
35
  {% endif %}
21
36
  {% if perms.dcim.add_poweroutlettemplate %}
22
- <li><a href="{% url 'dcim:poweroutlettemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=poweroutlets">Power Outlets</a></li>
37
+ <li>
38
+ <a class="dropdown-item"
39
+ href="{% url 'dcim:poweroutlettemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=poweroutlets">
40
+ <span class="mdi mdi-power-socket" aria-hidden="true"></span> Power Outlets
41
+ </a>
42
+ </li>
23
43
  {% endif %}
24
44
  {% if perms.dcim.add_interfacetemplate %}
25
- <li><a href="{% url 'dcim:interfacetemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=interfaces">Interfaces</a></li>
45
+ <li>
46
+ <a class="dropdown-item"
47
+ href="{% url 'dcim:interfacetemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=interfaces">
48
+ <span class="mdi mdi-ethernet" aria-hidden="true"></span> Interfaces
49
+ </a>
50
+ </li>
26
51
  {% endif %}
27
52
  {% if perms.dcim.add_frontporttemplate %}
28
- <li><a href="{% url 'dcim:frontporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=frontports">Front Ports</a></li>
53
+ <li>
54
+ <a class="dropdown-item"
55
+ href="{% url 'dcim:frontporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=frontports">
56
+ <span class="mdi mdi-square-rounded-outline" aria-hidden="true"></span> Front Ports
57
+ </a>
58
+ </li>
29
59
  {% endif %}
30
60
  {% if perms.dcim.add_rearporttemplate %}
31
- <li><a href="{% url 'dcim:rearporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=rearports">Rear Ports</a></li>
61
+ <li>
62
+ <a class="dropdown-item"
63
+ href="{% url 'dcim:rearporttemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=rearports">
64
+ <span class="mdi mdi-square-rounded-outline" aria-hidden="true"></span> Rear Ports
65
+ </a>
66
+ </li>
32
67
  {% endif %}
33
68
  {% if perms.dcim.add_modulebaytemplate %}
34
- <li><a href="{% url 'dcim:modulebaytemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=modulebays">Module Bays</a></li>
69
+ <li>
70
+ <a class="dropdown-item"
71
+ href="{% url 'dcim:modulebaytemplate_add' %}?module_type={{ object.pk }}&return_url={{ object.get_absolute_url }}%3Ftab=modulebays">
72
+ <span class="mdi mdi-tray" aria-hidden="true"></span> Module Bays
73
+ </a>
74
+ </li>
35
75
  {% endif %}
36
76
  </ul>
37
77
  </div>
@@ -32,7 +32,7 @@
32
32
  <div class="modal-dialog" role="document">
33
33
  <div class="modal-content">
34
34
  <div class="modal-header">
35
- <h4 class="modal-title"><code>Network driver</code> Choices</h4>
35
+ <h4 class="modal-title">Network Driver Choices</h4>
36
36
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
37
37
  </div>
38
38
  <div class="modal-body">
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/powerfeed_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 %}
@@ -1,2 +1,2 @@
1
- {% extends 'dcim/powerpanel_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 %}
@@ -99,12 +99,13 @@
99
99
  Not connected
100
100
  {% if perms.dcim.add_cable %}
101
101
  <span class="dropdown float-end">
102
- <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
102
+ {# comment The "fixed" strategy allows the dropdown to break out of the containing card #}
103
+ <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"}'>
103
104
  <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
104
105
  </button>
105
- <ul class="dropdown-menu dropdown-menu-right">
106
- <li><a href="{% url 'dcim:powerport_connect' termination_a_id=object.pk termination_b_type='power-outlet' %}?return_url={{ object.get_absolute_url }}">Power Outlet</a></li>
107
- <li><a href="{% url 'dcim:powerport_connect' termination_a_id=object.pk termination_b_type='power-feed' %}?return_url={{ object.get_absolute_url }}">Power Feed</a></li>
106
+ <ul class="dropdown-menu dropdown-menu-end">
107
+ <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' termination_a_id=object.pk termination_b_type='power-outlet' %}?return_url={{ object.get_absolute_url }}">Power Outlet</a></li>
108
+ <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' termination_a_id=object.pk termination_b_type='power-feed' %}?return_url={{ object.get_absolute_url }}">Power Feed</a></li>
108
109
  </ul>
109
110
  </span>
110
111
  {% endif %}
@@ -10,12 +10,24 @@
10
10
  <span class="mdi mdi-checkbox-marked-circle-outline" aria-hidden="true"></span> Show Images
11
11
  </button>
12
12
  <div class="btn-group" role="group">
13
- <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='front' %}" class="btn btn-secondary{% if rack_face == 'front' %} active{% endif %}">Front</a>
14
- <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request face='rear' %}" class="btn btn-secondary{% if rack_face == 'rear' %} active{% endif %}">Rear</a>
13
+ <a href="{% django_querystring face='front' %}"
14
+ class="btn btn-primary{% if rack_face == 'front' %} bg-primary nb-text-body-bg{% endif %}">
15
+ <span class="mdi mdi-flip-to-front"></span> Front
16
+ </a>
17
+ <a href="{% django_querystring face='rear' %}"
18
+ class="btn btn-primary{% if rack_face == 'rear' %} bg-primary nb-text-body-bg{% endif %}">
19
+ <span class="mdi mdi-flip-to-back"></span> Rear
20
+ </a>
15
21
  </div>
16
22
  <div class="btn-group" role="group">
17
- <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse=None %}" class="btn btn-secondary{% if not reverse %} active{% endif %}">Normal</a>
18
- <a href="{% url 'dcim:rack_elevation_list' %}{% legacy_querystring request reverse='true' %}" class="btn btn-secondary{% if reverse %} active{% endif %}">Reversed</a>
23
+ <a href="{% django_querystring reverse=None %}"
24
+ class="btn btn-primary{% if not reverse %} bg-primary nb-text-body-bg{% endif %}">
25
+ <span class="mdi mdi-arrow-right"></span> Normal
26
+ </a>
27
+ <a href="{% django_querystring reverse='true' %}"
28
+ class="btn btn-primary{% if reverse %} bg-primary nb-text-body-bg{% endif %}">
29
+ <span class="mdi mdi-arrow-left"></span> Reversed
30
+ </a>
19
31
  </div>
20
32
  {% endblock %}
21
33