decidim-core 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (275) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +3 -0
  3. data/app/assets/javascripts/decidim/social_share.js +2 -0
  4. data/app/assets/stylesheets/decidim/extras/_social_share.css.scss +36 -0
  5. data/app/assets/stylesheets/decidim/modules/_input-gallery.scss +24 -0
  6. data/app/assets/stylesheets/decidim/modules/_navbar.scss +1 -1
  7. data/app/cells/decidim/activities_cell.rb +13 -8
  8. data/app/cells/decidim/activity_cell.rb +19 -5
  9. data/app/cells/decidim/address/details.erb +2 -2
  10. data/app/cells/decidim/amendable/amenders_list/show.erb +1 -1
  11. data/app/cells/decidim/amendable/amenders_list_cell.rb +5 -1
  12. data/app/cells/decidim/amendable/announcement_cell.rb +22 -9
  13. data/app/cells/decidim/amendable/wizard_step_form_cell.rb +121 -0
  14. data/app/cells/decidim/announcement_cell.rb +1 -0
  15. data/app/cells/decidim/author_cell.rb +7 -0
  16. data/app/cells/decidim/card_m_cell.rb +3 -1
  17. data/app/cells/decidim/coauthorships_cell.rb +3 -1
  18. data/app/cells/decidim/collapsible_authors_cell.rb +1 -0
  19. data/app/cells/decidim/collapsible_list_cell.rb +1 -0
  20. data/app/cells/decidim/content_blocks/highlighted_content_banner_cell.rb +1 -0
  21. data/app/cells/decidim/content_blocks/last_activity_cell.rb +3 -2
  22. data/app/cells/decidim/content_blocks/metrics_cell.rb +1 -0
  23. data/app/cells/decidim/content_blocks/stats_cell.rb +1 -0
  24. data/app/cells/decidim/content_blocks/sub_hero_cell.rb +1 -0
  25. data/app/cells/decidim/diff_cell.rb +1 -1
  26. data/app/cells/decidim/fingerprint/show.erb +1 -1
  27. data/app/cells/decidim/follow_button_cell.rb +3 -0
  28. data/app/cells/decidim/members_cell.rb +1 -0
  29. data/app/cells/decidim/notifications/show.erb +1 -1
  30. data/app/cells/decidim/profile_cell.rb +1 -0
  31. data/app/cells/decidim/profile_sidebar_cell.rb +4 -0
  32. data/app/cells/decidim/search_results_cell.rb +1 -0
  33. data/app/cells/decidim/search_results_section/show.erb +1 -1
  34. data/app/cells/decidim/tos_page_cell.rb +1 -0
  35. data/app/cells/decidim/user_group_pending_invitations_list_cell.rb +1 -0
  36. data/app/cells/decidim/user_group_pending_requests_list_cell.rb +1 -0
  37. data/app/cells/decidim/wizard_step_form/wizard_aside.erb +14 -0
  38. data/app/cells/decidim/wizard_step_form/wizard_header.erb +18 -0
  39. data/app/cells/decidim/wizard_step_form_cell.rb +112 -0
  40. data/app/commands/decidim/amendable/accept.rb +1 -1
  41. data/app/commands/decidim/amendable/create_draft.rb +70 -0
  42. data/app/commands/decidim/amendable/destroy_draft.rb +40 -0
  43. data/app/commands/decidim/amendable/promote.rb +13 -11
  44. data/app/commands/decidim/amendable/publish_draft.rb +76 -0
  45. data/app/commands/decidim/amendable/update_draft.rb +54 -0
  46. data/app/commands/decidim/amendable/withdraw.rb +31 -15
  47. data/app/commands/decidim/create_follow.rb +1 -0
  48. data/app/commands/decidim/create_omniauth_registration.rb +22 -4
  49. data/app/commands/decidim/create_registration.rb +5 -0
  50. data/app/commands/decidim/delete_follow.rb +1 -0
  51. data/app/commands/decidim/search.rb +1 -0
  52. data/app/controllers/concerns/decidim/action_authorization.rb +2 -0
  53. data/app/controllers/concerns/decidim/amendments_controller.rb +148 -28
  54. data/app/controllers/concerns/decidim/devise_controllers.rb +3 -2
  55. data/app/controllers/concerns/decidim/force_authentication.rb +38 -0
  56. data/app/controllers/concerns/decidim/impersonate_users.rb +1 -0
  57. data/app/controllers/concerns/decidim/locale_switcher.rb +44 -17
  58. data/app/controllers/concerns/decidim/needs_tos_accepted.rb +8 -0
  59. data/app/controllers/concerns/decidim/orderable.rb +36 -0
  60. data/app/controllers/concerns/decidim/participatory_space_context.rb +2 -0
  61. data/app/controllers/concerns/decidim/safe_redirect.rb +24 -0
  62. data/app/controllers/decidim/application_controller.rb +19 -2
  63. data/app/controllers/decidim/devise/confirmations_controller.rb +6 -0
  64. data/app/controllers/decidim/devise/invitations_controller.rb +8 -4
  65. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +4 -1
  66. data/app/controllers/decidim/errors_controller.rb +3 -0
  67. data/app/controllers/decidim/follows_controller.rb +2 -2
  68. data/app/controllers/decidim/messaging/conversations_controller.rb +2 -2
  69. data/app/controllers/decidim/profiles_controller.rb +4 -1
  70. data/app/controllers/decidim/scopes_controller.rb +16 -4
  71. data/app/events/decidim/amendable/amendment_base_event.rb +4 -0
  72. data/app/forms/decidim/account_form.rb +1 -1
  73. data/app/forms/decidim/amendable/create_form.rb +3 -19
  74. data/app/forms/decidim/amendable/edit_form.rb +22 -0
  75. data/app/forms/decidim/amendable/form.rb +42 -20
  76. data/app/forms/decidim/amendable/promote_form.rb +4 -7
  77. data/app/forms/decidim/amendable/publish_form.rb +21 -0
  78. data/app/forms/decidim/amendable/reject_form.rb +1 -1
  79. data/app/forms/decidim/amendable/review_form.rb +9 -4
  80. data/app/forms/decidim/invite_user_form.rb +1 -0
  81. data/app/forms/decidim/notifications_settings_form.rb +1 -0
  82. data/app/forms/decidim/registration_form.rb +4 -3
  83. data/app/forms/decidim/user_group_form.rb +1 -0
  84. data/app/forms/decidim/user_interests_form.rb +1 -0
  85. data/app/helpers/decidim/amendments_helper.rb +33 -19
  86. data/app/helpers/decidim/cells_helper.rb +2 -0
  87. data/app/helpers/decidim/layout_helper.rb +1 -0
  88. data/app/helpers/decidim/map_helper.rb +1 -1
  89. data/app/helpers/decidim/meta_tags_helper.rb +1 -0
  90. data/app/helpers/decidim/resource_reference_helper.rb +1 -0
  91. data/app/jobs/decidim/event_publisher_job.rb +60 -0
  92. data/app/jobs/decidim/metric_job.rb +1 -0
  93. data/app/models/decidim/action_log.rb +12 -0
  94. data/app/models/decidim/amendment.rb +31 -2
  95. data/app/models/decidim/attachment.rb +2 -0
  96. data/app/models/decidim/authorization.rb +1 -0
  97. data/app/models/decidim/category.rb +1 -0
  98. data/app/models/decidim/component.rb +7 -0
  99. data/app/models/decidim/content_block.rb +1 -0
  100. data/app/models/decidim/follow.rb +3 -0
  101. data/app/models/decidim/identity.rb +1 -0
  102. data/app/models/decidim/impersonation_log.rb +2 -0
  103. data/app/models/decidim/newsletter.rb +1 -0
  104. data/app/models/decidim/participatory_process_user_role.rb +1 -0
  105. data/app/models/decidim/participatory_space_private_user.rb +1 -0
  106. data/app/models/decidim/permission_action.rb +2 -0
  107. data/app/models/decidim/report.rb +1 -0
  108. data/app/models/decidim/scope.rb +1 -0
  109. data/app/models/decidim/searchable_resource.rb +1 -1
  110. data/app/models/decidim/static_page.rb +1 -0
  111. data/app/models/decidim/user.rb +2 -0
  112. data/app/permissions/decidim/permissions.rb +18 -14
  113. data/app/permissions/decidim/user_manager_permissions.rb +9 -2
  114. data/app/presenters/decidim/admin_log/organization_presenter.rb +1 -0
  115. data/app/presenters/decidim/admin_log/participatory_space_private_user_presenter.rb +1 -1
  116. data/app/presenters/decidim/admin_log/user_presenter.rb +1 -1
  117. data/app/presenters/decidim/hashtag_presenter.rb +1 -1
  118. data/app/presenters/decidim/log/base_presenter.rb +1 -0
  119. data/app/presenters/decidim/log/diff_presenter.rb +1 -1
  120. data/app/presenters/decidim/log/value_types/area_presenter.rb +1 -0
  121. data/app/presenters/decidim/log/value_types/area_type_presenter.rb +1 -0
  122. data/app/presenters/decidim/log/value_types/currency_presenter.rb +1 -0
  123. data/app/presenters/decidim/log/value_types/date_presenter.rb +1 -0
  124. data/app/presenters/decidim/log/value_types/locale_presenter.rb +1 -0
  125. data/app/presenters/decidim/log/value_types/percentage_presenter.rb +1 -0
  126. data/app/presenters/decidim/log/value_types/scope_presenter.rb +1 -0
  127. data/app/presenters/decidim/log/value_types/scope_type_presenter.rb +1 -0
  128. data/app/presenters/decidim/metric_charts_presenter.rb +1 -0
  129. data/app/presenters/decidim/metric_object_presenter.rb +4 -0
  130. data/app/queries/decidim/metric_manage.rb +3 -0
  131. data/app/queries/decidim/metric_measure.rb +1 -0
  132. data/app/queries/decidim/metrics/followers_metric_manage.rb +3 -0
  133. data/app/queries/decidim/metrics/participants_metric_manage.rb +4 -0
  134. data/app/queries/decidim/similar_emendations.rb +56 -0
  135. data/app/resolvers/decidim/core/metric_resolver.rb +1 -0
  136. data/app/services/decidim/action_authorizer.rb +1 -0
  137. data/app/services/decidim/action_logger.rb +1 -0
  138. data/app/services/decidim/activity_search.rb +1 -0
  139. data/app/services/decidim/email_notification_generator.rb +4 -0
  140. data/app/services/decidim/notification_generator.rb +2 -0
  141. data/app/services/decidim/notification_generator_for_recipient.rb +0 -1
  142. data/app/services/decidim/resource_search.rb +1 -1
  143. data/app/services/decidim/traceability.rb +1 -0
  144. data/app/uploaders/decidim/application_uploader.rb +1 -0
  145. data/app/uploaders/decidim/attachment_uploader.rb +16 -0
  146. data/app/uploaders/decidim/avatar_uploader.rb +0 -2
  147. data/app/uploaders/decidim/data_portability_uploader.rb +1 -0
  148. data/app/uploaders/decidim/homepage_image_uploader.rb +0 -2
  149. data/app/uploaders/decidim/image_uploader.rb +15 -1
  150. data/app/uploaders/decidim/oauth_application_logo_uploader.rb +0 -1
  151. data/app/uploaders/decidim/official_image_footer_uploader.rb +0 -1
  152. data/app/uploaders/decidim/official_image_header_uploader.rb +0 -1
  153. data/app/uploaders/decidim/open_data_uploader.rb +1 -0
  154. data/app/validators/etiquette_validator.rb +5 -0
  155. data/app/views/decidim/account/delete.html.erb +2 -2
  156. data/app/views/decidim/account/show.html.erb +1 -1
  157. data/app/views/decidim/amendments/_edit_form_fields.html.erb +16 -13
  158. data/app/views/decidim/amendments/_similar_emendation.html.erb +24 -0
  159. data/app/views/decidim/amendments/compare_draft.html.erb +21 -0
  160. data/app/views/decidim/amendments/edit_draft.html.erb +31 -0
  161. data/app/views/decidim/amendments/new.html.erb +5 -17
  162. data/app/views/decidim/amendments/preview_draft.html.erb +32 -0
  163. data/app/views/decidim/amendments/review.html.erb +5 -3
  164. data/app/views/decidim/application/_document.html.erb +1 -1
  165. data/app/views/decidim/application/_photos.html.erb +1 -1
  166. data/app/views/decidim/data_portability/show.html.erb +1 -1
  167. data/app/views/decidim/devise/invitations/edit.html.erb +2 -2
  168. data/app/views/decidim/devise/sessions/new.html.erb +1 -1
  169. data/app/views/decidim/doorkeeper/authorizations/new.html.erb +3 -3
  170. data/app/views/decidim/export_mailer/data_portability_export.html.erb +1 -1
  171. data/app/views/decidim/searches/index.js.erb +6 -0
  172. data/app/views/decidim/shared/_address_details.html.erb +2 -2
  173. data/app/views/decidim/shared/_embed_modal.html.erb +1 -1
  174. data/app/views/decidim/shared/_share_modal.html.erb +7 -4
  175. data/app/views/layouts/decidim/_application.html.erb +0 -1
  176. data/app/views/layouts/decidim/_head.html.erb +13 -12
  177. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  178. data/app/views/layouts/decidim/_social_media_links.html.erb +5 -5
  179. data/app/views/layouts/decidim/_user_menu.html.erb +1 -1
  180. data/app/views/layouts/decidim/_wrapper.html.erb +2 -2
  181. data/app/views/layouts/decidim/mailer.html.erb +2 -2
  182. data/config/locales/ar.yml +27 -17
  183. data/config/locales/ca.yml +79 -15
  184. data/config/locales/cs.yml +73 -14
  185. data/config/locales/de.yml +62 -12
  186. data/config/locales/en.yml +80 -16
  187. data/config/locales/eo-UY.yml +16 -0
  188. data/config/locales/es-MX.yml +73 -11
  189. data/config/locales/es-PY.yml +73 -11
  190. data/config/locales/es.yml +79 -15
  191. data/config/locales/eu.yml +6 -13
  192. data/config/locales/fi-plain.yml +75 -11
  193. data/config/locales/fi.yml +80 -16
  194. data/config/locales/fr.yml +70 -16
  195. data/config/locales/gl.yml +6 -13
  196. data/config/locales/hu.yml +80 -17
  197. data/config/locales/id-ID.yml +6 -12
  198. data/config/locales/it.yml +56 -14
  199. data/config/locales/nl.yml +76 -12
  200. data/config/locales/no.yml +11 -2
  201. data/config/locales/pl.yml +6 -15
  202. data/config/locales/pt-BR.yml +6 -13
  203. data/config/locales/pt.yml +6 -13
  204. data/config/locales/ru.yml +7 -2
  205. data/config/locales/sv.yml +34 -18
  206. data/config/locales/tr-TR.yml +15 -12
  207. data/config/locales/uk.yml +7 -2
  208. data/config/routes.rb +7 -0
  209. data/db/migrate/20180226140756_add_version_to_action_logs.rb +1 -0
  210. data/db/migrate/20180305132906_rename_features_to_components.rb +1 -0
  211. data/db/migrate/20190412131728_fix_user_names.rb +1 -1
  212. data/db/migrate/20190610093742_add_force_users_to_authenticate_before_access_organization.rb +10 -0
  213. data/db/migrate/20190618075906_add_confidential_to_doorkeeper_application.rb +13 -0
  214. data/db/migrate/{20190925091507_add_uniq_index_to_decidim_metrics.rb → 20190829092826_add_uniq_index_to_decidim_metrics.rb} +0 -0
  215. data/lib/decidim/amendable.rb +87 -13
  216. data/lib/decidim/attributes/localized_date.rb +5 -0
  217. data/lib/decidim/attributes/time_with_zone.rb +5 -0
  218. data/lib/decidim/authorable.rb +3 -0
  219. data/lib/decidim/authorization_form_builder.rb +2 -2
  220. data/lib/decidim/component_manifest.rb +2 -0
  221. data/lib/decidim/content_parsers.rb +2 -0
  222. data/lib/decidim/content_parsers/hashtag_parser.rb +1 -1
  223. data/lib/decidim/content_parsers/link_parser.rb +10 -0
  224. data/lib/decidim/content_parsers/newline_parser.rb +20 -0
  225. data/lib/decidim/content_parsers/user_parser.rb +1 -1
  226. data/lib/decidim/content_processor.rb +2 -0
  227. data/lib/decidim/content_renderers.rb +1 -0
  228. data/lib/decidim/content_renderers/hashtag_renderer.rb +1 -1
  229. data/lib/decidim/content_renderers/link_renderer.rb +24 -0
  230. data/lib/decidim/content_renderers/user_renderer.rb +2 -2
  231. data/lib/decidim/core.rb +11 -0
  232. data/lib/decidim/core/engine.rb +2 -28
  233. data/lib/decidim/core/test.rb +4 -1
  234. data/lib/decidim/core/test/factories.rb +35 -8
  235. data/lib/decidim/core/test/shared_examples/amendable/create_amendment_draft_examples.rb +50 -0
  236. data/lib/decidim/core/test/shared_examples/amendable/destroy_amendment_draft_examples.rb +39 -0
  237. data/lib/decidim/core/test/shared_examples/amendable/promote_amendment_examples.rb +27 -3
  238. data/lib/decidim/core/test/shared_examples/amendable/{create_amendment_examples.rb → publish_amendment_draft_examples.rb} +26 -17
  239. data/lib/decidim/core/test/shared_examples/amendable/update_amendment_draft_examples.rb +42 -0
  240. data/lib/decidim/core/test/shared_examples/amendable/withdraw_amendment_examples.rb +19 -11
  241. data/lib/decidim/core/test/shared_examples/has_attachment_collections.rb +1 -1
  242. data/lib/decidim/core/test/shared_examples/has_attachments.rb +1 -1
  243. data/lib/decidim/core/test/shared_examples/simple_event.rb +4 -0
  244. data/lib/decidim/core/version.rb +1 -1
  245. data/lib/decidim/data_portability_file_zipper.rb +3 -0
  246. data/lib/decidim/events/author_event.rb +1 -0
  247. data/lib/decidim/events/base_event.rb +12 -22
  248. data/lib/decidim/events/coauthor_event.rb +1 -0
  249. data/lib/decidim/events/simple_event.rb +3 -0
  250. data/lib/decidim/exporters/csv.rb +1 -0
  251. data/lib/decidim/fingerprintable.rb +1 -0
  252. data/lib/decidim/followable.rb +8 -0
  253. data/lib/decidim/form_builder.rb +24 -3
  254. data/lib/decidim/gamification.rb +4 -0
  255. data/lib/decidim/gamification/badge_status.rb +1 -0
  256. data/lib/decidim/has_category.rb +2 -0
  257. data/lib/decidim/has_component.rb +2 -7
  258. data/lib/decidim/has_private_users.rb +8 -1
  259. data/lib/decidim/has_settings.rb +12 -8
  260. data/lib/decidim/hashtaggable.rb +4 -0
  261. data/lib/decidim/metric_operation_manifest.rb +1 -0
  262. data/lib/decidim/nicknamizable.rb +1 -0
  263. data/lib/decidim/participable.rb +1 -0
  264. data/lib/decidim/participatory_space_resourceable.rb +1 -0
  265. data/lib/decidim/randomable.rb +20 -0
  266. data/lib/decidim/search_resource_fields_mapper.rb +2 -0
  267. data/lib/decidim/searchable.rb +2 -0
  268. data/lib/decidim/settings_manifest.rb +10 -1
  269. data/lib/decidim/stats_registry.rb +1 -0
  270. data/lib/decidim/view_model.rb +1 -1
  271. data/lib/tasks/decidim_data_portability_tasks.rake +1 -0
  272. data/lib/tasks/decidim_metrics_tasks.rake +2 -0
  273. data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.no.js +12 -12
  274. metadata +140 -82
  275. data/app/commands/decidim/amendable/create.rb +0 -80
@@ -19,6 +19,7 @@ module Decidim::Amendable
19
19
 
20
20
  def emendation_author
21
21
  return unless emendation_resource
22
+
22
23
  @emendation_author ||= if emendation_resource.is_a?(Decidim::Coauthorable)
23
24
  Decidim::UserPresenter.new(emendation_resource.creator_author)
24
25
  else
@@ -28,16 +29,19 @@ module Decidim::Amendable
28
29
 
29
30
  def emendation_author_nickname
30
31
  return unless emendation_resource
32
+
31
33
  @emendation_author_nickname ||= emendation_author.nickname
32
34
  end
33
35
 
34
36
  def emendation_author_path
35
37
  return unless emendation_resource
38
+
36
39
  @emendation_author_path ||= emendation_author.profile_path
37
40
  end
38
41
 
39
42
  def emendation_path
40
43
  return unless emendation_resource
44
+
41
45
  @emendation_path ||= Decidim::ResourceLocatorPresenter.new(emendation_resource).path
42
46
  end
43
47
  end
@@ -18,7 +18,7 @@ module Decidim
18
18
 
19
19
  validates :name, presence: true
20
20
  validates :email, presence: true, 'valid_email_2/email': { disposable: true }
21
- validates :nickname, presence: true
21
+ validates :nickname, presence: true, format: /\A[\w\-]+\z/
22
22
 
