decidim 0.29.2 → 0.30.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/decidim.gemspec +1 -1
- data/docs/antora.yml +1 -1
- data/docs/modules/configure/assets/images/system-dashboard.png +0 -0
- data/docs/modules/configure/assets/images/system-log_in.png +0 -0
- data/docs/modules/configure/pages/environment_variables.adoc +24 -0
- data/docs/modules/configure/pages/initializer.adoc +26 -0
- data/docs/modules/configure/pages/system.adoc +145 -0
- data/docs/modules/customize/pages/menu.adoc +1 -1
- data/docs/modules/develop/assets/images/taxonomies.png +0 -0
- data/docs/modules/develop/pages/ai_tools/lang_detection_formatter.adoc +9 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_analyzer.adoc +20 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_service.adoc +25 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_strategy.adoc +43 -0
- data/docs/modules/develop/pages/ai_tools/spam_detection_trainer.adoc +83 -0
- data/docs/modules/develop/pages/ai_tools.adoc +12 -0
- data/docs/modules/develop/pages/classes/models.adoc +4 -3
- data/docs/modules/develop/pages/commentable.adoc +127 -0
- data/docs/modules/develop/pages/endorsable.adoc +6 -15
- data/docs/modules/develop/pages/share_tokens.adoc +153 -11
- data/docs/modules/develop/pages/taxonomies.adoc +476 -0
- data/docs/modules/install/pages/manual.adoc +1 -1
- data/docs/modules/services/pages/aitools.adoc +164 -0
- data/docs/modules/services/pages/index.adoc +1 -0
- data/docs/modules/services/pages/maps.adoc +2 -2
- data/lib/decidim/version.rb +1 -1
- data/package-lock.json +300 -167
- data/packages/browserslist-config/package.json +1 -1
- data/packages/core/package.json +4 -2
- data/packages/dev/package.json +1 -1
- data/packages/eslint-config/package.json +1 -1
- data/packages/prettier-config/package.json +1 -1
- data/packages/stylelint-config/package.json +1 -1
- data/packages/webpacker/package.json +1 -1
- data/packages/webpacker/src/override-config.js +11 -1
- metadata +55 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0b6d4745bd4402702b958b586f5ceae765d0aeb700679c76188a99153e2baf7
|
4
|
+
data.tar.gz: b7e81f9856aa1dce039bc61fd41b526b5afa2b36c768cb35041b7a5f88acc91e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2da4f1073487e3f9549de150f87f159bda559dedf1f7b79bc39702686585782e3ddf5e690898dee631bb74a338829a7771f266da9939dd571d1b562a517291e0
|
7
|
+
data.tar.gz: d9e0d83a5e3b79be2f51b78f1c9dae8818b1867b353cda1a184f5aa974d02f4ada20f448e9bf6065b05375e94409e7b126e65a6cfb3bc39b5a2a39b84476145a
|
data/decidim.gemspec
CHANGED
data/docs/antora.yml
CHANGED
Binary file
|
Binary file
|
@@ -628,6 +628,30 @@ Additional context: This has been revealed as an issue during a security audit o
|
|
628
628
|
|false
|
629
629
|
|No
|
630
630
|
|
631
|
+
|*DECIDIM_ENABLE_ETIQUETTE_VALIDATOR*
|
632
|
+
|Enable/Disable Etiquette validator. The etiquette validator is applied to the create and edit forms of Proposals, Meetings, and Debates for both regular and admin users.
|
633
|
+
|true
|
634
|
+
|No
|
635
|
+
|
636
|
+
|*DECIDIM_SPAM_DETECTION_BACKEND_USER*
|
637
|
+
| The adapter type needed for user classifier. (for CI purposes, you can set "memory")
|
638
|
+
| redis
|
639
|
+
| No
|
640
|
+
|
641
|
+
|*DECIDIM_SPAM_DETECTION_BACKEND_USER_REDIS_URL*
|
642
|
+
| The redis connection url used by the user classifier
|
643
|
+
| redis://localhost:6379/3
|
644
|
+
| No
|
645
|
+
|
646
|
+
|*DECIDIM_SPAM_DETECTION_BACKEND_RESOURCE*
|
647
|
+
| The adapter type needed for resource classifier. (for CI purposes, you can set "memory")
|
648
|
+
| redis
|
649
|
+
| No
|
650
|
+
|
651
|
+
|*DECIDIM_SPAM_DETECTION_BACKEND_RESOURCE_REDIS_URL*
|
652
|
+
| The redis connection url used by the resource classifier
|
653
|
+
| redis://localhost:6379/2
|
654
|
+
| No
|
631
655
|
|
632
656
|
|===
|
633
657
|
|
@@ -508,3 +508,29 @@ Additional Reading:
|
|
508
508
|
|
509
509
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy[Content-Security-Policy in MDN web docs]
|
510
510
|
* xref:customize:content_security_policy.adoc[Customize Content Security Policy]
|
511
|
+
|
512
|
+
== Etiquette validator configuration
|
513
|
+
|
514
|
+
This configuration option is used to enable or disable the etiquette validator in your Ruby on Rails application. The etiquette validator is responsible for ensuring that user-generated content meets specific formatting guidelines.
|
515
|
+
|
516
|
+
=== Description
|
517
|
+
|
518
|
+
The etiquette validator is applied to the create and edit forms of Proposals, Meetings, and Debates for both regular and admin users. Admin users can use the admin panel to use these forms. The validator checks for the following conditions:
|
519
|
+
|
520
|
+
* `too_much_caps`: Ensures that the content does not contain an excessive amount of capital letters.
|
521
|
+
* `too_many_marks`: Ensures that the content does not contain too many punctuation marks.
|
522
|
+
* `must_start_with_caps`: Ensures that the content starts with a capital letter.
|
523
|
+
|
524
|
+
=== Configuration
|
525
|
+
|
526
|
+
To disable the etiquette validator, set the following in your application's configuration file:
|
527
|
+
[source,ruby]
|
528
|
+
....
|
529
|
+
config.enable_etiquette_validator = false
|
530
|
+
....
|
531
|
+
|
532
|
+
Alternatively, you can use an environment variable:
|
533
|
+
[source,ruby]
|
534
|
+
....
|
535
|
+
DECIDIM_ENABLE_ETIQUETTE_VALIDATOR
|
536
|
+
....
|
@@ -0,0 +1,145 @@
|
|
1
|
+
= System
|
2
|
+
|
3
|
+
Every Decidim is multi-tenant by default. That means that you can have multiple organizations inside a same installation.
|
4
|
+
This is being used for instance for the Barcelona and Girona Provincial Governments, for offering Decidim installations
|
5
|
+
to many small cities, or by the City of Barcelona, for giving service to lots of organizations (associations,
|
6
|
+
federations, cooperatives, etc).
|
7
|
+
|
8
|
+
Even if you only have one organization you need to create it through the System Panel.
|
9
|
+
It is available after you have installed Decidim, at `/system`. For instance if your domain is `example.org`,
|
10
|
+
then it should be available at `http://example.org/system`.
|
11
|
+
|
12
|
+
After you have freshly installed Decidim, you are redirected to the System panel log-in page:
|
13
|
+
|
14
|
+
image::system-log_in.png[system panel log in]
|
15
|
+
|
16
|
+
== 1. Create a system admin account
|
17
|
+
|
18
|
+
For logging in to this dashboard, you need to create a system admin account from your terminal:
|
19
|
+
|
20
|
+
[source, console]
|
21
|
+
....
|
22
|
+
bin/rails decidim_system:create_admin
|
23
|
+
....
|
24
|
+
|
25
|
+
You will be asked for an email and a password.
|
26
|
+
For security, the password will not get displayed back at you and you need to confirm it.
|
27
|
+
|
28
|
+
== 2. Access the Dashboard
|
29
|
+
|
30
|
+
With the email and password that you have added in the past step, you are able to log in.
|
31
|
+
After you have logged in, you should see an empty dashboard:
|
32
|
+
|
33
|
+
image::system-dashboard.png[system empty dashboard]
|
34
|
+
|
35
|
+
== 3. Create a new organization
|
36
|
+
|
37
|
+
Inside of the system panel, you need to create your Organization through the form:
|
38
|
+
|
39
|
+
TIP: Please mind that some of these fields cannot change through the System Form, as changing them could
|
40
|
+
potentially leave your database in a broken state. You can change it through the console, but you will be on your own.
|
41
|
+
|
42
|
+
=== General settings
|
43
|
+
|
44
|
+
.System - New Organization form general settings
|
45
|
+
[cols="20h,10h,~"]
|
46
|
+
|===
|
47
|
+
|Field |Type |Description
|
48
|
+
|
49
|
+
|Name
|
50
|
+
|Required
|
51
|
+
|Name of your organization. For instance, "Decidim Barcelona".
|
52
|
+
|
53
|
+
|Reference prefix
|
54
|
+
|Required
|
55
|
+
|The reference prefix is used to uniquely identify resources across all organizations. For instance, "BCN". You can change how
|
56
|
+
it is created through xref:configure:initializer.adoc[Decidim's initializer] (see **Custom resource reference**).
|
57
|
+
|
58
|
+
|Host
|
59
|
+
|Required
|
60
|
+
|Fully qualified domain name. For instance, "example.org" or "decidim.barcelona".
|
61
|
+
|
62
|
+
|Secondary hosts
|
63
|
+
|Optional
|
64
|
+
|Others domains or subdomains that point to this same installation. Normally this should not be used.
|
65
|
+
Enter each one of them in a new line. For instance, "example.com".
|
66
|
+
|
67
|
+
|Organization admin name
|
68
|
+
|Required
|
69
|
+
|Name of the admin account. For instance, "Admin"
|
70
|
+
|
71
|
+
|Organization admin email
|
72
|
+
|Required
|
73
|
+
|Email for the admin account. For instance, "admin@example.org"
|
74
|
+
|
75
|
+
|Organization locales
|
76
|
+
|Required
|
77
|
+
|You need to configure at least one language. Decidim is multilingual, meaning that you can have most of the admin
|
78
|
+
contents with any number of languages. For seeing other languages you need to configure first the
|
79
|
+
xref:configure:initializer.adoc[Decidim's initializer].
|
80
|
+
|
81
|
+
|Force authentication
|
82
|
+
|Optional
|
83
|
+
|Check if you want to **Force users to authenticate before access organization**.
|
84
|
+
That means visitor they do not see any published content and they only have access to the log-in form.
|
85
|
+
|
86
|
+
|Users registration mode
|
87
|
+
|Optional
|
88
|
+
|Control how you want the login / participant register or signup to work. See below.
|
89
|
+
|
90
|
+
|Available authorizations
|
91
|
+
|Optional
|
92
|
+
|How you want to authorize and verify that your participants are who they say they are.
|
93
|
+
It depends a lot on your Organization, country, etc. See xref:customize:authorizations.adoc[Authorizations customization].
|
94
|
+
|
95
|
+
|===
|
96
|
+
|
97
|
+
=== Advanced settings
|
98
|
+
|
99
|
+
.System - New Organization form advanced settings
|
100
|
+
[cols="20h,10h,~"]
|
101
|
+
|===
|
102
|
+
|Field |Type |Description
|
103
|
+
|
104
|
+
|SMTP settings
|
105
|
+
|Optional
|
106
|
+
|Allows you to configure different SMTP servers for every organization in this installation.
|
107
|
+
See xref:services:smtp.adoc[SMTP configuration].
|
108
|
+
|
109
|
+
|Omniauth settings
|
110
|
+
|Optional
|
111
|
+
|Allows you to configure through external OAUTH providers for every Organization in this installation.
|
112
|
+
See xref:services:social_providers.adoc[Social providers configuration].
|
113
|
+
|
114
|
+
|File upload settings
|
115
|
+
|Optional
|
116
|
+
|Allows you to configure the formats accepted on your instance, as well as default file sizes for file uploads
|
117
|
+
|
118
|
+
|Content security policy
|
119
|
+
|Optional
|
120
|
+
|Allows you to configure organization based rules, but also to configure system wide policies in case your decidim instance is running
|
121
|
+
in multi tenant mode. To learn more, check this https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP[CSP header documentation].
|
122
|
+
|
123
|
+
|===
|
124
|
+
|
125
|
+
=== Users registration mode
|
126
|
+
|
127
|
+
==== Allow participants to register and login
|
128
|
+
|
129
|
+
Most of the installations use this setting. Means that everyone can register a participant account and login, without restrictions, only with an email account confirmation.
|
130
|
+
You can disable that confirmation also if you want to through xref:configure:initializer.adoc[Decidim's initializer], although we do not recommend doing that,
|
131
|
+
as it is a measure for stopping spam accounts.
|
132
|
+
|
133
|
+
==== Do not allow participants to register, but allow existing participants to login
|
134
|
+
|
135
|
+
This is for when you make a manual import of participants' accounts.
|
136
|
+
|
137
|
+
==== Access only can be done with external accounts
|
138
|
+
|
139
|
+
In the case where you have an external provider configured (like the `Omniauth settings`) and you want to have accounts from only this provider.
|
140
|
+
|
141
|
+
== Edit an organization
|
142
|
+
|
143
|
+
Finally, you can also Edit an organization, although some fields cannot be changed as some contents in the database depends on them.
|
144
|
+
|
145
|
+
For accessing your newly created Organization, you can do it by going to the domain or subdomain that you have configured in `Host`.
|
@@ -57,7 +57,7 @@ After applying the below initializer, the menu rendering will be modified to:
|
|
57
57
|
# config/initializers/decidim.user_menu.rb
|
58
58
|
|
59
59
|
Decidim.menu :user_menu do |menu|
|
60
|
-
menu.remove_item :
|
60
|
+
menu.remove_item :authorizations
|
61
61
|
menu.move :own_user_groups, after: :account
|
62
62
|
menu.move :authorizations, before: :notifications_settings
|
63
63
|
end
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
= Spam detection Analyzer
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
class ResourceAnalyzer < Decidim::Ai::SpamDetection::Resource::Base
|
5
|
+
def fields
|
6
|
+
[:title, :body, :etc]
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
def query
|
12
|
+
Your::Model.including()
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource_hidden?(resource); end
|
16
|
+
def batch_train; end
|
17
|
+
def train; end # delegated to classifier
|
18
|
+
def untrain; end # delegated to classifier
|
19
|
+
end
|
20
|
+
```
|
@@ -0,0 +1,25 @@
|
|
1
|
+
= Spam detection Service
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
class SpamDetection::Service
|
5
|
+
def initialize
|
6
|
+
@registry = Decidim::Ai.spam_detection_registry
|
7
|
+
end
|
8
|
+
|
9
|
+
def train(category, text)
|
10
|
+
# train the strategy
|
11
|
+
end
|
12
|
+
|
13
|
+
def classify(text)
|
14
|
+
# classify the text
|
15
|
+
end
|
16
|
+
|
17
|
+
def untrain(category, text)
|
18
|
+
# untrain the strategy
|
19
|
+
end
|
20
|
+
|
21
|
+
def classification_log
|
22
|
+
# return the classification log
|
23
|
+
end
|
24
|
+
end
|
25
|
+
```
|
@@ -0,0 +1,43 @@
|
|
1
|
+
= Spam detection Strategy
|
2
|
+
|
3
|
+
```ruby
|
4
|
+
module SpamDetection::Strategy
|
5
|
+
class Bayes < Base
|
6
|
+
def initialize(options = {})
|
7
|
+
# Add here your configuration, assign your variables
|
8
|
+
end
|
9
|
+
|
10
|
+
def log
|
11
|
+
return unless category
|
12
|
+
|
13
|
+
"The Classification engine marked this as #{category}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def train(category, text)
|
17
|
+
# some call to the original backend
|
18
|
+
end
|
19
|
+
|
20
|
+
# Calling this method without any trained categories will throw an error
|
21
|
+
def untrain(category, content)
|
22
|
+
# some call to the original backend
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
# some call that actually resets the backend data
|
27
|
+
end
|
28
|
+
|
29
|
+
def classify(content)
|
30
|
+
@category, @internal_score = backend.classify_with_score(content)
|
31
|
+
category
|
32
|
+
end
|
33
|
+
|
34
|
+
def score
|
35
|
+
category.presence == "spam" ? 1 : 0
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# your implementation
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
@@ -0,0 +1,83 @@
|
|
1
|
+
= Real-time training
|
2
|
+
|
3
|
+
In some instances, there may be the need to add Real-time training of the spam data. To achieve that, Decidim allows you to subscribe to 2 different events. Take into account that if you follow this strategy, you could have lots of false positives, as some spammers are using relevant content provided by participants to "cheat" the system.
|
4
|
+
|
5
|
+
== Resource training
|
6
|
+
|
7
|
+
In order to enable realtime training for based on your data, you will need to subscribe to the `decidim.admin.hide_resource:after` event by adding to your `config/initializers/ai_tools.rb` file the following content:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
Decidim::EventsManager.subscribe("decidim.admin.hide_resource:after") do |_event_name, data|
|
11
|
+
Decidim::MyModule::TrainHiddenResourceDataJob.perform_later(data[:resource])
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
In this case `data[:resource]` is the actual resource that is being hidden.
|
16
|
+
A class that would train / untrain that may look like:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# frozen_string_literal: true
|
20
|
+
|
21
|
+
module Decidim
|
22
|
+
module MyModule
|
23
|
+
class TrainHiddenResourceDataJob < ApplicationJob
|
24
|
+
include Decidim::TranslatableAttributes
|
25
|
+
|
26
|
+
def perform(resource)
|
27
|
+
return unless resource.respond_to?(:hidden?)
|
28
|
+
|
29
|
+
resource.reload
|
30
|
+
|
31
|
+
wrapped = Decidim::Ai::SpamDetection.resource_models[resource.class.name].constantize.new
|
32
|
+
|
33
|
+
if resource.hidden?
|
34
|
+
wrapped.fields.each do |field|
|
35
|
+
wrapped.untrain :ham, translated_attribute(resource.send(field))
|
36
|
+
wrapped.train :spam, translated_attribute(resource.send(field))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
== User training
|
46
|
+
As you can do the same as above for the user.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Decidim::EventsManager.subscribe("decidim.admin.block_user:after") do |_event_name, data|
|
50
|
+
Decidim::MyModule::TrainUserDataJob.perform_later(data[:resource])
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
In this case `data[:resource]` is the actual user that is being hidden.
|
55
|
+
A class that would train / untrain that may look like:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
# frozen_string_literal: true
|
59
|
+
|
60
|
+
module Decidim
|
61
|
+
module MyModule
|
62
|
+
class TrainUserDataJob < ApplicationJob
|
63
|
+
def perform(user)
|
64
|
+
user.reload
|
65
|
+
|
66
|
+
if user.blocked?
|
67
|
+
classifier.untrain :ham, user.about
|
68
|
+
classifier.train :spam, user.about
|
69
|
+
else
|
70
|
+
classifier.untrain :spam, user.about
|
71
|
+
classifier.train :ham, user.about
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def classifier
|
78
|
+
@classifier ||= Decidim::Ai::SpamDetection.user_classifier
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
```
|
@@ -0,0 +1,12 @@
|
|
1
|
+
= AI tools for decidim
|
2
|
+
|
3
|
+
== Configuration reference
|
4
|
+
* xref:services:aitools.adoc[AI Tools configuration]
|
5
|
+
|
6
|
+
== Class Specific reference
|
7
|
+
|
8
|
+
* xref:develop:ai_tools/lang_detection_formatter.adoc[Language Detection Formatter]
|
9
|
+
* xref:develop:ai_tools/spam_detection_strategy.adoc[Spam detection Strategy]
|
10
|
+
* xref:develop:ai_tools/spam_detection_service.adoc[Spam detection Service]
|
11
|
+
* xref:develop:ai_tools/spam_detection_analyzer.adoc[Spam detection Analyzer]
|
12
|
+
* xref:develop:ai_tools/spam_detection_trainer.adoc[Real-time training]
|
@@ -73,6 +73,7 @@ Most commonly used concerns are:
|
|
73
73
|
- `Decidim::ScopableParticipatorySpace`
|
74
74
|
- `Decidim::ScopableResource`
|
75
75
|
- `Decidim::Searchable`
|
76
|
+
- `xref:develop:taxonomies.adoc[Decidim::Taxonomizable]`
|
76
77
|
- `xref:develop:share_tokens.adoc[Decidim::ShareableWithToken]`
|
77
78
|
- `xref:develop:traceable.adoc[Decidim::Traceable]`
|
78
79
|
- `xref:develop:machine_translations.adoc[Decidim::TranslatableAttributes]`
|
@@ -80,9 +81,9 @@ Most commonly used concerns are:
|
|
80
81
|
|
81
82
|
=== Module specific concerns
|
82
83
|
|
83
|
-
- `Decidim::Comments::Commentable`
|
84
|
-
- `Decidim::Comments::CommentableWithComponent`
|
85
|
-
- `Decidim::Comments::HasAvailabilityAttributes`
|
84
|
+
- `xref:develop:commentable.adoc[Decidim::Comments::Commentable]`
|
85
|
+
- `xref:develop:commentable.adoc[Decidim::Comments::CommentableWithComponent]`
|
86
|
+
- `xref:develop:commentable.adoc[Decidim::Comments::HasAvailabilityAttributes]`
|
86
87
|
- `Decidim::Forms::HasQuestionnaire`
|
87
88
|
- `Decidim::Initiatives::HasArea`
|
88
89
|
- `Decidim::Initiatives::InitiativeSlug`
|
@@ -0,0 +1,127 @@
|
|
1
|
+
= Commentable
|
2
|
+
|
3
|
+
== Things can be commentable
|
4
|
+
|
5
|
+
`Commentable` is a feature to allow participants to comment on resources. This feature is used in many places in Decidim, like proposals, meetings, debates, etc.
|
6
|
+
|
7
|
+
When commenting a resource, the comments counter is increased and a notification to all the followers of the participant, the participatory space and/or the resource is sent.
|
8
|
+
|
9
|
+
Participants can comment with their own identity or with the identify of the `user_groups` they belong to.
|
10
|
+
|
11
|
+
== Data model
|
12
|
+
|
13
|
+
The `decidim_comments` table stores all the comments given to resources that are commentable. This is, one commentable has many comments, and each comment belongs to one commentable. Also, a comment can be a commentable itself, so comments can be nested.
|
14
|
+
For performance, a commentable has a counter cache of comments.
|
15
|
+
|
16
|
+
[source,ascii]
|
17
|
+
----
|
18
|
+
+----------------------+
|
19
|
+
| Decidim::Commentable |
|
20
|
+
| ((Proposal,...)) | +-------------+
|
21
|
+
+----------------------+ 0..N +-------------------+ +--+Decidim::User|
|
22
|
+
|-has_many comments |-------+Decidim::Comment | | +-------------+
|
23
|
+
|#counter cache column | +-------------------+ |
|
24
|
+
|-comments_counter | |-author: may be a |<--+
|
25
|
+
+----------------------+ | user or a | |
|
26
|
+
| user_group| | +------------------+
|
27
|
+
+-------------------+ +--+Decidim::UserGroup|
|
28
|
+
+------------------+
|
29
|
+
----
|
30
|
+
|
31
|
+
Thus, each commentable must have the comments counter cache column.
|
32
|
+
This is an example migration to add the comments counter cache column to a resource:
|
33
|
+
|
34
|
+
[source,ruby]
|
35
|
+
----
|
36
|
+
class AddCommentableCounterCacheToMeetings < ActiveRecord::Migration[5.2]
|
37
|
+
def change
|
38
|
+
add_column :decidim_meetings_meetings, :comments_count, :integer, null: false, default: 0
|
39
|
+
Decidim::Meetings::Meeting.reset_column_information
|
40
|
+
Decidim::Meetings::Meeting.find_each(&:update_comments_count)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
----
|
44
|
+
|
45
|
+
== Public view
|
46
|
+
|
47
|
+
=== The "Comment" cell
|
48
|
+
|
49
|
+
The `Comment` cell is used to render a comment in the public view. Usually, it is used in the `Comments` cell to render a list of comments.
|
50
|
+
|
51
|
+
[source,ruby]
|
52
|
+
----
|
53
|
+
cell("decidim/comments", resource)
|
54
|
+
----
|
55
|
+
|
56
|
+
This will render all the comments for the given resource.
|
57
|
+
|
58
|
+
=== Comments actions
|
59
|
+
|
60
|
+
Each comment has a set of actions that can be performed by the user. By default, these actions are available:
|
61
|
+
|
62
|
+
- A user can edit and delete their own comments.
|
63
|
+
- A user can report a comment.
|
64
|
+
- A user can copy the link to a comment.
|
65
|
+
|
66
|
+
These actions are available through a dropdown menu in the comment.
|
67
|
+
|
68
|
+
=== Resource-specific extra actions
|
69
|
+
|
70
|
+
Each resource can define extra actions that can be performed on comments. These actions must be returned by the resource object through the `actions_for_comment` method. If the resource does not define this method, or returns empty, no extra actions will be available.
|
71
|
+
|
72
|
+
This method will receive two parameters, the comment itself and the current user that wants to interact with the comment.
|
73
|
+
|
74
|
+
It must return an array of hashes, where each hash has the following keys:
|
75
|
+
|
76
|
+
- `label`: The text for the link for the action.
|
77
|
+
- `url`: The URL where the action will be performed.
|
78
|
+
- `icon`: The icon to be displayed for the action (optional).
|
79
|
+
- `method`: The HTTP method for the action, usually `:post` or `:delete` (optional as it defaults to `get`).
|
80
|
+
- `data`: A hash with the data attributes for the link (optional).
|
81
|
+
|
82
|
+
All these extra actions will be displayed in the dropdown menu of the comment after the default ones.
|
83
|
+
|
84
|
+
For example, this is how the `Proposal` model defines extra actions for comments:
|
85
|
+
|
86
|
+
[source,ruby]
|
87
|
+
----
|
88
|
+
def user_has_actions?(user)
|
89
|
+
return false if authors.include?(user)
|
90
|
+
return false if user&.blocked?
|
91
|
+
return false if user&.deleted?
|
92
|
+
return false unless user&.confirmed?
|
93
|
+
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def actions_for_comment(comment, current_user)
|
98
|
+
return if comment.commentable != self
|
99
|
+
return unless authors.include?(current_user)
|
100
|
+
return unless user_has_actions?(comment.author)
|
101
|
+
|
102
|
+
if coauthor_invitations_for(comment.author).any?
|
103
|
+
[
|
104
|
+
{
|
105
|
+
label: I18n.t("decidim.proposals.actions.cancel_coauthor_invitation"),
|
106
|
+
url: EngineRouter.main_proxy(component).cancel_proposal_invite_coauthors_path(proposal_id: id, id: comment.author.id),
|
107
|
+
icon: "user-forbid-line",
|
108
|
+
method: :delete,
|
109
|
+
data: { confirm: I18n.t("decidim.proposals.actions.cancel_coauthor_invitation_confirm") }
|
110
|
+
}
|
111
|
+
]
|
112
|
+
else
|
113
|
+
[
|
114
|
+
{
|
115
|
+
label: I18n.t("decidim.proposals.actions.mark_as_coauthor"),
|
116
|
+
url: EngineRouter.main_proxy(component).proposal_invite_coauthors_path(proposal_id: id, id: comment.author.id),
|
117
|
+
icon: "user-add-line",
|
118
|
+
method: :post,
|
119
|
+
data: { confirm: I18n.t("decidim.proposals.actions.mark_as_coauthor_confirm") }
|
120
|
+
}
|
121
|
+
]
|
122
|
+
end
|
123
|
+
end
|
124
|
+
----
|
125
|
+
|
126
|
+
This will render a new menu item with the text "Mark as coauthor" or "Cancel coauthor invitation" depending on the state of the comment author that will allow to add the comment's author as a co-author of the proposal.
|
127
|
+
|
@@ -70,7 +70,7 @@ Given that some settings have been defined in the Administration Panel, for the
|
|
70
70
|
|
71
71
|
=== The "Endorse" buttons cell
|
72
72
|
|
73
|
-
It normally appears in the resource detail view (show)
|
73
|
+
It normally appears in the resource detail view (show), at the bottom of the resource content, but above the comments when comments are enabled.
|
74
74
|
It allows users to endorse with any of their identities, the personal one, and/or their user_groups', if any.
|
75
75
|
It also shows the current number of endorsements for this resource.
|
76
76
|
|
@@ -81,34 +81,25 @@ To render this button, `decidim-core` offers the `decidim/endorsement_buttons` c
|
|
81
81
|
cell("decidim/endorsement_buttons", resource)
|
82
82
|
----
|
83
83
|
|
84
|
-
This cell
|
84
|
+
This cell will render the endorsement buttons depending on whether user endorsed the resource or not. The endorsements are labeled as *Likes*.
|
85
85
|
|
86
86
|
[source,ruby]
|
87
87
|
----
|
88
88
|
# By default the `show` method is invoked as usual
|
89
89
|
# Renders `render_endorsements_count` and `render_endorsements_button` in a block.
|
90
|
-
|
91
|
-
# It is recommended to use the `endorsement_buttons_cell` helper method
|
92
|
-
endorsement_buttons_cell(resource)
|
93
|
-
|
94
|
-
# Renders the "Endorse" button
|
90
|
+
#
|
95
91
|
# It takes into account:
|
96
92
|
# - if endorsements are enabled
|
97
93
|
# - if users are logged in
|
98
94
|
# - if users can endorse with many identities (of their user_groups)
|
99
95
|
# - if users require verification
|
100
|
-
|
101
|
-
|
102
|
-
# Renders the counter of endorsements that appears in card.
|
103
|
-
endorsement_buttons_cell(resource).render_endorsements_count
|
104
|
-
|
105
|
-
# Renders a button to perform the endorse action, but only with the personal identity of the user. It does not take into account if the user belongs to any user group.
|
106
|
-
endorsement_buttons_cell(resource).render_user_identity_endorse_button
|
96
|
+
#
|
97
|
+
cell("decidim/endorsement_buttons", resource)
|
107
98
|
----
|
108
99
|
|
109
100
|
=== The list of endorsers
|
110
101
|
|
111
|
-
The `Decidim::EndorsersListCell` renders the list of endorsers of a resource. It is usually rendered in the show of the resource, just upside the comments.
|
102
|
+
The `Decidim::EndorsersListCell` renders the list of endorsers of a resource. It is usually rendered in the show page of the resource, just upside the comments. Additionally, this cell also renders the pop-up required to view the endorsers of a certain resource.
|
112
103
|
|
113
104
|
[source,ruby]
|
114
105
|
----
|