decidim-admin 0.29.2 → 0.30.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.
Files changed (236) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/admin/multi_select_picker/show.erb +10 -0
  3. data/app/cells/decidim/admin/multi_select_picker_cell.rb +38 -0
  4. data/app/commands/decidim/admin/bulk_action.rb +92 -0
  5. data/app/commands/decidim/admin/bulk_block_users.rb +75 -0
  6. data/app/commands/decidim/admin/bulk_unblock_users.rb +66 -0
  7. data/app/commands/decidim/admin/bulk_unreport_users.rb +69 -0
  8. data/app/commands/decidim/admin/content_blocks/update_content_block.rb +1 -1
  9. data/app/commands/decidim/admin/create_participatory_space_private_user.rb +3 -1
  10. data/app/commands/decidim/admin/create_share_token.rb +39 -0
  11. data/app/commands/decidim/admin/create_taxonomy.rb +23 -0
  12. data/app/commands/decidim/admin/create_taxonomy_filter.rb +24 -0
  13. data/app/commands/decidim/admin/destroy_share_token.rb +22 -0
  14. data/app/commands/decidim/admin/destroy_taxonomy.rb +18 -0
  15. data/app/commands/decidim/admin/destroy_taxonomy_filter.rb +20 -0
  16. data/app/commands/decidim/admin/hide_menu_component.rb +37 -0
  17. data/app/commands/decidim/admin/hide_resource.rb +4 -3
  18. data/app/commands/decidim/admin/publish_all_participatory_space_private_users.rb +50 -0
  19. data/app/commands/decidim/admin/publish_component.rb +3 -0
  20. data/app/commands/decidim/admin/reorder_components.rb +47 -0
  21. data/app/commands/decidim/admin/reorder_taxonomies.rb +76 -0
  22. data/app/commands/decidim/admin/unhide_resource.rb +11 -3
  23. data/app/commands/decidim/admin/unpublish_all_participatory_space_private_users.rb +50 -0
  24. data/app/commands/decidim/admin/unreport_resource.rb +11 -3
  25. data/app/commands/decidim/admin/update_component_permissions.rb +53 -13
  26. data/app/commands/decidim/admin/update_participatory_space_private_user.rb +11 -0
  27. data/app/commands/decidim/admin/update_share_token.rb +24 -0
  28. data/app/commands/decidim/admin/update_taxonomy.rb +20 -0
  29. data/app/commands/decidim/admin/update_taxonomy_filter.rb +28 -0
  30. data/app/controllers/concerns/decidim/admin/component_taxonomies_helper.rb +19 -0
  31. data/app/controllers/concerns/decidim/admin/filterable.rb +15 -18
  32. data/app/controllers/concerns/decidim/admin/has_trashable_resources.rb +170 -0
  33. data/app/controllers/concerns/decidim/admin/needs_admin_tos_accepted.rb +2 -29
  34. data/app/controllers/concerns/decidim/admin/participatory_space_admin_context.rb +12 -2
  35. data/app/controllers/concerns/decidim/admin/taxonomies/filterable.rb +27 -0
  36. data/app/controllers/decidim/admin/application_controller.rb +1 -2
  37. data/app/controllers/decidim/admin/areas_controller.rb +1 -0
  38. data/app/controllers/decidim/admin/block_user_controller.rb +42 -0
  39. data/app/controllers/decidim/admin/component_permissions_controller.rb +2 -4
  40. data/app/controllers/decidim/admin/components_controller.rb +50 -9
  41. data/app/controllers/decidim/admin/concerns/has_private_users.rb +59 -2
  42. data/app/controllers/decidim/admin/global_moderations_controller.rb +4 -0
  43. data/app/controllers/decidim/admin/moderated_users_controller.rb +26 -0
  44. data/app/controllers/decidim/admin/moderations_controller.rb +18 -0
  45. data/app/controllers/decidim/admin/newsletters_controller.rb +50 -7
  46. data/app/controllers/decidim/admin/resource_permissions_controller.rb +1 -1
  47. data/app/controllers/decidim/admin/scopes_controller.rb +1 -0
  48. data/app/controllers/decidim/admin/share_tokens_controller.rb +109 -7
  49. data/app/controllers/decidim/admin/taxonomies_controller.rb +129 -0
  50. data/app/controllers/decidim/admin/taxonomy_filters_controller.rb +112 -0
  51. data/app/controllers/decidim/admin/taxonomy_filters_selector_controller.rb +81 -0
  52. data/app/controllers/decidim/admin/taxonomy_items_controller.rb +91 -0
  53. data/app/forms/concerns/decidim/has_taxonomy_form_attributes.rb +57 -0
  54. data/app/forms/decidim/admin/block_users_form.rb +21 -0
  55. data/app/forms/decidim/admin/import_example_form.rb +1 -1
  56. data/app/forms/decidim/admin/newsletter_form.rb +1 -1
  57. data/app/forms/decidim/admin/participatory_space_private_user_form.rb +5 -0
  58. data/app/forms/decidim/admin/selective_newsletter_form.rb +46 -11
  59. data/app/forms/decidim/admin/share_token_form.rb +55 -0
  60. data/app/forms/decidim/admin/taxonomy_filter_form.rb +85 -0
  61. data/app/forms/decidim/admin/taxonomy_form.rb +20 -0
  62. data/app/forms/decidim/admin/taxonomy_item_form.rb +54 -0
  63. data/app/helpers/decidim/admin/application_helper.rb +0 -1
  64. data/app/helpers/decidim/admin/bulk_actions_helper.rb +0 -31
  65. data/app/helpers/decidim/admin/moderations/reports_helper.rb +1 -1
  66. data/app/helpers/decidim/admin/moderations_helper.rb +1 -1
  67. data/app/helpers/decidim/admin/newsletters_helper.rb +57 -27
  68. data/app/helpers/decidim/admin/scopes_helper.rb +0 -6
  69. data/app/helpers/decidim/admin/search_form_helper.rb +1 -1
  70. data/app/helpers/decidim/admin/settings_helper.rb +85 -11
  71. data/app/jobs/decidim/admin/newsletter_job.rb +3 -1
  72. data/app/packs/entrypoints/decidim_admin.js +4 -0
  73. data/app/packs/src/decidim/admin/application.js +2 -0
  74. data/app/packs/src/decidim/admin/draggable-table.js +33 -0
  75. data/app/packs/src/decidim/admin/form.js +0 -1
  76. data/app/packs/src/decidim/admin/global_moderations.js +186 -0
  77. data/app/packs/src/decidim/admin/managed_moderated_users.js +186 -0
  78. data/app/packs/src/decidim/admin/newsletters.js +164 -82
  79. data/app/packs/src/decidim/admin/proposal_infinite_edit.js +3 -6
  80. data/app/packs/src/decidim/admin/sortable.js +28 -16
  81. data/app/packs/src/decidim/admin/taxonomy_filters.js +93 -0
  82. data/app/packs/stylesheets/decidim/admin/_component-show.scss +66 -5
  83. data/app/packs/stylesheets/decidim/admin/_legacy_foundation.scss +13 -0
  84. data/app/packs/stylesheets/decidim/admin/_select_picker.scss +20 -0
  85. data/app/packs/stylesheets/decidim/admin/_table-list.scss +22 -0
  86. data/app/packs/stylesheets/decidim/admin/_taxonomies.scss +74 -0
  87. data/app/packs/stylesheets/decidim/admin/application.scss +3 -0
  88. data/app/permissions/decidim/admin/permissions.rb +32 -1
  89. data/app/queries/decidim/admin/newsletter_recipients.rb +50 -14
  90. data/app/views/decidim/admin/areas/index.html.erb +3 -0
  91. data/app/views/decidim/admin/block_user/bulk_new.html.erb +45 -0
  92. data/app/views/decidim/admin/components/_actions.html.erb +50 -33
  93. data/app/views/decidim/admin/components/{_component.html.erb → _component_row.html.erb} +10 -5
  94. data/app/views/decidim/admin/components/_components_table.html.erb +18 -0
  95. data/app/views/decidim/admin/components/_form.html.erb +0 -12
  96. data/app/views/decidim/admin/components/_taxonomy_filters_drawer.html.erb +2 -0
  97. data/app/views/decidim/admin/components/_visibility_label.html.erb +9 -0
  98. data/app/views/decidim/admin/components/index.html.erb +12 -14
  99. data/app/views/decidim/admin/components/manage_trash.html.erb +11 -0
  100. data/app/views/decidim/admin/moderated_users/_bulk-actions.html.erb +6 -0
  101. data/app/views/decidim/admin/moderated_users/bulk_actions/_block.html.erb +20 -0
  102. data/app/views/decidim/admin/moderated_users/bulk_actions/_dropdown.html.erb +40 -0
  103. data/app/views/decidim/admin/moderated_users/bulk_actions/_unblock.html.erb +20 -0
  104. data/app/views/decidim/admin/moderated_users/bulk_actions/_unreport.html.erb +20 -0
  105. data/app/views/decidim/admin/moderated_users/index.html.erb +14 -6
  106. data/app/views/decidim/admin/moderations/_bulk-actions.html.erb +7 -0
  107. data/app/views/decidim/admin/moderations/_moderation-tr.html.erb +50 -0
  108. data/app/views/decidim/admin/moderations/_moderations-thead.html.erb +18 -0
  109. data/app/views/decidim/admin/moderations/bulk_actions/_dropdown.html.erb +43 -0
  110. data/app/views/decidim/admin/moderations/bulk_actions/_hide.html.erb +20 -0
  111. data/app/views/decidim/admin/moderations/bulk_actions/_unhide.html.erb +20 -0
  112. data/app/views/decidim/admin/moderations/bulk_actions/_unreport.html.erb +20 -0
  113. data/app/views/decidim/admin/moderations/index.html.erb +13 -81
  114. data/app/views/decidim/admin/newsletters/confirm_recipients.html.erb +64 -0
  115. data/app/views/decidim/admin/newsletters/select_recipients_to_deliver.html.erb +44 -20
  116. data/app/views/decidim/admin/participatory_space_private_users/_form.html.erb +6 -0
  117. data/app/views/decidim/admin/participatory_space_private_users/edit.html.erb +19 -0
  118. data/app/views/decidim/admin/participatory_space_private_users/index.html.erb +15 -1
  119. data/app/views/decidim/admin/resource_permissions/_options_form.html.erb +5 -0
  120. data/app/views/decidim/admin/resource_permissions/edit.html.erb +2 -2
  121. data/app/views/decidim/admin/scope_types/index.html.erb +3 -0
  122. data/app/views/decidim/admin/scopes/index.html.erb +3 -0
  123. data/app/views/decidim/admin/share_tokens/_form.html.erb +52 -0
  124. data/app/views/decidim/admin/share_tokens/edit.html.erb +33 -0
  125. data/app/views/decidim/admin/share_tokens/index.html.erb +47 -0
  126. data/app/views/decidim/admin/share_tokens/new.html.erb +69 -0
  127. data/app/views/decidim/admin/taxonomies/_filters.html.erb +19 -0
  128. data/app/views/decidim/admin/taxonomies/_form.html.erb +5 -0
  129. data/app/views/decidim/admin/taxonomies/_row.html.erb +40 -0
  130. data/app/views/decidim/admin/taxonomies/_row_children.html.erb +8 -0
  131. data/app/views/decidim/admin/taxonomies/_table.html.erb +86 -0
  132. data/app/views/decidim/admin/taxonomies/_taxonomy_actions.html.erb +15 -0
  133. data/app/views/decidim/admin/taxonomies/edit.html.erb +87 -0
  134. data/app/views/decidim/admin/taxonomies/index.html.erb +28 -0
  135. data/app/views/decidim/admin/taxonomies/new.html.erb +16 -0
  136. data/app/views/decidim/admin/taxonomy_filters/_check_boxes.html.erb +10 -0
  137. data/app/views/decidim/admin/taxonomy_filters/_form.html.erb +96 -0
  138. data/app/views/decidim/admin/taxonomy_filters/_table.html.erb +33 -0
  139. data/app/views/decidim/admin/taxonomy_filters/edit.html.erb +22 -0
  140. data/app/views/decidim/admin/taxonomy_filters/index.html.erb +26 -0
  141. data/app/views/decidim/admin/taxonomy_filters/new.html.erb +32 -0
  142. data/app/views/decidim/admin/taxonomy_filters_selector/_check_boxes.html.erb +7 -0
  143. data/app/views/decidim/admin/taxonomy_filters_selector/_component_table.html.erb +25 -0
  144. data/app/views/decidim/admin/taxonomy_filters_selector/_taxonomies_select.html.erb +16 -0
  145. data/app/views/decidim/admin/taxonomy_filters_selector/index.html.erb +1 -0
  146. data/app/views/decidim/admin/taxonomy_filters_selector/new.html.erb +27 -0
  147. data/app/views/decidim/admin/taxonomy_filters_selector/show.html.erb +18 -0
  148. data/app/views/decidim/admin/taxonomy_items/_form.html.erb +8 -0
  149. data/app/views/decidim/admin/taxonomy_items/edit.html.erb +12 -0
  150. data/app/views/decidim/admin/taxonomy_items/new.html.erb +12 -0
  151. data/app/views/layouts/decidim/admin/taxonomy_filters.html.erb +17 -0
  152. data/app/views/layouts/decidim/admin/taxonomy_filters_selector.html.erb +10 -0
  153. data/config/locales/ar.yml +45 -37
  154. data/config/locales/bg.yml +48 -51
  155. data/config/locales/bs-BA.yml +1 -27
  156. data/config/locales/ca.yml +301 -50
  157. data/config/locales/cs.yml +299 -46
  158. data/config/locales/de.yml +301 -50
  159. data/config/locales/el.yml +1 -50
  160. data/config/locales/en.yml +301 -50
  161. data/config/locales/es-MX.yml +298 -47
  162. data/config/locales/es-PY.yml +298 -47
  163. data/config/locales/es.yml +298 -47
  164. data/config/locales/eu.yml +302 -51
  165. data/config/locales/fi-plain.yml +298 -47
  166. data/config/locales/fi.yml +298 -47
  167. data/config/locales/fr-CA.yml +184 -47
  168. data/config/locales/fr.yml +184 -47
  169. data/config/locales/ga-IE.yml +0 -23
  170. data/config/locales/gl.yml +1 -46
  171. data/config/locales/hu.yml +1 -51
  172. data/config/locales/id-ID.yml +0 -24
  173. data/config/locales/is-IS.yml +0 -30
  174. data/config/locales/it.yml +2 -46
  175. data/config/locales/ja.yml +299 -50
  176. data/config/locales/kaa.yml +0 -7
  177. data/config/locales/ko.yml +0 -50
  178. data/config/locales/lb.yml +1 -46
  179. data/config/locales/lt.yml +1 -50
  180. data/config/locales/lv.yml +1 -28
  181. data/config/locales/nl.yml +1 -46
  182. data/config/locales/no.yml +1 -46
  183. data/config/locales/pl.yml +3 -51
  184. data/config/locales/pt-BR.yml +38 -50
  185. data/config/locales/pt.yml +29 -49
  186. data/config/locales/ro-RO.yml +38 -52
  187. data/config/locales/ru.yml +1 -24
  188. data/config/locales/sk.yml +1 -28
  189. data/config/locales/sl.yml +0 -5
  190. data/config/locales/sq-AL.yml +0 -22
  191. data/config/locales/sr-CS.yml +1 -27
  192. data/config/locales/sv.yml +296 -46
  193. data/config/locales/th-TH.yml +0 -10
  194. data/config/locales/tr-TR.yml +1 -44
  195. data/config/locales/uk.yml +0 -23
  196. data/config/locales/zh-CN.yml +0 -38
  197. data/config/locales/zh-TW.yml +1 -50
  198. data/config/routes.rb +13 -12
  199. data/decidim-admin.gemspec +1 -1
  200. data/lib/decidim/admin/engine.rb +2 -1
  201. data/lib/decidim/admin/import/creator.rb +2 -6
  202. data/lib/decidim/admin/import/readers/json.rb +1 -1
  203. data/lib/decidim/admin/menu.rb +9 -1
  204. data/lib/decidim/admin/search_form_builder.rb +1 -1
  205. data/lib/decidim/admin/test/destroy_admin_examples.rb +2 -2
  206. data/lib/decidim/admin/test/filterable_examples.rb +100 -9
  207. data/lib/decidim/admin/test/forms/attachment_collection_form_examples.rb +1 -1
  208. data/lib/decidim/admin/test/forms/attachment_form_examples.rb +1 -1
  209. data/lib/decidim/admin/test/invite_participatory_space_admins_shared_examples.rb +2 -4
  210. data/lib/decidim/admin/test/manage_component_permissions_examples.rb +5 -5
  211. data/lib/decidim/admin/test/manage_hide_content_examples.rb +0 -1
  212. data/lib/decidim/admin/test/manage_moderations_examples.rb +3 -3
  213. data/lib/decidim/admin/test/manage_resource_soft_deletion_examples.rb +113 -0
  214. data/lib/decidim/admin/test/manage_taxonomy_filters_examples.rb +127 -0
  215. data/lib/decidim/admin/test/taxonomy_filters_examples.rb +32 -0
  216. data/lib/decidim/admin/test.rb +3 -1
  217. data/lib/decidim/admin/version.rb +1 -1
  218. metadata +103 -29
  219. data/app/commands/decidim/admin/create_category.rb +0 -15
  220. data/app/commands/decidim/admin/destroy_category.rb +0 -15
  221. data/app/commands/decidim/admin/destroy_component.rb +0 -19
  222. data/app/commands/decidim/admin/update_category.rb +0 -11
  223. data/app/controllers/decidim/admin/categories_controller.rb +0 -98
  224. data/app/forms/decidim/admin/category_form.rb +0 -32
  225. data/app/helpers/decidim/admin/resource_scope_helper.rb +0 -52
  226. data/app/packs/src/decidim/admin/scope_picker_enabler.component.js +0 -12
  227. data/app/views/decidim/admin/categories/_form.html.erb +0 -18
  228. data/app/views/decidim/admin/categories/edit.html.erb +0 -19
  229. data/app/views/decidim/admin/categories/index.html.erb +0 -65
  230. data/app/views/decidim/admin/categories/new.html.erb +0 -19
  231. data/app/views/decidim/admin/share_tokens/_share_tokens.html.erb +0 -45
  232. data/lib/decidim/admin/test/commands/create_category_examples.rb +0 -74
  233. data/lib/decidim/admin/test/commands/destroy_category_examples.rb +0 -83
  234. data/lib/decidim/admin/test/commands/update_category_examples.rb +0 -76
  235. data/lib/decidim/admin/test/forms/category_form_examples.rb +0 -70
  236. data/lib/decidim/admin/test/manage_categories_examples.rb +0 -128
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module HasTaxonomyFormAttributes
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ attribute :taxonomies, Array[Integer]
9
+
10
+ validate :taxonomies_belong_to_current_organization
11
+
12
+ # Returns the participatory space manifest for search the available filters (ie: participatory_processes, assemblies, etc)
13
+ # To implement where this concern is included.
14
+ def participatory_space_manifest
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def taxonomizations
19
+ @taxonomizations ||= compact_taxonomies.map do |taxonomy_id|
20
+ Decidim::Taxonomization.new(taxonomy_id:)
21
+ end
22
+ end
23
+
24
+ def taxonomy_filters
25
+ @taxonomy_filters ||= if defined?(current_component) && current_component&.settings.respond_to?(:taxonomy_filters)
26
+ all_taxonomy_filters.where(id: current_component.settings.taxonomy_filters)
27
+ else
28
+ all_taxonomy_filters.for_manifest(participatory_space_manifest)
29
+ end
30
+ end
31
+
32
+ def all_taxonomy_filters
33
+ @all_taxonomy_filters ||= TaxonomyFilter.where(root_taxonomy: root_taxonomies)
34
+ end
35
+
36
+ def root_taxonomies
37
+ @root_taxonomies ||= current_organization.taxonomies.roots
38
+ end
39
+
40
+ private
41
+
42
+ def taxonomies_belong_to_current_organization
43
+ return if compact_taxonomies.empty?
44
+
45
+ Decidim::Taxonomy.where(id: compact_taxonomies).find_each do |taxonomy|
46
+ next if taxonomy.decidim_organization_id == current_organization.id
47
+
48
+ errors.add(:taxonomies, :invalid)
49
+ end
50
+ end
51
+
52
+ def compact_taxonomies
53
+ @compact_taxonomies ||= taxonomies.compact
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A form object used to block users or user groups on the admin dashboard.
6
+ class BlockUsersForm < Form
7
+ attribute :user_ids, Array[Integer]
8
+ attribute :justification, String
9
+ attribute :hide, Boolean, default: false
10
+
11
+ validates :justification, presence: true, length: { minimum: UserBlock::MINIMUM_JUSTIFICATION_LENGTH }
12
+
13
+ def users
14
+ @users ||= Decidim::UserBaseEntity.where(
15
+ id: user_ids,
16
+ organization: current_organization
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
@@ -35,7 +35,7 @@ module Decidim
35
35
  end
36
36
 
37
37
  def reader
38
- @reader ||= reader_klass ? reader_klass.new("/dev/null") : nil
38
+ @reader ||= reader_klass ? reader_klass.new(File::NULL) : nil
39
39
  end
40
40
 
41
41
  def reader_klass
@@ -12,7 +12,7 @@ module Decidim
12
12
  validates :subject, translatable_presence: true
13
13
 
14
14
  def map_model(content_block)
15
- super(content_block)
15
+ super
16
16
  self.subject = newsletter_for(content_block).try(:subject)
17
17
  end
18
18
 
@@ -6,10 +6,15 @@ module Decidim
6
6
  # admin dashboard.
7
7
  #
8
8
  class ParticipatorySpacePrivateUserForm < Form
9
+ include TranslatableAttributes
10
+
9
11
  mimic :participatory_space_private_user
10
12
 
11
13
  attribute :name, String
12
14
  attribute :email, String
15
+ attribute :published, Boolean
16
+
17
+ translatable_attribute :role, String
13
18
 
14
19
  validates :name, :email, presence: true
15
20
 
@@ -7,33 +7,33 @@ module Decidim
7
7
  mimic :newsletter
8
8
 
9
9
  attribute :participatory_space_types, Array[SelectiveNewsletterParticipatorySpaceTypeForm]
10
- attribute :scope_ids, Array
10
+ attribute :verification_types, Array[String]
11
11
  attribute :send_to_all_users, Boolean
12
+ attribute :send_to_verified_users, Boolean
12
13
  attribute :send_to_participants, Boolean
13
14
  attribute :send_to_followers, Boolean
15
+ attribute :send_to_private_members, Boolean
14
16
 
15
- validates :send_to_all_users, presence: true, unless: ->(form) { form.send_to_participants.present? || form.send_to_followers.present? }
16
- validates :send_to_followers, presence: true, if: ->(form) { form.send_to_all_users.blank? && form.send_to_participants.blank? }
17
- validates :send_to_participants, presence: true, if: ->(form) { form.send_to_all_users.blank? && form.send_to_followers.blank? }
17
+ validates :send_to_all_users, presence: true, unless: :other_groups_selected_for_all_users?
18
+ validates :send_to_verified_users, presence: true, unless: :other_groups_selected_for_verified_users?
19
+ validates :send_to_followers, presence: true, if: :only_followers_selected?
20
+ validates :send_to_participants, presence: true, if: :only_participants_selected?
21
+ validates :send_to_private_members, presence: true, if: :only_private_members_selected?
18
22
 
19
23
  validate :at_least_one_participatory_space_selected
20
24
 
21
- def map_model(_newsletter)
25
+ def map_model(newsletter)
22
26
  self.participatory_space_types = Decidim.participatory_space_manifests.map do |manifest|
23
27
  SelectiveNewsletterParticipatorySpaceTypeForm.from_model(manifest:)
24
28
  end
25
- end
26
29
 
27
- # Make sure the empty scope is not passed because then some logic could
28
- # assume erroneously that some scope is selected.
29
- def scope_ids
30
- super.select(&:presence)
30
+ self.verification_types = newsletter.organization.available_authorizations
31
31
  end
32
32
 
33
33
  private
34
34
 
35
35
  def at_least_one_participatory_space_selected
36
- return if send_to_all_users && current_user.admin?
36
+ return if (send_to_all_users || send_to_verified_users) && current_user.admin?
37
37
 
38
38
  errors.add(:base, :at_least_one_space) if spaces_selected.blank?
39
39
  end
@@ -44,6 +44,41 @@ module Decidim
44
44
  [type.manifest_name, spaces] if spaces.present?
45
45
  end.compact
46
46
  end
47
+
48
+ def other_groups_selected_for_all_users?
49
+ send_to_verified_users.present? ||
50
+ send_to_participants.present? ||
51
+ send_to_followers.present? ||
52
+ send_to_private_members.present?
53
+ end
54
+
55
+ def other_groups_selected_for_verified_users?
56
+ send_to_all_users.present? ||
57
+ send_to_participants.present? ||
58
+ send_to_followers.present? ||
59
+ send_to_private_members.present?
60
+ end
61
+
62
+ def only_followers_selected?
63
+ send_to_all_users.blank? &&
64
+ send_to_participants.blank? &&
65
+ send_to_private_members.blank? &&
66
+ send_to_verified_users.blank?
67
+ end
68
+
69
+ def only_participants_selected?
70
+ send_to_all_users.blank? &&
71
+ send_to_followers.blank? &&
72
+ send_to_private_members.blank? &&
73
+ send_to_verified_users.blank?
74
+ end
75
+
76
+ def only_private_members_selected?
77
+ send_to_all_users.blank? &&
78
+ send_to_followers.blank? &&
79
+ send_to_participants.blank? &&
80
+ send_to_verified_users.blank?
81
+ end
47
82
  end
48
83
  end
49
84
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ class ShareTokenForm < Decidim::Form
6
+ mimic :share_token
7
+
8
+ attribute :token, String
9
+ attribute :automatic_token, Boolean, default: true
10
+ attribute :expires_at, Decidim::Attributes::TimeWithZone
11
+ attribute :no_expiration, Boolean, default: true
12
+ attribute :registered_only, Boolean, default: false
13
+
14
+ validates :token, presence: true, if: ->(form) { form.automatic_token.blank? }
15
+ validate :token_uniqueness, if: ->(form) { form.automatic_token.blank? }
16
+
17
+ validates_format_of :token, with: /\A[a-zA-Z0-9_-]+\z/, allow_blank: true
18
+ validates :expires_at, presence: true, if: ->(form) { form.no_expiration.blank? }
19
+
20
+ def map_model(model)
21
+ self.no_expiration = model.expires_at.blank?
22
+ end
23
+
24
+ def token
25
+ super.strip.upcase.gsub(/\s+/, "-") if super.present?
26
+ end
27
+
28
+ def expires_at
29
+ return nil if no_expiration.present?
30
+
31
+ super
32
+ end
33
+
34
+ def token_for
35
+ context[:resource]
36
+ end
37
+
38
+ def organization
39
+ context[:current_organization]
40
+ end
41
+
42
+ def user
43
+ context[:current_user]
44
+ end
45
+
46
+ private
47
+
48
+ def token_uniqueness
49
+ return unless Decidim::ShareToken.where(organization:, token_for:, token:).where.not(id:).any?
50
+
51
+ errors.add(:token, :taken)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A form object to create or update areas.
6
+ class TaxonomyFilterForm < Form
7
+ include TranslatableAttributes
8
+ Item = Struct.new(:name, :value, :children)
9
+ Manifest = Struct.new(:id, :name)
10
+
11
+ attribute :root_taxonomy_id, Integer
12
+ translatable_attribute :name, String
13
+ translatable_attribute :internal_name, String
14
+ attribute :participatory_space_manifests, Array, default: []
15
+ attribute :taxonomy_items, Array
16
+
17
+ mimic :taxonomy_filter
18
+
19
+ validates :root_taxonomy_id, :taxonomy_items, presence: true
20
+ validate :valid_taxonomy_items
21
+
22
+ def map_model(model)
23
+ self.root_taxonomy_id = model.root_taxonomy_id
24
+ self.taxonomy_items = model.filter_items.map(&:taxonomy_item_id)
25
+ self.name = {} if model.attributes["name"]&.compact_blank.blank?
26
+ self.internal_name = {} if model.attributes["internal_name"]&.compact_blank.blank?
27
+ end
28
+
29
+ def taxonomy_items
30
+ super.compact_blank
31
+ end
32
+
33
+ def participatory_space_manifests
34
+ super.compact_blank
35
+ end
36
+
37
+ def filter_items
38
+ taxonomy_items.map do |item|
39
+ Decidim::TaxonomyFilterItem.new(taxonomy_item_id: item)
40
+ end
41
+ end
42
+
43
+ def items_collection
44
+ return [] unless root_taxonomy
45
+
46
+ @items_collection ||= map_items_collection(root_taxonomy)
47
+ end
48
+
49
+ def root_taxonomy
50
+ @root_taxonomy ||= current_organization.taxonomies.find_by(id: root_taxonomy_id)
51
+ end
52
+
53
+ def available_participatory_space_manifests
54
+ @participatory_space_manifests ||= Decidim.participatory_space_manifests.map do |manifest|
55
+ Manifest.new(
56
+ id: manifest.name.to_s,
57
+ name: I18n.t("decidim.admin.taxonomy_filters.space_filter_for.#{manifest.name}")
58
+ )
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def map_items_collection(taxonomy)
65
+ taxonomy.children.map do |item|
66
+ Item.new(
67
+ name: translated_attribute(item.name),
68
+ value: item.id,
69
+ children: map_items_collection(item)
70
+ )
71
+ end
72
+ end
73
+
74
+ def valid_taxonomy_items
75
+ return if taxonomy_items.all? do |item|
76
+ next unless root_taxonomy
77
+
78
+ root_taxonomy.all_children.map(&:id).include?(item.to_i)
79
+ end
80
+
81
+ errors.add(:taxonomy_items, :invalid)
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A form object to be used when creating or updating a taxonomy.
6
+ class TaxonomyForm < Decidim::Form
7
+ include Decidim::TranslatableAttributes
8
+
9
+ mimic :taxonomy
10
+
11
+ translatable_attribute :name, String
12
+
13
+ validates :name, translatable_presence: true
14
+
15
+ alias organization current_organization
16
+
17
+ def parent_id = nil
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Admin
5
+ # A form object to be used when creating or updating a taxonomy.
6
+ class TaxonomyItemForm < Decidim::Form
7
+ include Decidim::TranslatableAttributes
8
+
9
+ mimic :taxonomy
10
+
11
+ # we do not use "name" here to avoid collisions when using foundation tabs for multilingual fields tabs
12
+ # as this is used in a modal and the name identifier is used for the root taxonomy
13
+ translatable_attribute :item_name, String
14
+ attribute :parent_id, Integer
15
+
16
+ validates :item_name, translatable_presence: true
17
+ validate :validate_parent_id_within_same_root_taxonomy
18
+
19
+ alias name item_name
20
+
21
+ def map_model(model)
22
+ self.item_name = model.name
23
+ end
24
+
25
+ def self.from_params(params, additional_params = {})
26
+ additional_params[:taxonomy] = {}
27
+ if params[:taxonomy]
28
+ params[:taxonomy].each do |key, value|
29
+ additional_params[:taxonomy][key[8..]] = value if key.start_with?("item_name_")
30
+ end
31
+ end
32
+ super
33
+ end
34
+
35
+ def validate_parent_id_within_same_root_taxonomy
36
+ if parent
37
+ current_root_taxonomy = if parent.root?
38
+ parent
39
+ else
40
+ parent.root_taxonomy
41
+ end
42
+
43
+ errors.add(:parent_id, :invalid) unless parent.root_taxonomy.id == current_root_taxonomy.id
44
+ else
45
+ errors.add(:parent_id, :invalid)
46
+ end
47
+ end
48
+
49
+ def parent
50
+ @parent ||= Decidim::Taxonomy.find_by(id: parent_id)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -13,7 +13,6 @@ module Decidim
13
13
  include Decidim::MapHelper
14
14
  include Decidim::Admin::LogRenderHelper
15
15
  include Decidim::Admin::UserRolesHelper
16
- include Decidim::Admin::ResourceScopeHelper
17
16
  include Decidim::Admin::SearchFormHelper
18
17
 
19
18
  # Public: Overwrites the `cell` helper method to automatically set some
@@ -3,37 +3,6 @@
3
3
  module Decidim
4
4
  module Admin
5
5
  module BulkActionsHelper
6
- # Public: Generates a select field with the categories. Only leaf categories can be set as selected.
7
- #
8
- # categories - A collection of categories.
9
- #
10
- # Returns a String.
11
- def bulk_categories_select(collection)
12
- categories = bulk_categories_for_select collection
13
- prompt = t("decidim.proposals.admin.proposals.index.change_category")
14
- select(:category, :id, options_for_select(categories, selected: []), prompt:)
15
- end
16
-
17
- def bulk_categories_for_select(scope)
18
- sorted_main_categories = scope.first_class.includes(:subcategories).sort_by do |category|
19
- translated_attribute(category.name, category.participatory_space.organization)
20
- end
21
-
22
- sorted_main_categories.flat_map do |category|
23
- parent = [[translated_attribute(category.name, category.participatory_space.organization), category.id]]
24
-
25
- sorted_subcategories = category.subcategories.sort_by do |subcategory|
26
- translated_attribute(subcategory.name, subcategory.participatory_space.organization)
27
- end
28
-
29
- sorted_subcategories.each do |subcategory|
30
- parent << ["- #{translated_attribute(subcategory.name, subcategory.participatory_space.organization)}", subcategory.id]
31
- end
32
-
33
- parent
34
- end
35
- end
36
-
37
6
  # Public: Generates a select field with the components.
38
7
  #
39
8
  # siblings - A collection of components.
@@ -14,7 +14,7 @@ module Decidim
14
14
  def reportable_author_name(reportable)
15
15
  reportable_authors = reportable.try(:authors) || [reportable.try(:normalized_author)]
16
16
  content_tag :ul, class: "reportable-authors" do
17
- reportable_authors.select(&:present?).map do |author|
17
+ reportable_authors.compact_blank.map do |author|
18
18
  case author
19
19
  when User
20
20
  content_tag :li do
@@ -13,7 +13,7 @@ module Decidim
13
13
 
14
14
  attribute_value
15
15
  end
16
- reportable_content.filter(&:present?).join(". ").truncate(options.fetch(:limit, 100))
16
+ reportable_content.compact_blank.join(". ").truncate(options.fetch(:limit, 100))
17
17
  end
18
18
  end
19
19
 
@@ -4,6 +4,13 @@ module Decidim
4
4
  module Admin
5
5
  # This module includes helpers to manage newsletters in admin layout
6
6
  module NewslettersHelper
7
+ def find_verification_types_for_select(organization)
8
+ available_verifications = organization.available_authorizations
9
+ available_verifications.map do |verification_type|
10
+ [t("decidim.authorization_handlers.#{verification_type}.name"), verification_type]
11
+ end
12
+ end
13
+
7
14
  def participatory_spaces_for_select(form_object)
8
15
  content_tag :div do
9
16
  @form.participatory_space_types.each do |space_type|
@@ -17,22 +24,32 @@ module Decidim
17
24
 
18
25
  html = ""
19
26
  form_object.fields_for "participatory_space_types[#{space_type.manifest_name}]", space_type do |ff|
27
+ html += participatory_space_title(space_type)
20
28
  html += ff.hidden_field :manifest_name, value: space_type.manifest_name
21
29
  html += select_tag_participatory_spaces(space_type.manifest_name, spaces_for_select(space_type.manifest_name.to_sym), ff)
22
30
  end
23
31
  html.html_safe
24
32
  end
25
33
 
34
+ def participatory_space_title(space_type)
35
+ return unless space_type
36
+
37
+ content_tag :h4 do
38
+ t("activerecord.models.decidim/#{space_type.manifest_name.singularize}.other")
39
+ end
40
+ end
41
+
26
42
  def select_tag_participatory_spaces(manifest_name, spaces, child_form)
27
43
  return unless spaces
28
44
 
29
- content_tag :div, class: "#{manifest_name}-block spaces-block-tag cell small-12 medium-6" do
30
- child_form.select :ids, options_for_select(spaces),
31
- { prompt: t("select_recipients_to_deliver.none", scope: "decidim.admin.newsletters"),
32
- label: t("activerecord.models.decidim/#{manifest_name.singularize}.other"),
33
- include_hidden: false },
34
- multiple: true, size: [spaces.size, 10].min, class: "chosen-select"
35
- end
45
+ raw(cell("decidim/admin/multi_select_picker", nil, context: {
46
+ select_id: "#{manifest_name}-spaces-select",
47
+ field_name: "#{child_form.object_name}[ids][]",
48
+ options_for_select: spaces,
49
+ selected_values: selected_options(:participatory_space_types)[manifest_name] || [],
50
+ placeholder: t("select_recipients_to_deliver.select_#{manifest_name}", scope: "decidim.admin.newsletters"),
51
+ class: "mb-2"
52
+ }))
36
53
  end
37
54
 
38
55
  def spaces_for_select(manifest_name)
@@ -45,21 +62,35 @@ module Decidim
45
62
  def selective_newsletter_to(newsletter)
46
63
  return content_tag(:strong, t("index.not_sent", scope: "decidim.admin.newsletters"), class: "text-warning") unless newsletter.sent?
47
64
  return content_tag(:strong, t("index.all_users", scope: "decidim.admin.newsletters"), class: "text-success") if newsletter.sent? && newsletter.extended_data.blank?
65
+ return sent_to_verified_users(newsletter) if newsletter.sent_to_verified_users?
48
66
 
49
67
  content_tag :div do
50
68
  concat sent_to_users newsletter
51
69
  concat sent_to_spaces newsletter
52
- concat sent_to_scopes newsletter
53
70
  end
54
71
  end
55
72
 
56
73
  def sent_to_users(newsletter)
57
74
  content_tag :p, style: "margin-bottom:0;" do
58
75
  concat content_tag(:strong, t("index.has_been_sent_to", scope: "decidim.admin.newsletters"), class: "text-success")
59
- concat content_tag(:strong, t("index.all_users", scope: "decidim.admin.newsletters")) if newsletter.sended_to_all_users?
60
- concat content_tag(:strong, t("index.followers", scope: "decidim.admin.newsletters")) if newsletter.sended_to_followers?
61
- concat t("index.and", scope: "decidim.admin.newsletters") if newsletter.sended_to_followers? && newsletter.sended_to_participants?
62
- concat content_tag(:strong, t("index.participants", scope: "decidim.admin.newsletters")) if newsletter.sended_to_participants?
76
+
77
+ recipients = []
78
+
79
+ recipients << content_tag(:strong, t("index.all_users", scope: "decidim.admin.newsletters")) if newsletter.sent_to_all_users?
80
+ recipients << content_tag(:strong, t("index.verified_users", scope: "decidim.admin.newsletters")) if newsletter.sent_to_verified_users?
81
+ recipients << content_tag(:strong, t("index.followers", scope: "decidim.admin.newsletters")) if newsletter.sent_to_followers?
82
+ recipients << content_tag(:strong, t("index.participants", scope: "decidim.admin.newsletters")) if newsletter.sent_to_participants?
83
+ recipients << content_tag(:strong, t("index.private_members", scope: "decidim.admin.newsletters")) if newsletter.sent_to_private_members?
84
+
85
+ concat recipients.join(t("index.and", scope: "decidim.admin.newsletters")).html_safe
86
+ end
87
+ end
88
+
89
+ def sent_to_verified_users(newsletter)
90
+ content_tag :p, style: "margin-bottom:0;" do
91
+ concat content_tag(:strong, t("index.has_been_sent_to", scope: "decidim.admin.newsletters"), class: "text-success")
92
+ concat content_tag(:strong, t("index.verified_users", scope: "decidim.admin.newsletters"))
93
+ concat content_tag(:p, t("index.verification_types", scope: "decidim.admin.newsletters", types: selected_verification_types(newsletter)))
63
94
  end
64
95
  end
65
96
 
@@ -68,12 +99,14 @@ module Decidim
68
99
  newsletter.sent_to_participatory_spaces.try(:each) do |type|
69
100
  next if type["ids"].blank?
70
101
 
102
+ ids = parse_ids(type["ids"])
103
+
71
104
  html += t("index.segmented_to", scope: "decidim.admin.newsletters", subject: t("activerecord.models.decidim/#{type["manifest_name"].singularize}.other"))
72
- if type["ids"].include?("all")
105
+ if ids.include?("all")
73
106
  html += "<strong> #{t("index.all", scope: "decidim.admin.newsletters")} </strong>"
74
107
  else
75
108
  Decidim.find_participatory_space_manifest(type["manifest_name"].to_sym)
76
- .participatory_spaces.call(current_organization).where(id: type["ids"]).each do |space|
109
+ .participatory_spaces.call(current_organization).where(id: ids).each do |space|
77
110
  html += "<strong>#{decidim_escape_translated(space.title)}</strong>"
78
111
  end
79
112
  end
@@ -83,19 +116,6 @@ module Decidim
83
116
  html.html_safe
84
117
  end
85
118
 
86
- def sent_to_scopes(newsletter)
87
- content_tag :p, style: "margin-bottom:0;" do
88
- concat t("index.segmented_to", scope: "decidim.admin.newsletters", subject: nil)
89
- if newsletter.sent_scopes.any?
90
- newsletter.sent_scopes.each do |scope|
91
- concat content_tag(:strong, decidim_escape_translated(scope.name).to_s)
92
- end
93
- else
94
- concat content_tag(:strong, t("index.no_scopes", scope: "decidim.admin.newsletters"))
95
- end
96
- end
97
- end
98
-
99
119
  def organization_participatory_space(manifest_name)
100
120
  @organization_participatory_spaces ||= {}
101
121
  @organization_participatory_spaces[manifest_name] ||= Decidim
@@ -144,6 +164,16 @@ module Decidim
144
164
  body:
145
165
  }
146
166
  end
167
+
168
+ def parse_ids(ids)
169
+ ids.size == 1 && ids.first.is_a?(String) ? ids.first.split.map(&:strip) : ids
170
+ end
171
+
172
+ def selected_verification_types(newsletter)
173
+ newsletter.sent_to_users_with_verification_types&.map do |type|
174
+ I18n.t("decidim.authorization_handlers.#{type}.name")
175
+ end&.join(", ")
176
+ end
147
177
  end
148
178
  end
149
179
  end
@@ -32,12 +32,6 @@ module Decidim
32
32
  Option.new(scope_type.id, translated_attribute(scope_type.name))
33
33
  end
34
34
  end
35
-
36
- def organization_scope_depths(organization = current_organization)
37
- organization.scope_types.map do |scope_type|
38
- Option.new(scope_type.id, translated_attribute(scope_type.name))
39
- end.reverse
40
- end
41
35
  end
42
36
  end
43
37
  end
@@ -12,7 +12,7 @@ module Decidim
12
12
  def search_form_for(record, options = {}, &)
13
13
  options[:builder] ||= SearchFormBuilder
14
14
 
15
- super(record, options, &)
15
+ super
16
16
  end
17
17
  end
18
18
  end