Hi all !
I would like to see with the script runner master if you got any tips on behaviours optimizations.
I found that there too much-repeated part of code on behaviour for me to consider this good and easy to maintain.
I remember finding a piece of behaviour code using array at start, handling customfield value and then using a .find() to set the hidden field in one time.
I can’t find something similar, and I’ve not kept the page in fav. Is someone using something cleaner to declare behaviours.
On another hand, do you have some tips on optimizing behaviours in a huge instance?
Thanks so much all !
Here is how I would rewrite the snippet you shared below...
Please note that based on the offerec script logic, I was only seeing 2 fields ever set visible: alert and categorie
def opt1 = 'Vulnérabilité'
def opt2 = 'Incident'
def opt3 = '...'
def fieldsConfigs = [
[id: 'customfield_10302', showOptions: [opt2]], //categorie
[id: 'customfield_10303',showOptions: []],//devicetype
[id: 'customfield_10304',showOptions: []], //attacktype
[id: 'customfield_10305',showOptions: []],//securitydevice
[id: 'customfield_10306',showOptions: []],//behaviourtype
[id: 'customfield_10307',showOptions: []], //cvftype
[id: 'customfield_10308', showOptions: [opt1], defaultValue: 10034],//alert
]
def decisionField = getFieldById('customfield_10301')
def decisionFieldVal = decisionField.value as String
fieldsConfigs.each { map ->
def hide = !map.showOptions.any { List<String> it -> decisionFieldVal.contains(it) }
def field = getFieldById(map.id)
field.setHidden(hide)
if (hide) {
field.setFormValue(null)
} else {
if(map.defaultValue) field.setFormValue(map.defaultValue)
}
}
The idea is to create a structured object that contains what you want to do for each field and then go through each item and perform the specified actions.
@Florian PEREZ - this is for ScriptRunner on-premise, yeah?
If you have Behaviors sharing the same code (either the initializer or for specific custom field/s), consider storing the script/s in a File instead of writing code inline?
Unsure if it's possible to share specific chunks of code in a file (or inline) across Behaviors.
p.s. I love your idea for this post!
Hey @Peter-Dave Sheehan & @Dave Liao
@Dave Liao Of course we're exited about hearing the new behaviour on cloud but I'm talking about on premise behaviour, you guess it right !
Btw Unsure if it's possible to share specific chunks of code in a file (or inline) across Behaviors.
This could be a huge part of optimization, but it can make the maintain more complex for other admins and since we're not all pure dev I'm more considering about pure interface optimisation.
I've done some research and find (easily on first page of google :'D) the following article for reference : https://coyotecrk.com/2016/11/23/best-practices-scriptrunner-behaviours/
I still find that the part they call recommended code is not so good :
This behaviour is kind of short considering the global capabilities of Scriptrunner Behaviours. I still think there repeated portion of code ( the get fieldById() or the .value.contain() part for exemple). I did not like this as an ex dev knowing the concepts of DRY and code smells and this code is only about one field, imagine if we had 10 or 20 customfields in conditions...
This was my start point about creating this article.
That’s a good point, not all admins would necessarily be devs or have dev experience.
I feel like we would want to translate some of the (by necessity) UX from ScriptRunner Cloud to on-prem?
I wonder if I can get someone from Adaptavist to comment on this discussion… @Nic Brough -Adaptavist- 👋 😉
Hi @Peter-Dave Sheehan I came back with an exemple of what I'm trying to improve:
// Hide other fields depending on 'Type'
def
decisionField = getFieldById(
'customfield_10301'
)
// Get a pointer to the fields to hide/show
def
categorie = getFieldById(
'customfield_10302'
)
def
devicetype = getFieldById(
'customfield_10303'
)
def
attacktype = getFieldById(
'customfield_10304'
)
def
securitydevice = getFieldById(
'customfield_10305'
)
def
behaviourtype = getFieldById(
'customfield_10306'
)
def
vcftype = getFieldById(
'customfield_10307'
)
def
alert = getFieldById(
'customfield_10308'
)
// Get the select list field value
def
decisionFieldVal = decisionField.getValue()
// Hide fields based on value
if
(decisionFieldVal.toString().
contains
(
"Vulnérabilité"
))
{
categorie.setHidden(true)
categorie.setFormValue(-
1
)
devicetype.setHidden(true)
devicetype.setFormValue(-
1
)
attacktype.setHidden(true)
attacktype.setFormValue(-
1
)
securitydevice.setHidden(true)
securitydevice.setFormValue(-
1
)
behaviourtype.setHidden(true)
behaviourtype.setFormValue(-
1
)
vcftype.setHidden(true)
vcftype.setFormValue(-
1
)
alert.setHidden(false)
alert.setFormValue(
10034
)
}
else
if
(decisionFieldVal.toString().
contains
(
"Incident"
))
{
categorie.setHidden(false)
devicetype.setHidden(true)
attacktype.setHidden(true)
securitydevice.setHidden(true)
behaviourtype.setHidden(true)
vcftype.setHidden(true)
alert.setHidden(true)
alert.setFormValue(-
1
)
}
else
{
categorie.setHidden(true)
devicetype.setHidden(true)
attacktype.setHidden(true)
securitydevice.setHidden(true)
behaviourtype.setHidden(true)
vcftype.setHidden(true)
alert.setHidden(true)
alert.setFormValue(-
1
)
}
Hope this can help to figure out what i'm trying to do !
def ComposantField = getFieldById('customfield_14087');
def ITServiceField = getFieldById('customfield_14707');
def PerimetreField = getFieldById('customfield_14708');
def ssSystemeField = getFieldById('customfield_12503');
def plateformeField = getFieldById('customfield_12501');
def multiSelectValue = PerimetreField.value as List
if(PerimetreField.getValue() == ["IT","Legacy"]){
//ComposantField.setHidden(false);
//ITServiceField.setHidden(false);
//ssSystemeField.setHidden(true);
//plateformeField.setHidden(true);
//ssSystemeField.setRequired(false);
//plateformeField.setRequired(false);
[ssSystemeField, plateformeField].each { it.setHidden(true) }
[ComposantField, ITServiceField].each { it.setHidden(false) }
[ssSystemeField, plateformeField].each { it.setRequired(false) }
}
else if (PerimetreField.getValue() == "IT")
{
//ComposantField.setHidden(true);
//ssSystemeField.setHidden(true);
//plateformeField.setHidden(true);
//ITServiceField.setHidden(false);
//ssSystemeField.setRequired(false);
//plateformeField.setRequired(false);
[ssSystemeField, plateformeField,ComposantField].each { it.setHidden(true) }
[ComposantField, ITServiceField].each { it.setHidden(false) }
[ssSystemeField, plateformeField].each { it.setRequired(false) }
}
else if (PerimetreField.getValue() == "Legacy")
{
//ComposantField.setHidden(false);
//ITServiceField.setHidden(true);
//ssSystemeField.setHidden(true);
//plateformeField.setHidden(true);
//ssSystemeField.setRequired(false);
//plateformeField.setRequired(false);
[ComposantField].each { it.setHidden(true) }
[ITServiceField,ssSystemeField, plateformeField].each { it.setHidden(false) }
[ssSystemeField, plateformeField].each { it.setRequired(false) }
}
else if (PerimetreField.getValue() == "GDS")
{
//ComposantField.setHidden(true);
//ITServiceField.setHidden(true);
//ssSystemeField.setHidden(false);
//plateformeField.setHidden(false);
//ssSystemeField.setRequired(true);
//plateformeField.setRequired(true);
[ComposantField,ITServiceField].each { it.setHidden(true) }
[ssSystemeField, plateformeField].each { it.setHidden(false) }
[ssSystemeField, plateformeField].each { it.setRequired(true) }
}
else {
//ssSystemeField.setRequired(true);
//plateformeField.setRequired(true);
//ssSystemeField.setFormValue(" ");
//plateformeField.setFormValue(" ");
[ssSystemeField, plateformeField].each { it.setRequired(true) }
[ssSystemeField, plateformeField].each { it.setFormValue(" ") }
}
Ooh, I like this!