Introduction
This control allows you to display and edit an agile release cycle. It has minimum of server-side logic and everything is implemented using JavaScript/JQuery and CSS, so it can be useful for all web developers.
Agile release cycle can be displayed in three different ways: monthly calendar, read-only list and editable list. All of them can contain the following items:
- Planning – only one per release cycle;
- Sprints – any number of sprints, but should be at least one;
- Holidays – any number of holidays;
- Team members’ vacations – any number of vacations.
You can download an example project from my website.
http://supperslonic.com/WebControls/AgileReleaseCycleCalendar.
Calendar view:
Each date contains a short description which is displayed on mouse over event.
The first day of the week is a configured property. You can easily switch to Monday or Sunday, or even Friday. =)
Dates in a calendar are selectable. You can bind any event handler to the "Select date(s)" event.
You can customize colors for each agile item: planning, sprints, holidays – everything can have its own color.
You can customize icons of your team members. If a team member has a vacation, his icon will be displayed in a calendar for the vacation period.
Read-only and edit modes:
An addition to the calendar there are also two templates to display agile release cycle in read-only mode and edit mode.
Read-only mode is very simple: just displays the list of planning, sprints, holidays and vacations.
Editing mode also displays all items in lists, but it allows you to:
- Add new items;
- Delete items by dragging them to the trash;
- Select colors with a pretty color-Picker;
- Select team members with a cool team-Member-Picker;
- Validate control and get JSON representation.
Using the code
Model
Project contains two models for the agile release cylce: domain model and view model. Domain model is used to retrieve data from the server and save it back. View model is populated based on the domain model and is used in rendering Html in views.
Domain model:
ReleaseCycleModel class describes a domain model for an agile release cycle. This class supports Xml serialization and deserialization.
An XML structure of the model is very simple, also project contains an XSD schema to validate an XML.
="1.0"="utf-8"
<releaseCycle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:supperslonic:agileCalendar">
<planning name="planning 1" start="2013-12-27" end="2014-01-03" color="yellow"/>
<sprint name="sprint 1" start="2014-01-06" end="2014-01-15" color="redTomato"/>
<sprint name="sprint 2" start="2014-01-16" end="2014-01-21" color="pinkSoftDark"/>
<sprint name="sprint 3" start="2014-01-22" end="2014-02-04" color="greenPeace"/>
<sprint name="sprint 4" start="2014-02-05" end="2014-02-17" color="blueGloss"/>
<holiday name="New Year" start="2014-01-01" end="2014-01-01" color="blueSky" />
<vacation name="Emmy's vacation" start="2014-02-05" end="2014-02-06" teamMemberIcon="teamMember5"/>
<vacation name="Maxic's vacation" start="2014-02-06" end="2014-02-15" teamMemberIcon="teamMember4"/>
</releaseCycle>
View model:
View model is used only to display agile release cycle in a monthly calendar.
The calendar rendering logic is decoupled from the agile data model and operates only with abstract classes.
There is a CalendarBuilder class which uses an abstract factory CalendarDateFactoryBase to render Html. Factory returns an abstract class CalendarDateBase which represents a calendar's date.
This allows you to reuse the calendar's rendering logic for any other purposes:
display any custom dates,
extend and cover it with tests easily.
Calendar's dates building logic using a custom factory:
public IList<CalendarDateBase> BuildDates()
{
IList<CalendarDateBase> result = new List<CalendarDateBase>();
DateTime startDate = this.datesFactory.StartDate;
DateTime endDate = this.datesFactory.EndDate;
MonthPeriodIterator monthIterator = new MonthPeriodIterator(startDate, endDate, this);
DatesIteratorBase alignIterator;
while (monthIterator.HasNext)
{
alignIterator = new AlignStartOfTheMonthIterator(monthIterator.CurrentDate, this);
while (alignIterator.HasNext)
result.Add(alignIterator.ReadNext(this.datesFactory.GetEmptyViewModel()));
monthIterator.IsNewMonth = false;
while (!monthIterator.IsNewMonth && monthIterator.HasNext)
result.Add(monthIterator.ReadNext(this.datesFactory.GetCalendarDate(monthIterator.CurrentDate)));
alignIterator = new AlignEndOfTheMonthIterator(monthIterator.CurrentDate, this);
while (alignIterator.HasNext)
result.Add(alignIterator.ReadNext(this.datesFactory.GetEmptyViewModel()));
}
return result;
}
There are three Iterators used inside the calendar’s build logic.
- AlignStartOfTheMonthIterator;
- AlignEndOfTheMonthIterator;
- MonthPeriodIterator.
First two iterators align the beginning and the end of the month with the days of the week, by generating “empty cells”.
The third iterator provides calendar’s dates from the factory and is used internally to indicate the beginning of the new month.
For an agile calendar an AgileDateFactory class exists which creates view model (CalendarDateBase) based on domain model.
[ChildActionOnly]
public ActionResult AgileCalendar(ReleaseCycleModel model)
{
AgileDateFactory factory = new AgileDateFactory(model.Normolize());
CalendarBuilder builder = new CalendarBuilder(DayOfWeek.Monday ,
factory);
return PartialView("Calendar", builder.Build() );
}
View
There 3 main views to display data:
- Monthly calendar view;
- Read-only view;
- Edit view.
Monthly calendar view operates over its own data model, abstracted from the agile release cycle. As already mentioned, this allows you to reuse this template for any other entities easily.
Read-only view displays agile release cycle in a simple and easy-to-read way.
Edit view displays data the same way as a read-only view, but allows data editing:
- There is a dynamically added template row to enter new data: new sprints, holidays or vacations;
- View has a color-Picker to set custom colors of the items;
- A team-member-Picker to edit vacations;
- There is a JavaScript function to validate control and to get JSON representation of the agile release cycle.
There are also some templates that are used internally in the main views. For the client-side support there are four .js files and four .css files:
- agileReleaseCycle.js agileReleaseCycle.css;
- calendar.js calendar.css;
- colorPicker.js colorPicker.css;
- teamMemberPicker.js teamMemberPicker.css.
Controller
Control doesn't have server-side logic. Only small examples of how to serialize/deserialize data and build a monthly calendar.
How to use
Read-only mode and monthly calendar:
@model AgileCalendarExample.Models.DomainModels.ReleaseCycleModel
@section Scripts
{
<script type="text/javascript" src="@Url.Content("~/Content/js/calendar.js")"></script>
}
<div>@Html.Action("AgileCalendar", Model)</div>
<div>@Html.DisplayFor(m => m, "ReleaseCycle")</div>
Edit mode:
@model AgileCalendarExample.Models.DomainModels.ReleaseCycleModel
@section Scripts
{
<script type="text/javascript" src="@Url.Content("~/Content/js/teamMemberPicker.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/js/colorPicker.js")"></script>
<script type="text/javascript" src="@Url.Content("~/Content/js/agileReleaseCycle.js")"></script>
}
<div>@Html.EditorFor(m => m, "ReleaseCycle")</div>
@Html.Action("GetTeamMembers", "TeamMembers")