Как стать автором
Обновить

«Kiss the cook» или еще пара рецептов для XWiki

Время на прочтение7 мин
Количество просмотров3.4K

Свободного времени становится всё меньше и меньше, поэтому перейду сразу к делу.

В прошлых статьях я обещал поделиться еще парой приёмов по настройке XWiki, которую я использую как портал для технической документации.

Лучше поздно чем никогда, поэтому сегодня мы:

Я буду давать минимум пояснений, ибо стал забывать, что да как. Примеры должны работать для XWiki 12.10.10 и 13.10.2.

Чиним связку ShowHide macro и аннотации

Популярный макрос ShowHide при добавлении аннотаций к тексту страницы перестает реагировать на клик мышью.

Это связано с особенностями отображения контента аннотированной страницы.

За помощь с решением проблемы большое спасибо @alexkhotkevich.

Для начала включите в настройках пользователя отображение скрытых страниц или просто нажмите комбинацию x+x+x+h.

Затем перейдите на страницу {XwikiURL)/bin/view/Macros/ShowHideMacro

Откройте редактор объектов и в объекте JavaScriptExtensionзамените код на следующий:

require(['jquery'], function($) {
    function onClick () {
        var button = $(this), 
            content = button.parent().next(), 
            effect = button.attr('data-show-effect'),
            data = button.data();
        if($.inArray(effect,['toggle','fadeToggle','slideToggle']) == -1) effect = 'toggle';
        data.showHideState = !(('showHideState' in data) ? data.showHideState : content.is(':visible'));
        button.html(button.attr(data.showHideState ? 'data-hide-message' : 'data-show-message'));
        content.stop()[effect](parseInt(button.attr('data-show-duration')));
        return false;
    }

  $(document).on('xwiki:dom:updated',
  function(){
    $('.showhidebutton').children('a').off('click');
    $('.showhidebutton').children('a').click(onClick);
            }
    )

});

Получится вот так:

Код макроса ShowHide
Код макроса ShowHide

Не забудьте сохранить. 

Чиним проблемы с поиском

Иногда полезно запустить индексацию. Перейдите в раздел "Поиск" в админ-панели, ничего не меняйте и нажмите кнопку "Подтвердить".

Через некоторое время отобразится прогресс индексации (если нет обновите страницу).

Настройки поиска - процесс индексации
Настройки поиска - процесс индексации

Меняем шаблон страницы авторизации

Создадим свой скин. Для начала создайте пустую страницу и добавьте к ней объект XWikiSkins с любым названием и базовым скином flamingo 

Создание скина
Создание скина

Сохраните страницу и закройте редактор объектов. На странице скина перейдите по ссылке "Редактировать скин". 

Переопределите шаблон login.vm и вставьте этот код:

Показать код
## ---------------------------------------------------------------------------
## See the NOTICE file distributed with this work for additional
## information regarding copyright ownership.
##
## This is free software; you can redistribute it and/or modify it
## under the terms of the GNU Lesser General Public License as
## published by the Free Software Foundation; either version 2.1 of
## the License, or (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with this software; if not, write to the Free
## Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
## 02110-1301 USA, or see the FSF site: http://www.fsf.org.
## ---------------------------------------------------------------------------
#if ($xcontext.user != 'XWiki.XWikiGuest')
  #if ($request.xredirect)
    $response.sendRedirect($request.xredirect)
  #else
    $response.sendRedirect($xwiki.getURL($services.model.resolveDocument('', 'default', $doc.documentReference.extractReference('WIKI'))))
  #end
#elseif($doc.fullName != 'XWiki.XWikiLogin')
  #set($qs = "$!{request.queryString}")
  #if(!$request.getParameter('xredirect'))
    #set($qs = "xredirect=$escapetool.url($doc.getURL('view'))&${qs}")
  #end
  $response.sendRedirect($xwiki.getURL('XWiki.XWikiLogin', 'login', $qs))
#else
###
### Login page
###
###
#template("startpage.vm")
<div class="main layoutsubsection">
<div id="mainContentArea">
<form id="loginForm" action="$doc.getURL('loginsubmit')" method="post" class="xform">
<div class="hidden"><input type="hidden" name="xredirect" value="$!{escapetool.xml($request.xredirect)}"/>
#if("$!request.srid" != '')
  <input type="hidden" name="srid" value="$!escapetool.xml($request.srid)"/>
#end
  <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}"/>
</div>
#xwikimessageboxstart($services.localization.render('login') '')
#set($message = $xcontext.message)
#if($message)
  <!-- previous login errors -->
  #error($services.localization.render($message))
#end
#set($authFailureStrategyMessage = $services.security.authentication.getErrorMessage($request.j_username))
#if ("$!authFailureStrategyMessage" != '')
  #error($authFailureStrategyMessage)
#end
#set ($supplementaryForm = $services.security.authentication.getForm($request.j_username))
<dl>
  <dt>
    <label for="j_username">$services.localization.render('username')</label>
    #if($xwiki.exists('XWiki.ForgotUsername') && $xwiki.hasAccessLevel('view', 'XWiki.ForgotUsername'))
      <span class="xAdditional"><a href="$xwiki.getURL('XWiki.ForgotUsername')" tabindex="500">$services.localization.render('xe.admin.forgotUsername.loginMessage')</a></span>
    #end
  </dt>
  <dd class="input-group">
    <span class="input-group-addon">$services.icon.renderHTML('user')</span>
    <input class="form-control" type="text" id="j_username" size="60" name="j_username" value="" tabindex="100"/>
  </dd>
  <dt>
    <label for="j_password">$services.localization.render('password')</label>
    #if($xwiki.exists('XWiki.ResetPassword') && $xwiki.hasAccessLevel('view', 'XWiki.ResetPassword'))
      <span class="xAdditional"><a href="$xwiki.getURL('XWiki.ResetPassword')" tabindex="600">$services.localization.render('xe.admin.passwordReset.loginMessage')</a></span>
    #end
  </dt>
  <dd class="input-group">
    <span class="input-group-addon">$services.icon.renderHTML('lock')</span>
    <input type="password" id="j_password" size="60" name="j_password" value="" tabindex="200"/>
  </dd>
  <dt></dt>
  <dd>
    <label class="xHint" for="rememberme">
      <input id="rememberme" type="checkbox" name="j_rememberme" value="true" tabindex="300"/> $services.localization.render('remembermeonthiscomp')
    </label>
  </dd>
  #if ("$!supplementaryForm" != "")
    <div id="dedicated-auth-failures-field">
      $supplementaryForm
    </div>
  #end
  <dt><input type="submit" class="btn btn-primary col-xs-12" value="$services.localization.render('login')" tabindex="400"/></dt>
</dl>
#xwikimessageboxend()
</form>
</div>## mainContentArea
</div>## main
## Ensure that the username field of the login form has the focus to make it easy for users to log in quickly
<script>
//<![CDATA[
  document.forms.loginForm.j_username.focus();
//]]>
</script>
<div id="customLogin"> ## info about wiki admins
<h2> Xwiki </h2>
Это мой скин страницы для входа, а это мой профиль на <a href="https://habr.com/ru/users/BosonBeard/">Habr</a>
</div>
 
<style>
#customLogin{
max-width: 450px;
margin:auto;
}
#customLoginOlimp h2{
color:#999;
}
</style>
#template("endpage.vm")
#end

Код шаблона login.vm из репозитория темы flamingo, я лишь немного его модифицировал для примера.

Остаётся только выбрать новый скин в параметрах темы.

Выбор скина
Выбор скина

Проверяем страницу входа

Пример окна авторизации
Пример окна авторизации

Оглавление страницы в боковой панели

Просто создайте панель со следующим кодом и разместите её в боковой панели (про панели см. в прошлой статье).

