mirror of
https://github.com/netbox-community/netbox.git
synced 2026-03-27 20:01:47 +01:00
1
netbox/templates/tenancy/attrs/email.html
Normal file
1
netbox/templates/tenancy/attrs/email.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="mailto:{{ value }}">{{ value }}</a>
|
||||
1
netbox/templates/tenancy/attrs/link.html
Normal file
1
netbox/templates/tenancy/attrs/link.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="{{ value }}">{{ value }}</a>
|
||||
1
netbox/templates/tenancy/attrs/phone.html
Normal file
1
netbox/templates/tenancy/attrs/phone.html
Normal file
@@ -0,0 +1 @@
|
||||
<a href="tel:{{ value }}">{{ value }}</a>
|
||||
@@ -1,100 +1 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
{% if object.group %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:contact_list' %}?group_id={{ object.group.pk }}">{{ object.group }}</a></li>
|
||||
{% endif %}
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-12 col-md-7">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Contact" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Groups" %}</th>
|
||||
<td>
|
||||
{% if object.groups.all|length > 0 %}
|
||||
<ol class="list-unstyled mb-0">
|
||||
{% for group in object.groups.all %}
|
||||
<li>{{ group|linkify|placeholder }}</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% else %}
|
||||
{{ ''|placeholder }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Name" %}</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Title" %}</th>
|
||||
<td>{{ object.title|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Phone" %}</th>
|
||||
<td>
|
||||
{% if object.phone %}
|
||||
<a href="tel:{{ object.phone }}">{{ object.phone }}</a>
|
||||
{% else %}
|
||||
{{ ''|placeholder }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Email" %}</th>
|
||||
<td>
|
||||
{% if object.email %}
|
||||
<a href="mailto:{{ object.email }}">{{ object.email }}</a>
|
||||
{% else %}
|
||||
{{ ''|placeholder }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Address" %}</th>
|
||||
<td>{{ object.address|linebreaksbr|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Link" %}</th>
|
||||
<td>
|
||||
{% if object.link %}
|
||||
<a href="{{ object.link }}">{{ object.link }}</a>
|
||||
{% else %}
|
||||
{{ ''|placeholder }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/panels/tags.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-md-5">
|
||||
{% include 'inc/panels/comments.html' %}
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Assignments" %}</h2>
|
||||
{% htmx_table 'tenancy:contactassignment_list' contact_id=object.pk %}
|
||||
</div>
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,60 +1,8 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
{% for contactgroup in object.get_ancestors %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:contactgroup_list' %}?parent_id={{ contactgroup.pk }}">{{ contactgroup }}</a></li>
|
||||
{% for ancestor in object.get_ancestors %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:contactgroup_list' %}?parent_id={{ ancestor.pk }}">{{ ancestor }}</a></li>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Contact Group" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Name" %}</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Parent" %}</th>
|
||||
<td>{{ object.parent|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/panels/tags.html' %}
|
||||
{% include 'inc/panels/comments.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
{% include 'inc/panels/related_objects.html' %}
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h2 class="card-header">
|
||||
{% trans "Child Groups" %}
|
||||
{% if perms.tenancy.add_contactgroup %}
|
||||
<div class="card-actions">
|
||||
<a href="{% url 'tenancy:contactgroup_add' %}?parent={{ object.pk }}" class="btn btn-ghost-primary btn-sm">
|
||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Add Contact Group" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% htmx_table 'tenancy:contactgroup_list' parent_id=object.pk %}
|
||||
</div>
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,42 +1 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:contactrole_list' %}">{% trans "Contact Roles" %}</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Contact Role" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Name" %}</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/panels/tags.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
{% include 'inc/panels/related_objects.html' %}
|
||||
{% include 'inc/panels/comments.html' %}
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,44 +1,11 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
{% if object.group %}
|
||||
{% for group in object.group.get_ancestors %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:tenant_list' %}?group_id={{ group.pk }}">{{ group }}</a></li>
|
||||
{% endfor %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:tenant_list' %}?group_id={{ object.group.pk }}">{{ object.group }}</a></li>
|
||||
{% endif %}
|
||||
{% endblock breadcrumbs %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col col-12 col-md-7">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Tenant" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Group" %}</th>
|
||||
<td>{{ object.group|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% include 'inc/panels/tags.html' %}
|
||||
{% include 'inc/panels/comments.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-md-5">
|
||||
{% include 'inc/panels/related_objects.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col col-md-12">
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
{% for tenantgroup in object.get_ancestors %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:tenantgroup_list' %}?parent_id={{ tenantgroup.pk }}">{{ tenantgroup }}</a></li>
|
||||
{% for ancestor in object.get_ancestors %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'tenancy:tenantgroup_list' %}?parent_id={{ ancestor.pk }}">{{ ancestor }}</a></li>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -18,53 +15,3 @@
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endblock extra_controls %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-12 col-md-6">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Tenant Group" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Name" %}</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Parent" %}</th>
|
||||
<td>{{ object.parent|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/panels/tags.html' %}
|
||||
{% include 'inc/panels/comments.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-12 col-md-6">
|
||||
{% include 'inc/panels/related_objects.html' %}
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
<div class="card">
|
||||
<h2 class="card-header">
|
||||
{% trans "Child Groups" %}
|
||||
{% if perms.tenancy.add_tenantgroup %}
|
||||
<div class="card-actions">
|
||||
<a href="{% url 'tenancy:tenantgroup_add' %}?parent={{ object.pk }}" class="btn btn-ghost-primary btn-sm">
|
||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> {% trans "Add Tenant Group" %}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% htmx_table 'tenancy:tenantgroup_list' parent_id=object.pk %}
|
||||
</div>
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
0
netbox/tenancy/ui/__init__.py
Normal file
0
netbox/tenancy/ui/__init__.py
Normal file
19
netbox/tenancy/ui/panels.py
Normal file
19
netbox/tenancy/ui/panels.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.ui import attrs, panels
|
||||
|
||||
|
||||
class TenantPanel(panels.ObjectAttributesPanel):
|
||||
group = attrs.RelatedObjectAttr('group', linkify=True)
|
||||
description = attrs.TextAttr('description')
|
||||
|
||||
|
||||
class ContactPanel(panels.ObjectAttributesPanel):
|
||||
groups = attrs.RelatedObjectListAttr('groups', linkify=True, label=_('Groups'))
|
||||
name = attrs.TextAttr('name')
|
||||
title = attrs.TextAttr('title')
|
||||
phone = attrs.TemplatedAttr('phone', label=_('Phone'), template_name='tenancy/attrs/phone.html')
|
||||
email = attrs.TemplatedAttr('email', label=_('Email'), template_name='tenancy/attrs/email.html')
|
||||
address = attrs.AddressAttr('address', map_url=False)
|
||||
link = attrs.TemplatedAttr('link', label=_('Link'), template_name='tenancy/attrs/link.html')
|
||||
description = attrs.TextAttr('description')
|
||||
@@ -1,13 +1,24 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from extras.ui.panels import CustomFieldsPanel, TagsPanel
|
||||
from netbox.object_actions import BulkDelete, BulkEdit, BulkExport, BulkImport
|
||||
from netbox.ui import actions, layout
|
||||
from netbox.ui.panels import (
|
||||
CommentsPanel,
|
||||
NestedGroupObjectPanel,
|
||||
ObjectsTablePanel,
|
||||
OrganizationalObjectPanel,
|
||||
RelatedObjectsPanel,
|
||||
)
|
||||
from netbox.views import generic
|
||||
from utilities.query import count_related
|
||||
from utilities.views import GetRelatedModelsMixin, register_model_view
|
||||
|
||||
from . import filtersets, forms, tables
|
||||
from .models import *
|
||||
from .ui import panels
|
||||
|
||||
#
|
||||
# Tenant groups
|
||||
@@ -31,6 +42,31 @@ class TenantGroupListView(generic.ObjectListView):
|
||||
@register_model_view(TenantGroup)
|
||||
class TenantGroupView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = TenantGroup.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
'tenancy.tenantgroup',
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
title=_('Child Groups'),
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'tenancy.tenantgroup',
|
||||
url_params={'parent': lambda ctx: ctx['object'].pk},
|
||||
label=_('Add Tenant Group'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
groups = instance.get_descendants(include_self=True)
|
||||
@@ -106,6 +142,17 @@ class TenantListView(generic.ObjectListView):
|
||||
@register_model_view(Tenant)
|
||||
class TenantView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Tenant.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.TenantPanel(),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
@@ -173,6 +220,31 @@ class ContactGroupListView(generic.ObjectListView):
|
||||
@register_model_view(ContactGroup)
|
||||
class ContactGroupView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = ContactGroup.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
'tenancy.contactgroup',
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
title=_('Child Groups'),
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'tenancy.contactgroup',
|
||||
url_params={'parent': lambda ctx: ctx['object'].pk},
|
||||
label=_('Add Contact Group'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
groups = instance.get_descendants(include_self=True)
|
||||
@@ -254,6 +326,17 @@ class ContactRoleListView(generic.ObjectListView):
|
||||
@register_model_view(ContactRole)
|
||||
class ContactRoleView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = ContactRole.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
OrganizationalObjectPanel(),
|
||||
TagsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
CommentsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
@@ -317,6 +400,23 @@ class ContactListView(generic.ObjectListView):
|
||||
@register_model_view(Contact)
|
||||
class ContactView(generic.ObjectView):
|
||||
queryset = Contact.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.ContactPanel(),
|
||||
TagsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
CommentsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
'tenancy.contactassignment',
|
||||
filters={'contact_id': lambda ctx: ctx['object'].pk},
|
||||
title=_('Assignments'),
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@register_model_view(Contact, 'add', detail=False)
|
||||
|
||||
Reference in New Issue
Block a user