Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 14 Next »

Overview

Read our step-by-step guide to learn more about Report Builder's capabilities and how to create your scripted report from scratch.

Introduction

Report Builder helps organizations with any Jira reporting need. It improves project management and helps to provide better project, team, and goal vision. The app has built-in personal and time reports templates, which cover most time reporting needs. With Scripted Reports, you will also build reports from scratch by implementing any calculation algorithm, parameter, and visualization library. Build your report with HTML and JavaScript basics.

Prerequisites

Make sure, you have a proper rights set by your app administrator to create Scripted Reports.

Notification for admins:

Only grant permissions for creating scripted reports to users with substantial JavaScript knowledge. Improper work with JavaScript may result in data corruption or loss. Granting this permission without proper control can expose your system to XSS or other injection attacks. Ensure you trust the users you are providing this access to.

Reporting essentials in Report Builder

To reach success with creating your own reports always follow the below structure concerning how to select, fetch and press data, and format resulting measures.

  1. Fill in some report parameters, like scope, dates, etc.

  2. Get raw data based on input parameters: projects, tickets, work logs, etc. 

  3. Apply an algorithm to calculate your report based on raw data and input parameters.

  4. Format your results to get the report in a table, chart, or any other format.


Let's build a report.

To build a report, first navigate to Reports gallery, as follows, and click the button shown on the screenshot below

You will be prompted to a dropdown menu. Select “New Scripted Report“. Then you will see screen as follwos:

Make sure you name report first, then add it to your reports and start adding new fields.

Our example: Actual time vs. estimation

We will use following three tabs to develop a report:

  1. General

  2. Template

  3. Script

Just to remind you, these tabs are located on the panel as shown below:

Note tab called Permissions will be helpful to share the report with someone, but we'll cover this part at the end of this guide.

Let's try to solve the task of getting a time tracking report from Jira based on JQL query and understanding each tab.

Tab 1: General

The tab provides the ability to add input fields and define the category of your report. At the moment, there are more than ten predefined input field types, which make the process of user interaction intuitive. You can choose any category from the list or skip this step.

In our case, we will choose the category "Table" because it would be a great way to see the estimated time over the spent time in table format.

We create two input fields:

  • JQL: to work with JQL query and get syntax check

  • Fields Picker: to select the worklog fields of the Jira issue

We set up those two fields the following way:

  • Field Name: choose a field name that will be part of the "name" HTML tag and use it for script logic.

  • Title: choose a title to be shown at the top of the field.

  • Type: choose a type that will predefine the behaviors of the field (syntax check or Jira object select).

Tab 2: Template

To control the final data view, the Template tab provides a Handlebars template editor. If you're not aware of Handlebars, we suggest checking out the official site of the template engine.

As mentioned before, we decided to use the table format to represent the data. We assume that it will be an array of issue objects from Jira API, so we need to create a table row for each of these objects.


Tab 3: Script

A comprehensive guide to Scripted Report API (aka SR API) is provided in this guide.

To manage the data provided, you can use JavaScript in the General tab. The code will run in the top-level await scope with the defined SR object. This object is constructed to help with tasks like interacting with Jira API, quickly getting data from the input fields of the General Tab, and passing the final data to the template.

Let's go over some of these methods:

  • SR.getValueByFieldName(fieldName:String)  – returns the input field value based on fieldName string parameter

  • SR.getIssuesByJQL(jql:String, <fields:String>) – returns an array of Jira issues based on JQL query and the list of comma-separated fields. If the fields parameter is not set, then Jira Navigable fields will be returned

  • SR.render(templateValues:Object, <callback:Function>) – passes the values from the JavaScript to the template defined in the Template tab. It is possible to set some after rendering logic with the callback parameter

You fill in the fields JQL and Fields Picker. The first thing you need to do is get the values in the script. 

To get the data from the input fields with the help of SR.getValueByFieldName() you need to pass the field name value that was set in the General tab. Please note that the Fields Picker is a multi-select field that returns an array of values.

As the SR.getIssuesByJQL() uses the string type for both parameters, you convert the selected fields to the comma-separated string. As the request to the Jira API is an asynchronous operation, you should be using top-level await to wait for a response.

Now, fetch the Jira issues and control the final data object which is possible with the JavaScript map() method: 

The issue in the last code shows the time that comes from Jira and is presented in milliseconds. So it would help if you defined the helper function that will convert incoming values into hours.

You now need to apply this conversion to the map callback function.

Finally, you're passing the value of the issues as part of the rendering object inside the SR.render() method. If you want to give more values, you need to add another property to the rendering object.

All you are now left with is clicking on the "Get Report" button at the top-right and viewing the results.


Here you can see the complete code for the Script tab:

Permission tab

To regulate the group of users that could view, edit and admin your report, you can configure the Permissions tab. The selected users will see the report in the "Shared" tab in the Scripted Report dashboard.

Currently, there are three roles of report users available:

  1. View access – the user can only view the report. The user cannot save the input parameter values or edit the report configuration tab.

  2. Edit access – the user can view the report and save the input parameter values. However, the user cannot edit the report configuration tab.

  3. Admin access – the user can view the report, save the input parameter values, and edit the report configuration tab.

