decidim-core 0.25.1 → 0.26.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 (165) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +5 -1
  3. data/app/cells/decidim/author/flag_user.erb +1 -1
  4. data/app/cells/decidim/author/profile_inline.erb +1 -1
  5. data/app/cells/decidim/author/withdraw.erb +2 -2
  6. data/app/cells/decidim/author_cell.rb +33 -0
  7. data/app/cells/decidim/card_m_cell.rb +1 -1
  8. data/app/cells/decidim/content_blocks/cta_cell.rb +1 -1
  9. data/app/cells/decidim/content_blocks/hero_cell.rb +1 -1
  10. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  11. data/app/cells/decidim/content_blocks/how_to_participate/show.erb +1 -1
  12. data/app/cells/decidim/content_blocks/last_activity_cell.rb +1 -1
  13. data/app/cells/decidim/content_blocks/stats_cell.rb +12 -0
  14. data/app/cells/decidim/endorsers_list_cell.rb +3 -1
  15. data/app/cells/decidim/flag_modal/flag_user.erb +2 -2
  16. data/app/cells/decidim/flag_modal/show.erb +2 -2
  17. data/app/cells/decidim/flag_modal_cell.rb +10 -0
  18. data/app/cells/decidim/notification/show.erb +31 -0
  19. data/app/cells/decidim/notification_cell.rb +20 -0
  20. data/app/cells/decidim/notifications/show.erb +1 -24
  21. data/app/cells/decidim/notifications_cell.rb +0 -1
  22. data/app/cells/decidim/profile_sidebar/show.erb +1 -1
  23. data/app/cells/decidim/user_conversation/conversation_header.erb +1 -1
  24. data/app/cells/decidim/user_conversation/show.erb +4 -2
  25. data/app/cells/decidim/user_conversations/conversation_item.erb +1 -1
  26. data/app/commands/decidim/create_editor_image.rb +41 -0
  27. data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
  28. data/app/controllers/decidim/editor_images_controller.rb +47 -0
  29. data/app/controllers/decidim/user_activities_controller.rb +2 -1
  30. data/app/forms/decidim/editor_image_form.rb +16 -0
  31. data/app/helpers/decidim/amendments_helper.rb +1 -1
  32. data/app/helpers/decidim/application_helper.rb +2 -2
  33. data/app/helpers/decidim/messaging/conversation_helper.rb +32 -3
  34. data/app/helpers/decidim/resource_versions_helper.rb +1 -1
  35. data/app/helpers/decidim/sanitize_helper.rb +65 -0
  36. data/app/models/decidim/editor_image.rb +14 -0
  37. data/app/models/decidim/messaging/conversation.rb +9 -0
  38. data/app/models/decidim/moderation.rb +3 -0
  39. data/app/models/decidim/participatory_space_private_user.rb +16 -0
  40. data/app/models/decidim/user.rb +3 -12
  41. data/app/models/decidim/user_base_entity.rb +6 -0
  42. data/app/models/decidim/user_group.rb +40 -3
  43. data/app/packs/entrypoints/decidim_core.js +1 -0
  44. data/app/packs/src/decidim/dialog_mode.js +143 -0
  45. data/app/packs/src/decidim/dialog_mode.test.js +168 -0
  46. data/app/packs/src/decidim/editor.js +56 -14
  47. data/app/packs/src/decidim/form_attachments.js +5 -0
  48. data/app/packs/src/decidim/index.js +4 -0
  49. data/app/packs/src/decidim/input_emoji.js +10 -1
  50. data/app/packs/src/decidim/vendor/image-resize.min.js +3 -0
  51. data/app/packs/src/decidim/vendor/image-upload.min.js +8 -0
  52. data/app/packs/stylesheets/decidim/extras/_extras.scss +0 -1
  53. data/app/packs/stylesheets/decidim/extras/_quill.scss +6 -0
  54. data/app/packs/stylesheets/decidim/modules/_buttons.scss +11 -4
  55. data/app/packs/stylesheets/decidim/modules/_cards.scss +4 -0
  56. data/app/packs/stylesheets/decidim/modules/_comments.scss +1 -0
  57. data/app/packs/stylesheets/decidim/modules/_layout.scss +1 -1
  58. data/app/permissions/decidim/permissions.rb +9 -0
  59. data/app/presenters/decidim/nil_presenter.rb +2 -2
  60. data/app/presenters/decidim/notification_presenter.rb +25 -0
  61. data/app/presenters/decidim/official_author_presenter.rb +1 -1
  62. data/app/presenters/decidim/validation_errors_presenter.rb +27 -0
  63. data/app/queries/decidim/similar_emendations.rb +1 -1
  64. data/app/resolvers/decidim/core/metric_resolver.rb +1 -1
  65. data/app/services/decidim/activity_search.rb +2 -2
  66. data/app/services/decidim/email_notification_generator.rb +4 -1
  67. data/app/services/decidim/html_truncation.rb +130 -0
  68. data/app/services/decidim/open_data_exporter.rb +29 -5
  69. data/app/services/decidim/resource_search.rb +1 -1
  70. data/app/uploaders/decidim/editor_image_uploader.rb +6 -0
  71. data/app/validators/password_validator.rb +123 -0
  72. data/app/views/decidim/account/_password_fields.html.erb +1 -1
  73. data/app/views/decidim/devise/passwords/edit.html.erb +1 -1
  74. data/app/views/decidim/devise/registrations/new.html.erb +1 -1
  75. data/app/views/decidim/devise/shared/_omniauth_buttons_mini.html.erb +6 -4
  76. data/app/views/decidim/messaging/conversations/_conversation.html.erb +9 -3
  77. data/app/views/decidim/messaging/conversations/_messages.html.erb +8 -2
  78. data/app/views/decidim/messaging/conversations/_show.html.erb +10 -12
  79. data/app/views/decidim/messaging/conversations/show.html.erb +4 -2
  80. data/app/views/decidim/newsletters/show.html.erb +1 -1
  81. data/app/views/decidim/notification_mailer/event_received.html.erb +17 -0
  82. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  83. data/app/views/decidim/searches/_filters_small_view.html.erb +3 -3
  84. data/app/views/decidim/shared/_login_modal.html.erb +5 -5
  85. data/app/views/decidim/shared/_orders.html.erb +1 -1
  86. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  87. data/app/views/decidim/shared/participatory_space_filters/_filters_small_view.html.erb +3 -3
  88. data/app/views/layouts/decidim/_application.html.erb +1 -12
  89. data/app/views/layouts/decidim/_head.html.erb +4 -0
  90. data/app/views/layouts/decidim/_language_chooser.html.erb +1 -1
  91. data/app/views/layouts/decidim/_meta_tags_config.html.erb +11 -0
  92. data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
  93. data/config/brakeman.ignore +149 -0
  94. data/config/initializers/devise.rb +1 -1
  95. data/config/initializers/rack_attack.rb +23 -21
  96. data/config/locales/ar.yml +8 -0
  97. data/config/locales/ca.yml +46 -0
  98. data/config/locales/cs.yml +60 -0
  99. data/config/locales/en.yml +46 -0
  100. data/config/locales/es-MX.yml +47 -0
  101. data/config/locales/es-PY.yml +47 -0
  102. data/config/locales/es.yml +47 -0
  103. data/config/locales/eu.yml +16 -5
  104. data/config/locales/fi-plain.yml +47 -0
  105. data/config/locales/fi.yml +47 -0
  106. data/config/locales/fr-CA.yml +46 -0
  107. data/config/locales/fr.yml +74 -28
  108. data/config/locales/gl.yml +46 -0
  109. data/config/locales/hu.yml +101 -0
  110. data/config/locales/it.yml +11 -0
  111. data/config/locales/ja.yml +87 -48
  112. data/config/locales/lb-LU.yml +1354 -0
  113. data/config/locales/lb.yml +1 -1
  114. data/config/locales/nl.yml +51 -0
  115. data/config/locales/no.yml +225 -0
  116. data/config/locales/pl.yml +5 -5
  117. data/config/locales/pt-BR.yml +1 -1
  118. data/config/locales/ro-RO.yml +38 -16
  119. data/config/locales/sv.yml +50 -3
  120. data/config/locales/val-ES.yml +1 -0
  121. data/config/routes.rb +2 -0
  122. data/db/migrate/20210730112319_create_decidim_editor_images.rb +12 -0
  123. data/db/migrate/20211126183540_add_timestamps_to_content_blocks.rb +14 -0
  124. data/db/seeds.rb +16 -14
  125. data/lib/decidim/api/functions/user_entity_finder.rb +2 -1
  126. data/lib/decidim/api/functions/user_entity_list.rb +3 -1
  127. data/lib/decidim/api/input_sorts/component_input_sort.rb +1 -1
  128. data/lib/decidim/common_passwords.rb +56 -0
  129. data/lib/decidim/content_parsers/inline_images_parser.rb +68 -0
  130. data/lib/decidim/content_parsers.rb +1 -0
  131. data/lib/decidim/content_renderers/link_renderer.rb +85 -1
  132. data/lib/decidim/content_renderers/user_group_renderer.rb +1 -1
  133. data/lib/decidim/content_renderers/user_renderer.rb +1 -1
  134. data/lib/decidim/core/engine.rb +3 -12
  135. data/lib/decidim/core/test/factories.rb +7 -1
  136. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +34 -0
  137. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +131 -0
  138. data/lib/decidim/core/test.rb +1 -0
  139. data/lib/decidim/core/version.rb +1 -1
  140. data/lib/decidim/core.rb +22 -5
  141. data/lib/decidim/db/common-passwords.txt +128420 -0
  142. data/lib/decidim/etherpad/pad.rb +48 -0
  143. data/lib/decidim/etherpad.rb +7 -0
  144. data/lib/decidim/events/base_event.rb +18 -0
  145. data/lib/decidim/events/machine_translated_event.rb +36 -0
  146. data/lib/decidim/events/user_group_event.rb +1 -3
  147. data/lib/decidim/events.rb +1 -0
  148. data/lib/decidim/exporters/csv.rb +7 -7
  149. data/lib/decidim/faker/localized.rb +15 -6
  150. data/lib/decidim/form_builder.rb +14 -4
  151. data/lib/decidim/has_attachments.rb +11 -4
  152. data/lib/decidim/importers/import_manifest.rb +103 -3
  153. data/lib/decidim/map/autocomplete.rb +12 -5
  154. data/lib/decidim/organization_settings.rb +1 -1
  155. data/lib/decidim/paddable.rb +1 -9
  156. data/lib/decidim/resourceable.rb +1 -0
  157. data/lib/decidim/searchable.rb +12 -6
  158. data/lib/decidim/settings_manifest.rb +2 -0
  159. data/lib/decidim/translatable_attributes.rb +6 -6
  160. data/lib/decidim/view_model.rb +10 -0
  161. data/lib/tasks/decidim_active_storage_migration_tasks.rake +68 -0
  162. data/lib/tasks/decidim_webpacker_tasks.rake +4 -10
  163. data/lib/tasks/upgrade/decidim_moderation_tasks.rake +32 -0
  164. metadata +60 -68
  165. data/app/packs/stylesheets/decidim/extras/_social_icons_mini.scss +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eca76c4ef82409ae6c776698ddc78d82295da48e750e5d94463d98c43804c01c
