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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nautobot might be problematic. Click here for more details.

Files changed (420) hide show
  1. nautobot/apps/choices.py +0 -2
  2. nautobot/apps/filters.py +7 -9
  3. nautobot/apps/models.py +2 -2
  4. nautobot/apps/ui.py +9 -1
  5. nautobot/circuits/filters.py +3 -2
  6. nautobot/circuits/navigation.py +3 -2
  7. nautobot/circuits/templates/circuits/circuit.html +1 -1
  8. nautobot/circuits/templates/circuits/circuit_create.html +3 -3
  9. nautobot/circuits/templates/circuits/circuittermination.html +1 -1
  10. nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
  11. nautobot/circuits/templates/circuits/circuittype.html +1 -1
  12. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
  13. nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
  14. nautobot/circuits/templates/circuits/providernetwork.html +1 -1
  15. nautobot/circuits/tests/integration/test_circuit.py +10 -13
  16. nautobot/cloud/filters.py +1 -1
  17. nautobot/cloud/navigation.py +3 -2
  18. nautobot/core/api/schema.py +1 -1
  19. nautobot/core/api/serializers.py +6 -1
  20. nautobot/core/api/urls.py +1 -0
  21. nautobot/core/api/views.py +8 -0
  22. nautobot/core/apps/__init__.py +11 -10
  23. nautobot/core/celery/__init__.py +3 -5
  24. nautobot/core/checks.py +46 -0
  25. nautobot/core/cli/bootstrap_v3_to_v5.py +70 -1
  26. nautobot/core/cli/migrate_deprecated_templates.py +200 -0
  27. nautobot/core/constants.py +3 -0
  28. nautobot/core/context_processors.py +9 -1
  29. nautobot/core/forms/forms.py +1 -1
  30. nautobot/core/jobs/__init__.py +6 -3
  31. nautobot/core/jobs/groups.py +31 -1
  32. nautobot/core/management/commands/generate_test_data.py +28 -9
  33. nautobot/core/models/generics.py +9 -1
  34. nautobot/core/models/tree_queries.py +10 -5
  35. nautobot/core/settings.py +18 -12
  36. nautobot/core/settings.yaml +13 -7
  37. nautobot/core/signals.py +12 -1
  38. nautobot/core/tables.py +13 -6
  39. nautobot/core/templates/40x.html +1 -1
  40. nautobot/core/templates/500.html +2 -2
  41. nautobot/core/templates/admin/config/config.html +12 -12
  42. nautobot/core/templates/admin/index.html +3 -3
  43. nautobot/core/templates/buttons/export.html +1 -1
  44. nautobot/core/templates/components/button/dropdown.html +5 -3
  45. nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
  46. nautobot/core/templates/components/panel/panel.html +3 -3
  47. nautobot/core/templates/components/tab/content_wrapper.html +2 -3
  48. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
  49. nautobot/core/templates/echarts/echarts.html +1 -1
  50. nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
  51. nautobot/core/templates/generic/object_bulk_create.html +4 -3
  52. nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
  53. nautobot/core/templates/generic/object_bulk_remove.html +2 -2
  54. nautobot/core/templates/generic/object_bulk_update.html +5 -4
  55. nautobot/core/templates/generic/object_create.html +5 -4
  56. nautobot/core/templates/generic/object_import.html +2 -1
  57. nautobot/core/templates/generic/object_list.html +12 -4
  58. nautobot/core/templates/generic/object_notes.html +5 -3
  59. nautobot/core/templates/generic/object_retrieve.html +2 -3
  60. nautobot/core/templates/graphene/graphiql.html +7 -7
  61. nautobot/core/templates/home.html +1 -1
  62. nautobot/core/templates/import_success.html +2 -1
  63. nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
  64. nautobot/core/templates/inc/created_updated.html +7 -3
  65. nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
  66. nautobot/core/templates/inc/form_static_field.html +6 -0
  67. nautobot/core/templates/inc/header.html +1 -1
  68. nautobot/core/templates/inc/image_attachments.html +2 -1
  69. nautobot/core/templates/inc/nav_menu.html +2 -1
  70. nautobot/core/templates/inc/search_panel.html +4 -4
  71. nautobot/core/templates/login.html +4 -2
  72. nautobot/core/templates/nautobot_config.py.j2 +6 -5
  73. nautobot/core/templates/redoc_ui.html +7 -0
  74. nautobot/core/templates/search.html +1 -1
  75. nautobot/core/templates/swagger_ui.html +17 -3
  76. nautobot/core/templates/system_jobs/import_objects.html +1 -2
  77. nautobot/core/templates/utilities/confirmation_form.html +2 -2
  78. nautobot/core/templates/utilities/obj_table.html +10 -2
  79. nautobot/core/templates/utilities/render_field.html +7 -7
  80. nautobot/core/templates/utilities/render_jinja2.html +2 -2
  81. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +4 -4
  82. nautobot/core/templates/utilities/theme_preview.html +16 -3
  83. nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
  84. nautobot/core/templatetags/helpers.py +52 -6
  85. nautobot/core/testing/api.py +68 -9
  86. nautobot/core/testing/filters.py +0 -23
  87. nautobot/core/testing/integration.py +23 -10
  88. nautobot/core/testing/mixins.py +2 -0
  89. nautobot/core/testing/views.py +4 -0
  90. nautobot/core/tests/integration/test_app_home.py +34 -30
  91. nautobot/core/tests/integration/test_app_navbar.py +3 -0
  92. nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
  93. nautobot/core/tests/runner.py +9 -1
  94. nautobot/core/tests/test_api.py +5 -3
  95. nautobot/core/tests/test_breadcrumbs.py +6 -7
  96. nautobot/core/tests/test_checks.py +28 -0
  97. nautobot/core/tests/test_cli.py +40 -0
  98. nautobot/core/tests/test_config.py +2 -1
  99. nautobot/core/tests/test_forms.py +55 -13
  100. nautobot/core/tests/test_jobs.py +75 -1
  101. nautobot/core/tests/test_nautobot_server.py +2 -0
  102. nautobot/core/tests/test_navigations.py +76 -1
  103. nautobot/core/tests/test_patch_social_django.py +42 -0
  104. nautobot/core/tests/test_tables.py +3 -1
  105. nautobot/core/tests/test_templatetags_helpers.py +53 -13
  106. nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
  107. nautobot/core/tests/test_tree_queries.py +14 -1
  108. nautobot/core/tests/test_ui.py +1 -1
  109. nautobot/core/tests/test_utils.py +31 -4
  110. nautobot/core/tests/test_views.py +159 -31
  111. nautobot/core/ui/breadcrumbs.py +2 -12
  112. nautobot/core/ui/choices.py +142 -10
  113. nautobot/core/ui/constants.py +76 -12
  114. nautobot/core/ui/object_detail.py +92 -12
  115. nautobot/core/urls.py +12 -1
  116. nautobot/core/utils/cache.py +2 -1
  117. nautobot/core/utils/filtering.py +17 -17
  118. nautobot/core/utils/lookup.py +3 -8
  119. nautobot/core/utils/module_loading.py +21 -0
  120. nautobot/core/utils/patch_social_django.py +128 -0
  121. nautobot/core/views/__init__.py +38 -1
  122. nautobot/core/views/generic.py +3 -3
  123. nautobot/core/views/mixins.py +15 -3
  124. nautobot/core/views/renderers.py +2 -0
  125. nautobot/core/views/viewsets.py +2 -1
  126. nautobot/data_validation/apps.py +1 -5
  127. nautobot/data_validation/custom_validators.py +4 -4
  128. nautobot/data_validation/filters.py +1 -1
  129. nautobot/data_validation/forms.py +40 -0
  130. nautobot/data_validation/migrations/0001_initial.py +0 -7
  131. nautobot/data_validation/migrations/0002_data_migration_from_app.py +0 -12
  132. nautobot/data_validation/models.py +16 -7
  133. nautobot/data_validation/navigation.py +8 -1
  134. nautobot/data_validation/tables.py +12 -5
  135. nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
  136. nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
  137. nautobot/data_validation/tests/__init__.py +2 -2
  138. nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
  139. nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
  140. nautobot/data_validation/tests/test_filters.py +8 -6
  141. nautobot/data_validation/tests/test_models.py +15 -0
  142. nautobot/data_validation/tests/test_views.py +190 -32
  143. nautobot/data_validation/urls.py +2 -5
  144. nautobot/data_validation/views.py +73 -40
  145. nautobot/dcim/api/serializers.py +0 -13
  146. nautobot/dcim/apps.py +4 -0
  147. nautobot/dcim/choices.py +16 -0
  148. nautobot/dcim/custom_validators.py +84 -0
  149. nautobot/dcim/filter_mixins.py +353 -4
  150. nautobot/dcim/{filters/__init__.py → filters.py} +2 -35
  151. nautobot/dcim/forms.py +1 -1
  152. nautobot/dcim/migrations/0078_remove_device_location_tenant_name_uniqueness.py +16 -0
  153. nautobot/dcim/migrations/0079_device_name_data_migration.py +59 -0
  154. nautobot/dcim/models/device_components.py +81 -68
  155. nautobot/dcim/models/devices.py +13 -16
  156. nautobot/dcim/navigation.py +7 -6
  157. nautobot/dcim/tables/devices.py +3 -0
  158. nautobot/dcim/tables/template_code.py +14 -14
  159. nautobot/dcim/templates/dcim/cable.html +2 -61
  160. nautobot/dcim/templates/dcim/cable_connect.html +28 -112
  161. nautobot/dcim/templates/dcim/cable_edit.html +2 -5
  162. nautobot/dcim/templates/dcim/cable_retrieve.html +61 -0
  163. nautobot/dcim/templates/dcim/cable_trace.html +1 -3
  164. nautobot/dcim/templates/dcim/cable_update.html +5 -0
  165. nautobot/dcim/templates/dcim/consoleport.html +6 -5
  166. nautobot/dcim/templates/dcim/consoleserverport.html +6 -5
  167. nautobot/dcim/templates/dcim/device/config.html +2 -2
  168. nautobot/dcim/templates/dcim/device/consoleports.html +1 -1
  169. nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -1
  170. nautobot/dcim/templates/dcim/device/devicebays.html +1 -1
  171. nautobot/dcim/templates/dcim/device/frontports.html +1 -1
  172. nautobot/dcim/templates/dcim/device/interfaces.html +1 -1
  173. nautobot/dcim/templates/dcim/device/inventory.html +1 -1
  174. nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
  175. nautobot/dcim/templates/dcim/device/modulebays.html +1 -1
  176. nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -1
  177. nautobot/dcim/templates/dcim/device/powerports.html +1 -1
  178. nautobot/dcim/templates/dcim/device/rearports.html +1 -1
  179. nautobot/dcim/templates/dcim/device/status.html +8 -8
  180. nautobot/dcim/templates/dcim/device/wireless.html +1 -1
  181. nautobot/dcim/templates/dcim/device.html +1 -1
  182. nautobot/dcim/templates/dcim/device_component_add.html +2 -2
  183. nautobot/dcim/templates/dcim/device_create.html +5 -3
  184. nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
  185. nautobot/dcim/templates/dcim/device_list.html +73 -10
  186. nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
  187. nautobot/dcim/templates/dcim/devicetype.html +1 -1
  188. nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
  189. nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
  190. nautobot/dcim/templates/dcim/frontport.html +9 -8
  191. nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
  192. nautobot/dcim/templates/dcim/interface.html +26 -6
  193. nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
  194. nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
  195. nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
  196. nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
  197. nautobot/dcim/templates/dcim/location_retrieve.html +1 -242
  198. nautobot/dcim/templates/dcim/module/base.html +49 -9
  199. nautobot/dcim/templates/dcim/module_list.html +57 -8
  200. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
  201. nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
  202. nautobot/dcim/templates/dcim/platform_create.html +1 -1
  203. nautobot/dcim/templates/dcim/powerfeed.html +1 -1
  204. nautobot/dcim/templates/dcim/powerpanel.html +1 -1
  205. nautobot/dcim/templates/dcim/powerport.html +5 -4
  206. nautobot/dcim/templates/dcim/rack_elevation_list.html +16 -4
  207. nautobot/dcim/templates/dcim/rack_retrieve.html +33 -15
  208. nautobot/dcim/templates/dcim/rearport.html +7 -6
  209. nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
  210. nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
  211. nautobot/dcim/templates/dcim/virtualchassis_update.html +14 -6
  212. nautobot/dcim/tests/integration/test_controller.py +1 -0
  213. nautobot/dcim/tests/test_api.py +8 -0
  214. nautobot/dcim/tests/test_custom_validators.py +229 -0
  215. nautobot/dcim/tests/test_filters.py +12 -6
  216. nautobot/dcim/tests/test_models.py +63 -4
  217. nautobot/dcim/tests/test_views.py +63 -22
  218. nautobot/dcim/urls.py +64 -21
  219. nautobot/dcim/utils.py +3 -3
  220. nautobot/dcim/views.py +547 -273
  221. nautobot/extras/api/views.py +9 -1
  222. nautobot/extras/choices.py +2 -13
  223. nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
  224. nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
  225. nautobot/extras/{filters/__init__.py → filters.py} +14 -46
  226. nautobot/extras/forms/forms.py +5 -13
  227. nautobot/extras/forms/mixins.py +0 -41
  228. nautobot/extras/management/__init__.py +9 -0
  229. nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
  230. nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
  231. nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
  232. nautobot/extras/models/__init__.py +1 -2
  233. nautobot/extras/models/approvals.py +22 -13
  234. nautobot/extras/models/contacts.py +2 -0
  235. nautobot/extras/models/groups.py +44 -5
  236. nautobot/extras/models/jobs.py +59 -1
  237. nautobot/extras/models/mixins.py +28 -0
  238. nautobot/extras/models/models.py +13 -0
  239. nautobot/extras/models/secrets.py +1 -0
  240. nautobot/extras/models/statuses.py +0 -15
  241. nautobot/extras/navigation.py +13 -9
  242. nautobot/extras/plugins/__init__.py +33 -55
  243. nautobot/extras/plugins/tables.py +3 -3
  244. nautobot/extras/plugins/urls.py +2 -21
  245. nautobot/extras/plugins/utils.py +1 -33
  246. nautobot/extras/plugins/views.py +0 -4
  247. nautobot/extras/signals.py +20 -19
  248. nautobot/extras/tables.py +52 -68
  249. nautobot/extras/templates/extras/approval_dashboard.html +7 -5
  250. nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
  251. nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
  252. nautobot/extras/templates/extras/computedfield.html +1 -1
  253. nautobot/extras/templates/extras/configcontext.html +1 -1
  254. nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
  255. nautobot/extras/templates/extras/customfield.html +1 -1
  256. nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
  257. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  258. nautobot/extras/templates/extras/gitrepository_result.html +0 -2
  259. nautobot/extras/templates/extras/graphqlquery_retrieve.html +1 -96
  260. nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
  261. nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
  262. nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
  263. nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
  264. nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
  265. nautobot/extras/templates/extras/inc/json_format.html +10 -3
  266. nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
  267. nautobot/extras/templates/extras/job.html +29 -12
  268. nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
  269. nautobot/extras/templates/extras/job_edit.html +52 -46
  270. nautobot/extras/templates/extras/job_list.html +29 -25
  271. nautobot/extras/templates/extras/marketplace.html +5 -9
  272. nautobot/extras/templates/extras/object_configcontext.html +1 -1
  273. nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
  274. nautobot/extras/templates/extras/objectchange_retrieve.html +19 -37
  275. nautobot/extras/templates/extras/plugin_detail.html +26 -21
  276. nautobot/extras/templates/extras/plugins_list.html +16 -26
  277. nautobot/extras/templates/extras/role_retrieve.html +64 -0
  278. nautobot/extras/templates/extras/scheduledjob.html +4 -2
  279. nautobot/extras/templates/extras/secretsgroup.html +1 -1
  280. nautobot/extras/templates/extras/tag.html +1 -1
  281. nautobot/extras/templatetags/custom_links.py +12 -12
  282. nautobot/extras/templatetags/job_buttons.py +14 -12
  283. nautobot/extras/test_jobs/invalid_import.py +9 -0
  284. nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
  285. nautobot/extras/test_jobs/missing_import.py +11 -0
  286. nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
  287. nautobot/extras/tests/integration/test_customfields.py +8 -7
  288. nautobot/extras/tests/integration/test_dynamicgroups.py +5 -1
  289. nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
  290. nautobot/extras/tests/integration/test_plugins.py +18 -6
  291. nautobot/extras/tests/test_api.py +27 -18
  292. nautobot/extras/tests/test_approvals.py +38 -38
  293. nautobot/extras/tests/test_changelog.py +35 -3
  294. nautobot/extras/tests/test_customfields.py +22 -13
  295. nautobot/extras/tests/test_customfields_filters.py +479 -0
  296. nautobot/extras/tests/test_dynamicgroups.py +39 -1
  297. nautobot/extras/tests/test_filters.py +21 -19
  298. nautobot/extras/tests/test_forms.py +18 -21
  299. nautobot/extras/tests/test_jobs.py +25 -4
  300. nautobot/extras/tests/test_migrations.py +1 -0
  301. nautobot/extras/tests/test_models.py +13 -31
  302. nautobot/extras/tests/test_plugins.py +36 -10
  303. nautobot/extras/tests/test_views.py +31 -30
  304. nautobot/extras/views.py +81 -19
  305. nautobot/ipam/factory.py +7 -0
  306. nautobot/ipam/filter_mixins.py +38 -0
  307. nautobot/ipam/filters.py +27 -38
  308. nautobot/ipam/formfields.py +1 -1
  309. nautobot/ipam/forms.py +6 -3
  310. nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
  311. nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
  312. nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
  313. nautobot/ipam/models.py +29 -2
  314. nautobot/ipam/navigation.py +3 -2
  315. nautobot/ipam/signals.py +71 -0
  316. nautobot/ipam/tables.py +13 -6
  317. nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
  318. nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
  319. nautobot/ipam/templates/ipam/ipaddress.html +14 -0
  320. nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
  321. nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
  322. nautobot/ipam/templates/ipam/namespace_update.html +15 -0
  323. nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
  324. nautobot/ipam/templates/ipam/prefix_list.html +14 -13
  325. nautobot/ipam/templates/ipam/service.html +1 -1
  326. nautobot/ipam/templates/ipam/vlan.html +1 -1
  327. nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
  328. nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
  329. nautobot/ipam/tests/migration/test_migrations.py +89 -0
  330. nautobot/ipam/tests/test_api.py +13 -6
  331. nautobot/ipam/tests/test_filters.py +10 -0
  332. nautobot/ipam/tests/test_forms.py +1 -1
  333. nautobot/ipam/tests/test_models.py +43 -1
  334. nautobot/ipam/tests/test_tables.py +1 -2
  335. nautobot/ipam/tests/test_utils.py +1 -1
  336. nautobot/ipam/tests/test_views.py +13 -14
  337. nautobot/ipam/ui.py +0 -17
  338. nautobot/ipam/utils/migrations.py +16 -2
  339. nautobot/ipam/utils/testing.py +9 -3
  340. nautobot/ipam/views.py +46 -6
  341. nautobot/project-static/dist/css/nautobot.css +1 -1
  342. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  343. nautobot/project-static/dist/js/nautobot.js +1 -1
  344. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  345. nautobot/project-static/js/cabletrace.js +1 -1
  346. nautobot/project-static/js/interface_filtering.js +20 -16
  347. nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
  348. nautobot/project-static/nautobot-icons/cloud.svg +1 -1
  349. nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
  350. nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
  351. nautobot/project-static/nautobot-icons/elements.svg +1 -1
  352. nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
  353. nautobot/project-static/nautobot-icons/hammer.svg +1 -1
  354. nautobot/project-static/nautobot-icons/organization.svg +3 -0
  355. nautobot/project-static/nautobot-icons/secrets.svg +1 -1
  356. nautobot/project-static/nautobot-icons/security.svg +3 -0
  357. nautobot/project-static/nautobot-icons/server.svg +1 -1
  358. nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
  359. nautobot/project-static/nautobot-icons/star.svg +1 -1
  360. nautobot/tenancy/api/serializers.py +1 -0
  361. nautobot/tenancy/api/views.py +2 -1
  362. nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
  363. nautobot/tenancy/navigation.py +3 -1
  364. nautobot/tenancy/tests/test_filters.py +0 -2
  365. nautobot/tenancy/views.py +2 -1
  366. nautobot/ui/src/js/collapse.js +3 -3
  367. nautobot/ui/src/js/nautobot.js +16 -0
  368. nautobot/ui/src/scss/colors.scss +1 -1
  369. nautobot/ui/src/scss/nautobot.scss +61 -28
  370. nautobot/users/templates/users/profile.html +45 -12
  371. nautobot/users/templates/users/sessionkey_delete.html +1 -1
  372. nautobot/users/tests/test_api.py +4 -0
  373. nautobot/users/views.py +4 -2
  374. nautobot/virtualization/models.py +1 -68
  375. nautobot/virtualization/navigation.py +3 -2
  376. nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
  377. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  378. nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
  379. nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
  380. nautobot/virtualization/tests/test_api.py +3 -0
  381. nautobot/virtualization/tests/test_models.py +44 -4
  382. nautobot/vpn/__init__.py +0 -0
  383. nautobot/vpn/api/serializers.py +113 -0
  384. nautobot/vpn/api/urls.py +19 -0
  385. nautobot/vpn/api/views.py +70 -0
  386. nautobot/vpn/apps.py +8 -0
  387. nautobot/vpn/choices.py +171 -0
  388. nautobot/vpn/factory.py +209 -0
  389. nautobot/vpn/filters.py +233 -0
  390. nautobot/vpn/forms.py +486 -0
  391. nautobot/vpn/homepage.py +19 -0
  392. nautobot/vpn/migrations/0001_initial.py +541 -0
  393. nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
  394. nautobot/vpn/migrations/__init__.py +0 -0
  395. nautobot/vpn/models.py +527 -0
  396. nautobot/vpn/navigation.py +98 -0
  397. nautobot/vpn/tables.py +380 -0
  398. nautobot/vpn/templates/vpn/vpnprofile.html +2 -0
  399. nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
  400. nautobot/vpn/tests/__init__.py +0 -0
  401. nautobot/vpn/tests/test_api.py +341 -0
  402. nautobot/vpn/tests/test_filters.py +139 -0
  403. nautobot/vpn/tests/test_forms.py +294 -0
  404. nautobot/vpn/tests/test_models.py +97 -0
  405. nautobot/vpn/tests/test_views.py +281 -0
  406. nautobot/vpn/urls.py +16 -0
  407. nautobot/vpn/views.py +437 -0
  408. nautobot/wireless/navigation.py +3 -2
  409. nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
  410. nautobot/wireless/tests/test_api.py +1 -1
  411. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/METADATA +14 -14
  412. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/RECORD +417 -366
  413. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/entry_points.txt +1 -0
  414. nautobot/data_validation/template_content.py +0 -42
  415. nautobot/dcim/filters/mixins.py +0 -354
  416. nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
  417. /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
  418. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/LICENSE.txt +0 -0
  419. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/NOTICE +0 -0
  420. {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/WHEEL +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"js/nautobot.js","mappings":"uBAAIA,E,4ICcG,MCdDC,EAAkB,eAClBC,EAA4B,yBAE5BC,EAAiB,cCFjBC,EAAoB,iBAQpBC,EAAe,CAACC,EAAQC,KAC5B,IAAKD,EACH,OAGFA,EAAOE,UAAUC,OAAOL,EAAmBG,GAE3C,MAAMG,EAASJ,EAAOE,UAAUG,SAASP,GAEzCE,EAAOM,aAAa,cAAeF,EAAS,QAAU,QAEtD,MAAMG,EAAgB,IAAIC,SAASC,iBAAiB,8CAA8CT,EAAOU,SASzG,GARAH,EAAcI,SAASC,GAAiBA,EAAaN,aAAa,gBAAiBF,EAAS,OAAS,WAQjGA,EAGF,IADoBI,SAASK,uBAAuBf,IAEjDgB,QAAQC,GAAeA,IAAef,IACtCW,SAASI,GAAehB,EAAagB,GAAY,KAEpD,MACE,IAAIC,EAAsB,IAG1BC,OAAOC,uBAAsB,SAASC,IACmC,YAA/CF,OAAOG,iBAAiBpB,GAAQqB,WAGtDrB,EAAOsB,QACEN,EAAsB,IAC/BA,GAAuB,EACvBC,OAAOC,sBAAsBC,GAEjC,GACD,EAdD,QAeK,GAAInB,EAAOK,SAASG,SAASe,eAAgB,CAClD,MAAMC,EAAoBjB,EAAc,IAAMC,SAASiB,cAAc,QACrED,GAAmBF,MAAM,CAAEI,eAAe,GAC5C,CAEA,MAAMC,EAAQvB,EAAS,mBAAqB,mBAC5CJ,EAAO4B,cAAc,IAAIC,YAAYF,EAAO,CAAEG,SAAS,EAAMC,YAAY,IAAQ,ECzD7EC,EAAsB,eA4CfC,EAAaC,IACxB,MAAMC,OAAwBC,IAAVF,EAAsBjB,OAAOoB,SAASH,MAAQA,OAE9CE,IAAhBD,GACFlB,OAAOqB,gBAAgBC,QAAQP,EAAqBQ,KAAKC,UAAUN,GACrE,ECnCWO,EAAgB,CAACC,EAAKC,EAAa,CAAC,KAAMC,KACrD,MAAMC,EAAUtC,SAASkC,cAAcC,GAUvC,OARAI,OAAOC,QAAQJ,GAAYjC,SAAQ,EAAEsC,EAAWC,KAC9CJ,EAAQxC,aAA2B,cAAd2C,EAA4B,QAAUA,EAAWC,KAGxEL,EAASlC,SAASwC,GACC,iBAAVA,EAAqBL,EAAQM,mBAAmB,YAAaD,GAASL,EAAQO,YAAYF,KAG5FL,CAAO,EAYHQ,EAAuB,CAACR,KAAYS,IAC/C,IAAIT,EAAQ5C,UAAU8C,WACnBlC,QAAO,EAAE,CAAE0C,MAAgBD,EAAOE,SAASD,KAC3C7C,SAAQ,EAAE,CAAE6C,KAAeV,EAAQ5C,UAAUwD,OAAOF,KAU5CG,EAAOC,IAClB,MAAMC,EAAe5C,OAAOG,iBAAiBZ,SAASsD,iBAAiBC,SACvE,OAAOH,EAAKI,SAASH,EAAc,GAAG,EClDlCI,EAAyBN,EAAI,IAC7BO,EAAMP,EAAI,GACVQ,EAAYR,EAAI,IAEhBS,EAA8B,GAAGH,EAAyBE,EAAYD,O,aCE5E,MAAMG,EAAcvB,GAAaA,aAAmBwB,UAAYxB,aAAmByB,QAAUzB,EAAUA,EAAQ,GAgBlG0B,EAAkB,CAACC,EAASvB,KACvCwB,EAAED,GAASE,IAAI,OAEdzB,GAAS,IAAIvC,SAASiC,IACrB,IAAK6B,EAAQhD,cAAc,iBAAiBmB,EAAWM,WAAY,CACjE,MAAM0B,EAASpE,SAASkC,cAAc,UACtCkC,EAAOC,UAAYjC,EAAWkC,KAC9BF,EAAOtE,aAAa,WAAY,QAChCsE,EAAOtE,aAAa,QAASsC,EAAWM,OACxCuB,EAAQpB,YAAYuB,EACtB,KAGF,MAAMG,EACA7B,EAAM8B,OAAS,EACwC,OAAtCP,GAASQ,aAAa,YACrB/B,EAAMgC,KAAKtC,GAAeA,EAAWM,QAASA,IAAQ,IAAIA,MAGzE,KAGTwB,EAAED,GAASE,IAAII,GAAWI,QAAQ,SAAS,EAiCvCC,EAAoB,CAACC,EAASC,EAAUC,IAC5C,IAAIlB,EAAWgB,GAAS5E,iBAAiB6E,IAAW3E,SAASmC,GAC3D4B,EAAE5B,GAAS2B,QAAQ,CACjBe,YAAY,EACZC,YAAa3C,EAAQmC,aAAa,gBAAkB,YACpDS,kBAAmB,iBACnBC,MAAO,cACPC,MAAO,SACJL,MAIHM,EAAwB,CAACR,EAASS,EAAiB,QAEvD,MAAMC,EAAuB,CAACC,EAAMC,KAC9BD,EAAKlD,SAEkBuB,EAAW4B,GACnB3F,aAAa,QAAS0F,EAAKlD,QAAQmC,aAAa,UAG5De,EAAKlB,MAGdM,EAAkBC,EAAS,iCAAkC,CAC3DS,iBACAI,eAAgBH,EAChBI,kBAAmBJ,GACnB,EAGEK,EAAmC,CAACf,EAASS,EAAiB,QAClEV,EAAkBC,EAAS,wBAAyB,CAClDgB,KAAM,CACJL,KAAM,SAAcM,GAClB,MAAOxD,GAAWyD,KAGZC,EAA6B,IAAnBF,EAAOG,KAAO,IAAW,EAInCC,EAAIJ,EAAOK,KAGXC,EAAe9D,EAAQmC,aAAa,iBAAmB,IAGvD4B,EAAc/D,EAAQmC,aAAa,oBAGnC6B,EAAQ9C,SAASlB,EAAQmC,aAAa,cAAe,KAAO,EAG5D8B,EAAejE,EAAQmC,aAAa,oBAGpC+B,EAAyBjE,OAAOkE,YACpC,IAAInE,EAAQF,YACT9B,QAAQmC,GAAcA,EAAUiE,KAAKzD,SAAS,uBAC9C0D,SAASlE,IACR,MAAO,CAAEmE,GAAcnE,EAAUiE,KAAKG,MAAM,qBAW5C,MATe,MACb,IACE,OAAO7E,KAAK8E,MAAMrE,EAAUC,MAE9B,CAAE,MAAOqE,GACP,MAAO,EACT,CACD,EAPc,GASDJ,SAASjE,IACrB,MAAMsE,EAAgBtE,EAAMuE,WAAW,KAGjCC,EAAYF,EACd,MACE,MAAMN,EAAOhE,EAAMyE,MAAM,GAEzB,GAAI7E,EAAQpC,GAAG+C,SAAS,YAAa,CACnC,MAAOmE,GAAa9E,EAAQpC,GAAGmH,MAAM,mBAAoB,IACzD,OAAOrH,SAASiB,cAAc,IAAImG,IAAYV,IAChD,CAMA,OAAIpE,EAAQgF,QAAQ,OAAO5H,UAAUG,SAAS,mBACrCyC,EAAQgF,QAAQ,MAAMrG,cAAc,eAAeyF,OAGrD1G,SAASiB,cAAc,OAAOyF,IACtC,EAjBD,GAkBA,KAEEa,EAAkBL,EACpB,MACE,MAAMM,GAnKVC,EAmKiCP,EAlKZ,OAArCO,GAAQhD,aAAa,YAAuBgD,GAAQ/E,MAAQ,IAAI+E,EAAOC,iBAAiBhD,KAAKN,GAAWA,EAAO1B,SADhG,IAAC+E,EAoKI,MAAME,EAAQlH,OAAOG,iBAAiBsG,GAEtC,OAAIM,GAAiC,MAAlBG,EAAMC,SAAwC,WAArBD,EAAM9G,WACzC2G,EAGLN,EAAUzC,aAAa,aAAeyC,EAAUzC,aAAa,oBACxD,YADT,CAKD,EAbD,GAcA,KAGJ,OAAOoD,OADab,EAAgBO,EAAkB7E,GAElD,CAAC,CAACkE,EAAYW,GAAmB7E,IACjC,EAAE,GACN,KAIFoF,EAAa,CACjBxB,MAAOyB,OAAOzB,GACd0B,MAAOD,OAnFK,IAoFZ/B,OAAQ+B,OAAO/B,MACXK,EAAc,CAAEA,oBAAgBzE,KAChC2E,EAAe,CAAEA,qBAAiB3E,KAClCsE,EAAI,CAAE,CAACE,GAAeF,QAAMtE,KAC7B4E,GAIL,OAAO,IAAIyB,gBAAgBH,GAAYI,UACzC,EACAC,MAAO,IACPC,eAAgB,SAAwB5C,GACtC,MAAOlD,GAAWyD,KAAKsC,SACvB,IAAI/F,EAAQrC,iBAAiB,WAAWE,SAASwC,GAAUA,EAAM2F,gBAAgB,cAEjF,MAAMC,EAAU,IAEVjG,EAAQmC,aAAa,qBAAyC,OAAlBe,EAAKgD,SACjD,CAAC,CAAEtI,GAAI,OAAQoE,KAAMhC,EAAQmC,aAAa,sBAC1C,MACDlC,OAAOkG,OACRjD,EAAK+C,QAAQG,QAAO,CAACC,EAAaC,EAAQC,KAExC,MAAMC,EAAWC,QAAQH,IAAStG,EAAQmC,aAAa,wBACjDvE,EAAK,EAAI0I,EAAQtG,EAAQmC,aAAa,iBAAmBmE,EAAO1I,GAChEoE,EAAO,EAAIsE,EAAQtG,EAAQmC,aAAa,mBAAqBmE,EAAOlC,KAEpEsC,EAAO,IAAKJ,EAAQE,WAAU5I,KAAIoE,SAClC,MAAE2E,EAAK,KAAEC,EAAI,IAAEC,GAAQH,EAOvBI,EAA0BL,QAAQI,GAAKlG,SAAS,mBAEhDoG,EAAa,MACjB,QAAQ,GACN,KAAKJ,eAAyCC,EAC5C,MAAO,CAAEI,SAAU,GAAGJ,EAAKxC,QAAQuC,EAAMvC,OAAQpC,KAAM,GAAG4E,EAAKxC,UAAUuC,EAAMvC,QAEjF,KAAKuC,QACH,MAAO,CAAEK,SAAUL,EAAMvC,KAAMpC,KAAM2E,EAAMvC,MAE7C,KAAKwC,QACH,MAAO,CAAEI,SAAUJ,EAAKxC,KAAMpC,KAAM4E,EAAKxC,MAE3C,KAAe,OAAVuC,GAA2B,OAATC,EACrB,MAAO,CAAEI,SAAU,SAAUhF,KAAM,UAErC,QACE,OAEL,EAjBkB,GAmBnB,MAAO,IACFqE,KACCU,EACA,CACE,CAACA,EAAWC,UAAW,IAClBX,EAAYU,EAAWC,aACtBX,EAAYU,EAAWC,eAAY1H,EAAY,CAAE0C,KAAM+E,EAAW/E,MACtEjC,SAAU+G,OACNxH,EACA,IAAK+G,EAAYU,EAAWC,WAAWjH,UAAY,GAAK2G,KAGhE,CAAE,CAACH,GAAQG,GAChB,GACA,CAAC,KAMR,MAAO,CAAEO,WAAY,CAAEC,KADa,OAAdhE,EAAKiE,MACmBlB,UAChD,EACAY,IAAK,WACH,MAAO7G,GAAWyD,KACZ2D,EAtOG,CAACP,IAChB,MAAMQ,EAAe,mBAErB,IAAItC,EACAuC,EAAeT,EAEnB,KAAQ9B,EAAQsC,EAAaE,KAAKV,IAAO,CACvC,MAAMW,EAAe9J,SAASiB,cAAc,OAAOoG,EAAM,MACnD0C,EAAmBD,GAAcpC,kBAAkB,IAAIjD,aAAa,aACpEuF,EACJD,GAAoBD,EAAapH,QAAUoH,EAAarF,aAAa,oBAAsB,YAAS7C,GAEtGgI,EAAeI,EAAUJ,EAAaI,QAAQ3C,EAAM,GAAI2C,GAAWJ,CACrE,CAEA,OAAOA,CAAY,EAuNGK,CAAS3H,EAAQmC,aAAa,aAG9C,OAAQiF,EAAQzG,SAAS,OAASyG,CACpC,GAEFpE,kBACA,EAGE4E,EAA2B,CAACrF,EAASS,EAAiB,OAC1DV,EAAkBC,EAAS,qCAAsC,CAC/DS,iBACA6E,SAAU,CAAEC,UAAW,IAAM,yCAC7BC,UAAU,EACVC,MAAM,IAGJC,EAAkC,CAAC1F,EAASS,EAAiB,OACjEV,EAAkBC,EAAS,2BAA4B,CAAES,mBAE9CkF,EAA2B3F,IACtCQ,EAAsBR,GACtBe,EAAiCf,GACjCqF,EAAyBrF,GACzB0F,EAAgC1F,GAEhC,IAAIhB,EAAWgB,GAAS5E,iBAAiB,WAAWE,SAASsK,IAC3DpF,EAAsBoF,EAAOA,GAC7B7E,EAAiC6E,EAAOA,GACxCP,EAAyBO,EAAOA,GAChCF,EAAgCE,EAAOA,EAAM,GAC7C,ECvTSC,EAAahE,GACxB1G,SAAS2K,OACN9D,MAAM,MACN+D,MAAMD,GAAWA,EAAO1D,WAAW,GAAGP,SACrCG,MAAM,KAAK,GASJgE,EAAY,CAACnE,EAAMhE,EAAOqC,KACrC,MAAM+F,EAAa,CAAE,CAACpE,GAAOhE,EAAOqI,KAAM,OAAQhG,GAClD/E,SAAS2K,OAASpI,OAAOC,QAAQsI,GAC9BpG,KAAKsG,GAAUA,EAAMC,KAAK,OAC1BA,KAAK,IAAI,EAQDC,EAAgBxE,GAASmE,EAAUnE,EAAM,GAAI,CAAEyE,QAAS,kCC5B/DC,EAAwB,oBAMjBC,EAAgB,KAC3B,MAAMC,EAAUtL,SAASiB,cAAc,uBAEjCsK,EAAWD,EAAQ7G,aAAa,iBAChC+G,EAAqD,SAA1CF,EAAQ7G,aAAa,iBAEtC6G,EAAQxL,aAAa,gBAAiBiI,QAAQyD,IAE9BxL,SAASyL,eAAeF,GAChC7L,UAAUC,OAAO,uBAAwB6L,GAE7CA,GACFX,EAAUO,EAAuB,QACjC3K,OAAOiL,cAAc3J,QAAQqJ,EAAuB,UAEpDF,EAAaE,GACb3K,OAAOiL,cAAcC,WAAWP,GAClC,ECtBIQ,EAAsB,CAAC,YAAa,qBCDpCC,EAAiB,cAEjBC,EAAa,OACbC,EAAc,QACdC,EAAe,SAcfC,EAAgB9G,GAAUA,IAAU2G,GAAc3G,IAAU4G,GAAe5G,IAAU6G,EAOrFE,EAAc,KAClB,MAAMC,EAAczB,EAAU,SAC9B,GAAIuB,EAAaE,GACf,OAAOA,EAGT,MAAMC,EAAoB3L,OAAOiL,cAAcW,QAAQ,SACvD,OAAIJ,EAAaG,GACRA,EAGFJ,CAAY,EASfM,EAAW,CAACnH,EAAOJ,KACvB,MAAMwH,EAAWxD,QAAQhE,GAASyH,QAE5B/B,EAAQzK,SAASyL,eAAeI,IACtBpB,GAAOxK,iBAAiB,0BAA4B,IAE5DE,SAASsM,GACf,CAAC,SAAU,kBAAkBtM,SAAS6C,GACpCyJ,EAAO/M,UAAUC,OAAOqD,EAAWyJ,EAAOC,QAAQC,UAAYxH,OAIlE,MAAMyH,EAAUzH,IAAU6G,EA9C1BvL,OAAOoM,aAAa,0BAA0Bf,MAAegB,QAAUhB,EAAaC,EA8Cf5G,EACrEnF,SAASsD,gBAAgBoJ,QAAQvH,MAAQyH,EACzC5M,SAASsD,gBAAgBoJ,QAAQE,QAAUA,EAEvCzH,IAAU6G,GACZd,EAAa,SACbzK,OAAOiL,cAAcC,WAAW,UACvBY,IACT1B,EAAU,QAAS1F,GACnB1E,OAAOiL,cAAc3J,QAAQ,QAASoD,KAGpCA,IAAU2G,GAAe3G,IAAU6G,GAAgBY,IAAYd,IACjE,IAAI9L,SAAS+M,qBAAqB,WAAW5M,SAAS6M,IACpDA,EAAOC,iBAAiB,QAAS9L,IAC3BA,EAAM+L,OAAOC,iBAKf,IAJehM,EAAM+L,OAAOC,gBAAgBJ,qBAAqB,YAC7C5L,EAAM+L,OAAOC,gBAAgB9M,uBAAuB,4BACrDc,EAAM+L,OAAOC,gBAAgB9M,uBAAuB,yBAE5BF,SAASiN,GAClDA,EAAWtN,aAAa,SAAU,yBAEtC,GACA,IAIFyM,GACFvM,SAASqN,SAASC,QACpB,ECpFF7M,OAAO8M,UAAY,EAGnB9M,OAAO+M,YAAc,EAGrB/M,OAAOgN,QAAUA,EAGjBhN,OAAOiN,UAAY,IAUnBjN,OAAOkN,KAAO,IAEd,IAAKC,iBAAiB,UAAWC,EAAA,GACjC,IAAKD,iBAAiB,OAAQE,EAAA,GAC9B,IAAKF,iBAAiB,MAAOG,EAAA,GAC7B,IAAKH,iBAAiB,OAAQI,EAAA,GAC9BvN,OAAOwN,KAAO,IAGdxN,OAAOyN,OAAS,EAChBzN,OAAOyD,EAAIzD,OAAOyN,OAgBlBlO,SAASiN,iBAAiB,oBAAoB,KAC5CxM,OAAO0N,KAAO,CAAC,ERtCQ,MACvB,MAAMzM,EAAQ,MACZ,IACE,MAAMsH,EAAOvI,OAAOqB,gBAAgBuK,QAAQ7K,GAC5C,OAAOwH,EAAOhH,KAAK8E,MAAMkC,QAAQpH,CAEnC,CAAE,MAAOmF,GACP,MACF,CACD,EARa,GAUd,QAAcnF,IAAVF,EAAqB,CACvB,MAAMyH,EAAM,GAAG1I,OAAO4M,SAASe,WAAW3N,OAAO4M,SAASgB,SAAS5N,OAAO4M,SAASiB,OACnF7N,OAAOoB,SAAS0M,aAAa7M,EAAO,GAAIyH,GACxC1I,OAAOqB,gBAAgB6J,WAAWnK,EACpC,GQ0BAgN,GACA/N,OAAO0N,GAAGtM,QAAU,CAAEJ,UAAS,GAG/B,IAAIzB,SAASC,iBAAiB,+BAA+BE,SAASsO,GAAY,IAAI,UAAkBA,KH1BzE,MAC/B,MAAMnD,EAAUtL,SAASiB,cAAc,uBAEvC,GAAIqK,EAAS,CAKX,MAAMoD,EACJhE,EAAUU,IAA0B3K,OAAOiL,cAAcW,QAAQjB,IAA0B,SAEzD,SAAjCsD,GAAqF,SAA1CpD,EAAQ7G,aAAa,kBAC/B,UAAjCiK,GAAsF,UAA1CpD,EAAQ7G,aAAa,mBAElE4G,IAGFC,EAAQ2B,iBAAiB,QAAS5B,EACpC,CAEA,IAAIrL,SAASC,iBAAiB,wCAAwCE,SAASwO,IAC7EA,EAAgB1B,iBAAiB,SAAS,KACxC,MAAM1B,EAAWoD,EAAgBlK,aAAa,iBACxC+G,EAA6D,SAAlDmD,EAAgBlK,aAAa,iBAE9CkK,EAAgB7O,aAAa,gBAAiBiI,QAAQyD,IAEtD,MAAMoD,EAAmBC,IACvB,MAAQ3B,OAAQ4B,GAAwBD,EAClCE,EAAgB/O,SAASyL,eAAeF,IAG3CoD,EAAgB9O,SAASiP,KAAyBC,EAAclP,SAASiP,KAG1EH,EAAgB7O,aAAa,gBAAiB,SAC9CE,SAASgP,oBAAoB,QAASJ,GACxC,EAGEpD,EACFxL,SAASgP,oBAAoB,QAASJ,GAEtC5O,SAASiN,iBAAiB,QAAS2B,EACrC,GACA,IAGJ,MAAMK,EAA4B/K,EAAE,iCACpC+K,EAA0BC,GAAG,UAAW/N,GAAUA,EAAMgO,cAAcC,KAAKC,WAC3EJ,EAA0BC,GAAG,gBAAgB,KAC3ClP,SAASiB,cAAc,qBAAqBnB,aAAa,gBAAiB,QAC1EE,SAASiB,cAAc,4CAA4CnB,aAAa,cAAe,mBAAmB,GAClH,EGxBFwP,GX/CyC,MACzC,MAAMC,EAAS,CAACC,EAAkBC,IAChCD,EAAiBE,OAAOpN,IACtB,MAAMqN,GAAerN,EAAQ5C,UAAUG,SAAS,QAChD,MAA+B,cAAxB4P,EAAsCE,GAAeA,CAAW,IAGrEC,EAA+BC,GAAsB,IACtD7P,SAASC,iBAAiB4P,EAAkBnD,QAAQoD,UAAY,cAqCrE9P,SAASiN,iBAAiB,SAlCT9L,IACf,MAAM0O,EAAoB1O,EAAM+L,OAAO5F,QAAQ,mCAE3CuI,GACFD,EAA4BC,GAAmB1P,SAAS4P,IACtD,MAAMC,EAAmBvP,OAAO8M,UAAU0C,SAASC,oBAAoBH,GACI,SAApDF,EAAkBpL,aAAa,iBAGpDuL,EAAiBG,OAEjBH,EAAiBI,MACnB,GAEJ,IAqBFpQ,SAASiN,iBAAiB,sBAlBC,IACzB,IAAIjN,SAASC,iBAAiB,oCAC3BK,QAAQuP,GAAsBN,EAAOK,EAA4BC,GAAoB,eACrF1P,SAAS0P,IACRA,EAAkB/P,aAAa,gBAAiB,SAChD+P,EAAkBQ,YAAc,YAAY,MAclDrQ,SAASiN,iBAAiB,qBAXA,IACxB,IAAIjN,SAASC,iBAAiB,oCAC3BK,QAAQuP,GAAsBN,EAAOK,EAA4BC,GAAoB,cACrF1P,SAAS0P,IACRA,EAAkB/P,aAAa,gBAAiB,QAChD+P,EAAkBQ,YAAc,cAAc,KAYnD,EWHDC,GV3DiC,MACjC,MAAMhJ,EAAU,CAAChF,EAASU,IAAcV,GAASgF,UAAU,IAAItE,KAEzDuN,EAA+BC,GAAiBrP,IACpD,MAAMsP,EAASnJ,EAAQnG,EAAM+L,OAPF,uBAQvBuD,GACgBnJ,EAAQmJ,EAAQtR,GACxBW,aAAa,YAAaiI,OAAOyI,GAC7C,EAGIE,EAAcH,GAA4B,GAC1CI,EAAYJ,GAA4B,GA6E9CvQ,SAASiN,iBAAiB,YAAayD,GACvC1Q,SAASiN,iBAAiB,UAAW0D,GACrC3Q,SAASiN,iBAAiB,aA7EL9L,IACnB,MAAMyP,EAAYtJ,EAAQnG,EAAM+L,OAAQ/N,GACpCyR,IACFzP,EAAM0P,aAAaC,UAAU,cAC7B3P,EAAM0P,aAAaE,QAAQ,aAAc5P,EAAM+L,OAAOhN,IACtD0Q,EAAUlR,UAAUsR,IAAI3R,GAC1B,IAwEFW,SAASiN,iBAAiB,WArEP9L,IACjB,MAAMyP,EAAYtJ,EAAQnG,EAAM+L,OAAQ/N,GACpCyR,IACFA,EAAUlR,UAAUwD,OAAO7D,GAC3BuR,EAAU9Q,aAAa,YAAa,SACtC,IAiEFE,SAASiN,iBAAiB,YA9DN9L,IACSmG,EAAQnG,EAAM+L,OAAQ9N,IAE/C+B,EAAM8P,gBACR,IA2DFjR,SAASiN,iBAAiB,QAxDV9L,IACd,MAAMyP,EAAY5Q,SAASyL,eAAetK,EAAM0P,aAAaK,QAAQ,eACrE,GAAIN,EAAW,CACbzP,EAAM8P,iBAEN,MAAMxL,EAAY6B,EAAQsJ,EAAWxR,GAE/B+R,EAAe,MAEnB,MAAMC,EAAgB9J,EAAQnG,EAAM+L,OAAQ/N,GAC5C,GAAIiS,EAAe,CAMjB,MAAM,OAAEC,EAAM,IAAEC,GAAQF,EAAcG,wBAEtC,OADkBpQ,EAAMqQ,QAAUF,EAAMD,EAAS,EAC9BD,EAAgBA,EAAcK,WACnD,CAGA,MAAO,IAAIhM,EAAUpD,UAAUuI,MAAMjI,IACnC,MAAM,KAAE+O,EAAI,MAAEC,EAAK,IAAEL,GAAQ3O,EAAM4O,wBAEnC,OAAIG,EAAOvQ,EAAMyQ,SAGND,GAASxQ,EAAMyQ,SAEpBN,GAAOnQ,EAAMqQ,OAKP,GAEf,EA9BoB,GAgCjBL,EACF1L,EAAU0L,aAAaP,EAAWO,GAGlC1L,EAAUoM,OAAOjB,GAGnBA,EAAUlR,UAAUsR,IAAI3R,EAC1B,IASuC,EUhCzCyS,GTDA9R,SAASiN,iBAAiB,mBAAoB9L,GAAU5B,EAAa4B,EAAM+L,QAAQ,KACnFlN,SAASiN,iBAAiB,kBAAmB9L,GAAU5B,EAAa4B,EAAM+L,QAAQ,KAClFlN,SAASiN,iBAAiB,oBAAqB9L,GAAU5B,EAAa4B,EAAM+L,UAE5ElN,SAASiN,iBAAiB,oBAAqB9L,IAC7C,GAAIA,EAAM+L,OAAOhN,GAAI,CACnB,MAAM6R,EAAY,IAAKtR,OAAOoB,SAASH,MAAOlC,OAAQ2B,EAAM+L,OAAOhN,IAC7DiJ,EAAM,GAAG1I,OAAO4M,SAASe,WAAW3N,OAAO4M,SAASgB,SAAS5N,OAAO4M,SAASiB,OACnF7N,OAAOoB,SAAS0M,aAAawD,EAAW,GAAI5I,EAC9C,KAGFnJ,SAASiN,iBAAiB,oBAAoB,KAE5C,MAAM,OAAEzN,KAAWwS,GACgB,iBAA1BvR,OAAOoB,SAASH,OAA+C,OAAzBjB,OAAOoB,QAAQH,MAAiBjB,OAAOoB,QAAQH,MAAQ,CAAC,EACjGqQ,EAAYxP,OAAO0P,KAAKD,GAAWxN,OAAS,EAAIwN,EAAY,KAC5D7I,EAAM,GAAG1I,OAAO4M,SAASe,WAAW3N,OAAO4M,SAASgB,SAAS5N,OAAO4M,SAASiB,OACnF7N,OAAOoB,SAAS0M,aAAawD,EAAW,GAAI5I,EAAI,IAGlDnJ,SAASiN,iBAAiB,SAAU9L,IAClC,MAAM+Q,EAAU/Q,EAAM+L,OAAO5F,QAAQ,qBAC/B3H,EAASwB,EAAM+L,OAAO5F,QAAQ,oBAEpC,GAAmC,WAA/B4K,GAASxF,QAAQyF,UAAwB,CAC3C,MAAM3S,EAAS0S,EAAQ5K,QAAQ,cAC/B9H,GAAQ4B,cAAc,IAAIC,YAAY,kBAAmB,CAAEC,SAAS,EAAMC,YAAY,IACxF,MAAO,GAAiC,WAA7B5B,GAAQ+M,QAAQ0F,SAAuB,CAChD,MAAM5S,EAASQ,SAASiB,cAActB,EAAO+M,QAAQoD,UACrDtQ,GAAQ4B,cAAc,IAAIC,YAAY,mBAAoB,CAAEC,SAAS,EAAMC,YAAY,IACzF,KAGEd,OAAOoB,SAASH,OAAOlC,QACzBQ,SACGyL,eAAehL,OAAOoB,QAAQH,MAAMlC,SACnC4B,cAAc,IAAIC,YAAY,iBAAkB,CAAEC,SAAS,EAAMC,YAAY,KU9F7C,MAEtC,MAAM8Q,EAAuB,IAAIC,sBAC/B,EAAEtH,KAAWA,EAAMkC,OAAOxN,UAAUC,OAAO,eAAgBqL,EAAMuH,kBAAoB,IACrF,CAAEC,UAAW,CAAC,KAGU,IAAIxS,SAASC,iBAAiB,2BACtCE,SAASsS,GAAqBJ,EAAqBK,QAAQD,IAI5E,EDqDDE,GNhE8B,MAC9B,MAAMC,EAAe5S,SAASyL,eAAe,iBAG7C,IAAKmH,EACH,MAAO,OAGT,MAAMC,EAAW,MACf,IACE,MAAMC,EAAU9S,SAASyL,eAAe,YACxC,OAAOqH,EAAU9Q,KAAK8E,MAAMgM,EAAQzC,aAAe,CAAC,CAEtD,CAAE,MAAOtJ,GACP,MAAO,CAAC,CACV,CACD,EARgB,GAcXgM,EAAoBxQ,OAAOkE,YAC/BlE,OAAOC,QAAQqQ,EAASG,MAAMrM,SAAQ,EAAE,CAAEsM,KACxC1Q,OAAOC,QAAQyQ,EAAYC,QAAQvM,SAAQ,EAAE,CAAEwM,KAC7C5Q,OAAOC,QAAQ2Q,EAAcC,OAAO1O,KAAI,EAAE2O,EAAWC,KAAkB,CAACD,EAAWC,UAKnFC,EAAgB,IAAIC,OACxB,oBAAoBjR,OAAOC,QAAQuQ,GAEhCpM,SAAQ,EAAE,EAAID,WAAY,CAACA,KAAS,CAAC,GAAI,IAAK,OAAOhC,KAAK+O,GAAc/M,EAAKsD,QAAQ,OAAQyJ,QAC7FxI,KAAK,YACR,KAGIyI,EAAoBd,EAAa3R,cAAc,SAE/C0S,EAAmB,KACvB,MAAMC,EAAc5T,SAASyL,eAAe,gBAExCmI,IACFA,EAAY1Q,SACZlD,SAAS6T,KAAKnU,UAAUC,OAAO,qBAAqB,GACtD,EAgBFK,SAASiN,iBAAiB,WAZP9L,IACjB,MAAM2S,EAAe3S,EAAM4S,mBAAmB,QACxCC,EAAgB7S,EAAM8S,SAEvBH,GAAgBE,IAAgC,MAAd7S,EAAM+S,KAC3C/S,EAAM8P,iBACNyC,EAAkB5S,SACK,WAAdK,EAAM+S,KACfP,GACF,IAqMFD,EAAkBzG,iBAAiB,SAhMX,KACtB,MAAM2G,EAAc5T,SAASyL,eAAe,gBAG5C,GAAImI,EAAa,CACf,MAAMO,EAAQP,EAAY3S,cAAc,SAGxC,OAFAkT,GAAOrT,aACPqT,GAAOC,mBAAmB,GAAI,EAEhC,CAEApU,SAAS6T,KAAKnU,UAAUC,OAAO,qBAAqB,GAEpD,MAAQ+R,KAAM2C,EAAW,EAAG1C,MAAO2C,EAAY,GAAMtU,SAASiB,cAAc,SAASsQ,yBAA2B,CAAC,GACzGD,IAAKiD,GAAyBb,EAAkBnC,wBAElDiD,EAAOtS,EAAc,OAAQ,CACjC,cAAe,OACfc,UACE,mHACF2E,MAAO,WAAWhE,gBAAwBA,UAGtC8Q,EAASvS,EAAc,OAAQ,CACnCc,UAAW,0DACX2E,MAAO,SAAS/D,OAGZuQ,EAAQjS,EAAc,QAAS,CACnCc,UAAW,qBACX0D,KAAM,IACNgO,SAAU,OACV/M,MAAO,mBAAmB/D,KAC1B+Q,KAAM,SACNjS,MAAOgR,EAAkBhR,QAGrBkS,EAAQ1S,EACZ,SACA,CACEc,UAAW,0JAAyK,KAAhBmR,EAAMzR,MAAe,uBAAyB,IAClNiF,MAAO,WAAWhE,gBAAwBA,QAC1CgR,KAAM,UAERzS,EAAc,OAAQ,CAAEc,UAAW,mBAAqB,UAG1D4R,EAAM3H,iBAAiB,SAAS,KAC9BkH,EAAMzR,MAAQ,GACdyR,EAAM/S,cAAc,IAAIyT,WAAW,UACnCV,EAAMrT,OAAO,IAGfqT,EAAMlH,iBAAiB,SAAS,KAC9B,MAAM6H,EAAkC,KAAhBX,EAAMzR,MAC9BkS,EAAMlV,UAAUC,OAAO,YAAamV,GACpCF,EAAMlV,UAAUC,OAAO,YAAamV,EAAgB,IAGtD,MAAMzF,EAASnN,EAAc,QAAS,CAAEc,UAAW,SAAU2R,KAAM,WAE7DvF,EAAOlN,EACX,OACA,CAAE6S,OAAQnC,EAAanO,aAAa,UAAWzB,UAAW,0BAA2BgS,KAAM,UAC3FR,EACAC,EACAN,EACAS,EACAvF,GAIFD,EAAKnC,iBAAiB,UAAU,KAC9B,MAAMgI,EAAQ7F,EAAKnO,cAAc,6BAE7BgU,GACF7F,EAAKtP,aAAa,SAAUmV,EAAMvI,QAAQwI,OAC5C,IAGF,MAAM3M,EAAUrG,EAAc,OAExBiT,EAAQjT,EACZ,MACA,CAAEc,UAAW,gBAAiB2E,MAAO,cAAcxE,EAAI,YACvDiM,EACA7G,GAGI6M,EAAUlT,EACd,MACA,CACEc,UAAW,sFACX9C,GAAI,eACJ8U,KAAM,SACNrN,MAAO,6DAA6D4M,mCAAsDF,SAAgBlR,EAAI,4CAA4CmR,SAAiBnR,EAAI,YAEjNgS,GAIFC,EAAQnI,iBAAiB,SAAU9L,IAC7BA,EAAM+L,SAAWkI,GACnBzB,GACF,IAGF3T,SAAS6T,KAAKhR,YAAYuS,GAE1B,MAAMC,EAAYC,IAChB,MAAM5O,EAAOnE,OAAOC,QAAQuQ,GAAmBnI,MAAK,EAAEyI,KAAeA,IAAciC,MAAQ,IAAI5O,MAAQ4O,EAEjGC,EAAerT,EACnB,SACA,CAAEyS,KAAM,UACRzS,EAAc,OAAQ,CAAE,cAAe,OAAQsT,MAAO,kBACtDtT,EAAc,OAAQ,CAAEsT,MAAO,mBAAqB,WAGhDP,EAAQ/S,EACZ,OACA,CAAEc,UAAW,eAAgB,eAAgBsS,GAC7C,OAAO5O,IACP6O,GAGFA,EAAatI,iBAAiB,SAAS,KACrCgI,EAAM/R,SACNiR,EAAMrT,OAAO,IAIf,IAAI2T,EAAOxU,iBAAiB,kBAAkBqV,QAAWnV,SAASsV,GAAaA,EAASvS,WAExFuR,EAAO5R,YAAYoS,GAGnB,IAAIR,EAAOpS,UAAU8E,MAAM,GAAG,GAAsBhH,SAASwC,GAAUA,EAAMO,UAAS,EAIjE,IAAIwS,gBAAe,KACxC,MAAM,MAAEtQ,GAAUqP,EAAOlD,wBACzB4C,EAAMxM,MAAMgO,mBAAqBvQ,EAC7B,QAAQxB,OAAiCwB,SAAa1B,QACtDE,CAA2B,IAGlB8O,QAAQ+B,GAEvBN,EAAMlH,iBAAiB,SAAS,KAC9B,MAAM5F,EAAQ8M,EAAMzR,MAAM2E,MAAMkM,GAEhC,GAAIlM,EAAO,CACT,MAAOuO,EAAQC,GAASxO,EAElByO,EAAaxR,GACjBA,EACGyR,OACAC,cACAhM,QAAQ,UAAW,IAClBsL,EAAO/S,OAAOC,QAAQuQ,GAAmBnI,MAC7C,EAAE,EAAIlE,WAAYoP,EAAUpP,KAAUoP,EAAUD,OAC9C,GAEAP,IAEFnB,EAAMzR,MAAQyR,EAAMzR,MAAMsH,QAAQ4L,EAAQ,IAC1CzB,EAAM/S,cAAc,IAAIyT,WAAW,UACnCQ,EAASC,GAEb,KAIFnB,EAAMlH,iBAAiB,WAAY9L,IACjC,MAAM8U,EAA4B,cAAd9U,EAAM+S,IACpBgC,EAAsC,IAAvB/B,EAAMgC,cAA+C,IAAzBhC,EAAMiC,eAEnDH,GAAeC,GACjBzB,EAAOxT,cAAc,gBAAgBiC,QACvC,IAIF0P,EAAa3S,iBAAiB,kBAAkBE,SAAS8U,GAAUI,EAASJ,EAAMvI,QAAQwI,UAG1Ff,EAAMrT,QACNqT,EAAMC,mBAAmB,GAAI,EAAE,GAShC,EMnMDiC,GAGA5V,OAAO0N,GAAGlK,QAAU,CAAEuG,wBAAuB,kBAAiB,GFkD7B,MACjC,MAAM8L,EAAkB,IAAItW,SAASC,iBAAiB,kBAAkByE,KAAKsO,IAC3E,MAAMuD,EAAiB,IAAIb,gBAAe,IA1HlB,CAAC1C,IAC3B,MAAMwD,EAAaxD,EAAKyD,WAGxB,IAAID,EAAWvW,iBAAiB,qCAAqCE,SAASuW,GAAcA,EAAUxT,WAGtG,MAAMwT,EAAY1D,EAAK2D,WAAU,GAGjCD,EAAUpO,gBAAgB,MAG1BoO,EAAUhK,QAAQkK,MAAQ,OAO1B,MAAMC,EAA4B,CAAC,cAAe,YAAa,oBAAqB,QACpFH,EAAUhX,UAAUsR,OAAO6F,GAGvB7D,EAAKvB,YACP+E,EAAWrF,aAAauF,EAAW1D,EAAKvB,aAExC+E,EAAW3T,YAAY6T,GAGzB,MAAMI,EAAqB,IAAMJ,EAAUnF,wBAAwBnM,MAAQ4N,EAAKzB,wBAAwBnM,MAGxG,IAAK0R,IAGH,OAFA9D,EAAKtT,UAAUwD,UAAU0I,QACzB4K,EAAWO,YAAYL,GASzB,MAAMM,EAAe9U,EAAc,KAAM,CAAEc,UAAW,oCAChDiU,EAAqB/U,EAAc,OAAQ,CAAEc,UAAW,iBACxDkU,EAAsBhV,EAAc,OAAQ,CAAEc,UAAW,mBAAqB,mBAC9EmU,EAAiBjV,EACrB,SACA,CACE,gBAAiB,QACjBc,UAAW,qCACX,iBAAkB,WAClB2R,KAAM,UAERsC,EACAC,GAEIE,EAAWlV,EACf,KACA,CAAEc,UAAW,uCACbmU,EACAH,GAEFN,EAAU7T,YAAYuU,GAMtB,MAAMC,EAAgB,GACtB,KAAOP,KAAsB,CAC3B,MAAMQ,EAAUF,EAASG,uBACzBF,EAAcG,QAAQF,GACtBZ,EAAUK,YAAYO,EACxB,CASAD,EAAclX,SAASsX,IACrB3U,EAAqB2U,GAErB,IAAIA,EAAapV,UAAUlC,SAASuX,IAClC5U,EAAqB4U,EAAS,SAAU,YACxCA,EAAQhY,UAAUsR,IAAI,gBAAiB,0BAA0B,IAGnEgG,EAAanU,YAAY4U,EAAa,IAOxC,IAAIf,EAAUzW,iBAAiB,MAAME,SAASwX,IAC5CA,EAAU1K,iBAAiB,gBAAgB,KACzC,MAAM2K,EAAc5E,EAAK/R,cAAc,WAAW0W,EAAUlT,aAAa,cAC7C,MAAcoT,YAAYD,IAAgB,IAAI,MAAcA,IACpExH,MAAM,GAC1B,IAIJ4C,EAAKtT,UAAUsR,OAAOpF,GACtB8K,EAAUhX,UAAUwD,UAAU2T,EAA0B,EAaNiB,CAAa9E,KAE7D,OADAuD,EAAe7D,QAAQM,GAChBuD,CAAc,GAG8D,EE3CrFwB,GDF6B,MAC7B,MAAMtN,EAAQzK,SAASyL,eAAeI,GAChCmM,EAAUvN,GAAOxK,iBAAiB,0BAA4B,GAEpEqM,EAASJ,KACTzL,OAAOoM,WAAW,0BAA0Bf,MAAemB,iBAAiB,UAAU,IAAMX,EAASJ,OAErG,MAAM+L,EAAW9W,GAAUmL,EAASnL,EAAMgO,cAAczC,QAAQC,QAAS,CAAEH,QAAQ,IACnFwL,EAAQ7X,SAASsM,GAAWA,EAAOQ,iBAAiB,QAASgL,IAEyB,ECLtFC,GAOAzX,OAAO0X,eALgB,CAAC7V,EAASnB,KAC3BA,EAAMiX,OAAOC,YACf/V,EAAQ5C,UAAUC,OAAO,SAC3B,EAQFc,OAAO6X,cAJe,CAAChW,EAASnB,KAC9B,MAAMoX,EAAajW,EAAQ5C,UAAUG,SAAS,UAC9CsB,EAAMiX,OAAOrN,KAAOwN,EAAajW,EAAQoK,QAAQ8L,UAAYlW,EAAQoK,QAAQ+L,MAAM,CAEjD,G,GE7GlCC,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBhX,IAAjBiX,EACH,OAAOA,EAAaC,QAGrB,IAAIC,EAASL,EAAyBE,GAAY,CAGjDE,QAAS,CAAC,GAOX,OAHAE,EAAoBJ,GAAUK,KAAKF,EAAOD,QAASC,EAAQA,EAAOD,QAASH,GAGpEI,EAAOD,OACf,CAGAH,EAAoBO,EAAIF,EdzBpB9Z,EAAW,GACfyZ,EAAoBQ,EAAI,CAACC,EAAQC,EAAUC,EAAIC,KAC9C,IAAGF,EAAH,CAMA,IAAIG,EAAeC,IACnB,IAASC,EAAI,EAAGA,EAAIxa,EAASsF,OAAQkV,IAAK,CAGzC,IAFA,IAAKL,EAAUC,EAAIC,GAAYra,EAASwa,GACpCC,GAAY,EACPC,EAAI,EAAGA,EAAIP,EAAS7U,OAAQoV,MACpB,EAAXL,GAAsBC,GAAgBD,IAAahX,OAAO0P,KAAK0G,EAAoBQ,GAAGzJ,OAAOwE,GAASyE,EAAoBQ,EAAEjF,GAAKmF,EAASO,MAC9IP,EAASQ,OAAOD,IAAK,IAErBD,GAAY,EACTJ,EAAWC,IAAcA,EAAeD,IAG7C,GAAGI,EAAW,CACbza,EAAS2a,OAAOH,IAAK,GACrB,IAAII,EAAIR,SACE1X,IAANkY,IAAiBV,EAASU,EAC/B,CACD,CACA,OAAOV,CAnBP,CAJCG,EAAWA,GAAY,EACvB,IAAI,IAAIG,EAAIxa,EAASsF,OAAQkV,EAAI,GAAKxa,EAASwa,EAAI,GAAG,GAAKH,EAAUG,IAAKxa,EAASwa,GAAKxa,EAASwa,EAAI,GACrGxa,EAASwa,GAAK,CAACL,EAAUC,EAAIC,EAqBjB,EezBdZ,EAAoBoB,EAAI,CAACjB,EAASkB,KACjC,IAAI,IAAI9F,KAAO8F,EACXrB,EAAoBsB,EAAED,EAAY9F,KAASyE,EAAoBsB,EAAEnB,EAAS5E,IAC5E3R,OAAO2X,eAAepB,EAAS5E,EAAK,CAAEiG,YAAY,EAAMC,IAAKJ,EAAW9F,IAE1E,ECNDyE,EAAoB0B,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAOvU,MAAQ,IAAIwU,SAAS,cAAb,EAChB,CAAE,MAAOC,GACR,GAAsB,iBAAX/Z,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxBkY,EAAoBsB,EAAI,CAACQ,EAAKC,IAAUnY,OAAOoY,UAAUC,eAAe3B,KAAKwB,EAAKC,GCClF/B,EAAoBmB,EAAKhB,IACH,oBAAX+B,QAA0BA,OAAOC,aAC1CvY,OAAO2X,eAAepB,EAAS+B,OAAOC,YAAa,CAAEpY,MAAO,WAE7DH,OAAO2X,eAAepB,EAAS,aAAc,CAAEpW,OAAO,GAAO,E,MCA9D,IAAIqY,EAAkB,CACrB,IAAK,GAaNpC,EAAoBQ,EAAES,EAAKoB,GAA0C,IAA7BD,EAAgBC,GAGxD,IAAIC,EAAuB,CAACC,EAA4B1V,KACvD,IAGIoT,EAAUoC,GAHT3B,EAAU8B,EAAaC,GAAW5V,EAGhBkU,EAAI,EAC3B,GAAGL,EAASgC,MAAMnb,GAAgC,IAAxB6a,EAAgB7a,KAAa,CACtD,IAAI0Y,KAAYuC,EACZxC,EAAoBsB,EAAEkB,EAAavC,KACrCD,EAAoBO,EAAEN,GAAYuC,EAAYvC,IAGhD,GAAGwC,EAAS,IAAIhC,EAASgC,EAAQzC,EAClC,CAEA,IADGuC,GAA4BA,EAA2B1V,GACrDkU,EAAIL,EAAS7U,OAAQkV,IACzBsB,EAAU3B,EAASK,GAChBf,EAAoBsB,EAAEc,EAAiBC,IAAYD,EAAgBC,IACrED,EAAgBC,GAAS,KAE1BD,EAAgBC,GAAW,EAE5B,OAAOrC,EAAoBQ,EAAEC,EAAO,EAGjCkC,EAAqBC,KAA2B,qBAAIA,KAA2B,sBAAK,GACxFD,EAAmBnb,QAAQ8a,EAAqBO,KAAK,KAAM,IAC3DF,EAAmBG,KAAOR,EAAqBO,KAAK,KAAMF,EAAmBG,KAAKD,KAAKF,G,KC7CvF,IAAII,EAAsB/C,EAAoBQ,OAAEvX,EAAW,CAAC,KAAK,IAAO+W,EAAoB,OAC5F+C,EAAsB/C,EAAoBQ,EAAEuC,E","sources":["webpack://nautobot/webpack/runtime/chunk loaded","webpack://nautobot/./src/js/collapse.js","webpack://nautobot/./src/js/draggable.js","webpack://nautobot/./src/js/drawer.js","webpack://nautobot/./src/js/history.js","webpack://nautobot/./src/js/utils.js","webpack://nautobot/./src/js/search.js","webpack://nautobot/./src/js/select2.js","webpack://nautobot/./src/js/cookie.js","webpack://nautobot/./src/js/sidenav.js","webpack://nautobot/./src/js/tabs.js","webpack://nautobot/./src/js/theme.js","webpack://nautobot/./src/js/nautobot.js","webpack://nautobot/./src/js/form.js","webpack://nautobot/webpack/bootstrap","webpack://nautobot/webpack/runtime/define property getters","webpack://nautobot/webpack/runtime/global","webpack://nautobot/webpack/runtime/hasOwnProperty shorthand","webpack://nautobot/webpack/runtime/make namespace object","webpack://nautobot/webpack/runtime/jsonp chunk loading","webpack://nautobot/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * Initialize collapse toggle all buttons identified by `data-nb-toggle=\"collapse-all\"` data attribute. Collapse toggle\n * all buttons can be further configured with `data-nb-target=\"{collapse CSS selector}\"` data attribute specifying which\n * collapse elements they control. When not explicitly set, target collapse CSS selector falls back to `\".collapse\"`.\n * ---\n * Critical difference between this and default Bootstrap 5 collapse implementation is that Bootstrap only supports\n * toggling individual panel states without an option to toggle them collectively. See an explanation below:\n * Bootstrap 5 on \"Collapse All\" button click: | Nautobot on \"Collapse All\" button click:\n * * X [expanded] -> [collapsed] | * X [expanded] -> [collapsed]\n * * Y [collapsed] -> [expanded] | * Y [collapsed] -> [collapsed]\n * * Z [expanded] -> [collapsed] | * Z [expanded] -> [collapsed]\n * ---\n * @returns {function(): void} Destructor function - remove all event listeners added during initialization.\n */\nexport const initializeCollapseToggleAll = () => {\n const areAll = (collapseElements, collapsedOrExpanded) =>\n collapseElements.every((element) => {\n const isCollapsed = !element.classList.contains('show');\n return collapsedOrExpanded === 'collapsed' ? isCollapsed : !isCollapsed;\n });\n\n const getCollapseToggleAllTargets = (collapseToggleAll) => [\n ...document.querySelectorAll(collapseToggleAll.dataset.nbTarget || '.collapse'),\n ];\n\n const onClick = (event) => {\n const collapseToggleAll = event.target.closest('[data-nb-toggle=\"collapse-all\"]');\n\n if (collapseToggleAll) {\n getCollapseToggleAllTargets(collapseToggleAll).forEach((collapse) => {\n const collapseInstance = window.bootstrap.Collapse.getOrCreateInstance(collapse);\n const shouldCollapse = collapseToggleAll.getAttribute('aria-expanded') === 'true';\n\n if (shouldCollapse) {\n collapseInstance.hide();\n } else {\n collapseInstance.show();\n }\n });\n }\n };\n\n const onHiddenBsCollapse = () =>\n [...document.querySelectorAll('[data-nb-toggle=\"collapse-all\"]')]\n .filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'collapsed'))\n .forEach((collapseToggleAll) => {\n collapseToggleAll.setAttribute('aria-expanded', 'false');\n collapseToggleAll.textContent = 'Expand All';\n });\n\n const onShownBsCollapse = () =>\n [...document.querySelectorAll('[data-nb-toggle=\"collapse-all\"]')]\n .filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'expanded'))\n .forEach((collapseToggleAll) => {\n collapseToggleAll.setAttribute('aria-expanded', 'true');\n collapseToggleAll.textContent = 'Collapse All';\n });\n\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('click', onClick);\n document.addEventListener('hidden.bs.collapse', onHiddenBsCollapse);\n document.addEventListener('shown.bs.collapse', onShownBsCollapse);\n\n return () => {\n document.removeEventListener('click', onClick);\n document.removeEventListener('hidden.bs.collapse', onHiddenBsCollapse);\n document.removeEventListener('shown.bs.collapse', onShownBsCollapse);\n };\n};\n","const DRAGGABLE_CLASS = 'nb-draggable';\nconst DRAGGABLE_CONTAINER_CLASS = 'nb-draggable-container';\nconst DRAGGABLE_HANDLE_CLASS = 'nb-draggable-handle';\nconst DRAGGING_CLASS = 'nb-dragging';\n\nexport const initializeDraggable = () => {\n const closest = (element, className) => element?.closest?.(`.${className}`);\n\n const createHandleOnMouseListener = (isDraggable) => (event) => {\n const handle = closest(event.target, DRAGGABLE_HANDLE_CLASS);\n if (handle) {\n const draggable = closest(handle, DRAGGABLE_CLASS);\n draggable.setAttribute('draggable', String(isDraggable));\n }\n };\n\n const onMouseDown = createHandleOnMouseListener(true);\n const onMouseUp = createHandleOnMouseListener(false);\n\n const onDragStart = (event) => {\n const draggable = closest(event.target, DRAGGABLE_CLASS);\n if (draggable) {\n event.dataTransfer.clearData('text/plain');\n event.dataTransfer.setData('text/plain', event.target.id);\n draggable.classList.add(DRAGGING_CLASS);\n }\n };\n\n const onDragEnd = (event) => {\n const draggable = closest(event.target, DRAGGABLE_CLASS);\n if (draggable) {\n draggable.classList.remove(DRAGGING_CLASS);\n draggable.setAttribute('draggable', 'false');\n }\n };\n\n const onDragOver = (event) => {\n const draggableContainer = closest(event.target, DRAGGABLE_CONTAINER_CLASS);\n if (draggableContainer) {\n event.preventDefault();\n }\n };\n\n const onDrop = (event) => {\n const draggable = document.getElementById(event.dataTransfer.getData('text/plain'));\n if (draggable) {\n event.preventDefault();\n\n const container = closest(draggable, DRAGGABLE_CONTAINER_CLASS);\n\n const insertBefore = (() => {\n // Were we dropped onto another draggable?\n const dropDraggable = closest(event.target, DRAGGABLE_CLASS);\n if (dropDraggable) {\n /*\n * Were we dropped in the top half or the bottom half of the target draggable?\n * - Top half - insert before that draggable.\n * - Bottom half - insert after that draggable.\n */\n const { height, top } = dropDraggable.getBoundingClientRect();\n const isTopHalf = event.clientY < top + height / 2;\n return isTopHalf ? dropDraggable : dropDraggable.nextSibling;\n }\n\n // We were dropped into empty space - find the closest draggable by geometry.\n return [...container.children].find((child) => {\n const { left, right, top } = child.getBoundingClientRect();\n // Are we in the correct column?\n if (left > event.clientX) {\n // Found the first child that is too far to the right, so we insert before that child.\n return true;\n } else if (right >= event.clientX) {\n // Child is in the correct column.\n if (top >= event.clientY) {\n // Found the first child in this column we were dropped above, so we insert before that child.\n return true;\n }\n }\n return false;\n });\n })();\n\n if (insertBefore) {\n container.insertBefore(draggable, insertBefore);\n } else {\n // Add to end of the list.\n container.append(draggable);\n }\n\n draggable.classList.add(DRAGGING_CLASS);\n }\n };\n\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('mousedown', onMouseDown);\n document.addEventListener('mouseup', onMouseUp);\n document.addEventListener('dragstart', onDragStart);\n document.addEventListener('dragend', onDragEnd);\n document.addEventListener('dragover', onDragOver);\n document.addEventListener('drop', onDrop);\n};\n","const DRAWER_CLASS = 'nb-drawer';\nconst DRAWER_OPEN_CLASS = 'nb-drawer-open';\n\n/**\n * Toggle drawer element with an option to force open/close.\n * @param {HTMLElement} drawer - Drawer HTML element to be toggled.\n * @param {boolean} [force] - Optionally force opening (`true`) or closing (`false`) regardless of current state.\n * @returns {void} Do not return any value, modify existing HTML element in-place.\n */\nconst toggleDrawer = (drawer, force) => {\n if (!drawer) {\n return;\n }\n\n drawer.classList.toggle(DRAWER_OPEN_CLASS, force);\n\n const isOpen = drawer.classList.contains(DRAWER_OPEN_CLASS);\n\n drawer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n\n const drawerToggles = [...document.querySelectorAll(`[data-nb-toggle=\"drawer\"][data-nb-target=\"#${drawer.id}\"]`)];\n drawerToggles.forEach((drawerToggle) => drawerToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'));\n\n /*\n * Maintain proper element focus when the drawer is:\n * 1. Open - focus the drawer as soon as it becomes visible and focusable.\n * 2. Closed - in case focus is within the drawer move it back to the first found drawer toggle and, if not\n * available, the `main` element instead.\n */\n if (isOpen) {\n // Close other open drawers if there are any. Effectively, this allows only one drawer to be open at a time.\n const openDrawers = document.getElementsByClassName(DRAWER_OPEN_CLASS);\n [...openDrawers]\n .filter((openDrawer) => openDrawer !== drawer)\n .forEach((openDrawer) => toggleDrawer(openDrawer, false));\n\n (() => {\n let rafRetriesRemaining = 100; // In case something goes wrong prevent falling into an infinite loop.\n\n // Use `requestAnimationFrame` to wait until drawer becomes visible and focusable.\n window.requestAnimationFrame(function focusDrawer() {\n const isDrawerVisible = window.getComputedStyle(drawer).visibility === 'visible';\n\n if (isDrawerVisible) {\n drawer.focus();\n } else if (rafRetriesRemaining > 0) {\n rafRetriesRemaining -= 1;\n window.requestAnimationFrame(focusDrawer);\n }\n });\n })();\n } else if (drawer.contains(document.activeElement)) {\n const nextActiveElement = drawerToggles[0] || document.querySelector('main');\n nextActiveElement?.focus({ preventScroll: true });\n }\n\n const event = isOpen ? 'nb-drawer:opened' : 'nb-drawer:closed';\n drawer.dispatchEvent(new CustomEvent(event, { bubbles: true, cancelable: true }));\n};\n\n/**\n * Initialize custom Nautobot drawers mechanism.\n * @returns {void} Do not return any value, attach an event listener.\n */\nexport const initializeDrawers = () => {\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('nb-drawer:close', (event) => toggleDrawer(event.target, false));\n document.addEventListener('nb-drawer:open', (event) => toggleDrawer(event.target, true));\n document.addEventListener('nb-drawer:toggle', (event) => toggleDrawer(event.target));\n\n document.addEventListener('nb-drawer:opened', (event) => {\n if (event.target.id) {\n const nextState = { ...window.history?.state, drawer: event.target.id };\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(nextState, '', url);\n }\n });\n\n document.addEventListener('nb-drawer:closed', () => {\n // eslint-disable-next-line no-unused-vars\n const { drawer, ...restState } =\n typeof window.history?.state === 'object' && window.history.state !== null ? window.history.state : {};\n const nextState = Object.keys(restState).length > 0 ? restState : null;\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(nextState, '', url);\n });\n\n document.addEventListener('click', (event) => {\n const dismiss = event.target.closest('[data-nb-dismiss]');\n const toggle = event.target.closest('[data-nb-toggle]');\n\n if (dismiss?.dataset.nbDismiss === 'drawer') {\n const drawer = dismiss.closest(`.${DRAWER_CLASS}`);\n drawer?.dispatchEvent(new CustomEvent(`nb-drawer:close`, { bubbles: true, cancelable: true }));\n } else if (toggle?.dataset.nbToggle === 'drawer') {\n const drawer = document.querySelector(toggle.dataset.nbTarget);\n drawer?.dispatchEvent(new CustomEvent(`nb-drawer:toggle`, { bubbles: true, cancelable: true }));\n }\n });\n\n if (window.history?.state?.drawer) {\n document\n .getElementById(window.history.state.drawer)\n ?.dispatchEvent(new CustomEvent('nb-drawer:open', { bubbles: true, cancelable: true }));\n }\n};\n","const SESSION_STORAGE_KEY = 'historyState';\n\n/**\n * Load last saved history state from `sessionStorage`.\n *\n * *The idea behind this and `saveState` function below is to be able to maintain history state between history entries\n * separated by a full document reload caused by navigation or form submission. Browsers do not export any native API\n * to manage history state in said scenario, so the workaround is to call `saveState` before full document reload and\n * then `loadState` after the document is loaded back again. `saveState` must be called on demand by arbitrary logic,\n * whereas `loadState` is executed automatically by the main `nautobot.js` script and should not be called manually.*\n *\n * @returns {void} Do not return any value, update current history entry with last saved state instead.\n */\nexport const loadState = () => {\n const state = (() => {\n try {\n const item = window.sessionStorage?.getItem(SESSION_STORAGE_KEY);\n return item ? JSON.parse(item) : undefined;\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return undefined;\n }\n })();\n\n if (state !== undefined) {\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(state, '', url);\n window.sessionStorage?.removeItem(SESSION_STORAGE_KEY);\n }\n};\n\n/**\n * Save given state, or current history entry state if not explicitly passed, into `sessionStorage`.\n *\n * *The idea behind this and `loadState` function above is to be able to maintain history state between history entries\n * separated by a full document reload caused by navigation or form submission. Browsers do not export any native API\n * to manage history state in said scenario, so the workaround is to call `saveState` before full document reload and\n * then `loadState` after the document is loaded back again. `saveState` must be called on demand by arbitrary logic,\n * whereas `loadState` is executed automatically by the main `nautobot.js` script and should not be called manually.*\n *\n * @param {object|null} [state] - Optional `state` object to be saved; current history entry state will be used if\n * `state` is not explicitly passed. Use `null` to remove history state from `sessionStorage`.\n * @returns {void} Do not return any value, save current history entry state into `sessionStorage` instead.\n */\nexport const saveState = (state) => {\n const stateToSave = state === undefined ? window.history?.state : state;\n\n if (stateToSave !== undefined) {\n window.sessionStorage?.setItem(SESSION_STORAGE_KEY, JSON.stringify(stateToSave));\n }\n};\n","/**\n * This function is heavily inspired by React `createElement`. Its purpose is to remove some boilerplate code otherwise\n * required for creating new HTML elements.\n * @example\n * // Create `row` and `col` elements with a valid parent-child relationship.\n * const child = createElement('div', { className: 'col' });\n * const parent = createElement('div', { className: 'row' }, child);\n * @param {string} tag - HTML element tag name to be passed to `document.createElement` function.\n * @param {object} [attributes={}] - Object containing HTML element attributes to be set on newly created HTML element.\n * `class` attribute is a special case in which `className` property name can be optionally used in order to avoid\n * ambiguation with JavaScript reserved `class` keyword.\n * @param {(HTMLElement|string)} [children] - HTML elements or string values to become newly created element children.\n * @returns {HTMLElement} New HTML element. Append it to an existing DOM node if you want it to appear in browser.\n */\nexport const createElement = (tag, attributes = {}, ...children) => {\n const element = document.createElement(tag);\n\n Object.entries(attributes).forEach(([attribute, value]) =>\n element.setAttribute(attribute === 'className' ? 'class' : attribute, value),\n );\n\n children.forEach((child) =>\n typeof child === 'string' ? element.insertAdjacentText('beforeend', child) : element.appendChild(child),\n );\n\n return element;\n};\n\n/**\n * Remove all classes from given element, optionally excluding some explicitly.\n * @example\n * // Remove all classes except `container-fluid` from given element.\n * removeElementClasses(element, 'container-fluid');\n * @param {HTMLElement} element - HTML element which classes are to be removed.\n * @param {string} [ignore] - Classes to ignore during class removal, i.e. should be left as-is.\n * @returns {void} Do not return any value, modify existing HTML element in-place.\n */\nexport const removeElementClasses = (element, ...ignore) =>\n [...element.classList.entries()]\n .filter(([, className]) => !ignore.includes(className))\n .forEach(([, className]) => element.classList.remove(className));\n\n/**\n * Convert `px` pixel value to `rem` units.\n * @example\n * // Convert `20` (`px`) to `rem`, return `1.25` (`rem`).\n * rem(20);\n * @param {number} px - Pixel value.\n * @returns {number} Given pixel value converted to `rem` units.\n */\nexport const rem = (px) => {\n const rootFontSize = window.getComputedStyle(document.documentElement).fontSize;\n return px / parseInt(rootFontSize, 10);\n};\n","import { createElement, rem } from './utils.js';\n\nconst FORM_CONTROL_PADDING_X = rem(12);\nconst GAP = rem(6);\nconst ICON_SIZE = rem(20);\n\nconst BASE_SEARCH_INPUT_PADDING_X = `${FORM_CONTROL_PADDING_X + ICON_SIZE + GAP}rem`;\n\nconst MAX_BADGE_COUNT = 1;\n\nexport const initializeSearch = () => {\n const headerSearch = document.getElementById('header_search');\n\n // Do nothing and `return` early when there is no `#header_search` element in the page.\n if (!headerSearch) {\n return () => {};\n }\n\n const NAV_MENU = (() => {\n try {\n const navMenu = document.getElementById('nav_menu');\n return navMenu ? JSON.parse(navMenu.textContent) : {};\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return {};\n }\n })();\n\n /*\n * Pick only the lowest level of nested `nav_menu` object. In TypeScript, it would be manifested as the following type:\n * `{ [item_link: string]: { name: string; weight: number } };`.\n */\n const SEARCHABLE_MODELS = Object.fromEntries(\n Object.entries(NAV_MENU.tabs).flatMap(([, tab_details]) =>\n Object.entries(tab_details.groups).flatMap(([, group_details]) =>\n Object.entries(group_details.items).map(([item_link, item_details]) => [item_link, item_details]),\n ),\n ),\n );\n\n const BADGE_REG_EXP = new RegExp(\n `^\\\\s*in\\\\s*:\\\\s*(${Object.entries(SEARCHABLE_MODELS)\n // Extend simple vanilla model name match with more word delimiter variants (or no word delimiters at all).\n .flatMap(([, { name }]) => [name, ...['', '_', '\\\\-'].map((delimiter) => name.replace(/\\s+/g, delimiter))])\n .join('|')})\\\\s+`,\n 'i',\n );\n\n const headerSearchInput = headerSearch.querySelector('input');\n\n const closeSearchPopup = () => {\n const searchPopup = document.getElementById('search_popup');\n\n if (searchPopup) {\n searchPopup.remove();\n document.body.classList.toggle('overflow-y-hidden', false);\n }\n };\n\n // Focus search input on Cmd+K or Ctrl+K shortcut and close search popup on Escape.\n const onKeyDown = (event) => {\n const isPressedCmd = event.getModifierState?.('Meta');\n const isPressedCtrl = event.ctrlKey;\n\n if ((isPressedCmd || isPressedCtrl) && event.key === 'k') {\n event.preventDefault();\n headerSearchInput.focus();\n } else if (event.key === 'Escape') {\n closeSearchPopup();\n }\n };\n\n document.addEventListener('keydown', onKeyDown);\n\n const openSearchPopup = () => {\n const searchPopup = document.getElementById('search_popup');\n\n // Just focus an existing search popup `input` and `return` early if `#searchPopup` is already open.\n if (searchPopup) {\n const input = searchPopup.querySelector('input');\n input?.focus();\n input?.setSelectionRange(-1, -1);\n return;\n }\n\n document.body.classList.toggle('overflow-y-hidden', true);\n\n const { left: mainLeft = 0, right: mainRight = 0 } = document.querySelector('main')?.getBoundingClientRect() ?? {};\n const { top: headerSearchInputTop } = headerSearchInput.getBoundingClientRect();\n\n const icon = createElement('span', {\n 'aria-hidden': 'true',\n className:\n 'mdi mdi-magnify d-inline-flex ms-12 mt-6 pe-none position-absolute start-0 text-secondary top-0 user-select-none',\n style: `height: ${ICON_SIZE}rem; width: ${ICON_SIZE}rem;`,\n });\n\n const badges = createElement('span', {\n className: 'd-inline-flex gap-6 left-0 my-6 position-absolute top-0',\n style: `left: ${BASE_SEARCH_INPUT_PADDING_X};`,\n });\n\n const input = createElement('input', {\n className: 'form-control w-100',\n name: 'q',\n required: 'true',\n style: `padding-inline: ${BASE_SEARCH_INPUT_PADDING_X};`,\n type: 'search',\n value: headerSearchInput.value,\n });\n\n const clear = createElement(\n 'button',\n {\n className: `btn mdi mdi-close bg-transparent border-0 end-0 hstack justify-content-center me-12 mt-6 p-0 position-absolute text-secondary top-0 nb-transition-base${input.value === '' ? ' invisible opacity-0' : ''}`,\n style: `height: ${ICON_SIZE}rem; width: ${ICON_SIZE}rem;`,\n type: 'button',\n },\n createElement('span', { className: 'visually-hidden' }, 'Clear'),\n );\n\n clear.addEventListener('click', () => {\n input.value = '';\n input.dispatchEvent(new InputEvent('input'));\n input.focus();\n });\n\n input.addEventListener('input', () => {\n const shouldHideClear = input.value === '';\n clear.classList.toggle('invisible', shouldHideClear);\n clear.classList.toggle('opacity-0', shouldHideClear);\n });\n\n const submit = createElement('input', { className: 'd-none', type: 'submit' });\n\n const form = createElement(\n 'form',\n { action: headerSearch.getAttribute('action'), className: 'position-relative w-100', role: 'search' },\n icon,\n badges,\n input,\n clear,\n submit,\n );\n\n /* In case there is no badge, use global search. Otherwise, navigate to badge specific model list view. */\n form.addEventListener('submit', () => {\n const badge = form.querySelector('[data-nb-link]:last-child');\n\n if (badge) {\n form.setAttribute('action', badge.dataset.nbLink);\n }\n });\n\n const results = createElement('div');\n\n const popup = createElement(\n 'div',\n { className: 'mx-auto w-100', style: `max-width: ${rem(720)}rem;` },\n form,\n results,\n );\n\n const overlay = createElement(\n 'div',\n {\n className: 'overflow-auto pb-20 position-fixed top-0 end-0 bottom-0 start-0 nb-z-modal-backdrop',\n id: 'search_popup',\n role: 'dialog',\n style: `background-color: rgba(0, 0, 0, .5); padding-block-start: ${headerSearchInputTop}px; padding-inline-start: calc(${mainLeft}px + ${rem(20)}rem); padding-inline-end: calc(100% - ${mainRight}px + ${rem(20)}rem);`,\n },\n popup,\n );\n\n // Close search popup on direct overlay click.\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) {\n closeSearchPopup();\n }\n });\n\n document.body.appendChild(overlay);\n\n const addBadge = (link) => {\n const name = Object.entries(SEARCHABLE_MODELS).find(([item_link]) => item_link === link)?.[1]?.name ?? link;\n\n const removeButton = createElement(\n 'button',\n { type: 'button' },\n createElement('span', { 'aria-hidden': 'true', class: 'mdi mdi-close' }),\n createElement('span', { class: 'visually-hidden' }, 'Remove'),\n );\n\n const badge = createElement(\n 'span',\n { className: 'badge border', 'data-nb-link': link },\n `in: ${name}`,\n removeButton,\n );\n\n removeButton.addEventListener('click', () => {\n badge.remove();\n input.focus();\n });\n\n // Before adding a new badge, remove existing badges with the same `link` to prevent duplicates.\n [...badges.querySelectorAll(`[data-nb-link=\"${link}\"]`)].forEach((existing) => existing.remove());\n\n badges.appendChild(badge);\n\n // Obey the `MAX_BADGE_COUNT` constraint.\n [...badges.children].slice(0, -1 * MAX_BADGE_COUNT).forEach((child) => child.remove());\n };\n\n // Recalculate search input left padding when badges container size changes, i.e. a badge is added or removed.\n const resizeObserver = new ResizeObserver(() => {\n const { width } = badges.getBoundingClientRect();\n input.style.paddingInlineStart = width\n ? `calc(${BASE_SEARCH_INPUT_PADDING_X} + ${width}px + ${GAP}rem)`\n : BASE_SEARCH_INPUT_PADDING_X;\n });\n\n resizeObserver.observe(badges);\n\n input.addEventListener('input', () => {\n const match = input.value.match(BADGE_REG_EXP);\n\n if (match) {\n const [phrase, model] = match;\n\n const normalize = (text) =>\n text\n .trim()\n .toLowerCase()\n .replace(/\\s|_|-/g, '');\n const link = Object.entries(SEARCHABLE_MODELS).find(\n ([, { name }]) => normalize(name) === normalize(model),\n )?.[0];\n\n if (link) {\n // Remove phrase that matched the badge-specific regular expression and replace it with a corresponding badge.\n input.value = input.value.replace(phrase, '');\n input.dispatchEvent(new InputEvent('input'));\n addBadge(link);\n }\n }\n });\n\n // Remove the first badge on the right-hand side when `'Backspace'` key is pressed on the input start position.\n input.addEventListener('keydown', (event) => {\n const isBackspace = event.key === 'Backspace';\n const isInputStart = input.selectionEnd === 0 && input.selectionStart === 0;\n\n if (isBackspace && isInputStart) {\n badges.querySelector(':last-child')?.remove();\n }\n });\n\n // When search popup is open, copy existing badges from `#header_search` to search popup input.\n headerSearch.querySelectorAll('[data-nb-link]').forEach((badge) => addBadge(badge.dataset.nbLink));\n\n // Automatically focus search popup input when opened and move cursor to the end of input field.\n input.focus();\n input.setSelectionRange(-1, -1);\n };\n\n headerSearchInput.addEventListener('focus', openSearchPopup);\n\n return () => {\n closeSearchPopup();\n document.removeEventListener('keydown', onKeyDown);\n headerSearchInput.removeEventListener('focus', openSearchPopup);\n };\n};\n","import get from 'lodash.get';\n\n/**\n * Get HTML `element`. This function accepts input as native `Document` and `Element` object and `jQuery` collection.\n * It should no longer be required after migrating away from jQuery.\n * @param {Document|Element|jQuery} `element` - `element` in question.\n * @returns {Document|Element} Native `element` object.\n */\nconst getElement = (element) => (element instanceof Document || element instanceof Element ? element : element[0]);\n\n/**\n * Get `select` element value.\n * @param {HTMLSelectElement} select - `select` element in question.\n * @returns {string|string[]} `string` value for single combobox, an array of `string` values for multiple combobox.\n */\nconst getValue = (select) =>\n select?.getAttribute('multiple') === null ? select?.value : [...select.selectedOptions].map((option) => option.value);\n\n/**\n * Set Select2 combobox value(s).\n * @param {HTMLSelectElement} select2 - Select2 combobox HTML element.\n * @param {{ text: string, value: string }[]|null} value - Array of objects containing `text` and `value` key-value\n * pairs; `null` to reset the field value.\n */\nexport const setSelect2Value = (select2, value) => {\n $(select2).val(null);\n\n (value ?? []).forEach((attributes) => {\n if (!select2.querySelector(`option[value=\"${attributes.value}\"]`)) {\n const option = document.createElement('option');\n option.innerText = attributes.text;\n option.setAttribute('selected', 'true');\n option.setAttribute('value', attributes.value);\n select2.appendChild(option);\n }\n });\n\n const nextValue = (() => {\n if (value.length > 0) {\n const isMultiple = select2?.getAttribute('multiple') !== null;\n return isMultiple ? value.map((attributes) => attributes.value) : value?.[0]?.value;\n }\n\n return null;\n })();\n\n $(select2).val(nextValue).trigger('change');\n};\n\n/**\n * Parse URLs which may contain variable references to other field values.\n * @param {string} url - URL template string.\n * @returns {string} URL with interpolated dynamic values.\n */\nconst parseURL = (url) => {\n const filter_regex = /\\{\\{([a-z_]+)}}/g;\n\n let match; // eslint-disable-line init-declarations\n let rendered_url = url;\n\n while ((match = filter_regex.exec(url))) {\n const filter_field = document.querySelector(`#id_${match[1]}`);\n const custom_attribute = filter_field?.selectedOptions?.[0]?.getAttribute('api-value');\n const replace =\n custom_attribute || filter_field.value || (filter_field.getAttribute('data-null-option') ? 'null' : undefined);\n\n rendered_url = replace ? rendered_url.replace(match[0], replace) : rendered_url;\n }\n\n return rendered_url;\n};\n\n/**\n * Initialize given Select2 components in passed `context` by `selector`, optionally with `options`.\n * @param {Document|Element|jQuery} context - Context root element.\n * @param {string} selector - CSS query selector of `select` elements to be initialized as Select2 components.\n * @param {object} [options] - Optional Select2 components initialization options.\n * @returns {void} Do not return any value, just initialize given Select2 components.\n */\nconst initializeSelect2 = (context, selector, options) =>\n [...getElement(context).querySelectorAll(selector)].forEach((element) =>\n $(element).select2({\n allowClear: true,\n placeholder: element.getAttribute('placeholder') || '---------',\n selectionCssClass: 'select2--small',\n theme: 'bootstrap-5',\n width: 'off',\n ...options,\n }),\n );\n\nconst initializeColorPicker = (context, dropdownParent = null) => {\n // Assign color picker selection classes.\n const colorPickerClassCopy = (data, container) => {\n if (data.element) {\n // Swap the style.\n const containerElement = getElement(container);\n containerElement.setAttribute('style', data.element.getAttribute('style'));\n }\n\n return data.text;\n };\n\n initializeSelect2(context, '.nautobot-select2-color-picker', {\n dropdownParent,\n templateResult: colorPickerClassCopy,\n templateSelection: colorPickerClassCopy,\n });\n};\n\nconst initializeDynamicChoiceSelection = (context, dropdownParent = null) => {\n initializeSelect2(context, '.nautobot-select2-api', {\n ajax: {\n data: function data(params) {\n const [element] = this;\n\n // Paging. Note that `params.page` indexes at 1.\n const offset = (params.page - 1) * 50 || 0;\n\n // Base query params.\n const limit = 50;\n const q = params.term;\n\n // Get search query param name, defaults to `'q'`.\n const search_field = element.getAttribute('search-field') || 'q';\n\n // Set api_version.\n const api_version = element.getAttribute('data-api-version');\n\n // Allow for controlling the depth setting from within APISelect.\n const depth = parseInt(element.getAttribute('data-depth'), 10) || 0;\n\n // Attach content_type to parameters.\n const content_type = element.getAttribute('data-contenttype');\n\n // Attach any extra query parameters\n const extra_query_parameters = Object.fromEntries(\n [...element.attributes]\n .filter((attribute) => attribute.name.includes('data-query-param-'))\n .flatMap((attribute) => {\n const [, param_name] = attribute.name.split('data-query-param-');\n\n const values = (() => {\n try {\n return JSON.parse(attribute.value);\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return [];\n }\n })();\n\n return values.flatMap((value) => {\n const has_ref_field = value.startsWith('$');\n\n // Referencing the value of another form field.\n const ref_field = has_ref_field\n ? (() => {\n const name = value.slice(1);\n\n if (element.id.includes('id_form-')) {\n const [id_prefix] = element.id.match(/id_form-[0-9]+-/i, '');\n return document.querySelector(`#${id_prefix}${name}`);\n }\n\n /*\n * If the element is in a table row with a class containing \"dynamic-formset\" we need to find the\n * reference field in the same row.\n */\n if (element.closest('tr')?.classList.contains('dynamic-formset')) {\n return element.closest('tr').querySelector(`select[id*=\"${name}\"]`);\n }\n\n return document.querySelector(`#id_${name}`);\n })()\n : null;\n\n const ref_field_value = ref_field\n ? (() => {\n const field_value = getValue(ref_field);\n const style = window.getComputedStyle(ref_field);\n\n if (field_value && style.opacity !== '0' && style.visibility !== 'hidden') {\n return field_value;\n }\n\n if (ref_field.getAttribute('required') && ref_field.getAttribute('data-null-option')) {\n return 'null';\n }\n\n return undefined;\n })()\n : null;\n\n const param_value = has_ref_field ? ref_field_value : value;\n return param_value !== null && param_value !== undefined\n ? [[param_name, ref_field_value || value]]\n : [];\n });\n }),\n );\n\n const parameters = {\n depth: String(depth),\n limit: String(limit),\n offset: String(offset),\n ...(api_version ? { api_version } : undefined),\n ...(content_type ? { content_type } : undefined),\n ...(q ? { [search_field]: q } : undefined),\n ...extra_query_parameters,\n };\n\n // This will handle params with multiple values (i.e. for list filter forms).\n return new URLSearchParams(parameters).toString();\n },\n delay: 500,\n processResults: function processResults(data) {\n const [element] = this.$element;\n [...element.querySelectorAll('option')].forEach((child) => child.removeAttribute('disabled'));\n\n const results = [\n // Handle the null option, but only add it once.\n ...(element.getAttribute('data-null-option') && data.previous === null\n ? [{ id: 'null', text: element.getAttribute('data-null-option') }]\n : []),\n ...Object.values(\n data.results.reduce((accumulator, record, index) => {\n // The disabled-indicator equated to true, so we disable this option.\n const disabled = Boolean(record?.[element.getAttribute('disabled-indicator')]);\n const id = get(record, element.getAttribute('value-field')) || record.id;\n const text = get(record, element.getAttribute('display-field')) || record.name;\n\n const item = { ...record, disabled, id, text };\n const { group, site, url } = item;\n\n /*\n * `DynamicGroupSerializer` has a `children` field which fits an inappropriate if condition in\n * `select2.min.js`, which will result in the incorrect rendering of `DynamicGroup` `DynamicChoiceField`.\n * So we nullify the field here since we do not need this field.\n */\n const should_nullify_children = Boolean(url?.includes('dynamic-groups'));\n\n const collection = (() => {\n switch (true) {\n case group !== undefined && group !== null && site !== undefined && site !== null:\n return { property: `${site.name}:${group.name}`, text: `${site.name} / ${group.name}` };\n\n case group !== undefined && group !== null:\n return { property: group.name, text: group.name };\n\n case site !== undefined && site !== null:\n return { property: site.name, text: site.name };\n\n case group === null && site === null:\n return { property: 'global', text: 'Global' };\n\n default:\n return undefined;\n }\n })();\n\n return {\n ...accumulator,\n ...(collection\n ? {\n [collection.property]: {\n ...accumulator[collection.property],\n ...(accumulator[collection.property] ? undefined : { text: collection.text }),\n children: should_nullify_children\n ? undefined\n : [...(accumulator[collection.property]?.children ?? []), item],\n },\n }\n : { [index]: item }),\n };\n }, {}),\n ),\n ];\n\n // Check if there are more results to page.\n const has_next_page = data.next !== null;\n return { pagination: { more: has_next_page }, results };\n },\n url: function url() {\n const [element] = this;\n const dataUrl = parseURL(element.getAttribute('data-url'));\n\n // If URL is not fully rendered yet, abort the request.\n return !dataUrl.includes('{{') && dataUrl;\n },\n },\n dropdownParent,\n });\n};\n\nconst initializeMultiValueChar = (context, dropdownParent = null) =>\n initializeSelect2(context, '.nautobot-select2-multi-value-char', {\n dropdownParent,\n language: { noResults: () => 'Type something to add it as an option' },\n multiple: true,\n tags: true,\n });\n\nconst initializeStaticChoiceSelection = (context, dropdownParent = null) =>\n initializeSelect2(context, '.nautobot-select2-static', { dropdownParent });\n\nexport const initializeSelect2Fields = (context) => {\n initializeColorPicker(context);\n initializeDynamicChoiceSelection(context);\n initializeMultiValueChar(context);\n initializeStaticChoiceSelection(context);\n\n [...getElement(context).querySelectorAll('.modal')].forEach((modal) => {\n initializeColorPicker(modal, modal);\n initializeDynamicChoiceSelection(modal, modal);\n initializeMultiValueChar(modal, modal);\n initializeStaticChoiceSelection(modal, modal);\n });\n};\n","/**\n * Get given cookie, based on MDN example: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#example_2_get_a_sample_cookie_named_test2\n * @param {string} name - Cookie name.\n * @returns {string|undefined} Cookie value.\n */\nexport const getCookie = (name) =>\n document.cookie\n .split('; ')\n .find((cookie) => cookie.startsWith(`${name}=`))\n ?.split('=')[1];\n\n/**\n * Set given cookie `value` with optional `options`.\n * @param {string} name - Cookie name.\n * @param {string} value - Cookie value.\n * @param {object} [options] - Cookie properties as key-value pairs, e.g. `path`, `expires`, etc.\n * @returns {void} Do not return any value, modify existing document cookies in-place.\n */\nexport const setCookie = (name, value, options) => {\n const properties = { [name]: value, path: '/', ...options };\n document.cookie = Object.entries(properties)\n .map((entry) => entry.join('='))\n .join(';');\n};\n\n/**\n * Remove given cookie.\n * @param {string} name - Cookie name.\n * @returns {void} Do not return any value, modify existing document cookies in-place.\n */\nexport const removeCookie = (name) => setCookie(name, '', { expires: 'Thu, 01 Jan 1970 00:00:00 GMT' });\n","import { getCookie, removeCookie, setCookie } from './cookie.js';\n\nconst SIDENAV_COLLAPSED_KEY = 'sidenav_collapsed';\n\n/**\n * Expand/collapse sidenav.\n * @returns {void} Do not return any value, modify existing HTML elements, cookies and localStorage in-place.\n */\nexport const toggleSidenav = () => {\n const toggler = document.querySelector('.nb-sidenav-toggler');\n\n const controls = toggler.getAttribute('aria-controls');\n const expanded = toggler.getAttribute('aria-expanded') === 'true';\n\n toggler.setAttribute('aria-expanded', String(!expanded));\n\n const sidenav = document.getElementById(controls);\n sidenav.classList.toggle('nb-sidenav-collapsed', expanded);\n\n if (expanded) {\n setCookie(SIDENAV_COLLAPSED_KEY, 'true');\n window.localStorage?.setItem(SIDENAV_COLLAPSED_KEY, 'true');\n } else {\n removeCookie(SIDENAV_COLLAPSED_KEY);\n window.localStorage?.removeItem(SIDENAV_COLLAPSED_KEY);\n }\n};\n\n/**\n * Initialize sidenav mechanisms, i.e. expand/collapse, fly-outs, and optionally version control branch picker.\n * @returns {void} Do not return any value, attach event listeners.\n */\nexport const initializeSidenav = () => {\n const toggler = document.querySelector('.nb-sidenav-toggler');\n\n if (toggler) {\n /*\n * Check if sidenav expanded/collapsed initial state is valid. If not, amend it by calling `toggleSidenav()`. This\n * should not happen due to template code properly handling the initial render, but we're being extra careful here.\n */\n const sidenavCollapsedInitialState =\n getCookie(SIDENAV_COLLAPSED_KEY) ?? window.localStorage?.getItem(SIDENAV_COLLAPSED_KEY) ?? 'false';\n const shouldToggleSidenav =\n (sidenavCollapsedInitialState === 'true' && toggler.getAttribute('aria-expanded') === 'true') ||\n (sidenavCollapsedInitialState === 'false' && toggler.getAttribute('aria-expanded') === 'false');\n if (shouldToggleSidenav) {\n toggleSidenav();\n }\n\n toggler.addEventListener('click', toggleSidenav);\n }\n\n [...document.querySelectorAll('.nb-sidenav-list-item:not(.nb-flat)')].forEach((sidenavListItem) => {\n sidenavListItem.addEventListener('click', () => {\n const controls = sidenavListItem.getAttribute('aria-controls');\n const expanded = sidenavListItem.getAttribute('aria-expanded') === 'true';\n\n sidenavListItem.setAttribute('aria-expanded', String(!expanded));\n\n const onClickDocument = (documentClickEvent) => {\n const { target: documentClickTarget } = documentClickEvent;\n const sidenavFlyout = document.getElementById(controls);\n\n const isClickOutside =\n !sidenavListItem.contains(documentClickTarget) && !sidenavFlyout.contains(documentClickTarget);\n\n if (isClickOutside) {\n sidenavListItem.setAttribute('aria-expanded', 'false');\n document.removeEventListener('click', onClickDocument);\n }\n };\n\n if (expanded) {\n document.removeEventListener('click', onClickDocument);\n } else {\n document.addEventListener('click', onClickDocument);\n }\n });\n });\n\n const sidenavBranchPickerSelect = $('#sidenav-branch-picker-select');\n sidenavBranchPickerSelect.on('change', (event) => event.currentTarget.form.submit());\n sidenavBranchPickerSelect.on('select2:open', () => {\n document.querySelector('.select2-dropdown').setAttribute('data-bs-theme', 'dark');\n document.querySelector('.select2-dropdown .select2-search__field').setAttribute('placeholder', 'Find a branch...');\n });\n};\n","import * as bootstrap from 'bootstrap';\nimport { createElement, removeElementClasses } from './utils.js';\n\nconst TABS_HIDDEN_CLASSES = ['invisible', 'position-absolute'];\n\n/**\n * Collapse wrapped tabs to dropdown menu in given tab container.\n * @param {HTMLElement} tabs - Tab container HTML element.\n * @returns {void} Do not return any value, modify DOM instead.\n */\nexport const collapseTabs = (tabs) => {\n const tabsParent = tabs.parentNode;\n\n // Remove existing tab clones to prevent duplicates because they will be created from scratch below if needed.\n [...tabsParent.querySelectorAll('.nav.nav-tabs[data-clone=\"true\"]')].forEach((tabsClone) => tabsClone.remove());\n\n // For safety, do not operate on original tabs element, deep clone tabs to operate on its clone instead.\n const tabsClone = tabs.cloneNode(true);\n\n // Remove `id` element attribute from cloned tabs element to avoid potential `id` conflicts.\n tabsClone.removeAttribute('id');\n\n // Set `data-clone` attribute to `\"true\"` on tabs clone element to be able to easily distinguish it from the original.\n tabsClone.dataset.clone = 'true';\n\n /*\n * Add following classes to cloned element to:\n * 1. Make tabs span across the whole required width without wrapping.\n * 2. Force them to be (temporarily) invisible.\n */\n const tabsCloneTemporaryClasses = ['flex-nowrap', 'invisible', 'position-absolute', 'z-n1'];\n tabsClone.classList.add(...tabsCloneTemporaryClasses);\n\n // Append currently invisible cloned tabs to DOM right after the original tabs element.\n if (tabs.nextSibling) {\n tabsParent.insertBefore(tabsClone, tabs.nextSibling);\n } else {\n tabsParent.appendChild(tabsClone);\n }\n // Excessive tabs should be collapsed if tabs clone is wider than the original. Remember - clone does not wrap.\n const shouldCollapseTabs = () => tabsClone.getBoundingClientRect().width > tabs.getBoundingClientRect().width;\n\n // If there is no need to collapse tabs, show original tabs (if previously hidden) clean up tabs clone and `return` early.\n if (!shouldCollapseTabs()) {\n tabs.classList.remove(...TABS_HIDDEN_CLASSES);\n tabsParent.removeChild(tabsClone);\n return;\n }\n\n /*\n * Compose dropdown element. Ignore dropdown items for now, they will be added to the dropdown menu soon anyway. The\n * most important thing about this step is to append dropdown with visible toggle button at the end of cloned tabs\n * list to reach maximum width (dropdown toggle has considerable size too) before starting to actually collapse tabs.\n */\n const dropdownMenu = createElement('ul', { className: 'dropdown-menu dropdown-menu-end' });\n const dropdownToggleIcon = createElement('span', { className: 'mdi mdi-menu' });\n const dropdownToggleLabel = createElement('span', { className: 'visually-hidden' }, 'Toggle Dropdown');\n const dropdownToggle = createElement(\n 'button',\n {\n 'aria-expanded': 'false',\n className: 'btn dropdown-toggle text-secondary',\n 'data-bs-toggle': 'dropdown',\n type: 'button',\n },\n dropdownToggleIcon,\n dropdownToggleLabel,\n );\n const dropdown = createElement(\n 'li',\n { className: 'dropdown flex-grow-1 mb-n1 text-end' },\n dropdownToggle,\n dropdownMenu,\n );\n tabsClone.appendChild(dropdown);\n\n /*\n * Identify tabs that require collapsing by taking out one by one from the right-hand side until tabs width can fit\n * inside its parent container. Essentially, overflowing tabs are moved from tab list to future dropdown menu.\n */\n const collapsedTabs = [];\n while (shouldCollapseTabs()) {\n const lastTab = dropdown.previousElementSibling; // With dropdown appended to DOM, its previous siblings are tabs.\n collapsedTabs.unshift(lastTab); // Use `unshift` instead of `push` because this loop is iterating backward in a sense.\n tabsClone.removeChild(lastTab);\n }\n\n /*\n * Properly convert collapsed tabs to dropdown items:\n * 1. Remove all `<li>` `nav-item` element classes.\n * 2. Remove all `<a>` `nav-link` element classes other than `active` and `disabled` to maintain valid tab state.\n * 3. Add `dropdown-item` class to `<a>` element (formerly `nav-link`).\n * 4. Append collapsed tab to dropdown menu.\n */\n collapsedTabs.forEach((collapsedTab) => {\n removeElementClasses(collapsedTab);\n\n [...collapsedTab.children].forEach((navLink) => {\n removeElementClasses(navLink, 'active', 'disabled');\n navLink.classList.add('dropdown-item', 'justify-content-between');\n });\n\n dropdownMenu.appendChild(collapsedTab);\n });\n\n /*\n * Tabs clone with collapsed tabs is now ready to be swapped with original. The only thing left to do is to\n * make it synchronize its state back to the original.\n */\n [...tabsClone.querySelectorAll('a')].forEach((clonedTab) => {\n clonedTab.addEventListener('shown.bs.tab', () => {\n const originalTab = tabs.querySelector(`a[href=\"${clonedTab.getAttribute('href')}\"]`);\n const originalTabInstance = bootstrap.Tab.getInstance(originalTab) || new bootstrap.Tab(originalTab);\n originalTabInstance.show();\n });\n });\n\n // Swap tabs clone with the original, in other words swap wrapped tabs with collapsed tabs.\n tabs.classList.add(...TABS_HIDDEN_CLASSES);\n tabsClone.classList.remove(...tabsCloneTemporaryClasses);\n};\n\n/**\n * Observe size changes of all tab containers on the page and collapse tabs inside of them if they wrap.\n * @example\n * // Run `collapseTabs` algorithm for all tabs on the page exactly once, i.e. observe and immediately unobserve.\n * const unobserveCollapseTabs = observeCollapseTabs();\n * unobserveCollapseTabs();\n * @returns {function(): void} Unobserve function - disconnect all resize observers created during function call.\n */\nexport const observeCollapseTabs = () => {\n const resizeObservers = [...document.querySelectorAll('.nav.nav-tabs')].map((tabs) => {\n const resizeObserver = new ResizeObserver(() => collapseTabs(tabs));\n resizeObserver.observe(tabs);\n return resizeObserver;\n });\n\n return () => resizeObservers.forEach((resizeObserver) => resizeObserver.disconnect());\n};\n","import { getCookie, removeCookie, setCookie } from './cookie.js';\n\nconst THEME_MODAL_ID = 'theme_modal';\n\nconst THEME_DARK = 'dark';\nconst THEME_LIGHT = 'light';\nconst THEME_SYSTEM = 'system';\n\n/**\n * Get preferred system color scheme.\n * @returns {('dark'|'light')} Preferred system color scheme.\n */\nconst getPreferredColorScheme = () =>\n window.matchMedia?.(`(prefers-color-scheme: ${THEME_DARK})`).matches ? THEME_DARK : THEME_LIGHT;\n\n/**\n * Check if given `theme` is a valid Nautobot theme, i.e. `'dark'`, `'light'`, or `'system'`.\n * @param {string} theme - Theme in question.\n * @returns {boolean} `true` is given `theme` is a valid Nautobot theme, `false` otherwise.\n */\nconst isValidTheme = (theme) => theme === THEME_DARK || theme === THEME_LIGHT || theme === THEME_SYSTEM;\n\n/**\n * Automatically detect Nautobot theme. It is derived from `cookie` or `localStorage` if set manually, and falls back to\n * preferred system color scheme by default.\n * @returns {('dark'|'light'|'system')} Detected Nautobot theme.\n */\nconst detectTheme = () => {\n const cookieTheme = getCookie('theme');\n if (isValidTheme(cookieTheme)) {\n return cookieTheme;\n }\n\n const localStorageTheme = window.localStorage?.getItem('theme');\n if (isValidTheme(localStorageTheme)) {\n return localStorageTheme;\n }\n\n return THEME_SYSTEM;\n};\n\n/**\n * Set Nautobot theme.\n * @param {('dark'|'light'|'system')} theme - Nautobot theme to be set.\n * @param {{ manual?: boolean }} [options] - Setter function options object. Currently supported option is `manual`.\n * @returns {void} Do not return any value, set given `theme` and save it into a persistent store if `manual` is `true`.\n */\nconst setTheme = (theme, options) => {\n const isManual = Boolean(options?.manual);\n\n const modal = document.getElementById(THEME_MODAL_ID);\n const buttons = modal?.querySelectorAll('button[data-nb-theme]') ?? [];\n\n buttons.forEach((button) =>\n ['border', 'border-primary'].forEach((className) =>\n button.classList.toggle(className, button.dataset.nbTheme === theme),\n ),\n );\n\n const bsTheme = theme === THEME_SYSTEM ? getPreferredColorScheme() : theme;\n document.documentElement.dataset.theme = bsTheme;\n document.documentElement.dataset.bsTheme = bsTheme;\n\n if (theme === THEME_SYSTEM) {\n removeCookie('theme');\n window.localStorage?.removeItem('theme');\n } else if (isManual) {\n setCookie('theme', theme);\n window.localStorage?.setItem('theme', theme);\n }\n\n if (theme === THEME_DARK || (theme === THEME_SYSTEM && bsTheme === THEME_DARK)) {\n [...document.getElementsByTagName('object')].forEach((object) => {\n object.addEventListener('load', (event) => {\n if (event.target.contentDocument) {\n const images = event.target.contentDocument.getElementsByTagName('image');\n const short_names = event.target.contentDocument.getElementsByClassName('rack-device-shortname');\n const full_names = event.target.contentDocument.getElementsByClassName('rack-device-fullname');\n\n [...images, ...short_names, ...full_names].forEach((rack_image) =>\n rack_image.setAttribute('filter', 'url(#darkmodeinvert)'),\n );\n }\n });\n });\n }\n\n if (isManual) {\n document.location.reload();\n }\n};\n\nexport const initializeTheme = () => {\n const modal = document.getElementById(THEME_MODAL_ID);\n const buttons = modal?.querySelectorAll('button[data-nb-theme]') ?? [];\n\n setTheme(detectTheme());\n window.matchMedia(`(prefers-color-scheme: ${THEME_DARK})`).addEventListener('change', () => setTheme(detectTheme()));\n\n const onClick = (event) => setTheme(event.currentTarget.dataset.nbTheme, { manual: true });\n buttons.forEach((button) => button.addEventListener('click', onClick));\n\n return () => buttons.forEach((button) => button.removeEventListener('click', onClick));\n};\n","/* eslint import/order: ['error', { alphabetize: { order: 'asc' }, 'newlines-between': 'ignore' }] */\n\nimport '../scss/nautobot.scss';\n\nimport * as bootstrap from 'bootstrap';\nwindow.bootstrap = bootstrap;\n\nimport ClipboardJS from 'clipboard';\nwindow.ClipboardJS = ClipboardJS;\n\nimport * as echarts from 'echarts';\nwindow.echarts = echarts;\n\nimport flatpickr from 'flatpickr';\nwindow.flatpickr = flatpickr;\n\nimport hljs from 'highlight.js/lib/core';\nimport 'highlight.js/styles/github.css';\nimport graphql from 'highlight.js/lib/languages/graphql';\nimport json from 'highlight.js/lib/languages/json';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\n\nimport htmx from 'htmx.org';\nwindow.htmx = htmx;\n\nhljs.registerLanguage('graphql', graphql);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('yaml', yaml);\nwindow.hljs = hljs;\n\nimport jQuery from 'jquery';\nwindow.jQuery = jQuery;\nwindow.$ = window.jQuery;\n\nimport 'jquery-ui';\nimport 'select2';\n\nimport { initializeCollapseToggleAll } from './collapse.js';\nimport { initializeDraggable } from './draggable.js';\nimport { initializeDrawers } from './drawer.js';\nimport { observeFormStickyFooters } from './form.js';\nimport { loadState, saveState } from './history.js';\nimport { initializeSearch } from './search.js';\nimport { initializeSelect2Fields, setSelect2Value } from './select2.js';\nimport { initializeSidenav } from './sidenav.js';\nimport { observeCollapseTabs } from './tabs.js';\nimport { initializeTheme } from './theme.js';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n window.nb ??= {};\n\n // History\n loadState();\n window.nb.history = { saveState };\n // Tooltips\n // https://getbootstrap.com/docs/5.3/components/tooltips/#enable-tooltips\n [...document.querySelectorAll('[data-bs-toggle=\"tooltip\"]')].forEach((tooltip) => new bootstrap.Tooltip(tooltip));\n\n // Sidenav\n initializeSidenav();\n\n // Collapse\n initializeCollapseToggleAll();\n\n // Draggable\n initializeDraggable();\n\n // Drawer\n initializeDrawers();\n\n // Form\n // TODO(norbert-mieczkowski-codilime): for htmx SPA-like behavior, re-initialize sticky footers like tabs below.\n observeFormStickyFooters();\n\n // Search\n initializeSearch();\n\n // Select2\n window.nb.select2 = { initializeSelect2Fields, setSelect2Value };\n\n // Tabs\n /*\n * TODO(norbert-mieczkowski-codilime): listen for proper event type(s) to re-initialize collapse tabs observers when\n * htmx dynamic content reloading is implemented. Said re-initialization should be as simple as something like:\n * ```js\n * let unobserveCollapseTabs = observeCollapseTabs();\n * document.body.addEventListener('htmx:xhr:loadend', () => unobserveCollapseTabs());\n * document.body.addEventListener('htmx:load', () => {\n * unobserveCollapseTabs = observeCollapseTabs();\n * });\n * ```\n */\n observeCollapseTabs();\n\n // Theme\n initializeTheme();\n\n const toggleFavorite = (element, event) => {\n if (event.detail.successful) {\n element.classList.toggle('active');\n }\n };\n window.toggleFavorite = toggleFavorite;\n\n const setRequestUrl = (element, event) => {\n const isFavorite = element.classList.contains('active');\n event.detail.path = isFavorite ? element.dataset.deleteUrl : element.dataset.addUrl;\n };\n window.setRequestUrl = setRequestUrl;\n});\n","/**\n * Observe pinned state of elements of class `nb-form-sticky-footer` on the page and add drop shadow with `nb-is-pinned`\n * class if they are pinned. This is purely cosmetic and does not affect functionality.\n * @example\n * // Run form sticky footers observer algorithm exactly once, i.e. observe and immediately unobserve.\n * const unobserveFormStickyFooters = observeFormStickyFooters();\n * unobserveFormStickyFooters();\n * @returns {function(): void} Unobserve function - disconnect all resize observers created during function call.\n */\nexport const observeFormStickyFooters = () => {\n // Form sticky footers pinned state detection with `IntersectionObserver` based on: https://stackoverflow.com/a/57991537.\n const intersectionObserver = new IntersectionObserver(\n ([entry]) => entry.target.classList.toggle('nb-is-pinned', entry.intersectionRatio < 1),\n { threshold: [1] },\n );\n\n const formStickyFooters = [...document.querySelectorAll('.nb-form-sticky-footer')];\n formStickyFooters.forEach((formStickyFooter) => intersectionObserver.observe(formStickyFooter));\n\n return () => {\n intersectionObserver.disconnect();\n };\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t825: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknautobot\"] = self[\"webpackChunknautobot\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [68], () => (__webpack_require__(226)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","DRAGGABLE_CLASS","DRAGGABLE_CONTAINER_CLASS","DRAGGING_CLASS","DRAWER_OPEN_CLASS","toggleDrawer","drawer","force","classList","toggle","isOpen","contains","setAttribute","drawerToggles","document","querySelectorAll","id","forEach","drawerToggle","getElementsByClassName","filter","openDrawer","rafRetriesRemaining","window","requestAnimationFrame","focusDrawer","getComputedStyle","visibility","focus","activeElement","nextActiveElement","querySelector","preventScroll","event","dispatchEvent","CustomEvent","bubbles","cancelable","SESSION_STORAGE_KEY","saveState","state","stateToSave","undefined","history","sessionStorage","setItem","JSON","stringify","createElement","tag","attributes","children","element","Object","entries","attribute","value","child","insertAdjacentText","appendChild","removeElementClasses","ignore","className","includes","remove","rem","px","rootFontSize","documentElement","fontSize","parseInt","FORM_CONTROL_PADDING_X","GAP","ICON_SIZE","BASE_SEARCH_INPUT_PADDING_X","getElement","Document","Element","setSelect2Value","select2","$","val","option","innerText","text","nextValue","length","getAttribute","map","trigger","initializeSelect2","context","selector","options","allowClear","placeholder","selectionCssClass","theme","width","initializeColorPicker","dropdownParent","colorPickerClassCopy","data","container","templateResult","templateSelection","initializeDynamicChoiceSelection","ajax","params","this","offset","page","q","term","search_field","api_version","depth","content_type","extra_query_parameters","fromEntries","name","flatMap","param_name","split","parse","exception","has_ref_field","startsWith","ref_field","slice","id_prefix","match","closest","ref_field_value","field_value","select","selectedOptions","style","opacity","param_value","parameters","String","limit","URLSearchParams","toString","delay","processResults","$element","removeAttribute","results","previous","values","reduce","accumulator","record","index","disabled","Boolean","item","group","site","url","should_nullify_children","collection","property","pagination","more","next","dataUrl","filter_regex","rendered_url","exec","filter_field","custom_attribute","replace","parseURL","initializeMultiValueChar","language","noResults","multiple","tags","initializeStaticChoiceSelection","initializeSelect2Fields","modal","getCookie","cookie","find","setCookie","properties","path","entry","join","removeCookie","expires","SIDENAV_COLLAPSED_KEY","toggleSidenav","toggler","controls","expanded","getElementById","localStorage","removeItem","TABS_HIDDEN_CLASSES","THEME_MODAL_ID","THEME_DARK","THEME_LIGHT","THEME_SYSTEM","isValidTheme","detectTheme","cookieTheme","localStorageTheme","getItem","setTheme","isManual","manual","button","dataset","nbTheme","bsTheme","matchMedia","matches","getElementsByTagName","object","addEventListener","target","contentDocument","rack_image","location","reload","bootstrap","ClipboardJS","echarts","flatpickr","htmx","registerLanguage","graphql","json","xml","yaml","hljs","jQuery","nb","pathname","search","hash","replaceState","loadState","tooltip","sidenavCollapsedInitialState","sidenavListItem","onClickDocument","documentClickEvent","documentClickTarget","sidenavFlyout","removeEventListener","sidenavBranchPickerSelect","on","currentTarget","form","submit","initializeSidenav","areAll","collapseElements","collapsedOrExpanded","every","isCollapsed","getCollapseToggleAllTargets","collapseToggleAll","nbTarget","collapse","collapseInstance","Collapse","getOrCreateInstance","hide","show","textContent","initializeCollapseToggleAll","createHandleOnMouseListener","isDraggable","handle","onMouseDown","onMouseUp","draggable","dataTransfer","clearData","setData","add","preventDefault","getData","insertBefore","dropDraggable","height","top","getBoundingClientRect","clientY","nextSibling","left","right","clientX","append","initializeDraggable","nextState","restState","keys","dismiss","nbDismiss","nbToggle","intersectionObserver","IntersectionObserver","intersectionRatio","threshold","formStickyFooter","observe","observeFormStickyFooters","headerSearch","NAV_MENU","navMenu","SEARCHABLE_MODELS","tabs","tab_details","groups","group_details","items","item_link","item_details","BADGE_REG_EXP","RegExp","delimiter","headerSearchInput","closeSearchPopup","searchPopup","body","isPressedCmd","getModifierState","isPressedCtrl","ctrlKey","key","input","setSelectionRange","mainLeft","mainRight","headerSearchInputTop","icon","badges","required","type","clear","InputEvent","shouldHideClear","action","role","badge","nbLink","popup","overlay","addBadge","link","removeButton","class","existing","ResizeObserver","paddingInlineStart","phrase","model","normalize","trim","toLowerCase","isBackspace","isInputStart","selectionEnd","selectionStart","initializeSearch","resizeObservers","resizeObserver","tabsParent","parentNode","tabsClone","cloneNode","clone","tabsCloneTemporaryClasses","shouldCollapseTabs","removeChild","dropdownMenu","dropdownToggleIcon","dropdownToggleLabel","dropdownToggle","dropdown","collapsedTabs","lastTab","previousElementSibling","unshift","collapsedTab","navLink","clonedTab","originalTab","getInstance","collapseTabs","observeCollapseTabs","buttons","onClick","initializeTheme","toggleFavorite","detail","successful","setRequestUrl","isFavorite","deleteUrl","addUrl","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","call","m","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","splice","r","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","push","__webpack_exports__"],"sourceRoot":""}
