nautobot 3.0.0a2__py3-none-any.whl → 3.0.0a3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/choices.py +0 -2
- nautobot/apps/filters.py +7 -9
- nautobot/apps/models.py +2 -2
- nautobot/apps/ui.py +9 -1
- nautobot/circuits/filters.py +3 -2
- nautobot/circuits/navigation.py +3 -2
- nautobot/circuits/templates/circuits/circuit.html +1 -1
- nautobot/circuits/templates/circuits/circuit_create.html +3 -3
- nautobot/circuits/templates/circuits/circuittermination.html +1 -1
- nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
- nautobot/circuits/templates/circuits/circuittype.html +1 -1
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
- nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
- nautobot/circuits/templates/circuits/providernetwork.html +1 -1
- nautobot/circuits/tests/integration/test_circuit.py +10 -13
- 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 +1 -0
- nautobot/core/api/views.py +8 -0
- nautobot/core/apps/__init__.py +11 -10
- nautobot/core/celery/__init__.py +3 -5
- nautobot/core/checks.py +46 -0
- nautobot/core/cli/bootstrap_v3_to_v5.py +70 -1
- nautobot/core/cli/migrate_deprecated_templates.py +200 -0
- nautobot/core/constants.py +3 -0
- nautobot/core/context_processors.py +9 -1
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/jobs/__init__.py +6 -3
- nautobot/core/jobs/groups.py +31 -1
- nautobot/core/management/commands/generate_test_data.py +28 -9
- nautobot/core/models/generics.py +9 -1
- nautobot/core/models/tree_queries.py +10 -5
- nautobot/core/settings.py +18 -12
- nautobot/core/settings.yaml +13 -7
- 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/config/config.html +12 -12
- nautobot/core/templates/admin/index.html +3 -3
- 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/panel.html +3 -3
- nautobot/core/templates/components/tab/content_wrapper.html +2 -3
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
- nautobot/core/templates/echarts/echarts.html +1 -1
- nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
- nautobot/core/templates/generic/object_bulk_create.html +4 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
- 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_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 +2 -3
- nautobot/core/templates/graphene/graphiql.html +7 -7
- 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/form_static_field.html +6 -0
- nautobot/core/templates/inc/header.html +1 -1
- nautobot/core/templates/inc/image_attachments.html +2 -1
- nautobot/core/templates/inc/nav_menu.html +2 -1
- nautobot/core/templates/inc/search_panel.html +4 -4
- nautobot/core/templates/login.html +4 -2
- nautobot/core/templates/nautobot_config.py.j2 +6 -5
- nautobot/core/templates/redoc_ui.html +7 -0
- 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 +4 -4
- nautobot/core/templates/utilities/theme_preview.html +16 -3
- nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
- nautobot/core/templatetags/helpers.py +52 -6
- nautobot/core/testing/api.py +68 -9
- nautobot/core/testing/filters.py +0 -23
- nautobot/core/testing/integration.py +23 -10
- nautobot/core/testing/mixins.py +2 -0
- nautobot/core/testing/views.py +4 -0
- nautobot/core/tests/integration/test_app_home.py +34 -30
- nautobot/core/tests/integration/test_app_navbar.py +3 -0
- nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
- nautobot/core/tests/runner.py +9 -1
- nautobot/core/tests/test_api.py +5 -3
- nautobot/core/tests/test_breadcrumbs.py +6 -7
- 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 +75 -1
- 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_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +53 -13
- nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
- nautobot/core/tests/test_tree_queries.py +14 -1
- nautobot/core/tests/test_ui.py +1 -1
- nautobot/core/tests/test_utils.py +31 -4
- nautobot/core/tests/test_views.py +159 -31
- nautobot/core/ui/breadcrumbs.py +2 -12
- nautobot/core/ui/choices.py +142 -10
- nautobot/core/ui/constants.py +76 -12
- nautobot/core/ui/object_detail.py +92 -12
- nautobot/core/urls.py +12 -1
- nautobot/core/utils/cache.py +2 -1
- nautobot/core/utils/filtering.py +17 -17
- nautobot/core/utils/lookup.py +3 -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 +15 -3
- nautobot/core/views/renderers.py +2 -0
- 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 +0 -12
- 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 +0 -13
- nautobot/dcim/apps.py +4 -0
- nautobot/dcim/choices.py +16 -0
- nautobot/dcim/custom_validators.py +84 -0
- nautobot/dcim/filter_mixins.py +353 -4
- nautobot/dcim/{filters/__init__.py → filters.py} +2 -35
- nautobot/dcim/forms.py +1 -1
- nautobot/dcim/migrations/0078_remove_device_location_tenant_name_uniqueness.py +16 -0
- nautobot/dcim/migrations/0079_device_name_data_migration.py +59 -0
- nautobot/dcim/models/device_components.py +81 -68
- nautobot/dcim/models/devices.py +13 -16
- nautobot/dcim/navigation.py +7 -6
- nautobot/dcim/tables/devices.py +3 -0
- nautobot/dcim/tables/template_code.py +14 -14
- nautobot/dcim/templates/dcim/cable.html +2 -61
- nautobot/dcim/templates/dcim/cable_connect.html +28 -112
- nautobot/dcim/templates/dcim/cable_edit.html +2 -5
- nautobot/dcim/templates/dcim/cable_retrieve.html +61 -0
- nautobot/dcim/templates/dcim/cable_trace.html +1 -3
- nautobot/dcim/templates/dcim/cable_update.html +5 -0
- nautobot/dcim/templates/dcim/consoleport.html +6 -5
- nautobot/dcim/templates/dcim/consoleserverport.html +6 -5
- nautobot/dcim/templates/dcim/device/config.html +2 -2
- nautobot/dcim/templates/dcim/device/consoleports.html +1 -1
- nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -1
- nautobot/dcim/templates/dcim/device/devicebays.html +1 -1
- nautobot/dcim/templates/dcim/device/frontports.html +1 -1
- nautobot/dcim/templates/dcim/device/interfaces.html +1 -1
- nautobot/dcim/templates/dcim/device/inventory.html +1 -1
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
- nautobot/dcim/templates/dcim/device/modulebays.html +1 -1
- nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -1
- nautobot/dcim/templates/dcim/device/powerports.html +1 -1
- nautobot/dcim/templates/dcim/device/rearports.html +1 -1
- nautobot/dcim/templates/dcim/device/status.html +8 -8
- nautobot/dcim/templates/dcim/device/wireless.html +1 -1
- 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_populate.html +2 -2
- nautobot/dcim/templates/dcim/devicetype.html +1 -1
- 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 +9 -8
- nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
- nautobot/dcim/templates/dcim/interface.html +26 -6
- nautobot/dcim/templates/dcim/interface_bulk_delete.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/location_retrieve.html +1 -242
- nautobot/dcim/templates/dcim/module/base.html +49 -9
- nautobot/dcim/templates/dcim/module_list.html +57 -8
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
- nautobot/dcim/templates/dcim/platform_create.html +1 -1
- nautobot/dcim/templates/dcim/powerfeed.html +1 -1
- nautobot/dcim/templates/dcim/powerpanel.html +1 -1
- nautobot/dcim/templates/dcim/powerport.html +5 -4
- nautobot/dcim/templates/dcim/rack_elevation_list.html +16 -4
- nautobot/dcim/templates/dcim/rack_retrieve.html +33 -15
- nautobot/dcim/templates/dcim/rearport.html +7 -6
- nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
- nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
- nautobot/dcim/templates/dcim/virtualchassis_update.html +14 -6
- nautobot/dcim/tests/integration/test_controller.py +1 -0
- nautobot/dcim/tests/test_api.py +8 -0
- nautobot/dcim/tests/test_custom_validators.py +229 -0
- nautobot/dcim/tests/test_filters.py +12 -6
- nautobot/dcim/tests/test_models.py +63 -4
- nautobot/dcim/tests/test_views.py +63 -22
- nautobot/dcim/urls.py +64 -21
- nautobot/dcim/utils.py +3 -3
- nautobot/dcim/views.py +547 -273
- nautobot/extras/api/views.py +9 -1
- nautobot/extras/choices.py +2 -13
- 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} +14 -46
- nautobot/extras/forms/forms.py +5 -13
- nautobot/extras/forms/mixins.py +0 -41
- nautobot/extras/management/__init__.py +9 -0
- 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/models/__init__.py +1 -2
- nautobot/extras/models/approvals.py +22 -13
- nautobot/extras/models/contacts.py +2 -0
- nautobot/extras/models/groups.py +44 -5
- nautobot/extras/models/jobs.py +59 -1
- nautobot/extras/models/mixins.py +28 -0
- nautobot/extras/models/models.py +13 -0
- 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/tables.py +3 -3
- nautobot/extras/plugins/urls.py +2 -21
- nautobot/extras/plugins/utils.py +1 -33
- nautobot/extras/plugins/views.py +0 -4
- nautobot/extras/signals.py +20 -19
- nautobot/extras/tables.py +52 -68
- 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/computedfield.html +1 -1
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
- nautobot/extras/templates/extras/customfield.html +1 -1
- 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/graphqlquery_retrieve.html +1 -96
- 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 -37
- nautobot/extras/templates/extras/plugin_detail.html +26 -21
- 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/secretsgroup.html +1 -1
- nautobot/extras/templates/extras/tag.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_configcontextschema.py +27 -26
- nautobot/extras/tests/integration/test_customfields.py +8 -7
- nautobot/extras/tests/integration/test_dynamicgroups.py +5 -1
- nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
- nautobot/extras/tests/integration/test_plugins.py +18 -6
- nautobot/extras/tests/test_api.py +27 -18
- nautobot/extras/tests/test_approvals.py +38 -38
- nautobot/extras/tests/test_changelog.py +35 -3
- 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 +21 -19
- 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 +13 -31
- nautobot/extras/tests/test_plugins.py +36 -10
- nautobot/extras/tests/test_views.py +31 -30
- nautobot/extras/views.py +81 -19
- nautobot/ipam/factory.py +7 -0
- nautobot/ipam/filter_mixins.py +38 -0
- nautobot/ipam/filters.py +27 -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 +13 -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_update.html +15 -0
- nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
- nautobot/ipam/templates/ipam/prefix_list.html +14 -13
- nautobot/ipam/templates/ipam/service.html +1 -1
- nautobot/ipam/templates/ipam/vlan.html +1 -1
- 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 +10 -0
- nautobot/ipam/tests/test_forms.py +1 -1
- nautobot/ipam/tests/test_models.py +43 -1
- 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 +46 -6
- nautobot/project-static/dist/css/nautobot.css +1 -1
- nautobot/project-static/dist/css/nautobot.css.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/interface_filtering.js +20 -16
- nautobot/project-static/nautobot-icons/battery-3.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/src/js/collapse.js +3 -3
- nautobot/ui/src/js/nautobot.js +16 -0
- nautobot/ui/src/scss/colors.scss +1 -1
- nautobot/ui/src/scss/nautobot.scss +61 -28
- 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/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.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_models.py +44 -4
- 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 +209 -0
- nautobot/vpn/filters.py +233 -0
- nautobot/vpn/forms.py +486 -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 +527 -0
- nautobot/vpn/navigation.py +98 -0
- nautobot/vpn/tables.py +380 -0
- nautobot/vpn/templates/vpn/vpnprofile.html +2 -0
- nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
- nautobot/vpn/tests/__init__.py +0 -0
- nautobot/vpn/tests/test_api.py +341 -0
- nautobot/vpn/tests/test_filters.py +139 -0
- nautobot/vpn/tests/test_forms.py +294 -0
- nautobot/vpn/tests/test_models.py +97 -0
- nautobot/vpn/tests/test_views.py +281 -0
- nautobot/vpn/urls.py +16 -0
- nautobot/vpn/views.py +437 -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.0a3.dist-info}/METADATA +14 -14
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/RECORD +417 -366
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/entry_points.txt +1 -0
- nautobot/data_validation/template_content.py +0 -42
- nautobot/dcim/filters/mixins.py +0 -354
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
- /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/LICENSE.txt +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/NOTICE +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0a3.dist-info}/WHEEL +0 -0
nautobot/ui/src/js/collapse.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ---
|
|
6
6
|
* Critical difference between this and default Bootstrap 5 collapse implementation is that Bootstrap only supports
|
|
7
7
|
* toggling individual panel states without an option to toggle them collectively. See an explanation below:
|
|
8
|
-
* Bootstrap 5 on "Collapse All" button click: | Nautobot on "Collapse All" button click:
|
|
8
|
+
* Bootstrap 5 on "Collapse All Groups" button click: | Nautobot on "Collapse All Groups" button click:
|
|
9
9
|
* * X [expanded] -> [collapsed] | * X [expanded] -> [collapsed]
|
|
10
10
|
* * Y [collapsed] -> [expanded] | * Y [collapsed] -> [collapsed]
|
|
11
11
|
* * Z [expanded] -> [collapsed] | * Z [expanded] -> [collapsed]
|
|
@@ -45,7 +45,7 @@ export const initializeCollapseToggleAll = () => {
|
|
|
45
45
|
.filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'collapsed'))
|
|
46
46
|
.forEach((collapseToggleAll) => {
|
|
47
47
|
collapseToggleAll.setAttribute('aria-expanded', 'false');
|
|
48
|
-
collapseToggleAll.textContent = 'Expand All';
|
|
48
|
+
collapseToggleAll.textContent = 'Expand All Groups';
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
const onShownBsCollapse = () =>
|
|
@@ -53,7 +53,7 @@ export const initializeCollapseToggleAll = () => {
|
|
|
53
53
|
.filter((collapseToggleAll) => areAll(getCollapseToggleAllTargets(collapseToggleAll), 'expanded'))
|
|
54
54
|
.forEach((collapseToggleAll) => {
|
|
55
55
|
collapseToggleAll.setAttribute('aria-expanded', 'true');
|
|
56
|
-
collapseToggleAll.textContent = 'Collapse All';
|
|
56
|
+
collapseToggleAll.textContent = 'Collapse All Groups';
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
// Using event delegation pattern here to avoid re-creating listeners each time DOM is modified.
|
nautobot/ui/src/js/nautobot.js
CHANGED
|
@@ -109,4 +109,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
109
109
|
event.detail.path = isFavorite ? element.dataset.deleteUrl : element.dataset.addUrl;
|
|
110
110
|
};
|
|
111
111
|
window.setRequestUrl = setRequestUrl;
|
|
112
|
+
|
|
113
|
+
// Remove the blur after clicking the footer links that are opening mostly in the new tab
|
|
114
|
+
// Keeping focus on those items is what keeps the tooltip as well
|
|
115
|
+
document.querySelectorAll('a[data-bs-toggle="tooltip"], div[data-bs-toggle="tooltip"] > a').forEach((el) => {
|
|
116
|
+
el.addEventListener('click', () => {
|
|
117
|
+
el.blur();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// When modal is being closed, bootstrap automatically restore the focus on the element that was triggering the modal
|
|
122
|
+
// As a result, after modal close tooltip was triggered as well
|
|
123
|
+
document.addEventListener('hidden.bs.modal', () => {
|
|
124
|
+
document.querySelectorAll('[data-bs-toggle="tooltip"] > a').forEach((el) => {
|
|
125
|
+
el.blur();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
112
128
|
});
|
nautobot/ui/src/scss/colors.scss
CHANGED
|
@@ -414,8 +414,8 @@ $btn-close-opacity: 0.68;
|
|
|
414
414
|
$btn-close-hover-opacity: 1;
|
|
415
415
|
$btn-close-focus-opacity: 1;
|
|
416
416
|
$btn-close-disabled-opacity: 0.31;
|
|
417
|
-
$btn-close-filter: invert(1%) sepia(10%) saturate(233%) hue-rotate(314deg) brightness(99%) contrast(81%);
|
|
418
|
-
$btn-close-filter-dark: invert(
|
|
417
|
+
$btn-close-filter: invert(1%) sepia(10%) saturate(233%) hue-rotate(314deg) brightness(99%) contrast(81%); /* $black-0: #1a1a1a; */
|
|
418
|
+
$btn-close-filter-dark: invert(100%); /* $black-0-dark: #ffffff; */
|
|
419
419
|
$btn-close-white-filter: $btn-close-filter-dark;
|
|
420
420
|
|
|
421
421
|
/* Code */
|
|
@@ -431,6 +431,18 @@ $kbd-bg: var(--#{$prefix}secondary-bg);
|
|
|
431
431
|
/* 4. Include any default map overrides here */
|
|
432
432
|
$theme-colors-rgb-dark: map-loop($theme-colors-dark, to-rgb, "$value");
|
|
433
433
|
|
|
434
|
+
/* Breakpoints */
|
|
435
|
+
$sidenav-width-for-breakpoints: 240px; // this is only for calculations below; sidenav has separate variable in rem in Layout section
|
|
436
|
+
|
|
437
|
+
$grid-breakpoints: (
|
|
438
|
+
xs: 0,
|
|
439
|
+
sm: 576px + $sidenav-width-for-breakpoints,
|
|
440
|
+
md: 768px + $sidenav-width-for-breakpoints,
|
|
441
|
+
lg: 992px + $sidenav-width-for-breakpoints,
|
|
442
|
+
xl: 1200px + $sidenav-width-for-breakpoints,
|
|
443
|
+
xxl: 1400px + $sidenav-width-for-breakpoints
|
|
444
|
+
);
|
|
445
|
+
|
|
434
446
|
/* 5. Include remainder of required parts */
|
|
435
447
|
@import "bootstrap/scss/maps";
|
|
436
448
|
@import "bootstrap/scss/mixins";
|
|
@@ -746,12 +758,6 @@ $nautobot-chevron-svg: "<svg viewBox='0 0 17 20' fill='none' xmlns='http://www.w
|
|
|
746
758
|
}
|
|
747
759
|
}
|
|
748
760
|
|
|
749
|
-
@mixin nb-firefox-only {
|
|
750
|
-
@supports (-moz-appearance: none) {
|
|
751
|
-
@content;
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
761
|
/* Links */
|
|
756
762
|
a,
|
|
757
763
|
button {
|
|
@@ -1114,6 +1120,11 @@ textarea {
|
|
|
1114
1120
|
}
|
|
1115
1121
|
}
|
|
1116
1122
|
|
|
1123
|
+
.nb-form-check-input-sm {
|
|
1124
|
+
height: 1rem; /* 16px */
|
|
1125
|
+
width: 1rem; /* 16px */
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1117
1128
|
.form-text {
|
|
1118
1129
|
display: block;
|
|
1119
1130
|
font-weight: $font-weight-normal;
|
|
@@ -1275,11 +1286,13 @@ textarea {
|
|
|
1275
1286
|
&.bg-danger,
|
|
1276
1287
|
&.bg-info,
|
|
1277
1288
|
&.bg-primary,
|
|
1289
|
+
&.bg-secondary,
|
|
1278
1290
|
&.bg-success,
|
|
1279
1291
|
&.bg-warning,
|
|
1280
1292
|
&.text-bg-danger,
|
|
1281
1293
|
&.text-bg-info,
|
|
1282
1294
|
&.text-bg-primary,
|
|
1295
|
+
&.text-bg-secondary,
|
|
1283
1296
|
&.text-bg-success,
|
|
1284
1297
|
&.text-bg-warning {
|
|
1285
1298
|
--#{$prefix}badge-color: var(--#{$prefix}body-bg);
|
|
@@ -1413,6 +1426,14 @@ textarea {
|
|
|
1413
1426
|
}
|
|
1414
1427
|
}
|
|
1415
1428
|
|
|
1429
|
+
/* Code */
|
|
1430
|
+
pre:not(:has(code.hljs)) { /* Do not include highlight.js in this rule because it has its own set of styles. */
|
|
1431
|
+
background: var(--#{$prefix}secondary-bg);
|
|
1432
|
+
border-radius: $border-radius;
|
|
1433
|
+
padding-block: map.get($spacers, 8);
|
|
1434
|
+
padding-inline: map.get($spacers, 10);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1416
1437
|
/* Collapse */
|
|
1417
1438
|
.nb-collapse-toggle {
|
|
1418
1439
|
@include transition($btn-transition);
|
|
@@ -1427,7 +1448,7 @@ textarea {
|
|
|
1427
1448
|
display: inline-block; /* `transform` does not work on standard `inline` elements, like `span`, hence `inline-block`. */
|
|
1428
1449
|
}
|
|
1429
1450
|
|
|
1430
|
-
&:not([aria-expanded="true"]) >
|
|
1451
|
+
&:not([aria-expanded="true"]) > .mdi-chevron-down {
|
|
1431
1452
|
transform: rotate(-90deg); /* Rotate chevron icon when collapse is closed. */
|
|
1432
1453
|
}
|
|
1433
1454
|
}
|
|
@@ -1452,7 +1473,8 @@ textarea {
|
|
|
1452
1473
|
$nb-drawer-closed-width: 0;
|
|
1453
1474
|
$nb-drawer-open-width: 20rem; /* 320px */
|
|
1454
1475
|
$sidenav-width-collapsed: 4rem; /* 64px */
|
|
1455
|
-
$sidenav-width-expanded:
|
|
1476
|
+
$sidenav-width-expanded: ($sidenav-width-for-breakpoints / 16px) * 1rem; /* 16px is default browser conversion rate */
|
|
1477
|
+
/* we're converting to rem to have better web accessibility support */
|
|
1456
1478
|
|
|
1457
1479
|
* {
|
|
1458
1480
|
margin: 0;
|
|
@@ -1515,8 +1537,8 @@ body {
|
|
|
1515
1537
|
/* Sidenav (a.k.a. navbar, nav menu, sidebar) */
|
|
1516
1538
|
#sidenav {
|
|
1517
1539
|
$sidenav-chevron-svg: "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path fill-rule='evenodd' clip-rule='evenodd' d='M14.53 5.46967C14.8229 5.76256 14.8229 6.23744 14.53 6.53033L10.7928 10.2676C10.388 10.6724 10.1167 10.9444 9.92461 11.1708C9.73817 11.3904 9.67071 11.5171 9.6393 11.6137C9.55773 11.8648 9.55773 12.1352 9.6393 12.3863C9.67071 12.4829 9.73817 12.6096 9.92461 12.8292C10.1167 13.0556 10.388 13.3276 10.7928 13.7324L14.53 17.4697C14.8229 17.7626 14.8229 18.2374 14.53 18.5303C14.2371 18.8232 13.7623 18.8232 13.4694 18.5303L9.73211 14.7931L9.71059 14.7715C9.33288 14.3939 9.01761 14.0786 8.7811 13.8C8.53443 13.5094 8.32969 13.2098 8.21272 12.8498C8.03326 12.2975 8.03326 11.7025 8.21272 11.1502C8.32969 10.7902 8.53443 10.4906 8.7811 10.2C9.01761 9.9214 9.33287 9.60615 9.71058 9.22845L9.73211 9.20693L13.4694 5.46967C13.7623 5.17678 14.2371 5.17678 14.53 5.46967Z' fill='#{$nav-white-0}'/></svg>";
|
|
1518
|
-
$sidenav-favorite-icon-svg: "<svg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><path d='
|
|
1519
|
-
$sidenav-favorite-icon-svg-filled: "<svg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><path d='
|
|
1540
|
+
$sidenav-favorite-icon-svg: "<svg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><path d='M11.4189 0.599609C11.8569 0.444608 12.3438 0.470222 12.7656 0.676758C13.1382 0.85937 13.3661 1.1983 13.5303 1.48926C13.7037 1.79665 13.8896 2.21226 14.1113 2.7041L16.4121 7.80957H20.7764C21.3853 7.80957 21.8928 7.80944 22.2793 7.84277C22.6369 7.87368 23.0791 7.9417 23.4111 8.22754C23.8327 8.59073 24.0486 9.13456 23.9902 9.68359C23.9441 10.116 23.6675 10.4639 23.4268 10.7266C23.1665 11.0102 22.7947 11.3503 22.3486 11.7588L18.7549 15.0479L20.415 19.7119C20.6345 20.3287 20.8155 20.837 20.9189 21.2324C21.0129 21.5918 21.1024 22.0532 20.9238 22.4707C20.7004 22.993 20.2266 23.3717 19.6621 23.4785C19.2108 23.5637 18.7714 23.3814 18.4346 23.2158C18.064 23.0337 17.5972 22.7531 17.0312 22.4131L12 19.3887L6.96875 22.4131C6.40288 22.7531 5.93606 23.0337 5.56543 23.2158C5.22855 23.3813 4.78918 23.5638 4.33789 23.4785C3.77339 23.3717 3.29963 22.993 3.07617 22.4707C2.89765 22.0532 2.9871 21.5918 3.08105 21.2324C3.18447 20.837 3.36558 20.3286 3.58496 19.7119L5.24414 15.0479L1.65137 11.7588C1.20524 11.3502 0.833466 11.0103 0.573242 10.7266C0.332409 10.4639 0.0559191 10.116 0.00976562 9.68359C-0.048592 9.13464 0.168374 8.59073 0.589844 8.22754L0.717773 8.13086C1.02957 7.92557 1.40768 7.86983 1.7207 7.84277C2.10716 7.80943 2.61462 7.80957 3.22363 7.80957H7.58789L9.88867 2.7041C10.1103 2.21236 10.2963 1.79663 10.4697 1.48926C10.6339 1.19837 10.862 0.859412 11.2344 0.676758L11.4189 0.599609ZM12.0918 1.97266C12.0325 1.94907 11.9664 1.94881 11.9072 1.97266C11.8903 1.99137 11.8406 2.05132 11.7588 2.19629C11.6253 2.43288 11.4699 2.77672 11.2363 3.29492L8.74121 8.83203C8.62278 9.09452 8.35775 9.26367 8.06641 9.26367H3.22363C2.58589 9.26367 2.15619 9.26459 1.84961 9.29102C1.65621 9.30775 1.57052 9.33069 1.54395 9.33887C1.4994 9.38481 1.47564 9.44621 1.47656 9.50977C1.4907 9.53411 1.53727 9.6094 1.66699 9.75098C1.87346 9.97601 2.18793 10.2644 2.65527 10.6924L6.60254 14.3066C6.81725 14.5033 6.89362 14.8073 6.79688 15.0801L4.97656 20.1943C4.74783 20.8372 4.59263 21.2751 4.50879 21.5957C4.45591 21.798 4.44774 21.8941 4.44629 21.9258C4.47718 21.982 4.52974 22.0236 4.5918 22.042C4.62177 22.0343 4.71557 22.0082 4.90723 21.9141C5.20782 21.7664 5.61016 21.5255 6.2002 21.1709L11.6162 17.916C11.8518 17.7744 12.1481 17.7744 12.3838 17.916L17.7998 21.1709C18.39 21.5256 18.7921 21.7664 19.0928 21.9141C19.2823 22.0072 19.3761 22.0339 19.4072 22.042C19.4695 22.0238 19.5216 21.982 19.5527 21.9258C19.5512 21.8941 19.5441 21.798 19.4912 21.5957C19.4073 21.2751 19.2522 20.8372 19.0234 20.1943L17.2031 15.0801C17.1064 14.8074 17.183 14.5034 17.3975 14.3066L21.3447 10.6924C21.8119 10.2645 22.1265 9.97601 22.333 9.75098C22.4617 9.61056 22.5079 9.53469 22.5225 9.50977C22.5233 9.44589 22.5 9.38489 22.4551 9.33887C22.4274 9.3304 22.3416 9.30754 22.1504 9.29102C21.8438 9.2646 21.414 9.26367 20.7764 9.26367H15.9336C15.6422 9.26359 15.3771 9.09454 15.2588 8.83203L12.7637 3.29492C12.53 2.7766 12.3747 2.43289 12.2412 2.19629C12.1584 2.04951 12.108 1.99058 12.0918 1.97266Z' fill='#{$nav-white-0}'/></svg>";
|
|
1541
|
+
$sidenav-favorite-icon-svg-filled: "<svg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><path d='M11.4189 0.599457C11.8569 0.444456 12.3438 0.470069 12.7656 0.676605C13.1383 0.859207 13.3671 1.19809 13.5312 1.48911C13.7046 1.79644 13.8897 2.21229 14.1113 2.70395L16.4121 7.80942H20.7773C21.386 7.80942 21.8929 7.80931 22.2793 7.84262C22.6369 7.87353 23.0791 7.94253 23.4111 8.22836C23.8325 8.59154 24.0496 9.13456 23.9912 9.68344C23.9451 10.1159 23.6676 10.4637 23.4268 10.7264C23.1665 11.0101 22.7947 11.3502 22.3486 11.7586L18.7559 15.0477L20.415 19.7118C20.6345 20.3285 20.8155 20.8368 20.9189 21.2323C21.0129 21.5917 21.1024 22.053 20.9238 22.4706C20.7003 22.9929 20.2267 23.3716 19.6621 23.4784C19.2108 23.5635 18.7714 23.3812 18.4346 23.2157C18.0641 23.0336 17.598 22.7529 17.0322 22.4129L12 19.3885L6.96875 22.4129C6.40284 22.753 5.93608 23.0336 5.56543 23.2157C5.22855 23.3811 4.78918 23.5636 4.33789 23.4784C3.77348 23.3715 3.29961 22.9928 3.07617 22.4706C2.89773 22.0531 2.98711 21.5916 3.08105 21.2323C3.18447 20.8368 3.36655 20.3284 3.58594 19.7118L5.24414 15.0477L1.65137 11.7586C1.20515 11.35 0.833472 11.0102 0.573242 10.7264C0.33238 10.4637 0.0558689 10.1159 0.00976562 9.68344C-0.0485905 9.1345 0.168395 8.59155 0.589844 8.22836L0.717773 8.13071C1.02957 7.92542 1.40768 7.86968 1.7207 7.84262C2.10718 7.80926 2.61454 7.80942 3.22363 7.80942H7.58789L9.88867 2.70395C10.1103 2.21223 10.2963 1.79647 10.4697 1.48911C10.6339 1.19814 10.8628 0.859214 11.2354 0.676605L11.4189 0.599457Z' fill='#{$nav-white-0}'/></svg>";
|
|
1520
1542
|
$sidenav-favorite-size: 1.25rem; /* 20px */
|
|
1521
1543
|
$sidenav-link-gap: map.get($spacers, 5);
|
|
1522
1544
|
$sidenav-link-segment-icon-height: 5.625rem; /* 90px */
|
|
@@ -1547,10 +1569,11 @@ body {
|
|
|
1547
1569
|
@mixin filter-nav-orange-0 {
|
|
1548
1570
|
/*
|
|
1549
1571
|
* CSS workaround to change element color (including its `background-image`)
|
|
1550
|
-
* from white to any given color, `$orange-0` in this case.
|
|
1572
|
+
* from white to any given color, `$orange-0-dark` in this case. Though it
|
|
1573
|
+
* evaluates to `#ff9938`, not the exact `#ff9933`, it is _good enough_.
|
|
1551
1574
|
* Generated with: https://codepen.io/jumarjuaton/full/mdJYWYq
|
|
1552
1575
|
*/
|
|
1553
|
-
filter: invert(
|
|
1576
|
+
filter: invert(57%) sepia(100%) saturate(478%) hue-rotate(336deg) brightness(141%) contrast(101%);
|
|
1554
1577
|
}
|
|
1555
1578
|
|
|
1556
1579
|
@mixin filter-nav-gray-3 {
|
|
@@ -1558,7 +1581,7 @@ body {
|
|
|
1558
1581
|
* CSS workaround to change element color (including its `background-image`) from white to `$nav-gray-3`.
|
|
1559
1582
|
* Generated with: https://codepen.io/jumarjuaton/full/mdJYWYq
|
|
1560
1583
|
*/
|
|
1561
|
-
filter: invert(
|
|
1584
|
+
filter: invert(69%) sepia(15%) saturate(1%) hue-rotate(311deg) brightness(223%) contrast(98%);
|
|
1562
1585
|
}
|
|
1563
1586
|
|
|
1564
1587
|
@include box-shadow(0.0625rem 0 0 0 $navy-2, $box-shadow);
|
|
@@ -1655,19 +1678,20 @@ body {
|
|
|
1655
1678
|
min-width: $sidenav-link-width;
|
|
1656
1679
|
|
|
1657
1680
|
/*
|
|
1658
|
-
* FIXME(norbert-mieczkowski-codilime): remove this
|
|
1681
|
+
* FIXME(norbert-mieczkowski-codilime): remove this hack when browsers fix their bug: https://bugzilla.mozilla.org/show_bug.cgi?id=995020.
|
|
1682
|
+
* Bug has already been observed in Firefox and Safari, Chrome is confirmed to be _clean_.
|
|
1659
1683
|
* Workaround based on: https://www.answeroverflow.com/m/1353731321620598945.
|
|
1660
1684
|
*/
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1685
|
+
/* hack */
|
|
1686
|
+
flex-direction: row;
|
|
1687
|
+
padding-block: map.get($spacers, 0);
|
|
1688
|
+
padding-inline: map.get($spacers, 20);
|
|
1689
|
+
writing-mode: vertical-lr;
|
|
1666
1690
|
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
}
|
|
1691
|
+
> * {
|
|
1692
|
+
writing-mode: horizontal-tb;
|
|
1670
1693
|
}
|
|
1694
|
+
/* endhack */
|
|
1671
1695
|
}
|
|
1672
1696
|
|
|
1673
1697
|
.nb-sidenav-link {
|
|
@@ -1683,7 +1707,7 @@ body {
|
|
|
1683
1707
|
width: $sidenav-link-width;
|
|
1684
1708
|
|
|
1685
1709
|
&-active {
|
|
1686
|
-
color: $orange-0;
|
|
1710
|
+
color: $orange-0-dark;
|
|
1687
1711
|
}
|
|
1688
1712
|
|
|
1689
1713
|
&::before { /* Segment icon */
|
|
@@ -1818,7 +1842,7 @@ body {
|
|
|
1818
1842
|
}
|
|
1819
1843
|
|
|
1820
1844
|
&:has(+ .nb-sidenav-flyout .nb-sidenav-link-active) { /* When list item contains an active link */
|
|
1821
|
-
color: $orange-0;
|
|
1845
|
+
color: $orange-0-dark;
|
|
1822
1846
|
|
|
1823
1847
|
> :first-child, /* Nav menu tab icon */
|
|
1824
1848
|
> :last-child::after { /* Chevron icon */
|
|
@@ -2233,11 +2257,11 @@ ul.nb-software-image-hierarchy {
|
|
|
2233
2257
|
|
|
2234
2258
|
ul.nb-tree-hierarchy {
|
|
2235
2259
|
list-style-type: none;
|
|
2236
|
-
padding-
|
|
2260
|
+
padding-inline-start: map.get($spacers, 0);
|
|
2237
2261
|
|
|
2238
2262
|
ul {
|
|
2239
2263
|
list-style-type: "↳ ";
|
|
2240
|
-
padding-
|
|
2264
|
+
padding-inline-start: 1.125rem; /* 18px */
|
|
2241
2265
|
}
|
|
2242
2266
|
}
|
|
2243
2267
|
|
|
@@ -2436,3 +2460,12 @@ pre code.hljs {
|
|
|
2436
2460
|
font-size: 1em;
|
|
2437
2461
|
}
|
|
2438
2462
|
}
|
|
2463
|
+
|
|
2464
|
+
.nb-lg-max-width {
|
|
2465
|
+
max-width: 960px;
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
/* Workaround to fix `d-none` being overridden by `d-md-flex` (and possibly other `d-{display}` classes). */
|
|
2469
|
+
.d-none {
|
|
2470
|
+
display: none !important;
|
|
2471
|
+
}
|
|
@@ -2,16 +2,49 @@
|
|
|
2
2
|
{% load helpers %}
|
|
3
3
|
|
|
4
4
|
{% block usercontent %}
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
5
|
+
<div class="row align-content-start flex-fill">
|
|
6
|
+
<div class="col-md-8 offset-md-2">
|
|
7
|
+
<div class="card">
|
|
8
|
+
<div class="card-header">
|
|
9
|
+
<strong>User Profile</strong>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="collapse show">
|
|
12
|
+
<table class="table table-hover attr-table">
|
|
13
|
+
<tr>
|
|
14
|
+
<td>User login</td>
|
|
15
|
+
<td>{{ request.user.username }}</td>
|
|
16
|
+
</tr>
|
|
17
|
+
<tr>
|
|
18
|
+
<td>Full name</td>
|
|
19
|
+
{% if request.user.first_name or request.user.last_name %}
|
|
20
|
+
<td>{{ request.user.first_name }} {{ request.user.last_name }}</td>
|
|
21
|
+
{% else %}
|
|
22
|
+
<td>{{ None|placeholder }}</td>
|
|
23
|
+
{% endif %}
|
|
24
|
+
</tr>
|
|
25
|
+
<tr>
|
|
26
|
+
<td>Email</td>
|
|
27
|
+
<td>{{ request.user.email|hyperlinked_email }}</td>
|
|
28
|
+
</tr>
|
|
29
|
+
<tr>
|
|
30
|
+
<td>Registered</td>
|
|
31
|
+
<td>{{ request.user.date_joined|date:settings.SHORT_DATETIME_FORMAT }}</td>
|
|
32
|
+
</tr>
|
|
33
|
+
<tr>
|
|
34
|
+
<td>Groups</td>
|
|
35
|
+
<td>{{ request.user.groups.all|join:', '|placeholder }}</td>
|
|
36
|
+
</tr>
|
|
37
|
+
<tr>
|
|
38
|
+
<td>Admin access</td>
|
|
39
|
+
<td>{{ request.user.is_staff|render_boolean }}</td>
|
|
40
|
+
</tr>
|
|
41
|
+
<tr>
|
|
42
|
+
<td>Superuser access</td>
|
|
43
|
+
<td>{{ request.user.is_superuser|render_boolean }}</td>
|
|
44
|
+
</tr>
|
|
45
|
+
</table>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
17
50
|
{% endblock %}
|
nautobot/users/tests/test_api.py
CHANGED
|
@@ -348,6 +348,10 @@ class TokenTest(APIViewTestCases.APIViewTestCase):
|
|
|
348
348
|
|
|
349
349
|
class ObjectPermissionTest(APIViewTestCases.APIViewTestCase):
|
|
350
350
|
model = ObjectPermission
|
|
351
|
+
validation_excluded_fields = [
|
|
352
|
+
"groups", # M2M field, excluded by default
|
|
353
|
+
"users", # M2M field, excluded by default
|
|
354
|
+
]
|
|
351
355
|
|
|
352
356
|
@classmethod
|
|
353
357
|
def setUpTestData(cls):
|
nautobot/users/views.py
CHANGED
|
@@ -64,6 +64,7 @@ class LoginView(View):
|
|
|
64
64
|
self.template_name,
|
|
65
65
|
{
|
|
66
66
|
"form": form,
|
|
67
|
+
"title": "Login",
|
|
67
68
|
},
|
|
68
69
|
)
|
|
69
70
|
|
|
@@ -91,6 +92,7 @@ class LoginView(View):
|
|
|
91
92
|
self.template_name,
|
|
92
93
|
{
|
|
93
94
|
"form": form,
|
|
95
|
+
"title": "Login",
|
|
94
96
|
},
|
|
95
97
|
)
|
|
96
98
|
|
|
@@ -402,7 +404,7 @@ class TokenDeleteView(GenericView):
|
|
|
402
404
|
|
|
403
405
|
return render(
|
|
404
406
|
request,
|
|
405
|
-
"generic/
|
|
407
|
+
"generic/object_destroy.html",
|
|
406
408
|
{
|
|
407
409
|
"obj": token,
|
|
408
410
|
"obj_type": token._meta.verbose_name,
|
|
@@ -421,7 +423,7 @@ class TokenDeleteView(GenericView):
|
|
|
421
423
|
|
|
422
424
|
return render(
|
|
423
425
|
request,
|
|
424
|
-
"generic/
|
|
426
|
+
"generic/object_destroy.html",
|
|
425
427
|
{
|
|
426
428
|
"obj": token,
|
|
427
429
|
"obj_type": token._meta.verbose_name,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from django.contrib.contenttypes.models import ContentType
|
|
2
2
|
from django.core.exceptions import ValidationError
|
|
3
|
-
from django.db import models
|
|
3
|
+
from django.db import models
|
|
4
4
|
|
|
5
5
|
from nautobot.core.constants import CHARFIELD_MAX_LENGTH
|
|
6
6
|
from nautobot.core.models import BaseManager
|
|
@@ -382,73 +382,6 @@ class VMInterface(PrimaryModel, BaseInterface):
|
|
|
382
382
|
|
|
383
383
|
return super().to_objectchange(action, related_object=virtual_machine, **kwargs)
|
|
384
384
|
|
|
385
|
-
def add_ip_addresses(
|
|
386
|
-
self,
|
|
387
|
-
ip_addresses,
|
|
388
|
-
is_source=False,
|
|
389
|
-
is_destination=False,
|
|
390
|
-
is_default=False,
|
|
391
|
-
is_preferred=False,
|
|
392
|
-
is_primary=False,
|
|
393
|
-
is_secondary=False,
|
|
394
|
-
is_standby=False,
|
|
395
|
-
):
|
|
396
|
-
"""Add one or more IPAddress instances to this interface's `ip_addresses` many-to-many relationship.
|
|
397
|
-
|
|
398
|
-
Args:
|
|
399
|
-
ip_addresses (:obj:`list` or `IPAddress`): Instance of `nautobot.ipam.models.IPAddress` or list of `IPAddress` instances.
|
|
400
|
-
is_source (bool, optional): Is source address. Defaults to False.
|
|
401
|
-
is_destination (bool, optional): Is destination address. Defaults to False.
|
|
402
|
-
is_default (bool, optional): Is default address. Defaults to False.
|
|
403
|
-
is_preferred (bool, optional): Is preferred address. Defaults to False.
|
|
404
|
-
is_primary (bool, optional): Is primary address. Defaults to False.
|
|
405
|
-
is_secondary (bool, optional): Is secondary address. Defaults to False.
|
|
406
|
-
is_standby (bool, optional): Is standby address. Defaults to False.
|
|
407
|
-
|
|
408
|
-
Returns:
|
|
409
|
-
Number of instances added.
|
|
410
|
-
"""
|
|
411
|
-
if not isinstance(ip_addresses, (tuple, list)):
|
|
412
|
-
ip_addresses = [ip_addresses]
|
|
413
|
-
with transaction.atomic():
|
|
414
|
-
for ip in ip_addresses:
|
|
415
|
-
instance = self.ip_addresses.through(
|
|
416
|
-
ip_address=ip,
|
|
417
|
-
vm_interface=self,
|
|
418
|
-
is_source=is_source,
|
|
419
|
-
is_destination=is_destination,
|
|
420
|
-
is_default=is_default,
|
|
421
|
-
is_preferred=is_preferred,
|
|
422
|
-
is_primary=is_primary,
|
|
423
|
-
is_secondary=is_secondary,
|
|
424
|
-
is_standby=is_standby,
|
|
425
|
-
)
|
|
426
|
-
instance.validated_save()
|
|
427
|
-
return len(ip_addresses)
|
|
428
|
-
|
|
429
|
-
add_ip_addresses.alters_data = True
|
|
430
|
-
|
|
431
|
-
def remove_ip_addresses(self, ip_addresses):
|
|
432
|
-
"""Remove one or more IPAddress instances from this interface's `ip_addresses` many-to-many relationship.
|
|
433
|
-
|
|
434
|
-
Args:
|
|
435
|
-
ip_addresses (:obj:`list` or `IPAddress`): Instance of `nautobot.ipam.models.IPAddress` or list of `IPAddress` instances.
|
|
436
|
-
|
|
437
|
-
Returns:
|
|
438
|
-
Number of instances removed.
|
|
439
|
-
"""
|
|
440
|
-
count = 0
|
|
441
|
-
if not isinstance(ip_addresses, (tuple, list)):
|
|
442
|
-
ip_addresses = [ip_addresses]
|
|
443
|
-
with transaction.atomic():
|
|
444
|
-
for ip in ip_addresses:
|
|
445
|
-
qs = self.ip_addresses.through.objects.filter(ip_address=ip, vm_interface=self)
|
|
446
|
-
deleted_count, _ = qs.delete()
|
|
447
|
-
count += deleted_count
|
|
448
|
-
return count
|
|
449
|
-
|
|
450
|
-
remove_ip_addresses.alters_data = True
|
|
451
|
-
|
|
452
385
|
@property
|
|
453
386
|
def parent(self):
|
|
454
387
|
return self.virtual_machine
|
|
@@ -4,12 +4,13 @@ from nautobot.core.apps import (
|
|
|
4
4
|
NavMenuItem,
|
|
5
5
|
NavMenuTab,
|
|
6
6
|
)
|
|
7
|
+
from nautobot.core.ui.choices import NavigationIconChoices, NavigationWeightChoices
|
|
7
8
|
|
|
8
9
|
menu_items = (
|
|
9
10
|
NavMenuTab(
|
|
10
11
|
name="Virtualization",
|
|
11
|
-
icon=
|
|
12
|
-
weight=
|
|
12
|
+
icon=NavigationIconChoices.VIRTUALIZATION,
|
|
13
|
+
weight=NavigationWeightChoices.VIRTUALIZATION,
|
|
13
14
|
groups=(
|
|
14
15
|
NavMenuGroup(
|
|
15
16
|
name="Virtual Machines",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
1
|
+
{% extends 'generic/object_retrieve.html' %}
|
|
2
2
|
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
{% block bulk_buttons %}
|
|
4
4
|
{% if perms.virtualization.change_virtualmachine %}
|
|
5
|
-
<div class="
|
|
5
|
+
<div class="dropdown d-inline-flex">
|
|
6
6
|
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
7
7
|
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Components <span class="mdi mdi-chevron-down"></span>
|
|
8
8
|
</button>
|
|
9
9
|
<ul class="dropdown-menu">
|
|
10
|
-
{% if perms.virtualization.add_vminterface %}<li><a href="{% url 'virtualization:virtualmachine_bulk_add_vminterface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="formaction">Interfaces</a></li>{% endif %}
|
|
10
|
+
{% if perms.virtualization.add_vminterface %}<li><a href="{% url 'virtualization:virtualmachine_bulk_add_vminterface' %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="dropdown-item formaction">Interfaces</a></li>{% endif %}
|
|
11
11
|
</ul>
|
|
12
12
|
</div>
|
|
13
13
|
{% endif %}
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
{% render_field form.primary_ip4 %}
|
|
32
32
|
{% render_field form.primary_ip6 %}
|
|
33
33
|
{% render_field form.software_version %}
|
|
34
|
-
<div class="mb-10 d-flex justify-content-center"
|
|
34
|
+
<div class="mb-10 d-flex justify-content-center"
|
|
35
|
+
id="software_version_image_container"
|
|
36
|
+
style="display:none !important">{# !important is required to override d-flex #}
|
|
35
37
|
<div class="col-lg-3"></div>
|
|
36
38
|
<div class="col-lg-9">
|
|
37
39
|
<span class="form-text">
|
|
@@ -281,6 +281,9 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
|
|
|
281
281
|
"description": "New description",
|
|
282
282
|
}
|
|
283
283
|
choices_fields = ["mode"]
|
|
284
|
+
validation_excluded_fields = [
|
|
285
|
+
"tagged_vlans", # M2M field, excluded by default
|
|
286
|
+
]
|
|
284
287
|
|
|
285
288
|
@classmethod
|
|
286
289
|
def setUpTestData(cls):
|