From ac01156d00b24d14225c8e75979fb59bba69640d Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 4 Aug 2026 17:13:18 +0200 Subject: Tidy up headings on house keeping views - Collapse page headers into one action row with an optional hint - limit will_paginate to one row --- app/views/assets/index.html.erb | 10 +-- app/views/events/index.html.erb | 12 ++-- app/views/menu_items/index.html.erb | 10 +-- app/views/nodes/_node_list.html.erb | 8 +-- app/views/nodes/index.html.erb | 14 ++--- app/views/shared/_page_actions.html.erb | 32 ++++++++++ app/views/users/_user.html.erb | 6 +- app/views/users/index.html.erb | 18 +++--- config/initializers/will_paginate.rb | 4 ++ config/locales/de.yml | 9 ++- config/locales/en.yml | 9 ++- public/stylesheets/admin.css | 108 +++++++++++++++++++++++++++++--- 12 files changed, 177 insertions(+), 63 deletions(-) create mode 100644 app/views/shared/_page_actions.html.erb create mode 100644 config/initializers/will_paginate.rb diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb index 81d2686a..af11f54f 100644 --- a/app/views/assets/index.html.erb +++ b/app/views/assets/index.html.erb @@ -1,8 +1,8 @@ -

<%= t(".title") %>

- -<%= link_to new_asset_path, class: 'action_button' do %> - <%= icon("plus", library: "tabler", "aria-hidden": true) %> <%= t(".create_asset") %> -<% end %> +<%= render "shared/page_actions", + :title => t(".title"), + :icon_name => "photo-plus", + :label => t(".create_asset"), + :options => [[t(".create_asset"), new_asset_path]] %> <%= will_paginate @assets %> diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index cc3f163d..c4f0a7f9 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,10 +1,8 @@ -

<%= t(".title") %>

- -
- <%= link_to new_event_path, class: 'action_button' do %> - <%= icon("plus", library: "tabler", "aria-hidden": true) %> <%= t(".create_event") %> - <% end %> -
+<%= render "shared/page_actions", + :title => t(".title"), + :icon_name => "calendar-plus", + :label => t(".create_event"), + :options => [[t(".create_event"), new_event_path]] %> <%= will_paginate @events %> diff --git a/app/views/menu_items/index.html.erb b/app/views/menu_items/index.html.erb index 0eacc34a..b1c235da 100644 --- a/app/views/menu_items/index.html.erb +++ b/app/views/menu_items/index.html.erb @@ -1,8 +1,8 @@ -

<%= t(".title") %>

- -<%= link_to new_menu_item_path, class: 'action_button' do %> - <%= icon("plus", library: "tabler", "aria-hidden": true) %> <%= t(".create_item") %> -<% end %> +<%= render "shared/page_actions", + :title => t(".title"), + :icon_name => "list-details", + :label => t(".create_item"), + :options => [[t(".create_item"), new_menu_item_path]] %>

<%= t(".reorder_hint") %>

diff --git a/app/views/nodes/_node_list.html.erb b/app/views/nodes/_node_list.html.erb index 458ab1ae..f3101058 100644 --- a/app/views/nodes/_node_list.html.erb +++ b/app/views/nodes/_node_list.html.erb @@ -14,11 +14,6 @@ <%= will_paginate @nodes %> - - - - - <% @nodes.each do |node| %> "> - <% end %>
<%= t("admin.columns.title") %><%= t("admin.columns.actions") %><%= t("admin.columns.rev") %>
@@ -30,7 +25,7 @@ t(".flag_embargo", :date => admin_datetime(node.head.published_at)), :tier => :attention) if node.embargoed? %> <%= flag("file-pencil", t(".flag_draft")) if node.draft %> - <%= flag("file-off", t(".flag_no_head")) unless node.head %> + <%= flag("world-off", t(".flag_no_head")) unless node.head %>
<%= link_to title_for_node(node), node_path(node) %>
@@ -54,7 +49,6 @@
<%= node.head ? node.head.revision : t(".no_revision") %>
diff --git a/app/views/nodes/index.html.erb b/app/views/nodes/index.html.erb index 357c938b..b88eca06 100644 --- a/app/views/nodes/index.html.erb +++ b/app/views/nodes/index.html.erb @@ -1,10 +1,8 @@ -

<%= t(".title") %>

- -
- <%= link_to new_node_path, class: 'action_button' do %> - <%= icon("plus", library: "tabler", "aria-hidden": true) %> <%= t(".create_node") %> - <% end %> - <%= t(".create_hint") %> -
+<%= render "shared/page_actions", + :title => t(".title"), + :icon_name => "file-plus", + :label => t(".create_node"), + :options => [[t(".create_node"), new_node_path]], + :hint => t(".create_hint") %> <%= render 'node_list' %> diff --git a/app/views/shared/_page_actions.html.erb b/app/views/shared/_page_actions.html.erb new file mode 100644 index 00000000..66aeb785 --- /dev/null +++ b/app/views/shared/_page_actions.html.erb @@ -0,0 +1,32 @@ +
+

<%= title %>

+ + <% if options.size == 1 %> + <%= link_to options.first.last, class: "action_button", + "aria-label" => options.first.first, title: options.first.first do %> + <%= icon(icon_name, library: "tabler", "aria-hidden": true) %> + <% end %> + <% else %> +
+
+ + <%= icon(icon_name, library: "tabler", "aria-hidden": true) %> + <%= icon("chevron-down", library: "tabler", "aria-hidden": true) %> + +
+ <% options.each do |option_label, path| %> + <%= link_to option_label, path, class: "action_button" %> + <% end %> +
+
+ + <% if local_assigns[:hint].present? %> +
+ " + title="<%= t("admin.common.explain") %>">? +

<%= hint %>

+
+ <% end %> +
+ <% end %> +
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb index 028ee02f..e70c7032 100644 --- a/app/views/users/_user.html.erb +++ b/app/views/users/_user.html.erb @@ -79,7 +79,7 @@ form: { data: { confirm: t(".confirm_revoke_redaktion", :login => user.login) }, class: 'button_to destructive' }, "aria-label" => t(".revoke_redaktion"), title: t(".revoke_redaktion") do %> - <%= icon("user-minus", library: "tabler", "aria-hidden": true) %> + <%= icon("users-minus", library: "tabler", "aria-hidden": true) %> <% end %> <% end %> <% elsif user.otp_enrolled? %> @@ -87,13 +87,13 @@ form: { data: { confirm: t(".confirm_grant_redaktion", :login => user.login) }, class: 'button_to state_changing' }, "aria-label" => t(".grant_redaktion"), title: t(".grant_redaktion") do %> - <%= icon("user-plus", library: "tabler", "aria-hidden": true) %> + <%= icon("users-plus", library: "tabler", "aria-hidden": true) %> <% end %> <% else %> <% end %> <% end %> diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 2936bbea..71102c2c 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,14 +1,10 @@ -

<%= t(".title") %>

- -

- <% UsersController::ROLE_PRESETS.each_key do |preset| %> - <%= link_to new_user_path(:preset => preset), class: 'action_button' do %> - <%= icon("plus", library: "tabler", "aria-hidden": true) %> - <%= t(".create_#{preset}") %> - <% end %> - <% end %> -

-

<%= t(".admin_hint") %>

+<%= render "shared/page_actions", + :title => t(".title"), + :icon_name => "user-plus", + :label => t(".create_account"), + :options => UsersController::ROLE_PRESETS.each_key.map { |preset| + [t(".create_#{preset}"), new_user_path(:preset => preset)] }, + :hint => t(".admin_hint") %> <% UsersController::GROUP_ORDER.each do |group| %> <% members = @users[group] || [] %> diff --git a/config/initializers/will_paginate.rb b/config/initializers/will_paginate.rb new file mode 100644 index 00000000..55c6d6e6 --- /dev/null +++ b/config/initializers/will_paginate.rb @@ -0,0 +1,4 @@ +Rails.application.config.to_prepare do + WillPaginate::ViewHelpers.pagination_options[:inner_window] = 1 + WillPaginate::ViewHelpers.pagination_options[:outer_window] = 0 +end diff --git a/config/locales/de.yml b/config/locales/de.yml index 6f8dd24a..a4181b9b 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -76,9 +76,9 @@ de: skip_last_comma: true will_paginate: - previous_label: "← Zurück" + previous_label: "←" previous_aria_label: "Vorherige Seite" - next_label: "Weiter →" + next_label: "→" next_aria_label: "Nächste Seite" page_gap: "…" container_aria_label: "Seitennavigation" @@ -337,6 +337,7 @@ de: action_log: "Letzte Änderungen dieses Kontos" index: title: "Benutzerkonten" + create_account: "Konto anlegen" create_editor: "Editor-Konto anlegen" create_redaktion: "Redaktions-Konto anlegen" create_admin: "Admin-Konto anlegen" @@ -374,14 +375,12 @@ de: toggle_preview: "Live-Vorschau umschalten" force_render: "Vorschau neu rendern" revisions: "Revisionen" + explain: "Was macht das?" "yes": "ja" "no": "nein" columns: - id: "ID" title: "Titel" - actions: "Aktionen" locked_by: "Gesperrt von" - rev: "Rev." path: "Pfad" preview: "Vorschau" name: "Name" diff --git a/config/locales/en.yml b/config/locales/en.yml index c7a728ab..4cf7f61f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -27,9 +27,9 @@ en: ccc_date: "%d %B, %Y" will_paginate: - previous_label: "← Previous" + previous_label: "←" previous_aria_label: "Previous page" - next_label: "Next →" + next_label: "→" next_aria_label: "Next page" page_gap: "…" container_aria_label: "Pagination" @@ -285,6 +285,7 @@ en: index: title: "User accounts" + create_account: "Create an account" create_editor: "Create editor account" create_redaktion: "Create Redaktion account" create_admin: "Create admin account" @@ -322,14 +323,12 @@ en: toggle_preview: "Toggle live preview" force_render: "Force preview render" revisions: "revisions" + explain: "What does this do?" "yes": "yes" "no": "no" columns: - id: "ID" title: "Title" - actions: "Actions" locked_by: "Locked by" - rev: "Rev." path: "Path" preview: "Preview" name: "Name" diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 8b976599..e6f31709 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -338,7 +338,7 @@ div.pagination span.gap { justify-content: center; min-width: 1.75rem; height: 1.75rem; - padding: 0 0.4rem; + padding: 0 0.2rem; border-radius: 4px; font-style: normal; } @@ -357,6 +357,11 @@ div.pagination span.gap { color: var(--text-muted); } +div.pagination .previous_page, +div.pagination .next_page { + min-width: 2rem; +} + div.pagination .previous_page.disabled, div.pagination .next_page.disabled { color: var(--text-muted); @@ -824,11 +829,6 @@ table.revisions_table tr:hover { .node_table td.actions { width: 1px; white-space: nowrap; -} - -/* Only where the action column is last. In the node lists rev. follows it, - and the 25px gutter is a real gap between columns there. */ -.user_table td.actions { padding-right: 0; } @@ -901,6 +901,7 @@ table.revisions_table tr:hover { .flag_stack { display: inline-flex; flex-direction: column; + flex-shrink: 0; align-items: flex-start; gap: 0.25rem; vertical-align: -0.15em; @@ -917,6 +918,11 @@ table.revisions_table tr:hover { .flag_stack .flag_attention svg { color: var(--accent); } .flag_stack .flag_alert svg { color: var(--danger); } +table.node_table td { + padding-top: 0.8rem; + padding-bottom: 0.8rem; +} + .title_with_flags { display: flex; align-items: flex-start; @@ -931,9 +937,15 @@ table.revisions_table tr:hover { } .node_table .node_path { - margin-top: 0.15rem; + margin-top: 0.25rem; + font-size: 0.875rem; } +.node_table .node_path a { + color: var(--text-muted); +} + + .user_group_heading { margin-top: 1.5rem; } @@ -1516,6 +1528,88 @@ input#menu_item_title { } } +.page_actions { + display: flex; + flex-wrap: wrap; + align-items: baseline; + gap: 0.5rem; + margin-bottom: 1rem; +} + +/* Pushes the actions to the right of the heading. */ +.page_actions h1 { + margin: 0 auto 0 0; +} + +.page_action_group { + display: flex; + align-items: flex-start; + gap: 0.5rem; +} + +.action_menu { + position: relative; +} + +/* Safari renders a disclosure triangle unless both are set. */ +.action_menu > summary, +.action_hint > summary { + cursor: pointer; + list-style: none; +} + +.action_menu > summary::-webkit-details-marker, +.action_hint > summary::-webkit-details-marker { + display: none; +} + +.action_menu_items { + position: absolute; + top: 100%; + right: 0; + z-index: 1; + display: flex; + flex-direction: column; + align-items: stretch; + gap: 0.25rem; + margin-top: 0.25rem; + padding: 0.5rem; + background-color: var(--surface-raised); + border: 1px solid var(--border); + border-radius: var(--radius); +} + +.action_hint > summary { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.5rem; + height: 1.5rem; + border: 1px solid var(--border); + border-radius: 50%; + color: var(--text-muted); + font-weight: bold; +} + +.action_hint { + position: relative; +} + +.action_hint p { + position: absolute; + top: 100%; + right: 0; + z-index: 1; + width: max-content; + max-width: 22rem; + margin: 0.5rem 0 0; + padding: 0.5rem; + color: var(--text-muted); + background-color: var(--surface-raised); + border: 1px solid var(--border); + border-radius: var(--radius); +} + /* ============================================================ Draft list (dashboard widget) ============================================================ */ -- cgit v1.3