Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Adding Field Screens Programatically in a plugin

Andrew Gilbert October 7, 2014

Hi

 

Is there some example of how i can add Field screens programatically in a plugin?

 

I have created a AddProjectHook class thats called buy my project-blueprint plugin and when this is added i want to create some customer field screens, but cannot find any examples of how to do this.

 

I am new to JIRA dev so would welcome some examples thank you in advance

 

Andy

3 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

6 votes
Answer accepted
Andreas Ebert
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 7, 2014

You will need FieldScreenManager to create a new screen, FieldScreenSchemeManager to add the screen to a scheme and IssueTypeScreenSchemeManager to assign the scheme to a Project and IssueTypes. A screen consists of a list of FieldScreenTabs, each containing a list of FieldScreenLayoutItems, which is essentially an OrderableField and its position in the tab.

Try something like this:

// component dependencies, get via Constructor Injection
FieldScreenManager fieldScreenManager;
FieldScreenSchemeManager fieldScreenSchemeManager;
FieldManager fieldManager;
IssueTypeScreenSchemeManager issueTypeScreenSchemeManager;
ConstantsManager constantsManager;

// create screen
FieldScreen myScreen = new FieldScreenImpl(fieldScreenManager);
myScreen.setName(myName);
myScreen.setDescription(myDescription);
myScreen.store();

// create tab
FieldScreenTab myTab = myScreen.addTab(myTabName);

// add field to tab
OrderableField myField = fieldManager.getOrderableField(myFieldId); // e.g. "assignee", "customfield_12345"
myTab.addFieldScreenLayoutItem(myField.getId());


// add screen to scheme

// get existing scheme...
FieldScreenScheme myScheme = fieldScreenSchemeManager.getFieldScreenScheme(mySchemeId);
// ... or create new scheme
FieldScreenScheme myScheme = new FieldScreenSchemeImpl(fieldScreenSchemeManager);
myScheme.setName(mySchemeName);
myScheme.setDescription(mySchemeDescription);
myScheme.store();

// add screen
FieldScreenSchemeItem mySchemeItem = new FieldScreenSchemeItemImpl(fieldScreenSchemeManager, fieldScreenManager);
mySchemeItem.setIssueOperation(IssueOperations.CREATE_ISSUE_OPERATION); // or: EDIT_ISSUE_OPERATION, VIEW_ISSUE_OPERATION
mySchemeItem.setFieldScreen(myScreen);
myScheme.addFieldScreenSchemeItem(mySchemeItem);

// create issueTypeScreenScheme
IssueTypeScreenScheme myIssueTypeScreenScheme = new IssueTypeScreenSchemeImpl(issueTypeScreenSchemeManager, null);
myIssueTypeScreenScheme.setName(myIssueTypeScreenSchemeName);
myIssueTypeScreenScheme.setDescription(myIssueTypeScreenSchemeDescription);
myIssueTypeScreenScheme.store();

// add scheme to issueTypeScreenScheme
IssueTypeScreenSchemeEntity myEntity = new IssueTypeScreenSchemeEntityImpl(
        issueTypeScreenSchemeManager, (GenericValue) null, fieldScreenSchemeManager, constantsManager);
IssueType issueType;
myEntity.setIssueTypeId(issueType != null ? issueType.getId() : null); // an entity can be for all IssueTypes (-> null), or just for 1
myEntity.setFieldScreenScheme(myScheme);
myIssueTypeScreenScheme.addEntity(myEntity);

// assign to project
issueTypeScreenSchemeManager.addSchemeAssociation(myProject, myIssueTypeScreenScheme);
Andrew Gilbert October 8, 2014

