decidim-core 0.26.0.rc1 → 0.26.1

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.

Potentially problematic release.


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

Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +3 -0
  3. data/app/cells/decidim/author_cell.rb +1 -0
  4. data/app/cells/decidim/card_m_cell.rb +1 -1
  5. data/app/cells/decidim/diff/diff_mode_dropdown.erb +13 -8
  6. data/app/cells/decidim/diff/diff_mode_html.erb +13 -8
  7. data/app/cells/decidim/diff/show.erb +5 -3
  8. data/app/cells/decidim/endorsement_buttons_cell.rb.2 +211 -0
  9. data/app/cells/decidim/endorsers_list/show.erb +1 -1
  10. data/app/cells/decidim/fingerprint/show.erb +1 -1
  11. data/app/cells/decidim/followers/show.erb +1 -1
  12. data/app/cells/decidim/following/show.erb +2 -2
  13. data/app/cells/decidim/groups/show.erb +1 -1
  14. data/app/cells/decidim/members/show.erb +1 -1
  15. data/app/cells/decidim/profile_sidebar/show.erb +1 -1
  16. data/app/cells/decidim/user_conversation/messages.erb +1 -1
  17. data/app/cells/decidim/user_conversation_cell.rb +4 -0
  18. data/app/cells/decidim/user_conversations/add_conversation_users.erb +1 -1
  19. data/app/cells/decidim/version_cell.rb +1 -1
  20. data/app/cells/decidim/versions_list_cell.rb +1 -1
  21. data/app/cells/decidim/versions_list_item/show.erb +2 -2
  22. data/app/commands/decidim/messaging/reply_to_conversation.rb +4 -1
  23. data/app/commands/decidim/unendorse_resource.rb +5 -4
  24. data/app/controllers/decidim/application_controller.rb +1 -0
  25. data/app/controllers/decidim/components/base_controller.rb +0 -1
  26. data/app/events/decidim/amendable/amendment_base_event.rb +1 -1
  27. data/app/forms/decidim/messaging/message_form.rb +1 -1
  28. data/app/helpers/decidim/endorsable_helper.rb +7 -6
  29. data/app/helpers/decidim/social_share_button_helper.rb +26 -0
  30. data/app/helpers/decidim/twitter_search_helper.rb +14 -0
  31. data/app/models/decidim/moderation.rb +3 -0
  32. data/app/models/decidim/user.rb +0 -9
  33. data/app/models/decidim/user_base_entity.rb +6 -0
  34. data/app/models/decidim/user_group.rb +0 -3
  35. data/app/packs/entrypoints/decidim_core.js +3 -0
  36. data/app/packs/src/decidim/back_to_list.js +26 -0
  37. data/app/packs/src/decidim/dialog_mode.js +11 -99
  38. data/app/packs/src/decidim/dialog_mode.test.js +17 -4
  39. data/app/packs/src/decidim/diff_mode_dropdown.js +3 -3
  40. data/app/packs/src/decidim/dropdowns_menus.js +1 -0
  41. data/app/packs/src/decidim/focus_guard.js +142 -0
  42. data/app/packs/src/decidim/form_filter.js +17 -1
  43. data/app/packs/src/decidim/form_remote.js +38 -0
  44. data/app/packs/src/decidim/index.js +15 -0
  45. data/app/packs/src/decidim/input_character_counter.js +4 -1
  46. data/app/packs/src/decidim/input_emoji.js +38 -6
  47. data/app/packs/src/decidim/input_multiple_mentions.js +19 -0
  48. data/app/packs/src/decidim/vendor/social-share-button.js +174 -0
  49. data/app/packs/stylesheets/decidim/extras/_quill.scss +1 -2
  50. data/app/packs/stylesheets/decidim/modules/_buttons.scss +2 -1
  51. data/app/packs/stylesheets/decidim/modules/_comments.scss +1 -0
  52. data/app/packs/stylesheets/decidim/modules/_forms.scss +6 -1
  53. data/app/packs/stylesheets/decidim/modules/_typography.scss +2 -0
  54. data/app/packs/stylesheets/decidim/utils/_settings.scss +1 -0
  55. data/app/packs/stylesheets/decidim/vendor/_social_share_button.scss +7 -1
  56. data/app/permissions/decidim/permissions.rb +9 -0
  57. data/app/presenters/decidim/menu_item_presenter.rb +9 -1
  58. data/app/views/decidim/account/show.html.erb +1 -1
  59. data/app/views/decidim/application/_collection.html.erb +2 -2
  60. data/app/views/decidim/endorsements/identities.html.erb +1 -1
  61. data/app/views/decidim/groups/new.html.erb +2 -0
  62. data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +1 -1
  63. data/app/views/decidim/messaging/conversations/_conversation.html.erb +8 -2
  64. data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
  65. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  66. data/app/views/decidim/messaging/conversations/create.js.erb +1 -0
  67. data/app/views/layouts/decidim/_language_chooser.html.erb +9 -2
  68. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  69. data/config/initializers/devise.rb +7 -19
  70. data/config/locales/ar.yml +63 -0
  71. data/config/locales/ca.yml +46 -2
  72. data/config/locales/cs.yml +10 -2
  73. data/config/locales/de.yml +12 -1
  74. data/config/locales/en.yml +9 -0
  75. data/config/locales/es-MX.yml +47 -0
  76. data/config/locales/es-PY.yml +47 -0
  77. data/config/locales/es.yml +2 -0
  78. data/config/locales/eu.yml +6 -0
  79. data/config/locales/fi-plain.yml +48 -0
  80. data/config/locales/fi.yml +10 -0
  81. data/config/locales/fr-CA.yml +16 -0
  82. data/config/locales/fr.yml +41 -25
  83. data/config/locales/gl.yml +51 -0
  84. data/config/locales/hu.yml +111 -0
  85. data/config/locales/it.yml +1 -0
  86. data/config/locales/ja.yml +16 -5
  87. data/config/locales/nl.yml +0 -3
  88. data/config/locales/no.yml +225 -0
  89. data/config/locales/ro-RO.yml +14 -0
  90. data/config/locales/sv.yml +45 -3
  91. data/db/seeds.rb +2 -2
  92. data/lib/decidim/api/functions/user_entity_finder.rb +2 -1
  93. data/lib/decidim/api/functions/user_entity_list.rb +2 -1
  94. data/lib/decidim/content_renderers/link_renderer.rb +1 -1
  95. data/lib/decidim/core/engine.rb +43 -0
  96. data/lib/decidim/core/test/shared_examples/amendable/amendment_accepted_event_examples.rb +0 -1
  97. data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +0 -1
  98. data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +0 -1
  99. data/lib/decidim/core/test/shared_examples/amendable/amendment_rejected_event_examples.rb +0 -1
  100. data/lib/decidim/core/test/shared_examples/comments_examples.rb +27 -0
  101. data/lib/decidim/core/test/shared_examples/conversations_examples.rb +19 -0
  102. data/lib/decidim/core/test/shared_examples/endorsable.rb +69 -0
  103. data/lib/decidim/core/test/shared_examples/searchable_results_examples.rb +34 -0
  104. data/lib/decidim/core/test.rb +2 -0
  105. data/lib/decidim/core/version.rb +1 -1
  106. data/lib/decidim/endorsable.rb +5 -1
  107. data/lib/decidim/map/autocomplete.rb +12 -5
  108. data/lib/decidim/middleware/rails_cookies.rb +23 -0
  109. data/lib/decidim/resourceable.rb +1 -0
  110. data/lib/decidim/searchable.rb +10 -4
  111. data/lib/decidim/social_share/service.rb +33 -0
  112. data/lib/decidim/social_share/service_registry.rb +63 -0
  113. data/lib/decidim/social_share.rb +45 -0
  114. data/lib/decidim/view_model.rb +0 -1
  115. data/lib/tasks/decidim_webpacker_tasks.rake +4 -10
  116. data/lib/tasks/upgrade/decidim_moderation_tasks.rake +32 -0
  117. metadata +22 -10
  118. data/app/helpers/decidim/filter_params_helper.rb +0 -30
  119. data/config/initializers/mail_previews.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dac5187d40c4a753efdf1ca3e005b5a0d6561fcde905fb50bbf054fac2eca159
