conung_vic (conung_vic) wrote,
conung_vic
conung_vic

Оглавление в вики в Redmine

На работе стали использовать систему управления проектами Redmine. Система хорошая, содержит в себе много модулей, и в том числе, вики.

Мы стали её использовать в качестве руководства пользователя и программиста, и довольно быстро её содержание стало очень большим и неудобным.

Под катом подробности, как я с этим поборолся.



Так как я в редмайне и в рельсах - новичок и нуб, то решил проблему довольно криво.

1. Переписал файл /app/views/wiki/special_page_index.rhtml

Было:
<%= render_page_hierarchy(@pages_by_parent_id, nil) %>


Стало:
<ul class="root_item">Оглавление
<%= render_page_hierarchy(@pages_by_parent_id, nil, true) %>
</ul>


2. Переписал файл /app/views/layots/base.rhtml
Было:

<%= call_hook :view_layouts_base_html_head %>

<!-- page specific tags -->

<%= yield :header_tags -%>

</head>


Стало:

<%= call_hook :view_layouts_base_html_head %>

<!-- page specific tags -->

<%= yield :header_tags -%>
<style type="text/css">

<!--

ul, li {cursor:pointer;}



li.root_item {list-style-type: none;list-style-image: url();}

li.open_item {list-style-image: url(PATH_TO_REDMINE/images/minus.gif);}

li.close_item {list-style-image: url(PATH_TO_REDMINE/images/plus.gif);}

li.list_item {list-style-type: none;list-style-image: url(PATH_TO_REDMINE/images/empty.gif);}



ul.open_list {display:block;list-style-type: none;list-style-image: none;}

ul.close_list {display:none;list-style-type: none;list-style-image: none;}

-->

</style>
<script language="javascript1.4" type="text/javascript">

    var DOM;

    var Opera;

    var IE;

    var Firefox;

  function do_some(src, evt) {

    if (!Firefox) {

        cls = src.children[1].className;

        if (cls=='open_list') {

          src.children[1].className = 'close_list';

          src.className = 'close_item';

        } else {

          src.children[1].className = 'open_list';

          src.className = 'open_item';

        }

        window.event.cancelBubble = true;

    } else {

        if (evt.eventPhase!=3) {

            cls = src.className;

             if (cls=='open_item') {

              src.childNodes[3].className = 'close_list';

              src.className = 'close_item';

            } else {

              src.childNodes[3].className = 'open_list';

              src.className = 'open_item';

            }

        }

    }

  }

  function Check() {

    if (!Firefox) {

      window.event.cancelBubble = true;

    }

  }



DOM = document.getElementById;

Opera = window.opera && DOM;

IE = document.all && !Opera;

Firefox = navigator.userAgent.indexOf("Firefox") >= 0;

</script>

</head>


3. Переписал файл /app/helpers/application_helper.rb
Было:

  def render_page_hierarchy(pages, node=nil)

    content = ''

    if pages[node]

      content << "<ul class=\"pages-hierarchy\">\n"

      pages[node].each do |page|

        content << "<li>"

        content << link_to(h(page.pretty_title), {:controller => 'wiki', :action => 'index', :id => page.project, :page => page.title},

                           :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))

        content << "\n" + render_page_hierarchy(pages, page.id) if pages[page.id]

        content << "</li>\n"

      end

      content << "</ul>\n"

    end

    content

  end


Стало:

  def render_page_hierarchy(pages, node=nil, first=nil)

     content = ''

     if pages[node]

       if first

         css_class = "open"

       else

         css_class = "close"

       end

       content << "<ul class=\""+css_class+"_list\" onClick=\"Check();\">\n"

       pages[node].each do |page|

         js = ""

         if pages[page.id]

           css_class = "close"

           js = "onClick=\"do_some(this, event);\""

           content << "<li class=\""+css_class+"_item\""+js+" >\n"

           content << h(page.pretty_title)+"&nbsp;"

           content << link_to("<b>=><img src=\"PATH_TO_REDMINE/images/external.png\"></b>", {:controller => 'wiki', :action => 'index', :id => page.project, :page => page.title},

                              :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))

           content << "\n"+render_page_hierarchy(pages, page.id)

         else

           css_class = "list"

           content << "<li class=\""+css_class+"_item\""+js+" >\n"

           content << link_to(h(page.pretty_title)+"&nbsp;", {:controller => 'wiki', :action => 'index', :id => page.project, :page => page.title},

                              :title => (page.respond_to?(:updated_on) ? l(:label_updated_time, distance_of_time_in_words(Time.now, page.updated_on)) : nil))

         end

         content << "</li> \n"

       end

       content << "</ul> \n"

     end

     content

  end


4. Добавил файлы plus.gif, minus.gif, empty.gif в каталог /public/images
(empty.gif - прозрачный однопиксельный файл)
- minus.gif

- plus.gif



Что получил:
1. Сворачиваемое/разворачиваемое содержание.
2. Для элементов, не имеющих дочерних ссылкой будет весь элемент.
3. Для элементов, имеющих дочерние - ссылкой будет доп. текст (=>)

Что не нравится:

1. Код далеко не идеальный, что JS, что Ruby. Можно было бы переписать, но я пока не умею лучше.
2. Привязка к абсолютному адресу сервера в пути к изображениям.

3. И САМОЕ ГЛАВНОЕ. При обновлении Redmine это все слетит, так как выполнено в виде хака. Как бы это сделать в виде плагина?


И что получил в итоге:



 
Tags: Программинг
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 2 comments