Created ObjectContactsView feature view, and refactor object_contacts.html template

This commit is contained in:
Renato Almeida de Oliveira Zaroubin 2025-03-26 22:30:05 +00:00
parent bd8e00a935
commit eb4794ded7
2 changed files with 132 additions and 1 deletions

View File

@ -12,9 +12,15 @@ from core.tables import JobTable, ObjectChangeTable
from extras.forms import JournalEntryForm
from extras.models import JournalEntry
from extras.tables import JournalEntryTable
from tenancy.models import ContactAssignment
from tenancy.tables import ContactAssignmentTable
from tenancy.filtersets import ContactAssignmentFilterSet
from tenancy.forms import ContactAssignmentFilterForm
from utilities.permissions import get_permission_for_model
from utilities.views import ConditionalLoginRequiredMixin, GetReturnURLMixin, ViewTab
from utilities.htmx import htmx_partial
from .base import BaseMultiObjectView
from .mixins import ActionsMixin, TableMixin
__all__ = (
'BulkSyncDataView',
@ -22,9 +28,81 @@ __all__ = (
'ObjectJobsView',
'ObjectJournalView',
'ObjectSyncDataView',
'ObjectContactsView',
)
class ObjectContactsView(ConditionalLoginRequiredMixin, ActionsMixin, TableMixin, View):
"""
Show all Contacts associated with an object. The model class must be passed as a keyword argument when referencing
this view in a URL path. For example:
path('sites/<int:pk>/contacts/', ObjectContactsView.as_view(), name='site_contacts', kwargs={'model': Site}),
Attributes:
base_template: The name of the template to extend. If not provided, "{app}/{model}.html" will be used.
"""
base_template = None
tab = ViewTab(
label=_('Contacts'),
badge=lambda obj: obj.contacts.count(),
permission='tenancy.view_contactassignment',
weight=9000
)
table = ContactAssignmentTable
filterset = ContactAssignmentFilterSet
filterset_form = ContactAssignmentFilterForm
def get(self, request, model, **kwargs):
# Handle QuerySet restriction of parent object if needed
if hasattr(model.objects, 'restrict'):
obj = get_object_or_404(model.objects.restrict(request.user, 'view'), **kwargs)
else:
obj = get_object_or_404(model, **kwargs)
# Gather all Contact Assignments for this object
content_type = ContentType.objects.get_for_model(model)
contactassignments = ContactAssignment.objects.restrict(request.user, 'view').prefetch_related(
'contact',
).filter(
object_type=content_type,
object_id=obj.pk
).order_by('priority', 'contact', 'role')
contactassignments = self.filterset(request.GET, contactassignments, request=request).qs
# Determine the available actions
actions = self.get_permitted_actions(request.user, model=ContactAssignment)
has_bulk_actions = any([a.startswith('bulk_') for a in actions])
table = self.get_table(contactassignments, request, has_bulk_actions)
table.columns.hide('object_type')
table.columns.hide('object')
if htmx_partial(request):
return render(request, 'htmx/table.html', {
'object': obj,
'table': table,
'model': ContactAssignment,
})
# Default to using "<app>/<model>.html" as the template, if it exists. Otherwise,
# fall back to using base.html.
if self.base_template is None:
self.base_template = f"{model._meta.app_label}/{model._meta.model_name}.html"
return render(request, 'tenancy/object_contacts.html', {
'object': obj,
'model': ContactAssignment,
'base_template': self.base_template,
'table': table,
'table_config': f'{table.name}_config',
'filter_form': self.filterset_form(request.GET) if self.filterset_form else None,
'actions': actions,
'tab': self.tab,
'return_url': request.get_full_path(),
})
class ObjectChangeLogView(ConditionalLoginRequiredMixin, View):
"""
Present a history of changes made to a particular object. The model class must be passed as a keyword argument

View File

@ -1,4 +1,4 @@
{% extends 'generic/object_children.html' %}
{% extends base_template %}
{% load helpers %}
{% load i18n %}
@ -11,3 +11,56 @@
{% endwith %}
{% endif %}
{% endblock %}
{% block content %}
{% block table_controls %}
{% include 'inc/table_controls_htmx.html' with table_modal=table_config %}
{% endblock table_controls %}
<form method="post">
{% csrf_token %}
<div class="card">
<div class="htmx-container table-responsive" id="object_list">
{% include 'htmx/table.html' %}
</div>
</div>
<div class="d-print-none mt-2">
{% block bulk_controls %}
<div class="btn-group" role="group">
{# Bulk edit buttons #}
{% block bulk_edit_controls %}
{% with bulk_edit_view=model|validated_viewname:"bulk_edit" %}
{% if 'bulk_edit' in actions and bulk_edit_view %}
<button type="submit" name="_edit"
{% formaction %}="{% url bulk_edit_view %}?return_url={{ return_url }}"
class="btn btn-warning">
<i class="mdi mdi-pencil" aria-hidden="true"></i> {% trans "Edit Selected" %}
</button>
{% endif %}
{% endwith %}
{% endblock bulk_edit_controls %}
</div>
<div class="btn-group" role="group">
{# Bulk delete buttons #}
{% block bulk_delete_controls %}
{% with bulk_delete_view=model|validated_viewname:"bulk_delete" %}
{% if 'bulk_delete' in actions and bulk_delete_view %}
<button type="submit"
{% formaction %}="{% url bulk_delete_view %}?return_url={{ return_url }}"
class="btn btn-danger">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> {% trans "Delete Selected" %}
</button>
{% endif %}
{% endwith %}
{% endblock bulk_delete_controls %}
</div>
{# Other bulk action buttons #}
{% block bulk_extra_controls %}{% endblock %}
{% endblock bulk_controls %}
</div>
</form>
{% endblock content %}
{% block modals %}
{{ block.super }}
{% table_config_form table %}
{% endblock modals %}