4
- data.tar.gz: 1f8d94bfb15701d211c27fd1299b1ccfb26f3c7416d1431fe2ef4c93cee19da5
3
+ metadata.gz: f92f8225a3998e9e26e1c147c90eafb9ebb90a7c153e300b3ea2b9695e63e2ba
4
+ data.tar.gz: 8c3eb2093ab824160548f3089e3b5ba68536a7231892f2c2484aa384c49307b5
5
5
  SHA512:
6
- metadata.gz: 1017e4e7f91af798732af3d223a5610843e306e62226c934916dff92e055f1fe3ad95ac396b76ac882946c413e7c55c81e7856b4b6a6bfd4bfa421215797b10a
7
- data.tar.gz: b59c04f0d040272d056716a57c97d0611a9cd2eccfe951d09eaab6c88408fa77d3e5100d10e634cfe2a392a3d8c20c3c49bebcb438717bb4615d27aaf999ce74
6
+ metadata.gz: 1abf1ab6e14a84745b3bb8fd176f002b7fd65ecbd497b1e4544202b517d265a2eded3d628e0ab27ed53f2385849da158f31571af32181e68cb7df02ee60844a4
7
+ data.tar.gz: 9f0209ace6ff368bd4dfb87d3b28c704d4ba1726abf8bfe29efab5a0aa52babb06eb214a6bee663d1b6d6728f9c4fff222ff83008b0f44cb868b5d575437be32
@@ -92,10 +92,14 @@ module Decidim
92
92
 
