diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-08 22:52:00 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-08 22:52:00 +0200 |
| commit | 168ff3f8b6037bc3c2b5bce74adac37e48366dac (patch) | |
| tree | 3d33fa85125266f3ec827528f73da4704b948f45 /app | |
| parent | 9427dc462e68eb4b902cd5b2ace5607b036504ef (diff) | |
Add the Status section to nodes#show and rebuild nodes#edit's action bar
Retires content_for :subnavigation on nodes#show entirely -- Preview
was fully redundant with Links' own preview URLs in every state, and
Edit is now a permanent, always-rendered action inside the new Status
section rather than a link floating at the top, consistent with the
"action lives next to the info" pattern People already established
for Unlock. Status surfaces head/draft/autosave plainly and gates
Edit/Publish/Destroy/Discard on lock ownership specifically, not mere
lock presence -- @node.locked? alone would have blocked the lock
owner's own session, caught by the click-test and fixed here rather
than shipped.
nodes#edit's action bar is rebuilt to sit outside form_for (both
button_to calls render their own nested form, invalid HTML the
browser was silently stripping) with Save wired back in via
form="..." rather than needing to live inside the form tag at all.
Also brings the locked-and-ready-to-edit flash message, and the
visual polish from this session's click-test: consistent button
heights across the bordered and pill-shaped variants sharing a row,
spacing between Status's data and its actions, and error_messages
styling reusing the destructive-red vocabulary already established
elsewhere.
Diffstat (limited to 'app')
| -rw-r--r-- | app/controllers/nodes_controller.rb | 2 | ||||
| -rw-r--r-- | app/views/nodes/edit.html.erb | 45 | ||||
| -rw-r--r-- | app/views/nodes/show.html.erb | 58 |
3 files changed, 77 insertions, 28 deletions
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index d8586e2..72d4a3e 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb | |||
| @@ -68,6 +68,8 @@ class NodesController < ApplicationController | |||
| 68 | @node.lock_for_editing!( current_user ) | 68 | @node.lock_for_editing!( current_user ) |
| 69 | @page = @node.autosave || @node.draft || @node.head | 69 | @page = @node.autosave || @node.draft || @node.head |
| 70 | 70 | ||
| 71 | flash.now[:notice] = "Node locked and ready to edit" unless @node.autosave | ||
| 72 | |||
| 71 | if @node.autosave | 73 | if @node.autosave |
| 72 | flash.now[:notice] = | 74 | flash.now[:notice] = |
| 73 | "This page has unsaved changes from a previous session, shown below. " \ | 75 | "This page has unsaved changes from a previous session, shown below. " \ |
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb index feba92a..cdc9b36 100644 --- a/app/views/nodes/edit.html.erb +++ b/app/views/nodes/edit.html.erb | |||
| @@ -1,3 +1,21 @@ | |||
| 1 | <h1><%= title_for_node(@node) %></h1> | ||
| 2 | |||
| 3 | <div class="node_action_bar"> | ||
| 4 | <%= button_to 'Unlock + Back', unlock_node_path(@node), method: :put, | ||
| 5 | form: { class: 'button_to state_changing' }, | ||
| 6 | disabled: @node.autosave.present? %> | ||
| 7 | |||
| 8 | <% if @node.autosave || (@node.draft && @node.head) %> | ||
| 9 | <%= button_to (@node.draft && !@node.autosave ? 'Destroy Draft' : 'Discard changes'), | ||
| 10 | revert_node_path(@node), method: :put, | ||
| 11 | form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } %> | ||
| 12 | <% end %> | ||
| 13 | |||
| 14 | <%= submit_tag "Save Draft", form: dom_id(@node, :edit) %> | ||
| 15 | <%= submit_tag "Save + Unlock + Exit", form: dom_id(@node, :edit) %> | ||
| 16 | <%= link_to "Preview ↗", preview_page_path(@page), target: "_blank", rel: "noopener", class: "preview_link" %> | ||
| 17 | </div> | ||
| 18 | |||
| 1 | <div id="page_editor"> | 19 | <div id="page_editor"> |
| 2 | <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %> | 20 | <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %> |
| 3 | <% if @node.errors.any? %> | 21 | <% if @node.errors.any? %> |
| @@ -6,25 +24,6 @@ | |||
| 6 | </div> | 24 | </div> |
| 7 | <% end %> | 25 | <% end %> |
| 8 | 26 | ||
| 9 | <h1><%= title_for_node(@node) %></h1> | ||
| 10 | |||
| 11 | <div id="node_action_bar"> | ||
| 12 | <%= button_to 'Unlock + Back', unlock_node_path(@node), method: :put, | ||
| 13 | form: { class: 'button_to state_changing' }, | ||
| 14 | disabled: @node.autosave.present? %> | ||
| 15 | |||
| 16 | <% if @node.autosave || (@node.draft && @node.head) %> | ||
| 17 | <%= button_to (@node.draft && !@node.autosave ? 'Destroy Draft' : 'Discard changes'), | ||
| 18 | revert_node_path(@node), method: :put, | ||
| 19 | form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } %> | ||
| 20 | <% end %> | ||
| 21 | |||
| 22 | <%= link_to 'Preview', preview_page_path(@page) %> | ||
| 23 | |||
| 24 | <%= f.submit 'Save Draft' %> | ||
| 25 | <%= f.submit 'Save + Unlock + Exit' %> | ||
| 26 | </div> | ||
| 27 | |||
| 28 | <details id="metadata_details"> | 27 | <details id="metadata_details"> |
| 29 | <summary>Metadata (slug, parent, tags, template, author, images)</summary> | 28 | <summary>Metadata (slug, parent, tags, template, author, images)</summary> |
| 30 | <div id="metadata"> | 29 | <div id="metadata"> |
| @@ -102,9 +101,9 @@ | |||
| 102 | <div class="node_content"><%= d.text_area :body, :class => 'with_editor' %></div> | 101 | <div class="node_content"><%= d.text_area :body, :class => 'with_editor' %></div> |
| 103 | <% end %> | 102 | <% end %> |
| 104 | 103 | ||
| 105 | <div id="node_action_bar"> | 104 | <div class="node_action_bar node_action_bar_save"> |
| 106 | <%= f.submit 'Save Draft' %> | 105 | <%= f.submit 'Save Draft' %> |
| 107 | <%= f.submit 'Save + Unlock + Exit' %> | 106 | <%= f.submit 'Save + Unlock + Exit' %> |
| 108 | </div> | 107 | </div> |
| 109 | <% end %> | 108 | <% end %> |
| 110 | </div> | 109 | </div> |
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb index 2ab7986..036caf2 100644 --- a/app/views/nodes/show.html.erb +++ b/app/views/nodes/show.html.erb | |||
| @@ -1,11 +1,59 @@ | |||
| 1 | <% content_for :subnavigation do %> | 1 | <% locked_by_other = @node.locked? && @node.lock_owner != current_user %> |
| 2 | <%= link_to 'Edit', edit_node_path(@node), :class => "unselected" %> | ||
| 3 | <%= link_to 'Preview', preview_page_path(@page) %> | ||
| 4 | <% end %> | ||
| 5 | |||
| 6 | <div id="page_editor" class="show_node"> | 2 | <div id="page_editor" class="show_node"> |
| 7 | <h1><%= title_for_node(@node) %></h1> | 3 | <h1><%= title_for_node(@node) %></h1> |
| 8 | <div id="content"> | 4 | <div id="content"> |
| 5 | <div class="node_description">Status</div> | ||
| 6 | <div class="node_content node_info_group node_status"> | ||
| 7 | <div class="node_info_group_items"> | ||
| 8 | <div class="node_info_item"> | ||
| 9 | <span class="node_info_label">Head</span> | ||
| 10 | <%= @node.head ? "#{@node.head.title} (rev #{@node.head.revision}, #{@node.head.updated_at})" : "none — never published" %> | ||
| 11 | </div> | ||
| 12 | <div class="node_info_item"> | ||
| 13 | <span class="node_info_label">Draft</span> | ||
| 14 | <%= @node.draft ? "#{@node.draft.title} (rev #{@node.draft.revision}, saved #{@node.draft.updated_at})" : "none" %> | ||
| 15 | </div> | ||
| 16 | <div class="node_info_item"> | ||
| 17 | <span class="node_info_label">Autosave</span> | ||
| 18 | <%= @node.autosave ? "#{@node.autosave.title} (unsaved, #{@node.autosave.updated_at})" : "none" %> | ||
| 19 | </div> | ||
| 20 | </div> | ||
| 21 | |||
| 22 | <% edit_label = @node.autosave ? "Continue Editing" : (@node.draft ? "Edit Draft" : "Edit") %> | ||
| 23 | <div class="node_info_group_items"> | ||
| 24 | <div class="node_info_item"> | ||
| 25 | <% if locked_by_other %> | ||
| 26 | <span class="disabled_action"><%= edit_label %></span> | ||
| 27 | <% else %> | ||
| 28 | <%= link_to (@node.autosave ? "Continue Editing" : (@node.draft ? "Edit Draft" : "Lock + Edit")), edit_node_path(@node), class: "action_button" %> | ||
| 29 | <% if !@node.draft && !@node.autosave %> | ||
| 30 | <span class="field_hint">Nothing pending — this will start a fresh draft.</span> | ||
| 31 | <% end %> | ||
| 32 | <% end %> | ||
| 33 | </div> | ||
| 34 | |||
| 35 | <% unless locked_by_other %> | ||
| 36 | <% if @node.draft && !@node.autosave %> | ||
| 37 | <div class="node_info_item"> | ||
| 38 | <%= button_to 'Publish', publish_node_path(@node), method: :put, | ||
| 39 | form: { data: { confirm: "Publish this draft?" }, class: 'button_to state_changing' } %> | ||
| 40 | </div> | ||
| 41 | <% end %> | ||
| 42 | <% if @node.draft || @node.autosave %> | ||
| 43 | <div class="node_info_item"> | ||
| 44 | <%= button_to (@node.draft && !@node.autosave ? 'Destroy Draft' : 'Discard changes'), | ||
| 45 | revert_node_path(@node), method: :put, | ||
| 46 | form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } %> | ||
| 47 | </div> | ||
| 48 | <% end %> | ||
| 49 | <% end %> | ||
| 50 | </div> | ||
| 51 | |||
| 52 | <% if locked_by_other %> | ||
| 53 | <span class="field_hint">Locked — see People below to unlock before editing, publishing, or discarding.</span> | ||
| 54 | <% end %> | ||
| 55 | </div> | ||
| 56 | |||
| 9 | <div class="node_description">People</div> | 57 | <div class="node_description">People</div> |
| 10 | <div class="node_content node_info_group"> | 58 | <div class="node_content node_info_group"> |
| 11 | <div class="node_info_group_items"> | 59 | <div class="node_info_group_items"> |
