I am currently building a website for a local magazine using Graffiti CMS. It handles most of the things that the site needs, with two notable exceptions:
- Show profiles for the various writers, along with links to their posts automatically
- Show an event calendar with details on local networking events
I'm still working on the first item (because we may be integrating it into the code base), but I have finished up the plug in for the second item. I found an example for handling events in Graffiti at http://pentonizer.com/csharp/event-calendar-for-graffiticms/, but I still needed more functionality than this. In addition to the little calendar Chalk extension for showing days with events, I wanted to change the entire Events category into an event calendar, so people could see which events happen on what days. This led to the creation of a new Graffiti Events plug in.
What the Events plug in Does
The plug in does a few things. First, when you enable it, it creates an “Events
” category in Graffiti (if needed). Then, it adds several custom fields for posts that fall into the Events
category:
- Event Date
- Start Time
- End Time
Event Date is stored as a date
, and Start/End Time are stored as string
s. They are stored this way to provide more flexibility when needed.
These few changes provide the backend requirements to make events work. Now, when you create a new post and set its category to Events, you will be given the option to add these additional fields to the post. You can then update your views (see the next section) to display this data and use it in interesting ways on your site.
The plug in also provides several new Chalk functions, both for working with Event posts as well as for rendering Calendars. These are as follows:
EventDate(Post post)
Provides a mechanism to get the DateTime
object for the Event Date
field of the current post. Since Custom Fields are stored as string
s, this gives you a mechanism to work with the field as a DateTime
instead, allowing any valid DateTime
functions, including formatting.
PostMonthUrl(Post post)
Returns the Category
page URL with the proper query string for the current post’s month/year. This will be used below for the breadcrumb links on event posts.
Calendar()
Displays a calendar generated for the current month (or the month provided via the querystring). This calendar shows all events in the selected month as links to the specific event post. All dates that have events also have a special CSS class set on them so they can be formatted differently.
Here is an example of this in use:
The Next/Previous month links are generated automatically and use the format of “/events/?d=YYYYMM”, which is handled by some Chalk code in the events.view file, which I will detail below.
MiniCalendar()
Displays a small calendar (for the sidebar) for the current month (or the month provided via the querystring). This calendar just shows the month dates with the additional CSS class to show dates with events. Events themselves are not shown. Here is an example of how this could look:
MiniCalendar(Post post)
This is a special version of the MiniCalendar
function above. This calendar shows the month for the current event post’s Event Date
and has a special CSS class set on said date. This allows you to display the calendar for the event’s month on the page with the event post, highlighting the date of the event so it stands out for the user. Here’s an example:
If you compare this to the example above, you will see the difference. This was taken from the post page for an event on March 2nd. In this case, only the event’s date is highlighted, and the event on March 24th is ignored.
MultipleMiniCalendars(int count, bool startWithNextMonth)
This allows you to show multiple MiniCalendar
s in the sidebar, with the option of starting with the month after the current selected month (using the same logic as other controls – either the current month or set via the querystring
). I am primarily using this on the Events category page to show the next three months’ dates with events. Here’s an example, taken from my Events category page for the month of February:
CalendarDate
DateTime
property that provides the logic used by the various calendars to determine which month to show (either the current month or picked using querystring
values). This is provided as a public Chalk
property to use when displaying titles and links on the Event category page.
UpcomingEvents(int count)
Returns a PostCollection
of upcoming events that you can iterate through. Using Chalk
, you can then render this in a way that lets you show upcoming events in the sidebar of the site. For example, you could make it look like this:
The Chalk
code to make this render is:
<h2 class="upcoming">Upcoming Events</h2>
#set ($eventList = $events.UpcomingEvents(5))
#set ($previousEventDate = "")
#foreach($event in $eventList)
#beforeall
<ul class="upcomingEvents">
#each
#set ($eventDate = $macros.FormattedDate($event.Custom("Event Date")))
#if ($previousEventDate != $eventDate)
#set ($previousEventDate = $eventDate)
<li class="upcomingEventDate">
$eventDate
#end
<li>
<a class="upcomingEvent" href="$event.Url">$event.Title</a>
#afterall
</li></ul>
#nodata
<div class="upcomingEvents">
No Upcoming Events
</div>
#end
Setting Up the events.view File
To get the Events
category to display how you want it, you need to create a new file in your theme called events.view. Here is the code that I have used to generate the sample above:
<div id="breadcrumbs">
<a href="/">Home</a> / $macros.CategoryLink($category)
/ $events.CalendarDate.ToString("MMMM yyyy")
</div>
<h1>$category.Name</h1>
$events.Calendar()
One thing I want to point out with this is the breadcrumbs section. This is set up to render the breadcrumbs one level lower than the category page. Normally, the breadcrumbs for this category would be “Home / Events”, but this will have it actually go one level deeper and put the current month as part of the breadcrumbs, so it will look like this “Home / Events / February 2010”. Provides a more accurate user experience, especially when the user chooses to view months beyond the current month.
Setting Up the events.post.view File
In addition to setting up the display for the Events category page, you will also need to modify the display of Events category posts. In this case, there are only a few minor changes needed:
<div id="breadcrumbs">
<a href="/">Home</a> / $macros.CategoryLink($category)
/ <a href="$events.PostMonthUrl($post)">
$events.EventDate($post).ToString("MMMM yyyy")</a> / $post.Title
</div>
<div class="article">
<h1>$post.Title</h1>
<div class="articleDate">
$macros.FormattedDate($post.Custom("Event Date"))
<strong>$post.Custom("Start Time") to $post.Custom("End Time")
</strong>
</div>
<div class="articleBody">
$post.Body
</div>
<p class="post_meta">
<span class="tag_list">
$macros.TagList($post.TagList)
</span>
</p>
</div>
Here, all I did was update the breadcrumbs in a way similar to what was done in events.view. However, this time, the “Month Year” breadcrumb is a link back to that specific event calendar view, using the EventDate
and PostMonthUrl Chalk
extensions to generate the link. In addition, I then displayed the Event Date, Start Time and End Time custom fields below the post’s Title when rendering the post. This will render a post like this:
Finishing Touches
The only thing left to do is to set up the sidebar to display the proper item (one/many mini calendars or the upcoming events) based on chosen criteria. The rules I set up are as follows:
- If on the Events category page, show 3 future months’ mini calendars, starting with the month after the currently displayed month
- If on a specific Event post, show the mini calendar for the posts’ Event Date
- Anywhere else, show the Upcoming Events
This is all handled in a Chalk
widget. Here’s the Chalk
code needed to accomplish this:
<div class="events">
#if ($category.Name == "Events" && $macros.IsNull($post))
$events.MultipleMiniCalendars(3, true)
#elseif ($category.Name == "Events")
$events.MiniCalendar($post)
#else
<h2 class="upcoming">Upcoming Events</h2>
#set ($eventList = $events.UpcomingEvents(5))
#set ($previousEventDate = "")
#foreach($event in $eventList)
#beforeall
<ul class="upcomingEvents">
#each
#set ($eventDate = $macros.FormattedDate($event.Custom("Event Date")))
#if ($previousEventDate != $eventDate)
#set ($previousEventDate = $eventDate)
<li class="upcomingEventDate">
$eventDate
</li>
#end
<li>
<a class="upcomingEvent" href="$event.Url">$event.Title</a>
</li>
#afterall
</ul>
#nodata
<div class="upcomingEvents">
No Upcoming Events
</div>
#end
#end
</div>
That's all there is to it. The Events plug in is fairly simple to use, but it does show some of the complexity and advanced capabilities that the Graffiti CMS system can provide. You can get the files from Codeplex at the link below. As always, any comments or suggestions are welcome.
References