В первой части мы сделали простой плагин для JIRA для работы с базой данных. Теперь придадим нашему плагину «стандартный» внешний вид JIRA.
Для начала добавим немного функционала в наш плагин. Пусть теперь для каждого проекта будет свой список студентов, т.е. студент будет привязан к строго одному проекту, и добавим студентам фамилии на всякий случай. Соответственно, нам придется переделать и выдачу студентов. Выдавать теперь будем только студентов, привязанных к определенному проекту. Для этого нам придется переписать класс Students, добавив туда необходимы атрибуты студента; добавить в интерфейс StudentDAO (и само собой класс StudentDAOImpl) новый метод для получения списка студентов именно для проекта; и переписать в классе MyAction методы execute() и doAdd() в соответствии с новыми изменениями.
Собственно, теперь можно переходить к основному контенту.
Подумав о внешнем виде нашей вкладки, обеспечим работу с изображениями. Пусть изображения будут лежать в папке images. Тогда в файл atlassian-plugin.xml в тег <atlassian-plugin> добавляем строку
Стили для логотипов на странице опишем в icon.css и добавим эти стили в atlassian-plugin.xml в тег <web-resource key=«my-resources»>
В icon.css уже используем пути к изображениям согласно тому пути, который мы указали в свойстве name, когда добавляли изображения к проекту. К примеру,
Собственно, правим наш success.vm под использование REST-API, изменяя тег следующим образом:
Здесь нужен для отображения загрузки, а в тег
Добавим точку входа в наш REST-API. Для этого в файл atlassian-plugin.xml в тег <atlassian-plugin> пропишем
В пакет resource.XML добавим 3 класса для работы нашего API: XmlStudent.java – представление студента при запросе и XmlStudents.java – список студентов. И Mapper.java – общий класс со статическими методами для приведения разных типов к XML виду. Подробности об использованных аннотациях можно прочитать тут.
Ну и добавляем само API. В пакет resource добавим класс StudentResource. Этот класс необходимо унаследовать от класса AbstractResource. Указать для этого класса аннотацию
Собственно, простое API для JIRA готово, теперь если, к примеру, в браузере перейду по адресу:
localhost:8080/rest/simple-api/1.0/project/10002/students
то я получу ответ:
{«pid»:10002,«count»:2,«students»:[{«id»:4,«name»:«Вася»,«surname»:«Пупкин»,«pid»:10002,«created»:«2014-05-07 14:48:15.83»},{«id»:5,«name»:«Игорь»,«surname»:«Петров»,«pid»:10002,«created»:«2014-05-07 17:47:58.5»}]}
Теперь надо написать js, который будет выдавать данные из API в нашу заготовку. Т.к. данные о студентах мы будем выдавать в таблицу, то использовать будем стандартный функционал JIRARestfultable. Проблемой при написании плагина стало найти документацию для версии 4.4. Поэтому здесь остановлюсь подробнее.
Для начала создадим шаблон вывода информации в таблицу – student.soy:
Входящий параметр student – это JSON-объект, содержащий информацию о студенте. Из этого шаблона будет автоматически создан js-код, который потом и будет рисовать строку в таблице.
Для трансформации этого шаблона в js код необходимо в этот же тег еще добавить jiraSoyTransformer — элемент, который сделает из шаблона *.soy скрипт js.
Чтобы корректно работал JIRARestfultable, необходимо добавить следующий элемент для работы механизма интернационализации в этот же тег:
Добавим скрипт StudentRow.js, который создает строки из шаблонов. Скрипты в общем плане типовые, поэтому не буду на них останавливаться.
Теперь создадим скрипт для инициализации нашей таблицы student-init.js:
Необходимо добавить все указанные файлы в тег <my-resources>.Собственно, ничего сложного:
Теперь реализуем удаление, редактирование и добавление студентов.
Для начала сделаем все во внешнем виде, а потом уже сделаем для него REST Api.
Немного переделаем student.soy, добавив в него шаблон JIRA.Templates.Student.editStudentRow для редактирования и добавления студентов. В шаблон JIRA.Templates.Student.studentRow добавим появление стандартной подсветки JIRA для полей, которые можно редактировать, и кнопку удаления. Напишем скрипт EditStudentRow.js для создания строки для редактирования из шаблона JIRA.Templates.Student.editStudentRow. И добавим возможность редактирования в student-init.js. В StudentRow.js. в функцию getStudent добавим обработку нажатия на кнопку удаления.
Осталось добавить новый файл EditStudentRow.js в atlassian-plugin.xml в тег my-resources. И мы получили:
С внешним видом мы закончили. Разберемся, какие запросы отравляются при нажатии на каждую кнопку:
добавление:
удаление:
изменение:
В url: 10000 – id проекта, 10 – id изменяемой строки, в request передаются измененные значения, т.е. если бы мы не меняли surname, то request был бы таким:
Перед тем как писать обработку этих запросов, дополним наш StudentDAO.java необходимыми методами добавления и удаления.
И осталось добавить в StudentResource.java обработку запросов.
Собственно, на этом все. Можно, конечно, дальше написать про MultiSelect и SingleSelect для Jira и как их использовать (свои собственные UserPicker, ProjectPicker, RolePicker и т.п.), как сделать перемещение строк внутри таблицы и много других мелочей, легко осуществимых с помощью restfultable и REST Api.
Код плагина на GitHub.
Первая часть.
Больше проектов:
Как за 5233 человеко-часа создать софт для микротомографа
Управление доступом к электронным документам. От DefView до Vivaldi
Разработка простого плагина для JIRA для работы с базой данных
Разработка простого плагина для JIRA для работы с базой данных: придаем нашему плагину нормальный внешний вид
Автообновление службы Windows через AWS для бедных
Для начала добавим немного функционала в наш плагин. Пусть теперь для каждого проекта будет свой список студентов, т.е. студент будет привязан к строго одному проекту, и добавим студентам фамилии на всякий случай. Соответственно, нам придется переделать и выдачу студентов. Выдавать теперь будем только студентов, привязанных к определенному проекту. Для этого нам придется переписать класс Students, добавив туда необходимы атрибуты студента; добавить в интерфейс StudentDAO (и само собой класс StudentDAOImpl) новый метод для получения списка студентов именно для проекта; и переписать в классе MyAction методы execute() и doAdd() в соответствии с новыми изменениями.
Собственно, теперь можно переходить к основному контенту.
Подумав о внешнем виде нашей вкладки, обеспечим работу с изображениями. Пусть изображения будут лежать в папке images. Тогда в файл atlassian-plugin.xml в тег <atlassian-plugin> добавляем строку
<resource type="download" name="images/" location="images/" />
Стили для логотипов на странице опишем в icon.css и добавим эти стили в atlassian-plugin.xml в тег <web-resource key=«my-resources»>
<resource type="download" name="icon.css" location="myaction/css/icon.css"/>
В icon.css уже используем пути к изображениям согласно тому пути, который мы указали в свойстве name, когда добавляли изображения к проекту. К примеру,
.project-config-icon48-students{
background: transparent url(images/student-48px.png) no-repeat 0 0;
}
Собственно, правим наш success.vm под использование REST-API, изменяя тег следующим образом:
<body>
<div id="project-config-panel-students" class="project-config-panel">
<div class="project-config-panel-header project-config-icon48-students">
<h2>Students</h2>
<p>Students description.</p>
</div>
<form id="project-config-students" class="loading" action="#">
<table class="aui" id="project-config-students-table">
<thead>
<tr>
<th><!--icon--></th>
<th>name</th>
<th>surname</th>
<th>created</th>
<th><!--buttons--></th>
<th><!--throbber--></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<div class="jira-restfultable-init">
<span class="jira-restfultable-throbber"></span>
<span class="jira-restfultable-loading">Loading</span>
</div>
</form>
</div>
</body>
Здесь нужен для отображения загрузки, а в тег
<table>
будут выводиться студенты. Страница без REST-API выглядит следующим образом:Добавим точку входа в наш REST-API. Для этого в файл atlassian-plugin.xml в тег <atlassian-plugin> пропишем
<rest key="pluginRESTpoints" path="/simple-api" version="1.0" />
В пакет resource.XML добавим 3 класса для работы нашего API: XmlStudent.java – представление студента при запросе и XmlStudents.java – список студентов. И Mapper.java – общий класс со статическими методами для приведения разных типов к XML виду. Подробности об использованных аннотациях можно прочитать тут.
Ну и добавляем само API. В пакет resource добавим класс StudentResource. Этот класс необходимо унаследовать от класса AbstractResource. Указать для этого класса аннотацию
@Path("project/{pid}/students")
, отвечающую за путь, по которому мы будем обращаться к этому классу посредством REST-API, и аннотацию @Produces({"application/json"})
, отвечающую за тип передаваемых данных. В классе создадим метод getStudents, который будет выдавать список студентов. Укажем для него аннотацию @GET
, соответствующую методу запроса. Параметрами метода будут: @PathParam("pid") String pid
– отвечает за id проекта и берется из пути, @QueryParam("id") String id
– отвечает за id студента и берется из запроса. Подробности об аннотациях можно прочитать тут.Собственно, простое API для JIRA готово, теперь если, к примеру, в браузере перейду по адресу:
localhost:8080/rest/simple-api/1.0/project/10002/students
то я получу ответ:
{«pid»:10002,«count»:2,«students»:[{«id»:4,«name»:«Вася»,«surname»:«Пупкин»,«pid»:10002,«created»:«2014-05-07 14:48:15.83»},{«id»:5,«name»:«Игорь»,«surname»:«Петров»,«pid»:10002,«created»:«2014-05-07 17:47:58.5»}]}
Теперь надо написать js, который будет выдавать данные из API в нашу заготовку. Т.к. данные о студентах мы будем выдавать в таблицу, то использовать будем стандартный функционал JIRARestfultable. Проблемой при написании плагина стало найти документацию для версии 4.4. Поэтому здесь остановлюсь подробнее.
Для начала создадим шаблон вывода информации в таблицу – student.soy:
{namespace JIRA.Templates.Student}
/**
* @param student
*/
{template .studentRow}
<td class="jira-restfultable-icon project-config-student-icon">
<span class="project-config-icon project-config-icon-student"></span>
</td>
<td class="project-config-student-name">
{$student.name}
</td>
<td class="project-config-student-surname">
{$student.surname}
</td>
<td class="project-config-student-created">
{$student.created}
</td>
<td class="jira-restfultable-operations"></td>
<td class="project-config-throbber"></td>
{/template}
Входящий параметр student – это JSON-объект, содержащий информацию о студенте. Из этого шаблона будет автоматически создан js-код, который потом и будет рисовать строку в таблице.
Для трансформации этого шаблона в js код необходимо в этот же тег еще добавить jiraSoyTransformer — элемент, который сделает из шаблона *.soy скрипт js.
<transformation extension="soy">
<transformer key="jiraSoyTransformer"/>
</transformation>
Чтобы корректно работал JIRARestfultable, необходимо добавить следующий элемент для работы механизма интернационализации в этот же тег:
<transformation extension="js">
<transformer key="jsI18n"/>
</transformation>
Добавим скрипт StudentRow.js, который создает строки из шаблонов. Скрипты в общем плане типовые, поэтому не буду на них останавливаться.
jQuery.namespace("JIRA.Admin.Student.StudentRow");
JIRA.Admin.Student.StudentRow = JIRA.RestfulTable.Row.extend({
initialize: function() {
JIRA.RestfulTable.Row.prototype.initialize.apply(this, arguments);
},
render: function() {
var data = this.model.toJSON(),
id = this.model.get("id"),
$el = this.$el;
$el.attr("id", "student-" + id + "-row").attr("data-id", id);
$el.html(JIRA.Templates.Student.studentRow({
student: data
}));
return this;
}
});
Теперь создадим скрипт для инициализации нашей таблицы student-init.js:
jQuery(function() {
var $table = AJS.$("#project-config-students-table");
var $project = AJS.$("meta[name=projectId]").attr("content");
function getResourceURL() {
return contextPath + "/rest/simple-api/1.0/project/" + $project + "/students";
}
function getStudent(callback) {
JIRA.SmartAjax.makeRequest({
url: getResourceURL(),
complete: function(xhr, status, response) {
if (response.successful) {
callback(response.data.students);
} else {
$table.trigger("serverError",
[JIRA.SmartAjax.buildSimpleErrorContent(response)]);
}
}
});
}
getStudent(function(students) {
JIRA.Admin.StudentTable = new JIRA.RestfulTable({
el: $table,
url: getResourceURL(),
entries: students,
noEntriesMsg: 'There are currently no students for this project.',
views: {
row: JIRA.Admin.Student.StudentRow
}
});
jQuery(".jira-restfultable-init").remove();
JIRA.userhover($table);
});
});
Необходимо добавить все указанные файлы в тег <my-resources>.Собственно, ничего сложного:
Теперь реализуем удаление, редактирование и добавление студентов.
Для начала сделаем все во внешнем виде, а потом уже сделаем для него REST Api.
Немного переделаем student.soy, добавив в него шаблон JIRA.Templates.Student.editStudentRow для редактирования и добавления студентов. В шаблон JIRA.Templates.Student.studentRow добавим появление стандартной подсветки JIRA для полей, которые можно редактировать, и кнопку удаления. Напишем скрипт EditStudentRow.js для создания строки для редактирования из шаблона JIRA.Templates.Student.editStudentRow. И добавим возможность редактирования в student-init.js. В StudentRow.js. в функцию getStudent добавим обработку нажатия на кнопку удаления.
Осталось добавить новый файл EditStudentRow.js в atlassian-plugin.xml в тег my-resources. И мы получили:
С внешним видом мы закончили. Разберемся, какие запросы отравляются при нажатии на каждую кнопку:
добавление:
url: http://localhost:8080/rest/simple-api/1.0/project/10000/students
method: POST
request: {"name":"Дима","surname":"Андреев"}
удаление:
url: http://localhost:8080/rest/simple-api/1.0/project/10000/students/10?[дальше идет request]
method: DELETE
1. request: id=10&name=Вася&surname=Пушкин&pid=10000&created=2014-05-13 15:54:12.803
изменение:
url: http://server/rest/simple-api/1.0/project/10000/students/10
method: PUT
request: {"id":10,"name":"Дима","surname":"Андреев"}
В url: 10000 – id проекта, 10 – id изменяемой строки, в request передаются измененные значения, т.е. если бы мы не меняли surname, то request был бы таким:
{"id":10,"name":"Дима"}
Перед тем как писать обработку этих запросов, дополним наш StudentDAO.java необходимыми методами добавления и удаления.
И осталось добавить в StudentResource.java обработку запросов.
Собственно, на этом все. Можно, конечно, дальше написать про MultiSelect и SingleSelect для Jira и как их использовать (свои собственные UserPicker, ProjectPicker, RolePicker и т.п.), как сделать перемещение строк внутри таблицы и много других мелочей, легко осуществимых с помощью restfultable и REST Api.
Код плагина на GitHub.
Первая часть.
Больше проектов:
Как за 5233 человеко-часа создать софт для микротомографа
Управление доступом к электронным документам. От DefView до Vivaldi
Разработка простого плагина для JIRA для работы с базой данных
Разработка простого плагина для JIRA для работы с базой данных: придаем нашему плагину нормальный внешний вид
Автообновление службы Windows через AWS для бедных