93
93
  def cache_hash
94
94
  hash = []
95
+ hash << I18n.locale.to_s
95
96
  hash << model.class.name.underscore
96
97
  hash << model.cache_key_with_version
98
+ if (author_cell = author)
99
+ hash.push(Digest::MD5.hexdigest(author_cell.send(:cache_hash)))
100
+ end
97
101
 
98
- hash.join("/")
102
+ hash.join(Decidim.cache_key_separator)
99
103
  end
100
104
 
101
105
  private
@@ -1,5 +1,5 @@
1
1
  <% if user_flaggable? && model.try(:id) != current_user.try(:id) %>
2
- <button type="button" class="link-alt" data-open="<%= current_user.present? ? "flagUserModal" : "loginModal" %>" title="<%= t("report", scope: "decidim.proposals.proposals.show") %>" aria-controls="<%= current_user.present? ? "flagUserModal" : "loginModal" %>" aria-haspopup="true" tabindex="0">
2
+ <button type="button" class="link-alt" data-open="<%= current_user.present? ? "flagUserModal" : "loginModal" %>" title="<%= t("report", scope: "decidim.proposals.proposals.show") %>" aria-controls="<%= current_user.present? ? "flagUserModal" : "loginModal" %>" aria-haspopup="dialog" tabindex="0">
3
3
  <%= icon "flag", aria_hidden: true, class: "icon--small", role: "img", "aria-hidden": true %>
