summaryrefslogtreecommitdiff
path: root/app
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
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')
-rw-r--r--app/views/assets/edit.html.erb18
-rw-r--r--app/views/assets/new.html.erb16
-rw-r--r--app/views/assets/show.html.erb26
-rw-r--r--app/views/elevations/new.html.erb17
-rw-r--r--app/views/events/edit.html.erb24
-rw-r--r--app/views/events/new.html.erb24
-rw-r--r--app/views/events/show.html.erb24
-rw-r--r--app/views/menu_items/_title_fields.html.erb16
-rw-r--r--app/views/menu_items/edit.html.erb30
-rw-r--r--app/views/menu_items/new.html.erb27
-rw-r--r--app/views/nodes/edit.html.erb317
-rw-r--r--app/views/nodes/new.html.erb109
-rw-r--r--app/views/nodes/show.html.erb39
-rw-r--r--app/views/otp_challenges/new.html.erb18
-rw-r--r--app/views/otp_enrollments/show.html.erb36
-rw-r--r--app/views/page_translations/edit.html.erb59
-rw-r--r--app/views/page_translations/show.html.erb38
-rw-r--r--app/views/revisions/diff.html.erb8
-rw-r--r--app/views/revisions/index.html.erb2
-rw-r--r--app/views/revisions/show.html.erb18
-rw-r--r--app/views/users/edit.html.erb106
-rw-r--r--app/views/users/new.html.erb56
-rw-r--r--app/views/users/show.html.erb24
23 files changed, 656 insertions, 396 deletions
diff --git a/app/views/assets/edit.html.erb b/app/views/assets/edit.html.erb
index 610ae20a..1e4ae8f1 100644
--- a/app/views/assets/edit.html.erb
+++ b/app/views/assets/edit.html.erb
@@ -4,15 +4,19 @@
4 <%= form_for(@asset, html: { multipart: true }) do |f| %> 4 <%= form_for(@asset, html: { multipart: true }) do |f| %>
5 <%= form_error_messages(f) %> 5 <%= form_error_messages(f) %>
6 6
7 <div id="content"> 7 <div class="layout_row">
8 <div class="layout_row_label"><%= f.label :name %></div> 8 <div class="layout_row_label"><%= f.label :name %></div>
9 <div class="layout_row_content"><%= f.text_field :name %></div> 9 <div class="layout_row_content"><%= f.text_field :name %></div>
10 </div>
10 11
11 <% if @asset.upload.present? %> 12 <% if @asset.upload.present? %>
13 <div class="layout_row">
12 <div class="layout_row_label"><%= t(".current_file") %></div> 14 <div class="layout_row_label"><%= t(".current_file") %></div>
13 <div class="layout_row_content"><%= @asset.upload.url %> (<%= number_to_human_size(@asset.upload.size) %>)</div> 15 <div class="layout_row_content"><%= @asset.upload.url %> (<%= number_to_human_size(@asset.upload.size) %>)</div>
14 <% end %> 16 </div>
17 <% end %>
15 18
19 <div class="layout_row">
16 <div class="layout_row_label"><%= f.label :upload, t(".replace_file") %></div> 20 <div class="layout_row_label"><%= f.label :upload, t(".replace_file") %></div>
17 <div class="layout_row_content"> 21 <div class="layout_row_content">
18 <div id="asset_dropzone"> 22 <div id="asset_dropzone">
@@ -20,13 +24,19 @@
20 <p class="field_hint"><%= t("assets.form.drop_hint") %></p> 24 <p class="field_hint"><%= t("assets.form.drop_hint") %></p>
21 </div> 25 </div>
22 </div> 26 </div>
27 </div>
23 28
29 <div class="layout_row">
24 <div class="layout_row_label"><%= f.label :creator %></div> 30 <div class="layout_row_label"><%= f.label :creator %></div>
25 <div class="layout_row_content"><%= f.text_field :creator %></div> 31 <div class="layout_row_content"><%= f.text_field :creator %></div>
32 </div>
26 33
34 <div class="layout_row">
27 <div class="layout_row_label"><%= f.label :source_url %></div> 35 <div class="layout_row_label"><%= f.label :source_url %></div>
28 <div class="layout_row_content"><%= f.text_field :source_url %></div> 36 <div class="layout_row_content"><%= f.text_field :source_url %></div>
37 </div>
29 38
39 <div class="layout_row">
30 <div class="layout_row_label"><%= f.label :license_key %></div> 40 <div class="layout_row_label"><%= f.label :license_key %></div>
31 <div class="layout_row_content"> 41 <div class="layout_row_content">
32 <%= f.select :license_key, 42 <%= f.select :license_key,
@@ -35,7 +45,9 @@
35 @asset.license_key 45 @asset.license_key
36 ) %> 46 ) %>
37 </div> 47 </div>
48 </div>
38 49
50 <div class="layout_row">
39 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 51 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
40 <div class="layout_row_content info_group"> 52 <div class="layout_row_content info_group">
41 <div class="info_group_items"> 53 <div class="info_group_items">
diff --git a/app/views/assets/new.html.erb b/app/views/assets/new.html.erb
index d3a66524..1260644f 100644
--- a/app/views/assets/new.html.erb
+++ b/app/views/assets/new.html.erb
@@ -4,10 +4,12 @@
4 <%= form_for(@asset, :html => { :multipart => true }) do |f| %> 4 <%= form_for(@asset, :html => { :multipart => true }) do |f| %>
5 <%= form_error_messages(f) %> 5 <%= form_error_messages(f) %>
6 6
7 <div id="content"> 7 <div class="layout_row">
8 <div class="layout_row_label"><%= f.label :name %></div> 8 <div class="layout_row_label"><%= f.label :name %></div>
9 <div class="layout_row_content"><%= f.text_field :name %></div> 9 <div class="layout_row_content"><%= f.text_field :name %></div>
10 </div>
10 11
12 <div class="layout_row">
11 <div class="layout_row_label"><%= f.label :upload %></div> 13 <div class="layout_row_label"><%= f.label :upload %></div>
12 <div class="layout_row_content"> 14 <div class="layout_row_content">
13 <div id="asset_dropzone"> 15 <div id="asset_dropzone">
@@ -15,13 +17,19 @@
15 <p class="field_hint"><%= t("assets.form.drop_hint") %></p> 17 <p class="field_hint"><%= t("assets.form.drop_hint") %></p>
16 </div> 18 </div>
17 </div> 19 </div>
20 </div>
18 21
22 <div class="layout_row">
19 <div class="layout_row_label"><%= f.label :creator %></div> 23 <div class="layout_row_label"><%= f.label :creator %></div>
20 <div class="layout_row_content"><%= f.text_field :creator %></div> 24 <div class="layout_row_content"><%= f.text_field :creator %></div>
25 </div>
21 26
27 <div class="layout_row">
22 <div class="layout_row_label"><%= f.label :source_url %></div> 28 <div class="layout_row_label"><%= f.label :source_url %></div>
23 <div class="layout_row_content"><%= f.text_field :source_url %></div> 29 <div class="layout_row_content"><%= f.text_field :source_url %></div>
30 </div>
24 31
32 <div class="layout_row">
25 <div class="layout_row_label"><%= f.label :license_key %></div> 33 <div class="layout_row_label"><%= f.label :license_key %></div>
26 <div class="layout_row_content"> 34 <div class="layout_row_content">
27 <%= f.select :license_key, 35 <%= f.select :license_key,
@@ -30,7 +38,9 @@
30 @asset.license_key 38 @asset.license_key
31 ) %> 39 ) %>
32 </div> 40 </div>
41 </div>
33 42
43 <div class="layout_row">
34 <div class="layout_row_label"><%= t("assets.form.attach_to_page") %></div> 44 <div class="layout_row_label"><%= t("assets.form.attach_to_page") %></div>
35 <div class="layout_row_content"> 45 <div class="layout_row_content">
36 <div class="restore_picker"> 46 <div class="restore_picker">
@@ -41,13 +51,17 @@
41 <%= hidden_field_tag :node_id, @attach_node&.id %> 51 <%= hidden_field_tag :node_id, @attach_node&.id %>
42 <span class="field_hint"><%= t("assets.form.attach_hint") %></span> 52 <span class="field_hint"><%= t("assets.form.attach_hint") %></span>
43 </div> 53 </div>
54 </div>
44 55
56 <div class="layout_row">
45 <div class="layout_row_label"></div> 57 <div class="layout_row_label"></div>
46 <div class="layout_row_content"> 58 <div class="layout_row_content">
47 <label><%= check_box_tag :headline, "1" %> <%= t("assets.form.as_headline") %></label> 59 <label><%= check_box_tag :headline, "1" %> <%= t("assets.form.as_headline") %></label>
48 <span class="field_hint"><%= t("assets.form.headline_hint") %></span> 60 <span class="field_hint"><%= t("assets.form.headline_hint") %></span>
49 </div> 61 </div>
62 </div>
50 63
64 <div class="layout_row">
51 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 65 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
52 <div class="layout_row_content info_group"> 66 <div class="layout_row_content info_group">
53 <div class="info_group_items"> 67 <div class="info_group_items">
diff --git a/app/views/assets/show.html.erb b/app/views/assets/show.html.erb
index c261e032..5c111c7b 100644
--- a/app/views/assets/show.html.erb
+++ b/app/views/assets/show.html.erb
@@ -1,7 +1,7 @@
1<div id="admin_layout"> 1<div id="admin_layout">
2 <h1><%= @asset.name %></h1> 2 <h1><%= @asset.name %></h1>
3 3
4 <div id="content"> 4 <div class="layout_row">
5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
6 <div class="layout_row_content info_group"> 6 <div class="layout_row_content info_group">
7 <div class="info_group_items"> 7 <div class="info_group_items">
@@ -35,12 +35,16 @@
35 </div> 35 </div>
36 </div> 36 </div>
37 </div> 37 </div>
38 </div>
38 39
39 <% if @asset.has_variant?(:medium) %> 40 <% if @asset.has_variant?(:medium) %>
41 <div class="layout_row">
40 <div class="layout_row_label"><%= t(".thumbnail") %></div> 42 <div class="layout_row_label"><%= t(".thumbnail") %></div>
41 <div class="layout_row_content"><%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %></div> 43 <div class="layout_row_content"><%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %></div>
42 <% end %> 44 </div>
45 <% end %>
43 46
47 <div class="layout_row">
44 <div class="layout_row_label"><%= t(".attached_to") %></div> 48 <div class="layout_row_label"><%= t(".attached_to") %></div>
45 <div class="layout_row_content"> 49 <div class="layout_row_content">
46 <% nodes = @asset.attached_nodes %> 50 <% nodes = @asset.attached_nodes %>
@@ -62,7 +66,9 @@
62 <%= t(".not_attached") %> 66 <%= t(".not_attached") %>
63 <% end %> 67 <% end %>
64 </div> 68 </div>
69 </div>
65 70
71 <div class="layout_row">
66 <div class="layout_row_label"><%= t("assets.form.attach_to_page") %></div> 72 <div class="layout_row_label"><%= t("assets.form.attach_to_page") %></div>
67 <div class="layout_row_content"> 73 <div class="layout_row_content">
68 <%= form_tag attach_to_node_asset_path(@asset), :class => "asset_attach_form" do %> 74 <%= form_tag attach_to_node_asset_path(@asset), :class => "asset_attach_form" do %>
@@ -78,14 +84,18 @@
78 <span class="field_hint"><%= t(".attach_hint") %></span> 84 <span class="field_hint"><%= t(".attach_hint") %></span>
79 <% end %> 85 <% end %>
80 </div> 86 </div>
87 </div>
81 88
89 <div class="layout_row">
82 <div class="layout_row_label"><%= t(".new_page") %></div> 90 <div class="layout_row_label"><%= t(".new_page") %></div>
83 <div class="layout_row_content"> 91 <div class="layout_row_content">
84 <%= link_to new_node_path(:asset_id => @asset.id), :class => "action_button" do %> 92 <%= link_to new_node_path(:asset_id => @asset.id), :class => "action_button" do %>
85 <%= icon("file-plus", library: "tabler", "aria-hidden": true) %> <%= t(".new_page_with_attachment") %> 93 <%= icon("file-plus", library: "tabler", "aria-hidden": true) %> <%= t(".new_page_with_attachment") %>
86 <% end %> 94 <% end %>
87 </div> 95 </div>
96 </div>
88 97
98 <div class="layout_row">
89 <div class="layout_row_label"><%= t(".public_path") %></div> 99 <div class="layout_row_label"><%= t(".public_path") %></div>
90 <div class="layout_row_content"> 100 <div class="layout_row_content">
91 <% public_path = @asset.upload.url.sub(/\?\d+$/, "") %> 101 <% public_path = @asset.upload.url.sub(/\?\d+$/, "") %>
@@ -96,10 +106,14 @@
96 <span class="copy_button_label"><%= t(".copy_url") %></span> 106 <span class="copy_button_label"><%= t(".copy_url") %></span>
97 </button> 107 </button>
98 </div> 108 </div>
109 </div>
99 110
111 <div class="layout_row">
100 <div class="layout_row_label"><%= t(".creator") %></div> 112 <div class="layout_row_label"><%= t(".creator") %></div>
101 <div class="layout_row_content"><%= @asset.creator.presence || "—" %></div> 113 <div class="layout_row_content"><%= @asset.creator.presence || "—" %></div>
114 </div>
102 115
116 <div class="layout_row">
103 <div class="layout_row_label"><%= t(".source") %></div> 117 <div class="layout_row_label"><%= t(".source") %></div>
104 <div class="layout_row_content"> 118 <div class="layout_row_content">
105 <% if @asset.source_url.present? %> 119 <% if @asset.source_url.present? %>
@@ -108,7 +122,9 @@
108 — 122 —
109 <% end %> 123 <% end %>
110 </div> 124 </div>
125 </div>
111 126
127 <div class="layout_row">
112 <div class="layout_row_label"><%= t(".license") %></div> 128 <div class="layout_row_label"><%= t(".license") %></div>
113 <div class="layout_row_content"> 129 <div class="layout_row_content">
114 <% if (license = AssetLicense.find(@asset.license_key)) %> 130 <% if (license = AssetLicense.find(@asset.license_key)) %>
@@ -117,10 +133,14 @@
117 — 133 —
118 <% end %> 134 <% end %>
119 </div> 135 </div>
136 </div>
120 137
138 <div class="layout_row">
121 <div class="layout_row_label"><%= t(".content_type") %></div> 139 <div class="layout_row_label"><%= t(".content_type") %></div>
122 <div class="layout_row_content"><%= @asset.upload.content_type %></div> 140 <div class="layout_row_content"><%= @asset.upload.content_type %></div>
141 </div>
123 142
143 <div class="layout_row">
124 <div class="layout_row_label"><%= t(".size") %></div> 144 <div class="layout_row_label"><%= t(".size") %></div>
125 <div class="layout_row_content"><%= "#{@asset.upload.size/1024} KB" %></div> 145 <div class="layout_row_content"><%= "#{@asset.upload.size/1024} KB" %></div>
126 </div> 146 </div>
diff --git a/app/views/elevations/new.html.erb b/app/views/elevations/new.html.erb
index 1091ff36..084fb9e4 100644
--- a/app/views/elevations/new.html.erb
+++ b/app/views/elevations/new.html.erb
@@ -6,13 +6,18 @@
6 <%= t(".hint", :minutes => AuthenticatedSystem::ELEVATION_MAX_AGE.in_minutes.to_i) %> 6 <%= t(".hint", :minutes => AuthenticatedSystem::ELEVATION_MAX_AGE.in_minutes.to_i) %>
7 </p> 7 </p>
8 <%= form_tag elevation_path do %> 8 <%= form_tag elevation_path do %>
9 <div class="layout_row_label"><%= t(".code") %></div> 9 <div class="layout_row">
10 <div class="layout_row_content"> 10 <div class="layout_row_label"><%= t(".code") %></div>
11 <%= text_field_tag :code, nil, :autocomplete => "one-time-code", 11 <div class="layout_row_content">
12 :inputmode => "numeric", :autofocus => true %> 12 <%= text_field_tag :code, nil, :autocomplete => "one-time-code",
13 :inputmode => "numeric", :autofocus => true %>
14 </div>
15 </div>
16
17 <div class="layout_row">
18 <div class="layout_row_label"></div>
19 <div class="layout_row_content"><%= submit_tag t(".elevate") %></div>
13 </div> 20 </div>
14 <div class="layout_row_label"></div>
15 <div class="layout_row_content"><%= submit_tag t(".elevate") %></div>
16 <% end %> 21 <% end %>
17 <% else %> 22 <% else %>
18 <%# An admin without an enrolled factor cannot elevate at all. Say so and 23 <%# An admin without an enrolled factor cannot elevate at all. Say so and
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb
index f3bf5339..7c855760 100644
--- a/app/views/events/edit.html.erb
+++ b/app/views/events/edit.html.erb
@@ -1,6 +1,6 @@
1<h1><%= t(".title") %></h1> 1<h1><%= t(".title") %></h1>
2 2
3<div class="node_action_bar standalone_action_bar"> 3<div class="node_action_bar">
4 <%= link_to t("admin.common.back"), safe_return_to(params[:return_to] || events_path) %> 4 <%= link_to t("admin.common.back"), safe_return_to(params[:return_to] || events_path) %>
5 <%= button_to event_path(@event), method: :delete, 5 <%= button_to event_path(@event), method: :delete,
6 form: { data: { confirm: t("events.confirm_delete") }, class: 'button_to destructive' } do %> 6 form: { data: { confirm: t("events.confirm_delete") }, class: 'button_to destructive' } do %>
@@ -13,7 +13,7 @@
13 <%= form_error_messages(f) %> 13 <%= form_error_messages(f) %>
14 14
15 <div id="admin_layout"> 15 <div id="admin_layout">
16 <div id="content"> 16 <div class="layout_row">
17 <div class="layout_row_label"><%= Event.human_attribute_name(:node) %> </div> 17 <div class="layout_row_label"><%= Event.human_attribute_name(:node) %> </div>
18 <div class="layout_row_content"> 18 <div class="layout_row_content">
19 <% if @event.node %> 19 <% if @event.node %>
@@ -31,39 +31,59 @@
31 <% end %> 31 <% end %>
32 <%= f.hidden_field :node_id %> 32 <%= f.hidden_field :node_id %>
33 </div> 33 </div>
34 </div>
34 35
36 <div class="layout_row">
35 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div> 37 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div>
36 <div class="layout_row_content"><%= f.datetime_select :start_time %></div> 38 <div class="layout_row_content"><%= f.datetime_select :start_time %></div>
39 </div>
37 40
41 <div class="layout_row">
38 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div> 42 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div>
39 <div class="layout_row_content"><%= f.datetime_select :end_time %></div> 43 <div class="layout_row_content"><%= f.datetime_select :end_time %></div>
44 </div>
40 45
46 <div class="layout_row">
41 <div class="layout_row_label"><%= t("events.form.recurrence") %></div> 47 <div class="layout_row_label"><%= t("events.form.recurrence") %></div>
42 <div class="layout_row_content"> 48 <div class="layout_row_content">
43 <%= render "rrule_builder", f: f %> 49 <%= render "rrule_builder", f: f %>
44 </div> 50 </div>
51 </div>
45 52
53 <div class="layout_row">
46 <div class="layout_row_label"><%= Event.human_attribute_name(:title) %></div> 54 <div class="layout_row_label"><%= Event.human_attribute_name(:title) %></div>
47 <div class="layout_row_content"> 55 <div class="layout_row_content">
48 <%= f.text_field :title %> 56 <%= f.text_field :title %>
49 <span id="event_title_hint" class="field_hint"><%= t("events.form.title_hint") %></span> 57 <span id="event_title_hint" class="field_hint"><%= t("events.form.title_hint") %></span>
50 </div> 58 </div>
59 </div>
51 60
61 <div class="layout_row">
52 <div class="layout_row_label"><%= Event.human_attribute_name(:tags) %></div> 62 <div class="layout_row_label"><%= Event.human_attribute_name(:tags) %></div>
53 <div class="layout_row_content"><%= f.text_field :tag_list %></div> 63 <div class="layout_row_content"><%= f.text_field :tag_list %></div>
64 </div>
54 65
66 <div class="layout_row">
55 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div> 67 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div>
56 <div class="layout_row_content"><%= f.check_box :allday %></div> 68 <div class="layout_row_content"><%= f.check_box :allday %></div>
69 </div>
57 70
71 <div class="layout_row">
58 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div> 72 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div>
59 <div class="layout_row_content"><%= f.text_field :url %></div> 73 <div class="layout_row_content"><%= f.text_field :url %></div>
74 </div>
60 75
76 <div class="layout_row">
61 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div> 77 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div>
62 <div class="layout_row_content"><%= f.text_field :latitude %></div> 78 <div class="layout_row_content"><%= f.text_field :latitude %></div>
79 </div>
63 80
81 <div class="layout_row">
64 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div> 82 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div>
65 <div class="layout_row_content"><%= f.text_field :longitude %></div> 83 <div class="layout_row_content"><%= f.text_field :longitude %></div>
84 </div>
66 85
86 <div class="layout_row">
67 <div class="layout_row_label"></div> 87 <div class="layout_row_label"></div>
68 <div class="layout_row_content"><%= f.submit t("admin.common.update") %></div> 88 <div class="layout_row_content"><%= f.submit t("admin.common.update") %></div>
69 </div> 89 </div>
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb
index 3eaf7e7d..5cc47b69 100644
--- a/app/views/events/new.html.erb
+++ b/app/views/events/new.html.erb
@@ -6,7 +6,7 @@
6 <%= form_error_messages(f) %> 6 <%= form_error_messages(f) %>
7 7
8 <div id="admin_layout"> 8 <div id="admin_layout">
9 <div id="content"> 9 <div class="layout_row">
10 <div class="layout_row_label"><%= Event.human_attribute_name(:node) %></div> 10 <div class="layout_row_label"><%= Event.human_attribute_name(:node) %></div>
11 <div class="layout_row_content"> 11 <div class="layout_row_content">
12 <%= text_field_tag :event_node_search_term %> 12 <%= text_field_tag :event_node_search_term %>
@@ -14,40 +14,62 @@
14 <%= f.hidden_field :node_id %> 14 <%= f.hidden_field :node_id %>
15 <span class="field_hint"><%= t("events.form.node_hint") %></span> 15 <span class="field_hint"><%= t("events.form.node_hint") %></span>
16 </div> 16 </div>
17 </div>
17 18
19 <div class="layout_row">
18 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div> 20 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div>
19 <div class="layout_row_content"><%= f.datetime_select :start_time %></div> 21 <div class="layout_row_content"><%= f.datetime_select :start_time %></div>
22 </div>
20 23
24 <div class="layout_row">
21 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div> 25 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div>
22 <div class="layout_row_content"><%= f.datetime_select :end_time %></div> 26 <div class="layout_row_content"><%= f.datetime_select :end_time %></div>
27 </div>
23 28
29 <div class="layout_row">
24 <div class="layout_row_label"><%= t("events.form.recurrence") %></div> 30 <div class="layout_row_label"><%= t("events.form.recurrence") %></div>
25 <div class="layout_row_content"><%= render "rrule_builder", f: f %></div> 31 <div class="layout_row_content"><%= render "rrule_builder", f: f %></div>
32 </div>
26 33
34 <div class="layout_row">
27 <div class="layout_row_label"><%= Event.human_attribute_name(:title) %></div> 35 <div class="layout_row_label"><%= Event.human_attribute_name(:title) %></div>
28 <div class="layout_row_content"> 36 <div class="layout_row_content">
29 <%= f.text_field :title %> 37 <%= f.text_field :title %>
30 <span id="event_title_hint" class="field_hint"><%= t("events.form.title_hint") %></span> 38 <span id="event_title_hint" class="field_hint"><%= t("events.form.title_hint") %></span>
31 </div> 39 </div>
40 </div>
32 41
42 <div class="layout_row">
33 <div class="layout_row_label"><%= Event.human_attribute_name(:tag_list) %></div> 43 <div class="layout_row_label"><%= Event.human_attribute_name(:tag_list) %></div>
34 <div class="layout_row_content"><%= f.text_field :tag_list %></div> 44 <div class="layout_row_content"><%= f.text_field :tag_list %></div>
45 </div>
35 46
47 <div class="layout_row">
36 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div> 48 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div>
37 <div class="layout_row_content"><%= f.check_box :allday %></div> 49 <div class="layout_row_content"><%= f.check_box :allday %></div>
50 </div>
38 51
52 <div class="layout_row">
39 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div> 53 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div>
40 <div class="layout_row_content"><%= f.text_field :url %></div> 54 <div class="layout_row_content"><%= f.text_field :url %></div>
55 </div>
41 56
57 <div class="layout_row">
42 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div> 58 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div>
43 <div class="layout_row_content"><%= f.text_field :latitude %></div> 59 <div class="layout_row_content"><%= f.text_field :latitude %></div>
60 </div>
44 61
62 <div class="layout_row">
45 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div> 63 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div>
46 <div class="layout_row_content"><%= f.text_field :longitude %></div> 64 <div class="layout_row_content"><%= f.text_field :longitude %></div>
65 </div>
47 66
67 <div class="layout_row">
48 <div class="layout_row_label"></div> 68 <div class="layout_row_label"></div>
49 <div class="layout_row_content"><%= hidden_field_tag :return_to, params[:return_to] %></div> 69 <div class="layout_row_content"><%= hidden_field_tag :return_to, params[:return_to] %></div>
70 </div>
50 71
72 <div class="layout_row">
51 <div class="layout_row_label"></div> 73 <div class="layout_row_label"></div>
52 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div> 74 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div>
53 </div> 75 </div>
diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb
index d77f770e..2f3d315d 100644
--- a/app/views/events/show.html.erb
+++ b/app/views/events/show.html.erb
@@ -1,7 +1,7 @@
1<div id="admin_layout" class="show_node"> 1<div id="admin_layout" class="show_node">
2 <h1><%= @event.node ? t(".title_for_node", :path => @event.node.unique_name) : t(".title") %></h1> 2 <h1><%= @event.node ? t(".title_for_node", :path => @event.node.unique_name) : t(".title") %></h1>
3 3
4 <div id="content"> 4 <div class="layout_row">
5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
6 <div class="layout_row_content info_group"> 6 <div class="layout_row_content info_group">
7 <div class="info_group_items"> 7 <div class="info_group_items">
@@ -22,33 +22,51 @@
22 </div> 22 </div>
23 </div> 23 </div>
24 </div> 24 </div>
25 </div>
25 26
27 <div class="layout_row">
26 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div> 28 <div class="layout_row_label"><%= Event.human_attribute_name(:start_time) %></div>
27 <div class="layout_row_content"><%= admin_datetime(@event.start_time) %></div> 29 <div class="layout_row_content"><%= admin_datetime(@event.start_time) %></div>
30 </div>
28 31
32 <div class="layout_row">
29 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div> 33 <div class="layout_row_label"><%= Event.human_attribute_name(:end_time) %></div>
30 <div class="layout_row_content"><%= admin_datetime(@event.end_time) %></div> 34 <div class="layout_row_content"><%= admin_datetime(@event.end_time) %></div>
35 </div>
31 36
37 <div class="layout_row">
32 <div class="layout_row_label"><%= Event.human_attribute_name(:rrule) %></div> 38 <div class="layout_row_label"><%= Event.human_attribute_name(:rrule) %></div>
33 <div class="layout_row_content"><%=h @event.rrule %></div> 39 <div class="layout_row_content"><%=h @event.rrule %></div>
40 </div>
34 41
35 <% if (human = @event.humanize_rrule(I18n.locale)) %> 42 <% if (human = @event.humanize_rrule(I18n.locale)) %>
43 <div class="layout_row">
36 <div class="layout_row_label"><%= t(".recurrence") %></div> 44 <div class="layout_row_label"><%= t(".recurrence") %></div>
37 <div class="layout_row_content"><em><%= human %></em></div> 45 <div class="layout_row_content"><em><%= human %></em></div>
38 <% end %> 46 </div>
47 <% end %>
39 48
49 <div class="layout_row">
40 <div class="layout_row_label"><%= Event.human_attribute_name(:tag_list) %></div> 50 <div class="layout_row_label"><%= Event.human_attribute_name(:tag_list) %></div>
41 <div class="layout_row_content"><%=h @event.tag_list %></div> 51 <div class="layout_row_content"><%=h @event.tag_list %></div>
52 </div>
42 53
54 <div class="layout_row">
43 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div> 55 <div class="layout_row_label"><%= Event.human_attribute_name(:allday) %></div>
44 <div class="layout_row_content"><%= @event.allday ? t("admin.common.yes") : t("admin.common.no") %></div> 56 <div class="layout_row_content"><%= @event.allday ? t("admin.common.yes") : t("admin.common.no") %></div>
57 </div>
45 58
59 <div class="layout_row">
46 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div> 60 <div class="layout_row_label"><%= Event.human_attribute_name(:url) %></div>
47 <div class="layout_row_content"><%=h @event.url %></div> 61 <div class="layout_row_content"><%=h @event.url %></div>
62 </div>
48 63
64 <div class="layout_row">
49 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div> 65 <div class="layout_row_label"><%= Event.human_attribute_name(:latitude) %></div>
50 <div class="layout_row_content"><%=h @event.latitude %></div> 66 <div class="layout_row_content"><%=h @event.latitude %></div>
67 </div>
51 68
69 <div class="layout_row">
52 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div> 70 <div class="layout_row_label"><%= Event.human_attribute_name(:longitude) %></div>
53 <div class="layout_row_content"><%=h @event.longitude %></div> 71 <div class="layout_row_content"><%=h @event.longitude %></div>
54 </div> 72 </div>
diff --git a/app/views/menu_items/_title_fields.html.erb b/app/views/menu_items/_title_fields.html.erb
index 81ec4ad6..daf449cf 100644
--- a/app/views/menu_items/_title_fields.html.erb
+++ b/app/views/menu_items/_title_fields.html.erb
@@ -1,10 +1,12 @@
1<% (I18n.available_locales - [:root]).each do |locale| %> 1<% (I18n.available_locales - [:root]).each do |locale| %>
2 <div class="layout_row_label"> 2 <div class="layout_row">
3 <%= MenuItem.human_attribute_name(:title) %> <%= locale.to_s.upcase %> 3 <div class="layout_row_label">
4 </div> 4 <%= MenuItem.human_attribute_name(:title) %> <%= locale.to_s.upcase %>
5 <div class="layout_row_content"> 5 </div>
6 <%= text_field_tag "menu_item[titles][#{locale}]", 6 <div class="layout_row_content">
7 menu_item.translations.find_by(:locale => locale)&.title, 7 <%= text_field_tag "menu_item[titles][#{locale}]",
8 :placeholder => (locale == I18n.default_locale ? nil : t(".falls_back")) %> 8 menu_item.translations.find_by(:locale => locale)&.title,
9 :placeholder => (locale == I18n.default_locale ? nil : t(".falls_back")) %>
10 </div>
9 </div> 11 </div>
10<% end %> 12<% end %>
diff --git a/app/views/menu_items/edit.html.erb b/app/views/menu_items/edit.html.erb
index 2bd65575..92e358d6 100644
--- a/app/views/menu_items/edit.html.erb
+++ b/app/views/menu_items/edit.html.erb
@@ -2,23 +2,29 @@
2 2
3<div id="admin_layout"> 3<div id="admin_layout">
4 <%= form_for @menu_item do |f| %> 4 <%= form_for @menu_item do |f| %>
5 <div id="content"> 5 <div class="layout_row">
6 <div class="layout_row_label"><%= t("admin.common.search") %></div> 6 <div class="layout_row_label"><%= t("admin.common.search") %></div>
7 <div class="layout_row_content"> 7 <div class="layout_row_content">
8 <%= text_field_tag :menu_search_term %> 8 <%= text_field_tag :menu_search_term %>
9 <div id="menu_item_search_results" class="search_results"></div> 9 <div id="menu_item_search_results" class="search_results"></div>
10 </div>
10 </div> 11 </div>
11 12
12 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:node_id) %></div> 13 <div class="layout_row">
13 <div class="layout_row_content"><%= f.text_field :node_id %></div> 14 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:node_id) %></div>
15 <div class="layout_row_content"><%= f.text_field :node_id %></div>
16 </div>
14 17
15 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:path) %></div> 18 <div class="layout_row">
16 <div class="layout_row_content"><%= f.text_field :path %></div> 19 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:path) %></div>
20 <div class="layout_row_content"><%= f.text_field :path %></div>
21 </div>
17 22
18 <%= render "title_fields", :menu_item => @menu_item %> 23 <%= render "title_fields", :menu_item => @menu_item %>
19 24
20 <div class="layout_row_label"></div> 25 <div class="layout_row">
21 <div class="layout_row_content"><%= f.submit t("admin.common.update") %></div> 26 <div class="layout_row_label"></div>
27 <div class="layout_row_content"><%= f.submit t("admin.common.update") %></div>
28 </div>
22 <% end %> 29 <% end %>
23 </div>
24</div> 30</div>
diff --git a/app/views/menu_items/new.html.erb b/app/views/menu_items/new.html.erb
index 08872ec0..047a5a25 100644
--- a/app/views/menu_items/new.html.erb
+++ b/app/views/menu_items/new.html.erb
@@ -1,19 +1,28 @@
1<h1><%= t(".title") %></h1> 1<h1><%= t(".title") %></h1>
2 2
3<%= form_for @menu_item do |f| %> 3<%= form_for @menu_item do |f| %>
4 <div class="layout_row_label"><%= t("admin.common.search") %></div> 4 <div class="layout_row">
5 <div class="layout_row_content"> 5 <div class="layout_row_label"><%= t("admin.common.search") %></div>
6 <%= text_field_tag :menu_search_term %> 6 <div class="layout_row_content">
7 <div id="menu_item_search_results" class="search_results"></div> 7 <%= text_field_tag :menu_search_term %>
8 <div id="menu_item_search_results" class="search_results"></div>
9 </div>
8 </div> 10 </div>
9 11
10 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:node_id) %></div> 12 <div class="layout_row">
11 <div class="layout_row_content"><%= f.text_field :node_id %></div> 13 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:node_id) %></div>
14 <div class="layout_row_content"><%= f.text_field :node_id %></div>
15 </div>
12 16
13 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:path) %></div> 17 <div class="layout_row">
14 <div class="layout_row_content"><%= f.text_field :path %></div> 18 <div class="layout_row_label"><%= MenuItem.human_attribute_name(:path) %></div>
19 <div class="layout_row_content"><%= f.text_field :path %></div>
20 </div>
15 21
16 <%= render "title_fields", :menu_item => @menu_item %> 22 <%= render "title_fields", :menu_item => @menu_item %>
17 23
18 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div> 24 <div class="layout_row">
25 <div class="layout_row_label"></div>
26 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div>
27 </div>
19<% end %> 28<% end %>
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>
diff --git a/app/views/nodes/new.html.erb b/app/views/nodes/new.html.erb
index 883909a6..dd7a6051 100644
--- a/app/views/nodes/new.html.erb
+++ b/app/views/nodes/new.html.erb
@@ -9,69 +9,80 @@
9<%= form_tag nodes_path do %> 9<%= form_tag nodes_path do %>
10<div id="new_node"> 10<div id="new_node">
11 11
12 <div class="layout_row_label"><%= t(".type") %></div> 12 <div class="layout_row">
13 <div class="layout_row_content"> 13 <div class="layout_row_label"><%= t(".type") %></div>
14 <% CccConventions::NODE_KINDS.each do |kind, config| %> 14 <div class="layout_row_content">
15 <% prefix = resolve_kind_text(config[:path_prefix]) %> 15 <% CccConventions::NODE_KINDS.each do |kind, config| %>
16 <p> 16 <% prefix = resolve_kind_text(config[:path_prefix]) %>
17 <%= radio_button_tag :kind, kind, kind == @selected_kind, 17 <p>
18 data: { path_prefix: prefix } %> 18 <%= radio_button_tag :kind, kind, kind == @selected_kind,
19 <%= resolve_kind_text(config[:label]) %> 19 data: { path_prefix: prefix } %>
20 <% if config[:hint] %> 20 <%= resolve_kind_text(config[:label]) %>
21 <span class="field_hint"><%= resolve_kind_text(config[:hint]) %></span> 21 <% if config[:hint] %>
22 <% end %> 22 <span class="field_hint"><%= resolve_kind_text(config[:hint]) %></span>
23 <% unless current_user.may_change_live_at?(prefix) %> 23 <% end %>
24 <span class="field_hint restricted_kind_hint"><%= t(".restricted_kind") %></span> 24 <% unless current_user.may_change_live_at?(prefix) %>
25 <% end %> 25 <span class="field_hint restricted_kind_hint"><%= t(".restricted_kind") %></span>
26 </p> 26 <% end %>
27 <% end %> 27 </p>
28 <% end %>
29 </div>
28 </div> 30 </div>
29 31
30 <div class="layout_row_label"><%= t("admin.columns.title") %></div> 32 <div class="layout_row">
31 <div class="layout_row_content"> 33 <div class="layout_row_label"><%= t("admin.columns.title") %></div>
32 <%= text_field_tag :title, nil, required: true %> 34 <div class="layout_row_content">
33 <span class="field_hint"><%= t(".slug_hint") %></span> 35 <%= text_field_tag :title, nil, required: true %>
36 <span class="field_hint"><%= t(".slug_hint") %></span>
37 </div>
34 </div> 38 </div>
35 39
36 <div id="parent_search_field" style="<%= @selected_kind == "generic" ? "" : "display: none;" %>"> 40 <div id="parent_search_field" style="<%= @selected_kind == "generic" ? "" : "display: none;" %>">
37 <div class="layout_row_label"><%= t(".parent") %></div> 41 <div class="layout_row">
38 <div class="layout_row_content"> 42 <div class="layout_row_label"><%= t(".parent") %></div>
39 <%= text_field_tag :parent_search_term, @parent&.title %> 43 <div class="layout_row_content">
40 <%= hidden_field_tag :parent_id, @parent&.id, data: { unique_name: @parent&.computed_unique_name } %> 44 <%= text_field_tag :parent_search_term, @parent&.title %>
41 <div id="parent_search_results" class="search_results"></div> 45 <%= hidden_field_tag :parent_id, @parent&.id, data: { unique_name: @parent&.computed_unique_name } %>
46 <div id="parent_search_results" class="search_results"></div>
47 </div>
42 </div> 48 </div>
43 </div> 49 </div>
44 50
45 <div class="layout_row_label"><%= t(".resulting_path") %></div> 51 <div class="layout_row">
46 <div class="layout_row_content"> 52 <div class="layout_row_label"><%= t(".resulting_path") %></div>
47 <span id="resulting_path">—</span> 53 <div class="layout_row_content">
48 <button type="button" id="copy_resulting_path" class="unselected copy_button" data-copy-target="#resulting_path"> 54 <span id="resulting_path">—</span>
49 <span class="copy_button_label"><%= t(".copy") %></span> 55 <button type="button" id="copy_resulting_path" class="unselected copy_button" data-copy-target="#resulting_path">
50 </button> 56 <span class="copy_button_label"><%= t(".copy") %></span>
57 </button>
51 58
52 <span class="field_hint"><%= t(".path_hint") %></span> 59 <span class="field_hint"><%= t(".path_hint") %></span>
60 </div>
53 </div> 61 </div>
54 62
55 <% if @attach_asset %> 63 <% if @attach_asset %>
56 <div class="layout_row_label"><%= t(".attachment") %></div> 64 <div class="layout_row">
57 <div class="layout_row_content"> 65 <div class="layout_row_label"><%= t(".attachment") %></div>
58 <ul class="thumbnail_list"> 66 <div class="layout_row_content">
59 <li> 67 <ul class="thumbnail_list">
60 <% if @attach_asset.has_variant?(:thumb) %> 68 <li>
61 <%= image_tag @attach_asset.upload.url(:thumb) %> 69 <% if @attach_asset.has_variant?(:thumb) %>
62 <% end %> 70 <%= image_tag @attach_asset.upload.url(:thumb) %>
63 <%= link_to @attach_asset.name, asset_path(@attach_asset), 71 <% end %>
64 :target => "_blank", :rel => "noopener" %> 72 <%= link_to @attach_asset.name, asset_path(@attach_asset),
65 </li> 73 :target => "_blank", :rel => "noopener" %>
66 </ul> 74 </li>
67 <span class="field_hint"><%= t(".attach_hint") %></span> 75 </ul>
68 <label><%= check_box_tag :asset_headline, "1" %> <%= t(".as_headline") %></label> 76 <span class="field_hint"><%= t(".attach_hint") %></span>
69 <%= hidden_field_tag :asset_id, @attach_asset.id %> 77 <label><%= check_box_tag :asset_headline, "1" %> <%= t(".as_headline") %></label>
78 <%= hidden_field_tag :asset_id, @attach_asset.id %>
79 </div>
70 </div> 80 </div>
71 <% end %> 81 <% end %>
72 82
73 <div class="layout_row_label"></div> 83 <div class="layout_row">
74 <div class="layout_row_content"><%= submit_tag t("admin.common.create") %></div> 84 <div class="layout_row_label"></div>
75 85 <div class="layout_row_content"><%= submit_tag t("admin.common.create") %></div>
86 </div>
76</div> 87</div>
77<% end %> 88<% end %>
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb
index a826be37..c9558ed0 100644
--- a/app/views/nodes/show.html.erb
+++ b/app/views/nodes/show.html.erb
@@ -2,7 +2,8 @@
2<% may_change_live = current_user.may_change_live?(@node) %> 2<% may_change_live = current_user.may_change_live?(@node) %>
3<div id="admin_layout" class="show_node"> 3<div id="admin_layout" class="show_node">
4 <h1><%= title_for_node(@node) %> <small>(<%= I18n.default_locale.to_s.upcase %>)</small></h1> 4 <h1><%= title_for_node(@node) %> <small>(<%= I18n.default_locale.to_s.upcase %>)</small></h1>
5 <div id="content"> 5
6 <div class="layout_row">
6 <div class="layout_row_label"><%= t(".status") %></div> 7 <div class="layout_row_label"><%= t(".status") %></div>
7 <div class="layout_row_content info_group node_status"> 8 <div class="layout_row_content info_group node_status">
8 <div class="info_group_items"> 9 <div class="info_group_items">
@@ -97,8 +98,10 @@
97 <span class="field_hint"><%= t(".restricted_hint") %></span> 98 <span class="field_hint"><%= t(".restricted_hint") %></span>
98 <% end %> 99 <% end %>
99 </div> 100 </div>
101 </div>
100 102
101 <% if @node.in_trash? %> 103 <% if @node.in_trash? %>
104 <div class="layout_row">
102 <div class="layout_row_label"><%= t(".trash") %></div> 105 <div class="layout_row_label"><%= t(".trash") %></div>
103 <div class="layout_row_content info_group"> 106 <div class="layout_row_content info_group">
104 <div class="info_group_items"> 107 <div class="info_group_items">
@@ -136,8 +139,10 @@
136 </div> 139 </div>
137 </div> 140 </div>
138 </div> 141 </div>
139 <% end %> 142 </div>
143 <% end %>
140 144
145 <div class="layout_row">
141 <div class="layout_row_label"><%= t(".translations") %></div> 146 <div class="layout_row_label"><%= t(".translations") %></div>
142 <div class="layout_row_content info_group"> 147 <div class="layout_row_content info_group">
143 <div class="info_group_items"> 148 <div class="info_group_items">
@@ -173,7 +178,9 @@
173 <% end %> 178 <% end %>
174 </div> 179 </div>
175 </div> 180 </div>
181 </div>
176 182
183 <div class="layout_row">
177 <div class="layout_row_label"><%= t(".people") %></div> 184 <div class="layout_row_label"><%= t(".people") %></div>
178 <div class="layout_row_content info_group"> 185 <div class="layout_row_content info_group">
179 <div class="info_group_items"> 186 <div class="info_group_items">
@@ -194,7 +201,9 @@
194 <% end %> 201 <% end %>
195 </div> 202 </div>
196 </div> 203 </div>
204 </div>
197 205
206 <div class="layout_row">
198 <div class="layout_row_label"><%= t(".dates") %></div> 207 <div class="layout_row_label"><%= t(".dates") %></div>
199 <div class="layout_row_content info_group"> 208 <div class="layout_row_content info_group">
200 <div class="info_group_items"> 209 <div class="info_group_items">
@@ -210,7 +219,9 @@
210 <% end %> 219 <% end %>
211 </div> 220 </div>
212 </div> 221 </div>
222 </div>
213 223
224 <div class="layout_row">
214 <div class="layout_row_label"><%= t(".links") %></div> 225 <div class="layout_row_label"><%= t(".links") %></div>
215 <div class="layout_row_content info_group"> 226 <div class="layout_row_content info_group">
216 <% 227 <%
@@ -325,7 +336,9 @@
325 <% end %> 336 <% end %>
326 </div> 337 </div>
327 </div> 338 </div>
339 </div>
328 340
341 <div class="layout_row">
329 <div class="layout_row_label"><%= t(".history") %></div> 342 <div class="layout_row_label"><%= t(".history") %></div>
330 <div class="layout_row_content info_group"> 343 <div class="layout_row_content info_group">
331 <details> 344 <details>
@@ -343,8 +356,9 @@
343 </details> 356 </details>
344 <p class="revisions_full_history_link"><%= link_to t(".revision_history"), node_revisions_path(@node) %> | <%= link_to t("node_actions.heading"), admin_log_path(:node_id => @node.id) %></p> 357 <p class="revisions_full_history_link"><%= link_to t(".revision_history"), node_revisions_path(@node) %> | <%= link_to t("node_actions.heading"), admin_log_path(:node_id => @node.id) %></p>
345 </div> 358 </div>
359 </div>
346 360
347 361 <div class="layout_row">
348 <div class="layout_row_label"><%= t(".tags") %></div> 362 <div class="layout_row_label"><%= t(".tags") %></div>
349 <div class="layout_row_content info_group"> 363 <div class="layout_row_content info_group">
350 <% if @page.tag_list.any? %> 364 <% if @page.tag_list.any? %>
@@ -357,7 +371,9 @@
357 <span class="field_hint"><%= t(".no_tags") %></span> 371 <span class="field_hint"><%= t(".no_tags") %></span>
358 <% end %> 372 <% end %>
359 </div> 373 </div>
374 </div>
360 375
376 <div class="layout_row">
361 <div class="layout_row_label"><%= t(".attachments") %></div> 377 <div class="layout_row_label"><%= t(".attachments") %></div>
362 <div class="layout_row_content info_group"> 378 <div class="layout_row_content info_group">
363 <% if @page.assets.any? %> 379 <% if @page.assets.any? %>
@@ -382,7 +398,9 @@
382 <span class="field_hint"><%= t(".attachments_hint") %></span> 398 <span class="field_hint"><%= t(".attachments_hint") %></span>
383 </p> 399 </p>
384 </div> 400 </div>
401 </div>
385 402
403 <div class="layout_row">
386 <div class="layout_row_label"><%= t(".events") %></div> 404 <div class="layout_row_label"><%= t(".events") %></div>
387 <div class="layout_row_content info_group"> 405 <div class="layout_row_content info_group">
388 <ul> 406 <ul>
@@ -401,9 +419,11 @@
401 <% end %> 419 <% end %>
402 </p> 420 </p>
403 </div> 421 </div>
422 </div>
404 423
405 <% matches = matching_node_kinds(@node) %> 424 <% matches = matching_node_kinds(@node) %>
406 <% if @node.children.any? || matches.any? %> 425 <% if @node.children.any? || matches.any? %>
426 <div class="layout_row">
407 <div class="layout_row_label"><%= t(".children") %></div> 427 <div class="layout_row_label"><%= t(".children") %></div>
408 <div class="layout_row_content info_group"> 428 <div class="layout_row_content info_group">
409 <% if @node.children.any? %> 429 <% if @node.children.any? %>
@@ -428,13 +448,16 @@
428 </p> 448 </p>
429 <% end %> 449 <% end %>
430 </div> 450 </div>
431 <% end %> 451 </div>
452 <% end %>
432 453
454 <div class="layout_row">
433 <div class="layout_row_label"><%= t(".abstract_locale", :lang => I18n.default_locale.to_s.upcase) %></div> 455 <div class="layout_row_label"><%= t(".abstract_locale", :lang => I18n.default_locale.to_s.upcase) %></div>
434 <div class="layout_row_content"><%= sanitize(@page.abstract) %></div> 456 <div class="layout_row_content"><%= sanitize(@page.abstract) %></div>
457 </div>
435 458
459 <div class="layout_row">
436 <div class="layout_row_label"><%= t(".body_locale", :lang => I18n.default_locale.to_s.upcase) %></div> 460 <div class="layout_row_label"><%= t(".body_locale", :lang => I18n.default_locale.to_s.upcase) %></div>
437 <div class="layout_row_content"><%= sanitize(@page.body) %></div> 461 <div class="layout_row_content"><%= sanitize(@page.body) %></div>
438
439 </div> 462 </div>
440</div> 463</div>
diff --git a/app/views/otp_challenges/new.html.erb b/app/views/otp_challenges/new.html.erb
index 677244c7..798fc024 100644
--- a/app/views/otp_challenges/new.html.erb
+++ b/app/views/otp_challenges/new.html.erb
@@ -1,13 +1,15 @@
1<h1><%= t(".title") %></h1> 1<h1><%= t(".title") %></h1>
2 2
3<div id="admin_layout"> 3<div id="admin_layout">
4 <div class="layout_row_label"> <%= t(".code") %> </div> 4 <div class="layout_row">
5 <div class="layout_row_content"> 5 <div class="layout_row_label"> <%= t(".code") %> </div>
6 <%= form_tag otp_challenge_path, :method => :post, :class => "otp_form" do %> 6 <div class="layout_row_content">
7 <%= text_field_tag :code, nil, :autofocus => true, 7 <%= form_tag otp_challenge_path, :method => :post, :class => "otp_form" do %>
8 :autocomplete => "one-time-code", :inputmode => "numeric" %> 8 <%= text_field_tag :code, nil, :autofocus => true,
9 <%= submit_tag t(".log_in") %> 9 :autocomplete => "one-time-code", :inputmode => "numeric" %>
10 <% end %> 10 <%= submit_tag t(".log_in") %>
11 <span class="field_hint"> <%= t(".hint") %> </span> 11 <% end %>
12 <span class="field_hint"> <%= t(".hint") %> </span>
13 </div>
12 </div> 14 </div>
13</div> 15</div>
diff --git a/app/views/otp_enrollments/show.html.erb b/app/views/otp_enrollments/show.html.erb
index 894885b0..03405d5f 100644
--- a/app/views/otp_enrollments/show.html.erb
+++ b/app/views/otp_enrollments/show.html.erb
@@ -1,25 +1,29 @@
1<h1><%= t(".title") %></h1> 1<h1><%= t(".title") %></h1>
2 2
3<div id="admin_layout"> 3<div id="admin_layout">
4 <div class="layout_row_label"><%= t(".scan") %></div> 4 <div class="layout_row">
5 <div class="layout_row_content"> 5 <div class="layout_row_label"><%= t(".scan") %></div>
6 <div class="otp_qr"> 6 <div class="layout_row_content">
7 <%= raw RQRCode::QRCode.new(current_user.pending_otp_provisioning_uri) 7 <div class="otp_qr">
8 .as_svg(:module_size => 4, :viewbox => true, 8 <%= raw RQRCode::QRCode.new(current_user.pending_otp_provisioning_uri)
9 :color => "000", :fill => "fff") %> 9 .as_svg(:module_size => 4, :viewbox => true,
10 :color => "000", :fill => "fff") %>
11 </div>
12 <span class="field_hint"><%= t(".manual_hint") %> <code><%= current_user.otp_pending_secret %></code></span>
10 </div> 13 </div>
11 <span class="field_hint"><%= t(".manual_hint") %> <code><%= current_user.otp_pending_secret %></code></span>
12 </div> 14 </div>
13 15
14 <div class="layout_row_label"><%= t(".confirm") %></div> 16 <div class="layout_row">
15 <div class="layout_row_content"> 17 <div class="layout_row_label"><%= t(".confirm") %></div>
16 <%= form_tag otp_enrollment_path, :method => :put, :class => "otp_form" do %> 18 <div class="layout_row_content">
17 <%= text_field_tag :code, nil, :autofocus => true, 19 <%= form_tag otp_enrollment_path, :method => :put, :class => "otp_form" do %>
18 :autocomplete => "one-time-code", :inputmode => "numeric" %> 20 <%= text_field_tag :code, nil, :autofocus => true,
19 <%= button_tag :type => "submit", :class => "action_button" do %> 21 :autocomplete => "one-time-code", :inputmode => "numeric" %>
20 <%= icon("shield-check", library: "tabler", "aria-hidden": true) %> <%= t(".confirm") %> 22 <%= button_tag :type => "submit", :class => "action_button" do %>
23 <%= icon("shield-check", library: "tabler", "aria-hidden": true) %> <%= t(".confirm") %>
24 <% end %>
21 <% end %> 25 <% end %>
22 <% end %> 26 <span class="field_hint"> <%= t(".app_hint", :issuer => OTP_ISSUER) %></span>
23 <span class="field_hint"> <%= t(".app_hint", :issuer => OTP_ISSUER) %></span> 27 </div>
24 </div> 28 </div>
25</div> 29</div>
diff --git a/app/views/page_translations/edit.html.erb b/app/views/page_translations/edit.html.erb
index 20ec1c9a..3a4c8659 100644
--- a/app/views/page_translations/edit.html.erb
+++ b/app/views/page_translations/edit.html.erb
@@ -2,7 +2,7 @@
2 <%= t(".editing_prefix") %> <strong><%= @locale.to_s.upcase %></strong> <%= t(".translation_of") %> <strong><%= title_for_node(@node) %></strong>. 2 <%= t(".editing_prefix") %> <strong><%= @locale.to_s.upcase %></strong> <%= t(".translation_of") %> <strong><%= title_for_node(@node) %></strong>.
3</div> 3</div>
4 4
5<p class="node_action_bar standalone_action_bar"><%= link_to t("page_translations.revision_history_link"), node_revisions_path(@node, :translation_locale => @locale) %></p> 5<p class="node_action_bar"><%= link_to t("page_translations.revision_history_link"), node_revisions_path(@node, :translation_locale => @locale) %></p>
6 6
7<p class="field_hint"> 7<p class="field_hint">
8 <%= t(".metadata_hint_prefix") %> <%= link_to t(".metadata_hint_link"), edit_node_path(@node) %>. 8 <%= t(".metadata_hint_prefix") %> <%= link_to t(".metadata_hint_link"), edit_node_path(@node) %>.
@@ -27,38 +27,45 @@
27 </li> 27 </li>
28 <% end %> 28 <% end %>
29 </ul> 29 </ul>
30
30 <%= form_with url: node_translation_path(@node, @locale), method: :patch, local: true, id: "translation_edit_form", 31 <%= form_with url: node_translation_path(@node, @locale), method: :patch, local: true, id: "translation_edit_form",
31 data: { autosave_url: autosave_node_translation_path(@node, @locale), show_url: node_path(@node) } do |f| %> 32 data: { autosave_url: autosave_node_translation_path(@node, @locale), show_url: node_path(@node) } do |f| %>
32 <div id="edit_grid"> 33 <div class="layout_row">
33 <div id="content"> 34 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div>
34 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div> 35 <div class="layout_row_content">
35 <div class="layout_row_content"> 36 <%= text_field_tag "page[title]", @translation&.title %>
36 <%= text_field_tag "page[title]", @translation&.title %> 37 </div>
37 </div> 38 </div>
38 39
39 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div> 40 <div class="layout_row">
40 <div class="layout_row_content"> 41 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div>
41 <%= text_area_tag "page[abstract]", @translation&.abstract %> 42 <div class="layout_row_content">
42 </div> 43 <%= text_area_tag "page[abstract]", @translation&.abstract %>
44 </div>
45 </div>
43 46
47 <div id="body_field">
48 <div class="layout_row">
44 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div> 49 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div>
45 <div class="body_toolbar_row"> 50 <div class="layout_row_content">
46 <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") %>"> 51 <div class="body_toolbar_row">
47 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span><%= t("nodes.edit.live_preview") %></span> 52 <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") %>">
48 </button> 53 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span><%= t("nodes.edit.live_preview") %></span>
49 <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") %>"> 54 </button>
50 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span><%= t("nodes.edit.force_refresh") %></span> 55 <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") %>">
51 </button> 56 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span><%= t("nodes.edit.force_refresh") %></span>
52 </div> 57 </button>
58 </div>
53 59
54 <div id="editor_and_preview"> 60 <div id="editor_and_preview">
55 <div class="preview_content"> 61 <div class="preview_content">
56 <div class="layout_row_content"> 62 <div class="layout_row_content">
57 <%= text_area_tag "page[body]", @translation&.body, :class => 'with_editor' %> 63 <%= text_area_tag "page[body]", @translation&.body, :class => 'with_editor' %>
64 </div>
65 </div>
66 <div id="preview_panel" style="display:none">
67 <iframe id="live_preview_iframe" title="<%= t("nodes.edit.live_preview") %>" data-src="<%= preview_page_path(@page, :locale => @locale) %>"></iframe>
58 </div> 68 </div>
59 </div>
60 <div id="preview_panel" style="display:none">
61 <iframe id="live_preview_iframe" title="<%= t("nodes.edit.live_preview") %>" data-src="<%= preview_page_path(@page, :locale => @locale) %>"></iframe>
62 </div> 69 </div>
63 </div> 70 </div>
64 </div> 71 </div>
diff --git a/app/views/page_translations/show.html.erb b/app/views/page_translations/show.html.erb
index 5f94ac38..b230c35e 100644
--- a/app/views/page_translations/show.html.erb
+++ b/app/views/page_translations/show.html.erb
@@ -1,29 +1,41 @@
1<h1><%= t(".title") %> — <%= title_for_node(@node) %></h1> 1<h1><%= t(".title") %> — <%= title_for_node(@node) %></h1>
2 2
3<p class="node_action_bar standalone_action_bar"><%= link_to t("page_translations.revision_history_link"), node_revisions_path(@node, :translation_locale => @locale) %></p> 3<p class="node_action_bar"><%= link_to t("page_translations.revision_history_link"), node_revisions_path(@node, :translation_locale => @locale) %></p>
4 4
5<div class="translation_compare"> 5<div class="translation_compare">
6 <div class="translation_compare_column"> 6 <div class="translation_compare_column">
7 <h2><%= @locale.to_s.upcase %></h2> 7 <h2><%= @locale.to_s.upcase %></h2>
8 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div> 8 <div class="layout_row">
9 <div class="layout_row_content"><%= @translation&.title %></div> 9 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div>
10 <div class="layout_row_content"><%= @translation&.title %></div>
11 </div>
10 12
11 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div> 13 <div class="layout_row">
12 <div class="layout_row_content"><%= sanitize(@translation&.abstract.to_s) %></div> 14 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div>
15 <div class="layout_row_content"><%= sanitize(@translation&.abstract.to_s) %></div>
16 </div>
13 17
14 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div> 18 <div class="layout_row">
15 <div class="layout_row_content"><%= sanitize(@translation&.body.to_s) %></div> 19 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div>
20 <div class="layout_row_content"><%= sanitize(@translation&.body.to_s) %></div>
21 </div>
16 </div> 22 </div>
17 23
18 <div class="translation_compare_column"> 24 <div class="translation_compare_column">
19 <h2><%= I18n.default_locale.to_s.upcase %> (<%= t(".default_marker") %>)</h2> 25 <h2><%= I18n.default_locale.to_s.upcase %> (<%= t(".default_marker") %>)</h2>
20 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div> 26 <div class="layout_row">
21 <div class="layout_row_content"><%= @default_translation&.title %></div> 27 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div>
28 <div class="layout_row_content"><%= @default_translation&.title %></div>
29 </div>
22 30
23 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div> 31 <div class="layout_row">
24 <div class="layout_row_content"><%= sanitize(@default_translation&.abstract.to_s) %></div> 32 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div>
33 <div class="layout_row_content"><%= sanitize(@default_translation&.abstract.to_s) %></div>
34 </div>
25 35
26 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div> 36 <div class="layout_row">
27 <div class="layout_row_content"><%= sanitize(@default_translation&.body.to_s) %></div> 37 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div>
38 <div class="layout_row_content"><%= sanitize(@default_translation&.body.to_s) %></div>
39 </div>
28 </div> 40 </div>
29</div> 41</div>
diff --git a/app/views/revisions/diff.html.erb b/app/views/revisions/diff.html.erb
index 25f5ad04..17146615 100644
--- a/app/views/revisions/diff.html.erb
+++ b/app/views/revisions/diff.html.erb
@@ -1,6 +1,6 @@
1<h1><%= t(".title") %></h1> 1<h1><%= t(".title") %></h1>
2 2
3<p class="node_action_bar standalone_action_bar"> 3<p class="node_action_bar">
4 <%= link_to t(".revisions_link"), node_revisions_path(@node) %> 4 <%= link_to t(".revisions_link"), node_revisions_path(@node) %>
5</p> 5</p>
6 6
@@ -23,7 +23,7 @@
23 <%= t(".comparing_html", :start => start_control, :end => end_control, 23 <%= t(".comparing_html", :start => start_control, :end => end_control,
24 :lang => locale_control, :view => view_control) %> 24 :lang => locale_control, :view => view_control) %>
25 </p> 25 </p>
26 <p class="node_action_bar standalone_action_bar diff_step_bar"> 26 <p class="node_action_bar diff_step_bar">
27 <% if earlier %> 27 <% if earlier %>
28 <%= link_to t(".pair_link", :from => earlier.first, :to => earlier.last), diff_node_revisions_path(@node, 28 <%= link_to t(".pair_link", :from => earlier.first, :to => earlier.last), diff_node_revisions_path(@node,
29 start_revision: earlier.first, end_revision: earlier.last, 29 start_revision: earlier.first, end_revision: earlier.last,
@@ -43,13 +43,13 @@
43<% end %> 43<% end %>
44 44
45<% unless numeric_comparison %> 45<% unless numeric_comparison %>
46 <p class="node_action_bar standalone_action_bar"> 46 <p class="node_action_bar">
47 <%= link_to t(".compare_numbered"), node_revisions_path(@node) %> 47 <%= link_to t(".compare_numbered"), node_revisions_path(@node) %>
48 </p> 48 </p>
49<% end %> 49<% end %>
50 50
51<% if @available_layer_pairs.present? %> 51<% if @available_layer_pairs.present? %>
52 <div class="node_action_bar standalone_action_bar"> 52 <div class="node_action_bar">
53 <% @available_layer_pairs.each do |pair| %> 53 <% @available_layer_pairs.each do |pair| %>
54 <% next if [params[:start_revision].to_s, params[:end_revision].to_s].sort == pair.map(&:to_s).sort %> 54 <% next if [params[:start_revision].to_s, params[:end_revision].to_s].sort == pair.map(&:to_s).sort %>
55 <%= button_to t("nodes.show.diff_layers", :from => t("nodes.show.layer_#{pair.first}"), :to => t("nodes.show.layer_#{pair.last}")), 55 <%= button_to t("nodes.show.diff_layers", :from => t("nodes.show.layer_#{pair.first}"), :to => t("nodes.show.layer_#{pair.last}")),
diff --git a/app/views/revisions/index.html.erb b/app/views/revisions/index.html.erb
index 09eac565..c913b2a9 100644
--- a/app/views/revisions/index.html.erb
+++ b/app/views/revisions/index.html.erb
@@ -1,6 +1,6 @@
1<h2><%= t(".title", :path => @node.unique_name) %></h2> 1<h2><%= t(".title", :path => @node.unique_name) %></h2>
2 2
3<p class="node_action_bar standalone_action_bar"> 3<p class="node_action_bar">
4 <%= link_to t(".back_to_node"), node_path(@node) %> 4 <%= link_to t(".back_to_node"), node_path(@node) %>
5</p> 5</p>
6 6
diff --git a/app/views/revisions/show.html.erb b/app/views/revisions/show.html.erb
index 1456a051..a898b7e6 100644
--- a/app/views/revisions/show.html.erb
+++ b/app/views/revisions/show.html.erb
@@ -2,7 +2,7 @@
2<div id="admin_layout" class="show_node"> 2<div id="admin_layout" class="show_node">
3 <h1><%= t(".title", :rev => @page.revision) %>: <%= translation&.title %> <small>(<%= @translation_locale.to_s.upcase %>)</small></h1> 3 <h1><%= t(".title", :rev => @page.revision) %>: <%= translation&.title %> <small>(<%= @translation_locale.to_s.upcase %>)</small></h1>
4 4
5 <div id="content"> 5 <div class="layout_row">
6 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 6 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
7 <div class="layout_row_content info_group"> 7 <div class="layout_row_content info_group">
8 <div class="info_group_items"> 8 <div class="info_group_items">
@@ -11,28 +11,44 @@
11 </div> 11 </div>
12 </div> 12 </div>
13 </div> 13 </div>
14 </div>
14 15
16 <div class="layout_row">
15 <div class="layout_row_label"><%= t("admin.columns.path") %></div> 17 <div class="layout_row_label"><%= t("admin.columns.path") %></div>
16 <div class="layout_row_content"><%= @page.public_link %></div> 18 <div class="layout_row_content"><%= @page.public_link %></div>
19 </div>
17 20
21 <div class="layout_row">
18 <div class="layout_row_label"><%= t("admin.columns.author") %></div> 22 <div class="layout_row_label"><%= t("admin.columns.author") %></div>
19 <div class="layout_row_content"><%= @page.user.try(:login) %></div> 23 <div class="layout_row_content"><%= @page.user.try(:login) %></div>
24 </div>
20 25
26 <div class="layout_row">
21 <div class="layout_row_label"><%= t("admin.columns.editor") %></div> 27 <div class="layout_row_label"><%= t("admin.columns.editor") %></div>
22 <div class="layout_row_content"><%= @page.editor.try(:login) %></div> 28 <div class="layout_row_content"><%= @page.editor.try(:login) %></div>
29 </div>
23 30
31 <div class="layout_row">
24 <div class="layout_row_label"><%= t("nodes.show.last_updated") %></div> 32 <div class="layout_row_label"><%= t("nodes.show.last_updated") %></div>
25 <div class="layout_row_content"><%= admin_datetime(@page.updated_at) %></div> 33 <div class="layout_row_content"><%= admin_datetime(@page.updated_at) %></div>
34 </div>
26 35
36 <div class="layout_row">
27 <div class="layout_row_label"><%= t("nodes.show.published_at") %></div> 37 <div class="layout_row_label"><%= t("nodes.show.published_at") %></div>
28 <div class="layout_row_content"><%= admin_datetime(@page.published_at) %></div> 38 <div class="layout_row_content"><%= admin_datetime(@page.published_at) %></div>
39 </div>
29 40
41 <div class="layout_row">
30 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div> 42 <div class="layout_row_label"><%= Page.human_attribute_name(:title) %></div>
31 <div class="layout_row_content"><%= translation&.title %></div> 43 <div class="layout_row_content"><%= translation&.title %></div>
44 </div>
32 45
46 <div class="layout_row">
33 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div> 47 <div class="layout_row_label"><%= Page.human_attribute_name(:abstract) %></div>
34 <div class="layout_row_content"><%= translation&.abstract %></div> 48 <div class="layout_row_content"><%= translation&.abstract %></div>
49 </div>
35 50
51 <div class="layout_row">
36 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div> 52 <div class="layout_row_label"><%= Page.human_attribute_name(:body) %></div>
37 <div class="layout_row_content"><%= raw translation&.body %></div> 53 <div class="layout_row_content"><%= raw translation&.body %></div>
38 </div> 54 </div>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index 1763394d..8a5900ce 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -8,67 +8,83 @@
8 <% end %> 8 <% end %>
9 9
10 <%= form_for @user do |f| %> 10 <%= form_for @user do |f| %>
11 <div class="layout_row_label"><%= t("users.labels.login") %></div> 11 <div class="layout_row">
12 <div class="layout_row_content"><%= f.text_field :login, :autocomplete => "username" %></div> 12 <div class="layout_row_label"><%= t("users.labels.login") %></div>
13 <div class="layout_row_content"><%= f.text_field :login, :autocomplete => "username" %></div>
14 </div>
13 15
14 <div class="layout_row_label"><%= t("users.labels.email") %></div> 16 <div class="layout_row">
15 <div class="layout_row_content"><%= f.text_field :email %></div> 17 <div class="layout_row_label"><%= t("users.labels.email") %></div>
18 <div class="layout_row_content"><%= f.text_field :email %></div>
19 </div>
16 20
17 <div class="layout_row_label"><%= t("users.labels.password") %></div> 21 <div class="layout_row">
18 <div class="layout_row_content"><%= f.password_field :password, :autocomplete => "new-password" %></div> 22 <div class="layout_row_label"><%= t("users.labels.password") %></div>
23 <div class="layout_row_content"><%= f.password_field :password, :autocomplete => "new-password" %></div>
24 </div>
19 25
20 <div class="layout_row_label"><%= t("users.labels.confirm") %></div> 26 <div class="layout_row">
21 <div class="layout_row_content"><%= f.password_field :password_confirmation, :autocomplete => "new-password" %></div> 27 <div class="layout_row_label"><%= t("users.labels.confirm") %></div>
28 <div class="layout_row_content"><%= f.password_field :password_confirmation, :autocomplete => "new-password" %></div>
29 </div>
22 30
23 <% if current_user.is_admin? %> 31 <% if current_user.is_admin? %>
24 <div class="layout_row_label"><%= t("users.labels.roles") %></div> 32 <div class="layout_row">
25 <div class="layout_row_content"> 33 <div class="layout_row_label"><%= t("users.labels.roles") %></div>
26 <% User::ROLES.each do |role| %> 34 <div class="layout_row_content">
27 <label class="role_choice"> 35 <% User::ROLES.each do |role| %>
28 <%= check_box_tag "user[roles][]", role, @user.roles.include?(role), 36 <label class="role_choice">
29 :id => "user_roles_#{role}" %> 37 <%= check_box_tag "user[roles][]", role, @user.roles.include?(role),
30 <%= t("users.roles.#{role}") %> 38 :id => "user_roles_#{role}" %>
31 <span class="field_hint"><%= t("users.role_hints.#{role}") %></span> 39 <%= t("users.roles.#{role}") %>
32 </label> 40 <span class="field_hint"><%= t("users.role_hints.#{role}") %></span>
33 <% end %> 41 </label>
34 <%= hidden_field_tag "user[roles][]", "" %> 42 <% end %>
43 <%= hidden_field_tag "user[roles][]", "" %>
44 </div>
35 </div> 45 </div>
36 <% end %> 46 <% end %>
37 47
38 <div class="layout_row_label"></div> 48 <div class="layout_row">
39 <div class="layout_row_content"><%= submit_tag t(".update") %></div> 49 <div class="layout_row_label"></div>
50 <div class="layout_row_content"><%= submit_tag t(".update") %></div>
51 </div>
40 <% end %> 52 <% end %>
41 53
42 <% if @user == current_user %> 54 <% if @user == current_user %>
43 <div class="layout_row_label"><%= t(".second_factor") %></div> 55 <div class="layout_row">
44 <div class="layout_row_content"> 56 <div class="layout_row_label"><%= t(".second_factor") %></div>
45 <% if current_user.otp_enrolled? %> 57 <div class="layout_row_content">
46 <p><%= t(".enabled") %></p> 58 <% if current_user.otp_enrolled? %>
47 <%= form_tag otp_enrollment_path, :method => :delete, :class => "otp_form" do %> 59 <p><%= t(".enabled") %></p>
48 <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password" %> 60 <%= form_tag otp_enrollment_path, :method => :delete, :class => "otp_form" do %>
49 <%= text_field_tag :code, nil, :placeholder => t(".current_code"), 61 <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password" %>
50 :autocomplete => "one-time-code", :inputmode => "numeric" %> 62 <%= text_field_tag :code, nil, :placeholder => t(".current_code"),
51 <%= button_tag :type => "submit", :class => "action_button" do %> 63 :autocomplete => "one-time-code", :inputmode => "numeric" %>
52 <%= icon("shield-off", library: "tabler", "aria-hidden": true) %> <%= t(".disable_second_factor") %> 64 <%= button_tag :type => "submit", :class => "action_button" do %>
65 <%= icon("shield-off", library: "tabler", "aria-hidden": true) %> <%= t(".disable_second_factor") %>
66 <% end %>
53 <% end %> 67 <% end %>
54 <% end %> 68 <% else %>
55 <% else %> 69 <p><%= t(".not_enrolled") %></p>
56 <p><%= t(".not_enrolled") %></p> 70 <%= form_tag otp_enrollment_path, :method => :post, :class => "otp_form" do %>
57 <%= form_tag otp_enrollment_path, :method => :post, :class => "otp_form" do %> 71 <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password"%>
58 <%= password_field_tag :current_password, nil, :placeholder => t(".current_password"), :autocomplete => "current-password"%> 72 <%= button_tag :type => "submit", :class => "action_button" do %>
59 <%= button_tag :type => "submit", :class => "action_button" do %> 73 <%= icon("shield-lock", library: "tabler", "aria-hidden": true) %> <%= t(".enable_second_factor") %>
60 <%= icon("shield-lock", library: "tabler", "aria-hidden": true) %> <%= t(".enable_second_factor") %> 74 <% end %>
61 <% end %> 75 <% end %>
62 <% end %> 76 <% end %>
63 <% end %> 77 </div>
64 </div> 78 </div>
65 <% elsif current_user.is_admin? && @user.otp_enrolled? %> 79 <% elsif current_user.is_admin? && @user.otp_enrolled? %>
66 <div class="layout_row_label"><%= t(".second_factor") %></div> 80 <div class="layout_row">
67 <div class="layout_row_content"> 81 <div class="layout_row_label"><%= t(".second_factor") %></div>
68 <%= t(".enabled") %> 82 <div class="layout_row_content">
69 <%= button_to t(".reset_second_factor"), reset_otp_user_path(@user), :method => :put, 83 <%= t(".enabled") %>
70 :form_class => "button_to destructive", 84 <%= button_to t(".reset_second_factor"), reset_otp_user_path(@user), :method => :put,
71 :form => { :data => { :confirm => t(".reset_confirm", :login => @user.login) } } %> 85 :form_class => "button_to destructive",
86 :form => { :data => { :confirm => t(".reset_confirm", :login => @user.login) } } %>
87 </div>
72 </div> 88 </div>
73 <% end %> 89 <% end %>
74</div> 90</div>
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index 8d99fd92..13a238b5 100644
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -8,34 +8,44 @@
8 8
9<div id="admin_layout"> 9<div id="admin_layout">
10 <%= form_for @user do |f| %> 10 <%= form_for @user do |f| %>
11 <div id="content"> 11 <div class="layout_row">
12 <div class="layout_row_label"><%= t("users.labels.login") %></div> 12 <div class="layout_row_label"><%= t("users.labels.login") %></div>
13 <div class="layout_row_content"><%= f.text_field :login %></div> 13 <div class="layout_row_content"><%= f.text_field :login %></div>
14 </div>
14 15
15 <div class="layout_row_label"><%= t("users.labels.email") %></div> 16 <div class="layout_row">
16 <div class="layout_row_content"><%= f.text_field :email %></div> 17 <div class="layout_row_label"><%= t("users.labels.email") %></div>
18 <div class="layout_row_content"><%= f.text_field :email %></div>
19 </div>
17 20
18 <div class="layout_row_label"><%= t("users.labels.password") %></div> 21 <div class="layout_row">
19 <div class="layout_row_content"><%= f.password_field :password %></div> 22 <div class="layout_row_label"><%= t("users.labels.password") %></div>
23 <div class="layout_row_content"><%= f.password_field :password %></div>
24 </div>
20 25
21 <div class="layout_row_label"><%= t("users.labels.confirm") %></div> 26 <div class="layout_row">
22 <div class="layout_row_content"><%= f.password_field :password_confirmation %></div> 27 <div class="layout_row_label"><%= t("users.labels.confirm") %></div>
28 <div class="layout_row_content"><%= f.password_field :password_confirmation %></div>
29 </div>
23 30
24 <div class="layout_row_label"><%= t("users.labels.roles") %></div> 31 <div class="layout_row">
25 <div class="layout_row_content"> 32 <div class="layout_row_label"><%= t("users.labels.roles") %></div>
26 <% User::ROLES.each do |role| %> 33 <div class="layout_row_content">
27 <label class="role_choice"> 34 <% User::ROLES.each do |role| %>
28 <%= check_box_tag "user[roles][]", role, @user.roles.include?(role), 35 <label class="role_choice">
29 :id => "user_roles_#{role}" %> 36 <%= check_box_tag "user[roles][]", role, @user.roles.include?(role),
30 <%= t("users.roles.#{role}") %> 37 :id => "user_roles_#{role}" %>
31 <span class="field_hint"><%= t("users.role_hints.#{role}") %></span> 38 <%= t("users.roles.#{role}") %>
32 </label> 39 <span class="field_hint"><%= t("users.role_hints.#{role}") %></span>
33 <% end %> 40 </label>
34 <%= hidden_field_tag "user[roles][]", "" %> 41 <% end %>
42 <%= hidden_field_tag "user[roles][]", "" %>
43 </div>
35 </div> 44 </div>
36 45
37 <div class="layout_row_label"></div> 46 <div class="layout_row">
38 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div> 47 <div class="layout_row_label"></div>
48 <div class="layout_row_content"><%= f.submit t("admin.common.create") %></div>
49 </div>
39 <% end %> 50 <% end %>
40 </div>
41</div> 51</div>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 2685a15b..9879e171 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -1,7 +1,7 @@
1<div id="admin_layout"> 1<div id="admin_layout">
2 <h1><%= @user.login %></h1> 2 <h1><%= @user.login %></h1>
3 3
4 <div id="content"> 4 <div class="layout_row">
5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div> 5 <div class="layout_row_label"><%= t("admin.columns.actions") %></div>
6 <div class="layout_row_content info_group"> 6 <div class="layout_row_content info_group">
7 <div class="info_group_items"> 7 <div class="info_group_items">
@@ -12,25 +12,33 @@
12 </div> 12 </div>
13 </div> 13 </div>
14 </div> 14 </div>
15 </div>
15 16
17 <div class="layout_row">
16 <div class="layout_row_label"><%= t("users.labels.login") %></div> 18 <div class="layout_row_label"><%= t("users.labels.login") %></div>
17 <div class="layout_row_content"><%= @user.login %></div> 19 <div class="layout_row_content"><%= @user.login %></div>
20 </div>
18 21
22 <div class="layout_row">
19 <div class="layout_row_label"><%= t("users.labels.email") %></div> 23 <div class="layout_row_label"><%= t("users.labels.email") %></div>
20 <div class="layout_row_content"><%= @user.email %></div> 24 <div class="layout_row_content"><%= @user.email %></div>
25 </div>
21 26
27 <div class="layout_row">
22 <div class="layout_row_label"><%= t("users.labels.roles") %></div> 28 <div class="layout_row_label"><%= t("users.labels.roles") %></div>
23 <div class="layout_row_content"> 29 <div class="layout_row_content">
24 <%= @user.roles.any? ? @user.role_labels.join(", ") : t("users.no_roles") %> 30 <%= @user.roles.any? ? @user.role_labels.join(", ") : t("users.no_roles") %>
25 </div> 31 </div>
26 </div> 32 </div>
27 33
28 <div class="layout_row_label"><%= t("users.labels.last_login") %></div> 34 <div class="layout_row">
29 <div class="layout_row_content"> 35 <div class="layout_row_label"><%= t("users.labels.last_login") %></div>
30 <% if @user.last_login_at %> 36 <div class="layout_row_content">
31 <%= admin_date(@user.last_login_at) %> 37 <% if @user.last_login_at %>
32 <% else %> 38 <%= admin_date(@user.last_login_at) %>
33 <%= t("users.never_signed_in") %> 39 <% else %>
34 <% end %> 40 <%= t("users.never_signed_in") %>
41 <% end %>
42 </div>
35 </div> 43 </div>
36</div> 44</div>