nautobot 2.3.16__py3-none-any.whl → 2.4.0b1__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 (675) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/api.py +0 -2
  3. nautobot/apps/config.py +32 -3
  4. nautobot/apps/events.py +19 -0
  5. nautobot/apps/exceptions.py +0 -2
  6. nautobot/apps/ui.py +44 -9
  7. nautobot/apps/utils.py +0 -8
  8. nautobot/apps/views.py +2 -0
  9. nautobot/circuits/navigation.py +0 -57
  10. nautobot/circuits/tables.py +1 -2
  11. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  12. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  13. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  15. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  16. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  17. nautobot/circuits/tests/test_filters.py +4 -8
  18. nautobot/circuits/views.py +143 -26
  19. nautobot/cloud/factory.py +4 -1
  20. nautobot/cloud/models.py +1 -1
  21. nautobot/cloud/tests/test_filters.py +5 -4
  22. nautobot/core/api/fields.py +5 -5
  23. nautobot/core/api/metadata.py +28 -256
  24. nautobot/core/api/pagination.py +3 -2
  25. nautobot/core/api/renderers.py +3 -0
  26. nautobot/core/api/serializers.py +24 -244
  27. nautobot/core/api/urls.py +3 -4
  28. nautobot/core/api/utils.py +0 -62
  29. nautobot/core/api/views.py +48 -158
  30. nautobot/core/apps/__init__.py +22 -578
  31. nautobot/core/celery/__init__.py +13 -0
  32. nautobot/core/celery/log.py +4 -4
  33. nautobot/core/celery/schedulers.py +48 -3
  34. nautobot/core/cli/__init__.py +8 -0
  35. nautobot/core/constants.py +7 -0
  36. nautobot/core/events/__init__.py +116 -0
  37. nautobot/core/events/base.py +27 -0
  38. nautobot/core/events/exceptions.py +10 -0
  39. nautobot/core/events/redis_broker.py +48 -0
  40. nautobot/core/events/syslog_broker.py +19 -0
  41. nautobot/core/exceptions.py +0 -6
  42. nautobot/core/filters.py +16 -21
  43. nautobot/core/fixtures/user-data.json +59 -0
  44. nautobot/core/forms/fields.py +53 -8
  45. nautobot/core/forms/utils.py +2 -1
  46. nautobot/core/graphql/schema.py +3 -1
  47. nautobot/core/graphql/types.py +1 -1
  48. nautobot/core/jobs/__init__.py +4 -4
  49. nautobot/core/jobs/cleanup.py +13 -49
  50. nautobot/core/jobs/groups.py +1 -1
  51. nautobot/core/management/commands/generate_test_data.py +21 -0
  52. nautobot/core/management/commands/validate_models.py +1 -1
  53. nautobot/core/middleware.py +16 -0
  54. nautobot/core/models/__init__.py +1 -1
  55. nautobot/core/models/fields.py +11 -7
  56. nautobot/core/models/query_functions.py +2 -2
  57. nautobot/core/models/tree_queries.py +3 -6
  58. nautobot/core/settings.py +44 -7
  59. nautobot/core/settings.yaml +86 -8
  60. nautobot/core/tables.py +15 -65
  61. nautobot/core/tasks.py +1 -1
  62. nautobot/core/templates/components/button/default.html +7 -0
  63. nautobot/core/templates/components/button/dropdown.html +20 -0
  64. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  65. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  66. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  67. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  68. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  69. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  70. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  71. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  72. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  73. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  74. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  75. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  76. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  77. nautobot/core/templates/components/panel/panel.html +16 -0
  78. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  79. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  80. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  81. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  82. nautobot/core/templates/generic/object_retrieve.html +28 -17
  83. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  84. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  85. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  86. nautobot/core/templates/inc/footer.html +1 -0
  87. nautobot/core/templates/inc/media.html +0 -3
  88. nautobot/core/templates/inc/nav_menu.html +1 -1
  89. nautobot/core/templates/inc/relationships_panel.html +1 -1
  90. nautobot/core/templates/nautobot_config.py.j2 +3 -3
  91. nautobot/core/templates/panel_table.html +12 -0
  92. nautobot/core/templates/search.html +0 -7
  93. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  94. nautobot/core/templatetags/helpers.py +101 -12
  95. nautobot/core/templatetags/ui_framework.py +40 -0
  96. nautobot/core/testing/api.py +23 -128
  97. nautobot/core/testing/context.py +18 -0
  98. nautobot/core/testing/filters.py +41 -58
  99. nautobot/core/testing/mixins.py +2 -7
  100. nautobot/core/testing/views.py +25 -123
  101. nautobot/core/tests/integration/test_app_home.py +1 -0
  102. nautobot/core/tests/integration/test_app_navbar.py +1 -0
  103. nautobot/core/tests/integration/test_filters.py +2 -0
  104. nautobot/core/tests/integration/test_home.py +1 -0
  105. nautobot/core/tests/integration/test_navbar.py +1 -0
  106. nautobot/core/tests/integration/test_view_authentication.py +1 -2
  107. nautobot/core/tests/nautobot_config.py +198 -0
  108. nautobot/core/tests/runner.py +3 -3
  109. nautobot/core/tests/test_api.py +82 -201
  110. nautobot/core/tests/test_csv.py +3 -25
  111. nautobot/core/tests/test_events.py +214 -0
  112. nautobot/core/tests/test_jinja_filters.py +1 -0
  113. nautobot/core/tests/test_jobs.py +84 -13
  114. nautobot/core/tests/test_navigations.py +7 -241
  115. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  116. nautobot/core/tests/test_ui.py +150 -0
  117. nautobot/core/tests/test_utils.py +0 -25
  118. nautobot/core/tests/test_views.py +123 -31
  119. nautobot/core/ui/__init__.py +0 -0
  120. nautobot/core/ui/base.py +11 -0
  121. nautobot/core/ui/choices.py +44 -0
  122. nautobot/core/ui/homepage.py +167 -0
  123. nautobot/core/ui/nav.py +279 -0
  124. nautobot/core/ui/object_detail.py +1841 -0
  125. nautobot/core/ui/utils.py +36 -0
  126. nautobot/core/urls.py +4 -9
  127. nautobot/core/utils/config.py +30 -3
  128. nautobot/core/utils/lookup.py +20 -13
  129. nautobot/core/views/__init__.py +6 -1
  130. nautobot/core/views/generic.py +47 -52
  131. nautobot/core/views/mixins.py +15 -25
  132. nautobot/core/views/paginator.py +8 -5
  133. nautobot/core/views/renderers.py +3 -3
  134. nautobot/core/views/utils.py +11 -0
  135. nautobot/core/wsgi.py +3 -3
  136. nautobot/dcim/api/serializers.py +80 -179
  137. nautobot/dcim/api/urls.py +5 -0
  138. nautobot/dcim/api/views.py +17 -4
  139. nautobot/dcim/apps.py +1 -0
  140. nautobot/dcim/choices.py +28 -0
  141. nautobot/dcim/factory.py +58 -0
  142. nautobot/dcim/filters/__init__.py +197 -24
  143. nautobot/dcim/forms.py +203 -12
  144. nautobot/dcim/graphql/types.py +2 -2
  145. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  146. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  147. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  148. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  149. nautobot/dcim/models/__init__.py +4 -0
  150. nautobot/dcim/models/device_component_templates.py +2 -2
  151. nautobot/dcim/models/device_components.py +20 -22
  152. nautobot/dcim/models/devices.py +173 -4
  153. nautobot/dcim/models/locations.py +3 -3
  154. nautobot/dcim/models/power.py +5 -6
  155. nautobot/dcim/models/racks.py +6 -6
  156. nautobot/dcim/navigation.py +25 -224
  157. nautobot/dcim/signals.py +44 -0
  158. nautobot/dcim/tables/__init__.py +5 -3
  159. nautobot/dcim/tables/devices.py +96 -2
  160. nautobot/dcim/tables/devicetypes.py +2 -2
  161. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  162. nautobot/dcim/templates/dcim/controller_create.html +1 -0
  163. nautobot/dcim/templates/dcim/controller_retrieve.html +5 -1
  164. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  165. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +66 -0
  166. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +46 -0
  167. nautobot/dcim/templates/dcim/device/base.html +6 -42
  168. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  169. nautobot/dcim/templates/dcim/device.html +3 -1
  170. nautobot/dcim/templates/dcim/interface.html +1 -0
  171. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  172. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  173. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  174. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +76 -0
  175. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +34 -0
  176. nautobot/dcim/tests/test_api.py +172 -61
  177. nautobot/dcim/tests/test_filters.py +171 -109
  178. nautobot/dcim/tests/test_forms.py +2 -51
  179. nautobot/dcim/tests/test_graphql.py +0 -52
  180. nautobot/dcim/tests/test_models.py +126 -4
  181. nautobot/dcim/tests/test_signals.py +1 -0
  182. nautobot/dcim/tests/test_views.py +103 -11
  183. nautobot/dcim/urls.py +72 -27
  184. nautobot/dcim/utils.py +2 -2
  185. nautobot/dcim/views.py +369 -62
  186. nautobot/extras/api/customfields.py +2 -2
  187. nautobot/extras/api/serializers.py +91 -75
  188. nautobot/extras/api/urls.py +4 -0
  189. nautobot/extras/api/views.py +78 -15
  190. nautobot/extras/choices.py +13 -0
  191. nautobot/extras/constants.py +0 -1
  192. nautobot/extras/context_managers.py +23 -6
  193. nautobot/extras/datasources/git.py +4 -1
  194. nautobot/extras/factory.py +27 -0
  195. nautobot/extras/filters/__init__.py +59 -0
  196. nautobot/extras/forms/forms.py +125 -30
  197. nautobot/extras/forms/mixins.py +3 -11
  198. nautobot/extras/graphql/types.py +25 -1
  199. nautobot/extras/group_sync.py +3 -3
  200. nautobot/extras/health_checks.py +2 -1
  201. nautobot/extras/jobs.py +62 -26
  202. nautobot/extras/management/__init__.py +1 -0
  203. nautobot/extras/management/commands/runjob.py +7 -79
  204. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  205. nautobot/extras/management/utils.py +87 -0
  206. nautobot/extras/managers.py +1 -3
  207. nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
  208. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  209. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  210. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  211. nautobot/extras/models/__init__.py +4 -0
  212. nautobot/extras/models/change_logging.py +7 -3
  213. nautobot/extras/models/customfields.py +11 -12
  214. nautobot/extras/models/groups.py +9 -13
  215. nautobot/extras/models/jobs.py +218 -37
  216. nautobot/extras/models/models.py +2 -2
  217. nautobot/extras/models/relationships.py +69 -1
  218. nautobot/extras/models/secrets.py +5 -0
  219. nautobot/extras/navigation.py +20 -262
  220. nautobot/extras/plugins/__init__.py +56 -32
  221. nautobot/extras/plugins/marketplace_manifest.yml +450 -0
  222. nautobot/extras/plugins/urls.py +1 -0
  223. nautobot/extras/plugins/views.py +48 -1
  224. nautobot/extras/signals.py +39 -1
  225. nautobot/extras/tables.py +40 -6
  226. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  227. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  228. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  229. nautobot/extras/templates/extras/job_detail.html +36 -6
  230. nautobot/extras/templates/extras/job_edit.html +5 -2
  231. nautobot/extras/templates/extras/job_list.html +2 -7
  232. nautobot/extras/templates/extras/jobqueue_retrieve.html +44 -0
  233. nautobot/extras/templates/extras/marketplace.html +278 -0
  234. nautobot/extras/templates/extras/plugins_list.html +35 -1
  235. nautobot/extras/templates/extras/plugins_tiles.html +79 -0
  236. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  237. nautobot/extras/templates/extras/secret.html +0 -65
  238. nautobot/extras/templates/extras/secret_check.js +16 -0
  239. nautobot/extras/templates/extras/secret_create.html +114 -0
  240. nautobot/extras/templates/extras/secret_edit.html +1 -114
  241. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  242. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  243. nautobot/extras/templatetags/job_buttons.py +5 -4
  244. nautobot/extras/templatetags/plugins.py +69 -6
  245. nautobot/extras/test_jobs/api_test_job.py +1 -1
  246. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  247. nautobot/extras/test_jobs/dry_run.py +1 -1
  248. nautobot/extras/test_jobs/fail.py +5 -5
  249. nautobot/extras/test_jobs/file_output.py +1 -1
  250. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  251. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  252. nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
  253. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  254. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  255. nautobot/extras/test_jobs/log_redaction.py +1 -1
  256. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  257. nautobot/extras/test_jobs/modify_db.py +1 -1
  258. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  259. nautobot/extras/test_jobs/object_var_required.py +1 -1
  260. nautobot/extras/test_jobs/object_vars.py +1 -1
  261. nautobot/extras/test_jobs/pass.py +3 -3
  262. nautobot/extras/test_jobs/profiling.py +1 -1
  263. nautobot/extras/test_jobs/relative_import.py +3 -3
  264. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  265. nautobot/extras/test_jobs/task_queues.py +1 -1
  266. nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
  267. nautobot/extras/tests/test_api.py +157 -55
  268. nautobot/extras/tests/test_context_managers.py +4 -1
  269. nautobot/extras/tests/test_customfields.py +1 -1
  270. nautobot/extras/tests/test_datasources.py +1 -2
  271. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  272. nautobot/extras/tests/test_filters.py +219 -535
  273. nautobot/extras/tests/test_forms.py +1 -20
  274. nautobot/extras/tests/test_job_variables.py +73 -152
  275. nautobot/extras/tests/test_jobs.py +43 -54
  276. nautobot/extras/tests/test_models.py +71 -16
  277. nautobot/extras/tests/test_relationships.py +5 -2
  278. nautobot/extras/tests/test_utils.py +23 -2
  279. nautobot/extras/tests/test_views.py +183 -43
  280. nautobot/extras/tests/test_webhooks.py +2 -1
  281. nautobot/extras/urls.py +2 -20
  282. nautobot/extras/utils.py +118 -4
  283. nautobot/extras/views.py +203 -92
  284. nautobot/extras/webhooks.py +5 -2
  285. nautobot/ipam/api/fields.py +3 -3
  286. nautobot/ipam/api/serializers.py +36 -137
  287. nautobot/ipam/api/views.py +93 -62
  288. nautobot/ipam/lookups.py +62 -101
  289. nautobot/ipam/models.py +11 -63
  290. nautobot/ipam/navigation.py +0 -90
  291. nautobot/ipam/querysets.py +2 -2
  292. nautobot/ipam/tables.py +6 -20
  293. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  294. nautobot/ipam/templates/ipam/vrf.html +0 -47
  295. nautobot/ipam/tests/test_api.py +8 -419
  296. nautobot/ipam/tests/test_filters.py +39 -119
  297. nautobot/ipam/tests/test_forms.py +47 -51
  298. nautobot/ipam/tests/test_migrations.py +30 -30
  299. nautobot/ipam/tests/test_models.py +0 -41
  300. nautobot/ipam/tests/test_querysets.py +1 -63
  301. nautobot/ipam/urls.py +3 -69
  302. nautobot/ipam/utils/__init__.py +0 -24
  303. nautobot/ipam/views.py +153 -198
  304. nautobot/project-static/css/base.css +38 -3
  305. nautobot/project-static/docs/404.html +421 -19
  306. nautobot/project-static/docs/apps/index.html +421 -19
  307. nautobot/project-static/docs/apps/nautobot-apps.html +421 -19
  308. nautobot/project-static/docs/assets/extra.css +5 -1
  309. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
  310. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
  311. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +421 -19
  312. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +421 -19
  313. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +421 -172
  314. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +421 -19
  315. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +421 -19
  316. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +425 -21
  317. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +421 -19
  318. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +424 -22
  319. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9809 -0
  320. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +424 -63
  321. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +421 -19
  322. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +421 -19
  323. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +457 -20
  324. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +421 -19
  325. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +425 -25
  326. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +457 -19
  327. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +421 -19
  328. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +421 -19
  329. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +425 -215
  330. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +430 -342
  331. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5799 -1054
  332. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +421 -19
  333. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +447 -176
  334. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +460 -21
  335. nautobot/project-static/docs/development/apps/api/configuration-view.html +421 -19
  336. nautobot/project-static/docs/development/apps/api/database-backend-config.html +421 -19
  337. nautobot/project-static/docs/development/apps/api/models/django-admin.html +421 -19
  338. nautobot/project-static/docs/development/apps/api/models/global-search.html +421 -19
  339. nautobot/project-static/docs/development/apps/api/models/graphql.html +421 -19
  340. nautobot/project-static/docs/development/apps/api/models/index.html +421 -19
  341. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +421 -19
  342. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +421 -19
  343. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +421 -19
  344. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +421 -19
  345. nautobot/project-static/docs/development/apps/api/platform-features/index.html +421 -19
  346. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +421 -19
  347. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +421 -19
  348. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +421 -19
  349. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +421 -19
  350. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +424 -41
  351. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +421 -19
  352. nautobot/project-static/docs/development/apps/api/prometheus.html +421 -19
  353. nautobot/project-static/docs/development/apps/api/setup.html +425 -155
  354. nautobot/project-static/docs/development/apps/api/testing.html +421 -19
  355. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +421 -19
  356. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +421 -19
  357. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +421 -19
  358. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +421 -19
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +701 -130
  360. nautobot/project-static/docs/development/apps/api/views/base-template.html +421 -19
  361. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +421 -19
  362. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +421 -19
  363. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +421 -19
  364. nautobot/project-static/docs/development/apps/api/views/index.html +423 -20
  365. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +425 -19
  366. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +451 -19
  367. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +421 -19
  368. nautobot/project-static/docs/development/apps/api/views/notes.html +421 -19
  369. nautobot/project-static/docs/development/apps/api/views/rest-api.html +421 -19
  370. nautobot/project-static/docs/development/apps/api/views/urls.html +421 -19
  371. nautobot/project-static/docs/development/apps/index.html +421 -19
  372. nautobot/project-static/docs/development/apps/migration/code-updates.html +422 -52
  373. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +422 -20
  374. nautobot/project-static/docs/development/apps/migration/from-v1.html +421 -19
  375. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +421 -19
  376. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +421 -19
  377. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +421 -19
  378. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +424 -22
  379. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9219 -0
  380. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9333 -0
  381. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9474 -0
  382. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9517 -0
  383. nautobot/project-static/docs/development/apps/porting-from-netbox.html +424 -22
  384. nautobot/project-static/docs/development/core/application-registry.html +421 -19
  385. nautobot/project-static/docs/development/core/best-practices.html +421 -19
  386. nautobot/project-static/docs/development/core/bootstrap-ui.html +421 -19
  387. nautobot/project-static/docs/development/core/caching.html +421 -19
  388. nautobot/project-static/docs/development/core/controllers.html +423 -19
  389. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +490 -45
  390. nautobot/project-static/docs/development/core/generic-views.html +421 -19
  391. nautobot/project-static/docs/development/core/getting-started.html +566 -179
  392. nautobot/project-static/docs/development/core/homepage.html +432 -30
  393. nautobot/project-static/docs/development/core/index.html +421 -19
  394. nautobot/project-static/docs/development/core/local-k8s.html +9453 -0
  395. nautobot/project-static/docs/development/core/model-checklist.html +424 -22
  396. nautobot/project-static/docs/development/core/model-features.html +421 -19
  397. nautobot/project-static/docs/development/core/natural-keys.html +421 -19
  398. nautobot/project-static/docs/development/core/navigation-menu.html +438 -26
  399. nautobot/project-static/docs/development/core/release-checklist.html +435 -45
  400. nautobot/project-static/docs/development/core/role-internals.html +421 -19
  401. nautobot/project-static/docs/development/core/settings.html +421 -19
  402. nautobot/project-static/docs/development/core/style-guide.html +421 -19
  403. nautobot/project-static/docs/development/core/templates.html +431 -22
  404. nautobot/project-static/docs/development/core/testing.html +421 -19
  405. nautobot/project-static/docs/development/core/ui-component-framework.html +11020 -0
  406. nautobot/project-static/docs/development/core/user-preferences.html +424 -22
  407. nautobot/project-static/docs/development/index.html +421 -19
  408. nautobot/project-static/docs/development/jobs/index.html +546 -160
  409. nautobot/project-static/docs/development/jobs/migration/from-v1.html +421 -19
  410. nautobot/project-static/docs/index.html +421 -19
  411. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  412. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  413. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  414. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  415. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  416. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  417. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  418. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  419. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  420. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  421. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  422. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  423. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  424. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  425. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  426. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  427. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  428. nautobot/project-static/docs/objects.inv +0 -0
  429. nautobot/project-static/docs/overview/application_stack.html +426 -20
  430. nautobot/project-static/docs/overview/design_philosophy.html +421 -19
  431. nautobot/project-static/docs/release-notes/index.html +445 -22
  432. nautobot/project-static/docs/release-notes/version-1.0.html +421 -19
  433. nautobot/project-static/docs/release-notes/version-1.1.html +421 -19
  434. nautobot/project-static/docs/release-notes/version-1.2.html +421 -19
  435. nautobot/project-static/docs/release-notes/version-1.3.html +421 -19
  436. nautobot/project-static/docs/release-notes/version-1.4.html +421 -19
  437. nautobot/project-static/docs/release-notes/version-1.5.html +421 -19
  438. nautobot/project-static/docs/release-notes/version-1.6.html +634 -667
  439. nautobot/project-static/docs/release-notes/version-2.0.html +421 -19
  440. nautobot/project-static/docs/release-notes/version-2.1.html +421 -19
  441. nautobot/project-static/docs/release-notes/version-2.2.html +421 -19
  442. nautobot/project-static/docs/release-notes/version-2.3.html +684 -886
  443. nautobot/project-static/docs/release-notes/version-2.4.html +10007 -0
  444. nautobot/project-static/docs/requirements.txt +2 -2
  445. nautobot/project-static/docs/search/search_index.json +1 -1
  446. nautobot/project-static/docs/sitemap.xml +334 -270
  447. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  448. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +421 -19
  449. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +421 -19
  450. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +423 -21
  451. nautobot/project-static/docs/user-guide/administration/configuration/index.html +433 -32
  452. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +421 -19
  453. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +765 -180
  454. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +421 -19
  455. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +421 -19
  456. nautobot/project-static/docs/user-guide/administration/guides/docker.html +434 -29
  457. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +421 -19
  458. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +421 -19
  459. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +421 -19
  460. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +421 -19
  461. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +421 -19
  462. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +421 -19
  463. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +421 -19
  464. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +421 -19
  465. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +421 -19
  466. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +421 -19
  467. nautobot/project-static/docs/user-guide/administration/installation/index.html +426 -20
  468. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +421 -19
  469. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +421 -19
  470. nautobot/project-static/docs/user-guide/administration/installation/services.html +421 -19
  471. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +421 -19
  472. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +442 -41
  473. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +435 -66
  474. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +435 -66
  475. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +421 -19
  476. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +421 -19
  477. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +421 -19
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +421 -19
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +421 -19
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +421 -19
  481. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +421 -19
  482. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  483. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +421 -19
  484. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +427 -21
  485. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +421 -19
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +421 -19
  487. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +421 -19
  488. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +421 -19
  489. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +421 -19
  490. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +421 -19
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +421 -19
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +421 -19
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +421 -19
  494. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +421 -19
  495. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +421 -19
  496. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +421 -19
  497. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +421 -19
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +421 -19
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +421 -19
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +421 -19
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +421 -19
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +457 -20
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +447 -22
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +421 -19
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +421 -19
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +421 -19
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +421 -19
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +421 -19
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +421 -19
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +421 -19
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +421 -19
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +421 -19
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +421 -19
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +421 -19
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +421 -19
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +421 -19
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +421 -19
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +421 -19
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +421 -19
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +421 -19
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +421 -19
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +421 -19
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +421 -19
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +421 -19
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +421 -19
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +421 -19
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +421 -19
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +421 -19
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +421 -19
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +421 -19
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +421 -19
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +421 -19
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +421 -19
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +421 -19
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +421 -19
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +421 -19
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +421 -19
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9333 -0
  539. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +424 -22
  540. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +421 -19
  541. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +421 -19
  542. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +421 -19
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +421 -19
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +421 -19
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +421 -19
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +421 -19
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +421 -19
  548. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +421 -19
  549. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +421 -19
  550. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +421 -19
  551. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +421 -19
  552. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +421 -19
  553. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +421 -19
  554. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +421 -19
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +421 -19
  556. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +421 -19
  557. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +421 -19
  558. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +421 -19
  559. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +424 -22
  560. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9271 -0
  561. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9175 -0
  562. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9169 -0
  563. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9235 -0
  564. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +421 -19
  565. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +421 -19
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +421 -19
  567. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +421 -19
  568. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +421 -19
  569. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +421 -19
  570. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +421 -19
  571. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +421 -19
  572. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +421 -19
  573. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +421 -19
  574. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +421 -19
  575. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +421 -19
  576. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +421 -19
  577. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +421 -19
  578. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +421 -19
  579. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +421 -19
  580. nautobot/project-static/docs/user-guide/index.html +421 -19
  581. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +424 -22
  582. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +421 -19
  583. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +421 -19
  584. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +421 -19
  585. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +421 -19
  586. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9575 -0
  587. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +424 -22
  588. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +421 -19
  589. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +421 -19
  590. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +421 -19
  591. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +421 -19
  592. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +421 -19
  593. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +426 -20
  594. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +424 -22
  595. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +421 -19
  596. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +421 -19
  597. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9182 -0
  598. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +424 -22
  599. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +421 -19
  600. nautobot/project-static/docs/user-guide/platform-functionality/note.html +421 -19
  601. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +421 -19
  602. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +424 -22
  603. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9250 -0
  604. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +421 -19
  605. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +421 -19
  606. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +424 -22
  607. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +421 -19
  608. nautobot/project-static/docs/user-guide/platform-functionality/role.html +421 -19
  609. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +421 -19
  610. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +421 -19
  611. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +424 -22
  612. nautobot/project-static/docs/user-guide/platform-functionality/status.html +421 -19
  613. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +421 -19
  614. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +489 -56
  615. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +421 -19
  616. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +421 -19
  617. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +421 -19
  618. nautobot/project-static/img/jinja_logo.svg +97 -0
  619. nautobot/project-static/js/forms.js +5 -0
  620. nautobot/project-static/js/nav_menu.js +2 -1
  621. nautobot/tenancy/api/serializers.py +0 -2
  622. nautobot/tenancy/factory.py +1 -1
  623. nautobot/tenancy/navigation.py +0 -29
  624. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  625. nautobot/tenancy/tests/test_filters.py +29 -134
  626. nautobot/tenancy/views.py +32 -23
  627. nautobot/users/admin.py +3 -1
  628. nautobot/users/api/serializers.py +4 -5
  629. nautobot/users/api/views.py +1 -1
  630. nautobot/users/forms.py +19 -0
  631. nautobot/users/templates/users/preferences.html +22 -0
  632. nautobot/users/tests/test_filters.py +1 -19
  633. nautobot/users/tests/test_views.py +57 -0
  634. nautobot/users/utils.py +8 -0
  635. nautobot/users/views.py +48 -11
  636. nautobot/virtualization/api/serializers.py +4 -4
  637. nautobot/virtualization/filters.py +2 -20
  638. nautobot/virtualization/navigation.py +0 -48
  639. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  640. nautobot/virtualization/tests/test_filters.py +57 -183
  641. nautobot/virtualization/views.py +18 -15
  642. nautobot/wireless/__init__.py +0 -0
  643. nautobot/wireless/api/__init__.py +0 -0
  644. nautobot/wireless/api/serializers.py +44 -0
  645. nautobot/wireless/api/urls.py +20 -0
  646. nautobot/wireless/api/views.py +34 -0
  647. nautobot/wireless/apps.py +8 -0
  648. nautobot/wireless/choices.py +345 -0
  649. nautobot/wireless/factory.py +138 -0
  650. nautobot/wireless/filters.py +167 -0
  651. nautobot/wireless/forms.py +283 -0
  652. nautobot/wireless/homepage.py +19 -0
  653. nautobot/wireless/migrations/0001_initial.py +223 -0
  654. nautobot/wireless/migrations/__init__.py +0 -0
  655. nautobot/wireless/models.py +207 -0
  656. nautobot/wireless/navigation.py +105 -0
  657. nautobot/wireless/tables.py +244 -0
  658. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  659. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  660. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  661. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +64 -0
  662. nautobot/wireless/tests/__init__.py +0 -0
  663. nautobot/wireless/tests/test_api.py +247 -0
  664. nautobot/wireless/tests/test_filters.py +54 -0
  665. nautobot/wireless/tests/test_models.py +22 -0
  666. nautobot/wireless/tests/test_views.py +378 -0
  667. nautobot/wireless/urls.py +13 -0
  668. nautobot/wireless/views.py +129 -0
  669. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +11 -14
  670. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +674 -551
  671. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
  672. nautobot/core/utils/navigation.py +0 -54
  673. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
  674. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
  675. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
nautobot/core/tables.py CHANGED
@@ -14,8 +14,7 @@ from django.utils.http import urlencode
14
14
  from django.utils.safestring import mark_safe
15
15
  from django.utils.text import Truncator
16
16
  import django_tables2
17
- from django_tables2.data import TableData, TableQuerysetData
18
- from django_tables2.rows import BoundRows
17
+ from django_tables2.data import TableQuerysetData
19
18
  from django_tables2.utils import Accessor, OrderBy, OrderByTuple
20
19
  from tree_queries.models import TreeNode
21
20
 
@@ -47,24 +46,8 @@ class BaseTable(django_tables2.Table):
47
46
  user=None,
48
47
  hide_hierarchy_ui=False,
49
48
  order_by=None,
50
- data_transform_callback=None,
51
49
  **kwargs,
52
50
  ):
53
- """
54
- Instantiate a BaseTable.
55
-
56
- Args:
57
- *args (list, optional): Passed through to django_tables2.Table
58
- table_changes_pending (bool): TODO
59
- saved_view (SavedView, optional): TODO
60
- user (User, optional): TODO
61
- hide_hierarchy_ui (bool): Whether to display or hide hierarchy indentation of nested objects.
62
- order_by (list, optional): Field(s) to sort by
63
- data_transform_callback (function, optional): A function that takes the given `data` as an input and
64
- returns new data. Runs after all of the queryset auto-optimization performed by this class.
65
- Used for example in IPAM views to inject "fake" records for "available" Prefixes, IPAddresses, or VLANs.
66
- **kwargs (dict, optional): Passed through to django_tables2.Table
67
- """
68
51
  # Add custom field columns
