summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-07-10 04:41:54 +0200
committererdgeist <erdgeist@erdgeist.org>2026-07-10 04:41:54 +0200
commit30ed9fd9a8bffb44e6ab91dfedb8c0e33837769a (patch)
tree38ed0ff848d7995951b0e9f0f3b00f2e4f52cea1
parent644744183602c68508abb02dbb9f1f321a63f88f (diff)
Include assets, tags and template in diff between revisions
-rw-r--r--app/models/page.rb33
-rw-r--r--app/views/revisions/diff.html.erb27
-rw-r--r--public/stylesheets/admin.css11
-rw-r--r--test/controllers/revisions_controller_test.rb13
-rw-r--r--test/models/page_test.rb43
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
552table.user_table td.user_login { 563table.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
151end 164end
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
231end 274end