Last updatedDec 3, 2019

Jira activity

Display your projects in Jira Cloud

In this tutorial, you'll learn about:

This tutorial shows you how to build a static Connect app that displays your Jira Cloud projects in a table, accessible via an Activity link in the navigation.

Your app will use the Jira Cloud REST API to get information about projects in your instance. You'll use the Node.js framework and Atlassian Connect Express (ACE) to interface with Jira Cloud.

When you're finished, your app will look similar to this:

Jira activity completed

Configuring your development environment

In this step, you'll confirm you have Node.js installed, and install the Atlassian Connect Express (ACE) toolkit. ACE helps you create Connect apps using Node.js. It also detects changes made to your atlassian-connect.json descriptor file, so you don't need to continually restart your app as you develop. Importantly, ACE also handles JSON web token (JWT), so that requests between your app and the Jira Cloud application are signed and authenticated.

  1. Install Node.js 4.5.0 or later. If you use Homebrew, you can use the following command:

    1
    brew install node

    If you use Windows or don't use Homebrew, you can download and install Node.js directly. You might need to enter sudo to install as administrator.

  2. Install ACE using the npm install command.

    1
    npm install -g atlas-connect
  3. Create a new ACE project called jira-activity.

    1
    atlas-connect new -t jira jira-activity
  4. Change to your new jira-activity directory.

    1
    cd jira-activity/
  5. Install Node.js dependencies for your jira-activity project.

    1
    npm install
  6. ACE currently integrates with Sequelize for persistence to store the host client information (i.e., client key, host public key, etc). When no adapter is specified, it defaults to Sequelize's fallback memory storage. The memory storage is using SQLite3 so we'll need to install it:

    1
    npm install --save sqlite3
  7. We'll want to test our app on our local development environment. To make our app accessible to Jira Cloud we'll need to make the app accessible to the internet. Ngrok is a simple tool that makes any port accessible to the internet temporarily. ACE will need this to run correctly. Let's install it.

    1
    npm install --save-dev ngrok@2
  8. Get a Jira Cloud development environment by following the Development Setup

Now you've got the basic architecture for your app. If you open your new jira-activity directory, you'll see essentials like the atlassian-connect.json descriptor in the root. You'll also see the credentials.json.sample and app.js files.

Updating atlassian-connect.json

In this step, you'll prune some of the stub code, and install your app in Jira Cloud.

  1. Open the atlassian-connect.json descriptor file in your favorite editor or IDE.
  2. Replace the key, name, description, and vendor name and url with these fields:

    1
    2
    3
    4
    5
    6
    7
    8
    {
        "key": "jira-activity",
        "name": "Jira Project Activity",
        "description": "A Connect app that displays Jira projects in a table",
        "vendor": {
            "name": "Atlassian Developers",
            "url": "https://developer.atlassian.com/"
    	},

    This describes your app in a Jira Cloud instance, and essentially makes it yours.

  3. Replace the content of modules with a generalPages module:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    "generalPages": [
        {
            "key": "activity",
            "location": "system.top.navigation.bar",
            "name": {
                "value": "Activity"
            },
            "url": "/activity",
            "conditions": [{
                "condition": "user_is_logged_in"
            }]
        }
    ]

    This adds an Activity link in the Jira Cloud navigation (system.top.navigation.bar), and sets a URL for your app to use under /activity. It also provides a condition so that the Activity link is only shown to users that are logged in. At this point, your descriptor file should look like this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    {
    	"key": "jira-activity",
    	"name": "Jira Project Activity",
    	"description": "A Connect app that displays Jira projects in a table",
    	"vendor": {
    		"name": "Atlassian Developers",
    		"url": "https://developer.atlassian.com/"
    	},
    	"baseUrl": "{{localBaseUrl}}",
    	"links": {
    		"self": "{{localBaseUrl}}/atlassian-connect.json",
    		"homepage": "{{localBaseUrl}}/atlassian-connect.json"
    	},
    	"authentication": {
    		"type": "jwt"
    	},
    	"lifecycle": {
    		"installed": "/installed"
    	},
    	"scopes": [
    		"READ"
    	],
    	"modules": {
    		"generalPages": [
    			{
    				"key": "activity",
    				"location": "system.top.navigation.bar",
    				"name": {
    					"value": "Activity"
    				},
    				"url": "/activity",
    				"conditions": [{
    					"condition": "user_is_logged_in"
    				}]
    			}
    		]
    	},
    	"apiMigrations": {
    		"gdpr": true
    	}
    }
  4. Save and close the atlassian-connect.json file.

Create credentials.json

ACE uses a credentials.json file for development to make the development journey easier when making changes. This file will contain the host information and username and password for the admin account of your Jira Cloud development environment you created earlier. This information will be used to install and uninstall your app when you start and stop your app. You should not upload this file to production.

  1. In the root of the folder you will see a credentials.json.sample file. Rename this file to credentials.json.
  2. Open credentials.json in your IDE or editor and update the hosts, username, and password values. For username, use your email address. For password, you will need to create and use an API token. Go to https://id.atlassian.com and click on the Security tab, then click on the Create and manage API tokens link. Click on the Create API token button and walk through creating a token. Copy that token and paste it in for the password.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    {
    	"hosts": {
    		"https://your-instance.atlassian.net": {
    			"product": "jira",
    			"username": "your-email@address.com",
    			"password": "your-api-token"
    		}
    	}
    }
  3. Save and close the credentials.json file.

