diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-10 04:41:54 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-10 04:41:54 +0200 |
| commit | 30ed9fd9a8bffb44e6ab91dfedb8c0e33837769a (patch) | |
| tree | 38ed0ff848d7995951b0e9f0f3b00f2e4f52cea1 | |
| parent | 644744183602c68508abb02dbb9f1f321a63f88f (diff) | |
Include assets, tags and template in diff between revisions
| -rw-r--r-- | app/models/page.rb | 33 | ||||
| -rw-r--r-- | app/views/revisions/diff.html.erb | 27 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 11 | ||||
| -rw-r--r-- | test/controllers/revisions_controller_test.rb | 13 | ||||
| -rw-r--r-- | test/models/page_test.rb | 43 |
5 files changed, 114 insertions, 13 deletions
diff --git a/app/models/page.rb b/app/models/page.rb index ea04cd6..740d42e 100644 --- a/app/models/page.rb +++ b/app/models/page.rb | |||
| @@ -176,19 +176,26 @@ class Page < ApplicationRecord | |||
| 176 | end | 176 | end |
| 177 | 177 | ||
| 178 | def diff_against other, view: :inline | 178 | def diff_against other, view: :inline |
| 179 | if view == :side_by_side | 179 | text_diffs = |
| 180 | { | 180 | if view == :side_by_side |
| 181 | title: HtmlWordDiff.side_by_side(other.title.to_s, title.to_s), | 181 | { |
| 182 | abstract: HtmlWordDiff.side_by_side(other.abstract.to_s, abstract.to_s), | 182 | title: HtmlWordDiff.side_by_side(other.title.to_s, title.to_s), |
| 183 | body: HtmlWordDiff.side_by_side(other.body.to_s, body.to_s) | 183 | abstract: HtmlWordDiff.side_by_side(other.abstract.to_s, abstract.to_s), |
| 184 | } | 184 | body: HtmlWordDiff.side_by_side(other.body.to_s, body.to_s) |
| 185 | else | 185 | } |
| 186 | { | 186 | else |
| 187 | title: HtmlWordDiff.inline(other.title.to_s, title.to_s), | 187 | { |
| 188 | abstract: HtmlWordDiff.inline(other.abstract.to_s, abstract.to_s), | 188 | title: HtmlWordDiff.inline(other.title.to_s, title.to_s), |
| 189 | body: HtmlWordDiff.inline(other.body.to_s, body.to_s) | 189 | abstract: HtmlWordDiff.inline(other.abstract.to_s, abstract.to_s), |
| 190 | } | 190 | body: HtmlWordDiff.inline(other.body.to_s, body.to_s) |
| 191 | end | 191 | } |
| 192 | end | ||
| 193 | |||
| 194 | text_diffs.merge( | ||
| 195 | tags: { added: tag_list.to_a - other.tag_list.to_a, removed: other.tag_list.to_a - tag_list.to_a }, | ||
| 196 | template_name: { from: other.template_name, to: template_name, changed: template_name != other.template_name }, | ||
| 197 | assets: { added: assets.to_a - other.assets.to_a, removed: other.assets.to_a - assets.to_a } | ||
| 198 | ) | ||
| 192 | end | 199 | end |
| 193 | 200 | ||
| 194 | def public? | 201 | def public? |
diff --git a/app/views/revisions/diff.html.erb b/app/views/revisions/diff.html.erb index d70503c..b9ce6bd 100644 --- a/app/views/revisions/diff.html.erb +++ b/app/views/revisions/diff.html.erb | |||
| @@ -85,4 +85,31 @@ | |||
| 85 | <h3>Body</h3> | 85 | <h3>Body</h3> |
| 86 | <%= raw @diff[:body] %> | 86 | <%= raw @diff[:body] %> |
| 87 | <% end %> | 87 | <% end %> |
| 88 | |||
| 89 | <h3>Tags</h3> | ||
| 90 | <% if @diff[:tags][:added].empty? && @diff[:tags][:removed].empty? %> | ||
| 91 | <p class="diff_unchanged">No change.</p> | ||
| 92 | <% else %> | ||
| 93 | <ul class="diff_set_list"> | ||
| 94 | <% @diff[:tags][:added].each do |tag| %><li><ins><%= tag %></ins></li><% end %> | ||
| 95 | <% @diff[:tags][:removed].each do |tag| %><li><del><%= tag %></del></li><% end %> | ||
| 96 | </ul> | ||
| 97 | <% end %> | ||
| 98 | |||
| 99 | <h3>Template</h3> | ||
| 100 | <% if @diff[:template_name][:changed] %> | ||
| 101 | <p><del><%= @diff[:template_name][:from] || '(none)' %></del> <ins><%= @diff[:template_name][:to] || '(none)' %></ins></p> | ||
| 102 | <% else %> | ||
| 103 | <p class="diff_unchanged">No change.</p> | ||
| 104 | <% end %> | ||
| 105 | |||
| 106 | <h3>Assets</h3> | ||
| 107 | <% if @diff[:assets][:added].empty? && @diff[:assets][:removed].empty? %> | ||
| 108 | <p class="diff_unchanged">No change.</p> | ||
| 109 | <% else %> | ||
| 110 | <ul class="diff_set_list"> | ||
| 111 | <% @diff[:assets][:added].each do |asset| %><li><ins><%= asset.upload_file_name %></ins></li><% end %> | ||
| 112 | <% @diff[:assets][:removed].each do |asset| %><li><del><%= asset.upload_file_name %></del></li><% end %> | ||
| 113 | </ul> | ||
| 114 | <% end %> | ||
| 88 | </div> | 115 | </div> |
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index e04499d..7b39c72 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -549,6 +549,17 @@ table.revisions_table tr:hover { | |||
| 549 | cursor: help; | 549 | cursor: help; |
| 550 | } | 550 | } |
| 551 | 551 | ||
| 552 | .diff_unchanged { | ||
| 553 | color: #969696; | ||
| 554 | font-style: italic; | ||
| 555 | } | ||
| 556 | |||
| 557 | .diff_set_list { | ||
| 558 | list-style: none; | ||
| 559 | padding-left: 0; | ||
| 560 | margin: 0; | ||
| 561 | } | ||
| 562 | |||
| 552 | table.user_table td.user_login { | 563 | table.user_table td.user_login { |
| 553 | padding-right: 30px; | 564 | padding-right: 30px; |
| 554 | } | 565 | } |
diff --git a/test/controllers/revisions_controller_test.rb b/test/controllers/revisions_controller_test.rb index bf92c5b..53927b4 100644 --- a/test/controllers/revisions_controller_test.rb +++ b/test/controllers/revisions_controller_test.rb | |||
| @@ -148,4 +148,17 @@ class RevisionsControllerTest < ActionController::TestCase | |||
| 148 | assert_response :success | 148 | assert_response :success |
| 149 | assert_select "a", "Side by side" | 149 | assert_select "a", "Side by side" |
| 150 | end | 150 | end |
| 151 | |||
| 152 | test "diffing two revisions also shows tag, template, and asset changes" do | ||
| 153 | login_as :quentin | ||
| 154 | @node.find_or_create_draft(@user) | ||
| 155 | @node.draft.tag_list = "update" | ||
| 156 | @node.draft.save! | ||
| 157 | |||
| 158 | post(:diff, params: { :node_id => @node.id, :start_revision => @node.pages.first.revision, :end_revision => @node.pages.last.revision }) | ||
| 159 | assert_response :success | ||
| 160 | assert_select "h3", "Tags" | ||
| 161 | assert_select "h3", "Template" | ||
| 162 | assert_select "h3", "Assets" | ||
| 163 | end | ||
| 151 | end | 164 | end |
diff --git a/test/models/page_test.rb b/test/models/page_test.rb index 3868a53..bcddc89 100644 --- a/test/models/page_test.rb +++ b/test/models/page_test.rb | |||
| @@ -228,4 +228,47 @@ class PageTest < ActiveSupport::TestCase | |||
| 228 | assert_equal 2, fragment.css('ins.diff_structural').length | 228 | assert_equal 2, fragment.css('ins.diff_structural').length |
| 229 | assert_match "der Zugang erfolgt über den Hinterhof.", fragment.text | 229 | assert_match "der Zugang erfolgt über den Hinterhof.", fragment.text |
| 230 | end | 230 | end |
| 231 | |||
| 232 | test "diff_against reports tag and template changes" do | ||
| 233 | n = Node.root.children.create! :slug => "field_diff_test" | ||
| 234 | d = n.find_or_create_draft @user1 | ||
| 235 | d.tag_list = "update" | ||
| 236 | d.template_name = "standard_template" | ||
| 237 | d.save! | ||
| 238 | n.publish_draft! | ||
| 239 | |||
| 240 | d2 = n.find_or_create_draft @user1 | ||
| 241 | d2.tag_list = "update, pressemitteilung" | ||
| 242 | d2.template_name = "title_only" | ||
| 243 | d2.save! | ||
| 244 | |||
| 245 | diff = d2.diff_against(n.head) | ||
| 246 | |||
| 247 | assert_equal ["pressemitteilung"], diff[:tags][:added] | ||
| 248 | assert_equal [], diff[:tags][:removed] | ||
| 249 | assert diff[:template_name][:changed] | ||
| 250 | assert_equal "standard_template", diff[:template_name][:from] | ||
| 251 | assert_equal "title_only", diff[:template_name][:to] | ||
| 252 | end | ||
| 253 | |||
| 254 | test "diff_against reports added and removed assets by filename" do | ||
| 255 | n = Node.root.children.create! :slug => "asset_diff_test" | ||
| 256 | d = n.find_or_create_draft @user1 | ||
| 257 | d.save! | ||
| 258 | n.publish_draft! | ||
| 259 | |||
| 260 | kept_asset = Asset.create!(:upload_file_name => "kept.png", :upload_content_type => "image/png", :upload_file_size => 1) | ||
| 261 | removed_asset = Asset.create!(:upload_file_name => "removed.pdf", :upload_content_type => "application/pdf", :upload_file_size => 1) | ||
| 262 | n.head.update_assets([kept_asset.id, removed_asset.id]) | ||
| 263 | |||
| 264 | d2 = n.find_or_create_draft @user1 | ||
| 265 | added_asset = Asset.create!(:upload_file_name => "added.png", :upload_content_type => "image/png", :upload_file_size => 1) | ||
| 266 | d2.update_assets([kept_asset.id, added_asset.id]) | ||
| 267 | d2.save! | ||
| 268 | |||
| 269 | diff = d2.diff_against(n.head) | ||
| 270 | |||
| 271 | assert_equal [added_asset], diff[:assets][:added] | ||
| 272 | assert_equal [removed_asset], diff[:assets][:removed] | ||
| 273 | end | ||
| 231 | end | 274 | end |
