Twisting JIRA Service Desk to manage multiple-choice forms


Posted by
Thomas BOUDIER

April 20, 2017

Whenever you take a training course, there’s always a couple of big question marks: do you belong in the class’s target audience, so the material is neither too advanced or too easy? Will it be in line with your expectations? It’s not always easy – for both the trainer and the trainee – to ensure the material will leave the customer 100% satisfied at the end of the class.

But there are ways to handle these expectations – how about just asking people upfront?

Offering quizzes to test the trainee’s level – both before the class to gain a sense of their current knowledge and again afterwards to check what material was absorbed – is an efficient way to assess what is working and change course when a teaching method is not working.

As Valiantys is an Atlassian Platinum Solution partner, we pride ourselves on enabling our customers to reach their fullest potential on the Atlassian suite through our training courses – improving how we deploy our training programmes is something we value and continuously try to improve upon.  With our quizzes, we’ve found that this quick, formalised recap often leads to a few final questions, clarifies lingering vagueness and provides additional recommendations from our expert consultant. It was the way to move our trainings forward.

In this blog, we share insights on why we picked JIRA Service Desk and some tips on how you can build quizzes with this powerful tool.

JIRA Service Desk as the evident answer

Our requirements

When searching for the right solution, we had a few points we needed to address:

  • Anyone should be able to take the tests without the need for our administrator to pre-register candidates manually. Manual registrations would be a tedious operation considering the numerous training courses we deliver. Furthermore, it would be impossible for potential students to be able to take the exam themselves online so they could check if they meet the prerequisites.
  • There should be an automated process for score calculation. Most form tools are designed around the idea of surveying customers: asking them for feedback or entering contact information for event registration – with no right or wrong answer. Yet our intent was to have a quiz that could deliver results immediately, with no human validation needed to return the score. Of course we can manually review the results at the end of our in-class trainings to answer follow-up questions, however we need something more instantaneous for testing the prerequisites.
  • The results should not be public, yet all our trainers should have an easy and autonomous access to the results of their trainees.
  • The tool should be user-friendly so it could be quickly deployed at Valiantys, and ideally customised in the future for evolving needs.

Choosing the right tool

Several tools were investigated, such as Google Forms, SurveyMonkey or Typeform, but none of them could fit perfectly with all of our top requirements. Sometimes calculating the score was ridiculously complicated to setup, sometimes customisation was too difficult, sometimes issues arose from managing access permissions to responses (for confidentiality reasons, we don’t want everyone to see the results!).

Using JIRA became increasingly evident as the right choice. In order to avoid any issues with the licenses, we turned to JIRA Service Desk.

JIRA Service Desk is the best tool to avoid manually entering each and every single participant’s contact information beforehand in the user database: test takers can register themselves, and they don’t need consume any licenses on the system.

Creating the quiz application in JIRA Service Desk

Once the tool was selected, there were several different choices we needed to make in order to implement the questionnaire: do we want questions to be asked one after the other, and evaluated straight away? Or are we happy with one single page per test? We went with the latter option.

Managing questions

For each multiple choice question, one custom field was set; either with radio buttons when there’s only one correct answer, or with checkboxes when several items must be selected for the answer to be right.

Radio

Creating one test per course

Every test has its own issue type. The associated screen contains all the questions (custom fields) that are linked to this specific test, plus a “score” field, contained in the issue but hidden from the associated request.

Tests are set as service desk request types, and the questions are the fields in the requests.

ProjectSetting

Calculating scores

A script is used for score calculation: for every request type, a template issue is filled with the right replies, and tagged as “template.”

Template

Then every time a request of the same type is filled, the script retrieves the corresponding template issue (with the right answers marked), compares the value of each custom field in the template issue and in the newly submitted issue, and the score is calculated depending on how many common replies they have. The script also writes which questions were answered correctly or incorrectly in the comments of the request.

Prereq Screen Shot

Here is the script we used:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.fields.screen.issuetype.IssueTypeScreenSchemeManager
import com.atlassian.jira.issue.operation.IssueOperations
import com.atlassian.jira.issue.fields.screen.issuetype.IssueTypeScreenSchemeImpl
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.project.Project
import com.atlassian.jira.project.ProjectManager
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.workflow.WorkflowTransitionUtil
import com.atlassian.jira.workflow.WorkflowTransitionUtilImpl
import com.atlassian.jira.util.JiraUtils
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.bc.issue.IssueService.TransitionValidationResult
import com.atlassian.jira.bc.issue.IssueService
import com.atlassian.jira.issue.IssueInputParameters
import com.atlassian.jira.issue.IssueInputParametersImpl

def MutableIssue issue = (MutableIssue) event.getIssue()
def issueService = ComponentAccessor.getIssueService()

Project issueproject = issue.getProjectObject()
WorkflowTransitionUtil workflowTransitionUtil = (WorkflowTransitionUtil) JiraUtils.loadComponent(WorkflowTransitionUtilImpl.class)
CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()

// Get the template (10/10) issue
def keyT = "MCQ-16"
def template = ComponentAccessor.getIssueManager().getIssueObject(keyT)

def issueTypeScreenSchemeManager = ComponentAccessor.getIssueTypeScreenSchemeManager()
def issueTypeScreenScheme = issueTypeScreenSchemeManager.getIssueTypeScreenScheme(issueproject)
def fieldScreenScheme = issueTypeScreenScheme.getEffectiveFieldScreenScheme(issue.getIssueType())
def fieldScreen = fieldScreenScheme.getFieldScreen(IssueOperations.EDIT_ISSUE_OPERATION)

// Get the QCM tab
def tab = fieldScreen.getTab(1)

// Get all the CF ids from a specific tab
// Compare the value of each CF to calaculate the final score
def score = 0
def fieldIds = tab.getFieldScreenLayoutItems()*.fieldId
fieldIds.each{fieldId->
def CF = customFieldManager.getCustomFieldObject(fieldId)
log.info(fieldId)
log.info("Value for issue = " + CF.getValue(issue))
log.info("Value for template = " + CF.getValue(template))
if(CF.getValue(issue) == CF.getValue(template)){
score++
}
log.info("score = " + score)
}

log.debug(score)

// Perform the appropriate transition regarding the score
if(score == 0){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(41)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 1){
log.debug("----- Score est 1 " + ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser() )
log.debug("issueid : " + issue.getId())
def transitionResult = issueService.validateTransition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), Long.valueOf(issue.getId()), 51, new IssueInputParametersImpl())
if (transitionResult.isValid()){
log.debug("----- Transition valid")
issueService.transition(ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser(), transitionResult)
}else{
}

/*workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(51)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()*/
}else if(score == 2){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(61)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 3){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(71)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 4){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(81)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 5){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(91)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 6){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(101)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 7){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(111)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 8){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(11)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 9){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(21)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}else if(score == 10){
workflowTransitionUtil.setIssue(issue)
workflowTransitionUtil.setUserkey("robot")
workflowTransitionUtil.setAction(31)
workflowTransitionUtil.validate()
workflowTransitionUtil.progress()
}

If you think that setting up a similar form on your JIRA would be helpful, but you lack sufficient knowledge of Atlassian tools, maybe some additional coaching from Valiantys could be of help! We offer hands-on, personalised learning and you’re guaranteed to get the right return on your investment. Check out our available courses below!

Our Training Courses