Привет!

В этой статье я расскажу, как сделать страницу в Atlassian Confluence с таблицей, данные в которую будут приходить из REST запроса.

Мы сделаем страницу в Confluence с таблицей, которая будет содержать данные о проектах в Jira. Эти данные мы будем получать из Jira при помощи метода project из стандартного Jira REST API.

Вы можете посмотреть видео по этой статье вот здесь.

Установим Power Scripts for Confluence


Мы будем выполнять вызов Jira REST API с помощью плагина Power Scripts for Confluence. Это бесплатный плагин, поэтому это решение ничего не будет Вам стоить.

Ну, и первое, что нам нужно сделать, это установить плагин Power Scripts for Confluence в наш Confluence. Подробную инструкцию, как это сделать, можно почитать вот здесь.

Напишем скрипт


Теперь перейдем в пункт меню шестеренка -> Manage apps -> SIL Manager.



Создадим файл getProjects.sil вот с таким кодом:

struct Project {
    string key;
    string name;
    string projectTypeKey;
}

HttpRequest request;
HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
request.headers += authHeader;
 
Project [] projects = httpGet("http://host.docker.internal:8080/rest/api/2/project", request);
runnerLog(projects);
return projects;

Измените адрес host.docker.internal:8080/ на адрес Вашего экземпляра Jira.

Запустите скрипт, чтобы проверить, что данные выбираются из Jira:



Создадим страницу в Confluence


Теперь создадим страницу в Confluence с макросом SIL table. В поле scripts введите имя нашего скрипта getProjects.sil:



Опубликуйте страницу и Вы увидите вот такой результат:



Усложним задачу


Добавим в таблицу следующую функциональность:

  • отобразим информацию о руководителе проекта
  • дадим полям более понятные наименования и желательно на русском

Для начала внесем изменения в скрипт getProjects.sil.

Заодно немного отрефакторим.

Вот что будет делать наш скрипт:

  • получаем данные о проектах из Jira через вызов Jira REST API
  • конвертируем полученные данные о проектах в табличный вид
  • выводим результат

Вот так это выглядит в коде:

Project [] projects = getProjectData();
TableRow [] tableRows =  convertProjectDataToTableData(projects);

return tableRows;

Теперь давайте конкретизируем, как мы получаем данные о проектах:

  • создаем запрос
  • создаем хедер в запросе с информацией о пользователе, который получает данные из Jira
  • добавляем параметр expand к нашему запросу. Нам нужно выбрать данные о руководителе проекта, но в ответе по умолчанию этих данных нет. Поэтому нам нужно сказать Jira, что мы хотим видеть данные о руководителе проекта в ответе. Для этого и используется параметр expand
  • выполняем запрос
  • возвращаем данные

А вот слова превратились в код:

function getProjectData() {
    HttpRequest request;
    HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
    request.headers += authHeader;
    HttpQueryParam param = httpCreateParameter("expand", "description,lead,url,projectKeys");
    request.parameters += param;
    Project[] projects = httpGet("http://host.docker.internal:8080/rest/api/2/project", request);
    return projects;
}

Теперь определим структуры данных о наших проектах.

Вот ответ, который возвращает project метод из Jira REST API (я удалил ненужные данные, чтобы сделать ответ короче и поэтому более читабельным):

[
   {
      "key":"KAN",
      "lead":{
         "name":"admin",
         "displayName":"Alexey Matveev",
      },
      "name":"kanban",
      "projectTypeKey":"software"
   },
   {
      "key":"SCRUM",
      "description":"",
      "lead":{
         "name":"admin",
         "displayName":"Alexey Matveev",
      },
      "name":"scrum",
      "projectTypeKey":"software"
   }
]

Как мы видим, значения для полей key, name и projectTypeKey определены на первом уровне нашего json. А вот для поля lead вместо значения мы видим json. А этот json уже и содержит значения полей name и displayName. Поэтому сначала создадим структуру для json в поле lead (Lead):

struct Lead {
    string name;
    string displayName;
}

Вот теперь мы готовы сделать структуру и для первого уровня нашего json (Project):

struct Project {
    string key;
    string name;
    string projectTypeKey;
    Lead lead;
}

Но проблема в том, что макрос SIL table может работать только с json с одним уровнем вложенности, поэтому нам нужно переконвертировать нашу структуру с двумя уровнями вложенности (Project) в структуру с одним уровнем вложенности (плоскую структуру). Но сначала создадим плоскую структуру (TableRow):

struct TableRow {
    string key;
    string name;
    string projectTypeKey;
    string lead;
    string leadDisplayName;
}

А теперь напишем функцию для конвертации данных в структуре Project в структуру TableRow:

function convertProjectDataToTableData(Project [] projectData) {
    TableRow [] tableRows;
    for (Project project in projectData) {
        TableRow tableRow;
        tableRow.key = project.key;
        tableRow.name = project.name;
        tableRow.projectTypeKey = project.projectTypeKey;
        tableRow.lead = project.lead.name;
        tableRow.leadDisplayName = project.lead.displayName;
        tableRows = arrayAddElement(tableRows, tableRow);
    } 
    return tableRows;
}

Все. Скрипт готов!

Вот финальный код getProjects.sil:

struct Lead {
    string name;
    string displayName;
}

struct Project {
    string key;
    string name;
    string projectTypeKey;
    Lead lead;
}

struct TableRow {
    string key;
    string name;
    string projectTypeKey;
    string lead;
    string leadDisplayName;
}

function getProjectData() {
    HttpRequest request;
    HttpHeader authHeader = httpBasicAuthHeader("admin", "admin");
    request.headers += authHeader;
    HttpQueryParam param = httpCreateParameter("expand", "description,lead,url,projectKeys");
    request.parameters += param;
    string pp = httpGet("http://host.docker.internal:8080/rest/api/2/project", request);
    runnerLog(pp);
    Project[] projects = httpGet("http://host.docker.internal:8080/rest/api/2/project", request);
    return projects;
}

function convertProjectDataToTableData(Project [] projectData) {
    TableRow [] tableRows;
    for (Project project in projectData) {
        TableRow tableRow;
        tableRow.key = project.key;
        tableRow.name = project.name;
        tableRow.projectTypeKey = project.projectTypeKey;
        tableRow.lead = project.lead.name;
        tableRow.leadDisplayName = project.lead.displayName;
        tableRows = arrayAddElement(tableRows, tableRow);
    } 
    return tableRows;
}Project [] projects = getProjectData();
TableRow [] tableRows =  convertProjectDataToTableData(projects);

return tableRows;

Теперь обновим страницу в Confluence и увидим, что наши данные о руководителе проекта подтянулись:



Но имена колонок какие-то невразумительные. Давайте дадим более красивые имена.

Редактирум страницу, Редактируем макрос SIL table и вводим «Ключ проекта, Имя проекта, Тип проекта, Руководитель проекта, ФИО руководителя проекта» в поле columns:



Сохраним страницу и вот результат:



Все получилось!