4
- data.tar.gz: 6ed72398e69f803c6ab3b328ff9b26ec217769a2878349c00fbadf76b65e120e
3
+ metadata.gz: 53feb2cc6c5c494c20cf8e6ae1d35cc933ddf3a91ee2704b9b2fb6436b267c87
4
+ data.tar.gz: 431d81f9df34a6c1f0a88a3786f138e748e4cc9b5a706707493e7735a7cf782a
5
5
  SHA512:
6
- metadata.gz: 532bcf1725b00692cf50880c865cd74b5e81f13870f65db9d9b61c227fb78b997ad5b1eff984f041a900b9e117a29d3c62d72097506ddd15bd40320c7c839dc2
7
- data.tar.gz: dfe236abe5ba215792e259e1e93d54a82c8ac60120b2f4af166e1e86343aefc9cf3ba7eb743987ec65b96202accd6c8cf53d8aebc0f4fd9ac3e5d028f4f12ee0
6
+ metadata.gz: 69ec72cc2adbd4c88933c2c21aade155b7b98dc9708c85d9f0677b32621ce205c8b247109d96c0b13d3b7e6b96214eea3ac1c03e3aedfdaae2ca0afba7de96cd
7
+ data.tar.gz: 92caf28a3f0ea16de36d307a4ff484478d071a5b442a6848a09741c657b1bdf86f1c53c9ccf799920901fabb8aea5284f32e661c07d3d6830e77e8299c482557
@@ -95,6 +95,9 @@ module Decidim
95
95
  hash << I18n.locale.to_s
