From da0581a172e82d3bf0b53a8d5123312ad6cf6255 Mon Sep 17 00:00:00 2001 From: Marius BALTEANU Date: Mon, 22 Jan 2018 21:21:30 +0000 Subject: [PATCH 2/2] replace preview link with write priview tabs --- app/controllers/messages_controller.rb | 2 +- app/controllers/previews_controller.rb | 23 +++--- app/controllers/wiki_controller.rb | 2 +- app/views/boards/show.html.erb | 3 - app/views/common/_preview.html.erb | 8 +- app/views/issues/_edit.html.erb | 7 +- app/views/issues/_form.html.erb | 2 +- app/views/issues/new.html.erb | 3 - app/views/journals/_notes_form.html.erb | 7 +- app/views/messages/_form.html.erb | 2 +- app/views/messages/edit.html.erb | 2 - app/views/messages/new.html.erb | 3 - app/views/messages/show.html.erb | 2 - app/views/news/_form.html.erb | 2 +- app/views/news/edit.html.erb | 2 - app/views/news/index.html.erb | 2 - app/views/news/new.html.erb | 2 - app/views/news/show.html.erb | 4 +- app/views/previews/issue.html.erb | 11 --- app/views/wiki/edit.html.erb | 7 +- config/locales/en.yml | 1 + config/routes.rb | 5 +- lib/redmine/wiki_formatting.rb | 2 +- lib/redmine/wiki_formatting/markdown/helper.rb | 4 +- lib/redmine/wiki_formatting/textile/helper.rb | 4 +- public/javascripts/application.js | 33 +++++--- public/javascripts/attachments.js | 3 +- public/javascripts/jstoolbar/jstoolbar.js | 96 ++++++++++++++++++++--- public/javascripts/jstoolbar/lang/jstoolbar-en.js | 2 + public/stylesheets/application.css | 20 ++++- public/stylesheets/jstoolbar.css | 32 +++++++- test/functional/messages_controller_test.rb | 14 ++-- test/functional/previews_controller_test.rb | 81 ++++--------------- test/integration/attachments_test.rb | 5 +- test/integration/layout_test.rb | 2 +- test/integration/routing/previews_test.rb | 14 ++-- test/system/issues_test.rb | 10 +-- 37 files changed, 229 insertions(+), 195 deletions(-) delete mode 100644 app/views/previews/issue.html.erb diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 76bc19c..0ba360e 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -118,7 +118,7 @@ class MessagesController < ApplicationController def preview message = @board.messages.find_by_id(params[:id]) - @text = (params[:message] || params[:reply])[:content] + @text = params[:text] ? params[:text] : nil @previewed = message render :partial => 'common/preview' end diff --git a/app/controllers/previews_controller.rb b/app/controllers/previews_controller.rb index 37cdc46..41e6941 100644 --- a/app/controllers/previews_controller.rb +++ b/app/controllers/previews_controller.rb @@ -16,31 +16,30 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. class PreviewsController < ApplicationController - before_action :find_project, :find_attachments + before_action :find_project, :except => :text + before_action :find_attachments def issue - @issue = Issue.visible.find_by_id(params[:id]) unless params[:id].blank? + @issue = Issue.visible.find_by_id(params[:issue_id]) unless params[:issue_id].blank? if @issue - @description = params[:issue] && params[:issue][:description] - if @description && @description.gsub(/(\r?\n|\n\r?)/, "\n") == @issue.description.to_s.gsub(/(\r?\n|\n\r?)/, "\n") - @description = nil - end - @notes = params[:journal] ? params[:journal][:notes] : nil - @notes ||= params[:issue] ? params[:issue][:notes] : nil - else - @description = (params[:issue] ? params[:issue][:description] : nil) + @previewed = @issue end - render :layout => false + @text = params[:text] ? params[:text] : nil + render :partial => 'common/preview' end def news if params[:id].present? && news = News.visible.find_by_id(params[:id]) @previewed = news end - @text = (params[:news] ? params[:news][:description] : nil) + @text = params[:text] ? params[:text] : nil render :partial => 'common/preview' end + def text + @text = params[:text] ? params[:text] : nil + render :partial => 'common/preview' + end private def find_project diff --git a/app/controllers/wiki_controller.rb b/app/controllers/wiki_controller.rb index b43b933..c5f7cdc 100644 --- a/app/controllers/wiki_controller.rb +++ b/app/controllers/wiki_controller.rb @@ -321,7 +321,7 @@ class WikiController < ApplicationController @attachments += page.attachments @previewed = page.content end - @text = params[:content][:text] + @text = params[:content].present? ? params[:content][:text] : params[:text] render :partial => 'common/preview' end diff --git a/app/views/boards/show.html.erb b/app/views/boards/show.html.erb index 4a0a588..02dffa2 100644 --- a/app/views/boards/show.html.erb +++ b/app/views/boards/show.html.erb @@ -14,10 +14,8 @@ <%= form_for @message, :url => new_board_message_path(@board), :html => {:multipart => true, :id => 'message-form'} do |f| %> <%= render :partial => 'messages/form', :locals => {:f => f} %>

