nautobot 3.0.0a2__py3-none-any.whl → 3.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nautobot/apps/choices.py +4 -2
- nautobot/apps/filters.py +7 -9
- nautobot/apps/models.py +2 -2
- nautobot/apps/ui.py +13 -1
- nautobot/apps/utils.py +8 -0
- nautobot/circuits/filters.py +3 -2
- nautobot/circuits/navigation.py +3 -2
- nautobot/circuits/templates/circuits/circuit_create.html +3 -3
- nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
- nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
- nautobot/circuits/tests/integration/test_circuit.py +10 -13
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
- nautobot/circuits/views.py +6 -2
- nautobot/cloud/filters.py +1 -1
- nautobot/cloud/navigation.py +3 -2
- nautobot/core/api/schema.py +1 -1
- nautobot/core/api/serializers.py +6 -1
- nautobot/core/api/urls.py +2 -0
- nautobot/core/api/views.py +12 -0
- nautobot/core/apps/__init__.py +11 -10
- nautobot/core/celery/__init__.py +3 -5
- nautobot/core/checks.py +46 -0
- nautobot/core/choices.py +1 -1
- nautobot/core/cli/bootstrap_v3_to_v5.py +105 -13
- nautobot/core/cli/migrate_deprecated_templates.py +227 -0
- nautobot/core/constants.py +3 -0
- nautobot/core/context_processors.py +9 -1
- nautobot/core/filters.py +4 -0
- nautobot/core/forms/__init__.py +2 -0
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/forms/widgets.py +21 -2
- nautobot/core/jobs/__init__.py +62 -3
- nautobot/core/jobs/groups.py +31 -1
- nautobot/core/management/commands/generate_test_data.py +28 -9
- nautobot/core/models/__init__.py +11 -0
- nautobot/core/models/generics.py +9 -1
- nautobot/core/models/tree_queries.py +10 -5
- nautobot/core/models/utils.py +1 -1
- nautobot/core/settings.py +35 -19
- nautobot/core/settings.yaml +17 -33
- nautobot/core/signals.py +12 -1
- nautobot/core/tables.py +13 -6
- nautobot/core/templates/40x.html +1 -1
- nautobot/core/templates/500.html +2 -2
- nautobot/core/templates/admin/base.html +1 -2
- nautobot/core/templates/admin/change_list.html +9 -12
- nautobot/core/templates/admin/config/config.html +12 -12
- nautobot/core/templates/admin/index.html +3 -3
- nautobot/core/templates/base_django.html +1 -2
- nautobot/core/templates/buttons/export.html +1 -1
- nautobot/core/templates/components/button/dropdown.html +5 -3
- nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/components/panel/panel.html +3 -3
- nautobot/core/templates/components/tab/content_wrapper.html +6 -7
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
- nautobot/core/templates/echarts/echarts.html +22 -9
- nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
- nautobot/core/templates/generic/object_bulk_create.html +6 -5
- nautobot/core/templates/generic/object_bulk_delete.html +1 -1
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
- nautobot/core/templates/generic/object_bulk_edit.html +1 -1
- nautobot/core/templates/generic/object_bulk_import.html +1 -1
- nautobot/core/templates/generic/object_bulk_remove.html +2 -2
- nautobot/core/templates/generic/object_bulk_update.html +5 -4
- nautobot/core/templates/generic/object_create.html +5 -4
- nautobot/core/templates/generic/object_delete.html +1 -1
- nautobot/core/templates/generic/object_detail.html +1 -1
- nautobot/core/templates/generic/object_edit.html +1 -1
- nautobot/core/templates/generic/object_import.html +2 -1
- nautobot/core/templates/generic/object_list.html +12 -4
- nautobot/core/templates/generic/object_notes.html +5 -3
- nautobot/core/templates/generic/object_retrieve.html +4 -5
- nautobot/core/templates/graphene/graphiql.html +7 -8
- nautobot/core/templates/home.html +1 -1
- nautobot/core/templates/import_success.html +2 -1
- nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/created_updated.html +7 -3
- nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/footer.html +3 -1
- nautobot/core/templates/inc/form_static_field.html +6 -0
- nautobot/core/templates/inc/header.html +11 -1
- nautobot/core/templates/inc/image_attachments.html +2 -1
- nautobot/core/templates/inc/media.html +14 -0
- nautobot/core/templates/inc/nav_menu.html +3 -9
- nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
- nautobot/core/templates/inc/search_panel.html +4 -4
- nautobot/core/templates/login.html +4 -2
- nautobot/core/templates/nautobot_config.py.j2 +6 -11
- nautobot/core/templates/redoc_ui.html +7 -0
- nautobot/core/templates/rest_framework/api.html +103 -2
- nautobot/core/templates/search.html +1 -1
- nautobot/core/templates/swagger_ui.html +17 -3
- nautobot/core/templates/system_jobs/import_objects.html +1 -2
- nautobot/core/templates/utilities/confirmation_form.html +2 -2
- nautobot/core/templates/utilities/obj_table.html +10 -2
- nautobot/core/templates/utilities/render_field.html +7 -7
- nautobot/core/templates/utilities/render_jinja2.html +2 -2
- nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +37 -4
- nautobot/core/templates/utilities/theme_preview.html +19 -3
- nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
- nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
- nautobot/core/templatetags/helpers.py +76 -18
- nautobot/core/testing/api.py +68 -9
- nautobot/core/testing/filters.py +0 -23
- nautobot/core/testing/integration.py +41 -17
- nautobot/core/testing/mixins.py +2 -0
- nautobot/core/testing/utils.py +18 -4
- nautobot/core/testing/views.py +104 -13
- nautobot/core/tests/integration/test_app_home.py +34 -30
- nautobot/core/tests/integration/test_app_navbar.py +3 -0
- nautobot/core/tests/integration/test_filters.py +48 -11
- nautobot/core/tests/integration/test_theme.py +22 -21
- nautobot/core/tests/nautobot_config.py +3 -0
- nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
- nautobot/core/tests/runner.py +8 -1
- nautobot/core/tests/test_api.py +5 -3
- nautobot/core/tests/test_breadcrumbs.py +27 -28
- nautobot/core/tests/test_checks.py +28 -0
- nautobot/core/tests/test_cli.py +40 -0
- nautobot/core/tests/test_config.py +2 -1
- nautobot/core/tests/test_forms.py +55 -13
- nautobot/core/tests/test_jobs.py +144 -3
- nautobot/core/tests/test_nautobot_server.py +2 -0
- nautobot/core/tests/test_navigations.py +76 -1
- nautobot/core/tests/test_patch_social_django.py +42 -0
- nautobot/core/tests/test_renderers.py +59 -0
- nautobot/core/tests/test_settings_schema.py +1 -0
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +62 -13
- nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
- nautobot/core/tests/test_titles.py +0 -16
- nautobot/core/tests/test_tree_queries.py +14 -1
- nautobot/core/tests/test_ui.py +123 -4
- nautobot/core/tests/test_utils.py +72 -5
- nautobot/core/tests/test_views.py +159 -31
- nautobot/core/ui/breadcrumbs.py +70 -29
- nautobot/core/ui/bulk_buttons.py +1 -1
- nautobot/core/ui/choices.py +143 -27
- nautobot/core/ui/constants.py +76 -12
- nautobot/core/ui/echarts.py +15 -20
- nautobot/core/ui/object_detail.py +143 -55
- nautobot/core/ui/titles.py +3 -6
- nautobot/core/urls.py +20 -9
- nautobot/core/utils/cache.py +2 -1
- nautobot/core/utils/filtering.py +28 -18
- nautobot/core/utils/lookup.py +49 -8
- nautobot/core/utils/module_loading.py +21 -0
- nautobot/core/utils/patch_social_django.py +128 -0
- nautobot/core/views/__init__.py +38 -1
- nautobot/core/views/generic.py +3 -3
- nautobot/core/views/mixins.py +45 -22
- nautobot/core/views/renderers.py +4 -3
- nautobot/core/views/viewsets.py +2 -1
- nautobot/data_validation/apps.py +1 -5
- nautobot/data_validation/custom_validators.py +4 -4
- nautobot/data_validation/filters.py +1 -1
- nautobot/data_validation/forms.py +40 -0
- nautobot/data_validation/migrations/0001_initial.py +0 -7
- nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -14
- nautobot/data_validation/models.py +16 -7
- nautobot/data_validation/navigation.py +8 -1
- nautobot/data_validation/tables.py +12 -5
- nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
- nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
- nautobot/data_validation/tests/__init__.py +2 -2
- nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
- nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
- nautobot/data_validation/tests/test_filters.py +8 -6
- nautobot/data_validation/tests/test_models.py +15 -0
- nautobot/data_validation/tests/test_views.py +190 -32
- nautobot/data_validation/urls.py +2 -5
- nautobot/data_validation/views.py +73 -40
- nautobot/dcim/api/serializers.py +3 -13
- nautobot/dcim/apps.py +4 -0
- nautobot/dcim/choices.py +65 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/custom_validators.py +84 -0
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filter_mixins.py +353 -4
- nautobot/dcim/{filters/__init__.py → filters.py} +15 -36
- nautobot/dcim/forms.py +90 -4
- nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
- nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
- nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
- nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
- nautobot/dcim/migrations/0079_remove_device_location_tenant_name_uniqueness.py +16 -0
- nautobot/dcim/migrations/0080_device_name_data_migration.py +59 -0
- nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
- nautobot/dcim/models/device_component_templates.py +33 -1
- nautobot/dcim/models/device_components.py +98 -64
- nautobot/dcim/models/devices.py +30 -20
- nautobot/dcim/navigation.py +7 -6
- nautobot/dcim/tables/devices.py +18 -0
- nautobot/dcim/tables/devicetypes.py +8 -1
- nautobot/dcim/tables/racks.py +0 -2
- nautobot/dcim/tables/template_code.py +15 -15
- nautobot/dcim/templates/dcim/cable_connect.html +28 -112
- nautobot/dcim/templates/dcim/cable_trace.html +0 -4
- nautobot/dcim/templates/dcim/{cable_edit.html → cable_update.html} +1 -1
- nautobot/dcim/templates/dcim/consoleport.html +7 -6
- nautobot/dcim/templates/dcim/consoleserverport.html +7 -6
- nautobot/dcim/templates/dcim/device/config.html +2 -2
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
- nautobot/dcim/templates/dcim/device/status.html +8 -8
- nautobot/dcim/templates/dcim/device.html +1 -1
- nautobot/dcim/templates/dcim/device_component_add.html +2 -2
- nautobot/dcim/templates/dcim/device_create.html +5 -3
- nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
- nautobot/dcim/templates/dcim/device_list.html +73 -10
- nautobot/dcim/templates/dcim/devicebay.html +1 -1
- nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
- nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
- nautobot/dcim/templates/dcim/frontport.html +10 -9
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
- nautobot/dcim/templates/dcim/interface.html +35 -7
- nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/interface_edit.html +2 -0
- nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
- nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
- nautobot/dcim/templates/dcim/module/base.html +49 -9
- nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
- nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
- nautobot/dcim/templates/dcim/module_frontports.html +1 -1
- nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
- nautobot/dcim/templates/dcim/module_list.html +57 -8
- nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
- nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
- nautobot/dcim/templates/dcim/module_powerports.html +1 -1
- nautobot/dcim/templates/dcim/module_rearports.html +1 -1
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
- nautobot/dcim/templates/dcim/platform_create.html +1 -1
- nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
- nautobot/dcim/templates/dcim/powerport.html +6 -5
- nautobot/dcim/templates/dcim/rack_elevation_list.html +17 -5
- nautobot/dcim/templates/dcim/rack_retrieve.html +22 -15
- nautobot/dcim/templates/dcim/rearport.html +8 -7
- nautobot/dcim/templates/dcim/trace/cable.html +1 -1
- nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
- nautobot/dcim/templates/dcim/virtualchassis_update.html +15 -7
- nautobot/dcim/tests/integration/test_controller.py +4 -6
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
- nautobot/dcim/tests/integration/test_create_device.py +0 -2
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
- nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
- nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
- nautobot/dcim/tests/test_api.py +194 -6
- nautobot/dcim/tests/test_custom_validators.py +229 -0
- nautobot/dcim/tests/test_filters.py +55 -7
- nautobot/dcim/tests/test_forms.py +110 -8
- nautobot/dcim/tests/test_graphql.py +44 -1
- nautobot/dcim/tests/test_models.py +328 -4
- nautobot/dcim/tests/test_tables.py +160 -0
- nautobot/dcim/tests/test_views.py +132 -29
- nautobot/dcim/urls.py +64 -21
- nautobot/dcim/utils.py +3 -3
- nautobot/dcim/views.py +777 -397
- nautobot/extras/api/views.py +60 -45
- nautobot/extras/choices.py +2 -13
- nautobot/extras/datasources/git.py +3 -1
- nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
- nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
- nautobot/extras/{filters/__init__.py → filters.py} +33 -48
- nautobot/extras/forms/forms.py +14 -15
- nautobot/extras/forms/mixins.py +0 -41
- nautobot/extras/jobs.py +2 -0
- nautobot/extras/jobs_ui.py +4 -3
- nautobot/extras/management/__init__.py +11 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
- nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
- nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
- nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
- nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
- nautobot/extras/models/__init__.py +1 -2
- nautobot/extras/models/approvals.py +33 -14
- nautobot/extras/models/change_logging.py +4 -0
- nautobot/extras/models/contacts.py +2 -0
- nautobot/extras/models/groups.py +44 -5
- nautobot/extras/models/jobs.py +60 -4
- nautobot/extras/models/mixins.py +28 -0
- nautobot/extras/models/models.py +23 -2
- nautobot/extras/models/secrets.py +1 -0
- nautobot/extras/models/statuses.py +0 -15
- nautobot/extras/navigation.py +13 -9
- nautobot/extras/plugins/__init__.py +33 -55
- nautobot/extras/plugins/marketplace_manifest.yml +49 -1
- nautobot/extras/plugins/tables.py +3 -3
- nautobot/extras/plugins/urls.py +2 -21
- nautobot/extras/plugins/utils.py +1 -33
- nautobot/extras/plugins/views.py +0 -9
- nautobot/extras/querysets.py +8 -0
- nautobot/extras/signals.py +20 -19
- nautobot/extras/tables.py +64 -68
- nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
- nautobot/extras/templates/extras/approval_dashboard.html +7 -5
- nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
- nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
- nautobot/extras/templates/extras/configcontext_update.html +1 -0
- nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
- nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
- nautobot/extras/templates/extras/gitrepository_result.html +0 -2
- nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
- nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
- nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
- nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
- nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
- nautobot/extras/templates/extras/inc/json_format.html +10 -3
- nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
- nautobot/extras/templates/extras/job.html +29 -12
- nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
- nautobot/extras/templates/extras/job_edit.html +52 -46
- nautobot/extras/templates/extras/job_list.html +29 -25
- nautobot/extras/templates/extras/marketplace.html +5 -9
- nautobot/extras/templates/extras/object_configcontext.html +1 -1
- nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
- nautobot/extras/templates/extras/objectchange_retrieve.html +19 -39
- nautobot/extras/templates/extras/plugin_detail.html +29 -24
- nautobot/extras/templates/extras/plugins_list.html +16 -26
- nautobot/extras/templates/extras/role_retrieve.html +64 -0
- nautobot/extras/templates/extras/scheduledjob.html +4 -2
- nautobot/extras/templates/extras/secret_create.html +1 -1
- nautobot/extras/templatetags/custom_links.py +12 -12
- nautobot/extras/templatetags/job_buttons.py +14 -12
- nautobot/extras/test_jobs/invalid_import.py +9 -0
- nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
- nautobot/extras/test_jobs/missing_import.py +11 -0
- nautobot/extras/tests/integration/test_computedfields.py +8 -9
- nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
- nautobot/extras/tests/integration/test_customfields.py +9 -10
- nautobot/extras/tests/integration/test_dynamicgroups.py +12 -9
- nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
- nautobot/extras/tests/integration/test_plugins.py +18 -6
- nautobot/extras/tests/integration/test_relationships.py +0 -2
- nautobot/extras/tests/test_api.py +90 -18
- nautobot/extras/tests/test_approvals.py +38 -38
- nautobot/extras/tests/test_changelog.py +59 -5
- nautobot/extras/tests/test_customfields.py +22 -13
- nautobot/extras/tests/test_customfields_filters.py +479 -0
- nautobot/extras/tests/test_dynamicgroups.py +39 -1
- nautobot/extras/tests/test_filters.py +57 -22
- nautobot/extras/tests/test_forms.py +18 -21
- nautobot/extras/tests/test_jobs.py +25 -4
- nautobot/extras/tests/test_migrations.py +1 -0
- nautobot/extras/tests/test_models.py +51 -33
- nautobot/extras/tests/test_plugins.py +36 -10
- nautobot/extras/tests/test_utils.py +3 -4
- nautobot/extras/tests/test_views.py +52 -112
- nautobot/extras/urls.py +0 -14
- nautobot/extras/views.py +164 -71
- nautobot/ipam/factory.py +7 -0
- nautobot/ipam/filter_mixins.py +38 -0
- nautobot/ipam/filters.py +53 -38
- nautobot/ipam/formfields.py +1 -1
- nautobot/ipam/forms.py +6 -3
- nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
- nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
- nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
- nautobot/ipam/models.py +29 -2
- nautobot/ipam/navigation.py +3 -2
- nautobot/ipam/signals.py +71 -0
- nautobot/ipam/tables.py +19 -6
- nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
- nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
- nautobot/ipam/templates/ipam/ipaddress.html +14 -0
- nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
- nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
- nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
- nautobot/ipam/templates/ipam/namespace_update.html +15 -0
- nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
- nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
- nautobot/ipam/templates/ipam/prefix_list.html +14 -13
- nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
- nautobot/ipam/tests/migration/test_migrations.py +89 -0
- nautobot/ipam/tests/test_api.py +13 -6
- nautobot/ipam/tests/test_filters.py +36 -1
- nautobot/ipam/tests/test_forms.py +1 -1
- nautobot/ipam/tests/test_models.py +44 -2
- nautobot/ipam/tests/test_tables.py +1 -2
- nautobot/ipam/tests/test_utils.py +1 -1
- nautobot/ipam/tests/test_views.py +13 -14
- nautobot/ipam/ui.py +0 -17
- nautobot/ipam/utils/migrations.py +16 -2
- nautobot/ipam/utils/testing.py +9 -3
- nautobot/ipam/views.py +53 -11
- nautobot/load_balancers/__init__.py +0 -0
- nautobot/load_balancers/api/__init__.py +1 -0
- nautobot/load_balancers/api/serializers.py +75 -0
- nautobot/load_balancers/api/urls.py +23 -0
- nautobot/load_balancers/api/views.py +61 -0
- nautobot/load_balancers/apps.py +17 -0
- nautobot/load_balancers/choices.py +167 -0
- nautobot/load_balancers/filters.py +225 -0
- nautobot/load_balancers/forms.py +532 -0
- nautobot/load_balancers/management/commands/__init__.py +0 -0
- nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
- nautobot/load_balancers/migrations/0001_initial.py +465 -0
- nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
- nautobot/load_balancers/migrations/__init__.py +0 -0
- nautobot/load_balancers/models.py +423 -0
- nautobot/load_balancers/navigation.py +80 -0
- nautobot/load_balancers/tables.py +255 -0
- nautobot/load_balancers/tests/__init__.py +474 -0
- nautobot/load_balancers/tests/test_api.py +353 -0
- nautobot/load_balancers/tests/test_filters.py +134 -0
- nautobot/load_balancers/tests/test_forms.py +266 -0
- nautobot/load_balancers/tests/test_models.py +195 -0
- nautobot/load_balancers/tests/test_views.py +229 -0
- nautobot/load_balancers/urls.py +17 -0
- nautobot/load_balancers/views.py +248 -0
- nautobot/project-static/dist/css/github-dark.min.css +10 -0
- nautobot/project-static/dist/css/github.min.css +10 -0
- nautobot/project-static/dist/css/nautobot.css +1 -11
- nautobot/project-static/dist/css/nautobot.css.map +1 -1
- nautobot/project-static/dist/js/libraries.js +1 -1
- nautobot/project-static/dist/js/libraries.js.map +1 -1
- nautobot/project-static/dist/js/nautobot.js +1 -1
- nautobot/project-static/dist/js/nautobot.js.map +1 -1
- nautobot/project-static/js/cabletrace.js +1 -1
- nautobot/project-static/js/forms.js +13 -0
- nautobot/project-static/js/interface_filtering.js +20 -16
- nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
- nautobot/project-static/nautobot-icons/cloud.svg +1 -1
- nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
- nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
- nautobot/project-static/nautobot-icons/elements.svg +1 -1
- nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
- nautobot/project-static/nautobot-icons/hammer.svg +1 -1
- nautobot/project-static/nautobot-icons/organization.svg +3 -0
- nautobot/project-static/nautobot-icons/secrets.svg +1 -1
- nautobot/project-static/nautobot-icons/security.svg +3 -0
- nautobot/project-static/nautobot-icons/server.svg +1 -1
- nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
- nautobot/project-static/nautobot-icons/star.svg +1 -1
- nautobot/tenancy/api/serializers.py +1 -0
- nautobot/tenancy/api/views.py +2 -1
- nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
- nautobot/tenancy/navigation.py +3 -1
- nautobot/tenancy/tests/test_filters.py +0 -2
- nautobot/tenancy/views.py +2 -1
- nautobot/ui/package-lock.json +87 -4
- nautobot/ui/package.json +2 -1
- nautobot/ui/src/js/collapse.js +3 -3
- nautobot/ui/src/js/nautobot.js +16 -1
- nautobot/ui/src/js/select2.js +53 -2
- nautobot/ui/src/scss/colors.scss +1 -1
- nautobot/ui/src/scss/nautobot.scss +112 -30
- nautobot/ui/webpack.config.js +13 -0
- nautobot/users/templates/users/preferences.html +11 -2
- nautobot/users/templates/users/profile.html +45 -12
- nautobot/users/templates/users/sessionkey_delete.html +1 -1
- nautobot/users/tests/test_api.py +4 -0
- nautobot/users/views.py +4 -2
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/models.py +1 -68
- nautobot/virtualization/navigation.py +3 -2
- nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
- nautobot/virtualization/tests/test_api.py +3 -0
- nautobot/virtualization/tests/test_filters.py +10 -1
- nautobot/virtualization/tests/test_models.py +45 -4
- nautobot/virtualization/views.py +4 -1
- nautobot/vpn/__init__.py +0 -0
- nautobot/vpn/api/serializers.py +113 -0
- nautobot/vpn/api/urls.py +19 -0
- nautobot/vpn/api/views.py +70 -0
- nautobot/vpn/apps.py +8 -0
- nautobot/vpn/choices.py +171 -0
- nautobot/vpn/factory.py +219 -0
- nautobot/vpn/filters.py +234 -0
- nautobot/vpn/forms.py +487 -0
- nautobot/vpn/homepage.py +19 -0
- nautobot/vpn/migrations/0001_initial.py +541 -0
- nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
- nautobot/vpn/migrations/__init__.py +0 -0
- nautobot/vpn/models.py +535 -0
- nautobot/vpn/navigation.py +98 -0
- nautobot/vpn/tables.py +383 -0
- nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
- nautobot/vpn/tests/__init__.py +0 -0
- nautobot/vpn/tests/test_api.py +336 -0
- nautobot/vpn/tests/test_filters.py +139 -0
- nautobot/vpn/tests/test_forms.py +293 -0
- nautobot/vpn/tests/test_models.py +147 -0
- nautobot/vpn/tests/test_views.py +300 -0
- nautobot/vpn/urls.py +16 -0
- nautobot/vpn/views.py +495 -0
- nautobot/wireless/navigation.py +3 -2
- nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
- nautobot/wireless/tests/test_api.py +1 -1
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +15 -15
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +514 -572
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +1 -0
- nautobot/circuits/templates/circuits/circuit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuit_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittermination.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittype.html +0 -2
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
- nautobot/circuits/templates/circuits/provider.html +0 -2
- nautobot/circuits/templates/circuits/provider_edit.html +0 -2
- nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
- nautobot/circuits/templates/circuits/provider_update.html +0 -1
- nautobot/circuits/templates/circuits/providernetwork.html +0 -2
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
- nautobot/core/templates/buttons/import.html +0 -9
- nautobot/data_validation/template_content.py +0 -42
- nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
- nautobot/dcim/filters/mixins.py +0 -354
- nautobot/dcim/templates/dcim/controller/base.html +0 -2
- nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/device/base.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
- nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
- nautobot/dcim/templates/dcim/device/frontports.html +0 -2
- nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
- nautobot/dcim/templates/dcim/device/inventory.html +0 -2
- nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
- nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
- nautobot/dcim/templates/dcim/device/powerports.html +0 -2
- nautobot/dcim/templates/dcim/device/rearports.html +0 -2
- nautobot/dcim/templates/dcim/device/wireless.html +0 -2
- nautobot/dcim/templates/dcim/device_component.html +0 -2
- nautobot/dcim/templates/dcim/device_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/devicetype.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
- nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/location.html +0 -2
- nautobot/dcim/templates/dcim/location_edit.html +0 -2
- nautobot/dcim/templates/dcim/location_retrieve.html +0 -243
- nautobot/dcim/templates/dcim/locationtype.html +0 -2
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/manufacturer.html +0 -2
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
- nautobot/dcim/templates/dcim/platform.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/rack.html +0 -2
- nautobot/dcim/templates/dcim/rack_edit.html +0 -2
- nautobot/dcim/templates/dcim/rackgroup.html +0 -2
- nautobot/dcim/templates/dcim/rackreservation.html +0 -2
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
- nautobot/dcim/ui.py +0 -29
- nautobot/extras/templates/extras/computedfield.html +0 -2
- nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontext.html +0 -2
- nautobot/extras/templates/extras/configcontext_edit.html +0 -2
- nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontextschema.html +0 -2
- nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
- nautobot/extras/templates/extras/contact_retrieve.html +0 -2
- nautobot/extras/templates/extras/customfield.html +0 -2
- nautobot/extras/templates/extras/customfield_edit.html +0 -2
- nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/customlink.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
- nautobot/extras/templates/extras/exporttemplate.html +0 -2
- nautobot/extras/templates/extras/gitrepository.html +0 -2
- nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
- nautobot/extras/templates/extras/graphqlquery.html +0 -2
- nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -97
- nautobot/extras/templates/extras/job_detail.html +0 -2
- nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobhook.html +0 -2
- nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobresult.html +0 -2
- nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
- nautobot/extras/templates/extras/note.html +0 -2
- nautobot/extras/templates/extras/note_retrieve.html +0 -1
- nautobot/extras/templates/extras/object_changelog.html +0 -2
- nautobot/extras/templates/extras/object_notes.html +0 -2
- nautobot/extras/templates/extras/objectchange.html +0 -2
- nautobot/extras/templates/extras/objectchange_list.html +0 -3
- nautobot/extras/templates/extras/relationship.html +0 -1
- nautobot/extras/templates/extras/secret.html +0 -1
- nautobot/extras/templates/extras/secret_edit.html +0 -1
- nautobot/extras/templates/extras/secretsgroup.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
- nautobot/extras/templates/extras/status.html +0 -2
- nautobot/extras/templates/extras/tag.html +0 -2
- nautobot/extras/templates/extras/tag_edit.html +0 -2
- nautobot/extras/templates/extras/tag_retrieve.html +0 -2
- nautobot/extras/templates/extras/team_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
- nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
- nautobot/ipam/templates/ipam/prefix.html +0 -2
- nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
- nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/rir.html +0 -2
- nautobot/ipam/templates/ipam/routetarget.html +0 -1
- nautobot/ipam/templates/ipam/service.html +0 -2
- nautobot/ipam/templates/ipam/service_edit.html +0 -2
- nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlan.html +0 -2
- nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
- nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlangroup.html +0 -2
- nautobot/ipam/templates/ipam/vrf.html +0 -1
- nautobot/tenancy/templates/tenancy/tenant.html +0 -2
- nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
- nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
- /nautobot/dcim/templates/dcim/{cable.html → cable_retrieve.html} +0 -0
- /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
nautobot/core/ui/breadcrumbs.py
CHANGED
|
@@ -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
|
-
|
|
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, "
|
|
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
|
-
|
|
455
|
-
if not instance or not
|
|
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(
|
|
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
|
-
|
|
475
|
-
if not instance or not
|
|
479
|
+
related_object = self.get_related_object(instance)
|
|
480
|
+
if not instance or not related_object:
|
|
476
481
|
return ""
|
|
477
|
-
return getattr(
|
|
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
|
|
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.
|
|
@@ -507,14 +558,7 @@ class Breadcrumbs:
|
|
|
507
558
|
and there is `context['detail'] = True` set in context
|
|
508
559
|
|
|
509
560
|
!!! important
|
|
510
|
-
|
|
511
|
-
- `InstanceBreadcrumbItem` at the end of `detail` breadcrumbs
|
|
512
|
-
- `ModelBreadcrumbItem` at the beginning of `list` and `detail` breadcrumbs
|
|
513
|
-
|
|
514
|
-
You can override this behavior by subclassing this class and updating
|
|
515
|
-
the `list_breadcrumb_item` or `detail_breadcrumb_item` attributes.
|
|
516
|
-
|
|
517
|
-
If you're using custom action other than `list` / `detail` you need to remember to add above breadcrumbs
|
|
561
|
+
If you're using custom action other than `list` / `detail` you need to remember to add list view breadcrumb manually
|
|
518
562
|
if you need them in your custom action.
|
|
519
563
|
|
|
520
564
|
Attributes:
|
|
@@ -553,7 +597,7 @@ class Breadcrumbs:
|
|
|
553
597
|
|
|
554
598
|
# Set the default breadcrumbs
|
|
555
599
|
self.items = {
|
|
556
|
-
"list": [
|
|
600
|
+
"list": [],
|
|
557
601
|
"detail": [*self.breadcrumb_items],
|
|
558
602
|
}
|
|
559
603
|
|
|
@@ -561,9 +605,6 @@ class Breadcrumbs:
|
|
|
561
605
|
if items:
|
|
562
606
|
self.items = {**self.items, **items}
|
|
563
607
|
|
|
564
|
-
# Built-in feature: always add the instance details at the end of breadcrumbs path
|
|
565
|
-
self.items["detail"].append(InstanceBreadcrumbItem(label=detail_item_label))
|
|
566
|
-
|
|
567
608
|
def get_breadcrumbs_items(self, context: Context) -> list[tuple[str, str]]:
|
|
568
609
|
"""
|
|
569
610
|
Compute the list of breadcrumb items for the given context.
|
|
@@ -579,7 +620,8 @@ class Breadcrumbs:
|
|
|
579
620
|
action = context.get("view_action", "")
|
|
580
621
|
detail = context.get("detail", False)
|
|
581
622
|
items = self.get_items_for_action(self.items, action, detail, context)
|
|
582
|
-
|
|
623
|
+
items_pairs = [item.as_pair(context) for item in items if item.should_render(context)]
|
|
624
|
+
return list(chain.from_iterable(items_pairs))
|
|
583
625
|
|
|
584
626
|
def filter_breadcrumbs_items(self, items: list[tuple[str, str]], context: Context) -> list[tuple[str, str]]:
|
|
585
627
|
"""
|
|
@@ -657,7 +699,7 @@ class Breadcrumbs:
|
|
|
657
699
|
Provide additional data to include in the rendering context, based on the configuration of this component.
|
|
658
700
|
|
|
659
701
|
Context updated here will be applied to resolving url and labels.
|
|
660
|
-
Please
|
|
702
|
+
Please note that you can't override `breadcrumb_items` here because items are generated after this method call.
|
|
661
703
|
|
|
662
704
|
Args:
|
|
663
705
|
context (Context): The current context passed to `render()`.
|
|
@@ -668,6 +710,7 @@ class Breadcrumbs:
|
|
|
668
710
|
return {}
|
|
669
711
|
|
|
670
712
|
|
|
713
|
+
@deprecation.class_deprecated("Functionality of this class was moved to the AncestorsInstanceBreadcrumbItem.")
|
|
671
714
|
class AncestorsBreadcrumbs(Breadcrumbs):
|
|
672
715
|
"""
|
|
673
716
|
Breadcrumbs class which can render list of ancestors of given instance.
|
|
@@ -675,7 +718,6 @@ class AncestorsBreadcrumbs(Breadcrumbs):
|
|
|
675
718
|
Default behavior:
|
|
676
719
|
- render breadcrumb item with link to the list view
|
|
677
720
|
- dynamically add list of `InstanceBreadcrumbItem` from `ancestors()`
|
|
678
|
-
- adds standard breadcrumb item with link to the details
|
|
679
721
|
"""
|
|
680
722
|
|
|
681
723
|
def get_items_for_action(
|
|
@@ -714,7 +756,6 @@ class AncestorsBreadcrumbs(Breadcrumbs):
|
|
|
714
756
|
return [
|
|
715
757
|
ModelBreadcrumbItem(model=instance),
|
|
716
758
|
*self.get_ancestors_items(instance),
|
|
717
|
-
InstanceBreadcrumbItem(instance=instance, label=self.detail_item_label),
|
|
718
759
|
]
|
|
719
760
|
|
|
720
761
|
def get_ancestors_items(self, instance: TreeModel) -> list[BaseBreadcrumbItem]:
|
nautobot/core/ui/bulk_buttons.py
CHANGED
nautobot/core/ui/choices.py
CHANGED
|
@@ -66,37 +66,153 @@ class EChartsTypeChoices(ChoiceSet):
|
|
|
66
66
|
)
|
|
67
67
|
|
|
68
68
|
|
|
69
|
-
class
|
|
70
|
-
"""Available chart
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
101
|
+
LIGHTER_GREEN_RED_COLORS = (
|
|
102
|
+
UI_COLORS["green-lighter"],
|
|
103
|
+
UI_COLORS["red-lighter"],
|
|
104
|
+
)
|
|
81
105
|
|
|
82
106
|
CHOICES = (
|
|
83
|
-
(
|
|
84
|
-
(
|
|
107
|
+
(NAUTOBOT, "Default Nautobot Colors"),
|
|
108
|
+
(LIGHTER_GREEN_AND_RED_ONLY, "Lighter Green and Red Only"),
|
|
85
109
|
)
|
|
86
110
|
|
|
87
111
|
COLORS = {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
UI_COLORS["orange-0"]["light"],
|
|
91
|
-
UI_COLORS["green-0"]["light"],
|
|
92
|
-
UI_COLORS["red-0"]["light"],
|
|
93
|
-
UI_COLORS["gray-0"]["light"],
|
|
94
|
-
],
|
|
95
|
-
DARK: [
|
|
96
|
-
UI_COLORS["blue-0"]["dark"],
|
|
97
|
-
UI_COLORS["orange-0"]["dark"],
|
|
98
|
-
UI_COLORS["green-0"]["dark"],
|
|
99
|
-
UI_COLORS["red-0"]["dark"],
|
|
100
|
-
UI_COLORS["gray-0"]["dark"],
|
|
101
|
-
],
|
|
112
|
+
NAUTOBOT: NAUTOBOT_COLORS,
|
|
113
|
+
LIGHTER_GREEN_AND_RED_ONLY: LIGHTER_GREEN_RED_COLORS,
|
|
102
114
|
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class NavigationIconChoices(ChoiceSet):
|
|
118
|
+
"""Navigation icons for major Nautobot sections."""
|
|
119
|
+
|
|
120
|
+
DEVICES = "server"
|
|
121
|
+
IPAM = "sitemap-outline"
|
|
122
|
+
ORGANIZATION = "organization"
|
|
123
|
+
CIRCUITS = "cable-data"
|
|
124
|
+
VPN = "bus-shield"
|
|
125
|
+
ROUTING = "route"
|
|
126
|
+
POWER = "battery-3"
|
|
127
|
+
WIRELESS = "wifi"
|
|
128
|
+
DEVICE_LIFECYCLE = "device-lifecycle"
|
|
129
|
+
SECRETS = "secrets"
|
|
130
|
+
SECURITY = "security"
|
|
131
|
+
LOAD_BALANCERS = "arrow-decision"
|
|
132
|
+
VIRTUALIZATION = "cloud-upload"
|
|
133
|
+
CLOUD = "cloud"
|
|
134
|
+
DESIGN = "hammer"
|
|
135
|
+
APPROVAL_WORKFLOWS = "checkbox-circle"
|
|
136
|
+
EXTENSIBILITY = "extensibility"
|
|
137
|
+
GOLDEN_CONFIG = "sliders-vert-2"
|
|
138
|
+
JOBS = "share"
|
|
139
|
+
APPS = "elements"
|
|
140
|
+
|
|
141
|
+
CHOICES = (
|
|
142
|
+
(DEVICES, "Devices"),
|
|
143
|
+
(IPAM, "IPAM"),
|
|
144
|
+
(ORGANIZATION, "Organization"),
|
|
145
|
+
(CIRCUITS, "Circuits"),
|
|
146
|
+
(VPN, "VPN"),
|
|
147
|
+
(ROUTING, "Routing"),
|
|
148
|
+
(POWER, "Power"),
|
|
149
|
+
(WIRELESS, "Wireless"),
|
|
150
|
+
(DEVICE_LIFECYCLE, "Device Lifecycle"),
|
|
151
|
+
(SECRETS, "Secrets"),
|
|
152
|
+
(SECURITY, "Security"),
|
|
153
|
+
(LOAD_BALANCERS, "Load Balancers"),
|
|
154
|
+
(VIRTUALIZATION, "Virtualization"),
|
|
155
|
+
(CLOUD, "Cloud"),
|
|
156
|
+
(DESIGN, "Design"),
|
|
157
|
+
(APPROVAL_WORKFLOWS, "Approval Workflows"),
|
|
158
|
+
(EXTENSIBILITY, "Extensibility"),
|
|
159
|
+
(GOLDEN_CONFIG, "Golden Config"),
|
|
160
|
+
(JOBS, "Jobs"),
|
|
161
|
+
(APPS, "Apps"),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class NavigationWeightChoices(ChoiceSet):
|
|
166
|
+
"""Navigation weights for major Nautobot sections."""
|
|
167
|
+
|
|
168
|
+
# In general we are looking to:
|
|
169
|
+
# - Keep data models before the default weight of 1000
|
|
170
|
+
# - Leave a gap between the default location of 1000
|
|
171
|
+
# - Keep non-model items after the default weight of 1000
|
|
172
|
+
# - Keep key items of GC, Jobs, and Apps at the end for easy access
|
|
173
|
+
DEVICES = 100
|
|
174
|
+
IPAM = 200
|
|
175
|
+
ORGANIZATION = 300
|
|
176
|
+
CIRCUITS = 400
|
|
177
|
+
VPN = 450
|
|
178
|
+
ROUTING = 500
|
|
179
|
+
POWER = 550
|
|
180
|
+
WIRELESS = 600
|
|
181
|
+
DEVICE_LIFECYCLE = 650
|
|
182
|
+
SECRETS = 700
|
|
183
|
+
SECURITY = 750
|
|
184
|
+
LOAD_BALANCERS = 800
|
|
185
|
+
VIRTUALIZATION = 850
|
|
186
|
+
CLOUD = 900
|
|
187
|
+
# We leave a gap here to allow for future expansion and don't use 1000
|
|
188
|
+
# since it the default weight for NavMenuTab if none is specified.
|
|
189
|
+
DESIGN = 1100
|
|
190
|
+
APPROVAL_WORKFLOWS = 1200
|
|
191
|
+
EXTENSIBILITY = 1300
|
|
192
|
+
# look to keep these last few items at the end of the nav for easy access
|
|
193
|
+
GOLDEN_CONFIG = 2000
|
|
194
|
+
JOBS = 2100
|
|
195
|
+
APPS = 2200
|
|
196
|
+
|
|
197
|
+
CHOICES = (
|
|
198
|
+
(DEVICES, "Devices"),
|
|
199
|
+
(IPAM, "IPAM"),
|
|
200
|
+
(ORGANIZATION, "Organization"),
|
|
201
|
+
(CIRCUITS, "Circuits"),
|
|
202
|
+
(VPN, "VPN"),
|
|
203
|
+
(ROUTING, "Routing"),
|
|
204
|
+
(POWER, "Power"),
|
|
205
|
+
(WIRELESS, "Wireless"),
|
|
206
|
+
(DEVICE_LIFECYCLE, "Device Lifecycle"),
|
|
207
|
+
(SECRETS, "Secrets"),
|
|
208
|
+
(SECURITY, "Security"),
|
|
209
|
+
(VIRTUALIZATION, "Virtualization"),
|
|
210
|
+
(LOAD_BALANCERS, "Load Balancers"),
|
|
211
|
+
(CLOUD, "Cloud"),
|
|
212
|
+
(DESIGN, "Design"),
|
|
213
|
+
(APPROVAL_WORKFLOWS, "Approval Workflows"),
|
|
214
|
+
(EXTENSIBILITY, "Extensibility"),
|
|
215
|
+
(GOLDEN_CONFIG, "Golden Config"),
|
|
216
|
+
(JOBS, "Jobs"),
|
|
217
|
+
(APPS, "Apps"),
|
|
218
|
+
)
|
nautobot/core/ui/constants.py
CHANGED
|
@@ -1,22 +1,86 @@
|
|
|
1
1
|
UI_COLORS = {
|
|
2
|
-
"blue
|
|
2
|
+
"blue": {
|
|
3
3
|
"light": "#007dff",
|
|
4
|
-
"dark": "#
|
|
4
|
+
"dark": "#339dff",
|
|
5
5
|
},
|
|
6
|
-
"
|
|
7
|
-
"light": "#
|
|
8
|
-
"dark": "#
|
|
6
|
+
"blue-darker": {
|
|
7
|
+
"light": "#0e4781",
|
|
8
|
+
"dark": "#255581",
|
|
9
|
+
},
|
|
10
|
+
"blue-lighter": {
|
|
11
|
+
"light": "#8cc5ff",
|
|
12
|
+
"dark": "#a3d3ff",
|
|
13
|
+
},
|
|
14
|
+
"gray": {
|
|
15
|
+
"light": "#b0b0b0",
|
|
16
|
+
"dark": "#828282",
|
|
17
|
+
},
|
|
18
|
+
"gray-darker": {
|
|
19
|
+
"light": "#5e5e5e",
|
|
20
|
+
"dark": "#494949",
|
|
21
|
+
},
|
|
22
|
+
"gray-lighter": {
|
|
23
|
+
"light": "#dbdbdb",
|
|
24
|
+
"dark": "#c7c7c7",
|
|
9
25
|
},
|
|
10
|
-
"green
|
|
26
|
+
"green": {
|
|
11
27
|
"light": "#1ca92a",
|
|
12
|
-
"dark": "#
|
|
28
|
+
"dark": "#2ecc40",
|
|
29
|
+
},
|
|
30
|
+
"green-darker": {
|
|
31
|
+
"light": "#1b5a21",
|
|
32
|
+
"dark": "#236a2b",
|
|
33
|
+
},
|
|
34
|
+
"green-lighter": {
|
|
35
|
+
"light": "#99d89f",
|
|
36
|
+
"dark": "#a1e8a9",
|
|
37
|
+
},
|
|
38
|
+
"orange": {
|
|
39
|
+
"light": "#e07807",
|
|
40
|
+
"dark": "#ff9933",
|
|
13
41
|
},
|
|
14
|
-
"
|
|
42
|
+
"orange-darker": {
|
|
43
|
+
"light": "#734411",
|
|
44
|
+
"dark": "#815325",
|
|
45
|
+
},
|
|
46
|
+
"orange-lighter": {
|
|
47
|
+
"light": "#f1c28f",
|
|
48
|
+
"dark": "#ffd1a3",
|
|
49
|
+
},
|
|
50
|
+
"purple": {
|
|
51
|
+
"light": "#7b61ff",
|
|
52
|
+
"dark": "#a394ff",
|
|
53
|
+
},
|
|
54
|
+
"purple-darker": {
|
|
55
|
+
"light": "#463a81",
|
|
56
|
+
"dark": "#585181",
|
|
57
|
+
},
|
|
58
|
+
"purple-lighter": {
|
|
59
|
+
"light": "#c4b8ff",
|
|
60
|
+
"dark": "#d6cfff",
|
|
61
|
+
},
|
|
62
|
+
"red": {
|
|
15
63
|
"light": "#e01f1f",
|
|
16
|
-
"dark": "#
|
|
64
|
+
"dark": "#ff4c4c",
|
|
65
|
+
},
|
|
66
|
+
"red-darker": {
|
|
67
|
+
"light": "#731c1c",
|
|
68
|
+
"dark": "#813131",
|
|
69
|
+
},
|
|
70
|
+
"red-lighter": {
|
|
71
|
+
"light": "#f19a9a",
|
|
72
|
+
"dark": "#ffaeae",
|
|
73
|
+
},
|
|
74
|
+
"turquoise": {
|
|
75
|
+
"light": "#00bfa5",
|
|
76
|
+
"dark": "#26d7c5",
|
|
77
|
+
},
|
|
78
|
+
"turquoise-darker": {
|
|
79
|
+
"light": "#0e6459",
|
|
80
|
+
"dark": "#1f6f67",
|
|
17
81
|
},
|
|
18
|
-
"
|
|
19
|
-
"light": "#
|
|
20
|
-
"dark": "#
|
|
82
|
+
"turquoise-lighter": {
|
|
83
|
+
"light": "#8ce2d7",
|
|
84
|
+
"dark": "#9dede5",
|
|
21
85
|
},
|
|
22
86
|
}
|
nautobot/core/ui/echarts.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|