Marwan Alwali fd2f7259c0 update
2025-08-14 18:05:05 +03:00

537 lines
22 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Reports - Analytics{% endblock %}
{% block css %}
<link href="{% static 'plugins/datatables.net-bs5/css/dataTables.bootstrap5.min.css' %}" rel="stylesheet" />
<link href="{% static 'plugins/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css' %}" rel="stylesheet" />
{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'analytics:dashboard' %}">Analytics</a></li>
<li class="breadcrumb-item active">Reports</li>
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
Analytics Reports
<small>Report Management & Generation</small>
</h1>
<!-- END page-header -->
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Report Management</h4>
<div class="panel-heading-btn">
<a href="{% url 'analytics:report_create' %}" class="btn btn-xs btn-success me-2">
<i class="fa fa-plus"></i> Create Report
</a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-reload"><i class="fa fa-redo"></i></a>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-collapse"><i class="fa fa-minus"></i></a>
</div>
</div>
<div class="panel-body">
<!-- Filters and Search -->
<div class="row mb-3">
<div class="col-md-4">
<label class="form-label">Search Reports</label>
<div class="input-group">
<input type="text" class="form-control" id="search-input" placeholder="Report name, description...">
<button class="btn btn-outline-secondary" type="button" id="search-btn">
<i class="fa fa-search"></i>
</button>
</div>
</div>
<div class="col-md-3">
<label class="form-label">Category</label>
<select class="form-select" id="category-filter">
<option value="">All Categories</option>
<option value="FINANCIAL">Financial</option>
<option value="CLINICAL">Clinical</option>
<option value="OPERATIONAL">Operational</option>
<option value="QUALITY">Quality</option>
<option value="COMPLIANCE">Compliance</option>
<option value="CUSTOM">Custom</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label">Status</label>
<select class="form-select" id="status-filter">
<option value="">All Status</option>
<option value="ACTIVE">Active</option>
<option value="DRAFT">Draft</option>
<option value="ARCHIVED">Archived</option>
</select>
</div>
<div class="col-md-2">
<label class="form-label">Type</label>
<select class="form-select" id="type-filter">
<option value="">All Types</option>
<option value="SCHEDULED">Scheduled</option>
<option value="ON_DEMAND">On Demand</option>
<option value="REAL_TIME">Real Time</option>
</select>
</div>
</div>
<!-- Quick Stats -->
<div class="row mb-4">
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 bg-primary text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-fill">
<div class="fs-10px text-white-transparent-5 mb-1">TOTAL REPORTS</div>
<div class="fs-18px fw-900 text-white" id="total-reports">-</div>
</div>
<div class="w-50px h-50px bg-white-transparent-2 rounded-circle d-flex align-items-center justify-content-center">
<i class="fa fa-chart-bar fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 bg-success text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-fill">
<div class="fs-10px text-white-transparent-5 mb-1">ACTIVE REPORTS</div>
<div class="fs-18px fw-900 text-white" id="active-reports">-</div>
</div>
<div class="w-50px h-50px bg-white-transparent-2 rounded-circle d-flex align-items-center justify-content-center">
<i class="fa fa-play fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 bg-warning text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-fill">
<div class="fs-10px text-white-transparent-5 mb-1">SCHEDULED</div>
<div class="fs-18px fw-900 text-white" id="scheduled-reports">-</div>
</div>
<div class="w-50px h-50px bg-white-transparent-2 rounded-circle d-flex align-items-center justify-content-center">
<i class="fa fa-clock fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-md-6 mb-3">
<div class="card border-0 bg-info text-white">
<div class="card-body">
<div class="d-flex align-items-center">
<div class="flex-fill">
<div class="fs-10px text-white-transparent-5 mb-1">GENERATED TODAY</div>
<div class="fs-18px fw-900 text-white" id="generated-today">-</div>
</div>
<div class="w-50px h-50px bg-white-transparent-2 rounded-circle d-flex align-items-center justify-content-center">
<i class="fa fa-file-alt fa-lg text-white"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="d-flex justify-content-between align-items-center mb-3">
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary" id="bulk-actions-btn" disabled>
<i class="fa fa-tasks me-2"></i>Bulk Actions
</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown" id="bulk-dropdown" disabled>
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="bulkGenerate()">
<i class="fa fa-play me-2"></i>Generate Selected
</a></li>
<li><a class="dropdown-item" href="#" onclick="bulkSchedule()">
<i class="fa fa-clock me-2"></i>Schedule Selected
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" onclick="bulkExport()">
<i class="fa fa-download me-2"></i>Export Selected
</a></li>
<li><a class="dropdown-item text-danger" href="#" onclick="bulkArchive()">
<i class="fa fa-archive me-2"></i>Archive Selected
</a></li>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-secondary" onclick="refreshTable()">
<i class="fa fa-refresh me-2"></i>Refresh
</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fa fa-download me-2"></i>Export
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="exportData('csv')">
<i class="fa fa-file-csv me-2"></i>Export as CSV
</a></li>
<li><a class="dropdown-item" href="#" onclick="exportData('excel')">
<i class="fa fa-file-excel me-2"></i>Export as Excel
</a></li>
</ul>
</div>
</div>
<!-- Reports Table -->
<div class="table-responsive">
<table id="reports-table" class="table table-striped table-bordered align-middle">
<thead>
<tr>
<th width="30">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="select-all">
</div>
</th>
<th>Report Name</th>
<th>Category</th>
<th>Type</th>
<th>Status</th>
<th>Last Generated</th>
<th>Next Run</th>
<th>Created By</th>
<th width="120">Actions</th>
</tr>
</thead>
<tbody>
<!-- Data will be loaded via AJAX -->
</tbody>
</table>
</div>
</div>
</div>
<!-- END panel -->
{% endblock %}
{% block js %}
<script src="{% static 'plugins/datatables.net/js/dataTables.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-bs5/js/dataTables.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive/js/dataTables.responsive.min.js' %}"></script>
<script src="{% static 'plugins/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js' %}"></script>
<script src="{% static 'plugins/moment/min/moment.min.js' %}"></script>
<script>
$(document).ready(function() {
var table;
// Initialize DataTable
table = $('#reports-table').DataTable({
processing: true,
serverSide: false,
ajax: {
url: '{% url "analytics:report_list_data" %}',
data: function(d) {
d.search_value = $('#search-input').val();
d.category = $('#category-filter').val();
d.status = $('#status-filter').val();
d.type = $('#type-filter').val();
}
},
columns: [
{
data: 'id',
orderable: false,
render: function(data, type, row) {
return '<div class="form-check"><input class="form-check-input report-checkbox" type="checkbox" value="' + data + '"></div>';
}
},
{
data: 'name',
render: function(data, type, row) {
return '<div>' +
'<div class="fw-bold">' + data + '</div>' +
(row.description ? '<div class="text-muted small">' + row.description + '</div>' : '') +
'</div>';
}
},
{
data: 'category',
render: function(data, type, row) {
var colors = {
'FINANCIAL': 'success',
'CLINICAL': 'primary',
'OPERATIONAL': 'info',
'QUALITY': 'warning',
'COMPLIANCE': 'danger',
'CUSTOM': 'secondary'
};
return '<span class="badge bg-' + (colors[data] || 'secondary') + '">' + row.category_display + '</span>';
}
},
{
data: 'type',
render: function(data, type, row) {
var icons = {
'SCHEDULED': 'clock',
'ON_DEMAND': 'play',
'REAL_TIME': 'bolt'
};
return '<i class="fa fa-' + (icons[data] || 'file') + ' me-2"></i>' + row.type_display;
}
},
{
data: 'status',
render: function(data, type, row) {
var colors = {
'ACTIVE': 'success',
'DRAFT': 'warning',
'ARCHIVED': 'secondary'
};
return '<span class="badge bg-' + (colors[data] || 'secondary') + '">' + row.status_display + '</span>';
}
},
{
data: 'last_generated',
render: function(data, type, row) {
if (data) {
return moment(data).format('MMM DD, YYYY HH:mm');
} else {
return '<span class="text-muted">Never</span>';
}
}
},
{
data: 'next_run',
render: function(data, type, row) {
if (data) {
return moment(data).format('MMM DD, YYYY HH:mm');
} else {
return '<span class="text-muted">Not scheduled</span>';
}
}
},
{
data: 'created_by',
render: function(data, type, row) {
return data ? data.full_name : '<span class="text-muted">System</span>';
}
},
{
data: 'id',
orderable: false,
render: function(data, type, row) {
var actions = '<div class="btn-group btn-group-sm">';
actions += '<button class="btn btn-outline-primary" onclick="viewReport(' + data + ')" title="View">';
actions += '<i class="fa fa-eye"></i></button>';
actions += '<button class="btn btn-outline-success" onclick="generateReport(' + data + ')" title="Generate">';
actions += '<i class="fa fa-play"></i></button>';
actions += '<button class="btn btn-outline-secondary" onclick="editReport(' + data + ')" title="Edit">';
actions += '<i class="fa fa-edit"></i></button>';
actions += '</div>';
console.log(data)
return actions;
}
}
],
order: [[5, 'desc']],
pageLength: 25,
responsive: true,
language: {
processing: '<div class="d-flex justify-content-center"><div class="spinner-border" role="status"></div></div>'
}
});
// Load stats
loadStats();
// Filter event handlers
$('#search-input, #category-filter, #status-filter, #type-filter').on('change keyup', function() {
table.draw();
});
// Select all checkbox
$('#select-all').on('change', function() {
$('.report-checkbox').prop('checked', this.checked);
updateBulkActions();
});
// Individual checkbox change
$(document).on('change', '.report-checkbox', function() {
updateBulkActions();
});
// Auto-refresh every 5 minutes
setInterval(function() {
table.ajax.reload(null, false);
loadStats();
}, 300000);
});
function loadStats() {
$.ajax({
url: '{% url "analytics:analytics_stats" %}',
success: function(data) {
$('#total-reports').text(data.total_reports);
$('#active-reports').text(data.active_reports);
$('#scheduled-reports').text(data.scheduled_reports);
$('#generated-today').text(data.generated_today);
}
});
}
function updateBulkActions() {
var checkedCount = $('.report-checkbox:checked').length;
$('#bulk-actions-btn, #bulk-dropdown').prop('disabled', checkedCount === 0);
}
function viewReport(reportId) {
const urlTemplate = "{% url 'analytics:report_detail' 0 %}";
window.location.href = urlTemplate.replace('0', reportId);
}
function editReport(reportId) {
window.location.href = '{% url "analytics:report_update" 0 %}'.replace('0', reportId);
}
{#function generateReport(reportId) {#}
{# if (confirm('Generate this report now?')) {#}
{# $.ajax({#}
{# url: '{% url "analytics:report_generate" 0 %}'.replace('0', reportId),#}
{# method: 'POST',#}
{# data: {#}
{# 'csrfmiddlewaretoken': '{{ csrf_token }}'#}
{# },#}
{# success: function(response) {#}
{# if (response.success) {#}
{# toastr.success('Report generation started');#}
{# $('#reports-table').DataTable().ajax.reload();#}
{# } else {#}
{# toastr.error('Failed to generate report');#}
{# }#}
{# },#}
{# error: function() {#}
{# toastr.error('An error occurred while generating the report');#}
{# }#}
{# });#}
{# }#}
{# }#}
{#function bulkGenerate() {#}
{# var selectedIds = $('.report-checkbox:checked').map(function() {#}
{# return this.value;#}
{# }).get();#}
{# #}
{# if (selectedIds.length === 0) {#}
{# toastr.warning('Please select reports to generate');#}
{# return;#}
{# }#}
{# #}
{# if (confirm('Generate ' + selectedIds.length + ' selected report(s)?')) {#}
{# $.ajax({#}
{# url: '{% url "analytics:report_bulk_generate" %}',#}
{# method: 'POST',#}
{# data: {#}
{# 'report_ids': selectedIds,#}
{# 'csrfmiddlewaretoken': '{{ csrf_token }}'#}
{# },#}
{# success: function(response) {#}
{# if (response.success) {#}
{# toastr.success(response.message);#}
{# $('#reports-table').DataTable().ajax.reload();#}
{# $('#select-all').prop('checked', false);#}
{# updateBulkActions();#}
{# } else {#}
{# toastr.error('Failed to generate reports');#}
{# }#}
{# },#}
{# error: function() {#}
{# toastr.error('An error occurred during bulk generation');#}
{# }#}
{# });#}
{# }#}
{# }#}
function bulkSchedule() {
var selectedIds = $('.report-checkbox:checked').map(function() {
return this.value;
}).get();
if (selectedIds.length === 0) {
toastr.warning('Please select reports to schedule');
return;
}
// Implementation for bulk scheduling
toastr.info('Bulk scheduling functionality will be implemented');
}
{#function bulkExport() {#}
{# var selectedIds = $('.report-checkbox:checked').map(function() {#}
{# return this.value;#}
{# }).get();#}
{# #}
{# if (selectedIds.length === 0) {#}
{# toastr.warning('Please select reports to export');#}
{# return;#}
{# }#}
{# #}
{# window.location.href = '{% url "analytics:report_export" %}?ids=' + selectedIds.join(',');#}
{# }#}
{#function bulkArchive() {#}
{# var selectedIds = $('.report-checkbox:checked').map(function() {#}
{# return this.value;#}
{# }).get();#}
{# #}
{# if (selectedIds.length === 0) {#}
{# toastr.warning('Please select reports to archive');#}
{# return;#}
{# }#}
{# #}
{# if (confirm('Archive ' + selectedIds.length + ' selected report(s)?')) {#}
{# $.ajax({#}
{# url: '{% url "analytics:report_bulk_archive" %}',#}
{# method: 'POST',#}
{# data: {#}
{# 'report_ids': selectedIds,#}
{# 'csrfmiddlewaretoken': '{{ csrf_token }}'#}
{# },#}
{# success: function(response) {#}
{# if (response.success) {#}
{# toastr.success(response.message);#}
{# $('#reports-table').DataTable().ajax.reload();#}
{# $('#select-all').prop('checked', false);#}
{# updateBulkActions();#}
{# } else {#}
{# toastr.error('Failed to archive reports');#}
{# }#}
{# },#}
{# error: function() {#}
{# toastr.error('An error occurred during bulk archiving');#}
{# }#}
{# });#}
{# }#}
{# }#}
{#function exportData(format) {#}
{# window.location.href = '{% url "analytics:report_export" %}?format=' + format;#}
{# }#}
function refreshTable() {
$('#reports-table').DataTable().ajax.reload();
loadStats();
toastr.info('Table refreshed');
}
</script>
{% endblock %}