Customizing with plugins

The most advanced customization can be accomplished by writing a custom plugin. With a plugin you can customize literally anything in Redmine. Of course, to write a full-featured plugin you need to be familiar with Ruby, Rails, Redmine API, JavaScript, HTML, CSS, web development concept, and so on. But who said, that you need a full-featured plugin?

As you know, a plugin's files are kept in a separate directory named after the plugin and located in the plugins subdirectory of the Redmine root. This way when Redmine gets upgraded, the plugin's files remain untouched. On the other side, many users put their customizations into Redmine core files, which get overwritten n upgrade. So why not put customizations into a plugin?

The Redmine plugin API is quite flexible and you allows to: overwrite any core view file without touching the original one; to add custom content to different views; load additional CSS style sheets, and so on. Therefore, a plugin can be used as a tool for customization. In fact, you do not need to write any complicated Ruby code to do this—just use small code snippets to activate different plugins capabilities. That's what we will learn in this topic.

Of course, to be able to customize Redmine's look and feel you need to be familiar, at least, with HTML. Familiarity with CSS is optional but will be very useful.

Writing a simple plugin

To be able to make use of the plugin capabilities we need to create a simple plugin first. Luckily, it's really simple.

Before proceeding, we need to choose a name for our plugin. Thus, for my website www.andriylesyuk.com, which runs Redmine too, I chose the name andriy_lesyuk. So, for this demo plugin I will choose just packtpub.

Tip

Name your customization plugin after your organization or site name. Use alphanumeric characters and dashes.

So now we will create a directory for our plugin in the plugins subdirectory of the Redmine root directory, which is /opt/redmine in my case. So the full path for the plugin will be /opt/redmine/plugins/packtpub.

After this, in the newly created directory, we will create the init.rb file (the entry point for the plugin) and put the following code in it:

require 'redmine'

Rails.logger.info 'Starting Packt Publishing Plugin for Redmine'

Redmine::Plugin.register :packtpub do
    name 'Packt Publishing customization'
    author 'Andriy Lesyuk'
    author_url 'http://www.andriylesyuk.com'
    description 'The demo of the customization using the plugin.'
    url 'http://redmine.packtpub.com'
    version '0.0.1'
end

In place of :packtpub write your plugin name (keep the colon at the beginning). What should be changed in the rest of the code, I believe, is quite clear.

When done, after restarting Redmine you should see your plugin in Administration | Plugins, as follows:

Writing a simple plugin

Of course, this plugin does nothing (besides putting itself into the plugin list), but that's all for now.

Customizing view files

Redmine is using the Model-View-Controller (MVC) architecture, where "view" files store the layout information. Most of the content of these files is just HTML code (the rest is eRuby, JavaScript, and so on). All views are located under the app/views path of Redmine. Any view can be overwritten just by copying the original view file into the appropriate path under the plugins app/views. So, let's now see how this works by reviewing one of the most common customization tasks, adding a logo to the layout.

First we need to create a directory for images in our plugin. This must be the assets/images directory. After creating it put the logo image into this directory.

When done, create the app/views directory in the plugins root and copy the app/views/layouts/base.html.erb file there from Redmine preserving the directory structure (thus, the full target location in my case is plugins/packtpub/app/views/layouts/base.html.erb).

Now open the base.html.erb file (the copy) and find the following line of code in there:

<h1><%= page_header_title %></h1>

This code renders the title of the page. Before this line, add the following line of code:

<%= image_tag('packtpub.png', :plugin => 'packtpub', :style => 'float: left; padding-right: 1em;') %>

Here packtpub.png is the name of the image file and 'packtpub' is the name of the plugin.

Tip

Alternatively, the logo can be added using CSS (for example, by creating a custom theme). To do this you can specify the background image for #header. However, the #header area should not already have the background image, which can be set, for example, by theme. The advantage of this method is that the customization, most likely, won't need to be updated after upgrades.

After saving changes, restarting Redmine, and reloading any Redmine page you will get something like the following screenshot:

Customizing view files

Track changes you make to copies of Redmine core files, as you may need to replicate them, if Redmine core files get modified with an upgrade.

Tip

The Plugin Views Revisions plugin of Vitaly Klimov allows you to bind the modified view file with certain Redmine version, thus, making it active only until an upgrade (this way preventing Redmine from crashes). More information can be found at http://www.redmine.org/plugins/redmine_plugin_views_revisions.

Using hooks

Redmine comes with "hooks" support. Hooks can be used to inject custom content into some pre-defined places in certain Redmine views. If possible, it is better to use hooks to add the content to the view instead of copying and modifying the view file, as for hooks you need to provide only the custom content and they are not affected by upgrades. Let's see how this works in another real-life example—let's add login instructions to the login page.

To be able to use hooks we need to add the hook listener to the plugin. To do this create the lib directory in the plugins root and place the packtpub_hook.rb file in it (you can use anything in place of packtpub in the filename). Now add the following code to the newly created file:

class PacktPubHook  < Redmine::Hook::ViewListener

    render_on :view_account_login_top, :partial => 'packtpub/login'

end

Here the name of the class, which is PacktPubHook, reflects the filename. :view_account_login_top is the hook, which gets called on the login form, and the :partial option contains the path to the custom content view file.

Now we need to create the file, which will contain the custom content. So first we will create the packtpub directory in app/views and then place the _login.html.erb file in it (note _ at the beginning of the filename—it is required). Now put your custom content, which can be just HTML, into the newly created file.

And finally we need to register our hook listener. To do this just add the following line of code to the init.rb file (under require 'redmine'):

require_dependency 'packtpub_hook'

Here packtpub_hook is the filename of the hook listener without extension.

Now when you restart Redmine and go to the login page, you should see something like the following screenshot:

Using hooks

The warning above the form is added using the hook.

The following table lists some other hooks, which can be interesting fo you:

Hook

Location

:view_welcome_index_left

Bottom of the left column (the start page)

:view_welcome_index_right

Bottom of the right column (the start page)

:view_account_login_bottom

Below the form on the login page

:view_layouts_base_content

Below the content on each page

:view_projects_show_left

Bottom of the left column (the project overview page)

:view_projects_show_right

Bottom of the right column (the project overview page)

:view_issues_new_top

Above the form on the new issue page

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset