From da59dea46f55c64a3090b83a6321fbecd2ee6f60 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sun, 2 Aug 2026 22:45:51 +0200 Subject: Witness calendar entries --- app/models/event.rb | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'app/models/event.rb') diff --git a/app/models/event.rb b/app/models/event.rb index b8651a81..7726f9bf 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -20,8 +20,85 @@ class Event < ApplicationRecord title.presence || node&.head&.title || "Untitled event" end + def save_witnessed(actor:) + saved = false + transaction do + saved = save + raise ActiveRecord::Rollback unless saved + witness_event!("event_create", actor) + end + saved + end + + def update_witnessed(attributes, actor:) + updated = false + transaction do + updated = update(attributes) + raise ActiveRecord::Rollback unless updated + changes = event_changes + witness_event!("event_update", actor, changes) if changes.any? + end + updated + end + + def destroy_witnessed(actor:) + destroyed = false + transaction do + witness_event!("event_destroy", actor) + destroyed = destroy + raise ActiveRecord::Rollback unless destroyed + end + destroyed + end + private def generate_occurrences Occurrence.generate self end + + def event_snapshot + { + :event_title => title.presence || node&.unique_name || "##{id}", + :start_time => start_time&.iso8601, + :end_time => end_time&.iso8601, + :allday => allday, + :rrule => rrule.presence, + :location => location.presence, + :url => url.presence, + :event_tags => tag_list.to_a.sort, + :path => node&.unique_name + }.compact + end + + def event_changes + pairs = {} + + saved_changes.except("updated_at", "created_at", "description") + .each do |attribute, (before, after)| + key, pair = + case attribute + when "node_id" + ["node_path", { "from" => Node.find_by(:id => before)&.unique_name, + "to" => Node.find_by(:id => after)&.unique_name }] + when "start_time", "end_time" + [attribute, { "from" => before&.iso8601, "to" => after&.iso8601 }] + when "tag_list" + ["tags", { "from" => Array(before).sort, "to" => Array(after).sort }] + else + [attribute, { "from" => before, "to" => after }] + end + pairs[key] = pair + end + + extra = {} + extra[:changes] = pairs if pairs.any? + extra[:description_changed] = true if saved_changes.key?("description") + extra + end + + def witness_event!(verb, actor, extra = {}) + NodeAction.record!(:node => node, :participants => [node, self].compact, + :action => verb, :user => actor, + **event_snapshot, **extra) + end end -- cgit v1.3