Разработка простого плагина для JIRA для работы с базой данных: придаем нашему плагину нормальный внешний вид

В первой части мы сделали простой плагин для JIRA для работы с базой данных. Теперь придадим нашему плагину «стандартный» внешний вид JIRA.2860b63683894a8e85be3c4ac9b6079a.png

Для начала добавим немного функционала в наш плагин. Пусть теперь для каждого проекта будет свой список студентов, т.е. студент будет привязан к строго одному проекту, и добавим студентам фамилии на всякий случай. Соответственно, нам придется переделать и выдачу студентов. Выдавать теперь будем только студентов, привязанных к определенному проекту. Для этого нам придется переписать класс Students, добавив туда необходимы атрибуты студента; добавить в интерфейс StudentDAO (и само собой класс StudentDAOImpl) новый метод для получения списка студентов именно для проекта; и переписать в классе MyAction методы execute () и doAdd () в соответствии с новыми изменениями.Собственно, теперь можно переходить к основному контенту.

Подумав о внешнем виде нашей вкладки, обеспечим работу с изображениями. Пусть изображения будут лежать в папке images. Тогда в файл atlassian-plugin.xml в тег добавляем строку

Стили для логотипов на странице опишем в icon.css и добавим эти стили в atlassian-plugin.xml в тег В icon.css уже используем пути к изображениям согласно тому пути, который мы указали в свойстве name, когда добавляли изображения к проекту. К примеру, .project-config-icon48-students{ background: transparent url (images/student-48 px.png) no-repeat 0 0; } Собственно, правим наш success.vm под использование REST-API, изменяя тег следующим образом:

Students

Students description.

name surname created
Loading
Здесь нужен для отображения загрузки, а в тег будут выводиться студенты. Страница без REST-API выглядит следующим образом: bb77c4cba0db474c8fb8181e10906df5.png

Добавим точку входа в наш REST-API. Для этого в файл atlassian-plugin.xml в тег пропишем

В пакет 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}

{/template} Входящий параметр student — это JSON-объект, содержащий информацию о студенте. Из этого шаблона будет автоматически создан js-код, который потом и будет рисовать строку в таблице.Для трансформации этого шаблона в js код необходимо в этот же тег еще добавить jiraSoyTransformer — элемент, который сделает из шаблона *.soy скрипт js.

Чтобы корректно работал JIRARestfultable, необходимо добавить следующий элемент для работы механизма интернационализации в этот же тег: Добавим скрипт 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); }); }); Необходимо добавить все указанные файлы в тег .Собственно, ничего сложного:

e891956995f444aaafd5ed3a10943544.png Теперь реализуем удаление, редактирование и добавление студентов.

Для начала сделаем все во внешнем виде, а потом уже сделаем для него 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. И мы получили:

b2b8bfd645b14e52949c578354f6818a.png

С внешним видом мы закончили. Разберемся, какие запросы отравляются при нажатии на каждую кнопку:

добавление:

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.

Первая часть.

© Habrahabr.ru




{$student.name} {$student.surname} {$student.created}