{{velocity}}
{{context document="$services.model.serialize($doc.documentReference)" transformationContext="document"}}
#set ($hasHeaders = [])
#set ($mydoc = $doc.getDocument())
#foreach ($block in $mydoc.getXDOM().getBlocks('class:HeaderBlock', 'DESCENDANT'))
 #set ($discard = $hasHeaders.add($block))
#end

#if($hasHeaders.size()>0)
 #panelheader('Table of Contents')
 {{box cssClass="righttoc"}}{{toc/}}{{/box}}
#end


{{/context}}
{{/velocity}}
Пример окна редактирования панели для оглавления
Пример окна редактирования панели для оглавления

Панель будет скрыта, если на странице нет оглавления.

Устанавливаем пакет из расширенного поиска и размещаем Swagger на странице

Иногда нужно установить расширения, которые не находит обычный поиск.

Для начала найдем нужный WebJar в репозитории.

Мы возьмем для примера Swagger UI 4.4.1

Откроем расширенный поиск и введем название и версию файла из описания:

Пример поискового запроса
Пример поискового запроса

Установите расширение.

Создайте пустую страницу.

Добавьте к ней вложение (у меня это swagger.json).

Откройте редактор, перейдите в режим редактирования исходного кода и вставьте этот код:

Открыть код
 

{{velocity}}
#set ($discard = $xwiki.linkx.use($services.webjars.url('swagger-ui', 'swagger-ui.css',
 {'evaluate': true}), {'type': 'text/css', 'rel': 'stylesheet'}))

{{html clean=false}}

<style type="text/css">
hgroup.main {

left:0px !important;

}


hgroup.main a {

word-wrap: break-word !important;

}
</style>

<div id="status">Загрузка Swagger</div>
<div id="swagger-ui">...</div>

<script>
var swaggerContainer = document.getElementById("swagger-ui")

swaggerContainer.style.display="none";
swagerContent = swaggerContainer.textContent

require.config({
   paths: {
      SwaggerUIBundle: "$services.webjars.url('swagger-ui','swagger-ui-bundle')",
      SwaggerUIStandalonePreset: "$services.webjars.url('swagger-ui','swagger-ui-standalone-preset')"
  }
}); 

require(["SwaggerUIBundle","SwaggerUIStandalonePreset"], function(SwaggerUIBundle,SwaggerUIStandalonePreset) {

    statusDom=document.getElementById("status");
    statusDom.textContent = 'Вставка Swagger...'
      window.onload =  function(){   
      // Begin Swagger UI call region
      // Don't forget to change url.
     const ui = SwaggerUIBundle({
    url:"http://localhost:8080/bin/download/%D0%9F%D1%80%D0%BE%D1%87%D0%B0%D1%8F%20%D0%B4%D0%BE%D0%BA%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D1%8F/%D0%9F%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0%20%D0%B3%D0%B8%D0%BF%D0%BE%D1%82%D0%B5%D0%B7%20%28%D1%82%D0%B5%D1%85%D0%BF%D0%B8%D1%81%29/Test%20Swagger/WebHome/swagger.json", 
    dom_id: '#swagger-ui',
    deepLinking: true,
        presets: [
          SwaggerUIBundle.presets.apis,
          SwaggerUIStandalonePreset
        ],
        plugins: [
          SwaggerUIBundle.plugins.DownloadUrl
        ],

      });
      // End Swagger UI call region
      window.ui = ui;
      statusDom.textContent = '';
      statusDom.style.display="none";
      swaggerContainer.style.display="block";
    };
});
</script>
{{/html}}{{/velocity}}

Не забудьте в url указать вашу ссылку на вложение.

Это вариант кода "на скорую руку" если будет время, в следующих статьях я покажу как сделать макрос для вставки Swagger.

Пример страницы со Swagger
Пример страницы со Swagger

Спасибо, что прочитали до конца. Надеюсь, что мои рецепты кому-то будут полезны.

Теги:
Хабы:
Всего голосов 5: ↑5 и ↓0+5
Комментарии0

Публикации

Ближайшие события