Hi Thank you for the repose its helped me loads. I am struggling to compile though as it complains that I have not initialised some of the component dependencies, how do I do this or should they be passed into the function.. FieldScreenManager fieldScreenManager; FieldScreenSchemeManager fieldScreenSchemeManager; FieldManager fieldManager; IssueTypeScreenSchemeManager issueTypeScreenSchemeManager; ConstantsManager constantsManager; I am running this in the AddProjectHook from a project blueprint project. I am new to this type of development so sorry for the questions! Should i be using the IssueTypeScreenSchemeManager issueTypeScreenSchemeManager; = ComponentAccessor.getIssueTypeScreenSchemeManager() ? If this is the case i cannot find a get command for the FieldScreenSchemeManager or the IssueType? Andy

Andreas Ebert
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 8, 2014

We're talking about Dependency Injection here. In many places JIRA will inject the dependent components if you simply write them as parameters in the constructor, where you can save them to variables and use them later. If that is not possible with AddProjectHooks, then you indeed have to use ComponentAccessor instead. But only for the components: "IssueType" is not a component. I merely put it in the code to point out that you could set the IssueTypeScreenSchemeEntity for a specific IssueType. But you don't have to. You could just use "null" there to assign the entity to all IssueTypes. For all components without a getter-method in ComponentAccessor you have to use ComponentAccessor.getComponent(Class<T> componentClass) instead, like so: ComponentAccessor.getComponent(FieldScreenSchemeManager.class)

Like Christian Wiemer likes this
Andrew Gilbert October 9, 2014

Hi This is great and i have managed to get it to work perfectly thank you. Also where can i find more documentation on how to use some of these class plus any examples as now i want to be able to add customer fields and import a workflow from a workflow backup in the same procedure as i am doing the above? Using the example blueprint code and using the JSON file example means it keeps creating separate workflows for every new project created with it when i want it to reuse the same workflow for all projects created with the blueprint so i think doing it in code and checking if it exists first is the best way.? Andy

Andreas Ebert
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 9, 2014

I sometimes find useful code examples by googling for short code snippets, e.g. for AddProjectHook I used this search: https://www.google.de/search?q=%22implements+addprojecthook%22 You can do the same for other components, e.g. "workflowmanager.getworkflow"

Andreas Ebert
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 15, 2014

@Andrew Gilbert, if my answer helped you, please "officially" mark it as correct by ticking the checkmark next to it. Thanks.

ylonkar June 15, 2017

Can you please provide updated solution. I am working with jira-api 7.2.2

Navi August 24, 2017

@Andreas Ebert,  Thanks for the solution. I am able to follow the steps and succesfully compiled the code but I dont know how can ii check the output screen? can you please share the steps to verify the output screen created? 

jingjing November 28, 2018

@Andreas Ebert ,according to your suggestion,i create a new issuetypescreenscheme and copy some fieldscreenscheme. assign fieldscreenscheme and issyetype to the new issuetypescreenscheme.when i assign  the new issuetypescreenscheme to my project ,it is Error. Is it because of my new issuetypescreenscheme don't set dafault fieldscreenscheme ?

1.png2.png3.png

1 vote
pelizza
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 10, 2016

Hey guys,

Thanks for sharing all this stuff, including the answer by @Rusi Popov that inspired my solution.

After digging a lot, I've found that is possible to create workflows, issue types, screens, resolutions, issue type screen schemes and screen schemes using only a .json config file. Here is an example:

{
    "issue-type-scheme": {
        "name": "my.translations.project.issuetype.scheme.name",
        "description": "my.translations.project.issuetype.scheme.description",
        "default-issue-type": "issueType1",
        "issue-types": [
            {
                "key": "issueType1",
                "name": "my.translations.issuetype.improvement.name",
                "description": "my.translations.issuetype.improvement.desc",
                "icon": "/images/issuetypes/improvement.png",
                "avatar": "improvement.svg"
            },
            {
                "key": "issueType2",
                "name": "my.translations.issuetype.sub-task.name",
                "description": "my.translations.issuetype.sub-task.desc",
                "icon": "/images/issuetypes/subtask.png",
                "sub-task": true,
                "avatar": "subtask.svg"
            },
            {
                "key": "issueType3",
                "name": "my.translations.issuetype.sales.name",
                "description": "my.translations.issuetype.sales.desc",
                "icon": "/images/issuetypes/sales.png",
                "avatar": "sales.svg",
                "screen-scheme": "salesScreenScheme"
            }
        ]
    },
    "issue-type-screen-scheme": {
        "name": "my.translations.project.issuetype.screen.scheme.name",
        "description": "my.translations.project.issuetype.screen.scheme.description",
        "default-screen-scheme": "defaultScreenScheme",
        "screens": [
            {
                "key": "defaultScreen",
                "name": "my.translations.project.screen.default.name",
                "description": "my.translations.project.screen.default.description",
                "tabs": [
                    {
                        "name": "my.translations.project.screen.tab.name",
                        "fields": [
                            "summary",
                            "issuetype",
                            "security",
                            "priority",
                            "duedate",
                            "components",
                            "fixVersions",
                            "assignee",
                            "reporter",
                            "description",
                            "attachment",
                            "issuelinks",
                            "labels",
                            "timetracking"
                        ]
                    }
                ]
            },
            {
                "key": "salesScreen",
                "name": "my.translations.project.screen.sales.name",
                "description": "my.translations.project.screen.sales.description",
                "tabs": [
                    {
                        "name": "my.translations.project.screen.tab.name",
                        "fields": [
                            "summary",
                            "issuetype",
                            "security",
                            "priority",
                            "duedate",
                            "components",
                            "versions",
                            "fixVersions",
                            "assignee",
                            "reporter",
                            "environment",
                            "description",
                            "attachment",
                            "issuelinks",
                            "labels",
                            "timetracking"
                        ]
                    }
                ]
            }
        ],
        "screen-schemes": [
            {
                "key": "defaultScreenScheme",
                "name": "my.translations.project.screen.scheme.default.name",
                "description": "my.translations.project.screen.scheme.default.description",
                "default-screen": "defaultScreen"
            },
            {
                "key": "salesScreenScheme",
                "name": "my.translations.project.screen.scheme.sales.name",
                "description": "my.translations.project.screen.scheme.sales.description",
                "default-screen": "salesScreen"
            }
        ]
    },
    "resolutions": [
        {
            "name": "my.translations.resolution.done.name",
            "description": "my.translations.resolution.done.desc"
        },
        {
            "name": "my.translations.resolution.wontdo.name",
            "description": "my.translations.resolution.wontdo.desc"
        }
    ]
}

If you need to add custom fields to the created screens, it is possible to be done on the "AddProjectHook" class.

I hope it helps!

Tarek Moustafa July 25, 2017

Hello @pelizza,

can you give  full example of that?
how you load that JSON file into the plugin?

 

BR,

 

Vitor Pelizza August 25, 2017

Sure,

In my case I've just declared a project-blueprint module in my atlassian-plugin.xml and referenced the xml files:

<project-blueprint key="project-template" weight="90">
<label key="project_template.name"/>
<projectTypeKey>business</projectTypeKey>
<description key="project_template.description"/>
<longDescription key="project_template.description.long"/>
<infoPage soy-template="JIRA.Templates.ProjectTemplates.MyTemplate.renderTemplateExplanation" />
<icon location="imagesproject-template-icon.png"/>
<add-project>
<hook class="com.my.company.blueprint.AddProjectHook"/>
<descriptor file="/com/my/company/config/project-template-config.json"/>
</add-project>
<condition class="com.my.company.conditions.ValidLicenseCondition"/>
</project-blueprint>
S T August 1, 2019

Hi @pelizza

Do you maybe have an example of the "AddProjectHook" class. I created a json with the configuration I need and this works perfectly well, but now I want to add a custom field, but I do not understand how to do that with the "AddProjectHook".

 

Thanks in advance.

Vitor Pelizza August 5, 2019

