summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/views/nodes/show.html.erb11
-rw-r--r--app/views/nodes/sitemap.html.erb50
-rw-r--r--config/locales/de.yml7
-rw-r--r--config/locales/en.yml7
-rw-r--r--public/stylesheets/admin.css64
-rw-r--r--test/controllers/nodes_controller_test.rb20
6 files changed, 130 insertions, 29 deletions
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb
index a94e001c..105e37ea 100644
--- a/app/views/nodes/show.html.erb
+++ b/app/views/nodes/show.html.erb
@@ -231,7 +231,7 @@
231 <% end %> 231 <% end %>
232 </div> 232 </div>
233 233
234 <% if @node.head %> 234 <% if @node.head && !@node.root? %>
235 <div class="link_matrix_row"> 235 <div class="link_matrix_row">
236 <span class="link_matrix_label"> 236 <span class="link_matrix_label">
237 <span class="info_label"><%= t(".public") %></span> 237 <span class="info_label"><%= t(".public") %></span>
@@ -251,6 +251,15 @@
251 </div> 251 </div>
252 <% end %> 252 <% end %>
253 253
254 <% if @node.root? %>
255 <div class="link_matrix_row">
256 <span class="link_matrix_label">
257 <span class="info_label"><%= t(".public") %></span>
258 <span class="field_hint"><%= t(".root_has_no_public_url") %></span>
259 </span>
260 </div>
261 <% end %>
262
254 <% if @node.draft %> 263 <% if @node.draft %>
255 <div class="link_matrix_row"> 264 <div class="link_matrix_row">
256 <span class="link_matrix_label"> 265 <span class="link_matrix_label">
diff --git a/app/views/nodes/sitemap.html.erb b/app/views/nodes/sitemap.html.erb
index ea64b356..019d4c92 100644
--- a/app/views/nodes/sitemap.html.erb
+++ b/app/views/nodes/sitemap.html.erb
@@ -1,23 +1,55 @@
1<h1><%= t(".title") %></h1> 1<%= render "shared/page_actions",
2 :title => t(".title"),
3 :icon_name => "file-plus",
4 :label => t(".create_at_root"),
5 :options => [[t(".create_at_root"), new_node_path(:parent_id => Node.root.id)]] %>
2 6
3<div id="sitemap"> 7<div id="sitemap">
8
4<% 9<%
5 open_details = [] # levels with a currently-open <details> 10 open_details = [] # levels with a currently-open <details>
11 world_icon = icon("world", library: "tabler", "aria-hidden": true)
12 create_icon = icon("file-plus", library: "tabler", "aria-hidden": true)
13 show_icon = icon("eye", library: "tabler", "aria-hidden": true)
6%> 14%>
15
7<% @sitemap.each_with_index do |(node, level), index| %> 16<% @sitemap.each_with_index do |(node, level), index| %>
8 <% while open_details.any? && open_details.last >= level %> 17 <% while open_details.any? && open_details.last >= level %>
9 </details> 18 </details>
10 <% open_details.pop %> 19 <% open_details.pop %>
11 <% end %> 20 <% end %>
12 21
13 <div class="sitemap_node"> 22 <% unless level.zero? %>
14 <h4><%= link_to title_for_node(node), node_path(node) %></h4> 23 <div class="sitemap_node">
15 <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span> 24 <div class="title_with_flags">
16 <p class="sitemap_node_actions"> 25 <span class="flag_stack">
17 <%= link_to 'Show', node_path(node) %> 26 <%= flag("file-text-shield", t(".flag_restricted"), :tier => :attention) if node.restricted? %>
18 <%= link_to 'Create Child', new_node_path(:parent_id => node.id) %> 27 <%= flag("external-link", t(".flag_external")) if node.external_url.present? %>
19 </p> 28 </span>
20 </div> 29 <div class="title_body">
30 <div class="node_title"><%= link_to title_for_node(node), node_path(node) %></div>
31 <div class="node_path">
32 <%= world_icon %>
33 <%= link_to_path(node.unique_name, node.unique_name) %>
34 </div>
35 </div>
36 <div class="action_grid">
37 <span class="action_item">
38 <%= link_to new_node_path(:parent_id => node.id),
39 "aria-label" => t(".create_child"), title: t(".create_child") do %>
40 <%= create_icon %>
41 <% end %>
42 </span>
43 <span class="action_item">
44 <%= link_to node_path(node), "aria-label" => t("admin.common.show"),
45 title: t("admin.common.show") do %>
46 <%= show_icon %>
47 <% end %>
48 </span>
49 </div>
50 </div>
51 </div>
52 <% end %>
21 53
22 <% next_level = @sitemap[index + 1]&.last %> 54 <% next_level = @sitemap[index + 1]&.last %>
23 <% if next_level && next_level > level %> 55 <% if next_level && next_level > level %>
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 591b45d1..10f4b606 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -538,7 +538,8 @@ de:
538 add_child: "Kind vom Typ %{kind} anlegen" 538 add_child: "Kind vom Typ %{kind} anlegen"
539 abstract_locale: "Abstract (%{lang})" 539 abstract_locale: "Abstract (%{lang})"
540 body_locale: "Text (%{lang})" 540 body_locale: "Text (%{lang})"
541 restricted_hint: "Geschützter Bereich — Veröffentlichen und Papierkorb sind der Redaktion vorbehalten. Entwürfe kannst du frei bearbeiten." 541 restricted_hint: "Geschützter Bereich. Veröffentlichen und Papierkorb sind der Redaktion vorbehalten. Entwürfe kannst du frei bearbeiten."
542 root_has_no_public_url: "Der Root-Node hat keine öffentliche Adresse. Er wird von der Startseite geliefert."
542 drafts: 543 drafts:
543 title: "Nodes mit Entwürfen, Autosaves oder Sperren" 544 title: "Nodes mit Entwürfen, Autosaves oder Sperren"
544 mine: 545 mine:
@@ -547,6 +548,10 @@ de:
547 title: "Nodes mit Tag: %{tag}" 548 title: "Nodes mit Tag: %{tag}"
548 sitemap: 549 sitemap:
549 title: "Sitemap" 550 title: "Sitemap"
551 create_at_root: "Seite auf oberster Ebene anlegen"
552 create_child: "Hier eine Seite anlegen"
553 flag_restricted: "Veröffentlichen unterhalb erfordert Redaktion"
554 flag_external: "Leitet weiter — hier keine Seiten anlegen"
550 descendants: 555 descendants:
551 one: "1 Unterseite" 556 one: "1 Unterseite"
552 other: "%{count} Unterseiten" 557 other: "%{count} Unterseiten"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f8a7144c..adcc591e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -485,7 +485,8 @@ en:
485 add_child: "Add child type %{kind}" 485 add_child: "Add child type %{kind}"
486 abstract_locale: "Abstract (%{lang})" 486 abstract_locale: "Abstract (%{lang})"
487 body_locale: "Body (%{lang})" 487 body_locale: "Body (%{lang})"
488 restricted_hint: "Protected section — publishing and trashing are reserved for Redaktion. You can edit drafts freely." 488 restricted_hint: "Protected section. Publishing and trashing are reserved for Redaktion. You can edit drafts freely."
489 root_has_no_public_url: "The root node has no public address. It is served from the home page."
489 drafts: 490 drafts:
490 title: "Nodes with drafts, autosaves or locks" 491 title: "Nodes with drafts, autosaves or locks"
491 mine: 492 mine:
@@ -494,6 +495,10 @@ en:
494 title: "Nodes tagged: %{tag}" 495 title: "Nodes tagged: %{tag}"
495 sitemap: 496 sitemap:
496 title: "Sitemap" 497 title: "Sitemap"
498 create_at_root: "Create a top-level page"
499 create_child: "Add a page here"
500 flag_restricted: "Publishing below this point needs Redaktion"
501 flag_external: "Redirects elsewhere — do not add pages under this"
497 descendants: 502 descendants:
498 one: "1 descendant" 503 one: "1 descendant"
499 other: "%{count} descendants" 504 other: "%{count} descendants"
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css
index acb87aba..334e0bd5 100644
--- a/public/stylesheets/admin.css
+++ b/public/stylesheets/admin.css
@@ -835,7 +835,6 @@ table.revisions_table tr:hover {
835 gap: 0.3rem; 835 gap: 0.3rem;
836 margin-top: 0.35rem; 836 margin-top: 0.35rem;
837 font-size: 0.875rem; 837 font-size: 0.875rem;
838 color: var(--text-muted);
839} 838}
840 839
841.assets_table .asset_meta svg, 840.assets_table .asset_meta svg,
@@ -1439,23 +1438,67 @@ form.button_to button[type="submit"] {
1439 margin-bottom: 0; 1438 margin-bottom: 0;
1440} 1439}
1441 1440
1441#sitemap {
1442 max-width: 60rem;
1443}
1444
1445#sitemap .title_with_flags {
1446 align-items: start;
1447}
1448
1449#sitemap .title_body {
1450 flex: 1;
1451}
1452
1453#sitemap .node_path {
1454 display: flex;
1455 align-items: center;
1456 gap: 0.3rem;
1457 margin-top: 0.15rem;
1458 font-size: 0.875rem;
1459 color: var(--text-muted);
1460}
1461
1462#sitemap .node_path svg {
1463 width: 0.875rem;
1464 height: 0.875rem;
1465 flex-shrink: 0;
1466}
1467
1468#sitemap .node_path a {
1469 color: var(--text-muted);
1470 overflow-wrap: anywhere;
1471}
1472
1473#sitemap .action_grid {
1474 grid-template-columns: repeat(2, auto);
1475}
1476
1442.sitemap_node { 1477.sitemap_node {
1443 padding-bottom: 0.5rem; 1478 padding-bottom: 0.5rem;
1444 margin-bottom: 0.5rem; 1479 margin-bottom: 0.5rem;
1445 border-bottom: 1px solid var(--hairline); 1480 border-bottom: 1px solid var(--hairline);
1446} 1481}
1447 1482
1448.sitemap_node h4 { 1483#sitemap .sitemap_node:has(+ details) {
1449 margin: 0; 1484 border-bottom: none;
1485 margin-bottom: 0;
1486 padding-bottom: 0.25rem;
1450} 1487}
1451 1488
1452.sitemap_node .field_hint { 1489#sitemap .sitemap_node:has(+ details) + details > summary {
1453 display: block; 1490 padding-bottom: 0.5rem;
1454 margin: 2px 0 0; 1491 margin-bottom: 0.5rem;
1492 border-bottom: 1px solid var(--hairline);
1455} 1493}
1456 1494
1457.sitemap_node p { 1495#sitemap > .sitemap_node {
1458 margin: 2px 0 0; 1496 border-bottom-width: 8px;
1497 margin-bottom: 0.75rem;
1498}
1499
1500#sitemap > details > summary {
1501 display: none;
1459} 1502}
1460 1503
1461#sitemap details details { 1504#sitemap details details {
@@ -1472,7 +1515,10 @@ form.button_to button[type="submit"] {
1472} 1515}
1473 1516
1474#sitemap summary { 1517#sitemap summary {
1475 padding: 4px 0; 1518 padding: 0.10rem 0 0.5rem 0;
1519 margin-left: -0.25rem;
1520 margin-top: -0.1rem;
1521 color: var(--text-muted);
1476} 1522}
1477 1523
1478#sitemap details:not([open]) > summary { 1524#sitemap details:not([open]) > summary {
diff --git a/test/controllers/nodes_controller_test.rb b/test/controllers/nodes_controller_test.rb
index 27c28cfe..c2898cbb 100644
--- a/test/controllers/nodes_controller_test.rb
+++ b/test/controllers/nodes_controller_test.rb
@@ -644,8 +644,8 @@ class NodesControllerTest < ActionController::TestCase
644 644
645 doc = Nokogiri::HTML::DocumentFragment.parse(response.body) 645 doc = Nokogiri::HTML::DocumentFragment.parse(response.body)
646 646
647 erfas_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.field_hint')&.text&.include?(erfas.unique_name) } 647 erfas_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.node_path')&.text&.include?(erfas.unique_name) }
648 other_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.field_hint')&.text&.include?(other.unique_name) } 648 other_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.node_path')&.text&.include?(other.unique_name) }
649 649
650 erfas_details = erfas_node_div.next_element 650 erfas_details = erfas_node_div.next_element
651 other_details = other_node_div.next_element 651 other_details = other_node_div.next_element
@@ -667,20 +667,24 @@ class NodesControllerTest < ActionController::TestCase
667 assert_response :success 667 assert_response :success
668 668
669 doc = Nokogiri::HTML::DocumentFragment.parse(response.body) 669 doc = Nokogiri::HTML::DocumentFragment.parse(response.body)
670 erfas_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.field_hint')&.text&.include?(erfas.unique_name) } 670 erfas_node_div = doc.css('.sitemap_node').find { |div| div.at_css('.node_path')&.text&.include?(erfas.unique_name) }
671 erfas_details = erfas_node_div.next_element 671 erfas_details = erfas_node_div.next_element
672 672
673 assert_equal 'details', erfas_details.name 673 assert_equal 'details', erfas_details.name
674 assert_match I18n.t("nodes.sitemap.descendants", :count => 2), @response.body 674 assert_match I18n.t("nodes.sitemap.descendants", :count => 2), @response.body
675 end 675 end
676 676
677 test "sitemap shows Show and Create Child, not Revisions" do 677 test "sitemap offers Create Child and Show, not Revisions" do
678 node = Node.root.children.create!(:slug => "sitemap_actions_test") 678 Node.root.children.create!(:slug => "sitemap_actions_test")
679 login_as :quentin 679 login_as :quentin
680 get :sitemap 680 get :sitemap
681 assert_select ".sitemap_node_actions", :text => /Show/ 681
682 assert_select ".sitemap_node_actions", :text => /Create Child/ 682 assert_select ".sitemap_node .action_grid a[title=?]",
683 assert_select ".sitemap_node_actions", :text => /Revisions/, :count => 0 683 I18n.t("nodes.sitemap.create_child")
684 assert_select ".sitemap_node .action_grid a[title=?]",
685 I18n.t("admin.common.show")
686 assert_select ".sitemap_node .action_grid a[title=?]",
687 I18n.t("admin.common.revisions"), :count => 0
684 end 688 end
685 689
686 test "create logs a create NodeAction with path and title" do 690 test "create logs a create NodeAction with path and title" do