4
4
  <span class="show-for-sr">
5
5
  <%= t("report", scope: "decidim.proposals.proposals.show") %>
@@ -1,5 +1,5 @@
1
1
  <span class="author__avatar">
2
- <%= image_tag model.avatar_url, alt: t("decidim.author.avatar", name: decidim_sanitize(author_name)) %>
2
+ <%= image_tag model.avatar_url(:thumb), alt: t("decidim.author.avatar", name: decidim_sanitize(author_name)) %>
3
3
  </span>
4
4
 
5
5
  <% if model.deleted? %>
@@ -1,6 +1,6 @@
1
1
  <% if withdrawable? %>
2
- <%= action_authorized_link_to :withdraw, withdraw_path, method: :put, class: "title-action__action button small hollow", title: t("withdraw_btn_hint", scope: "decidim.proposals.proposals.show"), data: { confirm: t("withdraw_confirmation_html", scope: "decidim.proposals.proposals.show") } do %>
3
- <%= t("withdraw_proposal", scope: "decidim.proposals.proposals.show") %>
2
+ <%= action_authorized_link_to :withdraw, withdraw_path, method: :put, class: "title-action__action button small hollow", title: t("withdraw_btn_hint", scope: resource_i18n_scope ), data: { confirm: t("withdraw_confirmation_html", scope: resource_i18n_scope ) } do %>
3
+ <%= t("withdraw_#{resource_name}", scope: resource_i18n_scope) %>
4
4
  <%= icon "x", role: "img", "aria-hidden": true %>
5
5
  <% end %>
6
6
  <% end %>
@@ -55,8 +55,29 @@ module Decidim
55
55
  render
56
56
  end
57
57
 
58
+ def perform_caching?
59
+ true
60
+ end
61
+
58
62
  private
59
63
 
64
+ def cache_hash
65
+ hash = []
66
+
67
+ hash.push(I18n.locale)
68
+ hash.push(model.cache_key_with_version) if model.respond_to?(:cache_key_with_version)
69
+ hash.push(from_context.cache_key_with_version) if from_context.respond_to?(:cache_key_with_version)
70
+ hash.push(current_user.try(:id))
71
+ hash.push(current_user.present?)
72
+ hash.push(commentable?)
73
+ hash.push(endorsable?)
74
+ hash.push(actionable?)
75
+ hash.push(withdrawable?)
76
+ hash.push(flaggable?)
77
+ hash.push(profile_path?)
78
+ hash.join(Decidim.cache_key_separator)
79
+ end
80
+
60
81
  def from_context_path
61
82
  resource_locator(from_context).path
62
83
  end
@@ -111,5 +132,17 @@ module Decidim
111
132
  def raw_model
112
133
  model.try(:__getobj__) || model
113
134
  end
135
+
136
+ def resource_i18n_scope
137
+ @resource_i18n_scope ||= [
138
+ from_context.class.name.deconstantize.underscore.gsub("/", "."),
139
+ resource_name.pluralize,
140
+ :show
141
+ ].join(".")
142
+ end
143
+
144
+ def resource_name
145
+ @resource_name ||= from_context.class.name.demodulize.underscore
146
+ end
114
147
  end
115
148
  end
@@ -64,7 +64,7 @@ module Decidim
64
64
  attribute = model.try(:short_description) || model.try(:body) || model.description
65
65
  text = translated_attribute(attribute)
66
66
 
67
- decidim_sanitize(html_truncate(text, length: 100))
67
+ decidim_sanitize_editor(html_truncate(text, length: 100))
68
68
  end
69
69
 
70
70
  def has_authors?
@@ -16,7 +16,7 @@ module Decidim
16
16
  end
17
17
 
18
18
  def translated_description
19
- @translated_description ||= decidim_sanitize(translated_attribute(model.settings.description))
19
+ @translated_description ||= decidim_sanitize_editor(translated_attribute(model.settings.description))
20
20
  end
21
21
 
22
22
  def button_url
