User Format

Available:

User Format plugin modules are available in Jira 3.13 and later.

User Format plugin modules are used to display user details in Jira. Jira ships with a number of default user format implementations that are used to render the full names for users system wide. You can use User Format plugin modules to implement custom behaviors for these user details.

Here are some examples:

  • Display a profile picture next to the user.
  • Link to an external profile page.
  • Display special avatars for users in certain groups.

For more information about apps in general, read Jira developer documentation. To learn how to install and configure apps (including macros), read about Managing Add-Ons.

The User Format plugin module

Here is an example of atlassian-plugin.xml file containing a single User Format plugin module:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<atlassian-plugin key="${atlassian.plugin.key}" name="${project.name}" plugins-version="2">
    <plugin-info>
        <description>${project.description}</description>
        <version>${project.version}</version>
        <vendor name="${project.organization.name}" url="${project.organization.url}" />
        <param name="plugin-icon">images/pluginIcon.png</param>
        <param name="plugin-logo">images/pluginLogo.png</param>
    </plugin-info>

    <resource type="i18n" name="i18n" location="profile-link-cursive"/>

    <web-resource key="soy" name="Soy Web Resources">
        <transformation extension="soy">
            <transformer key="soyTransformer"/>
        </transformation>
        <transformation extension="js">
            <transformer key="jsI18n"/>
        </transformation>
        <resource type="soy" location="/templates/profile-link-cursive.soy" name="profileLinksCursive.js"/>
    </web-resource>


    <user-format key="profile-link-user-format" i18n-name-key="user.format.plugin.profile.name" name="Cursive Profile Link User Format" class="com.example.plugins.ProfileLinkCursiveUserFormat">
        <description key="user.format.plugin.profile.desc">Simple link to a user's profile page displaying the user's full name.</description>
        <type i18n-name-key="user.format.type.profile.link.cursive">profileLinkCursive</type>
        <resource type="soy" name="view" location=":soy/Example.Templates.UserFormat.profileLinkCursive" />
    </user-format>
</atlassian-plugin>

* the class attribute of user-format needs to implement com.atlassian.jira.plugin.profile.UserFormat.

  • The resource elements (one or more) can be used to implement complicated rendering using velocity or Soy templates.
  • The type attribute defines where the user format will be used. The system types that are pre-defined include the following.

    Type

    Description

    profileLink

    Simple link to a user's profile page displaying the user's full name.

    fullName

    Safely displays the user's full name.

    profileLinkSearcher

    Simple link to a user's profile page displaying the user's full name from the issue navigator.

    profileLinkExternal

    Simple link to a user's profile used in emails, word documents, excel downloads, and so on.

    profileLinkActionHeader

    Simple link to a user's profile in issue action headers, such as comments.

    fullProfile

    Full user description including user operation links and report links.

Choosing your user format

After you add your own user format, use g + g shortcut and start typing "Look and Feel" or click Cog wheel > System > Look and Feel.

This page allows you to select the User Format that will be used across Jira.

Screenshot: View Look and Feel Configuration.

Sample Implementation

