summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/nodes_controller.rb2
-rw-r--r--app/controllers/page_translations_controller.rb3
-rw-r--r--app/models/node.rb65
-rw-r--r--app/models/node_action.rb33
-rw-r--r--app/views/admin/_recent_changes.html.erb24
-rw-r--r--app/views/admin/index.html.erb12
-rw-r--r--app/views/nodes/_recent_change_item.html.erb9
-rw-r--r--app/views/nodes/recent.html.erb6
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 @@
1class 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
33end
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 %>