23
23
  validates :nickname, length: { maximum: Decidim::User.nickname_max_length, allow_blank: true }
24
24
  validates :password, confirmation: true
@@ -4,35 +4,19 @@ module Decidim
4
4
  module Amendable
5
5
  # A form object to be used when users want to amend an amendable resource.
6
6
  class CreateForm < Decidim::Amendable::Form
7
- include Decidim::ApplicationHelper
8
-
9
7
  mimic :amendment
10
8
 
11
9
  attribute :amendable_gid, String
12
10
  attribute :user_group_id, Integer
13
- attribute :emendation_params, Object
11
+ attribute :emendation_params, Hash
14
12
 
15
13
  validates :amendable_gid, presence: true
16
- validates :emendation_params, presence: true
17
- validate :emendation_changes_amendable
18
- validate :check_amendable_form_validations
19
-
20
- def emendation_changes_amendable
21
- return unless amendable.amendable_fields == [:title, :body]
22
- return unless present(amendable).title == present(emendation).title
23
- return unless present(amendable).body.delete("\r") == present(emendation).body.delete("\r")
24
-
25
- amendable_form.errors.add(:title, :identical)
26
- amendable_form.errors.add(:body, :identical)
27
- end
14
+ validate :emendation_must_change_amendable
15
+ validate :amendable_form_must_be_valid
28
16
 
