Files
project-managment/templates/components/gantt_chart.html
T
sankalp 71b700388b feat(templates): add polished login UI with Tailwind and Alpine.js
Enhances user experience with dark‑mode detection, responsive layout, and streamlined role selection workflow
2026-06-28 14:15:39 +05:45

220 lines
6.7 KiB
HTML

<!-- DHTMLX Gantt Assets & Styles -->
<link rel="stylesheet" href="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.css" type="text/css">
<style>
.gantt_task_line.overdue {
background-color: #ef4444 !important;
border-color: #dc2626 !important;
}
.gantt_task_progress.overdue {
background-color: #b91c1c !important;
}
.gantt_marker.today {
background-color: #EF4444 !important;
opacity: 0.8;
z-index: 9000;
}
.gantt_marker.today .gantt_marker_content {
background-color: #EF4444 !important;
color: white !important;
font-weight: bold;
font-size: 12px;
padding: 2px 6px;
border-radius: 4px;
white-space: nowrap;
}
.dark .gantt_container,
.dark .gantt_grid,
.dark .gantt_task,
.dark .gantt_task_bg {
background-color: #030712 !important;
}
.dark .gantt_grid_scale,
.dark .gantt_grid_head_cell {
background-color: #1f2937 !important;
color: #f3f4f6 !important;
border-color: #374151 !important;
}
.dark .gantt_cell,
.dark .gantt_grid_data .gantt_cell {
background-color: #030712 !important;
color: #e5e7eb !important;
border-color: #1f2937 !important;
}
.dark .gantt_row,
.dark .gantt_row.odd {
background-color: #030712 !important;
border-color: #1f2937 !important;
}
.dark .gantt_row:hover,
.dark .gantt_row.odd:hover {
background-color: #1f2937 !important;
}
.dark .gantt_task_cell {
border-color: #1f2937 !important;
}
.dark .gantt_scale_line,
.dark .gantt_scale_cell {
background-color: #1f2937 !important;
color: #f3f4f6 !important;
border-color: #374151 !important;
}
.dark .gantt_task_scale .gantt_scale_cell {
border-color: #374151 !important;
}
.dark .gantt_side_content {
color: #e5e7eb !important;
}
.dark .gantt_link_arrow {
border-color: #9ca3af !important;
}
.dark .gantt_link_line_wrapper .gantt_link_line {
background-color: #9ca3af !important;
}
.dark .gantt_grid_data .gantt_row {
border-bottom: 1px solid #1f2937 !important;
}
.dark .gantt_grid_data .gantt_cell {
border-right: 1px solid #1f2937 !important;
}
.dark .gantt_task_row {
background-color: #030712 !important;
border-bottom: 1px solid #1f2937 !important;
}
.dark .gantt_task_row.gantt_row_task:hover {
background-color: #1f2937 !important;
}
.dark .gantt_layout_cell::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.dark .gantt_layout_cell::-webkit-scrollbar-track {
background: #030712;
}
.dark .gantt_layout_cell::-webkit-scrollbar-thumb {
background: #374151;
border-radius: 4px;
}
.dark .gantt_layout_cell::-webkit-scrollbar-thumb:hover {
background: #6b7280;
}
</style>
<div id="{{ gantt_element_id|default:'gantt_here' }}" style="width:100%;height:{{ gantt_height|default:'600' }}px;min-height:{{ gantt_height|default:'600' }}px;">
<div class="flex items-center justify-center h-full text-gray-400 dark:text-gray-500">
<i class="fas fa-spinner fa-spin text-lg mr-2"></i> Loading timeline...
</div>
</div>
<script src="https://cdn.dhtmlx.com/gantt/edge/dhtmlxgantt.js"></script>
<script>
(function() {
const ganttData = {{ gantt_data|safe }};
const elementId = "{{ gantt_element_id|default:'gantt_here' }}";
const nameColumnLabel = "{{ name_column_label|default:'Name' }}";
function initGantt() {
if (typeof gantt === 'undefined' || !gantt.init) {
setTimeout(initGantt, 200);
return;
}
const container = document.getElementById(elementId);
if (!container || container.offsetParent === null) {
setTimeout(initGantt, 200);
return;
}
if (!ganttData.data || ganttData.data.length === 0) return;
try {
try { gantt.plugins({ marker: true }); } catch(e) {}
gantt.config.date_format = "%Y-%m-%d %H:%i";
gantt.config.xml_date = "%Y-%m-%d %H:%i";
{% if is_project_timeline %}
gantt.config.scales = [
{ unit: "year", step: 1, format: "%Y" },
{ unit: "month", step: 1, format: "%F" }
];
{% else %}
gantt.config.scales = [
{ unit: "month", step: 1, format: "%F %Y" },
{ unit: "day", step: 1, format: "%j" }
];
{% endif %}
gantt.config.readonly = true;
gantt.config.drag_move = false;
gantt.config.drag_resize = false;
gantt.config.drag_progress = false;
gantt.config.drag_links = false;
gantt.config.grid_width = 350;
gantt.config.row_height = 40;
gantt.config.task_height = 32;
gantt.config.bar_height = 24;
gantt.config.columns = [
{ name: "text", label: nameColumnLabel, width: 200, tree: true },
{ name: "status", label: "Status", width: 100, align: "center" },
{ name: "duration", label: "<span style='font-size:11px; letter-spacing:-0.5px;'>Duration</span>", width: 50, align: "center" }
];
gantt.templates.task_class = function(start, end, task) {
return task.is_overdue ? "overdue" : "";
};
gantt.templates.tooltip_text = function(start, end, task) {
return '<b>' + nameColumnLabel + ':</b> ' + task.text + '<br/>' +
'<b>Status:</b> ' + task.status + '<br/>' +
'<b>Duration:</b> ' + task.duration + ' day(s)<br/>' +
'<b>Progress:</b> ' + Math.round(task.progress * 100) + '%<br/>' +
'<b>Start:</b> ' + gantt.templates.tooltip_date_format(start) + '<br/>' +
'<b>End:</b> ' + gantt.templates.tooltip_date_format(end) +
(task.is_overdue ? '<br/><b style="color: #ef4444;">&#9888; OVERDUE</b>' : '');
};
gantt.init(elementId);
gantt.clearAll();
const processedData = {
data: ganttData.data.map(function(task) {
function convertDate(dateStr) {
if (!dateStr) return dateStr;
if (dateStr.indexOf('-') === 2) {
var parts = dateStr.split(' ');
var datePart = parts[0];
var timePart = parts[1] || '00:00';
var d = datePart.split('-');
return d[2] + '-' + d[1] + '-' + d[0] + ' ' + timePart;
}
return dateStr;
}
return Object.assign({}, task, {
start_date: convertDate(task.start_date),
end_date: convertDate(task.end_date)
});
}),
links: ganttData.links || []
};
gantt.parse(processedData);
if (typeof gantt.addMarker === 'function') {
gantt.addMarker({
start_date: new Date(),
css: "today",
text: "Today"
});
}
} catch(e) {
console.error('Gantt init error:', e);
}
}
if (document.readyState === 'complete') {
initGantt();
} else {
window.addEventListener('load', initGantt);
}
})();
</script>