decidim-core 0.26.0 → 0.26.1

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/card_m_cell.rb +1 -1
  3. data/app/cells/decidim/diff/diff_mode_dropdown.erb +13 -8
  4. data/app/cells/decidim/diff/diff_mode_html.erb +13 -8
  5. data/app/cells/decidim/diff/show.erb +5 -3
  6. data/app/cells/decidim/endorsement_buttons_cell.rb.2 +211 -0
  7. data/app/cells/decidim/endorsers_list/show.erb +1 -1
  8. data/app/cells/decidim/fingerprint/show.erb +1 -1
  9. data/app/cells/decidim/followers/show.erb +1 -1
  10. data/app/cells/decidim/following/show.erb +2 -2
  11. data/app/cells/decidim/groups/show.erb +1 -1
  12. data/app/cells/decidim/members/show.erb +1 -1
  13. data/app/cells/decidim/profile_sidebar/show.erb +1 -1
  14. data/app/cells/decidim/user_conversation/messages.erb +1 -1
  15. data/app/cells/decidim/user_conversation_cell.rb +4 -0
  16. data/app/cells/decidim/user_conversations/add_conversation_users.erb +1 -1
  17. data/app/cells/decidim/version_cell.rb +1 -1
  18. data/app/cells/decidim/versions_list_cell.rb +1 -1
  19. data/app/cells/decidim/versions_list_item/show.erb +2 -2
  20. data/app/commands/decidim/messaging/reply_to_conversation.rb +4 -1
  21. data/app/commands/decidim/unendorse_resource.rb +5 -4
  22. data/app/controllers/decidim/application_controller.rb +1 -0
  23. data/app/controllers/decidim/components/base_controller.rb +0 -1
  24. data/app/events/decidim/amendable/amendment_base_event.rb +1 -1
  25. data/app/forms/decidim/messaging/message_form.rb +1 -1
  26. data/app/helpers/decidim/endorsable_helper.rb +7 -6
  27. data/app/helpers/decidim/social_share_button_helper.rb +26 -0
  28. data/app/helpers/decidim/twitter_search_helper.rb +14 -0
  29. data/app/packs/entrypoints/decidim_core.js +3 -0
  30. data/app/packs/src/decidim/back_to_list.js +26 -0
  31. data/app/packs/src/decidim/dialog_mode.js +11 -99
  32. data/app/packs/src/decidim/dialog_mode.test.js +17 -4
  33. data/app/packs/src/decidim/diff_mode_dropdown.js +3 -3
  34. data/app/packs/src/decidim/dropdowns_menus.js +1 -0
  35. data/app/packs/src/decidim/focus_guard.js +142 -0
  36. data/app/packs/src/decidim/form_filter.js +17 -1
  37. data/app/packs/src/decidim/form_remote.js +38 -0
  38. data/app/packs/src/decidim/index.js +15 -0
  39. data/app/packs/src/decidim/input_character_counter.js +4 -1
  40. data/app/packs/src/decidim/input_emoji.js +28 -5
  41. data/app/packs/src/decidim/input_multiple_mentions.js +19 -0
  42. data/app/packs/src/decidim/vendor/social-share-button.js +174 -0
  43. data/app/packs/stylesheets/decidim/modules/_buttons.scss +2 -1
  44. data/app/packs/stylesheets/decidim/modules/_forms.scss +6 -1
  45. data/app/packs/stylesheets/decidim/modules/_typography.scss +2 -0
  46. data/app/packs/stylesheets/decidim/utils/_settings.scss +1 -0
  47. data/app/packs/stylesheets/decidim/vendor/_social_share_button.scss +7 -1
  48. data/app/presenters/decidim/menu_item_presenter.rb +9 -1
  49. data/app/views/decidim/account/show.html.erb +1 -1
  50. data/app/views/decidim/application/_collection.html.erb +2 -2
  51. data/app/views/decidim/endorsements/identities.html.erb +1 -1
  52. data/app/views/decidim/groups/new.html.erb +2 -0
  53. data/app/views/decidim/messaging/conversations/_add_conversation_users.html.erb +1 -1
  54. data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
  55. data/app/views/decidim/messaging/conversations/_start.html.erb +1 -1
  56. data/app/views/decidim/messaging/conversations/create.js.erb +1 -0
  57. data/app/views/layouts/decidim/_language_chooser.html.erb +9 -2
  58. data/app/views/layouts/decidim/_logo.html.erb +1 -1
  59. data/config/initializers/devise.rb +7 -19
  60. data/config/locales/ar.yml +55 -0
  61. data/config/locales/cs.yml +8 -0
  62. data/config/locales/de.yml +12 -1
  63. data/config/locales/en.yml +8 -0
  64. data/config/locales/fi-plain.yml +7 -0
  65. data/config/locales/fi.yml +8 -0
  66. data/config/locales/fr-CA.yml +8 -0
  67. data/config/locales/fr.yml +8 -0
  68. data/config/locales/gl.yml +10 -0
  69. data/config/locales/hu.yml +10 -0
  70. data/config/locales/it.yml +1 -0
  71. data/config/locales/ja.yml +13 -5
  72. data/db/seeds.rb +2 -2
  73. data/lib/decidim/content_renderers/link_renderer.rb +1 -1
  74. data/lib/decidim/core/engine.rb +43 -0
  75. data/lib/decidim/core/test/shared_examples/amendable/amendment_accepted_event_examples.rb +0 -1
  76. data/lib/decidim/core/test/shared_examples/amendable/amendment_created_event_examples.rb +0 -1
  77. data/lib/decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples.rb +0 -1
  78. data/lib/decidim/core/test/shared_examples/amendable/amendment_rejected_event_examples.rb +0 -1
  79. data/lib/decidim/core/test/shared_examples/comments_examples.rb +27 -0
  80. data/lib/decidim/core/test/shared_examples/conversations_examples.rb +19 -0
  81. data/lib/decidim/core/test/shared_examples/endorsable.rb +69 -0
  82. data/lib/decidim/core/test.rb +2 -0
  83. data/lib/decidim/core/version.rb +1 -1
  84. data/lib/decidim/endorsable.rb +5 -1
  85. data/lib/decidim/middleware/rails_cookies.rb +23 -0
  86. data/lib/decidim/social_share/service.rb +33 -0
  87. data/lib/decidim/social_share/service_registry.rb +63 -0
  88. data/lib/decidim/social_share.rb +45 -0
  89. data/lib/decidim/view_model.rb +0 -1
  90. metadata +19 -8
  91. data/app/helpers/decidim/filter_params_helper.rb +0 -30
  92. data/config/initializers/mail_previews.rb +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f92f8225a3998e9e26e1c147c90eafb9ebb90a7c153e300b3ea2b9695e63e2ba