1
+ {"version":3,"file":"js/nautobot.js","mappings":"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","sources":["webpack://nautobot/webpack/runtime/chunk loaded","webpack://nautobot/./src/js/collapse.js","webpack://nautobot/./src/js/draggable.js","webpack://nautobot/./src/js/drawer.js","webpack://nautobot/./src/js/history.js","webpack://nautobot/./src/js/utils.js","webpack://nautobot/./src/js/search.js","webpack://nautobot/./src/js/select2.js","webpack://nautobot/./src/js/cookie.js","webpack://nautobot/./src/js/sidenav.js","webpack://nautobot/./src/js/tabs.js","webpack://nautobot/./src/js/theme.js","webpack://nautobot/./src/js/nautobot.js","webpack://nautobot/./src/js/form.js","webpack://nautobot/webpack/bootstrap","webpack://nautobot/webpack/runtime/define property getters","webpack://nautobot/webpack/runtime/global","webpack://nautobot/webpack/runtime/hasOwnProperty shorthand","webpack://nautobot/webpack/runtime/make namespace object","webpack://nautobot/webpack/runtime/jsonp chunk loading","webpack://nautobot/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * Initialize collapse toggle all buttons identified by `data-nb-toggle=\"collapse-all\"` data attribute. Collapse toggle\n * all buttons can be further configured with `data-nb-target=\"{collapse CSS selector}\"` data attribute specifying which\n * collapse elements they control. When not explicitly set, target collapse CSS selector falls back to `\".collapse\"`.\n * ---\n * Critical difference between this and default Bootstrap 5 collapse implementation is that Bootstrap only supports\n * toggling individual panel states without an option to toggle them collectively. See an explanation below:\n * Bootstrap 5 on \"Collapse All Groups\" button click: | Nautobot on \"Collapse All Groups\" button click:\n * * X [expanded] -> [collapsed] | * X [expanded] -> [collapsed]\n * * Y [collapsed] -> [expanded] | * Y [collapsed] -> [collapsed]\n * * Z [expanded] -> [collapsed] | * Z [expanded] -> [collapsed]\n * ---\n * @returns {function(): void} Destructor function - remove all event listeners added during initialization.\n */\nexport const initializeCollapseToggleAll = () => {\n const areAll = (collapseElements, collapsedOrExpanded) =>\n collapseElements.every((element) => {\n const isCollapsed = !element.classList.contains('show');\n return collapsedOrExpanded === 'collapsed' ? isCollapsed : !isCollapsed;\n });\n\n const getCollapseToggleAllTargets = (collapseToggleAll) => [\n ...document.querySelectorAll(collapseToggleAll.dataset.nbTarget || '.collapse'),\n ];\n\n const onClick = (event) => {\n const collapseToggleAll = event.target.closest('[data-nb-toggle=\"collapse-all\"]');\n\n if (collapseToggleAll) {\n getCollapseToggleAllTargets(collapseToggleAll).forEach((collapse) => {\n const collapseInstance = window.bootstrap.Collapse.getOrCreateInstance(collapse);\n const shouldCollapse = collapseToggleAll.getAttribute('aria-expanded') === 'true';\n\n if (shouldCollapse) {\n collapseInstance.hide();\n } else {\n collapseInstance.show();\n }\n });\n }\n };\n\n const onHiddenBsCollapse = () =>\n [...document.querySelectorAll('[data-nb-toggle=\"collapse-all\"]')]\n .filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'collapsed'))\n .forEach((collapseToggleAll) => {\n collapseToggleAll.setAttribute('aria-expanded', 'false');\n collapseToggleAll.textContent = 'Expand All Groups';\n });\n\n const onShownBsCollapse = () =>\n [...document.querySelectorAll('[data-nb-toggle=\"collapse-all\"]')]\n .filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'expanded'))\n .forEach((collapseToggleAll) => {\n collapseToggleAll.setAttribute('aria-expanded', 'true');\n collapseToggleAll.textContent = 'Collapse All Groups';\n });\n\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('click', onClick);\n document.addEventListener('hidden.bs.collapse', onHiddenBsCollapse);\n document.addEventListener('shown.bs.collapse', onShownBsCollapse);\n\n return () => {\n document.removeEventListener('click', onClick);\n document.removeEventListener('hidden.bs.collapse', onHiddenBsCollapse);\n document.removeEventListener('shown.bs.collapse', onShownBsCollapse);\n };\n};\n","const DRAGGABLE_CLASS = 'nb-draggable';\nconst DRAGGABLE_CONTAINER_CLASS = 'nb-draggable-container';\nconst DRAGGABLE_HANDLE_CLASS = 'nb-draggable-handle';\nconst DRAGGING_CLASS = 'nb-dragging';\n\nexport const initializeDraggable = () => {\n const closest = (element, className) => element?.closest?.(`.${className}`);\n\n const createHandleOnMouseListener = (isDraggable) => (event) => {\n const handle = closest(event.target, DRAGGABLE_HANDLE_CLASS);\n if (handle) {\n const draggable = closest(handle, DRAGGABLE_CLASS);\n draggable.setAttribute('draggable', String(isDraggable));\n }\n };\n\n const onMouseDown = createHandleOnMouseListener(true);\n const onMouseUp = createHandleOnMouseListener(false);\n\n const onDragStart = (event) => {\n const draggable = closest(event.target, DRAGGABLE_CLASS);\n if (draggable) {\n event.dataTransfer.clearData('text/plain');\n event.dataTransfer.setData('text/plain', event.target.id);\n draggable.classList.add(DRAGGING_CLASS);\n }\n };\n\n const onDragEnd = (event) => {\n const draggable = closest(event.target, DRAGGABLE_CLASS);\n if (draggable) {\n draggable.classList.remove(DRAGGING_CLASS);\n draggable.setAttribute('draggable', 'false');\n }\n };\n\n const onDragOver = (event) => {\n const draggableContainer = closest(event.target, DRAGGABLE_CONTAINER_CLASS);\n if (draggableContainer) {\n event.preventDefault();\n }\n };\n\n const onDrop = (event) => {\n const draggable = document.getElementById(event.dataTransfer.getData('text/plain'));\n if (draggable) {\n event.preventDefault();\n\n const container = closest(draggable, DRAGGABLE_CONTAINER_CLASS);\n\n const insertBefore = (() => {\n // Were we dropped onto another draggable?\n const dropDraggable = closest(event.target, DRAGGABLE_CLASS);\n if (dropDraggable) {\n /*\n * Were we dropped in the top half or the bottom half of the target draggable?\n * - Top half - insert before that draggable.\n * - Bottom half - insert after that draggable.\n */\n const { height, top } = dropDraggable.getBoundingClientRect();\n const isTopHalf = event.clientY < top + height / 2;\n return isTopHalf ? dropDraggable : dropDraggable.nextSibling;\n }\n\n // We were dropped into empty space - find the closest draggable by geometry.\n return [...container.children].find((child) => {\n const { left, right, top } = child.getBoundingClientRect();\n // Are we in the correct column?\n if (left > event.clientX) {\n // Found the first child that is too far to the right, so we insert before that child.\n return true;\n } else if (right >= event.clientX) {\n // Child is in the correct column.\n if (top >= event.clientY) {\n // Found the first child in this column we were dropped above, so we insert before that child.\n return true;\n }\n }\n return false;\n });\n })();\n\n if (insertBefore) {\n container.insertBefore(draggable, insertBefore);\n } else {\n // Add to end of the list.\n container.append(draggable);\n }\n\n draggable.classList.add(DRAGGING_CLASS);\n }\n };\n\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('mousedown', onMouseDown);\n document.addEventListener('mouseup', onMouseUp);\n document.addEventListener('dragstart', onDragStart);\n document.addEventListener('dragend', onDragEnd);\n document.addEventListener('dragover', onDragOver);\n document.addEventListener('drop', onDrop);\n};\n","const DRAWER_CLASS = 'nb-drawer';\nconst DRAWER_OPEN_CLASS = 'nb-drawer-open';\n\n/**\n * Toggle drawer element with an option to force open/close.\n * @param {HTMLElement} drawer - Drawer HTML element to be toggled.\n * @param {boolean} [force] - Optionally force opening (`true`) or closing (`false`) regardless of current state.\n * @returns {void} Do not return any value, modify existing HTML element in-place.\n */\nconst toggleDrawer = (drawer, force) => {\n if (!drawer) {\n return;\n }\n\n drawer.classList.toggle(DRAWER_OPEN_CLASS, force);\n\n const isOpen = drawer.classList.contains(DRAWER_OPEN_CLASS);\n\n drawer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');\n\n const drawerToggles = [...document.querySelectorAll(`[data-nb-toggle=\"drawer\"][data-nb-target=\"#${drawer.id}\"]`)];\n drawerToggles.forEach((drawerToggle) => drawerToggle.setAttribute('aria-expanded', isOpen ? 'true' : 'false'));\n\n /*\n * Maintain proper element focus when the drawer is:\n * 1. Open - focus the drawer as soon as it becomes visible and focusable.\n * 2. Closed - in case focus is within the drawer move it back to the first found drawer toggle and, if not\n * available, the `main` element instead.\n */\n if (isOpen) {\n // Close other open drawers if there are any. Effectively, this allows only one drawer to be open at a time.\n const openDrawers = document.getElementsByClassName(DRAWER_OPEN_CLASS);\n [...openDrawers]\n .filter((openDrawer) => openDrawer !== drawer)\n .forEach((openDrawer) => toggleDrawer(openDrawer, false));\n\n (() => {\n let rafRetriesRemaining = 100; // In case something goes wrong prevent falling into an infinite loop.\n\n // Use `requestAnimationFrame` to wait until drawer becomes visible and focusable.\n window.requestAnimationFrame(function focusDrawer() {\n const isDrawerVisible = window.getComputedStyle(drawer).visibility === 'visible';\n\n if (isDrawerVisible) {\n drawer.focus();\n } else if (rafRetriesRemaining > 0) {\n rafRetriesRemaining -= 1;\n window.requestAnimationFrame(focusDrawer);\n }\n });\n })();\n } else if (drawer.contains(document.activeElement)) {\n const nextActiveElement = drawerToggles[0] || document.querySelector('main');\n nextActiveElement?.focus({ preventScroll: true });\n }\n\n const event = isOpen ? 'nb-drawer:opened' : 'nb-drawer:closed';\n drawer.dispatchEvent(new CustomEvent(event, { bubbles: true, cancelable: true }));\n};\n\n/**\n * Initialize custom Nautobot drawers mechanism.\n * @returns {void} Do not return any value, attach an event listener.\n */\nexport const initializeDrawers = () => {\n // Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.\n document.addEventListener('nb-drawer:close', (event) => toggleDrawer(event.target, false));\n document.addEventListener('nb-drawer:open', (event) => toggleDrawer(event.target, true));\n document.addEventListener('nb-drawer:toggle', (event) => toggleDrawer(event.target));\n\n document.addEventListener('nb-drawer:opened', (event) => {\n if (event.target.id) {\n const nextState = { ...window.history?.state, drawer: event.target.id };\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(nextState, '', url);\n }\n });\n\n document.addEventListener('nb-drawer:closed', () => {\n // eslint-disable-next-line no-unused-vars\n const { drawer, ...restState } =\n typeof window.history?.state === 'object' && window.history.state !== null ? window.history.state : {};\n const nextState = Object.keys(restState).length > 0 ? restState : null;\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(nextState, '', url);\n });\n\n document.addEventListener('click', (event) => {\n const dismiss = event.target.closest('[data-nb-dismiss]');\n const toggle = event.target.closest('[data-nb-toggle]');\n\n if (dismiss?.dataset.nbDismiss === 'drawer') {\n const drawer = dismiss.closest(`.${DRAWER_CLASS}`);\n drawer?.dispatchEvent(new CustomEvent(`nb-drawer:close`, { bubbles: true, cancelable: true }));\n } else if (toggle?.dataset.nbToggle === 'drawer') {\n const drawer = document.querySelector(toggle.dataset.nbTarget);\n drawer?.dispatchEvent(new CustomEvent(`nb-drawer:toggle`, { bubbles: true, cancelable: true }));\n }\n });\n\n if (window.history?.state?.drawer) {\n document\n .getElementById(window.history.state.drawer)\n ?.dispatchEvent(new CustomEvent('nb-drawer:open', { bubbles: true, cancelable: true }));\n }\n};\n","const SESSION_STORAGE_KEY = 'historyState';\n\n/**\n * Load last saved history state from `sessionStorage`.\n *\n * *The idea behind this and `saveState` function below is to be able to maintain history state between history entries\n * separated by a full document reload caused by navigation or form submission. Browsers do not export any native API\n * to manage history state in said scenario, so the workaround is to call `saveState` before full document reload and\n * then `loadState` after the document is loaded back again. `saveState` must be called on demand by arbitrary logic,\n * whereas `loadState` is executed automatically by the main `nautobot.js` script and should not be called manually.*\n *\n * @returns {void} Do not return any value, update current history entry with last saved state instead.\n */\nexport const loadState = () => {\n const state = (() => {\n try {\n const item = window.sessionStorage?.getItem(SESSION_STORAGE_KEY);\n return item ? JSON.parse(item) : undefined;\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return undefined;\n }\n })();\n\n if (state !== undefined) {\n const url = `${window.location.pathname}${window.location.search}${window.location.hash}`;\n window.history?.replaceState(state, '', url);\n window.sessionStorage?.removeItem(SESSION_STORAGE_KEY);\n }\n};\n\n/**\n * Save given state, or current history entry state if not explicitly passed, into `sessionStorage`.\n *\n * *The idea behind this and `loadState` function above is to be able to maintain history state between history entries\n * separated by a full document reload caused by navigation or form submission. Browsers do not export any native API\n * to manage history state in said scenario, so the workaround is to call `saveState` before full document reload and\n * then `loadState` after the document is loaded back again. `saveState` must be called on demand by arbitrary logic,\n * whereas `loadState` is executed automatically by the main `nautobot.js` script and should not be called manually.*\n *\n * @param {object|null} [state] - Optional `state` object to be saved; current history entry state will be used if\n * `state` is not explicitly passed. Use `null` to remove history state from `sessionStorage`.\n * @returns {void} Do not return any value, save current history entry state into `sessionStorage` instead.\n */\nexport const saveState = (state) => {\n const stateToSave = state === undefined ? window.history?.state : state;\n\n if (stateToSave !== undefined) {\n window.sessionStorage?.setItem(SESSION_STORAGE_KEY, JSON.stringify(stateToSave));\n }\n};\n","/**\n * This function is heavily inspired by React `createElement`. Its purpose is to remove some boilerplate code otherwise\n * required for creating new HTML elements.\n * @example\n * // Create `row` and `col` elements with a valid parent-child relationship.\n * const child = createElement('div', { className: 'col' });\n * const parent = createElement('div', { className: 'row' }, child);\n * @param {string} tag - HTML element tag name to be passed to `document.createElement` function.\n * @param {object} [attributes={}] - Object containing HTML element attributes to be set on newly created HTML element.\n * `class` attribute is a special case in which `className` property name can be optionally used in order to avoid\n * ambiguation with JavaScript reserved `class` keyword.\n * @param {(HTMLElement|string)} [children] - HTML elements or string values to become newly created element children.\n * @returns {HTMLElement} New HTML element. Append it to an existing DOM node if you want it to appear in browser.\n */\nexport const createElement = (tag, attributes = {}, ...children) => {\n const element = document.createElement(tag);\n\n Object.entries(attributes).forEach(([attribute, value]) =>\n element.setAttribute(attribute === 'className' ? 'class' : attribute, value),\n );\n\n children.forEach((child) =>\n typeof child === 'string' ? element.insertAdjacentText('beforeend', child) : element.appendChild(child),\n );\n\n return element;\n};\n\n/**\n * Remove all classes from given element, optionally excluding some explicitly.\n * @example\n * // Remove all classes except `container-fluid` from given element.\n * removeElementClasses(element, 'container-fluid');\n * @param {HTMLElement} element - HTML element which classes are to be removed.\n * @param {string} [ignore] - Classes to ignore during class removal, i.e. should be left as-is.\n * @returns {void} Do not return any value, modify existing HTML element in-place.\n */\nexport const removeElementClasses = (element, ...ignore) =>\n [...element.classList.entries()]\n .filter(([, className]) => !ignore.includes(className))\n .forEach(([, className]) => element.classList.remove(className));\n\n/**\n * Convert `px` pixel value to `rem` units.\n * @example\n * // Convert `20` (`px`) to `rem`, return `1.25` (`rem`).\n * rem(20);\n * @param {number} px - Pixel value.\n * @returns {number} Given pixel value converted to `rem` units.\n */\nexport const rem = (px) => {\n const rootFontSize = window.getComputedStyle(document.documentElement).fontSize;\n return px / parseInt(rootFontSize, 10);\n};\n","import { createElement, rem } from './utils.js';\n\nconst FORM_CONTROL_PADDING_X = rem(12);\nconst GAP = rem(6);\nconst ICON_SIZE = rem(20);\n\nconst BASE_SEARCH_INPUT_PADDING_X = `${FORM_CONTROL_PADDING_X + ICON_SIZE + GAP}rem`;\n\nconst MAX_BADGE_COUNT = 1;\n\nexport const initializeSearch = () => {\n const headerSearch = document.getElementById('header_search');\n\n // Do nothing and `return` early when there is no `#header_search` element in the page.\n if (!headerSearch) {\n return () => {};\n }\n\n const NAV_MENU = (() => {\n try {\n const navMenu = document.getElementById('nav_menu');\n return navMenu ? JSON.parse(navMenu.textContent) : {};\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return {};\n }\n })();\n\n /*\n * Pick only the lowest level of nested `nav_menu` object. In TypeScript, it would be manifested as the following type:\n * `{ [item_link: string]: { name: string; weight: number } };`.\n */\n const SEARCHABLE_MODELS = Object.fromEntries(\n Object.entries(NAV_MENU.tabs).flatMap(([, tab_details]) =>\n Object.entries(tab_details.groups).flatMap(([, group_details]) =>\n Object.entries(group_details.items).map(([item_link, item_details]) => [item_link, item_details]),\n ),\n ),\n );\n\n const BADGE_REG_EXP = new RegExp(\n `^\\\\s*in\\\\s*:\\\\s*(${Object.entries(SEARCHABLE_MODELS)\n // Extend simple vanilla model name match with more word delimiter variants (or no word delimiters at all).\n .flatMap(([, { name }]) => [name, ...['', '_', '\\\\-'].map((delimiter) => name.replace(/\\s+/g, delimiter))])\n .join('|')})\\\\s+`,\n 'i',\n );\n\n const headerSearchInput = headerSearch.querySelector('input');\n\n const closeSearchPopup = () => {\n const searchPopup = document.getElementById('search_popup');\n\n if (searchPopup) {\n searchPopup.remove();\n document.body.classList.toggle('overflow-y-hidden', false);\n }\n };\n\n // Focus search input on Cmd+K or Ctrl+K shortcut and close search popup on Escape.\n const onKeyDown = (event) => {\n const isPressedCmd = event.getModifierState?.('Meta');\n const isPressedCtrl = event.ctrlKey;\n\n if ((isPressedCmd || isPressedCtrl) && event.key === 'k') {\n event.preventDefault();\n headerSearchInput.focus();\n } else if (event.key === 'Escape') {\n closeSearchPopup();\n }\n };\n\n document.addEventListener('keydown', onKeyDown);\n\n const openSearchPopup = () => {\n const searchPopup = document.getElementById('search_popup');\n\n // Just focus an existing search popup `input` and `return` early if `#searchPopup` is already open.\n if (searchPopup) {\n const input = searchPopup.querySelector('input');\n input?.focus();\n input?.setSelectionRange(-1, -1);\n return;\n }\n\n document.body.classList.toggle('overflow-y-hidden', true);\n\n const { left: mainLeft = 0, right: mainRight = 0 } = document.querySelector('main')?.getBoundingClientRect() ?? {};\n const { top: headerSearchInputTop } = headerSearchInput.getBoundingClientRect();\n\n const icon = createElement('span', {\n 'aria-hidden': 'true',\n className:\n 'mdi mdi-magnify d-inline-flex ms-12 mt-6 pe-none position-absolute start-0 text-secondary top-0 user-select-none',\n style: `height: ${ICON_SIZE}rem; width: ${ICON_SIZE}rem;`,\n });\n\n const badges = createElement('span', {\n className: 'd-inline-flex gap-6 left-0 my-6 position-absolute top-0',\n style: `left: ${BASE_SEARCH_INPUT_PADDING_X};`,\n });\n\n const input = createElement('input', {\n className: 'form-control w-100',\n name: 'q',\n required: 'true',\n style: `padding-inline: ${BASE_SEARCH_INPUT_PADDING_X};`,\n type: 'search',\n value: headerSearchInput.value,\n });\n\n const clear = createElement(\n 'button',\n {\n className: `btn mdi mdi-close bg-transparent border-0 end-0 hstack justify-content-center me-12 mt-6 p-0 position-absolute text-secondary top-0 nb-transition-base${input.value === '' ? ' invisible opacity-0' : ''}`,\n style: `height: ${ICON_SIZE}rem; width: ${ICON_SIZE}rem;`,\n type: 'button',\n },\n createElement('span', { className: 'visually-hidden' }, 'Clear'),\n );\n\n clear.addEventListener('click', () => {\n input.value = '';\n input.dispatchEvent(new InputEvent('input'));\n input.focus();\n });\n\n input.addEventListener('input', () => {\n const shouldHideClear = input.value === '';\n clear.classList.toggle('invisible', shouldHideClear);\n clear.classList.toggle('opacity-0', shouldHideClear);\n });\n\n const submit = createElement('input', { className: 'd-none', type: 'submit' });\n\n const form = createElement(\n 'form',\n { action: headerSearch.getAttribute('action'), className: 'position-relative w-100', role: 'search' },\n icon,\n badges,\n input,\n clear,\n submit,\n );\n\n /* In case there is no badge, use global search. Otherwise, navigate to badge specific model list view. */\n form.addEventListener('submit', () => {\n const badge = form.querySelector('[data-nb-link]:last-child');\n\n if (badge) {\n form.setAttribute('action', badge.dataset.nbLink);\n }\n });\n\n const results = createElement('div');\n\n const popup = createElement(\n 'div',\n { className: 'mx-auto w-100', style: `max-width: ${rem(720)}rem;` },\n form,\n results,\n );\n\n const overlay = createElement(\n 'div',\n {\n className: 'overflow-auto pb-20 position-fixed top-0 end-0 bottom-0 start-0 nb-z-modal-backdrop',\n id: 'search_popup',\n role: 'dialog',\n style: `background-color: rgba(0, 0, 0, .5); padding-block-start: ${headerSearchInputTop}px; padding-inline-start: calc(${mainLeft}px + ${rem(20)}rem); padding-inline-end: calc(100% - ${mainRight}px + ${rem(20)}rem);`,\n },\n popup,\n );\n\n // Close search popup on direct overlay click.\n overlay.addEventListener('click', (event) => {\n if (event.target === overlay) {\n closeSearchPopup();\n }\n });\n\n document.body.appendChild(overlay);\n\n const addBadge = (link) => {\n const name = Object.entries(SEARCHABLE_MODELS).find(([item_link]) => item_link === link)?.[1]?.name ?? link;\n\n const removeButton = createElement(\n 'button',\n { type: 'button' },\n createElement('span', { 'aria-hidden': 'true', class: 'mdi mdi-close' }),\n createElement('span', { class: 'visually-hidden' }, 'Remove'),\n );\n\n const badge = createElement(\n 'span',\n { className: 'badge border', 'data-nb-link': link },\n `in: ${name}`,\n removeButton,\n );\n\n removeButton.addEventListener('click', () => {\n badge.remove();\n input.focus();\n });\n\n // Before adding a new badge, remove existing badges with the same `link` to prevent duplicates.\n [...badges.querySelectorAll(`[data-nb-link=\"${link}\"]`)].forEach((existing) => existing.remove());\n\n badges.appendChild(badge);\n\n // Obey the `MAX_BADGE_COUNT` constraint.\n [...badges.children].slice(0, -1 * MAX_BADGE_COUNT).forEach((child) => child.remove());\n };\n\n // Recalculate search input left padding when badges container size changes, i.e. a badge is added or removed.\n const resizeObserver = new ResizeObserver(() => {\n const { width } = badges.getBoundingClientRect();\n input.style.paddingInlineStart = width\n ? `calc(${BASE_SEARCH_INPUT_PADDING_X} + ${width}px + ${GAP}rem)`\n : BASE_SEARCH_INPUT_PADDING_X;\n });\n\n resizeObserver.observe(badges);\n\n input.addEventListener('input', () => {\n const match = input.value.match(BADGE_REG_EXP);\n\n if (match) {\n const [phrase, model] = match;\n\n const normalize = (text) =>\n text\n .trim()\n .toLowerCase()\n .replace(/\\s|_|-/g, '');\n const link = Object.entries(SEARCHABLE_MODELS).find(\n ([, { name }]) => normalize(name) === normalize(model),\n )?.[0];\n\n if (link) {\n // Remove phrase that matched the badge-specific regular expression and replace it with a corresponding badge.\n input.value = input.value.replace(phrase, '');\n input.dispatchEvent(new InputEvent('input'));\n addBadge(link);\n }\n }\n });\n\n // Remove the first badge on the right-hand side when `'Backspace'` key is pressed on the input start position.\n input.addEventListener('keydown', (event) => {\n const isBackspace = event.key === 'Backspace';\n const isInputStart = input.selectionEnd === 0 && input.selectionStart === 0;\n\n if (isBackspace && isInputStart) {\n badges.querySelector(':last-child')?.remove();\n }\n });\n\n // When search popup is open, copy existing badges from `#header_search` to search popup input.\n headerSearch.querySelectorAll('[data-nb-link]').forEach((badge) => addBadge(badge.dataset.nbLink));\n\n // Automatically focus search popup input when opened and move cursor to the end of input field.\n input.focus();\n input.setSelectionRange(-1, -1);\n };\n\n headerSearchInput.addEventListener('focus', openSearchPopup);\n\n return () => {\n closeSearchPopup();\n document.removeEventListener('keydown', onKeyDown);\n headerSearchInput.removeEventListener('focus', openSearchPopup);\n };\n};\n","import get from 'lodash.get';\n\n/**\n * Get HTML `element`. This function accepts input as native `Document` and `Element` object and `jQuery` collection.\n * It should no longer be required after migrating away from jQuery.\n * @param {Document|Element|jQuery} `element` - `element` in question.\n * @returns {Document|Element} Native `element` object.\n */\nconst getElement = (element) => (element instanceof Document || element instanceof Element ? element : element[0]);\n\n/**\n * Get `select` element value.\n * @param {HTMLSelectElement} select - `select` element in question.\n * @returns {string|string[]} `string` value for single combobox, an array of `string` values for multiple combobox.\n */\nconst getValue = (select) =>\n select?.getAttribute('multiple') === null ? select?.value : [...select.selectedOptions].map((option) => option.value);\n\n/**\n * Set Select2 combobox value(s).\n * @param {HTMLSelectElement} select2 - Select2 combobox HTML element.\n * @param {{ text: string, value: string }[]|null} value - Array of objects containing `text` and `value` key-value\n * pairs; `null` to reset the field value.\n */\nexport const setSelect2Value = (select2, value) => {\n $(select2).val(null);\n\n (value ?? []).forEach((attributes) => {\n if (!select2.querySelector(`option[value=\"${attributes.value}\"]`)) {\n const option = document.createElement('option');\n option.innerText = attributes.text;\n option.setAttribute('selected', 'true');\n option.setAttribute('value', attributes.value);\n select2.appendChild(option);\n }\n });\n\n const nextValue = (() => {\n if (value.length > 0) {\n const isMultiple = select2?.getAttribute('multiple') !== null;\n return isMultiple ? value.map((attributes) => attributes.value) : value?.[0]?.value;\n }\n\n return null;\n })();\n\n $(select2).val(nextValue).trigger('change');\n};\n\n/**\n * Parse URLs which may contain variable references to other field values.\n * @param {string} url - URL template string.\n * @returns {string} URL with interpolated dynamic values.\n */\nconst parseURL = (url) => {\n const filter_regex = /\\{\\{([a-z_]+)}}/g;\n\n let match; // eslint-disable-line init-declarations\n let rendered_url = url;\n\n while ((match = filter_regex.exec(url))) {\n const filter_field = document.querySelector(`#id_${match[1]}`);\n const custom_attribute = filter_field?.selectedOptions?.[0]?.getAttribute('api-value');\n const replace =\n custom_attribute || filter_field.value || (filter_field.getAttribute('data-null-option') ? 'null' : undefined);\n\n rendered_url = replace ? rendered_url.replace(match[0], replace) : rendered_url;\n }\n\n return rendered_url;\n};\n\n/**\n * Initialize given Select2 components in passed `context` by `selector`, optionally with `options`.\n * @param {Document|Element|jQuery} context - Context root element.\n * @param {string} selector - CSS query selector of `select` elements to be initialized as Select2 components.\n * @param {object} [options] - Optional Select2 components initialization options.\n * @returns {void} Do not return any value, just initialize given Select2 components.\n */\nconst initializeSelect2 = (context, selector, options) =>\n [...getElement(context).querySelectorAll(selector)].forEach((element) =>\n $(element).select2({\n allowClear: true,\n placeholder: element.getAttribute('placeholder') || '---------',\n selectionCssClass: 'select2--small',\n theme: 'bootstrap-5',\n width: 'off',\n ...options,\n }),\n );\n\nconst initializeColorPicker = (context, dropdownParent = null) => {\n // Assign color picker selection classes.\n const colorPickerClassCopy = (data, container) => {\n if (data.element) {\n // Swap the style.\n const containerElement = getElement(container);\n containerElement.setAttribute('style', data.element.getAttribute('style'));\n }\n\n return data.text;\n };\n\n initializeSelect2(context, '.nautobot-select2-color-picker', {\n dropdownParent,\n templateResult: colorPickerClassCopy,\n templateSelection: colorPickerClassCopy,\n });\n};\n\nconst initializeDynamicChoiceSelection = (context, dropdownParent = null) => {\n initializeSelect2(context, '.nautobot-select2-api', {\n ajax: {\n data: function data(params) {\n const [element] = this;\n\n // Paging. Note that `params.page` indexes at 1.\n const offset = (params.page - 1) * 50 || 0;\n\n // Base query params.\n const limit = 50;\n const q = params.term;\n\n // Get search query param name, defaults to `'q'`.\n const search_field = element.getAttribute('search-field') || 'q';\n\n // Set api_version.\n const api_version = element.getAttribute('data-api-version');\n\n // Allow for controlling the depth setting from within APISelect.\n const depth = parseInt(element.getAttribute('data-depth'), 10) || 0;\n\n // Attach content_type to parameters.\n const content_type = element.getAttribute('data-contenttype');\n\n // Attach any extra query parameters\n const extra_query_parameters = Object.fromEntries(\n [...element.attributes]\n .filter((attribute) => attribute.name.includes('data-query-param-'))\n .flatMap((attribute) => {\n const [, param_name] = attribute.name.split('data-query-param-');\n\n const values = (() => {\n try {\n return JSON.parse(attribute.value);\n // eslint-disable-next-line no-unused-vars\n } catch (exception) {\n return [];\n }\n })();\n\n return values.flatMap((value) => {\n const has_ref_field = value.startsWith('$');\n\n // Referencing the value of another form field.\n const ref_field = has_ref_field\n ? (() => {\n const name = value.slice(1);\n\n if (element.id.includes('id_form-')) {\n const [id_prefix] = element.id.match(/id_form-[0-9]+-/i, '');\n return document.querySelector(`#${id_prefix}${name}`);\n }\n\n /*\n * If the element is in a table row with a class containing \"dynamic-formset\" we need to find the\n * reference field in the same row.\n */\n if (element.closest('tr')?.classList.contains('dynamic-formset')) {\n return element.closest('tr').querySelector(`select[id*=\"${name}\"]`);\n }\n\n return document.querySelector(`#id_${name}`);\n })()\n : null;\n\n const ref_field_value = ref_field\n ? (() => {\n const field_value = getValue(ref_field);\n const style = window.getComputedStyle(ref_field);\n\n if (field_value && style.opacity !== '0' && style.visibility !== 'hidden') {\n return field_value;\n }\n\n if (ref_field.getAttribute('required') && ref_field.getAttribute('data-null-option')) {\n return 'null';\n }\n\n return undefined;\n })()\n : null;\n\n const param_value = has_ref_field ? ref_field_value : value;\n return param_value !== null && param_value !== undefined\n ? [[param_name, ref_field_value || value]]\n : [];\n });\n }),\n );\n\n const parameters = {\n depth: String(depth),\n limit: String(limit),\n offset: String(offset),\n ...(api_version ? { api_version } : undefined),\n ...(content_type ? { content_type } : undefined),\n ...(q ? { [search_field]: q } : undefined),\n ...extra_query_parameters,\n };\n\n // This will handle params with multiple values (i.e. for list filter forms).\n return new URLSearchParams(parameters).toString();\n },\n delay: 500,\n processResults: function processResults(data) {\n const [element] = this.$element;\n [...element.querySelectorAll('option')].forEach((child) => child.removeAttribute('disabled'));\n\n const results = [\n // Handle the null option, but only add it once.\n ...(element.getAttribute('data-null-option') && data.previous === null\n ? [{ id: 'null', text: element.getAttribute('data-null-option') }]\n : []),\n ...Object.values(\n data.results.reduce((accumulator, record, index) => {\n // The disabled-indicator equated to true, so we disable this option.\n const disabled = Boolean(record?.[element.getAttribute('disabled-indicator')]);\n const id = get(record, element.getAttribute('value-field')) || record.id;\n const text = get(record, element.getAttribute('display-field')) || record.name;\n\n const item = { ...record, disabled, id, text };\n const { group, site, url } = item;\n\n /*\n * `DynamicGroupSerializer` has a `children` field which fits an inappropriate if condition in\n * `select2.min.js`, which will result in the incorrect rendering of `DynamicGroup` `DynamicChoiceField`.\n * So we nullify the field here since we do not need this field.\n */\n const should_nullify_children = Boolean(url?.includes('dynamic-groups'));\n\n const collection = (() => {\n switch (true) {\n case group !== undefined && group !== null && site !== undefined && site !== null:\n return { property: `${site.name}:${group.name}`, text: `${site.name} / ${group.name}` };\n\n case group !== undefined && group !== null:\n return { property: group.name, text: group.name };\n\n case site !== undefined && site !== null:\n return { property: site.name, text: site.name };\n\n case group === null && site === null:\n return { property: 'global', text: 'Global' };\n\n default:\n return undefined;\n }\n })();\n\n return {\n ...accumulator,\n ...(collection\n ? {\n [collection.property]: {\n ...accumulator[collection.property],\n ...(accumulator[collection.property] ? undefined : { text: collection.text }),\n children: should_nullify_children\n ? undefined\n : [...(accumulator[collection.property]?.children ?? []), item],\n },\n }\n : { [index]: item }),\n };\n }, {}),\n ),\n ];\n\n // Check if there are more results to page.\n const has_next_page = data.next !== null;\n return { pagination: { more: has_next_page }, results };\n },\n url: function url() {\n const [element] = this;\n const dataUrl = parseURL(element.getAttribute('data-url'));\n\n // If URL is not fully rendered yet, abort the request.\n return !dataUrl.includes('{{') && dataUrl;\n },\n },\n dropdownParent,\n });\n};\n\nconst initializeMultiValueChar = (context, dropdownParent = null) =>\n initializeSelect2(context, '.nautobot-select2-multi-value-char', {\n dropdownParent,\n language: { noResults: () => 'Type something to add it as an option' },\n multiple: true,\n tags: true,\n });\n\nconst initializeStaticChoiceSelection = (context, dropdownParent = null) =>\n initializeSelect2(context, '.nautobot-select2-static', { dropdownParent });\n\nexport const initializeSelect2Fields = (context) => {\n initializeColorPicker(context);\n initializeDynamicChoiceSelection(context);\n initializeMultiValueChar(context);\n initializeStaticChoiceSelection(context);\n\n [...getElement(context).querySelectorAll('.modal')].forEach((modal) => {\n initializeColorPicker(modal, modal);\n initializeDynamicChoiceSelection(modal, modal);\n initializeMultiValueChar(modal, modal);\n initializeStaticChoiceSelection(modal, modal);\n });\n};\n","/**\n * Get given cookie, based on MDN example: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#example_2_get_a_sample_cookie_named_test2\n * @param {string} name - Cookie name.\n * @returns {string|undefined} Cookie value.\n */\nexport const getCookie = (name) =>\n document.cookie\n .split('; ')\n .find((cookie) => cookie.startsWith(`${name}=`))\n ?.split('=')[1];\n\n/**\n * Set given cookie `value` with optional `options`.\n * @param {string} name - Cookie name.\n * @param {string} value - Cookie value.\n * @param {object} [options] - Cookie properties as key-value pairs, e.g. `path`, `expires`, etc.\n * @returns {void} Do not return any value, modify existing document cookies in-place.\n */\nexport const setCookie = (name, value, options) => {\n const properties = { [name]: value, path: '/', ...options };\n document.cookie = Object.entries(properties)\n .map((entry) => entry.join('='))\n .join(';');\n};\n\n/**\n * Remove given cookie.\n * @param {string} name - Cookie name.\n * @returns {void} Do not return any value, modify existing document cookies in-place.\n */\nexport const removeCookie = (name) => setCookie(name, '', { expires: 'Thu, 01 Jan 1970 00:00:00 GMT' });\n","import { getCookie, removeCookie, setCookie } from './cookie.js';\n\nconst SIDENAV_COLLAPSED_KEY = 'sidenav_collapsed';\n\n/**\n * Expand/collapse sidenav.\n * @returns {void} Do not return any value, modify existing HTML elements, cookies and localStorage in-place.\n */\nexport const toggleSidenav = () => {\n const toggler = document.querySelector('.nb-sidenav-toggler');\n\n const controls = toggler.getAttribute('aria-controls');\n const expanded = toggler.getAttribute('aria-expanded') === 'true';\n\n toggler.setAttribute('aria-expanded', String(!expanded));\n\n const sidenav = document.getElementById(controls);\n sidenav.classList.toggle('nb-sidenav-collapsed', expanded);\n\n if (expanded) {\n setCookie(SIDENAV_COLLAPSED_KEY, 'true');\n window.localStorage?.setItem(SIDENAV_COLLAPSED_KEY, 'true');\n } else {\n removeCookie(SIDENAV_COLLAPSED_KEY);\n window.localStorage?.removeItem(SIDENAV_COLLAPSED_KEY);\n }\n};\n\n/**\n * Initialize sidenav mechanisms, i.e. expand/collapse, fly-outs, and optionally version control branch picker.\n * @returns {void} Do not return any value, attach event listeners.\n */\nexport const initializeSidenav = () => {\n const toggler = document.querySelector('.nb-sidenav-toggler');\n\n if (toggler) {\n /*\n * Check if sidenav expanded/collapsed initial state is valid. If not, amend it by calling `toggleSidenav()`. This\n * should not happen due to template code properly handling the initial render, but we're being extra careful here.\n */\n const sidenavCollapsedInitialState =\n getCookie(SIDENAV_COLLAPSED_KEY) ?? window.localStorage?.getItem(SIDENAV_COLLAPSED_KEY) ?? 'false';\n const shouldToggleSidenav =\n (sidenavCollapsedInitialState === 'true' && toggler.getAttribute('aria-expanded') === 'true') ||\n (sidenavCollapsedInitialState === 'false' && toggler.getAttribute('aria-expanded') === 'false');\n if (shouldToggleSidenav) {\n toggleSidenav();\n }\n\n toggler.addEventListener('click', toggleSidenav);\n }\n\n [...document.querySelectorAll('.nb-sidenav-list-item:not(.nb-flat)')].forEach((sidenavListItem) => {\n sidenavListItem.addEventListener('click', () => {\n const controls = sidenavListItem.getAttribute('aria-controls');\n const expanded = sidenavListItem.getAttribute('aria-expanded') === 'true';\n\n sidenavListItem.setAttribute('aria-expanded', String(!expanded));\n\n const onClickDocument = (documentClickEvent) => {\n const { target: documentClickTarget } = documentClickEvent;\n const sidenavFlyout = document.getElementById(controls);\n\n const isClickOutside =\n !sidenavListItem.contains(documentClickTarget) && !sidenavFlyout.contains(documentClickTarget);\n\n if (isClickOutside) {\n sidenavListItem.setAttribute('aria-expanded', 'false');\n document.removeEventListener('click', onClickDocument);\n }\n };\n\n if (expanded) {\n document.removeEventListener('click', onClickDocument);\n } else {\n document.addEventListener('click', onClickDocument);\n }\n });\n });\n\n const sidenavBranchPickerSelect = $('#sidenav-branch-picker-select');\n sidenavBranchPickerSelect.on('change', (event) => event.currentTarget.form.submit());\n sidenavBranchPickerSelect.on('select2:open', () => {\n document.querySelector('.select2-dropdown').setAttribute('data-bs-theme', 'dark');\n document.querySelector('.select2-dropdown .select2-search__field').setAttribute('placeholder', 'Find a branch...');\n });\n};\n","import * as bootstrap from 'bootstrap';\nimport { createElement, removeElementClasses } from './utils.js';\n\nconst TABS_HIDDEN_CLASSES = ['invisible', 'position-absolute'];\n\n/**\n * Collapse wrapped tabs to dropdown menu in given tab container.\n * @param {HTMLElement} tabs - Tab container HTML element.\n * @returns {void} Do not return any value, modify DOM instead.\n */\nexport const collapseTabs = (tabs) => {\n const tabsParent = tabs.parentNode;\n\n // Remove existing tab clones to prevent duplicates because they will be created from scratch below if needed.\n [...tabsParent.querySelectorAll('.nav.nav-tabs[data-clone=\"true\"]')].forEach((tabsClone) => tabsClone.remove());\n\n // For safety, do not operate on original tabs element, deep clone tabs to operate on its clone instead.\n const tabsClone = tabs.cloneNode(true);\n\n // Remove `id` element attribute from cloned tabs element to avoid potential `id` conflicts.\n tabsClone.removeAttribute('id');\n\n // Set `data-clone` attribute to `\"true\"` on tabs clone element to be able to easily distinguish it from the original.\n tabsClone.dataset.clone = 'true';\n\n /*\n * Add following classes to cloned element to:\n * 1. Make tabs span across the whole required width without wrapping.\n * 2. Force them to be (temporarily) invisible.\n */\n const tabsCloneTemporaryClasses = ['flex-nowrap', 'invisible', 'position-absolute', 'z-n1'];\n tabsClone.classList.add(...tabsCloneTemporaryClasses);\n\n // Append currently invisible cloned tabs to DOM right after the original tabs element.\n if (tabs.nextSibling) {\n tabsParent.insertBefore(tabsClone, tabs.nextSibling);\n } else {\n tabsParent.appendChild(tabsClone);\n }\n // Excessive tabs should be collapsed if tabs clone is wider than the original. Remember - clone does not wrap.\n const shouldCollapseTabs = () => tabsClone.getBoundingClientRect().width > tabs.getBoundingClientRect().width;\n\n // If there is no need to collapse tabs, show original tabs (if previously hidden) clean up tabs clone and `return` early.\n if (!shouldCollapseTabs()) {\n tabs.classList.remove(...TABS_HIDDEN_CLASSES);\n tabsParent.removeChild(tabsClone);\n return;\n }\n\n /*\n * Compose dropdown element. Ignore dropdown items for now, they will be added to the dropdown menu soon anyway. The\n * most important thing about this step is to append dropdown with visible toggle button at the end of cloned tabs\n * list to reach maximum width (dropdown toggle has considerable size too) before starting to actually collapse tabs.\n */\n const dropdownMenu = createElement('ul', { className: 'dropdown-menu dropdown-menu-end' });\n const dropdownToggleIcon = createElement('span', { className: 'mdi mdi-menu' });\n const dropdownToggleLabel = createElement('span', { className: 'visually-hidden' }, 'Toggle Dropdown');\n const dropdownToggle = createElement(\n 'button',\n {\n 'aria-expanded': 'false',\n className: 'btn dropdown-toggle text-secondary',\n 'data-bs-toggle': 'dropdown',\n type: 'button',\n },\n dropdownToggleIcon,\n dropdownToggleLabel,\n );\n const dropdown = createElement(\n 'li',\n { className: 'dropdown flex-grow-1 mb-n1 text-end' },\n dropdownToggle,\n dropdownMenu,\n );\n tabsClone.appendChild(dropdown);\n\n /*\n * Identify tabs that require collapsing by taking out one by one from the right-hand side until tabs width can fit\n * inside its parent container. Essentially, overflowing tabs are moved from tab list to future dropdown menu.\n */\n const collapsedTabs = [];\n while (shouldCollapseTabs()) {\n const lastTab = dropdown.previousElementSibling; // With dropdown appended to DOM, its previous siblings are tabs.\n collapsedTabs.unshift(lastTab); // Use `unshift` instead of `push` because this loop is iterating backward in a sense.\n tabsClone.removeChild(lastTab);\n }\n\n /*\n * Properly convert collapsed tabs to dropdown items:\n * 1. Remove all `<li>` `nav-item` element classes.\n * 2. Remove all `<a>` `nav-link` element classes other than `active` and `disabled` to maintain valid tab state.\n * 3. Add `dropdown-item` class to `<a>` element (formerly `nav-link`).\n * 4. Append collapsed tab to dropdown menu.\n */\n collapsedTabs.forEach((collapsedTab) => {\n removeElementClasses(collapsedTab);\n\n [...collapsedTab.children].forEach((navLink) => {\n removeElementClasses(navLink, 'active', 'disabled');\n navLink.classList.add('dropdown-item', 'justify-content-between');\n });\n\n dropdownMenu.appendChild(collapsedTab);\n });\n\n /*\n * Tabs clone with collapsed tabs is now ready to be swapped with original. The only thing left to do is to\n * make it synchronize its state back to the original.\n */\n [...tabsClone.querySelectorAll('a')].forEach((clonedTab) => {\n clonedTab.addEventListener('shown.bs.tab', () => {\n const originalTab = tabs.querySelector(`a[href=\"${clonedTab.getAttribute('href')}\"]`);\n const originalTabInstance = bootstrap.Tab.getInstance(originalTab) || new bootstrap.Tab(originalTab);\n originalTabInstance.show();\n });\n });\n\n // Swap tabs clone with the original, in other words swap wrapped tabs with collapsed tabs.\n tabs.classList.add(...TABS_HIDDEN_CLASSES);\n tabsClone.classList.remove(...tabsCloneTemporaryClasses);\n};\n\n/**\n * Observe size changes of all tab containers on the page and collapse tabs inside of them if they wrap.\n * @example\n * // Run `collapseTabs` algorithm for all tabs on the page exactly once, i.e. observe and immediately unobserve.\n * const unobserveCollapseTabs = observeCollapseTabs();\n * unobserveCollapseTabs();\n * @returns {function(): void} Unobserve function - disconnect all resize observers created during function call.\n */\nexport const observeCollapseTabs = () => {\n const resizeObservers = [...document.querySelectorAll('.nav.nav-tabs')].map((tabs) => {\n const resizeObserver = new ResizeObserver(() => collapseTabs(tabs));\n resizeObserver.observe(tabs);\n return resizeObserver;\n });\n\n return () => resizeObservers.forEach((resizeObserver) => resizeObserver.disconnect());\n};\n","import { getCookie, removeCookie, setCookie } from './cookie.js';\n\nconst THEME_MODAL_ID = 'theme_modal';\n\nconst THEME_DARK = 'dark';\nconst THEME_LIGHT = 'light';\nconst THEME_SYSTEM = 'system';\n\n/**\n * Get preferred system color scheme.\n * @returns {('dark'|'light')} Preferred system color scheme.\n */\nconst getPreferredColorScheme = () =>\n window.matchMedia?.(`(prefers-color-scheme: ${THEME_DARK})`).matches ? THEME_DARK : THEME_LIGHT;\n\n/**\n * Check if given `theme` is a valid Nautobot theme, i.e. `'dark'`, `'light'`, or `'system'`.\n * @param {string} theme - Theme in question.\n * @returns {boolean} `true` is given `theme` is a valid Nautobot theme, `false` otherwise.\n */\nconst isValidTheme = (theme) => theme === THEME_DARK || theme === THEME_LIGHT || theme === THEME_SYSTEM;\n\n/**\n * Automatically detect Nautobot theme. It is derived from `cookie` or `localStorage` if set manually, and falls back to\n * preferred system color scheme by default.\n * @returns {('dark'|'light'|'system')} Detected Nautobot theme.\n */\nconst detectTheme = () => {\n const cookieTheme = getCookie('theme');\n if (isValidTheme(cookieTheme)) {\n return cookieTheme;\n }\n\n const localStorageTheme = window.localStorage?.getItem('theme');\n if (isValidTheme(localStorageTheme)) {\n return localStorageTheme;\n }\n\n return THEME_SYSTEM;\n};\n\n/**\n * Set Nautobot theme.\n * @param {('dark'|'light'|'system')} theme - Nautobot theme to be set.\n * @param {{ manual?: boolean }} [options] - Setter function options object. Currently supported option is `manual`.\n * @returns {void} Do not return any value, set given `theme` and save it into a persistent store if `manual` is `true`.\n */\nconst setTheme = (theme, options) => {\n const isManual = Boolean(options?.manual);\n\n const modal = document.getElementById(THEME_MODAL_ID);\n const buttons = modal?.querySelectorAll('button[data-nb-theme]') ?? [];\n\n buttons.forEach((button) =>\n ['border', 'border-primary'].forEach((className) =>\n button.classList.toggle(className, button.dataset.nbTheme === theme),\n ),\n );\n\n const bsTheme = theme === THEME_SYSTEM ? getPreferredColorScheme() : theme;\n document.documentElement.dataset.theme = bsTheme;\n document.documentElement.dataset.bsTheme = bsTheme;\n\n if (theme === THEME_SYSTEM) {\n removeCookie('theme');\n window.localStorage?.removeItem('theme');\n } else if (isManual) {\n setCookie('theme', theme);\n window.localStorage?.setItem('theme', theme);\n }\n\n if (theme === THEME_DARK || (theme === THEME_SYSTEM && bsTheme === THEME_DARK)) {\n [...document.getElementsByTagName('object')].forEach((object) => {\n object.addEventListener('load', (event) => {\n if (event.target.contentDocument) {\n const images = event.target.contentDocument.getElementsByTagName('image');\n const short_names = event.target.contentDocument.getElementsByClassName('rack-device-shortname');\n const full_names = event.target.contentDocument.getElementsByClassName('rack-device-fullname');\n\n [...images, ...short_names, ...full_names].forEach((rack_image) =>\n rack_image.setAttribute('filter', 'url(#darkmodeinvert)'),\n );\n }\n });\n });\n }\n\n if (isManual) {\n document.location.reload();\n }\n};\n\nexport const initializeTheme = () => {\n const modal = document.getElementById(THEME_MODAL_ID);\n const buttons = modal?.querySelectorAll('button[data-nb-theme]') ?? [];\n\n setTheme(detectTheme());\n window.matchMedia(`(prefers-color-scheme: ${THEME_DARK})`).addEventListener('change', () => setTheme(detectTheme()));\n\n const onClick = (event) => setTheme(event.currentTarget.dataset.nbTheme, { manual: true });\n buttons.forEach((button) => button.addEventListener('click', onClick));\n\n return () => buttons.forEach((button) => button.removeEventListener('click', onClick));\n};\n","/* eslint import/order: ['error', { alphabetize: { order: 'asc' }, 'newlines-between': 'ignore' }] */\n\nimport '../scss/nautobot.scss';\n\nimport * as bootstrap from 'bootstrap';\nwindow.bootstrap = bootstrap;\n\nimport ClipboardJS from 'clipboard';\nwindow.ClipboardJS = ClipboardJS;\n\nimport * as echarts from 'echarts';\nwindow.echarts = echarts;\n\nimport flatpickr from 'flatpickr';\nwindow.flatpickr = flatpickr;\n\nimport hljs from 'highlight.js/lib/core';\nimport 'highlight.js/styles/github.css';\nimport graphql from 'highlight.js/lib/languages/graphql';\nimport json from 'highlight.js/lib/languages/json';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\n\nimport htmx from 'htmx.org';\nwindow.htmx = htmx;\n\nhljs.registerLanguage('graphql', graphql);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('yaml', yaml);\nwindow.hljs = hljs;\n\nimport jQuery from 'jquery';\nwindow.jQuery = jQuery;\nwindow.$ = window.jQuery;\n\nimport 'jquery-ui';\nimport 'select2';\n\nimport { initializeCollapseToggleAll } from './collapse.js';\nimport { initializeDraggable } from './draggable.js';\nimport { initializeDrawers } from './drawer.js';\nimport { observeFormStickyFooters } from './form.js';\nimport { loadState, saveState } from './history.js';\nimport { initializeSearch } from './search.js';\nimport { initializeSelect2Fields, setSelect2Value } from './select2.js';\nimport { initializeSidenav } from './sidenav.js';\nimport { observeCollapseTabs } from './tabs.js';\nimport { initializeTheme } from './theme.js';\n\ndocument.addEventListener('DOMContentLoaded', () => {\n window.nb ??= {};\n\n // History\n loadState();\n window.nb.history = { saveState };\n // Tooltips\n // https://getbootstrap.com/docs/5.3/components/tooltips/#enable-tooltips\n [...document.querySelectorAll('[data-bs-toggle=\"tooltip\"]')].forEach((tooltip) => new bootstrap.Tooltip(tooltip));\n\n // Sidenav\n initializeSidenav();\n\n // Collapse\n initializeCollapseToggleAll();\n\n // Draggable\n initializeDraggable();\n\n // Drawer\n initializeDrawers();\n\n // Form\n // TODO(norbert-mieczkowski-codilime): for htmx SPA-like behavior, re-initialize sticky footers like tabs below.\n observeFormStickyFooters();\n\n // Search\n initializeSearch();\n\n // Select2\n window.nb.select2 = { initializeSelect2Fields, setSelect2Value };\n\n // Tabs\n /*\n * TODO(norbert-mieczkowski-codilime): listen for proper event type(s) to re-initialize collapse tabs observers when\n * htmx dynamic content reloading is implemented. Said re-initialization should be as simple as something like:\n * ```js\n * let unobserveCollapseTabs = observeCollapseTabs();\n * document.body.addEventListener('htmx:xhr:loadend', () => unobserveCollapseTabs());\n * document.body.addEventListener('htmx:load', () => {\n * unobserveCollapseTabs = observeCollapseTabs();\n * });\n * ```\n */\n observeCollapseTabs();\n\n // Theme\n initializeTheme();\n\n const toggleFavorite = (element, event) => {\n if (event.detail.successful) {\n element.classList.toggle('active');\n }\n };\n window.toggleFavorite = toggleFavorite;\n\n const setRequestUrl = (element, event) => {\n const isFavorite = element.classList.contains('active');\n event.detail.path = isFavorite ? element.dataset.deleteUrl : element.dataset.addUrl;\n };\n window.setRequestUrl = setRequestUrl;\n\n // Remove the blur after clicking the footer links that are opening mostly in the new tab\n // Keeping focus on those items is what keeps the tooltip as well\n document.querySelectorAll('a[data-bs-toggle=\"tooltip\"], div[data-bs-toggle=\"tooltip\"] > a').forEach((el) => {\n el.addEventListener('click', () => {\n el.blur();\n });\n });\n\n // When modal is being closed, bootstrap automatically restore the focus on the element that was triggering the modal\n // As a result, after modal close tooltip was triggered as well\n document.addEventListener('hidden.bs.modal', () => {\n document.querySelectorAll('[data-bs-toggle=\"tooltip\"] > a').forEach((el) => {\n el.blur();\n });\n });\n});\n","/**\n * Observe pinned state of elements of class `nb-form-sticky-footer` on the page and add drop shadow with `nb-is-pinned`\n * class if they are pinned. This is purely cosmetic and does not affect functionality.\n * @example\n * // Run form sticky footers observer algorithm exactly once, i.e. observe and immediately unobserve.\n * const unobserveFormStickyFooters = observeFormStickyFooters();\n * unobserveFormStickyFooters();\n * @returns {function(): void} Unobserve function - disconnect all resize observers created during function call.\n */\nexport const observeFormStickyFooters = () => {\n // Form sticky footers pinned state detection with `IntersectionObserver` based on: https://stackoverflow.com/a/57991537.\n const intersectionObserver = new IntersectionObserver(\n ([entry]) => entry.target.classList.toggle('nb-is-pinned', entry.intersectionRatio < 1),\n { threshold: [1] },\n );\n\n const formStickyFooters = [...document.querySelectorAll('.nb-form-sticky-footer')];\n formStickyFooters.forEach((formStickyFooter) => intersectionObserver.observe(formStickyFooter));\n\n return () => {\n intersectionObserver.disconnect();\n };\n};\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t825: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknautobot\"] = self[\"webpackChunknautobot\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [68], () => (__webpack_require__(226)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","DRAGGABLE_CLASS","DRAGGABLE_CONTAINER_CLASS","DRAGGING_CLASS","DRAWER_OPEN_CLASS","toggleDrawer","drawer","force","classList","toggle","isOpen","contains","setAttribute","drawerToggles","document","querySelectorAll","id","forEach","drawerToggle","getElementsByClassName","filter","openDrawer","rafRetriesRemaining","window","requestAnimationFrame","focusDrawer","getComputedStyle","visibility","focus","activeElement","nextActiveElement","querySelector","preventScroll","event","dispatchEvent","CustomEvent","bubbles","cancelable","SESSION_STORAGE_KEY","saveState","state","stateToSave","undefined","history","sessionStorage","setItem","JSON","stringify","createElement","tag","attributes","children","element","Object","entries","attribute","value","child","insertAdjacentText","appendChild","removeElementClasses","ignore","className","includes","remove","rem","px","rootFontSize","documentElement","fontSize","parseInt","FORM_CONTROL_PADDING_X","GAP","ICON_SIZE","BASE_SEARCH_INPUT_PADDING_X","getElement","Document","Element","setSelect2Value","select2","$","val","option","innerText","text","nextValue","length","getAttribute","map","trigger","initializeSelect2","context","selector","options","allowClear","placeholder","selectionCssClass","theme","width","initializeColorPicker","dropdownParent","colorPickerClassCopy","data","container","templateResult","templateSelection","initializeDynamicChoiceSelection","ajax","params","this","offset","page","q","term","search_field","api_version","depth","content_type","extra_query_parameters","fromEntries","name","flatMap","param_name","split","parse","exception","has_ref_field","startsWith","ref_field","slice","id_prefix","match","closest","ref_field_value","field_value","select","selectedOptions","style","opacity","param_value","parameters","String","limit","URLSearchParams","toString","delay","processResults","$element","removeAttribute","results","previous","values","reduce","accumulator","record","index","disabled","Boolean","item","group","site","url","should_nullify_children","collection","property","pagination","more","next","dataUrl","filter_regex","rendered_url","exec","filter_field","custom_attribute","replace","parseURL","initializeMultiValueChar","language","noResults","multiple","tags","initializeStaticChoiceSelection","initializeSelect2Fields","modal","getCookie","cookie","find","setCookie","properties","path","entry","join","removeCookie","expires","SIDENAV_COLLAPSED_KEY","toggleSidenav","toggler","controls","expanded","getElementById","localStorage","removeItem","TABS_HIDDEN_CLASSES","THEME_MODAL_ID","THEME_DARK","THEME_LIGHT","THEME_SYSTEM","isValidTheme","detectTheme","cookieTheme","localStorageTheme","getItem","setTheme","isManual","manual","button","dataset","nbTheme","bsTheme","matchMedia","matches","getElementsByTagName","object","addEventListener","target","contentDocument","rack_image","location","reload","bootstrap","ClipboardJS","echarts","flatpickr","htmx","registerLanguage","graphql","json","xml","yaml","hljs","jQuery","nb","pathname","search","hash","replaceState","loadState","tooltip","sidenavCollapsedInitialState","sidenavListItem","onClickDocument","documentClickEvent","documentClickTarget","sidenavFlyout","removeEventListener","sidenavBranchPickerSelect","on","currentTarget","form","submit","initializeSidenav","areAll","collapseElements","collapsedOrExpanded","every","isCollapsed","getCollapseToggleAllTargets","collapseToggleAll","nbTarget","collapse","collapseInstance","Collapse","getOrCreateInstance","hide","show","textContent","initializeCollapseToggleAll","createHandleOnMouseListener","isDraggable","handle","onMouseDown","onMouseUp","draggable","dataTransfer","clearData","setData","add","preventDefault","getData","insertBefore","dropDraggable","height","top","getBoundingClientRect","clientY","nextSibling","left","right","clientX","append","initializeDraggable","nextState","restState","keys","dismiss","nbDismiss","nbToggle","intersectionObserver","IntersectionObserver","intersectionRatio","threshold","formStickyFooter","observe","observeFormStickyFooters","headerSearch","NAV_MENU","navMenu","SEARCHABLE_MODELS","tabs","tab_details","groups","group_details","items","item_link","item_details","BADGE_REG_EXP","RegExp","delimiter","headerSearchInput","closeSearchPopup","searchPopup","body","isPressedCmd","getModifierState","isPressedCtrl","ctrlKey","key","input","setSelectionRange","mainLeft","mainRight","headerSearchInputTop","icon","badges","required","type","clear","InputEvent","shouldHideClear","action","role","badge","nbLink","popup","overlay","addBadge","link","removeButton","class","existing","ResizeObserver","paddingInlineStart","phrase","model","normalize","trim","toLowerCase","isBackspace","isInputStart","selectionEnd","selectionStart","initializeSearch","resizeObservers","resizeObserver","tabsParent","parentNode","tabsClone","cloneNode","clone","tabsCloneTemporaryClasses","shouldCollapseTabs","removeChild","dropdownMenu","dropdownToggleIcon","dropdownToggleLabel","dropdownToggle","dropdown","collapsedTabs","lastTab","previousElementSibling","unshift","collapsedTab","navLink","clonedTab","originalTab","getInstance","collapseTabs","observeCollapseTabs","buttons","onClick","initializeTheme","toggleFavorite","detail","successful","setRequestUrl","isFavorite","deleteUrl","addUrl","el","blur","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","call","m","O","result","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","splice","r","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","e","obj","prop","prototype","hasOwnProperty","Symbol","toStringTag","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","push","__webpack_exports__"],"sourceRoot":""}
@@ -16,7 +16,7 @@ $('#cabletrace_modal').on('show.bs.modal', function (event) {
16
16
  '<div class="col-md-4 text-center">' + segment[0].device.name + '<br />' + segment[0].name + '</div>' +
17
17
  '<div class="col-md-4 text-center">Cable #' + segment[1].id + '</div>' +
18
18
  '<div class="col-md-4 text-center">' + segment[2].device.name + '<br />' + segment[2].name + '</div>' +
19
- '</div><hr />'
19
+ '</div><hr class="border-top" />'
20
20
  );
21
21
  })
