From 51629c5c42270a346885057a441095c964101cc1 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 30 Jun 2026 03:55:42 +0200 Subject: Fix events CRUD for standalone events and add events to admin menu - event_params now permits title, description, is_primary - event_information helper lists all node.events, not just the first - Occurrence.generate handles nil node (standalone events) - Page.aggregate order_by title uses correlated subquery to avoid GROUP BY conflict with tag-filter path; order_direction whitelisted to ASC/DESC to prevent SQL injection - Events link added to admin menu bar - events/index shows title, is_primary; drops latitude/longitude columns --- app/views/events/index.html.erb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 19b21ce8..064fa860 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -2,27 +2,27 @@ + + - - <% @events.each do |event| %> + + - - -- cgit v1.3 From b6416e86c9c58b8e886c14de55b01aeb863b8676 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 2 Jul 2026 00:12:02 +0200 Subject: Clean up events views: return_to, subnav, remove custom_rrule - events_controller: wire return_to through show and new actions; create respects return_to with fallback to node/event path; new pre-populates node_id and tag_list from params - events/edit: remove custom_rrule checkbox; node link removed from subnav (use show for node navigation); destroy button added - events/new: remove custom_rrule checkbox; add return_to hidden field and back link; tag_list field added - events/show: fix back link via safe_return_to; add node link to subnav; add destroy button; remove custom_rrule display; show humanized rrule below raw string - events/index: destructive class on destroy button; node_id column replaced with node link; show/edit links carry return_to - nodes/show: add show/edit links to event entries with return_to --- app/controllers/events_controller.rb | 10 +++++++--- app/views/events/edit.html.erb | 9 +++------ app/views/events/index.html.erb | 10 ++++------ app/views/events/new.html.erb | 7 ++++--- app/views/events/show.html.erb | 16 +++++++++++----- app/views/nodes/show.html.erb | 6 +++++- 6 files changed, 34 insertions(+), 24 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 3a60cf93..9bed5ddd 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -21,6 +21,7 @@ class EventsController < ApplicationController # GET /events/1.xml def show @event = Event.find(params[:id]) + @return_to = params[:return_to] || events_path respond_to do |format| format.html # show.html.erb @@ -31,7 +32,10 @@ class EventsController < ApplicationController # GET /events/new # GET /events/new.xml def new - @event = Event.new(:node_id => params[:node_id]) + @event = Event.new( + node_id: params[:node_id], + tag_list: params[:tag_list] + ) respond_to do |format| format.html # new.html.erb @@ -53,7 +57,7 @@ class EventsController < ApplicationController respond_to do |format| if @event.save flash[:notice] = 'Event was successfully created.' - format.html { redirect_to(@event.node ? edit_node_path(@event.node) : edit_event_path(@event)) } + format.html { redirect_to(safe_return_to(params[:return_to] || (@event.node ? edit_node_path(@event.node) : edit_event_path(@event)))) } format.xml { render :xml => @event, :status => :created, :location => @event } else format.html { render :action => "new" } @@ -94,6 +98,6 @@ class EventsController < ApplicationController private def event_params - params.require(:event).permit(:title, :description, :is_primary, :start_time, :end_time, :rrule, :custom_rrule, :allday, :url, :latitude, :longitude, :node_id, :location) + params.require(:event).permit(:title, :description, :start_time, :end_time, :rrule, :allday, :url, :latitude, :longitude, :node_id, :location, :tag_list) end end diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb index 17457df4..5aee5019 100644 --- a/app/views/events/edit.html.erb +++ b/app/views/events/edit.html.erb @@ -1,9 +1,6 @@ <% content_for :subnavigation do %> <%= link_to 'back', safe_return_to(params[:return_to] || events_path) %> - <% if @event.node %> - <%= link_to 'node', edit_node_path(@event.node) %> - <% end %> - <%= link_to 'show', @event %> + <%= button_to 'destroy', event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> <% end %>

Editing event

@@ -25,8 +22,8 @@ <%= f.text_field :rrule %>

- <%= f.label :custom_rrule %>
- <%= f.check_box :custom_rrule %> + <%= f.label :tag_list, "Tags" %>
+ <%= f.text_field :tag_list %>

<%= f.label :allday %>
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 064fa860..d0458d71 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -3,7 +3,6 @@

TitleIs primary Start time End time Rrule Custom rrule Allday UrlLatitudeLongitude Node
<%=h event.display_title %><%=h event.is_primary %> <%=h event.start_time %> <%=h event.end_time %> <%=h event.rrule %> <%=h event.custom_rrule %> <%=h event.allday %> <%=h event.url %><%=h event.latitude %><%=h event.longitude %> <%=h event.node_id %> <%= link_to 'Show', event %> <%= link_to 'Edit', edit_event_path(event) %>
- @@ -16,17 +15,16 @@ <% @events.each do |event| %> - - - - - + + + + <% end %>
TitleIs primary Start time End time Rrule
<%=h event.display_title %><%=h event.is_primary %> <%=h event.start_time %> <%=h event.end_time %> <%=h event.rrule %> <%=h event.custom_rrule %> <%=h event.allday %> <%=h event.url %><%=h event.node_id %><%= link_to 'Show', event %><%= link_to 'Edit', edit_event_path(event) %><%= button_to 'Destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' } } %><%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %><%= link_to 'show', event %><%= link_to 'edit', edit_event_path(event) %><%= button_to 'destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } %>
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb index cd892c5d..4e1ef53e 100644 --- a/app/views/events/new.html.erb +++ b/app/views/events/new.html.erb @@ -16,8 +16,8 @@ <%= f.text_field :rrule %>

- <%= f.label :custom_rrule %>
- <%= f.check_box :custom_rrule %> + <%= f.label :tag_list, "Tags" %>
+ <%= f.text_field :tag_list %>

<%= f.label :allday %>
@@ -37,10 +37,11 @@

<%= f.hidden_field :node_id %> + <%= hidden_field_tag :return_to, params[:return_to] %>

<%= f.submit 'Create' %>

<% end %> -<%= link_to 'Back', events_path %> +<%= link_to 'Back', safe_return_to(params[:return_to] || events_path) %> diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb index ba14a7d3..e206bc4c 100644 --- a/app/views/events/show.html.erb +++ b/app/views/events/show.html.erb @@ -1,6 +1,9 @@ <% content_for :subnavigation do %> - <%= link_to 'back', edit_node_path(@event.node) %> - <%= link_to 'edit', edit_event_path(@event) %> + <% if @event.node %> + <%= link_to 'node', node_path(@event.node) %> + <% end %> + <%= link_to 'edit', edit_event_path(@event, return_to: request.path) %> + <%= button_to 'destroy', event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> <% end %>

Event for node <%= @event.node.unique_name %>

@@ -18,11 +21,14 @@

Rrule: <%=h @event.rrule %> + <% if (human = @event.humanize_rrule(I18n.locale)) %> +
( <%= human %> ) + <% end %>

- Custom rrule: - <%=h @event.custom_rrule %> + Tags: + <%=h @event.tag_list %>

@@ -43,4 +49,4 @@

Longitude: <%=h @event.longitude %> -

\ No newline at end of file +

diff --git a/app/views/nodes/show.html.erb b/app/views/nodes/show.html.erb index 72232194..2ce3853e 100644 --- a/app/views/nodes/show.html.erb +++ b/app/views/nodes/show.html.erb @@ -48,7 +48,11 @@ -- cgit v1.3 From 970f10854bccee0528de8435e5a65cdcc18ba93e Mon Sep 17 00:00:00 2001 From: erdgeist Date: Mon, 6 Jul 2026 04:20:55 +0200 Subject: Remove dead custom_rrule references after column drop events#index still read event.custom_rrule - a live bug the column-drop migration introduced, not just stale test data. Caught by four test failures (three fixtures/direct attribute hashes still setting the removed column, one UnknownAttributeError from a stale fixture loaded before any test method runs), none of which were actually testing this view - "should get index" passed throughout with zero Event records present, meaning it could never have caught a per-row rendering bug. Strengthened to create one real event first, so a future stray reference to a dropped or renamed column fails loudly instead of silently passing on an empty table. --- app/views/events/index.html.erb | 2 -- test/controllers/events_controller_test.rb | 3 +++ test/models/event_test.rb | 4 ---- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index d0458d71..ae4f4773 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -6,7 +6,6 @@ Start time End time Rrule - Custom rrule Allday Url Node @@ -18,7 +17,6 @@ <%=h event.start_time %> <%=h event.end_time %> <%=h event.rrule %> - <%=h event.custom_rrule %> <%=h event.allday %> <%=h event.url %> <%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %> diff --git a/test/controllers/events_controller_test.rb b/test/controllers/events_controller_test.rb index 9371ca78..46f3f4f1 100644 --- a/test/controllers/events_controller_test.rb +++ b/test/controllers/events_controller_test.rb @@ -4,6 +4,9 @@ class EventsControllerTest < ActionController::TestCase test "should get index" do login_as :quentin + node = create_node_with_published_page + Event.create!(node_id: node.id, start_time: Time.now, end_time: Time.now + 1.hour) + get :index assert_response :success assert_not_nil assigns(:events) diff --git a/test/models/event_test.rb b/test/models/event_test.rb index d85aadd9..e98605e7 100644 --- a/test/models/event_test.rb +++ b/test/models/event_test.rb @@ -29,7 +29,6 @@ class EventTest < ActiveSupport::TestCase :longitude => 13.378944, :rrule => "FOOBAR", :allday => false, - :custom_rrule => false, :node_id => @cal_node.id ) end @@ -44,7 +43,6 @@ class EventTest < ActiveSupport::TestCase :longitude => 13.378944, :rrule => nil, :allday => false, - :custom_rrule => false, :node_id => @cal_node.id ) @@ -62,7 +60,6 @@ class EventTest < ActiveSupport::TestCase :longitude => 13.378944, :rrule => "FREQ=WEEKLY;INTERVAL=1", :allday => false, - :custom_rrule => false, :node_id => @cal_node.id ) @@ -97,7 +94,6 @@ class EventTest < ActiveSupport::TestCase :longitude => 13.378944, :rrule => "FREQ=MONTHLY;INTERVAL=1;BYDAY=-1WE", :allday => false, - :custom_rrule => true, :node_id => @cal_node.id ) -- cgit v1.3 From cb610cebffae879344d5a8c6bebcc71ca5c04b2a Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 7 Jul 2026 21:45:35 +0200 Subject: Add or fix class names for the link underline rules to match --- app/views/assets/index.html.erb | 2 +- app/views/events/index.html.erb | 2 +- app/views/users/index.html.erb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb index e26830ba..31dae598 100644 --- a/app/views/assets/index.html.erb +++ b/app/views/assets/index.html.erb @@ -5,7 +5,7 @@ <%= will_paginate @assets %> - +
<% @assets.each do |asset| %> diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index ae4f4773..3065efd7 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,6 +1,6 @@

