Hi community,
I'm trying to add users in the multi-user picker custom field based on the selection of a value in the Insight Object field.
There is an "Asset" schema, it has many objects, one is "Operating System", under the OS we have child objects, like "Windows 10", "Windows Server", "CentOS", "Red Hat" etc. I created an insight field and configured the Operating System object to display Name, and the field is associated with a Jira Software project. In the create screen I'm able to see all values from the "Operating System" insight dropdown field. I have a multi-user picker custom field (Approver). By default, it is adding 'user1' and 'user2' in the custom user field but I want it to change users based on value selection from the Operating System field. I wrote the below behaviour script, but it's not working with the if statement. How can I make it works?
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
def oSystem= getFieldById('customfield_10403')
def custApr = 'projLead'
if(oSystem.value == 'Windows 10') {
custApr = 'wUser1, wUser2, wUser3'
}
def customAprFormField = getFieldById('customfield_10410')
customAprFormField.setFormValue(custApr)
Thank you
For one thing, unless that has changed in recent versions of scriptrunner, oSystem.value will return the object Key for the selected object. You may need to use the objectFaced to retrieve an actual ObjectBean. Then you can look at the Label.
The other possible problem is that multi-user pickers expect an array of usernames
You could try it like this:
def custApr = ['projLead']
if(objSystem.labeel == 'Windows 10') {
custApr = ['wUser1', 'wUser2', 'wUser3']
}
But perhaps a better solution would be to actually store the list of users for approval in the insight object. This way you can easily maintain that list without changing the code.
But you will have to fetch the values for the "Approvers" attribute in your object. This will be user keys, so you will need to convert them to user names.
Hi @PD Sheehan thank you for your response. I replaced value to label, but it didn't work. I don't know how ObjectFaced and ObjectBean work. Can you please help me out? I appreciate your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Here is an example with hardcoded approvers:
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def defaultApprovers = ['projLead']
def systemApproversMap = ['Windows 10':['wUser1', 'wUser2', 'wUser3']]
def systemVal = systemFld.value as List<String>
if(systemVal){
def systemObject = objectFacade.loadObjectBean(systemVal[0])
def approvers = systemApproversMap[systemObject.label]
if(!approvers) approvers = defaultApprovers
approversFld.setFormValue(approvers)
}
And here is the more complex example where the approvers are stored in the System Object using an attribute "System Approvers" (type user, allow multiple=true)
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeBean
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeValueBean
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
@PluginModule ObjectTypeAttributeFacade objectTypeAttributeFacade
def userManager = ComponentAccessor.userManager
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def approverAtrtributeName = 'System Approvers'
def defaultApprovers = ['projLead']
def systemVal = systemFld.value as List<String>
if(systemVal){
def systemObject = objectFacade.loadObjectBean(systemVal[0])
def approverAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttribute(systemObject.objectTypeId, approverAtrtributeName)
def approverObjectAttribute = systemObject.objectAttributeBeans.find{ it.objectTypeAttributeId == approverAttributeBean.id }
def approverUsers = approverObjectAttribute.objectAttributeValueBeans.collect{ userManager.getUserByKey(it.value as String)}
def approvers = defaultApprovers
if(approverUsers){
approvers = approverUsers*.name
}
approversFld.setFormValue(approvers)
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @PD Sheehan I tried both scripts. The first one is not working properly. In the issue create screen it won't display users, but when I create the issue and go to the edit screen I can see users there however there isn't a space between usernames so it won't be displayed on the viewscreen. If I go to the edit screen and manually add space between users then it displays users in the view screen. Also, it is not adding the default user to the approver's field if I leave oSystem field empty. Any idea?
For the second one, I used a different object (servers) and the "Affected Server" custom field. I created the "System Approvers" attribute and added two users. I added the second script but it didn't work. I'm not sure I didn't configure it properly. Here are screenshots.
Thank you for your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
That's surprising behavior for me.
But I was able to replicate and confirm.
You can get around it with (in either script):
approversFld.setFormValue(approvers.join(', '))
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@PD SheehanI noticed it works if I switch the issue type. For example on create issue screen if I select "Windows 10" from the OS field, then switch the issue type to a different issue type it'll display users in the approver fields. I also added the script in both the initializer and server-side. I tested with both the data center and server but had the same result. Any idea why it happening?
The second question about the first script is how can I map more OS values with different users? Currently "Windows 10" is mapped with wUser1,2 and 3. I would like to map another os with other users for example CentOS should map cUser1,2,3 and the same other Values with different users.
Appreciate your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
If you want to add more hardcoded users for different OS, you can just add them to the map:
def systemApproversMap = [
'Windows 10':['wUser1', 'wUser2', 'wUser3'],
'CentOS': ['cUser1', 'cUser2', 'cUser3']
]
You should only need to add the script to the server-side script on the System custom field.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I meant I tried both. Actually, I added in the server-side script from day one, but when I noticed the issue today I tried the initializer. Do you have any idea what is causing this? Thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm not sure what issue you are talking about.
I've already provided a solution for how to correctly fill-in the Approvers field with the correct spacing.
Can you describe what issue remains?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
My apology I didn't explain it well. I was trying to say that the users are not populating in the Approver field if I select "Windows 10" from the field. There are two ways it is populating the users, first one is if I select the option and create the issue and then come back and edit the issue it shows the users in the field, but it won't display the user when I create the issue in the first place.
The second way it displays the users in the approver field is if I select the "Windows 10" option, then I switch to a different Issue type. For example, I click to create the issue and the Task issue type is already selected and I select the "Windows 10" option from the OS field, it won't add those mapped users in the approver field, however, if I switch the Task issue type to Story then I can see the mapped users.
I'm trying to say by default it is not working, either I have to create the issue first by filling fields then have to edit in order to see users and save the issue in order to see mapped users or I have to switch issue types while creating an issue and leaving "Windows 10" option selected from the field to see mapped users in the approver field. I hope it helps.
Thank you for your help.
Edit: Added screenshot
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Can you show me the behavior configuration for the Operating System field?
Are you sure there is not more than one other behaviour mapping that includes a configuration for Operating System?
Also I'm noticing that the Operating System appears to allow multiple values. What should happen if the user selected both "Windows 10" and "CentOS"? Should approvers be wUser1,2,3 and cUser1,2,3 ?
The current script I offered will only include the approvers for the first selected OS.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @PD Sheehan if uncheck the "Multiple" option it won't add users in the approver's field regardless of switching the issue type. But if I leave it checked then it can add the users if I switch the issue types from one to another after selecting the option "Windows 10" from the operating system field. or if I select two options then it adds users to the approver field, for example, I didn't map the "Windows Server" option with any users, if I select "Windows 10" then "Windows Server", then will add the users to the approver field.
I just want to say that the only time it works is if I leave multiple option checks from the field configuration and switch issueype or add multiple options in the system field. If I won't do it won't add users in the approver field.
Looks like it won't work if uncheck the multiple options. There is only behaviour for that project. Attaching screenshot.
Thank you for your help
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I'm on an older version of scriptrunner. I'll try to upgrade and see if I can get similar issues as you do and find a fix.
However, there might be a difference in our version of Jira as well. I only have access to 8.13.x at the moment.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Ah yes, I often tend to forget the following little fact:
formField.getValue() on an Insight object custom field will return either a string or an arrayList depending on whether this is the first value or one of many.
The way I test something like this is I add the following script to a field I want to examine:
def fld = getFieldById(fieldChanged)
fld.setHelpText("$fld.value (${fld.value.getClass()})")
This way each time you change the field value, you can see what the getValue() method returns and what type it returns.
Based on that, we can make a modification to the script like this:
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeBean
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeValueBean
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
@PluginModule ObjectTypeAttributeFacade objectTypeAttributeFacade
def userManager = ComponentAccessor.userManager
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def approverAtrtributeName = 'System Approvers'
def defaultApprovers = ['projLead']
def systemVal = systemFld.value
if(!systemVal){
//nothing selected, nothing to do, exit the script
return
}
def selectedKey
if(systemVal instanceof List){
selectedKey = systemVal[0] //There are multiple. Get only the first one
} else {
selectedKey = systemVal //This is what we get where there is a single value (whether multiple are allowed of not)
}
if(systemVal){
def systemObject = objectFacade.loadObjectBean(selectedKey)
def approverAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttribute(systemObject.objectTypeId, approverAtrtributeName)
def approverObjectAttribute = systemObject.objectAttributeBeans.find{ it.objectTypeAttributeId == approverAttributeBean.id }
def approverUsers = approverObjectAttribute.objectAttributeValueBeans.collect{ userManager.getUserByKey(it.value as String)}
def approvers = defaultApprovers
if(approverUsers){
approvers = approverUsers*.name
}
approversFld.setFormValue(approvers)
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you, we are using the Jira server version 8.13.18 in production and v8.20.7 in a lower environment. Script runner v6.48.1, and 6.49.0. I tested in both environments and the result was the same.
Thank you for your help
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you so much @PD Sheehan it is working as expected regardless of leaving the multiple option check or uncheck from the field configuration.
The only default user part is not working. If System Approvers attributes field doesn't have a user it won't add the default user in the approver field.
Second, can you please be able to update the shorter script that the user added manually? I mean where you mapped Windows 10 with users and so on. I would like to have both options in case leadership won't allow us to add system attributes in the insight.
I appreciate your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I recommend you try to understand what each of the two scripts does differently and figure out how to change one into the other. Remember, if you deploy this, someone may have to maintain it in the future.
But if you attempt the exercise yourself and want to check youself, here is a version of the first script with modifications we worked out along the way:
import com.onresolve.jira.groovy.user.FieldBehaviours
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def defaultApprovers = ['projLead']
def systemApproversMap = [
'Windows 10':['wUser1', 'wUser2', 'wUser3'],
'CentOS': ['cUser1', 'cUser2', 'cUser3']
]
def systemVal = systemFld.value
if(!systemVal){
//nothing selected, nothing to do, exit the script
return
}
def selectedKey
if(systemVal instanceof List){
selectedKey = systemVal[0] //There are multiple. Get only the first one
} else {
selectedKey = systemVal //This is what we get where there is a single value (whether multiple are allowed of not)
}
if(systemVal){
def systemObject = objectFacade.loadObjectBean(selectedKey)
def approvers = systemApproversMap[systemObject.label]
if(!approvers) approvers = defaultApprovers
approversFld.setFormValue(approvers)
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you so much @PD Sheehan the last script works perfectly.
However, I'm trying to understand both of the scripts. I'm trying to figure out how I can add the default approver in the approver field if the "System Approvers" attribute from System Object doesn't have any users. Can you be able to help me one last time figure out how can I get the default user if there isn't a user in the System Approvers attribute?
greatly appreciated your help
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
On the Map-based script, this should already be happening with this line:
if(!approvers) approvers = defaultApprovers
When the the "approvers" variable is "falsy" (this means it is empty, null, false or zero) then we set it to the defaultApprovers value.
So that in the following line:
approversFld.setFormValue(approvers.join(', '))
We set the form value to that variable. The variable will either contain the approvers we identified from the map or the defaultApprover if the approvers had been empty.
In the object attribute based script, this section should do it
def approverUsers = approverObjectAttribute.objectAttributeValueBeans.collect{ userManager.getUserByKey(it.value as String)}
def approvers = defaultApprovers
if(approverUsers){
approvers = approverUsers*.name
}
approversFld.setFormValue(approvers.join(', '))
1) We get user objects from the attribute values
2) We temporarily assign the approvers variable to the default approvers (just as above)
3) If approverUsers is truthy (reverse of falsy defined above), then
4) Set the approvers to the names of the approverUsers
5) So that we can set the form value to those names (joined together with a comma and a space)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you @PD Sheehan the mapping script is working fine. The system approver attribute one is not adding default users. I'll give it a shot and see if I can be able to figure it out.
Yesterday you said, "Remember, if you deploy this, someone may have to maintain it in the future". I just realize it might be an issue for someone to go make changes in script or System Attributes. I am thinking to use groups instead of individual users that no one needs to touch the script. They can just maintain the groups.
I was able to make changes to the simpler script (users mapped with a value (windows 10)). I created a custom group picker field and it worked with no issue with that script. However, it didn't work with other scripts where we have the System Approver attribute within the insight object. I changed the attribute type from user to group and added the group to the object but it didn't show in the group picker field.
I believe group attributes somewhere need to be defined. I was not able to figure it out. How can define groups instead of users for the system approver attribute? Also, where can I find all these system objects, attribute beans, etc code information? I am still learning I'm able to create a simple script that can define a field with a name or id, but these are complicated. Can you recommend something that I can find these kinds of code for the future?
Thank you for your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Are you talking about "Group" attribute type in Insight? Or group picker custom field in Jira?
Here is a version of the script that will look into a group attribute (named Approval Group) and retrieve all the active users from the selected group(s).
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeBean
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeValueBean
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
@PluginModule ObjectTypeAttributeFacade objectTypeAttributeFacade
def groupManager = ComponentAccessor.groupManager
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def groupAttribute = "Approval Group"
def defaultApprovers = ['projLead']
def systemVal = systemFld.value
if(!systemVal){
//nothing selected, nothing to do, exit the script
return
}
def selectedKey
if(systemVal instanceof List){
selectedKey = systemVal[0] //There are multiple. Get only the first one
} else {
selectedKey = systemVal //This is what we get where there is a single value (whether multiple are allowed of not)
}
if(systemVal){
def systemObject = objectFacade.loadObjectBean(selectedKey)
def groupAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttribute(systemObject.objectTypeId, groupAttribute)
def groupObjectAttribute = systemObject.objectAttributeBeans.find{ it.objectTypeAttributeId == groupAttributeBean.id }
def approverUsers = groupObjectAttribute.objectAttributeValueBeans.collect{
groupManager.getUsersInGroup(it.value as String).findAll{it.active}
}.flatten().unique()
def approvers = defaultApprovers
if(approverUsers){
approvers = approverUsers*.name
}
approversFld.setFormValue(approvers.join(', '))
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @PD Sheehan yes I was asking about Group attribute type in Insight. I created the "Approval Group" attribute associated with a group and it works fine. However, the default user part is not working. I mean if the "Approval Group" attribute is empty for an object like if there is no group added in "Approval Group" for the "Windows Server" object then it is not taking the default user that mentions in the script. How can I fix that? Thank you so much for your help.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Try like this:
import com.atlassian.jira.component.ComponentAccessor
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeBean
import com.riadalabs.jira.plugins.insight.services.model.ObjectAttributeValueBean
import groovy.transform.BaseScript
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectFacade
import com.riadalabs.jira.plugins.insight.channel.external.api.facade.ObjectTypeAttributeFacade
@WithPlugin('com.riadalabs.jira.plugins.insight')
@BaseScript FieldBehaviours fieldBehaviours
@PluginModule ObjectFacade objectFacade
@PluginModule ObjectTypeAttributeFacade objectTypeAttributeFacade
def groupManager = ComponentAccessor.groupManager
def systemFld = getFieldById('customfield_10403')
def approversFld = getFieldById('customfield_10410')
def groupAttribute = "Approval Group"
def defaultApprovers = ['projLead']
def systemVal = systemFld.value
if(!systemVal){
//nothing selected, nothing to do, exit the script
return
}
def selectedKey
if(systemVal instanceof List){
selectedKey = systemVal[0] //There are multiple. Get only the first one
} else {
selectedKey = systemVal //This is what we get where there is a single value (whether multiple are allowed of not)
}
if(systemVal){
def systemObject = objectFacade.loadObjectBean(selectedKey)
def groupAttributeBean = objectTypeAttributeFacade.loadObjectTypeAttribute(systemObject.objectTypeId, groupAttribute)
def groupObjectAttribute = systemObject.objectAttributeBeans.find{ it.objectTypeAttributeId == groupAttributeBean.id }
def approvers = defaultApprovers
def approverUsers
if(groupObjectAttribute && groupObjectAttribute.objectAttributeValueBeans) {
approverUsers = groupObjectAttribute.objectAttributeValueBeans.collect {
groupManager.getUsersInGroup(it.value as String).findAll { it.active }
}.flatten().unique()
}
if(approverUsers){
approvers = approverUsers*.name
}
approversFld.setFormValue(approvers.join(', '))
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
It works, thank you so much @PD Sheehan
Do you have any recommendations? how can learn about all this scripting stuff? Thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Glad I was able to help.
Please be sure to mark the response as accepted.
As for learning scripting, having some coding background helps.
Adaptavist (the maker of scriptrunner) offer this on their site.
Beyond that, I think there is no better learning than by doing. You have to experiment and fail and try again until you build the experience of what works and what doesn't.
Start by taking existing scripts either from here in the community or from the library.adaptivist.com and then change them to suit your different requirements.
Throw various statements to the log and inspect the results as you change a keyword or line.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.