Script Runner之Behavior功能应用实例
Script Runner之Behavior功能应用实例
Scripts Runner的behavior功能实在是令人惊叹,用来实现页面上的输入限制或者自动输入时,相当的方便。这段视频中展示的效果,就是通过Scripts Runner达成的。
在任务分解的时候,大家很自然的希望能够自动将任务的开始时间设置为当前时间或明天,到期日可以根据工作量预估自动的计算,如果有前置任务的话,开始时间能够自动安排在前置任务完成时间之后,如果还能够避开周末或节假日就更完美了。而这个想法,通过Script Runner的Behavior+groovy定制化脚本开发,变得并不是那么的难以实现了。
需求描述
开始日期:默认为当前日期+1,若添加了问题链接为”is blocked by”的子任务,则根据所有阻塞任务计算最晚到期日,此时创建issue的开始日期=最晚到期日+1,开始日期也允许自行选择更晚的时间
工期预估:默认为1,允许自行输入,单位为工作日
到期日:根据开始时间+工期预估获得,计算时需剔除周末及节假日
由于JIRA的内置字段中并没有开始日期,首先需要创建一个日期型的自定义字段:开始日期,字段类型选择为:日期选择器
需求中要求工期预估的单位为天,因此新建一个数值型的字段”预计工期”
接下来需要在Behavior插件中配置”开始日期”、”预计工期”、”到期日”及”问题链接”这几个字段的行为干预。
Behavior设置
【设置】->【插件】->【Behaviors】,添加一个Behavior
点击下图中的【Field】或【Add Mapping】进行行为设置
【Add Mapping】主要是设置该行为在什么项目中,针对什么问题类型生效,刚开始的时候,可以只选择测试的项目,测试通过后再向所有项目开放。
接下来就是配置的重头戏【Field】,这部分的设置分为两块,第一块是初始化配置,第二部分是针对监听的字段进行设置。
在此二次开发的groovy脚本既可以使用inline scripts的方式,也可以指定一个服务器上的groovy文件
如果要指定服务器上的groovy文件,需要将这个文件放在指定的目录里。
Scripts Runner默认的为 /application-data/scripts,把groovy脚本按照包名的路径存放即可,此时就可以在配置界面上指定脚本路径,在输入脚本名字的时候,插件会自动的显示脚本路径,非常的方便。
具体的脚本内容不详细贴出和介绍了,这里介绍几个脚本开发中的技巧。
groovy脚本示例
1. 使用File的方式,需要在脚本前import如下内容
import com.onresolve.jira.groovy.user.FieldBehaviours
import com.onresolve.jira.groovy.user.FormField
import groovy.transform.BaseScript
@BaseScript FieldBehaviours fieldBehaviours
2. Field中添加的字段为脚本需要监听内容变化的字段,可以根据字段的内容变 化进行相应的设置。
如例子中监听的是”链接的问题”字段,这是个比较复杂的二级级联控件,以下代码可以实现根据选择的 issuetype为”is blocked by”的阻塞issue列表,计算最晚的开始日期。
def linkedIssuesCF = getFieldById(getFieldChanged()) //监听字段变化使用getFieldChanged()方法
def issueLinksCF = getFieldById("issuelinks-linktype") //获取某个字段Form,则直接指定字段id或Name
def linkedIssueForm = getFieldById("issuelinks-issues")
def begindateForm = getFieldByName("开始日期")
if ( issueLinksCF.getFormValue() == "is blocked by" ) { //对应FormField.getFormValue()的方法可以获取字段值
if ( linkedIssueForm.getValue() instanceof java.util.List ) {
keys = ((String[])linkedIssueForm.getValue()).toList()
}else if (linkedIssueForm.getValue()){ //getValue()方法返回对象,getFormValue()方法返回String
keys.add((String)linkedIssueForm.getValue())
}else{
log.info("linked issue is empty!")
}
import dateHandler //这里使用了一个import的handler脚本,用以循环获取所有的阻塞任务到期日,以此计算被阻塞任务开始日期
def handler = new dateHandler()
latest_begin_date = handler.getLatestBeginDate(latest_begin_date,keys)
begindateForm.setFormValue(latest_begin_date) //设置字段值
}
每个FormField可以根据ID或name获取,在浏览器访问时按F2,通过查找页面元素的方法,找到对应form的id或name。
例如:
FormField = getFieldById("duedate")
or
FormField = getFieldByName("预计工期")
3. 设置Form的值
FormField.setFormValue()
4. 设置Form为只读:
FormField.setReadOnly(true)
5. 设置Form报错:
FormField.setError()
6. 当输入正确值后,需要清除这个报错:
FormField.clearError()
7. hidden的Form对应的值也可以读出,例如在子任务创建时,读出隐藏的 Issue id:
issueidForm = getFieldById("id")
dateHandler.groovy
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.component.ComponentAccessor
import java.text.SimpleDateFormat;
SimpleDateFormat sdf_date = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
def String getLatestBeginDate (String begindate, List keys) {
def issueManager = ComponentAccessor.getIssueManager()
def d_latest_begin_date = sdf_date.parse(begindate)
Calendar cal = Calendar.getInstance();
cal.setTime(d_latest_begin_date)
if (keys) {
for ( String key in keys) {
def linkedIssue = issueManager.getIssueObject(key)
if (linkedIssue) {
if (linkedIssue.dueDate ) {
if ( linkedIssue.dueDate.after(d_latest_begin_date) ){
d_latest_begin_date = linkedIssue.dueDate
}
}
}
}
}
if (d_latest_begin_date.after(sdf_date.parse(begindate))){
cal.setTime(sdf.parse(sdf_date.format(d_latest_begin_date) +" 23:59:59"));
cal.add(Calendar.SECOND,1)
}
return sdf_date.format(cal.getTime())
}
根据问题链接来计算被阻塞任务的开始时间,实现起来最为复杂,因此在本例中列举,其余根据开始日期、预计工期和到期日相互计算的过程就不一一赘言了。
到期日计算时剔除周末和节假日,则是另外写了个WorkCalendar.groovy来实现,在到期日碰到周末或者节假日时会自动顺延。
其实JIRA的DateUtils类已经实现了非周末的工作日计算,只是并没有剔除节假日,如果对节假日顺延并不特别在意的话,可以直接使用DateUtils类来计算。
上一篇: npm script之传参