diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-23 17:49:18 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-23 17:49:18 +0200 |
| commit | f993853db3e233f05a55de5ba2a87b77acf041aa (patch) | |
| tree | 0a28289ff471ab5853b22c2a68ed21ce4e0eb4ac /app | |
| parent | 932d4a4be40587fa6d489eca16a1ef6d6f2936d1 (diff) | |
Record asset deltas at publish, with changed assets as participants
Diffstat (limited to 'app')
| -rw-r--r-- | app/helpers/node_actions_helper.rb | 9 | ||||
| -rw-r--r-- | app/models/node.rb | 8 | ||||
| -rw-r--r-- | app/models/node_action.rb | 34 |
3 files changed, 45 insertions, 6 deletions
diff --git a/app/helpers/node_actions_helper.rb b/app/helpers/node_actions_helper.rb index ed8d0407..4041ffa9 100644 --- a/app/helpers/node_actions_helper.rb +++ b/app/helpers/node_actions_helper.rb | |||
| @@ -49,7 +49,7 @@ module NodeActionsHelper | |||
| 49 | m = action.metadata | 49 | m = action.metadata |
| 50 | return true if m["translation_diff"].present? | 50 | return true if m["translation_diff"].present? |
| 51 | return true if m["title"].is_a?(Hash) && m.dig("title", "from") != m.dig("title", "to") | 51 | return true if m["title"].is_a?(Hash) && m.dig("title", "from") != m.dig("title", "to") |
| 52 | %w[author tags template_changed assets_changed | 52 | %w[author tags template_changed assets assets_changed assets_reordered |
| 53 | abstract_changed body_changed].any? { |key| m[key].present? } | 53 | abstract_changed body_changed].any? { |key| m[key].present? } |
| 54 | end | 54 | end |
| 55 | 55 | ||
| @@ -69,6 +69,13 @@ module NodeActionsHelper | |||
| 69 | items << t("node_actions.abstract_changed") if m["abstract_changed"] | 69 | items << t("node_actions.abstract_changed") if m["abstract_changed"] |
| 70 | items << t("node_actions.body_changed") if m["body_changed"] | 70 | items << t("node_actions.body_changed") if m["body_changed"] |
| 71 | items << t("node_actions.template_changed") if m["template_changed"] | 71 | items << t("node_actions.template_changed") if m["template_changed"] |
| 72 | if m["assets"] | ||
| 73 | items << t("node_actions.detail_assets_added", | ||
| 74 | :names => Array(m.dig("assets", "added")).join(", ")) if m.dig("assets", "added") | ||
| 75 | items << t("node_actions.detail_assets_removed", | ||
| 76 | :names => Array(m.dig("assets", "removed")).join(", ")) if m.dig("assets", "removed") | ||
| 77 | end | ||
| 78 | items << t("node_actions.assets_reordered") if m["assets_reordered"] | ||
| 72 | items << t("node_actions.assets_changed") if m["assets_changed"] | 79 | items << t("node_actions.assets_changed") if m["assets_changed"] |
| 73 | items | 80 | items |
| 74 | end | 81 | end |
diff --git a/app/models/node.rb b/app/models/node.rb index 0a9cd2d1..274b2f94 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -249,7 +249,9 @@ class Node < ApplicationRecord | |||
| 249 | self.head.save! | 249 | self.head.save! |
| 250 | self.draft = nil | 250 | self.draft = nil |
| 251 | 251 | ||
| 252 | NodeAction.record!(:node => self, :page => self.head, :user => current_user, | 252 | NodeAction.record!(:node => self, |
| 253 | :participants => [self] + NodeAction.changed_assets(outgoing_head, self.head), | ||
| 254 | :page => self.head, :user => current_user, | ||
| 253 | :action => "publish", :via => "draft", | 255 | :action => "publish", :via => "draft", |
| 254 | **NodeAction.head_diff(outgoing_head, self.head)) | 256 | **NodeAction.head_diff(outgoing_head, self.head)) |
| 255 | end | 257 | end |
| @@ -296,7 +298,9 @@ class Node < ApplicationRecord | |||
| 296 | self.head = page | 298 | self.head = page |
| 297 | self.save! | 299 | self.save! |
| 298 | 300 | ||
| 299 | NodeAction.record!(:node => self, :page => page, :user => current_user, | 301 | NodeAction.record!(:node => self, |
| 302 | :participants => [self] + NodeAction.changed_assets(outgoing_head, page), | ||
| 303 | :page => page, :user => current_user, | ||
| 300 | :action => "publish", :via => "revision", | 304 | :action => "publish", :via => "revision", |
| 301 | **NodeAction.head_diff(outgoing_head, page)) | 305 | **NodeAction.head_diff(outgoing_head, page)) |
| 302 | self | 306 | self |
diff --git a/app/models/node_action.rb b/app/models/node_action.rb index aa52f489..afa2195c 100644 --- a/app/models/node_action.rb +++ b/app/models/node_action.rb | |||
| @@ -35,8 +35,16 @@ class NodeAction < ApplicationRecord | |||
| 35 | # "title" -- pair, always; "from" null on first publish | 35 | # "title" -- pair, always; "from" null on first publish |
| 36 | # "author" -- pair, when the byline changed (incl. first publish) | 36 | # "author" -- pair, when the byline changed (incl. first publish) |
| 37 | # "tags" -- pair of arrays, when changed | 37 | # "tags" -- pair of arrays, when changed |
| 38 | # "assets_changed", "template_changed", | 38 | # "assets" -- {"added" => [asset names], "removed" => [asset names]}, |
| 39 | # "abstract_changed", "body_changed" | 39 | # keys only when any; a delta, not a pair. The event IS |
| 40 | # the delta, full sets would bloat every entry. Changed | ||
| 41 | # assets are participants of the entry. Replaces the | ||
| 42 | # legacy "assets_changed" boolean, which witnessed | ||
| 43 | # pre-contract entries still carry and the renderer keeps | ||
| 44 | # understanding. Assets destroyed since leave no trace in | ||
| 45 | # regenerated deltas, their joins died with them. | ||
| 46 | # "assets_reordered" -- boolean, set unchanged but gallery order not | ||
| 47 | # "template_changed", "abstract_changed", "body_changed" | ||
| 40 | # -- the last two for the default locale; page_id links | 48 | # -- the last two for the default locale; page_id links |
| 41 | # to the revision for the real diff (never stored) | 49 | # to the revision for the real diff (never stored) |
| 42 | # "translation_diff" -- only when a non-default locale differs: | 50 | # "translation_diff" -- only when a non-default locale differs: |
| @@ -155,7 +163,17 @@ class NodeAction < ApplicationRecord | |||
| 155 | diff[:tags] = { "from" => old_tags, "to" => new_tags } if old_tags != new_tags | 163 | diff[:tags] = { "from" => old_tags, "to" => new_tags } if old_tags != new_tags |
| 156 | 164 | ||
| 157 | diff[:template_changed] = true if old_page.template_name != new_page.template_name | 165 | diff[:template_changed] = true if old_page.template_name != new_page.template_name |
| 158 | diff[:assets_changed] = true if old_page.assets.map(&:id) != new_page.assets.map(&:id) | 166 | |
| 167 | old_assets, new_assets = old_page.assets.to_a, new_page.assets.to_a | ||
| 168 | added, removed = new_assets - old_assets, old_assets - new_assets | ||
| 169 | if added.any? || removed.any? | ||
| 170 | assets = {} | ||
| 171 | assets["added"] = added.map { |a| a.name.presence || a.upload_file_name } if added.any? | ||
| 172 | assets["removed"] = removed.map { |a| a.name.presence || a.upload_file_name } if removed.any? | ||
| 173 | diff[:assets] = assets | ||
| 174 | elsif old_assets.map(&:id) != new_assets.map(&:id) | ||
| 175 | diff[:assets_reordered] = true | ||
| 176 | end | ||
| 159 | 177 | ||
| 160 | old_t = old_page.translations.find_by(:locale => default) | 178 | old_t = old_page.translations.find_by(:locale => default) |
| 161 | new_t = new_page.translations.find_by(:locale => default) | 179 | new_t = new_page.translations.find_by(:locale => default) |
| @@ -188,6 +206,16 @@ class NodeAction < ApplicationRecord | |||
| 188 | diff | 206 | diff |
| 189 | end | 207 | end |
| 190 | 208 | ||
| 209 | # The asset records added or removed between an outgoing head and its | ||
| 210 | # replacement -- the participant complement to head_diff's "assets" | ||
| 211 | # names. Empty on first publish, mirroring head_diff, which records | ||
| 212 | # no asset delta when everything is new. | ||
| 213 | def self.changed_assets old_page, new_page | ||
| 214 | return [] unless old_page | ||
| 215 | old_a, new_a = old_page.assets.to_a, new_page.assets.to_a | ||
| 216 | (new_a - old_a) | (old_a - new_a) | ||
| 217 | end | ||
| 218 | |||
| 191 | def actor_name | 219 | def actor_name |
| 192 | metadata["username"] || "unknown" | 220 | metadata["username"] || "unknown" |
| 193 | end | 221 | end |