29
17
  def amendable
30
18
  @amendable ||= GlobalID::Locator.locate_signed(amendable_gid)
31
19
  end
32
-
33
- def emendation
34
- amendable.amendable_type.constantize.new(@emendation_params)
35
- end
36
20
  end
37
21
  end
38
22
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Amendable
5
+ # A form object used to edit emendations
6
+ class EditForm < Decidim::Amendable::Form
7
+ mimic :amendment
8
+
9
+ attribute :id, Integer
10
+ attribute :user_group_id, Integer
11
+ attribute :emendation_params, Hash
12
+
13
+ validates :id, presence: true
14
+ validate :emendation_must_change_amendable
15
+ validate :amendable_form_must_be_valid
16
+
17
+ def map_model(model)
18
+ self.emendation_params = model.emendation.attributes.slice(*amendable_fields_as_string)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -18,40 +18,62 @@ module Decidim
18
18
  @emendation ||= amendment&.emendation
19
19
  end
20
20
 
21
- def check_amendable_form_validations
21
+ def amender
22
+ @amender ||= amendment&.amender
23
+ end
24
+
25
+ private
26
+
27
+ # Validates the emendation is not identical to the amendable.
28
+ def emendation_must_change_amendable
29
+ return unless %w(title body).all? { |attr| attr.in? amendable_fields_as_string }
30
+
31
+ emendation = amendable.class.new(emendation_params)
32
+ return unless amendable.title == emendation.title
33
+ return unless normalized_body(amendable) == normalized_body(emendation)
34
+
35
+ amendable_form.errors.add(:title, :identical)
36
+ amendable_form.errors.add(:body, :identical)
37
+ end
38
+
39
+ # Normalizes the escape sequences used for newlines.
40
+ def normalized_body(resource)
41
+ Decidim::ContentParsers::NewlineParser.new(resource.body, context: {}).rewrite
42
+ end
43
+
44
+ # Validates the emendation using the amendable form.
45
+ def amendable_form_must_be_valid
22
46
  parse_hashtaggable_params
