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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. nautobot/apps/choices.py +4 -0
  2. nautobot/apps/ui.py +4 -0
  3. nautobot/apps/utils.py +8 -0
  4. nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
  5. nautobot/circuits/views.py +6 -2
  6. nautobot/core/api/serializers.py +1 -1
  7. nautobot/core/api/urls.py +1 -0
  8. nautobot/core/api/views.py +4 -0
  9. nautobot/core/choices.py +1 -1
  10. nautobot/core/cli/bootstrap_v3_to_v5.py +36 -13
  11. nautobot/core/cli/migrate_deprecated_templates.py +36 -9
  12. nautobot/core/filters.py +4 -0
  13. nautobot/core/forms/__init__.py +2 -0
  14. nautobot/core/forms/widgets.py +21 -2
  15. nautobot/core/jobs/__init__.py +56 -0
  16. nautobot/core/management/commands/generate_test_data.py +3 -3
  17. nautobot/core/models/__init__.py +11 -0
  18. nautobot/core/models/utils.py +1 -1
  19. nautobot/core/settings.py +17 -7
  20. nautobot/core/settings.yaml +4 -26
  21. nautobot/core/templates/admin/base.html +1 -2
  22. nautobot/core/templates/admin/change_list.html +9 -12
  23. nautobot/core/templates/base_django.html +1 -2
  24. nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
  25. nautobot/core/templates/components/tab/content_wrapper.html +4 -4
  26. nautobot/core/templates/echarts/echarts.html +21 -8
  27. nautobot/core/templates/generic/object_bulk_create.html +2 -2
  28. nautobot/core/templates/generic/object_bulk_delete.html +1 -1
  29. nautobot/core/templates/generic/object_bulk_edit.html +1 -1
  30. nautobot/core/templates/generic/object_bulk_import.html +1 -1
  31. nautobot/core/templates/generic/object_delete.html +1 -1
  32. nautobot/core/templates/generic/object_detail.html +1 -1
  33. nautobot/core/templates/generic/object_edit.html +1 -1
  34. nautobot/core/templates/generic/object_retrieve.html +2 -2
  35. nautobot/core/templates/graphene/graphiql.html +0 -1
  36. nautobot/core/templates/inc/footer.html +3 -1
  37. nautobot/core/templates/inc/header.html +10 -0
  38. nautobot/core/templates/inc/media.html +14 -0
  39. nautobot/core/templates/inc/nav_menu.html +1 -8
  40. nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
  41. nautobot/core/templates/nautobot_config.py.j2 +0 -6
  42. nautobot/core/templates/rest_framework/api.html +103 -2
  43. nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +33 -0
  44. nautobot/core/templates/utilities/theme_preview.html +3 -0
  45. nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
  46. nautobot/core/templatetags/helpers.py +24 -12
  47. nautobot/core/testing/integration.py +24 -13
  48. nautobot/core/testing/utils.py +18 -4
  49. nautobot/core/testing/views.py +104 -17
  50. nautobot/core/tests/integration/test_filters.py +48 -11
  51. nautobot/core/tests/integration/test_theme.py +22 -21
  52. nautobot/core/tests/nautobot_config.py +3 -0
  53. nautobot/core/tests/runner.py +1 -2
  54. nautobot/core/tests/test_breadcrumbs.py +21 -21
  55. nautobot/core/tests/test_jobs.py +73 -6
  56. nautobot/core/tests/test_renderers.py +59 -0
  57. nautobot/core/tests/test_settings_schema.py +1 -0
  58. nautobot/core/tests/test_templatetags_helpers.py +9 -0
  59. nautobot/core/tests/test_titles.py +0 -16
  60. nautobot/core/tests/test_ui.py +122 -3
  61. nautobot/core/tests/test_utils.py +41 -1
  62. nautobot/core/ui/breadcrumbs.py +68 -17
  63. nautobot/core/ui/bulk_buttons.py +1 -1
  64. nautobot/core/ui/choices.py +49 -65
  65. nautobot/core/ui/echarts.py +15 -20
  66. nautobot/core/ui/object_detail.py +54 -46
  67. nautobot/core/ui/titles.py +3 -6
  68. nautobot/core/urls.py +8 -8
  69. nautobot/core/utils/filtering.py +11 -1
  70. nautobot/core/utils/lookup.py +46 -0
  71. nautobot/core/views/mixins.py +31 -20
  72. nautobot/core/views/renderers.py +2 -3
  73. nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -2
  74. nautobot/dcim/api/serializers.py +3 -0
  75. nautobot/dcim/choices.py +49 -0
  76. nautobot/dcim/constants.py +7 -0
  77. nautobot/dcim/factory.py +1 -1
  78. nautobot/dcim/filters.py +13 -1
  79. nautobot/dcim/forms.py +89 -3
  80. nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
  81. nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
  82. nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
  83. nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
  84. nautobot/dcim/migrations/{0078_remove_device_location_tenant_name_uniqueness.py → 0079_remove_device_location_tenant_name_uniqueness.py} +1 -1
  85. nautobot/dcim/migrations/{0079_device_name_data_migration.py → 0080_device_name_data_migration.py} +1 -1
  86. nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
  87. nautobot/dcim/models/device_component_templates.py +33 -1
  88. nautobot/dcim/models/device_components.py +22 -1
  89. nautobot/dcim/models/devices.py +17 -4
  90. nautobot/dcim/tables/devices.py +15 -0
  91. nautobot/dcim/tables/devicetypes.py +8 -1
  92. nautobot/dcim/tables/racks.py +0 -2
  93. nautobot/dcim/tables/template_code.py +1 -1
  94. nautobot/dcim/templates/dcim/cable_trace.html +0 -2
  95. nautobot/dcim/templates/dcim/consoleport.html +1 -1
  96. nautobot/dcim/templates/dcim/consoleserverport.html +1 -1
  97. nautobot/dcim/templates/dcim/devicebay.html +1 -1
  98. nautobot/dcim/templates/dcim/frontport.html +1 -1
  99. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  100. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
  101. nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
  102. nautobot/dcim/templates/dcim/interface.html +9 -1
  103. nautobot/dcim/templates/dcim/interface_edit.html +2 -0
  104. nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
  105. nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
  106. nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
  107. nautobot/dcim/templates/dcim/module_frontports.html +1 -1
  108. nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
  109. nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
  110. nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
  111. nautobot/dcim/templates/dcim/module_powerports.html +1 -1
  112. nautobot/dcim/templates/dcim/module_rearports.html +1 -1
  113. nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
  114. nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
  115. nautobot/dcim/templates/dcim/powerport.html +1 -1
  116. nautobot/dcim/templates/dcim/rack_elevation_list.html +1 -1
  117. nautobot/dcim/templates/dcim/rack_retrieve.html +0 -11
  118. nautobot/dcim/templates/dcim/rearport.html +1 -1
  119. nautobot/dcim/templates/dcim/trace/cable.html +1 -1
  120. nautobot/dcim/templates/dcim/virtualchassis_update.html +1 -1
  121. nautobot/dcim/tests/integration/test_controller.py +3 -6
  122. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
  123. nautobot/dcim/tests/integration/test_create_device.py +0 -2
  124. nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
  125. nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
  126. nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
  127. nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
  128. nautobot/dcim/tests/test_api.py +186 -6
  129. nautobot/dcim/tests/test_filters.py +43 -1
  130. nautobot/dcim/tests/test_forms.py +110 -8
  131. nautobot/dcim/tests/test_graphql.py +44 -1
  132. nautobot/dcim/tests/test_models.py +265 -0
  133. nautobot/dcim/tests/test_tables.py +160 -0
  134. nautobot/dcim/tests/test_views.py +69 -7
  135. nautobot/dcim/views.py +232 -126
  136. nautobot/extras/api/views.py +51 -44
  137. nautobot/extras/datasources/git.py +3 -1
  138. nautobot/extras/filters.py +19 -2
  139. nautobot/extras/forms/forms.py +9 -2
  140. nautobot/extras/jobs.py +2 -0
  141. nautobot/extras/jobs_ui.py +4 -3
  142. nautobot/extras/management/__init__.py +2 -0
  143. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
  144. nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
  145. nautobot/extras/models/approvals.py +11 -1
  146. nautobot/extras/models/change_logging.py +4 -0
  147. nautobot/extras/models/jobs.py +1 -3
  148. nautobot/extras/models/models.py +10 -2
  149. nautobot/extras/plugins/marketplace_manifest.yml +49 -1
  150. nautobot/extras/plugins/views.py +0 -5
  151. nautobot/extras/querysets.py +8 -0
  152. nautobot/extras/tables.py +12 -0
  153. nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
  154. nautobot/extras/templates/extras/configcontext_update.html +1 -0
  155. nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
  156. nautobot/extras/templates/extras/objectchange_retrieve.html +0 -2
  157. nautobot/extras/templates/extras/plugin_detail.html +3 -3
  158. nautobot/extras/templates/extras/secret_create.html +1 -1
  159. nautobot/extras/tests/integration/test_computedfields.py +8 -9
  160. nautobot/extras/tests/integration/test_customfields.py +1 -3
  161. nautobot/extras/tests/integration/test_dynamicgroups.py +7 -8
  162. nautobot/extras/tests/integration/test_relationships.py +0 -2
  163. nautobot/extras/tests/test_api.py +63 -0
  164. nautobot/extras/tests/test_changelog.py +24 -2
  165. nautobot/extras/tests/test_filters.py +36 -3
  166. nautobot/extras/tests/test_models.py +38 -2
  167. nautobot/extras/tests/test_utils.py +3 -4
  168. nautobot/extras/tests/test_views.py +22 -83
  169. nautobot/extras/urls.py +0 -14
  170. nautobot/extras/views.py +83 -52
  171. nautobot/ipam/filters.py +26 -0
  172. nautobot/ipam/tables.py +6 -0
  173. nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
  174. nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
  175. nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
  176. nautobot/ipam/tests/test_filters.py +26 -1
  177. nautobot/ipam/tests/test_models.py +1 -1
  178. nautobot/ipam/views.py +9 -7
  179. nautobot/load_balancers/__init__.py +0 -0
  180. nautobot/load_balancers/api/__init__.py +1 -0
  181. nautobot/load_balancers/api/serializers.py +75 -0
  182. nautobot/load_balancers/api/urls.py +23 -0
  183. nautobot/load_balancers/api/views.py +61 -0
  184. nautobot/load_balancers/apps.py +17 -0
  185. nautobot/load_balancers/choices.py +167 -0
  186. nautobot/load_balancers/filters.py +225 -0
  187. nautobot/load_balancers/forms.py +532 -0
  188. nautobot/load_balancers/management/commands/__init__.py +0 -0
  189. nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
  190. nautobot/load_balancers/migrations/0001_initial.py +465 -0
  191. nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
  192. nautobot/load_balancers/migrations/__init__.py +0 -0
  193. nautobot/load_balancers/models.py +423 -0
  194. nautobot/load_balancers/navigation.py +80 -0
  195. nautobot/load_balancers/tables.py +255 -0
  196. nautobot/load_balancers/tests/__init__.py +474 -0
  197. nautobot/load_balancers/tests/test_api.py +353 -0
  198. nautobot/load_balancers/tests/test_filters.py +134 -0
  199. nautobot/load_balancers/tests/test_forms.py +266 -0
  200. nautobot/load_balancers/tests/test_models.py +195 -0
  201. nautobot/load_balancers/tests/test_views.py +229 -0
  202. nautobot/load_balancers/urls.py +17 -0
  203. nautobot/load_balancers/views.py +248 -0
  204. nautobot/project-static/dist/css/github-dark.min.css +10 -0
  205. nautobot/project-static/dist/css/github.min.css +10 -0
  206. nautobot/project-static/dist/css/nautobot.css +1 -11
  207. nautobot/project-static/dist/css/nautobot.css.map +1 -1
  208. nautobot/project-static/dist/js/libraries.js +1 -1
  209. nautobot/project-static/dist/js/libraries.js.map +1 -1
  210. nautobot/project-static/dist/js/nautobot.js +1 -1
  211. nautobot/project-static/dist/js/nautobot.js.map +1 -1
  212. nautobot/project-static/js/forms.js +13 -0
  213. nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
  214. nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
  215. nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
  216. nautobot/ui/package-lock.json +87 -4
  217. nautobot/ui/package.json +2 -1
  218. nautobot/ui/src/js/nautobot.js +0 -1
  219. nautobot/ui/src/js/select2.js +53 -2
  220. nautobot/ui/src/scss/nautobot.scss +51 -2
  221. nautobot/ui/webpack.config.js +13 -0
  222. nautobot/users/templates/users/preferences.html +11 -2
  223. nautobot/virtualization/filters.py +6 -1
  224. nautobot/virtualization/tests/test_filters.py +10 -1
  225. nautobot/virtualization/tests/test_models.py +1 -0
  226. nautobot/virtualization/views.py +4 -1
  227. nautobot/vpn/factory.py +25 -15
  228. nautobot/vpn/filters.py +1 -0
  229. nautobot/vpn/forms.py +1 -0
  230. nautobot/vpn/migrations/0001_initial.py +1 -1
  231. nautobot/vpn/models.py +16 -8
  232. nautobot/vpn/tables.py +5 -2
  233. nautobot/vpn/tests/test_api.py +0 -5
  234. nautobot/vpn/tests/test_forms.py +1 -2
  235. nautobot/vpn/tests/test_models.py +57 -7
  236. nautobot/vpn/tests/test_views.py +22 -3
  237. nautobot/vpn/views.py +78 -20
  238. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +4 -4
  239. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +243 -352
  240. nautobot/circuits/templates/circuits/circuit.html +0 -2
  241. nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
  242. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
  243. nautobot/circuits/templates/circuits/circuit_update.html +0 -1
  244. nautobot/circuits/templates/circuits/circuittermination.html +0 -2
  245. nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
  246. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
  247. nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
  248. nautobot/circuits/templates/circuits/circuittype.html +0 -2
  249. nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
  250. nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
  251. nautobot/circuits/templates/circuits/provider.html +0 -2
  252. nautobot/circuits/templates/circuits/provider_edit.html +0 -2
  253. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
  254. nautobot/circuits/templates/circuits/provider_update.html +0 -1
  255. nautobot/circuits/templates/circuits/providernetwork.html +0 -2
  256. nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
  257. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
  258. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
  259. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
  260. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
  261. nautobot/core/templates/buttons/import.html +0 -9
  262. nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
  263. nautobot/dcim/templates/dcim/cable.html +0 -2
  264. nautobot/dcim/templates/dcim/cable_edit.html +0 -2
  265. nautobot/dcim/templates/dcim/controller/base.html +0 -2
  266. nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
  267. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
  268. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
  269. nautobot/dcim/templates/dcim/device/base.html +0 -2
  270. nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
  271. nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
  272. nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
  273. nautobot/dcim/templates/dcim/device/frontports.html +0 -2
  274. nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
  275. nautobot/dcim/templates/dcim/device/inventory.html +0 -2
  276. nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
  277. nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
  278. nautobot/dcim/templates/dcim/device/powerports.html +0 -2
  279. nautobot/dcim/templates/dcim/device/rearports.html +0 -2
  280. nautobot/dcim/templates/dcim/device/wireless.html +0 -2
  281. nautobot/dcim/templates/dcim/device_component.html +0 -2
  282. nautobot/dcim/templates/dcim/device_edit.html +0 -2
  283. nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
  284. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
  285. nautobot/dcim/templates/dcim/devicetype.html +0 -2
  286. nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
  287. nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
  288. nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
  289. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
  290. nautobot/dcim/templates/dcim/location.html +0 -2
  291. nautobot/dcim/templates/dcim/location_edit.html +0 -2
  292. nautobot/dcim/templates/dcim/location_retrieve.html +0 -2
  293. nautobot/dcim/templates/dcim/locationtype.html +0 -2
  294. nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
  295. nautobot/dcim/templates/dcim/manufacturer.html +0 -2
  296. nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
  297. nautobot/dcim/templates/dcim/platform.html +0 -2
  298. nautobot/dcim/templates/dcim/powerfeed.html +0 -2
  299. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
  300. nautobot/dcim/templates/dcim/powerpanel.html +0 -2
  301. nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
  302. nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
  303. nautobot/dcim/templates/dcim/rack.html +0 -2
  304. nautobot/dcim/templates/dcim/rack_edit.html +0 -2
  305. nautobot/dcim/templates/dcim/rackgroup.html +0 -2
  306. nautobot/dcim/templates/dcim/rackreservation.html +0 -2
  307. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
  308. nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
  309. nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
  310. nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
  311. nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
  312. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
  313. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
  314. nautobot/dcim/ui.py +0 -29
  315. nautobot/extras/templates/extras/computedfield.html +0 -2
  316. nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
  317. nautobot/extras/templates/extras/configcontext.html +0 -2
  318. nautobot/extras/templates/extras/configcontext_edit.html +0 -2
  319. nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
  320. nautobot/extras/templates/extras/configcontextschema.html +0 -2
  321. nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
  322. nautobot/extras/templates/extras/contact_retrieve.html +0 -2
  323. nautobot/extras/templates/extras/customfield.html +0 -2
  324. nautobot/extras/templates/extras/customfield_edit.html +0 -2
  325. nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
  326. nautobot/extras/templates/extras/customlink.html +0 -2
  327. nautobot/extras/templates/extras/dynamicgroup.html +0 -2
  328. nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
  329. nautobot/extras/templates/extras/exporttemplate.html +0 -2
  330. nautobot/extras/templates/extras/gitrepository.html +0 -2
  331. nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
  332. nautobot/extras/templates/extras/graphqlquery.html +0 -2
  333. nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
  334. nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -2
  335. nautobot/extras/templates/extras/job_detail.html +0 -2
  336. nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
  337. nautobot/extras/templates/extras/jobhook.html +0 -2
  338. nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
  339. nautobot/extras/templates/extras/jobresult.html +0 -2
  340. nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
  341. nautobot/extras/templates/extras/note.html +0 -2
  342. nautobot/extras/templates/extras/note_retrieve.html +0 -1
  343. nautobot/extras/templates/extras/object_changelog.html +0 -2
  344. nautobot/extras/templates/extras/object_notes.html +0 -2
  345. nautobot/extras/templates/extras/objectchange.html +0 -2
  346. nautobot/extras/templates/extras/objectchange_list.html +0 -3
  347. nautobot/extras/templates/extras/relationship.html +0 -1
  348. nautobot/extras/templates/extras/secret.html +0 -1
  349. nautobot/extras/templates/extras/secret_edit.html +0 -1
  350. nautobot/extras/templates/extras/secretsgroup.html +0 -2
  351. nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
  352. nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
  353. nautobot/extras/templates/extras/status.html +0 -2
  354. nautobot/extras/templates/extras/tag.html +0 -2
  355. nautobot/extras/templates/extras/tag_edit.html +0 -2
  356. nautobot/extras/templates/extras/tag_retrieve.html +0 -2
  357. nautobot/extras/templates/extras/team_retrieve.html +0 -2
  358. nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
  359. nautobot/ipam/templates/ipam/prefix.html +0 -2
  360. nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
  361. nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
  362. nautobot/ipam/templates/ipam/rir.html +0 -2
  363. nautobot/ipam/templates/ipam/routetarget.html +0 -1
  364. nautobot/ipam/templates/ipam/service.html +0 -2
  365. nautobot/ipam/templates/ipam/service_edit.html +0 -2
  366. nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
  367. nautobot/ipam/templates/ipam/vlan.html +0 -2
  368. nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
  369. nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
  370. nautobot/ipam/templates/ipam/vlangroup.html +0 -2
  371. nautobot/ipam/templates/ipam/vrf.html +0 -1
  372. nautobot/tenancy/templates/tenancy/tenant.html +0 -2
  373. nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
  374. nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
  375. nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
  376. nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
  377. nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
  378. nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
  379. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
  380. nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
  381. nautobot/vpn/templates/vpn/vpnprofile.html +0 -2
  382. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
  383. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
  384. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
  385. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
  386. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
  387. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
  388. {nautobot-3.0.0a3.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +0 -0
@@ -1,7 +1,8 @@
1
1
  from dataclasses import dataclass
2
+ from itertools import chain
2
3
  import logging
3
4
  from operator import attrgetter
4
- from typing import Any, Callable, Literal, Optional, Protocol, Type, Union
5
+ from typing import Any, Callable, Iterator, Literal, Optional, Protocol, Type, Union
5
6
  from urllib.parse import urlencode
6
7
 
7
8
  from django.db.models import Model
@@ -11,7 +12,7 @@ from django.urls import NoReverseMatch, reverse
11
12
  from nautobot.core.models.tree_queries import TreeModel
12
13
  from nautobot.core.templatetags import helpers
13
14
  from nautobot.core.ui.utils import get_absolute_url, render_component_template
14
- from nautobot.core.utils import lookup
15
+ from nautobot.core.utils import deprecation, lookup
15
16
  from nautobot.core.utils.lookup import get_model_for_view_name, get_model_from_name
16
17
  from nautobot.core.views.utils import get_obj_from_context
17
18
 
@@ -153,7 +154,7 @@ class BaseBreadcrumbItem:
153
154
  return params
154
155
  return {}
155
156
 
156
- def as_pair(self, context: Context) -> tuple[str, str]:
157
+ def as_pair(self, context: Context) -> Iterator[tuple[str, str]]:
157
158
  """
158
159
  Construct the (URL, label) pair for the breadcrumb.
159
160
 
@@ -163,12 +164,12 @@ class BaseBreadcrumbItem:
163
164
  context (Context): Context object used to resolve the breadcrumb parts.
164
165
 
165
166
  Returns:
166
- tuple[str, Optional[str]]: A tuple of (URL, label), where URL may be an empty string
167
+ Iterator[tuple[str, Optional[str]]]: A tuple of (URL, label), where URL may be an empty string
167
168
  if unresolved, and label.
168
169
  """
169
170
  url = self.get_url(context) or ""
170
171
  label = self.get_label(context)
171
- return url, label
172
+ yield url, label
172
173
 
173
174
 
174
175
  @dataclass
@@ -387,7 +388,7 @@ class InstanceBreadcrumbItem(BaseBreadcrumbItem):
387
388
  instance = self.get_instance(context)
388
389
  if not instance:
389
390
  return ""
390
- return getattr(instance, "display", str(instance))
391
+ return getattr(instance, "page_title", str(instance))
391
392
 
392
393
  def get_instance(self, context: Context) -> Optional[Model]:
393
394
  """
@@ -419,6 +420,7 @@ class InstanceParentBreadcrumbItem(InstanceBreadcrumbItem):
419
420
 
420
421
  Attributes:
421
422
  parent_key (str): Instance attribute to get the parent instance. Default: "parent".
423
+ parent (Optional[Model]): Instance or related object (parent).
422
424
  parent_query_param (Optional[str]): Query param name under which parent lookup key will be added into breadcrumb url. If None, will be the same as `parent_key`.
423
425
  parent_lookup_key (Optional[str]): Parent attribute which will be used to build the url and filter the instance list url. Can be set to None to use parent as key.
424
426
 
@@ -430,6 +432,7 @@ class InstanceParentBreadcrumbItem(InstanceBreadcrumbItem):
430
432
  """
431
433
 
432
434
  parent_key: str = "parent"
435
+ parent: Optional[Model] = None
433
436
  parent_query_param: Optional[str] = None
434
437
  parent_lookup_key: Optional[str] = "pk"
435
438
 
@@ -451,12 +454,14 @@ class InstanceParentBreadcrumbItem(InstanceBreadcrumbItem):
451
454
  Optional[str]: The URL as a string, or None.
452
455
  """
453
456
  instance = self.get_instance(context)
454
- parent = self.get_parent_attr(instance)
455
- if not instance or not parent:
457
+ related_object = self.get_related_object(instance)
458
+ if not instance or not related_object:
456
459
  return None
457
460
 
458
461
  view_name = lookup.get_route_for_model(instance, "list")
459
- return self.reverse_view_name(view_name, context, reverse_query_params=self.get_reverse_query_params(parent))
462
+ return self.reverse_view_name(
463
+ view_name, context, reverse_query_params=self.get_reverse_query_params(related_object)
464
+ )
460
465
 
461
466
  def get_label(self, context: Context) -> str:
462
467
  """
@@ -471,10 +476,10 @@ class InstanceParentBreadcrumbItem(InstanceBreadcrumbItem):
471
476
  if self.label or self.label_key:
472
477
  return super().get_label(context)
473
478
  instance = self.get_instance(context)
474
- parent = self.get_parent_attr(instance)
475
- if not instance or not parent:
479
+ related_object = self.get_related_object(instance)
480
+ if not instance or not related_object:
476
481
  return ""
477
- return getattr(parent, "display", str(parent))
482
+ return getattr(related_object, "page_title", str(related_object))
478
483
 
479
484
  def get_reverse_query_params(self, parent: Model) -> Optional[dict]:
480
485
  if self.parent_lookup_key is None:
@@ -485,12 +490,58 @@ class InstanceParentBreadcrumbItem(InstanceBreadcrumbItem):
485
490
  return {self.parent_query_param: query_param}
486
491
  return {}
487
492
 
488
- def get_parent_attr(self, instance: Model) -> Optional[Model]:
493
+ def get_related_object(self, instance: Model) -> Optional[Model]:
494
+ if self.parent:
495
+ return self.parent
496
+
489
497
  if hasattr(instance, self.parent_key):
490
498
  return getattr(instance, self.parent_key) or None
499
+
491
500
  return None
492
501
 
493
502
 
503
+ @dataclass
504
+ class AncestorsInstanceBreadcrumbItem(InstanceBreadcrumbItem):
505
+ """
506
+ Item class which can render list of ancestors of given instance.
507
+
508
+ By default, it won't include itself.
509
+
510
+ Attributes:
511
+ include_self (bool): Whether to include self as last item of ancestors.
512
+
513
+ Examples:
514
+ >>> AncestorsInstanceBreadcrumbItem(instance=location)
515
+ ("/dcim/locations/<pk>", "Parent 2"), ("/dcim/locations/<pk>", "Parent 1")
516
+ >>> AncestorsInstanceBreadcrumbItem(instance=location, include_self=True)
517
+ ("/dcim/locations/<pk>", "Parent 2"), ("/dcim/locations/<pk>", "Parent 1"), ("/dcim/locations/<pk>", "Location")
518
+ """
519
+
520
+ ancestor_item: Callable[[Model], BaseBreadcrumbItem] = lambda instance: InstanceBreadcrumbItem(instance=instance)
521
+ include_self: bool = False
522
+
523
+ def as_pair(self, context: Context) -> Iterator[tuple[str, str]]:
524
+ """
525
+ Construct the (URL, label) pair for the breadcrumb with all the instance ancestors.
526
+
527
+ Creates separate `InstanceBreadcrumbItem` with copied data from self.
528
+
529
+ Args:
530
+ context (Context): Context object used to resolve the breadcrumb parts.
531
+
532
+ Returns:
533
+ Iterator[tuple[str, Optional[str]]]: A tuple of (URL, label), where URL may be an empty string
534
+ if unresolved, and label.
535
+ """
536
+ instance = self.get_instance(context)
537
+
538
+ for ancestor in instance.ancestors():
539
+ yield from self.ancestor_item(ancestor).as_pair(context)
540
+
541
+ if self.include_self:
542
+ yield from self.ancestor_item(instance).as_pair(context)
543
+
544
+
494
545
  class Breadcrumbs:
495
546
  """
496
547
  Base class responsible for generating and rendering breadcrumbs for a page.
@@ -569,7 +620,8 @@ class Breadcrumbs:
569
620
  action = context.get("view_action", "")
570
621
  detail = context.get("detail", False)
571
622
  items = self.get_items_for_action(self.items, action, detail, context)
572
- return [item.as_pair(context) for item in items if item.should_render(context)]
623
+ items_pairs = [item.as_pair(context) for item in items if item.should_render(context)]
624
+ return list(chain.from_iterable(items_pairs))
573
625
 
574
626
  def filter_breadcrumbs_items(self, items: list[tuple[str, str]], context: Context) -> list[tuple[str, str]]:
575
627
  """
@@ -647,7 +699,7 @@ class Breadcrumbs:
647
699
  Provide additional data to include in the rendering context, based on the configuration of this component.
648
700
 
649
701
  Context updated here will be applied to resolving url and labels.
650
- Please ote that you can't override `breadcrumb_items` here because items are generated after this method call.
702
+ Please note that you can't override `breadcrumb_items` here because items are generated after this method call.
651
703
 
652
704
  Args:
653
705
  context (Context): The current context passed to `render()`.
@@ -658,6 +710,7 @@ class Breadcrumbs:
658
710
  return {}
659
711
 
660
712
 
713
+ @deprecation.class_deprecated("Functionality of this class was moved to the AncestorsInstanceBreadcrumbItem.")
661
714
  class AncestorsBreadcrumbs(Breadcrumbs):
662
715
  """
663
716
  Breadcrumbs class which can render list of ancestors of given instance.
@@ -665,7 +718,6 @@ class AncestorsBreadcrumbs(Breadcrumbs):
665
718
  Default behavior:
666
719
  - render breadcrumb item with link to the list view
667
720
  - dynamically add list of `InstanceBreadcrumbItem` from `ancestors()`
668
- - adds standard breadcrumb item with link to the details
669
721
  """
670
722
 
671
723
  def get_items_for_action(
@@ -704,7 +756,6 @@ class AncestorsBreadcrumbs(Breadcrumbs):
704
756
  return [
705
757
  ModelBreadcrumbItem(model=instance),
706
758
  *self.get_ancestors_items(instance),
707
- InstanceBreadcrumbItem(instance=instance, label=self.detail_item_label),
708
759
  ]
709
760
 
710
761
  def get_ancestors_items(self, instance: TreeModel) -> list[BaseBreadcrumbItem]:
@@ -32,7 +32,7 @@ class BaseBulkButton(object_detail.FormButton):
32
32
  class BulkRenameButton(BaseBulkButton):
33
33
  action = "rename"
34
34
  color = ButtonActionColorChoices.RENAME
35
- icon = "mdi-pencil"
35
+ icon = "mdi-rename"
36
36
  label = "Rename"
37
37
  weight = 200
38
38
 
@@ -66,71 +66,51 @@ class EChartsTypeChoices(ChoiceSet):
66
66
  )
67
67
 
68
68
 
69
- class EChartsTypeTheme(ChoiceSet):
70
- """Available chart theme for ECharts.
71
-
72
- Attributes:
73
- LIGHT (str): Light theme (value: light)
74
- DARK (str): Dark theme (value: dark)
75
- """
76
-
77
- LIGHT = "default"
78
- DARK = "dark"
69
+ class EChartsThemeColors(ChoiceSet):
70
+ """Available chart colors for ECharts."""
71
+
72
+ NAUTOBOT = "default"
73
+ LIGHTER_GREEN_AND_RED_ONLY = "lighter-green-red-only"
74
+ DEFAULT = NAUTOBOT
75
+
76
+ # Color lists - direct access
77
+ NAUTOBOT_COLORS = (
78
+ UI_COLORS["blue"],
79
+ UI_COLORS["purple"],
80
+ UI_COLORS["turquoise"],
81
+ UI_COLORS["orange"],
82
+ UI_COLORS["green"],
83
+ UI_COLORS["red"],
84
+ UI_COLORS["gray"],
85
+ UI_COLORS["blue-lighter"],
86
+ UI_COLORS["purple-lighter"],
87
+ UI_COLORS["turquoise-lighter"],
88
+ UI_COLORS["orange-lighter"],
89
+ UI_COLORS["green-lighter"],
90
+ UI_COLORS["red-lighter"],
91
+ UI_COLORS["gray-lighter"],
92
+ UI_COLORS["blue-darker"],
93
+ UI_COLORS["purple-darker"],
94
+ UI_COLORS["turquoise-darker"],
95
+ UI_COLORS["orange-darker"],
96
+ UI_COLORS["green-darker"],
97
+ UI_COLORS["red-darker"],
98
+ UI_COLORS["gray-darker"],
99
+ )
79
100
 
80
- DEFAULT = LIGHT
101
+ LIGHTER_GREEN_RED_COLORS = (
102
+ UI_COLORS["green-lighter"],
103
+ UI_COLORS["red-lighter"],
104
+ )
81
105
 
82
106
  CHOICES = (
83
- (LIGHT, "Default theme"),
84
- (DARK, "Dark theme"),
107
+ (NAUTOBOT, "Default Nautobot Colors"),
108
+ (LIGHTER_GREEN_AND_RED_ONLY, "Lighter Green and Red Only"),
85
109
  )
86
110
 
87
111
  COLORS = {
88
- LIGHT: [
89
- UI_COLORS["blue"]["light"],
90
- UI_COLORS["purple"]["light"],
91
- UI_COLORS["turquoise"]["light"],
92
- UI_COLORS["orange"]["light"],
93
- UI_COLORS["green"]["light"],
94
- UI_COLORS["red"]["light"],
95
- UI_COLORS["gray"]["light"],
96
- UI_COLORS["blue-lighter"]["light"],
97
- UI_COLORS["purple-lighter"]["light"],
98
- UI_COLORS["turquoise-lighter"]["light"],
99
- UI_COLORS["orange-lighter"]["light"],
100
- UI_COLORS["green-lighter"]["light"],
101
- UI_COLORS["red-lighter"]["light"],
102
- UI_COLORS["gray-lighter"]["light"],
103
- UI_COLORS["blue-darker"]["light"],
104
- UI_COLORS["purple-darker"]["light"],
105
- UI_COLORS["turquoise-darker"]["light"],
106
- UI_COLORS["orange-darker"]["light"],
107
- UI_COLORS["green-darker"]["light"],
108
- UI_COLORS["red-darker"]["light"],
109
- UI_COLORS["gray-darker"]["light"],
110
- ],
111
- DARK: [
112
- UI_COLORS["blue"]["dark"],
113
- UI_COLORS["purple"]["dark"],
114
- UI_COLORS["turquoise"]["dark"],
115
- UI_COLORS["orange"]["dark"],
116
- UI_COLORS["green"]["dark"],
117
- UI_COLORS["red"]["dark"],
118
- UI_COLORS["gray"]["dark"],
119
- UI_COLORS["blue-lighter"]["dark"],
120
- UI_COLORS["purple-lighter"]["dark"],
121
- UI_COLORS["turquoise-lighter"]["dark"],
122
- UI_COLORS["orange-lighter"]["dark"],
123
- UI_COLORS["green-lighter"]["dark"],
124
- UI_COLORS["red-lighter"]["dark"],
125
- UI_COLORS["gray-lighter"]["dark"],
126
- UI_COLORS["blue-darker"]["dark"],
127
- UI_COLORS["purple-darker"]["dark"],
128
- UI_COLORS["turquoise-darker"]["dark"],
129
- UI_COLORS["orange-darker"]["dark"],
130
- UI_COLORS["green-darker"]["dark"],
131
- UI_COLORS["red-darker"]["dark"],
132
- UI_COLORS["gray-darker"]["dark"],
133
- ],
112
+ NAUTOBOT: NAUTOBOT_COLORS,
113
+ LIGHTER_GREEN_AND_RED_ONLY: LIGHTER_GREEN_RED_COLORS,
134
114
  }
135
115
 
136
116
 
@@ -141,10 +121,11 @@ class NavigationIconChoices(ChoiceSet):
141
121
  IPAM = "sitemap-outline"
142
122
  ORGANIZATION = "organization"
143
123
  CIRCUITS = "cable-data"
144
- VPN = "atom"
124
+ VPN = "bus-shield"
145
125
  ROUTING = "route"
146
126
  POWER = "battery-3"
147
127
  WIRELESS = "wifi"
128
+ DEVICE_LIFECYCLE = "device-lifecycle"
148
129
  SECRETS = "secrets"
149
130
  SECURITY = "security"
150
131
  LOAD_BALANCERS = "arrow-decision"
@@ -166,6 +147,7 @@ class NavigationIconChoices(ChoiceSet):
166
147
  (ROUTING, "Routing"),
167
148
  (POWER, "Power"),
168
149
  (WIRELESS, "Wireless"),
150
+ (DEVICE_LIFECYCLE, "Device Lifecycle"),
169
151
  (SECRETS, "Secrets"),
170
152
  (SECURITY, "Security"),
171
153
  (LOAD_BALANCERS, "Load Balancers"),
@@ -196,11 +178,12 @@ class NavigationWeightChoices(ChoiceSet):
196
178
  ROUTING = 500
197
179
  POWER = 550
198
180
  WIRELESS = 600
199
- SECRETS = 650
200
- SECURITY = 700
201
- LOAD_BALANCERS = 750
202
- VIRTUALIZATION = 800
203
- CLOUD = 850
181
+ DEVICE_LIFECYCLE = 650
182
+ SECRETS = 700
183
+ SECURITY = 750
184
+ LOAD_BALANCERS = 800
185
+ VIRTUALIZATION = 850
186
+ CLOUD = 900
204
187
  # We leave a gap here to allow for future expansion and don't use 1000
205
188
  # since it the default weight for NavMenuTab if none is specified.
206
189
  DESIGN = 1100
@@ -220,6 +203,7 @@ class NavigationWeightChoices(ChoiceSet):
220
203
  (ROUTING, "Routing"),
221
204
  (POWER, "Power"),
222
205
  (WIRELESS, "Wireless"),
206
+ (DEVICE_LIFECYCLE, "Device Lifecycle"),
223
207
  (SECRETS, "Secrets"),
224
208
  (SECURITY, "Security"),
225
209
  (VIRTUALIZATION, "Virtualization"),
@@ -5,7 +5,7 @@ from typing import Any, Callable
5
5
  from django.db.models import QuerySet
6
6
  from django.template import Context
7
7
 
8
- from nautobot.core.ui.choices import EChartsTypeChoices, EChartsTypeTheme
8
+ from nautobot.core.ui.choices import EChartsThemeColors, EChartsTypeChoices
9
9
  from nautobot.core.utils.lookup import resolve_attr
10
10
 
11
11
 
@@ -216,7 +216,7 @@ class EChartsBase:
216
216
  x_label="X",
217
217
  y_label="Y",
218
218
  legend=None,
219
- theme=EChartsTypeTheme.DEFAULT,
219
+ theme_colors=None,
220
220
  renderer="canvas",
221
221
  show_toolbox=True,
222
222
  save_image_options=None,
@@ -245,7 +245,8 @@ class EChartsBase:
245
245
  }