96
96
  hash << model.class.name.underscore
97
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
98
101
 
99
102
  hash.join(Decidim.cache_key_separator)
100
103
  end
@@ -66,6 +66,7 @@ module Decidim
66
66
 
67
67
  hash.push(I18n.locale)
68
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)
69
70
  hash.push(current_user.try(:id))
70
71
  hash.push(current_user.present?)
71
72
  hash.push(commentable?)
@@ -19,7 +19,7 @@ module Decidim
19
19
  private
20
20
 
21
21
  def resource_path
22
- resource_locator(model).path(filter_link_params)
22
+ resource_locator(model).path
23
23
  end
24
24
 
25
25
  def resource_image_path
@@ -4,21 +4,26 @@
4
4
  <%= t("versions.dropdown.choose_diff_view_mode") %>
5
5
  </span>
6
6
 
7
- <ul class="dropdown menu" data-dropdown-menu>
8
- <li class="is-dropdown-submenu-parent">
9
- <a id="diff-view-selected">
7
+ <ul class="dropdown menu" data-dropdown-menu
8
+ data-autoclose="false"
9
+ data-disable-hover="true"
10
+ data-click-open="true"
11
+ data-close-on-click="true"
12
+ role="menubar">
13
+ <li class="is-dropdown-submenu-parent" role="presentation">
14
+ <a href="#diffmode-chooser-menu" id="diff-view-selected" aria-controls="diffmode-chooser-menu" aria-haspopup="true" aria-label="<%= t("versions.dropdown.choose_diff_view_mode_menu") %>" role="menuitem">
10
15
  <%= t("versions.dropdown.option_unified") %>
11
16
  </a>
12
17
 
13
- <ul class="menu">
14
- <li>
15
- <%= link_to "#diff-view-unified", class: "diff-view-mode", id:"diff-view-unified" do %>
18
+ <ul class="menu is-dropdown-submenu" id="diffmode-chooser-menu" role="menu" aria-labelledby="diff-view-selected">
19
+ <li role="presentation">
20
+ <%= link_to "#diff-view-unified", class: "diff-view-mode", id:"diff-view-unified", role: "menuitem" do %>
16
21
  <%= t("versions.dropdown.option_unified") %>
17
22
  <% end %>
18
23
  </li>
19
24
 
20
- <li>
21
- <%= link_to "#diff-view-split", class: "diff-view-mode", id:"diff-view-split" do %>
25
+ <li role="presentation">
26
+ <%= link_to "#diff-view-split", class: "diff-view-mode", id:"diff-view-split", role: "menuitem" do %>
22
27
  <%= t("versions.dropdown.option_split") %>
23
28
  <% end %>
24
29
  </li>
@@ -5,21 +5,26 @@
5
5
  <%= t("versions.dropdown.choose_diff_view_html") %>
6
6
  </span>
7
7
 
8
- <ul class="dropdown menu" data-dropdown-menu>
9
- <li class="is-dropdown-submenu-parent">
10
- <a id="diff-view-selected">
8
+ <ul class="dropdown menu" data-dropdown-menu
9
+ data-autoclose="false"
10
+ data-disable-hover="true"
11
+ data-click-open="true"
12
+ data-close-on-click="true"
13
+ role="menubar">
14
+ <li class="is-dropdown-submenu-parent" role="presentation">
15
+ <a href="#htmlmode-chooser-menu" id="diff-view-html-selected" aria-controls="htmlmode-chooser-menu" aria-haspopup="true" aria-label="<%= t("versions.dropdown.choose_diff_view_mode_menu") %>" role="menuitem">
11
16
  <%= t("versions.dropdown.option_unescaped") %>
12
17
  </a>
13
18
 
14
- <ul class="menu">
15
- <li>
16
- <%= link_to "#unescaped-html", class: "diff-view-html", id:"unescaped-html" do %>
19
+ <ul class="menu is-dropdown-submenu" id="htmlmode-chooser-menu" role="menu" aria-labelledby="diff-view-html-selected">
20
+ <li role="presentation">
21
+ <%= link_to "#diff-view-unescaped-html", class: "diff-view-html", id: "diff-view-unescaped-html", role: "menuitem" do %>
17
22
  <%= t("versions.dropdown.option_unescaped") %>
18
23
  <% end %>
19
24
  </li>
20
25
 
21
- <li>
22
- <%= link_to "#escaped-html", class: "diff-view-html", id:"escaped-html" do %>
26
+ <li role="presentation">
27
+ <%= link_to "#diff-view-escaped-html", class: "diff-view-html", id: "diff-view-escaped-html", role: "menuitem" do %>
23
28
  <%= t("versions.dropdown.option_escaped") %>
24
29
  <% end %>
25
30
  </li>
@@ -1,6 +1,8 @@
1
1
  <%= render :diff_mode_dropdown %>
2
2
  <%= render :diff_mode_html %>
3
3
 
4
- <% diff_data.each do |data| %>
5
- <%= attribute(data) %>
6
- <% end %>
4
+ <div aria-live="polite">
5
+ <% diff_data.each do |data| %>
6
+ <%= attribute(data) %>
7
+ <% end %>
8
+ </div>
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # This cell renders the endrosement button and the endorsements count.
5
+ # It only supports one row of buttons per page due to current tag ids used by javascript.
6
+ class EndorsementButtonsCell < Decidim::ViewModel
7
+ include LayoutHelper
8
+ include CellsHelper
9
+ include EndorsableHelper
10
+ include ResourceHelper
11
+ include Decidim::SanitizeHelper
12
+
13
+ delegate :current_user, to: :controller, prefix: false
14
+ delegate :current_settings, to: :controller, prefix: false
15
+ delegate :current_component, to: :controller, prefix: false
16
+ delegate :allowed_to?, to: :controller, prefix: false
17
+
18
+ def show
19
+ render
20
+ end
21
+
22
+ # Public: Renders the "Endorse" button.
23
+ # Contains all the logic about how the button should be rendered
24
+ # and which actions the button must trigger.
25
+ #
26
+ # It takes into account:
27
+ # - if endorsements are enabled
28
+ # - if users are logged in
29
+ # - if users can endorse with many identities (of their user_groups)
30
+ # - if users require verification
31
+ def render_endorsements_button
32
+ render_disabled_endorsements_button if endorsements_blocked_or_user_can_not_participate?
33
+ render_user_login_button unless current_user
34
+ render "select_identity_button" if current_user_and_allowed? && user_has_verified_groups?
35
+ render_user_identity_endorse_button if current_user_and_allowed?
36
+
37
+ render_verification_modal
38
+ end
39
+
40
+ # Public: Renders the counter of endorsements that appears in m-cards.
41
+ def render_endorsements_count
42
+ content = icon("bullhorn", class: "icon--small", aria_label: t("decidim.endorsable.endorsements_count"), role: "img")
43
+ content += resource.endorsements_count.to_s
44
+ html_class = "button small compact button--shadow secondary"
45
+ html_class += " active" if fully_endorsed?(resource, current_user)
46
+ tag_params = { id: "resource-#{resource.id}-endorsements-count", class: html_class }
47
+ if resource.endorsements_count.positive?
48
+ link_to "#list-of-endorsements", tag_params do
49
+ content
50
+ end
51
+ else
52
+ content_tag(:div, tag_params) do
53
+ content
54
+ end
55
+ end
56
+ end
57
+
58
+ # Public: Renders the endorsements button but disabled.
59
+ # To be used to let the user know that endorsements are enabled but are blocked or cant participate.
60
+ def render_disabled_endorsements_button
61
+ content_tag :span, class: "#{card_button_html_class} #{endorsement_button_classes(from_resourcess_list: false)} disabled", disabled: true, title: endorse_translated do
62
+ endorse_translated + render_screen_reader_context_title
63
+ end
64
+ end
65
+
66
+ # Public: Render content for screen readers only (accessibility)
67
+ def render_screen_reader_context_title
68
+ content_tag :span, class: "show-for-sr" do
69
+ decidim_html_escape(resource_title(resource))
70
+ end
71
+ end
72
+
73
+ # Public: Returns the CSS classes used for proposal endorsement button in both proposals list and show pages
74
+ #
75
+ # from_resourcess_list - A boolean to indicate if the template is rendered from the list page of the resource.
76
+ #
77
+ # Returns a string with the value of the css classes.
78
+ def endorsement_button_classes(from_resourcess_list: false)
79
+ return "small" if from_resourcess_list
80
+
81
+ "button small compact light button--sc expanded secondary"
82
+ end
83
+
84
+ # Public: Returns the CSS classes used for proposal endorsement button
85
+ def card_button_html_class
86
+ "card__button button"
87
+ end
88
+
89
+ # Public: Renders a button to endorse the given +resource+ with the personal identity of the user.
90
+ # To override the translation for both buttons: endorse and unendorse (use to be the name of the user/user_group).
91
+ #
92
+ # This button may have different behaviours:
93
+ # - If the user is not logged in, the button will open the signin/signup popup.
94
+ # - If the user is logged in, and the resource has not been endorsed, the button will allow to endorse.
95
+ # - If the user is logged in, and the resource has already been endorsed, the button will allow to UNendorse.
96
+ #
97
+ # Parameters:
98
+ # resources - The endorsable resource.
99
+ def render_user_identity_endorse_button
100
+ content_tag(:div, id: "resource-#{resource.id}-endorsement-button") do
101
+ if !current_user
102
+ render_user_login_button
103
+ elsif resource.endorsed_by?(current_user)
104
+ unendorse_label = t("decidim.endorsement_buttons_cell.already_endorsed")
105
+ destroy_endorsement_url = path_to_destroy_endorsement(resource)
106
+ action_authorized_button_to(
107
+ :endorse,
108
+ destroy_endorsement_url,
109
+ resource: resource,
110
+ method: :delete,
111
+ remote: true,
112
+ class: "button #{endorsement_button_classes} active",
113
+ id: "endorsement_button"
114
+ ) do
115
+ unendorse_label + render_screen_reader_context_title
116
+ end
117
+ else
118
+ action_authorized_button_to(
119
+ :endorse,
120
+ path_to_create_endorsement(resource),
121
+ resource: resource,
122
+ remote: true,
123
+ class: "button #{endorsement_button_classes}",
124
+ id: "endorsement_button"
125
+ ) do
126
+ endorse_translated + render_screen_reader_context_title
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ # Public: The resource being un/endorsed is the Cell's model.
133
+ def resource
134
+ model
135
+ end
136
+
137
+ # Public: produce the reveal identities URL as the cell doesn't have access to routes
138
+ def reveal_identities_url
139
+ decidim.identities_endorsement_path(resource.to_gid.to_param)
140
+ end
141
+
142
+ # Public: produce the path to endorsements from the engine routes as the cell doesn't have access to routes
143
+ def endorsements_path(*args)
144
+ decidim.endorsements_path(*args)
145
+ end
146
+
147
+ # Public: produce the path to an endorsement from the engine routes as the cell doesn't have access to routes
148
+ def endorsement_path(*args)
149
+ decidim.endorsement_path(*args)
150
+ end
151
+
152
+ # Public; returns the identity presenter for user and user groups
153
+ def endorsement_identity_presenter(endorsement)
154
+ if endorsement.user_group
155
+ Decidim::UserGroupPresenter.new(endorsement.user_group)
156
+ else
157
+ Decidim::UserPresenter.new(endorsement.author)
158
+ end
159
+ end
160
+
161
+ private
162
+
163
+ # Private: render the user login button for visitors (non logged in users)
164
+ def render_user_login_button
165
+ action_authorized_button_to(:endorse,
166
+ path_to_create_endorsement(resource),
167
+ resource: resource,
168
+ class: "button #{endorsement_button_classes}") do
169
+ endorse_translated + render_screen_reader_context_title
170
+ end
171
+ end
172
+
173
+ # Private: render the verification modal when there's a current user that needs an authorization
174
+ def render_verification_modal
175
+ button_to(endorsement_path(resource),
176
+ data: { open: "authorizationModal", "open-url": modal_path(:endorse, resource) },
177
+ class: "#{card_button_html_class} #{endorsement_button_classes(from_resourcess_list: false)}") do
178
+ endorse_translated + render_screen_reader_context_title
179
+ end
180
+ end
181
+
182
+ # Private: check if the endorsements are blocked or the user can't participate
183
+ #
184
+ # Returns a boolean
185
+ def endorsements_blocked_or_user_can_not_participate?
186
+ current_settings.endorsements_blocked? || !current_component.participatory_space.can_participate?(current_user)
187
+ end
188
+
189
+ # Private: check if there's an user logged in and they have permissions
190
+ #
191
+ # Returns a boolean
192
+ def current_user_and_allowed?
193
+ current_user && allowed_to?(:create, :endorsement, resource: resource)
194
+ end
195
+
196
+ # Private: check if there's an user logged in and they have user groups associated
197
+ #
198
+ # Returns a boolean
199
+ def user_has_verified_groups?
200
+ current_user && Decidim::UserGroups::ManageableUserGroups.for(current_user).verified.any?
201
+ end
202
+
203
+ def endorse_translated
204
+ @endorse_translated ||= t("decidim.endorsement_buttons_cell.endorse")
205
+ end
206
+
207
+ def raw_model
208
+ model.try(:__getobj__) || model
209
+ end
210
+ end
211
+ end
@@ -1,7 +1,7 @@
1
1
  <div id="list-of-endorsements" class="section">
