diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index b3f102b9f..4e70f73a7 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -127,6 +127,7 @@ PATCH) to maintain backward compatibility. This behavior will be discontinued be ## Enhancements +* [#33](https://github.com/digitalocean/netbox/issues/33) - Add ability to clone objects (pre-populate form fields) * [#792](https://github.com/digitalocean/netbox/issues/792) - Add power port and power outlet types * [#1865](https://github.com/digitalocean/netbox/issues/1865) - Add console port and console server port types * [#2902](https://github.com/digitalocean/netbox/issues/2902) - Replace `supervisord` with `systemd` diff --git a/netbox/circuits/models.py b/netbox/circuits/models.py index 5f80a4bfe..672e18b62 100644 --- a/netbox/circuits/models.py +++ b/netbox/circuits/models.py @@ -57,7 +57,12 @@ class Provider(ChangeLoggedModel, CustomFieldModel): tags = TaggableManager(through=TaggedItem) - csv_headers = ['name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments'] + csv_headers = [ + 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments', + ] + clone_fields = [ + 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', + ] class Meta: ordering = ['name'] @@ -171,6 +176,9 @@ class Circuit(ChangeLoggedModel, CustomFieldModel): csv_headers = [ 'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments', ] + clone_fields = [ + 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', + ] STATUS_CLASS_MAP = { CircuitStatusChoices.STATUS_DEPROVISIONING: 'warning', diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 6f46c0c96..2297909b4 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -331,6 +331,10 @@ class Site(ChangeLoggedModel, CustomFieldModel): 'name', 'slug', 'status', 'region', 'tenant', 'facility', 'asn', 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', 'contact_email', 'comments', ] + clone_fields = [ + 'status', 'region', 'tenant', 'facility', 'asn', 'time_zone', 'description', 'physical_address', + 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', 'contact_email', + ] STATUS_CLASS_MAP = { SiteStatusChoices.STATUS_ACTIVE: 'success', @@ -559,6 +563,10 @@ class Rack(ChangeLoggedModel, CustomFieldModel): 'site', 'group_name', 'name', 'facility_id', 'tenant', 'status', 'role', 'type', 'serial', 'asset_tag', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'comments', ] + clone_fields = [ + 'site', 'group', 'tenant', 'status', 'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width', + 'outer_depth', 'outer_unit', + ] STATUS_CLASS_MAP = { RackStatusChoices.STATUS_RESERVED: 'warning', @@ -948,6 +956,9 @@ class DeviceType(ChangeLoggedModel, CustomFieldModel): csv_headers = [ 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', 'comments', ] + clone_fields = [ + 'manufacturer', 'u_height', 'is_full_depth', 'subdevice_role', + ] class Meta: ordering = ['manufacturer', 'model'] @@ -1617,6 +1628,9 @@ class Device(ChangeLoggedModel, ConfigContextModel, CustomFieldModel): 'name', 'device_role', 'tenant', 'manufacturer', 'model_name', 'platform', 'serial', 'asset_tag', 'status', 'site', 'rack_group', 'rack_name', 'position', 'face', 'comments', ] + clone_fields = [ + 'device_type', 'device_role', 'tenant', 'platform', 'site', 'rack', 'status', 'cluster', + ] STATUS_CLASS_MAP = { DeviceStatusChoices.STATUS_OFFLINE: 'warning', @@ -3159,6 +3173,10 @@ class PowerFeed(ChangeLoggedModel, CableTermination, CustomFieldModel): 'site', 'panel_name', 'rack_group', 'rack_name', 'name', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', 'comments', ] + clone_fields = [ + 'power_panel', 'rack', 'status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization', + 'available_power', + ] STATUS_CLASS_MAP = { PowerFeedStatusChoices.STATUS_OFFLINE: 'warning', diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 79a6f48ad..68cefe77f 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -78,6 +78,9 @@ class VRF(ChangeLoggedModel, CustomFieldModel): tags = TaggableManager(through=TaggedItem) csv_headers = ['name', 'rd', 'tenant', 'enforce_unique', 'description'] + clone_fields = [ + 'tenant', 'enforce_unique', 'description', + ] class Meta: ordering = ['name', 'rd'] @@ -177,6 +180,9 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): tags = TaggableManager(through=TaggedItem) csv_headers = ['prefix', 'rir', 'date_added', 'description'] + clone_fields = [ + 'rir', 'date_added', 'description', + ] class Meta: ordering = ['family', 'prefix'] @@ -350,6 +356,9 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): csv_headers = [ 'prefix', 'vrf', 'tenant', 'site', 'vlan_group', 'vlan_vid', 'status', 'role', 'is_pool', 'description', ] + clone_fields = [ + 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description', + ] STATUS_CLASS_MAP = { 'container': 'default', @@ -627,6 +636,9 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel): 'address', 'vrf', 'tenant', 'status', 'role', 'device', 'virtual_machine', 'interface_name', 'is_primary', 'dns_name', 'description', ] + clone_fields = [ + 'vrf', 'tenant', 'status', 'role', 'description', + ] STATUS_CLASS_MAP = { 'active': 'primary', @@ -898,6 +910,9 @@ class VLAN(ChangeLoggedModel, CustomFieldModel): tags = TaggableManager(through=TaggedItem) csv_headers = ['site', 'group_name', 'vid', 'name', 'tenant', 'status', 'role', 'description'] + clone_fields = [ + 'site', 'group', 'tenant', 'status', 'role', 'description', + ] STATUS_CLASS_MAP = { 'active': 'primary', diff --git a/netbox/templates/circuits/circuit.html b/netbox/templates/circuits/circuit.html index a29a2ed7c..41a195bed 100644 --- a/netbox/templates/circuits/circuit.html +++ b/netbox/templates/circuits/circuit.html @@ -1,4 +1,5 @@ {% extends '_base.html' %} +{% load buttons %} {% load custom_links %} {% load helpers %} @@ -27,6 +28,9 @@
+ {% endif %} + {% if perms.dcim.add_device %} + {% clone_button 'dcim:device_add' device %} + {% endif %} + {% if perms.dcim.change_device %} Edit this device diff --git a/netbox/templates/dcim/devicetype.html b/netbox/templates/dcim/devicetype.html index 2e244ac55..b7d5a013c 100644 --- a/netbox/templates/dcim/devicetype.html +++ b/netbox/templates/dcim/devicetype.html @@ -1,4 +1,5 @@ {% extends '_base.html' %} +{% load buttons %} {% load custom_links %} {% load helpers %} @@ -14,37 +15,40 @@ - {% if perms.dcim.change_devicetype or perms.dcim.delete_devicetype %} -