Created
December 7, 2023 18:06
-
-
Save RyanJulyan/1d8cee2c8d5a0660cad64b3be60041e7 to your computer and use it in GitHub Desktop.
Gantt Chart CRUD page leveraging frappe-gantt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Gantt Chart</title> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/frappe-gantt/0.6.1/frappe-gantt.min.css" integrity="sha512-b6CPl1eORfMoZgwWGEYWNxYv79KG0dALXfVu4uReZJOXAfkINSK4UhA0ELwGcBBY7VJN7sykwrCGQnbS8qTKhQ==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/frappe-gantt/0.6.1/frappe-gantt.min.js" integrity="sha512-HyGTvFEibBWxuZkDsE2wmy0VQ0JRirYgGieHp0pUmmwyrcFkAbn55kZrSXzCgKga04SIti5jZQVjbTSzFpzMlg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> | |
<style> | |
.details-container{ | |
min-width: 200px; | |
padding: 5px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Gantt Chart CRUD</h1> | |
<form id="task-form"> | |
<input type="text" id="task-id" placeholder="Task ID" required> | |
<br/> | |
<input type="text" id="task-name" placeholder="Task Name" required> | |
<br/> | |
<input type="date" id="task-start" placeholder="Start Date" required> | |
<br/> | |
<input type="date" id="task-end" placeholder="End Date" required> | |
<br/> | |
<input type="number" id="task-progress" placeholder="Progress" required> | |
<br/> | |
<input type="text" id="task-dependencies" placeholder="Dependencies (comma-separated IDs)"> | |
<br/> | |
<button type="submit">Add Task</button> | |
</form> | |
<div id="gantt"></div> | |
<script> | |
// Our data model | |
let tasks = JSON.parse(localStorage.getItem('tasks')) || []; | |
// Create a task | |
function createTask(task) { | |
if (!task.id || !task.name || !task.start || !task.end || typeof task.progress === 'undefined') { | |
console.error('All task properties (id, name, start, end, progress) must be defined'); | |
return; | |
} | |
// Convert the task ID to a string | |
task.id = String(task.id); | |
// Convert the dependencies to a string | |
if (task.dependencies) { | |
task.dependencies = task.dependencies.map(String).join(','); | |
} | |
tasks.push(task); | |
localStorage.setItem('tasks', JSON.stringify(tasks)); | |
updateGanttChart(); | |
} | |
// Read a task | |
function readTask(index) { | |
return tasks[index]; | |
} | |
// Update a task | |
function updateTask(index, updatedTask) { | |
if (!updatedTask.id || !updatedTask.name || !updatedTask.start || !updatedTask.end || typeof updatedTask.progress === 'undefined') { | |
console.error('All task properties (id, name, start, end, progress) must be defined'); | |
return; | |
} | |
// Convert the task ID to a string | |
updatedTask.id = String(updatedTask.id); | |
// Convert the dependencies to a string | |
if (updatedTask.dependencies) { | |
updatedTask.dependencies = updatedTask.dependencies.map(String).join(','); | |
} | |
tasks[index] = updatedTask; | |
localStorage.setItem('tasks', JSON.stringify(tasks)); | |
updateGanttChart(); | |
} | |
// Delete a task | |
function deleteTask(index) { | |
tasks.splice(index, 1); | |
localStorage.setItem('tasks', JSON.stringify(tasks)); | |
updateGanttChart(); | |
} | |
// Export tasks to JSON | |
function exportTasksToJSON() { | |
return JSON.stringify(tasks); | |
} | |
// Update the Gantt chart with the current tasks | |
function updateGanttChart() { | |
// Clear the SVG element | |
document.querySelector('#gantt').innerHTML = ''; | |
let gantt = new Gantt("#gantt", tasks, { | |
on_click: function (task) { | |
// Do nothing on click, we'll handle updates in the popup | |
}, | |
custom_popup_html: function(task) { | |
// Create a form in the popup for updating the task | |
return ` | |
<div class="details-container"> | |
<h4>Task ID: ${task.id}</h4> | |
<form id="popup-form" onsubmit="event.preventDefault(); updateTaskFromPopup(${task.id});" oninput="x.value=parseInt(progress.value)"> | |
<label for="name">Name:</label> | |
<br/> | |
<input type="text" id="name" name="name" value="${task.name}" style="width: 96%"> | |
<br/> | |
<label for="start">Start Date:</label> | |
<br/> | |
<input type="date" id="start" name="start" value="${task.start}" style="width: 96%"> | |
<br/> | |
<label for="end">End Date:</label> | |
<br/> | |
<input type="date" id="end" name="end" value="${task.end}" style="width: 96%"> | |
<br/> | |
<label for="progress">Progress: <output name="x" for="progress">${task.progress}</output>%</label> | |
<br/> | |
<input type="range" id="progress" min="1" max="100" value="${task.progress}" class="slider" style="width: 96%" > | |
<br/> | |
<br/> | |
<button type="submit" style="width: 100%">Update</button> | |
<br/> | |
<br/> | |
</form> | |
</div> | |
`; | |
}, | |
on_date_change: function(task, start, end) { | |
console.log(task, start, end); | |
// Update the task in the data model | |
let index = tasks.findIndex(t => t.id === task.id); | |
if (index > -1) { | |
tasks[index].start = start; | |
tasks[index].end = end; | |
localStorage.setItem('tasks', JSON.stringify(tasks)); | |
} | |
}, | |
on_progress_change: function(task, progress) { | |
console.log(task, progress); | |
// Update the task in the data model | |
let index = tasks.findIndex(t => t.id === task.id); | |
if (index > -1) { | |
tasks[index].progress = progress; | |
localStorage.setItem('tasks', JSON.stringify(tasks)); | |
} | |
}, | |
on_view_change: function(mode) { | |
console.log(mode); | |
}, | |
}); | |
gantt.change_view_mode('Day') // Quarter Day, Half Day, Day, Week, Month | |
} | |
function updateTaskFromPopup(taskId) { | |
// Get the form data | |
let name = document.getElementById('name').value; | |
let start = document.getElementById('start').value; | |
let end = document.getElementById('end').value; | |
let progress = document.getElementById('progress').value; | |
// Update the task | |
let index = tasks.findIndex(t => t.id === String(taskId)); | |
if (index > -1) { | |
updateTask(index, { | |
id: taskId, | |
name: name, | |
start: start, | |
end: end, | |
progress: parseInt(progress, 10), | |
dependencies: tasks[index].dependencies | |
}); | |
} | |
} | |
// // Let's create, read, update, and delete some tasks | |
// createTask({ id: 1, name: 'Task 1', start: '2023-06-24', end: '2023-06-30', progress: 0 }); | |
// console.log(readTask(0)); // { id: 1, name: 'Task 1', start: '2023-06-24', end: '2023-06-30' } | |
// updateTask(0, { id: 1, name: 'Updated Task 1', start: '2023-06-24', end: '2023-06-30', progress: 10 }); | |
// console.log(readTask(0)); // { id: 1, name: 'Updated Task 1', start: '2023-06-24', end: '2023-06-30' } | |
// // deleteTask(0); | |
// console.log(tasks); // [] | |
// // Let's create some tasks and export them to JSON | |
// createTask({ id: 2, name: 'Task 2', start: '2023-06-24', end: '2023-06-30', progress: 0, dependencies: [1] }); | |
// createTask({ id: 3, name: 'Task 3', start: '2023-07-01', end: '2023-07-07', progress: 0 }); | |
// console.log(exportTasksToJSON()); // [{"id":1,"name":"Task 1","start":"2023-06-24","end":"2023-06-30"},{"id":2,"name":"Task 2","start":"2023-07-01","end":"2023-07-07"}] | |
// // Initialize the Gantt chart | |
updateGanttChart(); | |
document.getElementById('task-form').addEventListener('submit', function(event) { | |
event.preventDefault(); | |
// Get the task details from the form | |
let id = document.getElementById('task-id').value; | |
let name = document.getElementById('task-name').value; | |
let start = document.getElementById('task-start').value; | |
let end = document.getElementById('task-end').value; | |
let progress = document.getElementById('task-progress').value; | |
let dependencies = document.getElementById('task-dependencies').value; | |
// Create the task | |
createTask({ | |
id: id, | |
name: name, | |
start: start, | |
end: end, | |
progress: parseInt(progress, 10), | |
dependencies: dependencies ? dependencies.split(',').map(String) : [] | |
}); | |
// Clear the form | |
document.getElementById('task-form').reset(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment