summaryrefslogtreecommitdiff
path: root/app/views/nodes/edit.html.erb
diff options
context:
space:
mode:
authorerdgeist <erdgeist@erdgeist.org>2026-08-13 01:11:29 +0200
committererdgeist <erdgeist@erdgeist.org>2026-08-13 01:11:29 +0200
commit862edbf4d5fdb9a88f84bfa1d51ab8cc83896094 (patch)
tree2b8d8082b3549f664ef6f4babff3be864af4aac8 /app/views/nodes/edit.html.erb
parenta06f35bc0085aa744aef5fe2f4c4c036338b469b (diff)
Give every admin page one horizontal gutter
by many views inside. The inner ones are gone nodes#edit's becomes #body_field, which is what #edit_grid places in its full-width row. Rows now reach into the label band themselves rather than depending on a page wrapper to do it. The label column plus its gap equals the escape, so a row's content starts at the gutter on every page; #edit_grid's rows are exempt because the grid already steps back. share one left edge. #new_node's -118px was compensating for that 10px and left the page 7px out once it went. standalone_action_bar was overridden everywhere it appeared. page_translations#edit no longer uses #edit_grid: it has no metadata column, so the two-column template pushed its abstract into the empty half. nodes#edit's lower action bar was inside #edit_grid, so it was a grid item inheriting the escape and sat 125px left of the form above it.
Diffstat (limited to 'app/views/nodes/edit.html.erb')
-rw-r--r--app/views/nodes/edit.html.erb317
1 files changed, 170 insertions, 147 deletions
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb
index 6b5a1234..d19fdd95 100644
--- a/app/views/nodes/edit.html.erb
+++ b/app/views/nodes/edit.html.erb
@@ -1,174 +1,197 @@
1<h1><%= title_for_node(@node) %></h1> 1<h1><%= title_for_node(@node) %></h1>
2 2
3<div class="node_action_bar"> 3<div id="admin_layout">
4 <%= button_to t(".unlock_back"), unlock_node_path(@node), method: :put, 4 <div class="node_action_bar">
5 form: { class: 'button_to state_changing' }, 5 <%= button_to t(".unlock_back"), unlock_node_path(@node), method: :put,
6 disabled: @node.autosave.present? %> 6 form: { class: 'button_to state_changing' },
7 disabled: @node.autosave.present? %>
7 8
8 <% if @node.autosave || (@node.draft && @node.head) %> 9 <% if @node.autosave || (@node.draft && @node.head) %>
9 <%= button_to revert_node_path(@node), method: :put, 10 <%= button_to revert_node_path(@node), method: :put,
10 form: { data: { confirm: t(".confirm_discard") }, class: 'button_to destructive' } do %> 11 form: { data: { confirm: t(".confirm_discard") }, class: 'button_to destructive' } do %>
11 <%= icon("trash", library: "tabler", "aria-hidden": true) %> 12 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
12 <%= @node.draft && !@node.autosave ? t(".destroy_draft") : t(".discard_autosave") %> 13 <%= @node.draft && !@node.autosave ? t(".destroy_draft") : t(".discard_autosave") %>
13 <% end %> 14 <% end %>
14 <% if pair = @node.available_layer_pairs.find { |p| p.include?(:autosave) } %> 15 <% if pair = @node.available_layer_pairs.find { |p| p.include?(:autosave) } %>
15 <%= button_to t(".what_changed"), 16 <%= button_to t(".what_changed"),
16 diff_node_revisions_path(@node), 17 diff_node_revisions_path(@node),
17 method: :get, 18 method: :get,
18 params: { start_revision: pair.first, end_revision: pair.last }, 19 params: { start_revision: pair.first, end_revision: pair.last },
19 form: { class: 'button_to computation' } %> 20 form: { class: 'button_to computation' } %>
21 <% end %>
20 <% end %> 22 <% end %>
21 <% end %>
22 23
23 <%= submit_tag t(".save_draft"), form: dom_id(@node, :edit) %> 24 <%= submit_tag t(".save_draft"), form: dom_id(@node, :edit) %>
24 <%= submit_tag t(".save_unlock_exit"), name: "unlock_exit", form: dom_id(@node, :edit) %> 25 <%= submit_tag t(".save_unlock_exit"), name: "unlock_exit", form: dom_id(@node, :edit) %>
25 <%= link_to t(".preview"), preview_page_path(@page), target: "_blank", rel: "noopener", class: "preview_link" %> 26 <%= link_to t(".preview"), preview_page_path(@page), target: "_blank", rel: "noopener", class: "preview_link" %>
26</div> 27 </div>
27 28
28<div id="admin_layout">
29 <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %> 29 <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %>
30 <% if @node.errors.any? %> 30 <% if @node.errors.any? %>
31 <div class="error_messages"> 31 <div class="error_messages">
32 <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul> 32 <ul><% @node.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul>
33 </div> 33 </div>
34 <% end %> 34 <% end %>
35
36 <%= fields_for @page do |d| %>
37 <div id="edit_grid">
38 35
39 <div id="main_fields"> 36 <%= fields_for @page do |d| %>
40 <div class="layout_row_label"><%= t("admin.columns.title") %></div> 37 <div id="edit_grid">
41 <div class="layout_row_content"><%= d.text_field :title %></div>
42 38
43 <div class="layout_row_label"><%= t(".abstract") %></div> 39 <div id="main_fields">
44 <div class="layout_row_content"><%= d.text_area :abstract %></div> 40 <div class="layout_row">
41 <div class="layout_row_label"><%= t("admin.columns.title") %></div>
42 <div class="layout_row_content"><%= d.text_field :title %></div>
43 </div>
45 44
46 <div class="layout_row_label"><%= t(".attachments") %></div> 45 <div class="layout_row">
47 <div class="layout_row_content"> 46 <div class="layout_row_label"><%= t(".abstract") %></div>
48 <div id="related_assets" 47 <div class="layout_row_content"><%= d.text_area :abstract %></div>
49 data-search-url="<%= search_node_related_assets_path(@node) %>" 48 </div>
50 data-create-url="<%= node_related_assets_path(@node) %>">
51 <ul id="related_asset_list" class="thumbnail_list">
52 <% @page.related_assets.includes(:asset).each do |related| %>
53 <li data-url="<%= node_related_asset_path(@node, related) %>"
54 data-asset-id="<%= related.asset.id %>"
55 data-large-url="<%= related.asset.upload.url(:large) %>"
56 data-original-url="<%= related.asset.upload.url %>"
57 data-name="<%= related.asset.name %>"
58 data-has-credit="<%= related.asset.show_credit? %>"
59 data-headline="<%= related.headline? %>"
60 class="<%= "is_headline" if related.headline? %>">
61 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span>
62 <%= image_tag related.asset.upload.url(:thumb) %>
63 <button type="button" class="related_asset_set_headline"
64 aria-pressed="<%= related.headline? %>" aria-label="<%= t('.set_headline_label') %>"
65 title="<%= t(".set_headline_title") %>">
66 <%= icon("star", library: "tabler", "aria-hidden": true) %>
67 </button>
68 <button type="button" class="related_asset_remove" aria-label="<%= t('.remove_image_label') %>">
69 <%= icon("x", library: "tabler", "aria-hidden": true) %>
70 </button>
71 </li>
72 <% end %>
73 </ul>
74 <p class="field_hint"><%= t(".headline_hint") %></p>
75 <%= text_field_tag nil, nil, id: "related_asset_search_term", placeholder: t(".attach_search_placeholder"), autocomplete: "off" %>
76 <div id="related_asset_search_results" class="search_results"></div>
77 </div>
78 </div>
79 49
80 <template id="related_asset_template"> 50 <div class="layout_row">
81 <li> 51 <div class="layout_row_label"><%= t(".attachments") %></div>
82 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span> 52 <div class="layout_row_content">
83 <img src=""> 53 <div id="related_assets"
84 <button type="button" class="related_asset_set_headline" aria-pressed="false" aria-label="<%= t('.set_headline_label') %>"> 54 data-search-url="<%= search_node_related_assets_path(@node) %>"
85 <%= icon("star", library: "tabler", "aria-hidden": true) %> 55 data-create-url="<%= node_related_assets_path(@node) %>">
86 </button> 56 <ul id="related_asset_list" class="thumbnail_list">
87 <button type="button" class="related_asset_remove" aria-label="<%= t('.remove_image_label') %>"> 57 <% @page.related_assets.includes(:asset).each do |related| %>
88 <%= icon("x", library: "tabler", "aria-hidden": true) %> 58 <li data-url="<%= node_related_asset_path(@node, related) %>"
89 </button> 59 data-asset-id="<%= related.asset.id %>"
90 </li> 60 data-large-url="<%= related.asset.upload.url(:large) %>"
91 </template> 61 data-original-url="<%= related.asset.upload.url %>"
92 </div> 62 data-name="<%= related.asset.name %>"
63 data-has-credit="<%= related.asset.show_credit? %>"
64 data-headline="<%= related.headline? %>"
65 class="<%= "is_headline" if related.headline? %>">
66 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span>
67 <%= image_tag related.asset.upload.url(:thumb) %>
68 <button type="button" class="related_asset_set_headline"
69 aria-pressed="<%= related.headline? %>" aria-label="<%= t('.set_headline_label') %>"
70 title="<%= t(".set_headline_title") %>">
71 <%= icon("star", library: "tabler", "aria-hidden": true) %>
72 </button>
73 <button type="button" class="related_asset_remove" aria-label="<%= t('.remove_image_label') %>">
74 <%= icon("x", library: "tabler", "aria-hidden": true) %>
75 </button>
76 </li>
77 <% end %>
78 </ul>
79 <p class="field_hint"><%= t(".headline_hint") %></p>
80 <%= text_field_tag nil, nil, id: "related_asset_search_term", placeholder: t(".attach_search_placeholder"), autocomplete: "off" %>
81 <div id="related_asset_search_results" class="search_results"></div>
82 </div>
83 </div>
84 </div>
93 85
94 <details id="metadata_details"> 86 <template id="related_asset_template">
95 <summary><%= t(".metadata_summary") %></summary> 87 <li>
96 <div id="metadata"> 88 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span>
97 <div class="layout_row_label"><%= t(".slug") %></div> 89 <img src="">
98 <div class="layout_row_content"> 90 <button type="button" class="related_asset_set_headline" aria-pressed="false" aria-label="<%= t('.set_headline_label') %>">
99 <%= d.text_field( 91 <%= icon("star", library: "tabler", "aria-hidden": true) %>
100 :slug, :value => @page.slug || @node.slug 92 </button>
101 ) 93 <button type="button" class="related_asset_remove" aria-label="<%= t('.remove_image_label') %>">
102 %> 94 <%= icon("x", library: "tabler", "aria-hidden": true) %>
95 </button>
96 </li>
97 </template>
103 </div> 98 </div>
104 99
105 <div class="layout_row_label"><%= t(".parent") %></div> 100 <details id="metadata_details">
106 <div class="layout_row_content"> 101 <summary><%= t(".metadata_summary") %></summary>
107 <%= text_field_tag :move_to_search_term, (Node.find_by(:id => @page.parent_node_id) || @node.parent)&.title %> 102 <div id="metadata">
108 <p class="field_hint"><%= t(".parent_hint") %></p> 103 <div class="layout_row">
109 <div id="move_to_search_results" class="search_results"></div> 104 <div class="layout_row_label"><%= t(".slug") %></div>
110 <%= d.hidden_field( 105 <div class="layout_row_content">
111 :parent_node_id, 106 <%= d.text_field(
112 :value => @page.parent_node_id || @node.parent_id 107 :slug, :value => @page.slug || @node.slug
113 ) 108 )
114 %> 109 %>
115 </div> 110 </div>
111 </div>
116 112
117 <div class="layout_row_label"><%= t(".external_url") %></div> 113 <div class="layout_row">
118 <div class="layout_row_content"> 114 <div class="layout_row_label"><%= t(".parent") %></div>
119 <%= d.text_field :external_url %> 115 <div class="layout_row_content">
120 </div> 116 <%= text_field_tag :move_to_search_term, (Node.find_by(:id => @page.parent_node_id) || @node.parent)&.title %>
117 <p class="field_hint"><%= t(".parent_hint") %></p>
118 <div id="move_to_search_results" class="search_results"></div>
119 <%= d.hidden_field(
120 :parent_node_id,
121 :value => @page.parent_node_id || @node.parent_id
122 )
123 %>
124 </div>
125 </div>
121 126
122 <div class="layout_row_label"><%= t(".tags") %></div> 127 <div class="layout_row">
123 <div class="layout_row_content"> 128 <div class="layout_row_label"><%= t(".external_url") %></div>
124 <%= text_field_tag :tag_list, @page.tag_list.join(', ') %> 129 <div class="layout_row_content">
125 <span class="field_hint"><%= t(".tags_hint") %></span> 130 <%= d.text_field :external_url %>
126 </div> 131 </div>
132 </div>
127 133
128 <div class="layout_row_label"><%= t(".publish_at") %></div> 134 <div class="layout_row">
129 <div class="layout_row_content"><%= d.datetime_select :published_at, :value => @page.published_at %></div> 135 <div class="layout_row_label"><%= t(".tags") %></div>
136 <div class="layout_row_content">
137 <%= text_field_tag :tag_list, @page.tag_list.join(', ') %>
138 <span class="field_hint"><%= t(".tags_hint") %></span>
139 </div>
140 </div>
130 141
131 <div class="layout_row_label"><%= t(".template") %></div> 142 <div class="layout_row">
132 <div class="layout_row_content"> 143 <div class="layout_row_label"><%= t(".publish_at") %></div>
133 <%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %> 144 <div class="layout_row_content"><%= d.datetime_select :published_at, :value => @page.published_at %></div>
134 <span class="field_hint"><%= t(".template_hint") %></span> 145 </div>
135 </div>
136 146
137 <div class="layout_row_label"><%= t(".author") %></div> 147 <div class="layout_row">
138 <div class="layout_row_content"> 148 <div class="layout_row_label"><%= t(".template") %></div>
139 <%= d.select :user_id, user_list, 149 <div class="layout_row_content">
140 :selected => @page.user_id || @node.draft&.user_id || @node.head&.user_id %> 150 <%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %>
141 </div> 151 <span class="field_hint"><%= t(".template_hint") %></span>
152 </div>
153 </div>
142 154
143 </div> 155 <div class="layout_row">
144 </details> 156 <div class="layout_row_label"><%= t(".author") %></div>
157 <div class="layout_row_content">
158 <%= d.select :user_id, user_list,
159 :selected => @page.user_id || @node.draft&.user_id || @node.head&.user_id %>
160 </div>
161 </div>
162 </div>
163 </details>
145 164
146 <div id="content"> 165 <div id="body_field">
147 <div class="layout_row_label"><%= t(".body") %></div> 166 <div class="layout_row">
148 <div class="body_toolbar_row"> 167 <div class="layout_row_label"><%= t(".body") %></div>
149 <button type="button" id="preview_toggle" class="view_toggle" aria-pressed="false" aria-label="<%= t('admin.common.toggle_preview') %>" title="<%= t('admin.common.toggle_preview') %>"> 168 <div class="layout_row_content">
150 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span><%= t(".live_preview") %></span> 169 <div class="body_toolbar_row">
151 </button> 170 <button type="button" id="preview_toggle" class="view_toggle" aria-pressed="false" aria-label="<%= t('admin.common.toggle_preview') %>" title="<%= t('admin.common.toggle_preview') %>">
152 <button type="button" id="preview_force_render" class="view_toggle" style="display:none" aria-label="<%= t('admin.common.force_render') %>" title="<%= t('admin.common.force_render') %>"> 171 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span><%= t(".live_preview") %></span>
153 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span><%= t(".force_refresh") %></span> 172 </button>
154 </button> 173 <button type="button" id="preview_force_render" class="view_toggle" style="display:none" aria-label="<%= t('admin.common.force_render') %>" title="<%= t('admin.common.force_render') %>">
155 </div> 174 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span><%= t(".force_refresh") %></span>
175 </button>
176 </div>
156 177
157 <div id="editor_and_preview"> 178 <div id="editor_and_preview">
158 <div class="preview_content"> 179 <div class="preview_content">
159 <div class="layout_row_content"><%= d.text_area :body, :class => 'with_editor' %></div> 180 <%= d.text_area :body, :class => 'with_editor' %>
160 </div> 181 </div>
161 <div id="preview_panel" style="display:none"> 182 <div id="preview_panel" style="display:none">
162 <iframe id="live_preview_iframe" title="<%= t('.live_preview') %>" data-src="<%= preview_page_path(@page, :locale => I18n.default_locale) %>"></iframe> 183 <iframe id="live_preview_iframe" title="<%= t('.live_preview') %>" data-src="<%= preview_page_path(@page, :locale => I18n.default_locale) %>"></iframe>
184 </div>
185 </div>
186 </div>
187 </div>
163 </div> 188 </div>
164 </div> 189 </div>
165 </div> 190 <% end %>
166 </div>
167 <% end %>
168 191
169 <div class="node_action_bar"> 192 <div class="node_action_bar">
170 <%= f.submit t(".save_draft") %> 193 <%= f.submit t(".save_draft") %>
171 <%= f.submit t(".save_unlock_exit"), name: "unlock_exit"%> 194 <%= f.submit t(".save_unlock_exit"), name: "unlock_exit"%>
172 </div> 195 </div>
173 <% end %> 196 <% end %>
174</div> 197</div>