hospital-management/templates/integration/webhook_management.html
2025-08-12 13:33:25 +03:00

725 lines
31 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Webhook Management - {{ block.super }}{% endblock %}
{% block css %}
<style>
.webhook-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 10px;
padding: 30px;
margin-bottom: 30px;
}
.webhook-card {
background: white;
border-radius: 8px;
padding: 20px;
margin: 15px 0;
border-left: 4px solid #007bff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease;
}
.webhook-card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
.webhook-active { border-left-color: #28a745; }
.webhook-inactive { border-left-color: #6c757d; }
.webhook-error { border-left-color: #dc3545; }
.webhook-pending { border-left-color: #ffc107; }
.webhook-status {
width: 12px;
height: 12px;
border-radius: 50%;
display: inline-block;
margin-right: 8px;
}
.status-active { background: #28a745; animation: pulse 2s infinite; }
.status-inactive { background: #6c757d; }
.status-error { background: #dc3545; }
.status-pending { background: #ffc107; }
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.6; }
100% { opacity: 1; }
}
.webhook-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 15px;
margin: 15px 0;
}
.stat-item {
text-align: center;
padding: 10px;
background: #f8f9fa;
border-radius: 6px;
}
.stat-value {
font-size: 1.5rem;
font-weight: bold;
color: #007bff;
}
.stat-label {
font-size: 0.8rem;
color: #6c757d;
margin-top: 5px;
}
.webhook-logs {
background: #f8f9fa;
border-radius: 6px;
padding: 15px;
margin: 15px 0;
max-height: 200px;
overflow-y: auto;
}
.log-entry {
font-family: monospace;
font-size: 0.85rem;
padding: 5px 0;
border-bottom: 1px solid #dee2e6;
}
.log-entry:last-child {
border-bottom: none;
}
.log-success { color: #28a745; }
.log-error { color: #dc3545; }
.log-warning { color: #ffc107; }
.log-info { color: #17a2b8; }
.webhook-form {
background: white;
border-radius: 8px;
padding: 20px;
margin: 15px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.payload-preview {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 15px;
font-family: monospace;
font-size: 0.9rem;
white-space: pre-wrap;
max-height: 300px;
overflow-y: auto;
}
.test-result {
margin: 15px 0;
padding: 15px;
border-radius: 6px;
display: none;
}
.test-success {
background: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.test-error {
background: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.webhook-actions {
display: flex;
gap: 10px;
margin-top: 15px;
}
.event-selector {
background: white;
border: 1px solid #dee2e6;
border-radius: 6px;
padding: 15px;
margin: 10px 0;
}
.event-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #f1f1f1;
}
.event-item:last-child {
border-bottom: none;
}
.security-settings {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 6px;
padding: 15px;
margin: 15px 0;
}
.delivery-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin: 20px 0;
}
.delivery-card {
background: white;
border-radius: 8px;
padding: 20px;
text-align: center;
border: 1px solid #dee2e6;
}
.delivery-value {
font-size: 2rem;
font-weight: bold;
color: #007bff;
}
.delivery-label {
color: #6c757d;
font-size: 0.9rem;
margin-top: 5px;
}
.retry-indicator {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 4px;
padding: 8px 12px;
font-size: 0.8rem;
display: inline-block;
margin: 5px 0;
}
</style>
{% endblock %}
{% block content %}
<div class="content">
<div class="container-fluid">
<!-- Page Header -->
<div class="row">
<div class="col-12">
<div class="page-header">
<div class="page-title">
<h4><i class="fas fa-webhook"></i> Webhook Management</h4>
<h6>Configure and monitor webhook endpoints</h6>
</div>
<div class="page-btn">
<button class="btn btn-primary me-2" data-bs-toggle="modal" data-bs-target="#webhookModal">
<i class="fas fa-plus"></i> Add Webhook
</button>
<button class="btn btn-info me-2" id="testAllWebhooks">
<i class="fas fa-vial"></i> Test All
</button>
<button class="btn btn-success" id="refreshWebhooks">
<i class="fas fa-sync-alt"></i> Refresh
</button>
</div>
</div>
</div>
</div>
<!-- Webhook Header -->
<div class="row">
<div class="col-12">
<div class="webhook-header">
<div class="row">
<div class="col-md-8">
<h5><i class="fas fa-broadcast-tower"></i> Webhook Monitoring</h5>
<p>Manage webhook endpoints for real-time data synchronization and event notifications</p>
</div>
<div class="col-md-4">
<div class="delivery-stats">
<div class="delivery-card">
<div class="delivery-value">12</div>
<div class="delivery-label">Active Webhooks</div>
</div>
<div class="delivery-card">
<div class="delivery-value">98.7%</div>
<div class="delivery-label">Success Rate</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Webhook List -->
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h5><i class="fas fa-list"></i> Configured Webhooks</h5>
</div>
<div class="card-body">
<!-- Active Webhook -->
<div class="webhook-card webhook-active">
<div class="row">
<div class="col-md-8">
<h6><span class="webhook-status status-active"></span>Patient Registration Webhook</h6>
<p><strong>URL:</strong> https://external-system.com/api/patient-webhook</p>
<p><strong>Events:</strong> patient.created, patient.updated</p>
<small class="text-muted">Last delivery: 2 minutes ago | Next retry: N/A</small>
</div>
<div class="col-md-4">
<div class="webhook-stats">
<div class="stat-item">
<div class="stat-value">247</div>
<div class="stat-label">Delivered</div>
</div>
<div class="stat-item">
<div class="stat-value">3</div>
<div class="stat-label">Failed</div>
</div>
<div class="stat-item">
<div class="stat-value">145ms</div>
<div class="stat-label">Avg Response</div>
</div>
</div>
<div class="webhook-actions">
<button class="btn btn-sm btn-outline-primary" onclick="testWebhook(1)">
<i class="fas fa-vial"></i> Test
</button>
<button class="btn btn-sm btn-outline-info" onclick="viewLogs(1)">
<i class="fas fa-list-alt"></i> Logs
</button>
<button class="btn btn-sm btn-outline-secondary" onclick="editWebhook(1)">
<i class="fas fa-edit"></i> Edit
</button>
</div>
</div>
</div>
</div>
<!-- Error Webhook -->
<div class="webhook-card webhook-error">
<div class="row">
<div class="col-md-8">
<h6><span class="webhook-status status-error"></span>Lab Results Webhook</h6>
<p><strong>URL:</strong> https://lab-system.com/api/results-webhook</p>
<p><strong>Events:</strong> lab_result.completed, lab_result.critical</p>
<small class="text-muted">Last delivery: 1 hour ago | Error: Connection timeout</small>
<div class="retry-indicator">
<i class="fas fa-redo"></i> Retrying in 15 minutes (Attempt 3/5)
</div>
</div>
<div class="col-md-4">
<div class="webhook-stats">
<div class="stat-item">
<div class="stat-value">89</div>
<div class="stat-label">Delivered</div>
</div>
<div class="stat-item">
<div class="stat-value">12</div>
<div class="stat-label">Failed</div>
</div>
<div class="stat-item">
<div class="stat-value">2.3s</div>
<div class="stat-label">Avg Response</div>
</div>
</div>
<div class="webhook-actions">
<button class="btn btn-sm btn-outline-warning" onclick="retryWebhook(2)">
<i class="fas fa-redo"></i> Retry
</button>
<button class="btn btn-sm btn-outline-danger" onclick="viewErrors(2)">
<i class="fas fa-exclamation-triangle"></i> Errors
</button>
<button class="btn btn-sm btn-outline-secondary" onclick="editWebhook(2)">
<i class="fas fa-edit"></i> Edit
</button>
</div>
</div>
</div>
</div>
<!-- Pending Webhook -->
<div class="webhook-card webhook-pending">
<div class="row">
<div class="col-md-8">
<h6><span class="webhook-status status-pending"></span>Appointment Webhook</h6>
<p><strong>URL:</strong> https://scheduling-system.com/api/appointment-webhook</p>
<p><strong>Events:</strong> appointment.scheduled, appointment.cancelled</p>
<small class="text-muted">Pending verification | Created: 10 minutes ago</small>
</div>
<div class="col-md-4">
<div class="webhook-stats">
<div class="stat-item">
<div class="stat-value">0</div>
<div class="stat-label">Delivered</div>
</div>
<div class="stat-item">
<div class="stat-value">0</div>
<div class="stat-label">Failed</div>
</div>
<div class="stat-item">
<div class="stat-value">-</div>
<div class="stat-label">Avg Response</div>
</div>
</div>
<div class="webhook-actions">
<button class="btn btn-sm btn-outline-success" onclick="verifyWebhook(3)">
<i class="fas fa-check"></i> Verify
</button>
<button class="btn btn-sm btn-outline-primary" onclick="testWebhook(3)">
<i class="fas fa-vial"></i> Test
</button>
<button class="btn btn-sm btn-outline-secondary" onclick="editWebhook(3)">
<i class="fas fa-edit"></i> Edit
</button>
</div>
</div>
</div>
</div>
<!-- Inactive Webhook -->
<div class="webhook-card webhook-inactive">
<div class="row">
<div class="col-md-8">
<h6><span class="webhook-status status-inactive"></span>Billing Webhook</h6>
<p><strong>URL:</strong> https://billing-system.com/api/billing-webhook</p>
<p><strong>Events:</strong> bill.created, payment.received</p>
<small class="text-muted">Disabled by user | Last active: 2 days ago</small>
</div>
<div class="col-md-4">
<div class="webhook-stats">
<div class="stat-item">
<div class="stat-value">1,247</div>
<div class="stat-label">Delivered</div>
</div>
<div class="stat-item">
<div class="stat-value">23</div>
<div class="stat-label">Failed</div>
</div>
<div class="stat-item">
<div class="stat-value">234ms</div>
<div class="stat-label">Avg Response</div>
</div>
</div>
<div class="webhook-actions">
<button class="btn btn-sm btn-outline-success" onclick="enableWebhook(4)">
<i class="fas fa-play"></i> Enable
</button>
<button class="btn btn-sm btn-outline-info" onclick="viewLogs(4)">
<i class="fas fa-list-alt"></i> Logs
</button>
<button class="btn btn-sm btn-outline-secondary" onclick="editWebhook(4)">
<i class="fas fa-edit"></i> Edit
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<!-- Webhook Statistics -->
<div class="card">
<div class="card-header">
<h5><i class="fas fa-chart-bar"></i> Delivery Statistics</h5>
</div>
<div class="card-body">
<div class="delivery-stats">
<div class="delivery-card">
<div class="delivery-value">1,583</div>
<div class="delivery-label">Total Deliveries</div>
</div>
<div class="delivery-card">
<div class="delivery-value">38</div>
<div class="delivery-label">Failed Deliveries</div>
</div>
<div class="delivery-card">
<div class="delivery-value">287ms</div>
<div class="delivery-label">Avg Response Time</div>
</div>
<div class="delivery-card">
<div class="delivery-value">5</div>
<div class="delivery-label">Pending Retries</div>
</div>
</div>
</div>
</div>
<!-- Recent Activity -->
<div class="card mt-3">
<div class="card-header">
<h5><i class="fas fa-clock"></i> Recent Activity</h5>
</div>
<div class="card-body">
<div class="webhook-logs">
<div class="log-entry log-success">
[14:32:15] SUCCESS: Patient webhook delivered (200ms)
</div>
<div class="log-entry log-success">
[14:31:42] SUCCESS: Lab result webhook delivered (145ms)
</div>
<div class="log-entry log-error">
[14:30:18] ERROR: Appointment webhook failed (timeout)
</div>
<div class="log-entry log-warning">
[14:29:55] WARNING: Billing webhook slow response (2.3s)
</div>
<div class="log-entry log-info">
[14:29:30] INFO: New webhook endpoint registered
</div>
<div class="log-entry log-success">
[14:28:45] SUCCESS: Patient webhook delivered (189ms)
</div>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="card mt-3">
<div class="card-header">
<h5><i class="fas fa-bolt"></i> Quick Actions</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button class="btn btn-outline-primary btn-sm" onclick="testAllWebhooks()">
<i class="fas fa-vial"></i> Test All Webhooks
</button>
<button class="btn btn-outline-warning btn-sm" onclick="retryFailedWebhooks()">
<i class="fas fa-redo"></i> Retry Failed
</button>
<button class="btn btn-outline-info btn-sm" onclick="exportWebhookLogs()">
<i class="fas fa-download"></i> Export Logs
</button>
<button class="btn btn-outline-success btn-sm" onclick="validateAllWebhooks()">
<i class="fas fa-check-circle"></i> Validate All
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Webhook Modal -->
<div class="modal fade" id="webhookModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-plus"></i> Add New Webhook</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="webhookForm">
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label>Webhook Name</label>
<input type="text" class="form-control" id="webhookName" placeholder="Enter webhook name">
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label>Endpoint URL</label>
<input type="url" class="form-control" id="webhookUrl" placeholder="https://example.com/webhook">
</div>
</div>
</div>
<div class="form-group mb-3">
<label>Description</label>
<textarea class="form-control" id="webhookDescription" rows="2" placeholder="Describe the webhook purpose"></textarea>
</div>
<div class="event-selector">
<h6>Select Events</h6>
<div class="event-item">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="patient.created"> Patient Created
</label>
<span class="badge bg-info">High Volume</span>
</div>
<div class="event-item">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="patient.updated"> Patient Updated
</label>
<span class="badge bg-info">High Volume</span>
</div>
<div class="event-item">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="appointment.scheduled"> Appointment Scheduled
</label>
<span class="badge bg-warning">Medium Volume</span>
</div>
<div class="event-item">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="lab_result.completed"> Lab Result Completed
</label>
<span class="badge bg-success">Low Volume</span>
</div>
<div class="event-item">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" value="bill.created"> Bill Created
</label>
<span class="badge bg-warning">Medium Volume</span>
</div>
</div>
<div class="security-settings">
<h6><i class="fas fa-shield-alt"></i> Security Settings</h6>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label>Secret Key</label>
<input type="text" class="form-control" id="webhookSecret" placeholder="Optional secret key">
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label>Authentication</label>
<select class="form-control" id="webhookAuth">
<option value="none">None</option>
<option value="basic">Basic Auth</option>
<option value="bearer">Bearer Token</option>
<option value="api_key">API Key</option>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label>Retry Attempts</label>
<select class="form-control" id="retryAttempts">
<option value="3">3 attempts</option>
<option value="5">5 attempts</option>
<option value="10">10 attempts</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-3">
<label>Timeout (seconds)</label>
<input type="number" class="form-control" id="webhookTimeout" value="30" min="5" max="300">
</div>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="webhookActive" checked>
<label class="form-check-label" for="webhookActive">
Activate webhook immediately
</label>
</div>
</form>
<div class="test-result" id="testResult"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-outline-primary" id="testWebhookBtn">
<i class="fas fa-vial"></i> Test Webhook
</button>
<button type="button" class="btn btn-primary" id="saveWebhookBtn">
<i class="fas fa-save"></i> Save Webhook
</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function() {
// Test individual webhook
window.testWebhook = function(webhookId) {
alert('Testing webhook #' + webhookId + '...');
// Simulate test result
setTimeout(function() {
alert('Webhook test completed successfully!');
}, 2000);
};
// View webhook logs
window.viewLogs = function(webhookId) {
alert('Opening logs for webhook #' + webhookId + '...');
};
// Edit webhook
window.editWebhook = function(webhookId) {
$('#webhookModal').modal('show');
// Pre-populate form with webhook data
};
// Retry webhook
window.retryWebhook = function(webhookId) {
alert('Retrying webhook #' + webhookId + '...');
};
// View errors
window.viewErrors = function(webhookId) {
alert('Opening error details for webhook #' + webhookId + '...');
};
// Verify webhook
window.verifyWebhook = function(webhookId) {
alert('Verifying webhook #' + webhookId + '...');
};
// Enable webhook
window.enableWebhook = function(webhookId) {
alert('Enabling webhook #' + webhookId + '...');
};
// Test webhook in modal
$('#testWebhookBtn').click(function() {
var url = $('#webhookUrl').val();
if (!url) {
alert('Please enter a webhook URL first');
return;
}
$('#testResult').removeClass('test-success test-error').addClass('test-success').show();
$('#testResult').html('<i class="fas fa-check"></i> Webhook test successful! Response time: 234ms');
});
// Save webhook
$('#saveWebhookBtn').click(function() {
var name = $('#webhookName').val();
var url = $('#webhookUrl').val();
if (!name || !url) {
alert('Please fill in required fields');
return;
}
alert('Webhook saved successfully!');
$('#webhookModal').modal('hide');
location.reload();
});
// Quick action functions
window.testAllWebhooks = function() {
alert('Testing all active webhooks...');
};
window.retryFailedWebhooks = function() {
alert('Retrying all failed webhook deliveries...');
};
window.exportWebhookLogs = function() {
alert('Exporting webhook logs...');
};
window.validateAllWebhooks = function() {
alert('Validating all webhook endpoints...');
};
// Refresh webhooks
$('#refreshWebhooks').click(function() {
location.reload();
});
// Test all webhooks button
$('#testAllWebhooks').click(function() {
testAllWebhooks();
});
});
</script>
{% endblock %}