Jira Cloud app: React and Atlaskit

Hello!

We created a Jira Cloud app in this article.

Now we will add React and Atlaskit to this app.

You can take the complete version of the code for this article here.

We will start form this code:

git clone git clone https://alex1mmm@bitbucket.org/alex1mmm/jira-cloud-hello-world.git --branch v.1 --single-branch

Move files to backend folder

Our app will have two folders: frontend and backend. In the frontend folder we will develop our React and Atlaskit modules and in the backend folder we will have our Java spring boot starter. Let’s create the two folders and move the src folder and pom.xml file to the backend folder:

Add files to frontend

Now we will add files to the frontend folder. First of all we will create the package.json file with the following contents:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.5.0",
    "@testing-library/user-event": "^7.2.1",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.1"
  },
  "scripts": {
    "build": "webpack --mode production",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@atlaskit/avatar": "^17.1.10",
    "@atlaskit/dropdown-menu": "^9.0.3",
    "@atlaskit/dynamic-table": "^13.7.4",
    "@atlaskit/form": "^7.2.1",
    "@atlaskit/textarea": "^2.2.8",
    "@atlaskit/textfield": "^3.1.10",
    "@atlaskit/toggle": "^8.1.7",
    "@atlaskit/reduced-ui-pack": "^13.0.3",
    "@atlaskit/css-reset": "^6.0.1",
    "@babel/core": "^7.9.6",
    "@babel/preset-env": "^7.9.6",
    "@babel/preset-flow": "^7.9.0",
    "@babel/preset-react": "^7.9.4",
    "@babel/preset-typescript": "^7.10.4",
    "atlassian-webresource-webpack-plugin": "^4.8.0",
    "axios": "^0.19.2",
    "babel-loader": "^8.1.0",
    "fibers": "^5.0.0",
    "fsevents": "^2.1.3",
    "node-sass": "^4.14.1",
    "sass": "^1.3.0",
    "styled-components": "^3.2.6",
    "typescript": "^3.8.3",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11"
  }
}

This file is an npm’s package file which contains all settings for our application. It will let us use React and Atlaskit in our application.

Next we will add the frontend/webpack.config.js with the following contents:

var path = require('path');
module.exports = {
    module: {
         rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    use: {
                         loader: "babel-loader"
                         }
                },
                {
                    test: /\.css$/,
                    loader: 'style-loader!css-loader'
                }
         ]
    },
    watch : true,
    entry: {
            'main': './src/main.js'
    },
    output: {
        filename: 'bundled.[name].js',
        path: path.resolve("../backend/src/main/resources/static")
    }
};

This file means that we will use the webpack module to get our final js file for our application. We will put the final js file to the backend/src/main/resources/static folder. This folder is accessible from our Jira Cloud app.

Next we will add frontend/.babelrc:

{
  "presets": ["@babel/preset-env",
    "@babel/preset-react",
    "@babel/preset-typescript",
    "@babel/preset-flow"],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-transform-runtime",
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-syntax-dynamic-import",

  ]
}

It means that we will use Babel to convert our ECMAScript 2015+ code into a backwards compatible version of JavaScript.

Now we will add the frontend/src/main.js file with a React component which uses Atlaskit :

import React from 'react';
import ReactDOM from 'react-dom';
import Button from '@atlaskit/button';
import '@atlaskit/css-reset';
import '@atlaskit/reduced-ui-pack';

function startRender() {
    ReactDOM.render(
        <Button>
            Button created using React Atlaskit
        </Button>
    , document.getElementById('react-container'));
}

window.onload = startRender;

Now we will add pom.xml file to the frontend folder to be able to package our frontend application:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <artifactId>frontend</artifactId>

    <parent>
        <groupId>ru.matveev.alexey.atlassian.cloud.tutorial</groupId>
        <artifactId>hello-world-parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <frontend-maven-plugin.version>1.6</frontend-maven-plugin.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>com.github.eirslett</groupId>
                <artifactId>frontend-maven-plugin</artifactId>
                <version>${frontend-maven-plugin.version}</version>
                <executions>
                    <!-- Install our node and npm version to run npm/node scripts-->
                    <execution>
                        <id>install node and npm</id>
                        <goals>
                            <goal>install-node-and-npm</goal>
                        </goals>
                        <configuration>
                            <nodeVersion>v11.13.0</nodeVersion>
                        </configuration>
                    </execution>
                    <!-- Install all project dependencies -->
                    <execution>
                        <id>npm install</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <!-- optional: default phase is "generate-resources" -->
                        <phase>generate-resources</phase>
                        <!-- Optional configuration which provides for running any npm command -->
                        <configuration>
                            <arguments>install</arguments>
                        </configuration>
                    </execution>
                    <execution>
                        <id>npm update</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <!-- optional: default phase is "generate-resources" -->

                        <!-- Optional configuration which provides for running any npm command -->
                        <configuration>
                            <arguments>update</arguments>
                        </configuration>
                    </execution>
                    <!-- Build and minify static files -->
                    <execution>
                        <id>npm run build</id>
                        <goals>
                            <goal>npm</goal>
                        </goals>
                        <configuration>
                            <arguments>run build</arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

As you can see we created this pom file as a child pom file. That is why we need to add the parent pom file to the main folder of our app:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
  

    <groupId>ru.matveev.alexey.atlassian.cloud.tutorial</groupId>
    <artifactId>hello-world-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
 
    <name>Parent Bundle</name>
    <url>http://maven.apache.org</url>

    <modules>
        <module>frontend</module>
        <module>backend</module>
    </modules>
</project>

Not let’s try to package our frontend.

As a result you should see the bundled.main.js file in the src/main/resources/static folder:

Fix html page file

Now we need to use our bundled.main.js file in our html page template. That is why we should change the contents of the src/main/resources/templates/helloworld.html file:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <script th:src="@{${atlassianConnectAllJsUrl}}" type="text/javascript"></script>
    <script type="text/javascript" src="/bundled.main.js" charset="utf-8"></script>
</head>
<body>
    <div id="react-container"></div>
    <button type="button" class="ak-button ak-button__appearance-default">Button created using the reduced-ui-pack</button>
</body>

Here we added bundled.main.js file to our html template and then we added a div element for our React component and also we created a button with Atlaskit styles. So basically we have two methods of using React and Atlaskit. I prefer the one with the div container.

Run our app

Now open a tunnel with ngrok

./ngrok http 8080

Copy the https link to your application and set it for the base-url parameter in the backend/application.yml file. You can find more info about ngrok and how to set this parameter in my previous article.

Now run the app and check that it successfully started on localhost by opening http://localhost:8080/atlassian-connect.json in your browser:

Now connect your app to your Jira Cloud (you can find more information in my previous article) and open Manage Apps -> Hello World menu:

Congratulations! Now you use React and Atlaskit in your Jira Cloud app.

To make it easier for you to build a new Jira Cloud app with React and Atlaskit onboard I created a maven archetype over here.

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Leave a Reply

%d bloggers like this:

Spelling error report

The following text will be sent to our editors: