mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Add UI views for webhooks
This commit is contained in:
@ -1,60 +1,6 @@
|
|||||||
from django import forms
|
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
|
|
||||||
from utilities.forms import ContentTypeMultipleChoiceField, LaxURLField
|
from .models import JobResult
|
||||||
from .models import JobResult, Webhook
|
|
||||||
from .utils import FeatureQuery
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Webhooks
|
|
||||||
#
|
|
||||||
|
|
||||||
class WebhookForm(forms.ModelForm):
|
|
||||||
content_types = ContentTypeMultipleChoiceField(
|
|
||||||
queryset=ContentType.objects.all(),
|
|
||||||
limit_choices_to=FeatureQuery('webhooks')
|
|
||||||
)
|
|
||||||
payload_url = LaxURLField(
|
|
||||||
label='URL'
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Webhook
|
|
||||||
exclude = ()
|
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Webhook)
|
|
||||||
class WebhookAdmin(admin.ModelAdmin):
|
|
||||||
list_display = [
|
|
||||||
'name', 'models', 'payload_url', 'http_content_type', 'enabled', 'type_create', 'type_update', 'type_delete',
|
|
||||||
'ssl_verification',
|
|
||||||
]
|
|
||||||
list_filter = [
|
|
||||||
'enabled', 'type_create', 'type_update', 'type_delete', 'content_types',
|
|
||||||
]
|
|
||||||
form = WebhookForm
|
|
||||||
fieldsets = (
|
|
||||||
(None, {
|
|
||||||
'fields': ('name', 'content_types', 'enabled')
|
|
||||||
}),
|
|
||||||
('Events', {
|
|
||||||
'fields': ('type_create', 'type_update', 'type_delete')
|
|
||||||
}),
|
|
||||||
('HTTP Request', {
|
|
||||||
'fields': (
|
|
||||||
'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret',
|
|
||||||
),
|
|
||||||
'classes': ('monospace',)
|
|
||||||
}),
|
|
||||||
('SSL', {
|
|
||||||
'fields': ('ssl_verification', 'ca_file_path')
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
def models(self, obj):
|
|
||||||
return ', '.join([ct.name for ct in obj.content_types.all()])
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -268,6 +268,129 @@ class ExportTemplateFilterForm(BootstrapMixin, forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Webhooks
|
||||||
|
#
|
||||||
|
|
||||||
|
class WebhookForm(BootstrapMixin, forms.ModelForm):
|
||||||
|
content_types = ContentTypeMultipleChoiceField(
|
||||||
|
queryset=ContentType.objects.all(),
|
||||||
|
limit_choices_to=FeatureQuery('webhooks')
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Webhook
|
||||||
|
fields = '__all__'
|
||||||
|
fieldsets = (
|
||||||
|
('Webhook', ('name', 'enabled')),
|
||||||
|
('Assigned Models', ('content_types',)),
|
||||||
|
('Events', ('type_create', 'type_update', 'type_delete')),
|
||||||
|
('HTTP Request', (
|
||||||
|
'payload_url', 'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret',
|
||||||
|
)),
|
||||||
|
('SSL', ('ssl_verification', 'ca_file_path')),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookCSVForm(CSVModelForm):
|
||||||
|
content_types = CSVMultipleContentTypeField(
|
||||||
|
queryset=ContentType.objects.all(),
|
||||||
|
limit_choices_to=FeatureQuery('webhooks'),
|
||||||
|
help_text="One or more assigned object types"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Webhook
|
||||||
|
fields = (
|
||||||
|
'name', 'enabled', 'content_types', 'type_create', 'type_update', 'type_delete', 'payload_url',
|
||||||
|
'http_method', 'http_content_type', 'additional_headers', 'body_template', 'secret', 'ssl_verification',
|
||||||
|
'ca_file_path'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookBulkEditForm(BootstrapMixin, BulkEditForm):
|
||||||
|
pk = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Webhook.objects.all(),
|
||||||
|
widget=forms.MultipleHiddenInput
|
||||||
|
)
|
||||||
|
enabled = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
type_create = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
type_update = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
type_delete = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
http_method = forms.ChoiceField(
|
||||||
|
choices=WebhookHttpMethodChoices,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
payload_url = forms.CharField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
ssl_verification = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
secret = forms.CharField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
ca_file_path = forms.CharField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
nullable_fields = ['secret', 'ca_file_path']
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookFilterForm(BootstrapMixin, forms.Form):
|
||||||
|
field_groups = [
|
||||||
|
['content_types', 'http_method'],
|
||||||
|
['enabled', 'type_create', 'type_update', 'type_delete'],
|
||||||
|
]
|
||||||
|
content_types = ContentTypeMultipleChoiceField(
|
||||||
|
queryset=ContentType.objects.all(),
|
||||||
|
limit_choices_to=FeatureQuery('custom_fields')
|
||||||
|
)
|
||||||
|
http_method = forms.MultipleChoiceField(
|
||||||
|
choices=WebhookHttpMethodChoices,
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2Multiple()
|
||||||
|
)
|
||||||
|
enabled = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2(
|
||||||
|
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
)
|
||||||
|
)
|
||||||
|
type_create = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2(
|
||||||
|
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
)
|
||||||
|
)
|
||||||
|
type_update = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2(
|
||||||
|
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
)
|
||||||
|
)
|
||||||
|
type_delete = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=StaticSelect2(
|
||||||
|
choices=BOOLEAN_WITH_BLANK_CHOICES
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Custom field models
|
# Custom field models
|
||||||
#
|
#
|
||||||
|
@ -38,4 +38,14 @@ class Migration(migrations.Migration):
|
|||||||
name='last_updated',
|
name='last_updated',
|
||||||
field=models.DateTimeField(auto_now=True, null=True),
|
field=models.DateTimeField(auto_now=True, null=True),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='created',
|
||||||
|
field=models.DateField(auto_now_add=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='webhook',
|
||||||
|
name='last_updated',
|
||||||
|
field=models.DateTimeField(auto_now=True, null=True),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -36,7 +36,8 @@ __all__ = (
|
|||||||
# Webhooks
|
# Webhooks
|
||||||
#
|
#
|
||||||
|
|
||||||
class Webhook(BigIDModel):
|
@extras_features('webhooks')
|
||||||
|
class Webhook(ChangeLoggedModel):
|
||||||
"""
|
"""
|
||||||
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or
|
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or
|
||||||
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
|
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
|
||||||
@ -129,6 +130,9 @@ class Webhook(BigIDModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('extras:webhook', args=[self.pk])
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
|
@ -86,6 +86,27 @@ class ExportTemplateTable(BaseTable):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Webhooks
|
||||||
|
#
|
||||||
|
|
||||||
|
class WebhookTable(BaseTable):
|
||||||
|
pk = ToggleColumn()
|
||||||
|
name = tables.Column(
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta(BaseTable.Meta):
|
||||||
|
model = Webhook
|
||||||
|
fields = (
|
||||||
|
'pk', 'name', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method', 'payload_url',
|
||||||
|
'secret', 'ssl_validation', 'ca_file_path',
|
||||||
|
)
|
||||||
|
default_columns = (
|
||||||
|
'pk', 'name', 'enabled', 'type_create', 'type_update', 'type_delete', 'http_method', 'payload_url',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tags
|
# Tags
|
||||||
#
|
#
|
||||||
|
@ -120,6 +120,49 @@ class ExportTemplateTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||||
|
model = Webhook
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
|
||||||
|
site_ct = ContentType.objects.get_for_model(Site)
|
||||||
|
webhooks = (
|
||||||
|
Webhook(name='Webhook 1', payload_url='http://example.com/?1', type_create=True, http_method='POST'),
|
||||||
|
Webhook(name='Webhook 2', payload_url='http://example.com/?2', type_create=True, http_method='POST'),
|
||||||
|
Webhook(name='Webhook 3', payload_url='http://example.com/?3', type_create=True, http_method='POST'),
|
||||||
|
)
|
||||||
|
for webhook in webhooks:
|
||||||
|
webhook.save()
|
||||||
|
webhook.content_types.add(site_ct)
|
||||||
|
|
||||||
|
cls.form_data = {
|
||||||
|
'name': 'Webhook X',
|
||||||
|
'content_types': [site_ct.pk],
|
||||||
|
'type_create': False,
|
||||||
|
'type_update': True,
|
||||||
|
'type_delete': True,
|
||||||
|
'payload_url': 'http://example.com/?x',
|
||||||
|
'http_method': 'GET',
|
||||||
|
'http_content_type': 'application/foo',
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.csv_data = (
|
||||||
|
"name,content_types,type_create,payload_url,http_method,http_content_type",
|
||||||
|
"Webhook 4,dcim.site,True,http://example.com/?4,GET,application/json",
|
||||||
|
"Webhook 5,dcim.site,True,http://example.com/?5,GET,application/json",
|
||||||
|
"Webhook 6,dcim.site,True,http://example.com/?6,GET,application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.bulk_edit_data = {
|
||||||
|
'enabled': False,
|
||||||
|
'type_create': False,
|
||||||
|
'type_update': True,
|
||||||
|
'type_delete': True,
|
||||||
|
'http_method': 'GET',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TagTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
class TagTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||||
model = Tag
|
model = Tag
|
||||||
|
|
||||||
|
@ -42,6 +42,18 @@ urlpatterns = [
|
|||||||
path('export-templates/<int:pk>/changelog/', views.ObjectChangeLogView.as_view(), name='exporttemplate_changelog',
|
path('export-templates/<int:pk>/changelog/', views.ObjectChangeLogView.as_view(), name='exporttemplate_changelog',
|
||||||
kwargs={'model': models.ExportTemplate}),
|
kwargs={'model': models.ExportTemplate}),
|
||||||
|
|
||||||
|
# Webhooks
|
||||||
|
path('webhooks/', views.WebhookListView.as_view(), name='webhook_list'),
|
||||||
|
path('webhooks/add/', views.WebhookEditView.as_view(), name='webhook_add'),
|
||||||
|
path('webhooks/import/', views.WebhookBulkImportView.as_view(), name='webhook_import'),
|
||||||
|
path('webhooks/edit/', views.WebhookBulkEditView.as_view(), name='webhook_bulk_edit'),
|
||||||
|
path('webhooks/delete/', views.WebhookBulkDeleteView.as_view(), name='webhook_bulk_delete'),
|
||||||
|
path('webhooks/<int:pk>/', views.WebhookView.as_view(), name='webhook'),
|
||||||
|
path('webhooks/<int:pk>/edit/', views.WebhookEditView.as_view(), name='webhook_edit'),
|
||||||
|
path('webhooks/<int:pk>/delete/', views.WebhookDeleteView.as_view(), name='webhook_delete'),
|
||||||
|
path('webhooks/<int:pk>/changelog/', views.ObjectChangeLogView.as_view(), name='webhook_changelog',
|
||||||
|
kwargs={'model': models.Webhook}),
|
||||||
|
|
||||||
# Tags
|
# Tags
|
||||||
path('tags/', views.TagListView.as_view(), name='tag_list'),
|
path('tags/', views.TagListView.as_view(), name='tag_list'),
|
||||||
path('tags/add/', views.TagEditView.as_view(), name='tag_add'),
|
path('tags/add/', views.TagEditView.as_view(), name='tag_add'),
|
||||||
|
@ -149,6 +149,49 @@ class ExportTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
table = tables.ExportTemplateTable
|
table = tables.ExportTemplateTable
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Webhooks
|
||||||
|
#
|
||||||
|
|
||||||
|
class WebhookListView(generic.ObjectListView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
filterset = filtersets.WebhookFilterSet
|
||||||
|
filterset_form = forms.WebhookFilterForm
|
||||||
|
table = tables.WebhookTable
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookView(generic.ObjectView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookEditView(generic.ObjectEditView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
model_form = forms.WebhookForm
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookDeleteView(generic.ObjectDeleteView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookBulkImportView(generic.BulkImportView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
model_form = forms.WebhookCSVForm
|
||||||
|
table = tables.WebhookTable
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookBulkEditView(generic.BulkEditView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
filterset = filtersets.WebhookFilterSet
|
||||||
|
table = tables.WebhookTable
|
||||||
|
form = forms.WebhookBulkEditForm
|
||||||
|
|
||||||
|
|
||||||
|
class WebhookBulkDeleteView(generic.BulkDeleteView):
|
||||||
|
queryset = Webhook.objects.all()
|
||||||
|
filterset = filtersets.WebhookFilterSet
|
||||||
|
table = tables.WebhookTable
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tags
|
# Tags
|
||||||
#
|
#
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
{% load plugins %}
|
{% load plugins %}
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
{% block breadcrumbs %}
|
||||||
<li class="breadcrumb-item"><a href="{% url 'extras:customfield_list' %}">Cusotm Fields</a></li>
|
<li class="breadcrumb-item"><a href="{% url 'extras:customfield_list' %}">Custom Fields</a></li>
|
||||||
<li class="breadcrumb-item">{{ object }}</li>
|
<li class="breadcrumb-item">{{ object }}</li>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
165
netbox/templates/extras/webhook.html
Normal file
165
netbox/templates/extras/webhook.html
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load helpers %}
|
||||||
|
{% load plugins %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<li class="breadcrumb-item"><a href="{% url 'extras:webhook_list' %}">Webhooks</a></li>
|
||||||
|
<li class="breadcrumb-item">{{ object }}</li>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Webhook
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Name</th>
|
||||||
|
<td>{{ object.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Enabled</th>
|
||||||
|
<td>
|
||||||
|
{% if object.enabled %}
|
||||||
|
<i class="mdi mdi-check-bold text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="mdi mdi-close-thick text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Events
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Create</th>
|
||||||
|
<td>
|
||||||
|
{% if object.type_create %}
|
||||||
|
<i class="mdi mdi-check-bold text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="mdi mdi-close-thick text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Update</th>
|
||||||
|
<td>
|
||||||
|
{% if object.type_create %}
|
||||||
|
<i class="mdi mdi-check-bold text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="mdi mdi-close-thick text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Delete</th>
|
||||||
|
<td>
|
||||||
|
{% if object.type_create %}
|
||||||
|
<i class="mdi mdi-check-bold text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="mdi mdi-close-thick text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
HTTP Request
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">HTTP Method</th>
|
||||||
|
<td>{{ object.get_http_method_display }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Payload URL</th>
|
||||||
|
<td><code>{{ object.payload_url }}</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">HTTP Content Type</th>
|
||||||
|
<td>{{ object.http_content_type }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Secret</th>
|
||||||
|
<td>{{ object.secret|placeholder }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
SSL
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">SSL Verification</th>
|
||||||
|
<td>
|
||||||
|
{% if object.ssl_verification %}
|
||||||
|
<i class="mdi mdi-check-bold text-success" title="Yes"></i>
|
||||||
|
{% else %}
|
||||||
|
<i class="mdi mdi-close-thick text-danger" title="No"></i>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">CA File Path</th>
|
||||||
|
<td>
|
||||||
|
{% if object.ca_file_path %}
|
||||||
|
<code>{{ object.ca_file_path }}</code>
|
||||||
|
{% else %}
|
||||||
|
&mdash
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Assigned Models
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
{% for ct in object.content_types.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ ct }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Additional Headers
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<pre>{{ object.additional_headers }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Body Template
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<pre>{{ object.body_template }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% plugin_right_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -287,6 +287,8 @@ OTHER_MENU = Menu(
|
|||||||
add_url=None, import_url=None),
|
add_url=None, import_url=None),
|
||||||
MenuItem(label="Journal Entries",
|
MenuItem(label="Journal Entries",
|
||||||
url="extras:journalentry_list", add_url=None, import_url=None),
|
url="extras:journalentry_list", add_url=None, import_url=None),
|
||||||
|
MenuItem(label="Webhooks", url="extras:webhook_list",
|
||||||
|
add_url="extras:webhook_add", import_url="extras:webhook_import"),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
MenuGroup(
|
MenuGroup(
|
||||||
|
Reference in New Issue
Block a user