@@ -30,7 +30,7 @@ module Decidim
30
30
  hash << current_organization.cache_key_with_version
31
31
  hash << I18n.locale.to_s
32
32
 
33
- hash.join("/")
33
+ hash.join(Decidim.cache_key_separator)
34
34
  end
35
35
  end
36
36
  end
@@ -7,7 +7,7 @@
7
7
  <%= translated_attribute current_organization.highlighted_content_banner_title %>
8
8
  </h1>
9
9
  <span class="text-highlight">
10
- <%= decidim_sanitize translated_attribute current_organization.highlighted_content_banner_short_description %>
10
+ <%= decidim_sanitize_editor translated_attribute current_organization.highlighted_content_banner_short_description %>
11
11
  </span>
12
12
  </div>
13
13
  <div class="columns large-2">
@@ -41,7 +41,7 @@
41
41
  <div class="row">
42
42
  <div class="columns small-centered small-10
43
43
  smallmedium-8 medium-6 large-4">
44
- <%= link_to t("decidim.pages.home.extended.more_info", resource_name: translated_attribute(current_organization.name, current_organization)), decidim.page_path("faq"), class: "button expanded hollow button--sc" %>
44
+ <%= link_to t("decidim.pages.home.extended.more_info", resource_name: translated_attribute(current_organization.name, current_organization)), decidim.pages_path, class: "button expanded hollow button--sc" %>
45
45
  </div>
46
46
  </div>
47
47
  </div>
@@ -52,7 +52,7 @@ module Decidim
52
52
  hash << Digest::MD5.hexdigest(valid_activities.map(&:cache_key_with_version).to_s)
53
53
  hash << I18n.locale.to_s
54
54
 
55
- hash.join("/")
55
+ hash.join(Decidim.cache_key_separator)
56
56
  end
57
57
 
58
58
  def activities
@@ -3,9 +3,21 @@
3
3
  module Decidim
4
4
  module ContentBlocks
5
5
  class StatsCell < Decidim::ViewModel
6
+ cache :show, expires_in: 10.minutes, if: :perform_caching? do
7
+ cache_hash
8
+ end
9
+
6
10
  def stats
7
11
  @stats ||= HomeStatsPresenter.new(organization: current_organization)
8
12
  end
13
+
14
+ private
15
+
16
+ def cache_hash
17
+ hash = []
18
+ hash.push(I18n.locale)
19
+ hash.join(Decidim.cache_key_separator)
20
+ end
9
21
  end
10
22
  end
11
23
  end
@@ -23,7 +23,9 @@ module Decidim
23
23
  #
24
24
  # Returns an Array of presented Users/UserGroups
25
25
  def endorsers
26
- @endorsers ||= model.endorsements.for_listing.map { |identity| present(identity.normalized_author) }
26
+ @endorsers ||= model.endorsements.for_listing
27
+ .includes(:author, :user_group)
28
+ .map { |identity| present(identity.normalized_author) }
27
29
  end
28
30
  end
29
31
  end
@@ -1,6 +1,6 @@
1
- <div class="reveal flag-modal" id="flagUserModal" data-reveal>
1
+ <div class="reveal flag-modal" id="flagUserModal" data-reveal role="dialog" aria-modal="true" aria-labelledby="flagUserModal-label">
2
2
  <div class="reveal__header">
3
- <h3 class="reveal__title"><%= t("decidim.shared.flag_user_modal.title") %></h3>
3
+ <h3 id="flagUserModal-label" class="reveal__title"><%= t("decidim.shared.flag_user_modal.title") %></h3>
4
4
  <button class="close-button" data-close aria-label="<%= t("decidim.shared.flag_user_modal.close") %>" type="button">
5
5
  <span aria-hidden="true">&times;</span>
6
6
  </button>
@@ -1,6 +1,6 @@
1
- <div class="reveal flag-modal" id="<%= modal_id %>" data-reveal>
1
+ <div class="reveal flag-modal" id="<%= modal_id %>" data-reveal role="dialog" aria-modal="true" aria-labelledby="<%= modal_id %>-label">
2
2
  <div class="reveal__header">
3
- <h3 class="reveal__title"><%= t("decidim.shared.flag_modal.title") %></h3>
3
+ <h3 id="<%= modal_id %>-label" class="reveal__title"><%= t("decidim.shared.flag_modal.title") %></h3>
4
4
  <button class="close-button" data-close aria-label="<%= t("decidim.shared.flag_modal.close") %>" type="button">
5
5
  <span aria-hidden="true">&times;</span>
6
6
  </button>
@@ -8,6 +8,16 @@ module Decidim
8
8
  render
9
9
  end
10
10
 
