nautobot 3.0.0a2__py3-none-any.whl → 3.0.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (659) hide show
  1. nautobot/apps/choices.py +4 -2
  2. nautobot/apps/filters.py +7 -9
  3. nautobot/apps/models.py +2 -2
  4. nautobot/apps/ui.py +13 -1
  5. nautobot/apps/utils.py +8 -0
  6. nautobot/circuits/filters.py +3 -2
  7. nautobot/circuits/navigation.py +3 -2
  8. nautobot/circuits/templates/circuits/circuit_create.html +3 -3
  9. nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
  10. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
  11. nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
  12. nautobot/circuits/tests/integration/test_circuit.py +10 -13
  13. nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
  14. nautobot/circuits/views.py +6 -2
  15. nautobot/cloud/filters.py +1 -1
  16. nautobot/cloud/navigation.py +3 -2
  17. nautobot/core/api/schema.py +1 -1
  18. nautobot/core/api/serializers.py +6 -1
  19. nautobot/core/api/urls.py +2 -0
  20. nautobot/core/api/views.py +12 -0
  21. nautobot/core/apps/__init__.py +11 -10
  22. nautobot/core/celery/__init__.py +3 -5
  23. nautobot/core/checks.py +46 -0
  24. nautobot/core/choices.py +1 -1
  25. nautobot/core/cli/bootstrap_v3_to_v5.py +105 -13
  26. nautobot/core/cli/migrate_deprecated_templates.py +227 -0
  27. nautobot/core/constants.py +3 -0
  28. nautobot/core/context_processors.py +9 -1
  29. nautobot/core/filters.py +4 -0
  30. nautobot/core/forms/__init__.py +2 -0
  31. nautobot/core/forms/forms.py +1 -1
  32. nautobot/core/forms/widgets.py +21 -2
  33. nautobot/core/jobs/__init__.py +62 -3
  34. nautobot/core/jobs/groups.py +31 -1
  35. nautobot/core/management/commands/generate_test_data.py +28 -9
  36. nautobot/core/models/__init__.py +11 -0
  37. nautobot/core/models/generics.py +9 -1
  38. nautobot/core/models/tree_queries.py +10 -5
  39. nautobot/core/models/utils.py +1 -1
  40. nautobot/core/settings.py +35 -19
  41. nautobot/core/settings.yaml +17 -33
  42. nautobot/core/signals.py +12 -1
  43. nautobot/core/tables.py +13 -6
  44. nautobot/core/templates/40x.html +1 -1
  45. nautobot/core/templates/500.html +2 -2
  46. nautobot/core/templates/admin/base.html +1 -2
  47. nautobot/core/templates/admin/change_list.html +9 -12
  48. nautobot/core/templates/admin/config/config.html +12 -12
  49. nautobot/core/templates/admin/index.html +3 -3
  50. nautobot/core/templates/base_django.html +1 -2
  51. nautobot/core/templates/buttons/export.html +1 -1
  52. nautobot/core/templates/components/button/dropdown.html +5 -3
  53. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  54. nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
  55. nautobot/core/templates/components/panel/panel.html +3 -3
  56. nautobot/core/templates/components/tab/content_wrapper.html +6 -7
  57. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
  58. nautobot/core/templates/echarts/echarts.html +22 -9
  59. nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
  60. nautobot/core/templates/generic/object_bulk_create.html +6 -5
  61. nautobot/core/templates/generic/object_bulk_delete.html +1 -1
  62. nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
  63. nautobot/core/templates/generic/object_bulk_edit.html +1 -1
  64. nautobot/core/templates/generic/object_bulk_import.html +1 -1
  65. nautobot/core/templates/generic/object_bulk_remove.html +2 -2
  66. nautobot/core/templates/generic/object_bulk_update.html +5 -4
  67. nautobot/core/templates/generic/object_create.html +5 -4
  68. nautobot/core/templates/generic/object_delete.html +1 -1
  69. nautobot/core/templates/generic/object_detail.html +1 -1
  70. nautobot/core/templates/generic/object_edit.html +1 -1
  71. nautobot/core/templates/generic/object_import.html +2 -1
  72. nautobot/core/templates/generic/object_list.html +12 -4
  73. nautobot/core/templates/generic/object_notes.html +5 -3
  74. nautobot/core/templates/generic/object_retrieve.html +4 -5
  75. nautobot/core/templates/graphene/graphiql.html +7 -8
  76. nautobot/core/templates/home.html +1 -1
  77. nautobot/core/templates/import_success.html +2 -1
  78. nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
  79. nautobot/core/templates/inc/created_updated.html +7 -3
  80. nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
  81. nautobot/core/templates/inc/footer.html +3 -1
  82. nautobot/core/templates/inc/form_static_field.html +6 -0
  83. nautobot/core/templates/inc/header.html +11 -1
  84. nautobot/core/templates/inc/image_attachments.html +2 -1
  85. nautobot/core/templates/inc/media.html +14 -0
  86. nautobot/core/templates/inc/nav_menu.html +3 -9
  87. nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
  88. nautobot/core/templates/inc/search_panel.html +4 -4
  89. nautobot/core/templates/login.html +4 -2
  90. nautobot/core/templates/nautobot_config.py.j2 +6 -11
  91. nautobot/core/templates/redoc_ui.html +7 -0
  92. nautobot/core/templates/rest_framework/api.html +103 -2
  93. nautobot/core/templates/search.html +1 -1
  94. nautobot/core/templates/swagger_ui.html +17 -3
  95. nautobot/core/templates/system_jobs/import_objects.html +1 -2
  96. nautobot/core/templates/utilities/confirmation_form.html +2 -2
  97. nautobot/core/templates/utilities/obj_table.html +10 -2
  98. nautobot/core/templates/utilities/render_field.html +7 -7
  99. nautobot/core/templates/utilities/render_jinja2.html +2 -2
  100. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +37 -4
  101. nautobot/core/templates/utilities/theme_preview.html +19 -3
  102. nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
  103. nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
  104. nautobot/core/templatetags/helpers.py +76 -18
  105. nautobot/core/testing/api.py +68 -9
  106. nautobot/core/testing/filters.py +0 -23
  107. nautobot/core/testing/integration.py +41 -17
  108. nautobot/core/testing/mixins.py +2 -0
  109. nautobot/core/testing/utils.py +18 -4
  110. nautobot/core/testing/views.py +104 -13
  111. nautobot/core/tests/integration/test_app_home.py +34 -30
  112. nautobot/core/tests/integration/test_app_navbar.py +3 -0
  113. nautobot/core/tests/integration/test_filters.py +48 -11
  114. nautobot/core/tests/integration/test_theme.py +22 -21
  115. nautobot/core/tests/nautobot_config.py +3 -0
  116. nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
  117. nautobot/core/tests/runner.py +8 -1
  118. nautobot/core/tests/test_api.py +5 -3
  119. nautobot/core/tests/test_breadcrumbs.py +27 -28
  120. nautobot/core/tests/test_checks.py +28 -0
  121. nautobot/core/tests/test_cli.py +40 -0
  122. nautobot/core/tests/test_config.py +2 -1
  123. nautobot/core/tests/test_forms.py +55 -13
  124. nautobot/core/tests/test_jobs.py +144 -3
  125. nautobot/core/tests/test_nautobot_server.py +2 -0
  126. nautobot/core/tests/test_navigations.py +76 -1
  127. nautobot/core/tests/test_patch_social_django.py +42 -0
  128. nautobot/core/tests/test_renderers.py +59 -0
  129. nautobot/core/tests/test_settings_schema.py +1 -0
  130. nautobot/core/tests/test_tables.py +3 -1
  131. nautobot/core/tests/test_templatetags_helpers.py +62 -13
  132. nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
  133. nautobot/core/tests/test_titles.py +0 -16
  134. nautobot/core/tests/test_tree_queries.py +14 -1
  135. nautobot/core/tests/test_ui.py +123 -4
  136. nautobot/core/tests/test_utils.py +72 -5
  137. nautobot/core/tests/test_views.py +159 -31
  138. nautobot/core/ui/breadcrumbs.py +70 -29
  139. nautobot/core/ui/bulk_buttons.py +1 -1
  140. nautobot/core/ui/choices.py +143 -27
  141. nautobot/core/ui/constants.py +76 -12
  142. nautobot/core/ui/echarts.py +15 -20
  143. nautobot/core/ui/object_detail.py +143 -55
  144. nautobot/core/ui/titles.py +3 -6
  145. nautobot/core/urls.py +20 -9
  146. nautobot/core/utils/cache.py +2 -1
  147. nautobot/core/utils/filtering.py +28 -18
  148. nautobot/core/utils/lookup.py +49 -8
  149. nautobot/core/utils/module_loading.py +21 -0
  150. nautobot/core/utils/patch_social_django.py +128 -0
  151. nautobot/core/views/__init__.py +38 -1
  152. nautobot/core/views/generic.py +3 -3
  153. nautobot/core/views/mixins.py +45 -22
  154. nautobot/core/views/renderers.py +4 -3
  155. nautobot/core/views/viewsets.py +2 -1
  156. nautobot/data_validation/apps.py +1 -5
  157. nautobot/data_validation/custom_validators.py +4 -4
  158. nautobot/data_validation/filters.py +1 -1
  159. nautobot/data_validation/forms.py +40 -0
  160. nautobot/data_validation/migrations/0001_initial.py +0 -7
  161. nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -14
  162. nautobot/data_validation/models.py +16 -7
  163. nautobot/data_validation/navigation.py +8 -1
  164. nautobot/data_validation/tables.py +12 -5
  165. nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
  166. nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
  167. nautobot/data_validation/tests/__init__.py +2 -2
  168. nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
  169. nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
  170. nautobot/data_validation/tests/test_filters.py +8 -6
  171. nautobot/data_validation/tests/test_models.py +15 -0
  172. nautobot/data_validation/tests/test_views.py +190 -32
  173. nautobot/data_validation/urls.py +2 -5
  174. nautobot/data_validation/views.py +73 -40
  175. nautobot/dcim/api/serializers.py +3 -13
  176. nautobot/dcim/apps.py +4 -0
  177. nautobot/dcim/choices.py +65 -0
  178. nautobot/dcim/constants.py +7 -0
  179. nautobot/dcim/custom_validators.py +84 -0
  180. nautobot/dcim/factory.py +1 -1
  181. nautobot/dcim/filter_mixins.py +353 -4
  182. nautobot/dcim/{filters/__init__.py → filters.py} +15 -36
  183. nautobot/dcim/forms.py +90 -4
  184. nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
  185. nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
  186. nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
  187. nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
  188. nautobot/dcim/migrations/0079_remove_device_location_tenant_name_uniqueness.py +16 -0
  189. nautobot/dcim/migrations/0080_device_name_data_migration.py +59 -0
  190. nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
  191. nautobot/dcim/models/device_component_templates.py +33 -1
  192. nautobot/dcim/models/device_components.py +98 -64
  193. nautobot/dcim/models/devices.py +30 -20
  194. nautobot/dcim/navigation.py +7 -6
  195. nautobot/dcim/tables/devices.py +18 -0
  196. nautobot/dcim/tables/devicetypes.py +8 -1
  197. nautobot/dcim/tables/racks.py +0 -2
  198. nautobot/dcim/tables/template_code.py +15 -15
  199. nautobot/dcim/templates/dcim/cable_connect.html +28 -112
  200. nautobot/dcim/templates/dcim/cable_trace.html +0 -4
  201. nautobot/dcim/templates/dcim/{cable_edit.html → cable_update.html} +1 -1
  202. nautobot/dcim/templates/dcim/consoleport.html +7 -6
  203. nautobot/dcim/templates/dcim/consoleserverport.html +7 -6
  204. nautobot/dcim/templates/dcim/device/config.html +2 -2
  205. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
  206. nautobot/dcim/templates/dcim/device/status.html +8 -8
  207. nautobot/dcim/templates/dcim/device.html +1 -1
  208. nautobot/dcim/templates/dcim/device_component_add.html +2 -2
  209. nautobot/dcim/templates/dcim/device_create.html +5 -3
  210. nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
  211. nautobot/dcim/templates/dcim/device_list.html +73 -10
  212. nautobot/dcim/templates/dcim/devicebay.html +1 -1
  213. nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
  214. nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
  215. nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
  216. nautobot/dcim/templates/dcim/frontport.html +10 -9
  217. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  218. nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
  219. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
  220. nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
  221. nautobot/dcim/templates/dcim/interface.html +35 -7
  222. nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
  223. nautobot/dcim/templates/dcim/interface_edit.html +2 -0
  224. nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
  225. nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
  226. nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
  227. nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
  228. nautobot/dcim/templates/dcim/module/base.html +49 -9
  229. nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
  230. nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
  231. nautobot/dcim/templates/dcim/module_frontports.html +1 -1
  232. nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
  233. nautobot/dcim/templates/dcim/module_list.html +57 -8
  234. nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
  235. nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
  236. nautobot/dcim/templates/dcim/module_powerports.html +1 -1
  237. nautobot/dcim/templates/dcim/module_rearports.html +1 -1
  238. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  239. nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
  240. nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
  241. nautobot/dcim/templates/dcim/platform_create.html +1 -1
  242. nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
  243. nautobot/dcim/templates/dcim/powerport.html +6 -5
  244. nautobot/dcim/templates/dcim/rack_elevation_list.html +17 -5
  245. nautobot/dcim/templates/dcim/rack_retrieve.html +22 -15
  246. nautobot/dcim/templates/dcim/rearport.html +8 -7
  247. nautobot/dcim/templates/dcim/trace/cable.html +1 -1
  248. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
  249. nautobot/dcim/templates/dcim/virtualchassis_update.html +15 -7
  250. nautobot/dcim/tests/integration/test_controller.py +4 -6
  251. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
  252. nautobot/dcim/tests/integration/test_create_device.py +0 -2
  253. nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
  254. nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
  255. nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
  256. nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
  257. nautobot/dcim/tests/test_api.py +194 -6
  258. nautobot/dcim/tests/test_custom_validators.py +229 -0
  259. nautobot/dcim/tests/test_filters.py +55 -7
  260. nautobot/dcim/tests/test_forms.py +110 -8
  261. nautobot/dcim/tests/test_graphql.py +44 -1
  262. nautobot/dcim/tests/test_models.py +328 -4
  263. nautobot/dcim/tests/test_tables.py +160 -0
  264. nautobot/dcim/tests/test_views.py +132 -29
  265. nautobot/dcim/urls.py +64 -21
  266. nautobot/dcim/utils.py +3 -3
  267. nautobot/dcim/views.py +777 -397
  268. nautobot/extras/api/views.py +60 -45
  269. nautobot/extras/choices.py +2 -13
  270. nautobot/extras/datasources/git.py +3 -1
  271. nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
  272. nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
  273. nautobot/extras/{filters/__init__.py → filters.py} +33 -48
  274. nautobot/extras/forms/forms.py +14 -15
  275. nautobot/extras/forms/mixins.py +0 -41
  276. nautobot/extras/jobs.py +2 -0
  277. nautobot/extras/jobs_ui.py +4 -3
  278. nautobot/extras/management/__init__.py +11 -0
  279. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
  280. nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
  281. nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
  282. nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
  283. nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
  284. nautobot/extras/models/__init__.py +1 -2
  285. nautobot/extras/models/approvals.py +33 -14
  286. nautobot/extras/models/change_logging.py +4 -0
  287. nautobot/extras/models/contacts.py +2 -0
  288. nautobot/extras/models/groups.py +44 -5
  289. nautobot/extras/models/jobs.py +60 -4
  290. nautobot/extras/models/mixins.py +28 -0
  291. nautobot/extras/models/models.py +23 -2
  292. nautobot/extras/models/secrets.py +1 -0
  293. nautobot/extras/models/statuses.py +0 -15
  294. nautobot/extras/navigation.py +13 -9
  295. nautobot/extras/plugins/__init__.py +33 -55
  296. nautobot/extras/plugins/marketplace_manifest.yml +49 -1
  297. nautobot/extras/plugins/tables.py +3 -3
  298. nautobot/extras/plugins/urls.py +2 -21
  299. nautobot/extras/plugins/utils.py +1 -33
  300. nautobot/extras/plugins/views.py +0 -9
  301. nautobot/extras/querysets.py +8 -0
  302. nautobot/extras/signals.py +20 -19
  303. nautobot/extras/tables.py +64 -68
  304. nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
  305. nautobot/extras/templates/extras/approval_dashboard.html +7 -5
  306. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
  307. nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
  308. nautobot/extras/templates/extras/configcontext_update.html +1 -0
  309. nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
  310. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
  311. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  312. nautobot/extras/templates/extras/gitrepository_result.html +0 -2
  313. nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
  314. nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
  315. nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
  316. nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
  317. nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
  318. nautobot/extras/templates/extras/inc/json_format.html +10 -3
  319. nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
  320. nautobot/extras/templates/extras/job.html +29 -12
  321. nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
  322. nautobot/extras/templates/extras/job_edit.html +52 -46
  323. nautobot/extras/templates/extras/job_list.html +29 -25
  324. nautobot/extras/templates/extras/marketplace.html +5 -9
  325. nautobot/extras/templates/extras/object_configcontext.html +1 -1
  326. nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
  327. nautobot/extras/templates/extras/objectchange_retrieve.html +19 -39
  328. nautobot/extras/templates/extras/plugin_detail.html +29 -24
  329. nautobot/extras/templates/extras/plugins_list.html +16 -26
  330. nautobot/extras/templates/extras/role_retrieve.html +64 -0
  331. nautobot/extras/templates/extras/scheduledjob.html +4 -2
  332. nautobot/extras/templates/extras/secret_create.html +1 -1
  333. nautobot/extras/templatetags/custom_links.py +12 -12
  334. nautobot/extras/templatetags/job_buttons.py +14 -12
  335. nautobot/extras/test_jobs/invalid_import.py +9 -0
  336. nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
  337. nautobot/extras/test_jobs/missing_import.py +11 -0
  338. nautobot/extras/tests/integration/test_computedfields.py +8 -9
  339. nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
  340. nautobot/extras/tests/integration/test_customfields.py +9 -10
  341. nautobot/extras/tests/integration/test_dynamicgroups.py +12 -9
  342. nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
  343. nautobot/extras/tests/integration/test_plugins.py +18 -6
  344. nautobot/extras/tests/integration/test_relationships.py +0 -2
  345. nautobot/extras/tests/test_api.py +90 -18
  346. nautobot/extras/tests/test_approvals.py +38 -38
  347. nautobot/extras/tests/test_changelog.py +59 -5
  348. nautobot/extras/tests/test_customfields.py +22 -13
  349. nautobot/extras/tests/test_customfields_filters.py +479 -0
  350. nautobot/extras/tests/test_dynamicgroups.py +39 -1
  351. nautobot/extras/tests/test_filters.py +57 -22
  352. nautobot/extras/tests/test_forms.py +18 -21
  353. nautobot/extras/tests/test_jobs.py +25 -4
  354. nautobot/extras/tests/test_migrations.py +1 -0
  355. nautobot/extras/tests/test_models.py +51 -33
  356. nautobot/extras/tests/test_plugins.py +36 -10
  357. nautobot/extras/tests/test_utils.py +3 -4
  358. nautobot/extras/tests/test_views.py +52 -112
  359. nautobot/extras/urls.py +0 -14
  360. nautobot/extras/views.py +164 -71
  361. nautobot/ipam/factory.py +7 -0
  362. nautobot/ipam/filter_mixins.py +38 -0
  363. nautobot/ipam/filters.py +53 -38
  364. nautobot/ipam/formfields.py +1 -1
  365. nautobot/ipam/forms.py +6 -3
  366. nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
  367. nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
  368. nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
  369. nautobot/ipam/models.py +29 -2
  370. nautobot/ipam/navigation.py +3 -2
  371. nautobot/ipam/signals.py +71 -0
  372. nautobot/ipam/tables.py +19 -6
  373. nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
  374. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
  375. nautobot/ipam/templates/ipam/ipaddress.html +14 -0
  376. nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
  377. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
  378. nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
  379. nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
  380. nautobot/ipam/templates/ipam/namespace_update.html +15 -0
  381. nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
  382. nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
  383. nautobot/ipam/templates/ipam/prefix_list.html +14 -13
  384. nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
  385. nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
  386. nautobot/ipam/tests/migration/test_migrations.py +89 -0
  387. nautobot/ipam/tests/test_api.py +13 -6
  388. nautobot/ipam/tests/test_filters.py +36 -1
  389. nautobot/ipam/tests/test_forms.py +1 -1
  390. nautobot/ipam/tests/test_models.py +44 -2
  391. nautobot/ipam/tests/test_tables.py +1 -2
  392. nautobot/ipam/tests/test_utils.py +1 -1
  393. nautobot/ipam/tests/test_views.py +13 -14
  394. nautobot/ipam/ui.py +0 -17
  395. nautobot/ipam/utils/migrations.py +16 -2
  396. nautobot/ipam/utils/testing.py +9 -3
  397. nautobot/ipam/views.py +53 -11
  398. nautobot/load_balancers/__init__.py +0 -0
  399. nautobot/load_balancers/api/__init__.py +1 -0
  400. nautobot/load_balancers/api/serializers.py +75 -0
  401. nautobot/load_balancers/api/urls.py +23 -0
  402. nautobot/load_balancers/api/views.py +61 -0
  403. nautobot/load_balancers/apps.py +17 -0
  404. nautobot/load_balancers/choices.py +167 -0
  405. nautobot/load_balancers/filters.py +225 -0
  406. nautobot/load_balancers/forms.py +532 -0
  407. nautobot/load_balancers/management/commands/__init__.py +0 -0
  408. nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
  409. nautobot/load_balancers/migrations/0001_initial.py +465 -0
  410. nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
  411. nautobot/load_balancers/migrations/__init__.py +0 -0
  412. nautobot/load_balancers/models.py +423 -0
  413. nautobot/load_balancers/navigation.py +80 -0
  414. nautobot/load_balancers/tables.py +255 -0
  415. nautobot/load_balancers/tests/__init__.py +474 -0
  416. nautobot/load_balancers/tests/test_api.py +353 -0
  417. nautobot/load_balancers/tests/test_filters.py +134 -0
  418. nautobot/load_balancers/tests/test_forms.py +266 -0
  419. nautobot/load_balancers/tests/test_models.py +195 -0
  420. nautobot/load_balancers/tests/test_views.py +229 -0
  421. nautobot/load_balancers/urls.py +17 -0
  422. nautobot/load_balancers/views.py +248 -0
  423. nautobot/project-static/dist/css/github-dark.min.css +10 -0
  424. nautobot/project-static/dist/css/github.min.css +10 -0
  425. nautobot/project-static/dist/css/nautobot.css +1 -11
  426. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  427. nautobot/project-static/dist/js/libraries.js +1 -1
  428. nautobot/project-static/dist/js/libraries.js.map +1 -1
  429. nautobot/project-static/dist/js/nautobot.js +1 -1
  430. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  431. nautobot/project-static/js/cabletrace.js +1 -1
  432. nautobot/project-static/js/forms.js +13 -0
  433. nautobot/project-static/js/interface_filtering.js +20 -16
  434. nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
  435. nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
  436. nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
  437. nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
  438. nautobot/project-static/nautobot-icons/cloud.svg +1 -1
  439. nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
  440. nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
  441. nautobot/project-static/nautobot-icons/elements.svg +1 -1
  442. nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
  443. nautobot/project-static/nautobot-icons/hammer.svg +1 -1
  444. nautobot/project-static/nautobot-icons/organization.svg +3 -0
  445. nautobot/project-static/nautobot-icons/secrets.svg +1 -1
  446. nautobot/project-static/nautobot-icons/security.svg +3 -0
  447. nautobot/project-static/nautobot-icons/server.svg +1 -1
  448. nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
  449. nautobot/project-static/nautobot-icons/star.svg +1 -1
  450. nautobot/tenancy/api/serializers.py +1 -0
  451. nautobot/tenancy/api/views.py +2 -1
  452. nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
  453. nautobot/tenancy/navigation.py +3 -1
  454. nautobot/tenancy/tests/test_filters.py +0 -2
  455. nautobot/tenancy/views.py +2 -1
  456. nautobot/ui/package-lock.json +87 -4
  457. nautobot/ui/package.json +2 -1
  458. nautobot/ui/src/js/collapse.js +3 -3
  459. nautobot/ui/src/js/nautobot.js +16 -1
  460. nautobot/ui/src/js/select2.js +53 -2
  461. nautobot/ui/src/scss/colors.scss +1 -1
  462. nautobot/ui/src/scss/nautobot.scss +112 -30
  463. nautobot/ui/webpack.config.js +13 -0
  464. nautobot/users/templates/users/preferences.html +11 -2
  465. nautobot/users/templates/users/profile.html +45 -12
  466. nautobot/users/templates/users/sessionkey_delete.html +1 -1
  467. nautobot/users/tests/test_api.py +4 -0
  468. nautobot/users/views.py +4 -2
  469. nautobot/virtualization/filters.py +6 -1
  470. nautobot/virtualization/models.py +1 -68
  471. nautobot/virtualization/navigation.py +3 -2
  472. nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
  473. nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
  474. nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
  475. nautobot/virtualization/tests/test_api.py +3 -0
  476. nautobot/virtualization/tests/test_filters.py +10 -1
  477. nautobot/virtualization/tests/test_models.py +45 -4
  478. nautobot/virtualization/views.py +4 -1
  479. nautobot/vpn/__init__.py +0 -0
  480. nautobot/vpn/api/serializers.py +113 -0
  481. nautobot/vpn/api/urls.py +19 -0
  482. nautobot/vpn/api/views.py +70 -0
  483. nautobot/vpn/apps.py +8 -0
  484. nautobot/vpn/choices.py +171 -0
  485. nautobot/vpn/factory.py +219 -0
  486. nautobot/vpn/filters.py +234 -0
  487. nautobot/vpn/forms.py +487 -0
  488. nautobot/vpn/homepage.py +19 -0
  489. nautobot/vpn/migrations/0001_initial.py +541 -0
  490. nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
  491. nautobot/vpn/migrations/__init__.py +0 -0
  492. nautobot/vpn/models.py +535 -0
  493. nautobot/vpn/navigation.py +98 -0
  494. nautobot/vpn/tables.py +383 -0
  495. nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
  496. nautobot/vpn/tests/__init__.py +0 -0
  497. nautobot/vpn/tests/test_api.py +336 -0
  498. nautobot/vpn/tests/test_filters.py +139 -0
  499. nautobot/vpn/tests/test_forms.py +293 -0
  500. nautobot/vpn/tests/test_models.py +147 -0
  501. nautobot/vpn/tests/test_views.py +300 -0
  502. nautobot/vpn/urls.py +16 -0
  503. nautobot/vpn/views.py +495 -0
  504. nautobot/wireless/navigation.py +3 -2
  505. nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
  506. nautobot/wireless/tests/test_api.py +1 -1
  507. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +15 -15
  508. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +514 -572
  509. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +1 -0
  510. nautobot/circuits/templates/circuits/circuit.html +0 -2
  511. nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
  512. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
  513. nautobot/circuits/templates/circuits/circuit_update.html +0 -1
  514. nautobot/circuits/templates/circuits/circuittermination.html +0 -2
  515. nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
  516. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
  517. nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
  518. nautobot/circuits/templates/circuits/circuittype.html +0 -2
  519. nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
  520. nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
  521. nautobot/circuits/templates/circuits/provider.html +0 -2
  522. nautobot/circuits/templates/circuits/provider_edit.html +0 -2
  523. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
  524. nautobot/circuits/templates/circuits/provider_update.html +0 -1
  525. nautobot/circuits/templates/circuits/providernetwork.html +0 -2
  526. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
  527. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
  528. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
  529. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
  530. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
  531. nautobot/core/templates/buttons/import.html +0 -9
  532. nautobot/data_validation/template_content.py +0 -42
  533. nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
  534. nautobot/dcim/filters/mixins.py +0 -354
  535. nautobot/dcim/templates/dcim/controller/base.html +0 -2
  536. nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
  537. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
  538. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
  539. nautobot/dcim/templates/dcim/device/base.html +0 -2
  540. nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
  541. nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
  542. nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
  543. nautobot/dcim/templates/dcim/device/frontports.html +0 -2
  544. nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
  545. nautobot/dcim/templates/dcim/device/inventory.html +0 -2
  546. nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
  547. nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
  548. nautobot/dcim/templates/dcim/device/powerports.html +0 -2
  549. nautobot/dcim/templates/dcim/device/rearports.html +0 -2
  550. nautobot/dcim/templates/dcim/device/wireless.html +0 -2
  551. nautobot/dcim/templates/dcim/device_component.html +0 -2
  552. nautobot/dcim/templates/dcim/device_edit.html +0 -2
  553. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
  554. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
  555. nautobot/dcim/templates/dcim/devicetype.html +0 -2
  556. nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
  557. nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
  558. nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
  559. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
  560. nautobot/dcim/templates/dcim/location.html +0 -2
  561. nautobot/dcim/templates/dcim/location_edit.html +0 -2
  562. nautobot/dcim/templates/dcim/location_retrieve.html +0 -243
  563. nautobot/dcim/templates/dcim/locationtype.html +0 -2
  564. nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
  565. nautobot/dcim/templates/dcim/manufacturer.html +0 -2
  566. nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
  567. nautobot/dcim/templates/dcim/platform.html +0 -2
  568. nautobot/dcim/templates/dcim/powerfeed.html +0 -2
  569. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
  570. nautobot/dcim/templates/dcim/powerpanel.html +0 -2
  571. nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
  572. nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
  573. nautobot/dcim/templates/dcim/rack.html +0 -2
  574. nautobot/dcim/templates/dcim/rack_edit.html +0 -2
  575. nautobot/dcim/templates/dcim/rackgroup.html +0 -2
  576. nautobot/dcim/templates/dcim/rackreservation.html +0 -2
  577. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
  578. nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
  579. nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
  580. nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
  581. nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
  582. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
  583. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
  584. nautobot/dcim/ui.py +0 -29
  585. nautobot/extras/templates/extras/computedfield.html +0 -2
  586. nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
  587. nautobot/extras/templates/extras/configcontext.html +0 -2
  588. nautobot/extras/templates/extras/configcontext_edit.html +0 -2
  589. nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
  590. nautobot/extras/templates/extras/configcontextschema.html +0 -2
  591. nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
  592. nautobot/extras/templates/extras/contact_retrieve.html +0 -2
  593. nautobot/extras/templates/extras/customfield.html +0 -2
  594. nautobot/extras/templates/extras/customfield_edit.html +0 -2
  595. nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
  596. nautobot/extras/templates/extras/customlink.html +0 -2
  597. nautobot/extras/templates/extras/dynamicgroup.html +0 -2
  598. nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
  599. nautobot/extras/templates/extras/exporttemplate.html +0 -2
  600. nautobot/extras/templates/extras/gitrepository.html +0 -2
  601. nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
  602. nautobot/extras/templates/extras/graphqlquery.html +0 -2
  603. nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
  604. nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -97
  605. nautobot/extras/templates/extras/job_detail.html +0 -2
  606. nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
  607. nautobot/extras/templates/extras/jobhook.html +0 -2
  608. nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
  609. nautobot/extras/templates/extras/jobresult.html +0 -2
  610. nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
  611. nautobot/extras/templates/extras/note.html +0 -2
  612. nautobot/extras/templates/extras/note_retrieve.html +0 -1
  613. nautobot/extras/templates/extras/object_changelog.html +0 -2
  614. nautobot/extras/templates/extras/object_notes.html +0 -2
  615. nautobot/extras/templates/extras/objectchange.html +0 -2
  616. nautobot/extras/templates/extras/objectchange_list.html +0 -3
  617. nautobot/extras/templates/extras/relationship.html +0 -1
  618. nautobot/extras/templates/extras/secret.html +0 -1
  619. nautobot/extras/templates/extras/secret_edit.html +0 -1
  620. nautobot/extras/templates/extras/secretsgroup.html +0 -2
  621. nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
  622. nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
  623. nautobot/extras/templates/extras/status.html +0 -2
  624. nautobot/extras/templates/extras/tag.html +0 -2
  625. nautobot/extras/templates/extras/tag_edit.html +0 -2
  626. nautobot/extras/templates/extras/tag_retrieve.html +0 -2
  627. nautobot/extras/templates/extras/team_retrieve.html +0 -2
  628. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
  629. nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
  630. nautobot/ipam/templates/ipam/prefix.html +0 -2
  631. nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
  632. nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
  633. nautobot/ipam/templates/ipam/rir.html +0 -2
  634. nautobot/ipam/templates/ipam/routetarget.html +0 -1
  635. nautobot/ipam/templates/ipam/service.html +0 -2
  636. nautobot/ipam/templates/ipam/service_edit.html +0 -2
  637. nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
  638. nautobot/ipam/templates/ipam/vlan.html +0 -2
  639. nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
  640. nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
  641. nautobot/ipam/templates/ipam/vlangroup.html +0 -2
  642. nautobot/ipam/templates/ipam/vrf.html +0 -1
  643. nautobot/tenancy/templates/tenancy/tenant.html +0 -2
  644. nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
  645. nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
  646. nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
  647. nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
  648. nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
  649. nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
  650. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
  651. nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
  652. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
  653. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
  654. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
  655. /nautobot/dcim/templates/dcim/{cable.html → cable_retrieve.html} +0 -0
  656. /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
  657. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
  658. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
  659. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
@@ -49,13 +49,13 @@ add "&raw" to the end of the URL within a browser.
49
49
  [data-bs-theme="dark"] .graphiql-dialog-overlay,
50
50
  [data-bs-theme="dark"] .graphiql-tooltip,
51
51
  [data-bs-theme="dark"] [data-radix-popper-content-wrapper] {
52
- --color-primary: 211, 96%, 36% !important; /* $blue-0-dark: #045ab4; */
53
- --color-secondary: 218, 14%, 36% !important; /* $gray-3-dark: #4f5868; */
54
- --color-tertiary: 0, 0%, 80% !important; /* $black-0-dark: #cbcbcb; */
55
- --color-success: 126, 100%, 18% !important; /* $green-0-dark: #005c09; */
56
- --color-warning: 31, 94%, 45% !important; /* $orange-0-dark: #e07807; */
57
- --color-error: 0, 92%, 31% !important; /* $red-0-dark: #960606; */
58
- --color-base: 222, 20%, 10% !important; /* $gray-0-dark: #14171e; */
52
+ --color-primary: 209, 100%, 60% !important; /* $blue-0-dark: #339dff; */
53
+ --color-secondary: 0, 0%, 71% !important; /* $gray-3-dark: #b5b5b5; */
54
+ --color-tertiary: 0, 0%, 100% !important; /* $black-0-dark: #ffffff; */
55
+ --color-success: 27, 63%, 49% !important; /* $green-0-dark: #2ecc40; */
56
+ --color-warning: 30, 100%, 60% !important; /* $orange-0-dark: #ff9933; */
57
+ --color-error: 0, 100%, 65% !important; /* $red-0-dark: #ff4c4c; */
58
+ --color-base: 0, 0%, 12% !important; /* $gray-0-dark: #1e1e1e; */
59
59
  }
