diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/controllers/nodes_controller.rb | 2 | ||||
| -rw-r--r-- | app/controllers/page_translations_controller.rb | 3 | ||||
| -rw-r--r-- | app/models/node.rb | 65 | ||||
| -rw-r--r-- | app/models/node_action.rb | 33 | ||||
| -rw-r--r-- | app/views/admin/_recent_changes.html.erb | 24 | ||||
| -rw-r--r-- | app/views/admin/index.html.erb | 12 | ||||
| -rw-r--r-- | app/views/nodes/_recent_change_item.html.erb | 9 | ||||
| -rw-r--r-- | app/views/nodes/recent.html.erb | 6 |
8 files changed, 89 insertions, 65 deletions
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index bff1733..9c5d228 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb | |||
| @@ -147,7 +147,7 @@ class NodesController < ApplicationController | |||
| 147 | end | 147 | end |
| 148 | 148 | ||
| 149 | def publish | 149 | def publish |
| 150 | @node.publish_draft! | 150 | @node.publish_draft!(current_user) |
| 151 | flash[:notice] = "Draft has been published" | 151 | flash[:notice] = "Draft has been published" |
| 152 | redirect_to node_path(@node) | 152 | redirect_to node_path(@node) |
| 153 | end | 153 | end |
diff --git a/app/controllers/page_translations_controller.rb b/app/controllers/page_translations_controller.rb index 38a7c4f..be4f488 100644 --- a/app/controllers/page_translations_controller.rb +++ b/app/controllers/page_translations_controller.rb | |||
| @@ -63,6 +63,9 @@ class PageTranslationsController < ApplicationController | |||
| 63 | draft.translations.where(:locale => @locale).delete_all | 63 | draft.translations.where(:locale => @locale).delete_all |
| 64 | draft.reload | 64 | draft.reload |
| 65 | 65 | ||
| 66 | NodeAction.record!(:node => @node, :page => draft, :user => current_user, | ||
| 67 | :action => "translation_destroy", :locale => @locale) | ||
| 68 | |||
| 66 | flash[:notice] = "#{@locale.upcase} translation removed from the draft. Publish to make this permanent." | 69 | flash[:notice] = "#{@locale.upcase} translation removed from the draft. Publish to make this permanent." |
| 67 | redirect_to node_path(@node) | 70 | redirect_to node_path(@node) |
| 68 | rescue LockedByAnotherUser => e | 71 | rescue LockedByAnotherUser => e |
diff --git a/app/models/node.rb b/app/models/node.rb index 311c5c0..b41df06 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -170,10 +170,12 @@ class Node < ApplicationRecord | |||
| 170 | self.autosave.destroy | 170 | self.autosave.destroy |
| 171 | self.autosave_id = nil | 171 | self.autosave_id = nil |
| 172 | self.save! | 172 | self.save! |
| 173 | NodeAction.record!(:node => self, :user => current_user, :action => "discard_autosave") | ||
| 173 | elsif self.draft && self.head | 174 | elsif self.draft && self.head |
| 174 | self.draft.destroy | 175 | self.draft.destroy |
| 175 | self.draft_id = nil | 176 | self.draft_id = nil |
| 176 | self.save! | 177 | self.save! |
| 178 | NodeAction.record!(:node => self, :user => current_user, :action => "destroy_draft") | ||
| 177 | end | 179 | end |
| 178 | 180 | ||
| 179 | self.unlock! unless self.draft | 181 | self.unlock! unless self.draft |
| @@ -188,43 +190,50 @@ class Node < ApplicationRecord | |||
| 188 | end | 190 | end |
| 189 | end | 191 | end |
| 190 | 192 | ||
| 191 | def publish_draft! | 193 | def publish_draft! current_user = nil |
| 192 | # Return nil if nothing to publish and no staged changes | 194 | # Return nil if nothing to publish and no staged changes |
| 193 | return nil unless self.draft || staged_slug || staged_parent_id | 195 | return nil unless self.draft || staged_slug || staged_parent_id |
| 194 | 196 | ||
| 195 | if self.draft | 197 | ActiveRecord::Base.transaction do |
| 196 | self.head = self.draft | 198 | if self.draft |
| 197 | self.head.published_at ||= Time.now | 199 | previous_title = self.head ? Globalize.with_locale(I18n.default_locale) { self.head.title } : nil |
| 198 | self.head.save! | 200 | self.head = self.draft |
| 199 | self.draft = nil | 201 | self.head.published_at ||= Time.now |
| 200 | end | 202 | self.head.save! |
| 201 | 203 | self.draft = nil | |
| 202 | if staged_slug && (staged_slug != slug) | ||
| 203 | self.slug = staged_slug | ||
| 204 | self.staged_slug = nil | ||
| 205 | end | ||
| 206 | 204 | ||
| 207 | if staged_parent_id && (staged_parent_id != parent_id) | 205 | new_title = Globalize.with_locale(I18n.default_locale) { self.head.title } |
| 208 | new_parent = Node.find(staged_parent_id) | 206 | NodeAction.record!(:node => self, :page => self.head, :user => current_user, |
| 207 | :action => "publish", :from => previous_title, :to => new_title) | ||
| 208 | end | ||
| 209 | 209 | ||
| 210 | if new_parent == self || self.descendants.include?(new_parent) | 210 | if staged_slug && (staged_slug != slug) |
| 211 | raise ActiveRecord::RecordInvalid.new(self), "Cannot move a node under itself or one of its own descendants" | 211 | self.slug = staged_slug |
| 212 | self.staged_slug = nil | ||
| 212 | end | 213 | end |
| 213 | 214 | ||
| 214 | self.staged_parent_id = nil | 215 | if staged_parent_id && (staged_parent_id != parent_id) |
| 215 | self.save! | 216 | new_parent = Node.find(staged_parent_id) |
| 216 | self.move_to_child_of(new_parent) | 217 | |
| 217 | else | 218 | if new_parent == self || self.descendants.include?(new_parent) |
| 218 | unless self.save | 219 | raise ActiveRecord::RecordInvalid.new(self), "Cannot move a node under itself or one of its own descendants" |
| 219 | raise ActiveRecord::RecordInvalid.new(self) | 220 | end |
| 221 | |||
| 222 | self.staged_parent_id = nil | ||
| 223 | self.save! | ||
| 224 | self.move_to_child_of(new_parent) | ||
| 225 | else | ||
| 226 | unless self.save | ||
| 227 | raise ActiveRecord::RecordInvalid.new(self) | ||
| 228 | end | ||
| 220 | end | 229 | end |
| 221 | end | ||
| 222 | 230 | ||
| 223 | self.reload | 231 | self.reload |
| 224 | self.update_unique_name | 232 | self.update_unique_name |
| 225 | self.send(:update_unique_names_of_children) | 233 | self.send(:update_unique_names_of_children) |
| 226 | self.unlock! | 234 | self.unlock! |
| 227 | self | 235 | self |
| 236 | end | ||
| 228 | end | 237 | end |
| 229 | 238 | ||
| 230 | def restore_revision! revision | 239 | def restore_revision! revision |
diff --git a/app/models/node_action.rb b/app/models/node_action.rb new file mode 100644 index 0000000..f32b5b7 --- /dev/null +++ b/app/models/node_action.rb | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | class NodeAction < ApplicationRecord | ||
| 2 | belongs_to :node, optional: true | ||
| 3 | belongs_to :page, optional: true | ||
| 4 | belongs_to :user, optional: true | ||
| 5 | |||
| 6 | validates :action, presence: true | ||
| 7 | validates :occurred_at, presence: true | ||
| 8 | |||
| 9 | def self.record!(node:, action:, user: nil, page: nil, locale: nil, **extra) | ||
| 10 | create!( | ||
| 11 | :node => node, | ||
| 12 | :page => page, | ||
| 13 | :user => user, | ||
| 14 | :action => action, | ||
| 15 | :locale => locale, | ||
| 16 | :occurred_at => Time.now, | ||
| 17 | :metadata => { | ||
| 18 | "username" => user&.login, | ||
| 19 | "human_readable_node_name" => Globalize.with_locale(I18n.default_locale) { | ||
| 20 | node&.head&.title || node&.draft&.title | ||
| 21 | }, | ||
| 22 | }.merge(extra.stringify_keys) | ||
| 23 | ) | ||
| 24 | end | ||
| 25 | |||
| 26 | def actor_name | ||
| 27 | metadata["username"] || "unknown" | ||
| 28 | end | ||
| 29 | |||
| 30 | def subject_name | ||
| 31 | metadata["human_readable_node_name"] || node&.unique_name || "deleted node" | ||
| 32 | end | ||
| 33 | end | ||
diff --git a/app/views/admin/_recent_changes.html.erb b/app/views/admin/_recent_changes.html.erb deleted file mode 100644 index 88b5e93..0000000 --- a/app/views/admin/_recent_changes.html.erb +++ /dev/null | |||
| @@ -1,24 +0,0 @@ | |||
| 1 | <h2>Recent Changes</h2> | ||
| 2 | <div id="draft_list"> | ||
| 3 | <table> | ||
| 4 | <tr class="header"> | ||
| 5 | <th>Title</th> | ||
| 6 | <th>path</th> | ||
| 7 | <th>user</th> | ||
| 8 | <th>date</th> | ||
| 9 | <th></th> | ||
| 10 | </tr> | ||
| 11 | <% @recent_changes.each do |node| %> | ||
| 12 | <tr> | ||
| 13 | <td><%= truncated_title_for_node node %></td> | ||
| 14 | <td><%= node.unique_name %></td> | ||
| 15 | <td><%= node.draft.user.login rescue "" %></td> | ||
| 16 | <td><%= node.updated_at.to_fs(:db) %></td> | ||
| 17 | <td class="actions"> | ||
| 18 | <%= link_to 'Show', node_path(node) %> | ||
| 19 | <%= link_to "Revisions", revision_path(:id => node.id) %> | ||
| 20 | </td> | ||
| 21 | </tr> | ||
| 22 | <% end %> | ||
| 23 | </table> | ||
| 24 | </div> \ No newline at end of file | ||
diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb index bdb555e..a9c0512 100644 --- a/app/views/admin/index.html.erb +++ b/app/views/admin/index.html.erb | |||
| @@ -43,17 +43,7 @@ | |||
| 43 | <div class="dashboard_widget"> | 43 | <div class="dashboard_widget"> |
| 44 | <h3>Recent changes</h3> | 44 | <h3>Recent changes</h3> |
| 45 | <ul> | 45 | <ul> |
| 46 | <% @recent_changes.each do |node| %> | 46 | <%= render partial: "nodes/recent_change_item", collection: @recent_changes, as: :node %> |
| 47 | <li> | ||
| 48 | <div> | ||
| 49 | <%= link_to title_for_node(node), node_path(node) %> | ||
| 50 | <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span> | ||
| 51 | </div> | ||
| 52 | <span class="dashboard_widget_meta"> | ||
| 53 | <%= (editor = node_head_editor(node)) ? t("published_by", editor: editor) : t("published") %>, <%= relative_time_phrase(node.head.updated_at) %> | ||
| 54 | </span> | ||
| 55 | </li> | ||
| 56 | <% end %> | ||
| 57 | </ul> | 47 | </ul> |
| 58 | <%= link_to "See all recent changes →", recent_nodes_path %> | 48 | <%= link_to "See all recent changes →", recent_nodes_path %> |
| 59 | </div> | 49 | </div> |
diff --git a/app/views/nodes/_recent_change_item.html.erb b/app/views/nodes/_recent_change_item.html.erb new file mode 100644 index 0000000..754a775 --- /dev/null +++ b/app/views/nodes/_recent_change_item.html.erb | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <li> | ||
| 2 | <div> | ||
| 3 | <%= link_to title_for_node(node), node_path(node) %> | ||
| 4 | <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span> | ||
| 5 | </div> | ||
| 6 | <span class="dashboard_widget_meta"> | ||
| 7 | <%= (editor = node_head_editor(node)) ? t("last_edited_by", editor: editor) : t("last_edited") %>, <%= relative_time_phrase(node.head.updated_at) %> | ||
| 8 | </span> | ||
| 9 | </li> | ||
diff --git a/app/views/nodes/recent.html.erb b/app/views/nodes/recent.html.erb index 3602775..d256253 100644 --- a/app/views/nodes/recent.html.erb +++ b/app/views/nodes/recent.html.erb | |||
| @@ -1,3 +1,7 @@ | |||
| 1 | <h1>Recently changed</h1> | 1 | <h1>Recently changed</h1> |
| 2 | 2 | ||
| 3 | <%= render 'node_list' %> | 3 | <%= will_paginate @nodes %> |
| 4 | <ul id="recent_changes_full_list"> | ||
| 5 | <%= render partial: "nodes/recent_change_item", collection: @nodes, as: :node %> | ||
| 6 | </ul> | ||
| 7 | <%= will_paginate @nodes %> | ||
