diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 07:07:05 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-08-04 07:07:05 +0200 |
| commit | 409d71ed471703be8c56f2639a3ecb0fa387e6a7 (patch) | |
| tree | 0a7108786cb549e343d8926b232f52a191570422 | |
| parent | 974062f16169f6d07f2289564be6d72610b8770e (diff) | |
Give node lists a flag column and a shared action bar
| -rw-r--r-- | app/controllers/nodes_controller.rb | 4 | ||||
| -rw-r--r-- | app/controllers/users_controller.rb | 2 | ||||
| -rw-r--r-- | app/models/node.rb | 4 | ||||
| -rw-r--r-- | app/models/user.rb | 18 | ||||
| -rw-r--r-- | app/views/events/index.html.erb | 10 | ||||
| -rw-r--r-- | app/views/nodes/_node_list.html.erb | 40 | ||||
| -rw-r--r-- | app/views/nodes/index.html.erb | 33 | ||||
| -rw-r--r-- | app/views/users/_user.html.erb | 18 | ||||
| -rw-r--r-- | app/views/users/edit.html.erb | 4 | ||||
| -rw-r--r-- | config/locales/de.yml | 1 | ||||
| -rw-r--r-- | config/locales/en.yml | 1 | ||||
| -rw-r--r-- | public/stylesheets/admin.css | 91 | ||||
| -rw-r--r-- | test/controllers/users_controller_test.rb | 2 |
13 files changed, 104 insertions, 124 deletions
diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index ca30976f..447d596d 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb | |||
| @@ -20,9 +20,7 @@ class NodesController < ApplicationController | |||
| 20 | ] | 20 | ] |
| 21 | 21 | ||
| 22 | def index | 22 | def index |
| 23 | @nodes = Node.root.descendants.includes(:head, :draft) | 23 | @nodes = index_matching(Node.root.descendants) |
| 24 | .order('id DESC') | ||
| 25 | .paginate(:page => params[:page], :per_page => 25) | ||
| 26 | end | 24 | end |
| 27 | 25 | ||
| 28 | def new | 26 | def new |
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index b06d11fd..20355aa8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb | |||
| @@ -140,7 +140,7 @@ class UsersController < ApplicationController | |||
| 140 | 140 | ||
| 141 | def verify_status | 141 | def verify_status |
| 142 | @user ||= User.new | 142 | @user ||= User.new |
| 143 | unless @user.id == current_user.id || current_user.admin | 143 | unless @user.id == current_user.id || current_user.is_admin? |
| 144 | deny_user_access | 144 | deny_user_access |
| 145 | end | 145 | end |
| 146 | end | 146 | end |
diff --git a/app/models/node.rb b/app/models/node.rb index d6fe32ff..f8c29b48 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -648,6 +648,10 @@ class Node < ApplicationRecord | |||
| 648 | ) | 648 | ) |
| 649 | end | 649 | end |
| 650 | 650 | ||
| 651 | def embargoed? | ||
| 652 | head&.published_at.present? && head.published_at > Time.zone.now | ||
| 653 | end | ||
| 654 | |||
| 651 | # Nodes are never destroyed recursively | 655 | # Nodes are never destroyed recursively |
| 652 | # Descendants must be removed or reparented individually first. | 656 | # Descendants must be removed or reparented individually first. |
| 653 | # The Trash feature will be the ordinary path to deletion. | 657 | # The Trash feature will be the ordinary path to deletion. |
diff --git a/app/models/user.rb b/app/models/user.rb index 786f8d14..95706f86 100644 --- a/app/models/user.rb +++ b/app/models/user.rb | |||
| @@ -70,24 +70,6 @@ class User < ApplicationRecord | |||
| 70 | roles.include?("admin") | 70 | roles.include?("admin") |
| 71 | end | 71 | end |
| 72 | 72 | ||
| 73 | # Compatibility shims for the users form, which posts user[admin] as a | ||
| 74 | # checkbox. Goes away when that form learns about roles. | ||
| 75 | def admin | ||
| 76 | is_admin? | ||
| 77 | end | ||
| 78 | |||
| 79 | def admin? | ||
| 80 | is_admin? | ||
| 81 | end | ||
| 82 | |||
| 83 | def admin=(value) | ||
| 84 | if ActiveModel::Type::Boolean.new.cast(value) | ||
| 85 | self.roles = (roles | ["admin"]) | ||
| 86 | else | ||
| 87 | self.roles = (roles - ["admin"]) | ||
| 88 | end | ||
| 89 | end | ||
| 90 | |||
| 91 | def redaktion? | 73 | def redaktion? |
| 92 | roles.include?("redaktion") | 74 | roles.include?("redaktion") |
| 93 | end | 75 | end |
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index a2710c2a..cc3f163d 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb | |||
| @@ -22,10 +22,12 @@ | |||
| 22 | <% @events.each do |event| %> | 22 | <% @events.each do |event| %> |
| 23 | <tr> | 23 | <tr> |
| 24 | <td> | 24 | <td> |
| 25 | <span class="flag_stack"> | 25 | <div class="title_with_flags"> |
| 26 | <%= flag("clock-off", Event.human_attribute_name(:allday)) if event.allday %> | 26 | <span class="flag_stack"> |
| 27 | </span> | 27 | <%= flag("clock-off", Event.human_attribute_name(:allday)) if event.allday %> |
| 28 | <%= link_to event.display_title, event %> | 28 | </span> |
| 29 | <div class="title_body"><%= link_to event.display_title, event %></div> | ||
| 30 | </div> | ||
| 29 | </td> | 31 | </td> |
| 30 | <td><%= admin_datetime(event.start_time) %></td> | 32 | <td><%= admin_datetime(event.start_time) %></td> |
| 31 | <td><%= admin_datetime(event.end_time) %></td> | 33 | <td><%= admin_datetime(event.end_time) %></td> |
diff --git a/app/views/nodes/_node_list.html.erb b/app/views/nodes/_node_list.html.erb index 0dc3c5a0..458ab1ae 100644 --- a/app/views/nodes/_node_list.html.erb +++ b/app/views/nodes/_node_list.html.erb | |||
| @@ -15,26 +15,46 @@ | |||
| 15 | <%= will_paginate @nodes %> | 15 | <%= will_paginate @nodes %> |
| 16 | <table class="node_table"> | 16 | <table class="node_table"> |
| 17 | <tr class="header"> | 17 | <tr class="header"> |
| 18 | <th class="node_id"><%= t("admin.columns.id") %></th> | ||
| 19 | <th class="title"><%= t("admin.columns.title") %></th> | 18 | <th class="title"><%= t("admin.columns.title") %></th> |
| 20 | <th class="actions"><%= t("admin.columns.actions") %></th> | 19 | <th class="actions"><%= t("admin.columns.actions") %></th> |
| 21 | <th class="editor"><%= t("admin.columns.locked_by") %></th> | ||
| 22 | <th class="revision"><%= t("admin.columns.rev") %></th> | 20 | <th class="revision"><%= t("admin.columns.rev") %></th> |
| 23 | </tr> | 21 | </tr> |
| 24 | <% @nodes.each do |node| %> | 22 | <% @nodes.each do |node| %> |
| 25 | <tr class="<%= cycle("even", "odd") %>"> | 23 | <tr class="<%= cycle("even", "odd") %>"> |
| 26 | <td class="node_id"><%= node.id %></td> | ||
| 27 | <td class="title"> | 24 | <td class="title"> |
| 28 | <h4><%= link_to title_for_node(node), node_path(node) %></h4> | 25 | <div class="title_with_flags"> |
| 29 | <p><%= link_to_path(node.unique_name, node.unique_name) %></p> | 26 | <span class="flag_stack"> |
| 27 | <%= flag("lock", t(".flag_locked", :login => node.lock_owner.login), | ||
| 28 | :tier => :attention) if node.lock_owner %> | ||
| 29 | <%= flag("calendar-clock", | ||
| 30 | t(".flag_embargo", :date => admin_datetime(node.head.published_at)), | ||
| 31 | :tier => :attention) if node.embargoed? %> | ||
| 32 | <%= flag("file-pencil", t(".flag_draft")) if node.draft %> | ||
| 33 | <%= flag("file-off", t(".flag_no_head")) unless node.head %> | ||
| 34 | </span> | ||
| 35 | <div class="title_body"> | ||
| 36 | <div class="node_title"><%= link_to title_for_node(node), node_path(node) %></div> | ||
| 37 | <div class="node_path"><%= link_to_path(node.unique_name, node.unique_name) %></div> | ||
| 38 | </div> | ||
| 39 | </div> | ||
| 30 | </td> | 40 | </td> |
| 31 | <td class="actions"> | 41 | <td class="actions"> |
| 32 | <%= link_to 'show', node_path(node) %> | 42 | <div class="action_grid"> |
| 33 | <%= link_to 'edit', edit_node_path(node) %> | 43 | <span class="action_item"> |
| 34 | <%= link_to 'revisions', node_revisions_path(node) %> | 44 | <%= link_to node_path(node), "aria-label" => t("admin.common.show"), |
| 45 | title: t("admin.common.show") do %> | ||
| 46 | <%= icon("eye", library: "tabler", "aria-hidden": true) %> | ||
| 47 | <% end %> | ||
| 48 | </span> | ||
| 49 | <span class="action_item"> | ||
| 50 | <%= link_to node_revisions_path(node), "aria-label" => t("admin.common.revisions"), | ||
| 51 | title: t("admin.common.revisions") do %> | ||
| 52 | <%= icon("history", library: "tabler", "aria-hidden": true) %> | ||
| 53 | <% end %> | ||
| 54 | </span> | ||
| 55 | </div> | ||
| 35 | </td> | 56 | </td> |
| 36 | <td><%= node.lock_owner.login if node.lock_owner %></td> | 57 | <td><%= node.head ? node.head.revision : t(".no_revision") %></td> |
| 37 | <td><%= node.draft ? node.draft.revision : (node.head ? node.head.revision : t(".no_revision")) %></td> | ||
| 38 | </tr> | 58 | </tr> |
| 39 | <% end %> | 59 | <% end %> |
| 40 | </table> | 60 | </table> |
diff --git a/app/views/nodes/index.html.erb b/app/views/nodes/index.html.erb index 7ab5679e..357c938b 100644 --- a/app/views/nodes/index.html.erb +++ b/app/views/nodes/index.html.erb | |||
| @@ -7,35 +7,4 @@ | |||
| 7 | <span class="field_hint"><%= t(".create_hint") %></span> | 7 | <span class="field_hint"><%= t(".create_hint") %></span> |
| 8 | </div> | 8 | </div> |
| 9 | 9 | ||
| 10 | <%= will_paginate @nodes %> | 10 | <%= render 'node_list' %> |
| 11 | <table class="node_table"> | ||
| 12 | <tr class="header"> | ||
| 13 | <th class="node_id"><%= t("admin.columns.id") %></th> | ||
| 14 | <th class="title"><%= t("admin.columns.title") %></th> | ||
| 15 | <th class="actions"><%= t("admin.columns.actions") %></th> | ||
| 16 | <th class="editor"><%= t("admin.columns.locked_by") %></th> | ||
| 17 | <th class="revision"><%= t("admin.columns.rev") %></th> | ||
| 18 | </tr> | ||
| 19 | <% @nodes.each do |node| %> | ||
| 20 | <tr class="<%= cycle("even", "odd") %>"> | ||
| 21 | <td class="node_id"><%= node.id %></td> | ||
| 22 | <td class="title"> | ||
| 23 | <h4><%= link_to title_for_node(node), node_path(node) %></h4> | ||
| 24 | <p><%= link_to_path(node.unique_name, node.unique_name) %></p> | ||
| 25 | </td> | ||
| 26 | <td class="actions"> | ||
| 27 | <%= link_to 'show', node_path(node) %> | ||
| 28 | <%= link_to 'edit', edit_node_path(node) %> | ||
| 29 | <%= link_to 'revisions', node_revisions_path(node) %> | ||
| 30 | </td> | ||
| 31 | <td> | ||
| 32 | <%= node.lock_owner.login if node.lock_owner %> | ||
| 33 | </td> | ||
| 34 | <td> | ||
| 35 | <%= node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY") %> | ||
| 36 | </td> | ||
| 37 | </tr> | ||
| 38 | <% end %> | ||
| 39 | </table> | ||
| 40 | <%= will_paginate @nodes %> | ||
| 41 | |||
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb index be92ad1d..028ee02f 100644 --- a/app/views/users/_user.html.erb +++ b/app/views/users/_user.html.erb | |||
| @@ -27,17 +27,17 @@ | |||
| 27 | <span class="field_hint"><%= t(".no_roles") %></span> | 27 | <span class="field_hint"><%= t(".no_roles") %></span> |
| 28 | <% end %> | 28 | <% end %> |
| 29 | </td> | 29 | </td> |
| 30 | <td class="user_actions"> | 30 | <td class="actions"> |
| 31 | <div class="user_action_grid"> | 31 | <div class="action_grid"> |
| 32 | <span class="user_action"> | 32 | <span class="action_item"> |
| 33 | <%= link_to user_path(user), "aria-label" => t("admin.common.show"), | 33 | <%= link_to user_path(user), "aria-label" => t("admin.common.show"), |
| 34 | title: t("admin.common.show") do %> | 34 | title: t("admin.common.show") do %> |
| 35 | <%= icon("eye", library: "tabler", "aria-hidden": true) %> | 35 | <%= icon("eye", library: "tabler", "aria-hidden": true) %> |
| 36 | <% end %> | 36 | <% end %> |
| 37 | </span> | 37 | </span> |
| 38 | 38 | ||
| 39 | <span class="user_action"> | 39 | <span class="action_item"> |
| 40 | <% if current_user.admin? || current_user == user %> | 40 | <% if current_user.is_admin? || current_user == user %> |
| 41 | <%= link_to edit_user_path(user), "aria-label" => t("admin.common.edit"), | 41 | <%= link_to edit_user_path(user), "aria-label" => t("admin.common.edit"), |
| 42 | title: t("admin.common.edit") do %> | 42 | title: t("admin.common.edit") do %> |
| 43 | <%= icon("edit", library: "tabler", "aria-hidden": true) %> | 43 | <%= icon("edit", library: "tabler", "aria-hidden": true) %> |
| @@ -45,15 +45,15 @@ | |||
| 45 | <% end %> | 45 | <% end %> |
| 46 | </span> | 46 | </span> |
| 47 | 47 | ||
| 48 | <span class="user_action"> | 48 | <span class="action_item"> |
| 49 | <%= link_to admin_log_path(:user_id => user.id), | 49 | <%= link_to admin_log_path(:user_id => user.id), |
| 50 | "aria-label" => t(".action_log"), title: t(".action_log") do %> | 50 | "aria-label" => t(".action_log"), title: t(".action_log") do %> |
| 51 | <%= icon("history", library: "tabler", "aria-hidden": true) %> | 51 | <%= icon("history", library: "tabler", "aria-hidden": true) %> |
| 52 | <% end %> | 52 | <% end %> |
| 53 | </span> | 53 | </span> |
| 54 | 54 | ||
| 55 | <span class="user_action"> | 55 | <span class="action_item"> |
| 56 | <% if current_user.admin? && current_user != user %> | 56 | <% if current_user.is_admin? && current_user != user %> |
| 57 | <% if user.alumni? %> | 57 | <% if user.alumni? %> |
| 58 | <%= button_to reactivate_user_path(user), method: :put, | 58 | <%= button_to reactivate_user_path(user), method: :put, |
| 59 | form: { class: 'button_to state_changing' }, | 59 | form: { class: 'button_to state_changing' }, |
| @@ -71,7 +71,7 @@ | |||
| 71 | <% end %> | 71 | <% end %> |
| 72 | </span> | 72 | </span> |
| 73 | 73 | ||
| 74 | <span class="user_action"> | 74 | <span class="action_item"> |
| 75 | <% if current_user.redaktion? && !user.alumni? %> | 75 | <% if current_user.redaktion? && !user.alumni? %> |
| 76 | <% if user.redaktion? %> | 76 | <% if user.redaktion? %> |
| 77 | <% unless user == current_user %> | 77 | <% unless user == current_user %> |
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index ad2e0891..1763394d 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | <div class="layout_row_label"><%= t("users.labels.confirm") %></div> | 20 | <div class="layout_row_label"><%= t("users.labels.confirm") %></div> |
| 21 | <div class="layout_row_content"><%= f.password_field :password_confirmation, :autocomplete => "new-password" %></div> | 21 | <div class="layout_row_content"><%= f.password_field :password_confirmation, :autocomplete => "new-password" %></div> |
| 22 | 22 | ||
| 23 | <% if current_user.admin? %> | 23 | <% if current_user.is_admin? %> |
| 24 | <div class="layout_row_label"><%= t("users.labels.roles") %></div> | 24 | <div class="layout_row_label"><%= t("users.labels.roles") %></div> |
| 25 | <div class="layout_row_content"> | 25 | <div class="layout_row_content"> |
| 26 | <% User::ROLES.each do |role| %> | 26 | <% User::ROLES.each do |role| %> |
| @@ -62,7 +62,7 @@ | |||
| 62 | <% end %> | 62 | <% end %> |
| 63 | <% end %> | 63 | <% end %> |
| 64 | </div> | 64 | </div> |
| 65 | <% elsif current_user.admin? && @user.otp_enrolled? %> | 65 | <% elsif current_user.is_admin? && @user.otp_enrolled? %> |
| 66 | <div class="layout_row_label"><%= t(".second_factor") %></div> | 66 | <div class="layout_row_label"><%= t(".second_factor") %></div> |
| 67 | <div class="layout_row_content"> | 67 | <div class="layout_row_content"> |
| 68 | <%= t(".enabled") %> | 68 | <%= t(".enabled") %> |
diff --git a/config/locales/de.yml b/config/locales/de.yml index a1b29199..6f8dd24a 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml | |||
| @@ -373,6 +373,7 @@ de: | |||
| 373 | unlock_confirm: "Wirklich entsperren?\nGesperrt von %{login}\nZuletzt geändert %{time}" | 373 | unlock_confirm: "Wirklich entsperren?\nGesperrt von %{login}\nZuletzt geändert %{time}" |
| 374 | toggle_preview: "Live-Vorschau umschalten" | 374 | toggle_preview: "Live-Vorschau umschalten" |
| 375 | force_render: "Vorschau neu rendern" | 375 | force_render: "Vorschau neu rendern" |
| 376 | revisions: "Revisionen" | ||
| 376 | "yes": "ja" | 377 | "yes": "ja" |
| 377 | "no": "nein" | 378 | "no": "nein" |
| 378 | columns: | 379 | columns: |
diff --git a/config/locales/en.yml b/config/locales/en.yml index fc011437..c7a728ab 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml | |||
| @@ -321,6 +321,7 @@ en: | |||
| 321 | unlock_confirm: "Are you sure you want to unlock?\nLocked by %{login}\nLast modified %{time}" | 321 | unlock_confirm: "Are you sure you want to unlock?\nLocked by %{login}\nLast modified %{time}" |
| 322 | toggle_preview: "Toggle live preview" | 322 | toggle_preview: "Toggle live preview" |
| 323 | force_render: "Force preview render" | 323 | force_render: "Force preview render" |
| 324 | revisions: "revisions" | ||
| 324 | "yes": "yes" | 325 | "yes": "yes" |
| 325 | "no": "no" | 326 | "no": "no" |
| 326 | columns: | 327 | columns: |
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 1c74bbf5..8b976599 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css | |||
| @@ -644,24 +644,20 @@ table tr.header { | |||
| 644 | text-align: left; | 644 | text-align: left; |
| 645 | } | 645 | } |
| 646 | 646 | ||
| 647 | table.node_table , | 647 | table.node_table, |
| 648 | table.assets_table, | 648 | table.assets_table, |
| 649 | table.user_table, | 649 | table.user_table, |
| 650 | table.events_table { | 650 | table.events_table { |
| 651 | border-collapse: collapse; | 651 | border-collapse: collapse; |
| 652 | } | 652 | } |
| 653 | 653 | ||
| 654 | table.node_table tr { | 654 | table.node_table tr, |
| 655 | border-bottom: 1px solid var(--text); | ||
| 656 | } | ||
| 657 | |||
| 658 | table.assets_table tr, | 655 | table.assets_table tr, |
| 659 | table.user_table tr, | 656 | table.user_table tr, |
| 660 | table.events_table tr { | 657 | table.events_table tr { |
| 661 | border-bottom: 1px solid var(--hairline); | 658 | border-bottom: 1px solid var(--hairline); |
| 662 | } | 659 | } |
| 663 | 660 | ||
| 664 | table.node_table th.node_id, | ||
| 665 | table.node_table th.revision { | 661 | table.node_table th.revision { |
| 666 | min-width: 4rem; | 662 | min-width: 4rem; |
| 667 | } | 663 | } |
| @@ -682,14 +678,7 @@ table.events_table tr.header { | |||
| 682 | text-align: left; | 678 | text-align: left; |
| 683 | } | 679 | } |
| 684 | 680 | ||
| 685 | table.node_table td { | 681 | table.node_table td, |
| 686 | padding-top: 0px; | ||
| 687 | padding-bottom: 0px; | ||
| 688 | padding-right: 25px; | ||
| 689 | padding-left: 0px; | ||
| 690 | min-width: 2rem; | ||
| 691 | } | ||
| 692 | |||
| 693 | table.assets_table td, | 682 | table.assets_table td, |
| 694 | table.user_table td, | 683 | table.user_table td, |
| 695 | table.events_table td { | 684 | table.events_table td { |
| @@ -700,15 +689,6 @@ table.events_table td { | |||
| 700 | min-width: 2rem; | 689 | min-width: 2rem; |
| 701 | } | 690 | } |
| 702 | 691 | ||
| 703 | table.node_table .node_id { | ||
| 704 | padding-left: 10px; | ||
| 705 | padding-right: 15px; | ||
| 706 | } | ||
| 707 | |||
| 708 | table.node_table .actions { | ||
| 709 | text-transform: lowercase; | ||
| 710 | } | ||
| 711 | |||
| 712 | table.node_table tr.header:hover, | 692 | table.node_table tr.header:hover, |
| 713 | table.assets_table tr.header:hover, | 693 | table.assets_table tr.header:hover, |
| 714 | table.user_table tr.header:hover, | 694 | table.user_table tr.header:hover, |
| @@ -723,10 +703,6 @@ table.events_table tr:hover { | |||
| 723 | background-color: var(--surface-tint); | 703 | background-color: var(--surface-tint); |
| 724 | } | 704 | } |
| 725 | 705 | ||
| 726 | #admin_sitemap_table .node_id:before { | ||
| 727 | content: "• "; | ||
| 728 | } | ||
| 729 | |||
| 730 | table.revisions_table { | 706 | table.revisions_table { |
| 731 | border-collapse: collapse; | 707 | border-collapse: collapse; |
| 732 | } | 708 | } |
| @@ -844,37 +820,47 @@ table.revisions_table tr:hover { | |||
| 844 | margin-bottom: 1.5rem; | 820 | margin-bottom: 1.5rem; |
| 845 | } | 821 | } |
| 846 | 822 | ||
| 847 | .user_table td.user_actions { | 823 | .user_table td.actions, |
| 824 | .node_table td.actions { | ||
| 848 | width: 1px; | 825 | width: 1px; |
| 849 | white-space: nowrap; | 826 | white-space: nowrap; |
| 827 | } | ||
| 828 | |||
| 829 | /* Only where the action column is last. In the node lists rev. follows it, | ||
| 830 | and the 25px gutter is a real gap between columns there. */ | ||
| 831 | .user_table td.actions { | ||
| 850 | padding-right: 0; | 832 | padding-right: 0; |
| 851 | } | 833 | } |
| 852 | 834 | ||
| 853 | .user_table .user_action_grid { | 835 | .action_grid { |
| 854 | display: grid; | 836 | display: grid; |
| 855 | grid-template-columns: repeat(3, auto); | ||
| 856 | gap: 0.4rem; | 837 | gap: 0.4rem; |
| 857 | justify-content: end; | 838 | justify-content: end; |
| 858 | } | 839 | } |
| 859 | 840 | ||
| 860 | .user_table .user_action { | 841 | .user_table .action_grid { grid-template-columns: repeat(3, auto); } |
| 842 | .node_table .action_grid { grid-template-columns: repeat(2, auto); } | ||
| 843 | |||
| 844 | /* min-height keeps a row the same height whether or not the viewer may see | ||
| 845 | the lower controls. */ | ||
| 846 | .action_item { | ||
| 861 | display: inline-flex; | 847 | display: inline-flex; |
| 862 | min-height: 2rem; | 848 | min-height: 2rem; |
| 863 | } | 849 | } |
| 864 | 850 | ||
| 865 | .user_table .user_action svg { | 851 | .action_item svg { |
| 866 | width: 1.25rem; | 852 | width: 1.25rem; |
| 867 | height: 1.25rem; | 853 | height: 1.25rem; |
| 868 | } | 854 | } |
| 869 | 855 | ||
| 870 | .user_table .user_action form.button_to { | 856 | .action_item form.button_to { |
| 871 | display: inline-flex; | 857 | display: inline-flex; |
| 872 | margin: 0; | 858 | margin: 0; |
| 873 | } | 859 | } |
| 874 | 860 | ||
| 875 | .user_table .user_action a, | 861 | .action_item a, |
| 876 | .user_table .user_action button[type="submit"], | 862 | .action_item form.button_to button[type="submit"], |
| 877 | .user_table .user_action .disabled_action { | 863 | .action_item .disabled_action { |
| 878 | display: inline-flex; | 864 | display: inline-flex; |
| 879 | align-items: center; | 865 | align-items: center; |
| 880 | justify-content: center; | 866 | justify-content: center; |
| @@ -886,22 +872,22 @@ table.revisions_table tr:hover { | |||
| 886 | text-decoration: none; | 872 | text-decoration: none; |
| 887 | } | 873 | } |
| 888 | 874 | ||
| 889 | .user_table .user_action a:hover { | 875 | .action_item a:hover { |
| 890 | color: var(--surface); | 876 | color: var(--surface); |
| 891 | background-color: var(--text); | 877 | background-color: var(--text); |
| 892 | } | 878 | } |
| 893 | 879 | ||
| 894 | .user_table .user_action form.button_to.destructive button:hover { | 880 | .action_item form.button_to.destructive button:hover { |
| 895 | color: var(--on-solid); | 881 | color: var(--on-solid); |
| 896 | background-color: var(--danger-solid); | 882 | background-color: var(--danger-solid); |
| 897 | } | 883 | } |
| 898 | 884 | ||
| 899 | .user_table .user_action form.button_to.state_changing button:hover { | 885 | .action_item form.button_to.state_changing button:hover { |
| 900 | color: var(--on-solid); | 886 | color: var(--on-solid); |
| 901 | background-color: var(--action-solid); | 887 | background-color: var(--action-solid); |
| 902 | } | 888 | } |
| 903 | 889 | ||
| 904 | .user_table .user_action .disabled_action { | 890 | .action_item .disabled_action { |
| 905 | color: var(--text-muted); | 891 | color: var(--text-muted); |
| 906 | background-color: transparent; | 892 | background-color: transparent; |
| 907 | border-color: var(--border); | 893 | border-color: var(--border); |
| @@ -915,22 +901,39 @@ table.revisions_table tr:hover { | |||
| 915 | .flag_stack { | 901 | .flag_stack { |
| 916 | display: inline-flex; | 902 | display: inline-flex; |
| 917 | flex-direction: column; | 903 | flex-direction: column; |
| 918 | align-items: center; | 904 | align-items: flex-start; |
| 919 | min-width: 1rem; | ||
| 920 | gap: 0.25rem; | 905 | gap: 0.25rem; |
| 921 | vertical-align: -0.15em; | 906 | vertical-align: -0.15em; |
| 922 | margin-right: 0.5rem; | 907 | margin-right: 0.5rem; |
| 908 | width: 1.5rem; | ||
| 923 | } | 909 | } |
| 924 | 910 | ||
| 925 | .flag_stack svg { | 911 | .flag_stack svg { |
| 926 | width: 1rem; | 912 | width: 1.25rem; |
| 927 | height: 1rem; | 913 | height: 1.25rem; |
| 928 | color: var(--text-muted); | 914 | color: var(--text-muted); |
| 929 | } | 915 | } |
| 930 | 916 | ||
| 931 | .flag_stack .flag_attention svg { color: var(--accent); } | 917 | .flag_stack .flag_attention svg { color: var(--accent); } |
| 932 | .flag_stack .flag_alert svg { color: var(--danger); } | 918 | .flag_stack .flag_alert svg { color: var(--danger); } |
| 933 | 919 | ||
| 920 | .title_with_flags { | ||
| 921 | display: flex; | ||
| 922 | align-items: flex-start; | ||
| 923 | } | ||
| 924 | |||
| 925 | .title_body { | ||
| 926 | min-width: 0; | ||
| 927 | } | ||
| 928 | |||
| 929 | .node_table .node_title { | ||
| 930 | font-weight: bold; | ||
| 931 | } | ||
| 932 | |||
| 933 | .node_table .node_path { | ||
| 934 | margin-top: 0.15rem; | ||
| 935 | } | ||
| 936 | |||
| 934 | .user_group_heading { | 937 | .user_group_heading { |
| 935 | margin-top: 1.5rem; | 938 | margin-top: 1.5rem; |
| 936 | } | 939 | } |
diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index aeff9bc7..d06b9298 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb | |||
| @@ -50,7 +50,7 @@ class UsersControllerTest < ActionController::TestCase | |||
| 50 | end | 50 | end |
| 51 | 51 | ||
| 52 | assert_redirected_to user_path(User.last) | 52 | assert_redirected_to user_path(User.last) |
| 53 | assert !User.last.admin | 53 | assert_not User.last.is_admin? |
| 54 | end | 54 | end |
| 55 | 55 | ||
| 56 | test "creating a Redaktion account" do | 56 | test "creating a Redaktion account" do |
