diff --git a/decidim-core/app/cells/decidim/address/show.erb b/decidim-core/app/cells/decidim/address/show.erb index 3b753f846ee75..17cf8020b4f83 100644 --- a/decidim-core/app/cells/decidim/address/show.erb +++ b/decidim-core/app/cells/decidim/address/show.erb @@ -24,6 +24,7 @@ <%= start_and_end_time %> + <% end %> diff --git a/decidim-core/app/cells/decidim/address_cell.rb b/decidim-core/app/cells/decidim/address_cell.rb index 718f134de1f47..efc3465fe625a 100644 --- a/decidim-core/app/cells/decidim/address_cell.rb +++ b/decidim-core/app/cells/decidim/address_cell.rb @@ -24,11 +24,13 @@ def location_hints end def location + return pending_address_text if pending_address? + decidim_sanitize_translated(model.location) end def address - decidim_sanitize_translated(model.address) + decidim_sanitize_translated(model.address) if model.respond_to?(:address) && model.address.present? end def display_start_and_end_time? @@ -63,5 +65,13 @@ def start_time def end_time l model.end_time, format: "%H:%M %p %Z" end + + def pending_address? + address.blank? && model.location.is_a?(Hash) ? model.location.values.none?(&:present?) : model.location.blank? + end + + def pending_address_text + t("show.pending_address", scope: "decidim.meetings.meetings") + end end end diff --git a/decidim-core/spec/cells/decidim/address_cell_spec.rb b/decidim-core/spec/cells/decidim/address_cell_spec.rb index 9cae2bdc83838..eafe1dc972fc4 100644 --- a/decidim-core/spec/cells/decidim/address_cell_spec.rb +++ b/decidim-core/spec/cells/decidim/address_cell_spec.rb @@ -37,6 +37,19 @@ end end + context "when address is pending" do + let(:location) { {} } + let(:address) { "" } + + before do + allow(model).to receive(:location).and_return(location) + end + + it "renders pending address text" do + expect(subject.find(".address__location")).to have_content(I18n.t("show.pending_address", scope: "decidim.meetings.meetings")) + end + end + context "with an online meeting url" do let(:my_cell) { cell("decidim/address", model, online: true) } let(:model) { create(:dummy_resource) } diff --git a/decidim-meetings/app/cells/decidim/meetings/dates_and_map_cell.rb b/decidim-meetings/app/cells/decidim/meetings/dates_and_map_cell.rb index 65e96c342aa80..ea48a3038d187 100644 --- a/decidim-meetings/app/cells/decidim/meetings/dates_and_map_cell.rb +++ b/decidim-meetings/app/cells/decidim/meetings/dates_and_map_cell.rb @@ -32,7 +32,7 @@ def same_day? end def display_map? - maps_enabled? && !online? + maps_enabled? && !online? && model.address.present? end end end 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 c4d9e687bed7f..e6a660fd17b38 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb @@ -49,10 +49,10 @@ def copy_meeting! description: parsed_description, end_time: form.end_time, start_time: form.start_time, - address: form.address, + address: form.location_pending ? "" : form.address, latitude: form.latitude, longitude: form.longitude, - location: form.location, + location: form.location_pending ? {} : form.location, location_hints: form.location_hints, component: meeting.component, private_meeting: form.private_meeting, 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 9e715ed897731..c9b276f39eb56 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb @@ -26,6 +26,8 @@ def attributes title: parsed_title, description: parsed_description, type_of_meeting: form.clean_type_of_meeting, + address: form.location_pending ? "" : form.address, + location: form.location_pending ? {} : form.location, author: form.current_organization, registration_terms: form.current_component.settings.default_registration_terms, questionnaire: Decidim::Forms::Questionnaire.new 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 b77ae4d23434a..d5e287e6445e5 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb @@ -27,7 +27,9 @@ def attributes super.merge({ title: parsed_title, description: parsed_description, - type_of_meeting: form.clean_type_of_meeting + type_of_meeting: form.clean_type_of_meeting, + address: form.location_pending ? "" : form.address, + location: form.location_pending ? nil : form.location }) 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 868ec17f20791..f699c752a4a56 100644 --- a/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/admin/meeting_form.rb @@ -7,6 +7,7 @@ module Admin class MeetingForm < ::Decidim::Meetings::BaseMeetingForm include TranslatableAttributes + attribute :location_pending, Boolean, default: false attribute :services, Array[MeetingServiceForm] attribute :component_ids, Array[Integer] attribute :private_meeting, Boolean @@ -32,7 +33,9 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :registration_type, presence: true validates :registration_url, presence: true, url: true, if: ->(form) { form.on_different_platform? } validates :type_of_meeting, presence: true - validates :location, translatable_presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? } + validates :location, translatable_presence: true, if: ->(form) { !form.location_pending && (form.in_person_meeting? || form.hybrid_meeting?) } + validates :address, presence: true, if: ->(form) { !form.location_pending && (form.in_person_meeting? || form.hybrid_meeting?) } + validates :address, geocoding: true, if: ->(form) { !form.location_pending && form.has_address? && !form.geocoded? } validates :online_meeting_url, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? } validates :comments_start_time, date: { before: :comments_end_time, allow_blank: true, if: proc { |obj| obj.comments_end_time.present? } } validates :comments_end_time, date: { after: :comments_start_time, allow_blank: true, if: proc { |obj| obj.comments_start_time.present? } } @@ -54,6 +57,7 @@ def map_model(model) presenter = MeetingEditionPresenter.new(model) self.title = presenter.title(all_locales: true) self.description = presenter.editor_description(all_locales: true) + self.location_pending = model.address.blank? && model.location.to_h.values.none?(&:present?) end def services_to_persist diff --git a/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb index c9b31783892a3..e638f4760d429 100644 --- a/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb @@ -14,9 +14,6 @@ class BaseMeetingForm < Decidim::Form attribute :end_time, Decidim::Attributes::TimeWithZone validates :current_component, presence: true - - validates :address, presence: true, if: ->(form) { form.needs_address? } - validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? } validates :start_time, presence: true, date: { before: :end_time } validates :end_time, presence: true, date: { after: :start_time } diff --git a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb index fb7da80a9aa6a..27b02f829abc4 100644 --- a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb @@ -22,6 +22,8 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :title, presence: true, etiquette: true validates :description, presence: true, etiquette: true validates :type_of_meeting, presence: true + validates :address, presence: true, if: ->(form) { form.needs_address? } + validates :address, geocoding: true, if: ->(form) { form.has_address? && !form.geocoded? && form.needs_address? } validates :location, presence: true, if: ->(form) { form.in_person_meeting? || form.hybrid_meeting? } validates :online_meeting_url, presence: true, url: true, if: ->(form) { form.online_meeting? || form.hybrid_meeting? } validates :registration_type, presence: true 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 b6538cedb4ab4..dee38bdfb71b7 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 @@ -17,11 +17,20 @@
- <%= form.geocoding_field :address, help_text: t(".address_help") %> + <%= form.check_box :location_pending, label: t("location_pending", scope: "decidim.meetings.admin.meetings.form"), "data-toggle": "location_fields-div" %> +

<%= t(".location_pending_help") %>

-
- <%= form.translated :text_area, :location, help_text: t(".location_help") %> +
"> +
+ <%= form.geocoding_field :address %> +

<%= t(".address_help") %>

+
+ +
+ <%= form.translated :text_area, :location %> +

<%= t(".location_help") %>

+
diff --git a/decidim-meetings/config/locales/en.yml b/decidim-meetings/config/locales/en.yml index 1b6e07e1f396f..7388469ded749 100644 --- a/decidim-meetings/config/locales/en.yml +++ b/decidim-meetings/config/locales/en.yml @@ -358,6 +358,8 @@ en: iframe_embed_type_html: 'Only a few services allow embedding in meeting or live event from the following domains: %{domains}' location_help: 'Location: message directed to the users implying the spot to meet at' 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.' + location_pending: In-person/Hybrid, venue to be decided + location_pending_help: Select this option if the venue has not been decided yet. The message 'Place will be communicated soon' will be shown on the public page. 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' select_a_meeting_type: Please select a meeting type @@ -604,6 +606,7 @@ en: micro_camera_permissions_warning: When you click on the button below, you will be asked for microphone and/or camera permissions, and you will join the videoconference no_slots_available: No slots available organizations: Attending organizations + pending_address: Place will be communicated soon. redirect_notice: This meeting is part of another space, so you have been moved to %{current_space_name}.
If you prefer, you can go back to %{previous_space_name}. registration_code_help_text: Your registration code registration_state: diff --git a/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb b/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb index 5dca45d71537b..6b6958e8afb69 100644 --- a/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb @@ -12,6 +12,7 @@ module Decidim::Meetings let!(:meeting) { create(:meeting, component:, taxonomies: [taxonomy]) } let(:current_user) { create(:user, :admin, :confirmed, organization:) } + let(:location_pending) { false } let(:address) { "address" } let(:invalid) { false } let(:latitude) { 40.1234 } @@ -32,6 +33,7 @@ module Decidim::Meetings invalid?: invalid, title: { en: "title" }, description: { en: "description" }, + location_pending:, location: { en: "location" }, location_hints: { en: "location hints" }, start_time:, @@ -90,6 +92,17 @@ module Decidim::Meetings expect { subject.call }.to broadcast(:ok) end + context "and location_pending is true" do + let(:location_pending) { true } + + it "sets location to nil" do + expect { subject.call }.to change(Meeting, :count).by(1) + new_meeting = Meeting.last + expect(new_meeting.location).to be_empty + expect(new_meeting.address).to be_empty + end + end + context "and saves the correct meeting type" do context "with in_person meeting type" do let!(:meeting) { create(:meeting, :in_person, component:) } diff --git a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb index 932882eb3712c..162972dfa9222 100644 --- a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb @@ -10,6 +10,7 @@ module Decidim::Meetings let(:current_user) { create(:user, :admin, :confirmed, organization:) } let(:participatory_process) { create(:participatory_process, organization:) } let(:current_component) { create(:component, participatory_space: participatory_process, manifest_name: "meetings") } + let(:location_pending) { false } let(:address) { "address" } let(:invalid) { false } let(:latitude) { 40.1234 } @@ -54,6 +55,7 @@ module Decidim::Meetings location_hints: { en: "location_hints" }, start_time:, end_time: 1.day.from_now + 1.hour, + location_pending:, address:, latitude:, longitude:, @@ -94,6 +96,17 @@ module Decidim::Meetings expect { subject.call }.to change(Meeting, :count).by(1) end + context "and location_pending is true" do + let(:location_pending) { true } + + it "sets location to nil" do + expect { subject.call }.to change(Meeting, :count).by(1) + new_meeting = Meeting.last + expect(new_meeting.location).to be_empty + expect(new_meeting.address).to be_empty + end + end + it "sets the taxonomies" do subject.call expect(meeting.taxonomizations).to match_array(taxonomizations) diff --git a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb index 982e0b2242708..e1baab21532c2 100644 --- a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb @@ -8,6 +8,7 @@ module Decidim::Meetings let(:meeting) { create(:meeting, :published) } let(:organization) { meeting.component.organization } + let(:location_pending) { false } let(:address) { meeting.address } let(:invalid) { false } let(:latitude) { 40.1234 } @@ -39,6 +40,7 @@ module Decidim::Meetings invalid?: invalid, title: { en: "title" }, description: { en: "description" }, + location_pending:, location: { en: "location" }, location_hints: { en: "location_hints" }, start_time: 1.day.from_now, @@ -80,6 +82,16 @@ module Decidim::Meetings expect(translated(meeting.title)).to eq "title" end + context "and location_pending is true" do + let(:location_pending) { true } + + it "sets location to nil" do + subject.call + expect(translated(meeting.location)).to be_nil + expect(meeting.address).to be_empty + end + end + it "sets the taxonomies" do subject.call expect(meeting.reload.taxonomies).to eq(taxonomizations.map(&:taxonomy)) @@ -137,6 +149,7 @@ module Decidim::Meetings invalid?: false, title:, description: meeting.description, + location_pending:, location: meeting.location, location_hints: meeting.location_hints, start_time:, diff --git a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb index c7f4b1caf1f3f..ca4fb3f89da38 100644 --- a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb +++ b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb @@ -37,6 +37,7 @@ module Decidim::Meetings let(:services_attributes) do services.map(&:attributes) end + let(:location_pending) { false } let(:address) { "Somewhere over the rainbow" } let(:latitude) { 40.1234 } let(:longitude) { 2.1234 } @@ -59,6 +60,7 @@ module Decidim::Meetings title_en: title[:en], description_en: description[:en], short_description_en: short_description[:en], + location_pending:, location_en: location[:en], location_hints_en: location_hints[:en], address:, @@ -93,6 +95,36 @@ module Decidim::Meetings it { is_expected.to be_valid } + describe "when location_pending enabled" do + let(:location_pending) { true } + + it { is_expected.to be_valid } + + context "and location is missing" do + let(:location) { { en: nil } } + + it { is_expected.to be_valid } + end + + context "and address is missing" do + let(:address) { nil } + + it { is_expected.to be_valid } + end + + context "and location is present" do + let(:location) { { en: "location" } } + + it { is_expected.to be_valid } + end + + context "and address is present" do + let(:address) { "Somewhere over the rainbow" } + + it { is_expected.to be_valid } + end + end + describe "when title is missing" do let(:title) { { en: nil } } diff --git a/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb b/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb index 7fa5700ea9c95..04a7ccfbde12b 100644 --- a/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb +++ b/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb @@ -324,6 +324,43 @@ expect(page).to have_content("created the #{translated(attributes[:title])} meeting on the") end + context "when the venue has not been decided yet" do + it "creates a new meeting without a location" do + click_on "New meeting" + + fill_in_i18n(:meeting_title, "#meeting-title-tabs", **attributes[:title].except("machine_translations")) + + expect(page).to have_no_field("In-person/Hybrid, venue to be decided") + + select "In person", from: :meeting_type_of_meeting + + expect(page).to have_field("In-person/Hybrid, venue to be decided") + + check "In-person/Hybrid, venue to be decided" + + expect(page).to have_no_field(:meeting_location_en) + expect(page).to have_no_field(:meeting_address) + + fill_in_i18n_editor(:meeting_description, "#meeting-description-tabs", **attributes[:description].except("machine_translations")) + select "Registration disabled", from: :meeting_registration_type + fill_in_datepicker :meeting_start_time_date, with: meeting_start_date + fill_in_timepicker :meeting_start_time_time, with: meeting_start_time + fill_in_datepicker :meeting_end_time_date, with: meeting_end_date + fill_in_timepicker :meeting_end_time_time, with: meeting_end_time + + within ".new_meeting" do + find("*[type=submit]").click + end + + expect(page).to have_admin_callout("successfully") + + new_meeting = Decidim::Meetings::Meeting.last + puts "Meeting location: #{new_meeting.location}" + expect(new_meeting.location).to be_empty + expect(new_meeting.address).to be_empty + end + end + context "when no taxonomy filter is selected" do let(:taxonomy_filter_ids) { [] } diff --git a/decidim-meetings/spec/system/meeting_spec.rb b/decidim-meetings/spec/system/meeting_spec.rb index 1171522c2869b..5e8ccfb093b5c 100644 --- a/decidim-meetings/spec/system/meeting_spec.rb +++ b/decidim-meetings/spec/system/meeting_spec.rb @@ -80,6 +80,17 @@ def visit_meeting expect(page).to have_css("div.meeting__calendar-container .static-map") end + + context "and meeting has no address" do + let(:meeting) { create(:meeting, :published, :with_services, component:, address: "", location: {}) } + + it "hides the map and displays pending address text" do + visit_meeting + + expect(page).to have_no_css("div.meeting__calendar-container .static-map") + expect(page).to have_content(I18n.t("show.pending_address", scope: "decidim.meetings.meetings")) + end + end end context "and meeting is hybrid" do @@ -138,6 +149,28 @@ def visit_meeting end end + context "when the meeting has no address and location" do + let(:meeting) { create(:meeting, :published, component:, address: "", location: {}) } + + it "displays the pending address text" do + visit_meeting + + expect(page).to have_content(I18n.t("show.pending_address", scope: "decidim.meetings.meetings")) + end + end + + context "when meeting has an address and location" do + let(:meeting) { create(:meeting, :published, component:, address: "123 Main St", location: { "en" => "Central Park" }) } + + it "displays the location and address" do + visit_meeting + + expect(page).to have_content("123 Main St") + expect(page).to have_content("Central Park") + expect(page).to have_no_content(I18n.t("show.pending_address", scope: "decidim.meetings.meetings")) + end + end + context "when user is logged and session is about to timeout" do before do allow(Decidim.config).to receive(:expire_session_after).and_return(2.minutes)