11
+ def cache_hash
12
+ hash = []
13
+ hash.push(I18n.locale)
14
+ hash.push(current_user.try(:id))
15
+ hash.push(model.reported_by?(current_user) ? 1 : 0)
16
+ hash.push(model.class.name.gsub("::", ":"))
17
+ hash.push(model.id)
18
+ hash.join(Decidim.cache_key_separator)
19
+ end
20
+
11
21
  private
12
22
 
13
23
  def user_report_form
@@ -0,0 +1,31 @@
1
+ <div class="card card--widget">
2
+ <ul class="card-data">
3
+ <li class="card-data__item">
4
+ <div class="card__link text-center">
5
+ <%= resource_icon notification.resource, class: "icon--large" %>
6
+ <span class="text-medium mt-xs" title="<%= l(notification.created_at) %>" data-tooltip="true" data-disable-hover="false">
7
+ <%= notification.created_at_in_words %>
8
+ </span>
9
+ </div>
10
+ </li>
11
+ <li class="card-data__item card-data__item--expand absolutes">
12
+ <div class="mr-s">
13
+ <span class="text-small"><%= notification.event_class.constantize.model_name.human %></span>
14
+ <br>
15
+ <span>
16
+ <%= notification.event_class_instance.notification_title %>
17
+ </span>
18
+ <% if notification.display_resource_text? %>
19
+ <p>
20
+ <em><%= notification.resource_text %></em>
21
+ </p>
22
+ <% end %>
23
+ </div>
24
+ <div class="right center mr-s">
25
+ <%= link_to model, remote: true, method: :delete, class: "mark-as-read-button" do %>
26
+ <%= icon "circle-x", class: "card__link", aria_label: t("mark_as_read", scope: "layouts.decidim.notifications_dashboard"), role: "img" %>
27
+ <% end %>
28
+ </div>
29
+ </li>
30
+ </ul>
31
+ </div>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This cell renders a notification from a notifications collection
5
+
6
+ class NotificationCell < Decidim::ViewModel
7
+ include Decidim::IconHelper
8
+ include Decidim::Core::Engine.routes.url_helpers
9
+
10
+ def show
11
+ render :show
12
+ end
13
+
14
+ private
15
+
16
+ def notification
17
+ @notification ||= Decidim::NotificationPresenter.new(model)
18
+ end
19
+ end
20
+ end
@@ -17,30 +17,7 @@
17
17
  </div>
18
18
 
19
19
  <% notifications.select(&:resource).each do |notification| %>
20
- <div class="card card--widget">
21
- <ul class="card-data">
22
- <li class="card-data__item">
23
- <div class="card__link text-center">
24
- <%= resource_icon notification.resource, class: "icon--large" %>
25
- <span class="text-medium mt-xs"><%= l notification.created_at, format: :day_of_week_long %></span>
26
- </div>
27
- </li>
28
- <li class="card-data__item card-data__item--expand absolutes">
29
- <div class="mr-s">
30
- <span class="text-small"><%= notification.event_class.constantize.model_name.human %></span>
31
- <br>
32
- <span>
33
- <%= notification.event_class_instance.notification_title %>
34
- </span>
35
- </div>
36
- <div class="right center mr-s">
37
- <%= link_to notification, remote: true, method: :delete, class: "mark-as-read-button" do %>
38
- <%= icon "circle-x", class: "card__link", aria_label: t("mark_as_read", scope: "layouts.decidim.notifications_dashboard"), role: "img" %>
39
- <% end %>
40
- </div>
41
- </li>
42
- </ul>
43
- </div>
20
+ <%= cell("decidim/notification", notification) %>
44
21
  <% end %>
45
22
  </div>
46
23
 
@@ -3,7 +3,6 @@
3
3
  module Decidim
4
4
  class NotificationsCell < Decidim::ViewModel
5
5
  include Decidim::CellsPaginateHelper
6
- include Decidim::IconHelper
7
6
  include Decidim::Core::Engine.routes.url_helpers
8
7
 
9
8
  helper_method :notifications
@@ -23,7 +23,7 @@
23
23
  <small><%= decidim_html_escape(profile_user.about.to_s) %></small>
24
24
  </div>
25
25
  <% if profile_user.personal_url.present? %>
26
- <%= link_to html_truncate(profile_user.personal_url.gsub(%r{https?\:\/\/}, ""), length: 30), profile_user.personal_url %>
26
+ <%= link_to html_truncate(profile_user.personal_url.gsub(%r{https?\:\/\/}, ""), length: 30), profile_user.personal_url, rel: "nofollow noopener" %>
27
27
  <% end %>
