1

I followed this extremely simple tutorial https://bitbucket.org/bhushan154/jira-issue-tab-panel-tutorial/wiki/Home to add a new issue tab panel. It shows how you can add simple content to the page using stringBuilder. Ideally I would want to use a velocity template as it's much easier to work with and separates the logic appropriately. I have a template file, that contains:

<div class="mod-header">
    <h3>$i18n.getText('service-now-tab-panel.label')</h3>
</div>

I've tried fiddeling around with this attempting to get it to display data appropriately, it's not doing anything and isn't rendering out content onto the issue detail page. Here's the controllers it's barebones right now as I need to get passed this road block.

package com.verys.jira.plugins.panels;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.atlassian.jira.plugin.issuetabpanel.AbstractIssueTabPanel;
import com.atlassian.jira.plugin.issuetabpanel.IssueTabPanel;
import com.atlassian.jira.issue.tabpanels.GenericMessageAction;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.crowd.embedded.api.User;
import java.util.Collections;
import java.util.List;

public class ServiceNowTabPanel extends AbstractIssueTabPanel implements IssueTabPanel
{
    private static final Logger log = LoggerFactory.getLogger(ServiceNowTabPanel.class);

    public List getActions(Issue issue, User remoteUser)
    {
        return Collections.singletonList(new GenericMessageAction("" + issue.getReporter().getDisplayName() + ""));
    }


    public boolean showPanel(Issue issue, User remoteUser)
    {

        return true;
    }
}

The documentation for rendering out velocity templates on issue tab panels is extremely sparse and almost non existent. If someone can just kindly point me in the right direction that would be great. Also here is the properties file

<issue-tabpanel key="service-now-tab-panel" name="Service Now Tab Panel" i18n-name-key="service-now-tab-panel.name" class="com.verys.jira.plugins.panels.ServiceNowTabPanel">
  <description key="service-now-tab-panel.description">The Service Now Tab Panel Plugin</description>
  <label key="service-now-tab-panel.label">Plugin Test</label>
  <order>10</order>
  <resource type="velocity" name="view" location="templates/tabpanels/service-now-tab-panel.vm"/>
  <supports-ajax-load>true</supports-ajax-load>
</issue-tabpanel>
djowinz
  • 356
  • 1
  • 4
  • 17

1 Answers1

2

In order to render out velocity templates you need to import 5 classes.

import com.atlassian.jira.config.properties.APKeys;
import com.atlassian.jira.config.properties.ApplicationProperties;
import com.atlassian.jira.util.VelocityParamFactory;
import com.atlassian.velocity.VelocityManager;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.config.properties.APKeys;

The inside your function you need to initialize the ComponentAccessor and get the application properties

ApplicationProperties ap = ComponentAccessor.getApplicationProperties();

Once you have the application properties "ap" you can get the application keys which the Velocity manager depends on.

String baseUrl = ap.getString(APKeys.JIRA_BASEURL);
String webworkEncoding = ap.getString(APKeys.JIRA_WEBWORK_ENCODING);

Once you have your baseUrl & your webworkEncoding you can then move onto initializing the VelocityManager & the VelocityParamFactory these two classes allow you to one create the manager which allows you to encode your template or get the body of your template as well as get the default parameters per velocity template.

VelocityManager vm = ComponentAccessor.getVelocityManager();
VelocityParamFactory vp = ComponentAccessor.getVelocityParamFactory();

After those are initialized you should create a Map of context values which are assigned to VelocityParamFactory that allow you to get & set the parameters per template. Which you can pass in values to be used later in your velocity template.

Map context = vp.getDefaultVelocityParams(); 

By using the map context you've set up earlier you can then start assigning values to the context variable using the put method to be later used in the velocity template.

context.put("testVariable", ["Value can be a string or an array or a collection"]);

Once you have that assuming you want to render out the velocity template you can either use the getBody method or the getEncodedBody method. Both essentially do the same thing but work very differently. I suggest reading up on how to use each one and which use case is correct for either or.

String renderedText = vm.getEncodedBody("templates/", "service-now-tab-panel.vm", baseUrl, webworkEncoding, context);

You need to set the templatePath, templateFile, baseUrl, webWorkEncoding, and finally the context which contains any of the parameters you put in context that will then be returned in the velocity template to the variable renderedText as a string.

Depending on how & what you are doing in Jira there are a couple of different ways to pass this to your view. I will leave that up to you to figure out, but for what I did creating a IssueTabPanel was to render it out like so below:

return Collections.singletonList(new GenericMessageAction( renderedText ));

So all together ti should look like so:

ApplicationProperties ap = ComponentAccessor.getApplicationProperties();
String baseUrl = ap.getString(APKeys.JIRA_BASEURL);
String webworkEncoding = ap.getString(APKeys.JIRA_WEBWORK_ENCODING);

VelocityManager vm = ComponentAccessor.getVelocityManager();
VelocityParamFactory vp = ComponentAccessor.getVelocityParamFactory();

Map context = vp.getDefaultVelocityParams();
context.put("test", "test");

String renderedText = vm.getEncodedBody("templates/", "service-now-tab-panel.vm", baseUrl, webworkEncoding, context);

return Collections.singletonList(new GenericMessageAction(renderedText));

This is my understanding of how this has worked done from research. It may not be the best way to do this and may not be the absolute correct way, but this method will work! If anyone has any additions to add to this to make it more clear, and thorough please edit it or turn it into a wiki.

djowinz
  • 356
  • 1
  • 4
  • 17
  • Dyllen, you did a great job to make it work without any documentation from atlassian! Here is my short tutorial on this subject which I compiled based on JIRA sources: https://answers.atlassian.com/questions/15835336/answers/15836488 – Volodymyr Krupach May 25 '15 at 06:00
  • 1
    @VolodymyrKrupach Hey thanks man, I really appreciate your answer. It's crazy to think that Atlassian's documentation is so sparse on the subject. This is my first JIRA plugin so I'm bound to make mistakes, its awesome to know there are other people out there running into the same issues developing simple solutions to this problem. I like how you implemented yours much better so I went ahead and switched my code around :)! Thanks!! – djowinz May 25 '15 at 07:31
  • 1
    > you implemented yours I just looked to JIRA sources and copied from there and that's what we have to do when there is no the documentation :-). – Volodymyr Krupach May 25 '15 at 09:18