<% details_items.each do |detail| %>
diff --git a/decidim-core/app/cells/decidim/user_activity_cell.rb b/decidim-core/app/cells/decidim/user_activity_cell.rb
index 0ee51977d51a3..7f6d25f41f282 100644
--- a/decidim-core/app/cells/decidim/user_activity_cell.rb
+++ b/decidim-core/app/cells/decidim/user_activity_cell.rb
@@ -11,7 +11,12 @@ def show
end
def activities
- context[:activities]
+ resource_ids_to_filter = context[:activities].select { |log| log[:action] == "delete" && log[:resource_type] == "Decidim::Comments::Comment" }.map(&:resource_id)
+ if resource_ids_to_filter.any?
+ context[:activities].where.not("resource_id in (?) AND resource_type = ?", resource_ids_to_filter, "Decidim::Comments::Comment")
+ else
+ context[:activities]
+ end
end
def resource_types
diff --git a/decidim-core/app/forms/decidim/user_group_form.rb b/decidim-core/app/forms/decidim/user_group_form.rb
index e29a26691d35b..add1de002af2b 100644
--- a/decidim-core/app/forms/decidim/user_group_form.rb
+++ b/decidim-core/app/forms/decidim/user_group_form.rb
@@ -16,10 +16,12 @@ class UserGroupForm < Form
attribute :phone
validates :name, presence: true
+ validates :name, format: { with: Decidim::UserBaseEntity::REGEXP_NAME }
validates :email, presence: true, "valid_email_2/email": { disposable: true }
validates :nickname, presence: true
validates :nickname, length: { maximum: Decidim::User.nickname_max_length, allow_blank: true }
+ validates :nickname, format: { with: Decidim::UserBaseEntity::REGEXP_NICKNAME }
validates :avatar, passthru: { to: Decidim::UserGroup }
validate :unique_document_number
diff --git a/decidim-core/app/packs/stylesheets/decidim/_author.scss b/decidim-core/app/packs/stylesheets/decidim/_author.scss
index d58a346fe74fa..ad47a1b2e4e0c 100644
--- a/decidim-core/app/packs/stylesheets/decidim/_author.scss
+++ b/decidim-core/app/packs/stylesheets/decidim/_author.scss
@@ -33,6 +33,10 @@
@apply text-secondary font-semibold;
}
+ &__badge svg {
+ @apply grid overflow-hidden place-items-center bg-primary rounded-full w-4 h-4 text-white fill-current;
+ }
+
&__metadata {
@apply flex items-center gap-1 text-gray-2 text-sm;
diff --git a/decidim-core/app/packs/stylesheets/decidim/_profile.scss b/decidim-core/app/packs/stylesheets/decidim/_profile.scss
index 1a20e680ac393..530ac405e420f 100644
--- a/decidim-core/app/packs/stylesheets/decidim/_profile.scss
+++ b/decidim-core/app/packs/stylesheets/decidim/_profile.scss
@@ -9,18 +9,18 @@
&-container {
@apply w-24 h-24 relative;
}
+ }
+
+ &__details {
+ @apply pb-3 space-y-2;
&-badge {
- @apply absolute top-full right-0 -translate-y-full grid place-items-center w-6 h-6 rounded-full overflow-hidden bg-primary border border-white;
+ @apply flex items-center gap-1 text-sm text-gray-2;
svg {
- @apply w-4 h-4 text-white fill-current;
+ @apply w-4 h-4 inline-block bg-primary rounded-full text-white fill-current;
}
}
- }
-
- &__details {
- @apply pb-3 space-y-2;
&-data {
@apply flex flex-wrap gap-x-6 gap-y-4;
diff --git a/decidim-core/app/packs/stylesheets/decidim/editor.scss b/decidim-core/app/packs/stylesheets/decidim/editor.scss
index 5035beaa02391..dcdb902403440 100644
--- a/decidim-core/app/packs/stylesheets/decidim/editor.scss
+++ b/decidim-core/app/packs/stylesheets/decidim/editor.scss
@@ -89,7 +89,9 @@
}
.ProseMirror {
- @apply relative p-2.5 outline-0 min-h-full prose max-w-none prose-headings:first:mt-0 prose-p:first:mt-0 prose-ul:first:mt-0 prose-ol:first:mt-0 prose-blockquote:first:mt-0 prose-pre:first:mt-0;
+ @apply relative p-2.5 outline-0 resize-y overflow-hidden prose max-w-none prose-headings:first:mt-0 prose-p:first:mt-0 prose-ul:first:mt-0 prose-ol:first:mt-0 prose-blockquote:first:mt-0 prose-pre:first:mt-0;
+
+ min-height: inherit;
&.ProseMirror-focused,
&.dialog-open {
diff --git a/decidim-core/app/validators/etiquette_validator.rb b/decidim-core/app/validators/etiquette_validator.rb
index e298189b48f6e..16fdebb1dad4b 100644
--- a/decidim-core/app/validators/etiquette_validator.rb
+++ b/decidim-core/app/validators/etiquette_validator.rb
@@ -24,7 +24,7 @@ def clean_value(value)
end
def validate_caps(record, attribute, value)
- number_of_caps = value.scan(/[A-Z]/).length
+ number_of_caps = value.scan(/[[:upper:]]/).length
return if number_of_caps.zero? || number_of_caps < value.length / 2 # 50%
record.errors.add(attribute, options[:message] || :too_much_caps)
@@ -37,7 +37,7 @@ def validate_marks(record, attribute, value)
end
def validate_caps_first(record, attribute, value)
- return if value.scan(/\A[a-z]{1}/).empty?
+ return if value.scan(/\A[[:lower:]]{1}/).empty?
record.errors.add(attribute, options[:message] || :must_start_with_caps)
end
diff --git a/decidim-core/lib/decidim/form_builder.rb b/decidim-core/lib/decidim/form_builder.rb
index 53cde5122a1e1..37b78ea251384 100644
--- a/decidim-core/lib/decidim/form_builder.rb
+++ b/decidim-core/lib/decidim/form_builder.rb
@@ -230,7 +230,7 @@ def editor(name, options = {})
disabled: options[:disabled],
options: editor_options[:editor]
}
- ) { content_tag(:div, nil, class: "editor-input", style: "height: #{lines}rem") }
+ ) { content_tag(:div, nil, class: "editor-input", style: "min-height: #{lines}rem") }
template += error_for(name, options) if error?(name)
template += editor_upload(editor_image, editor_options[:upload])
template.html_safe
diff --git a/decidim-core/lib/decidim/settings_manifest.rb b/decidim-core/lib/decidim/settings_manifest.rb
index 3f32b8b7ab73d..028dbf143d4a5 100644
--- a/decidim-core/lib/decidim/settings_manifest.rb
+++ b/decidim-core/lib/decidim/settings_manifest.rb
@@ -129,6 +129,7 @@ class Attribute
attribute :required_for_authorization, Boolean, default: false
attribute :readonly
attribute :choices
+ attribute :raw_choices, Boolean, default: false
attribute :units
attribute :include_blank, Boolean, default: false
@@ -154,8 +155,8 @@ def default_value
default || TYPES[type][:default]
end
- def build_choices
- choices.try(:call) || choices
+ def build_choices(context = nil)
+ choices.try(:call, context) || choices
end
def build_units
diff --git a/decidim-core/spec/cells/decidim/author_cell_spec.rb b/decidim-core/spec/cells/decidim/author_cell_spec.rb
index 2496acd3b41fe..d45d38041ca99 100644
--- a/decidim-core/spec/cells/decidim/author_cell_spec.rb
+++ b/decidim-core/spec/cells/decidim/author_cell_spec.rb
@@ -8,7 +8,7 @@
controller Decidim::PagesController
let(:my_cell) { cell("decidim/author", model) }
- let!(:organization) { create(:organization) }
+ let!(:organization) { build(:organization) }
let(:user) { create(:user, :confirmed, organization:) }
let(:user_group) { create(:user_group, :verified) }
let(:model) { Decidim::UserPresenter.new(user) }
@@ -17,6 +17,14 @@
it "renders a User author card" do
expect(subject).to have_css("[data-author]")
end
+
+ context "and when this user is officialized" do
+ let(:user) { create(:user, :confirmed, :officialized, organization:) }
+
+ it "shows the officialization badge" do
+ expect(subject).to have_xpath("//svg/use[contains(@href, 'ri-star-s-fill')]")
+ end
+ end
end
context "when rendering a user group" do
diff --git a/decidim-core/spec/cells/decidim/profile_cell_spec.rb b/decidim-core/spec/cells/decidim/profile_cell_spec.rb
index 0c3703714b193..65768a668a4eb 100644
--- a/decidim-core/spec/cells/decidim/profile_cell_spec.rb
+++ b/decidim-core/spec/cells/decidim/profile_cell_spec.rb
@@ -6,9 +6,9 @@
controller Decidim::ProfilesController
subject { my_cell.call }
- let(:organization) { create(:organization, user_groups_enabled: true) }
- let(:user) { create(:user, :managed, organization:, blocked: false) }
- let(:context) { { content_cell: "decidim/user_conversations", conversations: [] } }
+ let(:organization) { build(:organization, user_groups_enabled: true) }
+ let(:user) { build(:user, :managed, organization:, blocked: false) }
+ let(:context) { { content_cell: "decidim/badges" } }
let(:my_cell) { cell("decidim/profile", user, context:) }
context "when show is rendered" do
@@ -19,7 +19,7 @@
context "when the user displayed is blocked" do
context "and is an admin" do
- let(:user) { create(:user, :managed, organization:, blocked: true, admin: true) }
+ let(:user) { build(:user, :managed, organization:, blocked: true, admin: true) }
it "shows the user profile" do
expect(subject).to have_no_text("This profile is inaccessible due to terms of service violation!")
@@ -27,11 +27,23 @@
end
context "and is not an admin" do
- let(:user) { create(:user, :managed, organization:, blocked: true, admin: false) }
+ let(:user) { build(:user, :managed, organization:, blocked: true, admin: false) }
it "shows the inaccessible profile alert" do
expect(subject).to have_text("This profile is inaccessible due to terms of service violation!")
end
end
end
+
+ context "when the user displayed is officialized" do
+ let(:user) { build(:user, :officialized, organization:) }
+
+ it "shows the officialization badge" do
+ expect(subject).to have_xpath("//svg/use[contains(@href, 'ri-star-s-fill')]")
+ end
+
+ it "shows the officialization name" do
+ expect(subject).to have_content(decidim_sanitize_translated(user.officialized_as))
+ end
+ end
end
diff --git a/decidim-core/spec/cells/decidim/user_activity_cell_spec.rb b/decidim-core/spec/cells/decidim/user_activity_cell_spec.rb
index 57116de1cbcaa..40265cf18496b 100644
--- a/decidim-core/spec/cells/decidim/user_activity_cell_spec.rb
+++ b/decidim-core/spec/cells/decidim/user_activity_cell_spec.rb
@@ -89,6 +89,33 @@
end
end
+ context "when comment is deleted" do
+ let!(:logs) do
+ comments.first(14).map do |comment|
+ create(
+ :action_log,
+ action: "publish",
+ visibility: "all",
+ user: model,
+ resource: comment,
+ organization: component.organization,
+ participatory_space: component.participatory_space
+ )
+ end
+ end
+ let!(:log_one) { create(:action_log, action: "create", visibility: "all", user: model, resource: comments.last, organization: component.organization, participatory_space: component.participatory_space) }
+ let!(:log_two) { create(:action_log, action: "delete", visibility: "all", user: model, resource: comments.last, organization: component.organization, participatory_space: component.participatory_space) }
+
+ it "does not display the references to the comment on the first page if comment has been deleted" do
+ logs.last(2) do |log|
+ root_link = Decidim::ResourceLocatorPresenter.new(log.resource.root_commentable).path
+ comment_link = "#{root_link}?commentId=#{log.resource.id}#comment_#{log.resource.id}"
+ title = html_truncate(translated_attribute(log.resource.root_commentable.title), length: 80)
+ expect(subject).to have_no_link(title, href: comment_link)
+ end
+ end
+ end
+
context "when on the second page" do
let(:current_page) { 2 }
diff --git a/decidim-core/spec/lib/settings_manifest_spec.rb b/decidim-core/spec/lib/settings_manifest_spec.rb
index a7671f3984ebd..596d8b991aa3a 100644
--- a/decidim-core/spec/lib/settings_manifest_spec.rb
+++ b/decidim-core/spec/lib/settings_manifest_spec.rb
@@ -91,7 +91,7 @@ module Decidim
subject.attribute :something, choices: %w(a b c)
expect(subject.attributes[:something].build_choices).to eq(%w(a b c))
- subject.attribute :something, choices: -> { %w(a b c) }
+ subject.attribute :something, choices: ->(_context) { %w(a b c) }
expect(subject.attributes[:something].build_choices).to eq(%w(a b c))
end
diff --git a/decidim-core/spec/system/user_group_creation_spec.rb b/decidim-core/spec/system/user_group_creation_spec.rb
index 0c326d756e421..c049c795530e1 100644
--- a/decidim-core/spec/system/user_group_creation_spec.rb
+++ b/decidim-core/spec/system/user_group_creation_spec.rb
@@ -36,4 +36,40 @@
expect(page).to have_content(user.name)
end
end
+
+ context "when nickname has invalid format" do
+ it "shows validation error in the form instead of raising exception" do
+ click_on "Create group"
+
+ fill_in "Name", with: "Valid Group Name"
+ fill_in "Nickname", with: "Invalid Nickname"
+ fill_in "Email", with: "user_group@decidim.org"
+ fill_in "Document number", with: "12345678X"
+ fill_in "Phone", with: "12345678"
+
+ click_on "Create group"
+
+ expect(page).to have_content("There was a problem creating the group")
+ expect(page).to have_css("small.form-error.is-visible", text: "is invalid")
+ expect(page).to have_css(".is-invalid-input#group_nickname")
+ end
+ end
+
+ context "when name has invalid format" do
+ it "shows validation error in the form instead of raising exception" do
+ click_on "Create group"
+
+ fill_in "Name", with: "
"
+ fill_in "Nickname", with: "valid_nickname"
+ fill_in "Email", with: "user_group@decidim.org"
+ fill_in "Document number", with: "12345678X"
+ fill_in "Phone", with: "12345678"
+
+ click_on "Create group"
+
+ expect(page).to have_content("There was a problem creating the group")
+ expect(page).to have_css("small.form-error.is-visible", text: "is invalid")
+ expect(page).to have_css(".is-invalid-input#group_name")
+ end
+ end
end
diff --git a/decidim-core/spec/validators/etiquette_validator_spec.rb b/decidim-core/spec/validators/etiquette_validator_spec.rb
index 885620d65b25c..4c0091810bfc5 100644
--- a/decidim-core/spec/validators/etiquette_validator_spec.rb
+++ b/decidim-core/spec/validators/etiquette_validator_spec.rb
@@ -24,7 +24,8 @@ def self.model_name
[
%(I am a very reasonable body, ain't I? I have the right length, the right style, the right words. Yup.),
%("Validate bodies", they said. "It is gonna be fun!", they said.),
- %(I contain special characters because I am à la mode.)
+ %(I contain special characters because I am à la mode.),
+ %(À la mode, I want to contain special characters.)
].each do |a_body|
describe "like \"#{a_body}\"" do
let(:body) { a_body }
@@ -50,6 +51,12 @@ def self.model_name
context "when etiquette_validator is enabled" do
it { is_expected.to be_invalid }
end
+
+ context "when the text has non-ascii uppercase characters" do
+ let(:body) { "À ÑÓ ÂÊ" }
+
+ it { is_expected.to be_invalid }
+ end
end
context "when the text has too many marks" do
@@ -85,6 +92,12 @@ def self.model_name
it { is_expected.to be_invalid }
end
+ context "with non ascii characters" do
+ let(:body) { "à la mode, we start with a non-ascii character in downcase." }
+
+ it { is_expected.to be_invalid }
+ end
+
context "with a multiple line body with the second line starting in downcase" do
let(:body) { "This is a multiline body\nwith a line starting with downcase." }
diff --git a/decidim-dev/lib/decidim/dev/common_rake.rb b/decidim-dev/lib/decidim/dev/common_rake.rb
index 3350d811aa6cc..001edb5748e7e 100644
--- a/decidim-dev/lib/decidim/dev/common_rake.rb
+++ b/decidim-dev/lib/decidim/dev/common_rake.rb
@@ -3,7 +3,6 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"
require "decidim/dev"
-require "parallel_tests/tasks"
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = "--format progress --format RspecJunitFormatter -o ~/rspec/rspec.xml" if ENV["CI"]
diff --git a/decidim-forms/config/locales/en.yml b/decidim-forms/config/locales/en.yml
index 2fe8fd83dae29..e42bdf27a76ad 100644
--- a/decidim-forms/config/locales/en.yml
+++ b/decidim-forms/config/locales/en.yml
@@ -55,7 +55,7 @@ en:
tos: Terms of service
questionnaires:
actions:
- back: Back to questions
+ back: Back to responses
publish_answers: Publish answers
show: Show responses
answer_option:
diff --git a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb
index 2ddd3dd899731..ae4bcfccf86b5 100644
--- a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb
+++ b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meeting-tr.html.erb
@@ -32,7 +32,15 @@
<%= present(meeting).taxonomy_names.join(", ") %>
|
-
+ | ">
+ <% if meeting.published? %>
+ <%= t("admin.meetings.index.published", scope: "decidim.meetings") %>
+ <% else %>
+ <%= t("admin.meetings.index.unpublished", scope: "decidim.meetings") %>
+ <% end %>
+ |
+
+ ">
<% if is_linked %>
<%= t("index.linked_meeting_warning_html", href: edit_meeting_path(meeting), name: present(meeting).space_title, scope: "decidim.meetings.admin.meetings") %>
<% else %>
diff --git a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb
index c432644fa8446..eb7eb20d0a364 100644
--- a/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb
+++ b/decidim-meetings/app/views/decidim/meetings/admin/meetings/_meetings-thead.html.erb
@@ -21,6 +21,9 @@
|
<%= sort_link(query, :scope_name, t("models.meeting.fields.taxonomies", scope: "decidim.meetings") ) %>
|
+
+ <%= t("models.meeting.fields.published", scope: "decidim.meetings") %>
+ |
<%= t("actions.title", scope: "decidim.meetings") %> |
diff --git a/decidim-meetings/config/locales/en.yml b/decidim-meetings/config/locales/en.yml
index 63720c7282b3f..16f3aab6d4c56 100644
--- a/decidim-meetings/config/locales/en.yml
+++ b/decidim-meetings/config/locales/en.yml
@@ -365,7 +365,9 @@ en:
select_an_iframe_access_level: Please select an iframe access level
index:
linked_meeting_warning_html: This meeting must be edited from
%{name}
+ published: Published
title: Meetings
+ unpublished: Unpublished
linked_spaces:
assign: Assign
link_a_space: Link a space
@@ -637,6 +639,7 @@ en:
id: ID
map: Map
official_meeting: Official meeting
+ published: Published
start_time: Start date
taxonomies: Taxonomies
title: Title
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 e828626e0d1c5..efed7584da53e 100644
--- a/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb
+++ b/decidim-meetings/spec/system/admin/admin_manages_meetings_spec.rb
@@ -48,7 +48,11 @@
accept_confirm { click_on "Unpublish" }
end
- expect(page).to have_admin_callout("successfully")
+ within "tr", text: Decidim::Meetings::MeetingPresenter.new(meeting).title do
+ expect(page).to have_content("Unpublished")
+ end
+
+ expect(page).to have_admin_callout("Meeting successfully unpublished")
within "tr", text: Decidim::Meetings::MeetingPresenter.new(meeting).title do
expect(page).to have_css(".action-icon--publish")
@@ -58,7 +62,11 @@
click_on "Publish"
end
- expect(page).to have_admin_callout("successfully")
+ within "tr", text: Decidim::Meetings::MeetingPresenter.new(meeting).title do
+ expect(page).to have_content("Published")
+ end
+
+ expect(page).to have_admin_callout("Meeting successfully published")
within "tr", text: Decidim::Meetings::MeetingPresenter.new(meeting).title do
expect(page).to have_css(".action-icon--unpublish")
diff --git a/decidim-participatory_processes/app/cells/decidim/participatory_processes/content_blocks/extra_data_cell.rb b/decidim-participatory_processes/app/cells/decidim/participatory_processes/content_blocks/extra_data_cell.rb
index 0021c1b281120..c4e8f7d946f77 100644
--- a/decidim-participatory_processes/app/cells/decidim/participatory_processes/content_blocks/extra_data_cell.rb
+++ b/decidim-participatory_processes/app/cells/decidim/participatory_processes/content_blocks/extra_data_cell.rb
@@ -11,7 +11,7 @@ class ExtraDataCell < Decidim::ContentBlocks::ParticipatorySpaceExtraDataCell
private
def extra_data_items
- [step_item, dates_item, group_item].compact
+ [dates_item, step_item, group_item].compact
end
def active_step_name
diff --git a/decidim-proposals/app/commands/decidim/proposals/create_proposal.rb b/decidim-proposals/app/commands/decidim/proposals/create_proposal.rb
index 76803e3a46ee1..f88f776cd89ee 100644
--- a/decidim-proposals/app/commands/decidim/proposals/create_proposal.rb
+++ b/decidim-proposals/app/commands/decidim/proposals/create_proposal.rb
@@ -84,7 +84,11 @@ def create_proposal
proposal.taxonomizations = form.taxonomizations if form.taxonomizations.present?
proposal.documents = form.documents if form.documents.present?
- proposal.address = form.address if form.has_address? && !form.geocoded?
+ if form.geocoded?
+ proposal.latitude = form.latitude
+ proposal.longitude = form.longitude
+ end
+ proposal.address = form.address if form.has_address?
proposal.add_coauthor(@current_user, user_group:)
proposal.save!
@attached_to = proposal
diff --git a/decidim-proposals/lib/decidim/proposals/component.rb b/decidim-proposals/lib/decidim/proposals/component.rb
index e76f16ef5e2b6..cad6e2e8c6c7d 100644
--- a/decidim-proposals/lib/decidim/proposals/component.rb
+++ b/decidim-proposals/lib/decidim/proposals/component.rb
@@ -34,12 +34,12 @@
settings.attribute :minimum_votes_per_user, type: :integer, default: 0, required: true
settings.attribute :proposal_limit, type: :integer, default: 0, required: true
settings.attribute :proposal_length, type: :integer, default: 500
- settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: -> { %w(infinite limited) }
+ settings.attribute :proposal_edit_time, type: :enum, default: "limited", choices: ->(_context) { %w(infinite limited) }
settings.attribute :edit_time, type: :integer_with_units, default: [5, "minutes"], required: true, units: %w(minutes hours days)
settings.attribute :threshold_per_proposal, type: :integer, default: 0, required: true
settings.attribute :can_accumulate_votes_beyond_threshold, type: :boolean, default: false
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
- settings.attribute :default_sort_order, type: :select, default: "automatic", choices: -> { POSSIBLE_SORT_ORDERS }
+ settings.attribute :default_sort_order, type: :select, default: "automatic", choices: ->(_context) { POSSIBLE_SORT_ORDERS }
settings.attribute :official_proposals_enabled, type: :boolean, default: true
settings.attribute :comments_enabled, type: :boolean, default: true
settings.attribute :comments_max_length, type: :integer, required: true
@@ -73,13 +73,13 @@
settings.attribute :proposal_answering_enabled, type: :boolean, default: true
settings.attribute :publish_answers_immediately, type: :boolean, default: true
settings.attribute :answers_with_costs, type: :boolean, default: false
- settings.attribute :default_sort_order, type: :select, include_blank: true, choices: -> { POSSIBLE_SORT_ORDERS }
+ settings.attribute :default_sort_order, type: :select, include_blank: true, choices: ->(_context) { POSSIBLE_SORT_ORDERS }
settings.attribute :amendment_creation_enabled, type: :boolean, default: true
settings.attribute :amendment_reaction_enabled, type: :boolean, default: true
settings.attribute :amendment_promotion_enabled, type: :boolean, default: true
settings.attribute :amendments_visibility,
type: :enum, default: "all",
- choices: -> { Decidim.config.amendments_visibility_options }
+ choices: ->(_context) { Decidim.config.amendments_visibility_options }
settings.attribute :announcement, type: :text, translated: true, editor: true
settings.attribute :automatic_hashtags, type: :text, editor: false, required: false
settings.attribute :suggested_hashtags, type: :text, editor: false, required: false
diff --git a/decidim-proposals/spec/commands/decidim/proposals/create_proposal_spec.rb b/decidim-proposals/spec/commands/decidim/proposals/create_proposal_spec.rb
index 3b2cbc5e01b51..3b5774fd00875 100644
--- a/decidim-proposals/spec/commands/decidim/proposals/create_proposal_spec.rb
+++ b/decidim-proposals/spec/commands/decidim/proposals/create_proposal_spec.rb
@@ -193,6 +193,28 @@ module Proposals
end
end
end
+
+ describe "when geocoding is enabled" do
+ let(:component) { create(:proposal_component, :with_geocoding_enabled) }
+ let(:form_params) do
+ {
+ title: "A reasonable proposal title",
+ body: "A reasonable proposal body",
+ address: "Barcelona",
+ latitude: 41.394897,
+ longitude: 2.153088
+ }
+ end
+
+ it "saves geocoding data" do
+ expect { command.call }.to broadcast(:ok)
+ proposal = Decidim::Proposals::Proposal.last
+
+ expect(proposal.address).to eq(form_params[:address])
+ expect(proposal.latitude).to eq(form_params[:latitude])
+ expect(proposal.longitude).to eq(form_params[:longitude])
+ end
+ end
end
end
end
diff --git a/decidim-surveys/app/views/decidim/surveys/admin/publish_answers/index.html.erb b/decidim-surveys/app/views/decidim/surveys/admin/publish_answers/index.html.erb
index 0d320a474a665..3bc756ef83171 100644
--- a/decidim-surveys/app/views/decidim/surveys/admin/publish_answers/index.html.erb
+++ b/decidim-surveys/app/views/decidim/surveys/admin/publish_answers/index.html.erb
@@ -4,7 +4,7 @@
diff --git a/docs/modules/customize/assets/images/content_security_policy.png b/docs/modules/customize/assets/images/content_security_policy.png
new file mode 100644
index 0000000000000..ab67864b33335
Binary files /dev/null and b/docs/modules/customize/assets/images/content_security_policy.png differ
diff --git a/docs/modules/customize/pages/content_security_policy.adoc b/docs/modules/customize/pages/content_security_policy.adoc
index ec84b02988ff0..e5ce7becba6ef 100644
--- a/docs/modules/customize/pages/content_security_policy.adoc
+++ b/docs/modules/customize/pages/content_security_policy.adoc
@@ -19,14 +19,20 @@ By default, the CSP is enabled, and is configured to be as restrictive as possib
In order to customize the CSP we are providing, have 2 options, either by using a configuration key the initializer `config/initializers/decidim.rb` or by setting values in the Organization's system admin.
-Using the initializer is the recommended way to customize the CSP when you have multiple organizations sharing the same Decidim instance, sharing the same tools. Fox example, if you are using a custom map provider, you will need to add the domain to the CSP, so that the map can be displayed. In this case, you will need to add the following to your initializer:
+We recommend using the System panel, as you will not need to be restarting the server when making changes.
+
+image::content_security_policy.png[Content Security Policy]
+
+On the other hand, the initializer is more comfortable when you have multiple organizations sharing the same Decidim instance, sharing the same tools. For example, if you are using a custom map provider, you will need to add the domain to the CSP, so that the map can be displayed. In this case, you will need to add the following to your initializer:
[source,ruby]
....
-config.content_security_policies_extra = {
- "connect-src" => %w(https://*.example.com),
- "img-src" => %w(https://*.example.com)
-}
+Decidim.configure do |config|
+ config.content_security_policies_extra = {
+ "connect-src" => %w(https://*.example.com),
+ "img-src" => %w(https://*.example.com)
+ }
+end
....
For specific organization setup, you could use the system panel to customize the Content Security Policies, by adding the domains or directives that you need to allow in the predesignated spots.
diff --git a/docs/modules/develop/pages/components.adoc b/docs/modules/develop/pages/components.adoc
index 805bb47035505..21167121ecc52 100644
--- a/docs/modules/develop/pages/components.adoc
+++ b/docs/modules/develop/pages/components.adoc
@@ -140,7 +140,7 @@ Decidim.register_component(:my_component) do |component|
component.settings(:step) do |settings|
settings.attribute :a_text_setting, type: :text, default: false, required: true, translated: true, editor: true
- settings.attribute :a_lambda_enum_setting, type: :enum, default: "all", choices: -> { SomeClass.enum_options }
+ settings.attribute :a_lambda_enum_setting, type: :enum, default: "all", choices: ->(_context) { SomeClass.enum_options }
settings.attribute :a_readonly_setting, type: :string, readonly: ->(context) { SomeClass.readonly?(context[:component]) }
end
diff --git a/docs/modules/services/pages/activestorage.adoc b/docs/modules/services/pages/activestorage.adoc
index e895773282adc..6b75c6099d3c8 100644
--- a/docs/modules/services/pages/activestorage.adoc
+++ b/docs/modules/services/pages/activestorage.adoc
@@ -4,6 +4,11 @@ Decidim uses https://edgeguides.rubyonrails.org/active_storage_overview.html[Act
In order to plug Decidim into a storage provider of your choice, you need to generate the Decidim application using the `--storage` modifier as explained at the xref:configure:index.adoc[configuration guide]. You will also need to provide the correct configuration options for the selected storage provider as explained at the xref:configure:environment_variables.adoc[environment variables guide].
+[NOTE]
+====
+If you use any other provider than the default (`local`) you will need to also configure the xref:customize:content_security_policy.adoc[Content security policy]. For the directives "default-src", "img-src", "media-src", and "connect-src"`.
+====
+
== Dynamic file uploads
Decidim allows participants to upload files dynamically from their browsers to the website using the upload modals where participants can drag and drop the files to or select them from their computer. With the default configuration using a local file storage, this feature does not require any additional configuration. With external storage providers, you have to configure those storages properly to support the client-side file uploads to Decidim.