28
28
  </div>
29
29
  <% if profile_user.badge.present? %>
@@ -9,6 +9,6 @@
9
9
  <% end %>
10
10
 
11
11
  <div class="ml-s">
12
- <%= t("decidim.user_conversations.show.title", usernames: interlocutors_names) %>
12
+ <%= t("decidim.user_conversations.show.title", usernames: interlocutors_names).html_safe %>
13
13
  </div>
14
14
  </div>
@@ -10,10 +10,12 @@
10
10
  <% end %>
11
11
  </div>
12
12
 
13
- <% if conversation.accept_user?(user) %>
13
+ <% if conversation.with_deleted_users?(user) %>
14
+ <div class="callout warning margin-top-2"><%= t "decidim.user_conversations.show.deleted_accounts" %></div>
15
+ <% elsif conversation.accept_user?(user) %>
14
16
  <%= render view: :reply, locals: { title: t("decidim.user_conversations.reply.title_reply") } %>
15
17
  <% else %>
16
- <em><%= t "decidim.user_conversations.show.not_allowed" %></em>
18
+ <div class="callout warning margin-top-2"><%= t "decidim.user_conversations.show.not_allowed" %></div>
17
19
  <% end %>
18
20
  </div>
19
21
  </div>
@@ -10,7 +10,7 @@
10
10
  </li>
11
11
  <li class="card-data__item card--list__item card-data__item--expand absolutes">
12
12
  <div class="mr-s">
13
- <%= t("decidim.user_conversations.index.from") %>: <strong><%= conversation_interlocutors(conversation) %></strong>
13
+ <%= t("decidim.user_conversations.index.from") %>: <strong><%= conversation_interlocutors(conversation).html_safe %></strong>
14
14
  <br>
15
15
  <span class="muted">
16
16
  <%= truncate conversation.last_message.body, length: 150 %>
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # A command with all the business logic to create an editor image.
5
+ class CreateEditorImage < Rectify::Command
6
+ # Public: Initializes the command.
7
+ #
8
+ # form - A form object with the params.
9
+ def initialize(form)
10
+ @form = form
11
+ end
12
+
13
+ # Executes the command. Broadcasts these events:
14
+ #
15
+ # - :ok when everything is valid.
16
+ # - :invalid if the form wasn't valid and we couldn't proceed.
17
+ #
18
+ # Returns nothing.
19
+ def call
20
+ return broadcast(:invalid) if form.invalid?
21
+
22
+ transaction do
23
+ create_editor_image
24
+ end
25
+
26
+ broadcast(:ok, @editor_image)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :form
32
+
33
+ def create_editor_image
34
+ @editor_image = EditorImage.create!(
35
+ decidim_author_id: form.current_user.id,
36
+ organization: form.organization,
37
+ file: form.file
38
+ )
39
+ end
40
+ end
41
+ end
@@ -10,6 +10,8 @@ module Decidim
10
10
  Decidim.config.consent_cookie_name,
11
11
  value: "true",
12
12
  path: "/",
13
+ httponly: true,
14
+ secure: request.session_options[:secure],
13
15
  expires: 1.year.from_now.utc
14
16
  )
15
17
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ class EditorImagesController < Decidim::ApplicationController
5
+ include FormFactory
6
+
7
+ # overwrite original rescue_from to ensure we print messages from ajax methods (update)
8
+ rescue_from Decidim::ActionForbidden, with: :ajax_user_has_no_permission
9
+
10
+ def create
11
+ enforce_permission_to :create, :editor_image
12
+
13
+ @form = form(EditorImageForm).from_params(form_values)
14
+
15
+ CreateEditorImage.call(@form) do
16
+ on(:ok) do |image|
17
+ render json: { url: image.attached_uploader(:file).path, message: I18n.t("success", scope: "decidim.editor_images.create") }
18
+ end
19
+
20
+ on(:invalid) do |_message|
21
+ render json: { message: I18n.t("error", scope: "decidim.editor_images.create") }, status: :unprocessable_entity
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ # Rescue ajax calls and print the update.js view which prints the info on the message ajax form
29
+ # Only if the request is AJAX, otherwise behave as Decidim standards
30
+ def ajax_user_has_no_permission
31
+ return user_has_no_permission unless request.xhr?
32
+
33
+ render json: { message: I18n.t("actions.unauthorized", scope: "decidim.core") }, status: :unprocessable_entity
34
+ end
35
+
36
+ def form_values
37
+ {
38
+ file: params[:image],
39
+ author_id: current_user.id
40
+ }
41
+ end
42
+
43
+ def permission_scope
44
+ :admin
45
+ end
46
+ end
47
+ end
@@ -12,7 +12,8 @@ module Decidim
12
12
  helper_method :activities, :resource_types, :user
