Sample Project
The sample project includes:
- DayPilot Lite 3.2.247
- C# Source Code
- VB.NET Source Code
- Visual Studio 2010/Visual Studio 2012 Solution
- SQL Server database
Online Demo
Requirements
- .NET Framework 4.0 or higher
- Visual Studio 2010/Visual Studio 2012
- Microsoft SQL Server 2008+ (Express)/ Microsoft SQL Server 2012 + (LocalCB)
License
The source code of this sample project is licensed under the Apache Software License 2.0.
Features
This sample project management ASP.NET application allows to create fast project time to completion estimate. It displays a project overview using a Gantt chart. Resource schedule and availability is displayed in a Resources view.
See also related tutorials on Gantt chart:
- Basic ASP.NET Gantt Chart Tutorial (Open-Source)
- Advanced ASP.NET Gantt Chart - Project Management Tutorial (DayPilot Pro)
This project uses the basic Gantt chart from DayPilot Lite (open-source).
Features:
- Visual project management
- Plan overview in a Gantt chart
- Multiple projects supported
- Resource utilization/availability
- Task tracking in real time
- Task status (planned, started, finished)
- Setting task priority using drag&drop
- Estimated time to completion
Advanced Gantt Chart Control
More advanced features can be found in the ASP.NET Gantt Chart control in DayPilot Pro (commercial):
See also the DayPilot Pro Gantt Chart tutorial:
Gantt Chart (Tasks)
The main view is based on DayPilot Scheduler Lite in Gantt mode.
Task Header
The task header is customized using BeforeResHeaderRender event:
- Status-indicating icon (blue/green/orange)
- Additional column data (estimated, spent, resource)
protected void DayPilotScheduler1_BeforeResHeaderRender(object sender, BeforeHeaderRenderEventArgs e) { DataItemWrapper task = e.DataItem; string name = (string)task["AssignmentNote"]; int id = Convert.ToInt32(task["AssignmentId"]); string resource = Convert.ToString(task["ResourceName"]); string status = Convert.ToString(task["AssignmentStatus"]); TimeSpan duration = TimeSpan.FromMinutes(Convert.ToInt32(task["AssignmentDuration"])); string durationString = duration.ToHourMinuteString(); string spentString = Binder.Get(task, "AssignmentDurationReal").IsNotNull ? Binder.Get(task, "AssignmentDurationReal").TimeSpanFromMinutes.ToHourMinuteString() : String.Empty; e.InnerHTML = TaskLink(name, id, status); e.Columns[0].InnerHTML = "<div style='text-align:right'>" + durationString + "</div>"; e.Columns[1].InnerHTML = "<div style='text-align:right'>" + spentString + "</div>"; e.Columns[2].InnerHTML = resource; }
Timeline and Time to Completion (TTC) Calculation
Calculation is done using Plan class:
DataTable table = new DataManager().GetAssignmentsPlanned(ProjectId); _plan = new Plan(); _plan.LoadTasks(table.Rows, "AssignmentId", "AssignmentDuration", "ResourceId"); _plan.Process();
The Plan class arranges the tasks into groups by resource and arranges them into a timeline. It takes the business hours (8-17) and weekends (Saturday, Sunday) into account.
All events are added to a single List.
private List<Task> Data { get { List<Task> all = new List<Task>(); if (!CheckBoxHideFinished.Checked) { all.AddRange(Finished); } all.AddRange(Started); all.AddRange(Plan.Processed); return all; } }
The resulting List is passed to DayPilot Scheduler (DataSource property) to be displayed in the Gantt chart:
private void LoadEvents() { DayPilotScheduler1.DataSource = Data; DataBind(); }
Task Reordering (Drag & Drop)
The task start dates are not fixed. Instead, a dynamic schedule is calculated and updated every time you display the Gantt chart.
You can set the priorities by dragging the planned (blue) tasks up or down.
The drag&drop reordering is implemented using jQuery:
function init() { $(document).ready(function () { $(".task_status.planned") .css("cursor", "move") .attr('unselectable', 'on') .css('user-select', 'none') .css('-webkit-user-select', 'none') .css('-moz-user-select', 'none') .each(function () { this.onselectstart = function (e) { if (e && e.preventDefault) e.preventDefault(); return false; }; }); $(".task_status.planned").mousedown(function (e) { var id = $(this).data("taskid"); drag.active = true; drag.id = id; drag.start = DayPilot.mo3($("#dps")[0], e.originalEvent); drag.source = $(this); var div = document.createElement("div"); div.style.position = "absolute"; div.style.height = "2px"; div.style.width = "60px"; div.style.backgroundColor = "red"; div.style.display = "none"; div.style.userSelect = "none"; div.style.webkitUserSelect = "none"; div.style.MozUserSelect = "none"; div.setAttribute("unselectable", "on"); $("#dps")[0].appendChild(div); $(document.body).addClass("moving"); drag.div = div; }); $(document).mousemove(function (e) { if (!drag.active) { return; } drag.source.parent().css({ opacity: 0.5 }); var rowHeight = 20; var headerHeight = 20; var coords = DayPilot.mo3($("#dps")[0], e.originalEvent); drag.position = Math.floor((coords.y - headerHeight) / rowHeight); drag.position = Math.max(0, drag.position); var offset = {}; offset.top = 0; offset.left = 0; drag.div.style.top = (offset.top + rowHeight * drag.position + headerHeight) + "px"; drag.div.style.left = offset.left + "px"; drag.div.style.display = ""; }); $(document).mouseup(function () { if (!drag.active) { return; } if (drag.div && drag.div.parentNode) { drag.div.parentNode.removeChild(drag.div); } $(document.body).removeClass("moving"); var order = []; var placed = false; $(".task_status").each(function (index) { if (!$(this).hasClass("planned")) { return; } var id = $(this).data("taskid"); //alert("id:" + id); if (index == drag.position) { order.push(drag.id); placed = true; } if (id == drag.id) { return; } order.push(id); }); if (!placed) { order.push(drag.id); } //alert("new order:" + order.join(",")); updateOrder(order.join(',')); drag = {}; }); }); }
Adding New Tasks
The new task popup is displayed using DayPilot.Modal dialog (open-source).
<div class="space"> <a href="javascript:create('<%# DateTime.Today.ToString("s") %>')" class="button">New task</a> </div>
JavaScript:
function create(start, end, resource) { createModal().showUrl(id.root + 'Project/New.aspx/' + id.project + '?start=' + start + "&end=" + end + "&resource=" + resource); } function edit(taskId) { createModal().setHeight(300).showUrl(id.root + 'Project/Edit.aspx/' + id.project + '?id=' + taskId); } function createModal() { var modal = new DayPilot.Modal(); modal.top = 60; modal.width = 300; modal.opacity = 50; modal.border = "10px solid #d0d0d0"; modal.closed = function () { if (this.result && this.result.refresh) { __doPostBack(id.refreshButton, ''); } }; modal.setHeight = function (height) { modal.height = height; return modal; }; modal.height = 260; modal.zIndex = 100; return modal; }
Task Status
The task status can be set to one of the following values:
- planned
- started
- finished
The time spent can be updated manually at any time.
If you don't specify the time spent on the task, it will be calculated automatically when the status is set to finished:
- If the task was started manually it will use the real time between start and finish.
- If the previous status was "planned" it will use the estimated time.
Planned Task
Started Task
Note the time summary below the form.
Finished Task
Note the start and end time of the task.
Resources View
You can also define a set of resources (people) and assign them to the tasks. The resources can be arranged in groups.
The resources view will display the schedule for each of the resource.
private void CreateResources() { DayPilotScheduler1.Resources.Clear(); AddDefaultGroup(); foreach (DataRow dr in Groups.Rows) { string name = (string) dr["GroupName"]; int id = Convert.ToInt32(dr["GroupId"]); string html = table(name, 0); DayPilotScheduler1.Resources.Add(new Resource(html, "GROUP")); AddChildren(id); } }
See Also
- ASP.NET MVC 5 Gantt Chart Tutorial (DayPilot Pro)