69
52
  model = self._meta.model
70
53
 
@@ -106,14 +89,6 @@ class BaseTable(django_tables2.Table):
106
89
  # Init table
107
90
  super().__init__(*args, order_by=order_by, **kwargs)
108
91
 
109
- if not isinstance(self.data, TableQuerysetData):
110
- # LinkedCountColumns don't work properly if the data is a list of dicts instead of a queryset,
111
- # as they rely on a `queryset.annotate()` call to gather the data.
112
- self.exclude = [
113
- *self.exclude,
114
- *[column.name for column in self.columns if isinstance(column.column, LinkedCountColumn)],
115
- ]
116
-
117
92
  # Don't show hierarchy if we're sorted
118
93
  if order_by is not None and hide_hierarchy_ui is None:
119
94
  hide_hierarchy_ui = True
@@ -147,7 +122,7 @@ class BaseTable(django_tables2.Table):
147
122
  columns = user.get_config(f"tables.{self.__class__.__name__}.columns")
148
123
  if columns:
149
124
  for name, column in self.base_columns.items():
150
- if name in columns and name not in self.exclude:
125
+ if name in columns:
151
126
  self.columns.show(name)
152
127
  else:
153
128
  self.columns.hide(name)
@@ -186,8 +161,7 @@ class BaseTable(django_tables2.Table):
186
161
  logger.error("Couldn't find model for %s", column.column.viewname)