246
246
  You can also hide the legend entirely by setting `"show": False`.
247
247
  More details here: https://echarts.apache.org/handbook/en/concepts/legend.
248
- theme (str): Theme for chart (default: EChartsTypeTheme.DEFAULT).
248
+ theme_colors (list[dict[str, str]]): Color palette for chart, each color is {'light': str, 'dark': str}
249
+ (default: EChartsThemeColors.NAUTOBOT_COLORS).
249
250
  renderer (str): If the renderer is set to 'canvas' when chart initialized (default), then
250
251
  'png' (default) and 'jpg' are supported. If the renderer is set to 'svg' when chart
251
252
  initialized, then only 'svg' is supported for type. See more details:
@@ -271,7 +272,7 @@ class EChartsBase:
271
272
  self.x_label = x_label
272
273
  self.y_label = y_label
273
274
  self.legend = legend or {}
274
- self.theme = theme
275
+ self.theme_colors = theme_colors or EChartsThemeColors.NAUTOBOT_COLORS
275
276
  self.renderer = renderer
276
277
  self.show_toolbox = show_toolbox
277
278
  self.save_image_options = {"name": self.header or "echart", "show": True, **(save_image_options or {})}
@@ -279,10 +280,12 @@ class EChartsBase:
279
280
  self.permission = permission
