Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Next challenges

Recent achievements

Recognition

  • Give kudos
  • My kudos

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to get an issue description from Jira and render it in the same way in a Confluence table?

Hi, 

this is midway between Jira and Confluence (server).

I need to generate a summary table from a list of Jira Issues in a Confluence page.

I can't use the Issue macro in Confluence, because the people who will have access to the page won't have permissions in Jira, so they just would see an error message in the field in the table. In addition, I want people to be able to insert inline comments, so what they find in the page should be selectable text, possibly not rendered macro.

Anyway, I had almost done the job with the following code (here I'm not yet sending the data to Confluence, I'll do it then with a REST call).

I could get the data I need from a Jira Structure, or directly from a Jira query (in this case I'm reading a Structure).

//Retrieve information from an LOP stored in Jira Structure

//Name of the Structure to call
String structureName="MARTHA-LOP"

//Generic import
import com.atlassian.jira.component.ComponentAccessor
import groovy.xml.MarkupBuilder

//Librerie per gestione Link con Confluence
import com.atlassian.applinks.api.ApplicationLink
import com.atlassian.applinks.api.ApplicationLinkService
import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.sal.api.net.Request
import com.atlassian.sal.api.net.Response
import com.atlassian.sal.api.net.ResponseException
import com.atlassian.sal.api.net.ResponseHandler
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper

//Specific import for Jira Structure
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.almworks.jira.structure.api.structure.StructureManager
import com.almworks.jira.structure.api.permissions.PermissionLevel
import com.almworks.jira.structure.api.forest.ForestSpec
import com.almworks.jira.structure.api.row.StructureRow
import com.almworks.jira.structure.api.row.RowManager
import com.almworks.jira.structure.api.structure.Structure
import com.almworks.jira.structure.api.StructureComponents
import com.almworks.jira.structure.api.item.ItemIdentity
import com.almworks.jira.structure.api.item.CoreIdentities
import com.almworks.jira.structure.api.attribute.StructureAttributeService
import com.almworks.jira.structure.api.attribute.CoreAttributeSpecs
import com.almworks.jira.structure.api.attribute.AttributeSpec
import com.almworks.jira.structure.api.attribute.AttributeSpecBuilder
import com.almworks.jira.structure.api.attribute.ValueFormat
import com.almworks.jira.structure.api.attribute.VersionedRowValues
import com.almworks.integers.LongArray
import com.almworks.integers.LongIterator

def issueManager = ComponentAccessor.getIssueManager()

//Stabilisco un collegamento con Confluence
def ApplicationLink getPrimaryConfluenceLink() {
def applicationLinkService = ComponentLocator.getComponent(ApplicationLinkService.class)
final ApplicationLink conflLink = applicationLinkService.getPrimaryApplicationLink(ConfluenceApplicationType.class)
conflLink
}
def confluenceLink = getPrimaryConfluenceLink()
assert confluenceLink // must have a working app link set up
def authenticatedRequestFactory = confluenceLink.createImpersonatingAuthenticatedRequestFactory()

//Also necessary for Jira Structure
@WithPlugin("com.almworks.jira.structure")
@PluginModule
StructureComponents sc

//Structure handlers
StructureManager sm = sc.getStructureManager()
RowManager rowManager = sc.getRowManager()
def forestService = sc.getForestService()

//Permission access to structure
def permission = PermissionLevel.valueOf("ADMIN")

//Get Structure
def struct = sm.getStructuresByName(structureName, permission)[0]
//Forest Specification
def forestSpec = ForestSpec.structure(struct.getId())
//Forest Source
def forestsrc=forestService.getForestSource(forestSpec)
//Forest - Last version
def forest = forestSrc.getLatest().getForest()
//Forest Rows
def forestRows=forest.getRows()


//

def myStructureId=struct.getId() // get id
def viewManager = sc.getViewManager()
log.warn("Structure Id: "+myStructureId)
def views=viewManager.getViewSettings(myStructureId).getAssociatedViews()
views.each {
associatedView->
def viewId = associatedView.getViewId()
log.warn(viewId)
def viewSpec = viewManager.getView(viewId, null /*permission level*/).getSpecification()
viewSpec.getColumns().forEach({
column ->
//log.warn(column)// request values by column spec (attr id and params)
})
}


//List of attributes to be retrieved and then used somewhere
List attributeSet = new ArrayList<>()
attributeSet.add(CoreAttributeSpecs.KEY)
attributeSet.add(CoreAttributeSpecs.SUMMARY)
attributeSet.add(CoreAttributeSpecs.DESCRIPTION)

//Build a matrix that relates forest rows with the attributes chosen before
VersionedRowValues values = sc.getAttributeService().getAttributeValues(forestSpec, forestRows, attributeSet);
log.warn(values)

//Def writer and xml to build output
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)