187
162
  continue
188
163
  reverse_lookup = column.column.reverse_lookup or next(iter(column.column.url_params.keys()))
189
- distinct = column.column.distinct
190
- count_fields.append((column.name, column_model, reverse_lookup, distinct))
164
+ count_fields.append((column.name, column_model, reverse_lookup))
191
165
  try:
192
166
  lookup = column.column.lookup or get_related_field_for_models(model, column_model).name
193
167
  # For some reason get_related_field_for_models(Tag, DynamicGroup) gives a M2M with the name
@@ -199,8 +173,7 @@ class BaseTable(django_tables2.Table):
199
173
  if lookup is not None:
200
174
  # Also attempt to prefetch the first matching record for display - see LinkedCountColumn
201
175
  prefetch_fields.append(
202
- # Use order_by() because we don't care about ordering here and it's potentially expensive
203
- Prefetch(lookup, column_model.objects.order_by()[:1], to_attr=f"{lookup}_list")
176
+ Prefetch(lookup, column_model.objects.all()[:1], to_attr=f"{lookup}_list")
204
177
  )
205
178
  continue
206
179
 
@@ -283,34 +256,24 @@ class BaseTable(django_tables2.Table):
283
256
  )
284
257
 
285
258
  if count_fields:
286
- for column_name, column_model, lookup_name, distinct in count_fields:
259
+ for column_name, column_model, lookup_name in count_fields:
287
260
  if hasattr(queryset.first(), column_name):
