decidim-admin 0.31.5 → 0.32.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -12
- data/app/cells/decidim/admin/attachments_privacy_warning/show.erb +1 -1
- data/app/cells/decidim/admin/attachments_privacy_warning_cell.rb +2 -6
- data/app/commands/decidim/admin/content_blocks/reorder_content_blocks.rb +1 -1
- data/app/commands/decidim/admin/participatory_space/create_member.rb +99 -0
- data/app/commands/decidim/admin/participatory_space/destroy_member.rb +30 -0
- data/app/commands/decidim/admin/participatory_space/import_member_csv.rb +46 -0
- data/app/commands/decidim/admin/participatory_space/publish_all_members.rb +52 -0
- data/app/commands/decidim/admin/participatory_space/unpublish_all_members.rb +52 -0
- data/app/commands/decidim/admin/participatory_space/update_member.rb +13 -0
- data/app/commands/decidim/admin/reorder_components.rb +1 -1
- data/app/commands/decidim/admin/reorder_taxonomies.rb +1 -1
- data/app/commands/decidim/admin/update_organization.rb +1 -1
- data/app/controllers/concerns/decidim/admin/content_blocks/landing_page.rb +1 -0
- data/app/controllers/concerns/decidim/admin/content_blocks/landing_page_content_blocks.rb +3 -2
- data/app/controllers/concerns/decidim/admin/filterable.rb +4 -4
- data/app/controllers/concerns/decidim/admin/participatory_space_admin_context.rb +1 -0
- data/app/controllers/concerns/decidim/admin/participatory_space_export.rb +1 -1
- data/app/controllers/decidim/admin/area_types_controller.rb +2 -2
- data/app/controllers/decidim/admin/areas_controller.rb +3 -2
- data/app/controllers/decidim/admin/block_user_controller.rb +2 -2
- data/app/controllers/decidim/admin/component_permissions_controller.rb +1 -1
- data/app/controllers/decidim/admin/components/base_controller.rb +13 -9
- data/app/controllers/decidim/admin/components_controller.rb +3 -2
- data/app/controllers/decidim/admin/concerns/has_attachment_collections.rb +2 -2
- data/app/controllers/decidim/admin/concerns/has_attachments.rb +2 -2
- data/app/controllers/decidim/admin/conflicts_controller.rb +1 -1
- data/app/controllers/decidim/admin/exports_controller.rb +1 -1
- data/app/controllers/decidim/admin/impersonations_controller.rb +1 -1
- data/app/controllers/decidim/admin/imports_controller.rb +2 -1
- data/app/controllers/decidim/admin/managed_users/promotions_controller.rb +1 -1
- data/app/controllers/decidim/admin/newsletters_controller.rb +9 -8
- data/app/controllers/decidim/admin/organization_appearance_controller.rb +1 -1
- data/app/controllers/decidim/admin/organization_controller.rb +1 -1
- data/app/controllers/decidim/admin/organization_external_domain_allowlist_controller.rb +1 -1
- data/app/controllers/decidim/admin/participatory_space/concerns/has_members.rb +166 -0
- data/app/controllers/decidim/admin/participatory_space/concerns/has_members_csv_import.rb +67 -0
- data/app/controllers/decidim/admin/participatory_space/concerns/members_filterable.rb +36 -0
- data/app/controllers/decidim/admin/participatory_space/user_role_controller.rb +2 -2
- data/app/controllers/decidim/admin/reminders_controller.rb +1 -1
- data/app/controllers/decidim/admin/resource_permissions_controller.rb +1 -1
- data/app/controllers/decidim/admin/scope_types_controller.rb +2 -2
- data/app/controllers/decidim/admin/scopes_controller.rb +3 -2
- data/app/controllers/decidim/admin/share_tokens_controller.rb +2 -2
- data/app/controllers/decidim/admin/space_publications_controller.rb +2 -2
- data/app/controllers/decidim/admin/static_page_topics_controller.rb +2 -2
- data/app/controllers/decidim/admin/static_pages_controller.rb +2 -2
- data/app/controllers/decidim/admin/taxonomies_controller.rb +3 -3
- data/app/controllers/decidim/admin/taxonomy_filters_controller.rb +3 -3
- data/app/controllers/decidim/admin/taxonomy_items_controller.rb +3 -3
- data/app/controllers/decidim/admin/users_controller.rb +1 -1
- data/app/forms/decidim/admin/content_block_form.rb +28 -1
- data/app/forms/decidim/admin/organization_form.rb +0 -1
- data/app/forms/decidim/admin/participatory_space/member_csv_import_form.rb +33 -0
- data/app/forms/decidim/admin/participatory_space/member_form.rb +26 -0
- data/app/forms/decidim/admin/participatory_space_admin_user_form.rb +1 -1
- data/app/forms/decidim/admin/selective_newsletter_form.rb +7 -7
- data/app/forms/decidim/admin/taxonomy_filter_form.rb +1 -0
- data/app/helpers/decidim/admin/newsletters_helper.rb +8 -5
- data/app/helpers/decidim/admin/search_form_helper.rb +17 -0
- data/app/helpers/decidim/admin/settings_helper.rb +2 -0
- data/app/jobs/decidim/admin/newsletter_job.rb +2 -2
- data/app/jobs/decidim/admin/participatory_space/destroy_members_follows_job.rb +36 -0
- data/app/jobs/decidim/admin/participatory_space/import_member_csv_job.rb +29 -0
- data/app/packs/src/decidim/admin/controllers/access_mode/access_mode.test.js +68 -0
- data/app/packs/src/decidim/admin/controllers/access_mode/controller.js +52 -0
- data/app/packs/src/decidim/admin/newsletters.js +2 -2
- data/app/packs/stylesheets/decidim/admin/_datepicker.scss +0 -4
- data/app/queries/decidim/admin/newsletter_recipients.rb +8 -8
- data/app/views/decidim/admin/admin_terms/show.html.erb +3 -1
- data/app/views/decidim/admin/area_types/index.html.erb +3 -2
- data/app/views/decidim/admin/areas/index.html.erb +3 -2
- data/app/views/decidim/admin/attachment_collections/edit.html.erb +2 -2
- data/app/views/decidim/admin/attachment_collections/index.html.erb +2 -2
- data/app/views/decidim/admin/attachment_collections/new.html.erb +2 -2
- data/app/views/decidim/admin/attachments/index.html.erb +3 -2
- data/app/views/decidim/admin/authorization_workflows/index.html.erb +2 -2
- data/app/views/decidim/admin/block_user/new.html.erb +1 -0
- data/app/views/decidim/admin/components/index.html.erb +2 -2
- data/app/views/decidim/admin/components/manage_trash.html.erb +2 -2
- data/app/views/decidim/admin/conflicts/edit.html.erb +3 -1
- data/app/views/decidim/admin/conflicts/index.html.erb +3 -2
- data/app/views/decidim/admin/dashboard/show.html.erb +4 -4
- data/app/views/decidim/admin/help_sections/update.html.erb +2 -0
- data/app/views/decidim/admin/impersonatable_users/index.html.erb +3 -2
- data/app/views/decidim/admin/impersonations/_form.html.erb +2 -2
- data/app/views/decidim/admin/impersonations/new.html.erb +3 -2
- data/app/views/decidim/admin/imports/new.html.erb +1 -0
- data/app/views/decidim/admin/logs/_logs_list.html.erb +1 -1
- data/app/views/decidim/admin/logs/index.html.erb +1 -1
- data/app/views/decidim/admin/managed_users/impersonation_logs/index.html.erb +6 -5
- data/app/views/decidim/admin/managed_users/promotions/new.html.erb +3 -2
- data/app/views/decidim/admin/{participatory_space_private_users → members}/edit.html.erb +2 -2
- data/app/views/decidim/admin/{participatory_space_private_users → members}/index.html.erb +25 -25
- data/app/views/decidim/admin/{participatory_space_private_users → members}/new.html.erb +2 -2
- data/app/views/decidim/admin/{participatory_space_private_users_csv_imports → members_csv_imports}/new.html.erb +2 -2
- data/app/views/decidim/admin/moderations/_moderation-tr.html.erb +2 -6
- data/app/views/decidim/admin/moderations/_moderations-thead.html.erb +0 -1
- data/app/views/decidim/admin/moderations/reports/index.html.erb +1 -1
- data/app/views/decidim/admin/newsletter_templates/show.html.erb +3 -2
- data/app/views/decidim/admin/newsletters/confirm_recipients.html.erb +4 -6
- data/app/views/decidim/admin/newsletters/index.html.erb +2 -2
- data/app/views/decidim/admin/newsletters/select_recipients_to_deliver.html.erb +2 -2
- data/app/views/decidim/admin/newsletters/show.html.erb +3 -2
- data/app/views/decidim/admin/officializations/index.html.erb +6 -4
- data/app/views/decidim/admin/officializations/show_email.html.erb +2 -0
- data/app/views/decidim/admin/organization/form/_extra_features.html.erb +0 -4
- data/app/views/decidim/admin/organization_external_domain_allowlist/_form.html.erb +2 -2
- data/app/views/decidim/admin/organization_external_domain_allowlist/edit.html.erb +2 -2
- data/app/views/decidim/admin/reminders/new.html.erb +8 -1
- data/app/views/decidim/admin/resource_permissions/edit.html.erb +2 -2
- data/app/views/decidim/admin/scope_types/index.html.erb +3 -2
- data/app/views/decidim/admin/scopes/index.html.erb +2 -2
- data/app/views/decidim/admin/share_tokens/index.html.erb +2 -0
- data/app/views/decidim/admin/shared/landing_page/_content_blocks.html.erb +0 -2
- data/app/views/decidim/admin/shared/landing_page/edit.html.erb +2 -0
- data/app/views/decidim/admin/shared/landing_page_content_blocks/edit.html.erb +1 -0
- data/app/views/decidim/admin/static_page_topics/index.html.erb +2 -2
- data/app/views/decidim/admin/static_pages/edit.html.erb +2 -1
- data/app/views/decidim/admin/static_pages/index.html.erb +2 -2
- data/app/views/decidim/admin/statistics/_statistics.html.erb +1 -1
- data/app/views/decidim/admin/statistics/index.html.erb +2 -0
- data/app/views/decidim/admin/taxonomies/_row.html.erb +1 -1
- data/app/views/decidim/admin/taxonomies/_row_children.html.erb +1 -1
- data/app/views/decidim/admin/taxonomies/_table.html.erb +1 -1
- data/app/views/decidim/admin/taxonomies/edit.html.erb +2 -2
- data/app/views/decidim/admin/taxonomies/index.html.erb +4 -4
- data/app/views/decidim/admin/taxonomy_filters/index.html.erb +2 -2
- data/app/views/decidim/admin/taxonomy_filters_selector/index.html.erb +2 -0
- data/app/views/decidim/admin/taxonomy_filters_selector/new.html.erb +2 -0
- data/app/views/decidim/admin/taxonomy_filters_selector/show.html.erb +2 -0
- data/app/views/decidim/admin/taxonomy_items/edit.html.erb +2 -0
- data/app/views/decidim/admin/taxonomy_items/new.html.erb +2 -0
- data/app/views/decidim/admin/users/index.html.erb +3 -2
- data/config/locales/ar.yml +4 -48
- data/config/locales/bg.yml +4 -54
- data/config/locales/bs-BA.yml +0 -23
- data/config/locales/ca-IT.yml +126 -98
- data/config/locales/ca.yml +126 -98
- data/config/locales/cs.yml +122 -95
- data/config/locales/de.yml +109 -93
- data/config/locales/el.yml +11 -44
- data/config/locales/en.yml +126 -98
- data/config/locales/eo.yml +0 -6
- data/config/locales/es-MX.yml +126 -98
- data/config/locales/es-PY.yml +126 -98
- data/config/locales/es.yml +126 -98
- data/config/locales/eu.yml +126 -98
- data/config/locales/fi-plain.yml +126 -98
- data/config/locales/fi.yml +126 -98
- data/config/locales/fr-CA.yml +91 -90
- data/config/locales/fr.yml +91 -90
- data/config/locales/ga-IE.yml +0 -12
- data/config/locales/gl.yml +4 -40
- data/config/locales/he-IL.yml +0 -4
- data/config/locales/hu.yml +4 -51
- data/config/locales/id-ID.yml +4 -33
- data/config/locales/is-IS.yml +0 -14
- data/config/locales/it.yml +4 -67
- data/config/locales/ja.yml +124 -98
- data/config/locales/kaa.yml +0 -15
- data/config/locales/ko.yml +0 -39
- data/config/locales/lb.yml +4 -40
- data/config/locales/lt.yml +4 -51
- data/config/locales/lv.yml +4 -37
- data/config/locales/nl.yml +4 -45
- data/config/locales/no.yml +4 -45
- data/config/locales/pl.yml +4 -53
- data/config/locales/pt-BR.yml +109 -96
- data/config/locales/pt.yml +4 -41
- data/config/locales/ro-RO.yml +9 -50
- data/config/locales/ru.yml +4 -34
- data/config/locales/sk.yml +126 -98
- data/config/locales/sl.yml +0 -6
- data/config/locales/sq-AL.yml +0 -20
- data/config/locales/sr-CS.yml +0 -23
- data/config/locales/sv.yml +74 -86
- data/config/locales/th-TH.yml +0 -7
- data/config/locales/tr-TR.yml +21 -57
- data/config/locales/uk.yml +0 -25
- data/config/locales/zh-CN.yml +4 -37
- data/config/locales/zh-TW.yml +4 -51
- data/decidim-admin.gemspec +7 -10
- data/lib/decidim/admin/engine.rb +5 -2
- data/lib/decidim/admin/menu.rb +1 -1
- data/lib/decidim/admin/test/admin_members_shared_examples.rb +119 -0
- data/lib/decidim/admin/test/admin_participatory_space_access_examples.rb +3 -3
- data/lib/decidim/admin/test/filterable_examples.rb +20 -11
- data/lib/decidim/admin/test/invite_participatory_space_admins_shared_examples.rb +17 -17
- data/lib/decidim/admin/test/invite_participatory_space_collaborators_shared_examples.rb +1 -1
- data/lib/decidim/admin/test/invite_participatory_space_moderators_shared_examples.rb +1 -1
- data/lib/decidim/admin/test/invite_participatory_space_users_shared_context.rb +1 -1
- data/lib/decidim/admin/test/manage_attachment_collections_examples.rb +3 -3
- data/lib/decidim/admin/test/manage_attachments_examples.rb +6 -6
- data/lib/decidim/admin/test/manage_component_permissions_examples.rb +5 -5
- data/lib/decidim/admin/test/manage_moderations_examples.rb +6 -6
- data/lib/decidim/admin/test/manage_participatory_space_publications_examples.rb +2 -2
- data/lib/decidim/admin/test/manage_resource_soft_deletion_examples.rb +3 -3
- data/lib/decidim/admin/version.rb +1 -1
- data/lib/decidim/admin.rb +0 -2
- metadata +39 -35
- data/app/commands/decidim/admin/create_participatory_space_private_user.rb +0 -98
- data/app/commands/decidim/admin/destroy_participatory_space_private_user.rb +0 -28
- data/app/commands/decidim/admin/process_participatory_space_private_user_import_csv.rb +0 -44
- data/app/commands/decidim/admin/publish_all_participatory_space_private_users.rb +0 -50
- data/app/commands/decidim/admin/unpublish_all_participatory_space_private_users.rb +0 -50
- data/app/commands/decidim/admin/update_participatory_space_private_user.rb +0 -11
- data/app/controllers/concerns/decidim/participatory_space_private_users/admin/filterable.rb +0 -34
- data/app/controllers/decidim/admin/concerns/has_private_users.rb +0 -169
- data/app/controllers/decidim/admin/concerns/has_private_users_csv_import.rb +0 -65
- data/app/forms/decidim/admin/participatory_space_private_user_csv_import_form.rb +0 -31
- data/app/forms/decidim/admin/participatory_space_private_user_form.rb +0 -24
- data/app/jobs/decidim/admin/destroy_private_users_follows_job.rb +0 -37
- data/app/jobs/decidim/admin/import_participatory_space_private_user_csv_job.rb +0 -27
- data/app/views/decidim/admin/devise/mailers/password_change.html.erb +0 -3
- data/app/views/decidim/admin/devise/mailers/reset_password_instructions.html.erb +0 -8
- /data/app/views/decidim/admin/{participatory_space_private_users → members}/_form.html.erb +0 -0
|
@@ -9,7 +9,7 @@ module Decidim
|
|
|
9
9
|
before_action do
|
|
10
10
|
if taxonomy_item && taxonomy_item.parent_ids.exclude?(taxonomy.id)
|
|
11
11
|
flash[:alert] = I18n.t("update.invalid", scope: "decidim.admin.taxonomies")
|
|
12
|
-
render plain: I18n.t("update.invalid", scope: "decidim.admin.taxonomies"), status: :
|
|
12
|
+
render plain: I18n.t("update.invalid", scope: "decidim.admin.taxonomies"), status: :unprocessable_content
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ module Decidim
|
|
|
29
29
|
|
|
30
30
|
on(:invalid) do
|
|
31
31
|
flash.now[:alert] = I18n.t("create.invalid", scope: "decidim.admin.taxonomies")
|
|
32
|
-
render action: "new", status: :
|
|
32
|
+
render action: "new", status: :unprocessable_content
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -50,7 +50,7 @@ module Decidim
|
|
|
50
50
|
|
|
51
51
|
on(:invalid) do
|
|
52
52
|
flash.now[:alert] = I18n.t("update.invalid", scope: "decidim.admin.taxonomies")
|
|
53
|
-
render action: "edit", status: :
|
|
53
|
+
render action: "edit", status: :unprocessable_content
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -12,12 +12,39 @@ module Decidim
|
|
|
12
12
|
attribute :settings, Object
|
|
13
13
|
attribute :images, Hash
|
|
14
14
|
|
|
15
|
+
validate :validate_settings
|
|
16
|
+
|
|
15
17
|
def map_model(model)
|
|
16
18
|
self.images = model.images_container
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def settings?
|
|
20
|
-
settings.manifest
|
|
22
|
+
return false unless settings.respond_to?(:manifest)
|
|
23
|
+
|
|
24
|
+
settings.manifest.attributes.any?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate_settings
|
|
30
|
+
coerce_settings if settings.respond_to?(:to_h) && !settings.respond_to?(:valid?)
|
|
31
|
+
|
|
32
|
+
return unless settings.respond_to?(:valid?)
|
|
33
|
+
return if settings.valid?
|
|
34
|
+
|
|
35
|
+
settings.errors.each do |error|
|
|
36
|
+
errors.add(:settings, error.message)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def coerce_settings
|
|
41
|
+
content_block = context[:content_block]
|
|
42
|
+
return unless content_block
|
|
43
|
+
|
|
44
|
+
self.settings = content_block.manifest.settings.schema.new(
|
|
45
|
+
settings.to_h,
|
|
46
|
+
content_block.organization.default_locale
|
|
47
|
+
)
|
|
21
48
|
end
|
|
22
49
|
end
|
|
23
50
|
end
|
|
@@ -20,7 +20,6 @@ module Decidim
|
|
|
20
20
|
attribute :rich_text_editor_in_public_views, Boolean
|
|
21
21
|
attribute :enable_machine_translations, Boolean
|
|
22
22
|
attribute :machine_translation_display_priority, String
|
|
23
|
-
attribute :enable_participatory_space_filters, Boolean
|
|
24
23
|
|
|
25
24
|
attribute :twitter_handler, String
|
|
26
25
|
attribute :facebook_handler, String
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "csv"
|
|
4
|
+
|
|
5
|
+
module Decidim
|
|
6
|
+
module Admin
|
|
7
|
+
module ParticipatorySpace
|
|
8
|
+
# A form object used to upload CSV to batch members.
|
|
9
|
+
#
|
|
10
|
+
class MemberCsvImportForm < Form
|
|
11
|
+
include Decidim::HasUploadValidations
|
|
12
|
+
include Decidim::Admin::CustomImport
|
|
13
|
+
|
|
14
|
+
attribute :file, Decidim::Attributes::Blob
|
|
15
|
+
attribute :user_name, String
|
|
16
|
+
attribute :email, String
|
|
17
|
+
|
|
18
|
+
validates :file, presence: true, file_content_type: { allow: ["text/csv"] }
|
|
19
|
+
validate :validate_csv
|
|
20
|
+
|
|
21
|
+
def validate_csv
|
|
22
|
+
return if file.blank?
|
|
23
|
+
|
|
24
|
+
process_import_file(file) do |(_email, user_name)|
|
|
25
|
+
errors.add(:user_name, :invalid) if user_name.blank? || !user_name.match?(UserBaseEntity::REGEXP_NAME)
|
|
26
|
+
end
|
|
27
|
+
rescue CSV::MalformedCSVError
|
|
28
|
+
errors.add(:file, :malformed)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Admin
|
|
5
|
+
module ParticipatorySpace
|
|
6
|
+
# A form object used to create members from the
|
|
7
|
+
# admin dashboard.
|
|
8
|
+
#
|
|
9
|
+
class MemberForm < Form
|
|
10
|
+
include TranslatableAttributes
|
|
11
|
+
|
|
12
|
+
mimic :member
|
|
13
|
+
|
|
14
|
+
attribute :name, String
|
|
15
|
+
attribute :email, String
|
|
16
|
+
attribute :published, Boolean
|
|
17
|
+
|
|
18
|
+
translatable_attribute :role, String
|
|
19
|
+
|
|
20
|
+
validates :name, :email, presence: true
|
|
21
|
+
|
|
22
|
+
validates :name, format: { with: UserBaseEntity::REGEXP_NAME }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -12,13 +12,13 @@ module Decidim
|
|
|
12
12
|
attribute :send_to_verified_users, Boolean
|
|
13
13
|
attribute :send_to_participants, Boolean
|
|
14
14
|
attribute :send_to_followers, Boolean
|
|
15
|
-
attribute :
|
|
15
|
+
attribute :send_to_members, Boolean
|
|
16
16
|
|
|
17
17
|
validates :send_to_all_users, presence: true, unless: :other_groups_selected_for_all_users?
|
|
18
18
|
validates :send_to_verified_users, presence: true, unless: :other_groups_selected_for_verified_users?
|
|
19
19
|
validates :send_to_followers, presence: true, if: :only_followers_selected?
|
|
20
20
|
validates :send_to_participants, presence: true, if: :only_participants_selected?
|
|
21
|
-
validates :
|
|
21
|
+
validates :send_to_members, presence: true, if: :only_members_selected?
|
|
22
22
|
|
|
23
23
|
validate :at_least_one_participatory_space_selected
|
|
24
24
|
|
|
@@ -49,31 +49,31 @@ module Decidim
|
|
|
49
49
|
send_to_verified_users.present? ||
|
|
50
50
|
send_to_participants.present? ||
|
|
51
51
|
send_to_followers.present? ||
|
|
52
|
-
|
|
52
|
+
send_to_members.present?
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def other_groups_selected_for_verified_users?
|
|
56
56
|
send_to_all_users.present? ||
|
|
57
57
|
send_to_participants.present? ||
|
|
58
58
|
send_to_followers.present? ||
|
|
59
|
-
|
|
59
|
+
send_to_members.present?
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def only_followers_selected?
|
|
63
63
|
send_to_all_users.blank? &&
|
|
64
64
|
send_to_participants.blank? &&
|
|
65
|
-
|
|
65
|
+
send_to_members.blank? &&
|
|
66
66
|
send_to_verified_users.blank?
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def only_participants_selected?
|
|
70
70
|
send_to_all_users.blank? &&
|
|
71
71
|
send_to_followers.blank? &&
|
|
72
|
-
|
|
72
|
+
send_to_members.blank? &&
|
|
73
73
|
send_to_verified_users.blank?
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
def
|
|
76
|
+
def only_members_selected?
|
|
77
77
|
send_to_all_users.blank? &&
|
|
78
78
|
send_to_followers.blank? &&
|
|
79
79
|
send_to_participants.blank? &&
|
|
@@ -23,10 +23,13 @@ module Decidim
|
|
|
23
23
|
return if spaces_user_can_admin[space_type.manifest_name.to_sym].blank?
|
|
24
24
|
|
|
25
25
|
html = ""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
|
|
27
|
+
form_object.fields_for :participatory_space_types do |f|
|
|
28
|
+
f.fields_for space_type.manifest_name, space_type do |ff|
|
|
29
|
+
html += participatory_space_title(space_type)
|
|
30
|
+
html += ff.hidden_field :manifest_name, value: space_type.manifest_name
|
|
31
|
+
html += select_tag_participatory_spaces(space_type.manifest_name, spaces_for_select(space_type.manifest_name.to_sym), ff)
|
|
32
|
+
end
|
|
30
33
|
end
|
|
31
34
|
html.html_safe
|
|
32
35
|
end
|
|
@@ -80,7 +83,7 @@ module Decidim
|
|
|
80
83
|
recipients << content_tag(:strong, t("index.verified_users", scope: "decidim.admin.newsletters")) if newsletter.sent_to_verified_users?
|
|
81
84
|
recipients << content_tag(:strong, t("index.followers", scope: "decidim.admin.newsletters")) if newsletter.sent_to_followers?
|
|
82
85
|
recipients << content_tag(:strong, t("index.participants", scope: "decidim.admin.newsletters")) if newsletter.sent_to_participants?
|
|
83
|
-
recipients << content_tag(:strong, t("index.
|
|
86
|
+
recipients << content_tag(:strong, t("index.members", scope: "decidim.admin.newsletters")) if newsletter.sent_to_members?
|
|
84
87
|
|
|
85
88
|
concat recipients.join(t("index.and", scope: "decidim.admin.newsletters")).html_safe
|
|
86
89
|
end
|
|
@@ -11,9 +11,26 @@ module Decidim
|
|
|
11
11
|
# as datetime pickers.
|
|
12
12
|
def search_form_for(record, options = {}, &)
|
|
13
13
|
options[:builder] ||= SearchFormBuilder
|
|
14
|
+
options[:url] = url_for(params.to_unsafe_h.except("locale", :locale).merge(locale: nil)) if options[:url].blank?
|
|
14
15
|
|
|
15
16
|
super
|
|
16
17
|
end
|
|
18
|
+
|
|
19
|
+
def sort_link(search_object, attribute, *args, &)
|
|
20
|
+
options = args.extract_options!
|
|
21
|
+
options = options.merge(params: sort_link_params)
|
|
22
|
+
args << options
|
|
23
|
+
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def sort_link_params
|
|
30
|
+
request_params = params.to_unsafe_h.except("locale", :locale).merge(locale: nil)
|
|
31
|
+
request_params["q"] = request_params["q"].except("s", :s) if request_params["q"].is_a?(Hash)
|
|
32
|
+
request_params
|
|
33
|
+
end
|
|
17
34
|
end
|
|
18
35
|
end
|
|
19
36
|
end
|
|
@@ -161,6 +161,7 @@ module Decidim
|
|
|
161
161
|
#
|
|
162
162
|
# @param attribute [Decidim::SettingsManifest::Attribute]
|
|
163
163
|
# @return [Symbol] The FormBuilder's method used to render
|
|
164
|
+
# @param [Object] options
|
|
164
165
|
def form_method_for_attribute(attribute, options)
|
|
165
166
|
return :editor if attribute.type.to_sym == :text && options[:editor]
|
|
166
167
|
|
|
@@ -225,6 +226,7 @@ module Decidim
|
|
|
225
226
|
#
|
|
226
227
|
# @param name (see #settings_attribute_input)
|
|
227
228
|
# @param i18n_scope (see #settings_attribute_input)
|
|
229
|
+
# @param [Object] form
|
|
228
230
|
def taxonomy_filters(form, name, i18n_scope)
|
|
229
231
|
return disabled_taxonomy_filters(name, i18n_scope) if @component&.new_record?
|
|
230
232
|
|
|
@@ -6,7 +6,7 @@ module Decidim
|
|
|
6
6
|
#
|
|
7
7
|
class NewsletterJob < ApplicationJob
|
|
8
8
|
queue_as :newsletter
|
|
9
|
-
self.enqueue_after_transaction_commit =
|
|
9
|
+
self.enqueue_after_transaction_commit = false
|
|
10
10
|
|
|
11
11
|
def perform(newsletter, form, recipients_ids)
|
|
12
12
|
@newsletter = newsletter
|
|
@@ -37,7 +37,7 @@ module Decidim
|
|
|
37
37
|
send_to_verified_users: @form["send_to_verified_users"],
|
|
38
38
|
send_to_followers: @form["send_to_followers"],
|
|
39
39
|
send_to_participants: @form["send_to_participants"],
|
|
40
|
-
|
|
40
|
+
send_to_members: @form["send_to_members"],
|
|
41
41
|
participatory_space_types: @form["participatory_space_types"],
|
|
42
42
|
verification_types: @form["verification_types"]
|
|
43
43
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Admin
|
|
5
|
+
module ParticipatorySpace
|
|
6
|
+
class DestroyMembersFollowsJob < ApplicationJob
|
|
7
|
+
queue_as :default
|
|
8
|
+
|
|
9
|
+
def perform(decidim_user_id, space)
|
|
10
|
+
return unless space.respond_to?(:restricted?) && space.restricted?
|
|
11
|
+
return if space.respond_to?(:transparent?) && space.transparent?
|
|
12
|
+
|
|
13
|
+
user = Decidim::User.find_by(id: decidim_user_id)
|
|
14
|
+
|
|
15
|
+
return if user.blank?
|
|
16
|
+
|
|
17
|
+
return if space.respond_to?(:can_participate?) && space.can_participate?(user)
|
|
18
|
+
|
|
19
|
+
follows = Decidim::Follow.where(user:)
|
|
20
|
+
follows.where(followable: space).destroy_all
|
|
21
|
+
|
|
22
|
+
destroy_children_follows(follows, space)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def destroy_children_follows(follows, space)
|
|
26
|
+
follows.map do |follow|
|
|
27
|
+
object = follow.followable.presence
|
|
28
|
+
next unless object.respond_to?(:decidim_component_id)
|
|
29
|
+
|
|
30
|
+
follow.destroy if space.component_ids.include?(object.decidim_component_id)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Admin
|
|
5
|
+
module ParticipatorySpace
|
|
6
|
+
# Custom ApplicationJob scoped to the admin panel.
|
|
7
|
+
#
|
|
8
|
+
class ImportMemberCsvJob < ApplicationJob
|
|
9
|
+
queue_as :exports
|
|
10
|
+
|
|
11
|
+
def perform(email, user_name, participatory_space, current_user)
|
|
12
|
+
return if email.blank? || user_name.blank?
|
|
13
|
+
|
|
14
|
+
params = {
|
|
15
|
+
name: user_name,
|
|
16
|
+
email: email.downcase.strip
|
|
17
|
+
}
|
|
18
|
+
member_form = MemberForm.from_params(params, participatory_space:)
|
|
19
|
+
.with_context(
|
|
20
|
+
current_user:,
|
|
21
|
+
current_participatory_space: participatory_space
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
CreateMember.call(member_form, participatory_space, via_csv: true)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/* global jest */
|
|
2
|
+
|
|
3
|
+
import { Application } from "@hotwired/stimulus"
|
|
4
|
+
import AccessModeController from "src/decidim/admin/controllers/access_mode/controller"
|
|
5
|
+
|
|
6
|
+
describe("AccessModeController", () => {
|
|
7
|
+
let application = null
|
|
8
|
+
let controller = null
|
|
9
|
+
let element = null
|
|
10
|
+
let checkbox = null
|
|
11
|
+
let accessModeFieldset = null
|
|
12
|
+
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
document.body.innerHTML = `
|
|
15
|
+
<div data-controller="access-mode">
|
|
16
|
+
<div id="has_members">
|
|
17
|
+
<input type="hidden" name="has_members" value="0">
|
|
18
|
+
<input type="checkbox" id="has_members_checkbox" name="has_members" value="1">
|
|
19
|
+
</div>
|
|
20
|
+
<fieldset id="access_mode">
|
|
21
|
+
<legend>Access mode</legend>
|
|
22
|
+
<label>Open<input type="radio" name="access_mode" value="open"></label>
|
|
23
|
+
</fieldset>
|
|
24
|
+
</div>
|
|
25
|
+
`
|
|
26
|
+
|
|
27
|
+
application = Application.start()
|
|
28
|
+
application.register("access-mode", AccessModeController)
|
|
29
|
+
|
|
30
|
+
element = document.querySelector("[data-controller='access-mode']")
|
|
31
|
+
checkbox = element.querySelector("#has_members input[type='checkbox']")
|
|
32
|
+
accessModeFieldset = element.querySelector("#access_mode")
|
|
33
|
+
|
|
34
|
+
await new Promise((resolve) => {
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
controller = application.getControllerForElementAndIdentifier(element, "access-mode")
|
|
37
|
+
resolve()
|
|
38
|
+
}, 0)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
controller.disconnect()
|
|
44
|
+
application.stop()
|
|
45
|
+
document.body.innerHTML = ""
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it("hides the access_mode fieldset when members checkbox is unchecked", () => {
|
|
49
|
+
expect(accessModeFieldset.hidden).toBe(true)
|
|
50
|
+
expect(accessModeFieldset.style.display).toBe("none")
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it("shows the fieldset when the members checkbox becomes checked", () => {
|
|
54
|
+
checkbox.checked = true
|
|
55
|
+
checkbox.dispatchEvent(new Event("change"))
|
|
56
|
+
|
|
57
|
+
expect(accessModeFieldset.hidden).toBe(false)
|
|
58
|
+
expect(accessModeFieldset.style.display).toBe("")
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it("removes the event listener on disconnect", () => {
|
|
62
|
+
const removeSpy = jest.spyOn(checkbox, "removeEventListener")
|
|
63
|
+
|
|
64
|
+
controller.disconnect()
|
|
65
|
+
|
|
66
|
+
expect(removeSpy).toHaveBeenCalledWith("change", controller.toggleAccessMode)
|
|
67
|
+
})
|
|
68
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Toggles the visibility of the access mode options according to the
|
|
5
|
+
* "This space has members" checkbox.
|
|
6
|
+
*
|
|
7
|
+
* The controller expects to sit on the access accordion so it can
|
|
8
|
+
* query the checkbox and the `#access_mode` fieldset that lives inside.
|
|
9
|
+
*/
|
|
10
|
+
export default class extends Controller {
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Find the relevant inputs and attach the change listener.
|
|
14
|
+
* @returns {void}
|
|
15
|
+
*/
|
|
16
|
+
connect() {
|
|
17
|
+
this.hasMembersCheckbox = this.element.querySelector("#has_members input[type='checkbox']")
|
|
18
|
+
this.accessModeFieldset = this.element.querySelector("#access_mode")
|
|
19
|
+
|
|
20
|
+
if (!this.hasMembersCheckbox || !this.accessModeFieldset) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
this.toggleAccessMode = this.toggleAccessMode.bind(this)
|
|
25
|
+
this.hasMembersCheckbox.addEventListener("change", this.toggleAccessMode)
|
|
26
|
+
this.toggleAccessMode()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Remove the listener bound during `connect`.
|
|
31
|
+
* @returns {void}
|
|
32
|
+
*/
|
|
33
|
+
disconnect() {
|
|
34
|
+
if (this.hasMembersCheckbox && this.toggleAccessMode) {
|
|
35
|
+
this.hasMembersCheckbox.removeEventListener("change", this.toggleAccessMode)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Show or hide the access mode fieldset depending on the checkbox state.
|
|
41
|
+
* @returns {void}
|
|
42
|
+
*/
|
|
43
|
+
toggleAccessMode() {
|
|
44
|
+
const showAccessMode = this.hasMembersCheckbox.checked
|
|
45
|
+
|
|
46
|
+
this.accessModeFieldset.disabled = !showAccessMode
|
|
47
|
+
this.accessModeFieldset.hidden = !showAccessMode
|
|
48
|
+
this.accessModeFieldset.style.display = showAccessMode
|
|
49
|
+
? ""
|
|
50
|
+
: "none"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -9,7 +9,7 @@ document.addEventListener("turbo:load", () => {
|
|
|
9
9
|
sendToVerifiedUsers: document.querySelector("#newsletter_send_to_verified_users"),
|
|
10
10
|
sendToParticipants: document.querySelector("#newsletter_send_to_participants"),
|
|
11
11
|
sendToFollowers: document.querySelector("#newsletter_send_to_followers"),
|
|
12
|
-
|
|
12
|
+
sendToMembers: document.querySelector("#newsletter_send_to_members"),
|
|
13
13
|
verificationTypesSelect: document.querySelector("#verification_types_for_select"),
|
|
14
14
|
participatorySpacesForSelect: document.querySelector("#participatory_spaces_for_select"),
|
|
15
15
|
deliverButton: document.querySelector("#deliver-button"),
|
|
@@ -24,7 +24,7 @@ document.addEventListener("turbo:load", () => {
|
|
|
24
24
|
checkboxes: [
|
|
25
25
|
selectors.sendToParticipants,
|
|
26
26
|
selectors.sendToFollowers,
|
|
27
|
-
selectors.
|
|
27
|
+
selectors.sendToMembers
|
|
28
28
|
].filter(Boolean)
|
|
29
29
|
};
|
|
30
30
|
|
|
@@ -46,14 +46,14 @@ module Decidim
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def filters_present?
|
|
49
|
-
@form.send_to_followers || @form.send_to_participants || @form.
|
|
49
|
+
@form.send_to_followers || @form.send_to_participants || @form.send_to_members
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def apply_filters(recipients)
|
|
53
53
|
filters = [
|
|
54
54
|
user_id_of_followers,
|
|
55
55
|
participant_ids,
|
|
56
|
-
|
|
56
|
+
member_ids
|
|
57
57
|
].compact.flatten.uniq
|
|
58
58
|
|
|
59
59
|
filters.empty? ? recipients.none : recipients.where(id: filters)
|
|
@@ -119,17 +119,17 @@ module Decidim
|
|
|
119
119
|
participant_ids.flatten.compact.uniq
|
|
120
120
|
end
|
|
121
121
|
|
|
122
|
-
def
|
|
122
|
+
def spaces_with_members
|
|
123
123
|
return [] if spaces.blank?
|
|
124
124
|
|
|
125
|
-
spaces.select { |space| space.
|
|
125
|
+
spaces.select { |space| space.respond_to?(:members) && space.members.exists? }
|
|
126
126
|
end
|
|
127
127
|
|
|
128
|
-
def
|
|
129
|
-
return unless @form.
|
|
130
|
-
return [] if
|
|
128
|
+
def member_ids
|
|
129
|
+
return unless @form.send_to_members
|
|
130
|
+
return [] if spaces_with_members.blank?
|
|
131
131
|
|
|
132
|
-
Decidim::
|
|
132
|
+
Decidim::ParticipatorySpace::Member.member_ids_for_participatory_spaces(spaces_with_members)
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
|
+
|
|
1
3
|
<%= cell("decidim/announcement", announcement_body, callout_class: current_user.admin_terms_accepted? ? "success" : "warning" ) %>
|
|
2
4
|
|
|
3
5
|
<div class="item_show__header">
|
|
4
6
|
<h1 class="item_show__header-title">
|
|
5
|
-
<%= t("title"
|
|
7
|
+
<%= t(".title") %>
|
|
6
8
|
</h1>
|
|
7
9
|
</div>
|
|
8
10
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
|
+
|
|
2
3
|
<div class="card" id="area-types">
|
|
3
4
|
<div class="item_show__header">
|
|
4
5
|
<h1 class="item_show__header-title">
|
|
5
|
-
<%= t
|
|
6
|
+
<%= t(".title") %>
|
|
6
7
|
<% if allowed_to? :create, :area_type %>
|
|
7
8
|
<%= link_to t("actions.add", scope: "decidim.admin"), [:new, :area_type], class: "button button__sm button__secondary new" %>
|
|
8
9
|
<% end %>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
|
+
|
|
2
3
|
<div class="card" id="areas">
|
|
3
4
|
<div class="item_show__header">
|
|
4
5
|
<h1 class="item_show__header-title">
|
|
5
|
-
<%= t "
|
|
6
|
+
<%= t ".title" %>
|
|
6
7
|
<% if allowed_to? :create, :area %>
|
|
7
8
|
<%= link_to t("actions.add", scope: "decidim.admin"), new_area_path, class: "button button__sm button__secondary new" %>
|
|
8
9
|
<% end %>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
2
|
|
|
3
3
|
<div class="item_show__header">
|
|
4
4
|
<h1 class="item_show__header-title">
|
|
5
|
-
<%= t("
|
|
5
|
+
<%= t(".title") %>
|
|
6
6
|
</h1>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
2
|
|
|
3
3
|
<div class="card" id="attachment_collections">
|
|
4
4
|
<div class="item_show__header">
|
|
5
5
|
<h1 class="item_show__header-title">
|
|
6
|
-
<%= t("
|
|
6
|
+
<%= t(".title") %>
|
|
7
7
|
<% if allowed_to? :create, :attachment_collection %>
|
|
8
8
|
<%= link_to t("actions.attachment_collection.new", scope: "decidim.admin"), url_for(action: :new), class: "button button__sm button__secondary new" %>
|
|
9
9
|
<% end %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<% add_decidim_page_title(t("
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
2
|
<div class="item_show__header">
|
|
3
3
|
<h1 class="item_show__header-title">
|
|
4
|
-
<%= t("
|
|
4
|
+
<%= t(".title") %>
|
|
5
5
|
</h1>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
<% add_decidim_page_title(t(".
|
|
1
|
+
<% add_decidim_page_title(t(".title")) %>
|
|
2
|
+
|
|
2
3
|
<div class="card" id="attachments">
|
|
3
4
|
<div class="item_show__header">
|
|
4
5
|
<h1 class="item_show__header-title">
|
|
5
|
-
<%= t(".
|
|
6
|
+
<%= t(".title") %>
|
|
6
7
|
<% if allowed_to? :create, :attachment %>
|
|
7
8
|
<%= link_to t("actions.attachment.new", scope: "decidim.admin"), url_for(action: :new), class: "button button__sm button__secondary new" %>
|
|
8
9
|
<% end %>
|