Uploaded image for project: 'Jira Software Data Center'
  1. Jira Software Data Center
  2. JSWSERVER-10725

Sub-task rank on Work tab doesn't mirror actual sub-task rank within issue

    • Icon: Suggestion Suggestion
    • Resolution: Unresolved
    • None
    • None
    • local installed (downloaded)
    • 2
    • 6
    • We collect Jira feedback from various sources, and we evaluate what we've collected when planning our product roadmap. To understand how this piece of feedback will be reviewed, see our Implementation of New Features Policy.

      Reproduce steps:
      1- Created new issue (type- story)
      2- Added many sub-tasks
      3- Within issue, re-ranked items to match business priority
      4- When viewing in work tab in Jira Agile, the sequence is NOT:

      • the sequence displayed in the ticket
      • the sequence it was entered
      • any other sequence we can determine

      Sprint team must open ticket to see priorities, which defeats point of board.

      Found in: JIRA Agile 6.3.13.1, Jira Version: v6.2.3#6260-sha1:63ef1d6 (installed by us in AWS cloud)

      I've see other tickets here, but most of them are closed from prior versions... I'm guessing this is a duplicate of another request, but couldn't find an open one to comment on.

          Form Name

            [JSWSERVER-10725] Sub-task rank on Work tab doesn't mirror actual sub-task rank within issue

            I wrote this ScriptRunner script in order to automate the rank of the issues depending on the sequence displayed. Thanks @David Waldhans for his snippet, it was so helpful to make this possible. Disclaimer, this is a slow method, so if you use it, you will reach the ScriptRunner timeout (60 seconds) constantly.

            import org.apache.log4j.Level
            import com.atlassian.jira.bc.issue.search.SearchService
            import com.atlassian.jira.component.ComponentAccessor
            import com.atlassian.jira.issue.search.SearchException
            import com.atlassian.jira.web.bean.PagerFilter
            import org.apache.log4j.Level
            
            import com.atlassian.jira.issue.Issue
            import com.atlassian.greenhopper.api.rank.RankService
            import com.onresolve.scriptrunner.runner.customisers.WithPlugin
            import com.onresolve.scriptrunner.runner.customisers.JiraAgileBean
            import com.atlassian.jira.component.ComponentAccessor
            
            @WithPlugin('com.pyxis.greenhopper.jira')
            
            @JiraAgileBean
            RankService rankService
            
            def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser
            def rank = rankService.getRankFields()[0].getIdAsLong()
            
            // Set log level to INFO
            log.setLevel(Level.INFO)
            
            // The JQL query you want to search with
            final jqlSearch = 'project = <your_project> and issuetype = "Master Ticket" and statusCategory != Done'
            
            // Parsing the query
            def searchService = ComponentAccessor.getComponentOfType(SearchService)
            def parseResult = searchService.parseQuery(user, jqlSearch)
            if (!parseResult.valid) {
                log.error('Invalid query')
                return null
            }
            
            try {
                // Perform the query to get the parent issues
                def results = searchService.search(user, parseResult.query, PagerFilter.unlimitedFilter)
                def issues = results.results
            
                // We now have the list of the parent issues, we will find which ones need to be "re-ranked"
                issues.each { parentIssue ->
                    // Getting the subtasks    
                    Collection subTasks = parentIssue.getSubTaskObjects()
                    // Sorting the subtasks by the displayed sequence
                    List sortedSubTasks = new ArrayList(subTasks.size())
                    subTasks.each { subtask ->
                        def subTaskLink = ComponentAccessor.issueLinkManager.getInwardLinks(subtask.id).find {
                            it.issueLinkType.name == "jira_subtask_link"
                        }
                        sortedSubTasks[subTaskLink.sequence] = subtask
                    }
            
                    List visibleSequencedSubtasksList = sortedSubTasks*.key
            
                    // Getting the same subtasks but ordered by rank to compare with the previous list
                    String rankedSubTasksJql = "PARENT = $parentIssue.key ORDER BY Rank ASC"
                    parseResult = searchService.parseQuery(user, rankedSubTasksJql)
                    results = searchService.search(user, parseResult.query, PagerFilter.unlimitedFilter)
                    def rankedSubtasksList = results.results*.key
            
                    // Comparing
                    if (visibleSequencedSubtasksList != rankedSubtasksList){
                        log.info("Parent $parentIssue.key needs re-rank")
                        log.info("Visible sequence : $visibleSequencedSubtasksList")
                        log.info("Ranked subtasks : $rankedSubtasksList")
                        
                        // Ok, let's sort them. 
                        // This is a slow method, since it is one call for each subtask. 
                        // It could be faster by using rankAfter or rankBefore only on the unordered subtasks.
                        // to improve the api calls.
                        // I recommend to first comment this block to check how many issues need to re-rank.
                        sortedSubTasks.each { subtask ->
                            rankService.rankLast(user, rank, subtask)
                        }
                    }
                }
            } catch (SearchException e) {
                e.printStackTrace()
                null
            }

            David Carrera del Castillo added a comment - - edited I wrote this ScriptRunner script in order to automate the rank of the issues depending on the sequence displayed. Thanks @David Waldhans for his snippet, it was so helpful to make this possible. Disclaimer, this is a slow method, so if you use it, you will reach the ScriptRunner timeout (60 seconds) constantly. import org.apache.log4j.Level import com.atlassian.jira.bc.issue.search.SearchService import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.search.SearchException import com.atlassian.jira.web.bean.PagerFilter import org.apache.log4j.Level import com.atlassian.jira.issue.Issue import com.atlassian.greenhopper.api.rank.RankService import com.onresolve.scriptrunner.runner.customisers.WithPlugin import com.onresolve.scriptrunner.runner.customisers.JiraAgileBean import com.atlassian.jira.component.ComponentAccessor @WithPlugin( 'com.pyxis.greenhopper.jira' ) @JiraAgileBean RankService rankService def user = ComponentAccessor.jiraAuthenticationContext.loggedInUser def rank = rankService.getRankFields()[0].getIdAsLong() // Set log level to INFO log.setLevel(Level.INFO) // The JQL query you want to search with final jqlSearch = 'project = <your_project> and issuetype = "Master Ticket" and statusCategory != Done' // Parsing the query def searchService = ComponentAccessor.getComponentOfType(SearchService) def parseResult = searchService.parseQuery(user, jqlSearch) if (!parseResult.valid) { log.error( 'Invalid query' ) return null } try { // Perform the query to get the parent issues def results = searchService.search(user, parseResult.query, PagerFilter.unlimitedFilter) def issues = results.results // We now have the list of the parent issues, we will find which ones need to be "re-ranked" issues.each { parentIssue -> // Getting the subtasks Collection subTasks = parentIssue.getSubTaskObjects() // Sorting the subtasks by the displayed sequence List sortedSubTasks = new ArrayList(subTasks.size()) subTasks.each { subtask -> def subTaskLink = ComponentAccessor.issueLinkManager.getInwardLinks(subtask.id).find { it.issueLinkType.name == "jira_subtask_link" } sortedSubTasks[subTaskLink.sequence] = subtask } List visibleSequencedSubtasksList = sortedSubTasks*.key // Getting the same subtasks but ordered by rank to compare with the previous list String rankedSubTasksJql = "PARENT = $parentIssue.key ORDER BY Rank ASC" parseResult = searchService.parseQuery(user, rankedSubTasksJql) results = searchService.search(user, parseResult.query, PagerFilter.unlimitedFilter) def rankedSubtasksList = results.results*.key // Comparing if (visibleSequencedSubtasksList != rankedSubtasksList){ log.info( "Parent $parentIssue.key needs re-rank" ) log.info( "Visible sequence : $visibleSequencedSubtasksList" ) log.info( "Ranked subtasks : $rankedSubtasksList" ) // Ok, let's sort them. // This is a slow method, since it is one call for each subtask. // It could be faster by using rankAfter or rankBefore only on the unordered subtasks. // to improve the api calls. // I recommend to first comment this block to check how many issues need to re-rank. sortedSubTasks.each { subtask -> rankService.rankLast(user, rank, subtask) } } } } catch (SearchException e) { e.printStackTrace() null }

            David W. added a comment - - edited

            Update: Since Jira seems to sort number values from scripted fields lexically (1, 10, 11, 2...) instead of numerically (1, 2, 3...), I updated the description below to return a string value with a three digit number that is left-padded with zeros.

            @Matt Parks thanks to your comment I found a solution to do this using a ScriptRunner scripted field returning a template of type "Text Field (multi-line)".

            Here is the script for the field:

            import com.atlassian.jira.component.ComponentAccessor
            
            def issueLinkManager = ComponentAccessor.issueLinkManager
            
            if (!issue.isSubTask()) {
                return null
            }
            
            def subTaskLink = issueLinkManager.getInwardLinks(issue.id).find {
                it.issueLinkType.name == "jira_subtask_link"
            }
            
            return subTaskLink ? String.format("%03d", subTaskLink.sequence) : null
            

            You do not need to add the field to any screen in order to be able to use it. Just write a JQL query returning the desired sub-tasks and use the scripted field in the ORDER BY clause.

            Hope this helps!

            David W. added a comment - - edited Update: Since Jira seems to sort number values from scripted fields lexically (1, 10, 11, 2...) instead of numerically (1, 2, 3...), I updated the description below to return a string value with a three digit number that is left-padded with zeros. @Matt Parks thanks to your comment I found a solution to do this using a ScriptRunner  scripted field returning a template of type "Text Field (multi-line)". Here is the script for the field: import com.atlassian.jira.component.ComponentAccessor def issueLinkManager = ComponentAccessor.issueLinkManager if (!issue.isSubTask()) { return null } def subTaskLink = issueLinkManager.getInwardLinks(issue.id).find { it.issueLinkType.name == "jira_subtask_link" } return subTaskLink ? String .format( "%03d" , subTaskLink.sequence) : null You do not need to add the field to any screen in order to be able to use it. Just write a JQL query returning the desired sub-tasks and use the scripted field in the ORDER BY clause. Hope this helps!

            Paul added a comment -

            This problem exists since 2014 - how many votes are required to fix it? 

            Paul added a comment - This problem exists since 2014 - how many votes are required to fix it? 

            Ed Bukoski added a comment -

            I arrived here because of JSWSERVER-12409.  All I would like is the screen in Jira to reflect the actual ordering and I don't care about the rest of the stuff mentioned in this ticket.  Users shouldn't have to manually hit refresh after a data update.  If you could just refresh the issue screen after a reorder so it reflects reality it would save a lot of confusion. 

            This seems to have been (unnecessarily) wrapped into a larger issue and now has been dragged out for years.

             

            Ed Bukoski added a comment - I arrived here because of  JSWSERVER-12409 .  All I would like is the screen in Jira to reflect the actual ordering and I don't care about the rest of the stuff mentioned in this ticket.  Users shouldn't have to manually hit refresh after a data update.  If you could just refresh the issue screen after a reorder so it reflects reality it would save a lot of confusion.  This seems to have been (unnecessarily) wrapped into a larger issue and now has been dragged out for years.  

            Matt Parks added a comment -

            When I look at the API, I see that the SubTask class has two methods, getDisplaySequence() and getSequence().

            I'm trying to create a Scripted Field that will store the value from getDisplaySequence() (which is a Long) on every issue that is a sub-task. That way, the filter for my Kanban board can order by this field (instead of Rank, which doesn't work).

            However, Scripted Fields seem to run on objects with a class of Issue, not SubTask, and the two methods are not part of the Issue class.

            Is there a way, within the script of the Scripted Field, to cast the object so that it is a SubTask, not an Issue?

            Matt Parks added a comment - When I look at the API, I see that the SubTask class has two methods, getDisplaySequence() and getSequence(). I'm trying to create a Scripted Field that will store the value from getDisplaySequence() (which is a Long) on every issue that is a sub-task. That way, the filter for my Kanban board can order by this field (instead of Rank, which doesn't work). However, Scripted Fields seem to run on objects with a class of Issue, not SubTask, and the two methods are not part of the Issue class. Is there a way, within the script of the Scripted Field, to cast the object so that it is a SubTask, not an Issue?

            Please note the linked ticket JSWSERVER-12409 "Rank to Top and Rank to Bottom do not work". In that ticket it says work on that issue will be tracked in this ticket.

            Dennis van den Berg added a comment - Please note the linked ticket  JSWSERVER-12409  "Rank to Top and Rank to Bottom do not work". In that ticket it says work on that issue will be tracked in this ticket.

            Since JIRA Agile and JIRA classic are now merged into the same product JIRA Software, I would expect it to work as suggested by the community. Thanks in advance

            Xavier Barry added a comment - Since JIRA Agile and JIRA classic are now merged into the same product JIRA Software, I would expect it to work as suggested by the community. Thanks in advance

            Kevin E. Schlabach added a comment - - edited

            A user can't rank issues while viewing the Work tab in Jira Agile... this tab reads the existing data for sequence display (I think users understand this). If the stories/bugs read the issue's "rank" field to set sequence (which is a field available outside of Jira Agile also), why don't the sub-tasks on the Work tab read the issue sub-task rank within the issue and similarly display per that?

            I guess I understand what you said, but you formulated the issue as the reverse of what I would have expected. (If I were writing the story for the backlog). Also, I understand that this is a "feature" but kind of shocked that Jira Agile didn't have this baked in from the start as it could be considered fundamental to Agile.

            Kevin E. Schlabach added a comment - - edited A user can't rank issues while viewing the Work tab in Jira Agile... this tab reads the existing data for sequence display (I think users understand this). If the stories/bugs read the issue's "rank" field to set sequence (which is a field available outside of Jira Agile also), why don't the sub-tasks on the Work tab read the issue sub-task rank within the issue and similarly display per that? I guess I understand what you said, but you formulated the issue as the reverse of what I would have expected. (If I were writing the story for the backlog). Also, I understand that this is a "feature" but kind of shocked that Jira Agile didn't have this baked in from the start as it could be considered fundamental to Agile.

            Hi,
            The sub task list in the View Issue page is part of JIRA and is not controlled by JIRA Agile. The ranking for sub tasks on the issue is different than the ranking of sub tasks on an Agile board. I'll convert this issue to a feature request.
            Regards,
            JIRA Agile team

            MichaelA (Inactive) added a comment - Hi, The sub task list in the View Issue page is part of JIRA and is not controlled by JIRA Agile. The ranking for sub tasks on the issue is different than the ranking of sub tasks on an Agile board. I'll convert this issue to a feature request. Regards, JIRA Agile team

              Unassigned Unassigned
              2d7ef749a7b5 Kevin E. Schlabach
              Votes:
              60 Vote for this issue
              Watchers:
              37 Start watching this issue

                Created:
                Updated: