467 lines
22 KiB
HTML
467 lines
22 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{{ object.template_name }} - Template Details{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid">
|
|
<!-- Breadcrumb -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
|
|
<h4 class="mb-sm-0">Template Details</h4>
|
|
<div class="page-title-right">
|
|
<ol class="breadcrumb m-0">
|
|
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'communications:dashboard' %}">Communications</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'communications:notification_template_list' %}">Templates</a></li>
|
|
<li class="breadcrumb-item active">Details</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Main Content -->
|
|
<div class="col-lg-8">
|
|
<!-- Template Overview -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-file-alt me-2"></i>
|
|
{{ object.template_name }}
|
|
</h5>
|
|
<div class="d-flex gap-2">
|
|
<span class="badge bg-{% if object.category == 'APPOINTMENT' %}primary{% elif object.category == 'REMINDER' %}warning{% elif object.category == 'ALERT' %}danger{% else %}info{% endif %} fs-6">
|
|
{{ object.get_category_display }}
|
|
</span>
|
|
<span class="badge bg-{% if object.message_type == 'EMAIL' %}info{% elif object.message_type == 'SMS' %}success{% elif object.message_type == 'PUSH' %}warning{% else %}secondary{% endif %} fs-6">
|
|
{{ object.get_message_type_display }}
|
|
</span>
|
|
<span class="badge bg-{% if object.is_active %}success{% else %}secondary{% endif %} fs-6">
|
|
{% if object.is_active %}Active{% else %}Inactive{% endif %}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Template Information -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Template Name:</td>
|
|
<td>{{ object.template_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Category:</td>
|
|
<td>{{ object.get_category_display }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Message Type:</td>
|
|
<td>{{ object.get_message_type_display }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Language:</td>
|
|
<td>{{ object.language|default:"English" }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Created:</td>
|
|
<td>{{ object.created_at|date:"M d, Y g:i A" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Last Updated:</td>
|
|
<td>{{ object.updated_at|date:"M d, Y g:i A" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Usage Count:</td>
|
|
<td>{{ object.usage_count|default:0 }} times</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Status:</td>
|
|
<td>
|
|
{% if object.is_active %}
|
|
<span class="text-success"><i class="fas fa-check-circle me-1"></i>Active</span>
|
|
{% else %}
|
|
<span class="text-secondary"><i class="fas fa-pause-circle me-1"></i>Inactive</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Description -->
|
|
{% if object.description %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Description:</h6>
|
|
<div class="bg-light p-3 rounded">
|
|
{{ object.description|linebreaks }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Subject Template -->
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Subject Template:</h6>
|
|
<div class="bg-light p-3 rounded">
|
|
<code>{{ object.subject_template }}</code>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Body Template -->
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Body Template:</h6>
|
|
<div class="bg-light p-3 rounded" style="max-height: 300px; overflow-y: auto;">
|
|
<pre class="mb-0">{{ object.body_template }}</pre>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Variables -->
|
|
{% if object.variables %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Template Variables:</h6>
|
|
<div class="row">
|
|
{% for variable in object.variables %}
|
|
<div class="col-md-6 mb-2">
|
|
<div class="d-flex align-items-center bg-light p-2 rounded">
|
|
<code class="me-2">{%verbatim%}{{ {% endverbatim %}{{ variable.name }}{% verbatim %} }}{% endverbatim %}</code>
|
|
<small class="text-muted">{{ variable.description|default:"No description" }}</small>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Metadata -->
|
|
{% if object.metadata %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Additional Metadata:</h6>
|
|
<div class="bg-light p-3 rounded">
|
|
<pre class="mb-0">{{ object.metadata|pprint }}</pre>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Template Preview -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-eye me-2"></i>
|
|
Template Preview
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">With Sample Data:</h6>
|
|
<div class="border rounded p-3">
|
|
<div class="mb-2">
|
|
<strong>Subject:</strong>
|
|
<div class="mt-1">{{ rendered_subject|default:"[Subject will be rendered here]" }}</div>
|
|
</div>
|
|
<div>
|
|
<strong>Body:</strong>
|
|
<div class="mt-1">{{ rendered_body|default:"[Body will be rendered here]"|linebreaks }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-2">Raw Template:</h6>
|
|
<div class="border rounded p-3 bg-light">
|
|
<div class="mb-2">
|
|
<strong>Subject:</strong>
|
|
<div class="mt-1"><code>{{ object.subject_template }}</code></div>
|
|
</div>
|
|
<div>
|
|
<strong>Body:</strong>
|
|
<div class="mt-1"><code>{{ object.body_template|truncatechars:200 }}</code></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Usage History -->
|
|
{% if usage_history %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-history me-2"></i>
|
|
Recent Usage History
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-nowrap table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Message</th>
|
|
<th>Recipients</th>
|
|
<th>Status</th>
|
|
<th>Sent By</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for usage in usage_history %}
|
|
<tr>
|
|
<td>{{ usage.created_at|date:"M d, Y g:i A" }}</td>
|
|
<td>
|
|
<a href="{% url 'communications:message_detail' usage.pk %}">
|
|
{{ usage.subject|truncatechars:40 }}
|
|
</a>
|
|
</td>
|
|
<td>{{ usage.messagerecipient_set.count }}</td>
|
|
<td>
|
|
<span class="badge bg-{% if usage.status == 'SENT' %}success{% elif usage.status == 'FAILED' %}danger{% else %}warning{% endif %}">
|
|
{{ usage.get_status_display }}
|
|
</span>
|
|
</td>
|
|
<td>{{ usage.sender.get_full_name }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="col-lg-4">
|
|
<!-- Quick Actions -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-bolt me-2"></i>
|
|
Quick Actions
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-grid gap-2">
|
|
<a href="{% url 'communications:message_create' %}?template={{ object.id }}" class="btn btn-success">
|
|
<i class="fas fa-paper-plane me-1"></i>
|
|
Use Template
|
|
</a>
|
|
<a href="{% url 'communications:notification_template_update' object.pk %}" class="btn btn-primary">
|
|
<i class="fas fa-edit me-1"></i>
|
|
Edit Template
|
|
</a>
|
|
|
|
<hr>
|
|
|
|
<button class="btn btn-outline-secondary" onclick="duplicateTemplate()">
|
|
<i class="fas fa-copy me-1"></i>
|
|
Duplicate Template
|
|
</button>
|
|
<button class="btn btn-outline-info" onclick="testTemplate()">
|
|
<i class="fas fa-flask me-1"></i>
|
|
Test Template
|
|
</button>
|
|
<button class="btn btn-outline-secondary" onclick="exportTemplate()">
|
|
<i class="fas fa-download me-1"></i>
|
|
Export Template
|
|
</button>
|
|
|
|
<hr>
|
|
|
|
{% if object.is_active %}
|
|
<button class="btn btn-outline-warning" onclick="toggleTemplate(false)">
|
|
<i class="fas fa-pause me-1"></i>
|
|
Deactivate Template
|
|
</button>
|
|
{% else %}
|
|
<button class="btn btn-outline-success" onclick="toggleTemplate(true)">
|
|
<i class="fas fa-play me-1"></i>
|
|
Activate Template
|
|
</button>
|
|
{% endif %}
|
|
|
|
<hr>
|
|
|
|
<a href="{% url 'communications:notification_template_delete' object.pk %}" class="btn btn-outline-danger">
|
|
<i class="fas fa-trash me-1"></i>
|
|
Delete Template
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Template Statistics -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-chart-bar me-2"></i>
|
|
Usage Statistics
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless table-sm">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Total Usage:</td>
|
|
<td>{{ object.usage_count|default:0 }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">This Month:</td>
|
|
<td>{{ monthly_usage|default:0 }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">This Week:</td>
|
|
<td>{{ weekly_usage|default:0 }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Success Rate:</td>
|
|
<td>
|
|
<span class="text-success">{{ success_rate|default:0 }}%</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Avg Recipients:</td>
|
|
<td>{{ avg_recipients|default:0 }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Template Information -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
Template Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless table-sm">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Variables:</td>
|
|
<td>{{ object.variables.count|default:0 }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Languages:</td>
|
|
<td>{{ object.languages.count|default:1 }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">File Size:</td>
|
|
<td>{{ template_size|default:"N/A" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Version:</td>
|
|
<td>{{ object.version|default:"1.0" }}</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Related Templates -->
|
|
{% if related_templates %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-link me-2"></i>
|
|
Related Templates
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
{% for template in related_templates %}
|
|
<div class="d-flex align-items-center mb-2">
|
|
<div class="avatar-xs me-2">
|
|
<div class="avatar-title bg-soft-primary text-primary rounded">
|
|
<i class="fas fa-file-alt"></i>
|
|
</div>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">
|
|
<a href="{% url 'communications:notification_template_detail' template.pk %}">
|
|
{{ template.template_name|truncatechars:25 }}
|
|
</a>
|
|
</h6>
|
|
<small class="text-muted">{{ template.get_category_display }}</small>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
function duplicateTemplate() {
|
|
if (confirm('Create a copy of this template?')) {
|
|
window.location.href = '{% url "communications:notification_template_create" %}?duplicate={{ object.id }}';
|
|
}
|
|
}
|
|
|
|
function testTemplate() {
|
|
if (confirm('Send a test message using this template?')) {
|
|
fetch(`{% url 'communications:notification_template_detail' object.pk %}test/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
|
|
'Content-Type': 'application/json',
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Test message sent successfully!');
|
|
} else {
|
|
alert('Error sending test message: ' + data.error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function exportTemplate() {
|
|
window.open(`{% url 'communications:notification_template_detail' object.pk %}export/`, '_blank');
|
|
}
|
|
|
|
function toggleTemplate(activate) {
|
|
const action = activate ? 'activate' : 'deactivate';
|
|
if (confirm(`${action.charAt(0).toUpperCase() + action.slice(1)} this template?`)) {
|
|
fetch(`{% url 'communications:notification_template_detail' object.pk %}toggle/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ active: activate })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
location.reload();
|
|
} else {
|
|
alert('Error updating template: ' + data.error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|