23
- run_validations
47
+ amendable_form.validate unless defined?(@amendable_form) # Preserves previously added errors.
24
48
  @errors = @amendable_form.errors
25
49
  end
26
50
 
51
+ # Parses :title and :body attribute values with HashtagParser.
27
52
  def parse_hashtaggable_params
28
53
  emendation_params.each do |key, value|
29
54
  next unless [:title, :body].include?(key)
30
- emendation_params[key] = Decidim::ContentProcessor
31
- .parse_with_processor(
32
- :hashtag,
33
- value,
34
- current_organization: amendable.organization
35
- ).rewrite
55
+
56
+ emendation_params[key] = Decidim::ContentParsers::HashtagParser.new(value, form_context).rewrite
36
57
  end
37
58
  end
38
59
 
60
+ # Returns an instance of the Form Object class defined in Decidim::Amendable#amendable_form
61
+ # constructed with the :emendation_params.
39
62
  def amendable_form
40
- @amendable_form ||= amendable
41
- .amendable_form
42
- .from_params(emendation_params)
43
- .with_context(
44
- current_component: amendable.component,
45
- current_participatory_space: amendable.participatory_space
46
- )
63
+ @amendable_form ||= amendable.amendable_form.from_params(emendation_params).with_context(form_context)
47
64
  end