288
261
  continue
289
262
  try:
290
263
  logger.debug(
291
- "Applying .annotate(%s=count_related(%s, %r, distinct=%s) to %s QuerySet",
264
+ "Applying .annotate(%s=count_related(%s, %r) to %s QuerySet",
292
265
  column_name,
293
266
  column_model.__name__,
294
267
  lookup_name,
295
- distinct,
296
268
  model.__name__,
297
269
  )
298
- queryset = queryset.annotate(
299
- **{column_name: count_related(column_model, lookup_name, distinct=distinct)}
300
- )
270
+ queryset = queryset.annotate(**{column_name: count_related(column_model, lookup_name)})
301
271
  except FieldError:
302
272
  # No error message logged here as the above is *very much* best-effort
303
273
  pass
304
274
 
305
275
  self.data.data = queryset
306
276
 
307
- # TODO: it would be better if we could apply this transformation and the above queryset optimizations
308
- # **before** calling super().__init__(), but the current implementation works for now, though inelegant.
309
- if data_transform_callback is not None:
310
- self.data = TableData.from_data(data_transform_callback(self.data.data))
311
- self.data.set_table(self)
312
- self.rows = BoundRows(data=self.data, table=self, pinned_data=self.pinned_data)
313
-
314
277
  @property
315
278
  def configurable_columns(self):
