From 9abed217e9e06ca029f8002d8f2763632bdeabf0 Mon Sep 17 00:00:00 2001 From: Anna Topalidi Date: Thu, 13 Feb 2025 13:48:46 +0100 Subject: [PATCH 1/3] reminred customization --- .../decidim/meetings/admin/copy_meeting.rb | 3 ++ .../decidim/meetings/admin/create_meeting.rb | 3 ++ .../decidim/meetings/admin/publish_meeting.rb | 2 +- .../decidim/meetings/admin/update_meeting.rb | 3 ++ .../decidim/meetings/create_meeting.rb | 6 ++- .../decidim/meetings/update_meeting.rb | 6 ++- .../meetings/upcoming_meeting_event.rb | 32 +++++++++++++++ .../decidim/meetings/admin/meeting_form.rb | 18 +++++++++ .../forms/decidim/meetings/meeting_form.rb | 18 +++++++++ .../decidim/meetings/meeting_presenter.rb | 9 +++++ .../meetings/admin/meetings/_form.html.erb | 12 ++++++ .../decidim/meetings/meetings/_form.html.erb | 11 +++++ decidim-meetings/config/locales/en.yml | 13 ++++-- ...inder_customization_to_decidim_meetings.rb | 9 +++++ decidim-meetings/lib/decidim/meetings.rb | 2 +- .../lib/decidim/meetings/test/factories.rb | 3 ++ .../spec/commands/admin/copy_meeting_spec.rb | 4 ++ .../commands/admin/create_meeting_spec.rb | 28 +++++++++++++ .../commands/admin/update_meeting_spec.rb | 16 ++++++++ .../spec/commands/create_meeting_spec.rb | 24 ++++++++++- .../spec/commands/update_meeting_spec.rb | 19 ++++++++- .../spec/forms/admin/meeting_form_spec.rb | 40 ++++++++++++++++++- .../spec/forms/meeting_form_spec.rb | 38 ++++++++++++++++++ 23 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 decidim-meetings/db/migrate/20250213114031_add_reminder_customization_to_decidim_meetings.rb diff --git a/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb index c9444c97dd31a..b683d64b23e57 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb @@ -69,6 +69,9 @@ def copy_meeting! comments_end_time: form.comments_end_time, registration_type: form.registration_type, registration_url: form.registration_url, + reminder_enabled: form.reminder_enabled, + send_reminders_before_hours: form.send_reminders_before_hours, + reminder_message_custom_content: form.reminder_message_custom_content, **fields_from_meeting ) end diff --git a/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb index 560d1b5d9430c..74f8f4d568e33 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb @@ -59,6 +59,9 @@ def create_meeting! comments_enabled: form.comments_enabled, comments_start_time: form.comments_start_time, comments_end_time: form.comments_end_time, + reminder_enabled: form.reminder_enabled, + send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil, + reminder_message_custom_content: form.reminder_enabled ? form.reminder_message_custom_content : {}, iframe_access_level: form.iframe_access_level } diff --git a/decidim-meetings/app/commands/decidim/meetings/admin/publish_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/admin/publish_meeting.rb index 56c59e67ff1d7..86f750bfba7d9 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/publish_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/publish_meeting.rb @@ -65,7 +65,7 @@ def schedule_upcoming_meeting_notification checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(meeting) Decidim::Meetings::UpcomingMeetingNotificationJob - .set(wait_until: meeting.start_time - Decidim::Meetings.upcoming_meeting_notification) + .set(wait_until: meeting.start_time - meeting.send_reminders_before_hours.hours) .perform_later(meeting.id, checksum) end end diff --git a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb index 0e4c42cf2a2a8..ea8607f2d3a9e 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb @@ -64,6 +64,9 @@ def update_meeting! comments_enabled: form.comments_enabled, comments_start_time: form.comments_start_time, comments_end_time: form.comments_end_time, + reminder_enabled: form.reminder_enabled, + send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil, + reminder_message_custom_content: form.reminder_enabled ? form.reminder_message_custom_content : nil, iframe_access_level: form.iframe_access_level ) end diff --git a/decidim-meetings/app/commands/decidim/meetings/create_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/create_meeting.rb index 841cf3bc4e3de..ed5fc2424f35c 100644 --- a/decidim-meetings/app/commands/decidim/meetings/create_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/create_meeting.rb @@ -32,6 +32,7 @@ def call def create_meeting! parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite parsed_description = Decidim::ContentProcessor.parse(form.description, current_organization: form.current_organization).rewrite + parsed_reminder_message = Decidim::ContentProcessor.parse(form.reminder_message_custom_content, current_organization: form.current_organization).rewrite params = { scope: form.scope, @@ -56,6 +57,9 @@ def create_meeting! type_of_meeting: form.clean_type_of_meeting, component: form.current_component, published_at: Time.current, + reminder_enabled: form.reminder_enabled, + send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil, + reminder_message_custom_content: form.reminder_enabled ? { I18n.locale => parsed_reminder_message } : {}, iframe_embed_type: form.iframe_embed_type, iframe_access_level: form.iframe_access_level } @@ -77,7 +81,7 @@ def schedule_upcoming_meeting_notification checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(meeting) Decidim::Meetings::UpcomingMeetingNotificationJob - .set(wait_until: meeting.start_time - Decidim::Meetings.upcoming_meeting_notification) + .set(wait_until: meeting.start_time - form.send_reminders_before_hours.hours) .perform_later(meeting.id, checksum) end diff --git a/decidim-meetings/app/commands/decidim/meetings/update_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/update_meeting.rb index 3bc92672e1717..f46b523601921 100644 --- a/decidim-meetings/app/commands/decidim/meetings/update_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/update_meeting.rb @@ -38,6 +38,7 @@ def call def update_meeting! parsed_title = Decidim::ContentProcessor.parse_with_processor(:hashtag, form.title, current_organization: form.current_organization).rewrite parsed_description = Decidim::ContentProcessor.parse(form.description, current_organization: form.current_organization).rewrite + parsed_reminder_message = Decidim::ContentProcessor.parse(form.reminder_message_custom_content, current_organization: form.current_organization).rewrite Decidim.traceability.update!( meeting, @@ -63,6 +64,9 @@ def update_meeting! registrations_enabled: form.registrations_enabled, type_of_meeting: form.clean_type_of_meeting, online_meeting_url: form.online_meeting_url, + reminder_enabled: form.reminder_enabled, + send_reminders_before_hours: form.reminder_enabled ? form.send_reminders_before_hours : nil, + reminder_message_custom_content: form.reminder_enabled ? { I18n.locale => parsed_reminder_message } : {}, iframe_embed_type: form.iframe_embed_type, iframe_access_level: form.iframe_access_level }, @@ -97,7 +101,7 @@ def schedule_upcoming_meeting_notification checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(meeting) Decidim::Meetings::UpcomingMeetingNotificationJob - .set(wait_until: meeting.start_time - Decidim::Meetings.upcoming_meeting_notification) + .set(wait_until: meeting.start_time - meeting.send_reminders_before_hours.hours) .perform_later(meeting.id, checksum) end end diff --git a/decidim-meetings/app/events/decidim/meetings/upcoming_meeting_event.rb b/decidim-meetings/app/events/decidim/meetings/upcoming_meeting_event.rb index 13bdb903bf367..6cfb4640483f3 100644 --- a/decidim-meetings/app/events/decidim/meetings/upcoming_meeting_event.rb +++ b/decidim-meetings/app/events/decidim/meetings/upcoming_meeting_event.rb @@ -4,6 +4,38 @@ module Decidim module Meetings class UpcomingMeetingEvent < Decidim::Events::SimpleEvent include Decidim::Meetings::MeetingEvent + + i18n_attributes :reminders_before_hours + + def email_intro + (custom_message.presence || default_email_intro).to_s.html_safe + end + + def i18n_options + { + resource_title: resource_title, + resource_path: resource_path, + resource_url: resource_url, + participatory_space_url: participatory_space_url, + participatory_space_title: participatory_space_title, + reminders_before_hours: resource.send_reminders_before_hours, + scope: event_name + } + end + + private + + def reminder_message + translated_attribute(resource.reminder_message_custom_content) + end + + def default_email_intro + I18n.t("decidim.events.meetings.upcoming_meeting.email_intro", **i18n_options) + end + + def custom_message + Decidim::Meetings::MeetingPresenter.new(resource).reminder_message_custom_content + end end end end diff --git a/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb index a76eb2ce97bf4..1b95aadc5a998 100644 --- a/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb @@ -21,11 +21,14 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm attribute :comments_start_time, Decidim::Attributes::TimeWithZone attribute :comments_end_time, Decidim::Attributes::TimeWithZone attribute :iframe_access_level, String + attribute :reminder_enabled, Boolean, default: true + attribute :send_reminders_before_hours, Integer, default: Decidim::Meetings.upcoming_meeting_notification.in_hours translatable_attribute :title, String translatable_attribute :description, String translatable_attribute :location, String translatable_attribute :location_hints, String + translatable_attribute :reminder_message_custom_content, String validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.iframe_embed_types } validates :title, translatable_presence: true @@ -41,6 +44,9 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? } validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? } validates :clean_type_of_meeting, presence: true + validates :send_reminders_before_hours, + presence: true, if: :reminder_enabled, + numericality: { only_integer: true, greater_than: 0, if: :reminder_enabled } validates( :iframe_access_level, inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels }, @@ -69,6 +75,18 @@ def number_of_services alias component current_component + def send_reminders_before_hours + return nil unless reminder_enabled + + super + end + + def reminder_message_custom_content + return {} unless reminder_enabled + + super + end + # Finds the Scope from the given decidim_scope_id, uses component scope if missing. # # Returns a Decidim::Scope diff --git a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb index 7bef17fe9bdd5..f28f6816d04dd 100644 --- a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb @@ -19,6 +19,9 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm attribute :registration_terms, String attribute :iframe_embed_type, String, default: "none" attribute :iframe_access_level, String + attribute :reminder_enabled, Boolean, default: true + attribute :send_reminders_before_hours, Integer, default: Decidim::Meetings.upcoming_meeting_notification.in_hours + attribute :reminder_message_custom_content, String validates :iframe_embed_type, inclusion: { in: Decidim::Meetings::Meeting.participants_iframe_embed_types } validates :title, presence: true @@ -34,6 +37,9 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? } validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? } validates :clean_type_of_meeting, presence: true + validates :send_reminders_before_hours, + presence: true, if: :reminder_enabled, + numericality: { only_integer: true, greater_than: 0, if: :reminder_enabled } validates( :iframe_access_level, inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels }, @@ -56,6 +62,18 @@ def map_model(model) alias component current_component + def send_reminders_before_hours + return nil unless reminder_enabled + + super + end + + def reminder_message_custom_content + return {} unless reminder_enabled + + super + end + # Finds the Scope from the given decidim_scope_id, uses the compoenent scope if missing. # # Returns a Decidim::Scope diff --git a/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb b/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb index 0a8ccb82f0c48..bb874b75ef946 100644 --- a/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb +++ b/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb @@ -76,6 +76,15 @@ def registration_email_custom_content(links: false, all_locales: false) end end + def reminder_message_custom_content(links: false, all_locales: false) + return unless meeting + + handle_locales(meeting.reminder_message_custom_content, all_locales) do |content| + renderer = Decidim::ContentRenderers::HashtagRenderer.new(content) + renderer.render(links: links).html_safe + end + end + # start time and end time in rfc3339 format removing '-' and ':' symbols # joined with '/'. This format is used to generate the dates query param # in google calendars event link diff --git a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb index 2fa6372ca17ed..a4a430fdd960f 100644 --- a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb @@ -99,6 +99,18 @@ <%= render partial: "decidim/comments/admin/shared/availability_fields", locals: { form: form } %> + +
+ <%= form.check_box :reminder_enabled, label: t("reminder_enabled", scope: "decidim.meetings.admin.meetings.form"), "data-toggle": "customize_reminder_times" %> +
+ +
"> +
+ <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form") %> +
+ + <%= form.translated :editor, :reminder_message_custom_content, label: t("reminder_message", scope: "decidim.meetings.admin.meetings.form"), hashtaggable: true, help_text: t("reminder_message_help_text", scope: "decidim.meetings.admin.meetings.form") %> +
diff --git a/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb b/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb index e655fe5a2fe49..3ebea79e947d4 100644 --- a/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb @@ -89,6 +89,17 @@
+
+ <%= form.check_box :reminder_enabled, label: t("reminder_enabled", scope: "decidim.meetings.admin.meetings.form"), "data-toggle": "customize_reminder_times" %> +
+ +
"> +
+ <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form") %> +
+ <%= text_editor_for(form, :reminder_message_custom_content, hashtaggable: true, label: t("reminder_message", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_message_help_text", scope: "decidim.meetings.admin.meetings.form") ) %> +
+
<%= form.select( :user_group_id, diff --git a/decidim-meetings/config/locales/en.yml b/decidim-meetings/config/locales/en.yml index 067d5c7408c39..a82ff7f3c963d 100644 --- a/decidim-meetings/config/locales/en.yml +++ b/decidim-meetings/config/locales/en.yml @@ -191,10 +191,10 @@ en: email_subject: The "%{resource_title}" meeting has enabled registrations. notification_title: The %{resource_title} meeting has enabled registrations. upcoming_meeting: - email_intro: The "%{resource_title}" meeting will start in less than 48h. - email_outro: You have received this notification because you are following the "%{resource_title}" meeting. You can unfollow it from the previous link. - email_subject: The "%{resource_title}" meeting will start in less than 48h. - notification_title: The %{resource_title} meeting will start in less than 48h. + email_intro: The "%{resource_title}" meeting will start in less than %{reminders_before_hours}h. + email_outro: You have received this notification because you are following the %{resource_title} meeting. You can unfollow it from the previous link. + email_subject: The "%{resource_title}" meeting will start in less than %{reminders_before_hours}h. + notification_title: The %{resource_title} meeting will start in less than %{reminders_before_hours}h. forms: meetings: attendees_count_help_text: Don't forget to include the total number of attendees at your meeting, whether in person, online or hybrid. @@ -318,9 +318,14 @@ en: location_hints_help: 'Location hints: additional info. Example: the floor of the building if it is an in-person meeting, or the meeting password if it is an online meeting with restricted access.' online_meeting_url_help: 'Link: allow participants to connect directly to your meeting' registration_url_help: 'Link: allow participants to go on the external service you are using for registrations' + reminder_enabled: Reminder enabled + reminder_help_text: Participants will receive an email the number of hours specified in advance of themeeting. Leave it empty or zero if no reminder is necessary. + reminder_message: Reminder message + reminder_message_help_text: Customize the message if necessary. This will be ignored if no reminder is scheduled. select_a_meeting_type: Please select a meeting type select_a_registration_type: Please select a registration type select_an_iframe_access_level: Please select an iframe access level + send_reminder: Send a reminder for this meeting show_embedded_iframe_help: 'Only a few services allow embedding in meeting or live event from the following domains: %{domains}' index: title: Meetings diff --git a/decidim-meetings/db/migrate/20250213114031_add_reminder_customization_to_decidim_meetings.rb b/decidim-meetings/db/migrate/20250213114031_add_reminder_customization_to_decidim_meetings.rb new file mode 100644 index 0000000000000..4ee18474f3b0d --- /dev/null +++ b/decidim-meetings/db/migrate/20250213114031_add_reminder_customization_to_decidim_meetings.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddReminderCustomizationToDecidimMeetings < ActiveRecord::Migration[6.0] + def change + add_column :decidim_meetings_meetings, :reminder_enabled, :boolean + add_column :decidim_meetings_meetings, :send_reminders_before_hours, :integer + add_column :decidim_meetings_meetings, :reminder_message_custom_content, :jsonb + end +end diff --git a/decidim-meetings/lib/decidim/meetings.rb b/decidim-meetings/lib/decidim/meetings.rb index b9653c5fa2074..1f82ffc623475 100644 --- a/decidim-meetings/lib/decidim/meetings.rb +++ b/decidim-meetings/lib/decidim/meetings.rb @@ -26,7 +26,7 @@ module Meetings # Public Setting that defines the interval when the upcoming meeting will be sent config_accessor :upcoming_meeting_notification do - 2.days + 48.hours end config_accessor :embeddable_services do diff --git a/decidim-meetings/lib/decidim/meetings/test/factories.rb b/decidim-meetings/lib/decidim/meetings/test/factories.rb index 75d723b6f6108..014461b430d5c 100644 --- a/decidim-meetings/lib/decidim/meetings/test/factories.rb +++ b/decidim-meetings/lib/decidim/meetings/test/factories.rb @@ -44,6 +44,9 @@ registration_type { :on_this_platform } type_of_meeting { :in_person } component { build(:meeting_component) } + reminder_enabled { true } + send_reminders_before_hours { 48 } + reminder_message_custom_content { {} } iframe_access_level { :all } iframe_embed_type { :none } diff --git a/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb b/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb index f4002671c2fcf..13671a50f7c49 100644 --- a/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb @@ -50,6 +50,9 @@ module Decidim::Meetings comments_enabled: meeting.comments_enabled, comments_start_time: meeting.comments_start_time, comments_end_time: meeting.comments_end_time, + reminder_enabled: meeting.reminder_enabled, + send_reminders_before_hours: meeting.send_reminders_before_hours, + reminder_message_custom_content: meeting.reminder_message_custom_content, registration_type: :on_this_platform, registration_url: meeting.registration_url, type_of_meeting: meeting.type_of_meeting @@ -77,6 +80,7 @@ module Decidim::Meetings expect(new_meeting.category).to eq(old_meeting.category) expect(new_meeting.component).to eq(old_meeting.component) expect(new_meeting.component).not_to eq(be_published) + expect(new_meeting.reminder_message_custom_content).to eq(old_meeting.reminder_message_custom_content) new_meeting.services.each_with_index do |service, index| expect(service.title).to eq(services[index]["title"]) diff --git a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb index f1e97a2febc97..b0f1da8e2dc11 100644 --- a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb @@ -25,6 +25,9 @@ module Decidim::Meetings let(:registration_url) { "http://decidim.org" } let(:registration_type) { "on_this_platform" } let(:registrations_enabled) { true } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 50 } + let(:reminder_message_custom_content) { { en: "Custom reminder message" } } let(:iframe_embed_type) { "embed_in_meeting_page" } let(:iframe_access_level) { "all" } let(:services) do @@ -72,6 +75,9 @@ module Decidim::Meetings comments_enabled: true, comments_start_time: nil, comments_end_time: nil, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: reminder_message_custom_content, iframe_access_level: iframe_access_level ) end @@ -123,6 +129,28 @@ module Decidim::Meetings expect(last_meeting.longitude).to eq(longitude) end + it "sets the reminder message" do + subject.call + expect(meeting.reminder_message_custom_content).to eq(reminder_message_custom_content) + end + + it "sets the send_reminders_before_hours" do + subject.call + expect(meeting.send_reminders_before_hours).to eq(send_reminders_before_hours) + expect(meeting.reminder_message_custom_content).to eq(reminder_message_custom_content) + end + + context "when reminder is not enabled" do + let(:reminder_enabled) { false } + + it "sends reminders before hours is nil" do + subject.call + + expect(meeting.send_reminders_before_hours).to be_nil + expect(meeting.reminder_message_custom_content).to be_empty + end + end + it "sets the services" do subject.call diff --git a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb index e0c6077a96e0f..479af13847429 100644 --- a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb @@ -29,6 +29,9 @@ module Decidim::Meetings let(:registration_url) { "http://decidim.org" } let(:registration_type) { "on_this_platform" } let(:registrations_enabled) { true } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 50 } + let(:reminder_message_custom_content) { { "en" => "Custom reminder message!" } } let(:iframe_embed_type) { "none" } let(:iframe_access_level) { nil } @@ -60,6 +63,9 @@ module Decidim::Meetings comments_enabled: true, comments_start_time: nil, comments_end_time: nil, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: reminder_message_custom_content, iframe_access_level: iframe_access_level ) end @@ -104,6 +110,13 @@ module Decidim::Meetings expect(meeting.registrations_enabled).to eq registrations_enabled end + it "sets the reminder settings" do + subject.call + expect(meeting.reminder_enabled).to eq reminder_enabled + expect(meeting.send_reminders_before_hours).to eq send_reminders_before_hours + expect(meeting.reminder_message_custom_content).to eq reminder_message_custom_content + end + it "sets the services" do subject.call meeting.services.each_with_index do |service, index| @@ -163,6 +176,9 @@ module Decidim::Meetings comments_enabled: true, comments_start_time: nil, comments_end_time: nil, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: reminder_message_custom_content, iframe_access_level: iframe_access_level ) end diff --git a/decidim-meetings/spec/commands/create_meeting_spec.rb b/decidim-meetings/spec/commands/create_meeting_spec.rb index 66d99615bb0a8..1fa986b5d0252 100644 --- a/decidim-meetings/spec/commands/create_meeting_spec.rb +++ b/decidim-meetings/spec/commands/create_meeting_spec.rb @@ -27,6 +27,8 @@ module Decidim::Meetings let(:registrations_enabled) { true } let(:available_slots) { 0 } let(:registration_terms) { Faker::Lorem.sentence(word_count: 3) } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 50 } let(:form) do double( invalid?: invalid, @@ -53,7 +55,10 @@ module Decidim::Meetings clean_type_of_meeting: type_of_meeting, online_meeting_url: online_meeting_url, iframe_embed_type: iframe_embed_type, - iframe_access_level: iframe_access_level + iframe_access_level: iframe_access_level, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: "Custom reminder message!" ) end @@ -91,6 +96,23 @@ module Decidim::Meetings expect(meeting.category).to eq category end + it "sets the reminder settings" do + subject.call + expect(meeting.reminder_enabled).to eq reminder_enabled + expect(meeting.send_reminders_before_hours).to eq send_reminders_before_hours + expect(meeting.reminder_message_custom_content).to include("en" => "Custom reminder message!") + end + + context "when reminder is not enabled" do + let(:reminder_enabled) { false } + + it "sends reminders before hours is nil" do + subject.call + expect(meeting.send_reminders_before_hours).to be_nil + expect(meeting.reminder_message_custom_content).to be_empty + end + end + it "sets the registration_terms" do subject.call expect(meeting.registration_terms).to eq("en" => registration_terms) diff --git a/decidim-meetings/spec/commands/update_meeting_spec.rb b/decidim-meetings/spec/commands/update_meeting_spec.rb index 1ed153b6af23e..69ce2ab2b7193 100644 --- a/decidim-meetings/spec/commands/update_meeting_spec.rb +++ b/decidim-meetings/spec/commands/update_meeting_spec.rb @@ -26,6 +26,8 @@ module Decidim::Meetings let(:registration_url) { "http://decidim.org" } let(:iframe_embed_type) { "none" } let(:iframe_access_level) { nil } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 50 } let(:form) do double( invalid?: invalid, @@ -51,7 +53,10 @@ module Decidim::Meetings clean_type_of_meeting: type_of_meeting, online_meeting_url: online_meeting_url, iframe_embed_type: iframe_embed_type, - iframe_access_level: iframe_access_level + iframe_access_level: iframe_access_level, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: "Custom reminder message!" ) end @@ -87,6 +92,13 @@ module Decidim::Meetings expect(meeting.longitude).to eq(longitude) end + it "sets the reminder settings" do + subject.call + expect(meeting.reminder_enabled).to eq reminder_enabled + expect(meeting.send_reminders_before_hours).to eq send_reminders_before_hours + expect(meeting.reminder_message_custom_content).to include("en" => "Custom reminder message!") + end + context "when the author is a user_group" do let(:user_group) { create :user_group, :verified, users: [current_user], organization: organization } let(:user_group_id) { user_group.id } @@ -150,7 +162,10 @@ module Decidim::Meetings clean_type_of_meeting: type_of_meeting, online_meeting_url: online_meeting_url, iframe_embed_type: iframe_embed_type, - iframe_access_level: iframe_access_level + iframe_access_level: iframe_access_level, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: "Custom reminder message!" ) end diff --git a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb index 84327fd00b29e..9d5970d7817f8 100644 --- a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb +++ b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb @@ -55,6 +55,9 @@ module Decidim::Meetings let(:registration_type) { "on_this_platform" } let(:registrations_enabled) { true } let(:available_slots) { 0 } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 48 } + let(:reminder_message_custom_content) { { en: "Custom reminder message" } } let(:iframe_embed_type) { "none" } let(:attributes) do { @@ -77,7 +80,10 @@ module Decidim::Meetings type_of_meeting: type_of_meeting, online_meeting_url: online_meeting_url, iframe_embed_type: iframe_embed_type, - registrations_enabled: registrations_enabled + registrations_enabled: registrations_enabled, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: reminder_message_custom_content } end @@ -150,6 +156,38 @@ module Decidim::Meetings it { is_expected.not_to be_valid } end + describe "when reminder_enabled is false" do + let(:reminder_enabled) { false } + + it { is_expected.to be_valid } + end + + describe "when reminder_enabled is true" do + context "and send_reminders_before_hours is missing" do + let(:send_reminders_before_hours) { nil } + + it { is_expected.not_to be_valid } + end + + context "and send_reminders_before_hours is present" do + let(:send_reminders_before_hours) { 50 } + + it { is_expected.to be_valid } + end + + context "and send_reminders_before_hours is not valid" do + let(:send_reminders_before_hours) { -1 } + + it { is_expected.not_to be_valid } + end + + context "and reminder_message_custom_content is missing" do + let(:reminder_message_custom_content) { nil } + + it { is_expected.to be_valid } + end + end + it "validates address and store its coordinates" do expect(subject).to be_valid expect(subject.latitude).to eq(latitude) diff --git a/decidim-meetings/spec/forms/meeting_form_spec.rb b/decidim-meetings/spec/forms/meeting_form_spec.rb index a639a38a60b2b..00483d734f4ca 100644 --- a/decidim-meetings/spec/forms/meeting_form_spec.rb +++ b/decidim-meetings/spec/forms/meeting_form_spec.rb @@ -38,6 +38,9 @@ module Decidim::Meetings let(:available_slots) { 0 } let(:registration_url) { "http://decidim.org" } let(:online_meeting_url) { "http://decidim.org" } + let(:reminder_enabled) { true } + let(:send_reminders_before_hours) { 48 } + let(:reminder_message_custom_content) { {} } let(:iframe_embed_type) { "none" } let(:registration_terms) { Faker::Lorem.sentence(word_count: 3) } let(:attributes) do @@ -61,6 +64,9 @@ module Decidim::Meetings registration_terms: registration_terms, registrations_enabled: true, registration_url: registration_url, + reminder_enabled: reminder_enabled, + send_reminders_before_hours: send_reminders_before_hours, + reminder_message_custom_content: reminder_message_custom_content, iframe_embed_type: iframe_embed_type } end @@ -134,6 +140,38 @@ module Decidim::Meetings it { is_expected.not_to be_valid } end + describe "when reminder_enabled is false" do + let(:reminder_enabled) { false } + + it { is_expected.to be_valid } + end + + describe "when reminder_enabled is true" do + context "and send_reminders_before_hours is missing" do + let(:send_reminders_before_hours) { nil } + + it { is_expected.not_to be_valid } + end + + context "and send_reminders_before_hours is present" do + let(:send_reminders_before_hours) { 50 } + + it { is_expected.to be_valid } + end + + context "and send_reminders_before_hours is not valid" do + let(:send_reminders_before_hours) { -1 } + + it { is_expected.not_to be_valid } + end + + context "and reminder_message_custom_content is missing" do + let(:reminder_message_custom_content) { nil } + + it { is_expected.to be_valid } + end + end + it "validates address and store its coordinates" do expect(subject).to be_valid expect(subject.latitude).to eq(latitude) From 0f5de569fe4c457a551f2d26017d15afae9bc7df Mon Sep 17 00:00:00 2001 From: Anna Topalidi Date: Tue, 18 Feb 2025 11:04:55 +0100 Subject: [PATCH 2/3] fix test --- decidim-meetings/spec/commands/admin/create_meeting_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb index b0f1da8e2dc11..9a203a9fca71f 100644 --- a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb @@ -27,7 +27,7 @@ module Decidim::Meetings let(:registrations_enabled) { true } let(:reminder_enabled) { true } let(:send_reminders_before_hours) { 50 } - let(:reminder_message_custom_content) { { en: "Custom reminder message" } } + let(:reminder_message_custom_content) { { "en" => "Custom reminder message" } } let(:iframe_embed_type) { "embed_in_meeting_page" } let(:iframe_access_level) { "all" } let(:services) do From 51fb32b7e4cbff2d7eec1b412cfa8e9ce4515e8e Mon Sep 17 00:00:00 2001 From: Anna Topalidi Date: Fri, 28 Feb 2025 14:15:33 +0100 Subject: [PATCH 3/3] change validation if send_reminders_before_hours is null --- .../decidim/meetings/admin/update_meeting.rb | 2 +- .../forms/decidim/meetings/admin/meeting_form.rb | 7 +++---- .../app/forms/decidim/meetings/meeting_form.rb | 8 ++++---- .../decidim/meetings/meeting_presenter.rb | 7 ++----- .../meetings/admin/meetings/_form.html.erb | 3 ++- .../decidim/meetings/meetings/_form.html.erb | 3 ++- decidim-meetings/config/locales/en.yml | 2 +- .../spec/forms/admin/meeting_form_spec.rb | 16 +++++++++++++++- decidim-meetings/spec/forms/meeting_form_spec.rb | 16 +++++++++++++++- 9 files changed, 45 insertions(+), 19 deletions(-) diff --git a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb index ea8607f2d3a9e..db4e1684521b5 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb @@ -105,7 +105,7 @@ def schedule_upcoming_meeting_notification checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(meeting) Decidim::Meetings::UpcomingMeetingNotificationJob - .set(wait_until: meeting.start_time - Decidim::Meetings.upcoming_meeting_notification) + .set(wait_until: meeting.start_time - meeting.send_reminders_before_hours.hours) .perform_later(meeting.id, checksum) end end diff --git a/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb index 1b95aadc5a998..cf005d1c4599d 100644 --- a/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb @@ -44,9 +44,7 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? } validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? } validates :clean_type_of_meeting, presence: true - validates :send_reminders_before_hours, - presence: true, if: :reminder_enabled, - numericality: { only_integer: true, greater_than: 0, if: :reminder_enabled } + validates :send_reminders_before_hours, numericality: { only_integer: true, greater_than_or_equal_to: 0, if: :reminder_enabled } validates( :iframe_access_level, inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels }, @@ -78,7 +76,8 @@ def number_of_services def send_reminders_before_hours return nil unless reminder_enabled - super + value = super.presence + value.blank? || value.to_i.zero? ? Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i : value.to_i end def reminder_message_custom_content diff --git a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb index f28f6816d04dd..69403b06c8b98 100644 --- a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb @@ -37,9 +37,7 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :scope, presence: true, if: ->(form) { form.decidim_scope_id.present? } validates :decidim_scope_id, scope_belongs_to_component: true, if: ->(form) { form.decidim_scope_id.present? } validates :clean_type_of_meeting, presence: true - validates :send_reminders_before_hours, - presence: true, if: :reminder_enabled, - numericality: { only_integer: true, greater_than: 0, if: :reminder_enabled } + validates :send_reminders_before_hours, numericality: { only_integer: true, greater_than_or_equal_to: 0, if: :reminder_enabled } validates( :iframe_access_level, inclusion: { in: Decidim::Meetings::Meeting.iframe_access_levels }, @@ -57,6 +55,7 @@ def map_model(model) self.location = presenter.location(all_locales: false) self.location_hints = presenter.location_hints(all_locales: false) self.registration_terms = presenter.registration_terms(all_locales: false) + self.reminder_message_custom_content = presenter.reminder_message_custom_content(all_locales: false) self.type_of_meeting = model.type_of_meeting end @@ -65,7 +64,8 @@ def map_model(model) def send_reminders_before_hours return nil unless reminder_enabled - super + value = super.presence + value.blank? || value.to_i.zero? ? Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i : value.to_i end def reminder_message_custom_content diff --git a/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb b/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb index bb874b75ef946..c434763697e71 100644 --- a/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb +++ b/decidim-meetings/app/presenters/decidim/meetings/meeting_presenter.rb @@ -76,13 +76,10 @@ def registration_email_custom_content(links: false, all_locales: false) end end - def reminder_message_custom_content(links: false, all_locales: false) + def reminder_message_custom_content(links: false, extras: true, strip_tags: false, all_locales: false) return unless meeting - handle_locales(meeting.reminder_message_custom_content, all_locales) do |content| - renderer = Decidim::ContentRenderers::HashtagRenderer.new(content) - renderer.render(links: links).html_safe - end + content_handle_locale(meeting.reminder_message_custom_content, all_locales, extras, links, strip_tags) end # start time and end time in rfc3339 format removing '-' and ':' symbols diff --git a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb index a4a430fdd960f..87630d4cd11ac 100644 --- a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_form.html.erb @@ -106,7 +106,8 @@
">
- <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form") %> + <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form") %> +

<%= t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form", default_value: Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i) %>

<%= form.translated :editor, :reminder_message_custom_content, label: t("reminder_message", scope: "decidim.meetings.admin.meetings.form"), hashtaggable: true, help_text: t("reminder_message_help_text", scope: "decidim.meetings.admin.meetings.form") %> diff --git a/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb b/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb index 3ebea79e947d4..8405beb7b47a2 100644 --- a/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/meetings/_form.html.erb @@ -95,7 +95,8 @@
">
- <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form") %> + <%= form.number_field :send_reminders_before_hours, label: t("send_reminder", scope: "decidim.meetings.admin.meetings.form") %> +

<%= t("reminder_help_text", scope: "decidim.meetings.admin.meetings.form", default_value: Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i) %>

<%= text_editor_for(form, :reminder_message_custom_content, hashtaggable: true, label: t("reminder_message", scope: "decidim.meetings.admin.meetings.form"), help_text: t("reminder_message_help_text", scope: "decidim.meetings.admin.meetings.form") ) %>
diff --git a/decidim-meetings/config/locales/en.yml b/decidim-meetings/config/locales/en.yml index a82ff7f3c963d..67d844f945819 100644 --- a/decidim-meetings/config/locales/en.yml +++ b/decidim-meetings/config/locales/en.yml @@ -319,7 +319,7 @@ en: online_meeting_url_help: 'Link: allow participants to connect directly to your meeting' registration_url_help: 'Link: allow participants to go on the external service you are using for registrations' reminder_enabled: Reminder enabled - reminder_help_text: Participants will receive an email the number of hours specified in advance of themeeting. Leave it empty or zero if no reminder is necessary. + reminder_help_text: Participants will receive an email the number of hours specified in advance of themeeting. If left empty or zero, the reminder will be sent at the default configured value of %{default_value} hours. reminder_message: Reminder message reminder_message_help_text: Customize the message if necessary. This will be ignored if no reminder is scheduled. select_a_meeting_type: Please select a meeting type diff --git a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb index 9d5970d7817f8..a6d3c0e30992a 100644 --- a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb +++ b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb @@ -166,7 +166,21 @@ module Decidim::Meetings context "and send_reminders_before_hours is missing" do let(:send_reminders_before_hours) { nil } - it { is_expected.not_to be_valid } + it { is_expected.to be_valid } + + it "returns the default value" do + expect(form.send_reminders_before_hours).to eq(Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i) + end + end + + context "and send_reminders_before_hours is zero" do + let(:send_reminders_before_hours) { 0 } + + it { is_expected.to be_valid } + + it "returns the default value" do + expect(form.send_reminders_before_hours).to eq(Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i) + end end context "and send_reminders_before_hours is present" do diff --git a/decidim-meetings/spec/forms/meeting_form_spec.rb b/decidim-meetings/spec/forms/meeting_form_spec.rb index 00483d734f4ca..8f7c2e5f2937c 100644 --- a/decidim-meetings/spec/forms/meeting_form_spec.rb +++ b/decidim-meetings/spec/forms/meeting_form_spec.rb @@ -150,7 +150,21 @@ module Decidim::Meetings context "and send_reminders_before_hours is missing" do let(:send_reminders_before_hours) { nil } - it { is_expected.not_to be_valid } + it { is_expected.to be_valid } + + it "returns the default value" do + expect(form.send_reminders_before_hours).to eq(Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i) + end + end + + context "and send_reminders_before_hours is zero" do + let(:send_reminders_before_hours) { 0 } + + it { is_expected.to be_valid } + + it "returns the default value" do + expect(form.send_reminders_before_hours).to eq Decidim::Meetings.upcoming_meeting_notification.in_hours.to_i + end end context "and send_reminders_before_hours is present" do