decidim-core 0.8.4 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/app/assets/images/decidim/decidim-logo.svg +23 -23
- data/app/assets/images/decidim/default-avatar.svg +7 -7
- data/app/assets/images/decidim/icons.svg +1 -0
- data/app/assets/javascripts/decidim.js.es6 +5 -2
- data/app/assets/javascripts/decidim/append_redirect_url_to_modals.js.es6 +84 -0
- data/app/assets/javascripts/decidim/data_picker.js.es6 +177 -0
- data/app/assets/javascripts/decidim/form_filter.component.js.es6 +25 -20
- data/app/assets/javascripts/decidim/form_filter.component.test.js +24 -13
- data/app/assets/javascripts/decidim/history.js.es6 +3 -3
- data/app/assets/stylesheets/decidim/_decidim.scss +1 -4
- data/app/assets/stylesheets/decidim/_variables.scss +4 -4
- data/app/assets/stylesheets/decidim/editor.scss +13 -0
- data/app/assets/stylesheets/decidim/email.css +9 -1
- data/app/assets/stylesheets/decidim/extras/_add_comments.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_announcement.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_collection-sort-controls.scss +2 -2
- data/app/assets/stylesheets/decidim/extras/_embed.scss +6 -5
- data/app/assets/stylesheets/decidim/extras/_impersonation-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/extras/_label-required.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_leaflet.scss +6 -4
- data/app/assets/stylesheets/decidim/extras/_meeting-registrations.scss +4 -4
- data/app/assets/stylesheets/decidim/extras/_process_stats.scss +11 -4
- data/app/assets/stylesheets/decidim/extras/_proposal_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_quill.scss +1 -1
- data/app/assets/stylesheets/decidim/extras/_reference.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_register_form.scss +3 -3
- data/app/assets/stylesheets/decidim/extras/_results-per-page.scss +10 -10
- data/app/assets/stylesheets/decidim/extras/_social_icons_mini.scss +4 -3
- data/app/assets/stylesheets/decidim/layouts/_highlighted_banner.scss +38 -0
- data/app/assets/stylesheets/decidim/layouts/_home.scss +33 -3
- data/app/assets/stylesheets/decidim/layouts/_user.scss +33 -5
- data/app/assets/stylesheets/decidim/layouts/_view.scss +1 -2
- data/app/assets/stylesheets/decidim/map.css +5 -3
- data/app/assets/stylesheets/decidim/modules/_address.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_author-avatar.scss +24 -9
- data/app/assets/stylesheets/decidim/modules/_buttons.scss +24 -10
- data/app/assets/stylesheets/decidim/modules/_callout.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_card-grid.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_cards.scss +102 -31
- data/app/assets/stylesheets/decidim/modules/_comments.scss +21 -20
- data/app/assets/stylesheets/decidim/modules/_cookie-bar.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_data-picker.scss +159 -0
- data/app/assets/stylesheets/decidim/modules/_datepicker.scss +36 -36
- data/app/assets/stylesheets/decidim/modules/_definition-data.scss +12 -9
- data/app/assets/stylesheets/decidim/modules/_extra.scss +4 -1
- data/app/assets/stylesheets/decidim/modules/_filter-tags.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_filters.scss +9 -5
- data/app/assets/stylesheets/decidim/modules/_flag.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_footer.scss +10 -0
- data/app/assets/stylesheets/decidim/modules/_forms.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_help.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_icons.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_layout.scss +4 -0
- data/app/assets/stylesheets/decidim/modules/_list-docs.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_main-container.scss +13 -7
- data/app/assets/stylesheets/decidim/modules/_map.scss +13 -1
- data/app/assets/stylesheets/decidim/modules/_margins.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_messages.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_modules.scss +3 -0
- data/app/assets/stylesheets/decidim/modules/_navbar.scss +36 -16
- data/app/assets/stylesheets/decidim/modules/_omnipresent_banner.scss +26 -0
- data/app/assets/stylesheets/decidim/modules/_opinion-toggle.scss +5 -0
- data/app/assets/stylesheets/decidim/modules/_order-by.scss +10 -10
- data/app/assets/stylesheets/decidim/modules/_pagination.scss +3 -2
- data/app/assets/stylesheets/decidim/modules/_process-header.scss +11 -2
- data/app/assets/stylesheets/decidim/modules/_process-info.scss +9 -1
- data/app/assets/stylesheets/decidim/modules/_process-nav.scss +20 -3
- data/app/assets/stylesheets/decidim/modules/_process-phase.scss +12 -3
- data/app/assets/stylesheets/decidim/modules/_progress-bar.scss +69 -0
- data/app/assets/stylesheets/decidim/modules/_reference.scss +1 -2
- data/app/assets/stylesheets/decidim/modules/_reveal.scss +1 -1
- data/app/assets/stylesheets/decidim/modules/_share.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_signup.scss +5 -1
- data/app/assets/stylesheets/decidim/modules/_static-pages.scss +6 -0
- data/app/assets/stylesheets/decidim/modules/_status-labels.scss +2 -0
- data/app/assets/stylesheets/decidim/modules/_tags.scss +3 -1
- data/app/assets/stylesheets/decidim/modules/_timeline.scss +41 -30
- data/app/assets/stylesheets/decidim/modules/_title-action.scss +2 -1
- data/app/assets/stylesheets/decidim/modules/_typography.scss +13 -4
- data/app/assets/stylesheets/decidim/modules/_user-form.scss +1 -0
- data/app/assets/stylesheets/decidim/modules/_video.scss +2 -2
- data/app/assets/stylesheets/decidim/utils/_fontface.scss +22 -20
- data/app/assets/stylesheets/decidim/utils/_helpers.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_keyframes.scss +6 -6
- data/app/assets/stylesheets/decidim/utils/_mixins.scss +24 -7
- data/app/assets/stylesheets/decidim/utils/_settings.scss +50 -52
- data/app/assets/stylesheets/decidim/utils/_toggle-expand.scss +1 -0
- data/app/commands/decidim/create_omniauth_registration.rb +3 -0
- data/app/commands/decidim/create_registration.rb +3 -1
- data/app/commands/decidim/destroy_account.rb +1 -0
- data/app/commands/decidim/invite_user_again.rb +1 -1
- data/app/commands/decidim/messaging/reply_to_conversation.rb +1 -3
- data/app/commands/decidim/unsubscribe_settings.rb +29 -0
- data/app/commands/decidim/update_account.rb +16 -3
- data/app/controllers/concerns/decidim/action_authorization.rb +1 -1
- data/app/controllers/concerns/decidim/devise_controllers.rb +10 -0
- data/app/controllers/concerns/decidim/form_factory.rb +2 -1
- data/app/controllers/concerns/decidim/impersonate_users.rb +13 -8
- data/app/controllers/concerns/decidim/participatory_space_context.rb +1 -1
- data/app/controllers/decidim/application_controller.rb +16 -0
- data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
- data/app/controllers/decidim/devise/invitations_controller.rb +9 -1
- data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +10 -1
- data/app/controllers/decidim/devise/sessions_controller.rb +9 -1
- data/app/controllers/decidim/locales_controller.rb +2 -3
- data/app/controllers/decidim/messaging/conversations_controller.rb +2 -2
- data/app/controllers/decidim/newsletters_controller.rb +60 -0
- data/app/controllers/decidim/pages_controller.rb +1 -0
- data/app/controllers/decidim/profiles_controller.rb +23 -0
- data/app/controllers/decidim/scopes_controller.rb +19 -20
- data/app/events/decidim/profile_updated_event.rb +27 -0
- data/app/forms/decidim/account_form.rb +34 -0
- data/app/forms/decidim/form.rb +1 -0
- data/app/forms/decidim/messaging/conversation_form.rb +5 -2
- data/app/forms/decidim/omniauth_registration_form.rb +5 -0
- data/app/forms/decidim/registration_form.rb +8 -1
- data/app/helpers/decidim/action_authorization_helper.rb +2 -2
- data/app/helpers/decidim/application_helper.rb +8 -0
- data/app/helpers/decidim/feature_path_helper.rb +12 -2
- data/app/helpers/decidim/feature_reference_helper.rb +1 -1
- data/app/helpers/decidim/messaging/conversation_helper.rb +27 -9
- data/app/helpers/decidim/newsletters_helper.rb +49 -0
- data/app/helpers/decidim/scopes_helper.rb +43 -2
- data/app/helpers/decidim/translations_helper.rb +6 -2
- data/app/mailers/decidim/decidim_devise_mailer.rb +1 -3
- data/app/mailers/decidim/messaging/conversation_mailer.rb +1 -1
- data/app/mailers/decidim/newsletter_mailer.rb +7 -8
- data/app/models/decidim/abilities/everyone_ability.rb +1 -0
- data/app/models/decidim/authorization.rb +19 -5
- data/app/models/decidim/impersonation_log.rb +2 -1
- data/app/models/decidim/messaging/conversation.rb +2 -0
- data/app/models/decidim/messaging/message.rb +4 -0
- data/app/models/decidim/organization.rb +1 -0
- data/app/models/decidim/scope.rb +10 -2
- data/app/models/decidim/user.rb +10 -2
- data/app/presenters/decidim/home_stats_presenter.rb +10 -4
- data/app/presenters/decidim/user_group_presenter.rb +28 -0
- data/app/presenters/decidim/user_presenter.rb +42 -0
- data/app/services/decidim/action_authorizer.rb +32 -68
- data/app/services/decidim/notification_generator_for_recipient.rb +8 -3
- data/app/uploaders/decidim/avatar_uploader.rb +2 -2
- data/app/views/decidim/account/delete.html.erb +1 -1
- data/app/views/decidim/account/show.html.erb +4 -1
- data/app/views/decidim/devise/invitations/edit.html.erb +2 -0
- data/app/views/decidim/devise/omniauth_registrations/new.html.erb +7 -1
- data/app/views/decidim/devise/registrations/new.html.erb +7 -1
- data/app/views/decidim/messaging/conversations/_message.html.erb +6 -12
- data/app/views/decidim/messaging/conversations/_reply.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/index.html.erb +1 -1
- data/app/views/decidim/messaging/conversations/update.js.erb +1 -0
- data/app/views/decidim/newsletter_mailer/newsletter.html.erb +11 -0
- data/app/views/decidim/newsletters/show.html.erb +11 -0
- data/app/views/decidim/newsletters/unsubscribe.html.erb +4 -0
- data/app/views/decidim/notifications/_notification.html.erb +1 -1
- data/app/views/decidim/profiles/show.html.erb +64 -0
- data/app/views/decidim/scopes/_scopes_picker_input.html.erb +6 -0
- data/app/views/decidim/scopes/picker.html.erb +36 -0
- data/app/views/decidim/shared/_action_authorization_modal.html.erb +25 -51
- data/app/views/decidim/shared/_author.html.erb +21 -0
- data/app/views/decidim/shared/_author_reference.html.erb +12 -0
- data/app/views/layouts/decidim/_application.html.erb +1 -0
- data/app/views/layouts/decidim/_impersonation_warning.html.erb +1 -1
- data/app/views/layouts/decidim/_mailer_logo.html.erb +6 -1
- data/app/views/layouts/decidim/_omnipresent_banner.html.erb +14 -0
- data/app/views/layouts/decidim/_user_menu.html.erb +3 -0
- data/app/views/layouts/decidim/mailer.html.erb +16 -4
- data/app/views/layouts/decidim/widget.html.erb +14 -9
- data/app/views/pages/home.html.erb +2 -0
- data/app/views/pages/home/_highlighted_content_banner.html.erb +26 -0
- data/config/initializers/devise.rb +1 -3
- data/config/locales/ca.yml +67 -9
- data/config/locales/en.yml +65 -4
- data/config/locales/es.yml +74 -14
- data/config/locales/eu.yml +66 -4
- data/config/locales/fi.yml +87 -25
- data/config/locales/fr.yml +71 -9
- data/config/locales/gl.yml +493 -0
- data/config/locales/it.yml +79 -17
- data/config/locales/nl.yml +71 -9
- data/config/locales/pl.yml +66 -4
- data/config/locales/pt-BR.yml +493 -0
- data/config/locales/pt.yml +99 -37
- data/config/locales/ru.yml +85 -13
- data/config/locales/sv.yml +493 -0
- data/config/locales/uk.yml +78 -16
- data/config/routes.rb +11 -1
- data/db/migrate/20171212103803_create_unique_nicknames.rb +29 -0
- data/db/migrate/20180115090038_extend_user_profile.rb +8 -0
- data/db/migrate/20180123125308_add_enable_omnipresent_banner_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125409_add_omnipresent_banner_title_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125432_add_omnipresent_banner_short_description_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180123125452_add_omnipresent_banner_url_to_decidim_organizations.rb +7 -0
- data/db/migrate/20180125063433_add_highlighted_content_banner_to_decidim_organizations.rb +13 -0
- data/db/seeds.rb +8 -2
- data/lib/decidim/abilities/participatory_process_role_ability.rb +1 -3
- data/lib/decidim/content_parsers.rb +8 -0
- data/lib/decidim/content_parsers/base_parser.rb +58 -0
- data/lib/decidim/content_parsers/user_parser.rb +46 -0
- data/lib/decidim/content_processor.rb +84 -0
- data/lib/decidim/content_renderers.rb +8 -0
- data/lib/decidim/content_renderers/base_renderer.rb +37 -0
- data/lib/decidim/content_renderers/user_renderer.rb +32 -0
- data/lib/decidim/core.rb +66 -1
- data/lib/decidim/core/api/author_interface.rb +3 -3
- data/lib/decidim/core/api/user_group_type.rb +10 -8
- data/lib/decidim/core/api/user_type.rb +13 -7
- data/lib/decidim/core/engine.rb +7 -5
- data/lib/decidim/core/test.rb +1 -1
- data/lib/decidim/core/test/factories.rb +21 -45
- data/lib/decidim/core/test/shared_examples/announcements_examples.rb +3 -2
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +5 -2
- data/lib/decidim/core/test/shared_examples/scope_helper_examples.rb +40 -3
- data/lib/decidim/core/test/shared_examples/simple_event.rb +73 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/events.rb +2 -0
- data/lib/decidim/events/author_event.rb +41 -0
- data/lib/decidim/events/base_event.rb +28 -3
- data/lib/decidim/events/email_event.rb +1 -1
- data/lib/decidim/events/notification_event.rb +1 -1
- data/lib/decidim/events/simple_event.rb +79 -0
- data/lib/decidim/filter_form_builder.rb +2 -3
- data/lib/decidim/form_builder.rb +39 -27
- data/lib/decidim/friendly_dates.rb +26 -0
- data/lib/decidim/has_feature.rb +1 -0
- data/lib/decidim/has_reference.rb +1 -1
- data/lib/decidim/i18n_exceptions.rb +1 -3
- data/lib/decidim/menu.rb +1 -1
- data/lib/decidim/newsletter_encryptor.rb +22 -0
- data/lib/decidim/nicknamizable.rb +56 -0
- data/lib/decidim/participable.rb +8 -0
- data/lib/decidim/participatory_space_manifest.rb +10 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.gl.js +13 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt-br.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.pt.js +5 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.ru.js +4 -1
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.sv.js +14 -0
- data/vendor/assets/javascripts/datepicker-locales/foundation-datepicker.uk.js +4 -1
- data/vendor/assets/javascripts/form_datepicker.js.es6 +4 -2
- data/vendor/assets/javascripts/foundation-datepicker.js +42 -26
- metadata +124 -84
- data/app/assets/javascripts/decidim/select2.field.js.es6 +0 -47
- data/app/assets/javascripts/decidim/select2.js.es6 +0 -11
- data/app/assets/stylesheets/decidim/editor.sass +0 -4
- data/app/assets/stylesheets/decidim/plugins/_select2.scss +0 -63
- data/app/helpers/decidim/datetime_helper.rb +0 -23
- data/app/queries/decidim/freetext_scopes.rb +0 -39
- data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +0 -64
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# This module contains all logic related to decidim's ability for process a content.
|
5
|
+
# Their main job is to {ContentProcessor#parse parse} or {ContentProcessor#render render}
|
6
|
+
# a content calling all the registered processors in the Decidim.content_processors config.
|
7
|
+
#
|
8
|
+
# Note that to render a content this must have been parsed before.
|
9
|
+
#
|
10
|
+
# When creating a new processor, the both sides must be declared: parser and renderer
|
11
|
+
# e.g. If we are creating a processor to parse and render user mentions, we can call this
|
12
|
+
# the `user` processor, so we will declare the parser and renderer classes like that:
|
13
|
+
#
|
14
|
+
# Decidim::ContentParsers::UserParser
|
15
|
+
# Decidim::ContentRenderers::UserRenderer
|
16
|
+
#
|
17
|
+
# and register it in an initializer, so it is executed:
|
18
|
+
#
|
19
|
+
# Decidim.content_processors += [:user]
|
20
|
+
#
|
21
|
+
# If for some reason you only want to do something in one of the both sides, please, also
|
22
|
+
# declare the other side making it "transparent" (declaring the class and leaving it empty).
|
23
|
+
#
|
24
|
+
# @example How to parse a content
|
25
|
+
# parsed = Decidim::ContentProcessor.parse(content)
|
26
|
+
# parsed.rewrite # contains rewritten content
|
27
|
+
# parsed.metadata # contains the merged metadata of all parsers
|
28
|
+
#
|
29
|
+
# @example How to render a content (must have been parsed before)
|
30
|
+
# rendered = Decidim::ContentProcessor.render(content)
|
31
|
+
# puts rendered
|
32
|
+
module ContentProcessor
|
33
|
+
# Class that represents the result of processing a text
|
34
|
+
#
|
35
|
+
# @!attribute rewrite
|
36
|
+
# @return [String] the rewritten content
|
37
|
+
# @!attribute metadata
|
38
|
+
# @return [Hash<Symbol, Metadata>] a hash where the keys are the parsers
|
39
|
+
# names, and the values are the Metadata object returned by the parser
|
40
|
+
Result = Struct.new(:rewrite, :metadata)
|
41
|
+
|
42
|
+
# This calls all registered processors one after the other and collects the
|
43
|
+
# metadata for each one and the resulting modified content
|
44
|
+
#
|
45
|
+
# @return [Result] a Result object with the content rewritten and the metadata
|
46
|
+
def self.parse(content)
|
47
|
+
parsed = Decidim.content_processors.each_with_object(rewrite: content, metadata: {}) do |type, result|
|
48
|
+
parser = parser_klass(type).constantize.new(result[:rewrite])
|
49
|
+
result[:rewrite] = parser.rewrite
|
50
|
+
result[:metadata][type] = parser.metadata
|
51
|
+
end
|
52
|
+
|
53
|
+
Result.new(parsed[:rewrite], parsed[:metadata])
|
54
|
+
end
|
55
|
+
|
56
|
+
# This calls all registered processors one after the other and returns
|
57
|
+
# the processed content ready to display.
|
58
|
+
#
|
59
|
+
# @return [String] the content processed and ready to display (it is expected to include HTML)
|
60
|
+
def self.render(content)
|
61
|
+
Decidim.content_processors.reduce(content) do |result, type|
|
62
|
+
renderer_klass(type).constantize.new(result).render
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Guess the class name of the parser for a processor
|
67
|
+
# represented by the given symbol
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @return [String] the content parser class name
|
71
|
+
def self.parser_klass(type)
|
72
|
+
"Decidim::ContentParsers::#{type.to_s.camelize}Parser"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Guess the class name of the renderer for a processor
|
76
|
+
# represented by the given symbol
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
# @return [String] the content renderer class name
|
80
|
+
def self.renderer_klass(type)
|
81
|
+
"Decidim::ContentRenderers::#{type.to_s.camelize}Renderer"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ContentRenderers
|
5
|
+
# Abstract base class for content renderers, so they have the same contract
|
6
|
+
#
|
7
|
+
# @example How to use a content renderer class
|
8
|
+
# renderer = Decidim::ContentRenderers::CustomRenderer.new(content)
|
9
|
+
# parser.render # returns the content formatted
|
10
|
+
#
|
11
|
+
# @abstract Subclass and override {#render} to implement a content renderer
|
12
|
+
class BaseRenderer
|
13
|
+
# @return [String] the content to be formatted
|
14
|
+
attr_reader :content
|
15
|
+
|
16
|
+
# Gets initialized with the `content` to format
|
17
|
+
#
|
18
|
+
# @param content [String] content to be formatted
|
19
|
+
def initialize(content)
|
20
|
+
@content = content || ""
|
21
|
+
end
|
22
|
+
|
23
|
+
# Format the content and return it ready to display
|
24
|
+
#
|
25
|
+
# @example Implementation to display prohibited words
|
26
|
+
# def render
|
27
|
+
# content.gsub(/\~\~(.*?)\~\~/, '<del>\1</del>')
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# @abstract Subclass is expected to implement it
|
31
|
+
# @return [String] the content processed and ready to display
|
32
|
+
def render
|
33
|
+
content
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ContentRenderers
|
5
|
+
# A renderer that searches Global IDs representing users in content
|
6
|
+
# and replaces it with a link to their profile with the nickname.
|
7
|
+
#
|
8
|
+
# e.g. gid://<APP_NAME>/Decidim::User/1
|
9
|
+
#
|
10
|
+
# @see BaseRenderer Examples of how to use a content renderer
|
11
|
+
class UserRenderer < BaseRenderer
|
12
|
+
# Matches a global id representing a Decidim::User
|
13
|
+
GLOBAL_ID_REGEX = %r{gid://.*/Decidim::User/\d+}
|
14
|
+
|
15
|
+
# Replaces found Global IDs matching an existing user with
|
16
|
+
# a link to their profile. The Global IDs representing an
|
17
|
+
# invalid Decidim::User are replaced with an empty string.
|
18
|
+
#
|
19
|
+
# @return [String] the content ready to display (contains HTML)
|
20
|
+
def render
|
21
|
+
content.gsub(GLOBAL_ID_REGEX) do |user_gid|
|
22
|
+
begin
|
23
|
+
user = GlobalID::Locator.locate(user_gid)
|
24
|
+
Decidim::UserPresenter.new(user).display_mention
|
25
|
+
rescue ActiveRecord::RecordNotFound => _ex
|
26
|
+
""
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/decidim/core.rb
CHANGED
@@ -21,6 +21,9 @@ module Decidim
|
|
21
21
|
autoload :Participable, "decidim/participable"
|
22
22
|
autoload :Publicable, "decidim/publicable"
|
23
23
|
autoload :Scopable, "decidim/scopable"
|
24
|
+
autoload :ContentParsers, "decidim/content_parsers"
|
25
|
+
autoload :ContentRenderers, "decidim/content_renderers"
|
26
|
+
autoload :ContentProcessor, "decidim/content_processor"
|
24
27
|
autoload :Features, "decidim/features"
|
25
28
|
autoload :HasAttachments, "decidim/has_attachments"
|
26
29
|
autoload :FeatureValidator, "decidim/feature_validator"
|
@@ -29,6 +32,8 @@ module Decidim
|
|
29
32
|
autoload :HasScope, "decidim/has_scope"
|
30
33
|
autoload :HasCategory, "decidim/has_category"
|
31
34
|
autoload :Followable, "decidim/followable"
|
35
|
+
autoload :FriendlyDates, "decidim/friendly_dates"
|
36
|
+
autoload :Nicknamizable, "decidim/nicknamizable"
|
32
37
|
autoload :HasReference, "decidim/has_reference"
|
33
38
|
autoload :Attributes, "decidim/attributes"
|
34
39
|
autoload :StatsRegistry, "decidim/stats_registry"
|
@@ -43,6 +48,7 @@ module Decidim
|
|
43
48
|
autoload :EngineRouter, "decidim/engine_router"
|
44
49
|
autoload :Events, "decidim/events"
|
45
50
|
autoload :ViewHooks, "decidim/view_hooks"
|
51
|
+
autoload :NewsletterEncryptor, "decidim/newsletter_encryptor"
|
46
52
|
|
47
53
|
include ActiveSupport::Configurable
|
48
54
|
|
@@ -87,7 +93,24 @@ module Decidim
|
|
87
93
|
|
88
94
|
# Exposes a configuration option: The application available locales.
|
89
95
|
config_accessor :available_locales do
|
90
|
-
%w(en ca es eu
|
96
|
+
%w(en ca es eu fi fr gl it nl pt pr-BR ru sv uk)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Exposes a configuration option: an array of symbols representing processors
|
100
|
+
# that will be automatically executed when a content is parsed or rendered.
|
101
|
+
#
|
102
|
+
# A content processor is a concept to refer to a set of two classes:
|
103
|
+
# the content parser class and the content renderer class.
|
104
|
+
# e.g. If we register a content processor named `user`:
|
105
|
+
#
|
106
|
+
# Decidim.content_processors += [:user]
|
107
|
+
#
|
108
|
+
# we must declare the following classes:
|
109
|
+
#
|
110
|
+
# Decidim::ContentParsers::UserParser < BaseParser
|
111
|
+
# Decidim::ContentRenderers::UserRenderer < BaseRenderer
|
112
|
+
config_accessor :content_processors do
|
113
|
+
[]
|
91
114
|
end
|
92
115
|
|
93
116
|
# Exposes a configuration option: The application default locale.
|
@@ -143,12 +166,54 @@ module Decidim
|
|
143
166
|
true
|
144
167
|
end
|
145
168
|
|
169
|
+
# Allow organization's administrators to track newsletter links
|
170
|
+
config_accessor :track_newsletter_links do
|
171
|
+
true
|
172
|
+
end
|
173
|
+
|
146
174
|
# A base path for the uploads. If set, make sure it ends in a slash.
|
147
175
|
# Uploads will be set to `<base_path>/uploads/`. This can be useful if you
|
148
176
|
# want to use the same uploads place for both staging and production
|
149
177
|
# environments, but in different folders.
|
150
178
|
config_accessor :base_uploads_path
|
151
179
|
|
180
|
+
# Public: Registers a global engine. This method is intended to be used
|
181
|
+
# by feature engines that also offer unscoped functionality
|
182
|
+
#
|
183
|
+
# name - The name of the engine to register. Should be unique.
|
184
|
+
# engine - The engine to register.
|
185
|
+
# options - Options to pass to the engine.
|
186
|
+
# :at - The route to mount the engine to.
|
187
|
+
#
|
188
|
+
# Returns nothing.
|
189
|
+
def self.register_global_engine(name, engine, options = {})
|
190
|
+
return if global_engines.keys.include?(name)
|
191
|
+
|
192
|
+
options[:at] ||= "/#{name}"
|
193
|
+
|
194
|
+
global_engines[name.to_sym] = {
|
195
|
+
at: options[:at],
|
196
|
+
engine: engine
|
197
|
+
}
|
198
|
+
end
|
199
|
+
|
200
|
+
# Semiprivate: Removes a global engine from the registry. Mostly used on testing,
|
201
|
+
# no real reason to use this on production.
|
202
|
+
#
|
203
|
+
# name - The name of the global engine to remove.
|
204
|
+
#
|
205
|
+
# Returns nothing.
|
206
|
+
def self.unregister_global_engine(name)
|
207
|
+
global_engines.delete(name.to_sym)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Public: Finds all registered engines via the 'register_global_engine' method.
|
211
|
+
#
|
212
|
+
# Returns an Array[::Rails::Engine]
|
213
|
+
def self.global_engines
|
214
|
+
@global_engines ||= {}
|
215
|
+
end
|
216
|
+
|
152
217
|
# Public: Registers a feature, usually held in an external library or in a
|
153
218
|
# separate folder in the main repository. Exposes a DSL defined by
|
154
219
|
# `Decidim::FeatureManifest`.
|
@@ -7,12 +7,12 @@ module Decidim
|
|
7
7
|
description "An author"
|
8
8
|
|
9
9
|
field :name, !types.String, "The author's name"
|
10
|
+
field :nickname, !types.String, "The author's nickname"
|
10
11
|
|
11
12
|
field :avatarUrl, !types.String, "The author's avatar url"
|
12
|
-
|
13
|
-
field :
|
13
|
+
field :profilePath, !types.String, "The author's profile path"
|
14
|
+
field :badge, !types.String, "The author's badge icon"
|
14
15
|
|
15
16
|
field :deleted, !types.Boolean, "Whether the author's account has been deleted or not"
|
16
|
-
field :isUser, !types.Boolean, "Whether the author is a user or another kind of author (User Group)"
|
17
17
|
end
|
18
18
|
end
|
@@ -14,22 +14,24 @@ module Decidim
|
|
14
14
|
|
15
15
|
field :name, !types.String, "The user group's name"
|
16
16
|
|
17
|
+
field :nickname, !types.String, "User groups have no nickname" do
|
18
|
+
resolve ->(obj, _args, _ctx) { UserGroupPresenter.new(obj).nickname }
|
19
|
+
end
|
20
|
+
|
17
21
|
field :avatarUrl, !types.String, "The user's avatar url" do
|
18
|
-
resolve ->(obj, _args, _ctx) { obj.
|
22
|
+
resolve ->(obj, _args, _ctx) { UserGroupPresenter.new(obj).avatar_url }
|
19
23
|
end
|
20
24
|
|
21
|
-
field :
|
22
|
-
resolve
|
23
|
-
obj.verified?
|
24
|
-
}
|
25
|
+
field :profilePath, !types.String, "The user's profile url" do
|
26
|
+
resolve ->(obj, _args, _ctx) { UserGroupPresenter.new(obj).profile_path }
|
25
27
|
end
|
26
28
|
|
27
29
|
field :deleted, !types.Boolean, "Whether the user group's has been deleted or not" do
|
28
|
-
resolve ->(
|
30
|
+
resolve ->(obj, _args, _ctx) { UserGroupPresenter.new(obj).deleted? }
|
29
31
|
end
|
30
32
|
|
31
|
-
field :
|
32
|
-
resolve ->(
|
33
|
+
field :badge, !types.String, "A badge for the user group" do
|
34
|
+
resolve ->(obj, _args, _ctx) { UserGroupPresenter.new(obj).badge }
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -12,22 +12,28 @@ module Decidim
|
|
12
12
|
|
13
13
|
field :name, !types.String, "The user's name"
|
14
14
|
|
15
|
+
field :nickname, !types.String, "The user's nickname" do
|
16
|
+
resolve ->(obj, _args, _ctx) { UserPresenter.new(obj).nickname }
|
17
|
+
end
|
18
|
+
|
15
19
|
field :avatarUrl, !types.String, "The user's avatar url" do
|
16
|
-
resolve ->(obj, _args, _ctx) { obj.
|
20
|
+
resolve ->(obj, _args, _ctx) { UserPresenter.new(obj).avatar_url(:thumb) }
|
21
|
+
end
|
22
|
+
|
23
|
+
field :profilePath, !types.String, "The user's profile url" do
|
24
|
+
resolve ->(obj, _args, _ctx) { UserPresenter.new(obj).profile_path }
|
17
25
|
end
|
18
26
|
|
19
27
|
field :organizationName, !types.String, "The user's organization name" do
|
20
28
|
resolve ->(obj, _args, _ctx) { obj.organization.name }
|
21
29
|
end
|
22
30
|
|
23
|
-
field :
|
24
|
-
resolve ->(
|
31
|
+
field :deleted, !types.Boolean, "Whether the user's account has been deleted or not" do
|
32
|
+
resolve ->(obj, _args, _ctx) { UserPresenter.new(obj).deleted? }
|
25
33
|
end
|
26
34
|
|
27
|
-
field :
|
28
|
-
|
29
|
-
field :isUser, !types.Boolean, "User groups are not users" do
|
30
|
-
resolve ->(_obj, _args, _ctx) { true }
|
35
|
+
field :badge, !types.String, "A badge for the user group" do
|
36
|
+
resolve ->(obj, _args, _ctx) { UserPresenter.new(obj).badge }
|
31
37
|
end
|
32
38
|
end
|
33
39
|
end
|
data/lib/decidim/core/engine.rb
CHANGED
@@ -56,6 +56,7 @@ module Decidim
|
|
56
56
|
end
|
57
57
|
|
58
58
|
initializer "decidim.assets" do |app|
|
59
|
+
app.config.assets.paths << File.expand_path("../../../app/assets/stylesheets", __dir__)
|
59
60
|
app.config.assets.precompile += %w(decidim_core_manifest.js)
|
60
61
|
|
61
62
|
Decidim.feature_manifests.each do |feature|
|
@@ -107,19 +108,14 @@ module Decidim
|
|
107
108
|
Geocoder.configure(
|
108
109
|
# geocoding service (see below for supported options):
|
109
110
|
lookup: :here,
|
110
|
-
|
111
111
|
# IP address geocoding service (see below for supported options):
|
112
112
|
# :ip_lookup => :maxmind,
|
113
|
-
|
114
113
|
# to use an API key:
|
115
114
|
api_key: [Decidim.geocoder&.fetch(:here_app_id), Decidim.geocoder&.fetch(:here_app_code)]
|
116
|
-
|
117
115
|
# geocoding service request timeout, in seconds (default 3):
|
118
116
|
# :timeout => 5,
|
119
|
-
|
120
117
|
# set default units to kilometers:
|
121
118
|
# :units => :km,
|
122
|
-
|
123
119
|
# caching (see below for details):
|
124
120
|
# :cache => Redis.new,
|
125
121
|
# :cache_prefix => "..."
|
@@ -203,6 +199,12 @@ module Decidim
|
|
203
199
|
end
|
204
200
|
end
|
205
201
|
|
202
|
+
initializer "decidim.content_processors" do |_app|
|
203
|
+
Decidim.configure do |config|
|
204
|
+
config.content_processors += [:user]
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
206
208
|
initializer "paper_trail" do
|
207
209
|
PaperTrail.config.track_associations = false
|
208
210
|
end
|
data/lib/decidim/core/test.rb
CHANGED
@@ -13,9 +13,9 @@ require "decidim/core/test/shared_examples/announcements_examples"
|
|
13
13
|
require "decidim/core/test/shared_examples/process_announcements_examples"
|
14
14
|
require "decidim/core/test/shared_examples/reportable"
|
15
15
|
require "decidim/core/test/shared_examples/reports_examples"
|
16
|
-
require "decidim/core/test/shared_examples/manage_moderations_examples"
|
17
16
|
require "decidim/core/test/shared_examples/paginated_resource_examples"
|
18
17
|
require "decidim/core/test/shared_examples/errors"
|
19
18
|
require "decidim/core/test/shared_examples/scope_helper_examples"
|
20
19
|
require "decidim/core/test/shared_examples/user_localised_email_examples"
|
21
20
|
require "decidim/core/test/shared_examples/follows_examples"
|
21
|
+
require "decidim/core/test/shared_examples/simple_event"
|
@@ -11,6 +11,10 @@ FactoryBot.define do
|
|
11
11
|
"#{Faker::Name.name} #{n}"
|
12
12
|
end
|
13
13
|
|
14
|
+
sequence(:nickname) do |n|
|
15
|
+
"#{Faker::Lorem.characters(rand(1..10))}_#{n}"
|
16
|
+
end
|
17
|
+
|
14
18
|
sequence(:email) do |n|
|
15
19
|
"user#{n}@example.org"
|
16
20
|
end
|
@@ -58,6 +62,8 @@ FactoryBot.define do
|
|
58
62
|
official_img_header { Decidim::Dev.test_file("avatar.jpg", "image/jpeg") }
|
59
63
|
official_img_footer { Decidim::Dev.test_file("avatar.jpg", "image/jpeg") }
|
60
64
|
official_url { Faker::Internet.url }
|
65
|
+
highlighted_content_banner_enabled false
|
66
|
+
enable_omnipresent_banner false
|
61
67
|
end
|
62
68
|
|
63
69
|
factory :user, class: "Decidim::User" do
|
@@ -65,10 +71,13 @@ FactoryBot.define do
|
|
65
71
|
password "password1234"
|
66
72
|
password_confirmation "password1234"
|
67
73
|
name { generate(:name) }
|
74
|
+
nickname { generate(:nickname) }
|
68
75
|
organization
|
69
76
|
locale { organization.default_locale }
|
70
77
|
tos_agreement "1"
|
71
78
|
avatar { Decidim::Dev.test_file("avatar.jpg", "image/jpeg") }
|
79
|
+
personal_url { Faker::Internet.url }
|
80
|
+
about { Faker::Lorem.paragraph(2) }
|
72
81
|
|
73
82
|
trait :confirmed do
|
74
83
|
confirmed_at { Time.current }
|
@@ -87,57 +96,16 @@ FactoryBot.define do
|
|
87
96
|
roles { ["user_manager"] }
|
88
97
|
end
|
89
98
|
|
90
|
-
trait :process_admin do
|
91
|
-
transient do
|
92
|
-
participatory_process { create(:participatory_process) }
|
93
|
-
end
|
94
|
-
|
95
|
-
organization { participatory_process.organization }
|
96
|
-
|
97
|
-
after(:create) do |user, evaluator|
|
98
|
-
create :participatory_process_user_role,
|
99
|
-
user: user,
|
100
|
-
participatory_process: evaluator.participatory_process,
|
101
|
-
role: :admin
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
trait :process_collaborator do
|
106
|
-
transient do
|
107
|
-
participatory_process { create(:participatory_process) }
|
108
|
-
end
|
109
|
-
|
110
|
-
organization { participatory_process.organization }
|
111
|
-
|
112
|
-
after(:create) do |user, evaluator|
|
113
|
-
create :participatory_process_user_role,
|
114
|
-
user: user,
|
115
|
-
participatory_process: evaluator.participatory_process,
|
116
|
-
role: :collaborator
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
trait :process_moderator do
|
121
|
-
transient do
|
122
|
-
participatory_process { create(:participatory_process) }
|
123
|
-
end
|
124
|
-
|
125
|
-
organization { participatory_process.organization }
|
126
|
-
|
127
|
-
after(:create) do |user, evaluator|
|
128
|
-
create :participatory_process_user_role,
|
129
|
-
user: user,
|
130
|
-
participatory_process: evaluator.participatory_process,
|
131
|
-
role: :moderator
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
99
|
trait :managed do
|
136
100
|
email { "" }
|
137
101
|
password { "" }
|
138
102
|
password_confirmation { "" }
|
139
103
|
managed { true }
|
140
104
|
end
|
105
|
+
|
106
|
+
trait :officialized do
|
107
|
+
officialized_at { Time.zone.now }
|
108
|
+
end
|
141
109
|
end
|
142
110
|
|
143
111
|
factory :participatory_process_user_role, class: "Decidim::ParticipatoryProcessUserRole" do
|
@@ -218,6 +186,8 @@ FactoryBot.define do
|
|
218
186
|
description { Decidim::Faker::Localized.wrapped("<p>", "</p>") { Decidim::Faker::Localized.sentence(4) } }
|
219
187
|
file { Decidim::Dev.test_file("city.jpeg", "image/jpeg") }
|
220
188
|
attached_to { build(:participatory_process) }
|
189
|
+
content_type { "image/jpeg" }
|
190
|
+
file_size { 108_908 }
|
221
191
|
|
222
192
|
trait :with_image do
|
223
193
|
file { Decidim::Dev.test_file("city.jpeg", "image/jpeg") }
|
@@ -225,6 +195,8 @@ FactoryBot.define do
|
|
225
195
|
|
226
196
|
trait :with_pdf do
|
227
197
|
file { Decidim::Dev.test_file("Exampledocument.pdf", "application/pdf") }
|
198
|
+
content_type { "application/pdf" }
|
199
|
+
file_size { 17_525 }
|
228
200
|
end
|
229
201
|
end
|
230
202
|
|
@@ -291,6 +263,10 @@ FactoryBot.define do
|
|
291
263
|
factory :moderation, class: "Decidim::Moderation" do
|
292
264
|
reportable { build(:dummy_resource) }
|
293
265
|
participatory_space { reportable.feature.participatory_space }
|
266
|
+
|
267
|
+
trait :hidden do
|
268
|
+
hidden_at { 1.day.ago }
|
269
|
+
end
|
294
270
|
end
|
295
271
|
|
296
272
|
factory :report, class: "Decidim::Report" do
|