<%= submit_tag l(:button_create) %> - <%= preview_link(preview_board_message_path(@board), 'message-form') %> | <%= link_to l(:button_cancel), "#", :onclick => '$("#add-message").hide(); return false;' %>

<% end %> -
<% end %> @@ -60,7 +58,6 @@ <% end %> <% html_title @board.name %> - <% content_for :header_tags do %> <%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@project}: #{@board}") %> <% end %> diff --git a/app/views/common/_preview.html.erb b/app/views/common/_preview.html.erb index 90d83ce..ee22288 100644 --- a/app/views/common/_preview.html.erb +++ b/app/views/common/_preview.html.erb @@ -1,3 +1,5 @@ -
<%= l(:label_preview) %> -<%= textilizable @text, :attachments => @attachments, :object => @previewed %> -
+<% unless @text.blank? %> + <%= textilizable @text, :attachments => @attachments, :object => @previewed %> +<% else %> +

<%= l(:label_nothing_to_preview) %>

+<% end %> \ No newline at end of file diff --git a/app/views/issues/_edit.html.erb b/app/views/issues/_edit.html.erb index fe2119a..3afaee4 100644 --- a/app/views/issues/_edit.html.erb +++ b/app/views/issues/_edit.html.erb @@ -30,7 +30,7 @@ <% if @issue.notes_addable? %>
<%= l(:field_notes) %> <%= f.text_area :notes, :cols => 60, :rows => 10, :class => 'wiki-edit', :no_label => true %> - <%= wikitoolbar_for 'issue_notes' %> + <%= wikitoolbar_for 'issue_notes', preview_issue_path(:project_id => @project, :issue_id => @issue) %> <% if @issue.safe_attribute? 'private_notes' %> <%= f.check_box :private_notes, :no_label => true %> @@ -68,13 +68,12 @@ <%= f.hidden_field :lock_version %> <%= hidden_field_tag 'last_journal_id', params[:last_journal_id] || @issue.last_journal_id %> <%= submit_tag l(:button_submit) %> - <%= preview_link preview_edit_issue_path(:project_id => @project, :id => @issue), 'issue-form' %> - | <%= link_to l(:button_cancel), issue_path(id: @issue.id), :onclick => params[:action] == 'show' ? "$('#update').hide(); return false;" : '' %> + <%= link_to l(:button_cancel), issue_path(id: @issue.id), :onclick => params[:action] == 'show' ? "$('#update').hide(); return false;" : '' %> <%= hidden_field_tag 'prev_issue_id', @prev_issue_id if @prev_issue_id %> <%= hidden_field_tag 'next_issue_id', @next_issue_id if @next_issue_id %> <%= hidden_field_tag 'issue_position', @issue_position if @issue_position %> <%= hidden_field_tag 'issue_count', @issue_count if @issue_count %> + <% end %> -
diff --git a/app/views/issues/_form.html.erb b/app/views/issues/_form.html.erb index f25cb3b..c99927d 100644 --- a/app/views/issues/_form.html.erb +++ b/app/views/issues/_form.html.erb @@ -37,7 +37,7 @@ :no_label => true %> <% end %>

-<%= wikitoolbar_for 'issue_description' %> +<%= wikitoolbar_for 'issue_description', preview_issue_path(:project_id => @issue.project, :issue_id => @issue.id) %> <% end %>
diff --git a/app/views/issues/new.html.erb b/app/views/issues/new.html.erb index 1c2c8ba..22a174a 100644 --- a/app/views/issues/new.html.erb +++ b/app/views/issues/new.html.erb @@ -39,11 +39,8 @@ <%= submit_tag l(:button_create) %> <%= submit_tag l(:button_create_and_continue), :name => 'continue' %> - <%= preview_link preview_new_issue_path(:project_id => @issue.project), 'issue-form' %> <% end %> -
- <% content_for :header_tags do %> <%= robot_exclusion_tag %> <% end %> diff --git a/app/views/journals/_notes_form.html.erb b/app/views/journals/_notes_form.html.erb index 2ab9787..eecc31d 100644 --- a/app/views/journals/_notes_form.html.erb +++ b/app/views/journals/_notes_form.html.erb @@ -14,11 +14,6 @@ <% end %> <%= call_hook(:view_journals_notes_form_after_notes, { :journal => @journal}) %>

<%= submit_tag l(:button_save) %> - <%= preview_link preview_edit_issue_path(:project_id => @project, :id => @journal.issue), - "journal-#{@journal.id}-form", - "journal_#{@journal.id}_preview" %> | <%= link_to l(:button_cancel), '#', :onclick => "$('#journal-#{@journal.id}-form').remove(); $('#journal-#{@journal.id}-notes').show(); return false;" %>

- -
<% end %> -<%= wikitoolbar_for "journal_#{@journal.id}_notes" %> +<%= wikitoolbar_for "journal_#{@journal.id}_notes", preview_issue_path(:project_id => @project, :issue_id => @journal.issue) %> diff --git a/app/views/messages/_form.html.erb b/app/views/messages/_form.html.erb index d9f48af..adba052 100644 --- a/app/views/messages/_form.html.erb +++ b/app/views/messages/_form.html.erb @@ -24,7 +24,7 @@

<%= label_tag "message_content", l(:description_message_content), :class => "hidden-for-sighted" %> <%= f.text_area :content, :cols => 80, :rows => 15, :class => 'wiki-edit', :id => 'message_content' %>

-<%= wikitoolbar_for 'message_content' %> +<%= wikitoolbar_for 'message_content', preview_board_message_path(:board_id => @board, :id => @message) %>

<%= l(:label_attachment_plural) %>
diff --git a/app/views/messages/edit.html.erb b/app/views/messages/edit.html.erb index 53948e4..0636761 100644 --- a/app/views/messages/edit.html.erb +++ b/app/views/messages/edit.html.erb @@ -12,6 +12,4 @@ <%= render :partial => 'form', :locals => {:f => f, :replying => !@message.parent.nil?} %> <%= submit_tag l(:button_save) %> - <%= preview_link({:controller => 'messages', :action => 'preview', :board_id => @board, :id => @message}, 'message-form') %> <% end %> -

diff --git a/app/views/messages/new.html.erb b/app/views/messages/new.html.erb index f8d8406..be63814 100644 --- a/app/views/messages/new.html.erb +++ b/app/views/messages/new.html.erb @@ -3,7 +3,4 @@ <%= form_for @message, :url => {:action => 'new'}, :html => {:multipart => true, :id => 'message-form'} do |f| %> <%= render :partial => 'form', :locals => {:f => f} %> <%= submit_tag l(:button_create) %> - <%= preview_link({:controller => 'messages', :action => 'preview', :board_id => @board}, 'message-form') %> <% end %> - -
diff --git a/app/views/messages/show.html.erb b/app/views/messages/show.html.erb index db41b0c..5756a92 100644 --- a/app/views/messages/show.html.erb +++ b/app/views/messages/show.html.erb @@ -85,9 +85,7 @@ <%= form_for @reply, :as => :reply, :url => {:action => 'reply', :id => @topic}, :html => {:multipart => true, :id => 'message-form'} do |f| %> <%= render :partial => 'form', :locals => {:f => f, :replying => true} %> <%= submit_tag l(:button_submit) %> - <%= preview_link({:controller => 'messages', :action => 'preview', :board_id => @board}, 'message-form') %> <% end %> -
<% end %> diff --git a/app/views/news/_form.html.erb b/app/views/news/_form.html.erb index 3f48d21..dbf21df 100644 --- a/app/views/news/_form.html.erb +++ b/app/views/news/_form.html.erb @@ -7,4 +7,4 @@

<%= render :partial => 'attachments/form', :locals => {:container => @news} %>

-<%= wikitoolbar_for 'news_description' %> +<%= wikitoolbar_for 'news_description', preview_news_path(:project_id => @project, :id => @news) %> \ No newline at end of file diff --git a/app/views/news/edit.html.erb b/app/views/news/edit.html.erb index 4e4cf2e..50b8973 100644 --- a/app/views/news/edit.html.erb +++ b/app/views/news/edit.html.erb @@ -3,9 +3,7 @@ <%= labelled_form_for @news, :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%= submit_tag l(:button_save) %> -<%= preview_link preview_news_path(:project_id => @project, :id => @news), 'news-form' %> <% end %> -
<% content_for :header_tags do %> <%= stylesheet_link_tag 'scm' %> diff --git a/app/views/news/index.html.erb b/app/views/news/index.html.erb index 2ff5a1c..cd51aa9 100644 --- a/app/views/news/index.html.erb +++ b/app/views/news/index.html.erb @@ -12,10 +12,8 @@ :html => { :id => 'news-form', :multipart => true } do |f| %> <%= render :partial => 'news/form', :locals => { :f => f } %> <%= submit_tag l(:button_create) %> -<%= preview_link preview_news_path(:project_id => @project), 'news-form' %> | <%= link_to l(:button_cancel), "#", :onclick => '$("#add-news").hide()' %> <% end if @project %> -

<%=l(:label_news_plural)%>

diff --git a/app/views/news/new.html.erb b/app/views/news/new.html.erb index f96dd5c..cf57140 100644 --- a/app/views/news/new.html.erb +++ b/app/views/news/new.html.erb @@ -4,6 +4,4 @@ :html => { :id => 'news-form', :multipart => true } do |f| %> <%= render :partial => 'news/form', :locals => { :f => f } %> <%= submit_tag l(:button_create) %> - <%= preview_link preview_news_path(:project_id => @project), 'news-form' %> <% end %> -
diff --git a/app/views/news/show.html.erb b/app/views/news/show.html.erb index 72c94a9..d8d098c 100644 --- a/app/views/news/show.html.erb +++ b/app/views/news/show.html.erb @@ -16,10 +16,8 @@ :html => { :id => 'news-form', :multipart => true, :method => :put } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%= submit_tag l(:button_save) %> -<%= preview_link preview_news_path(:project_id => @project, :id => @news), 'news-form' %> | <%= link_to l(:button_cancel), "#", :onclick => '$("#edit-news").hide(); return false;' %> <% end %> -
<% end %> @@ -56,7 +54,7 @@ <%= form_tag({:controller => 'comments', :action => 'create', :id => @news}, :id => "add_comment_form", :style => "display:none;") do %>
<%= text_area 'comment', 'comments', :cols => 80, :rows => 15, :class => 'wiki-edit' %> - <%= wikitoolbar_for 'comment_comments' %> + <%= wikitoolbar_for 'comment_comments', preview_news_path(:project_id => @project, :id => @news) %>

<%= submit_tag l(:button_add) %>

<% end %> diff --git a/app/views/previews/issue.html.erb b/app/views/previews/issue.html.erb deleted file mode 100644 index a88bec6..0000000 --- a/app/views/previews/issue.html.erb +++ /dev/null @@ -1,11 +0,0 @@ -<% if @notes %> -
<%= l(:field_notes) %> - <%= textilizable @notes, :attachments => @attachments, :object => @issue %> -
-<% end %> - -<% if @description %> -
<%= l(:field_description) %> - <%= textilizable @description, :attachments => @attachments, :object => @issue %> -
-<% end %> diff --git a/app/views/wiki/edit.html.erb b/app/views/wiki/edit.html.erb index 6692cfa..60a2f65 100644 --- a/app/views/wiki/edit.html.erb +++ b/app/views/wiki/edit.html.erb @@ -57,14 +57,11 @@

<%= submit_tag l(:button_save) %> - <%= preview_link({:controller => 'wiki', :action => 'preview', :project_id => @project, :id => @page.title }, 'wiki_form') %> - | <%= link_to l(:button_cancel), wiki_page_edit_cancel_path(@page) %> + <%= link_to l(:button_cancel), wiki_page_edit_cancel_path(@page) %>

-<%= wikitoolbar_for 'content_text' %> +<%= wikitoolbar_for 'content_text', preview_project_wiki_page_path(:project_id => @project, :id => @page.title) %> <% end %> -
- <% content_for :header_tags do %> <%= robot_exclusion_tag %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d8f0943..ce23c08 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1026,6 +1026,7 @@ en: label_font_monospace: Monospaced font label_font_proportional: Proportional font label_last_notes: Last notes + label_nothing_to_preview: Nothing to preview button_login: Login button_submit: Submit diff --git a/config/routes.rb b/config/routes.rb index 8b8aa13..d27e087 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,9 +26,8 @@ Rails.application.routes.draw do get 'account/activation_email', :to => 'account#activation_email', :as => 'activation_email' match '/news/preview', :controller => 'previews', :action => 'news', :as => 'preview_news', :via => [:get, :post, :put, :patch] - match '/issues/preview/new/:project_id', :to => 'previews#issue', :as => 'preview_new_issue', :via => [:get, :post, :put, :patch] - match '/issues/preview/edit/:id', :to => 'previews#issue', :as => 'preview_edit_issue', :via => [:get, :post, :put, :patch] match '/issues/preview', :to => 'previews#issue', :as => 'preview_issue', :via => [:get, :post, :put, :patch] + match '/preview/text', :to => 'previews#text', :as => 'preview_text', :via => [:get, :post, :put, :patch] match 'projects/:id/wiki/destroy', :to => 'wikis#destroy', :via => [:get, :post] @@ -156,7 +155,7 @@ Rails.application.routes.draw do end end end - + match 'wiki/index', :controller => 'wiki', :action => 'index', :via => :get resources :wiki, :except => [:index, :create], :as => 'wiki_page' do member do diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index f4496d9..6676455 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -214,7 +214,7 @@ module Redmine end module Helper - def wikitoolbar_for(field_id) + def wikitoolbar_for(field_id, preview_url = preview_text_path) end def heads_for_wiki_formatter diff --git a/lib/redmine/wiki_formatting/markdown/helper.rb b/lib/redmine/wiki_formatting/markdown/helper.rb index f41fee6..fac2f8b 100644 --- a/lib/redmine/wiki_formatting/markdown/helper.rb +++ b/lib/redmine/wiki_formatting/markdown/helper.rb @@ -19,10 +19,10 @@ module Redmine module WikiFormatting module Markdown module Helper - def wikitoolbar_for(field_id) + def wikitoolbar_for(field_id, preview_url = preview_text_path) heads_for_wiki_formatter url = "#{Redmine::Utils.relative_url_root}/help/#{current_language.to_s.downcase}/wiki_syntax_markdown.html" - javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.draw();") + javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.setPreviewUrl('#{preview_url}'); wikiToolbar.draw();") end def initial_page_content(page) diff --git a/lib/redmine/wiki_formatting/textile/helper.rb b/lib/redmine/wiki_formatting/textile/helper.rb index f8cb411..6e8ba98 100644 --- a/lib/redmine/wiki_formatting/textile/helper.rb +++ b/lib/redmine/wiki_formatting/textile/helper.rb @@ -19,11 +19,11 @@ module Redmine module WikiFormatting module Textile module Helper - def wikitoolbar_for(field_id) + def wikitoolbar_for(field_id, preview_url = preview_text_path) heads_for_wiki_formatter # Is there a simple way to link to a public resource? url = "#{Redmine::Utils.relative_url_root}/help/#{current_language.to_s.downcase}/wiki_syntax_textile.html" - javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.draw();") + javascript_tag("var wikiToolbar = new jsToolBar(document.getElementById('#{field_id}')); wikiToolbar.setHelpLink('#{escape_javascript url}'); wikiToolbar.setPreviewUrl('#{preview_url}'); wikiToolbar.draw();") end def initial_page_content(page) diff --git a/public/javascripts/application.js b/public/javascripts/application.js index c8a7df1..0a807ab 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -449,17 +449,6 @@ function hideModal(el) { modal.dialog("close"); } -function submitPreview(url, form, target) { - $.ajax({ - url: url, - type: 'post', - data: $('#'+form).serialize(), - success: function(data){ - $('#'+target).html(data); - } - }); -} - function collapseScmEntry(id) { $('.'+id).each(function() { if ($(this).hasClass('open')) { @@ -846,6 +835,28 @@ $(document).ready(function(){ toggleDisabledInit(); }); +$(document).ready(function(){ + $('#content').on('click', 'div.jstTabs a.tab-preview', function(event){ + var tab = $(event.target); + + var url = tab.data('url'); + var form = tab.parents('form'); + var jstBlock = tab.parents('.jstBlock'); + + var element = encodeURIComponent(jstBlock.find('.wiki-edit').val()); + var attachments = form.find('.attachments_fields input').serialize(); + + $.ajax({ + url: url, + type: 'post', + data: "text=" + element + '&' + attachments, + success: function(data){ + jstBlock.find('.wiki-preview').html(data); + } + }); + }); +}); + function keepAnchorOnSignIn(form){ var hash = decodeURIComponent(self.document.location.hash); if (hash) { diff --git a/public/javascripts/attachments.js b/public/javascripts/attachments.js index 1baafc0..753855f 100644 --- a/public/javascripts/attachments.js +++ b/public/javascripts/attachments.js @@ -237,8 +237,7 @@ function addInlineAttachmentMarkup(file) { 'selectionStart': cursorPosition + newLineBefore, 'selectionEnd': cursorPosition + inlineFilename.length + newLineBefore }); - $textarea.closest('.jstEditor') - .siblings('.jstElements') + $textarea.parents('.jstBlock') .find('.jstb_img').click(); // move cursor into next line diff --git a/public/javascripts/jstoolbar/jstoolbar.js b/public/javascripts/jstoolbar/jstoolbar.js index bbda5f8..98dae6f 100644 --- a/public/javascripts/jstoolbar/jstoolbar.js +++ b/public/javascripts/jstoolbar/jstoolbar.js @@ -7,12 +7,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * DotClear 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 General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with DotClear; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -34,15 +34,45 @@ function jsToolBar(textarea) { this.textarea = textarea; + this.toolbarBlock = document.createElement('div'); + this.toolbarBlock.className = 'jstBlock'; + this.textarea.parentNode.insertBefore(this.toolbarBlock, this.textarea); + this.editor = document.createElement('div'); this.editor.className = 'jstEditor'; - this.textarea.parentNode.insertBefore(this.editor,this.textarea); + this.preview = document.createElement('div'); + this.preview.className = 'wiki wiki-preview hidden'; + this.preview.setAttribute('id', 'preview_' + textarea.getAttribute('id')); + this.editor.appendChild(this.textarea); + this.editor.appendChild(this.preview); + + this.tabsBlock = document.createElement('div'); + this.tabsBlock.className = 'jstTabs tabs'; + + var This = this; + this.writeTab = new jsTab('Write', true); + this.writeTab.onclick = function(event) { This.hidePreview.call(This, event); return false; }; + + this.previewTab = new jsTab('Preview'); + this.previewTab.onclick = function(event) { This.showPreview.call(This, event); return false; }; + + var elementsTab = document.createElement('li'); + elementsTab.classList = 'tab-elements'; + + var tabs = document.createElement('ul'); + tabs.appendChild(this.writeTab); + tabs.appendChild(this.previewTab); + tabs.appendChild(elementsTab); + this.tabsBlock.appendChild(tabs); this.toolbar = document.createElement("div"); this.toolbar.className = 'jstElements'; - this.editor.parentNode.insertBefore(this.toolbar,this.editor); + elementsTab.appendChild(this.toolbar); + + this.toolbarBlock.appendChild(this.tabsBlock); + this.toolbarBlock.appendChild(this.editor); // Dragable resizing if (this.editor.addEventListener && navigator.appVersion.match(/\bMSIE\b/)) @@ -53,19 +83,40 @@ function jsToolBar(textarea) { var This = this; this.handle.addEventListener('mousedown',function(event) { dragStart.call(This,event); },false); // fix memory leak in Firefox (bug #241518) - window.addEventListener('unload',function() { + window.addEventListener('unload',function() { var del = This.handle.parentNode.removeChild(This.handle); delete(This.handle); },false); - + this.editor.parentNode.insertBefore(this.handle,this.editor.nextSibling); } - + this.context = null; - this.toolNodes = {}; // lorsque la toolbar est dessinée , cet objet est garni + this.toolNodes = {}; // lorsque la toolbar est dessinée , cet objet est garni // de raccourcis vers les éléments DOM correspondants aux outils. } +function jsTab(name, selected) { + selected = selected || false; + if(typeof jsToolBar.strings == 'undefined') { + var tabName = name || null; + } else { + var tabName = jsToolBar.strings[name] || name || null; + } + + var tab = document.createElement('li'); + var link = document.createElement('a'); + link.setAttribute('href', '#'); + link.innerText = tabName; + link.className = 'tab-' + name.toLowerCase(); + + if (selected == true) { + link.classList.add('selected'); + } + tab.appendChild(link) + + return tab; +} function jsButton(title, fn, scope, className) { if(typeof jsToolBar.strings == 'undefined') { this.title = title || null; @@ -91,6 +142,7 @@ jsButton.prototype.draw = function() { if (this.icon != undefined) { button.style.backgroundImage = 'url('+this.icon+')'; } + if (typeof(this.fn) == 'function') { var This = this; button.onclick = function() { try { This.fn.apply(This.scope, arguments) } catch (e) {} return false; }; @@ -110,7 +162,7 @@ jsSpace.prototype.draw = function() { if (this.width) span.style.marginRight = this.width+'px'; return span; -} +} function jsCombo(title, options, scope, fn, className) { this.title = title || null; @@ -136,7 +188,7 @@ jsCombo.prototype.draw = function() { var This = this; select.onchange = function() { - try { + try { This.fn.call(This.scope, this.value); } catch (e) { alert(e); } @@ -152,7 +204,7 @@ jsToolBar.prototype = { mode: 'wiki', elements: {}, help_link: '', - + getMode: function() { return this.mode; }, @@ -170,6 +222,10 @@ jsToolBar.prototype = { this.help_link = link; }, + setPreviewUrl: function(url) { + this.previewTab.firstChild.setAttribute('data-url', url); + }, + button: function(toolName) { var tool = this.elements[toolName]; if (typeof tool.fn[this.mode] != 'function') return null; @@ -292,7 +348,6 @@ jsToolBar.prototype = { encloseSelection: function(prefix, suffix, fn) { this.textarea.focus(); - prefix = prefix || ''; suffix = suffix || ''; @@ -343,7 +398,24 @@ jsToolBar.prototype = { this.textarea.scrollTop = scrollPos; } }, + showPreview: function(event) { + if (event.target.classList.contains('selected')) { return; } + this.preview.setAttribute('style', 'min-height: ' + this.textarea.clientHeight + 'px;') + this.toolbar.classList.add('hidden'); + this.textarea.classList.add('hidden'); + this.preview.classList.remove('hidden'); + this.tabsBlock.getElementsByClassName('tab-write')[0].classList.remove('selected'); + event.target.classList.add('selected'); + }, + hidePreview: function(event) { + if (event.target.classList.contains('selected')) { return; } + this.toolbar.classList.remove('hidden'); + this.textarea.classList.remove('hidden'); + this.preview.classList.add('hidden'); + this.tabsBlock.getElementsByClassName('tab-preview')[0].classList.remove('selected'); + event.target.classList.add('selected'); + }, stripBaseURL: function(url) { if (this.base_url != '') { var pos = url.indexOf(this.base_url); diff --git a/public/javascripts/jstoolbar/lang/jstoolbar-en.js b/public/javascripts/jstoolbar/lang/jstoolbar-en.js index 4f72f08..c52e855 100644 --- a/public/javascripts/jstoolbar/lang/jstoolbar-en.js +++ b/public/javascripts/jstoolbar/lang/jstoolbar-en.js @@ -15,3 +15,5 @@ jsToolBar.strings['Unquote'] = 'Remove Quote'; jsToolBar.strings['Preformatted text'] = 'Preformatted text'; jsToolBar.strings['Wiki link'] = 'Link to a Wiki page'; jsToolBar.strings['Image'] = 'Image'; +jsToolBar.strings['Write'] = 'Write'; +jsToolBar.strings['Preview'] = 'Preview'; \ No newline at end of file diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 6abf778..13b8ab3 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -273,7 +273,6 @@ tr.issue.idnt-8 td.subject {padding-left: 136px; background-position: 120px 50%; tr.issue.idnt-9 td.subject {padding-left: 152px; background-position: 136px 50%;} table.issue-report {table-layout:fixed;} -table.issue-report th {white-space: normal;} tr.entry { border: 1px solid #f8f8f8; } tr.entry td { white-space: nowrap; } @@ -679,7 +678,6 @@ span.pagination>span {white-space:nowrap;} min-height: 2em; clear:left; } - html>body .tabular p {overflow:hidden;} .tabular input, .tabular select {max-width:95%} @@ -731,11 +729,25 @@ label.no-css { input#time_entry_comments { width: 90%;} input#months { width: 30px; } -fieldset.preview {margin-top: 1em; min-width: inherit; background: url(../images/draft.png)} +.jstBlock .jstTabs, .jstBlock .wiki-preview { width: 99%; } + +.jstBlock .jstTabs { padding-right: 6px; } +.jstBlock .wiki-preview { padding: 2px; } +.jstBlock .wiki-preview p:first-child { padding-top: 0 !important;} +.jstBlock .wiki-preview p:last-child { padding-bottom: 0 !important;} +#content .box .jstBlock .jstTabs li { background-color: #f6f6f6; } + +.tabular .wiki-preview, .tabular .jstTabs {width: 95%;} +.tabular.settings .wiki-preview, .tabular.settings .jstTabs { width: 99%; } +.tabular .wiki-preview p { + min-height: initial; + padding: 1em 0 1em 0 !important; + overflow: initial; +} .tabular.settings p{ padding-left: 300px; } .tabular.settings label{ margin-left: -300px; width: 295px; } -.tabular.settings textarea { width: 99%; } +.tabular.settings textarea, .tabular.settings .wiki-preview, .tabular.settings .jstTabs { width: 99%; } .settings.enabled_scm table {width:100%} .settings.enabled_scm td.scm_name{ font-weight: bold; } diff --git a/public/stylesheets/jstoolbar.css b/public/stylesheets/jstoolbar.css index 4bf6745..dc195b2 100644 --- a/public/stylesheets/jstoolbar.css +++ b/public/stylesheets/jstoolbar.css @@ -1,19 +1,45 @@ +.jstBlock .hidden { + display: none; +} .jstEditor { padding-left: 0px; } .jstEditor textarea, .jstEditor iframe { margin: 0; } - .jstHandle { height: 10px; font-size: 0.1em; cursor: s-resize; /*background: transparent url(img/resizer.png) no-repeat 45% 50%;*/ } - +#content .jstTabs.tabs { + margin-bottom: 10px; +} +#content .jstTabs.tabs li { + height: 42px; +} +#content .jstTabs.tabs li:before{ + content: ''; + display: inline-block; + vertical-align: middle; + height: 100%; +} +#content .jstTabs.tabs li a { + display: inline-block; + vertical-align: bottom; + line-height: 19px; +} .jstElements { - padding: 3px 3px 3px 0; + display: inline-block; + vertical-align: bottom; + border-bottom: 1px solid #bbbbbb; + padding-left: 6px; + height: 26px; +} +.wiki-preview { + background-color: #ffffff; + border: 1px solid #bbbbbb; } .jstElements button { diff --git a/test/functional/messages_controller_test.rb b/test/functional/messages_controller_test.rb index 353100a..0f3d937 100644 --- a/test/functional/messages_controller_test.rb +++ b/test/functional/messages_controller_test.rb @@ -33,7 +33,7 @@ class MessagesControllerTest < Redmine::ControllerTest assert_select 'h2', :text => 'First post' end - + def test_show_should_contain_reply_field_tags_for_quoting @request.session[:user_id] = 2 get :show, :params => { @@ -214,7 +214,7 @@ class MessagesControllerTest < Redmine::ControllerTest :id => 1, :reply => { :content => 'This is a test reply', - :subject => 'Test reply' + :subject => 'Test reply' } } reply = Message.order('id DESC').first @@ -265,9 +265,9 @@ class MessagesControllerTest < Redmine::ControllerTest post :preview, :params => { :board_id => 1, :message => { - :subject => "", - :content => "Previewed text" - } + :subject => "" + }, + :text => "Previewed text" } assert_response :success assert_include 'Previewed text', response.body @@ -280,8 +280,8 @@ class MessagesControllerTest < Redmine::ControllerTest :board_id => 1, :message => { :subject => "", - :content => "Previewed text" - } + }, + :text => "Previewed text" } assert_response :success assert_include 'Previewed text', response.body diff --git a/test/functional/previews_controller_test.rb b/test/functional/previews_controller_test.rb index 65fb9ae..5512cff 100644 --- a/test/functional/previews_controller_test.rb +++ b/test/functional/previews_controller_test.rb @@ -28,62 +28,36 @@ class PreviewsControllerTest < Redmine::ControllerTest :journals, :journal_details, :news - def test_preview_new_issue + def test_preview_new_issue_description @request.session[:user_id] = 2 post :issue, :params => { :project_id => '1', - :issue => { - :description => 'Foo' - } + :text => 'Foo' } assert_response :success - assert_select 'fieldset' do - assert_select 'legend', :text => 'Description' - assert_select 'p', :text => 'Foo' - end + assert_select 'p', :text => 'Foo' end - def test_preview_issue_notes_with_no_change_to_description + def test_preview_issue_description @request.session[:user_id] = 2 post :issue, :params => { :project_id => '1', - :id => 1, - :issue => { - :description => Issue.find(1).description, - :notes => 'Foo' - } + :issue_id => 1, + :text => 'Unable to print recipes' } assert_response :success - assert_select 'legend', :text => 'Description', :count => 0 - assert_select 'legend', :text => 'Notes' - end - def test_preview_issue_notes_with_change_to_description - @request.session[:user_id] = 2 - post :issue, :params => { - :project_id => '1', - :id => 1, - :issue => { - :description => 'Changed description', - :notes => 'Foo' - } - } - assert_response :success - assert_select 'legend', :text => 'Description' - assert_select 'legend', :text => 'Notes' + assert_select 'p', :text => 'Unable to print recipes' end - def test_preview_journal_notes_for_update + def test_preview_issue_notes @request.session[:user_id] = 2 post :issue, :params => { :project_id => '1', :id => 1, - :journal => { - :notes => 'Foo' - } + :text => 'Foo' } assert_response :success - assert_select 'legend', :text => 'Notes' assert_select 'p', :text => 'Foo' end @@ -92,53 +66,30 @@ class PreviewsControllerTest < Redmine::ControllerTest @request.session[:user_id] = 2 post :issue, :params => { :project_id => '1', - :id => 1, - :issue => { - :notes => 'attachment:foo.bar' - } + :issue_id => 1, + :field => 'notes', + :text => 'attachment:foo.bar' } assert_response :success assert_select 'a.attachment', :text => 'foo.bar' end - def test_preview_issue_with_project_changed - @request.session[:user_id] = 2 - post :issue, :params => { - :project_id => '1', - :id => 1, - :issue => { - :notes => 'notes', - :project_id => 2 - } - } - assert_response :success - assert_select 'legend', :text => 'Notes' - end - def test_preview_new_news get :news, :params => { :project_id => 1, - :news => { - :title => '', - :description => 'News description', - :summary => '' - } + :text => 'News description', } assert_response :success - assert_select 'fieldset.preview', :text => /News description/ + assert_select 'p', :text => /News description/ end def test_preview_existing_news get :news, :params => { :project_id => 1, :id => 2, - :news => { - :title => '', - :description => 'News description', - :summary => '' - } + :text => 'News description' } assert_response :success - assert_select 'fieldset.preview', :text => /News description/ + assert_select 'p', :text => /News description/ end end diff --git a/test/integration/attachments_test.rb b/test/integration/attachments_test.rb index 6fd58ed..0b3bf18 100644 --- a/test/integration/attachments_test.rb +++ b/test/integration/attachments_test.rb @@ -77,8 +77,9 @@ class AttachmentsTest < Redmine::IntegrationTest token = ajax_upload('myupload.jpg', 'JPEG content') - post '/issues/preview/new/ecookbook', :params => { - :issue => {:tracker_id => 1, :description => 'Inline upload: !myupload.jpg!'}, + post '/issues/preview', :params => { + :issue => {:tracker_id => 1, :project_id => 'ecookbook'}, + :text => 'Inline upload: !myupload.jpg!', :attachments => {'1' => {:filename => 'myupload.jpg', :description => 'My uploaded file', :token => token}} } assert_response :success diff --git a/test/integration/layout_test.rb b/test/integration/layout_test.rb index a529432..08e7214 100644 --- a/test/integration/layout_test.rb +++ b/test/integration/layout_test.rb @@ -63,7 +63,7 @@ class LayoutTest < Redmine::IntegrationTest Role.anonymous.add_permission! :add_issues get '/projects/ecookbook/issues/new' - assert_select 'head script[src^=?]', '/javascripts/jstoolbar/jstoolbar-textile.min.js?' + assert_select 'head script[src^=?]', '/javascripts/jstoolbar/jstoolbar.js?' end def test_calendar_header_tags diff --git a/test/integration/routing/previews_test.rb b/test/integration/routing/previews_test.rb index c6a7875..c5b4eea 100644 --- a/test/integration/routing/previews_test.rb +++ b/test/integration/routing/previews_test.rb @@ -19,14 +19,14 @@ require File.expand_path('../../../test_helper', __FILE__) class RoutingPreviewsTest < Redmine::RoutingTest def test_previews - should_route 'GET /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo' - should_route 'PUT /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo' - should_route 'POST /issues/preview/new/foo' => 'previews#issue', :project_id => 'foo' - - should_route 'GET /issues/preview/edit/321' => 'previews#issue', :id => '321' - should_route 'PUT /issues/preview/edit/321' => 'previews#issue', :id => '321' - should_route 'POST /issues/preview/edit/321' => 'previews#issue', :id => '321' + should_route 'GET /issues/preview' => 'previews#issue' + should_route 'PUT /issues/preview' => 'previews#issue' + should_route 'POST /issues/preview' => 'previews#issue' should_route 'GET /news/preview' => 'previews#news' + + should_route 'GET /preview/text' => 'previews#text' + should_route 'PUT /preview/text' => 'previews#text' + should_route 'POST /preview/text' => 'previews#text' end end diff --git a/test/system/issues_test.rb b/test/system/issues_test.rb index 0ffc1c2..f4c5299 100644 --- a/test/system/issues_test.rb +++ b/test/system/issues_test.rb @@ -179,10 +179,10 @@ class IssuesTest < ApplicationSystemTestCase fill_in 'Subject', :with => 'new issue subject' fill_in 'Description', :with => 'new issue description' click_link 'Preview' + find 'div.wiki-preview', :visible => true, :text => 'new issue description' end - find 'div#preview fieldset', :visible => true, :text => 'new issue description' assert_difference 'Issue.count' do - find('input[name=commit]').click + click_button('Create') end issue = Issue.order('id desc').first @@ -314,9 +314,9 @@ class IssuesTest < ApplicationSystemTestCase # Update the notes fill_in 'Notes', :with => 'Updated notes' # Preview the change - click_on 'Preview' - assert page.has_css?('#journal_2_preview') - assert page.first('#journal_2_preview').has_content?('Updated notes') + page.first('#change-2 a.tab-preview').click + assert page.has_css?('#preview_journal_2_notes') + assert page.first('#preview_journal_2_notes').has_content?('Updated notes') # Save click_on 'Save' -- 2.1.4