[Из песочницы] Сравниваем страницы. Простой плагин для 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

yvkjuy_l56v_0sri2qq29n2ca20.png

и проверим работу локальной установки по адресу http://localhost:1990/confluence/. Логин admin, пароль admin. В базе уже создано демонстрационное пространство и несколько статей.

Немного функционала


Начнем с меню. Добавим в дескриптор плагина atlassian-plugin.xml модуль web-item.


    Add diff item to drop-down menu
    


Где:

  • атрибут 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. Плагин будет автоматически перезагружен и появится наш пункт меню.

tzynzmmcrwkk1gus95aexxfhsck.png

Модальное окно


Для выбора страницы удобно использовать модальное окно. Продолжим править 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-х символов.

nwpysw_kghikw3t012tkqhhw4t8.png

Основной функционал


Приступим к реализации основного функционала. Добавим в пакет 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
    

$action.getText("diff.page.error")

$action.getText("diff.page.error.message")

#end


Написание плагина закончено. Еще раз выполним maven package, выберем страницу и насладимся полученным результатом.

jsmqgxhol59trstolgios-aosx0.png

Полный код проекта доступен на GitHub.

© Habrahabr.ru