60
60
 
61
61
  #main-content {
@@ -108,7 +108,6 @@ add "&raw" to the end of the URL within a browser.
108
108
  </div>
109
109
  {% block header %}{% endblock header %}
110
110
  </header>
111
- {% include 'modals/modal_theme.html' with name='theme'%}
112
111
  {% include 'inc/javascript.html' %}
113
112
  <main class="container-fluid wrapper" id="main-content" tabindex="-1">
114
113
  <!-- GraphiQL page contents -->
@@ -2,7 +2,7 @@
2
2
  {% load helpers %}
3
3
  {% load registry %}
4
4
 
5
- {# TODO: Figure out better solution: this is a quick hack to remove "chevrons" from homepage because in this commit I'm adding the cheverons in base_django.html #}
5
+ {# TODO: Figure out better solution: this is a quick hack to remove "chevrons" from homepage because in this commit I'm adding the chevrons in base_django.html #}
6
6
  {% block page_title %}{% endblock %}
7
7
 
8
8
  {% block header %}
@@ -1,7 +1,8 @@
1
1
  {% extends 'base.html' %}
2
2
 
3
+ {% block title %}Import Completed{% endblock %}
4
+
3
5
  {% block content %}
4
- <h1>{% block title %}Import Completed{% endblock %}</h1>
5
6
  {% include 'responsive_table.html' %}
6
7
  <a href="{{ request.path }}" class="btn btn-primary">
7
8
  <span class="mdi mdi-database-import-outline" aria-hidden="true"></span>
@@ -10,7 +10,7 @@
10
10
  data-nb-toggle="collapse-all"
11
11
  type="button"
12
12
  >
13
- Collapse All
13
+ Collapse All Groups
14
14
  </button>
15
15
  </div>
16
16
  <table id="computed_fields_accordion_{{ advanced_ui }}" class="table table-hover card-body attr-table">
@@ -2,10 +2,14 @@
2
2
  {% if object.last_updated %}
3
3
  <small class="align-items-center d-inline-flex gap-4 text-secondary">
4
4
  {% if object.created %}
5
- <span class="mdi mdi-bookmark-plus"></span> {{ object.created }}
6
- <span class="vr mx-4"></span>
5
+ <span data-bs-toggle="tooltip" title="Created at">
6
+ <span class="mdi mdi-bookmark-plus"></span> {{ object.created }}
7
+ <span class="vr mx-4"></span>
8
+ </span>
7
9
  {% endif %}
8
- <span class="mdi mdi-clock"></span> {{ object.last_updated|timesince }} ago
10
+ <span data-bs-toggle="tooltip" title="Last updated">
11
+ <span class="mdi mdi-clock"></span> {{ object.last_updated|timesince }} ago
12
+ </span>
9
13
  </small>
10
14
  {% endif %}
11
15
  </p>
@@ -10,7 +10,7 @@
10
10
  data-nb-toggle="collapse-all"
11
11
  type="button"
12
12
  >
13
- Collapse All
13
+ Collapse All Groups
14
14
  </button>
15
15
  </div>
16
16
  <table id="custom_fields_accordion_{{ advanced_ui }}" class="table table-hover card-body attr-table">
@@ -9,7 +9,7 @@
9
9
  {% if request.user.is_authenticated %}
10
10
  {% if settings.BRANDING_FILEPATHS.logo and settings.BRANDING_POWERED_BY_URL %}
11
11
  <a
12
- class="align-items-center d-inline-flex gap-4 my-n4 text-decoration-none"
12
+ class="align-items-center d-inline-flex fs-5 gap-4 my-n4 text-decoration-none"
13
13
  href="{{ settings.BRANDING_POWERED_BY_URL }}"
14
14
  target="_blank"
15
15
  >
@@ -102,3 +102,5 @@
102
102
  </div>
103
103
  </div>
104
104
  </footer>
105
+
106
+ {% include 'modals/modal_theme.html' with name='theme'%}
@@ -0,0 +1,6 @@
1
+ <div class="mb-10 d-md-flex">
2
+ <label class="col-md-3 col-form-label{% if required %} nb-required{% endif %}">{{ label }}</label>
3
+ <div class="col-md-9">
4
+ <p class="form-control-plaintext">{{ value }}</p>
5
+ </div>
6
+ </div>
@@ -1,4 +1,5 @@
1
1
  {% load helpers %}
2
+ {% load static %}
2
3
 
3
4
  {% if request.user.is_authenticated %}
4
5
  {% with is_apple_os=request.META.HTTP_USER_AGENT|split:'Mac OS X'|length|divisibleby:'2' %}
@@ -60,7 +61,7 @@
60
61
  {% firstof request.user.get_full_name request.user.username %}
61
62
  </button>
62
63
  <ul class="dropdown-menu dropdown-menu-end">
63
- <li><a class="dropdown-item" href="{% url 'about' %}"><span class="mdi mdi-information"></span>About</a></li>
64
+ <li><a class="dropdown-item" href="{% url 'about' %}"><span class="mdi mdi-information"></span>About Nautobot</a></li>
64
65
  <li><a class="dropdown-item" href="{% url 'user:profile' %}"><span class="mdi mdi-account-box"></span>Profile</a></li>
65
66
  <li><a class="dropdown-item" href="{% url 'extras:approver_dashboard' %}"><span class="mdi mdi-check-bold"></span>Approval Dashboard</a></li>
66
67
  {% if request.user.is_staff %}
@@ -72,4 +73,13 @@
72
73
  </ul>
73
74
  </div>
74
75
  </div>
76
+ {% else %}
77
+ {% url settings.LOGIN_URL as login_url %}
78
+ {% if request.path != login_url %}
79
+ <div class="col-4 offset-4 text-end">
80
+ <a class="btn btn-primary" href="{{ login_url }}?next={{ request.get_full_path | urlencode }}">
81
+ <span aria-hidden="true" class="mdi mdi-login me-4"></span>Log in
82
+ </a>
83
+ </div>
84
+ {% endif %}
75
85
  {% endif %}
@@ -1,3 +1,4 @@
1
+ {% comment %}3.0 TODO: Potentially remove this template pending no other references to it.{% endcomment %}
1
2
  {% if images %}
2
3
  <table class="table table-hover card-body">
3
4
  <tr>
@@ -33,4 +34,4 @@
33
34
  <div class="card-body">
34
35
  <span class="text-secondary">None</span>
35
36
  </div>
36
- {% endif %}
37
+ {% endif %}
@@ -9,6 +9,20 @@
9
9
  <link rel="stylesheet"
10
10
  href="{% static 'dist/css/materialdesignicons.css' %}"
11
11
  onerror="window.location='{% url 'media_failure' %}?filename=dist/css/materialdesignicons.css'">
12
+ {% with cookie_theme=request.COOKIES|get_item:'theme' %}
13
+ {% if not cookie_theme or cookie_theme == 'light' %}
14
+ <link rel="stylesheet"
15
+ href="{% static 'dist/css/github.min.css' %}"
16
+ onerror="window.location='{% url 'media_failure' %}?filename=dist/css/github.min.css'"
17
+ {% if not cookie_theme %}media="not (prefers-color-scheme: dark)"{% endif %}>
18
+ {% endif %}
19
+ {% if not cookie_theme or cookie_theme == 'dark' %}
20
+ <link rel="stylesheet"
21
+ href="{% static 'dist/css/github-dark.min.css' %}"
22
+ onerror="window.location='{% url 'media_failure' %}?filename=dist/css/github-dark.min.css'"
23
+ {% if not cookie_theme %}media="(prefers-color-scheme: dark)"{% endif %}>
24
+ {% endif %}
25
+ {% endwith %}
12
26
  {% if settings.BRANDING_FILEPATHS.css %}
13
27
  <link rel="stylesheet" id="custom-css" href="{% custom_branding_or_static 'css' None %}">
14
28
  {% endif %}
@@ -10,17 +10,18 @@
10
10
  aria-expanded="{% if cookie_sidenav_collapsed == 'true' %}false{% else %}true{% endif %}"
11
11
  aria-label="Collapse sidenav"
12
12
  class="bg-warning btn btm-sm btn-warning overflow-hidden p-4 position-absolute nb-sidenav-toggler"
13
+ data-bs-theme="dark"
13
14
  type="button"
14
15
  ></button>
15
16
 
16
17
  <a class="nb-sidenav-brand" href="{% url 'home' %}">
17
- <img src="{% custom_branding_or_static 'icon' 'img/nautobot_icon.svg' %}"/>
18
+ <img src="{% custom_branding_or_static 'icon_32' 'img/nautobot_icon.svg' %}"/>
18
19
  </a>
19
20
  <a class="position-absolute nb-sidenav-brand" href="{% url 'home' %}">
20
21
  <img src="{% custom_branding_or_static 'logo' 'img/nautobot_logo.svg' %}"/>
21
22
  </a>
22
23
 
23
- <ul class="list-unstyled my-0 overflow-auto pt-10 w-100">
24
+ <ul class="list-unstyled my-0 overflow-x-hidden overflow-y-auto pt-10 w-100">
24
25
  {% if request.user.is_authenticated %}
25
26
  {% if nav_menu_version_control %}
26
27
  <li>
@@ -148,13 +149,6 @@
148
149
  </li>
149
150
  {% endfor %}
150
151
  {% endwith %}
151
- {% else %}
152
- <li class="nb-sidenav-link-wrapper">
153
- <a class="nb-sidenav-link flat" href="{% url settings.LOGIN_URL %}?next={{ request.get_full_path | urlencode }}">
154
- <span class="mdi mdi-login"></span>
155
- <span class="ms-10">Log in</span>
156
- </a>
157
- </li>
158
152
  {% endif %}
159
153
  </ul>
160
154
  </nav>
@@ -68,13 +68,13 @@
68
68
  {% if object.created %}
69
69
  <tr>
70
70
  <td>Created</td>
71
- <td>{{ object.created }}</td>
71
+ <td><span data-bs-toggle="tooltip" title="Created at">{{ object.created }}</span></td>
72
72
  </tr>
73
73
  {% endif %}
74
74
  {% if object.last_updated %}
75
75
  <tr>
76
76
  <td>Updated</td>
77
- <td>{{ object.last_updated }}</td>
77
+ <td><span data-bs-toggle="tooltip" title="Last updated">{{ object.last_updated }}</span></td>
78
78
  </tr>
79
79
  {% endif %}
80
80
  <tr>
@@ -21,13 +21,13 @@
21
21
  {% endfor %}
22
22
  </div>
23
23
  <div class="justify-content-between mb-n20 nb-form-sticky-footer">
24
- <button type="reset" class="btn btn-secondary">
25
- <span aria-hidden="true" class="mdi mdi-close me-4"></span><!--
26
- -->Clear All
27
- </button>
28
24
  <button type="submit" class="btn btn-primary">
29
25
  <span class="mdi mdi-check me-4" aria-hidden="true"></span><!--
30
26
  -->Apply Specified
31
27
  </button>
28
+ <button type="reset" class="btn btn-secondary">
29
+ <span aria-hidden="true" class="mdi mdi-close me-4"></span><!--
30
+ -->Clear All
31
+ </button>
32
32
  </div>
33
33
  </form>
@@ -2,9 +2,11 @@
2
2
  {% load helpers %}
3
3
  {% load form_helpers %}
4
4
 
5
+ {% block title %}Home{% endblock title %}
6
+
5
7
  {% block content %}
6
- <div class="row" style="margin-block-start: {% if 'BANNER_LOGIN'|settings_or_config %}6.25{% else %}9.375{% endif %}rem;">
7
- <div class="col-md-4 offset-md-4">
8
+ <div class="row justify-content-center" style="margin-block-start: {% if 'BANNER_LOGIN'|settings_or_config %}6.25{% else %}9.375{% endif %}rem;">
9
+ <div class="col-sm-12 col-md-9 col-lg-7 nb-lg-max-width">
8
10
  {% if "BANNER_LOGIN"|settings_or_config %}
9
11
  <div class="alert alert-info text-center" role="alert">
10
12
  {{ "BANNER_LOGIN"|settings_or_config|render_markdown }}
@@ -261,12 +261,6 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
261
261
  # "icon_mask": os.getenv(
262
262
  # "NAUTOBOT_BRANDING_FILEPATHS_ICON_MASK", None
263
263
  # ), # mono-chrome icon used for the mask-icon header
264
- # "header_bullet": os.getenv(
265
- # "NAUTOBOT_BRANDING_FILEPATHS_HEADER_BULLET", None
266
- # ), # bullet image used for various view headers
267
- # "nav_bullet": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_NAV_BULLET", None), # bullet image used for nav menu headers
268
- # "css": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_CSS", None), # Custom global CSS
269
- # "javascript": os.getenv("NAUTOBOT_BRANDING_FILEPATHS_JAVASCRIPT", None), # Custom global JavaScript
270
264
  # }
271
265
 
272
266
  # Prepended to CSV, YAML and export template filenames (i.e. `nautobot_device.yml`)
@@ -358,11 +352,12 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
358
352
  # DEPLOYMENT_ID = os.environ["NAUTOBOT_DEPLOYMENT_ID"]
359
353
 
360
354
  # Device names are not guaranteed globally-unique by Nautobot but in practice they often are.
361
- # Set this to True to use the device name alone as the natural key for Device objects.
362
- # Set this to False to use the sequence (name, tenant, location) as the natural key instead.
363
- #
364
- # if "NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY" in os.environ and os.environ["NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY"] != "":
365
- # DEVICE_NAME_AS_NATURAL_KEY = is_truthy(os.environ["NAUTOBOT_DEVICE_NAME_AS_NATURAL_KEY"])
355
+ # Select how Devices are uniquely identified:
356
+ # - 'location_tenant_name': combination of Location + Tenant + Name
357
+ # - 'name': Device name must be globally unique
358
+ # - 'none': No enforced uniqueness (rely on other validation rules or custom validators)
359
+ # if "NAUTOBOT_DEVICE_UNIQUENESS" in os.environ and os.environ["NAUTOBOT_DEVICE_UNIQUENESS"] != "":
360
+ # DEVICE_UNIQUENESS = os.environ["NAUTOBOT_DEVICE_UNIQUENESS"]
366
361
 
367
362
  # Event Brokers
368
363
  # EVENT_BROKERS = {}
@@ -51,6 +51,13 @@
51
51
 
52
52
  {# Redoc doesn't change outer page styles. #}
53
53
  body { margin: 0; padding: 0; }
54
+
55
+ [data-bs-theme="dark"] .redoc-wrap,
56
+ [data-bs-theme="dark"] .redoc-wrap > :last-child,
57
+ [data-bs-theme="dark"] .redoc-wrap .api-content > [data-section-id] > [data-section-id] > :last-child,
58
+ [data-bs-theme="dark"] .redoc-wrap .menu-content .operation-type {
59
+ filter: hue-rotate(180deg) invert(1);
60
+ }
54
61
  </style>
55
62
  {% endblock extra_styles %}
56
63
 
@@ -2,6 +2,8 @@
2
2
  {% load helpers %}
3
3
  {% load plugins %}
4
4
  {% load static %}
5
+ {% load i18n %}
6
+ {% load rest_framework %}
5
7
  {% load ui_framework %}
6
8
 
7
9
  {% block bootstrap_theme %}
@@ -37,7 +39,83 @@
37
39
  </header>
38
40
  <main class="container-fluid wrapper" id="main-content" tabindex="-1">
39
41
  {% block content %}
40
- {{ block.super }}
42
+ <div class="region" aria-label="{% trans "request form" %}">
43
+ {% block request_forms %}
44
+
45
+ {% if 'GET' in allowed_methods %}
46
+ <form id="get-form" class="button-form">
47
+ <fieldset>
48
+ {% if api_settings.URL_FORMAT_OVERRIDE %}
49
+ <div class="btn-group format-selection">
50
+ <a class="btn btn-primary js-tooltip" href="{{ request.get_full_path }}" rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
51
+
52
+ <button class="btn btn-primary dropdown-toggle js-tooltip" data-bs-toggle="dropdown" title="Specify a format for the GET request">
53
+ <span class="mdi mdi-chevron-down"></span>
54
+ </button>
55
+ <ul class="dropdown-menu">
56
+ {% for format in available_formats %}
57
+ <li>
58
+ <a class="js-tooltip format-option dropdown-item" href="{% add_query_param request api_settings.URL_FORMAT_OVERRIDE format %}" rel="nofollow" title="Make a GET request on the {{ name }} resource with the format set to `{{ format }}`">{{ format }}</a>
59
+ </li>
60
+ {% endfor %}
61
+ </ul>
62
+ </div>
63
+ {% else %}
64
+ <a class="btn btn-primary js-tooltip" href="{{ request.get_full_path }}" rel="nofollow" title="Make a GET request on the {{ name }} resource">GET</a>
65
+ {% endif %}
66
+ </fieldset>
67
+ </form>
68
+ {% endif %}
69
+
70
+ {% if options_form %}
71
+ {# djlint:off H029 OPTIONS is an HTTP method #}
72
+ <form class="button-form" action="{{ request.get_full_path }}" data-method="OPTIONS">
73
+ <button class="btn btn-primary js-tooltip" title="Make an OPTIONS request on the {{ name }} resource">OPTIONS</button>
74
+ </form>
75
+ {# djlint:on H029 #}
76
+ {% endif %}
77
+
78
+ {% if extra_actions %}
79
+ <div class="dropdown" style="float: right; margin-right: 10px">
80
+ <button class="btn btn-secondary" id="extra-actions-menu" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
81
+ {% trans "Extra Actions" %}
82
+ <span class="mdi mdi-chevron-down"></span>
83
+ </button>
84
+ <ul class="dropdown-menu" aria-labelledby="extra-actions-menu">
85
+ {% for action_name, url in extra_actions|items %}
86
+ <li><a href="{{ url }}" class="dropdown-item">{{ action_name }}</a></li>
87
+ {% endfor %}
88
+ </ul>
89
+ </div>
90
+ {% endif %}
91
+
92
+ {% endblock request_forms %}
93
+ </div>
94
+
95
+ <div class="content-main" role="main" aria-label="{% trans "main content" %}">
96
+ <div class="float-start">
97
+ {% block description %}
98
+ {{ description }}
99
+ {% endblock %}
100
+ </div>
101
+
102
+ {% if paginator %}
103
+ <nav class="float-end">
104
+ {% get_pagination_html paginator %}
105
+ </nav>
106
+ {% endif %}
107
+
108
+ <div class="request-info pt-4" aria-label="{% trans "request info" %}">
109
+ <pre class="language-json"><b>{{ request.method }}</b> {{ request.get_full_path }}</pre>
110
+ </div>
111
+
112
+ <div class="response-info" aria-label="{% trans "response info" %}">
113
+ <pre class="language-json"><span class="meta nocode"><b>HTTP {{ response.status_code }} {{ response.status_text }}</b>{% for key, val in response_headers|items %}
114
+ <b>{{ key }}:</b> <span class="lit">{{ val|urlize }}</span>{% endfor %}
115
+
116
+ </span>{{ content|urlize }}</pre>
117
+ </div>
118
+ </div>
41
119
  {% endblock %}
42
120
  </main>
43
121
  {% include 'inc/footer.html' %}
@@ -49,12 +127,35 @@
49
127
 
50
128
  {% block script %}
51
129
  {% include 'inc/javascript.html' %}
52
- <script src="{% static "rest_framework/js/prettify-min.js" %}"></script>
53
130
  <script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
54
131
  <script src="{% static "rest_framework/js/default.js" %}"></script>
55
132
  <script>
133
+ function linkifyHighlightedUrls() {
134
+ // Find all hljs-string spans
135
+ const stringSpans = document.querySelectorAll('span.hljs-string');
136
+
137
+ stringSpans.forEach(span => {
138
+ const text = span.textContent;
139
+
140
+ // Check if the string starts with "http
141
+ if (text.match(/^["']https?:\/\/.*["']$/)) {
142
+ // Extract the URL (remove quotes)
143
+ const url = text.slice(1, -1); // Remove opening and closing quotes
144
+
145
+ // Create a clickable link while preserving the syntax highlighting
146
+ const link = document.createElement('a');
147
+ link.href = url;
148
+ link.className = 'hljs-string'; // Maintain the syntax highlighting class
149
+ link.textContent = text; // Keep the original text with quotes
150
+
151
+ // Replace the span with the link
152
+ span.parentNode.replaceChild(link, span);
153
+ }
154
+ });
155
+ }
56
156
  $(document).ready(function() {
57
157
  $('form').ajaxForm();
158
+ linkifyHighlightedUrls();
58
159
  });
59
160
  </script>
60
161
  {% endblock script %}
@@ -32,7 +32,7 @@
32
32
  {% for obj_type in results %}
33
33
  <a href="#{{ obj_type.name|lower }}" class="list-group-item">
34
34
  {{ obj_type.name|bettertitle }}
35
- <span class="badge">{{ obj_type.table.page.paginator.count }}</span>
35
+ <span class="badge bg-primary">{{ obj_type.table.page.paginator.count }}</span>
36
36
  </a>
37
37
  {% endfor %}
38
38
  </div>
@@ -7,13 +7,27 @@
7
7
  {% block extra_styles %}
8
8
  <link rel="stylesheet" href="{% static 'drf_spectacular_sidecar/swagger-ui-dist/swagger-ui.css' %}">
9
9
  <style>
10
- /* Manual styling inherited from drf-spectacular */
10
+ /* Manual styling inherited from drf-spectacular */
11
11
  html { box-sizing: border-box; overflow-y: scroll; }
12
12
  *, *:after, *:before { box-sizing: inherit; }
13
- body { background: #fafafa; margin: 0; }
14
- /* Style overrides to address conflicts between Swagger styling and Nautobot/Bootstrap styling */
13
+ body { background: var(--bs-body-bg); margin: 0; }
14
+ /* Style overrides to address conflicts between Swagger styling and Nautobot/Bootstrap styling */
15
15
  pre.version { border: none; background: none; }
16
16
  .loading-container .loading { display: block; }
17
+ /* Dark theme support */
18
+ [data-bs-theme="dark"] .swagger-ui,
19
+ [data-bs-theme="dark"] .swagger-ui .backdrop-ux,
20
+ [data-bs-theme="dark"] .swagger-ui .microlight,
21
+ [data-bs-theme="dark"] .swagger-ui .opblock .opblock-summary-method {
22
+ filter: hue-rotate(180deg) invert(1);
23
+ }
24
+ [data-bs-theme="dark"] .swagger-ui input:is([type="email"], [type="file"], [type="password"], [type="search"], [type="text"]),
25
+ [data-bs-theme="dark"] .swagger-ui textarea {
26
+ color: var(--bs-body-bg);
27
+ }
28
+ [data-bs-theme="dark"] .swagger-ui .scheme-container {
29
+ background: transparent;
30
+ }
17
31
  </style>
18
32
  {% endblock extra_styles %}
19
33
 
@@ -164,10 +164,9 @@
164
164
  <div class="modal-dialog" role="document">
165
165
  <div class="modal-content">
166
166
  <div class="modal-header">
167
+ <h4 class="modal-title">${field.name} Choices</h4>
167
168
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
168
- <span aria-hidden="true">&times;</span>
169
169
  </button>
170
- <h4 class="modal-title"><code>${field.name}</code> Choices</h4>
171
170
  </div>
172
171
  <table class="table table-hover modal-body">
173
172
  <tr><th>Import Value</th><th>Label</th></tr>
@@ -3,7 +3,7 @@
3
3
 
4
4
  {% block content %}
5
5
  <div class="row">
6
- <div class="col-md-6 mx-auto">
6
+ <div class="col-md-8 col-lg-6 mx-auto nb-lg-max-width">
7
7
  <form action="" method="post">
8
8
  {% csrf_token %}
9
9
  {% for field in form.hidden_fields %}
@@ -14,7 +14,7 @@
14
14
  {% block title %}{% endblock %}
15
15
  </div>
16
16
  <div class="card-body">
17
- {% block message %}<p>Are you sure?</p>{% endblock %}
17
+ <div class="mb-16">{% block message %}<p>Are you sure?</p>{% endblock %}</div>
18
18
  <div class="gap-8 hstack justify-content-end">
19
19
  <button type="submit" name="_confirm" class="btn btn-{{ button_class|default:'danger' }}">
20
20
  <span aria-hidden="true" class="mdi mdi-check me-4"></span><!--
@@ -14,12 +14,20 @@
14
14
  </div>
15
15
  <div class="hstack gap-8">
16
16
  {% if bulk_edit_url and permissions.change %}
17
- <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if bulk_querystring %}?{{ bulk_querystring }}{% elif request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm" disabled="disabled">
17
+ <button type="submit"
18
+ name="_edit"
19
+ formaction="{% url bulk_edit_url %}{% if bulk_querystring %}?{{ bulk_querystring }}{% elif request.GET %}?{{ request.GET.urlencode }}{% endif %}"
20
+ class="btn btn-warning btn-sm"
21
+ disabled>
18
22
  <span class="mdi mdi-pencil me-4" aria-hidden="true"></span>Edit All
19
23
  </button>
20
24
  {% endif %}
21
25
  {% if bulk_delete_url and permissions.delete %}
22
- <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if bulk_querystring %}?{{ bulk_querystring }}{% elif request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm" disabled="disabled">
26
+ <button type="submit"
27
+ name="_delete"
28
+ formaction="{% url bulk_delete_url %}{% if bulk_querystring %}?{{ bulk_querystring }}{% elif request.GET %}?{{ request.GET.urlencode }}{% endif %}"
29
+ class="btn btn-danger btn-sm"
30
+ disabled>
23
31
  <span class="mdi mdi-trash-can-outline me-4" aria-hidden="true"></span>Delete All
24
32
  </button>
25
33
  {% endif %}
@@ -1,15 +1,12 @@
1
1
  {% load form_helpers %}
2
2
 
3
- <div class="mb-10 d-flex justify-content-center{% if field.errors %} has-error{% endif %}">
3
+ <div class="mb-10 d-md-flex justify-content-center{% if field.errors %} has-error{% endif %}">
4
4
  {% if field|widget_type == 'checkboxinput' %}
5
5
  <div class="col-md-9 offset-md-3">
6
6
  <div class="form-check mt-6{% if field.errors %} has-error{% endif %}">
7
7
  {{ field }}
8
8
  <label class="form-check-label" for="{{ field.id_for_label }}">
9
9
  {{ field.label }}
10
- {% if field.help_text %}
11
- <span class="form-text">{{ field.help_text|safe }}</span>
12
- {% endif %}
13
10
  </label>
14
11
  </div>
15
12
  {% if bulk_nullable %}
@@ -18,6 +15,9 @@
18
15
  <label class="form-check-label" for="{{ field.id_for_label }}_nullify">Set null</label>
19
16
  </div>
20
17
  {% endif %}
18
+ {% if field.help_text %}
19
+ <span class="form-text">{{ field.help_text|safe }}</span>
20
+ {% endif %}
21
21
  {% elif field|widget_type == 'textarea' and not field.label %}
22
22
  <div class="col-md-12">
23
23
  {{ field }}
@@ -33,9 +33,6 @@
33
33
  {% else %}
34
34
  <label class="col-md-3 col-form-label{% if field.field.required %} nb-required{% endif %}" for="{{ field.id_for_label }}">
35
35
  {{ field.label }}
36
- {% if field.help_text %}
37
- <span class="form-text">{{ field.help_text|safe }}</span>
38
- {% endif %}
39
36
  </label>
40
37
  <div class="col-md-9">
41
38
  {{ field }}
@@ -45,6 +42,9 @@
45
42
  <label class="form-check-label" for="{{ field.id_for_label }}_nullify">Set null</label>
46
43
  </div>
47
44
  {% endif %}
45
+ {% if field.help_text %}
46
+ <span class="form-text">{{ field.help_text|safe }}</span>
47
+ {% endif %}
48
48
  {% endif %}
49
49
  {% if field.errors %}
50
50
  <ul class="mb-0 mt-4">
@@ -26,13 +26,13 @@
26
26
  <div class="card">
27
27
  <div class="card-header"><strong>Template</strong></div>
28
28
  <div class="card-body">
29
- <div class="mb-10 d-flex justify-content-center">
29
+ <div class="mb-10 d-lg-flex">
30
30
  <label class="col-lg-3 col-form-label nb-required" for="id_template_code">Jinja Template</label>
31
31
  <div class="col-lg-9">
32
32
  <textarea cols="40" rows="10" class="form-control" id="id_template_code" required=""></textarea>
33
33
  </div>
34
34
  </div>
35
- <div class="mb-10 d-flex justify-content-center">
35
+ <div class="mb-10 d-lg-flex">
36
36
  <label class="col-lg-3 col-form-label" for="id_context">Data</label>
37
37
  <div class="col-lg-9">
38
38
  <textarea cols="40" rows="10" class="form-control" placeholder="{}" id="id_context">{}</textarea>