Web panels can be used to add HTML snippets to parts of a page. They could be used to display additional information on a particular build, a plan, or the system navigation. For more information, read up on web panels in the Atlassian documentation.

Display a simple panel

As a simple example, let’s imagine we want to add a warning banner to a plan that is deprecated.

From the Script Fragments page, choose the Show a web panel built-in script, and configure it as follows:

web panel

The main thing to copy is the location, which should be plan.result.header.breadcrumbs.

The weight field is optional, and it only takes positive integers. Lower weights will make the panel be displayed at the top of its section. If blank it will appear at the end of its section.

Provider class/script (either directly as an inline script, or from a file):

writer.write("""<div style='background-color: yellow; text-align: center'>
    This build plan is deprecrated, and will be removed soon. Please switch to using
    the WIDGET build plan in this same project.
</div>""")
You must write to the provided Writer object, not just return a String.

Once configured, you should see a box of yellow text at the top of a build page.

web panel banner

Using the Context

So, that’s handy, but what if you want to restrict that banner to only certain plans? After all, you probably didn’t deprecate every build in your instance. Let’s say that we know which plans are deprecated based on their plan key containing the word "LEGACY". Add the following condition to the panel’s configuration. You can ignore the red static compilation error in the code editor.

context["plan"].key.contains("LEGACY")

The context object has information about the currently displayed page, and will vary somewhat from page to page. You can experiment with what’s available in the context by logging it and viewing your server’s log files.

log.warn "Context: $context"

Display technical support contact for a particular plan

This example expands on the simple example above, we recommend you take a look at that one first.

Sometimes Bamboo plans do not always run successfully which can block users whilst they figure out who to contact. Usually the first point of contact is internal support or an admin of the instance.

However a plan can be setup by various users who may not be that first person, but will have the knowledge to rectify the issue. Therefore to quickly resolve the problem it’s useful to display a technical support contact on a particular plan.

In this example we use a plan admin as the technical support contact. The script for rendering the panel is shown below:

import com.atlassian.bamboo.plan.cache.ImmutablePlan
import com.atlassian.bamboo.security.BambooPermissionManager
import com.atlassian.bamboo.security.acegi.acls.BambooAclUpdateHelper
import com.atlassian.bamboo.user.BambooUserManager
import com.atlassian.sal.api.component.ComponentLocator
import groovy.xml.MarkupBuilder

def userManager = ComponentLocator.getComponent(BambooUserManager)

def aclUpdateHelper = ComponentLocator.getComponent(BambooAclUpdateHelper)
def bambooPermissionManager = ComponentLocator.getComponent(BambooPermissionManager)

def plan = context["plan"] as ImmutablePlan

def acl = bambooPermissionManager.getAcl(plan)

def grantedPerms = []
def users = [] as List<String>
def groups = []
def nonProcessedGrantedPerms = []

aclUpdateHelper.buildPermissionAndUserGroupListsFromAcl(grantedPerms, users, groups, nonProcessedGrantedPerms, acl, true, bambooPermissionManager)

def adminUsernames = users.findAll { username ->
    def adminPermissionKey = "bambooPermission_user_${username}_ADMINISTRATION".toString()
    grantedPerms.contains(adminPermissionKey)
}

def adminUsers = adminUsernames.collect { userManager.getBambooUser(it) }

def stringWriter = new StringWriter()
def markupBuilder = new MarkupBuilder(stringWriter)

def adminUser = adminUsers.first()

markupBuilder.div(class: "aui-message info", style: "display: inline-block") {
    p(class: "title") {
        strong("Technical Support")
    }

    p {
        mkp.yield("If you experience issues with this plan please contact ")
        a(href: "mailto:$adminUser.email", adminUser.fullName)
    }
}

writer.write(stringWriter.toString())

To get started create a new custom web panel that is configured like below:

tech support plan config

In this example we are using a script file located under our script root rather than copying and pasting the script directly as it’s a fairly large one. For testing purposes you can just copy and paste the script above into the "Provider class/script" field.

If you look closely you’ll notice some errors highlighted in red. These are simply static type errors caused by Groovy not being able to work out particular types at compile time. But the types will be resolved at runtime. Some of them have been fixed by specifying the types, but you don’t have to do this.

After adding the panel, when we go to view a particular plan we should see an info panel like the one displayed below:

tech support plan panel

If we click on the user "Jon Brown" we’ll be able to get the email address to contact that user to request support.

Display Datadog shared graphs (or suitable alternative) for a particular plan

Script Fragments allow you to embed relevant data from other third party systems directly into your build plan.

In this example we are using Datadog, but the example extends to any third party application that allows you to generate some iframe content.

In the below web panel script fragment we have generated two iframe graphs from within Datadog, which we have then embedded within an information panel for display.

import groovy.xml.MarkupBuilder

def hostMapIframe = '<iframe src="https://app.datadoghq.com/graph/embed?token=<TOKEN>&height=200&width=400&legend=true" width="400" height="200" frameborder="0"></iframe>'
def systemLoadIframe = '<iframe src="https://app.datadoghq.com/graph/embed?token=<TOKEN>&height=200&width=400&legend=false" width="400" height="200" frameborder="0"></iframe>'

def stringWriter = new StringWriter()
def markupBuilder = new MarkupBuilder(stringWriter)

markupBuilder.div(id: "datadog-graphs", class: "aui-message info", style: "display: inline-block") {
    div(style: "margin:10px; display:inline") {
        mkp.yieldUnescaped(hostMapIframe)
    }
    div(style: "margin:10px; display:inline") {
        mkp.yieldUnescaped(systemLoadIframe)
    }
}

writer.write(stringWriter.toString())

To get started create a new custom web panel that is configured like below:

datadog graphs config

In this example we are using a script file located under our script root rather than copying and pasting the script directly. However you can just copy and paste the script above into the "Provider class/script" field.

After adding the panel, when we go to view a particular plan we should see an info panel like the one displayed below:

datadog graphs output

Have questions? Visit the Atlassian Community to connect, share, and learn with other Atlassian users and experts, including Adaptavist staff.

Ask a question about ScriptRunner for JIRA, Bitbucket Server, or Confluence.

Want to learn more? Check out courses on Adaptavist Learn, an online platform to onboard and train new users for Atlassian solutions.