4
- data.tar.gz: 8c3eb2093ab824160548f3089e3b5ba68536a7231892f2c2484aa384c49307b5
3
+ metadata.gz: 53feb2cc6c5c494c20cf8e6ae1d35cc933ddf3a91ee2704b9b2fb6436b267c87
4
+ data.tar.gz: 431d81f9df34a6c1f0a88a3786f138e748e4cc9b5a706707493e7735a7cf782a
5
5
  SHA512:
6
- metadata.gz: 1abf1ab6e14a84745b3bb8fd176f002b7fd65ecbd497b1e4544202b517d265a2eded3d628e0ab27ed53f2385849da158f31571af32181e68cb7df02ee60844a4
7
- data.tar.gz: 9f0209ace6ff368bd4dfb87d3b28c704d4ba1726abf8bfe29efab5a0aa52babb06eb214a6bee663d1b6d6728f9c4fff222ff83008b0f44cb868b5d575437be32
6
+ metadata.gz: 69ec72cc2adbd4c88933c2c21aade155b7b98dc9708c85d9f0677b32621ce205c8b247109d96c0b13d3b7e6b96214eea3ac1c03e3aedfdaae2ca0afba7de96cd
7
+ data.tar.gz: 92caf28a3f0ea16de36d307a4ff484478d071a5b442a6848a09741c657b1bdf86f1c53c9ccf799920901fabb8aea5284f32e661c07d3d6830e77e8299c482557
@@ -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, rel: "nofollow noopener" %>
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
@@ -13,6 +13,7 @@ window.morphdom = morphdom
13
13
  import "src/decidim/vendor/foundation-datepicker"
14
14
  import "src/decidim/foundation_datepicker_locales"
15
15
  import "src/decidim/vendor/modernizr"
16
+ import "src/decidim/vendor/social-share-button"
16
17
  import "social-share-button"
17
18
 
18
19
  import "src/decidim/input_tags"
@@ -33,6 +34,7 @@ import "src/decidim/dropdowns_menus"
33
34
  import "src/decidim/append_redirect_url_to_modals"
34
35
  import "src/decidim/form_attachments"
35
36
  import "src/decidim/form_validator"
37
+ import "src/decidim/form_remote"
36
38
  import "src/decidim/ajax_modals"
37
39
  import "src/decidim/conferences"
38
40
  import "src/decidim/tooltip_keep_on_hover"
@@ -55,6 +57,7 @@ import "src/decidim/start_conversation_dialog"
55
57
  import "src/decidim/notifications"
56
58
  import "src/decidim/identity_selector_dialog"
57
59
  import "src/decidim/gallery"
60
+ import "src/decidim/back_to_list"
58
61
 
59
62
  // CSS
60
63
  import "entrypoints/decidim_core.scss"
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Changes "Back to list" links to the one saved in sessionStorage API
3
+ * To apply this to a link, at least one element must have the class "js-back-to-list".
4
+ * For this to work it needs the filteredParams in SessionStorage, that's saved on FormFilterComponent.
5
+ * @param {NodeList} links - Hyperlinks elements that point to the filters page that will use the fitererd params
6
+ * @returns {void}
7
+ */
8
+ export default function backToListLink(links) {
9
+
10
+ if (!links) {
11
+ return;
12
+ }
13
+
14
+ if (!window.sessionStorage) {
15
+ return;
16
+ }
17
+
18
+ const filteredParams = JSON.parse(sessionStorage.getItem("filteredParams")) || {};
19
+ links.forEach((link) => {
20
+ const href = link.getAttribute("href");
21
+ if (filteredParams[href]) {
22
+ link.setAttribute("href", filteredParams[href]);
23
+ }
24
+ });
25
+
26
+ }