13
13
 
14
14
  def index
15
- raise ActionController::RoutingError, "Blocked User" if user&.blocked? && !current_user&.admin?
15
+ raise ActionController::RoutingError, "Missing user: #{params[:nickname]}" unless user
16
+ raise ActionController::RoutingError, "Blocked User" if user.blocked? && !current_user&.admin?
16
17
  end
17
18
 
18
19
  private
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ class EditorImageForm < Decidim::Form
5
+ mimic :editor_image
6
+
7
+ attribute :file
8
+ attribute :author_id, Integer
9
+
10
+ validates :author_id, presence: true
11
+ validates :file, presence: true
12
+ validates :file, passthru: { to: Decidim::EditorImage }
13
+
14
+ alias organization current_organization
15
+ end
16
+ end
@@ -136,7 +136,7 @@ module Decidim
136
136
 
137
137
  return body unless rich_text_editor_in_public_views?
138
138
 
139
- decidim_sanitize(body)
139
+ decidim_sanitize_editor(body)
140
140
  end
141
141
 
142
142
  # Return the edited field value or presents the original attribute value in a form.
@@ -15,7 +15,7 @@ module Decidim
15
15
  # options - A Hash with the options to truncate the text (default: {}):
16
16
  # :length - An Integer number with the max length of the text.
17
17
  # :separator - A String to append to the text when it's being
18
- # truncated. See `truncato` gem for more options.
18
+ # truncated.
19
19
  #
20
20
  # Returns a String.
21
21
  def html_truncate(text, options = {})
@@ -25,7 +25,7 @@ module Decidim
25
25
  options[:count_tail] ||= false
26
26
  options[:tail_before_final_tag] = true unless options.has_key?(:tail_before_final_tag)
27
27
 
28
- Truncato.truncate(text, options)
28
+ Decidim::HtmlTruncation.new(text, options).perform
29
29
  end
30
30
 
31
31
  def present(object, presenter_class: nil)
@@ -3,14 +3,43 @@
3
3
  module Decidim
4
4
  module Messaging
5
5
  module ConversationHelper
6
+ def conversation_name_for(users)
7
+ return content_tag(:span, t("decidim.profile.deleted"), class: "label label--small label--basic") if users.first.deleted?
8
+
9
+ content_tag = content_tag(:strong, users.first.name)
10
+ content_tag << tag.br
11
+ content_tag << content_tag(:span, "@#{users.first.nickname}", class: "muted")
12
+ content_tag
13
+ end
14
+
15
+ def conversation_label_for(participants)
16
+ return t("title", scope: "decidim.messaging.conversations.show", usernames: username_list(participants)) unless participants.count == 1
17
+
18
+ chat_with_user = if participants.first.deleted?
19
+ t("decidim.profile.deleted")
20
+ else
21
+ "#{participants.first.name} (@#{participants.first.nickname})"
22
+ end
23
+
24
+ "#{t("chat_with", scope: "decidim.messaging.conversations.show")} #{chat_with_user}"
25
+ end
26
+
6
27
  #
7
28
  # Generates a visualization of users for listing conversations threads
8
29
  #
9
30
  def username_list(users, shorten: false)
10
- return users.pluck(:name).join(", ") unless shorten
11
- return users.pluck(:name).join(", ") unless users.count > 3
31
+ content_tags = []
32
+ first_users = shorten ? users.first(3) : users
33
+ deleted_user_tag = content_tag(:span, t("decidim.profile.deleted"), class: "label label--small label--basic")
34
+ first_users.each do |u|
35
+ content_tags.push(u.deleted? ? deleted_user_tag : content_tag(:strong, u.name))
36
+ end
37
+
38
+ return content_tags.join(", ") unless shorten
39
+ return content_tags.join(", ") unless users.count > 3
12
40
 
13
- "#{users.first(3).pluck(:name).join(", ")} + #{users.count - 3}"
41
+ content_tags.push(content_tag(:strong, " + #{users.count - 3}"))
42
+ content_tags.join(", ")
14
43
  end
15
44
 
16
45
  #
@@ -13,7 +13,7 @@ module Decidim
13
13
  #
14
14
  # Returns a String.
15
15
  def resource_version(resource, options = {})
16
- return unless resource.respond_to?(:versions) && resource.versions.present?
16
+ return unless resource.respond_to?(:versions) && resource.versions_count.positive?
17
17
 
18
18
  html = []
19
19
  html << resource_version_number(resource.versions_count)