Listing events

-
+
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 59806db2..cf00ef69 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,4 +1,4 @@ -
Title Start time
+
-- cgit v1.3 From 92c3acb860adff26e1b960c275fd9c83fc2cf4ca Mon Sep 17 00:00:00 2001 From: erdgeist Date: Tue, 7 Jul 2026 21:46:25 +0200 Subject: Fix column count between table header and body --- app/views/events/index.html.erb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 3065efd7..3143a7b1 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -9,6 +9,7 @@ + <% @events.each do |event| %> @@ -20,9 +21,7 @@ - - - + <% end %>

Admins

Allday Url NodeAction
<%=h event.allday %> <%=h event.url %> <%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %><%= link_to 'show', event %><%= link_to 'edit', edit_event_path(event) %><%= button_to 'destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } %><%= link_to 'show', event %> | <%= link_to 'edit', edit_event_path(event) %> | <%= button_to 'destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } %>
-- cgit v1.3 From 3ae22916cd5fd0f63ffacc7a9e1aa97d311b83e6 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 9 Jul 2026 04:53:56 +0200 Subject: Fix button height mismatch between bordered and pill button styles, extend table styling to assets/users/events Fix button height mismatch, extend table styling to assets/users/events a.action_button (bordered) and the state_changing/destructive/computation pills (borderless) rendered at different heights, since each pill variant set its own padding at higher specificity than the shared rule meant to equalize them. Padding and border-radius now live only in one shared rule; also restores the #page_editor prefix on a.action_button, needed to outrank the #page_editor a wavy-underline rule. table.assets_table, table.user_table, and table.events_table now share table.node_table's border-collapse/header/hover treatment. tr min-height is dropped -- browsers don't honor height on -- in favor of cell padding, kept at zero for node_table (spacing already comes from its h4/p content) and set to 8px for the plain-text tables. --- app/views/assets/index.html.erb | 9 +++- app/views/events/index.html.erb | 12 ++--- app/views/events/show.html.erb | 103 ++++++++++++++++++++-------------------- app/views/users/index.html.erb | 14 +++++- public/stylesheets/admin.css | 60 ++++++++++++++++------- 5 files changed, 118 insertions(+), 80 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb index 31dae598..4301fee6 100644 --- a/app/views/assets/index.html.erb +++ b/app/views/assets/index.html.erb @@ -2,11 +2,16 @@ <%= link_to 'New asset', new_asset_path %> <% end %> - <%= will_paginate @assets %> - + + + + + + + <% @assets.each do |asset| %> diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 3143a7b1..c3e0e5ae 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,7 +1,7 @@

Listing events

PreviewNameType
- + @@ -9,23 +9,21 @@ - + <% @events.each do |event| %> - + - + <% end %>
Title Start time End timeAllday Url NodeAction
<%=h event.display_title %><%= link_to event.display_title, event %> <%=h event.start_time %> <%=h event.end_time %> <%=h event.rrule %> <%=h event.allday %> <%=h event.url %> <%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %><%= link_to 'show', event %> | <%= link_to 'edit', edit_event_path(event) %> | <%= button_to 'destroy', event, method: :delete, form: { data: { confirm: 'Are you sure?' }, class: 'button_to destructive' } %><%= link_to 'edit', edit_event_path(event) %>
-
- -<%= link_to 'New event', new_event_path %> +<%= link_to 'New event', new_event_path, class: 'action_button' %> diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb index e206bc4c..58122280 100644 --- a/app/views/events/show.html.erb +++ b/app/views/events/show.html.erb @@ -1,52 +1,51 @@ -<% content_for :subnavigation do %> - <% if @event.node %> - <%= link_to 'node', node_path(@event.node) %> - <% end %> - <%= link_to 'edit', edit_event_path(@event, return_to: request.path) %> - <%= button_to 'destroy', event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> -<% end %> - -

Event for node <%= @event.node.unique_name %>

- -

- Start time: - <%=h @event.start_time %> -

- -

- End time: - <%=h @event.end_time %> -

- -

- Rrule: - <%=h @event.rrule %> - <% if (human = @event.humanize_rrule(I18n.locale)) %> -
( <%= human %> ) - <% end %> -

- -

- Tags: - <%=h @event.tag_list %> -

- -

- Allday: - <%=h @event.allday %> -

- -

- Url: - <%=h @event.url %> -

- -

- Latitude: - <%=h @event.latitude %> -

- -

- Longitude: - <%=h @event.longitude %> -

+
+

<%= @event.node ? "Event for node #{@event.node.unique_name}" : "Event" %>

+ +
+
Actions
+
+
+ <% if @event.node %> +
+ <%= link_to 'Node', node_path(@event.node) %> +
+ <% end %> +
+ <%= link_to 'Edit', edit_event_path(@event, return_to: request.path), class: 'action_button' %> +
+
+ <%= button_to 'Destroy', event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> +
+
+
+ +
Start time
+
<%=h @event.start_time %>
+ +
End time
+
<%=h @event.end_time %>
+ +
Rrule
+
<%=h @event.rrule %>
+ + <% if (human = @event.humanize_rrule(I18n.locale)) %> +
Recurrence
+
<%= human %>
+ <% end %> + +
Tags
+
<%=h @event.tag_list %>
+ +
Allday
+
<%=h @event.allday %>
+ +
Url
+
<%=h @event.url %>
+ +
Latitude
+
<%=h @event.latitude %>
+ +
Longitude
+
<%=h @event.longitude %>
+
+
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index cf00ef69..88868f56 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -2,13 +2,25 @@

Admins

+ + Login + + + + <%= render :partial => "user", :locals => {:users => @users[:admin] ||= []} %>

Users