The following example demonstrates how to implement a User Format that prints a user's full name with a link to the user's profile page in Jira.

  1. Implement the UserFormat interface in the ProfileLinkUserFormat.java file:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    package com.example.plugins;
    
    import com.atlassian.jira.plugin.profile.UserFormat;
    import com.atlassian.jira.plugin.userformat.UserFormatModuleDescriptor;
    import com.atlassian.jira.security.JiraAuthenticationContext;
    import com.atlassian.jira.user.ApplicationUser;
    import com.atlassian.jira.user.UserKeyService;
    import com.atlassian.jira.user.util.UserManager;
    import com.atlassian.jira.user.util.UserUtil;
    import com.atlassian.jira.util.I18nHelper;
    import com.atlassian.jira.util.collect.MapBuilder;
    import com.atlassian.plugin.PluginAccessor;
    import com.atlassian.plugin.spring.scanner.annotation.component.Scanned;
    import com.atlassian.plugin.spring.scanner.annotation.imports.JiraImport;
    import com.atlassian.sal.api.ApplicationProperties;
    import com.atlassian.sal.api.UrlMode;
    
    import java.util.Map;
    
    @Scanned
    public class ProfileLinkCursiveUserFormat implements UserFormat {
        public static final String TYPE = "profileLink";
    
        private UserFormatModuleDescriptor moduleDescriptor;
        @JiraImport
        private UserManager userManager;
        @JiraImport
        private UserKeyService userKeyService;
        @JiraImport
        private UserUtil userUtil;
        @JiraImport
        private I18nHelper i18nHelper;
        @JiraImport
        private JiraAuthenticationContext jiraAuthenticationContext;
        @JiraImport
        private ApplicationProperties applicationProperties;
    
        public ProfileLinkCursiveUserFormat(@JiraImport PluginAccessor pluginAccessor,
                                             I18nHelper i18nHelper,
                                             UserUtil userUtil,
                                             UserManager userManager,
                                             JiraAuthenticationContext jiraAuthenticationContext,
                                             UserKeyService userKeyService,
                                             ApplicationProperties applicationProperties) {
            this.userManager = userManager;
            this.userUtil = userUtil;
            this.i18nHelper = i18nHelper;
            this.userKeyService = userKeyService;
            this.jiraAuthenticationContext = jiraAuthenticationContext;
            this.applicationProperties = applicationProperties;
            this.moduleDescriptor = (UserFormatModuleDescriptor)pluginAccessor.getPluginModule("com.example.plugins.profile-link-cursive:profile-link-user-format");
        }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    public String format(String userkey, String id) {
        Map<String, Object> params = getInitialParams(userkey, id);
        return moduleDescriptor.getHtml(VIEW_TEMPLATE, params);
    }

    public String format(String userkey, String id, Map params) {
        Map<String, Object> velocityParams = getInitialParams(userkey, id);
        velocityParams.putAll(params);
        return moduleDescriptor.getHtml(VIEW_TEMPLATE, velocityParams);
    }

    private Map<String, Object> getInitialParams(final String userkey, final String id) {
        ApplicationUser user = null;
        String username = null;
        String fullName = null;

        if (userkey != null) {
            user = userManager.getUserByKey(userkey);
            if (user == null) {
                // Attempt to show the correct username even for deleted users
                username = userKeyService.getUsernameForKey(userkey);
                if (username == null) {
                    // Well, we need to show *something*...
                    username = userkey;
                }
                fullName = username;
            } else {
                username = user.getUsername();
                fullName = userUtil.getDisplayableNameSafely(user);
                if (!user.isActive()) {
                    fullName += " (" + jiraAuthenticationContext.getI18nHelper().getText("admin.common.words.inactive") + ')';
                }
            }
        }

        return MapBuilder.<String, Object>newBuilder()
                .add("defaultFullName", i18nHelper.getText("common.words.anonymous"))
                .add("fullName", fullName)
                .add("id", id)
                .add("user", user)
                .add("username", username)
                .add("baseUrl", applicationProperties.getBaseUrl(UrlMode.CANONICAL))
                .toMutableMap();
    }
}
```
  1. In the profile-link-cursive.soy file, implement the view Soy template that is used to display the user:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    {namespace Example.Templates.UserFormat}
    
    /**
     * Simple user profile link template.
     * @param id
     * @param username
     * @param fullName
     * @param user
     * @param defaultFullName
     * @param baseUrl
     */
    {template .profileLinkCursive}
        {if $username}
            {if $user}
                <em><a class="user-hover" rel="{$username}" id="{$id}_{$username}" href="{$baseUrl}/secure/ViewProfile.jspa?name={$username |escapeUri}">{$fullName}</a></em>
            {else}
                {$username}
            {/if}
        {else}
            {$defaultFullName}
        {/if}
    {/template}
  2. Update i18n profile-link-cursive.properties with following:

    1
    2
    3
    user.format.plugin.profile.link.cursive.name=Cursive Profile Link User Format
    user.format.plugin.profile.link.cursive.desc=Simple link to a user's profile page displaying the user's full name.
    user.format.type.profile.link.cursive=Profile Link Cursive
  3. To format user, you can use this module as shown below:

    1
    $userformat.formatUser($worklog.author, 'profileLink', "worklog_${worklog.id}_header")

In this case, profileLink is the type and worklog_${worklog.id}_header is the ID that are passed to the UserFormat.format method for rendering.