Bladeren bron

#20923 - Convert tenancy to new UI layout (#21745)

Arthur Hanson 1 dag geleden
bovenliggende
commit
ea756b29e9

+ 1 - 0
netbox/templates/tenancy/attrs/email.html

@@ -0,0 +1 @@
+<a href="mailto:{{ value }}">{{ value }}</a>

+ 1 - 0
netbox/templates/tenancy/attrs/link.html

@@ -0,0 +1 @@
+<a href="{{ value }}">{{ value }}</a>

+ 1 - 0
netbox/templates/tenancy/attrs/phone.html

@@ -0,0 +1 @@
+<a href="tel:{{ value }}">{{ value }}</a>

+ 0 - 99
netbox/templates/tenancy/contact.html

@@ -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 %}

+ 2 - 54
netbox/templates/tenancy/contactgroup.html

@@ -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 %}

+ 0 - 41
netbox/templates/tenancy/contactrole.html

@@ -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 %}

+ 3 - 36
netbox/templates/tenancy/tenant.html

@@ -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 %}

+ 2 - 55
netbox/templates/tenancy/tenantgroup.html

@@ -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 - 0
netbox/tenancy/ui/__init__.py


+ 19 - 0
netbox/tenancy/ui/panels.py

@@ -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')

+ 100 - 0
netbox/tenancy/views.py

@@ -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)