//Build table
xml.table(class: "aui") {

thead {
tr {
th("Key")
th("Summary")
th("Description (got from structure)")
th("Description (direct from jira issue)")
}
}

// Row counter
int rowNumber=0

tbody{

//Iterate among forest rows
for (LongIterator ri : forestRows) {
//Get the specific row
StructureRow row = rowManager.getRow(ri.value())
rowNumber=rowNumber+1
//Identify type of item in the row
ItemIdentity itemId = row.getItemId()

tr{

//In case of an Issue
if (CoreIdentities.isIssue(itemId)){
//definisco oggetto issue
def issue = issueManager.getIssueObject(values.get(ri.value(), CoreAttributeSpecs.KEY))
def issueKey =values.get(ri.value(), CoreAttributeSpecs.KEY)
td(values.get(ri.value(), CoreAttributeSpecs.KEY))
td(values.get(ri.value(), CoreAttributeSpecs.SUMMARY))
td(values.get(ri.value(), CoreAttributeSpecs.DESCRIPTION))
td(issue.getDescription())
}
//In case of another item "(normally folders)"
else{
}
}

}
}
}



//Evaluate output in Scriptrunner console
return writer.toString()

 

The problem then is that I'm not able to render the Issue Description in the same way I see it in Jira :-(

Here is how the description is rendered in Jira

 

image.png

 

and here is what I get in my table

 

image.png

When I send the data to confluence I get the same effect above.

Thanks in advance for any suggestment.

Andrea

 

 

 

2 answers

1 accepted

0 votes
Answer accepted

Hi

You wrote

>>The problem then is that I'm not able to render the Issue Description in the same way I see it in Jira :-(

Have you tried to convert description from wiki to html format?

Here is an example from scriptrunner console, may be it will be helpful

import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.event.api.EventPublisher
import com.atlassian.jira.util.velocity.VelocityRequestContextFactory
import com.atlassian.jira.issue.fields.renderer.wiki.AtlassianWikiRenderer
import com.atlassian.jira.issue.fields.renderer.wiki.*
import com.atlassian.jira.issue.fields.renderer.*
import com.atlassian.jira.config.properties.ApplicationProperties
import com.atlassian.jira.config.FeatureManager


def ap = ComponentAccessor.getApplicationProperties();
def fm = ComponentAccessor.getOSGiComponentInstanceOfType(FeatureManager);
def ism = ComponentAccessor.getIssueManager();
MutableIssue iss = ism.getIssueByCurrentKey('<issue Key>');
def desc = iss.getDescription();




EventPublisher eventPublisher = ComponentAccessor.getOSGiComponentInstanceOfType(EventPublisher.class);
VelocityRequestContextFactory velocityRequestContextFactory = ComponentAccessor.getOSGiComponentInstanceOfType(VelocityRequestContextFactory.class);
def wikiRenderer = new AtlassianWikiRenderer(eventPublisher, ap, velocityRequestContextFactory, fm);

String descHtml = wikiRenderer.render(desc, null);

return descHtml

Hy @fjodors , and thanks for your message.

The content of your descHtml is actually the same the content I got already in the strings I was using.

If I return directly this string to the console, it works perfectly.

The main issue (for me, due to my limited knowledge), is how to generate the equivalent MarkupBuilder instructions from the string, in order to put it in the table cell.

 

If I simply add

td('<p><b>20/11/19-A.Boerio:</b>Ciao</p>')

and then return the writer, I get a table with a cell that shows

   <p><b>20/11/19-A.Boerio:</b>Ciao</p>

and not

   20/11/19-A.Boerio:Ciao

I'm sorry I don't know how can I describe it better.

Andrea

Ops, I guess I could solve it by using mkp.yieldUnescaped()

I try.

Done!

 

It's was just a matter of introducing 

 

def mkp = new MarkupBuilderHelper(xml)

 

and then, when defining the table, using

td{

mkp.yieldUnescaped('<p><b>20/11/19-A.Boerio:</b>Ciao</p>')

}

instead of 

td('<p><b>20/11/19-A.Boerio:</b>Ciao</p>')

 

So simple ... when you know it :-(

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Published in Jira Software

How to create Jira issus from Excel file?

When to use CSV importer When managing your processes in Jira, there are many occasions where you need to create a lot of tasks. Creating them one by one will cost you a lot of time and effort and i...

4,624 views 22 33
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you