decidim-decidim_awesome 0.9.3 → 0.10.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-decidim_awesome might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +121 -8
- data/Rakefile +1 -0
- data/app/cells/concerns/decidim/decidim_awesome/proposal_m_cell_override.rb +38 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_base_cell.rb +40 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_counter/show.erb +15 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_counter/vote_button.erb +15 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_counter_cell.rb +21 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/show.erb +35 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal/vote_block_for.erb +16 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal_cell.rb +87 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal_modal/show.erb +16 -0
- data/app/cells/decidim/decidim_awesome/voting/voting_cards_proposal_modal_cell.rb +20 -0
- data/app/cells/decidim/proposals/proposal_m/footer.erb +13 -0
- data/app/controllers/concerns/decidim/decidim_awesome/not_found_redirect.rb +2 -2
- data/app/controllers/concerns/decidim/decidim_awesome/proposals/orderable_override.rb +100 -0
- data/app/controllers/concerns/decidim/decidim_awesome/proposals/proposal_votes_controller_override.rb +64 -0
- data/app/controllers/decidim/decidim_awesome/admin/checks_controller.rb +2 -6
- data/app/controllers/decidim/decidim_awesome/admin/config_controller.rb +1 -1
- data/app/controllers/decidim/decidim_awesome/admin/custom_redirects_controller.rb +1 -1
- data/app/controllers/decidim/decidim_awesome/admin/menu_hacks_controller.rb +1 -1
- data/app/forms/decidim/decidim_awesome/admin/config_form.rb +7 -0
- data/app/forms/decidim/decidim_awesome/admin/custom_redirect_form.rb +1 -1
- data/app/forms/decidim/decidim_awesome/proposals/proposal_wizard_create_step_form_override.rb +1 -1
- data/app/helpers/decidim/decidim_awesome/admin/system_checker_helpers.rb +4 -0
- data/app/models/concerns/decidim/decidim_awesome/has_proposal_extra_fields.rb +51 -0
- data/app/models/concerns/decidim/decidim_awesome/has_vote_weight.rb +30 -0
- data/app/models/decidim/decidim_awesome/proposal_extra_field.rb +11 -0
- data/app/models/decidim/decidim_awesome/vote_weight.rb +30 -0
- data/app/overrides/decidim/proposals/admin/proposals/_form/replace_editor.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/_vote_button/replace_vote_button.html.erb.deface +7 -0
- data/app/overrides/decidim/proposals/proposals/_votes_count/replace_counter.html.erb.deface +10 -0
- data/app/{views/layouts/decidim/_head.html.erb → overrides/layouts/decidim/_application/add_intergram.html.erb.deface} +1 -1
- data/app/overrides/layouts/decidim/_head/add_awesome_legacy_scripts.rb +11 -0
- data/app/overrides/layouts/decidim/_head/add_awesome_tags.html.erb.deface +11 -0
- data/app/{views/layouts/decidim/admin/_header.html.erb → overrides/layouts/decidim/admin/_application/add_intergram.html.erb.deface} +1 -1
- data/app/{views/v0.26/layouts/decidim/admin/_header.html.erb → overrides/layouts/decidim/admin/_header/replace_scripts.html.erb.deface} +1 -6
- data/app/overrides/layouts/decidim/admin/_header/replace_styles.html.erb.deface +3 -0
- data/app/packs/images/decidim/decidim_awesome/handcard.svg +14 -0
- data/app/packs/images/decidim/decidim_awesome/handcheck.svg +17 -0
- data/app/packs/src/decidim/decidim_awesome/admin/proposal_sortings.js +13 -0
- data/app/packs/src/decidim/decidim_awesome/awesome_admin.js +1 -0
- data/app/packs/src/decidim/decidim_awesome/awesome_application.js +1 -0
- data/app/packs/src/decidim/decidim_awesome/awesome_map/controllers/controller.js +1 -7
- data/app/packs/src/decidim/decidim_awesome/editors/editor.js +10 -4
- data/app/packs/src/decidim/decidim_awesome/forms/custom_fields_renderer.js +1 -1
- data/app/packs/src/decidim/decidim_awesome/voting/voting_cards.js +63 -0
- data/app/packs/stylesheets/decidim/decidim_awesome/awesome_application.scss +1 -0
- data/app/packs/stylesheets/decidim/decidim_awesome/voting/voting_cards.scss +223 -0
- data/app/serializers/concerns/decidim/decidim_awesome/proposal_serializer_override.rb +64 -0
- data/app/types/concerns/decidim/decidim_awesome/proposal_type_override.rb +18 -0
- data/app/views/decidim/decidim_awesome/admin/checks/_assets_tester.html.erb +1 -1
- data/app/views/decidim/decidim_awesome/admin/checks/index.html.erb +1 -0
- data/app/views/decidim/decidim_awesome/admin/config/_form_proposals.html.erb +19 -1
- data/app/views/decidim/decidim_awesome/voting/voting_cards/_proposal_m_cell_footer.erb +15 -0
- data/app/views/decidim/decidim_awesome/voting/voting_cards/_show_vote_button.html.erb +6 -0
- data/app/views/decidim/decidim_awesome/voting/voting_cards/_show_votes_count.html.erb +1 -0
- data/app/views/layouts/decidim/decidim_awesome/_awesome_config.html.erb +1 -0
- data/app/views/layouts/decidim/{admin/decidim_awesome.html.erb → decidim_awesome/admin/application.html.erb} +1 -1
- data/config/locales/ca.yml +64 -1
- data/config/locales/cs.yml +46 -1
- data/config/locales/de.yml +63 -0
- data/config/locales/en.yml +73 -1
- data/config/locales/es.yml +65 -1
- data/config/locales/eu.yml +5 -0
- data/config/locales/fr.yml +58 -1
- data/config/locales/hu.yml +227 -0
- data/config/locales/it.yml +133 -4
- data/config/locales/ja.yml +64 -1
- data/config/locales/lt.yml +102 -0
- data/config/locales/nl.yml +5 -1
- data/config/locales/pt-BR.yml +5 -1
- data/config/locales/pt-PT.yml +1 -0
- data/config/locales/ro-RO.yml +148 -0
- data/config/locales/sv.yml +5 -0
- data/db/migrate/20231006113837_create_decidim_awesome_vote_weights.rb +13 -0
- data/db/migrate/20231006113841_create_decidim_awesome_proposal_extra_fields.rb +14 -0
- data/lib/decidim/decidim_awesome/awesome.rb +43 -4
- data/lib/decidim/decidim_awesome/awesome_helpers.rb +7 -0
- data/lib/decidim/decidim_awesome/checksums.yml +17 -0
- data/lib/decidim/decidim_awesome/config.rb +10 -2
- data/lib/decidim/decidim_awesome/engine.rb +80 -2
- data/lib/decidim/decidim_awesome/system_checker.rb +4 -0
- data/lib/decidim/decidim_awesome/test/factories.rb +18 -0
- data/lib/decidim/decidim_awesome/test/initializer.rb +10 -1
- data/lib/decidim/decidim_awesome/version.rb +1 -1
- data/lib/decidim/decidim_awesome/voting_manifest.rb +60 -0
- data/lib/tasks/decidim_awesome_upgrade_tasks.rake +9 -0
- data/package.json +5 -4
- metadata +61 -11
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +0 -101
- data/app/views/v0.26/layouts/decidim/_head.html.erb +0 -45
- data/app/views/v0.27/layouts/decidim/_head.html.erb +0 -49
- data/app/views/v0.27/layouts/decidim/admin/_header.html.erb +0 -11
- /data/app/models/{decidim → concerns/decidim}/decidim_awesome/user_override.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20437252da9942039c146c8b99dd93e0268bc4c988ffaf38b050580a1f93434f
|
4
|
+
data.tar.gz: 6ca1cad28ea84836b317cde0bd8094ca2607bbf644c2daf607e80bf599f54e1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b98a417b7ac9ade6622f7689dd8f8a68b0a48824c03f1580f53a8f38f7b16afbf4786fecc1da33d44a4b235eb5ffd99a9b3ec31fbe60d7e93ad918ba7b12a333
|
7
|
+
data.tar.gz: 2fdc3eda2f8c77bef0fb25b25fa809b3bb9c64b75015d597439af830c7c76ad1fc1cc60a0ba64e6aefc5158692e8eaa90d1406b38785457fe93a961739bcf766
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
=========
|
3
3
|
|
4
|
+
v0.10.0
|
5
|
+
------
|
6
|
+
|
7
|
+
Compatibility:
|
8
|
+
- Decidim v0.27.4
|
9
|
+
- Decidim v0.26.8
|
10
|
+
|
11
|
+
Features:
|
12
|
+
- Migrate to [Deface](https://github.com/spree/deface) for overrides
|
13
|
+
- Introduce Weighted Voting with configurable manifests for different types of votings with grades
|
14
|
+
- Fix wrong behaviour showing proposals on map
|
15
|
+
- Introduced new sorting options for proposals. Added alphabetical sorting, reverse sorting, sorting by votes first and last.
|
16
|
+
|
4
17
|
v0.9.3
|
5
18
|
------
|
6
19
|
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Usability and UX tweaks for Decidim.
|
|
12
12
|
This plugin allows the administrators to expand the possibilities of Decidim beyond some existing limitations.
|
13
13
|
All tweaks are provided in a optional fashion with granular permissions that let the administrator to choose exactly where to apply those mods. Some tweaks can be applied to any assembly, other in an specific participatory process or even in type of component only.
|
14
14
|
|
15
|
-
**DISCLAIMER: This module is heavily tested and widely used,
|
15
|
+
**DISCLAIMER: This module is heavily tested and widely used, however we do not accept any responsibility for breaking anything. Feedback is appreciated though.**
|
16
16
|
|
17
17
|
## Why this plugin?
|
18
18
|
|
@@ -104,7 +104,7 @@ Feel free to hide, modify or add items in the Decidim's main menu. You can also
|
|
104
104
|
|
105
105
|
#### 11. Assign admins to specific scopes and prevent them modify anything else
|
106
106
|
|
107
|
-
Convert any user on the platform (that is not currently an admin) to a limited subset of participatory spaces or event
|
107
|
+
Convert any user on the platform (that is not currently an admin) to a limited subset of participatory spaces or event components. Just add users to a box and scope them to some constraints. These users will see the "Edit" button in everywhere they have permissions. Any access to non allowed zones will redirect the user to the admin index page.
|
108
108
|
|
109
109
|
![Scoped admins authorized](examples/scoped_admins_authorized.png)
|
110
110
|
![Scoped admins unauthorized](examples/scoped_admins_unauthorized.png)
|
@@ -136,7 +136,7 @@ Using a link with a query string (ie: `/take-me-somewhere?locale=es`) that will
|
|
136
136
|
* `/processes/canary-islands?locale=es` if query string is not sanitized
|
137
137
|
|
138
138
|
> Redirections work only after all other routes have been processed, you cannot override an existing route.
|
139
|
-
> The admin panel comes with a button to check if the redirection works (meaning that no other route is used by
|
139
|
+
> The admin panel comes with a button to check if the redirection works (meaning that no other route is used by the application).
|
140
140
|
> Non-working routes will simply be ignored.
|
141
141
|
|
142
142
|
![Custom redirections screenshot](examples/custom-redirections.png)
|
@@ -149,7 +149,7 @@ Rules available:
|
|
149
149
|
|
150
150
|
* Minimum title and body length (defaults to 15 chars).
|
151
151
|
* Maximum percentage of capital letters for title and body (defaults to 25%).
|
152
|
-
* Maximum number of "marks" (aka: exclamation and interrogation signs) that can be
|
152
|
+
* Maximum number of "marks" (aka: exclamation and interrogation signs) that can be consecutive in the title or the body (defaults to 1).
|
153
153
|
* Enable/disable forcing to start the title or the body with a capital letter (defaults to "enabled").
|
154
154
|
|
155
155
|
![Custom validations](examples/custom_validations.png)
|
@@ -162,6 +162,119 @@ Results can be filtered by role and by time range and also exported as CSV or ot
|
|
162
162
|
|
163
163
|
![Admin accountability](examples/admin_accountability.png)
|
164
164
|
|
165
|
+
#### 16. Additional proposal sortings
|
166
|
+
|
167
|
+
![Proposal sorting](examples/proposal_sorting.png)
|
168
|
+
![Proposal sorting admin](examples/proposal_sorting-admin.png)
|
169
|
+
|
170
|
+
This feature allows you to add additional sorting options to the proposals component. By default 4 additional sortings are included:
|
171
|
+
|
172
|
+
- `supported_first`: Sort proposals supported by me first.
|
173
|
+
- `supported_last`: Sort proposals supported by me last.
|
174
|
+
- `az`: Sort proposals alphabetically.
|
175
|
+
- `za`: Sort proposals alphabetically (reverse).
|
176
|
+
|
177
|
+
By enabling this feature the user choosed sorting method will be stored in the browser's session. This means that if the user changes the sorting method and then navigates to another page, the same sorting will be applied.
|
178
|
+
|
179
|
+
You can disable or configure the available sorting types by setting the variable `additional_proposal_sortings` configuration in an initializer:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
# config/initializers/awesome_defaults.rb
|
183
|
+
Decidim::DecidimAwesome.configure do |config|
|
184
|
+
config.additional_proposal_sortings = :disabled
|
185
|
+
end
|
186
|
+
|
187
|
+
# Or, to disable alphabetical sorting:
|
188
|
+
|
189
|
+
Decidim::DecidimAwesome.configure do |config|
|
190
|
+
config.additional_proposal_sortings = [:supported_first, :supported_last]
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
#### 17. Weighted voting
|
195
|
+
|
196
|
+
This feature allows you to configure a proposals component to use a weighted voting system. This means that each vote can have a different weight and the result of the vote is calculated as the sum of all the weights.
|
197
|
+
|
198
|
+
Weighted voting can have different presentations that can be registered in a manifest. Admins can then choose between what type of voting they want for their proposals according to the different manifests registered (classic is always available).
|
199
|
+
|
200
|
+
Some manifests are included by default in Decidim Awesome, if you consider to create (or pay) for a new one, please open a PR or contact us.
|
201
|
+
|
202
|
+
For instance, here is how the 3-flag voting system looks like:
|
203
|
+
|
204
|
+
![Weighted voting](examples/weighted_voting.png)
|
205
|
+
|
206
|
+
##### Creating a new manifest for weighted voting
|
207
|
+
|
208
|
+
A manifest is defined in a initializer in this way:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
if Decidim::DecidimAwesome.enabled?(:weighted_proposal_voting)
|
212
|
+
# register available processors
|
213
|
+
Decidim::DecidimAwesome.voting_registry.register(:no_admins_vote) do |voting|
|
214
|
+
voting.show_vote_button_view = "decidim/decidim_awesome/voting/no_admins_vote/show_vote_button"
|
215
|
+
voting.show_votes_count_view = "decidim/decidim_awesome/voting/no_admins_vote/show_votes_count"
|
216
|
+
# voting.show_votes_count_view = "" # hide votes count if needed
|
217
|
+
voting.proposal_m_cell_footer = "decidim/decidim_awesome/voting/no_admins_vote/proposal_m_cell_footer"
|
218
|
+
# define a weight validator (optional, by default all weights are valid)
|
219
|
+
voting.weight_validator do |weight, context|
|
220
|
+
# don't allow admins to vote
|
221
|
+
next if context[:user].admin?
|
222
|
+
# don't allow to vote official proposals
|
223
|
+
next if context[:proposal].official?
|
224
|
+
|
225
|
+
weight.in? [1, 2, 3, 5]
|
226
|
+
end
|
227
|
+
|
228
|
+
# optionally, define a label generator block
|
229
|
+
# by default labels are extracted from a I18n key following this rule
|
230
|
+
# "decidim.decidim_awesome.voting.{MANIFEST_NAME}.weights.weight_{WEIGHT}"
|
231
|
+
#
|
232
|
+
# voting.label_generator do |weight, context|
|
233
|
+
# "Weight #{weight.round}"
|
234
|
+
# end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
```
|
238
|
+
|
239
|
+
A manifest must define a vote button view for the main proposal view, a vote count view for the proposal list view, a footer for the proposal cell (used in lists) and a validator for the weight value.
|
240
|
+
|
241
|
+
All views are optional, if set to `nil` they will use the original ones. If set to an empty string `""` they will be hidden.
|
242
|
+
|
243
|
+
The `weight_validator` is a Proc that receives the weight value and the context with the current user and the proposal and returns true or false if the weight is valid or not.
|
244
|
+
|
245
|
+
**Notes for view `show_vote_button_view`**
|
246
|
+
|
247
|
+
When building a new view for the vote button ([see the original](https://github.com/decidim/decidim/blob/release/0.27-stable/decidim-proposals/app/views/decidim/proposals/proposals/_vote_button.html.erb)) is important to take into account the following situations:
|
248
|
+
|
249
|
+
- If there's a `current_user` logged in
|
250
|
+
- If votes are blocked `if current_settings.votes_blocked?`
|
251
|
+
- If the user has already voted `if @voted_proposals ? @voted_proposals.include?(proposal.id) : proposal.voted_by?(current_user)`
|
252
|
+
- If maximum votes have already reached `if proposal.maximum_votes_reached?`
|
253
|
+
- If the proposal can accumulate supports beyond maximum `if proposal.can_accumulate_supports_beyond_threshold`
|
254
|
+
- If the current component allows the user to participate `if current_component.participatory_space.can_participate?(current_user)`
|
255
|
+
- Note that the [original view](https://github.com/decidim/decidim/blob/release/0.27-stable/decidim-proposals/app/views/decidim/proposals/proposals/_vote_button.html.erb) is overridden only inside the tag `<div id="proposal-<%= proposal.id %>-vote-button" class="button--vote-button">`. You only need to substitute the part inside.
|
256
|
+
|
257
|
+
To cast a vote a `POST` action is needed with the parameters `proposal_id`, `from_proposals_list` and `weight`. The route where to send the vote can be constructed such as:
|
258
|
+
|
259
|
+
```erb
|
260
|
+
<%= link_to "Vote with weight=3", proposal_proposal_vote_path(proposal_id: proposal, from_proposals_list: from_proposals_list, weight: 3), remote: true, method: :post %>
|
261
|
+
```
|
262
|
+
|
263
|
+
To delete a vote, you just need to change the method to `:delete`
|
264
|
+
|
265
|
+
**Notes for view `show_votes_count_view`**
|
266
|
+
|
267
|
+
This view must implement the number of votes already cast. It requires an HTML tag with the id `proposal-<%= proposal.id %>-votes-count`, this is used by the Ajax vote re-loader feature: It will replace it's content with the new number.
|
268
|
+
|
269
|
+
You can also completely hide this view (using `voting.show_votes_count_view = ""` in the manifest declaration). This is useful if you are using the same `show_vote_button_view` to also display the total counters (or your implementation does not use that).
|
270
|
+
|
271
|
+
**Notes for view `proposal_m_cell_footer`**
|
272
|
+
|
273
|
+
This view is used by the proposal cell in lists. It must implement the vote button and the vote count. The vote button must be a link with the same characteristics as the one explained above for the `show_vote_button_view` (typically you can just render the same view using `<%= render partial: my/path/to/view, { locals: model: proposal, from_proposals_list: true } %>`).
|
274
|
+
|
275
|
+
Note that, it is strongly recommended to add and HTML tag element with the id `proposal-<%= proposal.id %>-votes-count` so the Ajax vote re-loader can work. Even if you don't use (in this case use a `style="display:none"` attribute), this is because the Ajax reloader always look for this element and throw JavaScript errors if not.
|
276
|
+
|
277
|
+
|
165
278
|
#### To be continued...
|
166
279
|
|
167
280
|
We're not done! Please check the [issues](/decidim-ice/decidim-module-decidim_awesome/issues) (and participate) to see what's on our mind
|
@@ -181,12 +294,10 @@ And then execute:
|
|
181
294
|
```bash
|
182
295
|
bundle
|
183
296
|
bundle exec rails decidim_decidim_awesome:install:migrations
|
184
|
-
bundle exec rails
|
297
|
+
bundle exec rails decidim:upgrade
|
185
298
|
bundle exec rails db:migrate
|
186
299
|
```
|
187
300
|
|
188
|
-
> NOTE: the `decidim_decidim_awesome:webpacker:install` is only necessary for Decidim versions starting at 0.25.
|
189
|
-
|
190
301
|
If you are upgrading from a version prior to 0.8, make sure to visit the URL `/admin/decidim_awesome/checks` and run image migrations for the old images:
|
191
302
|
|
192
303
|
![Check image migrations](examples/check_image_migrations.png)
|
@@ -203,12 +314,13 @@ RAILS_ENV=production bin/rails decidim_awesome:active_storage_migrations:check_m
|
|
203
314
|
```
|
204
315
|
|
205
316
|
The correct version of Decidim Awesome should resolved automatically by the Bundler.
|
206
|
-
However you can force some specific version using `gem "decidim-decidim_awesome", "~> 0.
|
317
|
+
However you can force some specific version using `gem "decidim-decidim_awesome", "~> 0.10.0"` in the Gemfile.
|
207
318
|
|
208
319
|
Depending on your Decidim version, choose the corresponding Awesome version to ensure compatibility:
|
209
320
|
|
210
321
|
| Awesome version | Compatible Decidim versions |
|
211
322
|
|---|---|
|
323
|
+
| 0.10.0 | >= 0.26.7, >= 0.27.3 |
|
212
324
|
| 0.9.2 | >= 0.26.7, >= 0.27.3 |
|
213
325
|
| 0.9.x | 0.26.x, 0.27.x |
|
214
326
|
| 0.8.x | 0.25.x, 0.26.x |
|
@@ -217,6 +329,7 @@ Depending on your Decidim version, choose the corresponding Awesome version to e
|
|
217
329
|
| 0.5.x | 0.21.x, 0.22.x |
|
218
330
|
|
219
331
|
> *Heads up!*
|
332
|
+
> * version 0.10.0 requires database migrations! Don't forget the migrations step when updating.
|
220
333
|
> * version 0.8.0 removes CSS Themes for tenants. If you have been using them you will have to manually migrate them to custom styles.
|
221
334
|
> * version 0.8.0 uses ActiveStorage, same as Decidim 0.25. 2 new rake task have been introduced to facilitate the migration: `bin/rails decidim_awesome:active_storage_migrations:check_migration_from_carrierwave` and
|
222
335
|
`bin/rails decidim_awesome:active_storage_migrations:migrate_from_carrierwave`
|
data/Rakefile
CHANGED
@@ -26,6 +26,7 @@ def copy_helpers
|
|
26
26
|
FileUtils.mkdir_p "spec/decidim_dummy_app/app/views/v0.11", verbose: true
|
27
27
|
FileUtils.cp_r "lib/decidim/decidim_awesome/test/layouts", "spec/decidim_dummy_app/app/views/v0.11/layouts", verbose: true
|
28
28
|
FileUtils.cp "lib/decidim/decidim_awesome/test/initializer.rb", "spec/decidim_dummy_app/config/initializers/decidim_awesome.rb", verbose: true
|
29
|
+
FileUtils.cp "spec/fixtures/files/tile-0.png", "spec/decidim_dummy_app/public/tile-0.png", verbose: true
|
29
30
|
end
|
30
31
|
|
31
32
|
desc "Generates a dummy app for testing"
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DecidimAwesome
|
5
|
+
module ProposalMCellOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
10
|
+
def cache_hash
|
11
|
+
hash = []
|
12
|
+
hash << I18n.locale.to_s
|
13
|
+
hash << model.cache_key_with_version
|
14
|
+
hash << model.proposal_votes_count
|
15
|
+
hash << model.extra_fields&.vote_weight_totals
|
16
|
+
hash << model.endorsements_count
|
17
|
+
hash << model.comments_count
|
18
|
+
hash << Digest::MD5.hexdigest(model.component.cache_key_with_version)
|
19
|
+
hash << Digest::MD5.hexdigest(resource_image_path) if resource_image_path
|
20
|
+
hash << render_space? ? 1 : 0
|
21
|
+
if current_user
|
22
|
+
hash << current_user.cache_key_with_version
|
23
|
+
hash << current_user.follows?(model) ? 1 : 0
|
24
|
+
end
|
25
|
+
hash << model.follows_count
|
26
|
+
hash << Digest::MD5.hexdigest(model.authors.map(&:cache_key_with_version).to_s)
|
27
|
+
hash << (model.must_render_translation?(model.organization) ? 1 : 0) if model.respond_to?(:must_render_translation?)
|
28
|
+
hash << model.component.participatory_space.active_step.id if model.component.participatory_space.try(:active_step)
|
29
|
+
hash << has_footer?
|
30
|
+
hash << has_actions?
|
31
|
+
|
32
|
+
hash.join(Decidim.cache_key_separator)
|
33
|
+
end
|
34
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DecidimAwesome
|
5
|
+
module Voting
|
6
|
+
class VotingCardsBaseCell < Decidim::ViewModel
|
7
|
+
include Decidim::IconHelper
|
8
|
+
include Decidim::ComponentPathHelper
|
9
|
+
include Decidim::Proposals::ProposalVotesHelper
|
10
|
+
include Decidim::Proposals::Engine.routes.url_helpers
|
11
|
+
|
12
|
+
delegate :current_settings, to: :current_component
|
13
|
+
|
14
|
+
def proposal
|
15
|
+
model
|
16
|
+
end
|
17
|
+
|
18
|
+
def sanitized_title
|
19
|
+
strip_tags(translated_attribute(proposal.title))
|
20
|
+
end
|
21
|
+
|
22
|
+
def current_component
|
23
|
+
proposal.component
|
24
|
+
end
|
25
|
+
|
26
|
+
def component_settings
|
27
|
+
current_component.settings
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_vote
|
31
|
+
@current_vote ||= Decidim::Proposals::ProposalVote.find_by(author: current_user, proposal: model)
|
32
|
+
end
|
33
|
+
|
34
|
+
def user_voted_weight
|
35
|
+
current_vote&.weight
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% unless proposal.rejected? || proposal.withdrawn? %>
|
2
|
+
<% unless current_settings.votes_hidden? %>
|
3
|
+
<span class="votes_counter">
|
4
|
+
<span data-weight="3" title="<%= proposal.manifest.label_for(3) %>" class="weight_3"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_3_short") %> <%= model.weight_count(3) %></span> |
|
5
|
+
<span data-weight="2" title="<%= proposal.manifest.label_for(2) %>" class="weight_2"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_2_short") %> <%= model.weight_count(2) %></span> |
|
6
|
+
<span data-weight="1" title="<%= proposal.manifest.label_for(1) %>" class="weight_1"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_1_short") %> <%= model.weight_count(1) %></span>
|
7
|
+
<% if current_component.settings.voting_cards_show_abstain %>
|
8
|
+
| <span title="<%= proposal.manifest.label_for(0) %>" data-weight="0" class="weight_0"><%= t("decidim.decidim_awesome.voting.voting_cards.weights.weight_0_short") %> <%= model.weight_count(0) %></span>
|
9
|
+
<% end %>
|
10
|
+
</span>
|
11
|
+
<% end %>
|
12
|
+
<div id="proposal-<%= model.id %>-vote-button">
|
13
|
+
<%= render "vote_button" %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%= link_to resource_path,
|
2
|
+
class: "button #{vote_btn_class} small button--sc#{" disabled" if current_settings.votes_blocked?}",
|
3
|
+
title: t("decidim.decidim_awesome.voting.voting_cards.vote_button") do %>
|
4
|
+
<% if user_voted_weight %>
|
5
|
+
<%= icon "actions", class: "icon" %> <%= t("decidim.decidim_awesome.voting.voting_cards.voted") %>
|
6
|
+
<% elsif proposal.maximum_votes_reached? && !proposal.can_accumulate_supports_beyond_threshold && current_component.participatory_space.can_participate?(current_user) %>
|
7
|
+
<%= t("decidim.proposals.proposals.vote_button.maximum_votes_reached") %>
|
8
|
+
<% elsif vote_limit_enabled? && remaining_votes_count_for(current_user) <= 0 %>
|
9
|
+
<%= t("decidim.proposals.proposals.vote_button.no_votes_remaining") %>
|
10
|
+
<% elsif current_settings.votes_blocked? || !current_component.participatory_space.can_participate?(current_user) %>
|
11
|
+
<%= t("decidim.proposals.proposals.vote_button.votes_blocked") %>
|
12
|
+
<% else %>
|
13
|
+
<%= t("decidim.decidim_awesome.voting.voting_cards.vote_button") %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DecidimAwesome
|
5
|
+
module Voting
|
6
|
+
class VotingCardsCounterCell < VotingCardsBaseCell
|
7
|
+
def show
|
8
|
+
render :show
|
9
|
+
end
|
10
|
+
|
11
|
+
def resource_path
|
12
|
+
resource_locator(model).path
|
13
|
+
end
|
14
|
+
|
15
|
+
def vote_btn_class
|
16
|
+
user_voted_weight ? "weight_#{user_voted_weight.to_i}" : "hollow"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<h4 class="heading4 vote-title"><%= title %></h4>
|
2
|
+
|
3
|
+
<div class="flex--sbc">
|
4
|
+
<%= vote_block_for(proposal, 3) %>
|
5
|
+
<%= vote_block_for(proposal, 2) %>
|
6
|
+
<%= vote_block_for(proposal, 1) %>
|
7
|
+
</div>
|
8
|
+
|
9
|
+
<% if component_settings.voting_cards_show_abstain? %>
|
10
|
+
<%= action_authorized_link_to :vote,
|
11
|
+
voted_for?(0) ? t("decidim.decidim_awesome.voting.voting_cards.abstained") : proposal.manifest.label_for(0),
|
12
|
+
proposal_vote_path(0),
|
13
|
+
link_options(0).merge({
|
14
|
+
title: t("decidim.decidim_awesome.voting.voting_cards.voting_for", proposal: sanitized_title, type: proposal.manifest.label_for(0)),
|
15
|
+
class: "button expanded vote-action abstain-button small #{classes_for(0)}"
|
16
|
+
}) %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% if voted_for_any? && !current_settings.votes_blocked? %>
|
20
|
+
<p class="text-center">
|
21
|
+
<%= action_authorized_link_to :unvote,
|
22
|
+
t("decidim.decidim_awesome.voting.voting_cards.change_vote"),
|
23
|
+
proposal_vote_path(current_vote&.weight),
|
24
|
+
remote: true,
|
25
|
+
method: :delete,
|
26
|
+
id: "change-vote",
|
27
|
+
class: "change-vote-button vote-action" %>
|
28
|
+
</p>
|
29
|
+
<% elsif proposal.maximum_votes_reached? && !proposal.can_accumulate_supports_beyond_threshold && current_component.participatory_space.can_participate?(current_user) %>
|
30
|
+
<p class="text-center"><%= t("decidim.proposals.proposals.vote_button.maximum_votes_reached") %></p>
|
31
|
+
<% elsif vote_limit_enabled? && remaining_votes_count_for(current_user) <= 0 %>
|
32
|
+
<p class="text-center"><%= t("decidim.proposals.proposals.vote_button.no_votes_remaining") %></p>
|
33
|
+
<% elsif current_settings.votes_blocked? || !current_component.participatory_space.can_participate?(current_user) %>
|
34
|
+
<p class="text-center"><%= t("decidim.proposals.proposals.vote_button.votes_blocked") %></p>
|
35
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div id="vote-container" data-proposal-id="<%= proposal.id %>">
|
2
|
+
<div class="vote-block">
|
3
|
+
<% unless current_settings.votes_hidden? %>
|
4
|
+
<p class="vote-count" data-weight="<%= weight %>"><%= proposal_votes(weight) %></p>
|
5
|
+
<% end %>
|
6
|
+
<%= action_authorized_link_to :vote,
|
7
|
+
proposal_vote_path(weight),
|
8
|
+
**link_options(weight) do %>
|
9
|
+
<span class="vote-label"><%= proposal.manifest.label_for(weight) %></span>
|
10
|
+
<%= content_tag :svg, role: "img" do
|
11
|
+
content_tag(:title, t("decidim.decidim_awesome.voting.voting_cards.voting_for", proposal: sanitized_title, type: proposal.manifest.label_for(weight))) +
|
12
|
+
content_tag(:use, "", "href" => svg_path(weight))
|
13
|
+
end %>
|
14
|
+
<% end %>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DecidimAwesome
|
5
|
+
module Voting
|
6
|
+
class VotingCardsProposalCell < VotingCardsBaseCell
|
7
|
+
VOTE_WEIGHTS = [0, 1, 2, 3].freeze
|
8
|
+
|
9
|
+
def show
|
10
|
+
render :show
|
11
|
+
end
|
12
|
+
|
13
|
+
def vote_block_for(proposal, weight)
|
14
|
+
render partial: "vote_block", locals: {
|
15
|
+
proposal: proposal,
|
16
|
+
weight: weight
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def proposal_votes(weight)
|
21
|
+
model.weight_count(weight)
|
22
|
+
end
|
23
|
+
|
24
|
+
def voted_for?(option)
|
25
|
+
user_voted_weight == option
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_proposals_list
|
29
|
+
options[:from_proposals_list]
|
30
|
+
end
|
31
|
+
|
32
|
+
def proposal_vote_path(weight)
|
33
|
+
proposal_proposal_vote_path(proposal_id: proposal.id, from_proposals_list: from_proposals_list, weight: weight)
|
34
|
+
end
|
35
|
+
|
36
|
+
def link_options(weight)
|
37
|
+
ops = {
|
38
|
+
class: "vote-action vote-card #{classes_for(weight)}"
|
39
|
+
}
|
40
|
+
if current_user
|
41
|
+
ops.merge!({
|
42
|
+
remote: true,
|
43
|
+
method: :post
|
44
|
+
})
|
45
|
+
end
|
46
|
+
ops
|
47
|
+
end
|
48
|
+
|
49
|
+
def svg_path(weight)
|
50
|
+
card = "handcard"
|
51
|
+
card = "handcheck" if voted_for?(weight)
|
52
|
+
"#{asset_pack_path("media/images/#{card}.svg")}#handcard"
|
53
|
+
end
|
54
|
+
|
55
|
+
def classes_for(weight)
|
56
|
+
ops = ["weight_#{weight}"]
|
57
|
+
ops << "voted" if voted_for?(weight)
|
58
|
+
ops << "dim" if voted_for_any? && !voted_for?(weight)
|
59
|
+
ops << "disabled" if disabled?
|
60
|
+
|
61
|
+
ops.join(" ")
|
62
|
+
end
|
63
|
+
|
64
|
+
def disabled?
|
65
|
+
return true if voted_for_any? || current_settings.votes_blocked?
|
66
|
+
|
67
|
+
if proposal.maximum_votes_reached? && !proposal.can_accumulate_supports_beyond_threshold && current_component.participatory_space.can_participate?(current_user)
|
68
|
+
return true
|
69
|
+
end
|
70
|
+
|
71
|
+
return true if vote_limit_enabled? && remaining_votes_count_for(current_user) <= 0
|
72
|
+
end
|
73
|
+
|
74
|
+
def voted_for_any?
|
75
|
+
VOTE_WEIGHTS.any? { |opt| voted_for?(opt) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def title
|
79
|
+
txt ||= translated_attribute(current_component.settings.voting_cards_box_title)
|
80
|
+
return "" if txt == "-"
|
81
|
+
|
82
|
+
txt.presence || t("decidim.decidim_awesome.voting.voting_cards.default_box_title")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!--the modal window will be used in another pr-->
|
2
|
+
<div class="reveal vote_proposal_modal voting-voting_cards" id="VotingCardsModalHelp" data-reveal role="dialog" aria-modal="true" aria-labelledby="VotingCardsModalHelp-label">
|
3
|
+
<div class="reveal__content">
|
4
|
+
<div class="instructions"><%= vote_instructions %></div>
|
5
|
+
<div class="current-choice voting-voting_cards"><div class="vote-card"></div></div>
|
6
|
+
<div class="future-dismiss">
|
7
|
+
<%= check_box_tag "voting_cards-skip_help", current_component.id, false %>
|
8
|
+
<%= label_tag "voting_cards-skip_help", t("decidim.decidim_awesome.voting.voting_cards.modal.skip") %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="text-center">
|
12
|
+
<button class="button vote-action"><%= t("decidim.decidim_awesome.voting.voting_cards.modal.proceed") %></button>
|
13
|
+
<button class="button cancel-action hollow secondary" data-close><%= t("decidim.decidim_awesome.voting.voting_cards.modal.cancel") %></button>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module DecidimAwesome
|
5
|
+
module Voting
|
6
|
+
class VotingCardsProposalModalCell < VotingCardsBaseCell
|
7
|
+
include Decidim::Proposals::Engine.routes.url_helpers
|
8
|
+
|
9
|
+
def show
|
10
|
+
render :show
|
11
|
+
end
|
12
|
+
|
13
|
+
def vote_instructions
|
14
|
+
translated_attribute(current_component.settings.voting_cards_instructions).presence || t("decidim.decidim_awesome.voting.voting_cards.default_instructions_html",
|
15
|
+
organization: current_organization.name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%#
|
2
|
+
A hack for the Trailblazer Cell component, here we obtain the "parent" view
|
3
|
+
https://github.com/trailblazer/cells/blob/master/lib/cell/view_model.rb#L102
|
4
|
+
renders parent view by removing the awesome override from the paths
|
5
|
+
%>
|
6
|
+
<% original = normalize_options(:footer) %>
|
7
|
+
<% original[:prefixes] = original[:prefixes].filter {|path| path != Decidim::DecidimAwesome::Engine.root.join("app/cells/decidim/proposals/proposal_m").to_s } %>
|
8
|
+
|
9
|
+
<% if view = awesome_voting_manifest_for(current_component)&.proposal_m_cell_footer %>
|
10
|
+
<%= render partial: view if view.present? %>
|
11
|
+
<% else %>
|
12
|
+
<%= render original %>
|
13
|
+
<% end %>
|
@@ -43,8 +43,8 @@ module Decidim
|
|
43
43
|
return unless redirects.is_a? Hash
|
44
44
|
|
45
45
|
path, query = fullpath.split("?")
|
46
|
-
destination = redirects.dig(path
|
47
|
-
pass_query = redirects.dig(path
|
46
|
+
destination = redirects.dig(path, "destination")
|
47
|
+
pass_query = redirects.dig(path, "pass_query")
|
48
48
|
if pass_query.present?
|
49
49
|
union = destination.include?("?") ? "&" : "?"
|
50
50
|
destination = "#{destination}#{union}#{query}"
|