diff --git a/resources/js/pages/dashboards/gantt.vue b/resources/js/pages/dashboards/gantt.vue index c2930ec..2578c22 100644 --- a/resources/js/pages/dashboards/gantt.vue +++ b/resources/js/pages/dashboards/gantt.vue @@ -6,12 +6,23 @@ export default { name: 'GanttChart', data() { return { + showDeleteModal: false, + showEditModal: false, + showAddModal: false, + currentTaskId: null, + currentTask: null, + taskForm: { + text: '', + start_date: '', + duration: 3, + progress: 0 + }, tasks: { data: [ { id: 1, text: "Office Itinerary", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 17, progress: 0.95, open: true @@ -19,7 +30,7 @@ export default { { id: 11, text: "Office facing", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 5, parent: 1, progress: 1 @@ -27,7 +38,7 @@ export default { { id: 111, text: "Interior office", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 3, parent: 11, progress: 1 @@ -35,7 +46,7 @@ export default { { id: 112, text: "Air conditioner check", - start_date: "05-04-2023", + start_date: "05-08-2025", duration: 2, parent: 11, progress: 1 @@ -43,7 +54,7 @@ export default { { id: 12, text: "Furniture installation", - start_date: "08-04-2023", + start_date: "08-08-2025", duration: 2, parent: 1, progress: 1 @@ -51,7 +62,7 @@ export default { { id: 13, text: "Employee relocation", - start_date: "10-04-2023", + start_date: "10-08-2025", duration: 8, parent: 1, progress: 0.67, @@ -60,7 +71,7 @@ export default { { id: 131, text: "Preparing workplaces", - start_date: "10-04-2023", + start_date: "10-08-2025", duration: 3, parent: 13, progress: 1 @@ -68,7 +79,7 @@ export default { { id: 132, text: "Workplaces importation", - start_date: "13-04-2023", + start_date: "13-08-2025", duration: 3, parent: 13, progress: 1 @@ -76,7 +87,7 @@ export default { { id: 133, text: "Workplaces exportation", - start_date: "16-04-2023", + start_date: "16-08-2025", duration: 2, parent: 13, progress: 0 @@ -84,7 +95,7 @@ export default { { id: 2, text: "Product launch", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 18, progress: 0.73, open: true @@ -92,7 +103,7 @@ export default { { id: 21, text: "Perform initial testing", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 5, parent: 2, progress: 1 @@ -100,7 +111,7 @@ export default { { id: 22, text: "Development", - start_date: "03-04-2023", + start_date: "03-08-2025", duration: 16, parent: 2, progress: 0.68, @@ -109,7 +120,7 @@ export default { { id: 221, text: "Develop System", - start_date: "03-04-2023", + start_date: "03-08-2025", duration: 5, parent: 22, progress: 1 @@ -117,7 +128,7 @@ export default { { id: 222, text: "Beta Release", - start_date: "08-04-2023", + start_date: "08-08-2025", duration: 1, parent: 22, progress: 1 @@ -125,7 +136,7 @@ export default { { id: 223, text: "Integrate System", - start_date: "09-04-2023", + start_date: "09-08-2025", duration: 4, parent: 22, progress: 1 @@ -133,7 +144,7 @@ export default { { id: 224, text: "Test", - start_date: "13-04-2023", + start_date: "13-08-2025", duration: 3, parent: 22, progress: 0.67 @@ -141,7 +152,7 @@ export default { { id: 225, text: "Marketing", - start_date: "16-04-2023", + start_date: "16-08-2025", duration: 3, parent: 22, progress: 0 @@ -149,7 +160,7 @@ export default { { id: 23, text: "Analysis", - start_date: "01-04-2023", + start_date: "01-08-2025", duration: 4, parent: 2, progress: 1 @@ -157,7 +168,7 @@ export default { { id: 24, text: "Design", - start_date: "06-04-2023", + start_date: "06-08-2025", duration: 6, parent: 2, progress: 0.75, @@ -166,7 +177,7 @@ export default { { id: 241, text: "Design database", - start_date: "06-04-2023", + start_date: "06-08-2025", duration: 4, parent: 24, progress: 1 @@ -174,7 +185,7 @@ export default { { id: 242, text: "Software design", - start_date: "10-04-2023", + start_date: "10-08-2025", duration: 2, parent: 24, progress: 0.5 @@ -207,6 +218,10 @@ export default { methods: { initGantt() { gantt.config.date_format = "%d-%m-%Y" + gantt.config.fit_tasks = true + gantt.config.start_date = null + gantt.config.end_date = null + gantt.config.columns = [ { name: "wbs", label: "WBS", width: 50, align: "center" }, { name: "text", label: "TASK NAME", width: 250, tree: true }, @@ -220,7 +235,7 @@ export default { gantt.config.row_height = 40 gantt.config.bar_height = 24 gantt.config.grid_width = 450 - + gantt.config.subscales = [ { unit: "month", step: 1, date: "%M %Y" }, { unit: "day", step: 1, date: "%j" } @@ -233,23 +248,19 @@ export default { gantt.config.details_on_create = true gantt.config.details_on_dblclick = true - gantt.templates.task_class = function(start, end, task) { + gantt.templates.task_class = function (start, end, task) { if (task.progress === 1) return "completed-task" if (task.progress >= 0.75) return "high-progress-task" if (task.progress >= 0.25) return "medium-progress-task" return "low-progress-task" } - gantt.templates.grid_row_class = function(start, end, task) { + gantt.templates.grid_row_class = function (start, end, task) { if (task.$level === 0) return "summary-row" return "" } - gantt.templates.leftside_text = function(start, end, task) { - return "" - } - - gantt.templates.rightside_text = function(start, end, task) { + gantt.templates.rightside_text = function (start, end, task) { if (task.progress === 1) { return "✓" } @@ -257,12 +268,7 @@ export default { } let taskCounter = 1 - gantt.templates.grid_row_class = function(start, end, task) { - if (task.$level === 0) return "summary-row" - return "" - } - - gantt.templates.grid_cell_value = function(item, column) { + gantt.templates.grid_cell_value = function (item, column) { if (column === "wbs") { if (item.$level === 0) { return taskCounter++ @@ -274,7 +280,6 @@ export default { return parent.$wbs + "." + childIndex } else if (item.$level === 2) { let parentIndex = gantt.getParent(item.id) - let grandParentIndex = gantt.getParent(parentIndex) let parent = gantt.getTask(parentIndex) let siblings = gantt.getChildren(parentIndex) let childIndex = siblings.indexOf(item.id) + 1 @@ -284,7 +289,7 @@ export default { return gantt.templates.grid_cell_value_default(item, column) } - gantt.attachEvent("onTaskLoading", function(task) { + gantt.attachEvent("onTaskLoading", function (task) { if (task.$level === 0) { task.$wbs = taskCounter taskCounter++ @@ -303,58 +308,213 @@ export default { return true }) - gantt.attachEvent("onAfterTaskAdd", function(id, item) { - this.saveToServer() - }.bind(this)) - - gantt.attachEvent("onAfterTaskDelete", function(id, item) { - this.saveToServer() - }.bind(this)) - - gantt.attachEvent("onAfterTaskUpdate", function(id, item) { - this.saveToServer() - }.bind(this)) - - gantt.attachEvent("onAfterLinkAdd", function(id, item) { - this.saveToServer() - }.bind(this)) - - gantt.attachEvent("onAfterLinkDelete", function(id, item) { - this.saveToServer() + gantt.attachEvent("onContextMenu", function(taskId, linkId, e) { + if (taskId) { + this.showContextMenu(e, taskId) + return false + } + return true }.bind(this)) gantt.init(this.$refs.ganttContainer) gantt.parse(this.tasks) }, + showContextMenu(e, taskId) { + this.hideContextMenu() + + const contextMenu = document.createElement('div') + contextMenu.id = 'gantt-context-menu' + contextMenu.className = 'gantt-context-menu' + contextMenu.innerHTML = ` +
+ + + + + ` + + contextMenu.style.position = 'fixed' + contextMenu.style.left = e.clientX + 'px' + contextMenu.style.top = e.clientY + 'px' + contextMenu.style.zIndex = '9999' + + document.body.appendChild(contextMenu) + + document.addEventListener('click', this.hideContextMenu) + window.ganttComponent = this + }, + hideContextMenu() { + const existingMenu = document.getElementById('gantt-context-menu') + if (existingMenu) { + existingMenu.remove() + } + document.removeEventListener('click', this.hideContextMenu) + }, + addSubTask(parentId) { + this.currentTaskId = parentId + this.taskForm = { + text: 'New Sub Task', + start_date: new Date().toISOString().split('T')[0], + duration: 3, + progress: 0 + } + this.showAddModal = true + this.hideContextMenu() + }, + editTask(taskId) { + this.currentTaskId = taskId + const task = gantt.getTask(taskId) + this.currentTask = task + this.taskForm = { + text: task.text, + start_date: gantt.date.date_to_str("%Y-%m-%d")(task.start_date), + duration: task.duration, + progress: task.progress + } + this.showEditModal = true + this.hideContextMenu() + }, + deleteTaskFromContext(taskId) { + this.currentTaskId = taskId + this.currentTask = gantt.getTask(taskId) + this.showDeleteModal = true + this.hideContextMenu() + }, + markTaskComplete(taskId) { + let task = gantt.getTask(taskId) + task.progress = task.progress === 1 ? 0 : 1 + gantt.updateTask(taskId) + gantt.render() + this.hideContextMenu() + }, addTask() { const selectedId = gantt.getSelectedId() - const newTaskId = gantt.uid() - const today = new Date() - const formattedDate = gantt.date.date_to_str("%d-%m-%Y")(today) - - const newTask = { - id: newTaskId, - text: "New Task", - start_date: formattedDate, + this.currentTaskId = selectedId + this.taskForm = { + text: 'New Task', + start_date: new Date().toISOString().split('T')[0], duration: 3, - progress: 0, - parent: selectedId || 0 + progress: 0 } - - gantt.addTask(newTask, selectedId || "") - gantt.selectTask(newTaskId) - gantt.showTask(newTaskId) + this.showAddModal = true }, deleteTask() { const selectedTask = gantt.getSelectedId() if (selectedTask) { - if (confirm('Are you sure you want to delete this task?')) { - gantt.deleteTask(selectedTask) - } + this.currentTaskId = selectedTask + this.currentTask = gantt.getTask(selectedTask) + this.showDeleteModal = true } else { - alert('Please select a task to delete') + this.showNotification('Please select a task to delete', 'warning') } }, + confirmDelete() { + if (this.currentTaskId) { + gantt.deleteTask(this.currentTaskId) + this.showDeleteModal = false + this.currentTaskId = null + this.currentTask = null + this.showNotification('Task deleted successfully', 'success') + } + }, + saveTask() { + if (!this.taskForm.text.trim()) { + this.showNotification('Task name is required', 'error') + return + } + + const taskData = { + text: this.taskForm.text, + start_date: gantt.date.str_to_date("%Y-%m-%d")(this.taskForm.start_date), + duration: parseInt(this.taskForm.duration), + progress: parseFloat(this.taskForm.progress) + } + + if (this.showEditModal) { + Object.assign(this.currentTask, taskData) + gantt.updateTask(this.currentTaskId) + gantt.render() + this.showEditModal = false + this.showNotification('Task updated successfully', 'success') + } else if (this.showAddModal) { + const newTaskId = gantt.uid() + const newTask = { + id: newTaskId, + ...taskData + } + + if (this.currentTaskId) { + newTask.parent = this.currentTaskId + } + + gantt.addTask(newTask) + gantt.refreshData() + gantt.selectTask(newTaskId) + gantt.showTask(newTaskId) + this.showAddModal = false + this.showNotification('Task added successfully', 'success') + } + + this.resetForm() + }, + resetForm() { + this.currentTaskId = null + this.currentTask = null + this.taskForm = { + text: '', + start_date: '', + duration: 3, + progress: 0 + } + }, + closeModal() { + this.showDeleteModal = false + this.showEditModal = false + this.showAddModal = false + this.resetForm() + }, + showNotification(message, type = 'info') { + const notification = document.createElement('div') + notification.className = `notification notification-${type}` + notification.innerHTML = ` +