diff options
| -rw-r--r-- | app/controllers/admin_controller.rb | 4 | ||||
| -rw-r--r-- | app/controllers/nodes_controller.rb | 2 | ||||
| -rw-r--r-- | app/models/node.rb | 11 | ||||
| -rw-r--r-- | app/views/admin/index.html.erb | 10 | ||||
| -rw-r--r-- | config/locales/de.yml | 7 | ||||
| -rw-r--r-- | config/locales/en.yml | 7 | ||||
| -rw-r--r-- | test/models/node_test.rb | 20 | ||||
| -rw-r--r-- | test/models/node_trash_test.rb | 2 |
8 files changed, 43 insertions, 20 deletions
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb index d9cf1be6..2b35fd20 100644 --- a/app/controllers/admin_controller.rb +++ b/app/controllers/admin_controller.rb | |||
| @@ -5,7 +5,9 @@ class AdminController < ApplicationController | |||
| 5 | before_action :login_required | 5 | before_action :login_required |
| 6 | 6 | ||
| 7 | def index | 7 | def index |
| 8 | @drafts = Node.drafts_and_autosaves(current_user_id: current_user.id).limit(5) | 8 | scope = Node.work_in_progress(current_user_id: current_user.id) |
| 9 | @drafts_total = scope.reorder(nil).count | ||
| 10 | @drafts = scope.includes(:head, :draft, :lock_owner).limit(5) | ||
| 9 | @actions = NodeAction.order(:occurred_at => :desc, :id => :desc).limit(5) | 11 | @actions = NodeAction.order(:occurred_at => :desc, :id => :desc).limit(5) |
| 10 | end | 12 | end |
| 11 | 13 | ||
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index 50b30881..2a2cde33 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb | |||
| @@ -231,7 +231,7 @@ class NodesController < ApplicationController | |||
| 231 | 231 | ||
| 232 | # Filter functions for admin views | 232 | # Filter functions for admin views |
| 233 | def drafts | 233 | def drafts |
| 234 | @nodes = index_matching(Node.drafts_and_autosaves) | 234 | @nodes = index_matching(Node.work_in_progress) |
| 235 | end | 235 | end |
| 236 | 236 | ||
| 237 | def mine | 237 | def mine |
diff --git a/app/models/node.rb b/app/models/node.rb index 02502f6c..1e61f9fe 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -593,12 +593,15 @@ class Node < ApplicationRecord | |||
| 593 | .distinct | 593 | .distinct |
| 594 | end | 594 | end |
| 595 | 595 | ||
| 596 | def self.drafts_and_autosaves(current_user_id: nil) | 596 | # Nodes carrying unfinished work: a draft, an autosave, or a lock with |
| 597 | scope = where("draft_id IS NOT NULL OR autosave_id IS NOT NULL").not_in_trash | 597 | # neither behind it |
| 598 | return scope.order("updated_at DESC") unless current_user_id | 598 | def self.work_in_progress(current_user_id: nil) |
| 599 | scope = where("draft_id IS NOT NULL OR autosave_id IS NOT NULL OR locking_user_id IS NOT NULL") | ||
| 600 | .not_in_trash | ||
| 601 | return scope.order("nodes.updated_at ASC") unless current_user_id | ||
| 599 | 602 | ||
| 600 | scope.order( | 603 | scope.order( |
| 601 | Arel.sql(sanitize_sql_array(["CASE WHEN locking_user_id = ? THEN 0 ELSE 1 END, updated_at DESC", current_user_id])) | 604 | Arel.sql(sanitize_sql_array(["CASE WHEN locking_user_id = ? THEN 0 ELSE 1 END, nodes.updated_at ASC", current_user_id])) |
| 602 | ) | 605 | ) |
| 603 | end | 606 | end |
| 604 | 607 | ||
diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb index 25bdbdc6..984858e5 100644 --- a/app/views/admin/index.html.erb +++ b/app/views/admin/index.html.erb | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | <div id="dashboard_widgets"> | 24 | <div id="dashboard_widgets"> |
| 25 | <div class="dashboard_widget"> | 25 | <div class="dashboard_widget"> |
| 26 | <h3><%= t(".drafts_widget") %></h3> | 26 | <h3><%= t(".drafts_widget", :total => @drafts_total) %></h3> |
| 27 | <ul> | 27 | <ul> |
| 28 | <% @drafts.each do |node| %> | 28 | <% @drafts.each do |node| %> |
| 29 | <li> | 29 | <li> |
| @@ -32,7 +32,13 @@ | |||
| 32 | <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span> | 32 | <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span> |
| 33 | </div> | 33 | </div> |
| 34 | <span class="dashboard_widget_meta"> | 34 | <span class="dashboard_widget_meta"> |
| 35 | <% if (editor = node_last_editor(node)) %><%= editor %>, <% end %><%= relative_time_phrase(node.updated_at) %> | 35 | <% if node.locked? %> |
| 36 | <%= icon("lock", library: "tabler", "aria-label": t(".held_by")) %> | ||
| 37 | <%= node.lock_owner.login %>, | ||
| 38 | <% elsif (editor = node_last_editor(node)) %> | ||
| 39 | <%= editor %>, | ||
| 40 | <% end %> | ||
| 41 | <%= relative_time_phrase(node.updated_at) %> | ||
| 36 | </span> | 42 | </span> |
| 37 | </li> | 43 | </li> |
| 38 | <% end %> | 44 | <% end %> |
diff --git a/config/locales/de.yml b/config/locales/de.yml index 6267fcff..30e2f1b5 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml | |||
| @@ -285,8 +285,9 @@ de: | |||
| 285 | find_chapter: "Chapter finden" | 285 | find_chapter: "Chapter finden" |
| 286 | upload_asset: "Asset hochladen" | 286 | upload_asset: "Asset hochladen" |
| 287 | add_in_tree: "Seite im Seitenbaum anlegen" | 287 | add_in_tree: "Seite im Seitenbaum anlegen" |
| 288 | drafts_widget: "Entwürfe und Autosaves" | 288 | drafts_widget: "In Arbeit (%{total})" |
| 289 | see_all_drafts: "Alle Entwürfe →" | 289 | held_by: "Gesperrt von" |
| 290 | see_all_drafts: "Alle Nodes in Arbeit →" | ||
| 290 | see_all_changes: "Alle Änderungen →" | 291 | see_all_changes: "Alle Änderungen →" |
| 291 | housekeeping: "Verwaltung" | 292 | housekeeping: "Verwaltung" |
| 292 | my_account: "Mein Konto" | 293 | my_account: "Mein Konto" |
| @@ -424,7 +425,7 @@ de: | |||
| 424 | abstract_locale: "Abstract (%{lang})" | 425 | abstract_locale: "Abstract (%{lang})" |
| 425 | body_locale: "Text (%{lang})" | 426 | body_locale: "Text (%{lang})" |
| 426 | drafts: | 427 | drafts: |
| 427 | title: "Nodes mit Entwürfen oder Autosaves" | 428 | title: "Nodes mit Entwürfen, Autosaves oder Sperren" |
| 428 | mine: | 429 | mine: |
| 429 | title: "Meine Arbeit" | 430 | title: "Meine Arbeit" |
| 430 | tags: | 431 | tags: |
diff --git a/config/locales/en.yml b/config/locales/en.yml index e5a4182f..f76dfecb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml | |||
| @@ -238,8 +238,9 @@ en: | |||
| 238 | find_chapter: "Find a chapter" | 238 | find_chapter: "Find a chapter" |
| 239 | upload_asset: "Upload asset" | 239 | upload_asset: "Upload asset" |
| 240 | add_in_tree: "Add a page in the page tree" | 240 | add_in_tree: "Add a page in the page tree" |
| 241 | drafts_widget: "Drafts and autosaves" | 241 | drafts_widget: "In progress (%{total})" |
| 242 | see_all_drafts: "See all drafts →" | 242 | held_by: "Locked by" |
| 243 | see_all_drafts: "See all WIP nodes →" | ||
| 243 | see_all_changes: "See all recent changes →" | 244 | see_all_changes: "See all recent changes →" |
| 244 | housekeeping: "Housekeeping" | 245 | housekeeping: "Housekeeping" |
| 245 | my_account: "My account" | 246 | my_account: "My account" |
| @@ -376,7 +377,7 @@ en: | |||
| 376 | abstract_locale: "Abstract (%{lang})" | 377 | abstract_locale: "Abstract (%{lang})" |
| 377 | body_locale: "Body (%{lang})" | 378 | body_locale: "Body (%{lang})" |
| 378 | drafts: | 379 | drafts: |
| 379 | title: "Nodes with drafts or autosaves" | 380 | title: "Nodes with drafts, autosaves or locks" |
| 380 | mine: | 381 | mine: |
| 381 | title: "My work" | 382 | title: "My work" |
| 382 | tags: | 383 | tags: |
diff --git a/test/models/node_test.rb b/test/models/node_test.rb index 8bdb90ee..c5b0d6a2 100644 --- a/test/models/node_test.rb +++ b/test/models/node_test.rb | |||
| @@ -522,17 +522,17 @@ class NodeTest < ActiveSupport::TestCase | |||
| 522 | assert_equal 0, Node.editor_search("Backspace Nonexistentstreet").count | 522 | assert_equal 0, Node.editor_search("Backspace Nonexistentstreet").count |
| 523 | end | 523 | end |
| 524 | 524 | ||
| 525 | test "drafts_and_autosaves without a user sorts by recency only" do | 525 | test "work_in_progress without a user sorts by oldest-first" do |
| 526 | older = Node.root.children.create!(:slug => "drafts_order_older") | 526 | older = Node.root.children.create!(:slug => "drafts_order_older") |
| 527 | find_or_create_draft(older, @user1) | 527 | find_or_create_draft(older, @user1) |
| 528 | newer = Node.root.children.create!(:slug => "drafts_order_newer") | 528 | newer = Node.root.children.create!(:slug => "drafts_order_newer") |
| 529 | find_or_create_draft(newer, @user1) | 529 | find_or_create_draft(newer, @user1) |
| 530 | 530 | ||
| 531 | result = Node.drafts_and_autosaves.to_a | 531 | result = Node.work_in_progress.to_a |
| 532 | assert result.index(newer) < result.index(older) | 532 | assert result.index(older) < result.index(newer) |
| 533 | end | 533 | end |
| 534 | 534 | ||
| 535 | test "drafts_and_autosaves with a user puts their own locked nodes first, regardless of recency" do | 535 | test "work_in_progress with a user puts their own locked nodes first, regardless of recency" do |
| 536 | mine = Node.root.children.create!(:slug => "drafts_order_mine") | 536 | mine = Node.root.children.create!(:slug => "drafts_order_mine") |
| 537 | mine.lock_for_editing!(@user1) | 537 | mine.lock_for_editing!(@user1) |
| 538 | mine.autosave!({:title => "mine"}, @user1) | 538 | mine.autosave!({:title => "mine"}, @user1) |
| @@ -542,10 +542,20 @@ class NodeTest < ActiveSupport::TestCase | |||
| 542 | someone_elses_newer.lock_for_editing!(other_user) | 542 | someone_elses_newer.lock_for_editing!(other_user) |
| 543 | someone_elses_newer.autosave!({:title => "theirs"}, other_user) | 543 | someone_elses_newer.autosave!({:title => "theirs"}, other_user) |
| 544 | 544 | ||
| 545 | result = Node.drafts_and_autosaves(current_user_id: @user1.id).to_a | 545 | result = Node.work_in_progress(current_user_id: @user1.id).to_a |
| 546 | assert result.index(mine) < result.index(someone_elses_newer) | 546 | assert result.index(mine) < result.index(someone_elses_newer) |
| 547 | end | 547 | end |
| 548 | 548 | ||
| 549 | test "work_in_progress includes a node that is only locked" do | ||
| 550 | locked = create_node_with_published_page | ||
| 551 | locked.lock_for_editing!(@user1) | ||
| 552 | locked.reload | ||
| 553 | |||
| 554 | assert_nil locked.draft | ||
| 555 | assert_nil locked.autosave | ||
| 556 | assert_includes Node.work_in_progress.to_a, locked | ||
| 557 | end | ||
| 558 | |||
| 549 | test "autosave! carries over the current related assets to the newly created autosave row" do | 559 | test "autosave! carries over the current related assets to the newly created autosave row" do |
| 550 | node = Node.root.children.create!(:slug => "autosave_asset_carryover_test") | 560 | node = Node.root.children.create!(:slug => "autosave_asset_carryover_test") |
| 551 | user = User.find_by_login("quentin") | 561 | user = User.find_by_login("quentin") |
diff --git a/test/models/node_trash_test.rb b/test/models/node_trash_test.rb index 52069d75..3947f20e 100644 --- a/test/models/node_trash_test.rb +++ b/test/models/node_trash_test.rb | |||
| @@ -161,7 +161,7 @@ class NodeTrashTest < ActiveSupport::TestCase | |||
| 161 | node = create_node_with_published_page | 161 | node = create_node_with_published_page |
| 162 | node.trash!(@user1) | 162 | node.trash!(@user1) |
| 163 | 163 | ||
| 164 | ids = Node.drafts_and_autosaves.pluck(:id) | 164 | ids = Node.work_in_progress.pluck(:id) |
| 165 | assert_not_includes ids, Node.trash.id | 165 | assert_not_includes ids, Node.trash.id |
| 166 | assert_not_includes ids, node.id | 166 | assert_not_includes ids, node.id |
| 167 | end | 167 | end |