+ + Login + + + + <%= render :partial => "user", :locals => {:users => @users[:user] ||= []} %> <% content_for :subnavigation do %> <%= link_to "create", new_user_path %> -<% end %> \ No newline at end of file +<% end %> diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 3607166f..66f13b8e 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -274,8 +274,6 @@ form.button_to.state_changing input[type="submit"], form.button_to.state_changing button[type="submit"] { color: #0d47a1; background-color: #e3f2fd; - border-radius: 2px; - padding: 2px 8px; } form.button_to.state_changing input[type="submit"]:hover, @@ -288,8 +286,6 @@ form.button_to.destructive input[type="submit"], form.button_to.destructive button[type="submit"] { color: #cc0000; background-color: #fdecea; - border-radius: 2px; - padding: 2px 8px; } form.button_to.destructive input[type="submit"]:hover, @@ -302,8 +298,6 @@ form.button_to.computation input[type="submit"], form.button_to.computation button[type="submit"] { color: #00838f; background-color: #e0f2f1; - border-radius: 2px; - padding: 2px 8px; } form.button_to.computation input[type="submit"]:hover, @@ -385,15 +379,23 @@ table tr.header { text-align: left; } -table.node_table { +table.node_table , +table.assets_table, +table.user_table, +table.events_table { border-collapse: collapse; } table.node_table tr { - min-height: 2rem; border-bottom: 1px solid #000000; } +table.assets_table tr, +table.user_table tr, +table.events_table tr { + border-bottom: 1px solid #e8e8e8; +} + table.node_table th.node_id, table.node_table th.revision, table.node_table th.title { @@ -408,7 +410,10 @@ table.node_table th.title { min-width: 12rem; } -table.node_table tr.header { +table.node_table tr.header, +table.assets_table tr.header, +table.user_table tr.header, +table.events_table tr.header { height: 2rem; text-align: left; } @@ -421,6 +426,16 @@ table.node_table td { min-width: 2rem; } +table.assets_table td, +table.user_table td, +table.events_table td { + padding-top: 8px; + padding-bottom: 8px; + padding-right: 25px; + padding-left: 0px; + min-width: 2rem; +} + table.node_table .node_id { padding-left: 10px; padding-right: 15px; @@ -430,11 +445,17 @@ table.node_table .actions { text-transform: lowercase; } -table.node_table tr.header:hover { +table.node_table tr.header:hover, +table.assets_table tr.header:hover, +table.user_table tr.header:hover, +table.events_table tr.header:hover { background-color: #ffffff; } -table.node_table tr:hover { +table.node_table tr:hover, +table.assets_table tr:hover, +table.user_table tr:hover, +table.events_table tr:hover { background-color: #f1f1f1; } @@ -598,17 +619,18 @@ table.user_table td.user_login { display: block; } -#page_editor a.action_button, -.node_status form.button_to input[type="submit"], -.node_status form.button_to button[type="submit"] { +a.action_button, +form.button_to input[type="submit"], +form.button_to button[type="submit"] { padding: 4px 12px; line-height: 1.2; box-sizing: border-box; } -.node_status form.button_to input[type="submit"], -.node_status form.button_to button[type="submit"] { +form.button_to input[type="submit"], +form.button_to button[type="submit"] { border: 1px solid transparent; + border-radius: 2px; } .field_hint { @@ -659,7 +681,8 @@ div#page_editor { margin-left: 10px; } -#page_editor a.action_button { +#page_editor a.action_button, +a.action_button { display: inline-block; -webkit-appearance: none; appearance: none; @@ -671,7 +694,8 @@ div#page_editor { color: #000000; } -#page_editor a.action_button:hover { +#page_editor a.action_button:hover, +a.action_button:hover { color: #ffffff; background-color: #000000; } -- cgit v1.3 From 8310751d4db2854597d6379b24e346c65622972d Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 9 Jul 2026 14:19:36 +0200 Subject: Major resource view cleanup Remove dead pages#index and occurrences resource; fix menu_items#new menu_items#new called menu_item_params, which requires a submitted menu_item key that can never be present on a fresh GET -- new only ever needs a blank record to render against. pages#index and the entire occurrences resource were unmodified Rails scaffold generator output, unlinked from any nav and unreachable except by direct URL. pages#index had no controller action at all (@pages was never assigned); occurrences#index queried every row with no scoping or pagination and its layout referenced a scaffold.css asset that no longer exists in the pipeline. Neither is a real editorial surface -- occurrences are auto-generated from an event's RRULE and were never meant to be browsed as a flat list. Removed rather than repaired. pages#preview and pages#sort_images remain, now as explicit routes rather than under a full resources :pages block. --- app/controllers/menu_items_controller.rb | 2 +- app/controllers/users_controller.rb | 2 +- app/views/assets/index.html.erb | 6 ++-- app/views/assets/show.html.erb | 50 ++++++++++++++++------------- app/views/events/index.html.erb | 4 ++- app/views/menu_items/edit.html.erb | 51 +++++++++++++----------------- app/views/menu_items/index.html.erb | 9 ++---- app/views/nodes/index.html.erb | 5 +++ app/views/occurrences/index.html.erb | 2 +- app/views/pages/index.html.erb | 2 +- app/views/users/edit.html.erb | 54 ++++++++++++++------------------ app/views/users/index.html.erb | 17 +++++----- app/views/users/new.html.erb | 52 ++++++++++++++---------------- app/views/users/show.html.erb | 39 ++++++++++++----------- config/routes.rb | 9 ++---- public/stylesheets/admin.css | 32 +++++++++++++++++++ 16 files changed, 177 insertions(+), 159 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/controllers/menu_items_controller.rb b/app/controllers/menu_items_controller.rb index 1b1eb598..314d1ead 100644 --- a/app/controllers/menu_items_controller.rb +++ b/app/controllers/menu_items_controller.rb @@ -14,7 +14,7 @@ class MenuItemsController < ApplicationController end def new - @menu_item = MenuItem.new menu_item_params + @menu_item = MenuItem.new end def create diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f01691f7..6572b7a2 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -15,7 +15,7 @@ class UsersController < ApplicationController end def new - @user = User.new + @user = User.new(admin: params[:admin].present?) end def create diff --git a/app/views/assets/index.html.erb b/app/views/assets/index.html.erb index 4301fee6..6591091e 100644 --- a/app/views/assets/index.html.erb +++ b/app/views/assets/index.html.erb @@ -1,6 +1,6 @@ -<% content_for :subnavigation do %> - <%= link_to 'New asset', new_asset_path %> -<% end %> +

Assets

+ +<%= link_to 'New asset', new_asset_path, class: 'action_button' %> <%= will_paginate @assets %> diff --git a/app/views/assets/show.html.erb b/app/views/assets/show.html.erb index 694be5a5..02866780 100644 --- a/app/views/assets/show.html.erb +++ b/app/views/assets/show.html.erb @@ -1,23 +1,29 @@ -<% content_for :subnavigation do %> - <%= link_to 'Edit', edit_asset_path(@asset) %> - <%= link_to 'Back', assets_path %> -<% end %> +
+

<%= @asset.name %>

- - - - - - - - - - - - - - - - - -
Thumbnail<%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %>
Public Path<%= @asset.upload.url.sub(/\?\d+$/, "") %>
Content Type<%= @asset.upload.content_type %>
Size<%= "#{@asset.upload.size/1024} KB" %>
+
+
Actions
+
+
+
+ <%= link_to 'Edit', edit_asset_path(@asset), class: 'action_button' %> +
+
+ <%= link_to 'Back', assets_path %> +
+
+
+ +
Thumbnail
+
<%= image_tag @asset.upload.url(:medium), style: "max-width: 300px; max-height: 300px;" %>
+ +
Public Path
+
<%= @asset.upload.url.sub(/\?\d+$/, "") %>
+ +
Content Type
+
<%= @asset.upload.content_type %>
+ +
Size
+
<%= "#{@asset.upload.size/1024} KB" %>
+
+
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index c3e0e5ae..b6a5b1f0 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,4 +1,6 @@ -

Listing events

+

Events

+ +<%= link_to 'New event', new_event_path, class: 'action_button' %> diff --git a/app/views/menu_items/edit.html.erb b/app/views/menu_items/edit.html.erb index 98917082..dc5e8f97 100644 --- a/app/views/menu_items/edit.html.erb +++ b/app/views/menu_items/edit.html.erb @@ -1,32 +1,25 @@

Edit Menu Item

-<%= form_for @menu_item do |f| %> -
- - - - - - - - - - - - - - - - - - - - - -
Search - <%= text_field_tag :menu_search_term %> -
+
+ <%= form_for @menu_item do |f| %> +
+
Search
+
+ <%= text_field_tag :menu_search_term %> +
+
-
-
Node Id<%= f.text_field :node_id %>
Path<%= f.text_field :path %>
Title<%= f.text_field :title %>
<%= f.submit 'Update' %>
-<% end %> +
Node Id
+
<%= f.text_field :node_id %>
+ +
Path
+
<%= f.text_field :path %>
+ +
Title
+
<%= f.text_field :title %>
+ +
+
<%= f.submit 'Update' %>
+ <% end %> + + diff --git a/app/views/menu_items/index.html.erb b/app/views/menu_items/index.html.erb index c52c1506..e84199b3 100644 --- a/app/views/menu_items/index.html.erb +++ b/app/views/menu_items/index.html.erb @@ -1,10 +1,7 @@ -<% content_for :subnavigation do %> - <%= link_to "new", new_menu_item_path %> -<% end %> - -

Menu Items

+<%= link_to 'New menu item', new_menu_item_path, class: 'action_button' %> + <% @menu_items.each do |menu_item| %> @@ -16,7 +13,7 @@ <% end %> diff --git a/app/views/nodes/index.html.erb b/app/views/nodes/index.html.erb index 2399105f..903e80bf 100644 --- a/app/views/nodes/index.html.erb +++ b/app/views/nodes/index.html.erb @@ -3,6 +3,11 @@ <% end %>

Nodes

+
+ <%= link_to 'New node', new_node_path, class: 'action_button' %> + 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. +
+ <%= will_paginate @nodes %> diff --git a/app/views/occurrences/index.html.erb b/app/views/occurrences/index.html.erb index 0e998572..82818d09 100644 --- a/app/views/occurrences/index.html.erb +++ b/app/views/occurrences/index.html.erb @@ -1,4 +1,4 @@ -

Listing occurrences

+

Occurrences

diff --git a/app/views/pages/index.html.erb b/app/views/pages/index.html.erb index 91e53598..05c73117 100644 --- a/app/views/pages/index.html.erb +++ b/app/views/pages/index.html.erb @@ -1,4 +1,4 @@ -

Listing pages

+

Pages

diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb index df1005bc..77b33c6a 100644 --- a/app/views/users/edit.html.erb +++ b/app/views/users/edit.html.erb @@ -2,38 +2,32 @@ <% if @user.errors.any? %>
-
    <% @user.errors.full_messages.each do |msg| %>
  • <%= msg.gsub("Slug", "Title") %>
  • <% end %>
+
    <% @user.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • <% end %>
<% end %> +
+ <%= form_for @user do |f| %> +
+
Login
+
<%= f.text_field :login %>
-<%= form_for @user do |f| %> -
- - - - - - - - - - - - - - - - - <% if current_user.admin? %> - - - - +
E-Mail
+
<%= f.text_field :email %>
+ +
Password
+
<%= f.password_field :password %>
+ +
Confirm
+
<%= f.password_field :password_confirmation %>
+ + <% if current_user.admin? %> +
Admin?
+
<%= f.check_box :admin %>
+ <% end %> + +
+
<%= f.submit "Update" %>
<% end %> - - - - -
Login<%= f.text_field :login %>
E-Mail<%= f.text_field :email %>
Password<%= f.password_field :password %>
Confirm<%= f.password_field :password_confirmation %>
Admin?<%= f.check_box :admin %>
<%= f.submit "Update" %>
-<% end %> + + diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index 88868f56..46e958bf 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -1,7 +1,6 @@ +

Admins

+<%= link_to 'New admin user', new_user_path(admin: true), class: 'action_button' %> - - - @@ -9,9 +8,11 @@ <%= render :partial => "user", :locals => {:users => @users[:admin] ||= []} %> - - - +

Admins

Login

Users

+ +

Users

+<%= link_to 'New user', new_user_path, class: 'action_button' %> + @@ -20,7 +21,3 @@ <%= render :partial => "user", :locals => {:users => @users[:user] ||= []} %>
Login
- -<% content_for :subnavigation do %> - <%= link_to "create", new_user_path %> -<% end %> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 6beda4f1..ce38fdf9 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -2,36 +2,30 @@ <% if @user.errors.any? %>
-
    <% @user.errors.full_messages.each do |msg| %>
  • <%= msg.gsub("Slug", "Title") %>
  • <% end %>
+
    <% @user.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • <% end %>
<% end %> +
+ <%= form_for @user do |f| %> +
+
Login
+
<%= f.text_field :login %>
-<%= form_for @user do |f| %> - - - - - - - - - - - - - - - - - - - - - - - - - -
Login<%= f.text_field :login %>
E-Mail<%= f.text_field :email %>
Password<%= f.password_field :password %>
Confirm<%= f.password_field :password_confirmation %>
Admin?<%= f.check_box :admin %>
<%= f.submit "Create" %>
-<% end %> +
E-Mail
+
<%= f.text_field :email %>
+ +
Password
+
<%= f.password_field :password %>
+ +
Confirm
+
<%= f.password_field :password_confirmation %>
+ +
Admin?
+
<%= f.check_box :admin %>
+ +
+
<%= f.submit "Create" %>
+ <% end %> +
+
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 80483d3b..e744efeb 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,20 +1,23 @@ -<% content_for :subnavigation do %> - <%= link_to 'Edit', edit_user_path(@user) %> -<% end %> +
+

<%= @user.login %>

-

User: <%= @user.login %>

+
+
Actions
+
+
+
+ <%= link_to 'Edit', edit_user_path(@user), class: 'action_button' %> +
+
+
- - - - - - - - - - - - - -
Login<%= @user.login %>
E-Mail<%= @user.email %>
Admin?<%= @user.admin ? "yes" : "no" %>
\ No newline at end of file +
Login
+
<%= @user.login %>
+ +
E-Mail
+
<%= @user.email %>
+ +
Admin?
+
<%= @user.admin ? "yes" : "no" %>
+
+
diff --git a/config/routes.rb b/config/routes.rb index da46e5c4..5d688285 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,15 +20,10 @@ Cccms::Application.routes.draw do scope '(:locale)', locale: /de|en/ do resources :tags - resources :occurrences resources :events - resources :pages do - member do - get :preview - put :sort_images - end - end + get 'pages/:id/preview', to: 'pages#preview', as: :preview_page + put 'pages/:id/sort_images', to: 'pages#sort_images', as: :sort_images_page resources :nodes do collection do diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 66f13b8e..f00a6581 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -640,6 +640,13 @@ form.button_to button[type="submit"] { color: #969696; padding-bottom: 4px; } + +.action_button + .field_hint { + display: inline; + margin-left: 0.5rem; + margin-top: 0; +} + /* Identical declaration block to #search_results p span.result_path / #menu_search_results p span.result_path below -- three independent copies of the same "small gray helper text" style. */ @@ -692,6 +699,7 @@ a.action_button { font-weight: bold; text-decoration: none; color: #000000; + margin-bottom: 1rem; } #page_editor a.action_button:hover, @@ -700,6 +708,11 @@ a.action_button:hover { background-color: #000000; } +#page_editor form input[type=text], +#page_editor form input[type=password] { + padding: 5px; +} + @media(min-width:1016px) { input#tag_list, input#node_staged_slug, @@ -731,6 +744,11 @@ a.action_button:hover { #page_editor #metadata, #page_editor #content, #admin_overview { margin-left: -125px; } + + #page_editor form input[type=text], + #page_editor form input[type=password] { + width: 690px; + } } @media(max-width:1015px) { @@ -773,6 +791,12 @@ a.action_button:hover { font-weight: bold; } + #page_editor form input[type=text], + #page_editor form input[type=password] { + box-sizing: border-box; + width: 100%; + } + input[type=text], textarea { font-size: 1.5rem; } @@ -920,6 +944,14 @@ div#draft_list table td.actions a { cursor: grab; } +#menu_item_list td a { + text-decoration: underline; + text-decoration-style: wavy; + text-decoration-color: #b0b0b0; + text-decoration-thickness: 1px; + text-underline-offset: 2px; +} + .ui-state-highlight td { height: 20px; } -- cgit v1.3 From ae48c9e86411f8f54f29e72a11b1e4ced48fe437 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 9 Jul 2026 15:50:22 +0200 Subject: Paginate Events index --- app/controllers/events_controller.rb | 4 ++-- app/views/events/index.html.erb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index b98a38e8..b9b78926 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -9,10 +9,10 @@ class EventsController < ApplicationController # GET /events # GET /events.xml def index - @events = Event.all + @events = Event.order(:id) respond_to do |format| - format.html # index.html.erb + format.html { @events = @events.paginate(page: params[:page], per_page: 25) } format.xml { render :xml => @events } end end diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index b6a5b1f0..f579fc06 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -2,6 +2,8 @@ <%= link_to 'New event', new_event_path, class: 'action_button' %> +<%= will_paginate @events %> + @@ -27,5 +29,3 @@ <% end %>
Title
- -<%= link_to 'New event', new_event_path, class: 'action_button' %> -- cgit v1.3 From 6dcbf019deda9ec2809f8735c8b10ba3a5701189 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Thu, 9 Jul 2026 18:55:04 +0200 Subject: Add an events view for events without node, part 2 --- app/controllers/events_controller.rb | 5 +++++ app/views/events/index.html.erb | 1 + 2 files changed, 6 insertions(+) (limited to 'app/views/events/index.html.erb') diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index b9b78926..be3f5476 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -17,6 +17,11 @@ class EventsController < ApplicationController end end + # GET /events/without_node + def without_node + @events = Event.where(node_id: nil).order(:start_time).paginate(page: params[:page], per_page: 25) + end + # GET /events/1 # GET /events/1.xml def show diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index f579fc06..8127e3a4 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,6 +1,7 @@

Events

<%= link_to 'New event', new_event_path, class: 'action_button' %> +<%= link_to 'View events without a page →', without_node_events_path %> <%= will_paginate @events %> -- cgit v1.3 From c9401e45433ea45b46f9a8faf1e7e537e4683244 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 10 Jul 2026 18:07:15 +0200 Subject: Fix rrule/url column overflow on events#index Long RRULEs previously overflowed their column with no wrap point; now escaped and rendered with a after each semicolon, so a long rule wraps at a clause boundary instead of running off the table. Deliberately not truncated -- a cut-off RRULE's trailing clause (BYDAY, BYMONTH, etc.) is usually the most specific part. The url column is now a real link, truncated with an ellipsis at a fixed width -- deliberately no tooltip, since hovering a real link already shows the full address in the browser's own status bar. rrule_with_break_opportunities splits on the raw string's own semicolons before escaping each piece, not after -- escaping first and searching the result for semicolons also matches the ones inside </> entities, corrupting anything containing a literal < or >. --- app/helpers/events_helper.rb | 11 +++++++++++ app/views/events/index.html.erb | 8 ++++++-- public/stylesheets/admin.css | 15 +++++++++++++++ test/models/helpers/events_helper_test.rb | 21 +++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) (limited to 'app/views/events/index.html.erb') diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 8a9a878c..5e84f534 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -1,2 +1,13 @@ +require 'cgi' + module EventsHelper + # Insert a zero-width break opportunity after each semicolon, so a long + # RRULE can wrap at a clause boundary instead of overflowing its column. + # Deliberately , not ellipsis -- unlike a URL, an RRULE's trailing + # characters (BYDAY, BYMONTH, etc.) are usually the most specific part, + # and truncating them would hide exactly the wrong end of the string. + def rrule_with_break_opportunities(rrule) + return "" if rrule.blank? + raw(rrule.split(';', -1).map { |part| CGI.escapeHTML(part) }.join(';')) + end end diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 8127e3a4..3d953d5f 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -22,9 +22,13 @@ <%= link_to event.display_title, event %> <%=h event.start_time %> <%=h event.end_time %> - <%=h event.rrule %> + <%= rrule_with_break_opportunities(event.rrule) %> <%=h event.allday %> - <%=h event.url %> + + <% if event.url.present? %> + <%= link_to event.url, event.url %> + <% end %> + <%= event.node ? link_to(event.node_id, node_path(event.node)) : '' %> <%= link_to 'edit', edit_event_path(event) %> diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css index 1a817286..4723f507 100644 --- a/public/stylesheets/admin.css +++ b/public/stylesheets/admin.css @@ -519,6 +519,21 @@ table.revisions_table tr:hover { background-color: #f1f1f1; } +.events_table .rrule_text { + display: inline-block; + max-width: 300px; + overflow-wrap: break-word; +} + +.events_table .truncate { + display: inline-block; + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + vertical-align: bottom; +} + #diffview del { background: #ffd7d5; color: #82071e; diff --git a/test/models/helpers/events_helper_test.rb b/test/models/helpers/events_helper_test.rb index 2e7567e0..0486b3e7 100644 --- a/test/models/helpers/events_helper_test.rb +++ b/test/models/helpers/events_helper_test.rb @@ -1,4 +1,25 @@ require 'test_helper' class EventsHelperTest < ActionView::TestCase + test "rrule_with_break_opportunities inserts a break opportunity after each semicolon" do + result = rrule_with_break_opportunities("FREQ=MONTHLY;BYMONTH=1,2,3;BYDAY=-1TH") + assert_equal "FREQ=MONTHLY;BYMONTH=1,2,3;BYDAY=-1TH", result + assert result.html_safe? + end + + test "rrule_with_break_opportunities escapes HTML-significant characters" do + result = rrule_with_break_opportunities("FREQ=WEEKLY;BYDAY=