decidim-core 0.25.2 → 0.26.0.rc1
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.
- checksums.yaml +4 -4
- data/app/cells/decidim/activity_cell.rb +2 -1
- data/app/cells/decidim/author/flag_user.erb +1 -1
- data/app/cells/decidim/author/profile_inline.erb +1 -1
- data/app/cells/decidim/author/withdraw.erb +2 -2
- data/app/cells/decidim/author_cell.rb +32 -0
- data/app/cells/decidim/card_m_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/cta_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/hero_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
- data/app/cells/decidim/content_blocks/last_activity_cell.rb +1 -1
- data/app/cells/decidim/content_blocks/stats_cell.rb +12 -0
- data/app/cells/decidim/endorsers_list_cell.rb +3 -1
- data/app/cells/decidim/flag_modal/flag_user.erb +2 -2
- data/app/cells/decidim/flag_modal/show.erb +2 -2
- data/app/cells/decidim/flag_modal_cell.rb +10 -0
- data/app/cells/decidim/notification/show.erb +31 -0
- data/app/cells/decidim/notification_cell.rb +20 -0
- data/app/cells/decidim/notifications/show.erb +1 -24
- data/app/cells/decidim/notifications_cell.rb +0 -1
- data/app/cells/decidim/user_conversation/conversation_header.erb +1 -1
- data/app/cells/decidim/user_conversation/show.erb +4 -2
- data/app/cells/decidim/user_conversations/conversation_item.erb +1 -1
- data/app/commands/decidim/create_editor_image.rb +41 -0
- data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
- data/app/controllers/decidim/editor_images_controller.rb +47 -0
- data/app/controllers/decidim/user_activities_controller.rb +2 -1
- data/app/forms/decidim/editor_image_form.rb +16 -0
- data/app/helpers/decidim/amendments_helper.rb +1 -1
- data/app/helpers/decidim/application_helper.rb +2 -2
- data/app/helpers/decidim/messaging/conversation_helper.rb +32 -3
- data/app/helpers/decidim/resource_versions_helper.rb +1 -1
- data/app/helpers/decidim/sanitize_helper.rb +65 -0
- data/app/models/decidim/editor_image.rb +14 -0
- data/app/models/decidim/messaging/conversation.rb +9 -0
- data/app/models/decidim/participatory_space_private_user.rb +16 -0
- data/app/models/decidim/user.rb +3 -3
- data/app/models/decidim/user_group.rb +40 -0
- data/app/packs/entrypoints/decidim_core.js +1 -0
- data/app/packs/src/decidim/dialog_mode.js +143 -0
- data/app/packs/src/decidim/dialog_mode.test.js +168 -0
- data/app/packs/src/decidim/editor.js +56 -14
- data/app/packs/src/decidim/form_attachments.js +5 -0
- data/app/packs/src/decidim/index.js +4 -0
- data/app/packs/src/decidim/vendor/image-resize.min.js +3 -0
- data/app/packs/src/decidim/vendor/image-upload.min.js +8 -0
- data/app/packs/stylesheets/decidim/extras/_extras.scss +0 -1
- data/app/packs/stylesheets/decidim/extras/_quill.scss +7 -0
- data/app/packs/stylesheets/decidim/modules/_buttons.scss +11 -4
- data/app/packs/stylesheets/decidim/modules/_cards.scss +4 -0
- data/app/packs/stylesheets/decidim/modules/_layout.scss +1 -1
- data/app/presenters/decidim/nil_presenter.rb +2 -2
- data/app/presenters/decidim/notification_presenter.rb +25 -0
- data/app/presenters/decidim/official_author_presenter.rb +1 -1
- data/app/presenters/decidim/validation_errors_presenter.rb +27 -0
- data/app/queries/decidim/similar_emendations.rb +1 -1
- data/app/resolvers/decidim/core/metric_resolver.rb +1 -1
- data/app/services/decidim/activity_search.rb +2 -2
- data/app/services/decidim/email_notification_generator.rb +4 -1
- data/app/services/decidim/html_truncation.rb +130 -0
- data/app/services/decidim/open_data_exporter.rb +29 -5
- data/app/services/decidim/resource_search.rb +1 -1
- data/app/uploaders/decidim/editor_image_uploader.rb +6 -0
- data/app/validators/password_validator.rb +123 -0
- data/app/views/decidim/account/_password_fields.html.erb +1 -1
- data/app/views/decidim/devise/passwords/edit.html.erb +1 -1
- data/app/views/decidim/devise/registrations/new.html.erb +1 -1
- data/app/views/decidim/devise/shared/_omniauth_buttons_mini.html.erb +6 -4
- data/app/views/decidim/messaging/conversations/_conversation.html.erb +3 -3
- data/app/views/decidim/messaging/conversations/_messages.html.erb +8 -2
- data/app/views/decidim/messaging/conversations/_show.html.erb +10 -12
- data/app/views/decidim/messaging/conversations/show.html.erb +4 -2
- data/app/views/decidim/newsletters/show.html.erb +1 -1
- data/app/views/decidim/notification_mailer/event_received.html.erb +17 -0
- data/app/views/decidim/pages/_tabbed.html.erb +1 -1
- data/app/views/decidim/searches/_filters_small_view.html.erb +3 -3
- data/app/views/decidim/shared/_login_modal.html.erb +5 -5
- data/app/views/decidim/shared/_orders.html.erb +1 -1
- data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
- data/app/views/decidim/shared/participatory_space_filters/_filters_small_view.html.erb +3 -3
- data/app/views/layouts/decidim/_application.html.erb +1 -12
- data/app/views/layouts/decidim/_head.html.erb +4 -0
- data/app/views/layouts/decidim/_language_chooser.html.erb +1 -1
- data/app/views/layouts/decidim/_meta_tags_config.html.erb +11 -0
- data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
- data/config/brakeman.ignore +149 -0
- data/config/initializers/devise.rb +1 -1
- data/config/initializers/rack_attack.rb +23 -21
- data/config/locales/ca.yml +2 -0
- data/config/locales/cs.yml +60 -0
- data/config/locales/en.yml +45 -0
- data/config/locales/es.yml +45 -0
- data/config/locales/eu.yml +5 -0
- data/config/locales/fi-plain.yml +6 -0
- data/config/locales/fi.yml +45 -0
- data/config/locales/fr-CA.yml +38 -0
- data/config/locales/fr.yml +44 -6
- data/config/locales/gl.yml +5 -0
- data/config/locales/it.yml +11 -0
- data/config/locales/ja.yml +72 -36
- data/config/locales/lb-LU.yml +1354 -0
- data/config/locales/lb.yml +1 -1
- data/config/locales/nl.yml +54 -0
- data/config/locales/pl.yml +5 -5
- data/config/locales/pt-BR.yml +1 -1
- data/config/locales/ro-RO.yml +8 -0
- data/config/locales/sv.yml +5 -0
- data/config/locales/val-ES.yml +1 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20210730112319_create_decidim_editor_images.rb +12 -0
- data/db/migrate/20211126183540_add_timestamps_to_content_blocks.rb +14 -0
- data/db/seeds.rb +16 -14
- data/lib/decidim/api/functions/user_entity_list.rb +1 -0
- data/lib/decidim/api/input_sorts/component_input_sort.rb +1 -1
- data/lib/decidim/common_passwords.rb +56 -0
- data/lib/decidim/content_parsers/inline_images_parser.rb +68 -0
- data/lib/decidim/content_parsers.rb +1 -0
- data/lib/decidim/content_renderers/link_renderer.rb +85 -1
- data/lib/decidim/content_renderers/user_group_renderer.rb +1 -1
- data/lib/decidim/content_renderers/user_renderer.rb +1 -1
- data/lib/decidim/core/engine.rb +3 -12
- data/lib/decidim/core/test/factories.rb +7 -1
- data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +131 -0
- data/lib/decidim/core/test.rb +1 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/core.rb +22 -5
- data/lib/decidim/db/common-passwords.txt +128420 -0
- data/lib/decidim/etherpad/pad.rb +48 -0
- data/lib/decidim/etherpad.rb +7 -0
- data/lib/decidim/events/base_event.rb +18 -0
- data/lib/decidim/events/machine_translated_event.rb +36 -0
- data/lib/decidim/events/user_group_event.rb +1 -3
- data/lib/decidim/events.rb +1 -0
- data/lib/decidim/exporters/csv.rb +7 -7
- data/lib/decidim/faker/localized.rb +15 -6
- data/lib/decidim/form_builder.rb +14 -4
- data/lib/decidim/has_attachments.rb +11 -4
- data/lib/decidim/importers/import_manifest.rb +103 -3
- data/lib/decidim/paddable.rb +1 -9
- data/lib/decidim/searchable.rb +2 -2
- data/lib/decidim/settings_manifest.rb +2 -0
- data/lib/decidim/translatable_attributes.rb +6 -6
- data/lib/decidim/view_model.rb +10 -0
- data/lib/tasks/decidim_active_storage_migration_tasks.rake +68 -0
- metadata +56 -65
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dac5187d40c4a753efdf1ca3e005b5a0d6561fcde905fb50bbf054fac2eca159
|
|
4
|
+
data.tar.gz: 6ed72398e69f803c6ab3b328ff9b26ec217769a2878349c00fbadf76b65e120e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 532bcf1725b00692cf50880c865cd74b5e81f13870f65db9d9b61c227fb78b997ad5b1eff984f041a900b9e117a29d3c62d72097506ddd15bd40320c7c839dc2
|
|
7
|
+
data.tar.gz: dfe236abe5ba215792e259e1e93d54a82c8ac60120b2f4af166e1e86343aefc9cf3ba7eb743987ec65b96202accd6c8cf53d8aebc0f4fd9ac3e5d028f4f12ee0
|
|
@@ -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="
|
|
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:
|
|
3
|
-
<%= t("
|
|
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,28 @@ 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(current_user.try(:id))
|
|
70
|
+
hash.push(current_user.present?)
|
|
71
|
+
hash.push(commentable?)
|
|
72
|
+
hash.push(endorsable?)
|
|
73
|
+
hash.push(actionable?)
|
|
74
|
+
hash.push(withdrawable?)
|
|
75
|
+
hash.push(flaggable?)
|
|
76
|
+
hash.push(profile_path?)
|
|
77
|
+
hash.join(Decidim.cache_key_separator)
|
|
78
|
+
end
|
|
79
|
+
|
|
60
80
|
def from_context_path
|
|
61
81
|
resource_locator(from_context).path
|
|
62
82
|
end
|
|
@@ -111,5 +131,17 @@ module Decidim
|
|
|
111
131
|
def raw_model
|
|
112
132
|
model.try(:__getobj__) || model
|
|
113
133
|
end
|
|
134
|
+
|
|
135
|
+
def resource_i18n_scope
|
|
136
|
+
@resource_i18n_scope ||= [
|
|
137
|
+
from_context.class.name.deconstantize.underscore.gsub("/", "."),
|
|
138
|
+
resource_name.pluralize,
|
|
139
|
+
:show
|
|
140
|
+
].join(".")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def resource_name
|
|
144
|
+
@resource_name ||= from_context.class.name.demodulize.underscore
|
|
145
|
+
end
|
|
114
146
|
end
|
|
115
147
|
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
|
-
|
|
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 ||=
|
|
19
|
+
@translated_description ||= decidim_sanitize_editor(translated_attribute(model.settings.description))
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def button_url
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<%= translated_attribute current_organization.highlighted_content_banner_title %>
|
|
8
8
|
</h1>
|
|
9
9
|
<span class="text-highlight">
|
|
10
|
-
<%=
|
|
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">
|
|
@@ -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
|
|
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">×</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">×</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
|
-
|
|
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
|
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
<% end %>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
<% if conversation.
|
|
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
|
-
<
|
|
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
|
|
@@ -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, "
|
|
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
|
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
11
|
-
|
|
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
|
-
|
|
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.
|
|
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)
|
|
@@ -5,6 +5,7 @@ module Decidim
|
|
|
5
5
|
module SanitizeHelper
|
|
6
6
|
def self.included(base)
|
|
7
7
|
base.include ActionView::Helpers::SanitizeHelper
|
|
8
|
+
base.include ActionView::Helpers::TagHelper
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
# Public: It sanitizes a user-inputted string with the
|
|
@@ -30,6 +31,10 @@ module Decidim
|
|
|
30
31
|
end
|
|
31
32
|
end
|
|
32
33
|
|
|
34
|
+
def decidim_sanitize_editor(html, options = {})
|
|
35
|
+
content_tag(:div, decidim_sanitize(html, options), class: %w(ql-editor ql-reset-decidim))
|
|
36
|
+
end
|
|
37
|
+
|
|
33
38
|
def decidim_html_escape(text)
|
|
34
39
|
ERB::Util.unwrapped_html_escape(text.to_str)
|
|
35
40
|
end
|
|
@@ -37,5 +42,65 @@ module Decidim
|
|
|
37
42
|
def decidim_url_escape(text)
|
|
38
43
|
decidim_html_escape(text).sub(/^javascript:/, "")
|
|
39
44
|
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# Maintains the paragraphs and lists separations with their bullet points and
|
|
49
|
+
# list numberings where appropriate.
|
|
50
|
+
#
|
|
51
|
+
# Returns a String.
|
|
52
|
+
def sanitize_text(text)
|
|
53
|
+
add_line_feeds(sanitize_ordered_lists(sanitize_unordered_lists(text)))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def sanitize_unordered_lists(text)
|
|
57
|
+
text.gsub(%r{(?=.*</ul>)(?!.*?<li>.*?</ol>.*?</ul>)<li>}) { |li| "#{li}• " }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def sanitize_ordered_lists(text)
|
|
61
|
+
i = 0
|
|
62
|
+
|
|
63
|
+
text.gsub(%r{(?=.*</ol>)(?!.*?<li>.*?</ul>.*?</ol>)<li>}) do |li|
|
|
64
|
+
i += 1
|
|
65
|
+
|
|
66
|
+
li + "#{i}. "
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def add_line_feeds_to_paragraphs(text)
|
|
71
|
+
text.gsub("</p>") { |p| "#{p}\n\n" }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def add_line_feeds_to_list_items(text)
|
|
75
|
+
text.gsub("</li>") { |li| "#{li}\n" }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Adds line feeds after the paragraph and list item closing tags.
|
|
79
|
+
#
|
|
80
|
+
# Returns a String.
|
|
81
|
+
def add_line_feeds(text)
|
|
82
|
+
add_line_feeds_to_paragraphs(add_line_feeds_to_list_items(text))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def content_handle_locale(body, all_locales, extras, links, strip_tags)
|
|
86
|
+
handle_locales(body, all_locales) do |content|
|
|
87
|
+
content = strip_tags(sanitize_text(content)) if strip_tags
|
|
88
|
+
|
|
89
|
+
renderer = Decidim::ContentRenderers::HashtagRenderer.new(content)
|
|
90
|
+
content = renderer.render(links: links, extras: extras).html_safe
|
|
91
|
+
|
|
92
|
+
content = Decidim::ContentRenderers::LinkRenderer.new(content).render if links
|
|
93
|
+
content
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def render_sanitized_content(resource, method)
|
|
98
|
+
content = present(resource).send(method, links: true, strip_tags: !safe_content?)
|
|
99
|
+
content = simple_format(content, {}, sanitize: false)
|
|
100
|
+
|
|
101
|
+
return content unless safe_content?
|
|
102
|
+
|
|
103
|
+
decidim_sanitize_editor(content)
|
|
104
|
+
end
|
|
40
105
|
end
|
|
41
106
|
end
|