[Из песочницы] Сравниваем страницы. Простой плагин для Atlassian Confluence
В Atlassian Confluence есть замечательный функционал сравнения версий страницы. Им удобно пользоваться, но выйти за пределы истории изменений не удастся. Как же быть? Поиск готового плагина в Marketplace результатов не дал и было принято решение написать свой.
Инструменты
Нам понадобятся:
- Oracle JDK или AdoptOpenJDK 1.8, работа с OpenJDK официально не поддерживается;
- Atlassian SDK — можно скачать с официального сайта для Windows и Linux/Mac без СМС и регистрации;
- Apache Maven;
- Любимая среда разработки, у меня IntelliJ IDEA.
Создадим проект
Установим SDK и выполним скрипт atlas-create-confluence-plugin
.
Вводим:
- group-id: com.kshch.confluence.plugins
- artifact-id: diff-page
- version: 1.0.0-SNAPSHOT
- package: com.kshch.confluence.plugins.diff.page
Для сборки можно воспользоваться maven-ом и зависимостями из SDK, но проще подключить дополнительные репозитории в своем settings.xml.
atlassian-public
https://packages.atlassian.com/maven/repository/public
true
never
warn
true
warn
atlassian-public
https://maven.atlassian.com/repository/public
true
warn
never
warn
Откроем получившийся проект в IDE, запустим Confluence в режиме отладки confluence:debug
и проверим работу локальной установки по адресу http://localhost:1990/confluence/. Логин admin, пароль admin. В базе уже создано демонстрационное пространство и несколько статей.
Немного функционала
Начнем с меню. Добавим в дескриптор плагина atlassian-plugin.xml модуль web-item.
Add diff item to drop-down menu
/plugins/diffPage/diffPagePopup.action?spaceKey=${space.key}&sourcePageId=${page.id}
Где:
- атрибут section — определяет место появления пункта меню;
- атрибут weight — отвечает за порядок сортировки;
- атрибут key тега label — ключ, по которому в файлах ресурсов находится название отображаемого пункта меню;
- тег link — содержит ссылку, а атрибут linkId ее id;
- condition — определяет условие появления, в нашем случае только на страницах.
Добавляем в diff-page.properties строку: diff.page.menu.name=Diff page
Если нужна поддержка переводов — создадим дополнительные property, например, для русской локализации файл будет называться diff-page_ru_RU.properties.
Выполним maven package
. Плагин будет автоматически перезагружен и появится наш пункт меню.
Модальное окно
Для выбора страницы удобно использовать модальное окно. Продолжим править atlassian-plugin.xml
Добавим немного ресурсов:
com.atlassian.auiplugin:ajs
com.atlassian.auiplugin:dialog2
page
Где:
- тег dependency — зависимость;
- в атрибутах resource указаны тип ресурса, имя и расположение на файловой системе;
- тег context — определяет видимость в зависимости от контекста.
Определим обработчики наших url-ов:
Diff page action
/templates/diff-page.vm
/templates/diff-page-popup.vm
Где:
- атрибут name тега action — определяет название ссылки, а class — java class для ее обработки;
- тег result — содержит ссылку на шаблон, в нашем случае velocity.
Создадим новый пакет com.kshch.confluence.plugins.diff.page.action и добавим в него класс DiffPagePopupAction, расширяющий ConfluenceActionSupport с 2-мя полями.
private String spaceKey;
private Long sourcePageId;
Сгенерируем к ним геттеры и сеттеры. В поле spaceKey будет содержаться ключ текущего пространства, а в sourcePageId — id текущей страницы.
Займемся фронтом. Для создания всплывающего окна воспользуемся элементом dialog2 из фреймворка AUI.
Добавим в диалог форму, кнопку submit и input-ы с css классами autocomplete-space и autocomplete-page, что позволит без дополнительных усилий организовать выбор пространства и страницы. Сохраним полученный результат в /templates/diff-page-popup.vm.
Для отображения окна создадим в ресурсах /js/diff-page-popup.js со следующим содержимым:
(function ($) {
$(function () {
AJS.$('#diff-page').unbind('click');
AJS.$('#diff-page').bind("click", function (e) {
e.preventDefault();
var link = AJS.$(this);
AJS.$.get(link.attr('href'), function (response) {
AJS.$('.aui-page-panel').after(response);
AJS.dialog2("#diff-page-popup").show();
Confluence.Binder.autocompletePage(AJS.$("#diff-page-popup-binder"));
});
return false;
});
});
})(AJS.$);
Его задача переопределить стандартное событие click и показать нам всплывающее окно, а не осуществить переход по ссылке.
Выполним maven package
и попробуем выбрать страницу и пространство. Подсказчик активируется после набора 2-х символов.
Основной функционал
Приступим к реализации основного функционала. Добавим в пакет com.kshch.confluence.plugins.diff.page.action еще один класс DiffPageAction, расширяющий ConfluenceActionSupport и реализующий интерфейс PageAware со следующими полями.
private Long sourcePageId;
private Long destinationPageId;
private String spaceKey;
private String destinationPageName;
private String sourcePageTitle;
private String destinationPageTitle;
private String diff;
private Page sourcePage;
private Differ differ;
private final PageManager pageManager;
Где:
- sourcePageId — id исходной страницы;
- destinationPageId — id сравниваемой страницы;
- spaceKey — ключ пространства;
- destinationPageName — имя сравниваемой страницы;
- sourcePageTitle — заголовок исходной страницы;
- destinationPageTitle — заголовок сравниваемой страницы;
- diff — результат сравнения.
Сгенерируем геттеры и сеттеры, реализуем все методы, кроме getPage, как предлагает IDE по умолчанию. В полях sourcePageId, spaceKey и destinationPageName будут содержаться данные, которые пришли из формы внутри dialog2.
@Override
public AbstractPage getPage() {
return this.sourcePage;
}
Переопределим метод execute своим. Именно в нем и заключена основная логика работы плагина.
@Override
public String execute() throws Exception {
if (this.sourcePageId != null && this.spaceKey != null && this.destinationPageName != null) {
this.sourcePage = this.pageManager.getPage(this.sourcePageId);
Page destinationPage = this.pageManager.getPage(this.spaceKey, this.destinationPageName);
if (this.sourcePage != null && destinationPage != null) {
this.destinationPageId = destinationPage.getId();
this.sourcePageTitle = this.sourcePage.getTitle();
this.destinationPageTitle = destinationPage.getTitle();
this.diff = this.differ.diff(this.sourcePage, destinationPage);
}
}
return super.execute();
}
Остается реализовать frontend сравнения 2-х страниц. Он гораздо проще всплывающего окна.
Создадим в ресурсах /templates/diff-page.vm. В нем, кроме верстки, реализуем простейшую проверку на ошибки.
#if ($action.getDiff())
#diffBody()
#else
#end
Написание плагина закончено. Еще раз выполним maven package
, выберем страницу и насладимся полученным результатом.
Полный код проекта доступен на GitHub.