Skip to content

Commit

Permalink
Cleanup and documentation for #1344
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Oct 18, 2021
1 parent f485a47 commit 487d677
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 8 deletions.
5 changes: 5 additions & 0 deletions docs/core-functionality/contacts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Contacts

{!models/tenancy/contact.md!}
{!models/tenancy/contactgroup.md!}
{!models/tenancy/contactrole.md!}
31 changes: 31 additions & 0 deletions docs/models/tenancy/contact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Contacts

A contact represent an individual or group that has been associated with an object in NetBox for administrative reasons. For example, you might assign one or more operational contacts to each site. Contacts can be arranged within nested contact groups.

Each contact must include a name, which is unique to its parent group (if any). The following optional descriptors are also available:

* Title
* Phone
* Email
* Address

## Contact Assignment

Each contact can be assigned to one or more objects, allowing for the efficient reuse of contact information. When assigning a contact to an object, the user may optionally specify a role and/or priority (primary, secondary, tertiary, or inactive) to better convey the nature of the contact's relationship to the assigned object.

The following models support the assignment of contacts:

* circuits.Circuit
* circuits.Provider
* dcim.Device
* dcim.Location
* dcim.Manufacturer
* dcim.PowerPanel
* dcim.Rack
* dcim.Region
* dcim.Site
* dcim.SiteGroup
* tenancy.Tenant
* virtualization.Cluster
* virtualization.ClusterGroup
* virtualization.VirtualMachine
3 changes: 3 additions & 0 deletions docs/models/tenancy/contactgroup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Contact Groups

Contacts can be organized into arbitrary groups. These groups can be recursively nested for convenience. Each contact within a group must have a unique name, but other attributes can be repeated.
3 changes: 3 additions & 0 deletions docs/models/tenancy/contactrole.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Contact Roles

Contacts can be organized by functional roles, which are fully customizable by the user. For example, you might create roles for administrative, operational, or emergency contacts.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ nav:
- Circuits: 'core-functionality/circuits.md'
- Power Tracking: 'core-functionality/power.md'
- Tenancy: 'core-functionality/tenancy.md'
- Contacts: 'core-functionality/contacts.md'
- Customization:
- Custom Fields: 'customization/custom-fields.md'
- Custom Validation: 'customization/custom-validation.md'
Expand Down
7 changes: 5 additions & 2 deletions netbox/tenancy/api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from django.contrib.auth.models import ContentType
from rest_framework import serializers

from netbox.api import ContentTypeField
from netbox.api import ChoiceField, ContentTypeField
from netbox.api.serializers import NestedGroupModelSerializer, OrganizationalModelSerializer, PrimaryModelSerializer
from tenancy.choices import ContactPriorityChoices
from tenancy.models import *
from .nested_serializers import *

Expand Down Expand Up @@ -93,9 +94,11 @@ class ContactAssignmentSerializer(PrimaryModelSerializer):
)
contact = NestedContactSerializer()
role = NestedContactRoleSerializer(required=False, allow_null=True)
priority = ChoiceField(choices=ContactPriorityChoices, required=False)

class Meta:
model = ContactAssignment
fields = [
'id', 'url', 'display', 'content_type', 'object_id', 'contact', 'role', 'created', 'last_updated',
'id', 'url', 'display', 'content_type', 'object_id', 'contact', 'role', 'priority', 'created',
'last_updated',
]
9 changes: 5 additions & 4 deletions netbox/tenancy/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from django.db.models import Q

from extras.filters import TagFilter
from netbox.filtersets import OrganizationalModelFilterSet, PrimaryModelFilterSet
from utilities.filters import TreeNodeMultipleChoiceFilter
from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, PrimaryModelFilterSet
from utilities.filters import ContentTypeFilter, TreeNodeMultipleChoiceFilter
from .models import *


Expand Down Expand Up @@ -168,7 +168,8 @@ def search(self, queryset, name, value):
)


class ContactAssignmentFilterSet(OrganizationalModelFilterSet):
class ContactAssignmentFilterSet(ChangeLoggedModelFilterSet):
content_type = ContentTypeFilter()
contact_id = django_filters.ModelMultipleChoiceFilter(
queryset=Contact.objects.all(),
label='Contact (ID)',
Expand All @@ -186,4 +187,4 @@ class ContactAssignmentFilterSet(OrganizationalModelFilterSet):

class Meta:
model = ContactAssignment
fields = ['id', 'priority']
fields = ['id', 'content_type_id', 'priority']
15 changes: 15 additions & 0 deletions netbox/tenancy/forms/bulk_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ class ContactBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBul
queryset=ContactGroup.objects.all(),
required=False
)
title = forms.CharField(
max_length=100,
required=False
)
phone = forms.CharField(
max_length=50,
required=False
)
email = forms.EmailField(
required=False
)
address = forms.CharField(
max_length=200,
required=False
)

class Meta:
nullable_fields = ['group', 'title', 'phone', 'email', 'address', 'comments']
10 changes: 8 additions & 2 deletions netbox/tenancy/forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,16 @@ class Meta:
class ContactAssignmentForm(BootstrapMixin, forms.ModelForm):
group = DynamicModelChoiceField(
queryset=ContactGroup.objects.all(),
required=False
required=False,
initial_params={
'contacts': '$contact'
}
)
contact = DynamicModelChoiceField(
queryset=Contact.objects.all()
queryset=Contact.objects.all(),
query_params={
'group_id': '$group'
}
)
role = DynamicModelChoiceField(
queryset=ContactRole.objects.all()
Expand Down
3 changes: 3 additions & 0 deletions netbox/tenancy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,6 @@ class ContactAssignment(ChangeLoggedModel):

class Meta:
ordering = ('priority', 'contact')

def __str__(self):
return f"{self.contact} ({self.get_priority_display()})" if self.priority else self.name

0 comments on commit 487d677

Please sign in to comment.