316
279
  selected_columns = [
@@ -325,7 +288,7 @@ class BaseTable(django_tables2.Table):
325
288
 
326
289
  @property
327
290
  def visible_columns(self):
328
- return [name for name in self.sequence if self.columns[name].visible and name not in self.exclude]
291
+ return [name for name in self.sequence if self.columns[name].visible]
329
292
 
330
293
  @property
331
294
  def order_by(self):
@@ -480,7 +443,7 @@ class ChoiceFieldColumn(django_tables2.Column):
480
443
  choices. The CSS class is derived by calling .get_FOO_class() on the row record.
481
444
  """
482
445
 
483
- def render(self, *, record, bound_column, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
446
+ def render(self, record, bound_column, value): # pylint: disable=arguments-differ
484
447
  if value:
485
448
  name = bound_column.name
486
449
  css_class = getattr(record, f"get_{name}_class")()
@@ -527,7 +490,6 @@ class LinkedCountColumn(django_tables2.Column):
527
490
  TODO: this currently does *not* support nested lookups via `__`. That may be solvable in the future.
528
491
  reverse_lookup (str, optional): The reverse lookup parameter to use to derive the count.
529
492
  If not specified, the first key in `url_params` will be implicitly used as the `reverse_lookup` value.
530
- distinct (bool, optional): Parameter passed through to `count_related()`.
531
493
  **kwargs (dict, optional): As the parent Column class.
532
494
 
533
495
  Examples:
@@ -552,37 +514,25 @@ class LinkedCountColumn(django_tables2.Column):
552
514
  # We'd like to do the below but this module isn't currently smart enough to build the right Prefetch()
553
515
  # for a nested lookup:
554
516
  # lookup="circuit_terminations__circuit",
555
- # For the count,
556
- # .annotate(circuit_count=count_related(Circuit, "circuit_terminations__cloud_network", distinct=True))
517
+ # For the count, .annotate(circuit_count=count_related(Circuit, "circuit_terminations__cloud_network"))
557
518
  reverse_lookup="circuit_terminations__cloud_network",
558
- distinct=True,
559
519
  verbose_name="Circuits",
560
520
  )
561
521
  ```
562
522
  """
563
523
 
564
524
  def __init__(
565
- self,
566
- viewname,
567
- *args,
568
- view_kwargs=None,
569
- url_params=None,
570
- lookup=None,
571
- reverse_lookup=None,
572
- distinct=False,
573
- default=None,
574
- **kwargs,
525
+ self, viewname, *args, view_kwargs=None, url_params=None, lookup=None, reverse_lookup=None, default=0, **kwargs
575
526
  ):
576
527
  self.viewname = viewname
577
528
  self.lookup = lookup
578
529
  self.view_kwargs = view_kwargs or {}
579
530
  self.url_params = url_params
580
531
  self.reverse_lookup = reverse_lookup or next(iter(url_params.keys()))
581
- self.distinct = distinct
582
532
  self.model = get_model_for_view_name(self.viewname)
583
533
  super().__init__(*args, default=default, **kwargs)
584
534
 
585
- def render(self, *, bound_column, record, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
535
+ def render(self, bound_column, record, value): # pylint: disable=arguments-differ
586
536
  related_record = None
587
537
  try:
588
538
  lookup = self.lookup or get_related_field_for_models(bound_column._table._meta.model, self.model).name
@@ -666,7 +616,7 @@ class ComputedFieldColumn(django_tables2.Column):
666
616
 
667
617
  super().__init__(*args, **kwargs)
668
618
 
669
- def render(self, *, record): # pylint: disable=arguments-differ # tables2 varies its kwargs
619
+ def render(self, record):
670
620
  return self.computedfield.render({"obj": record})
671
621
 
672
622
 
@@ -685,7 +635,7 @@ class CustomFieldColumn(django_tables2.Column):
685
635
 
686
636
  super().__init__(*args, **kwargs)
687
637
 
688
- def render(self, *, record, bound_column, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
638
+ def render(self, record, bound_column, value): # pylint: disable=arguments-differ
689
639
  if self.customfield.type == choices.CustomFieldTypeChoices.TYPE_BOOLEAN:
690
640
  template = helpers.render_boolean(value)
691
641
  elif self.customfield.type == choices.CustomFieldTypeChoices.TYPE_MULTISELECT:
@@ -716,7 +666,7 @@ class RelationshipColumn(django_tables2.Column):
716
666
  kwargs.setdefault("accessor", Accessor("associations"))
717
667
  super().__init__(orderable=False, *args, **kwargs)
718
668
 
719
- def render(self, *, record, value): # pylint: disable=arguments-differ # tables2 varies its kwargs
669
+ def render(self, record, value): # pylint: disable=arguments-differ
720
670
  # Filter the relationship associations by the relationship instance.
721
671
  # Since associations accessor returns all the relationship associations regardless of the relationship.
722
672
  value = [v for v in value if v.relationship == self.relationship]
nautobot/core/tasks.py CHANGED
@@ -49,7 +49,7 @@ def get_releases(pre_releases=False):
49
49
  cache.set(
50
50
  "nautobot.core.releases.get_latest_release",
51
51
  max(releases),
52
- config.get_settings_or_config("RELEASE_CHECK_TIMEOUT"),
52
+ config.get_settings_or_config("RELEASE_CHECK_TIMEOUT", fallback=24 * 3600),
53
53
  )
54
54
 
55
55
  # Since this is a Celery task, we can't return Version objects as they are not JSON serializable.
@@ -0,0 +1,7 @@
1
+ {% if link %}<a href="{{ link }}"{% else %}<button type="button"{% endif %}
2
+ class="btn btn-{{ color }}"
3
+ {% for key, value in attributes.items %}{{ key }}="{{ value }}" {% endfor %}
4
+ >
5
+ {% if icon %}<span class="mdi {{ icon }}" aria-hidden="true"></span>{% endif %}
6
+ {{ label }}
7
+ {% if link %}</a>{% else %}</button>{% endif %}
@@ -0,0 +1,20 @@
1
+ <div class="btn-group">
2
+ <button type="button" class="btn btn-{{ color }} dropdown-toggle" data-toggle="dropdown"
3
+ aria-haspopup="true" aria-expanded="false"
4
+ {% for key, value in attributes.items %}{{ key }}="{{ value }}" {% endfor %}
5
+ >
6
+ {% if icon %}<span class="mdi {{ icon }}" aria-hidden="true"></span>{% endif %}
7
+ {{ label }}
8
+ <span class="caret"></span>
9
+ </button>
10
+ <ul class="dropdown-menu">
11
+ {% for child in children %}
12
+ <li><a href="{{ child.link }}" class="text-{{ child.color }}"
13
+ {% for key, value in child.attributes.items %}{{ key }}="{{ value }}" {% endfor %}
14
+ >
15
+ {% if child.icon %}<span class="mdi {{ child.icon }}" aria-hidden="true"></span>{% endif %}
16
+ {{ child.label }}
17
+ </a></li>
18
+ {% endfor %}
19
+ </ul>
20
+ </div>
@@ -0,0 +1,19 @@
1
+ {% load ui_framework %}
2
+ {% load plugins %}
3
+
4
+ <div class="row">
5
+ <div class="col-md-12">
6
+ {% render_components full_width_panels %}
7
+ {% if include_plugin_content %}{% plugin_full_width_page object %}{% endif %}
8
+ </div>
9
+ </div>
10
+ <div class="row">
11
+ <div class="col-md-6">
12
+ {% render_components left_half_panels %}
13
+ {% if include_plugin_content %}{% plugin_left_page object %}{% endif %}
14
+ </div>
15
+ <div class="col-md-6">
16
+ {% render_components right_half_panels %}
17
+ {% if include_plugin_content %}{% plugin_right_page object %}{% endif %}
18
+ </div>
19
+ </div>
@@ -0,0 +1,19 @@
1
+ {% load ui_framework %}
2
+ {% load plugins %}
3
+
4
+ <div class="row">
5
+ <div class="col-md-6">
6
+ {% render_components left_half_panels %}
7
+ {% if include_plugin_content %}{% plugin_left_page object %}{% endif %}
8
+ </div>
9
+ <div class="col-md-6">
10
+ {% render_components right_half_panels %}
11
+ {% if include_plugin_content %}{% plugin_right_page object %}{% endif %}
12
+ </div>
13
+ </div>
14
+ <div class="row">
15
+ <div class="col-md-12">
16
+ {% render_components full_width_panels %}
17
+ {% if include_plugin_content %}{% plugin_full_width_page object %}{% endif %}
18
+ </div>
19
+ </div>
@@ -0,0 +1,27 @@
1
+ {% load helpers %}
2
+ <table class="table table-hover table-headings">
3
+ {% if data %}
4
+ {% if column_headers %}
5
+ <thead>
6
+ <tr>
7
+ {% for column_header in column_headers %}
8
+ <th>{{ column_header }}</th>
9
+ {% endfor %}
10
+ </tr>
11
+ </thead>
12
+ {% endif %}
13
+ <tbody>
14
+ {% for entry in data %}
15
+ <tr>
16
+ {% for column in columns %}
17
+ <td>{{ entry|get_item:column|placeholder }}</td>
18
+ {% endfor %}
19
+ </tr>
20
+ {% endfor %}
21
+ </tbody>
22
+ {% else %}
23
+ <tr>
24
+ <td colspan="{{ columns|length }}" class="text-center text-muted">&mdash; No data &mdash;</td>
25
+ </td>
26
+ {% endif %}
27
+ </table>
@@ -0,0 +1,4 @@
1
+ {% load render_table from django_tables2 %}
2
+ {% with table=body_content_table %}
3
+ {% render_table table 'inc/table.html' %}
4
+ {% endwith %}
@@ -0,0 +1,6 @@
1
+ {% load helpers %}
2
+ {% for tag in tags %}
3
+ {% tag tag list_url_name %}
4
+ {% empty %}
5
+ <span class="text-muted">No tags assigned</span>
6
+ {% endfor %}
@@ -0,0 +1,12 @@
1
+ {% load helpers %}
2
+ {% if render_as == 'json' %}
3
+ <pre>{{ value | render_json }}</pre>
4
+ {% elif render_as == 'yaml' %}
5
+ <pre>{{ value | render_yaml }}</pre>
6
+ {% elif render_as == 'markdown' %}
7
+ {{ value | render_markdown }}
8
+ {% elif render_as == 'code' %}
9
+ <pre>{{ value }}</pre>
10
+ {% else %}
11
+ {{ value }}
12
+ {% endif %}
@@ -0,0 +1,3 @@
1
+ <div class="panel-body"{% if body_id %} id="{{ body_id }}"{% endif %}>
2
+ {{ body_content }}
3
+ </div>
@@ -0,0 +1,3 @@
1
+ <table class="table table-hover panel-body attr-table"{% if body_id %} id="{{ body_id }}"{% endif %}>
2
+ {{ body_content }}
3
+ </table>
@@ -0,0 +1,3 @@
1
+ <div class="table-responsive"{% if body_id %} id="{{ body_id }}"{% endif %}>
2
+ {{ body_content }}
3
+ </div>
@@ -0,0 +1,20 @@
1
+ {% with request.path|add:"?tab=contacts"|urlencode as return_url %}
2
+ {% if perms.extras.change_contactassociation %}
3
+ <button type="submit" name="_edit" formaction="{% url 'extras:contactassociation_bulk_edit' %}?return_url={{return_url}}" class="btn btn-warning btn-xs">
4
+ <span class="mdi mdi-pencil" aria-hidden="true"></span> Edit
5
+ </button>
6
+ {% endif %}
7
+ {% if perms.extras.delete_contactassociation %}
8
+ <button type="submit" formaction="{% url 'extras:contactassociation_bulk_delete' %}?return_url={{return_url}}" class="btn btn-danger btn-xs">
9
+ <span class="mdi mdi-trash-can-outline" aria-hidden="true"></span> Delete
10
+ </button>
11
+ {% endif %}
12
+ {% if perms.extras.add_contactassociation %}
13
+ <div class="pull-right">
14
+ <a href="{% url 'extras:object_contact_team_assign' %}?return_url={{return_url}}&associated_object_id={{object.id}}&associated_object_type={{content_type.id}}" class="btn btn-primary btn-xs">
15
+ <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Contact
16
+ </a>
17
+ </div>
18
+ {% endif %}
19
+ <div class="clearfix"></div>
20
+ {% endwith %}
@@ -0,0 +1,14 @@
1
+ {% if body_content_table_list_url and more_queryset_count > 0 %}
2
+ <a href="{{ body_content_table_list_url }}">
3
+ <span class="mdi mdi-dots-horizontal" aria-hidden="true"></span> View {{ more_queryset_count }} more {{ body_content_table_verbose_name_plural }}
4
+ </a>
5
+ {% endif %}
6
+
7
+ {% if body_content_table_add_url %}
8
+ <div class="pull-right">
9
+ <a href="{{ body_content_table_add_url }}" class="btn btn-xs btn-primary">
10
+ <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add {{ body_content_table_verbose_name }}
11
+ </a>
12
+ </div>
13
+ <div class="clearfix"></div>
14
+ {% endif %}
@@ -0,0 +1,14 @@
1
+ <tr>
2
+ <td colspan="2">
3
+ <strong>
4
+ <!-- TODO: this is not very consistent with other button styling -->
5
+ <button type="button"
6
+ class="accordion-toggle mdi mdi-chevron-down"
7
+ name="grouping.{{ grouping }}"
8
+ data-toggle="collapse"
9
+ data-target=".collapseme-{{ body_id }}-{{ counter }}">
10
+ {{ grouping }}
11
+ </button>
12
+ </strong>
13
+ </td>
14
+ </tr>
@@ -0,0 +1,3 @@
1
+ {% load helpers %}
2
+
3
+ <strong>{{ body_content_table_verbose_name_plural|bettertitle }}</strong> {% if body_content_table_list_url %}<a href="{{ body_content_table_list_url }}" class="badge badge-primary">{{ body_content_table.rows|length }}</a>{% endif %}
@@ -0,0 +1,16 @@
1
+ <div class="panel panel-default">
2
+ {% if label.strip or header_extra_content.strip %}
3
+ <div class="panel-heading">
4
+ {% if label %}
5
+ <strong>{{ label }}</strong>
6
+ {% endif %}
7
+ {{ header_extra_content }}
8
+ </div>
9
+ {% endif %}
10
+ {{ body }}
11
+ {% if footer_content.strip %}
12
+ <div class="panel-footer">
13
+ {{ footer_content }}
14
+ </div>
15
+ {% endif %}
16
+ </div>
@@ -0,0 +1,8 @@
1
+ <div class="panel-body">
2
+ {% for url, value, title in stats.values %}
3
+ <div class="col-md-4 text-center">
4
+ <h2><a href="{% url url %}?{{ filter_name }}={{ object.pk }}" class="btn {% if value > 0 %}btn-primary{% else %}btn-default{% endif %} btn-lg">{{ value }}</a></h2>
5
+ <p>{{ title }}</p>
6
+ </div>
7
+ {% endfor %}
8
+ </div>
@@ -0,0 +1,3 @@
1
+ <div id="{{ tab_id }}" role="tabpanel" class="tab-pane {% if request.GET.tab == tab_id %}active{% else %}fade{% endif %}">
2
+ {{ tab_content }}
3
+ </div>
@@ -0,0 +1,5 @@
1
+ <li role="presentation"{% if request.GET.tab == tab_id %} class="active"{% endif %}>
2
+ <a href="{{ object.get_absolute_url }}#{{ tab_id }}" onclick="switch_tab(this.href)" aria-controls="{{ tab_id }}" role="tab" data-toggle="tab">
3
+ {{ label }}
4
+ </a>
5
+ </li>
@@ -0,0 +1,3 @@
1
+ <li role="presentation"{% if request.GET.tab == tab_id %} class="active"{% endif %}>
2
+ <a href="{{ url }}?tab={{ tab_id }}">{{ label }}</a>
3
+ </li>
@@ -8,6 +8,7 @@
8
8
  {% load plugins %}
9
9
  {% load static %}
10
10
  {% load tz %}
11
+ {% load ui_framework %}
11
12
 
12
13
  {% block header %}
13
14
  <div class="row noprint">
@@ -38,13 +39,14 @@
38
39
  </div>
39
40
  </form>
40
41
  </div>
41
- {% endif%}
42
+ {% endif %}
42
43
  {% endwith %}
43
44
  </div>
44
45
 
45
46
  <div class="pull-right noprint">
46
47
  {% block buttons %}
47
48
  {% plugin_buttons object %}
49
+ {% render_detail_view_extra_buttons %}
48
50
  {% block extra_buttons %}{% endblock extra_buttons %}
49
51
  {% consolidate_detail_view_action_buttons %}
50
52
  {% endblock buttons %}
@@ -69,6 +71,9 @@
69
71
 
70
72
  <ul id="tabs" class="nav nav-tabs">
71
73
  {% block nav_tabs %}
74
+ {% if object_detail_content %}
75
+ {% render_tabs_labels object_detail_content.tabs %}
76
+ {% else %}
72
77
  <li role="presentation"{% if active_tab == "main" or request.GET.tab == "main" %} class="active"{% endif %}>
73
78
  <a href="{{ object.get_absolute_url }}#main" onclick="switch_tab(this.href)" aria-controls="main" role="tab" data-toggle="tab">
74
79
  {{ verbose_name|bettertitle }}
@@ -86,14 +91,6 @@
86
91
  </a>
87
92
  </li>
88
93
  {% endif %}
89
- {% block extra_nav_tabs %}{% endblock extra_nav_tabs %}
90
- {% if perms.extras.view_note %}
91
- {% if active_tab != 'notes' and object.get_notes_url or active_tab == 'notes' %}
92
- <li role="presentation"{% if active_tab == 'notes' %} class="active"{% endif %}>
93
- <a href="{{ object.get_notes_url }}">Notes</a>
94
- </li>
95
- {% endif %}
96
- {% endif %}
97
94
  {% if object.is_dynamic_group_associable_model and perms.extras.view_dynamicgroup %}
98
95
  {% with object.dynamic_groups.count as dg_count %}
99
96
  {% if dg_count %}
@@ -116,6 +113,14 @@
116
113
  {% endif %}
117
114
  {% endwith %}
118
115
  {% endif %}
116
+ {% endif %}
117
+ {% if perms.extras.view_note %}
118
+ {% if active_tab != 'notes' and object.get_notes_url or active_tab == 'notes' %}
119
+ <li role="presentation"{% if active_tab == 'notes' %} class="active"{% endif %}>
120
+ <a href="{{ object.get_notes_url }}">Notes</a>
121
+ </li>
122
+ {% endif %}
123
+ {% endif %}
119
124
  {% if perms.extras.view_objectchange %}
120
125
  {% if active_tab != 'changelog' and object.get_changelog_url or active_tab == 'changelog' %}
121
126
  <li role="presentation"{% if active_tab == 'changelog' %} class="active"{% endif %}>
@@ -123,6 +128,7 @@
123
128
  </li>
124
129
  {% endif %}
125
130
  {% endif %}
131
+ {% block extra_nav_tabs %}{% endblock extra_nav_tabs %}
126
132
  {% endblock nav_tabs %}
127
133
  {% plugin_object_detail_tabs object %}
128
134
  </ul>
@@ -130,11 +136,14 @@
130
136
 
131
137
  {% block content %}
132
138
  <div class="tab-content">
139
+ {% if object_detail_content %}
140
+ {% render_components object_detail_content.tabs %}
141
+ {% else %}
133
142
  <div id="main" role="tabpanel" class="tab-pane {% if active_tab == "main" or request.GET.tab == "main" %}active{% else %}fade{% endif %}">
134
143
  <div class="row">
135
144
  <div class="col-md-6">
136
145
  {% block content_left_page %}{% endblock content_left_page %}
137
- {% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic computed_fields=object.get_computed_fields_grouping_basic computed_fields_advanced_ui=False %}
146
+ {% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic custom_fields_advanced_ui=False computed_fields=object.get_computed_fields_grouping_basic computed_fields_advanced_ui=False %}
138
147
  {% include 'inc/relationships_panel.html' %}
139
148
  {% include 'extras/inc/tags_panel.html' %}
140
149
  {% plugin_left_page object %}
@@ -267,6 +276,8 @@
267
276
  </div>
268
277
  </div>
269
278
  {% endif %}
279
+ {% endif %}
280
+ {% plugin_object_detail_tab_content object %}
270
281
  {% block extra_tab_content %}{% endblock extra_tab_content %}
271
282
  </div>
272
283
  {% endblock content %}
@@ -325,28 +336,28 @@
325
336
  $(`#tabs a[href="{{ object.get_absolute_url }}#${event.state.id}"]`).tab('show');
326
337
  }
327
338
  // Toggle v -. >
328
- $("#accordion .accordion-toggle").click(function () {
339
+ $(".accordion-toggle").click(function () {
329
340
  $(this).toggleClass("mdi-chevron-down mdi-chevron-right");
330
341
  });
331
342
  // Dynamically collapse/expand all when clicking the "Collapse All" button, and then update the button text.
332
- $('#accordion-toggle-all').click(function () {
343
+ $('.accordion-toggle-all').click(function () {
333
344
 
334
345
  if ($(this).data("lastState") === null || $(this).data("lastState") === 1) {
335
- $('.collapse').collapse('show');
346
+ $($(this).data("target") + ' .collapse').collapse('show');
336
347
  $(this).data("lastState", 0);
337
348
 
338
- $("#accordion .accordion-toggle").addClass("mdi-chevron-down").removeClass("mdi-chevron-right");
349
+ $($(this).data("target") + " .accordion-toggle").addClass("mdi-chevron-down").removeClass("mdi-chevron-right");
339
350
 
340
351
  $(this).text("Collapse All");
341
352
  }
342
353
  else {
343
- $('[class^=collapseme]').removeData('bs.collapse').collapse({parent: false, toggle: false})
354
+ $($(this).data("target") + ' [class^=collapseme]').removeData('bs.collapse').collapse({parent: false, toggle: false})
344
355
  .collapse('hide')
345
356
  .removeData('bs.collapse')
346
- .collapse({parent: '#accordion', toggle: false});
357
+ .collapse({parent: $(this).data("target"), toggle: false});
347
358
 
348
359
  $(this).data("lastState", 1);
349
- $("#accordion .accordion-toggle").addClass("mdi-chevron-right").removeClass("mdi-chevron-down");
360
+ $($(this).data("target") + " .accordion-toggle").addClass("mdi-chevron-right").removeClass("mdi-chevron-down");
350
361
 
351
362
  $(this).text("Expand All");
352
363
  }
@@ -1,16 +1,13 @@
1
1
  {% load helpers %}
2
2
  {% if computed_fields %}
3
- <style>
4
- .accordion-toggle {
5
- font-size: 14px;
6
- }
7
- </style>
8
3
  <div class="panel panel-default">
9
4
  <div class="panel-heading">
10
5
  <strong>Computed Fields</strong>
11
- <button type="button" class="btn-xs btn-primary pull-right" id="accordion-toggle-all">Collapse All</button>
6
+ <button type="button"
7
+ class="btn-xs btn-primary pull-right accordion-toggle-all"
8
+ data-target="#computed_fields_accordion_{{ advanced_ui }}">Collapse All</button>
12
9
  </div>
13
- <table id="accordion" class="table table-hover panel-body attr-table">
10
+ <table id="computed_fields_accordion_{{ advanced_ui }}" class="table table-hover panel-body attr-table">
14
11
  {% for grouping, fields in computed_fields.items %}
15
12
  {% with forloop.counter0 as count %}
16
13
  {% if grouping != "" %}
@@ -1,3 +1,3 @@
1
1
  {% load helpers %}
2
- {% include 'inc/custom_fields/panel_data.html' %}
3
- {% include 'inc/computed_fields/panel_data.html' with advanced_ui=computed_fields_advanced_ui %}
2
+ {% include 'inc/custom_fields/panel_data.html' with advanced_ui=custom_fields_advanced_ui %}
3
+ {% include 'inc/computed_fields/panel_data.html' with advanced_ui=computed_fields_advanced_ui %}
@@ -1,16 +1,13 @@
1
1
  {% load helpers %}
2
2
  {% if custom_fields %}
3
- <style>
4
- .accordion-toggle {
5
- font-size: 14px;
6
- }
7
- </style>
8
3
  <div class="panel panel-default">
9
4
  <div class="panel-heading">
10
5
  <strong>Custom Fields</strong>
11
- <button type="button" class="btn-xs btn-primary pull-right" id="accordion-toggle-all">Collapse All</button>
6
+ <button type="button"
7
+ class="btn-xs btn-primary pull-right accordion-toggle-all"
8
+ data-target="#custom_fields_accordion_{{ advanced_ui }}">Collapse All</button>
12
9
  </div>
13
- <table id="accordion" class="table table-hover panel-body attr-table">
10
+ <table id="custom_fields_accordion_{{ advanced_ui }}" class="table table-hover panel-body attr-table">
14
11
  {% for grouping, fields in custom_fields.items %}
15
12
  {% with forloop.counter0 as count %}
16
13
  {% if grouping != "" %}