280
281
  self.combined_with = combined_with
281
282
 
282
- @property
283
- def get_tranform_data(self) -> dict[str, Any]:
283
+ def get_transform_data(self, context: Context | None = None) -> dict[str, Any]:
284
284
  """Get the chart data in ECharts format, ready for rendering."""
285
- resolved_data = self._data() if callable(self._data) else self._data
285
+ if context and callable(self._data):
286
+ resolved_data = self._data(context)
287
+ else:
288
+ resolved_data = self._data() if callable(self._data) else self._data
286
289
  return self._transform_data(resolved_data or {})
287
290
 
288
291
  @property
@@ -299,11 +302,6 @@ class EChartsBase:
299
302
  """
300
303
  return self._data
301
304
 
302
- @data.setter
303
- def data(self, data):
304
- """Set the data."""
305
- self._data = data
306
-
307
305
  @property
308
306
  def chart_type(self):
309
307
  """Get the current chart type."""
@@ -378,13 +376,9 @@ class EChartsBase:
378
376
 
379
377
  return original
380
378
 
381
- def get_theme_colors(self):
382
- """Map SCSS palette to echarts theme colors (manual sync)."""
383
- return EChartsTypeTheme.COLORS.get(self.theme, EChartsTypeTheme.COLORS[EChartsTypeTheme.DEFAULT])
384
-
385
- def get_config(self):
379
+ def get_config(self, context: Context | None = None):
386
380
  """Return a dict ready to dump into echarts option JSON."""
387
- data = self.get_tranform_data
381
+ data = self.get_transform_data(context=context)
388
382
 
389
383
  # Base configuration
390
384
  config = {
@@ -393,7 +387,7 @@ class EChartsBase:
393
387
  "toolbox": self.strategy.get_toolbox_config(
394
388
  self.show_toolbox, self.save_image_options, self.data_view_options
395
389
  ),
396
- "color": self.get_theme_colors(),
390
+ "color": self.theme_colors,
397
391
  "legend": self.legend,
398
392
  }
399
393
  axis_config = self.strategy.get_axis_config(data, self.x_label, self.y_label)
@@ -408,7 +402,8 @@ class EChartsBase:
408
402
 
409
403
  # Handle combined charts
410
404
  if self.combined_with:
411
- combined_series = self.combined_with.strategy.get_series_config(self.combined_with.data)
405
+ data = self.combined_with.get_transform_data(context=context)
406
+ combined_series = self.combined_with.strategy.get_series_config(data)
412
407
  config["series"].extend(combined_series)
413
408
 
414
409
  return config