Плагин для Jira Cloud: React и Atlaskit

Привет!

Вот в этой статье мы создали плагин для Jira Cloud.

Сейчас мы добавим в этот плагин поддержку React и Atlaskit.

Вы можете взять исходный код получившегося плагина вот здесь.

Мы начнем с кода, который мы сделали в прошлой статье. Можно взять отсюда:

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

Перемещаем файлы в папку backend

Наш плагин будет состоять из двух папок: backend и frontend. В папке frontend у нас будет лежать наше приложение на JavaScript, разработанное на React и Atlaskit. В папке backend у нас будет находиться код на atalssian-connect-spring-boot для старта нашего приложения. Итак, переместим в папку backend папку src и файл pom.xml:

Добавим файлы в папку frontend

Теперь начнем заполнять папку frontend. Сначала создадим файл package.json:

{
  "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"
  }
}

Этот файл нужен для npm и содержит зависимости, которые нам понадобятся, чтобы разрабатывать код на React и Atlaskit.

Теперь создадим файл frontend/webpack.config.js:

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")
    }
};

Этот файл говорит о том, что мы будет использовать webpack для того, чтобы собрать все наши компоненты на React и Atlaskit в один JS файл. Этот JS файл будет записываться в папку backend/src/main/resources/static. Эта папка доступна из нашего плагина.

Далее создадим файл 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",

  ]
}

Это означает, что мы будем использвать Babel для конвертации кода ECMAScript 2015+ в код, который будет понятен браузерам.

Теперь добавим наш компонент React с Atlaskit. Создадим файл frontend/src/main.js:

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;

Готово. Теперь создадим файл pom.xml, который будет собирать наш фронт:

<?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>

Как Вы видите это pom является дочерним, поэтому нам нужно создать родительский pom.xml в корневом каталоге нашего плагина:

<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>

Теперь соберем наш фронтенд.

В резульате сборки у Вас должен создаться файл bundled.main.js в папке src/main/resources/statiс:

Правим HTML шаблон

Теперь нам нужно подцепить созданный bundled.main.js file в наш HTML шаблон. Для этого мы запишем в файл src/main/resources/templates/helloworld.html вот такой код:

<!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>

Мы добавили ссылку на bundled.main.js, добавили div элемент для отображения нашего React компонента, а также создали кнопку, которая тоже работает с Atlaskit но без элемента div. В реальном проекте я предпочитаю работать с элементом div.

Запускаем наш плагин

Открываем туннель ngrok

./ngrok http 8080

Скопируйте https ссылку на Ваш плагин и установите ее как значение параметра base-url в файле backend/application.yml. Вы можете подробнее об этом почитать в моей предыдущей статье.

Теперь запустим плагин и проверим, что он запустился, перейдя по ссылке http://localhost:8080/atlassian-connect.json в браузере:

Теперь подцепим наш плагин к Вашему Jira Cloud инстансу (подробнее как это сделать, можете почитать в моей предыдущей статье) и откроем пункт меню Manage Apps -> Hello World:

Поздравляю! Вы сделали Jira Cloud плагин, который использует React и Atlaskit.

Чтобы облегчить жизнь по созданию новых плагинов для Jira Cloud с поддержкой React и Atlaskit, я создал архетип maven вот здесь.

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: