diff --git a/decidim-core/app/cells/decidim/address_cell.rb b/decidim-core/app/cells/decidim/address_cell.rb index 0be1df3cc9fb7..04432caf3301b 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_attribute(model.location)) end def address - decidim_sanitize(translated_attribute(model.address)) + decidim_sanitize(translated_attribute(model.address)) if model.respond_to?(:address) && model.address.present? end private @@ -36,5 +38,13 @@ def address def resource_icon icon "meetings", class: "icon--big", role: "img", "aria-hidden": true 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 1c7be4ec8f332..9a7545e0c0765 100644 --- a/decidim-core/spec/cells/decidim/address_cell_spec.rb +++ b/decidim-core/spec/cells/decidim/address_cell_spec.rb @@ -32,4 +32,17 @@ expect(icondata_address).to have_no_content(model.latitude) expect(icondata_address).to have_no_content(model.longitude) 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(icondata_address).to have_content(I18n.t("show.pending_address", scope: "decidim.meetings.meetings")) + 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 5764e779ca32b..4a5daae0d1017 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/copy_meeting.rb @@ -50,10 +50,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 74f8f4d568e33..9026a48e571f7 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/create_meeting.rb @@ -43,10 +43,10 @@ def create_meeting! registration_type: form.registration_type, registration_url: form.registration_url, type_of_meeting: form.clean_type_of_meeting, - 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, private_meeting: form.private_meeting, transparent: form.transparent, 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 db4e1684521b5..653a60730a484 100644 --- a/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb +++ b/decidim-meetings/app/commands/decidim/meetings/admin/update_meeting.rb @@ -53,10 +53,10 @@ def update_meeting! registration_url: form.registration_url, registrations_enabled: form.registrations_enabled, type_of_meeting: form.clean_type_of_meeting, - address: form.address, + address: form.location_pending ? "" : form.address, latitude: form.latitude, longitude: form.longitude, - location: form.location, + location: form.location_pending ? nil : form.location, location_hints: form.location_hints, private_meeting: form.private_meeting, transparent: form.transparent, 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 cf005d1c4599d..42a721bbb9820 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 :decidim_scope_id, Integer attribute :decidim_category_id, Integer @@ -36,7 +37,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? } } @@ -61,6 +64,7 @@ def map_model(model) self.decidim_category_id = model.categorization.decidim_category_id if model.categorization self.type_of_meeting = model.type_of_meeting + 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 7555b2402c6f8..88df12fe0f03a 100644 --- a/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/base_meeting_form.rb @@ -13,8 +13,6 @@ class BaseMeetingForm < Decidim::Form 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 69403b06c8b98..c756e5c0e4d25 100644 --- a/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb +++ b/decidim-meetings/app/forms/decidim/meetings/meeting_form.rb @@ -27,6 +27,8 @@ class MeetingForm < ::Decidim::Meetings::BaseMeetingForm validates :title, presence: true validates :description, presence: 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 87630d4cd11ac..284d193436c43 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 @@ -19,13 +19,20 @@
- <%= form.geocoding_field :address %> -

<%= 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 %> -

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

+
"> +
+ <%= form.geocoding_field :address %> +

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

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

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

+
diff --git a/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb b/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb index 770a36db54c4f..ff19e0e4b4fb8 100644 --- a/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb +++ b/decidim-meetings/app/views/decidim/meetings/meetings/show.html.erb @@ -132,7 +132,7 @@ edit_link( <% end %> <%= render_meeting_body(@meeting) %> - <% if meeting.maps_enabled? && !meeting.online_meeting? %> + <% if meeting.maps_enabled? && !meeting.online_meeting? && meeting.address.present? %> <%= render partial: "decidim/shared/static_map", locals: { icon_name: "meetings", geolocalizable: meeting } %> <% end %> diff --git a/decidim-meetings/config/locales/en.yml b/decidim-meetings/config/locales/en.yml index feeb8821e6632..5a06143042fbc 100644 --- a/decidim-meetings/config/locales/en.yml +++ b/decidim-meetings/config/locales/en.yml @@ -319,6 +319,8 @@ en: disclaimer: 'Disclaimer: By using an external registration system, you''re aware that the organizers of %{organization} are not responsible for the data provided by the users to the external service.' 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' reminder_enabled: Reminder enabled @@ -571,6 +573,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. registration_code_help_text: Your registration code registration_confirmation: Are you sure you want to cancel your registration for this meeting? 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 13671a50f7c49..500cac513e5ab 100644 --- a/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/copy_meeting_spec.rb @@ -16,6 +16,7 @@ module Decidim::Meetings let(:start_time) { 1.day.from_now } let(:private_meeting) { false } let(:transparent) { true } + let(:location_pending) { false } let(:services) do build_list(:service, 2, meeting: meeting) end @@ -28,6 +29,7 @@ module Decidim::Meetings invalid?: invalid, title: { en: "title" }, description: { en: "description" }, + location_pending: location_pending, location: { en: "location" }, location_hints: { en: "location hints" }, start_time: start_time, @@ -125,6 +127,17 @@ module Decidim::Meetings end end 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 end describe "events" do diff --git a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb index 9a203a9fca71f..239cdc753c980 100644 --- a/decidim-meetings/spec/commands/admin/create_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/create_meeting_spec.rb @@ -12,6 +12,7 @@ module Decidim::Meetings let(:current_component) { create :component, participatory_space: participatory_process, manifest_name: "meetings" } let(:scope) { create :scope, organization: organization } let(:category) { create :category, participatory_space: participatory_process } + let(:location_pending) { false } let(:address) { "address" } let(:invalid) { false } let(:latitude) { 40.1234 } @@ -55,6 +56,7 @@ module Decidim::Meetings location_hints: { en: "location_hints" }, start_time: start_time, end_time: 1.day.from_now + 1.hour, + location_pending: location_pending, address: address, latitude: latitude, longitude: longitude, @@ -122,6 +124,17 @@ module Decidim::Meetings expect(meeting.component).to eq current_component 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 longitude and latitude" do subject.call last_meeting = Meeting.last diff --git a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb index 479af13847429..d77fcea99e8fd 100644 --- a/decidim-meetings/spec/commands/admin/update_meeting_spec.rb +++ b/decidim-meetings/spec/commands/admin/update_meeting_spec.rb @@ -12,6 +12,7 @@ module Decidim::Meetings let(:category) { create :category, participatory_space: meeting.component.participatory_space } let(:address) { meeting.address } let(:invalid) { false } + let(:location_pending) { false } let(:latitude) { 40.1234 } let(:longitude) { 2.1234 } let(:service_objects) { build_list(:service, 2) } @@ -46,6 +47,7 @@ module Decidim::Meetings end_time: 1.day.from_now + 1.hour, scope: scope, category: category, + location_pending: location_pending, address: address, latitude: latitude, longitude: longitude, @@ -142,6 +144,16 @@ module Decidim::Meetings expect(action_log.version).to be_present 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 + describe "events" do let!(:follow) { create :follow, followable: meeting, user: user } let(:title) { meeting.title } @@ -159,6 +171,7 @@ module Decidim::Meetings end_time: end_time, scope: meeting.scope, category: meeting.category, + location_pending: location_pending, address: address, latitude: meeting.latitude, longitude: meeting.longitude, diff --git a/decidim-meetings/spec/forms/admin/meeting_form_spec.rb b/decidim-meetings/spec/forms/admin/meeting_form_spec.rb index a6d3c0e30992a..18daec309652d 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 } @@ -66,6 +67,7 @@ module Decidim::Meetings title_en: title[:en], description_en: description[:en], short_description_en: short_description[:en], + location_pending: location_pending, location_en: location[:en], location_hints_en: location_hints[:en], address: address, @@ -107,6 +109,36 @@ module Decidim::Meetings it { is_expected.not_to be_valid } end + 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 location is missing and type of meeting is in_person" do let(:type_of_meeting) { "in_person" } let(:location) { { 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 6986789c3b283..3a36b69cb2d4e 100644 --- a/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb +++ b/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb @@ -316,6 +316,51 @@ 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 + find(".card-title a.button").click + + 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 + page.execute_script("$('#meeting_start_time').focus()") + page.find(".datepicker-dropdown .day:not(.new)", text: "12").click + page.find(".datepicker-dropdown .hour", text: "10:00").click + page.find(".datepicker-dropdown .minute", text: "10:50").click + + page.execute_script("$('#meeting_end_time').focus()") + page.find(".datepicker-dropdown .day:not(.new)", text: "12").click + page.find(".datepicker-dropdown .hour", text: "12:00").click + page.find(".datepicker-dropdown .minute", text: "12:50").click + + scope_pick select_data_picker(:meeting_decidim_scope_id), scope + select translated(category.name), from: :meeting_decidim_category_id + + 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 using the front-end geocoder", :serves_geocoding_autocomplete do it_behaves_like( "a record with front-end geocoding address field", diff --git a/decidim-meetings/spec/system/meeting_spec.rb b/decidim-meetings/spec/system/meeting_spec.rb index f3c6d6eec1612..691ee86dbf332 100644 --- a/decidim-meetings/spec/system/meeting_spec.rb +++ b/decidim-meetings/spec/system/meeting_spec.rb @@ -76,6 +76,16 @@ def visit_meeting expect(page).to have_css("div.address__map") end + + context "and meeting has no address" do + let(:meeting) { create(:meeting, :published, :with_services, component: component, address: "", location: {}) } + + it "hides the map and displays pending address text" do + visit_meeting + + expect(page).to have_no_css("div.address__map") + end + end end context "and meeting is hybrid" do @@ -119,6 +129,26 @@ def visit_meeting expect(page).to have_no_css("div.address__map") end end + + context "when the meeting has no address and location" do + let!(:meeting) { create(:meeting, :published, component: component, address: "", location: {}) } + + it "displays the pending address text" do + visit main_component_path(component) + expect(page).to have_content("PLACE WILL BE COMMUNICATED SOON") + end + end + + context "when meeting has an address and location" do + let!(:meeting) { create(:meeting, :published, component: component, address: "123 Main St", location: { "en" => "Central Park" }) } + + it "displays the location and address" do + visit main_component_path(component) + expect(page).to have_content("123 Main St") + expect(page).to have_content("CENTRAL PARK") + expect(page).to have_no_content("PLACE WILL BE COMMUNICATED SOON") + end + end end context "when the meeting is the same as the current year" do