Drupal Views: Custom field for todo list

Thu, 05/29/2014 - 15:59

I have an intranet setup for my own projects (and life), where I have tickets (aka a todo system). On the different list of tickets I have the following fields:

  • Title
  • Tags
  • Status

What I wanted to do was to have a visual display of the ticket status instead of just text. I wanted to make it simple, so I would just use FontAwesome icons.

Goal

There are two reasons for doing this. First of all I want to be able to get an overview of what projects - coding, social this, DIY, etc. - I want to do and is currently doing. I can't keep track of this without writing it down because of my scatter brain. This overview works better if it gives me a visual indicated instead of just a wall of text.

Another reason for this exercise is to learn more about Drupal. I like Drupal but I am aware that my knowledge of the inner workings and possibilities is limited. This was a great opportunity to learn something new.

In the process I also learned how to add a font (FontAwesome in this case) to a Drupal site.

What I've done

FontAwesome

First I've added FontAwesome to my theme. I tried the FontAwesome module, but it didn't work for me for some reason. I also tried downloading the FontAwesome project to my site, but this no luck. What ended up working was adding the css file to my site pointing it to netdna.bootstrapcdn.com. Because I use my own custom theme I could just update the template.php and add a hook.

/**
 * Implements hook_preprocess_html().
 */
function tssintra_preprocess_html(&$variables) {
  drupal_add_css(
    'http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css',
    array('type' => 'external')
  );
}

I tried the latest version (4.1.0 at the time of writing) but that gave me trouble too.

After clearing the cache I was able to add icons on my site both in the theme and in nodes.

<i class="icon-check"></i>

View handler

Next task was allowing me to add a custom field to my views. It took me some time to figure out exactly what to do, but in the end I found out that I needed to create a views_handler_field class. I dug around the views module and other modules exposing custom fields to figure out what to do. The views_handler_field class is in the views/handlers/ folder. My implementation looks like this (located in [modulefolder]/includes/intra_handler_field_todo_status.inc):

/**
 * @file
 * Definition of intra_handler_field_todo_status.
 */

class intra_handler_field_todo_status extends views_handler_field {
  /**
   * Override parent::query(), since this is not a field in the database.
   */
  function query() {
    $this->field_alias = 'intra_todo_status_'. $this->position;
  }

  function render($values) {
    $value = $values->field_field_status;
    $status = 'unknown';
    if (isset($value[0]['raw']['taxonomy_term'])) {
      $status = $value[0]['raw']['taxonomy_term']->name;
    }

    $box = '<input type="checkbox"& />';
    switch (strtolower($status)) {
      case 'todo':
        $icon = 'icon-check-empty';
        break;
      case 'doing':
        $icon = 'icon-check-minus';
        break;
      case 'done':
        $icon = 'icon-check';
        break;
      case 'unknown':
      default:
        $icon = 'fa-question';
    }
    return '<i class="' . $icon . '"></i>';
  }
}

To be able to use the field in views, I needed to expose it. To do this I added the following to the intra.module file

/**
 * Implementation hook_views_api
 */
function intra_views_api() {
  return array(
    'api' => 3,
  );
}

And included the file to the intra.info file. If this is missing you will be able to add the field, but Views will give an error saying the view handler is missing/broken.

files[] = includes/intra_handler_field_todo_status.inc

View configuration

After adding the view handler module and enabling it I was able to add the field to my view just like any other field.

See views-config.png

End result

See views-end-result.png

Possible future changes

  • Make the view handle configurable so it's not dependent on a specific field.
  • Update the view handler to not require the Status field to be added and hidden in Views.
  • Allow icons for each status to be configurable.