How to connect and sync Bryntum Task Board to Jira
With Bryntum TaskBoard, you can build a fully customizable TaskBoard with pure JavaScript. You can easily use Bryntum TaskBoard with React, Vue, or Angular.
In this tutorial, we’ll connect and sync Bryntum TaskBoard to Atlassian’s Jira software. We’ll do the following:
- Use Atlassian’s Jira REST API to get items from your Jira project.
- Display the Jira issues in a Bryntum TaskBoard.
- Sync event changes in Bryntum TaskBoard with your Jira project.
Getting started
Clone the starter GitHub repository. This starter repository uses development server and JavaScript bundler Vite. You’ll need Node.js version 14.18+ for Vite to work.
Install the Vite dev dependency by running the following command:
npm install
The dev server is configured to run on http://localhost:8080/
in the vite.config.js
file. Run the local dev server now using npm run dev
and you’ll see a blank page.
Create a task board using Bryntum TaskBoard
We’ll install the Bryntum TaskBoard component using npm. Follow step one of the Bryntum TaskBoard set up guide to log into the Bryntum registry component.
Then initialize your application using the npm CLI command:
npm init
You will be asked a series of questions in the terminal; accept all the defaults by pressing the enter key for each question.
Now follow step four of the Bryntum TaskBoard set up guide to install Bryntum TaskBoard.
Let’s import the Bryntum TaskBoard component and give it some basic configuration. In the index.js
file, add the following lines:
import { TaskBoard } from '@bryntum/taskboard/taskboard.module.js';
const taskBoard = new TaskBoard({
appendTo : document.body,
columnField : 'status',
columns : [
'todo',
'doing',
'done'
],
project : {
tasksData : [
{ id : 1, name : 'My first task', status : 'doing' },
{ id : 2, name : 'My second task', status : 'todo' }
]
}
});
Here we import Bryntum TaskBoard, create a new Bryntum TaskBoard instance, and pass a configuration object into it. We add the TaskBoard to the <body>
of the DOM.
We pass in data inline to populate the project
tasksData
for simplicity. We have two task items within it. You can learn more about working with data in the Bryntum docs.
If you run your dev server now, you’ll see the items in our Bryntum TaskBoard:
Our TaskBoard chart uses the Stockholm theme, which is one of five available themes for Bryntum TaskBoard. We’ve linked to the CSS for the Stockholm theme in index.html
. If you’d like to create a custom theme, read more about styling your TaskBoard in our customization documentation.
Now let’s learn how to retrieve a list of Jira issues from an Atlassian account using the Jira REST API.
Set up Atlassian Jira project
You will need an account on Atlassian. Sign up or log in to your Atlassian account. After verifying your email, create your site name and keep this address safe, we will need it later.
Once you’ve created your site, you will be prompted to set up your Jira software. Follow the steps below to complete the setup:
- You will see a loading page, wait for your site to be set up.
- On the “Help us set up your Jira” page, answer the question prompts and click “Next”.
- On the next page, give your project a name and click “Create”.
- On the next page you will be asked to connect apps, click “Skip”.
- On the “Invite your teammates” page click “Done”.
After completing these steps you will see your project board like the one below:
Create a new issue by clicking the + Create issue
button in the “TO DO” column. Give it any name, we are creating this issue so that we can test if our integration is working later on.
To communicate with the Jira REST API, we’ll need our project key and an API token.
Get your project key
To get your project key, click the “Projects” button at the top of your board view, then click “View all projects”.
There you will see a list of your Jira projects. Take note of the key assigned to the project we’ve just created.
Get your access token
To create an access token:
- Click on your profile image in the top right of the screen.
- Click “Manage account”.
- On the next page, click “Security” in the menu on the left.
- Click “Create and manage API tokens”.
- Click “Create API token”.
- Give your token a label and click “Create”.
- Finally, when your token has been created, click “Copy” to copy your token.
Keep the token somewhere safe so that we can use it to authenticate our requests to the Jira REST API.
Use Jira REST API to access your Jira issues
Now that we have an access token, we can use it to query the Jira REST API and retrieve all the issues from our project.
In the request.js
file, add the code below:
import { createTaskBoard } from './index.js';
const serverAddress = 'http://localhost:3000';
const clientAddress = 'http://localhost:8080';
async function getTasksFromJira() {
fetch(`${serverAddress}/getIssues/`, {
method: 'GET',
mode: 'cors',
headers: {
'Access-Control-Allow-Origin': clientAddress,
'Content-Type': 'application/json',
},
})
.then((response) => response.json())
.then((data) => createTaskBoard(data));
}
export { getTasksFromJira };
Here we define a function called getTasksFromJira
that makes a query to the server that we will create in the next step. The query receives a list of all the issues from our server and then initiates a function called createTaskBoard
. This function call will create our TaskBoard with all the data from our Jira project included.
Before we sync our TaskBoard we must set up our local server. In the server.js
file, add the code below:
import express from 'express';
import fetch from 'node-fetch';
import cors from 'cors';
const atlassianAddress = '<your-atlassian-address-here>' + 'rest/api';
const projectKey = '<your-project-key-here>';
const email = '<your-email-here>';
const token = '<your-api-token-here>';
const transitionList = {
'to do': '11',
'in progress': '21',
'done': '31',
};
const authHeaders = {
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Basic ${Buffer.from(
`${email}:${token}`,
).toString('base64')}`,
};
const app = express();
app.use(cors({
origin: 'http://localhost:8080',
}));
app.use(express.json());
app.get('/getIssues', function (req, res) {
fetch(`${atlassianAddress}/2/search?jql=project=${projectKey}`, {
method: 'GET',
headers: authHeaders,
})
.then((res) => res.json())
.then((json) => res.send(json));
});
app.listen(3000, function () {
console.log('Listening on port 3000!');
});
Here we use ExpressJS to create a get
route on /getIssues
which will make a request to the Jira REST API and return all of the issues from our Jira project. We also create our server with app.listen
which will run our server on port 3000.
Add your own information as follows:
- Replace
<your-atlassian-address-here>
with the site address you created when setting up your Atlassian account. Be sure to end off the address with a forward slash/
and prefix the address with a protocol. - Replace
<your-project-key-here>
with the Jira project key we retrieved earlier. - Replace
<your-email-here>
with the email address you used to create your Atlassian account. - Replace
<your-api-token-here>
with the API token we created earlier.
Take note that in this example, we hard-code the access token and personal information for the sake of simplicity. For production environments, it’s more secure to keep sensitive information in environment variables.
Next, install the packages we need to run our server with the following command:
npm install cors express node-fetch
Next we will add our Jira issues to our Bryntum TaskBoard. Replace all the code in the index.js
file with the following code:
import { TaskBoard, TaskStore } from '@bryntum/taskboard/taskboard.module.js';
import { getTasksFromJira } from './request.js';
getTasksFromJira();
function getIssueData(issues) {
const issueList = [];
issues = issues.issues;
for (let i = 0; i < issues.length; i++) {
const newIssue = {
jiraId: issues[i].key,
name: issues[i].fields.summary,
status: issues[i].fields.status.name.toLowerCase(),
};
issueList.push(newIssue);
}
return issueList;
}
function createTaskBoard(issues) {
const taskStore = new TaskStore({
data: getIssueData(issues),
});
const taskBoard = new TaskBoard({
appendTo: document.body,
columnField: 'status',
columns: [
'to do',
'in progress',
'done'
],
project: {
taskStore
}
});
}
export { createTaskBoard };
Here we create the createTaskBoard
function that will create our TaskBoard instance, then we create our issues using the getIssueData
function. The getIssueData
function takes in the results of the request to Jira and formats the issues to match the Bryntum inline data format.
Now run your newly created server using the following command:
node server.js
If you run npm run dev
in a new terminal now, you will see the items from your Jira project reflected in the Bryntum TaskBoard.
Implementing CRUD
Now that our Bryntum TaskBoard has received all the items from our Jira API, we’ll implement the rest of the CRUD functionality by taking advantage of Jira’s REST API.
Create events
In the server.js
file, add the following lines above app.listen
:
app.post('/addIssue', function (req, res) {
const transitionType = transitionList[req.body.status];
const bodyData = {
'fields': {
'summary': req.body.summary,
'project': {
'key': projectKey,
},
'issuetype': {
'id': '10001',
},
},
'transition': {
'id': transitionType,
}
};
fetch(`${atlassianAddress}/3/issue`, {
method: 'POST',
headers: authHeaders,
body: JSON.stringify(bodyData),
})
.then((res) => res.json())
.then((json) => res.send(json))
.catch((err) => console.log(err));
});
Here we define the /addIssue
post request, this will create an issue in our Jira project using the name and status (to do, in progress, and done). The name is changed through the summary
definition and the status is defined through the transition
definition.
Update events
In the server.js
file, add the following lines above app.listen
:
app.put('/updateName', function (req, res) {
fetch(`${atlassianAddress}/2/issue/${req.body.key}`, {
method: 'PUT',
headers: authHeaders,
body: JSON.stringify({
'update': {
'summary': [
{
'set': req.body.summary,
}
],
},
}),
})
.catch((err) => console.log(err));
});
app.post('/updateTransition', function (req, res) {
const transitionType = transitionList[req.body.status];
fetch(`${atlassianAddress}/2/issue/${req.body.key}/transitions`, {
method: 'POST',
headers: authHeaders,
body: JSON.stringify({
'transition': {
'id': transitionType,
}
}),
})
.catch((err) => console.log(err));
});
The /updateName
and /updateTransition
routes will handle the requests to change the name and status of our issues.
Delete events
In the server.js
file, add the following lines above app.listen
:
app.delete('/deleteIssue', function (req, res) {
fetch(`${atlassianAddress}/3/issue/${req.body.key}`, {
method: 'DELETE',
headers: authHeaders,
})
.catch((err) => console.log(err));
});
The /deleteIssue
route will identify the appropriate issue by its key
and delete the issue from our Jira project.
Listening for event data changes in Bryntum TaskBoard
Next, we’ll set the listeners for our Bryntum TaskBoard so that it will know when the user updates the TaskBoard events.
In the index.js
file, add the listener property above the data: getIssueData(issues),
line:
listeners: {
change: function (event) {
updateJira(event);
}
},
Here we set a listener on our Bryntum TaskBoard to listen for any changes to the task board’s data store. This will fire an "add"
event whenever a task board item is created, an "update"
event when an item is updated, and a "remove"
event whenever an item is deleted.
The item retrieved from the change
listener also carries event data about the specific TaskBoard item that has been altered. We’ll use the event data to identify which item is being altered and what’s being changed.
Next we’ll create a function called updateJira
that will update your Jira project when the appropriate "add"
, "update"
, or "delete"
event is fired.
Add the following code below the getTasksFromJira
function in the request.js
file:
async function sendRequest(event, address, requestMethod) {
const requestBody = {
'key': event.records[0].data.jiraId,
'status': event.records[0].data.status,
'summary': event.records[0].data.name,
};
await fetch(`${serverAddress}/${address}/`, {
method: requestMethod,
mode: 'cors',
headers: {
'Access-Control-Allow-Origin': clientAddress,
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody),
})
.then((res) => res.json())
.then((results) => event.records[0].data.jiraId = results.id)
.then((data) => console.log(data));
}
async function updateJira(event) {
if (event.action === 'update' && 'name' in event.changes) {
sendRequest(event, 'updateName', 'PUT');
} else if (event.action === 'update' && 'status' in event.changes) {
sendRequest(event, 'updateTransition', 'POST');
} else if (event.action === 'add' && event.records.length === 1) {
sendRequest(event, 'addIssue', 'POST');
} else if (event.action === 'remove' && event.records.length === 1) {
sendRequest(event, 'deleteIssue', 'DELETE');
}
}
Here we create the updateJira
function that is called on all changes to the data store of Bryntum TaskBoard. It then creates a request to our server with the sendRequest
function to request the appropriate Jira REST API CRUD functions we defined.
On "update"
, we check whether the item name or status is being updated. We then make the request to either the /updateName
or /updateTransition
route. We pass in the event
information since we can extract the Bryntum TaskBoard task’s name, status, and ID for the request.
async function updateJira(event) {
if (event.action === 'update' && 'name' in event.changes) {
sendRequest(event, 'updateName', 'PUT');
} else if (event.action === 'update' && 'status' in event.changes) {
sendRequest(event, 'updateTransition', 'POST');
}
On "add"
, we make the request to the /addIssue
route.
else if (event.action === 'add' && event.records.length === 1) {
sendRequest(event, 'addIssue', 'POST');
}
On "remove"
, we make the request to the /deleteIssue
route.
else if (event.action === 'remove' && event.records.length === 1) {
sendRequest(event, 'deleteIssue', 'DELETE');
}
Finally, change the exports in request.js
to the following:
export { getTasksFromJira, updateJira };
And change the imports in index.js
to the following:
import { TaskBoard, TaskStore } from '@bryntum/taskboard/taskboard.module.js';
import { getTasksFromJira, updateJira } from './request.js';
Now run your server to create, update, delete, and edit an item in the Bryntum TaskBoard. You’ll see the changes reflected in your Jira project.
Next steps
This tutorial gives you a starting point for creating a Bryntum TaskBoard using vanilla JavaScript and syncing it with Atlassian’s Jira software. There are many ways you can improve your Bryntum TaskBoard, for example, you can add features such as task filters. Take a look at our demos page to see demos of the available features.