724 lines
38 KiB
HTML
724 lines
38 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}{% if object %}Edit Notification - {{ object.title }}{% else %}Create New Notification{% endif %}{% 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">{% if object %}Edit Notification{% else %}Create New Notification{% endif %}</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">{% if object %}Edit{% else %}Create{% endif %}</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Main Form -->
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-{% if object %}edit{% else %}plus{% endif %} me-2"></i>
|
|
Notification Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="post" id="notificationForm">
|
|
{% csrf_token %}
|
|
|
|
<!-- Basic Information -->
|
|
<div class="row mb-4">
|
|
{# <div class="col-md-6">#}
|
|
{# <div class="form-floating mb-3">#}
|
|
{# {{ form.category }}#}
|
|
{# <label for="{{ form.category.id_for_label }}">Category *</label>#}
|
|
{# {% if form.category.errors %}#}
|
|
{# <div class="invalid-feedback d-block">{{ form.category.errors.0 }}</div>#}
|
|
{# {% endif %}#}
|
|
{# </div>#}
|
|
{# </div>#}
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.title }}
|
|
<label for="{{ form.title.id_for_label }}">Title *</label>
|
|
{% if form.title.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.title.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.priority }}
|
|
<label for="{{ form.priority.id_for_label }}">Priority *</label>
|
|
{% if form.priority.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.priority.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<div class="mb-3">
|
|
<label for="{{ form.message.id_for_label }}" class="form-label">Message *</label>
|
|
{{ form.message }}
|
|
{% if form.message.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.message.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Display Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h6 class="card-title mb-0">Display Settings</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
{# <div class="col-md-6">#}
|
|
{# <div class="form-floating mb-3">#}
|
|
{# {{ form.display_location }}#}
|
|
{# <label for="{{ form.display_location.id_for_label }}">Display Location *</label>#}
|
|
{# {% if form.display_location.errors %}#}
|
|
{# <div class="invalid-feedback d-block">{{ form.display_location.errors.0 }}</div>#}
|
|
{# {% endif %}#}
|
|
{# </div>#}
|
|
{# </div>#}
|
|
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.start_date }}
|
|
<label for="{{ form.start_date.id_for_label }}">Start Date *</label>
|
|
{% if form.start_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.start_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.end_date }}
|
|
<label for="{{ form.end_date.id_for_label }}">End Date *</label>
|
|
{% if form.end_date.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.end_date.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row mb-3 p-1">
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
{{ form.is_dismissible }}
|
|
<label class="form-check-label" for="{{ form.is_dismissible.id_for_label }}">
|
|
Allow users to dismiss this notification
|
|
</label>
|
|
{% if form.is_dismissible.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_dismissible.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch">
|
|
{{ form.is_active }}
|
|
<label class="form-check-label" for="{{ form.is_active.id_for_label }}">
|
|
Active Notification
|
|
</label>
|
|
{% if form.is_active.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_active.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Link -->
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h6 class="card-title mb-0">Action Link (Optional)</h6>
|
|
<button class="btn btn-sm btn-link" type="button" data-bs-toggle="collapse" data-bs-target="#actionLinkSection">
|
|
<i class="fas fa-chevron-down"></i>
|
|
</button>
|
|
</div>
|
|
<div class="collapse" id="actionLinkSection">
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.action_url }}
|
|
<label for="{{ form.action_url.id_for_label }}">Link URL</label>
|
|
{% if form.action_url.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.action_url.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-floating mb-3">
|
|
{{ form.action_text }}
|
|
<label for="{{ form.action_text.id_for_label }}">Link Text</label>
|
|
{% if form.action_text.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.action_text.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Target Audience -->
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h6 class="card-title mb-0">Target Audience (Optional)</h6>
|
|
<button class="btn btn-sm btn-link" type="button" data-bs-toggle="collapse" data-bs-target="#targetAudienceSection">
|
|
<i class="fas fa-chevron-down"></i>
|
|
</button>
|
|
</div>
|
|
<div class="collapse" id="targetAudienceSection">
|
|
<div class="card-body">
|
|
<div class="alert alert-info">
|
|
<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">If no specific targets are selected, the notification will be shown to all users.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label for="{{ form.target_roles.id_for_label }}" class="form-label">Target Roles</label>
|
|
{{ form.target_roles }}
|
|
{% if form.target_roles.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.target_roles.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Hold Ctrl/Cmd to select multiple roles</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="{{ form.target_departments.id_for_label }}" class="form-label">Target Departments</label>
|
|
{{ form.target_departments }}
|
|
{% if form.target_departments.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.target_departments.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Hold Ctrl/Cmd to select multiple departments</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Advanced Options -->
|
|
<div class="card mb-4">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h6 class="card-title mb-0">Advanced Options</h6>
|
|
<button class="btn btn-sm btn-link" type="button" data-bs-toggle="collapse" data-bs-target="#advancedOptions">
|
|
<i class="fas fa-chevron-down"></i>
|
|
</button>
|
|
</div>
|
|
<div class="collapse" id="advancedOptions">
|
|
<div class="card-body">
|
|
<div class="row mb-3">
|
|
<div class="col-12">
|
|
<div class="mb-3">
|
|
<label for="{{ form.additional_data.id_for_label }}" class="form-label">Additional Data (JSON)</label>
|
|
{{ form.additional_data }}
|
|
{% if form.additional_data.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.additional_data.errors.0 }}</div>
|
|
{% endif %}
|
|
<div class="form-text">Enter valid JSON format</div>
|
|
</div>
|
|
<div class="mb-3">
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="validateJson()">
|
|
<i class="fas fa-check me-1"></i>
|
|
Validate JSON
|
|
</button>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary ms-2" onclick="formatJson()">
|
|
<i class="fas fa-indent me-1"></i>
|
|
Format JSON
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
{# <div class="col-md-6">#}
|
|
{# <div class="form-floating mb-3">#}
|
|
{# {{ form.icon_class }}#}
|
|
{# <label for="{{ form.icon_class.id_for_label }}">Icon Class</label>#}
|
|
{# {% if form.icon_class.errors %}#}
|
|
{# <div class="invalid-feedback d-block">{{ form.icon_class.errors.0 }}</div>#}
|
|
{# {% endif %}#}
|
|
{# </div>#}
|
|
{# <div class="form-text">FontAwesome icon class (e.g., fa-info-circle)</div>#}
|
|
{# </div>#}
|
|
<div class="col-md-6">
|
|
<div class="form-check form-switch mt-4">
|
|
{{ form.is_persistent }}
|
|
<label class="form-check-label" for="{{ form.is_persistent.id_for_label }}">
|
|
Persistent Notification
|
|
</label>
|
|
{% if form.is_persistent.errors %}
|
|
<div class="invalid-feedback d-block">{{ form.is_persistent.errors.0 }}</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="form-text">If enabled, notification will persist across sessions</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form Actions -->
|
|
<div class="d-flex justify-content-between">
|
|
<a href="{% url 'core:system_notification_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>
|
|
Cancel
|
|
</a>
|
|
<div>
|
|
<button type="button" class="btn btn-outline-primary me-2" onclick="previewNotification()">
|
|
<i class="fas fa-eye me-1"></i>
|
|
Preview
|
|
</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-save me-1"></i>
|
|
{% if object %}Update Notification{% else %}Create Notification{% endif %}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Help Sidebar -->
|
|
<div class="col-lg-4">
|
|
<!-- Live Preview -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-eye me-2"></i>
|
|
Live Preview
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div id="notificationPreview" class="alert alert-info">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-bell"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">Notification Title</h5>
|
|
<p class="mb-0">Notification message will appear here.</p>
|
|
<hr>
|
|
<p class="mb-0">
|
|
<a href="#" class="alert-link">Action Link</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="text-center">
|
|
<small class="text-muted">This preview updates as you type</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Help & Guidelines -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-question-circle me-2"></i>
|
|
Help & Guidelines
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="accordion" id="helpAccordion">
|
|
<!-- Priority Levels -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="priorityHelp">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#priorityContent">
|
|
Priority Levels
|
|
</button>
|
|
</h2>
|
|
<div id="priorityContent" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
|
|
<div class="accordion-body">
|
|
<ul class="list-unstyled">
|
|
<li><span class="badge bg-success me-2">Low</span> Informational messages, tips, updates</li>
|
|
<li><span class="badge bg-info me-2">Medium</span> Important information, reminders</li>
|
|
<li><span class="badge bg-warning me-2">High</span> Urgent messages, warnings</li>
|
|
<li><span class="badge bg-danger me-2">Critical</span> Emergency alerts, system critical issues</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Display Locations -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="locationsHelp">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#locationsContent">
|
|
Display Locations
|
|
</button>
|
|
</h2>
|
|
<div id="locationsContent" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
|
|
<div class="accordion-body">
|
|
<ul class="list-unstyled">
|
|
<li><strong>Dashboard:</strong> Appears on the main dashboard</li>
|
|
<li><strong>Header:</strong> Appears in the site header</li>
|
|
<li><strong>Sidebar:</strong> Appears in the navigation sidebar</li>
|
|
<li><strong>Modal:</strong> Appears as a popup modal</li>
|
|
<li><strong>Toast:</strong> Appears as a temporary toast notification</li>
|
|
<li><strong>Banner:</strong> Appears as a full-width banner</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Message Formatting -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="formattingHelp">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#formattingContent">
|
|
Message Formatting
|
|
</button>
|
|
</h2>
|
|
<div id="formattingContent" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
|
|
<div class="accordion-body">
|
|
<p>Basic formatting is supported:</p>
|
|
<ul class="list-unstyled">
|
|
<li><code>**bold text**</code> - <strong>bold text</strong></li>
|
|
<li><code>*italic text*</code> - <em>italic text</em></li>
|
|
<li><code>[link text](url)</code> - <a href="#">link text</a></li>
|
|
<li><code>- list item</code> - bulleted list</li>
|
|
</ul>
|
|
<div class="alert alert-warning alert-sm">
|
|
<small>Keep messages concise and clear for better user experience.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Best Practices -->
|
|
<div class="accordion-item">
|
|
<h2 class="accordion-header" id="practicesHelp">
|
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#practicesContent">
|
|
Best Practices
|
|
</button>
|
|
</h2>
|
|
<div id="practicesContent" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
|
|
<div class="accordion-body">
|
|
<ul class="list-unstyled">
|
|
<li><i class="fas fa-check-circle text-success me-2"></i> Keep titles short and descriptive</li>
|
|
<li><i class="fas fa-check-circle text-success me-2"></i> Use appropriate priority levels</li>
|
|
<li><i class="fas fa-check-circle text-success me-2"></i> Include clear action steps when needed</li>
|
|
<li><i class="fas fa-check-circle text-success me-2"></i> Target specific audiences when possible</li>
|
|
<li><i class="fas fa-times-circle text-danger me-2"></i> Avoid overusing high/critical priorities</li>
|
|
<li><i class="fas fa-times-circle text-danger me-2"></i> Don't create too many concurrent notifications</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Preview Modal -->
|
|
<div class="modal fade" id="previewModal" tabindex="-1" aria-labelledby="previewModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="previewModalLabel">Notification Preview</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<h6 class="text-muted mb-3">Dashboard View</h6>
|
|
<div id="dashboardPreview" class="alert alert-info">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-bell fa-lg"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">Notification Title</h5>
|
|
<p class="mb-0">Notification message will appear here.</p>
|
|
<hr>
|
|
<p class="mb-0">
|
|
<a href="#" class="alert-link">Action Link</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-3">Toast View</h6>
|
|
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
|
|
<div class="toast-header">
|
|
<i id="toastIcon" class="fas fa-bell me-2"></i>
|
|
<strong class="me-auto" id="toastTitle">Notification Title</strong>
|
|
<small>Just now</small>
|
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
</div>
|
|
<div class="toast-body" id="toastMessage">
|
|
Notification message will appear here.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<h6 class="text-muted mb-3">Banner View</h6>
|
|
<div id="bannerPreview" class="alert alert-info mb-0">
|
|
<div class="d-flex align-items-center">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-bell"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-2" id="bannerTitle">
|
|
Notification Title
|
|
</div>
|
|
<div class="flex-shrink-0">
|
|
<a href="#" class="text-decoration-none" id="bannerLink">Action Link</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<h6 class="text-muted mb-3">Modal View</h6>
|
|
<div class="card">
|
|
<div class="card-header" id="modalTitle">
|
|
Notification Title
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="card-text" id="modalMessage">Notification message will appear here.</p>
|
|
<a href="#" class="btn btn-primary btn-sm" id="modalLink">Action Link</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Live preview updates
|
|
const titleInput = document.getElementById('{{ form.title.id_for_label }}');
|
|
const messageInput = document.getElementById('{{ form.message.id_for_label }}');
|
|
const prioritySelect = document.getElementById('{{ form.priority.id_for_label }}');
|
|
const linkUrlInput = document.getElementById('{{ form.action_url.id_for_label }}');
|
|
const linkTextInput = document.getElementById('{{ form.action_text.id_for_label }}');
|
|
{#const iconClassInput = document.getElementById('{{ form.icon_class.id_for_label }}');#}
|
|
|
|
// Initialize preview
|
|
updatePreview();
|
|
|
|
// Add event listeners
|
|
titleInput.addEventListener('input', updatePreview);
|
|
messageInput.addEventListener('input', updatePreview);
|
|
prioritySelect.addEventListener('change', updatePreview);
|
|
linkUrlInput.addEventListener('input', updatePreview);
|
|
linkTextInput.addEventListener('input', updatePreview);
|
|
iconClassInput.addEventListener('input', updatePreview);
|
|
|
|
// Initialize date pickers if needed
|
|
if (typeof flatpickr !== 'undefined') {
|
|
flatpickr('#{{ form.start_date.id_for_label }}', {
|
|
enableTime: false,
|
|
dateFormat: 'Y-m-d',
|
|
});
|
|
|
|
flatpickr('#{{ form.end_date.id_for_label }}', {
|
|
enableTime: false,
|
|
dateFormat: 'Y-m-d',
|
|
});
|
|
}
|
|
});
|
|
|
|
function updatePreview() {
|
|
const title = document.getElementById('{{ form.title.id_for_label }}').value || 'Notification Title';
|
|
const message = document.getElementById('{{ form.message.id_for_label }}').value || 'Notification message will appear here.';
|
|
const priority = document.getElementById('{{ form.priority.id_for_label }}').value;
|
|
const linkUrl = document.getElementById('{{ form.action_url.id_for_label }}').value;
|
|
const linkText = document.getElementById('{{ form.action_text.id_for_label }}').value || 'Action Link';
|
|
const iconClass = document.getElementById('{{ form.icon_class.id_for_label }}').value || 'fa-bell';
|
|
|
|
// Determine alert class based on priority
|
|
let alertClass = 'alert-info';
|
|
if (priority === 'LOW') alertClass = 'alert-success';
|
|
else if (priority === 'MEDIUM') alertClass = 'alert-info';
|
|
else if (priority === 'HIGH') alertClass = 'alert-warning';
|
|
else if (priority === 'CRITICAL') alertClass = 'alert-danger';
|
|
|
|
// Update live preview
|
|
const preview = document.getElementById('notificationPreview');
|
|
preview.className = `alert ${alertClass}`;
|
|
|
|
// Update icon
|
|
let icon = 'fa-bell';
|
|
if (priority === 'LOW') icon = 'fa-info-circle';
|
|
else if (priority === 'MEDIUM') icon = 'fa-exclamation-circle';
|
|
else if (priority === 'HIGH') icon = 'fa-exclamation-triangle';
|
|
else if (priority === 'CRITICAL') icon = 'fa-radiation';
|
|
|
|
if (iconClass) {
|
|
icon = iconClass;
|
|
}
|
|
|
|
// Update content
|
|
let previewContent = `
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas ${icon}"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">${title}</h5>
|
|
<p class="mb-0">${message}</p>
|
|
`;
|
|
|
|
if (linkUrl) {
|
|
previewContent += `
|
|
<hr>
|
|
<p class="mb-0">
|
|
<a href="${linkUrl}" class="alert-link">${linkText}</a>
|
|
</p>
|
|
`;
|
|
}
|
|
|
|
previewContent += `
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
preview.innerHTML = previewContent;
|
|
}
|
|
|
|
function validateJson() {
|
|
const jsonField = document.getElementById('{{ form.additional_data.id_for_label }}');
|
|
const jsonValue = jsonField.value.trim();
|
|
|
|
if (!jsonValue) {
|
|
alert('Please enter JSON content to validate');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const parsedJson = JSON.parse(jsonValue);
|
|
alert('JSON is valid!');
|
|
} catch (error) {
|
|
alert('Invalid JSON: ' + error.message);
|
|
}
|
|
}
|
|
|
|
function formatJson() {
|
|
const jsonField = document.getElementById('{{ form.additional_data.id_for_label }}');
|
|
const jsonValue = jsonField.value.trim();
|
|
|
|
if (!jsonValue) {
|
|
alert('Please enter JSON content to format');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const parsedJson = JSON.parse(jsonValue);
|
|
jsonField.value = JSON.stringify(parsedJson, null, 2);
|
|
} catch (error) {
|
|
alert('Cannot format invalid JSON: ' + error.message);
|
|
}
|
|
}
|
|
|
|
function previewNotification() {
|
|
const title = document.getElementById('{{ form.title.id_for_label }}').value || 'Notification Title';
|
|
const message = document.getElementById('{{ form.message.id_for_label }}').value || 'Notification message will appear here.';
|
|
const priority = document.getElementById('{{ form.priority.id_for_label }}').value;
|
|
const linkUrl = document.getElementById('{{ form.action_url.id_for_label }}').value || '#';
|
|
const linkText = document.getElementById('{{ form.action_text.id_for_label }}').value || 'Action Link';
|
|
const iconClass = document.getElementById('{{ form.icon_class.id_for_label }}').value || 'fa-bell';
|
|
|
|
// Determine alert class based on priority
|
|
let alertClass = 'alert-info';
|
|
if (priority === 'LOW') alertClass = 'alert-success';
|
|
else if (priority === 'MEDIUM') alertClass = 'alert-info';
|
|
else if (priority === 'HIGH') alertClass = 'alert-warning';
|
|
else if (priority === 'CRITICAL') alertClass = 'alert-danger';
|
|
|
|
// Update icon
|
|
let icon = 'fa-bell';
|
|
if (priority === 'LOW') icon = 'fa-info-circle';
|
|
else if (priority === 'MEDIUM') icon = 'fa-exclamation-circle';
|
|
else if (priority === 'HIGH') icon = 'fa-exclamation-triangle';
|
|
else if (priority === 'CRITICAL') icon = 'fa-radiation';
|
|
|
|
if (iconClass) {
|
|
icon = iconClass;
|
|
}
|
|
|
|
// Update dashboard preview
|
|
const dashboardPreview = document.getElementById('dashboardPreview');
|
|
dashboardPreview.className = `alert ${alertClass}`;
|
|
dashboardPreview.innerHTML = `
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas ${icon} fa-lg"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">${title}</h5>
|
|
<p class="mb-0">${message}</p>
|
|
<hr>
|
|
<p class="mb-0">
|
|
<a href="${linkUrl}" class="alert-link">${linkText}</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// Update toast preview
|
|
document.getElementById('toastIcon').className = `fas ${icon} me-2`;
|
|
document.getElementById('toastTitle').textContent = title;
|
|
document.getElementById('toastMessage').textContent = message;
|
|
|
|
// Update banner preview
|
|
const bannerPreview = document.getElementById('bannerPreview');
|
|
bannerPreview.className = `alert ${alertClass} mb-0`;
|
|
document.getElementById('bannerTitle').textContent = title;
|
|
document.getElementById('bannerLink').textContent = linkText;
|
|
document.getElementById('bannerLink').href = linkUrl;
|
|
|
|
// Update modal preview
|
|
document.getElementById('modalTitle').textContent = title;
|
|
document.getElementById('modalMessage').textContent = message;
|
|
document.getElementById('modalLink').textContent = linkText;
|
|
document.getElementById('modalLink').href = linkUrl;
|
|
|
|
// Show the modal
|
|
const previewModal = new bootstrap.Modal(document.getElementById('previewModal'));
|
|
previewModal.show();
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|