Time Ago Template for date fields in .Net MVC

I wanted to display dates for certain models in my views like “15 minutes ago.” I tried at first extending the HTML Helper, but I found it easier to just create a template.

@model DateTime
@{
    TimeSpan timeSince = DateTime.Now.Subtract(Model);
}
@if (timeSince.TotalMilliseconds < 1)
  { <text>not yet</text> }
else if (timeSince.TotalMinutes < 1)
  { <text>just now</text> }
else if (timeSince.TotalMinutes < 2)
  { <text>1 minute ago</text> }
else if (timeSince.TotalMinutes < 60)
  { <text>@string.Format("{0} minutes ago", timeSince.Minutes)</text> }
else if (timeSince.TotalMinutes < 120)
  { <text>1 hour ago</text> }
else if (timeSince.TotalHours < 24)
  { <text>@string.Format("{0} hours ago", timeSince.Hours)</text> }
else if (timeSince.TotalDays < 2)
  { <text>yesterday</text> }
else if (timeSince.TotalDays < 7)
  { <text>@string.Format("{0} days ago", timeSince.Days)</text> }
else if (timeSince.TotalDays < 14)
   { <text>"last week</text> }
else if (timeSince.TotalDays < 21)
   { <text>2 weeks ago</text> }
else if (timeSince.TotalDays < 28)
   { <text>3 weeks ago</text> }
else if (timeSince.TotalDays < 60)
   { <text>last month</text> }
else if (timeSince.TotalDays < 365)
   { <text>@string.Format("{0} months ago", Math.Round(timeSince.TotalDays / 30))</text> }
else if (timeSince.TotalDays < 730)
   { <text>last year</text> }
else
   { <text>@string.Format("{0} years ago", Math.Round(timeSince.TotalDays / 365))</text> }

Then I specified the UIHint for the field.

        [UIHint("RelativeDateTime")]
        public DateTime? DateCreated { get; set; }

Then my dates are formated as expected in my views.

  @Html.DisplayFor(modelItem => item.Brand.Name)

Screen shot

Converting BB Press 1.x attachments to BB Press 2.x

If you were using BB Press 1.x with the BB Attachments plugin it can be a bit of a challenge to re-attach them to BB Press 2.0 in Wordpress using the GD bbPress Attachments plugin.

Here are the steps I took to accomplish this migration.

1. Run the BB Press migration process making sure that both the original BB Press 1.x tables and Wordpress tables are in the same database.
2. Download the original attachments from the bb-attachments folder.
3. Switch Wordpress to not use year/month upload folders under Settings – Media.
4. Upload the attachments to the wp-content/uploads folder.
5. Install the GD bbPress Attachments plugin if you haven’t already.
6. Run the following MySQL script

INSERT INTO wp_posts
(post_author, post_date, post_date_gmt, post_content, post_title, post_status,
comment_status, ping_status, post_name, post_modified, post_modified_gmt,
post_parent, guid, menu_order, post_type, post_mime_type, comment_count)
SELECT replies.post_author, replies.post_date, replies.post_date_gmt,
SUBSTRING_INDEX(filename, '.', 1), SUBSTRING_INDEX(filename, '.', 1), 'inherit',
'open', 'open', CONCAT(bb_attachments.id,'.',SUBSTRING_INDEX(filename, '.', 1)),
replies.post_modified, replies.post_modified_gmt, replies.ID,
CONCAT('http://nonamers.org/wp-content/uploads/',bb_attachments.id,'.',filename) as guid,
0, 'attachment', mime, 0 FROM `bb_attachments`
JOIN bb_posts ON bb_posts.post_id = bb_attachments.post_id
JOIN bb_topics ON bb_topics.topic_id = bb_posts.topic_id AND bb_topics.topic_status = 0
LEFT JOIN wp_posts as topics ON topics.post_status = 'publish'
AND topics.post_type = 'topic' AND topics.post_title = bb_topics.topic_title
LEFT JOIN wp_posts as replies ON replies.post_parent = topics.ID
AND replies.post_status = 'publish' AND replies.post_type = 'reply'
AND replies.post_author = bb_posts.poster_id
AND replies.post_date_gmt = bb_posts.post_time
WHERE bb_attachments.status = 0 AND replies.ID IS NOT NULL

Tweak any attachments if necessary.

Fix for sorting in Job Manager Wordpress Plugin

If you want to sort jobs alphabetically in Job Manager and use sticky sort for highlighted items it will mess up the order of all non-highlighted opportunities. This was my quick workaround. Hopefully it will help someone.

In frontend-jobs.php

<?php
function jobman_sort_highlighted_jobs( $a, $b ) {
	$ahighlighted = get_post_meta( $a->ID, 'highlighted', true );
	$bhighlighted = get_post_meta( $b->ID, 'highlighted', true );
	if( $ahighlighted == $bhighlighted )
		return strnatcmp($a->post_title, $b->post_title);
	if( 1 == $ahighlighted )
		return -1;
	if( 1 == $bhighlighted )
		return 1;
	return strnatcmp($a->post_title, $b->post_title);
}
?>

NextGen Gallery – auto-detect gallery

By default the NextGen gallery for wordpress requires you select the gallery to display when you use the shortcode [nggallery id=1]. However, you may note in the gallery itself you’ve already specified the page where the gallery is to be displayed (”Page Link to:”). So why select the gallery in the shortcode when the database already has this information. This short bit of code will allow you to manage the association in the gallery itself and no longer have to use the id parameter.
Read more

CakePHP Auth Compontent Management

CakePHP 1.3’s Auth Component has made authentication and ACL much easier. It however, leaves most the implementation of user management to the developer. Here are some helpful lessons we have learned to make this process less painful.
Read more

CakeFest 2010 Wrap

A quick run down of CakeFest 2010. It was great meeting a bunch of programmers and enthusiasts and finding out how they use CakePHP.

Here are my brief notes for the talks I attended and links to the presentations if I have them.

Read more

The future of flash

Whether we like it or not Flash is here to stay, especially now that CS5 is going to allow deployment to iPhone, iPad, and other “smart” devices. It just won’t be used as much for your standard web site, just for specialized applications where that level of control is necessary. Adobe isn’t stupid. They realize that Flash is a platform, not a product or a plugin. They are changing the direction of how it will be used and from what I can tell that use will be more appropriate than creating Tetris or a bunch of words floating on a web page. A great example is TweetDeck. The battle for the top platform of tomorrow’s interactive app platform is just heating up.