48
65
 
49
- # Run validations only if `@amendable_form` is `nil`. This preserves
50
- # the artificial errors (:identical) added in `create_form.rb`
51
- def run_validations
52
- return if @amendable_form.present?
66
+ # Returns the amendable fields keys as String.
67
+ def amendable_fields_as_string
68
+ amendable.amendable_fields.map(&:to_s)
69
+ end
53
70
 
54
- amendable_form.validate
71
+ # Adds additional information to the base context from the current controller.
72
+ def form_context
73
+ context.to_h.merge(
74
+ current_component: amendable.component,
75
+ current_participatory_space: amendable.participatory_space
76
+ )
55
77
  end
56
78
  end
57
79
  end
@@ -6,16 +6,13 @@ module Decidim
6
6
  class PromoteForm < Decidim::Amendable::Form
7
7
  mimic :amendment
8
8
 
9
- attribute :id, String
10
- attribute :emendation_params, Object
9
+ attribute :id, Integer
10
+ attribute :emendation_params, Hash
11
11
 
12
12
  validates :id, presence: true
13
13
 
14
- def emendation_params
15
- {
16
- title: emendation&.title,
17
- body: emendation&.body
18
- }
14
+ def map_model(model)
15
+ self.emendation_params = model.emendation.attributes.slice(*amendable_fields_as_string)
19
16
  end
20
17
  end
21
18
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Amendable
5
+ # A form object used to publish emendations
6
+ class PublishForm < Decidim::Amendable::Form
7
+ mimic :amendment
8
+
9
+ attribute :id, Integer
10
+ attribute :amendable_params, Hash
11
+ attribute :emendation_params, Hash
12
+
13
+ validates :id, presence: true
14
+
15
+ def map_model(model)
16
+ self.amendable_params = model.amendable.attributes.slice(*amendable_fields_as_string)
17
+ self.emendation_params = model.emendation.attributes.slice(*amendable_fields_as_string)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -6,7 +6,7 @@ module Decidim
6
6
  class RejectForm < Decidim::Amendable::Form
7
7
  mimic :amendment
8
8
 
9
- attribute :id, String
9
+ attribute :id, Integer
10
10
 
11
11
  validates :id, presence: true
12
12
  end
@@ -6,11 +6,16 @@ module Decidim
6
6
  class ReviewForm < Decidim::Amendable::Form
7
7
  mimic :amendment
8
8
 
9
- attribute :id, String
10
- attribute :emendation_params, Object
9
+ attribute :id, Integer
10
+ attribute :emendation_params, Hash
11
11
 
12
- validates :emendation_params, presence: true
13
- validate :check_amendable_form_validations
12
+ validates :id, presence: true
13
+ validate :emendation_must_change_amendable
14
+ validate :amendable_form_must_be_valid
15
+
16
+ def map_model(model)
17
+ self.emendation_params = model.emendation.attributes.slice(*amendable_fields_as_string)
18
+ end
14
19
  end
15
20
  end
16
21
  end
@@ -16,6 +16,7 @@ module Decidim
16
16
  validates :email, :name, :organization, :invitation_instructions, presence: true
17
17
  validates :role, inclusion: { in: Decidim::User::Roles.all }
18
18
 
19
+ validates :name, format: { with: /\A(?!.*[<>?%&\^*#@\(\)\[\]\=\+\:\;\"\{\}\\\|])/ }
19
20
  validate :admin_uniqueness
20
21
 
21
22
  def email
@@ -19,6 +19,7 @@ module Decidim
19
19
 
20
20
  def newsletter_notifications_at
21
21
  return nil unless newsletter_notifications
22
+
22
23
  Time.current
23
24
  end
24
25
 
@@ -14,7 +14,7 @@ module Decidim
14
14
  attribute :tos_agreement, Boolean
15
15
 
16
16
  validates :name, presence: true
17
- validates :nickname, presence: true, length: { maximum: Decidim::User.nickname_max_length }
17
+ validates :nickname, presence: true, format: /\A[\w\-]+\z/, length: { maximum: Decidim::User.nickname_max_length }
18
18
  validates :email, presence: true, 'valid_email_2/email': { disposable: true }
19
19
  validates :password, confirmation: true
20
20
  validates :password, password: { name: :name, email: :email, username: :nickname }
@@ -26,17 +26,18 @@ module Decidim
26
26
 
27
27
  def newsletter_at
28
28
  return nil unless newsletter?
29
+
29
30
  Time.current
30
31
  end
31
32
 
32
33
  private
33
34
 
34
35
  def email_unique_in_organization
35
- errors.add :email, :taken if User.find_by(email: email, organization: current_organization).present?
36
+ errors.add :email, :taken if User.no_active_invitation.find_by(email: email, organization: current_organization).present?
36
37
  end
37
38
 
38
39
  def nickname_unique_in_organization
39
- errors.add :nickname, :taken if User.find_by(nickname: nickname, organization: current_organization).present?
40
+ errors.add :nickname, :taken if User.no_active_invitation.find_by(nickname: nickname, organization: current_organization).present?
40
41
  end
41
42
  end
42
43
  end
@@ -29,6 +29,7 @@ module Decidim
29
29
 
30
30
  def unique_document_number
31
31
  return if document_number.blank?
32
+
32
33
  errors.add :document_number, :taken if UserGroup
33
34
  .with_document_number(
34
35
  context.current_organization,
@@ -10,6 +10,7 @@ module Decidim
10
10
 
11
11
  def newsletter_notifications_at
12
12
  return nil unless newsletter_notifications
13
+
13
14
  Time.current
14
15
  end
15
16
 
@@ -7,16 +7,17 @@ module Decidim
7
7
  #
8
8
  # Returns Html grid of CardM.
9
9
  def amendments_for(amendable)
10
- return unless amendable.amendable? && amendable.emendations.count.positive?
10
+ return unless amendable.amendable?
11
+ return unless (emendations = amendable.visible_emendations_for(current_user)).any?
11
12
 
12
13
  content = content_tag(:h2, class: "section-heading", id: "amendments") do
13
- t("section_heading", scope: "decidim.amendments.amendable", count: amendable.emendations.count)
14
+ t("section_heading", scope: "decidim.amendments.amendable", count: emendations.count)
14
15
  end
15
16
 
16
17
  content << cell("decidim/collapsible_list",
17
- amendable.emendations,
18
+ emendations,
18
19
  cell_options: { context: { current_user: current_user } },
19
- list_class: "row small-up-1 medium-up-2 card-grid",
20
+ list_class: "row small-up-1 medium-up-2 card-grid amendment-list",
20
21
  size: 4).to_s
21
22
 
22
23
  content_tag :div, content.html_safe, class: "section"
@@ -41,10 +42,20 @@ module Decidim
41
42
  # Returns Html action button card to AMEND an amendable resource
42
43
  def amend_button_for(amendable)
43
44
  return unless amendments_enabled? && amendable.amendable?
45
+ return unless current_component.current_settings.amendment_creation_enabled
46
+ return unless can_participate_in_private_space?
44
47
 
45
48
  cell("decidim/amendable/amend_button_card", amendable)
46
49
  end
47
50
 
51
+ # Checks if the user can participate in a participatory space
52
+ # based on its settings related with Decidim::HasPrivateUsers.
53
+ def can_participate_in_private_space?
54
+ return true unless current_participatory_space.class.included_modules.include?(HasPrivateUsers)
55
+
56
+ current_participatory_space.can_participate?(current_user)
57
+ end
58
+
48
59
  # Returns Html action button cards for an emendation
49
60
  def emendation_actions_for(emendation)
50
61
  return unless amendments_enabled? && can_react_to_emendation?(emendation)
@@ -76,7 +87,7 @@ module Decidim
76
87
  def can_react_to_emendation?(emendation)
77
88
  return unless current_user && emendation.emendation?
78
89
 
79
- true
90
+ current_component.current_settings.amendment_reaction_enabled
80
91
  end
81
92
 
82
93
  # Checks if the user can accept and reject the emendation
@@ -89,18 +100,9 @@ module Decidim
89
100
  # Checks if the user can promote the emendation
90
101
  def allowed_to_promote?(emendation)
91
102
  return unless emendation.amendment.rejected? && emendation.created_by?(current_user)
92
- return if promoted?(emendation)
103
+ return if emendation.amendment.promoted?
93
104
 
94
- true
95
- end
96
-
97
- # Checks if the unique ActionLog created in the promote command exists.
98
- def promoted?(emendation)
99
- logs = Decidim::ActionLog.where(decidim_component_id: emendation.component)
100
- .where(decidim_user_id: emendation.creator_author)
101
- .where(action: "promote")
102
-
103
- logs.select { |log| log.extra["promoted_from"] == emendation.id }.present?
105
+ current_component.current_settings.amendment_promotion_enabled
104
106
  end
105
107
 
106
108
  # Renders a UserGroup select field in a form.
@@ -112,11 +114,23 @@ module Decidim
112
114
  label: t("new.amendment_author", scope: "decidim.amendments"))
113
115
  end
114
116
 
117
+ # Return the translated attribute name to use as label in a form.
118
+ # Returns a String.
119
+ def amendments_form_fields_label(attribute)
120
+ model_name = amendable.model_name.singular_route_key
121
+ I18n.t(attribute, scope: "activemodel.attributes.#{model_name}")
122
+ end
123
+
115
124
  # Return the edited field value or presents the original attribute value in a form.
116
- def emendation_field_value(form, original, key)
117
- return params[:amendment][:emendation_params][key] if params[:amendment].present?
125
+ #
126
+ # original_resource - name of the method to send to the controller (:amendable or :emendation)
127
+ # attribute - name of the attribute to send to the original_resource Presenter
128
+ #
129
+ # Returns a String.
130
+ def amendments_form_fields_value(original_resource, attribute)
131
+ return params[:amendment][:emendation_params][attribute] if params[:amendment].present?
118
132
 
119
- present(form.object.send(original)).send(key)
133
+ present(send(original_resource)).send(attribute)
120
134
  end
121
135
  end
122
136
  end
@@ -34,6 +34,7 @@ module Decidim
34
34
  return unless from_context
35
35
  return unless proposals_controller?
36
36
  return if index_action?
37
+
37
38
  from_context.withdrawable_by?(current_user)
38
39
  end
39
40
 
@@ -41,6 +42,7 @@ module Decidim
41
42
  return unless from_context
42
43
  return unless proposals_controller? || collaborative_drafts_controller?
43
44
  return if index_action?
45
+
44
46
  true
45
47
  end
46
48
  end
@@ -69,6 +69,7 @@ module Decidim
69
69
 
70
70
  def extended_navigation_bar(items, max_items: 5)
71
71
  return unless items.any?
72
+
72
73
  extra_items = items.slice((max_items + 1)..-1) || []
73
74
  active_item = items.find { |item| item[:active] }
74
75