Hi there. Sure, this is what I have for mine, just with the implementation of each method omitted. But I suppose you'll figure out what to do once you implement the correct interface:

@Scanned
public class AddProjectHook implements com.atlassian.jira.project.template.hook.AddProjectHook {
private final WorkflowManager workflowManager;
private final WorkflowFunctionDescriptorFactory workflowFunctionDescriptorFactory;
private final CustomFieldManager customFieldManager;
private final OptionsManager optionsManager;
private final PluginSettingsFactory pluginSettingsFactory;

public AddProjectHook(@ComponentImport final WorkflowManager workflowManager,
@ComponentImport final WorkflowFunctionDescriptorFactory workflowFunctionDescriptorFactory,
@ComponentImport final CustomFieldManager customFieldManager,
@ComponentImport final OptionsManager optionsManager,
@ComponentImport final PluginSettingsFactory pluginSettingsFactory) {
this.workflowManager = workflowManager;
this.workflowFunctionDescriptorFactory = workflowFunctionDescriptorFactory;
this.customFieldManager = customFieldManager;
this.optionsManager = optionsManager;
this.pluginSettingsFactory = pluginSettingsFactory;
}

@Override
public ValidateResponse validate(final ValidateData validateData) { ...}

@Override
public ConfigureResponse configure(final ConfigureData configureData) { ...}
}




And then, you link this class into your atlassian-plugin.xml:

<project-blueprint key="my-project-template" weight="90">
<label key="com.sample.project_template.name"/>
<projectTypeKey>business</projectTypeKey>
<description key="com.sample.project_template.description"/>
<longDescription key="com.sample.project_template.description.long"/>
<infoPage soy-template="JIRA.Templates.ProjectTemplates.MySample.renderTemplateExplanation" />
<icon location="images/sample-project-template-icon.png"/>
<add-project>
<hook class="com.sample.blueprint.AddProjectHook"/>
<descriptor file="/com/sample/config/project-template-config.json"/>
</add-project>
</project-blueprint>
S T August 15, 2019

Thank you very much, that helped a lot!

But I have another question now, with which you maybe can help me.
I am not able to import the FieldScreenImp. I try to use 

import com.atlassian.jira.issue.fields.screen.FieldScreenImpl;

but Intellij tells me, that it cannot resolve symbol. I need this to create a screen I want to add my custom field then.
Do I do something wrong, or did they change FieldScreenImp to something else?
Other import statements like 

import com.atlassian.jira.issue.fields.screen.FieldScreen

do work well.

 

Thank you very much for your help!

Vitor Pelizza August 15, 2019

I don't know that one, but I don't think you are supposed to import the Impl class. Probably what you need is to use some other service to create the screen and then return the screen object for you, instead of doing something like new FieldScreen.

S T August 15, 2019

Hmm ok.

I was checking the internet for the last few days, but I did not find anything else than the Impl class and fortunately I am not that good yet at plugin development. 
But I will have another look, thank for the suggestion :)

0 votes
Rusi Popov
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 19, 2016

In order to avoid copying the workflows when instantiating a new project from template, in the from the project-template-config.json file remove the "workflow-scheme" section and the "workflow" references from from "issue-type-scheme"/"issue-types" sections. In this case JIRA assigns the default workflow schema, which one could replace with another (ready made) workflow schema in the configure() method of the project hook class:

 

public ConfigureResponse configure(final ConfigureData configureData) {
  AssignableWorkflowScheme workflowSchema;
  Scheme scheme;
  // assign the specific existing workflow schema
  workflowSchema = workflowSchemeManager.getWorkflowSchemeObj( "workflow schema name" );
  if ( workflowSchema != null ) {
    scheme = workflowSchemeManager.getSchemeObject( workflowSchema.getId() );
    workflowSchemeManager.addSchemeToProject(configureData.project(), scheme);
  }
  return ConfigureResponse.create();
}
TAGS
AUG Leaders

Atlassian Community Events