The creator of the report always has admin access rights! Creator rights cannot be changed.

The Permissions tab allows sharing the direct link to the report. Please note that the respective user should have permission to view the shared report (role 1).

Saving your report

When the report set up suits your goals, save your report and choose a self-descriptive name. You will find all your report in the Scripted Report dashboard in the tab "My reports."

Report improvements: Changing the script

You already know how to get the spent time in comparison to the estimated time for issues. But what if you want to get a report that will calculate the work time for a whole project, so multiple issues from multiple users? This can be achieved with minor changes in the report script.

First, you need to define the object that will store each project worklog as a key-value pair.

Next, pick the project field in the Fields Picker to be returned from the Jira API. Define the calculation logic inside the foundIssues.map() callback:

Finally, pass the "projects" object as part of the rendering object and update the Template tab to show the data.

These operations will show you the report with extended data.

Please note that you didn't lose the previous report but calculated project logs in addition to it. This shows the flexibility of Scripted Reports to fetch and use the Jira data in multiple ways. 

Template:

<div class="issues-container">
    <h2>Issues work vs original estimate</h2>
    <table>
        <tr>
            <th>Ticket</th>
            <th>Actual work</th>
            <th>Original estimate</th>
            <th>Remaining estimate</th>
        </tr>
        {{#each issues}}
        <tr>
            <td>{{this.key}}</td>
            <td>{{this.timespent}} h</td>
            <td>{{this.timeestimate}} h</td>
            <td>{{this.remaining}} h</td>
        </tr>
        {{/each}}
    </table>
</div>

<div class="projects-container">
    <h2>Projects work vs original estimate</h2>
    <table>
        <tr>
            <th>Project Key</th>
            <th>Actual work</th>
            <th>Original estimate</th>
            <th>Remaining estimate</th>
        </tr>
        {{#each projects}}
        <tr>
            <td>{{this.key}}</td>
            <td>{{this.timespentHours}} h</td>
            <td>{{this.timeestimateHours}} h</td>
            <td>{{this.remainingHours}} h</td>
        </tr>
        {{/each}}
    </table>
</div>

Script:

  /* 1. Define constants */
  const projects = {};
  
  /* 2. Define helper functions */
  const millisecondsToHours = (milliseconds) => {
      if (isNaN(milliseconds)) {
          return 0;
      }

      return (Math.round(((milliseconds / 3600) + Number.EPSILON) * 100) / 100);
  };

  /* 3. Getting parameters for the JQL request */
  const jqlValue = SR.getValueByFieldName('jql-field');
  const selectedFields = SR.getValueByFieldName('fields-picker-field').join(',');

  /* 4. Requesting issues by JQL string and fields list */
  const foundIssues = await SR.getIssuesByJQL(jqlValue, selectedFields);
  
  console.log('foundIssues', foundIssues)

  /* 5. Parsing data from the response and creating the final object */
  const issues = foundIssues.map(({ key, fields }) => {
      /* 5.1 Get properties:
          key - issue key
          projectKey - project key
          timespent - Time Spent
          timeoriginalestimate - Original estimate
          timeestimate - Remaining
      */
      const {
          project: {
              key: projectKey,
          },
          timeestimate,
          timeoriginalestimate,
          timespent,
      } = fields;

      /* 5.2 Projects work time vs original estimate logic  */
      if (projects[projectKey]) {
          /* 5.3  If project key is already exist then recalculate time */
          projects[projectKey].timeestimate += timeoriginalestimate;
          projects[projectKey].timespent += timespent;
          projects[projectKey].remaining += timeestimate;

          projects[projectKey].timeestimateHours = millisecondsToHours(projects[projectKey].timeestimate);
          projects[projectKey].timespentHours = millisecondsToHours(projects[projectKey].timespent);
          projects[projectKey].remainingHours = millisecondsToHours(projects[projectKey].remaining);
      } else {
          /* 5.4  If project key is not exist then create object with initial time  */

          projects[projectKey] = {
              key: projectKey,
              timespent,
              timeestimate: timeoriginalestimate,
              remaining: timeestimate,
              timeestimateHours: millisecondsToHours(timeoriginalestimate),
              timespentHours: millisecondsToHours(timespent),
              remainingHours: millisecondsToHours(timeestimate),
          };
      }

      /* 5.5 Issue work time vs original estimate logic  */
      return {
          key,
          timespent: millisecondsToHours(timespent),
          timeestimate: millisecondsToHours(timeoriginalestimate),
          remaining: millisecondsToHours(timeestimate),
      };
  });

  /* 6. Passing values to the handlebars template engine */
  SR.render({ issues, projects });


Using the report gallery

The integrated report gallery is a list of predefined reports. The goal of Scripted Reports is to cover basic user needs and create a platform for unique report creation. The predefined gallery reports cannot be edited inside the Gallery itself, but you can copy them into your private report list for editing.

  1. Please click the button “Export to JSON“ as follows:

2. Copy the JSON

3. Proceed to your reports dashboard, and import the JSON copied

Report Building Service

If you have any further reporting needs, please get in touch with our Report Building Service team, which will provide any report for you. Read more about our service here.

  • No labels