decidim-core 0.19.1 → 0.20.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of decidim-core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +19 -0
- data/app/assets/javascripts/decidim.js.es6 +2 -1
- data/app/assets/javascripts/decidim/input_hashtags.js.es6 +1 -1
- data/app/assets/javascripts/decidim/input_mentions.js.es6 +112 -50
- data/app/assets/stylesheets/decidim/modules/_signup.scss +57 -0
- data/app/cells/decidim/coauthorships_cell.rb +2 -6
- data/app/cells/decidim/diff_cell.rb +3 -7
- data/app/controllers/decidim/application_controller.rb +0 -8
- data/app/controllers/decidim/devise/unlocks_controller.rb +25 -0
- data/app/controllers/decidim/searches_controller.rb +0 -1
- data/app/jobs/decidim/export_participatory_space_job.rb +20 -0
- data/app/models/decidim/category.rb +2 -0
- data/app/models/decidim/component.rb +2 -0
- data/app/models/decidim/user.rb +9 -2
- data/app/models/decidim/user_group.rb +7 -0
- data/app/presenters/decidim/attachment_presenter.rb +21 -0
- data/app/resolvers/decidim/core/user_resolver.rb +61 -0
- data/app/scrubbers/decidim/user_input_scrubber.rb +2 -2
- data/app/serializers/decidim/exporters/participatory_space_components_serializer.rb +46 -0
- data/{lib → app/serializers}/decidim/exporters/serializer.rb +0 -0
- data/app/serializers/decidim/importers/importer.rb +25 -0
- data/app/serializers/decidim/importers/participatory_space_components_importer.rb +67 -0
- data/app/services/decidim/open_data_exporter.rb +1 -1
- data/app/uploaders/decidim/banner_image_uploader.rb +0 -1
- data/app/views/decidim/devise/invitations/edit.html.erb +4 -2
- data/app/views/decidim/devise/registrations/new.html.erb +2 -2
- data/app/views/decidim/devise/unlocks/new.html.erb +33 -0
- data/app/views/decidim/searches/_filters.html.erb +3 -19
- data/app/views/decidim/searches/_resources_filter_block.html.erb +20 -0
- data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
- data/app/views/layouts/decidim/_main_footer.html.erb +26 -0
- data/app/views/layouts/decidim/_mini_footer.html.erb +21 -0
- data/app/views/layouts/decidim/_wrapper.html.erb +7 -50
- data/config/initializers/devise.rb +6 -6
- data/config/locales/en.yml +0 -10
- data/config/routes.rb +1 -0
- data/db/migrate/20191028135718_add_lockable_to_users.rb +10 -0
- data/db/migrate/20191118120529_add_weight_to_categories.rb +7 -0
- data/db/migrate/20191212102051_remove_continuity_badges.rb +13 -0
- data/db/seeds.rb +18 -0
- data/lib/decidim/acts_as_author.rb +21 -0
- data/lib/decidim/component_manifest.rb +45 -4
- data/lib/decidim/core.rb +1 -0
- data/lib/decidim/core/engine.rb +0 -4
- data/lib/decidim/core/test.rb +3 -0
- data/lib/decidim/core/test/factories.rb +5 -0
- data/lib/decidim/core/test/shared_examples/acts_as_author_examples.rb +12 -0
- data/lib/decidim/core/test/shared_examples/comments_examples.rb +41 -2
- data/lib/decidim/core/test/shared_examples/searchable_participatory_space_examples.rb +145 -0
- data/lib/decidim/core/test/shared_examples/searchable_resources_shared_context.rb +12 -0
- data/lib/decidim/core/version.rb +1 -1
- data/lib/decidim/exporters.rb +0 -1
- data/lib/decidim/exporters/export_manifest.rb +72 -0
- data/lib/decidim/faker/localized.rb +10 -0
- data/lib/decidim/form_builder.rb +2 -3
- data/lib/decidim/participatory_space_manifest.rb +33 -0
- data/lib/decidim/participatory_space_resourceable.rb +8 -0
- data/lib/decidim/query_extensions.rb +16 -0
- data/lib/decidim/resourceable.rb +1 -1
- data/lib/decidim/searchable.rb +19 -1
- data/vendor/assets/javascripts/tribute.js +1683 -1621
- metadata +29 -13
- data/app/assets/images/decidim/gamification/badges/continuity.svg +0 -73
- data/app/models/decidim/continuity_badge_status.rb +0 -9
- data/app/services/decidim/continuity_badge_tracker.rb +0 -64
- data/lib/decidim/components/export_manifest.rb +0 -63
@@ -0,0 +1,26 @@
|
|
1
|
+
<div class="main-footer">
|
2
|
+
<% if current_organization.official_img_footer? %>
|
3
|
+
<%= link_to current_organization.official_url, class: "main-footer__badge" do %>
|
4
|
+
<%= image_tag current_organization.official_img_footer.url.to_s , alt: current_organization.name %>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
7
|
+
<div class="row">
|
8
|
+
<div class="medium-8 large-6 large-offset-3 column main__footer__nav">
|
9
|
+
<ul class="footer-nav">
|
10
|
+
<% if current_organization.static_pages.any? %>
|
11
|
+
<% current_organization.static_page_topics.where(show_in_footer: true).each do |page_topic| %>
|
12
|
+
<% if page_topic.pages.any? %>
|
13
|
+
<li><%= link_to translated_attribute(page_topic.title), decidim.page_path(page_topic.pages.first) %></li>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% current_organization.static_pages.where(show_in_footer: true).each do |page| %>
|
18
|
+
<li><%= link_to translated_attribute(page.title), decidim.page_path(page) %></li>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
21
|
+
<li><%= link_to t("layouts.decidim.footer.download_open_data"), decidim.open_data_download_path %></li>
|
22
|
+
</ul>
|
23
|
+
</div>
|
24
|
+
<%= render partial: "layouts/decidim/social_media_links" %>
|
25
|
+
</div>
|
26
|
+
</div>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<div class="mini-footer">
|
2
|
+
<div class="row">
|
3
|
+
<div class="medium-3 large-4 column">
|
4
|
+
<a rel="license" class="cc-badge"
|
5
|
+
href="http://creativecommons.org/licenses/by-sa/4.0/"
|
6
|
+
target="_blank" rel="noopener">
|
7
|
+
<%= image_tag("decidim/cc-badge.png", alt: "Creative Commons License" ) %>
|
8
|
+
</a>
|
9
|
+
<%= t("layouts.decidim.footer.made_with_open_source").html_safe %>
|
10
|
+
</div>
|
11
|
+
<div class="medium-3 large-2 column">
|
12
|
+
<div class="decidim-logo">
|
13
|
+
<a rel="decidim"
|
14
|
+
href="https://decidim.org/"
|
15
|
+
target="_blank" rel="noopener">
|
16
|
+
<%= image_tag("decidim/decidim-logo.svg", alt: "Decidim Logo" ) %>
|
17
|
+
</a>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
@@ -24,6 +24,8 @@ end
|
|
24
24
|
<div class="hide-for-medium" data-set="nav-holder"></div>
|
25
25
|
<div class="hide-for-medium usermenu-off-canvas-holder"
|
26
26
|
data-set="nav-login-holder"></div>
|
27
|
+
<div class="hide-for-medium mt-s ml-s mr-s search-off-canvas-holder"
|
28
|
+
data-set="nav-search-holder"></div>
|
27
29
|
</div>
|
28
30
|
<div class="off-canvas-content" data-off-canvas-content>
|
29
31
|
<div class="footer-separator">
|
@@ -95,54 +97,9 @@ end
|
|
95
97
|
<%= display_flash_messages %>
|
96
98
|
<%= yield %>
|
97
99
|
</main>
|
98
|
-
</div><!-- /.footer-separator -->
|
99
|
-
<div class="main-footer">
|
100
|
-
<% if current_organization.official_img_footer? %>
|
101
|
-
<%= link_to current_organization.official_url, class: "main-footer__badge" do %>
|
102
|
-
<%= image_tag current_organization.official_img_footer.url.to_s , alt: current_organization.name %>
|
103
|
-
<% end %>
|
104
|
-
<% end %>
|
105
|
-
<div class="row">
|
106
|
-
<div class="medium-8 large-6 large-offset-3 column main__footer__nav">
|
107
|
-
<ul class="footer-nav">
|
108
|
-
<% if current_organization.static_pages.any? %>
|
109
|
-
<% current_organization.static_page_topics.where(show_in_footer: true).each do |page_topic| %>
|
110
|
-
<% if page_topic.pages.any? %>
|
111
|
-
<li><%= link_to translated_attribute(page_topic.title), decidim.page_path(page_topic.pages.first) %></li>
|
112
|
-
<% end %>
|
113
|
-
<% end %>
|
114
|
-
|
115
|
-
<% current_organization.static_pages.where(show_in_footer: true).each do |page| %>
|
116
|
-
<li><%= link_to translated_attribute(page.title), decidim.page_path(page) %></li>
|
117
|
-
<% end %>
|
118
|
-
<% end %>
|
119
|
-
<li><%= link_to t("layouts.decidim.footer.download_open_data"), decidim.open_data_download_path %></li>
|
120
|
-
</ul>
|
121
|
-
</div>
|
122
|
-
<%= render partial: "layouts/decidim/social_media_links" %>
|
123
|
-
</div>
|
124
100
|
</div>
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
target="_blank" rel="noopener">
|
131
|
-
<%= image_tag("decidim/cc-badge.png", alt: "Creative Commons License" ) %>
|
132
|
-
</a>
|
133
|
-
<%= t("layouts.decidim.footer.made_with_open_source").html_safe %>
|
134
|
-
</div>
|
135
|
-
<div class="medium-3 large-2 column">
|
136
|
-
<div class="decidim-logo">
|
137
|
-
<a rel="decidim"
|
138
|
-
href="https://decidim.org/"
|
139
|
-
target="_blank" rel="noopener">
|
140
|
-
<%= image_tag("decidim/decidim-logo.svg", alt: "Decidim Logo" ) %>
|
141
|
-
</a>
|
142
|
-
</div>
|
143
|
-
</div>
|
144
|
-
</div>
|
145
|
-
</div>
|
146
|
-
</div><!--/.off-canvas-content-->
|
147
|
-
</div><!--/.off-canvas-wrapper-inner-->
|
148
|
-
</div><!--/.off-canvas-wrapper-->
|
101
|
+
<%= render partial: "layouts/decidim/main_footer" %>
|
102
|
+
<%= render partial: "layouts/decidim/mini_footer" %>
|
103
|
+
</div>
|
104
|
+
</div>
|
105
|
+
</div>
|
@@ -223,27 +223,27 @@ Devise.setup do |config|
|
|
223
223
|
# Defines which strategy will be used to lock an account.
|
224
224
|
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
|
225
225
|
# :none = No lock strategy. You should handle locking by yourself.
|
226
|
-
|
226
|
+
config.lock_strategy = :failed_attempts
|
227
227
|
|
228
228
|
# Defines which key will be used when locking and unlocking an account
|
229
|
-
|
229
|
+
config.unlock_keys = [:email]
|
230
230
|
|
231
231
|
# Defines which strategy will be used to unlock an account.
|
232
232
|
# :email = Sends an unlock link to the user email
|
233
233
|
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
|
234
234
|
# :both = Enables both strategies
|
235
235
|
# :none = No unlock strategy. You should handle unlocking by yourself.
|
236
|
-
|
236
|
+
config.unlock_strategy = :both
|
237
237
|
|
238
238
|
# Number of authentication tries before locking an account if lock_strategy
|
239
239
|
# is failed attempts.
|
240
|
-
|
240
|
+
config.maximum_attempts = 20
|
241
241
|
|
242
242
|
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
243
|
-
|
243
|
+
config.unlock_in = 1.hour
|
244
244
|
|
245
245
|
# Warn on the last attempt before the account is locked.
|
246
|
-
|
246
|
+
config.last_attempt_warning = true
|
247
247
|
|
248
248
|
# ==> Configuration for :recoverable
|
249
249
|
#
|
data/config/locales/en.yml
CHANGED
@@ -600,16 +600,6 @@ en:
|
|
600
600
|
gamification:
|
601
601
|
all_badges_link: See all available badges.
|
602
602
|
badges:
|
603
|
-
continuity:
|
604
|
-
conditions:
|
605
|
-
- Come here often
|
606
|
-
description: This badge is granted when you visit the platform in a regular way. We like having you around here!
|
607
|
-
description_another: This participant has connected for %{score} consecutive days at some point.
|
608
|
-
description_own: You have connected for %{score} consecutive days at some point.
|
609
|
-
name: Continuity
|
610
|
-
next_level_in: Connect for %{score} consecutive days to get to the next level!
|
611
|
-
unearned_another: This participant hasn't signed in for more than one consecutive day.
|
612
|
-
unearned_own: You haven't connected for more than one consecutive day.
|
613
603
|
followers:
|
614
604
|
conditions:
|
615
605
|
- Being active and following other people will surely make other people follow you.
|
data/config/routes.rb
CHANGED
@@ -13,6 +13,7 @@ Decidim::Core::Engine.routes.draw do
|
|
13
13
|
confirmations: "decidim/devise/confirmations",
|
14
14
|
registrations: "decidim/devise/registrations",
|
15
15
|
passwords: "decidim/devise/passwords",
|
16
|
+
unlocks: "decidim/devise/unlocks",
|
16
17
|
omniauth_callbacks: "decidim/devise/omniauth_registrations"
|
17
18
|
}
|
18
19
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AddLockableToUsers < ActiveRecord::Migration[5.2]
|
4
|
+
def change
|
5
|
+
add_column :decidim_users, :failed_attempts, :integer, default: 0, null: false # Only if lock strategy is :failed_attempts
|
6
|
+
add_column :decidim_users, :unlock_token, :string # Only if unlock strategy is :email or :both
|
7
|
+
add_column :decidim_users, :locked_at, :datetime
|
8
|
+
add_index :decidim_users, :unlock_token, unique: true
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RemoveContinuityBadges < ActiveRecord::Migration[5.2]
|
4
|
+
class BadgeScore < ApplicationRecord
|
5
|
+
self.table_name = :decidim_gamification_badge_scores
|
6
|
+
end
|
7
|
+
|
8
|
+
def change
|
9
|
+
drop_table :decidim_continuity_badge_statuses
|
10
|
+
|
11
|
+
BadgeScore.where(badge_name: :continuity).delete_all
|
12
|
+
end
|
13
|
+
end
|
data/db/seeds.rb
CHANGED
@@ -139,6 +139,24 @@ if !Rails.env.production? || ENV["SEED"]
|
|
139
139
|
accepted_tos_version: organization.tos_version
|
140
140
|
)
|
141
141
|
|
142
|
+
locked_user = Decidim::User.find_or_initialize_by(email: "locked_user@example.org")
|
143
|
+
|
144
|
+
locked_user.update!(
|
145
|
+
name: Faker::Name.name,
|
146
|
+
nickname: Faker::Twitter.unique.screen_name,
|
147
|
+
password: "decidim123456",
|
148
|
+
password_confirmation: "decidim123456",
|
149
|
+
confirmed_at: Time.current,
|
150
|
+
locale: I18n.default_locale,
|
151
|
+
organization: organization,
|
152
|
+
tos_agreement: true,
|
153
|
+
personal_url: Faker::Internet.url,
|
154
|
+
about: Faker::Lorem.paragraph(2),
|
155
|
+
accepted_tos_version: organization.tos_version
|
156
|
+
)
|
157
|
+
|
158
|
+
locked_user.lock_access!
|
159
|
+
|
142
160
|
Decidim::Messaging::Conversation.start!(
|
143
161
|
originator: admin,
|
144
162
|
interlocutors: [regular_user],
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
# This concern contains the logic related to being an author.
|
5
|
+
#
|
6
|
+
# it mainly declares abstract methods to be implemented by artifacts
|
7
|
+
# including it in its inheritance hierarchy.
|
8
|
+
#
|
9
|
+
module ActsAsAuthor
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
# Authors of Authorables must provide its presenters.
|
14
|
+
#
|
15
|
+
# Return: The presenter for the current author.
|
16
|
+
def presenter
|
17
|
+
raise NotImlementedError, "Authors must return an instance of its Presenter via this method."
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "decidim/settings_manifest"
|
4
|
-
require "decidim/
|
4
|
+
require "decidim/exporters/export_manifest"
|
5
5
|
|
6
6
|
module Decidim
|
7
7
|
# This class handles all the logic associated to configuring a component
|
@@ -58,6 +58,25 @@ module Decidim
|
|
58
58
|
# probably have the form of `Decidim::<MyComponent>::Permissions`.
|
59
59
|
attribute :permissions_class_name, String, default: "Decidim::DefaultPermissions"
|
60
60
|
|
61
|
+
# Does this component have specific data to serialize and import?
|
62
|
+
# Beyond the attributes in decidim_component table.
|
63
|
+
attribute :serializes_specific_data, Boolean, default: false
|
64
|
+
|
65
|
+
# The class to be used to serialize specific data for the current component.
|
66
|
+
# Should be a kind of `Decidim::Exporters::Serializer`.
|
67
|
+
#
|
68
|
+
# Note that this class will be initialized with the component as argument.
|
69
|
+
# Then it makes no sense to use the base Decidim::Exporters::Serializer because it
|
70
|
+
# will serialize the component itself, not the specific data depending on it.
|
71
|
+
# Thus you will always be setting a subclass of `Decidim::Exporters::Serializer`.
|
72
|
+
#
|
73
|
+
attribute :specific_data_serializer_class_name, String
|
74
|
+
|
75
|
+
# The class to be used to import specific data for the current component.
|
76
|
+
# Should be a kind of `Decidim::Importers::Importer`.
|
77
|
+
#
|
78
|
+
attribute :specific_data_importer_class_name, String
|
79
|
+
|
61
80
|
validates :name, presence: true
|
62
81
|
|
63
82
|
# Public: Registers a hook to this manifest. Hooks get fired when some
|
@@ -134,7 +153,7 @@ module Decidim
|
|
134
153
|
end
|
135
154
|
|
136
155
|
# Public: Registers an export artifact with a name and its properties
|
137
|
-
# defined in `Decidim::
|
156
|
+
# defined in `Decidim::Exporters::ExportManifest`.
|
138
157
|
#
|
139
158
|
# Export artifacts provide an unified way for components to register
|
140
159
|
# exportable collections serialized via a `Serializer` than eventually
|
@@ -156,15 +175,19 @@ module Decidim
|
|
156
175
|
# Pubic: Returns a collection of previously registered export manifests
|
157
176
|
# for this component.
|
158
177
|
#
|
159
|
-
# Returns an Array<Decidim::
|
178
|
+
# Returns an Array<Decidim::Exporters::ExportManifest>.
|
160
179
|
def export_manifests
|
161
180
|
@export_manifests ||= Array(@exports).map do |(name, block)|
|
162
|
-
Decidim::
|
181
|
+
Decidim::Exporters::ExportManifest.new(name, self).tap do |manifest|
|
163
182
|
block.call(manifest)
|
164
183
|
end
|
165
184
|
end
|
166
185
|
end
|
167
186
|
|
187
|
+
def serializes_specific_data?
|
188
|
+
serializes_specific_data
|
189
|
+
end
|
190
|
+
|
168
191
|
# Public: Stores an instance of StatsRegistry
|
169
192
|
def stats
|
170
193
|
@stats ||= StatsRegistry.new
|
@@ -192,6 +215,24 @@ module Decidim
|
|
192
215
|
permissions_class_name&.constantize
|
193
216
|
end
|
194
217
|
|
218
|
+
# Public: Finds the specific data serializer class from its name, using the
|
219
|
+
# `specific_data_serializer_class_name` attribute. If the class does not exist,
|
220
|
+
# it raises an exception. If the class name is not set, it returns nil.
|
221
|
+
#
|
222
|
+
# Returns a Decidim::Exporters::Serializer subclass or nil.
|
223
|
+
def specific_data_serializer_class
|
224
|
+
specific_data_serializer_class_name&.constantize
|
225
|
+
end
|
226
|
+
|
227
|
+
# Public: Finds the specific data importer class from its name, using the
|
228
|
+
# `specific_data_importerer_class_name` attribute. If the class does not exist,
|
229
|
+
# it raises an exception. If the class name is not set, it returns nil.
|
230
|
+
#
|
231
|
+
# Returns a Decidim::Importers::Importer subclass or nil.
|
232
|
+
def specific_data_importer_class
|
233
|
+
specific_data_importer_class_name&.constantize
|
234
|
+
end
|
235
|
+
|
195
236
|
# Public: Registers a resource. Exposes a DSL defined by
|
196
237
|
# `Decidim::ResourceManifest`. Automatically sets the component manifest
|
197
238
|
# for that resource to the current one.
|
data/lib/decidim/core.rb
CHANGED
@@ -5,6 +5,7 @@ require "decidim/core/api"
|
|
5
5
|
require "decidim/core/version"
|
6
6
|
# Decidim configuration.
|
7
7
|
module Decidim
|
8
|
+
autoload :ActsAsAuthor, "decidim/acts_as_author"
|
8
9
|
autoload :TranslatableAttributes, "decidim/translatable_attributes"
|
9
10
|
autoload :JsonbAttributes, "decidim/jsonb_attributes"
|
10
11
|
autoload :FormBuilder, "decidim/form_builder"
|
data/lib/decidim/core/engine.rb
CHANGED
@@ -379,10 +379,6 @@ module Decidim
|
|
379
379
|
badge.levels = [1, 15, 30, 60, 100]
|
380
380
|
badge.reset = ->(user) { user.followers.count }
|
381
381
|
end
|
382
|
-
|
383
|
-
Decidim::Gamification.register_badge(:continuity) do |badge|
|
384
|
-
badge.levels = [2, 10, 30, 60, 180, 365]
|
385
|
-
end
|
386
382
|
end
|
387
383
|
|
388
384
|
initializer "nbspw" do
|
data/lib/decidim/core/test.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "decidim/core/test/shared_examples/acts_as_author_examples"
|
3
4
|
require "decidim/core/test/shared_examples/authorable"
|
4
5
|
require "decidim/core/test/shared_examples/coauthorable"
|
5
6
|
require "decidim/core/test/shared_examples/publicable"
|
@@ -42,4 +43,6 @@ require "decidim/core/test/shared_examples/amendable/amendment_accepted_event_ex
|
|
42
43
|
require "decidim/core/test/shared_examples/amendable/amendment_rejected_event_examples"
|
43
44
|
require "decidim/core/test/shared_examples/amendable/amendment_promoted_event_examples"
|
44
45
|
require "decidim/core/test/shared_examples/uncommentable_component_examples"
|
46
|
+
require "decidim/core/test/shared_examples/searchable_resources_shared_context"
|
47
|
+
require "decidim/core/test/shared_examples/searchable_participatory_space_examples"
|
45
48
|
require "decidim/core/test/shared_examples/has_private_users"
|
@@ -55,6 +55,7 @@ FactoryBot.define do
|
|
55
55
|
factory :category, class: "Decidim::Category" do
|
56
56
|
name { generate_localized_title }
|
57
57
|
description { Decidim::Faker::Localized.wrapped("<p>", "</p>") { generate_localized_title } }
|
58
|
+
weight { 0 }
|
58
59
|
|
59
60
|
association :participatory_space, factory: :participatory_process
|
60
61
|
end
|
@@ -339,6 +340,10 @@ FactoryBot.define do
|
|
339
340
|
}
|
340
341
|
end
|
341
342
|
end
|
343
|
+
|
344
|
+
trait :with_permissions do
|
345
|
+
settings { { Random.rand => Random.new.bytes(5) } }
|
346
|
+
end
|
342
347
|
end
|
343
348
|
|
344
349
|
factory :scope_type, class: "Decidim::ScopeType" do
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
# users of this test should delare the `subject` variable.
|
6
|
+
shared_examples "acts as author" do
|
7
|
+
describe "presenter" do
|
8
|
+
it "returns an instance of the presenter for this author" do
|
9
|
+
expect(subject.presenter).to be_present
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -193,13 +193,12 @@ shared_examples "comments" do
|
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
196
|
-
describe "mentions" do
|
196
|
+
describe "mentions drop-down", :slow do
|
197
197
|
before do
|
198
198
|
visit resource_path
|
199
199
|
|
200
200
|
within ".add-comment form" do
|
201
201
|
fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: content
|
202
|
-
click_button "Send"
|
203
202
|
end
|
204
203
|
end
|
205
204
|
|
@@ -207,6 +206,46 @@ shared_examples "comments" do
|
|
207
206
|
let!(:mentioned_user) { create(:user, :confirmed, organization: organization) }
|
208
207
|
let(:content) { "A valid user mention: @#{mentioned_user.nickname}" }
|
209
208
|
|
209
|
+
context "when text finish with a mention" do
|
210
|
+
it "shows the tribute container" do
|
211
|
+
expect(page).to have_selector(".tribute-container", text: mentioned_user.name)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "when text contains a mention" do
|
216
|
+
let(:content) { "A valid user mention: @#{mentioned_user.nickname}." }
|
217
|
+
|
218
|
+
it "shows the tribute container" do
|
219
|
+
expect(page).not_to have_selector(".tribute-container", text: mentioned_user.name)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context "when mentioning a non valid user" do
|
225
|
+
let!(:mentioned_user) { create(:user, organization: organization) }
|
226
|
+
let(:content) { "A unconfirmed user mention: @#{mentioned_user.nickname}" }
|
227
|
+
|
228
|
+
it "do not show the tribute container" do
|
229
|
+
expect(page).not_to have_selector(".tribute-container")
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
describe "mentions", :slow do
|
235
|
+
before do
|
236
|
+
visit resource_path
|
237
|
+
|
238
|
+
within ".add-comment form" do
|
239
|
+
fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: content
|
240
|
+
click_button "Send"
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "when mentioning a valid user" do
|
245
|
+
let!(:mentioned_user) { create(:user, :confirmed, organization: organization) }
|
246
|
+
# do not finish with the mention to avoid trigger the drop-down
|
247
|
+
let(:content) { "A valid user mention: @#{mentioned_user.nickname}." }
|
248
|
+
|
210
249
|
it "replaces the mention with a link to the user's profile" do
|
211
250
|
expect(page).to have_comment_from(user, "A valid user mention: @#{mentioned_user.nickname}")
|
212
251
|
expect(page).to have_link "@#{mentioned_user.nickname}", href: "/profiles/#{mentioned_user.nickname}"
|