520 lines
28 KiB
HTML
520 lines
28 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block title %}Delete Alert Rule - Communications{% 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">Delete Alert Rule</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:alert_rule_list' %}">Alert Rules</a></li>
|
|
<li class="breadcrumb-item active">Delete</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header bg-danger text-white">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
Confirm Alert Rule Deletion
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<!-- Critical Warning -->
|
|
<div class="alert alert-danger" role="alert">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-exclamation-triangle fa-2x"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h5 class="alert-heading">Critical Warning: Permanent Action</h5>
|
|
<p class="mb-0">
|
|
You are about to permanently delete this alert rule. This action cannot be undone and may affect:
|
|
</p>
|
|
<ul class="mt-2 mb-0">
|
|
<li>Active monitoring and alerting capabilities</li>
|
|
<li>Patient safety and care quality monitoring</li>
|
|
<li>System performance and equipment monitoring</li>
|
|
<li>Compliance and audit requirements</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Rule Details -->
|
|
<div class="card bg-light">
|
|
<div class="card-body">
|
|
<h6 class="card-title">Alert Rule to be deleted:</h6>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless table-sm">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Rule Name:</td>
|
|
<td>{{ object.rule_name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Category:</td>
|
|
<td>
|
|
<span class="badge bg-{% if object.category == 'SYSTEM' %}primary{% elif object.category == 'PATIENT' %}success{% elif object.category == 'EQUIPMENT' %}warning{% elif object.category == 'MEDICATION' %}info{% else %}secondary{% endif %}">
|
|
{{ object.get_category_display }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Severity:</td>
|
|
<td>
|
|
<span class="badge bg-{% if object.severity == 'CRITICAL' %}danger{% elif object.severity == 'HIGH' %}warning{% elif object.severity == 'MEDIUM' %}info{% else %}secondary{% endif %}">
|
|
{{ object.get_severity_display }}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Status:</td>
|
|
<td>
|
|
<span class="badge bg-{% if object.is_active %}success{% else %}secondary{% endif %}">
|
|
{% if object.is_active %}Active{% else %}Inactive{% endif %}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="table-responsive">
|
|
<table class="table table-borderless table-sm">
|
|
<tr>
|
|
<td class="fw-bold text-muted">Created:</td>
|
|
<td>{{ object.created_at|date:"M d, Y" }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Last Triggered:</td>
|
|
<td>
|
|
{% if object.last_triggered %}
|
|
{{ object.last_triggered|date:"M d, Y g:i A" }}
|
|
{% else %}
|
|
<span class="text-muted">Never</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Trigger Count:</td>
|
|
<td>{{ object.trigger_count|default:0 }} times</td>
|
|
</tr>
|
|
<tr>
|
|
<td class="fw-bold text-muted">Recipients:</td>
|
|
<td>{{ object.recipients.count|default:0 }} users</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Condition Preview -->
|
|
<div class="mt-3">
|
|
<h6 class="text-muted">Condition Expression:</h6>
|
|
<div class="bg-dark p-2 rounded">
|
|
<code class="text-light">{{ object.condition_expression }}</code>
|
|
</div>
|
|
</div>
|
|
|
|
{% if object.description %}
|
|
<div class="mt-3">
|
|
<h6 class="text-muted">Description:</h6>
|
|
<div class="bg-white p-2 rounded border">
|
|
{{ object.description|linebreaks }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Impact Assessment -->
|
|
<div class="mt-4">
|
|
<h6 class="text-muted mb-3">Deletion Impact Assessment:</h6>
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="text-center p-3 bg-light rounded">
|
|
<i class="fas fa-bell fa-2x text-primary mb-2"></i>
|
|
<h6>{{ active_instances|default:0 }}</h6>
|
|
<small class="text-muted">Active alert instances</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center p-3 bg-light rounded">
|
|
<i class="fas fa-users fa-2x text-success mb-2"></i>
|
|
<h6>{{ object.recipients.count|default:0 }}</h6>
|
|
<small class="text-muted">Affected recipients</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center p-3 bg-light rounded">
|
|
<i class="fas fa-history fa-2x text-info mb-2"></i>
|
|
<h6>{{ historical_instances|default:0 }}</h6>
|
|
<small class="text-muted">Historical instances</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center p-3 bg-light rounded">
|
|
<i class="fas fa-link fa-2x text-warning mb-2"></i>
|
|
<h6>{{ dependent_rules|default:0 }}</h6>
|
|
<small class="text-muted">Dependent rules</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Safety Recommendations -->
|
|
<div class="mt-4">
|
|
<h6 class="text-muted mb-3">Safety Recommendations:</h6>
|
|
|
|
{% if object.severity == 'CRITICAL' %}
|
|
<div class="alert alert-danger" role="alert">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-exclamation-circle fa-lg"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h6 class="alert-heading">Critical Alert Rule Warning</h6>
|
|
<p class="mb-0">
|
|
This is a CRITICAL severity alert rule. Deleting it may compromise patient safety
|
|
and system monitoring. Consider deactivating instead of deleting.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="list-group">
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<h6 class="mb-1">Deactivate Instead</h6>
|
|
<small class="text-success">Recommended</small>
|
|
</div>
|
|
<p class="mb-1">Keep the rule but disable it to preserve historical data and allow future reactivation.</p>
|
|
<button class="btn btn-sm btn-outline-warning" onclick="deactivateRule()">
|
|
<i class="fas fa-pause me-1"></i>Deactivate Rule
|
|
</button>
|
|
</div>
|
|
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<h6 class="mb-1">Archive Rule Data</h6>
|
|
<small class="text-info">Backup Option</small>
|
|
</div>
|
|
<p class="mb-1">Export rule configuration and historical data before deletion.</p>
|
|
<button class="btn btn-sm btn-outline-info" onclick="archiveRule()">
|
|
<i class="fas fa-archive me-1"></i>Archive & Export
|
|
</button>
|
|
</div>
|
|
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<h6 class="mb-1">Create Replacement</h6>
|
|
<small class="text-primary">Safe Transition</small>
|
|
</div>
|
|
<p class="mb-1">Create a new rule to replace this one before deletion.</p>
|
|
<button class="btn btn-sm btn-outline-primary" onclick="createReplacement()">
|
|
<i class="fas fa-plus me-1"></i>Create Replacement
|
|
</button>
|
|
</div>
|
|
|
|
<div class="list-group-item">
|
|
<div class="d-flex w-100 justify-content-between">
|
|
<h6 class="mb-1">Transfer Recipients</h6>
|
|
<small class="text-secondary">Migration</small>
|
|
</div>
|
|
<p class="mb-1">Move recipients to another alert rule before deletion.</p>
|
|
<button class="btn btn-sm btn-outline-secondary" onclick="transferRecipients()">
|
|
<i class="fas fa-exchange-alt me-1"></i>Transfer Recipients
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Active Dependencies Warning -->
|
|
{% if active_instances > 0 or dependent_rules > 0 %}
|
|
<div class="mt-4">
|
|
<div class="alert alert-warning" role="alert">
|
|
<div class="d-flex">
|
|
<div class="flex-shrink-0">
|
|
<i class="fas fa-exclamation-triangle fa-2x"></i>
|
|
</div>
|
|
<div class="flex-grow-1 ms-3">
|
|
<h6 class="alert-heading">Active Dependencies Detected!</h6>
|
|
<p class="mb-2">This rule has active dependencies that will be affected:</p>
|
|
<ul class="mb-0">
|
|
{% if active_instances > 0 %}
|
|
<li><strong>{{ active_instances }}</strong> active alert instance(s) will be orphaned</li>
|
|
{% endif %}
|
|
{% if dependent_rules > 0 %}
|
|
<li><strong>{{ dependent_rules }}</strong> dependent rule(s) may be affected</li>
|
|
{% endif %}
|
|
<li>Historical data and audit trails will be lost</li>
|
|
<li>Monitoring coverage gaps may occur</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Confirmation Form -->
|
|
<form method="post" class="mt-4">
|
|
{% csrf_token %}
|
|
|
|
<!-- Confirmation Checkboxes -->
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" id="confirmUnderstand" required>
|
|
<label class="form-check-label fw-bold text-danger" for="confirmUnderstand">
|
|
I understand this action is permanent and cannot be undone
|
|
</label>
|
|
</div>
|
|
|
|
{% if object.severity == 'CRITICAL' %}
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" id="confirmCritical" required>
|
|
<label class="form-check-label fw-bold text-danger" for="confirmCritical">
|
|
I acknowledge this is a CRITICAL alert rule and its deletion may compromise patient safety
|
|
</label>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if active_instances > 0 %}
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" id="confirmActiveInstances" required>
|
|
<label class="form-check-label fw-bold text-danger" for="confirmActiveInstances">
|
|
I acknowledge that {{ active_instances }} active alert instance(s) will be affected
|
|
</label>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="checkbox" id="confirmResponsibility" required>
|
|
<label class="form-check-label fw-bold text-danger" for="confirmResponsibility">
|
|
I take full responsibility for any consequences of this deletion
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Reason for Deletion -->
|
|
<div class="mb-3">
|
|
<label for="deletionReason" class="form-label">Reason for deletion (required):</label>
|
|
<select class="form-select" id="deletionReason" name="deletion_reason" required>
|
|
<option value="">Select a reason...</option>
|
|
<option value="duplicate">Duplicate rule</option>
|
|
<option value="obsolete">Rule is obsolete</option>
|
|
<option value="incorrect">Incorrect configuration</option>
|
|
<option value="replaced">Replaced by new rule</option>
|
|
<option value="compliance">Compliance requirement</option>
|
|
<option value="system_change">System architecture change</option>
|
|
<option value="false_positives">Too many false positives</option>
|
|
<option value="other">Other</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Replacement Rule -->
|
|
<div class="mb-3" id="replacementGroup" style="display: none;">
|
|
<label for="replacementRule" class="form-label">Replacement rule (if applicable):</label>
|
|
<select class="form-select" id="replacementRule" name="replacement_rule">
|
|
<option value="">No replacement</option>
|
|
{% for rule in available_rules %}
|
|
<option value="{{ rule.id }}">{{ rule.rule_name }} ({{ rule.get_category_display }})</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<!-- Additional Comments -->
|
|
<div class="mb-4">
|
|
<label for="deletionComments" class="form-label">Additional comments and justification:</label>
|
|
<textarea class="form-control" id="deletionComments" name="deletion_comments" rows="4"
|
|
placeholder="Provide detailed justification for this deletion, including any safety considerations and mitigation measures..."></textarea>
|
|
</div>
|
|
|
|
<!-- Final Confirmation -->
|
|
<div class="mb-4">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="finalConfirmation" required>
|
|
<label class="form-check-label fw-bold text-danger" for="finalConfirmation">
|
|
I have read all warnings and confirm I want to permanently delete this alert rule
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="d-flex gap-2 justify-content-end">
|
|
<a href="{% url 'communications:alert_rule_detail' object.pk %}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>
|
|
Cancel
|
|
</a>
|
|
<a href="{% url 'communications:alert_rule_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-list me-1"></i>
|
|
Back to List
|
|
</a>
|
|
<button type="submit" class="btn btn-danger" id="deleteButton" disabled>
|
|
<i class="fas fa-trash me-1"></i>
|
|
Delete Alert Rule Permanently
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block js %}
|
|
<script>
|
|
// Enable delete button only when all confirmations are checked
|
|
function updateDeleteButton() {
|
|
const confirmUnderstand = document.getElementById('confirmUnderstand').checked;
|
|
const confirmCritical = document.getElementById('confirmCritical');
|
|
const criticalChecked = !confirmCritical || confirmCritical.checked;
|
|
const confirmActiveInstances = document.getElementById('confirmActiveInstances');
|
|
const instancesChecked = !confirmActiveInstances || confirmActiveInstances.checked;
|
|
const confirmResponsibility = document.getElementById('confirmResponsibility').checked;
|
|
const finalConfirmation = document.getElementById('finalConfirmation').checked;
|
|
const reasonSelected = document.getElementById('deletionReason').value !== '';
|
|
|
|
document.getElementById('deleteButton').disabled = !(
|
|
confirmUnderstand && criticalChecked && instancesChecked &&
|
|
confirmResponsibility && finalConfirmation && reasonSelected
|
|
);
|
|
}
|
|
|
|
// Add event listeners
|
|
document.getElementById('confirmUnderstand').addEventListener('change', updateDeleteButton);
|
|
document.getElementById('confirmResponsibility').addEventListener('change', updateDeleteButton);
|
|
document.getElementById('finalConfirmation').addEventListener('change', updateDeleteButton);
|
|
document.getElementById('deletionReason').addEventListener('change', function() {
|
|
updateDeleteButton();
|
|
|
|
// Show replacement field if reason is "replaced"
|
|
const replacementGroup = document.getElementById('replacementGroup');
|
|
replacementGroup.style.display = this.value === 'replaced' ? 'block' : 'none';
|
|
});
|
|
|
|
{% if object.severity == 'CRITICAL' %}
|
|
document.getElementById('confirmCritical').addEventListener('change', updateDeleteButton);
|
|
{% endif %}
|
|
|
|
{% if active_instances > 0 %}
|
|
document.getElementById('confirmActiveInstances').addEventListener('change', updateDeleteButton);
|
|
{% endif %}
|
|
|
|
// Alternative action functions
|
|
function deactivateRule() {
|
|
if (confirm('Deactivate this alert rule instead of deleting it?')) {
|
|
fetch(`{% url 'communications:alert_rule_detail' object.pk %}toggle/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({ active: false })
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
alert('Rule deactivated successfully');
|
|
window.location.href = '{% url "communications:alert_rule_list" %}';
|
|
} else {
|
|
alert('Error deactivating rule: ' + data.error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function archiveRule() {
|
|
if (confirm('Archive and export this rule data before deletion?')) {
|
|
fetch(`{% url 'communications:alert_rule_detail' object.pk %}archive/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value,
|
|
'Content-Type': 'application/json',
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Download the archive
|
|
const link = document.createElement('a');
|
|
link.href = data.download_url;
|
|
link.download = data.filename;
|
|
link.click();
|
|
|
|
alert('Rule data archived and downloaded successfully');
|
|
} else {
|
|
alert('Error archiving rule: ' + data.error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function createReplacement() {
|
|
if (confirm('Create a replacement rule based on this one?')) {
|
|
window.location.href = '{% url "communications:alert_rule_create" %}?duplicate={{ object.id }}&replace=true';
|
|
}
|
|
}
|
|
|
|
function transferRecipients() {
|
|
if (confirm('Transfer recipients to another alert rule?')) {
|
|
window.location.href = '{% url "communications:alert_rule_list" %}?transfer_from={{ object.id }}';
|
|
}
|
|
}
|
|
|
|
// Form submission with additional validation
|
|
document.querySelector('form').addEventListener('submit', function(e) {
|
|
const reason = document.getElementById('deletionReason').value;
|
|
const comments = document.getElementById('deletionComments').value.trim();
|
|
|
|
if (!reason) {
|
|
e.preventDefault();
|
|
alert('Please select a reason for deletion.');
|
|
return;
|
|
}
|
|
|
|
if (comments.length < 20) {
|
|
e.preventDefault();
|
|
alert('Please provide detailed comments (minimum 20 characters) justifying this deletion.');
|
|
return;
|
|
}
|
|
|
|
const finalConfirm = confirm(
|
|
'FINAL CONFIRMATION:\n\n' +
|
|
'You are about to PERMANENTLY DELETE this alert rule:\n\n' +
|
|
'Rule: {{ object.rule_name|escapejs }}\n' +
|
|
'Category: {{ object.get_category_display|escapejs }}\n' +
|
|
'Severity: {{ object.get_severity_display|escapejs }}\n' +
|
|
{% if active_instances > 0 %}'Active instances: {{ active_instances }}\n' +{% endif %}
|
|
{% if object.recipients.count > 0 %}'Recipients affected: {{ object.recipients.count }}\n' +{% endif %}
|
|
'\nReason: ' + reason + '\n\n' +
|
|
'This action CANNOT be undone and may affect patient safety!\n\n' +
|
|
'Are you absolutely certain you want to proceed?'
|
|
);
|
|
|
|
if (!finalConfirm) {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
// Initialize
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
updateDeleteButton();
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|