2
2
  <div class="row">
3
3
  <div class="columns large-12">
4
- <h4 class="section-heading"><%= t("decidim.proposals.proposals.show.endorsements_list") %></h4>
4
+ <h3 class="section-heading"><%= t("decidim.proposals.proposals.show.endorsements_list") %></h3>
5
5
  </div>
6
6
  <div class="columns large-12">
7
7
  <%= cell(
@@ -3,7 +3,7 @@
3
3
  </div>
4
4
 
5
5
  <div id="<%= modal_name %>" class="reveal fingerprint-dialog" data-reveal aria-labelledby="modalTitle" aria-hidden="true" role="dialog">
6
- <h2 id="modalTitle"><%= t "decidim.fingerprint.title" %></h2>
6
+ <h2 id="modalTitle" class="reveal__title"><%= t "decidim.fingerprint.title" %></h2>
7
7
  <p><%= t "decidim.fingerprint.explanation" %></p>
8
8
  <p>
9
9
  <strong><%= t "decidim.fingerprint.value" %>:</strong>
@@ -1,4 +1,4 @@
1
- <div class="empty-notifications callout secondary <%= "hide" if followers.any? %>">
1
+ <div class="callout secondary <%= "hide" if followers.any? %>">
2
2
  <p><%= t("decidim.followers.no_followers") %></p>
3
3
  </div>
4
4
  <div class="row small-up-1 medium-up-2 card-grid">
@@ -1,6 +1,6 @@
1
1
  <% if public_followings.any? %>
2
2
  <% if non_public_followings? %>
3
- <div class="empty-notifications callout secondary">
3
+ <div class="callout secondary">
4
4
  <p><%= t("decidim.following.non_public_followings") %></p>
5
5
  </div>
6
6
  <% end %>
@@ -12,7 +12,7 @@
12
12
  </div>
13
13
  <%= decidim_paginate public_followings %>
14
14
  <% else %>
15
- <div class="empty-notifications callout secondary">
15
+ <div class="callout secondary">
16
16
  <p><%= t("decidim.following.no_followings") %></p>
17
17
  </div>
18
18
  <% end %>
@@ -1,5 +1,5 @@
1
1
  <%= cell "decidim/user_group_pending_invitations_list", model %>
2
- <div class="empty-notifications callout secondary <%= "hide" if user_groups.any? %>">
2
+ <div class="callout secondary <%= "hide" if user_groups.any? %>">
3
3
  <p><%= t("decidim.groups.no_user_groups") %></p>
4
4
  </div>
5
5
  <div class="row small-up-1 medium-up-2 card-grid">
@@ -1,4 +1,4 @@
1
- <div class="empty-notifications callout secondary <%= "hide" if memberships.any? %>">
1
+ <div class="callout secondary <%= "hide" if memberships.any? %>">
2
2
  <p><%= t("decidim.members.no_members") %></p>
3
3
  </div>
4
4
  <div class="row small-up-1 medium-up-2 card-grid">
@@ -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 noreferrer ugc" %>
27
27
  <% end %>
28
28
  </div>
29
29
  <% if profile_user.badge.present? %>
@@ -1,6 +1,6 @@
1
1
  <div class="conversation-chat<%= " conversation-chat--offset" if sender_is_user?(sender) %>">
2
2
  <%= link_to sender.personal_url do %>
3
- <%= image_tag sender.attached_uploader(:avatar).url(host: current_organization.host), alt: t("decidim.author.avatar", name: decidim_sanitize(sender.name)) %>
3
+ <%= image_tag avatar_url_for(sender), alt: t("decidim.author.avatar", name: decidim_sanitize(sender.name)) %>
4
4
  <% end %>
5
5
  <div>
6
6
  <% messages.each do |message| %>
@@ -37,6 +37,10 @@ module Decidim
37
37
  user.id == sender.id
38
38
  end
39
39
 
40
+ def avatar_url_for(sender)
41
+ present(sender).avatar_url
42
+ end
43
+
40
44
  def conversation_avatar
41
45
  if interlocutors.count == 1
42
46
  present(interlocutors.first).avatar_url
@@ -2,7 +2,7 @@
2
2
  <div class="wrapper wrapper--inner">
3
3
  <div class="row">
4
4
  <div class="large-12">
5
- <h2 id="modalTitle"> <%= t "decidim.user_conversations.index.modal_title" %> </h2>
5
+ <h2 id="modalTitle" class="reveal__title"><%= t "decidim.user_conversations.index.modal_title" %></h2>
6
6
  </div>
7
7
  </div>
8
8
  <div class="row">
@@ -77,7 +77,7 @@ module Decidim
77
77
  end
78
78
 
79
79
  def resource_path
80
- resource_locator(versioned_resource).path(filter_link_params)
80
+ resource_locator(versioned_resource).path
81
81
  end
82
82
  end
83
83
  end
@@ -13,7 +13,7 @@ module Decidim
13
13
  end
14
14
 
15
15
  def resource_path
16
- resource_locator(versioned_resource).path(filter_link_params)
16
+ resource_locator(versioned_resource).path
17
17
  end
18
18
 
19
19
  def i18n_changes_title
@@ -2,9 +2,9 @@
2
2
  <div class="card--list__text">
3
3
  <div>
4
4
  <%= link_to version_path do %>
5
- <h6 class="card--list__heading heading6">
5
+ <h4 class="card--list__heading heading6">
6
6
  <%= i18n_version_index %>
7
- </h6>
7
+ </h4>
8
8
  <% end %>
9
9
  <div class="author-data">
10
10
  <%= render_resource_editor(version) %>
@@ -20,7 +20,10 @@ module Decidim
20
20
  #
21
21
  # Returns nothing.
22
22
  def call
23
- return broadcast(:invalid) if form.invalid?
23
+ if form.invalid?
24
+ message.valid?
25
+ return broadcast(:invalid, message.errors.full_messages)
26
+ end
24
27
 
25
28
  if message.save
26
29
  notify_interlocutors
@@ -28,10 +28,11 @@ module Decidim
28
28
  private
29
29
 
30
30
  def destroy_resource_endorsement
31
- query = @resource.endorsements.where(
32
- author: @current_user,
33
- decidim_user_group_id: @current_group&.id
34
- )
31
+ query = if @current_group.present?
32
+ @resource.endorsements.where(decidim_user_group_id: @current_group&.id)
33
+ else
34
+ @resource.endorsements.where(author: @current_user)
35
+ end
35
36
  query.destroy_all
36
37
  end
37
38
  end
@@ -33,6 +33,7 @@ module Decidim
33
33
  helper Decidim::ViewHooksHelper
34
34
  helper Decidim::CardHelper
35
35
  helper Decidim::SanitizeHelper
36
+ helper Decidim::TwitterSearchHelper
36
37
 
37
38
  register_permissions(::Decidim::ApplicationController,
38
39
  ::Decidim::Admin::Permissions,
@@ -24,7 +24,6 @@ module Decidim
24
24
  helper Decidim::AttachmentsHelper
25
25
  helper Decidim::SanitizeHelper
26
26
  helper Decidim::PadHelper
27
- helper Decidim::FilterParamsHelper
28
27
 
29
28
  helper_method :current_component,
30
29
  :current_participatory_space,
@@ -6,7 +6,7 @@ module Decidim::Amendable
6
6
  :emendation_path, :emendation_author_nickname, :emendation_author_path
7
7
 
8
8
  def amendable_title
9
- @amendable_title ||= amendable_resource.title
9
+ @amendable_title ||= translated_attribute(amendable_resource.title)
10
10
  end
11
11
 
12
12
  def amendable_type
@@ -8,7 +8,7 @@ module Decidim
8
8
 
9
9
  attribute :body, Decidim::Attributes::CleanString
10
10
 
11
- validates :body, presence: true
11
+ validates :body, presence: true, length: { maximum: Decidim.config.maximum_conversation_message_length }
12
12
  end
13
13
  end
14
14
  end
@@ -76,12 +76,13 @@ module Decidim
76
76
  # user - The user that is endorsing at the end (mandatory).
77
77
  # user_group - The user_group on behalf of which the endorsement is being done (optional).
78
78
  def render_endorsement_identity(resource, user, user_group = nil)
79
- presenter = if user_group
80
- Decidim::UserGroupPresenter.new(user_group)
81
- else
82
- Decidim::UserPresenter.new(user)
83
- end
84
- selected = resource.endorsed_by?(user, user_group)
79
+ if user_group
80
+ presenter = Decidim::UserGroupPresenter.new(user_group)
81
+ selected = resource.endorsed_by?(user, user_group)
82
+ else
83
+ presenter = Decidim::UserPresenter.new(user)
84
+ selected = resource.endorsed_by?(user)
85
+ end
85
86
  http_method = selected ? :delete : :post
86
87
  render partial: "decidim/endorsements/identity", locals:
87
88
  { identity: presenter, selected: selected,
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ # A Helper that reimplements the SocialShareButton gem helpers, so that we don't depend on it anymore.
5
+ module SocialShareButtonHelper
6
+ def social_share_button_tag(title, **args)
7
+ content_tag :div, class: "social-share-button" do
8
+ render_social_share_buttons(enabled_services, title, **args)
9
+ end
10
+ end
11
+
12
+ def render_social_share_buttons(services, title, **args)
13
+ services.map do |service|
14
+ link_to service.formatted_share_uri(title, **args), rel: "nofollow", class: "ssb-icon ssb-#{service.name}", title: t(".share_on", service: service.name) do
15
+ image_tag service.icon_path
16
+ end
17
+ end.join.html_safe
18
+ end
19
+
20
+ private
21
+
22
+ def enabled_services
23
+ Decidim::SocialShare.enabled_services
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TwitterSearchHelper
5
+ # Builds the URL for Twitter's hashtag search.
6
+ #
7
+ # @param hashtag [String] The hasthag to search
8
+ #
9
+ # @return [String]
10
+ def twitter_hashtag_url(hashtag)
11
+ format("https://twitter.com/hashtag/%{hashtag}?src=hash", hashtag: hashtag)
12
+ end
13
+ end
14
+ end
@@ -12,6 +12,9 @@ module Decidim
12
12
 
13
13
  delegate :component, :organization, to: :reportable
14
14
 
15
+ scope :hidden, -> { where.not(hidden_at: nil) }
16
+ scope :not_hidden, -> { where(hidden_at: nil) }
17
+
15
18
  def self.log_presenter_class_for(_log)
16
19
  Decidim::AdminLog::ModerationPresenter
17
20
  end
@@ -50,9 +50,6 @@ module Decidim
50
50
 
51
51
  validate :all_roles_are_valid
52
52
 
53
- has_one_attached :avatar
54
- validates_upload :avatar, uploader: Decidim::AvatarUploader
55
-
56
53
  has_one_attached :data_portability_file
57
54
 
58
55
  scope :not_deleted, -> { where(deleted_at: nil) }
@@ -63,12 +60,6 @@ module Decidim
63
60
  scope :officialized, -> { where.not(officialized_at: nil) }
64
61
  scope :not_officialized, -> { where(officialized_at: nil) }
65
62
 
66
- scope :confirmed, -> { where.not(confirmed_at: nil) }
67
- scope :not_confirmed, -> { where(confirmed_at: nil) }
68
-
69
- scope :blocked, -> { where(blocked: true) }
70
- scope :not_blocked, -> { where(blocked: false) }
71
-
72
63
  scope :interested_in_scopes, lambda { |scope_ids|
73
64
  actual_ids = scope_ids.select(&:presence)
74
65
  if actual_ids.count.positive?