From d41ee504caedbe858e24ab2a23c7a804454c64c8 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 18 Jul 2026 02:15:29 +0200 Subject: Add Trash affordances: cockpit, listing, dashboard entry nodes#show gains a Trash section on trashed nodes: provenance from the trash entry, a restore form whose parent picker pre-fills the old parent while it still lives, and permanent deletion. A Move-to-Trash button joins the status actions on living nodes. nodes#trashed lists trashed subtree roots with weight, provenance, and deletion; the dashboard housekeeping row links to it, and trash/destroy redirect there. Deletion from Trash now removes the whole subtree, deepest first, each node through a real destroy! so every per-node cascade runs -- amending the never-recursive rule for this one sanctioned path (both confirms state the count; the root entry carries destroyed_descendants). Bare Node#destroy still refuses children. --- app/views/nodes/show.html.erb | 53 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'app/views/nodes/show.html.erb') diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb index ae25571d..4d4f6d51 100644 --- a/app/views/nodes/show.html.erb +++ b/app/views/nodes/show.html.erb @@ -46,7 +46,7 @@ <% end %> <% unless locked_by_other %> - <% if @node.draft && !@node.autosave %> + <% if @node.draft && !@node.autosave && !@node.in_trash? && !@node.trash_node? %>
<%= button_to 'Publish', publish_node_path(@node), method: :put, form: { data: { confirm: "Publish this draft?" }, class: 'button_to state_changing' } %> @@ -62,6 +62,15 @@ <% end %>
<% end %> + <% unless @node.trash_node? || @node.in_trash? || @node.root? %> +
+ <%= button_to trash_node_path(@node), method: :put, + form: { data: { confirm: "Move this page and everything beneath it to the Trash? All published content in it will go offline." }, class: 'button_to destructive' } do %> + <%= icon("trash", library: "tabler", "aria-hidden": true) %> + Move to Trash + <% end %> +
+ <% end %> <% end %> @@ -70,6 +79,48 @@ <% end %> + <% if @node.in_trash? %> +
Trash
+
+
+ <% if (entry = @node.last_trash_entry) && entry.metadata.dig("path", "from") %> +
+ Was at + <%= entry.metadata.dig("path", "from") %> +
+ <% end %> +
+ Restore to + <% suggestion = @node.suggested_restore_parent %> + <%= form_tag restore_from_trash_node_path(@node), :method => :put, :class => "aligned_action_row" do %> +
+ <%= text_field_tag :restore_search_term, + suggestion && (suggestion.head&.title || suggestion.draft&.title || suggestion.slug), + :placeholder => "Search for a new parent…" %> +
+
+ <%= hidden_field_tag :parent_id, suggestion&.id %> + <%= submit_tag "Restore here", :class => "action_button action_button_no_margin_top" %> + <% end %> + Restored pages come back unpublished. Republish each page deliberately. +
+
+
+
+ <% doomed_below = @node.descendants.count %> + <%= button_to node_path(@node), method: :delete, + form: { data: { confirm: doomed_below > 0 ? + "Delete this page and the #{doomed_below} pages beneath it permanently? This cannot be undone." : + "Delete this page permanently? This cannot be undone." }, + class: 'button_to destructive' } do %> + <%= icon("trash-x", library: "tabler", "aria-hidden": true) %> + Delete permanently<%= " (including #{doomed_below} beneath)" if doomed_below > 0 %> + <% end %> +
+
+
+ <% end %> +
Translations
-- cgit v1.3