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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/decidim.gemspec +1 -1
  3. data/docs/antora.yml +1 -1
  4. data/docs/modules/configure/assets/images/system-dashboard.png +0 -0
  5. data/docs/modules/configure/assets/images/system-log_in.png +0 -0
  6. data/docs/modules/configure/pages/environment_variables.adoc +24 -0
  7. data/docs/modules/configure/pages/initializer.adoc +26 -0
  8. data/docs/modules/configure/pages/system.adoc +145 -0
  9. data/docs/modules/customize/pages/menu.adoc +1 -1
  10. data/docs/modules/develop/assets/images/taxonomies.png +0 -0
  11. data/docs/modules/develop/pages/ai_tools/lang_detection_formatter.adoc +9 -0
  12. data/docs/modules/develop/pages/ai_tools/spam_detection_analyzer.adoc +20 -0
  13. data/docs/modules/develop/pages/ai_tools/spam_detection_service.adoc +25 -0
  14. data/docs/modules/develop/pages/ai_tools/spam_detection_strategy.adoc +43 -0
  15. data/docs/modules/develop/pages/ai_tools/spam_detection_trainer.adoc +83 -0
  16. data/docs/modules/develop/pages/ai_tools.adoc +12 -0
  17. data/docs/modules/develop/pages/classes/models.adoc +4 -3
  18. data/docs/modules/develop/pages/commentable.adoc +127 -0
  19. data/docs/modules/develop/pages/endorsable.adoc +6 -15
  20. data/docs/modules/develop/pages/share_tokens.adoc +153 -11
  21. data/docs/modules/develop/pages/taxonomies.adoc +476 -0
  22. data/docs/modules/install/pages/manual.adoc +1 -1
  23. data/docs/modules/services/pages/aitools.adoc +164 -0
  24. data/docs/modules/services/pages/index.adoc +1 -0
  25. data/docs/modules/services/pages/maps.adoc +2 -2
  26. data/lib/decidim/version.rb +1 -1
  27. data/package-lock.json +300 -167
  28. data/packages/browserslist-config/package.json +1 -1
  29. data/packages/core/package.json +4 -2
  30. data/packages/dev/package.json +1 -1
  31. data/packages/eslint-config/package.json +1 -1
  32. data/packages/prettier-config/package.json +1 -1
  33. data/packages/stylelint-config/package.json +1 -1
  34. data/packages/webpacker/package.json +1 -1
  35. data/packages/webpacker/src/override-config.js +11 -1
  36. metadata +55 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cfd0fd311aafc5b4ba94457a9f19a5f8cf6bf4a7ca9d53b76f13631104c87da7
4
- data.tar.gz: 8d5340c17877bf7ce67940bcbbd88a1bf3cb3f6eeb2a55a6d73466378003f528
3
+ metadata.gz: b0b6d4745bd4402702b958b586f5ceae765d0aeb700679c76188a99153e2baf7
4
+ data.tar.gz: b7e81f9856aa1dce039bc61fd41b526b5afa2b36c768cb35041b7a5f88acc91e
5
5
  SHA512:
6
- metadata.gz: e52b078d48d1ce5128005863d1d9256a28a441b2c1a6a9bee365a0b8d256a987bdee753f40d4a7f258b138276b3b4e662223618325bc2a1257852dac5d146bad
7
- data.tar.gz: 29c0a84e18b6e5577e8440f141c380377ccd7da117e10e9af44614b3422bcbd1098735d0736fe6a0d1de374966d422204dbec7199b4f368ccd1ecd63449b444d
6
+ metadata.gz: 2da4f1073487e3f9549de150f87f159bda559dedf1f7b79bc39702686585782e3ddf5e690898dee631bb74a338829a7771f266da9939dd571d1b562a517291e0
7
+ data.tar.gz: d9e0d83a5e3b79be2f51b78f1c9dae8818b1867b353cda1a184f5aa974d02f4ada20f448e9bf6065b05375e94409e7b126e65a6cfb3bc39b5a2a39b84476145a
data/decidim.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  "homepage_uri" => "https://decidim.org",
19
19
  "source_code_uri" => "https://github.com/decidim/decidim"
20
20
  }
21
- s.required_ruby_version = "~> 3.2.0"
21
+ s.required_ruby_version = "~> 3.3.0"
22
22
 
23
23
  s.name = "decidim"
24
24
 
data/docs/antora.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  name: en
2
2
  title: "Decidim Documentation"
3
- version: v0.29
3
+ version: v0.30
4
4
  asciidoc:
5
5
  attributes:
6
6
  page-lang: en@
@@ -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 :user_interests
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
@@ -0,0 +1,9 @@
1
+ = Language Detection Formatter
2
+
3
+ ```ruby
4
+ class Formatter
5
+ def cleanup(text)
6
+ strip_tags(text)
7
+ end
8
+ end
9
+ ```
@@ -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). At the action card, in right-side of the view.
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, renders the endorsements counter and the endorsement button by default. But it has the possibility to be invoked to render elements separately.
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
- cell("decidim/endorsement_buttons", resource)
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
- endorsement_buttons_cell(resource).render_endorsements_button
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
  ----