summaryrefslogtreecommitdiff
path: root/app/views
diff options
context:
space:
mode:
Diffstat (limited to 'app/views')
-rw-r--r--app/views/admin/_drafts.html.erb2
-rw-r--r--app/views/admin/_menu.html.erb13
-rw-r--r--app/views/admin/_recent_changes.html.erb24
-rw-r--r--app/views/admin/conventions.html.erb11
-rw-r--r--app/views/admin/index.html.erb201
-rw-r--r--app/views/admin/search_results.html.erb11
-rw-r--r--app/views/assets/index.html.erb21
-rw-r--r--app/views/assets/show.html.erb60
-rw-r--r--app/views/content/_open_erfas_today.html.erb11
-rw-r--r--app/views/custom/page_templates/public/chapter_detail.html.erb34
-rw-r--r--app/views/custom/partials/_chapter.html.erb26
-rw-r--r--app/views/events/_rrule_builder.html.erb33
-rw-r--r--app/views/events/edit.html.erb110
-rw-r--r--app/views/events/index.html.erb42
-rw-r--r--app/views/events/new.html.erb89
-rw-r--r--app/views/events/show.html.erb83
-rw-r--r--app/views/events/without_node.html.erb30
-rw-r--r--app/views/layouts/admin.html.erb45
-rw-r--r--app/views/layouts/application.html.erb21
-rw-r--r--app/views/layouts/events.html.erb17
-rw-r--r--app/views/menu_items/edit.html.erb51
-rw-r--r--app/views/menu_items/index.html.erb16
-rw-r--r--app/views/menu_items/new.html.erb42
-rw-r--r--app/views/node_actions/_action_row.html.erb18
-rw-r--r--app/views/node_actions/_change_details.html.erb35
-rw-r--r--app/views/node_actions/index.html.erb13
-rw-r--r--app/views/nodes/_node_list.html.erb41
-rw-r--r--app/views/nodes/_recent_change_item.html.erb9
-rw-r--r--app/views/nodes/chapters.html.erb11
-rw-r--r--app/views/nodes/destroy.html.erb2
-rw-r--r--app/views/nodes/drafts.html.erb3
-rw-r--r--app/views/nodes/edit.html.erb175
-rw-r--r--app/views/nodes/index.html.erb13
-rw-r--r--app/views/nodes/mine.html.erb3
-rw-r--r--app/views/nodes/new.html.erb82
-rw-r--r--app/views/nodes/recent.html.erb7
-rw-r--r--app/views/nodes/show.html.erb372
-rw-r--r--app/views/nodes/sitemap.html.erb32
-rw-r--r--app/views/nodes/tags.html.erb3
-rw-r--r--app/views/nodes/trashed.html.erb42
-rw-r--r--app/views/occurrences/index.html.erb6
-rw-r--r--app/views/page_translations/edit.html.erb67
-rw-r--r--app/views/page_translations/show.html.erb29
-rw-r--r--app/views/pages/index.html.erb6
-rw-r--r--app/views/revisions/diff.html.erb177
-rw-r--r--app/views/revisions/index.html.erb125
-rw-r--r--app/views/revisions/show.html.erb91
-rw-r--r--app/views/rss/updates.xml.builder4
-rw-r--r--app/views/sessions/new.html.erb31
-rw-r--r--app/views/users/_user.html.erb7
-rw-r--r--app/views/users/edit.html.erb54
-rw-r--r--app/views/users/index.html.erb31
-rw-r--r--app/views/users/new.html.erb52
-rw-r--r--app/views/users/show.html.erb41
54 files changed, 1696 insertions, 879 deletions
diff --git a/app/views/admin/_drafts.html.erb b/app/views/admin/_drafts.html.erb
index a35b0ab..4ef568f 100644
--- a/app/views/admin/_drafts.html.erb
+++ b/app/views/admin/_drafts.html.erb
@@ -17,7 +17,7 @@
17 <td class="actions"> 17 <td class="actions">
18 <%= link_to 'Show', node_path(draft.node) %> 18 <%= link_to 'Show', node_path(draft.node) %>
19 <%= link_to "Revisions", revision_path(draft.node.id) %> 19 <%= link_to "Revisions", revision_path(draft.node.id) %>
20 <%= button_to "Publish", publish_node_path(draft.node), method: :put, form: { data: { confirm: "Do you really want to publish?" } } %> 20 <%= button_to "Publish", publish_node_path(draft.node), method: :put, form: { data: { confirm: "Do you really want to publish?" }, class: 'button_to state_changing' } %>
21 </td> 21 </td>
22 </tr> 22 </tr>
23 <% end %> 23 <% end %>
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index 6dba085..7270df4 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -1,8 +1,5 @@
1<%= language_selector %> 1<%= link_to icon("home", library: "tabler", "aria-hidden": true), admin_path, "aria-label": "Dashboard", title: "Dashboard" %>
2<%= button_to 'Logout', logout_path, method: :delete %> 2<a href="#" onclick="admin_search.display_toggle(); return false;" aria-label="Search" title="Search"><%= icon("search", library: "tabler", "aria-hidden": true) %></a>
3<%= link_to 'Overview', admin_path %> 3<%= button_to logout_path, method: :delete, aria: { label: "Log out" }, title: "Log out" do %>
4<a href="#" onclick="admin_search.display_toggle(); return false;">search</a> 4 <%= icon("logout", library: "tabler", "aria-hidden": true) %>
5<%= link_to 'Nodes', nodes_path, selected?('nodes') %> 5<% end %>
6<%= link_to 'Assets', assets_path, selected?('assets') %>
7<%= link_to 'User', users_path, selected?('users') %>
8<%= link_to 'Navigation', menu_items_path, selected?('menu_items') %> &gt;&nbsp;
diff --git a/app/views/admin/_recent_changes.html.erb b/app/views/admin/_recent_changes.html.erb
deleted file mode 100644
index 88b5e93..0000000
--- a/app/views/admin/_recent_changes.html.erb
+++ /dev/null
@@ -1,24 +0,0 @@
1<h2>Recent Changes</h2>
2<div id="draft_list">
3 <table>
4 <tr class="header">
5 <th>Title</th>
6 <th>path</th>
7 <th>user</th>
8 <th>date</th>
9 <th></th>
10 </tr>
11 <% @recent_changes.each do |node| %>
12 <tr>
13 <td><%= truncated_title_for_node node %></td>
14 <td><%= node.unique_name %></td>
15 <td><%= node.draft.user.login rescue "" %></td>
16 <td><%= node.updated_at.to_fs(:db) %></td>
17 <td class="actions">
18 <%= link_to 'Show', node_path(node) %>
19 <%= link_to "Revisions", revision_path(:id => node.id) %>
20 </td>
21 </tr>
22 <% end %>
23 </table>
24</div> \ No newline at end of file
diff --git a/app/views/admin/conventions.html.erb b/app/views/admin/conventions.html.erb
new file mode 100644
index 0000000..72f6214
--- /dev/null
+++ b/app/views/admin/conventions.html.erb
@@ -0,0 +1,11 @@
1<h1>Node creation conventions</h1>
2
3<table id="conventions">
4 <tr><th>Kind</th><th>What happens</th></tr>
5 <% @node_kinds.each do |kind, config| %>
6 <tr>
7 <td><%= kind %></td>
8 <td><%= resolve_kind_text(config[:label]) %> — <%= resolve_kind_text(config[:hint]) %></td>
9 </tr>
10 <% end %>
11</table>
diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb
index 2741db3..319530d 100644
--- a/app/views/admin/index.html.erb
+++ b/app/views/admin/index.html.erb
@@ -1,147 +1,76 @@
1<div id="admin_wizard"> 1<h1>cccms dashboard</h1>
2 <div class="admin_wizard_button"><%= link_to 'Create Update or Pressemitteilung', new_node_path, :only_path => false %></div> 2<div id="dashboard_search">
3 <div class="admin_wizard_button"><a href="#" id="admin_wizard_my_work" class="button">Continue my work</a></div> 3 <%= form_tag admin_search_path, method: :get do %>
4 <div class="admin_wizard_button"><a href="#" id="admin_wizard_create_page" class="button">Add a page in the page tree</a></div> 4 <%= text_field_tag :search_term, nil, id: "dashboard_search_term", placeholder: "Search nodes and tags…", autocomplete: "off" %>
5 <div class="admin_wizard_button"><%= link_to("Upload a new asset", new_asset_path, :only_path => false) %></div> 5 <% end %>
6 <div id="dashboard_search_results" class="search_results"></div>
6</div> 7</div>
7 8
8<p id="overview_toggle"> 9<div id="dashboard_signposts" class="button_row">
9 <a href="#" id="recent_changes_toggle" class="button">recent changes</a> 10 <%= link_to new_node_path, class: "action_button" do %>
10 <a href="#" id="my_work_toggle" class="button">my work</a> 11 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create post
11 <a href="#" id="current_drafts_toggle" class="button">current drafts (<%= @drafts_count %>)</a> 12 <% end %>
12 <a href="#" id="admin_sitemap_toggle" class="button">site map</a> 13 <%= link_to chapters_nodes_path, class: "action_button" do %>
13</p> 14 <%= icon("map-pin", library: "tabler", "aria-hidden": true) %> Find a chapter
14 15 <% end %>
15<div id="recent_changes_table"> 16 <%= link_to new_asset_path, class: "action_button" do %>
16 17 <%= icon("upload", library: "tabler", "aria-hidden": true) %> Upload asset
17 <h1>Recent Changes</h1> 18 <% end %>
18 19 <%= link_to sitemap_nodes_path, class: "action_button" do %>
19 <table class="node_table"> 20 <%= icon("list-tree", library: "tabler", "aria-hidden": true) %> Add a page in the page tree
20 <tr class="header"> 21 <% end %>
21 <th class="node_id">ID</th>
22 <th class="title">Title</th>
23 <th class="actions">Actions</th>
24 <th class="editor">Locked by</th>
25 <th class="revision">Rev.</th>
26 </tr>
27 <% @recent_changes.each do |node| %>
28 <tr class="<%= cycle("even", "odd") %>">
29 <td class="node_id"><%= node.id %></td>
30 <td class="title">
31 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
32 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
33 </td>
34 <td class="actions">
35 <%= link_to 'show', node_path(node) %>
36 <%= link_to 'Revisions', node_revisions_path(node) %>
37 </td>
38 <td>
39 <%= node.lock_owner.login if node.lock_owner %>
40 </td>
41 <td>
42 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
43 </td>
44 </tr>
45 <% end %>
46 </table>
47</div> 22</div>
48 23
49<div id="my_work_table"> 24<div id="dashboard_widgets">
50 25 <div class="dashboard_widget">
51 <h1>My Work</h1> 26 <h3>Drafts and autosaves</h3>
27 <ul>
28 <% @drafts.each do |node| %>
29 <li>
30 <div>
31 <%= link_to title_for_node(node), node_path(node) %>
32 <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span>
33 </div>
34 <span class="dashboard_widget_meta">
35 <% if (editor = node_last_editor(node)) %><%= editor %>, <% end %><%= relative_time_phrase(node.updated_at) %>
36 </span>
37 </li>
38 <% end %>
39 </ul>
40 <%= link_to "See all drafts →", drafts_nodes_path %>
41 </div>
52 42
53 <table class="node_table"> 43 <div class="dashboard_widget">
54 <tr class="header"> 44 <h3>Recent changes</h3>
55 <th class="node_id">ID</th> 45 <table id="node_action_list">
56 <th class="title">Title</th> 46 <%= render partial: "node_actions/action_row", collection: @actions, as: :action %>
57 <th class="actions">Actions</th> 47 </table>
58 <th class="editor">Locked by</th> 48 <%= link_to "See all recent changes →", admin_log_path %>
59 <th class="revision">Rev.</th> 49 </div>
60 </tr>
61 <% @mynodes.each do |node| %>
62 <tr class="<%= cycle("even", "odd") %>">
63 <td class="node_id"><%= node.id %></td>
64 <td class="title">
65 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
66 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
67 </td>
68 <td class="actions">
69 <%= link_to 'show', node_path(node) %>
70 <%= link_to 'Revisions', node_revisions_path(node) %>
71 </td>
72 <td>
73 <%= node.lock_owner.login if node.lock_owner %>
74 </td>
75 <td>
76 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
77 </td>
78 </tr>
79 <% end %>
80 </table>
81</div>
82 50
83<div id="current_drafts_table">
84
85 <h1>Current Drafts (<%= @drafts_count %>)</h1>
86
87 <table class="node_table">
88 <tr class="header">
89 <th class="node_id">ID</th>
90 <th class="title">Title</th>
91 <th class="actions">Actions</th>
92 <th class="editor">Locked by</th>
93 <th class="revision">Rev.</th>
94 </tr>
95 <% @drafts.each do |node| %>
96 <tr class="<%= cycle("even", "odd") %>">
97 <td class="node_id"><%= node.id %></td>
98 <td class="title">
99 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
100 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
101 </td>
102 <td class="actions">
103 <%= link_to 'show', node_path(node) %>
104 <%= link_to 'Revisions', node_revisions_path(node) %>
105 </td>
106 <td>
107 <%= node.lock_owner.login if node.lock_owner %>
108 </td>
109 <td>
110 <%= link_to ( node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY" ) ), node_revisions_path(node) %>
111 </td>
112 </tr>
113 <% end %>
114 </table>
115</div> 51</div>
116 52
117<div id="admin_sitemap_table"> 53<div id="dashboard_housekeeping">
118 54 <h3>Housekeeping</h3>
119 <h1>Sitemap</h1> 55 <div class="button_row">
120 56 <%= link_to nodes_path, class: "action_button" do %>
121 <table class="node_table"> 57 <%= icon("list", library: "tabler", "aria-hidden": true) %> Nodes
122 <tr class="header"> 58 <% end %>
123 <th class="node_id">ID</th> 59 <%= link_to events_path, class: "action_button" do %>
124 <th class="title">Title</th> 60 <%= icon("calendar", library: "tabler", "aria-hidden": true) %> Events
125 <th class="actions">Actions</th> 61 <% end %>
126 <th class="editor">Locked by</th> 62 <%= link_to assets_path, class: "action_button" do %>
127 </tr> 63 <%= icon("folder", library: "tabler", "aria-hidden": true) %> Assets
128 <% @sitemap.each do |node| %> 64 <% end %>
129 <% if !node.nil? %> 65 <%= link_to users_path, class: "action_button" do %>
130 <tr class="<%= cycle("even", "odd") %>"> 66 <%= icon("users", library: "tabler", "aria-hidden": true) %> Users
131 <td class="node_id" style="padding-left: <%= @sitemap_depth[node.id] * 30 %>px;"><%= node.id %></td> 67 <% end %>
132 <td class="title" style="padding-left: <%= @sitemap_depth[node.id] * 30 %>px;"> 68 <%= link_to menu_items_path, class: "action_button" do %>
133 <h4><%= link_to title_for_node(node), node_path(node) %></h4> 69 <%= icon("menu-2", library: "tabler", "aria-hidden": true) %> Navigation
134 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
135 </td>
136 <td class="actions">
137 <%= link_to 'create subpage', new_node_path(:parent_id => node.id) %>
138 <%= link_to 'Revisions', node_revisions_path(node) %>
139 </td>
140 <td>
141 <%= node.lock_owner.login if node.lock_owner %>
142 </td>
143 </tr>
144 <% end %> 70 <% end %>
71 <% trash_count = Node.trash.children.count %>
72 <%= link_to trashed_nodes_path, class: "action_button" do %>
73 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Trash<%= " (#{trash_count})" if trash_count > 0 %>
145 <% end %> 74 <% end %>
146 </table> 75 </div>
147</div> 76</div>
diff --git a/app/views/admin/search_results.html.erb b/app/views/admin/search_results.html.erb
index f8aece0..a757197 100644
--- a/app/views/admin/search_results.html.erb
+++ b/app/views/admin/search_results.html.erb
@@ -1,7 +1,10 @@
1<h1>Search Results</h1> 1<h1>Search Results</h1>
2 2
3<ul> 3<ul class="search_results_list">
4<%- @results.each do |result| %> 4 <% @results.each do |result| %>
5 <li><%= link_to "#{result.title} (#{result.unique_name})", edit_node_path(result) %></li> 5 <li>
6<% end %> 6 <%= link_to title_for_node(result), node_path(result) %>
7 <span class="field_hint"><%= link_to_path("#{result.unique_name} ↗", result.unique_name) %></span>
8 </li>
9 <% end %>
7</ul> 10</ul>
diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb
index 51fc486..8c35561 100644
--- a/app/views/assets/index.html.erb
+++ b/app/views/assets/index.html.erb
@@ -1,12 +1,19 @@
1<% content_for :subnavigation do %> 1<h1>Assets</h1>
2 <%= link_to 'New asset', new_asset_path %>
3<% end %>
4 2
3<%= link_to new_asset_path, class: 'action_button' do %>
4 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create asset
5<% end %>
5 6
6<%= will_paginate @assets %> 7<%= will_paginate @assets %>
7 8
8<table> 9<table class="assets_table">
9 <tr> 10 <tr class="header">
11 <th>Preview</th>
12 <th>Name</th>
13 <th>Type</th>
14 <th></th>
15 <th></th>
16 <th></th>
10 </tr> 17 </tr>
11<% @assets.each do |asset| %> 18<% @assets.each do |asset| %>
12 <tr> 19 <tr>
@@ -15,7 +22,9 @@
15 <td><%= asset.upload.content_type %></td> 22 <td><%= asset.upload.content_type %></td>
16 <td><%= link_to 'Show', asset %></td> 23 <td><%= link_to 'Show', asset %></td>
17 <td><%= link_to 'Edit', edit_asset_path(asset) %></td> 24 <td><%= link_to 'Edit', edit_asset_path(asset) %></td>
18 <td><%= button_to 'Destroy', asset, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td> 25 <td><%= button_to asset, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } do %>
26 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
27 <% end %></td>
19 </tr> 28 </tr>
20<% end %> 29<% end %>
21</table> 30</table>
diff --git a/app/views/assets/show.html.erb b/app/views/assets/show.html.erb
index 694be5a..ff00883 100644
--- a/app/views/assets/show.html.erb
+++ b/app/views/assets/show.html.erb
@@ -1,23 +1,39 @@
1<% content_for :subnavigation do %> 1<div id="page_editor">
2 <%= link_to 'Edit', edit_asset_path(@asset) %> 2 <h1><%= @asset.name %></h1>
3 <%= link_to 'Back', assets_path %>
4<% end %>
5 3
6<table> 4 <div id="content">
7 <tr> 5 <div class="node_description">Actions</div>
8 <td>Thumbnail</td> 6 <div class="node_content node_info_group">
9 <td><%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %></td> 7 <div class="node_info_group_items">
10 </tr> 8 <div class="node_info_item">
11 <tr> 9 <%= link_to edit_asset_path(@asset), class: 'action_button' do %>
12 <td>Public Path</td> 10 <%= icon("edit", library: "tabler", "aria-hidden": true) %> Edit
13 <td><%= @asset.upload.url.sub(/\?\d+$/, "") %></td> 11 <% end %>
14 </tr> 12 </div>
15 <tr> 13 <div class="node_info_item">
16 <td>Content Type</td> 14 <%= link_to 'Back', assets_path %>
17 <td><%= @asset.upload.content_type %></td> 15 </div>
18 </tr> 16 </div>
19 <tr> 17 </div>
20 <td>Size</td> 18
21 <td><%= "#{@asset.upload.size/1024} KB" %></td> 19 <div class="node_description">Thumbnail</div>
22 </tr> 20 <div class="node_content"><%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %></div>
23</table> 21
22 <div class="node_description">Public Path</div>
23 <div class="node_content">
24 <% public_path = @asset.upload.url.sub(/\?\d+$/, "") %>
25 <%= link_to public_path, public_path, target: "_blank", rel: "noopener" %>
26 <button type="button" class="action_button copy_button"
27 data-copy-url="<%= request.base_url + public_path %>">
28 <%= icon("copy", library: "tabler", "aria-hidden": true) %>
29 <span class="copy_button_label">Copy URL</span>
30 </button>
31 </div>
32
33 <div class="node_description">Content Type</div>
34 <div class="node_content"><%= @asset.upload.content_type %></div>
35
36 <div class="node_description">Size</div>
37 <div class="node_content"><%= "#{@asset.upload.size/1024} KB" %></div>
38 </div>
39</div>
diff --git a/app/views/content/_open_erfas_today.html.erb b/app/views/content/_open_erfas_today.html.erb
new file mode 100644
index 0000000..468bedc
--- /dev/null
+++ b/app/views/content/_open_erfas_today.html.erb
@@ -0,0 +1,11 @@
1<div id="open_erfas_today">
2 <h2><%= t(:open_today) %></h2>
3 <ul class="teasertext">
4 <% occurrences.each do |occurrence| %>
5 <li>
6 <%= link_to_path occurrence.node.head.title, occurrence.node.unique_name %>
7 <span class="event_time"><%= weekday_abbr(occurrence.start_time) %>&nbsp;<%= occurrence.start_time.strftime("%H:%M") %></span>
8 </li>
9 <% end %>
10 </ul>
11</div>
diff --git a/app/views/custom/page_templates/public/chapter_detail.html.erb b/app/views/custom/page_templates/public/chapter_detail.html.erb
new file mode 100644
index 0000000..c4c2598
--- /dev/null
+++ b/app/views/custom/page_templates/public/chapter_detail.html.erb
@@ -0,0 +1,34 @@
1<div class="article" lang="<%= @page.effective_lang %>">
2 <h2 class="headline"><%= @page.title %></h2>
3 <%= headline_image %>
4 <% if @page.node.external_url.present? %>
5 <div class="chapter_url"><%= link_to @page.node.external_url, @page.node.external_url, target: '_blank', rel: 'noopener' %></div>
6 <% end %>
7 <p><%= sanitize(@page.abstract) %></p>
8 <%= aggregate?(@page.body) %>
9 <% open_days = @page.node.events.tagged_with('open-day').order(:start_time) %>
10 <% other_events = @page.node.events.where.not(id: open_days.map(&:id)).order(:start_time) %>
11 <% if open_days.any? %>
12 <div class="chapter_events open_days">
13 <h3><%= t(:open_days) %></h3>
14 <ul>
15 <% open_days.each do |event| %>
16 <li><%= event_schedule_text(event) %></li>
17 <% end %>
18 </ul>
19 </div>
20 <% end %>
21 <% if other_events.any? %>
22 <div class="chapter_events">
23 <h3><%= t(:upcoming_events) %></h3>
24 <ul>
25 <% other_events.each do |event| %>
26 <li>
27 <span class="event_title"><%= event.display_title %></span>
28 <span class="event_schedule"><%= event_schedule_text(event) %></span>
29 </li>
30 <% end %>
31 </ul>
32 </div>
33 <% end %>
34</div>
diff --git a/app/views/custom/partials/_chapter.html.erb b/app/views/custom/partials/_chapter.html.erb
new file mode 100644
index 0000000..47f3950
--- /dev/null
+++ b/app/views/custom/partials/_chapter.html.erb
@@ -0,0 +1,26 @@
1<div class="article_partial chapter_partial" lang="<%= page.effective_lang %>">
2 <div class="chapter_partial_layout">
3 <% if page.assets.images.any? %>
4 <%= link_to_path image_tag(page.assets.images.first.upload.url(:thumb), :alt => ""), page.node.unique_name, class: "chapter_thumbnail" %>
5 <% end %>
6 <div class="chapter_partial_content">
7 <h2 class="headline"><%= link_to_path page.title, page.node.unique_name %></h2>
8 <% if page.abstract.present? %>
9 <div class="chapter_location"><%= page.abstract %></div>
10 <% end %>
11 <% if page.node.external_url.present? %>
12 <div class="chapter_url"><%= link_to page.node.external_url, page.node.external_url, target: '_blank', rel: 'noopener' %></div>
13 <% end %>
14 <% open_days = page.node.events.tagged_with('open-day').order(:start_time) %>
15 <% if open_days.any? %>
16 <div class="chapter_open_days">
17 <span class="open_days_label"><%= t(:open_days_label) %>: </span>
18 <% open_days.each do |event| %>
19 <span class="event_schedule"><%= event_schedule_text(event) %></span>
20 <% end %>
21 </div>
22 <% end %>
23 <p class="excerpt"><%= sanitize page.body %></p>
24 </div>
25 </div>
26</div>
diff --git a/app/views/events/_rrule_builder.html.erb b/app/views/events/_rrule_builder.html.erb
new file mode 100644
index 0000000..1ffec0a
--- /dev/null
+++ b/app/views/events/_rrule_builder.html.erb
@@ -0,0 +1,33 @@
1<div id="rrule_builder">
2 <p>
3 <label><%= radio_button_tag "rrule_freq", "weekly", true %> Weekly</label>
4 <label><%= radio_button_tag "rrule_freq", "monthly" %> Monthly</label>
5 </p>
6 <div id="rrule_weekly_options">
7 <p><label><%= check_box_tag "rrule_biweekly" %> Every 2 weeks</label></p>
8 <p>
9 <% %w[MO TU WE TH FR SA SU].each do |code| %>
10 <label><%= check_box_tag "rrule_byday_#{code}" %> <%= RruleHumanizer::WEEKDAY_NAMES_ABBR[:de][code] %></label>
11 <% end %>
12 </p>
13 </div>
14 <div id="rrule_monthly_options" style="display: none;">
15 <p><label><%= check_box_tag "rrule_monthly_ordinal" %> On a specific weekday each month</label></p>
16 <p id="rrule_ordinal_fields" style="display: none;">
17 <%= select_tag "rrule_ordinal", options_for_select([["1.", 1], ["2.", 2], ["3.", 3], ["4.", 4], ["letzter", -1], ["vorletzter", -2], ["Selected weeks", "custom"]]) %>
18 <%= select_tag "rrule_ordinal_day", options_for_select(%w[MO TU WE TH FR SA SU].map { |c| [RruleHumanizer::WEEKDAY_NAMES[:de][c], c] }) %>
19 </p>
20 <p id="rrule_custom_ordinal_fields" style="display: none;">
21 Weeks of the month:
22 <% (1..5).each do |ordinal| %>
23 <label><%= check_box_tag "rrule_custom_ordinal_#{ordinal}" %> <%= ordinal %>.</label>
24 <% end %>
25 </p>
26 </div>
27 <p>
28 <label><%= check_box_tag "rrule_exclude_month" %> Except in one month</label>
29 <%= select_tag "rrule_excluded_month", options_for_select((1..12).map { |m| [RruleHumanizer::MONTH_NAMES[:de][m-1], m] }), style: "display: none;" %>
30 </p>
31 <span class="field_hint">Builds the field below automatically. If your pattern is more complex than this covers, just edit it directly below - these controls won't touch it unless you use them.</span>
32</div>
33<%= f.text_field :rrule, id: "event_rrule" %>
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb
index 17457df..4532ff2 100644
--- a/app/views/events/edit.html.erb
+++ b/app/views/events/edit.html.erb
@@ -1,53 +1,71 @@
1<% content_for :subnavigation do %>
2 <%= link_to 'back', safe_return_to(params[:return_to] || events_path) %>
3 <% if @event.node %>
4 <%= link_to 'node', edit_node_path(@event.node) %>
5 <% end %>
6 <%= link_to 'show', @event %>
7<% end %>
8
9<h1>Editing event</h1> 1<h1>Editing event</h1>
10 2
3<div class="node_action_bar standalone_action_bar">
4 <%= link_to 'Back', safe_return_to(params[:return_to] || events_path) %>
5 <%= button_to event_path(@event), method: :delete,
6 form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } do %>
7 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
8 <% end %>
9</div>
10
11<%= form_for(@event) do |f| %> 11<%= form_for(@event) do |f| %>
12 <%= hidden_field_tag :return_to, @return_to %> 12 <%= hidden_field_tag :return_to, @return_to %>
13 <%= form_error_messages(f) %> 13 <%= form_error_messages(f) %>
14 14
15 <p> 15 <div id="page_editor">
16 <%= f.label :start_time %><br /> 16 <div id="content">
17 <%= f.datetime_select :start_time %> 17 <div class="node_description">Node</div>
18 </p> 18 <div class="node_content">
19 <p> 19 <% if @event.node %>
20 <%= f.label :end_time %><br /> 20 <%= link_to @event.node.title, node_path(@event.node) %>
21 <%= f.datetime_select :end_time %> 21 <details>
22 </p> 22 <summary>Change node</summary>
23 <p> 23 <%= text_field_tag :event_node_search_term %>
24 <%= f.label :rrule %><br /> 24 <div id="event_search_results" class="search_results"></div>
25 <%= f.text_field :rrule %> 25 <span class="field_hint">This will re-link the event to a different node — rarely needed.</span>
26 </p> 26 </details>
27 <p> 27 <% else %>
28 <%= f.label :custom_rrule %><br /> 28 <%= text_field_tag :event_node_search_term %>
29 <%= f.check_box :custom_rrule %> 29 <div id="event_search_results" class="search_results"></div>
30 </p> 30 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span>
31 <p> 31 <% end %>
32 <%= f.label :allday %><br /> 32 <%= f.hidden_field :node_id %>
33 <%= f.check_box :allday %> 33 </div>
34 </p> 34
35 <p> 35 <div class="node_description">Start time</div>
36 <%= f.label :url %><br /> 36 <div class="node_content"><%= f.datetime_select :start_time %></div>
37 <%= f.text_field :url %> 37
38 </p> 38 <div class="node_description">End time</div>
39 <p> 39 <div class="node_content"><%= f.datetime_select :end_time %></div>
40 <%= f.label :latitude %><br /> 40
41 <%= f.text_field :latitude %> 41 <div class="node_description">Recurrence</div>
42 </p> 42 <div class="node_content">
43 <p> 43 <%= render "rrule_builder", f: f %>
44 <%= f.label :longitude %><br /> 44 </div>
45 <%= f.text_field :longitude %> 45
46 </p> 46 <div class="node_description">Title</div>
47 <p> 47 <div class="node_content">
48 <%= f.hidden_field :node_id %> 48 <%= f.text_field :title %>
49 </p> 49 <span id="event_title_hint" class="field_hint">Optional — if left blank, the associated node's title is used.</span>
50 <p> 50 </div>
51 <%= f.submit 'Update' %> 51
52 </p> 52 <div class="node_description">Tags</div>
53 <div class="node_content"><%= f.text_field :tag_list %></div>
54
55 <div class="node_description">Allday</div>
56 <div class="node_content"><%= f.check_box :allday %></div>
57
58 <div class="node_description">Url</div>
59 <div class="node_content"><%= f.text_field :url %></div>
60
61 <div class="node_description">Latitude</div>
62 <div class="node_content"><%= f.text_field :latitude %></div>
63
64 <div class="node_description">Longitude</div>
65 <div class="node_content"><%= f.text_field :longitude %></div>
66
67 <div class="node_description"></div>
68 <div class="node_content"><%= f.submit 'Update' %></div>
69 </div>
70 </div>
53<% end %> 71<% end %>
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb
index 19b21ce..dde897e 100644
--- a/app/views/events/index.html.erb
+++ b/app/views/events/index.html.erb
@@ -1,36 +1,40 @@
1<h1>Listing events</h1> 1<h1>Events</h1>
2 2
3<table> 3<div class="button_row">
4 <tr> 4 <%= link_to new_event_path, class: 'action_button' do %>
5 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create event
6 <% end %>
7 <%= link_to 'View events without a page →', without_node_events_path %>
8</div>
9
10<%= will_paginate @events %>
11
12<table class="events_table">
13 <tr class="header">
14 <th>Title</th>
5 <th>Start time</th> 15 <th>Start time</th>
6 <th>End time</th> 16 <th>End time</th>
7 <th>Rrule</th> 17 <th>Rrule</th>
8 <th>Custom rrule</th>
9 <th>Allday</th> 18 <th>Allday</th>
10 <th>Url</th> 19 <th>Url</th>
11 <th>Latitude</th>
12 <th>Longitude</th>
13 <th>Node</th> 20 <th>Node</th>
21 <th></th>
14 </tr> 22 </tr>
15 23
16<% @events.each do |event| %> 24<% @events.each do |event| %>
17 <tr> 25 <tr>
26 <td><%= link_to event.display_title, event %></td>
18 <td><%=h event.start_time %></td> 27 <td><%=h event.start_time %></td>
19 <td><%=h event.end_time %></td> 28 <td><%=h event.end_time %></td>
20 <td><%=h event.rrule %></td> 29 <td class="rrule_cell"><span class="rrule_text"><%= rrule_with_break_opportunities(event.rrule) %></span></td>
21 <td><%=h event.custom_rrule %></td>
22 <td><%=h event.allday %></td> 30 <td><%=h event.allday %></td>
23 <td><%=h event.url %></td> 31 <td class="url_cell">
24 <td><%=h event.latitude %></td> 32 <% if event.url.present? %>
25 <td><%=h event.longitude %></td> 33 <span class="truncate"><%= link_to event.url, event.url %></span>
26 <td><%=h event.node_id %></td> 34 <% end %>
27 <td><%= link_to 'Show', event %></td> 35 </td>
28 <td><%= link_to 'Edit', edit_event_path(event) %></td> 36 <td><%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %></td>
29 <td><%= button_to 'Destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td> 37 <td><%= link_to 'edit', edit_event_path(event) %></td>
30 </tr> 38 </tr>
31<% end %> 39<% end %>
32</table> 40</table>
33
34<br />
35
36<%= link_to 'New event', new_event_path %>
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb
index cd892c5..028fce7 100644
--- a/app/views/events/new.html.erb
+++ b/app/views/events/new.html.erb
@@ -1,46 +1,55 @@
1<h1>New event</h1> 1<h1>New event</h1>
2 2
3<%= link_to 'Back', safe_return_to(params[:return_to] || events_path) %>
4
3<%= form_for(@event) do |f| %> 5<%= form_for(@event) do |f| %>
4 <%= form_error_messages(f) %> 6 <%= form_error_messages(f) %>
5 7
6 <p> 8 <div id="page_editor">
7 <%= f.label :start_time %><br /> 9 <div id="content">
8 <%= f.datetime_select :start_time %> 10 <div class="node_description">Node</div>
9 </p> 11 <div class="node_content">
10 <p> 12 <%= text_field_tag :event_node_search_term %>
11 <%= f.label :end_time %><br /> 13 <div id="event_search_results" class="search_results"></div>
12 <%= f.datetime_select :end_time %> 14 <%= f.hidden_field :node_id %>
13 </p> 15 <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span>
14 <p> 16 </div>
15 <%= f.label :rrule %><br /> 17
16 <%= f.text_field :rrule %> 18 <div class="node_description">Start time</div>
17 </p> 19 <div class="node_content"><%= f.datetime_select :start_time %></div>
18 <p> 20
19 <%= f.label :custom_rrule %><br /> 21 <div class="node_description">End time</div>
20 <%= f.check_box :custom_rrule %> 22 <div class="node_content"><%= f.datetime_select :end_time %></div>
21 </p> 23
22 <p> 24 <div class="node_description">Recurrence</div>
23 <%= f.label :allday %><br /> 25 <div class="node_content"><%= render "rrule_builder", f: f %></div>
24 <%= f.check_box :allday %> 26
25 </p> 27 <div class="node_description">Title</div>
26 <p> 28 <div class="node_content">
27 <%= f.label :url %><br /> 29 <%= f.text_field :title %>
28 <%= f.text_field :url %> 30 <span id="event_title_hint" class="field_hint">Optional — if left blank, the associated node's title is used.</span>
29 </p> 31 </div>
30 <p> 32
31 <%= f.label :latitude %><br /> 33 <div class="node_description">Tags</div>
32 <%= f.text_field :latitude %> 34 <div class="node_content"><%= f.text_field :tag_list %></div>
33 </p>
34 <p>
35 <%= f.label :longitude %><br />
36 <%= f.text_field :longitude %>
37 </p>
38 <p>
39 <%= f.hidden_field :node_id %>
40 </p>
41 <p>
42 <%= f.submit 'Create' %>
43 </p>
44<% end %>
45 35
46<%= link_to 'Back', events_path %> 36 <div class="node_description">Allday</div>
37 <div class="node_content"><%= f.check_box :allday %></div>
38
39 <div class="node_description">Url</div>
40 <div class="node_content"><%= f.text_field :url %></div>
41
42 <div class="node_description">Latitude</div>
43 <div class="node_content"><%= f.text_field :latitude %></div>
44
45 <div class="node_description">Longitude</div>
46 <div class="node_content"><%= f.text_field :longitude %></div>
47
48 <div class="node_description"></div>
49 <div class="node_content"><%= hidden_field_tag :return_to, params[:return_to] %></div>
50
51 <div class="node_description"></div>
52 <div class="node_content"><%= f.submit 'Create' %></div>
53 </div>
54 </div>
55<% end %>
diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb
index ba14a7d..ac084c9 100644
--- a/app/views/events/show.html.erb
+++ b/app/views/events/show.html.erb
@@ -1,46 +1,55 @@
1<% content_for :subnavigation do %> 1<div id="page_editor" class="show_node">
2 <%= link_to 'back', edit_node_path(@event.node) %> 2 <h1><%= @event.node ? "Event for node #{@event.node.unique_name}" : "Event" %></h1>
3 <%= link_to 'edit', edit_event_path(@event) %>
4<% end %>
5 3
6<h2>Event for node <%= @event.node.unique_name %></h2> 4 <div id="content">
5 <div class="node_description">Actions</div>
6 <div class="node_content node_info_group">
7 <div class="node_info_group_items">
8 <% if @event.node %>
9 <div class="node_info_item">
10 <%= link_to 'Node', node_path(@event.node) %>
11 </div>
12 <% end %>
13 <div class="node_info_item">
14 <%= link_to edit_event_path(@event, return_to: request.path), class: 'action_button' do %>
15 <%= icon("edit", library: "tabler", "aria-hidden": true) %> Edit
16 <% end %>
17 </div>
18 <div class="node_info_item">
19 <%= button_to event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } do %>
20 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
21 <% end %>
22 </div>
23 </div>
24 </div>
7 25
8<p> 26 <div class="node_description">Start time</div>
9 <b>Start time:</b> 27 <div class="node_content"><%=h @event.start_time %></div>
10 <%=h @event.start_time %>
11</p>
12 28
13<p> 29 <div class="node_description">End time</div>
14 <b>End time:</b> 30 <div class="node_content"><%=h @event.end_time %></div>
15 <%=h @event.end_time %>
16</p>
17 31
18<p> 32 <div class="node_description">Rrule</div>
19 <b>Rrule:</b> 33 <div class="node_content"><%=h @event.rrule %></div>
20 <%=h @event.rrule %>
21</p>
22 34
23<p> 35 <% if (human = @event.humanize_rrule(I18n.locale)) %>
24 <b>Custom rrule:</b> 36 <div class="node_description">Recurrence</div>
25 <%=h @event.custom_rrule %> 37 <div class="node_content"><em><%= human %></em></div>
26</p> 38 <% end %>
27 39
28<p> 40 <div class="node_description">Tags</div>
29 <b>Allday:</b> 41 <div class="node_content"><%=h @event.tag_list %></div>
30 <%=h @event.allday %>
31</p>
32 42
33<p> 43 <div class="node_description">Allday</div>
34 <b>Url:</b> 44 <div class="node_content"><%=h @event.allday %></div>
35 <%=h @event.url %>
36</p>
37 45
38<p> 46 <div class="node_description">Url</div>
39 <b>Latitude:</b> 47 <div class="node_content"><%=h @event.url %></div>
40 <%=h @event.latitude %>
41</p>
42 48
43<p> 49 <div class="node_description">Latitude</div>
44 <b>Longitude:</b> 50 <div class="node_content"><%=h @event.latitude %></div>
45 <%=h @event.longitude %> 51
46</p> \ No newline at end of file 52 <div class="node_description">Longitude</div>
53 <div class="node_content"><%=h @event.longitude %></div>
54 </div>
55</div>
diff --git a/app/views/events/without_node.html.erb b/app/views/events/without_node.html.erb
new file mode 100644
index 0000000..bb27173
--- /dev/null
+++ b/app/views/events/without_node.html.erb
@@ -0,0 +1,30 @@
1<h1>Events without a node</h1>
2
3<%= link_to '← All events', events_path %>
4<%= link_to new_event_path, class: 'action_button' do %>
5 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create event
6<% end %>
7
8<%= will_paginate @events %>
9
10<table class="events_table">
11 <tr class="header">
12 <th>Title</th>
13 <th>Start time</th>
14 <th>End time</th>
15 <th>Allday</th>
16 <th>Url</th>
17 <th></th>
18 </tr>
19
20<% @events.each do |event| %>
21 <tr>
22 <td><%= link_to event.display_title, event %></td>
23 <td><%=h event.start_time %></td>
24 <td><%=h event.end_time %></td>
25 <td><%=h event.allday %></td>
26 <td><%=h event.url %></td>
27 <td><%= link_to 'edit', edit_event_path(event) %></td>
28 </tr>
29<% end %>
30</table>
diff --git a/app/views/layouts/admin.html.erb b/app/views/layouts/admin.html.erb
index 4536693..e220beb 100644
--- a/app/views/layouts/admin.html.erb
+++ b/app/views/layouts/admin.html.erb
@@ -7,16 +7,18 @@
7 <%= csrf_meta_tags %> 7 <%= csrf_meta_tags %>
8 8
9 <title><%= "#{params[:controller]} | #{params[:action]}" %></title> 9 <title><%= "#{params[:controller]} | #{params[:action]}" %></title>
10 <%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
11 <%= javascript_include_tag 'admin_bundle' %> 10 <%= javascript_include_tag 'admin_bundle' %>
12 <%= tinymce_assets %> 11 <%= tinymce_assets %>
13 <link rel="stylesheet" href="/stylesheets/admin.css"> 12 <link rel="stylesheet" href="<%= mtime_busted_path('/stylesheets/admin.css') %>">
14 <script src="/javascripts/admin_search.js"></script> 13 <script src="<%= mtime_busted_path('/javascripts/admin_search.js') %>"></script>
15 <script src="/javascripts/admin_interface.js"></script> 14 <script src="<%= mtime_busted_path('/javascripts/admin_interface.js') %>"></script>
16 <script> 15 <script src="<%= mtime_busted_path('/javascripts/related_assets.js') %>"></script>
16 <%= javascript_tag nonce: true do %>
17 var ADMIN_SEARCH_URL = "<%= admin_search_path %>"; 17 var ADMIN_SEARCH_URL = "<%= admin_search_path %>";
18 var ADMIN_MENU_SEARCH_URL = "<%= admin_menu_search_path %>"; 18 var ADMIN_MENU_SEARCH_URL = "<%= admin_menu_search_path %>";
19 </script> 19 var PARAMETERIZE_PREVIEW_URL = "<%= parameterize_preview_nodes_path %>";
20 var DASHBOARD_SEARCH_URL = "<%= admin_dashboard_search_path %>";
21 <% end %>
20 </head> 22 </head>
21 23
22 <body> 24 <body>
@@ -25,33 +27,36 @@
25 <div id="main_navigation"> 27 <div id="main_navigation">
26 <%= render :partial => 'admin/menu' if current_user %> 28 <%= render :partial => 'admin/menu' if current_user %>
27 </div> 29 </div>
28 <div id="sub_navigation"> 30 <div id="search_widget" style="display: none;">
29 <%= yield :subnavigation %> 31 <div>
32 <%= form_tag admin_search_path, method: :get do %>
33 <%= text_field_tag :search_term, nil, placeholder: "Search nodes…", autocomplete: "off" %>
34 <% end %>
35 </div>
36 <div id="menu_search_results" class="search_results" style="display: none"></div>
30 </div> 37 </div>
31 </div> 38 </div>
32 <div style="clear: both;"></div> 39 <div class="admin_content_spacer"></div>
40 <% if flash[:notice].present? || flash[:error].present? %>
33 <div id="flash"> 41 <div id="flash">
34 <%= flash[:notice] %> 42 <%= flash[:notice] %>
43 <% if flash[:status_path] %>
44 <%= link_to 'Go to Status', flash[:status_path] %>
45 <% end %>
46 <% if flash[:stale_locale_path] %>
47 The <%= flash[:stale_locale] %> translation may be out of date —
48 <%= link_to 'review it', flash[:stale_locale_path] %> too.
49 <% end %>
35 <% if flash[:error] %> 50 <% if flash[:error] %>
36 <span id="flash_error"><%= flash[:error] %></span> 51 <span id="flash_error"><%= flash[:error] %></span>
37 <% end %> 52 <% end %>
38 </div> 53 </div>
54 <% end %>
39 <div id="content"> 55 <div id="content">
40 <%= yield %> 56 <%= yield %>
41 </div> 57 </div>
42 58
43 <div id="results"></div> 59 <div id="results"></div>
44 </div> 60 </div>
45
46 <div id="search_widget" style="display: none;">
47 <div>
48 <%= form_tag admin_search_path, method: :get do %>
49 <span>Search: </span><%= text_field_tag :search_term, nil, autocomplete: "off" %>
50 <% end %>
51 </div>
52 <div id="search_results" style="display: none">
53
54 </div>
55 </div>
56 </body> 61 </body>
57</html> 62</html>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index edab5fc..f981fc1 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -10,20 +10,20 @@
10 <meta property="og:description" content="Der Chaos Computer Club ist eine galaktische Gemeinschaft von Lebewesen für Informationsfreiheit und Technikfolgenabschätzung." /> 10 <meta property="og:description" content="Der Chaos Computer Club ist eine galaktische Gemeinschaft von Lebewesen für Informationsfreiheit und Technikfolgenabschätzung." />
11 11
12 <title><%= page_title %></title> 12 <title><%= page_title %></title>
13 <link rel="stylesheet" href="/stylesheets/ccc.css"> 13 <link rel="stylesheet" href="<%= mtime_busted_path('/stylesheets/ccc.css') %>">
14 <link rel="stylesheet" href="/stylesheets/glightbox.min.css"> 14 <link rel="stylesheet" href="<%= mtime_busted_path('/stylesheets/glightbox.min.css') %>">
15 <script src="/javascripts/glightbox.min.js"></script> 15 <script src="<%= mtime_busted_path('/javascripts/glightbox.min.js') %>"></script>
16 <script src="/javascripts/public.js"></script> 16 <script src="<%= mtime_busted_path('/javascripts/public.js') %>"></script>
17 17
18 <%= auto_discovery_link_tag(:atom, '/rss/updates.xml', title: "ATOM") %> 18 <%= auto_discovery_link_tag(:atom, '/rss/updates.xml', title: "ATOM") %>
19 <%= auto_discovery_link_tag(:rss, '/rss/updates.rdf', title: "RSS") %> 19 <%= auto_discovery_link_tag(:rss, '/rss/updates.rdf', title: "RSS") %>
20 20
21 <script> 21 <%= javascript_tag nonce: true do %>
22 (function() { document.addEventListener("DOMContentLoaded", function() { 22 document.addEventListener("DOMContentLoaded", function() {
23 if (localStorage.getItem('override-prefers-color-scheme', false)) 23 if (localStorage.getItem('override-prefers-color-scheme'))
24 document.getElementById("light-mode").checked = true; 24 document.getElementById("light-mode").checked = true;
25 }); })(); 25 });
26 </script> 26 <% end %>
27 27
28 </head> 28 </head>
29 29
@@ -62,16 +62,15 @@
62 <div id="center_column"> 62 <div id="center_column">
63 <%= yield :layout %> 63 <%= yield :layout %>
64 <div id="footer"> 64 <div id="footer">
65 <br />
66 <p style="text-align: center"> 65 <p style="text-align: center">
67 <%= link_to "Impressum", content_path("imprint") %> 66 <%= link_to "Impressum", content_path("imprint") %>
68 <%= link_to "Datenschutz", content_path("datenschutz") %> 67 <%= link_to "Datenschutz", content_path("datenschutz") %>
69 <%= language_selector %> 68 <%= language_selector %>
70 <!-- %= link_to t(:sponsors), content_path("sponsors") % -->
71 </p> 69 </p>
72 </div> 70 </div>
73 </div> 71 </div>
74 <div id="right_column"> 72 <div id="right_column">
73 <%= open_erfas_today %>
75 <%= tags %> 74 <%= tags %>
76 <%= featured_articles %> 75 <%= featured_articles %>
77 </div> 76 </div>
diff --git a/app/views/layouts/events.html.erb b/app/views/layouts/events.html.erb
deleted file mode 100644
index 93a6c0c..0000000
--- a/app/views/layouts/events.html.erb
+++ /dev/null
@@ -1,17 +0,0 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
4<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5<head>
6 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7 <title>Events: <%= controller.action_name %></title>
8 <%= stylesheet_link_tag 'scaffold' %>
9</head>
10<body>
11
12<p style="color: green"><%= flash[:notice] %></p>
13
14<%= yield %>
15
16</body>
17</html>
diff --git a/app/views/menu_items/edit.html.erb b/app/views/menu_items/edit.html.erb
index 9891708..44e5a79 100644
--- a/app/views/menu_items/edit.html.erb
+++ b/app/views/menu_items/edit.html.erb
@@ -1,32 +1,25 @@
1<h1>Edit Menu Item</h1> 1<h1>Edit Menu Item</h1>
2 2
3<%= form_for @menu_item do |f| %> 3<div id="page_editor">
4 <table> 4 <%= form_for @menu_item do |f| %>
5 5 <div id="content">
6 <tr> 6 <div class="node_description">Search</div>
7 <td class="description">Search</td> 7 <div class="node_content">
8 <td> 8 <%= text_field_tag :menu_search_term %>
9 <%= text_field_tag :menu_search_term %> 9 <div id="menu_item_search_results" class="search_results"></div>
10 <div id="search_results"> 10 </div>
11 11
12 </div> 12 <div class="node_description">Node Id</div>
13 </td> 13 <div class="node_content"><%= f.text_field :node_id %></div>
14 </tr> 14
15 <tr> 15 <div class="node_description">Path</div>
16 <td class="description">Node Id</td> 16 <div class="node_content"><%= f.text_field :path %></div>
17 <td><%= f.text_field :node_id %></td> 17
18 </tr> 18 <div class="node_description">Title</div>
19 <tr> 19 <div class="node_content"><%= f.text_field :title %></div>
20 <td class="description">Path</td> 20
21 <td><%= f.text_field :path %></td> 21 <div class="node_description"></div>
22 </tr> 22 <div class="node_content"><%= f.submit 'Update' %></div>
23 <tr> 23 <% end %>
24 <td class="description">Title</td> 24 </div>
25 <td><%= f.text_field :title %></td> 25</div>
26 </tr>
27 <tr>
28 <td></td>
29 <td class="right"><%= f.submit 'Update' %></td>
30 </tr>
31 </table>
32<% end %>
diff --git a/app/views/menu_items/index.html.erb b/app/views/menu_items/index.html.erb
index c52c150..591eb68 100644
--- a/app/views/menu_items/index.html.erb
+++ b/app/views/menu_items/index.html.erb
@@ -1,10 +1,9 @@
1<% content_for :subnavigation do %>
2 <%= link_to "new", new_menu_item_path %>
3<% end %>
4
5
6<h1>Menu Items</h1> 1<h1>Menu Items</h1>
7 2
3<%= link_to new_menu_item_path, class: 'action_button' do %>
4 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create menu item
5<% end %>
6
8<table id="menu_item_list"> 7<table id="menu_item_list">
9 <% @menu_items.each do |menu_item| %> 8 <% @menu_items.each do |menu_item| %>
10 <tr id="menu_items-<%= menu_item.id %>"> 9 <tr id="menu_items-<%= menu_item.id %>">
@@ -14,9 +13,10 @@
14 <td class="menu_item_title"><%= menu_item.title %></td> 13 <td class="menu_item_title"><%= menu_item.title %></td>
15 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td> 14 <td><%= link_to "Edit", edit_menu_item_path(menu_item) %></td>
16 <td> 15 <td>
17 <%= button_to "Delete", menu_item_path(menu_item), 16 <%= button_to menu_item_path(menu_item), method: :delete,
18 method: :delete, 17 form: { data: { confirm: "Do you really want to destroy the menu entry?" }, class: 'button_to destructive' } do %>
19 form: { data: { confirm: "Are you sure?" } } %> 18 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
19 <% end %>
20 </td> 20 </td>
21 </tr> 21 </tr>
22 <% end %> 22 <% end %>
diff --git a/app/views/menu_items/new.html.erb b/app/views/menu_items/new.html.erb
index 68081d0..8957293 100644
--- a/app/views/menu_items/new.html.erb
+++ b/app/views/menu_items/new.html.erb
@@ -1,32 +1,20 @@
1<h1>Add Menu Item</h1> 1<h1>Add Menu Item</h1>
2 2
3<%= form_for @menu_item do |f| %> 3<%= form_for @menu_item do |f| %>
4 <table> 4 <div class="node_description">Search</div>
5 5 <div class="node_content">
6 <tr> 6 <%= text_field_tag :menu_search_term %>
7 <td class="description">Search</td> 7 <div id="menu_item_search_results" class="search_results"></div>
8 <td> 8 </div>
9 <%= text_field_tag :menu_search_term %>
10 <div id="search_results">
11 9
12 </div> 10 <div class="node_description">Node Id</div>
13 </td> 11 <div class="node_content"><%= f.text_field :node_id %></div>
14 </tr> 12
15 <tr> 13 <div class="node_description">Path</div>
16 <td class="description">Node Id</td> 14 <div class="node_content"><%= f.text_field :path %></div>
17 <td><%= f.text_field :node_id %></td> 15
18 </tr> 16 <div class="node_description">Title</div>
19 <tr> 17 <div class="node_content"><%= f.text_field :title %></div>
20 <td class="description">Path</td> 18
21 <td><%= f.text_field :path %></td> 19 <div class="node_content"><%= f.submit 'Create' %></div>
22 </tr>
23 <tr>
24 <td class="description">Title</td>
25 <td><%= f.text_field :title %></td>
26 </tr>
27 <tr>
28 <td></td>
29 <td class="right"><%= f.submit 'Create' %></td>
30 </tr>
31 </table>
32<% end %> 20<% end %>
diff --git a/app/views/node_actions/_action_row.html.erb b/app/views/node_actions/_action_row.html.erb
new file mode 100644
index 0000000..a9a3b8d
--- /dev/null
+++ b/app/views/node_actions/_action_row.html.erb
@@ -0,0 +1,18 @@
1<tr class="node_action node_action--<%= action.action %>">
2 <td class="node_action_time">
3 <span class="node_action_date"><%= action.occurred_at.strftime("%Y-%m-%d") %></span>
4 <%= verb_icon(action) %>
5 <span class="node_action_clock"><%= action.occurred_at.strftime("%H:%M") %></span>
6 </td>
7 <td class="node_action_body">
8 <%= action_summary(action) %>
9 <% if action.node_id && params[:node_id].blank? %>
10 <%= link_to t("node_actions.node_history"), admin_log_path(:node_id => action.node_id), :class => "node_action_zoom" %>
11 <% end %>
12 <% if action.inferred_from %>
13 <span class="node_action_inferred" title="<%= action.inferred_from %>"><%= t("node_actions.backfilled") %></span>
14 <% end %>
15 <%= render "node_actions/change_details", :action_entry => action if action_details?(action) %>
16 </td>
17</tr>
18
diff --git a/app/views/node_actions/_change_details.html.erb b/app/views/node_actions/_change_details.html.erb
new file mode 100644
index 0000000..066d0f3
--- /dev/null
+++ b/app/views/node_actions/_change_details.html.erb
@@ -0,0 +1,35 @@
1<details class="node_action_details">
2 <summary><%= t("node_actions.show_changes") %></summary>
3 <table>
4 <% if (default_items = default_locale_changes(action_entry)).any? %>
5 <tr>
6 <th><%= I18n.default_locale.to_s.upcase %></th>
7 <td>
8 <%= safe_join(default_items, tag.br) %>
9 <% if action_entry.page && action_entry.node %>
10 <% if (diff_params = action_entry.diff_link_params) %>
11 <%= link_to t("node_actions.view_diff"), diff_node_revisions_path(action_entry.node, diff_params) %>
12 <% else %>
13 <%= link_to t("node_actions.view_revision"), node_revision_path(action_entry.node, action_entry.page) %>
14 <% end %>
15 <% end %>
16 </td>
17 </tr>
18 <% end %>
19 <% (action_entry.metadata["translation_diff"] || {}).each do |locale, diff| %>
20 <tr>
21 <th><%= locale.upcase %></th>
22 <td>
23 <%= safe_join(translation_changes(diff), tag.br) %>
24 <% if action_entry.page && action_entry.node %>
25 <% if (diff_params = action_entry.diff_link_params) %>
26 <%= link_to t("node_actions.view_diff"), diff_node_revisions_path(action_entry.node, diff_params.merge(:locale => locale)) %>
27 <% else %>
28 <%= link_to t("node_actions.view_revision"), node_revision_path(action_entry.node, action_entry.page, :locale => locale) %>
29 <% end %>
30 <% end %>
31 </td>
32 </tr>
33 <% end %>
34 </table>
35</details>
diff --git a/app/views/node_actions/index.html.erb b/app/views/node_actions/index.html.erb
new file mode 100644
index 0000000..20ef5b3
--- /dev/null
+++ b/app/views/node_actions/index.html.erb
@@ -0,0 +1,13 @@
1<h1><%= t("node_actions.heading") %></h1>
2
3<% if params[:node_id].present? || params[:user_id].present? %>
4 <p><%= link_to t("node_actions.show_all"), admin_log_path %></p>
5<% end %>
6
7<%= will_paginate @actions %>
8
9<table id="node_action_list">
10 <%= render partial: "node_actions/action_row", collection: @actions, as: :action %>
11</table>
12
13<%= will_paginate @actions %>
diff --git a/app/views/nodes/_node_list.html.erb b/app/views/nodes/_node_list.html.erb
new file mode 100644
index 0000000..f7210f1
--- /dev/null
+++ b/app/views/nodes/_node_list.html.erb
@@ -0,0 +1,41 @@
1<%= form_tag url_for(controller: params[:controller], action: params[:action]), method: :get, class: "node_search_form" do %>
2 <% Array(params[:kinds]).each do |kind| %>
3 <%= hidden_field_tag "kinds[]", kind %>
4 <% end %>
5 <%= hidden_field_tag :tags, params[:tags] if params[:tags].present? %>
6 <%= text_field_tag :q, params[:q], placeholder: "Search title, abstract, body…" %>
7 <%= button_tag type: "submit", class: "action_button" do %>
8 <%= icon("search", library: "tabler", "aria-hidden": true) %> Search
9 <% end %>
10 <% if params[:q].present? || params[:kinds].present? || params[:tags].present? %>
11 <%= link_to "Reset", url_for(controller: params[:controller], action: params[:action]) %>
12 <% end %>
13<% end %>
14
15<%= will_paginate @nodes %>
16<table class="node_table">
17 <tr class="header">
18 <th class="node_id">ID</th>
19 <th class="title">Title</th>
20 <th class="actions">Actions</th>
21 <th class="editor">Locked by</th>
22 <th class="revision">Rev.</th>
23 </tr>
24 <% @nodes.each do |node| %>
25 <tr class="<%= cycle("even", "odd") %>">
26 <td class="node_id"><%= node.id %></td>
27 <td class="title">
28 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
29 <p><%= link_to_path(node.unique_name, node.unique_name) %></p>
30 </td>
31 <td class="actions">
32 <%= link_to 'show', node_path(node) %>
33 <%= link_to 'edit', edit_node_path(node) %>
34 <%= link_to 'revisions', node_revisions_path(node) %>
35 </td>
36 <td><%= node.lock_owner.login if node.lock_owner %></td>
37 <td><%= node.draft ? node.draft.revision : (node.head ? node.head.revision : "EMPTY") %></td>
38 </tr>
39 <% end %>
40</table>
41<%= will_paginate @nodes %>
diff --git a/app/views/nodes/_recent_change_item.html.erb b/app/views/nodes/_recent_change_item.html.erb
new file mode 100644
index 0000000..754a775
--- /dev/null
+++ b/app/views/nodes/_recent_change_item.html.erb
@@ -0,0 +1,9 @@
1<li>
2 <div>
3 <%= link_to title_for_node(node), node_path(node) %>
4 <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span>
5 </div>
6 <span class="dashboard_widget_meta">
7 <%= (editor = node_head_editor(node)) ? t("last_edited_by", editor: editor) : t("last_edited") %>, <%= relative_time_phrase(node.head.updated_at) %>
8 </span>
9</li>
diff --git a/app/views/nodes/chapters.html.erb b/app/views/nodes/chapters.html.erb
new file mode 100644
index 0000000..543bc53
--- /dev/null
+++ b/app/views/nodes/chapters.html.erb
@@ -0,0 +1,11 @@
1<h1>Chapters</h1>
2
3<%= form_tag chapters_nodes_path, method: :get, class: "node_search_form" do %>
4 <label><%= check_box_tag 'kinds[]', 'erfa', @kind_keys.include?('erfa') %> Erfa</label>
5 <label><%= check_box_tag 'kinds[]', 'chaostreff', @kind_keys.include?('chaostreff') %> Chaostreff</label>
6 <%= button_tag type: "submit", class: "action_button" do %>
7 <%= icon("filter", library: "tabler", "aria-hidden": true) %> Filter
8 <% end %>
9<% end %>
10
11<%= render 'node_list' %>
diff --git a/app/views/nodes/destroy.html.erb b/app/views/nodes/destroy.html.erb
deleted file mode 100644
index 065cf1d..0000000
--- a/app/views/nodes/destroy.html.erb
+++ /dev/null
@@ -1,2 +0,0 @@
1<h1>Nodes#destroy</h1>
2<p>Find me in app/views/nodes/destroy.html.erb</p>
diff --git a/app/views/nodes/drafts.html.erb b/app/views/nodes/drafts.html.erb
new file mode 100644
index 0000000..6d0830c
--- /dev/null
+++ b/app/views/nodes/drafts.html.erb
@@ -0,0 +1,3 @@
1<h1>Nodes with drafts or autosaves</h1>
2
3<%= render 'node_list' %>
diff --git a/app/views/nodes/edit.html.erb b/app/views/nodes/edit.html.erb
index 498fa1f..25f15c2 100644
--- a/app/views/nodes/edit.html.erb
+++ b/app/views/nodes/edit.html.erb
@@ -1,79 +1,116 @@
1<% content_for :subnavigation do %> 1<h1><%= title_for_node(@node) %></h1>
2 <%= link_to 'metadata', '#', :id => 'button', :class => "unselected" %> 2
3 <%= link_to 'Show', @node %> 3<div class="node_action_bar">
4 <%= link_to 'Preview', preview_page_path(@draft) %> 4 <%= button_to 'Unlock + Back', unlock_node_path(@node), method: :put,
5 <%= button_to 'Publish', publish_node_path(@node), method: :put, form: { data: { confirm: "Publish this draft?" } } %> 5 form: { class: 'button_to state_changing' },
6 <%= link_to 'Revisions', node_revisions_path(@node) %> 6 disabled: @node.autosave.present? %>
7<% end %> 7
8 <% if @node.autosave || (@node.draft && @node.head) %>
9 <%= button_to revert_node_path(@node), method: :put,
10 form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } do %>
11 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
12 <%= @node.draft && !@node.autosave ? "Destroy Draft" : "Discard Autosave" %>
13 <% end %>
14 <% if pair = @node.available_layer_pairs.find { |p| p.include?(:autosave) } %>
15 <%= button_to 'What changed?',
16 diff_node_revisions_path(@node),
17 method: :get,
18 params: { start_revision: pair.first, end_revision: pair.last },
19 form: { class: 'button_to computation' } %>
20 <% end %>
21 <% end %>
22
23 <%= submit_tag "Save Draft", form: dom_id(@node, :edit) %>
24 <%= submit_tag "Save + Unlock + Exit", form: dom_id(@node, :edit) %>
25 <%= link_to "Preview ↗", preview_page_path(@page), target: "_blank", rel: "noopener", class: "preview_link" %>
26</div>
8 27
9<div id="page_editor"> 28<div id="page_editor">
10<%= form_for(@node) do |f| %> 29 <%= form_for(@node, html: { data: { autosave_url: autosave_node_path(@node), show_url: node_path(@node) } }) do |f| %>
11 <% if @node.errors.any? %> 30 <% if @node.errors.any? %>
12 <div class="error_messages"> 31 <div class="error_messages">
13 <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>
14 </div> 33 </div>
15 <% end %> 34 <% end %>
16
17 <div id="metadata">
18 <div class="node_description">Event</div>
19 <div class="node_content"><%= event_information %></div>
20
21 <div class="node_description">Slug</div>
22 <div class="node_content">
23 <%= f.text_field(
24 :staged_slug, :value => @node.staged_slug || @node.slug
25 )
26 %>
27 </div>
28 35
29 <div class="node_description">parent</div> 36 <details id="metadata_details">
30 <div class="node_content"> 37 <summary>Metadata (slug, parent, tags, template, author, images)</summary>
31 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %> 38 <div id="metadata">
32 <div id="search_results"> 39 <div class="node_description">Slug</div>
40 <div class="node_content">
41 <%= f.text_field(
42 :staged_slug, :value => @node.staged_slug || @node.slug
43 )
44 %>
45 </div>
33 46
34 </div> 47 <div class="node_description">parent</div>
48 <div class="node_content">
49 <%= text_field_tag :move_to_search_term, @node.parent.title rescue "" %>
50 <div id="move_to_search_results" class="search_results"></div>
35 <%= f.hidden_field( 51 <%= f.hidden_field(
36 :staged_parent_id, 52 :staged_parent_id,
37 :value => @node.staged_parent_id || @node.parent_id 53 :value => @node.staged_parent_id || @node.parent_id
38 ) 54 )
39 %> 55 %>
40 </div> 56 </div>
41
42 <%= fields_for @draft do |d| %>
43 <div class="node_description">Tags - comma seperated</div>
44 <div class="node_content"><%= text_field_tag :tag_list, @draft.tag_list.join(', ') %></div>
45 57
46 <div class="node_description">Publish at</div> 58 <%= fields_for @page do |d| %>
47 <div class="node_content"><%= d.datetime_select :published_at, :value => @draft.published_at %></div> 59 <div class="node_description">Tags - comma seperated</div>
60 <div class="node_content"><%= text_field_tag :tag_list, @page.tag_list.join(', ') %></div>
48 61
49 <div class="node_description">Template</div> 62 <div class="node_description">Publish at</div>
50 <div class="node_content"><%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %></div> 63 <div class="node_content"><%= d.datetime_select :published_at, :value => @page.published_at %></div>
51 64
52 <div class="node_description">Author</div> 65 <div class="node_description">Template</div>
53 <div class="node_content"><%= d.select :user_id, user_list %></div> 66 <div class="node_content">
67 <%= d.select :template_name, custom_page_templates, {:prompt => 'Select Template'} %>
68 <span class="field_hint">Set automatically based on how this node was created - change it if needed.</span>
69 </div>
54 70
55 <div class="node_description">Images</div> 71 <div class="node_description">Author</div>
56 <div class="node_content"> 72 <div class="node_content">
57 <ul id="image_box" rel="<%= @draft.id %>"> 73 <%= d.select :user_id, user_list,
58 <% @draft.assets.images.each do |image| %> 74 :selected => @page.user_id || @node.draft&.user_id || @node.head&.user_id %>
59 <li rel="images_<%= image.id %>">
60 <%= image_tag(image.upload.url(:thumb)) %>
61 </li>
62 <% end %>
63 </ul>
64 <div class="clear_left right">
65 <a id="image_browser_toggle" class="unselected" href="#">image browser</a>
66 </div> 75 </div>
67 <div id="image_browser"> 76
68 <ul> 77 <div class="node_description">Images</div>
69 <% Asset.images.each do |image| %> 78 <div class="node_content">
70 <li rel="images_<%= image.id %>"><%= image_tag(image.upload.url(:thumb)) %></li> 79 <div id="related_assets"
71 <% end %> 80 data-search-url="<%= search_node_related_assets_path(@node) %>"
72 </ul> 81 data-create-url="<%= node_related_assets_path(@node) %>">
82 <ul id="related_asset_list" class="thumbnail_list">
83 <% @page.related_assets.includes(:asset).each do |related| %>
84 <li data-url="<%= node_related_asset_path(@node, related) %>"
85 data-large-url="<%= related.asset.upload.url(:large) %>"
86 data-original-url="<%= related.asset.upload.url %>"
87 data-name="<%= related.asset.name %>">
88 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span>
89 <%= image_tag related.asset.upload.url(:thumb) %>
90 <button type="button" class="related_asset_remove" aria-label="Remove image">
91 <%= icon("x", library: "tabler", "aria-hidden": true) %>
92 </button>
93 </li>
94 <% end %>
95 </ul>
96 <%= text_field_tag nil, nil, id: "related_asset_search_term", placeholder: "Search images to attach…", autocomplete: "off" %>
97 <div id="related_asset_search_results" class="search_results"></div>
98 </div>
73 </div> 99 </div>
100
101 <template id="related_asset_template">
102 <li>
103 <span class="related_asset_handle"><%= icon("grip-vertical", library: "tabler", "aria-hidden": true) %></span>
104 <img src="">
105 <button type="button" class="related_asset_remove" aria-label="Remove image">
106 <%= icon("x", library: "tabler", "aria-hidden": true) %>
107 </button>
108 </li>
109 </template>
110
74 </div> 111 </div>
75 </div> 112 </details>
76 113
77 <div id="content"> 114 <div id="content">
78 <div class="node_description">Title</div> 115 <div class="node_description">Title</div>
79 <div class="node_content"><%= d.text_field :title %></div> 116 <div class="node_content"><%= d.text_field :title %></div>
@@ -82,9 +119,29 @@
82 <div class="node_content"><%= d.text_area :abstract %></div> 119 <div class="node_content"><%= d.text_area :abstract %></div>
83 120
84 <div class="node_description">Body</div> 121 <div class="node_description">Body</div>
85 <div class="node_content"><%= d.text_area :body, :class => 'with_editor' %></div> 122 <div class="body_toolbar_row">
123 <button type="button" id="preview_toggle" class="view_toggle" aria-pressed="false" aria-label="Toggle live preview" title="Toggle live preview">
124 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span>Live preview</span>
125 </button>
126 <button type="button" id="preview_force_render" class="view_toggle" style="display:none" aria-label="Force preview render" title="Force preview render">
127 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span>Force refresh</span>
128 </button>
129 </div>
86 130
87 <div><%= d.submit 'save' %></div> 131 <div id="editor_and_preview">
132 <div class="preview_content">
133 <div class="node_content"><%= d.text_area :body, :class => 'with_editor' %></div>
134 </div>
135 <div id="preview_panel" style="display:none">
136 <iframe id="live_preview_iframe" title="Live preview" data-src="<%= preview_page_path(@page, :locale => I18n.default_locale) %>"></iframe>
137 </div>
138 </div>
139 </div>
140 <% end %>
141
142 <div class="node_action_bar">
143 <%= f.submit 'Save Draft' %>
144 <%= f.submit 'Save + Unlock + Exit' %>
145 </div>
88 <% end %> 146 <% end %>
89<% end %>
90</div> 147</div>
diff --git a/app/views/nodes/index.html.erb b/app/views/nodes/index.html.erb
index e5a55d4..3bb251c 100644
--- a/app/views/nodes/index.html.erb
+++ b/app/views/nodes/index.html.erb
@@ -1,8 +1,12 @@
1<% content_for :subnavigation do %>
2 <%= link_to 'Create', new_node_path %>
3<% end %>
4<h1>Nodes</h1> 1<h1>Nodes</h1>
5 2
3<div>
4 <%= link_to new_node_path, class: 'action_button' do %>
5 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create node
6 <% end %>
7 <span class="field_hint">Creates a node with no parent or kind set — for a specific page, use the wizard's create flow or "add child" from an existing node instead.</span>
8</div>
9
6<%= will_paginate @nodes %> 10<%= will_paginate @nodes %>
7 <table class="node_table"> 11 <table class="node_table">
8 <tr class="header"> 12 <tr class="header">
@@ -21,7 +25,8 @@
21 </td> 25 </td>
22 <td class="actions"> 26 <td class="actions">
23 <%= link_to 'show', node_path(node) %> 27 <%= link_to 'show', node_path(node) %>
24 <%= link_to 'Revisions', node_revisions_path(node) %> 28 <%= link_to 'edit', edit_node_path(node) %>
29 <%= link_to 'revisions', node_revisions_path(node) %>
25 </td> 30 </td>
26 <td> 31 <td>
27 <%= node.lock_owner.login if node.lock_owner %> 32 <%= node.lock_owner.login if node.lock_owner %>
diff --git a/app/views/nodes/mine.html.erb b/app/views/nodes/mine.html.erb
new file mode 100644
index 0000000..fc5680a
--- /dev/null
+++ b/app/views/nodes/mine.html.erb
@@ -0,0 +1,3 @@
1<h1>My work</h1>
2
3<%= render 'node_list' %>
diff --git a/app/views/nodes/new.html.erb b/app/views/nodes/new.html.erb
index 028d727..805fbc9 100644
--- a/app/views/nodes/new.html.erb
+++ b/app/views/nodes/new.html.erb
@@ -6,48 +6,50 @@
6 </div> 6 </div>
7<% end %> 7<% end %>
8 8
9<p>What kind of node do you want to create?</p>
10
11<%= form_tag nodes_path do %> 9<%= form_tag nodes_path do %>
12<table id="new_node"> 10<div id="new_node">
13 <tr> 11
14 <td class="description">Type</td> 12 <div class="node_description">Type</div>
15 <td> 13 <div class="node_content">
16 <div> 14 <% CccConventions::NODE_KINDS.each do |kind, config| %>
17 <%= radio_button_tag :kind, "top_level" %>
18 Top Level
19 </div>
20 <p>
21 <%= radio_button_tag :kind, "generic", :selected => true %>
22 Generic ( can be created anywhere )
23 </p>
24 <p>
25 <%= radio_button_tag :kind, "update" %>
26 Update ( is automatically created in /updates/<%= Time.now.year.to_s %>/ and gets tag "update" )
27 </p>
28 <p> 15 <p>
29 <%= radio_button_tag :kind, "press_release" %> 16 <%= radio_button_tag :kind, kind, kind == @selected_kind,
30 Pressemitteilung ( is automatically created in /updates/<%= Time.now.year.to_s %>/ and gets tags "update, pressemitteilung" ) 17 data: { path_prefix: resolve_kind_text(config[:path_prefix]) } %>
18 <%= resolve_kind_text(config[:label]) %>
19 <% if config[:hint] %>
20 <span class="field_hint"><%= resolve_kind_text(config[:hint]) %></span>
21 <% end %>
31 </p> 22 </p>
32 </td> 23 <% end %>
33 </tr> 24 </div>
34 <tr> 25
35 <td class="description">Title</td> 26 <div class="node_description">Title</div>
36 <td><%= text_field_tag :title %></td> 27 <div class="node_content">
37 </tr> 28 <%= text_field_tag :title, nil, required: true %>
38 <tr id="parent_search_field"> 29 <span class="field_hint">A URL slug will be generated from this automatically. You can review or adjust it afterward under the "metadata" section's Slug field.</span>
39 <td class="description">Parent</td> 30 </div>
40 <td> 31
41 <%= text_field_tag :parent_search_term, @parent_name %> 32 <div id="parent_search_field" style="<%= @selected_kind == "generic" ? "" : "display: none;" %>">
42 <%= hidden_field_tag :parent_id, @parent_id %> 33 <div class="node_description">Parent</div>
43 <div id="search_results"> 34 <div class="node_content">
35 <%= text_field_tag :parent_search_term, @parent&.title %>
36 <%= hidden_field_tag :parent_id, @parent&.id, data: { unique_name: @parent&.computed_unique_name } %>
37 <div id="parent_search_results" class="search_results"></div>
38 </div>
39 </div>
40
41 <div class="node_description">Resulting path</div>
42 <div class="node_content">
43 <span id="resulting_path">—</span>
44 <button type="button" id="copy_resulting_path" class="unselected copy_button" data-copy-target="#resulting_path">
45 <span class="copy_button_label">copy</span>
46 </button>
47
48 <span class="field_hint">This preview updates as you type. The final path can still be changed afterward by editing the title (for the last segment) or moving the node to a different parent (for everything before it).</span>
49 </div>
50
51 <div class="node_description"></div>
52 <div class="node_content"><%= submit_tag "Create" %></div>
44 53
45 </div> 54</div>
46 </td>
47 </tr>
48 <tr>
49 <td></td>
50 <td class="right"><%= submit_tag "Create" %></td>
51 </tr>
52</table>
53<% end %> 55<% end %>
diff --git a/app/views/nodes/recent.html.erb b/app/views/nodes/recent.html.erb
new file mode 100644
index 0000000..d256253
--- /dev/null
+++ b/app/views/nodes/recent.html.erb
@@ -0,0 +1,7 @@
1<h1>Recently changed</h1>
2
3<%= will_paginate @nodes %>
4<ul id="recent_changes_full_list">
5 <%= render partial: "nodes/recent_change_item", collection: @nodes, as: :node %>
6</ul>
7<%= will_paginate @nodes %>
diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb
index de4d8a2..af05778 100644
--- a/app/views/nodes/show.html.erb
+++ b/app/views/nodes/show.html.erb
@@ -1,62 +1,316 @@
1<% content_for :subnavigation do %> 1<% locked_by_other = @node.locked? && @node.lock_owner != current_user %>
2 <%= link_to 'Edit', edit_node_path(@node), :class => "unselected" %> 2<div id="page_editor" class="show_node">
3 <%= link_to 'Preview', preview_page_path(@page) %> 3 <h1><%= title_for_node(@node) %> <small>(<%= I18n.default_locale.to_s.upcase %>)</small></h1>
4 <%= link_to 'Revisions', node_revisions_path(@node) %> 4 <div id="content">
5 <%= unlock_link if @node.locked? %> 5 <div class="node_description">Status</div>
6<% end %> 6 <div class="node_content node_info_group node_status">
7 <div class="node_info_group_items">
8 <div class="node_info_item">
9 <span class="node_info_label">Head</span>
10 <%= @node.head ? "#{@node.head.title} (rev #{@node.head.revision}, #{@node.head.updated_at})" : "none — never published" %>
11 </div>
12 <div class="node_info_item">
13 <span class="node_info_label">Draft</span>
14 <%= @node.draft ? "#{@node.draft.title} (rev #{@node.draft.revision}, saved #{@node.draft.updated_at})" : "none" %>
15 </div>
16 <div class="node_info_item">
17 <span class="node_info_label">Autosave</span>
18 <%= @node.autosave ? "#{@node.autosave.title} (unsaved, #{@node.autosave.updated_at})" : "none" %>
19 </div>
20 </div>
7 21
22 <% edit_label = @node.autosave ? "Continue Editing" : (@node.draft ? "Edit Draft" : "Edit") %>
23 <div class="node_info_group_items">
24 <div class="node_info_item">
25 <% if locked_by_other %>
26 <span class="disabled_action"><%= edit_label %></span>
27 <% else %>
28 <%= link_to edit_node_path(@node), class: "action_button" do %>
29 <%= icon("edit", library: "tabler", "aria-hidden": true) %>
30 <%= @node.autosave ? "Continue Editing" : (@node.draft ? "Edit Draft" : "Lock + Edit") %>
31 <% end %>
32 <% if !@node.draft && !@node.autosave %>
33 <span class="field_hint">Nothing pending — this will start a fresh draft.</span>
34 <% end %>
35 <% end %>
36 </div>
8 37
9<div id="page_editor" class="show_node"> 38 <% @node.available_layer_pairs.each do |pair| %>
10 <table id="content"> 39 <div class="node_info_item">
11 <tr> 40 <%= button_to "Diff #{pair.first.to_s.capitalize} vs. #{pair.last.to_s.capitalize}",
12 <td class="description">Public Link</td> 41 diff_node_revisions_path(@node),
13 <td><%= link_to @page.public_link, content_url(@node.unique_path) %></td> 42 method: :get,
14 </tr> 43 params: { start_revision: pair.first, end_revision: pair.last },
15 <tr> 44 form: { class: 'button_to computation' } %>
16 <td class="description">Author</td> 45 </div>
17 <td><%= @page.user.try(:login) %></td> 46 <% end %>
18 </tr> 47
19 <tr> 48 <% unless locked_by_other %>
20 <td class="description">Editor</td> 49 <% if @node.draft && !@node.autosave && !@node.in_trash? && !@node.trash_node? %>
21 <td><%= @page.editor.try(:login) %></td> 50 <div class="node_info_item">
22 </tr> 51 <%= button_to 'Publish', publish_node_path(@node), method: :put,
23 <% if @page.node.locked? %> 52 form: { data: { confirm: "Publish this draft?" }, class: 'button_to state_changing' } %>
24 <tr> 53 </div>
25 <td class="description">Locked by</td> 54 <% end %>
26 <td><span class="warning"><%= @page.node.lock_owner.login %></span></td> 55 <% if @node.autosave || (@node.draft && @node.head) %>
27 </tr> 56 <div class="node_info_item">
57 <%= button_to revert_node_path(@node), method: :put,
58 params: { return_to: request.path },
59 form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } do %>
60 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
61 <%= @node.draft && !@node.autosave ? "Destroy Draft" : "Discard Autosave" %>
62 <% end %>
63 </div>
64 <% end %>
65 <% unless @node.trash_node? || @node.in_trash? || @node.root? %>
66 <div class="node_info_item">
67 <%= button_to trash_node_path(@node), method: :put,
68 form: { data: { confirm: "Move this page and everything beneath it to the Trash? All published content in it will go offline." }, class: 'button_to destructive' } do %>
69 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
70 Move to Trash
71 <% end %>
72 </div>
73 <% end %>
74 <% end %>
75 </div>
76
77 <% if locked_by_other %>
78 <span class="field_hint">Locked — see People below to unlock before editing, publishing, or discarding.</span>
79 <% end %>
80 </div>
81
82 <% if @node.in_trash? %>
83 <div class="node_description">Trash</div>
84 <div class="node_content node_info_group">
85 <div class="node_info_group_items">
86 <% if (entry = @node.last_trash_entry) && entry.metadata.dig("path", "from") %>
87 <div class="node_info_item">
88 <span class="node_info_label">Was at</span>
89 <%= entry.metadata.dig("path", "from") %>
90 </div>
91 <% end %>
92 <div class="node_info_item">
93 <span class="node_info_label">Restore to</span>
94 <% suggestion = @node.suggested_restore_parent %>
95 <%= form_tag restore_from_trash_node_path(@node), :method => :put, :class => "aligned_action_row" do %>
96 <div class="restore_picker">
97 <%= text_field_tag :restore_search_term,
98 suggestion && (suggestion.head&.title || suggestion.draft&.title || suggestion.slug),
99 :placeholder => "Search for a new parent…" %>
100 <div id="restore_search_results" class="search_results"></div>
101 </div>
102 <%= hidden_field_tag :parent_id, suggestion&.id %>
103 <%= submit_tag "Restore here", :class => "action_button action_button_no_margin_top" %>
104 <% end %>
105 <span class="field_hint">Restored pages come back unpublished. Republish each page deliberately.</span>
106 </div>
107 </div>
108 <div class="node_info_group_items">
109 <div class="node_info_item">
110 <% doomed_below = @node.descendants.count %>
111 <%= button_to node_path(@node), method: :delete,
112 form: { data: { confirm: doomed_below > 0 ?
113 "Delete this page and the #{doomed_below} pages beneath it permanently? This cannot be undone." :
114 "Delete this page permanently? This cannot be undone." },
115 class: 'button_to destructive' } do %>
116 <%= icon("trash-x", library: "tabler", "aria-hidden": true) %>
117 Delete permanently<%= " (including #{doomed_below} beneath)" if doomed_below > 0 %>
118 <% end %>
119 </div>
120 </div>
121 </div>
122 <% end %>
123
124 <div class="node_description">Translations</div>
125 <div class="node_content node_info_group">
126 <div class="node_info_group_items">
127 <% @translations.each do |t| %>
128 <div class="node_info_item">
129 <span class="node_info_label"><%= t[:locale].to_s.upcase %></span>
130 <div class="aligned_action_row">
131 <% if t[:exists] %>
132 <%= link_to t[:title], node_translation_path(@node, t[:locale]) %> — updated <%= t[:updated_at] %>
133 <% if t[:outdated] %>
134 <span class="warning">may be outdated</span>
135 <% end %>
136 <% else %>
137 <span class="field_hint">Not yet translated.</span>
138 <% end %>
139 <% if locked_by_other %>
140 <span class="disabled_action"><%= t[:exists] ? "Lock + Edit" : "Create translation + Lock" %></span>
141 <% else %>
142 <%= link_to edit_node_translation_path(@node, t[:locale]), class: "action_button" do %>
143 <%= icon(t[:exists] ? "edit" : "language", library: "tabler", "aria-hidden": true) %>
144 <%= t[:exists] ? "Lock + Edit" : "Create translation + Lock" %>
145 <% end %>
146 <% if t[:exists] %>
147 <%= button_to node_translation_path(@node, t[:locale]), method: :delete,
148 form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } do %>
149 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
150 Destroy Translation
151 <% end %>
152 <% end %>
153 <% end %>
154 </div>
155 </div>
156 <% end %>
157 </div>
158 </div>
159
160 <div class="node_description">People</div>
161 <div class="node_content node_info_group">
162 <div class="node_info_group_items">
163 <div class="node_info_item">
164 <span class="node_info_label">Author</span>
165 <%= @page.user.try(:login) %>
166 </div>
167 <div class="node_info_item">
168 <span class="node_info_label">Editor</span>
169 <%= @page.editor.try(:login) %>
170 </div>
171 <% if @node.locked? %>
172 <div class="node_info_item">
173 <span class="node_info_label">Locked by</span>
174 <span class="warning"><%= @node.lock_owner.login %></span>
175 <%= unlock_link %>
176 </div>
177 <% end %>
178 </div>
179 </div>
180
181 <div class="node_description">Dates</div>
182 <div class="node_content node_info_group">
183 <div class="node_info_group_items">
184 <div class="node_info_item">
185 <span class="node_info_label">Last updated</span>
186 <%= @page.updated_at %>
187 </div>
188 <% if @page.published_at.present? %>
189 <div class="node_info_item">
190 <span class="node_info_label"><%= @page.public? ? 'Published at' : 'Will publish at' %></span>
191 <%= @page.published_at %>
192 </div>
193 <% end %>
194 </div>
195 </div>
196
197 <div class="node_description">Links</div>
198 <div class="node_content node_info_group">
199 <div class="node_info_group_items">
200 <div class="node_info_item">
201 <span class="node_info_label">Public</span>
202 <%= link_to @page.public_link, content_url(@node.unique_path) %>
203 </div>
204 <% if @node.draft %>
205 <div class="node_info_item">
206 <span class="node_info_label">Admin Preview</span>
207 <%= link_to preview_page_path(@node.draft), preview_page_path(@node.draft) %>
208 </div>
209 <div class="node_info_item">
210 <span class="node_info_label">Public Preview</span>
211 <% if @node.draft.preview_token.present? %>
212 <div class="aligned_action_row">
213 <%= link_to shared_preview_path(token: @node.draft.preview_token), shared_preview_url(token: @node.draft.preview_token), target: "_blank", rel: "noopener" %>
214 <%= button_to 'Revoke', revoke_shared_preview_node_path(@node), method: :put, form: { data: { confirm: "Revoke this preview link? Anyone currently using it will immediately lose access." }, class: 'button_to state_changing' } %>
215 </div>
216 <% else %>
217 <%= button_to 'Create public preview link', generate_shared_preview_node_path(@node), method: :put, form: { class: 'button_to state_changing' } %>
218 <% end %>
219 </div>
220 <% end %>
221 </div>
222 </div>
223
224 <div class="node_description">History</div>
225 <div class="node_content node_info_group">
226 <details>
227 <summary>
228 <%= pluralize(@node.pages.count, 'published revision', 'published revisions') %>
229 </summary>
230 <ul>
231 <% @node.pages.order(:revision).each do |page| %>
232 <li>
233 <%= link_to "##{page.revision} — #{page.title} (#{page.editor.try(:login)}, #{page.updated_at})", node_revision_path(@node, page) %>
234 <span class="revision_lifecycle"><%= revision_lifecycle_badges(@page_actions[page.id]) %></span>
235 </li>
236 <% end %>
237 </ul>
238 </details>
239 <p class="revisions_full_history_link"><%= link_to 'Revision history (diff / restore)', node_revisions_path(@node) %> | <%= link_to t("node_actions.heading"), admin_log_path(:node_id => @node.id) %></p>
240 </div>
241
242
243 <div class="node_description">Tags</div>
244 <div class="node_content node_info_group">
245 <% if @page.tag_list.any? %>
246 <ul class="tag_pill_list">
247 <% @page.tag_list.sort.each do |tag| %>
248 <li class="tag_pill"><%= tag %></li>
249 <% end %>
250 </ul>
251 <% else %>
252 <span class="field_hint">No tags.</span>
253 <% end %>
254 </div>
255
256 <% if @page.assets.images.any? %>
257 <div class="node_description">Images</div>
258 <div class="node_content node_info_group">
259 <ul class="thumbnail_list">
260 <% @page.assets.images.each do |asset| %>
261 <li><%= link_to image_tag(asset.upload.url(:thumb)), asset_path(asset) %></li>
262 <% end %>
263 </ul>
264 </div>
265 <% end %>
266
267 <div class="node_description">Events</div>
268 <div class="node_content node_info_group">
269 <ul>
270 <% @node.events.order(:start_time).each do |event| %>
271 <li>
272 <%= event_schedule_text(event) %>
273 [<%= link_to 'show', event_path(event, return_to: request.path) %>
274 | <%= link_to 'edit', edit_event_path(event, return_to: request.path) %>]
275 </li>
276 <% end %>
277 </ul>
278 <% mapping = default_event_tag_mapping(@page) %>
279 <%= link_to 'add event', new_event_path(node_id: @node.id, tag_list: mapping&.last, auto_tag_source: mapping&.first, return_to: request.path) %>
280 </div>
281
282 <% matches = matching_node_kinds(@node) %>
283 <% if @node.children.any? || matches.any? %>
284 <div class="node_description">Children</div>
285 <div class="node_content node_info_group">
286 <% if @node.children.any? %>
287 <details>
288 <summary><%= pluralize(@node.children.count, 'child', 'children') %></summary>
289 <ul>
290 <% @node.children.order(:slug).each do |child| %>
291 <li><%= link_to (child.head&.title || child.draft&.title || child.slug), node_path(child) %></li>
292 <% end %>
293 </ul>
294 </details>
295 <% end %>
296 <% if matches.any? %>
297 <p class="add_child_links">
298 <% matches.each_with_index do |(kind, config), index| %>
299 <%= " &middot; ".html_safe if index > 0 %>
300 <% link_params = { kind: kind } %>
301 <% link_params[:parent_id] = @node.id if kind == "generic" %>
302 <%= link_to "add '#{resolve_kind_text(config[:label])}' child", new_node_path(link_params) %>
303 <% end %>
304 </p>
305 <% end %>
306 </div>
28 <% end %> 307 <% end %>
29 <tr> 308
30 <td class="description">Last updated</td> 309 <div class="node_description">Abstract (<%= I18n.default_locale.to_s.upcase %>)</div>
31 <td><%= @page.updated_at %></td> 310 <div class="node_content"><%= sanitize(@page.abstract) %></div>
32 </tr> 311
33 <tr> 312 <div class="node_description">Body (<%= I18n.default_locale.to_s.upcase %>)</div>
34 <td class="description">Published at</td> 313 <div class="node_content"><%= sanitize(@page.body) %></div>
35 <td><%= @page.published_at %></td> 314
36 </tr> 315 </div>
37 <tr> 316</div>
38 <td class="description">Revision</td>
39 <td><%= @page.revision %></td>
40 </tr>
41 <tr>
42 <td class="description">Tagged with:</td>
43 <td><%= @page.tag_list %></td>
44 </tr>
45 <tr>
46 <td class="description"><strong>Title</strong></td>
47 <td><%= sanitize( @page.title ) %></td>
48 </tr>
49 <tr>
50 <td class="description"><strong>Abstract</strong></td>
51 <td><%= sanitize( @page.abstract ) %></td>
52 </tr>
53 <tr>
54 <td class="description"><strong>Body</strong></td>
55 <td><%= sanitize( @page.body ) %></td>
56 </tr>
57 <tr>
58 <td></td>
59 <td class="right"></td>
60 </tr>
61 </table>
62</div> \ No newline at end of file
diff --git a/app/views/nodes/sitemap.html.erb b/app/views/nodes/sitemap.html.erb
new file mode 100644
index 0000000..a799c17
--- /dev/null
+++ b/app/views/nodes/sitemap.html.erb
@@ -0,0 +1,32 @@
1<h1>Sitemap</h1>
2
3<div id="sitemap">
4<%
5 open_details = [] # levels with a currently-open <details>
6%>
7<% @sitemap.each_with_index do |(node, level), index| %>
8 <% while open_details.any? && open_details.last >= level %>
9 </details>
10 <% open_details.pop %>
11 <% end %>
12
13 <div class="sitemap_node">
14 <h4><%= link_to title_for_node(node), node_path(node) %></h4>
15 <span class="field_hint"><%= link_to_path("#{node.unique_name} ↗", node.unique_name) %></span>
16 <p class="sitemap_node_actions">
17 <%= link_to 'Show', node_path(node) %>
18 <%= link_to 'Create Child', new_node_path(:parent_id => node.id) %>
19 </p>
20 </div>
21
22 <% next_level = @sitemap[index + 1]&.last %>
23 <% if next_level && next_level > level %>
24 <details<%= ' open' if sitemap_node_open?(node) %>>
25 <summary>
26 <%= pluralize(@sitemap_descendant_counts[node.id], 'descendant', 'descendants') %>
27 </summary>
28 <% open_details.push(level) %>
29 <% end %>
30<% end %>
31<% open_details.length.times { %></details><% } %>
32</div>
diff --git a/app/views/nodes/tags.html.erb b/app/views/nodes/tags.html.erb
new file mode 100644
index 0000000..0ebc6ce
--- /dev/null
+++ b/app/views/nodes/tags.html.erb
@@ -0,0 +1,3 @@
1<h1>Nodes tagged: <%= params[:tags] %></h1>
2
3<%= render 'node_list' %>
diff --git a/app/views/nodes/trashed.html.erb b/app/views/nodes/trashed.html.erb
new file mode 100644
index 0000000..9a4808e
--- /dev/null
+++ b/app/views/nodes/trashed.html.erb
@@ -0,0 +1,42 @@
1<h1>Trash</h1>
2
3<% if @nodes.empty? %>
4 <p class="field_hint">The Trash is empty.</p>
5<% else %>
6 <%= will_paginate @nodes %>
7 <table id="trashed_node_list">
8 <tr>
9 <th>Title</th>
10 <th>Was at</th>
11 <th>Trashed</th>
12 <th>Actions</th>
13 </tr>
14 <% @nodes.each do |node| %>
15 <% entry = node.last_trash_entry %>
16 <tr>
17 <% doomed_below = node.descendants.count %>
18 <td>
19 <%= link_to (node.draft&.title || node.slug), node_path(node) %><%= " (+ #{doomed_below} beneath)" if doomed_below > 0 %>
20 </td>
21 <td><%= entry&.metadata&.dig("path", "from") %></td>
22 <td>
23 <% if entry %>
24 <%= entry.occurred_at.strftime("%Y-%m-%d %H:%M") %> by <%= entry.actor_name %>
25 <% end %>
26 </td>
27 <td>
28 <%= button_to node_path(node), method: :delete,
29 form: { data: { confirm: doomed_below > 0 ?
30 "Delete \"#{node.draft&.title || node.slug}\" and the #{doomed_below} pages beneath it permanently? This cannot be undone." :
31 "Delete \"#{node.draft&.title || node.slug}\" permanently? This cannot be undone." },
32 class: 'button_to destructive' } do %>
33 <%= icon("trash-x", library: "tabler", "aria-hidden": true) %>
34 Delete permanently
35 <% end %>
36 </td>
37 </tr>
38 <% end %>
39 </table>
40 <%= will_paginate @nodes %>
41 <p class="field_hint">To restore a page, open it and pick a new parent in its Trash section.</p>
42<% end %>
diff --git a/app/views/occurrences/index.html.erb b/app/views/occurrences/index.html.erb
index 0e99857..aa084ed 100644
--- a/app/views/occurrences/index.html.erb
+++ b/app/views/occurrences/index.html.erb
@@ -1,4 +1,4 @@
1<h1>Listing occurrences</h1> 1<h1>Occurrences</h1>
2 2
3<table> 3<table>
4 <tr> 4 <tr>
@@ -18,7 +18,9 @@
18 <td><%=h occurrence.event_id %></td> 18 <td><%=h occurrence.event_id %></td>
19 <td><%= link_to 'Show', occurrence %></td> 19 <td><%= link_to 'Show', occurrence %></td>
20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td> 20 <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td>
21 <td><%= button_to 'Destroy', occurrence, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td> 21 <td><%= button_to occurrence, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } do %>
22 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
23 <% end %></td>
22 </tr> 24 </tr>
23<% end %> 25<% end %>
24</table> 26</table>
diff --git a/app/views/page_translations/edit.html.erb b/app/views/page_translations/edit.html.erb
new file mode 100644
index 0000000..00bf221
--- /dev/null
+++ b/app/views/page_translations/edit.html.erb
@@ -0,0 +1,67 @@
1<div class="translation_banner">
2 Editing the <strong><%= @locale.to_s.upcase %></strong> translation of <strong><%= title_for_node(@node) %></strong>.
3</div>
4
5<p class="node_action_bar standalone_action_bar"><%= link_to 'View revision history', node_revisions_path(@node, :locale => @locale) %></p>
6
7<p class="field_hint">
8 Metadata such as images, tags, template, and author belong to the page
9 as a whole, not to a single translation — change those from the
10 <%= link_to 'default-locale editor', edit_node_path(@node) %>.
11</p>
12
13<div class="node_action_bar">
14 <%= button_to 'Unlock + Back', unlock_node_path(@node), method: :put,
15 form: { class: 'button_to state_changing' },
16 disabled: @node.autosave.present? %>
17 <%= submit_tag "Save #{@locale.to_s.upcase} translation", form: "translation_edit_form" %>
18 <%= submit_tag "Save + Unlock + Exit", form: "translation_edit_form" %>
19 <%= link_to "Preview ↗", preview_page_path(@page, :locale => @locale), target: "_blank", rel: "noopener", class: "preview_link" %>
20</div>
21
22<div id="page_editor">
23 <ul id="related_asset_list" style="display:none">
24 <% @page.related_assets.includes(:asset).each do |related| %>
25 <li data-large-url="<%= related.asset.upload.url(:large) %>"
26 data-original-url="<%= related.asset.upload.url %>"
27 data-name="<%= related.asset.name %>">
28 <%= image_tag related.asset.upload.url(:thumb) %>
29 </li>
30 <% end %>
31 </ul>
32 <%= form_with url: node_translation_path(@node, @locale), method: :patch, local: true, id: "translation_edit_form",
33 data: { autosave_url: autosave_node_translation_path(@node, @locale), show_url: node_path(@node) } do |f| %>
34 <div id="content">
35 <div class="node_description">Title</div>
36 <div class="node_content">
37 <%= text_field_tag "page[title]", @translation&.title %>
38 </div>
39
40 <div class="node_description">Abstract</div>
41 <div class="node_content">
42 <%= text_area_tag "page[abstract]", @translation&.abstract %>
43 </div>
44
45 <div class="node_description">Body</div>
46 <div class="body_toolbar_row">
47 <button type="button" id="preview_toggle" class="view_toggle" aria-pressed="false" aria-label="Toggle live preview" title="Toggle live preview">
48 <%= icon("layout-sidebar-right", library: "tabler", "aria-hidden": true) %> <span>Live preview</span>
49 </button>
50 <button type="button" id="preview_force_render" class="view_toggle" style="display:none" aria-label="Force preview render" title="Force preview render">
51 <%= icon("refresh", library: "tabler", "aria-hidden": true) %> <span>Force refresh</span>
52 </button>
53 </div>
54
55 <div id="editor_and_preview">
56 <div class="preview_content">
57 <div class="node_content">
58 <%= text_area_tag "page[body]", @translation&.body, :class => 'with_editor' %>
59 </div>
60 </div>
61 <div id="preview_panel" style="display:none">
62 <iframe id="live_preview_iframe" title="Live preview" data-src="<%= preview_page_path(@page, :locale => @locale) %>"></iframe>
63 </div>
64 </div>
65 </div>
66 <% end %>
67</div>
diff --git a/app/views/page_translations/show.html.erb b/app/views/page_translations/show.html.erb
new file mode 100644
index 0000000..60eb7cf
--- /dev/null
+++ b/app/views/page_translations/show.html.erb
@@ -0,0 +1,29 @@
1<h1>Compare — <%= title_for_node(@node) %></h1>
2
3<p class="node_action_bar standalone_action_bar"><%= link_to 'View revision history', node_revisions_path(@node, :locale => @locale) %></p>
4
5<div class="translation_compare">
6 <div class="translation_compare_column">
7 <h2><%= @locale.to_s.upcase %></h2>
8 <div class="node_description">Title</div>
9 <div class="node_content"><%= @translation&.title %></div>
10
11 <div class="node_description">Abstract</div>
12 <div class="node_content"><%= sanitize(@translation&.abstract.to_s) %></div>
13
14 <div class="node_description">Body</div>
15 <div class="node_content"><%= sanitize(@translation&.body.to_s) %></div>
16 </div>
17
18 <div class="translation_compare_column">
19 <h2><%= I18n.default_locale.to_s.upcase %> (default)</h2>
20 <div class="node_description">Title</div>
21 <div class="node_content"><%= @default_translation&.title %></div>
22
23 <div class="node_description">Abstract</div>
24 <div class="node_content"><%= sanitize(@default_translation&.abstract.to_s) %></div>
25
26 <div class="node_description">Body</div>
27 <div class="node_content"><%= sanitize(@default_translation&.body.to_s) %></div>
28 </div>
29</div>
diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb
index 91e5359..da67871 100644
--- a/app/views/pages/index.html.erb
+++ b/app/views/pages/index.html.erb
@@ -1,4 +1,4 @@
1<h1>Listing pages</h1> 1<h1>Pages</h1>
2 2
3<table> 3<table>
4 <tr> 4 <tr>
@@ -12,7 +12,9 @@
12 <td><%=h page.title %></td> 12 <td><%=h page.title %></td>
13 <td><%= link_to 'Show', content_path(:page_path => page.node.unique_path) %></td> 13 <td><%= link_to 'Show', content_path(:page_path => page.node.unique_path) %></td>
14 <td><%= link_to 'Edit', edit_page_path(page) %></td> 14 <td><%= link_to 'Edit', edit_page_path(page) %></td>
15 <td><%= button_to 'Destroy', page, method: :delete, form: { data: { confirm: 'Are you sure?' } } %></td> 15 <td><%= button_to page, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } do %>
16 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
17 <% end %></td>
16 </tr> 18 </tr>
17<% end %> 19<% end %>
18</table> 20</table>
diff --git a/app/views/revisions/diff.html.erb b/app/views/revisions/diff.html.erb
index b8d061d..7e7b729 100644
--- a/app/views/revisions/diff.html.erb
+++ b/app/views/revisions/diff.html.erb
@@ -1,65 +1,134 @@
1<% content_for :subnavigation do %>
2 <%= link_to 'Edit', edit_node_path(@node) %>
3 <%= link_to 'Revisions', node_revisions_path(@node) %>
4<% end %>
5
6<h1>Revisions#diff</h1> 1<h1>Revisions#diff</h1>
7 2
8<%= form_tag diff_node_revisions_path do %> 3<p class="node_action_bar standalone_action_bar">
9 <%= select_tag :start_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:start_revision].to_i) %> 4 <%= link_to 'Revisions', node_revisions_path(@node) %>
10 <%= select_tag :end_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:end_revision].to_i) %> 5</p>
11 <%= submit_tag 'Diff' %>
12<% end %>
13 6
14<div id="start_title" style="display: none;"> 7<p class="diff_comparison_label">
15 <%= h(@start.title) %> 8 Comparing <strong><%= describe_page_reference(params[:start_revision]) %></strong>
16</div> 9 against <strong><%= describe_page_reference(params[:end_revision]) %></strong>
10 — showing the <strong><%= @locale.to_s.upcase %></strong> translation
11</p>
17 12
18<div id="end_title" style="display: none;"> 13<% if @locale_summary.size > 1 %>
19 <%= h(@end.title) %> 14 <p class="diff_locale_toggle">
20</div> 15 Locale:
16 <% @locale_summary.each_with_index do |s, i| %>
17 <%= " &middot; ".html_safe if i > 0 %>
18 <% label = "#{s[:locale].to_s.upcase}#{' *' if s[:changed]}" %>
19 <% if s[:locale] == @locale %>
20 <strong><%= label %></strong>
21 <% else %>
22 <%= link_to label, diff_node_revisions_path(@node, start_revision: params[:start_revision], end_revision: params[:end_revision], view: @diff_view, locale: s[:locale]) %>
23 <% end %>
24 <% end %>
25 </p>
26 <p class="field_hint">* has a difference between these two versions.</p>
27<% end %>
21 28
22<div id="start_abstract" style="display: none;"> 29<p class="diff_view_toggle">
23 <%= h(@start.abstract) %> 30 View:
24</div> 31 <% if @diff_view == :inline %>
32 <strong>Inline</strong>
33 <% else %>
34 <%= link_to 'Inline', diff_node_revisions_path(@node, start_revision: params[:start_revision], end_revision: params[:end_revision], view: 'inline', locale: @locale) %>
35 <% end %>
36 &middot;
37 <% if @diff_view == :side_by_side %>
38 <strong>Side by side</strong>
39 <% else %>
40 <%= link_to 'Side by side', diff_node_revisions_path(@node, start_revision: params[:start_revision], end_revision: params[:end_revision], view: 'side_by_side', locale: @locale) %>
41 <% end %>
42</p>
25 43
26<div id="end_abstract" style="display: none;"> 44<% numeric_comparison = params[:start_revision].to_s =~ /\A\d+\z/ && params[:end_revision].to_s =~ /\A\d+\z/ %>
27 <%= h(@end.abstract) %>
28</div>
29 45
30<pre> 46<% if numeric_comparison %>
31 <div id="start_body" style="display: none;"> 47 <%= form_tag diff_node_revisions_path do %>
32 <%= (@start.body) %> 48 <%= select_tag :start_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:start_revision].to_i) %>
33 </div> 49 <%= select_tag :end_revision, options_for_select(@node.pages.map{|x| x.revision}, params[:end_revision].to_i) %>
34</pre> 50 <%= hidden_field_tag :view, @diff_view %>
35<pre> 51 <%= hidden_field_tag :locale, @locale %>
36 <div id="end_body" style="display: none;"> 52 <%= submit_tag 'Diff' %>
37 <%= (@end.body) %> 53 <% end %>
38 </div> 54<% else %>
39</pre> 55 <p class="node_action_bar standalone_action_bar"><%= link_to 'Compare two numbered revisions instead', node_revisions_path(@node) %></p>
56<% end %>
40 57
41<script src="/javascripts/cacycle_diff.js"></script> 58<% if @available_layer_pairs.present? %>
42<script type="text/javascript" charset="utf-8"> 59 <div class="node_action_bar standalone_action_bar">
43 window.onload = function() { 60 <% @available_layer_pairs.each do |pair| %>
44 title1 = document.getElementById('start_title').innerHTML; 61 <% next if [params[:start_revision].to_s, params[:end_revision].to_s].sort == pair.map(&:to_s).sort %>
45 title2 = document.getElementById('end_title').innerHTML; 62 <%= button_to "Diff #{pair.first.to_s.capitalize} vs. #{pair.last.to_s.capitalize}",
46 abstract1 = document.getElementById('start_abstract').innerHTML; 63 diff_node_revisions_path(@node),
47 abstract2 = document.getElementById('end_abstract').innerHTML; 64 method: :get,
48 body1 = document.getElementById('start_body').innerHTML; 65 params: { start_revision: pair.first, end_revision: pair.last, view: @diff_view, locale: @locale },
49 body2 = document.getElementById('end_body').innerHTML; 66 form: { class: 'button_to computation' } %>
50 document.getElementById('diffview_title').innerHTML = WDiffString(title1, title2); 67 <% end %>
51 document.getElementById('diffview_abstract').innerHTML = WDiffString(abstract1, abstract2); 68 <% if !@locked_by_other && (@node.autosave || @node.draft) %>
52 document.getElementById('diffview_body').innerHTML = WDiffString(body1, body2); 69 <%= button_to revert_node_path(@node), method: :put,
53 } 70 params: { return_to: request.fullpath },
54</script> 71 form: { data: { confirm: "This cannot be undone. Continue?" }, class: 'button_to destructive' } do %>
72 <%= icon("trash", library: "tabler", "aria-hidden": true) %>
73 <%= @node.draft && !@node.autosave ? "Destroy Draft" : "Discard Autosave" %>
74 <% end %>
75 <% end %>
76 </div>
77<% end %>
55 78
56<div id="diffview"> 79<div id="diffview">
57 <h3>Title</h3> 80 <% if @diff_view == :side_by_side %>
58 <p id="diffview_title"></p> 81 <div class="diff_side_by_side">
59 82 <div class="diff_column">
60 <h3>Abstract</h3> 83 <h3>Title</h3>
61 <p id="diffview_abstract"></p> 84 <p><%= raw @diff[:title][0] %></p>
62 85 <h3>Abstract</h3>
63 <h3>Body</h3> 86 <p><%= raw @diff[:abstract][0] %></p>
64 <p id="diffview_body"></p> 87 <h3>Body</h3>
88 <%= raw @diff[:body][0] %>
89 </div>
90 <div class="diff_column">
91 <h3>Title</h3>
92 <p><%= raw @diff[:title][1] %></p>
93 <h3>Abstract</h3>
94 <p><%= raw @diff[:abstract][1] %></p>
95 <h3>Body</h3>
96 <%= raw @diff[:body][1] %>
97 </div>
98 </div>
99 <% else %>
100 <h3>Title</h3>
101 <p><%= raw @diff[:title] %></p>
102 <h3>Abstract</h3>
103 <p><%= raw @diff[:abstract] %></p>
104 <h3>Body</h3>
105 <%= raw @diff[:body] %>
106 <% end %>
107
108 <h3>Tags</h3>
109 <% if @diff[:tags][:added].empty? && @diff[:tags][:removed].empty? %>
110 <p class="diff_unchanged">No change.</p>
111 <% else %>
112 <ul class="diff_set_list">
113 <% @diff[:tags][:added].each do |tag| %><li><ins><%= tag %></ins></li><% end %>
114 <% @diff[:tags][:removed].each do |tag| %><li><del><%= tag %></del></li><% end %>
115 </ul>
116 <% end %>
117
118 <h3>Template</h3>
119 <% if @diff[:template_name][:changed] %>
120 <p><del><%= @diff[:template_name][:from] || '(none)' %></del> <ins><%= @diff[:template_name][:to] || '(none)' %></ins></p>
121 <% else %>
122 <p class="diff_unchanged">No change.</p>
123 <% end %>
124
125 <h3>Assets</h3>
126 <% if @diff[:assets][:added].empty? && @diff[:assets][:removed].empty? %>
127 <p class="diff_unchanged">No change.</p>
128 <% else %>
129 <ul class="diff_set_list">
130 <% @diff[:assets][:added].each do |asset| %><li><ins><%= asset.upload_file_name %></ins></li><% end %>
131 <% @diff[:assets][:removed].each do |asset| %><li><del><%= asset.upload_file_name %></del></li><% end %>
132 </ul>
133 <% end %>
65</div> 134</div>
diff --git a/app/views/revisions/index.html.erb b/app/views/revisions/index.html.erb
index b875a4f..7ea74a6 100644
--- a/app/views/revisions/index.html.erb
+++ b/app/views/revisions/index.html.erb
@@ -1,49 +1,95 @@
1<% content_for :subnavigation do %>
2 <%= link_to 'Edit', edit_node_path(@node) %>
3<% end %>
4
5<h2>Revisions for Node: <%= @node.unique_name %></h2> 1<h2>Revisions for Node: <%= @node.unique_name %></h2>
6 2
7<table id="revisions"> 3<p class="node_action_bar standalone_action_bar">
8 <tr class="header"> 4 <%= link_to 'Back to node', node_path(@node) %>
9 <th>First</th> 5</p>
10 <th>Last</th> 6
11 <th>Rev.</th> 7<% if Page.non_default_locales.any? %>
12 <th>Title</th> 8 <p class="diff_locale_toggle">
13 <th>Editor</th> 9 Locale:
14 <th>Date</th> 10 <% ([I18n.default_locale] + Page.non_default_locales).each_with_index do |locale, i| %>
15 <th></th> 11 <%= " &middot; ".html_safe if i > 0 %>
16 <th></th> 12 <% if locale == @locale %>
17 </tr> 13 <strong><%= locale.to_s.upcase %></strong>
18<% (@pages || @node.pages.all).reverse.each do |page| %> 14 <% else %>
19 <tr> 15 <%= link_to locale.to_s.upcase, node_revisions_path(@node, :locale => locale) %>
20 <td><%= radio_button_tag :start_revision, page.revision %></td> 16 <% end %>
21 <td><%= radio_button_tag :end_revision, page.revision %></td> 17 <% end %>
22 <td class="revision"><%= page.revision %></td> 18 </p>
23 <td class="title"><%= page.title %></td>
24 <td class="user"><%= page.editor.try(:login) %></td>
25 <td class="date"><%= page.updated_at %></td>
26 <td><%= link_to 'show', node_revision_path(@node, page) %></td>
27 <td>
28 <%= button_to 'restore', restore_node_revision_path(@node, page),
29 method: :put,
30 form: { data: { confirm: "Restore this revision?" } } %>
31 </td>
32 </tr>
33<% end %> 19<% end %>
34 <tr class="no_hover"> 20
35 <td colspan="8" class="right"> 21<table id="revisions" class="revisions_table">
36 <%= button_to 'Diff revisions', diff_node_revisions_path(@node), 22 <thead>
37 method: :post, 23 <tr class="header">
38 form: { id: 'diff_form' } %> 24 <th>First</th>
39 </td> 25 <th>Last</th>
40 </tr> 26 <th>Rev.</th>
27 <th>Title</th>
28 <th>Editor</th>
29 <th>Date</th>
30 <th></th>
31 <th></th>
32 </tr>
33 <tr class="no_hover diff_sticky_bar">
34 <td colspan="8">
35 <%= button_to 'Diff revisions', diff_node_revisions_path(@node),
36 method: :post,
37 params: { locale: @locale },
38 form: { id: 'diff_form', class: 'button_to computation' },
39 disabled: true %>
40 <span id="diff_selection_label"></span>
41 <label><%= radio_button_tag :view, 'inline', true %> Inline</label>
42 <label><%= radio_button_tag :view, 'side_by_side', false %> Side by side</label>
43 </td>
44 </tr>
45 </thead>
46 <tbody>
47 <% pages = (@pages || @node.pages.all).reverse %>
48 <% pages.each_with_index do |page, index| %>
49 <tr>
50 <td><%= radio_button_tag :start_revision, page.revision, index == 1 %></td>
51 <td><%= radio_button_tag :end_revision, page.revision, index == 0 %></td>
52 <td class="revision"><%= page.revision %></td>
53 <td class="title"><%= page.translations.find_by(:locale => @locale)&.title || "—" %></td>
54 <td class="user"><%= page.editor.try(:login) %></td>
55 <td class="date"><%= page.updated_at %></td>
56 <td><%= link_to 'show', node_revision_path(@node, page, :locale => @locale) %></td>
57 <td>
58 <%= button_to 'restore', restore_node_revision_path(@node, page),
59 method: :put,
60 form: { data: { confirm: "Restore this revision?" }, class: 'button_to state_changing' } %>
61 </td>
62 </tr>
63 <% end %>
64 </tbody>
41</table> 65</table>
42 66
43<script> 67<script>
68 function update_diff_button_state() {
69 var start = document.querySelector('input[name="start_revision"]:checked');
70 var end = document.querySelector('input[name="end_revision"]:checked');
71 var valid = start && end && start.value !== end.value;
72 document.querySelector('#diff_form button[type="submit"]').disabled = !valid;
73
74 var label = document.getElementById('diff_selection_label');
75 if (start && end) {
76 label.textContent = start.value + ' against ' + end.value;
77 } else if (start || end) {
78 label.textContent = (start || end).value + ' selected';
79 } else {
80 label.textContent = '';
81 }
82 }
83
84 document.querySelectorAll('input[name="start_revision"], input[name="end_revision"]')
85 .forEach(function(radio) { radio.addEventListener('change', update_diff_button_state); });
86
87 update_diff_button_state();
88
44 document.getElementById('diff_form').addEventListener('submit', function(e) { 89 document.getElementById('diff_form').addEventListener('submit', function(e) {
45 var start = document.querySelector('input[name="start_revision"]:checked'); 90 var start = document.querySelector('input[name="start_revision"]:checked');
46 var end = document.querySelector('input[name="end_revision"]:checked'); 91 var end = document.querySelector('input[name="end_revision"]:checked');
92 var view = document.querySelector('input[name="view"]:checked');
47 if (start) { 93 if (start) {
48 var s = document.createElement('input'); 94 var s = document.createElement('input');
49 s.type = 'hidden'; s.name = 'start_revision'; s.value = start.value; 95 s.type = 'hidden'; s.name = 'start_revision'; s.value = start.value;
@@ -54,5 +100,10 @@
54 en.type = 'hidden'; en.name = 'end_revision'; en.value = end.value; 100 en.type = 'hidden'; en.name = 'end_revision'; en.value = end.value;
55 this.appendChild(en); 101 this.appendChild(en);
56 } 102 }
103 if (view) {
104 var v = document.createElement('input');
105 v.type = 'hidden'; v.name = 'view'; v.value = view.value;
106 this.appendChild(v);
107 }
57 }); 108 });
58</script> 109</script>
diff --git a/app/views/revisions/show.html.erb b/app/views/revisions/show.html.erb
index f2a2895..74fb51f 100644
--- a/app/views/revisions/show.html.erb
+++ b/app/views/revisions/show.html.erb
@@ -1,54 +1,39 @@
1<% content_for :subnavigation do %> 1<% translation = @page.translations.find_by(:locale => @locale) %>
2 <%= link_to 'show all revisions', node_revisions_path(@node) %>
3<% end %>
4
5<div id="page_editor" class="show_node"> 2<div id="page_editor" class="show_node">
6 <table id="content"> 3 <h1>Revision <%= @page.revision %>: <%= translation&.title %> <small>(<%= @locale.to_s.upcase %>)</small></h1>
7 <tr> 4
8 <td class="description">Path</td> 5 <div id="content">
9 <td><%= @page.public_link %></td> 6 <div class="node_description">Actions</div>
10 </tr> 7 <div class="node_content node_info_group">
11 <tr> 8 <div class="node_info_group_items">
12 <td class="description">Author</td> 9 <div class="node_info_item">
13 <td><%= @page.user.try(:login) %></td> 10 <%= link_to 'Show all revisions', node_revisions_path(@node, :locale => @locale) %>
14 </tr> 11 </div>
15 <tr> 12 </div>
16 <td class="description">Editor</td> 13 </div>
17 <td><%= @page.editor.try(:login) %></td> 14
18 </tr> 15 <div class="node_description">Path</div>
19 <% if @page.node.locked? %> 16 <div class="node_content"><%= @page.public_link %></div>
20 <tr> 17
21 <td class="description">Locked by</td> 18 <div class="node_description">Author</div>
22 <td><%= @page.node.lock_owner.login %></td> 19 <div class="node_content"><%= @page.user.try(:login) %></div>
23 </tr> 20
24 <% end %> 21 <div class="node_description">Editor</div>
25 <tr> 22 <div class="node_content"><%= @page.editor.try(:login) %></div>
26 <td class="description">Last updated</td> 23
27 <td><%= @page.updated_at %></td> 24 <div class="node_description">Last updated</div>
28 </tr> 25 <div class="node_content"><%= @page.updated_at %></div>
29 <tr> 26
30 <td class="description">Published at</td> 27 <div class="node_description">Published at</div>
31 <td><%= @page.published_at %></td> 28 <div class="node_content"><%= @page.published_at %></div>
32 </tr> 29
33 <tr> 30 <div class="node_description">Title</div>
34 <td class="description">Revision</td> 31 <div class="node_content"><%= translation&.title %></div>
35 <td><%= @page.revision %></td> 32
36 </tr> 33 <div class="node_description">Abstract</div>
37 <tr> 34 <div class="node_content"><%= translation&.abstract %></div>
38 <td class="description"><strong>Title</strong></td> 35
39 <td><%= @page.title %></td> 36 <div class="node_description">Body</div>
40 </tr> 37 <div class="node_content"><%= raw translation&.body %></div>
41 <tr> 38 </div>
42 <td class="description"><strong>Abstract</strong></td> 39</div>
43 <td><%= @page.abstract %></td>
44 </tr>
45 <tr>
46 <td class="description"><strong>Body</strong></td>
47 <td><%= @page.body %></td>
48 </tr>
49 <tr>
50 <td></td>
51 <td class="right"></td>
52 </tr>
53 </table>
54</div> \ No newline at end of file
diff --git a/app/views/rss/updates.xml.builder b/app/views/rss/updates.xml.builder
index 4b2e2f7..27845c4 100644
--- a/app/views/rss/updates.xml.builder
+++ b/app/views/rss/updates.xml.builder
@@ -22,9 +22,7 @@ xml.feed(:xmlns => "http://www.w3.org/2005/Atom", "xml:base" => @host) do
22 xml.updated(item.updated_at.xmlschema) 22 xml.updated(item.updated_at.xmlschema)
23 xml.published(item.published_at.xmlschema) 23 xml.published(item.published_at.xmlschema)
24 xml.summary(CGI.escapeHTML(item.abstract.to_s)) 24 xml.summary(CGI.escapeHTML(item.abstract.to_s))
25 xml.content(:type => "xhtml") do 25 xml.content(CGI.escapeHTML(item.body.to_s), :type => "html")
26 xml.div(item.body, :xmlns => "http://www.w3.org/1999/xhtml")
27 end
28 end 26 end
29 27
30 end 28 end
diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb
index 3c10303..23952b7 100644
--- a/app/views/sessions/new.html.erb
+++ b/app/views/sessions/new.html.erb
@@ -1,24 +1,15 @@
1<div id="login_form"> 1<div id="login_form">
2 <%= form_tag session_path do -%> 2 <%= form_tag session_path do -%>
3 <table> 3 <% if flash[:error] %>
4 <tr> 4 <div class="error_messages"><%= flash[:error] %></div>
5 <td></td> 5 <% end %>
6 <td> 6
7 <%= flash[:error] %>&nbsp; 7 <div class="node_description">Login</div>
8 </td> 8 <div class="node_content"><%= text_field_tag 'login', @login %></div>
9 </tr> 9
10 <tr> 10 <div class="node_description">Password</div>
11 <td class="description">Login</td> 11 <div class="node_content"><%= password_field_tag 'password', nil %></div>
12 <td><%= text_field_tag 'login', @login %></td> 12
13 </tr> 13 <div class="node_content"><%= submit_tag 'log in' %></div>
14 <tr>
15 <td class="description">Password</td>
16 <td><%= password_field_tag 'password', nil %></td>
17 </tr>
18 <tr>
19 <td></td>
20 <td class="right"><%= submit_tag 'log in' %></td>
21 </tr>
22 </table>
23 <% end -%> 14 <% end -%>
24</div> 15</div>
diff --git a/app/views/users/_user.html.erb b/app/views/users/_user.html.erb
index ddb7afd..3a88f5e 100644
--- a/app/views/users/_user.html.erb
+++ b/app/views/users/_user.html.erb
@@ -7,9 +7,10 @@
7 <%= link_to "edit", edit_user_path(user) %> 7 <%= link_to "edit", edit_user_path(user) %>
8 </td> 8 </td>
9 <td> 9 <td>
10 <%= button_to "destroy", user_path(user), 10 <%= button_to user_path(user), method: :delete,
11 method: :delete, 11 form: { data: { confirm: "Do you really want to destroy user #{user.login}?" }, class: 'button_to destructive' } do %>
12 form: { data: { confirm: "Do you really want to delete user #{user.login}?" } } %> 12 <%= icon("trash", library: "tabler", "aria-hidden": true) %> Destroy
13 <% end %>
13 </td> 14 </td>
14 <% end %> 15 <% end %>
15</tr> 16</tr>
diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb
index df1005b..77b33c6 100644
--- a/app/views/users/edit.html.erb
+++ b/app/views/users/edit.html.erb
@@ -2,38 +2,32 @@
2 2
3<% if @user.errors.any? %> 3<% if @user.errors.any? %>
4 <div class="error_messages"> 4 <div class="error_messages">
5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg.gsub("Slug", "Title") %></li><% end %></ul> 5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul>
6 </div> 6 </div>
7<% end %> 7<% end %>
8 8
9<div id="page_editor">
10 <%= form_for @user do |f| %>
11 <div id="content">
12 <div class="node_description">Login</div>
13 <div class="node_content"><%= f.text_field :login %></div>
9 14
10<%= form_for @user do |f| %> 15 <div class="node_description">E-Mail</div>
11<table id="new_node"> 16 <div class="node_content"><%= f.text_field :email %></div>
12 <tr> 17
13 <td class="description">Login</td> 18 <div class="node_description">Password</div>
14 <td><%= f.text_field :login %></td> 19 <div class="node_content"><%= f.password_field :password %></div>
15 </tr> 20
16 <tr> 21 <div class="node_description">Confirm</div>
17 <td class="description">E-Mail</td> 22 <div class="node_content"><%= f.password_field :password_confirmation %></div>
18 <td><%= f.text_field :email %></td> 23
19 </tr> 24 <% if current_user.admin? %>
20 <tr> 25 <div class="node_description">Admin?</div>
21 <td class="description">Password</td> 26 <div class="node_content"><%= f.check_box :admin %></div>
22 <td><%= f.password_field :password %></td> 27 <% end %>
23 </tr> 28
24 <tr> 29 <div class="node_description"></div>
25 <td class="description">Confirm</td> 30 <div class="node_content"><%= f.submit "Update" %></div>
26 <td><%= f.password_field :password_confirmation %></td>
27 </tr>
28 <% if current_user.admin? %>
29 <tr>
30 <td class="description">Admin?</td>
31 <td><%= f.check_box :admin %></td>
32 </tr>
33 <% end %> 31 <% end %>
34 <tr> 32 </div>
35 <td class="description"></td> 33</div>
36 <td class="right"><%= f.submit "Update" %></td>
37 </tr>
38</table>
39<% end %>
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb
index 59806db..4f5266d 100644
--- a/app/views/users/index.html.erb
+++ b/app/views/users/index.html.erb
@@ -1,14 +1,27 @@
1<table class="user_list"> 1<h1>Admins</h1>
2 <tr> 2<%= link_to new_user_path(admin: true), class: 'action_button' do %>
3 <td><h1>Admins</h1></td> 3 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create admin user
4<% end %>
5<table class="user_table">
6 <tr class="header">
7 <th>Login</th>
8 <th></th>
9 <th></th>
10 <th></th>
4 </tr> 11 </tr>
5 <%= render :partial => "user", :locals => {:users => @users[:admin] ||= []} %> 12 <%= render :partial => "user", :locals => {:users => @users[:admin] ||= []} %>
6 <tr> 13</table>
7 <td><h1>Users</h1></td> 14
15<h1>Users</h1>
16<%= link_to new_user_path, class: 'action_button' do %>
17 <%= icon("plus", library: "tabler", "aria-hidden": true) %> Create user
18<% end %>
19<table class="user_table">
20 <tr class="header">
21 <th>Login</th>
22 <th></th>
23 <th></th>
24 <th></th>
8 </tr> 25 </tr>
9 <%= render :partial => "user", :locals => {:users => @users[:user] ||= []} %> 26 <%= render :partial => "user", :locals => {:users => @users[:user] ||= []} %>
10</table> 27</table>
11
12<% content_for :subnavigation do %>
13 <%= link_to "create", new_user_path %>
14<% end %> \ No newline at end of file
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index 6beda4f..ce38fdf 100644
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -2,36 +2,30 @@
2 2
3<% if @user.errors.any? %> 3<% if @user.errors.any? %>
4 <div class="error_messages"> 4 <div class="error_messages">
5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg.gsub("Slug", "Title") %></li><% end %></ul> 5 <ul><% @user.errors.full_messages.each do |msg| %><li><%= msg %></li><% end %></ul>
6 </div> 6 </div>
7<% end %> 7<% end %>
8 8
9<div id="page_editor">
10 <%= form_for @user do |f| %>
11 <div id="content">
12 <div class="node_description">Login</div>
13 <div class="node_content"><%= f.text_field :login %></div>
9 14
10<%= form_for @user do |f| %> 15 <div class="node_description">E-Mail</div>
11<table id="new_node"> 16 <div class="node_content"><%= f.text_field :email %></div>
12 <tr> 17
13 <td class="description">Login</td> 18 <div class="node_description">Password</div>
14 <td><%= f.text_field :login %></td> 19 <div class="node_content"><%= f.password_field :password %></div>
15 </tr> 20
16 <tr> 21 <div class="node_description">Confirm</div>
17 <td class="description">E-Mail</td> 22 <div class="node_content"><%= f.password_field :password_confirmation %></div>
18 <td><%= f.text_field :email %></td> 23
19 </tr> 24 <div class="node_description">Admin?</div>
20 <tr> 25 <div class="node_content"><%= f.check_box :admin %></div>
21 <td class="description">Password</td> 26
22 <td><%= f.password_field :password %></td> 27 <div class="node_description"></div>
23 </tr> 28 <div class="node_content"><%= f.submit "Create" %></div>
24 <tr> 29 <% end %>
25 <td class="description">Confirm</td> 30 </div>
26 <td><%= f.password_field :password_confirmation %></td> 31</div>
27 </tr>
28 <tr>
29 <td class="description">Admin?</td>
30 <td><%= f.check_box :admin %></td>
31 </tr>
32 <tr>
33 <td class="description"></td>
34 <td class="right"><%= f.submit "Create" %></td>
35 </tr>
36</table>
37<% end %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index 80483d3..70881db 100644
--- a/app/views/users/show.html.erb
+++ b/app/views/users/show.html.erb
@@ -1,20 +1,25 @@
1<% content_for :subnavigation do %> 1<div id="page_editor">
2 <%= link_to 'Edit', edit_user_path(@user) %> 2 <h1><%= @user.login %></h1>
3<% end %>
4 3
5<h1>User: <%= @user.login %></h1> 4 <div id="content">
5 <div class="node_description">Actions</div>
6 <div class="node_content node_info_group">
7 <div class="node_info_group_items">
8 <div class="node_info_item">
9 <%= link_to edit_user_path(@user), class: 'action_button' do %>
10 <%= icon("edit", library: "tabler", "aria-hidden": true) %> Edit
11 <% end %>
12 </div>
13 </div>
14 </div>
6 15
7<table id="new_node"> 16 <div class="node_description">Login</div>
8 <tr> 17 <div class="node_content"><%= @user.login %></div>
9 <td class="description">Login</td> 18
10 <td><%= @user.login %></td> 19 <div class="node_description">E-Mail</div>
11 </tr> 20 <div class="node_content"><%= @user.email %></div>
12 <tr> 21
13 <td class="description">E-Mail</td> 22 <div class="node_description">Admin?</div>
14 <td><%= @user.email %></td> 23 <div class="node_content"><%= @user.admin ? "yes" : "no" %></div>
15 </tr> 24 </div>
16 <tr> 25</div>
17 <td class="description">Admin?</td>
18 <td><%= @user.admin ? "yes" : "no" %></td>
19 </tr>
20</table> \ No newline at end of file