Run the app

  1. Open a new terminal window.
  2. From your jira-activity root, start up a Node.js server:

    1
    npm start

    This starts up your app on a server locally. If you set up ngrok correctly it'll make your app publicly visible to Jira Cloud. If you set up your credentials correctly the app will auto install into your developer instance.

  3. Verify that the app has successfully installed. Refresh Jira in your browser. You'll see the Activity label in the navigation: Jira activity This link doesn't go anywhere - yet. You'll fix this in future steps.

  4. Back in your editor, open routes/index.js. From here, you'll add the /activity route to your app.
  5. After the /hello-world stub code, add:

    1
    2
    3
    app.get('/activity', addon.authenticate(), function(req, res) {
        res.render('activity', { title: "Jira activity" });
    });

    Your routes/index.js file should resemble this:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    export default function routes(app, addon) {
    	// Redirect root path to /atlassian-connect.json,
    	// which will be served by atlassian-connect-express.
    	app.get('/', (req, res) => {
    		res.redirect('/atlassian-connect.json');
    	});
    
    	// This is an example route used by "generalPages" module (see atlassian-connect.json).
    	// Verify that the incoming request is authenticated with Atlassian Connect.
    	app.get('/hello-world', addon.authenticate(), (req, res) => {
    		// Rendering a template is easy; the render method takes two params:
    		// name of template and a json object to pass the context in.
    		res.render('hello-world', {
    			title: 'Atlassian Connect'
    			//issueId: req.query['issueId']
    		});
    	});
    
    	// Add additional route handlers here...
    
    	app.get('/activity', addon.authenticate(), function(req, res) {
    		res.render('activity', { title: "Jira activity" });
    	});
    }

    This route titles your Activity page "Jira activity", and ensures that your app is authenticated.

  6. Close and save your routes/index.js file.

Build the static Activity page

You've added a link in the Jira Cloud navigation, and now you'll define how your page should look. In this step, you'll style the page using Atlaskit.

  1. Open views/layout.hbs.
  2. Replace the entire file with the following:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="ap-local-base-url" content="{{localBaseUrl}}">
    <title>{{title}}</title>
    <link rel="stylesheet" href="https://unpkg.com/@atlaskit/css-reset@3.0.5/dist/bundle.css" />
    <link rel="stylesheet" href="https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.4/dist/bundle.css" />
    
    <script src="{{hostScriptUrl}}" type="text/javascript" data-options="sizeToParent: true;"></script>
    </head>
    <body>
    <div style="padding: 20px;">
    	{{{body}}}
    </div>
    <script src="/js/jira-activity.js"></script>
    </body>
    </html>

    This loads the Atlaskit Reduced UI pack and CSS reset that will style our app to look like Jira Cloud.

  3. Create a new file called views/activity.hbs. This file is a template you'll use to render the /activity URL.

  4. Add the following content:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    {{!< layout}}
    
    <h1>{{title}}</h1>
    
    <table id="projects">
    <thead>
    	<tr>
    	<th>Logo</th>
    	<th>Key</th>
    	<th>Name</th>
    	</tr>
    </thead>
    <tbody>
    	<tr></tr>
    </tbody>
    </table>
  5. You'll see an empty page with your "Jira activity" title: Jira activity.

Add some data, and verify your app works

  1. Create a file called public/js/jira-activity.js. This file will request a list of your projects, and generate an HTML table.
  2. Add the following content:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    AP.request('/rest/api/3/project/search', {
    	success: function(responseText){
    		var projectTable = document.getElementById("projects");
    		var data = JSON.parse(responseText);
    
    		for (var x = 0; x < data.values.length; x++) {
    		var value = data.values[x];
    		console.log(value);
    		var newRow = projectTable.insertRow(-1);
    		var newCellLogo = newRow.insertCell(0)
    		var newCellKey = newRow.insertCell(1);
    		var newCellProject = newRow.insertCell(2);
    
    		newCellLogo.innerHTML = "<img src='" + value.avatarUrls["16x16"] + "' width='16'>";
        	newCellKey.innerHTML = "<code>" + value.key + "</code>";
        	newCellProject.innerHTML = "<a href='/browse/" + value.key + "'>" + value.name + "</a>";
    		};
    
    		projectTable.deleteRow(1);
    	}
    });
  3. Save and close all files.

  4. Restart the Node.js app. Shut down the app with CTRL+C and re-run the npm start command.
  5. Click Activity in the navigation. You should have a list of projects that look like this: Jira activity.

Additional resources

Thanks for trying the tutorial! If you'd like to check your work, feel free to check out the repository here:

https://bitbucket.org/atlassianlabs/jira-activity-tutorial-source