547 lines
27 KiB
HTML
547 lines
27 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Notification - {{ notification.title }}{% 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">Notification Detail</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 'core:system_notification_list' %}">Notifications</a></li>
|
|
<li class="breadcrumb-item active">{{ notification.title|truncatechars:30 }}</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Main Content -->
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} bg-opacity-25">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-shrink-0">
|
|
<div class="avatar-sm me-3">
|
|
<span class="avatar-title rounded-circle bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} text-white">
|
|
<i class="fas fa-{% if notification.priority == 'LOW' %}info{% elif notification.priority == 'MEDIUM' %}exclamation{% elif notification.priority == 'HIGH' %}exclamation-triangle{% elif notification.priority == 'CRITICAL' %}radiation{% else %}bell{% endif %}"></i>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h5 class="card-title mb-0">{{ notification.title }}</h5>
|
|
<small class="text-muted">{{ notification.category }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-tag text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Priority</h6>
|
|
<p class="mb-0">
|
|
<span class="badge bg-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %}">
|
|
{{ notification.get_priority_display }}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-folder text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Category</h6>
|
|
<p class="mb-0">{{ notification.category }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-calendar-alt text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Start Date</h6>
|
|
<p class="text-muted mb-0">{{ notification.start_date|date:"F j, Y" }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-calendar-check text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">End Date</h6>
|
|
<p class="text-muted mb-0">{{ notification.end_date|date:"F j, Y" }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-toggle-on text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Status</h6>
|
|
<p class="mb-0">
|
|
{% if notification.is_active %}
|
|
{% if notification.start_date <= now and notification.end_date >= now %}
|
|
<span class="badge bg-success">Active</span>
|
|
{% elif notification.start_date > now %}
|
|
<span class="badge bg-info">Scheduled</span>
|
|
{% elif notification.end_date < now %}
|
|
<span class="badge bg-secondary">Expired</span>
|
|
{% endif %}
|
|
{% else %}
|
|
<span class="badge bg-danger">Inactive</span>
|
|
{% endif %}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-bullhorn text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Display Location</h6>
|
|
<p class="text-muted mb-0">{{ notification.get_display_location_display }}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Message</h6>
|
|
<div class="p-3 bg-light rounded">
|
|
{{ notification.message|linebreaks }}
|
|
</div>
|
|
</div>
|
|
|
|
{% if notification.link_url %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Action Link</h6>
|
|
<div class="p-3 bg-light rounded">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-external-link-alt text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<p class="mb-0">
|
|
<a href="{{ notification.link_url }}" target="_blank" class="text-primary">
|
|
{{ notification.link_text|default:notification.link_url }}
|
|
</a>
|
|
</p>
|
|
{% if notification.link_text %}
|
|
<small class="text-muted">{{ notification.link_url }}</small>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.target_roles.exists or notification.target_departments.exists %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Target Audience</h6>
|
|
<div class="p-3 bg-light rounded">
|
|
{% if notification.target_roles.exists %}
|
|
<div class="mb-3">
|
|
<h6 class="mb-2">Roles</h6>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% for role in notification.target_roles.all %}
|
|
<span class="badge bg-info">{{ role.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.target_departments.exists %}
|
|
<div>
|
|
<h6 class="mb-2">Departments</h6>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
{% for department in notification.target_departments.all %}
|
|
<span class="badge bg-secondary">{{ department.name }}</span>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.additional_data %}
|
|
<div class="mb-4">
|
|
<h6 class="text-muted mb-2">Additional Data</h6>
|
|
<div class="p-3 bg-light rounded">
|
|
<pre class="mb-0"><code>{{ notification.additional_data|pprint }}</code></pre>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="row mb-0">
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-clock text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Created</h6>
|
|
<p class="text-muted mb-0">{{ notification.created_at|date:"M d, Y g:i A" }}</p>
|
|
<small class="text-muted">{{ notification.created_at|timesince }} ago</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex mb-3">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-edit text-muted me-2"></i>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">Last Updated</h6>
|
|
<p class="text-muted mb-0">{{ notification.updated_at|date:"M d, Y g:i A" }}</p>
|
|
<small class="text-muted">{{ notification.updated_at|timesince }} ago</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notification Preview -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-eye me-2"></i>
|
|
Notification Preview
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-{% if notification.priority == 'LOW' %}success{% elif notification.priority == 'MEDIUM' %}info{% elif notification.priority == 'HIGH' %}warning{% elif notification.priority == 'CRITICAL' %}danger{% else %}secondary{% endif %} mb-0">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-{% if notification.priority == 'LOW' %}info{% elif notification.priority == 'MEDIUM' %}exclamation{% elif notification.priority == 'HIGH' %}exclamation-triangle{% elif notification.priority == 'CRITICAL' %}radiation{% else %}bell{% endif %} fa-lg"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">{{ notification.title }}</h5>
|
|
<p class="mb-0">{{ notification.message }}</p>
|
|
{% if notification.link_url %}
|
|
<hr>
|
|
<p class="mb-0">
|
|
<a href="{{ notification.link_url }}" class="alert-link">
|
|
{{ notification.link_text|default:"Learn More" }}
|
|
</a>
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Notification Statistics -->
|
|
{% if notification_stats %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-chart-bar me-2"></i>
|
|
Notification Statistics
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-4">
|
|
<div class="card border-0 bg-light">
|
|
<div class="card-body text-center">
|
|
<h2 class="mb-0">{{ notification_stats.impressions|default:0 }}</h2>
|
|
<p class="text-muted mb-0">Impressions</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card border-0 bg-light">
|
|
<div class="card-body text-center">
|
|
<h2 class="mb-0">{{ notification_stats.dismissals|default:0 }}</h2>
|
|
<p class="text-muted mb-0">Dismissals</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card border-0 bg-light">
|
|
<div class="card-body text-center">
|
|
<h2 class="mb-0">{{ notification_stats.clicks|default:0 }}</h2>
|
|
<p class="text-muted mb-0">Link Clicks</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if notification_stats.impressions > 0 %}
|
|
<div class="mt-4">
|
|
<h6 class="text-muted mb-2">Engagement Rate</h6>
|
|
<div class="progress" style="height: 10px;">
|
|
<div class="progress-bar bg-success" role="progressbar" style="width: {{ notification_stats.engagement_rate }}%;" aria-valuenow="{{ notification_stats.engagement_rate }}" aria-valuemin="0" aria-valuemax="100">{{ notification_stats.engagement_rate }}%</div>
|
|
</div>
|
|
<small class="text-muted">Based on link clicks and positive interactions</small>
|
|
</div>
|
|
{% endif %}
|
|
</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 'core:system_notification_list' %}" class="btn btn-outline-primary">
|
|
<i class="fas fa-arrow-left me-2"></i>
|
|
Back to Notifications
|
|
</a>
|
|
|
|
<a href="{% url 'core:system_notification_update' notification.pk %}" class="btn btn-outline-success">
|
|
<i class="fas fa-edit me-2"></i>
|
|
Edit Notification
|
|
</a>
|
|
|
|
{% if notification.is_active %}
|
|
<a href="{% url 'core:deactivate_notification' notification.pk %}" class="btn btn-outline-warning">
|
|
<i class="fas fa-power-off me-2"></i>
|
|
Deactivate Notification
|
|
</a>
|
|
{% else %}
|
|
<a href="{% url 'core:activate_notification' notification.pk %}" class="btn btn-outline-success">
|
|
<i class="fas fa-power-off me-2"></i>
|
|
Activate Notification
|
|
</a>
|
|
{% endif %}
|
|
|
|
<a href="{% url 'core:system_notification_delete' notification.pk %}" class="btn btn-outline-danger">
|
|
<i class="fas fa-trash me-2"></i>
|
|
Delete Notification
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Status Timeline -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-history me-2"></i>
|
|
Status Timeline
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="timeline">
|
|
{% if notification.created_at %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-success">
|
|
<i class="fas fa-plus"></i>
|
|
</div>
|
|
<div class="timeline-content">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">Created</h6>
|
|
<p class="text-muted mb-0">Notification created</p>
|
|
</div>
|
|
<small class="text-muted">{{ notification.created_at|date:"M d, Y" }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.start_date %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker {% if notification.start_date <= now %}bg-info{% else %}bg-secondary{% endif %}">
|
|
<i class="fas fa-calendar-alt"></i>
|
|
</div>
|
|
<div class="timeline-content">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">Start Date</h6>
|
|
<p class="text-muted mb-0">Notification becomes active</p>
|
|
</div>
|
|
<small class="text-muted">{{ notification.start_date|date:"M d, Y" }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.updated_at and notification.updated_at != notification.created_at %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker bg-primary">
|
|
<i class="fas fa-edit"></i>
|
|
</div>
|
|
<div class="timeline-content">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">Updated</h6>
|
|
<p class="text-muted mb-0">Notification last modified</p>
|
|
</div>
|
|
<small class="text-muted">{{ notification.updated_at|date:"M d, Y" }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if notification.end_date %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-marker {% if notification.end_date < now %}bg-secondary{% else %}bg-warning{% endif %}">
|
|
<i class="fas fa-calendar-check"></i>
|
|
</div>
|
|
<div class="timeline-content">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<div>
|
|
<h6 class="mb-1">End Date</h6>
|
|
<p class="text-muted mb-0">Notification expires</p>
|
|
</div>
|
|
<small class="text-muted">{{ notification.end_date|date:"M d, Y" }}</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tenant Information -->
|
|
{% if notification.tenant %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-building me-2"></i>
|
|
Tenant Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center mb-3">
|
|
<div class="flex-shrink-0">
|
|
<div class="avatar-sm me-3">
|
|
<span class="avatar-title rounded-circle bg-primary text-white">
|
|
{{ notification.tenant.name|first|upper }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="flex-grow-1">
|
|
<h6 class="mb-0">{{ notification.tenant.name }}</h6>
|
|
<small class="text-muted">{{ notification.tenant.get_organization_type_display }}</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-0">
|
|
<div class="d-flex justify-content-between align-items-center mb-1">
|
|
<small class="text-muted">Status</small>
|
|
<small class="text-{% if notification.tenant.is_active %}success{% else %}danger{% endif %}">
|
|
{% if notification.tenant.is_active %}Active{% else %}Inactive{% endif %}
|
|
</small>
|
|
</div>
|
|
<div class="progress" style="height: 6px;">
|
|
<div class="progress-bar bg-{% if notification.tenant.is_active %}success{% else %}danger{% endif %}"
|
|
style="width: {% if notification.tenant.is_active %}100{% else %}100{% endif %}%"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-globe me-2"></i>
|
|
System-Wide Notification
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-info mb-0">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-info-circle"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<p class="mb-0">This notification applies to all tenants in the system.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block css %}
|
|
<style>
|
|
.timeline {
|
|
position: relative;
|
|
padding-left: 30px;
|
|
}
|
|
|
|
.timeline::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 15px;
|
|
top: 0;
|
|
bottom: 0;
|
|
width: 2px;
|
|
background: #dee2e6;
|
|
}
|
|
|
|
.timeline-item {
|
|
position: relative;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.timeline-marker {
|
|
position: absolute;
|
|
left: -22px;
|
|
width: 30px;
|
|
height: 30px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.timeline-content {
|
|
margin-left: 20px;
|
|
padding: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
border-left: 3px solid #dee2e6;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|