Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

On this page:

Table of Contents
minLevel1
maxLevel6
outlinefalse
styledefault
typelist
printabletrue

To explain how to create an extension for dashboard gadgets, we will base this on an example using the Show Saved Filter with Columns for Jira plugin , and its Show Saved Filter with Columns gadget.

Info
titleExample source code

The complete source code for this example is available at https://bitbucket.org/Adaptavist/example-gadget-extension/src/master/.

...

Step 1: Create the gadget feature and export it with

...

PCJ

First create an example of a gadget in a dashboard in Jira, configuring it as required. The screenshot below shows an example configuration.Dashboard configuration screenImage Removed

...

Next, export a configuration with PC PCJ that includes the dashboard. Bear in mind that Project Configurator does not export dashboards as a default, so you have to select the export option that exports the dashboard you created as a sample. Go to the Dashboards Options drop-down menu in on the Export Projects page and select an option that is appropriate for your case. In the example below, we have chosen to export all dashboards, which guarantees all dashboards in this instance will be exported (even private ones):Image Removed

...

Once this configuration is exported, open the created XML file with an editor of your preference and locate the gadget description. There is a dashboards element in the file that contains all exported dashboards. Each of these will have several gadget items. It is easy to identify a dashboard by its name and owner , or as the default dashboard (system dashboard). You will see something similar to the following:

...

Section of XML file exported by Project Configurator

Code Block
collapselanguagetruexml
<dashboards>
	<dashboard>
		<default>false</default>
		<owner>admin</owner>
		<name>Test dashboard</name>
		<description>Dashboard with samplegadget</description>
		<layout>AA</layout>
		<gadget>
			<type>rest/gadgets/1.0/g/com.ja.jira.plugin.searchrequest:sswc-gadget/gadget_wc.xml</type>
			<column>0</column>
			<row>0</row>
			<color>color1</color>
			<parameter>
				<key>columnNames</key>
				<value>issuetype@@issuekey@@summary@@priority</value>
			</parameter>
			<parameter>
				<key>filterId</key>
				<value>10000</value>
			</parameter>
			<parameter>
				<key>isConfigured</key>
				<value>true</value>
			</parameter>
			<parameter>
				<key>num</key>
				<value>10</value>
			</parameter>
			<parameter>
				<key>refresh</key>
				<value>120</value>
			</parameter>
			<parameter>
				<key>showActions</key>
				<value>true</value>
			</parameter>
			<parameter>
				<key>sortBy</key>
				<value></value>
			</parameter>
			<parameter>
				<key>sortByGlobal</key>
				<value>true</value>
			</parameter>
			<parameter>
				<key>title</key>
				<value>Project PDLF filter</value>
			</parameter>
		</gadget>
	</dashboard>


Notice how each gadget has several parameters that represent how you configured the gadget at the Jira user interface, setting preferences like the filter, the number of results to display, and the refresh period.

Step 2: Implement interface HookPointCollection

This step is the same as the example in Workflow Extensions. It is even possible to have workflow and gadget extensions within the same instance of HookPointCollection.

Step 3: Implement the gadget extension

Analyze

First, check which of the parameter elements in your gadget contain references to other entities in Jira. As with workflows, you have to specify how these references can be found in the configuration for dashboards and what their content is. In this example, you can find two references:

  • A parameter with key "columNames" that is a list of field identifiers

  • A parameter with key "filterId"

Parameter The parameter "columNames" can be ignored. This appears in many gadgets, and it is already handled by Project Configurator "out of the box".

Focus on the parameter "filterId". If you check the filter set up setup during dashboard configuration, you will notice this parameter contains a string with the internal the internal Jira ID for the selected filter.

Info

Adding support for a parameter in a gadget means creating an instance of GadgetHookPoint. As in the case of workflows, you must specify two things: its location and the content of the reference the parameter holds.

Define location

The "location" of a gadget parameter consists of:

  • The type of gadget and where it

    appear

    appears;

  • In which of the user preferences/parameters it appears for that gadget type.

If you look at the GadgetHookPoint  GadgetHookPoint interface, you  you will notice it has these methods:

com.atlassian.plugin.ModuleCompleteKey getModuleKey()

String getTypeURIString()

String getParamKey()

One of the first two methods will be used to identify the gadget type; , most often, often getTypeURIString(). In this example, looking at the XML file with the dashboard description, you can see the gadget element has a child element <type>:

Gadget type

Code Block
languagexmltitleGadget type
...
		<gadget>
			<type>rest/gadgets/1.0/g/com.ja.jira.plugin.searchrequest:sswc-gadget/gadget_wc.xml</type>
			<column>0</column>
...

This means the gadget type is identified by its URI (otherwise, it would contain a child <completeModuleKey> element). Use the text of the <type> element as a return value for the getTypeURIString() method of the associated GadgetHookPoint.

Define the content of the reference

This is described the same way as with workflow extensions. GadgetHookPoint extends the interface HookPoint; therefore, therefore it must implement the method:

Code Block
languagejava
ReferenceProcessor<String> getReferenceProcessor();

In this case, the reference is a filter ID. Navigate first to the predefined kinds of ReferenceProcessor offered by SimpleReferenceProcessorFactory. Among the possible values for ReferenceOption, there is one that handles a filter ID:TranslateOption valuesImage Removed

...

Combining the location and reference content, you define the GadgetHookPoint. It could be similar to the following code:

Implementing GadgetHookPoint

Code Block
title
languagejavaImplementing GadgetHookPoint
public GadgetHookPoint getSSSCGadgetFilterHookPoint() {

	return new GadgetHookPointImpl.Builder(). 
		withReferenceProcessor(simpleReferenceProcessorFactory.fromOption(FILTER_ID)). 
		withUri("rest/gadgets/1.0/g/com.ja.jira.plugin.searchrequest:sswc-gadget/gadget_wc.xml"). 
		withParamKey("filterId").build();
}

Remember to add this as a method of the class you created in step 2, so you will have the following:

Complete implementation of HookPointCollection

title
Code Block
title
languagejavaComplete implementation of HookPointCollection
package com.adaptavist.projectconfigurator.ssscextension;

import com.atlassian.plugin.spring.scanner.annotation.Profile;
import com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport;
import com.awnaba.projectconfigurator.extensionpoints.common.HookPointCollection;
import com.awnaba.projectconfigurator.extensionpoints.extensionservices.SimpleReferenceProcessorFactory;
import com.awnaba.projectconfigurator.extensionpoints.gadget.GadgetHookPoint;
import com.awnaba.projectconfigurator.extensionpoints.gadget.GadgetHookPointImpl; 
import org.springframework.stereotype.Component;

import javax.inject.Inject; 

@Profile("pc4j-extensions")
@Component
public class SSSCExtensionModule implements HookPointCollection {

	private SimpleReferenceProcessorFactory simpleReferenceProcessorFactory;

	@Inject
	public SSSCExtensionModule(@ComponentImport SimpleReferenceProcessorFactory simpleReferenceProcessorFactory) { 
		this.simpleReferenceProcessorFactory = simpleReferenceProcessorFactory;
	}

	public GadgetHookPoint getSSSCGadgetFilterHookPoint() { 
		return new GadgetHookPointImpl.Builder(). 
			withReferenceProcessor(simpleReferenceProcessorFactory.fromOption(FILTER_ID)). 
			withUri("rest/gadgets/1.0/g/com.ja.jira.plugin.searchrequest:sswc-gadget/gadget_wc.xml"). 
			withParamKey("filterId").build();
	}
}


Info
Tip

And that's it!

You have now completed an integration of this gadget type with Project Configurator.

...