22
22
  }
@@ -1,17 +1,21 @@
1
- // Inteface filtering
2
- $('input.interface-filter').on('input', function() {
3
- let filter = new RegExp(this.value);
4
- let interface;
1
+ // Interface filtering
2
+ document.querySelectorAll('input.interface-filter').forEach(input => {
3
+ input.addEventListener('input', function() {
4
+ const filter = new RegExp(this.value);
5
+ const rows = document.querySelectorAll('table > tbody > tr');
6
+ const toggleChecked = document.querySelector('input.toggle')?.checked || false;
5
7
 
6
- for (interface of $('table > tbody > tr')) {
7
- if (filter.test(interface.getAttribute('data-name'))) {
8
- // Match the toggle in case the filter now matches the interface
9
- $(interface).find('input:checkbox[name=pk]').prop('checked', $('input.toggle').prop('checked'));
10
- $(interface).show();
11
- } else {
12
- // Uncheck to prevent actions from including it when it doesn't match
13
- $(interface).find('input:checkbox[name=pk]').prop('checked', false);
14
- $(interface).hide();
15
- }
16
- }
17
- });
8
+ rows.forEach(row => {
9
+ const name = row.getAttribute('data-name') || '';
10
+ const checkbox = row.querySelector('input[type="checkbox"][name="pk"]');
11
+
12
+ if (filter.test(name)) {
13
+ if (checkbox) checkbox.checked = toggleChecked;
14
+ row.style.display = '';
15
+ } else {
16
+ if (checkbox) checkbox.checked = false;
17
+ row.style.display = 'none';
18
+ }
19
+ });
20
+ });
21
+ });
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" color="#FFFFFF" xmlns="http://www.w3.org/2000/svg">
2
+ <path id="vector" fill-rule="evenodd" clip-rule="evenodd" d="M16.0498 4.25001C16.5975 4.25001 17.0537 4.24898 17.4248 4.2793C17.8045 4.31034 18.1609 4.3781 18.4981 4.54981C19.0155 4.81346 19.4365 5.23452 19.7002 5.75196C19.8719 6.0891 19.9397 6.44547 19.9707 6.8252C20.001 7.19633 20 7.65253 20 8.2002L20 8.29591C20.1658 8.23694 20.3521 8.23326 20.5283 8.30372L21.1719 8.56055C22.5781 9.1231 23.5 10.4855 23.5 12C23.5 13.5146 22.5781 14.8769 21.1719 15.4395L20.5283 15.6963C20.3521 15.7668 20.1658 15.7631 20 15.7041L20 15.7998C20 16.3475 20.001 16.8037 19.9707 17.1748C19.9397 17.5545 19.8719 17.9109 19.7002 18.2481C19.4365 18.7655 19.0155 19.1866 18.498 19.4502C18.1609 19.6219 17.8045 19.6897 17.4248 19.7207C17.0537 19.751 16.5975 19.75 16.0498 19.75L4.4502 19.75C3.90252 19.75 3.44633 19.751 3.0752 19.7207C2.69547 19.6897 2.3391 19.6219 2.00195 19.4502C1.48451 19.1865 1.06346 18.7655 0.799806 18.2481C0.628095 17.9109 0.560331 17.5545 0.529299 17.1748C0.498977 16.8037 0.500002 16.3475 0.500002 15.7998L0.500003 8.2002C0.500003 7.65252 0.498978 7.19633 0.529301 6.8252C0.560333 6.44547 0.628096 6.0891 0.799809 5.75196C1.06346 5.23451 1.48451 4.81346 2.00196 4.54981C2.3391 4.3781 2.69547 4.31033 3.0752 4.2793C3.44633 4.24898 3.90252 4.25 4.4502 4.25L16.0498 4.25001ZM4.4502 5.75C3.87777 5.75 3.49315 5.75024 3.19727 5.77442C2.91027 5.79788 2.77316 5.84059 2.68262 5.88672C2.44751 6.00655 2.25655 6.19751 2.13672 6.43262C2.09059 6.52316 2.04788 6.66027 2.02442 6.94727C2.00024 7.24315 2 7.62777 2 8.2002L2 15.7998C2 16.3722 2.00024 16.7569 2.02442 17.0527C2.04788 17.3397 2.09059 17.4768 2.13672 17.5674C2.25655 17.8025 2.4475 17.9935 2.68262 18.1133C2.77316 18.1594 2.91027 18.2021 3.19727 18.2256C3.49315 18.2498 3.87777 18.25 4.4502 18.25L16.0498 18.25C16.6222 18.25 17.0069 18.2498 17.3027 18.2256C17.5897 18.2021 17.7268 18.1594 17.8174 18.1133C18.0525 17.9935 18.2435 17.8025 18.3633 17.5674C18.4094 17.4768 18.4521 17.3397 18.4756 17.0527C18.4998 16.7569 18.5 16.3722 18.5 15.7998L18.5 8.2002C18.5 7.62777 18.4998 7.24315 18.4756 6.94727C18.4521 6.66027 18.4094 6.52317 18.3633 6.43262C18.2435 6.19751 18.0525 6.00655 17.8174 5.88673C17.7268 5.84059 17.5897 5.79788 17.3027 5.77442C17.0069 5.75025 16.6222 5.75001 16.0498 5.75001L4.4502 5.75ZM5.0625 7.59766C5.47672 7.59766 5.8125 7.93345 5.8125 8.34766L5.8125 15.6533C5.81224 16.0673 5.47655 16.4033 5.0625 16.4033C4.64845 16.4033 4.31277 16.0673 4.3125 15.6533L4.3125 8.34766C4.3125 7.93345 4.64829 7.59766 5.0625 7.59766ZM9.0625 7.59766C9.47672 7.59766 9.8125 7.93345 9.8125 8.34766L9.8125 15.6533C9.81224 16.0673 9.47655 16.4033 9.0625 16.4033C8.64845 16.4033 8.31277 16.0673 8.3125 15.6533L8.3125 8.34766C8.3125 7.93345 8.64829 7.59766 9.0625 7.59766ZM13.0625 7.59669C13.4766 7.59669 13.8122 7.9327 13.8125 8.34669L13.8125 15.6524C13.8125 16.0666 13.4767 16.4024 13.0625 16.4024C12.6483 16.4023 12.3125 16.0666 12.3125 15.6523L12.3125 8.34669C12.3128 7.9327 12.6485 7.59669 13.0625 7.59669ZM20 14.292L20.6143 14.0469C21.4511 13.7122 22 12.9013 22 12C22 11.0988 21.451 10.2879 20.6143 9.95313L20 9.70704L20 14.292Z" fill="currentcolor"/>
3
+ </svg>
@@ -1,3 +1,3 @@
1
1
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" color="#FFFFFF" xmlns="http://www.w3.org/2000/svg">
2
- <path id="vector" fill-rule="evenodd" clip-rule="evenodd" d="M12 3.75C8.18257 3.75 5.05 6.94483 5.05 10.9333C5.05 10.9767 5.05037 11.0199 5.05111 11.063C5.05701 11.408 4.82678 11.7125 4.49325 11.8008C2.92894 12.2152 1.75 13.6888 1.75 15.4667C1.75 17.5774 3.40511 19.25 5.4 19.25H17.5C20.1024 19.25 22.25 17.07 22.25 14.3333C22.25 12.2298 20.9764 10.4475 19.2033 9.74208C18.9761 9.65166 18.8072 9.45612 18.7508 9.21813C18.0035 6.06449 15.2514 3.75 12 3.75ZM3.55893 10.5311C3.76319 5.9413 7.4446 2.25 12 2.25C15.8601 2.25 19.095 4.90344 20.1145 8.50352C22.268 9.52279 23.75 11.7563 23.75 14.3333C23.75 17.8559 20.9727 20.75 17.5 20.75H5.4C2.53479 20.75 0.25 18.3633 0.25 15.4667C0.25 13.225 1.61442 11.2944 3.55893 10.5311Z" fill="currentcolor"/>
2
+ <path id="vector" fill-rule="evenodd" clip-rule="evenodd" d="M12.1016 2.52621C14.9791 2.52621 17.5874 4.21791 18.1055 7.18832C21.4719 7.52106 23.9177 10.3454 23.918 13.577C23.918 15.9528 22.7448 18.0558 20.9473 19.3582C19.7392 20.2336 18.2465 20.7498 16.6348 20.7498H5.2168C2.33274 20.7498 0.0830948 18.2578 0.0830078 15.2967C0.0830728 12.4299 2.19181 10.0021 4.94336 9.85043V9.38364C4.94366 5.56299 8.18268 2.52643 12.1016 2.52621ZM12.1016 4.02621C8.94235 4.02643 6.44366 6.45854 6.44336 9.38364V11.3436H5.21582C3.25824 11.3443 1.58307 13.0633 1.58301 15.2967C1.58309 17.5305 3.25877 19.2497 5.2168 19.2498H16.6348C17.9216 19.2498 19.1074 18.8382 20.0664 18.1434C21.4966 17.1071 22.418 15.4453 22.418 13.577C22.4177 10.9422 20.2937 8.6561 17.4375 8.6561H16.7344L16.6895 7.95395C16.5326 5.52645 14.5774 4.02621 12.1016 4.02621Z" fill="currentcolor"/>
3
3
  </svg>