Commit a739edce1f172e39cbd3ca8a6a1e43bae8279171

Authored by Rodrigo Souto
2 parents 48038fc5 4825fe87

Merge branch 'article-version' of https://gitlab.com/juniorsilva1001/noosfero in…

…to juniorsilva1001/noosfero-article-version

Conflicts:
	app/views/content_viewer/versioned_article.rhtml
	db/schema.rb
	public/stylesheets/application.css
app/controllers/public/content_viewer_controller.rb
  1 +require 'diffy'
  2 +
1 class ContentViewerController < ApplicationController 3 class ContentViewerController < ApplicationController
2 4
3 needs_profile 5 needs_profile
@@ -117,6 +119,13 @@ class ContentViewerController &lt; ApplicationController @@ -117,6 +119,13 @@ class ContentViewerController &lt; ApplicationController
117 end 119 end
118 end 120 end
119 121
  122 + def versions_diff
  123 + path = params[:page].join('/')
  124 + @page = profile.articles.find_by_path(path)
  125 + @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2])
  126 + p params
  127 + end
  128 +
120 def article_versions 129 def article_versions
121 path = params[:page].join('/') 130 path = params[:page].join('/')
122 @page = profile.articles.find_by_path(path) 131 @page = profile.articles.find_by_path(path)
@@ -184,3 +193,7 @@ class ContentViewerController &lt; ApplicationController @@ -184,3 +193,7 @@ class ContentViewerController &lt; ApplicationController
184 end 193 end
185 194
186 end 195 end
  196 +
  197 +
  198 +
  199 +
app/views/content_viewer/article_versions.rhtml
  1 +<div class="article-versions">
  2 + <%= button(:back, _('Go back to post'), {:action => 'view_page'}) %>
  3 +</div>
  4 +
1 <%= article_title(@page, :no_link => true) %> 5 <%= article_title(@page, :no_link => true) %>
2 6
3 <p><%= _('This is the list of all versions of this content. Select a version to see it and then revert to it.') %>.</p> 7 <p><%= _('This is the list of all versions of this content. Select a version to see it and then revert to it.') %>.</p>
4 8
5 -<ul class='article-versions'>  
6 - <% @versions.each do |v| %>  
7 - <li>  
8 - <%= link_to(_("Version #{v.version}"), @page.url.merge(:version => v.version)) %>  
9 - <%= @page.version == v.version ? _('(current)') : '' %>  
10 - <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url)} %></span>  
11 - <div class='updated-on'><%= show_time(v.updated_at) %></div>  
12 - </li>  
13 - <% end %>  
14 -</ul> 9 +<% form_tag({:controller => 'content_viewer', :action => 'versions_diff', :profile => profile.identifier, :page => @page.path.split('/')}, :method => 'get') do %>
  10 + <ul id="article-versions">
  11 + <% @versions.each do |v| %>
  12 + <li>
  13 + <%= radio_button_tag 'v1', v.version, false, :onclick => 'versionInputClicked(this)' %>
  14 + <%= radio_button_tag 'v2', v.version, false, :onclick => 'versionInputClicked(this)' %>
  15 + <%= link_to(_("Version #{v.version}"), @page.url.merge(:version => v.version)) %>
  16 + <%= @page.version == v.version ? _('(current)') : '' %>
  17 + <span class='updated-by'><%= _('by %{author}') % {:author => link_to(@page.author_name(v.version), @page.author_url)} %></span>
  18 + <span class='updated-on'><%= show_time(v.updated_at) %></span>
  19 + </li>
  20 + <% end %>
  21 + </ul>
  22 +
  23 +<script>
  24 + function versionInputClicked(input) {
  25 + var selectedColumn = input.name;
  26 + var sisterColumn = (selectedColumn == 'v1') ? 'v2' : 'v1';
  27 + var li = input.parentNode;
  28 + var checkedBrotherLi = jQuery('#article-versions input[name=' + sisterColumn + ']:checked').parent()[0];
  29 + updateColumn(selectedColumn, li);
  30 + updateColumn(sisterColumn, checkedBrotherLi);
  31 + }
15 32
  33 + function updateColumn(selectedColumn, startLi){
  34 + var sisterColumn = (selectedColumn == 'v1') ? 'v2' : 'v1';
  35 + var walkMethod = (selectedColumn == 'v1') ? 'prev' : 'next';
  36 + var li = startLi;
  37 + var foundCheckedBrother = false;
  38 + while(li = jQuery(li)[walkMethod]()[0]) {
  39 + li.className = '';
  40 + if (!foundCheckedBrother){
  41 + li.className = 'selected';
  42 + foundCheckedBrother = jQuery('input[name=' + sisterColumn + ']', li)[0].checked;
  43 + }
  44 + jQuery('input[name=' + selectedColumn + ']', li)[0].disabled = foundCheckedBrother;
  45 + }
  46 + }
  47 +
  48 + var penultVersion = jQuery('#article-versions input[name=v1]')[1];
  49 + var lastVersion = jQuery('#article-versions input[name=v2]')[0];
  50 + jQuery('#article-versions input').attr('disabled', false);
  51 + if (penultVersion && lastVersion) {
  52 + penultVersion.checked = lastVersion.checked = true;
  53 + lastVersion.onclick();
  54 + }
  55 +</script>
  56 + <%= submit_button(:clock, _('Show differences between selected versions')) %>
  57 +<% end %>
16 <%= pagination_links @versions, :param_name => 'npage' %> 58 <%= pagination_links @versions, :param_name => 'npage' %>
  59 +
app/views/content_viewer/versioned_article.rhtml
  1 +<div class="article-versions">
  2 + <%= button(:back, _('Back to the versions'), {:action => 'article_versions'}) %>
  3 +</div>
  4 +
1 <div id="article" class="<%= @page.css_class_name %>"> 5 <div id="article" class="<%= @page.css_class_name %>">
2 6
3 <div id="article-actions"> 7 <div id="article-actions">
4 <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %> 8 <%= button(:clock, _('All versions'), {:controller => 'content_viewer', :profile => profile.identifier, :action => 'article_versions'}, :id => 'article-versions-link') %>
5 9
6 - <% if @page.allow_edit?(user) && !remove_content_button(:edit) %> 10 + <% if @page.allow_edit?(user) && !remove_content_button(:undo) %>
7 <% content = content_tag('span', _('Revert to this version')) %> 11 <% content = content_tag('span', _('Revert to this version')) %>
8 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %> 12 <% url = profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id, :version => @version }) %>
9 - <%= expirable_button @page, :edit, content, url, :id => 'article-revert-version-link' %> 13 + <%= expirable_button @page, :undo, content, url, :id => 'article-revert-version-link' %>
10 <% end %> 14 <% end %>
11 - </div>  
12 15
  16 + <%= button(:forward, _('Go to latest version'), {:action => 'view_page'}) %>
  17 +</div>
13 <div id="article-header"> 18 <div id="article-header">
14 <h1 class='title'><%= @versioned_article.name %></h1> 19 <h1 class='title'><%= @versioned_article.name %></h1>
15 <%= _("Version %{version} - %{author} on %{date}") % {:version => @version, :author => @page.author_name(@version), :date => show_time(@versioned_article.updated_at) } %> 20 <%= _("Version %{version} - %{author} on %{date}") % {:version => @version, :author => @page.author_name(@version), :date => show_time(@versioned_article.updated_at) } %>
16 </div> 21 </div>
17 22
  23 + <p id="no-current-version">
  24 + <%= _('This is not the latest version of this content.') %>
  25 + </p>
  26 +</div>
  27 +
18 <% version_license = @page.version_license(@version) %> 28 <% version_license = @page.version_license(@version) %>
19 <%# This seemingly doubled verification exists because the article-sub-header 29 <%# This seemingly doubled verification exists because the article-sub-header
20 - div must appear only if at least one content inside it will appeart. 30 + div must appear only if at least one content inside it will appear.
21 Although we have only one content now, we might have others in the future. 31 Although we have only one content now, we might have others in the future.
22 So we're keeping it like that to avoid mistakes. %> 32 So we're keeping it like that to avoid mistakes. %>
23 <% if version_license.present? %> 33 <% if version_license.present? %>
app/views/content_viewer/versions_diff.html.erb 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +<div class="article-versions">
  2 +<%= button(:back, _('Back to the versions'), {:action => 'article_versions'}) %>
  3 +</div>
  4 +
  5 +<h1><%= _('Changes on "%s"') % @page.title %></h1>
  6 +
  7 +<p> <%= _('Changes from %s &rarr; %s') % [show_time(@v1.updated_at), show_time(@v2.updated_at)] %> </p>
  8 +
  9 +<% diffContent = Diffy::Diff.new(@v1.body, @v2.body, :context => 1) %>
  10 +<% if diffContent.to_s(:text).blank? %>
  11 + <p id="article-versions-no-diff">
  12 + <%= _('These versions range have no differences.')%>
  13 + </p>
  14 +<% else %>
  15 + <%= diffContent.to_s(:html) %>
  16 +<% end %>
config/routes.rb
@@ -129,6 +129,9 @@ ActionController::Routing::Routes.draw do |map| @@ -129,6 +129,9 @@ ActionController::Routing::Routes.draw do |map|
129 map.connect ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } 129 map.connect ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
130 map.connect '*page/versions', :controller => 'content_viewer', :action => 'article_versions' 130 map.connect '*page/versions', :controller => 'content_viewer', :action => 'article_versions'
131 131
  132 + map.connect ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
  133 + map.connect '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff'
  134 +
132 # match requests for profiles that don't have a custom domain 135 # match requests for profiles that don't have a custom domain
133 map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } } 136 map.homepage ':profile/*page', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :conditions => { :if => lambda { |env| !Domain.hosting_profile_at(env[:host]) } }
134 137
@@ -10,7 +10,6 @@ @@ -10,7 +10,6 @@
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 ActiveRecord::Schema.define(:version => 20140314200103) do 12 ActiveRecord::Schema.define(:version => 20140314200103) do
13 -  
14 create_table "abuse_reports", :force => true do |t| 13 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 14 t.integer "reporter_id"
16 t.integer "abuse_complaint_id" 15 t.integer "abuse_complaint_id"
@@ -148,6 +147,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -148,6 +147,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
148 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id" 147 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id"
149 add_index "articles", ["slug"], :name => "index_articles_on_slug" 148 add_index "articles", ["slug"], :name => "index_articles_on_slug"
150 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" 149 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id"
  150 + add_index "articles", [nil], :name => "pg_search_plugin_article"
151 151
152 create_table "articles_categories", :id => false, :force => true do |t| 152 create_table "articles_categories", :id => false, :force => true do |t|
153 t.integer "article_id" 153 t.integer "article_id"
@@ -201,6 +201,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -201,6 +201,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
201 t.string "abbreviation" 201 t.string "abbreviation"
202 end 202 end
203 203
  204 + add_index "categories", [nil], :name => "pg_search_plugin_category"
  205 +
204 create_table "categories_profiles", :id => false, :force => true do |t| 206 create_table "categories_profiles", :id => false, :force => true do |t|
205 t.integer "profile_id" 207 t.integer "profile_id"
206 t.integer "category_id" 208 t.integer "category_id"
@@ -219,6 +221,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -219,6 +221,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
219 t.datetime "updated_at" 221 t.datetime "updated_at"
220 end 222 end
221 223
  224 + add_index "certifiers", [nil], :name => "pg_search_plugin_certifier"
  225 +
222 create_table "comments", :force => true do |t| 226 create_table "comments", :force => true do |t|
223 t.string "title" 227 t.string "title"
224 t.text "body" 228 t.text "body"
@@ -233,9 +237,11 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -233,9 +237,11 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
233 t.string "source_type" 237 t.string "source_type"
234 t.string "user_agent" 238 t.string "user_agent"
235 t.string "referrer" 239 t.string "referrer"
  240 + t.integer "group_id"
236 end 241 end
237 242
238 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" 243 add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
  244 + add_index "comments", [nil], :name => "pg_search_plugin_comment"
239 245
240 create_table "contact_lists", :force => true do |t| 246 create_table "contact_lists", :force => true do |t|
241 t.text "list" 247 t.text "list"
@@ -245,6 +251,50 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -245,6 +251,50 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
245 t.datetime "updated_at" 251 t.datetime "updated_at"
246 end 252 end
247 253
  254 + create_table "custom_forms_plugin_answers", :force => true do |t|
  255 + t.text "value"
  256 + t.integer "field_id"
  257 + t.integer "submission_id"
  258 + end
  259 +
  260 + create_table "custom_forms_plugin_fields", :force => true do |t|
  261 + t.string "name"
  262 + t.string "slug"
  263 + t.string "type"
  264 + t.string "default_value"
  265 + t.string "choices"
  266 + t.float "minimum"
  267 + t.float "maximum"
  268 + t.integer "form_id"
  269 + t.boolean "mandatory", :default => false
  270 + t.boolean "multiple"
  271 + t.boolean "list"
  272 + t.integer "position", :default => 0
  273 + end
  274 +
  275 + create_table "custom_forms_plugin_forms", :force => true do |t|
  276 + t.string "name"
  277 + t.string "slug"
  278 + t.text "description"
  279 + t.integer "profile_id"
  280 + t.datetime "begining"
  281 + t.datetime "ending"
  282 + t.boolean "report_submissions", :default => false
  283 + t.boolean "on_membership", :default => false
  284 + t.string "access"
  285 + t.datetime "created_at"
  286 + t.datetime "updated_at"
  287 + end
  288 +
  289 + create_table "custom_forms_plugin_submissions", :force => true do |t|
  290 + t.string "author_name"
  291 + t.string "author_email"
  292 + t.integer "profile_id"
  293 + t.integer "form_id"
  294 + t.datetime "created_at"
  295 + t.datetime "updated_at"
  296 + end
  297 +
248 create_table "delayed_jobs", :force => true do |t| 298 create_table "delayed_jobs", :force => true do |t|
249 t.integer "priority", :default => 0 299 t.integer "priority", :default => 0
250 t.integer "attempts", :default => 0 300 t.integer "attempts", :default => 0
@@ -311,6 +361,10 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -311,6 +361,10 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
311 t.integer "enterprise_id" 361 t.integer "enterprise_id"
312 end 362 end
313 363
  364 + create_table "foo_plugin_bars", :force => true do |t|
  365 + t.string "name"
  366 + end
  367 +
314 create_table "friendships", :force => true do |t| 368 create_table "friendships", :force => true do |t|
315 t.integer "person_id" 369 t.integer "person_id"
316 t.integer "friend_id" 370 t.integer "friend_id"
@@ -356,6 +410,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -356,6 +410,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
356 t.integer "environment_id", :null => false 410 t.integer "environment_id", :null => false
357 end 411 end
358 412
  413 + add_index "licenses", [nil], :name => "pg_search_plugin_license"
  414 +
359 create_table "mailing_sents", :force => true do |t| 415 create_table "mailing_sents", :force => true do |t|
360 t.integer "mailing_id" 416 t.integer "mailing_id"
361 t.integer "person_id" 417 t.integer "person_id"
@@ -390,6 +446,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -390,6 +446,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
390 446
391 add_index "national_regions", ["name"], :name => "name_index" 447 add_index "national_regions", ["name"], :name => "name_index"
392 add_index "national_regions", ["national_region_code"], :name => "code_index" 448 add_index "national_regions", ["national_region_code"], :name => "code_index"
  449 + add_index "national_regions", [nil], :name => "pg_search_plugin_nationalregion"
393 450
394 create_table "price_details", :force => true do |t| 451 create_table "price_details", :force => true do |t|
395 t.decimal "price", :default => 0.0 452 t.decimal "price", :default => 0.0
@@ -488,6 +545,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -488,6 +545,7 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
488 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier" 545 add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
489 add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count" 546 add_index "profiles", ["members_count"], :name => "index_profiles_on_members_count"
490 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id" 547 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
  548 + add_index "profiles", [nil], :name => "pg_search_plugin_profile"
491 549
492 create_table "qualifier_certifiers", :force => true do |t| 550 create_table "qualifier_certifiers", :force => true do |t|
493 t.integer "qualifier_id" 551 t.integer "qualifier_id"
@@ -501,6 +559,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -501,6 +559,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
501 t.datetime "updated_at" 559 t.datetime "updated_at"
502 end 560 end
503 561
  562 + add_index "qualifiers", [nil], :name => "pg_search_plugin_qualifier"
  563 +
504 create_table "refused_join_community", :id => false, :force => true do |t| 564 create_table "refused_join_community", :id => false, :force => true do |t|
505 t.integer "person_id" 565 t.integer "person_id"
506 t.integer "community_id" 566 t.integer "community_id"
@@ -547,6 +607,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -547,6 +607,8 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
547 t.integer "context_id" 607 t.integer "context_id"
548 end 608 end
549 609
  610 + add_index "scraps", [nil], :name => "pg_search_plugin_scrap"
  611 +
550 create_table "sessions", :force => true do |t| 612 create_table "sessions", :force => true do |t|
551 t.string "session_id", :null => false 613 t.string "session_id", :null => false
552 t.text "data" 614 t.text "data"
@@ -606,6 +668,19 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do @@ -606,6 +668,19 @@ ActiveRecord::Schema.define(:version =&gt; 20140314200103) do
606 t.string "thumbnail" 668 t.string "thumbnail"
607 end 669 end
608 670
  671 + create_table "tolerance_time_plugin_publications", :force => true do |t|
  672 + t.integer "target_id"
  673 + t.string "target_type"
  674 + t.datetime "created_at"
  675 + t.datetime "updated_at"
  676 + end
  677 +
  678 + create_table "tolerance_time_plugin_tolerances", :force => true do |t|
  679 + t.integer "profile_id"
  680 + t.integer "content_tolerance"
  681 + t.integer "comment_tolerance"
  682 + end
  683 +
609 create_table "units", :force => true do |t| 684 create_table "units", :force => true do |t|
610 t.string "singular", :null => false 685 t.string "singular", :null => false
611 t.string "plural", :null => false 686 t.string "plural", :null => false
public/designs/icons/tango/style.css
1 /******************SMALL ICONS********************/ 1 /******************SMALL ICONS********************/
2 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) } 2 .icon-edit { background-image: url(Tango/16x16/apps/text-editor.png) }
  3 +.icon-undo { background-image: url(Tango/16x16/actions/edit-undo.png) }
3 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) } 4 .icon-home { background-image: url(Tango/16x16/actions/go-home.png) }
4 .icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) } 5 .icon-home-not { background-image: url(mod/16x16/actions/go-home-not.png) }
5 .icon-new, 6 .icon-new,
public/stylesheets/application.css
@@ -6510,11 +6510,6 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -6510,11 +6510,6 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6510 text-align: center; 6510 text-align: center;
6511 } 6511 }
6512 6512
6513 -ul.article-versions li {  
6514 - font-size: 13px;  
6515 - padding: 3px 0px;  
6516 -}  
6517 -  
6518 /* * * Admin manage fields * * */ 6513 /* * * Admin manage fields * * */
6519 6514
6520 .controller-features .manage-fields-batch-actions, 6515 .controller-features .manage-fields-batch-actions,
@@ -6526,3 +6521,90 @@ ul.article-versions li { @@ -6526,3 +6521,90 @@ ul.article-versions li {
6526 .controller-features .manage-fields-batch-actions td { 6521 .controller-features .manage-fields-batch-actions td {
6527 font-style: italic; 6522 font-style: italic;
6528 } 6523 }
  6524 +
  6525 +/* * * Article versions * * */
  6526 +
  6527 +#article-versions {
  6528 + margin: 0 0 15px 0;
  6529 + padding: 0;
  6530 +}
  6531 +
  6532 +#article-versions li {
  6533 + list-style: none;
  6534 + margin: 0;
  6535 + padding: 3px 0px;
  6536 +}
  6537 +
  6538 +#article-versions input:disabled {
  6539 + opacity: 0.3;
  6540 +}
  6541 +
  6542 +#article-versions .selected {
  6543 + background: #ff9;
  6544 +}
  6545 +
  6546 +#article-versions-no-diff {
  6547 + text-align: center;
  6548 + font-style: italic;
  6549 +}
  6550 +
  6551 +#no-current-version {
  6552 + text-align: center;
  6553 + font-style: italic;
  6554 + background: #faa;
  6555 + padding: 3px;
  6556 +}
  6557 +
  6558 +.article-versions {
  6559 + margin: 5px 0px;
  6560 + text-align: right;
  6561 +}
  6562 +
  6563 +.action-content_viewer-versions_diff .diff {
  6564 + text-align: justify;
  6565 +}
  6566 +
  6567 +.diff ul {
  6568 + list-style: none;
  6569 + margin: 0;
  6570 + padding: 0;
  6571 +}
  6572 +
  6573 +.diff del, .diff ins {
  6574 + display: block;
  6575 + text-decoration: none;
  6576 +}
  6577 +
  6578 +.diff li {
  6579 + padding: 5px 10px;
  6580 + margin: 0;
  6581 + line-height: 150%;
  6582 +}
  6583 +
  6584 +.diff li.ins {
  6585 + background: #dfd;
  6586 +}
  6587 +
  6588 +.diff li.del {
  6589 + background: #fee;
  6590 +}
  6591 +
  6592 +.diff li.ins:hover {
  6593 + background: #8f8;
  6594 +}
  6595 +
  6596 +.diff li.del:hover {
  6597 + background: #f99;
  6598 +}
  6599 +
  6600 +.diff strong {
  6601 + background: rgba(255, 255, 0, 0.2);
  6602 +}
  6603 +
  6604 +.diff li.diff-comment {
  6605 + display: none;
  6606 +}
  6607 +
  6608 +.diff li.diff-block-info {
  6609 + background: none repeat scroll 0 0 gray;
  6610 +}
test/functional/content_viewer_controller_test.rb
@@ -396,6 +396,17 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -396,6 +396,17 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
396 assert_tag :tag => 'div', :attributes => { :class => /article-body/ }, :content => /edited article/ 396 assert_tag :tag => 'div', :attributes => { :class => /article-body/ }, :content => /edited article/
397 end 397 end
398 398
  399 + should "display differences between article's versions" do
  400 + page = TextArticle.create!(:name => 'myarticle', :body => 'original article', :display_versions => true, :profile => profile)
  401 + page.body = 'edited article'; page.save
  402 +
  403 + get :versions_diff, :profile => profile.identifier, :page => [ 'myarticle' ], :v1 => 1, :v2 => 2;
  404 +
  405 + assert_tag :tag => 'li', :attributes => { :class => /del/ }, :content => /original article/
  406 + assert_tag :tag => 'li', :attributes => { :class => /ins/ }, :content => /edited article/
  407 + assert_response :success
  408 + end
  409 +
399 should 'not return an article of a different user' do 410 should 'not return an article of a different user' do
400 p1 = create_user('test_user').person 411 p1 = create_user('test_user').person
401 a = p1.articles.create!(:name => 'old-name') 412 a = p1.articles.create!(:name => 'old-name')