diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-09 19:27:47 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-09 19:27:47 +0200 |
| commit | ff2edea873de50c5be41cd24bb7a8d1e0d75d9ee (patch) | |
| tree | 7fa86c82b0ead0c91fab1252be22d413908f9a9a /app/views/events/edit.html.erb | |
| parent | 83a74c6d01e0be50d5806d8253de9f2ad6d5c143 (diff) | |
Modernize events#edit: node re-link guard, editable Title, layout overhaul
Converts the <p>-per-field layout to node_description/node_content,
matching every other converted view. The RRULE builder's internal
markup and JS-driven show/hide are untouched -- only its containing
block moved.
Adds the same node picker and optional Title field events#new just
got, with one addition specific to edit: an already-linked event
shows its node as a plain link, with the picker itself gated behind
a <details> disclosure. Re-linking a live event to a different node
is rare and has real side effects (which page it appears under, which
tag-prefill applies), so it gets an extra click rather than sitting
as easy to trigger as the unlinked case, which stays unguarded.
Moves Destroy out of the subnav and into the page body, matching
events#show. Required extracting it (and Back) into their own block
outside form_for -- button_to generates its own nested <form>, which
the browser silently drops when nested inside another; this is the
same failure mode nodes#edit hit earlier in this branch. Reuses the
existing .node_action_bar class rather than the naked block that
would've resulted, adding a "standalone_action_bar" modifier for the
two things specific to living outside #page_editor: the -125px
margin every other line in the form gets for free, and link
underline visibility, since this is the first .node_action_bar
instance with a bare <a> rather than only buttons.
Diffstat (limited to 'app/views/events/edit.html.erb')
| -rw-r--r-- | app/views/events/edit.html.erb | 151 |
1 files changed, 85 insertions, 66 deletions
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb index d37c299..6cb04bd 100644 --- a/app/views/events/edit.html.erb +++ b/app/views/events/edit.html.erb | |||
| @@ -1,76 +1,95 @@ | |||
| 1 | <% content_for :subnavigation do %> | ||
| 2 | <%= link_to 'back', safe_return_to(params[:return_to] || events_path) %> | ||
| 3 | <%= button_to 'destroy', event_path(@event), method: :delete, form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> | ||
| 4 | <% end %> | ||
| 5 | |||
| 6 | <h1>Editing event</h1> | 1 | <h1>Editing event</h1> |
| 7 | 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 'Destroy', event_path(@event), method: :delete, | ||
| 6 | form: { data: { confirm: 'Delete this event?' }, class: 'button_to destructive' } %> | ||
| 7 | </div> | ||
| 8 | |||
| 8 | <%= form_for(@event) do |f| %> | 9 | <%= form_for(@event) do |f| %> |
| 9 | <%= hidden_field_tag :return_to, @return_to %> | 10 | <%= hidden_field_tag :return_to, @return_to %> |
| 10 | <%= form_error_messages(f) %> | 11 | <%= form_error_messages(f) %> |
| 11 | 12 | ||
| 12 | <p> | 13 | <div id="page_editor"> |
| 13 | <%= f.label :start_time %><br /> | 14 | <div id="content"> |
| 14 | <%= f.datetime_select :start_time %> | 15 | <div class="node_description">Node</div> |
| 15 | </p> | 16 | <div class="node_content"> |
| 16 | <p> | 17 | <% if @event.node %> |
| 17 | <%= f.label :end_time %><br /> | 18 | <%= link_to @event.node.title, node_path(@event.node) %> |
| 18 | <%= f.datetime_select :end_time %> | 19 | <details> |
| 19 | </p> | 20 | <summary>Change node</summary> |
| 20 | <p> | 21 | <%= text_field_tag :event_node_search_term %> |
| 21 | <%= f.label :rrule, "Recurrence" %> | 22 | <div id="search_results"></div> |
| 22 | <div id="rrule_builder"> | 23 | <span class="field_hint">This will re-link the event to a different node — rarely needed.</span> |
| 23 | <p> | 24 | </details> |
| 24 | <label><%= radio_button_tag "rrule_freq", "weekly", true %> Weekly</label> | 25 | <% else %> |
| 25 | <label><%= radio_button_tag "rrule_freq", "monthly" %> Monthly</label> | 26 | <%= text_field_tag :event_node_search_term %> |
| 26 | </p> | 27 | <div id="search_results"></div> |
| 27 | <div id="rrule_weekly_options"> | 28 | <span class="field_hint">Optional — search and pick a node to associate this event with a page.</span> |
| 28 | <p><label><%= check_box_tag "rrule_biweekly" %> Every 2 weeks</label></p> | 29 | <% end %> |
| 29 | <p> | 30 | <%= f.hidden_field :node_id %> |
| 30 | <% %w[MO TU WE TH FR SA SU].each do |code| %> | 31 | </div> |
| 31 | <label><%= check_box_tag "rrule_byday_#{code}" %> <%= RruleHumanizer::WEEKDAY_NAMES_ABBR[:de][code] %></label> | 32 | |
| 32 | <% end %> | 33 | <div class="node_description">Start time</div> |
| 33 | </p> | 34 | <div class="node_content"><%= f.datetime_select :start_time %></div> |
| 35 | |||
| 36 | <div class="node_description">End time</div> | ||
| 37 | <div class="node_content"><%= f.datetime_select :end_time %></div> | ||
| 38 | |||
| 39 | <div class="node_description">Recurrence</div> | ||
| 40 | <div class="node_content"> | ||
| 41 | <div id="rrule_builder"> | ||
| 42 | <p> | ||
| 43 | <label><%= radio_button_tag "rrule_freq", "weekly", true %> Weekly</label> | ||
| 44 | <label><%= radio_button_tag "rrule_freq", "monthly" %> Monthly</label> | ||
| 45 | </p> | ||
| 46 | <div id="rrule_weekly_options"> | ||
| 47 | <p><label><%= check_box_tag "rrule_biweekly" %> Every 2 weeks</label></p> | ||
| 48 | <p> | ||
| 49 | <% %w[MO TU WE TH FR SA SU].each do |code| %> | ||
| 50 | <label><%= check_box_tag "rrule_byday_#{code}" %> <%= RruleHumanizer::WEEKDAY_NAMES_ABBR[:de][code] %></label> | ||
| 51 | <% end %> | ||
| 52 | </p> | ||
| 53 | </div> | ||
| 54 | <div id="rrule_monthly_options" style="display: none;"> | ||
| 55 | <p><label><%= check_box_tag "rrule_monthly_ordinal" %> On a specific weekday each month</label></p> | ||
| 56 | <p id="rrule_ordinal_fields" style="display: none;"> | ||
| 57 | <%= select_tag "rrule_ordinal", options_for_select([["1.", 1], ["2.", 2], ["3.", 3], ["4.", 4], ["letzter", -1], ["vorletzter", -2]]) %> | ||
| 58 | <%= select_tag "rrule_ordinal_day", options_for_select(%w[MO TU WE TH FR SA SU].map { |c| [RruleHumanizer::WEEKDAY_NAMES[:de][c], c] }) %> | ||
| 59 | </p> | ||
| 60 | </div> | ||
| 61 | <p> | ||
| 62 | <label><%= check_box_tag "rrule_exclude_month" %> Except in one month</label> | ||
| 63 | <%= select_tag "rrule_excluded_month", options_for_select((1..12).map { |m| [RruleHumanizer::MONTH_NAMES[:de][m-1], m] }), style: "display: none;" %> | ||
| 64 | </p> | ||
| 65 | <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> | ||
| 66 | </div> | ||
| 67 | <%= f.text_field :rrule, id: "event_rrule" %> | ||
| 34 | </div> | 68 | </div> |
| 35 | <div id="rrule_monthly_options" style="display: none;"> | 69 | |
| 36 | <p><label><%= check_box_tag "rrule_monthly_ordinal" %> On a specific weekday each month</label></p> | 70 | <div class="node_description">Title</div> |
| 37 | <p id="rrule_ordinal_fields" style="display: none;"> | 71 | <div class="node_content"> |
| 38 | <%= select_tag "rrule_ordinal", options_for_select([["1.", 1], ["2.", 2], ["3.", 3], ["4.", 4], ["letzter", -1], ["vorletzter", -2]]) %> | 72 | <%= f.text_field :title %> |
| 39 | <%= select_tag "rrule_ordinal_day", options_for_select(%w[MO TU WE TH FR SA SU].map { |c| [RruleHumanizer::WEEKDAY_NAMES[:de][c], c] }) %> | 73 | <span id="event_title_hint" class="field_hint">Optional — if left blank, the associated node's title is used.</span> |
| 40 | </p> | ||
| 41 | </div> | 74 | </div> |
| 42 | <p> | 75 | |
| 43 | <label><%= check_box_tag "rrule_exclude_month" %> Except in one month</label> | 76 | <div class="node_description">Tags</div> |
| 44 | <%= select_tag "rrule_excluded_month", options_for_select((1..12).map { |m| [RruleHumanizer::MONTH_NAMES[:de][m-1], m] }), style: "display: none;" %> | 77 | <div class="node_content"><%= f.text_field :tag_list %></div> |
| 45 | </p> | 78 | |
| 46 | <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> | 79 | <div class="node_description">Allday</div> |
| 80 | <div class="node_content"><%= f.check_box :allday %></div> | ||
| 81 | |||
| 82 | <div class="node_description">Url</div> | ||
| 83 | <div class="node_content"><%= f.text_field :url %></div> | ||
| 84 | |||
| 85 | <div class="node_description">Latitude</div> | ||
| 86 | <div class="node_content"><%= f.text_field :latitude %></div> | ||
| 87 | |||
| 88 | <div class="node_description">Longitude</div> | ||
| 89 | <div class="node_content"><%= f.text_field :longitude %></div> | ||
| 90 | |||
| 91 | <div class="node_description"></div> | ||
| 92 | <div class="node_content"><%= f.submit 'Update' %></div> | ||
| 47 | </div> | 93 | </div> |
| 48 | <%= f.text_field :rrule, id: "event_rrule" %> | 94 | </div> |
| 49 | </p> | ||
| 50 | <p> | ||
| 51 | <%= f.label :tag_list, "Tags" %><br /> | ||
| 52 | <%= f.text_field :tag_list %> | ||
| 53 | </p> | ||
| 54 | <p> | ||
| 55 | <%= f.label :allday %><br /> | ||
| 56 | <%= f.check_box :allday %> | ||
| 57 | </p> | ||
| 58 | <p> | ||
| 59 | <%= f.label :url %><br /> | ||
| 60 | <%= f.text_field :url %> | ||
| 61 | </p> | ||
| 62 | <p> | ||
| 63 | <%= f.label :latitude %><br /> | ||
| 64 | <%= f.text_field :latitude %> | ||
| 65 | </p> | ||
| 66 | <p> | ||
| 67 | <%= f.label :longitude %><br /> | ||
| 68 | <%= f.text_field :longitude %> | ||
| 69 | </p> | ||
| 70 | <p> | ||
| 71 | <%= f.hidden_field :node_id %> | ||
| 72 | </p> | ||
| 73 | <p> | ||
| 74 | <%= f.submit 'Update' %> | ||
| 75 | </p> | ||
| 76 | <% end %> | 95 | <% end %> |
