decidim-proposals 0.20.1 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/decidim/proposals/admin/proposals.es6 +24 -11
- data/app/cells/decidim/proposals/cost_report/show.erb +35 -0
- data/app/cells/decidim/proposals/cost_report_cell.rb +42 -0
- data/app/cells/decidim/proposals/proposal_m_cell.rb +9 -1
- data/app/cells/decidim/proposals/proposal_tags/show.erb +12 -10
- data/app/cells/decidim/proposals/proposal_tags_cell.rb +5 -0
- data/app/commands/decidim/proposals/admin/answer_proposal.rb +24 -46
- data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +61 -0
- data/app/commands/decidim/proposals/admin/create_proposal.rb +5 -0
- data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +85 -0
- data/app/commands/decidim/proposals/admin/publish_answers.rb +67 -0
- data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +62 -0
- data/app/commands/decidim/proposals/admin/update_proposal_scope.rb +75 -0
- data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +82 -0
- data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +16 -6
- data/app/controllers/decidim/proposals/admin/proposal_notes_controller.rb +8 -9
- data/app/controllers/decidim/proposals/admin/proposals_controller.rb +105 -29
- data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +58 -0
- data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +19 -3
- data/app/controllers/decidim/proposals/proposals_controller.rb +42 -7
- data/app/controllers/decidim/proposals/versions_controller.rb +4 -1
- data/app/events/decidim/proposals/admin/update_proposal_scope_event.rb +11 -0
- data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +27 -2
- data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +37 -0
- data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +8 -0
- data/app/helpers/decidim/proposals/admin/filterable_helper.rb +17 -0
- data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +35 -0
- data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +63 -0
- data/app/helpers/decidim/proposals/admin/proposals_helper.rb +122 -0
- data/app/helpers/decidim/proposals/application_helper.rb +36 -25
- data/app/helpers/decidim/proposals/collaborative_draft_helper.rb +9 -9
- data/app/helpers/decidim/proposals/proposal_cells_helper.rb +1 -1
- data/app/helpers/decidim/proposals/proposals_helper.rb +18 -0
- data/app/models/decidim/proposals/proposal.rb +163 -16
- data/app/models/decidim/proposals/valuation_assignment.rb +24 -0
- data/app/permissions/decidim/proposals/admin/permissions.rb +77 -11
- data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -1
- data/app/presenters/decidim/proposals/admin_log/valuation_assignment_presenter.rb +51 -0
- data/app/presenters/decidim/proposals/admin_log/value_types/valuator_role_user_presenter.rb +19 -0
- data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +2 -28
- data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +22 -0
- data/app/presenters/decidim/proposals/proposal_presenter.rb +26 -1
- data/app/services/decidim/proposals/collaborative_draft_search.rb +18 -10
- data/app/services/decidim/proposals/proposal_search.rb +33 -40
- data/app/types/decidim/proposals/proposal_input_filter.rb +29 -0
- data/app/types/decidim/proposals/proposal_input_sort.rb +28 -0
- data/app/types/decidim/proposals/proposal_type.rb +35 -4
- data/app/types/decidim/proposals/proposals_type.rb +14 -17
- data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +35 -0
- data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +8 -2
- data/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
- data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +25 -17
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +21 -1
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +14 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +25 -0
- data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +15 -0
- data/app/views/decidim/proposals/admin/proposals/index.html.erb +16 -7
- data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +12 -0
- data/app/views/decidim/proposals/admin/proposals/show.html.erb +186 -0
- data/app/views/decidim/proposals/admin/proposals/update_category.js.erb +3 -2
- data/app/views/decidim/proposals/admin/proposals/update_scope.js.erb +27 -0
- data/app/views/decidim/proposals/collaborative_drafts/_filters.html.erb +3 -3
- data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_filters.html.erb +12 -12
- data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +1 -4
- data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/_vote_button.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/index.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/new.html.erb +1 -1
- data/app/views/decidim/proposals/proposals/show.html.erb +17 -23
- data/config/locales/ar.yml +69 -17
- data/config/locales/ca.yml +113 -18
- data/config/locales/cs.yml +123 -31
- data/config/locales/de.yml +38 -18
- data/config/locales/el.yml +1 -0
- data/config/locales/en.yml +112 -17
- data/config/locales/es-MX.yml +112 -17
- data/config/locales/es-PY.yml +112 -17
- data/config/locales/es.yml +113 -18
- data/config/locales/eu.yml +38 -18
- data/config/locales/fi-plain.yml +113 -18
- data/config/locales/fi.yml +113 -18
- data/config/locales/fr.yml +38 -18
- data/config/locales/gl.yml +38 -18
- data/config/locales/hu.yml +112 -17
- data/config/locales/id-ID.yml +38 -18
- data/config/locales/is-IS.yml +25 -15
- data/config/locales/it.yml +38 -18
- data/config/locales/nl.yml +43 -18
- data/config/locales/no.yml +66 -18
- data/config/locales/pl.yml +38 -18
- data/config/locales/pt-BR.yml +39 -19
- data/config/locales/pt.yml +39 -19
- data/config/locales/ru.yml +25 -17
- data/config/locales/sv.yml +39 -18
- data/config/locales/tr-TR.yml +38 -18
- data/config/locales/uk.yml +25 -17
- data/db/migrate/20200203111239_add_proposal_valuation_assignments.rb +12 -0
- data/db/migrate/20200210135152_add_costs_to_proposals.rb +9 -0
- data/db/migrate/20200212120110_sync_proposals_state_with_amendments_state.rb +28 -0
- data/db/migrate/20200227175922_add_state_published_at_to_proposals.rb +7 -0
- data/db/migrate/20200306123652_publish_existing_proposals_state.rb +15 -0
- data/lib/decidim/proposals.rb +1 -0
- data/lib/decidim/proposals/admin_engine.rb +7 -3
- data/lib/decidim/proposals/component.rb +39 -19
- data/lib/decidim/proposals/engine.rb +1 -1
- data/lib/decidim/proposals/test/factories.rb +55 -0
- data/lib/decidim/proposals/valuatable.rb +21 -0
- data/lib/decidim/proposals/version.rb +1 -1
- metadata +53 -36
- data/app/views/decidim/proposals/admin/proposal_answers/edit.html.erb +0 -22
- data/app/views/decidim/proposals/admin/proposal_notes/index.html.erb +0 -3
- data/app/views/decidim/proposals/admin/shared/_info_proposal.html.erb +0 -20
- data/app/views/decidim/proposals/proposal_widgets/show.html.erb +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e2beae792f2e71369afee5770fce30f6ec7b4b2baf3e89da9cd905c2c99a1e9
|
|
4
|
+
data.tar.gz: b4faeabfaa6b595a48acb8fb0e320bb404c746da7fb1fe0229b8888efa39b0ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18a69a6b8e6ce11c8a91acb8f6370111140612b3e33f62d73de4424d2834691c2f84074adac3c63fa77049954c4285f66876a12748216c4e2ddba55888253a8e
|
|
7
|
+
data.tar.gz: 2dc55deb9e785df8f31b8b3fc940a09049688b2fa96ec38ab55687428edd2b977433e186e6cebafdf4d98205687d65c89c758a39e92d44d6cf11d30657ae7308
|
|
@@ -4,18 +4,31 @@ $(document).ready(function () {
|
|
|
4
4
|
return $('.table-list .js-check-all-proposal:checked').length
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
let selectedProposalsNotPublishedAnswerCount = function() {
|
|
8
|
+
return $('.table-list [data-published-state=false] .js-check-all-proposal:checked').length
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
window.selectedProposalsCountUpdate = function() {
|
|
8
|
-
|
|
12
|
+
const selectedProposals = selectedProposalsCount();
|
|
13
|
+
const selectedProposalsNotPublishedAnswer = selectedProposalsNotPublishedAnswerCount();
|
|
14
|
+
if(selectedProposals == 0){
|
|
9
15
|
$("#js-selected-proposals-count").text("")
|
|
10
16
|
} else {
|
|
11
|
-
$("#js-selected-proposals-count").text(
|
|
17
|
+
$("#js-selected-proposals-count").text(selectedProposals);
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
if(
|
|
20
|
+
if(selectedProposals >= 2) {
|
|
15
21
|
$('button[data-action="merge-proposals"]').parent().show();
|
|
16
22
|
} else {
|
|
17
23
|
$('button[data-action="merge-proposals"]').parent().hide();
|
|
18
24
|
}
|
|
25
|
+
|
|
26
|
+
if(selectedProposalsNotPublishedAnswer > 0) {
|
|
27
|
+
$('button[data-action="publish-answers"]').parent().show();
|
|
28
|
+
$('#js-form-publish-answers-number').text(selectedProposalsNotPublishedAnswer);
|
|
29
|
+
} else {
|
|
30
|
+
$('button[data-action="publish-answers"]').parent().hide();
|
|
31
|
+
}
|
|
19
32
|
}
|
|
20
33
|
|
|
21
34
|
let showBulkActionsButton = function() {
|
|
@@ -24,7 +37,7 @@ $(document).ready(function () {
|
|
|
24
37
|
}
|
|
25
38
|
}
|
|
26
39
|
|
|
27
|
-
|
|
40
|
+
window.hideBulkActionsButton = function(force = false) {
|
|
28
41
|
if(selectedProposalsCount() == 0 || force == true){
|
|
29
42
|
$("#js-bulk-actions-button").addClass('hide');
|
|
30
43
|
$("#js-bulk-actions-dropdown").removeClass('is-open');
|
|
@@ -35,12 +48,12 @@ $(document).ready(function () {
|
|
|
35
48
|
$("#js-other-actions-wrapper").removeClass('hide');
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
|
|
51
|
+
window.hideOtherActionsButtons = function() {
|
|
39
52
|
$("#js-other-actions-wrapper").addClass('hide');
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
window.hideBulkActionForms = function() {
|
|
43
|
-
|
|
56
|
+
$(".js-bulk-action-form").addClass('hide');
|
|
44
57
|
}
|
|
45
58
|
|
|
46
59
|
if ($('.js-bulk-action-form').length) {
|
|
@@ -57,8 +70,8 @@ $(document).ready(function () {
|
|
|
57
70
|
})
|
|
58
71
|
|
|
59
72
|
$(`#js-${action}-actions`).removeClass('hide');
|
|
60
|
-
hideBulkActionsButton(true);
|
|
61
|
-
hideOtherActionsButtons();
|
|
73
|
+
window.hideBulkActionsButton(true);
|
|
74
|
+
window.hideOtherActionsButtons();
|
|
62
75
|
}
|
|
63
76
|
})
|
|
64
77
|
|
|
@@ -71,7 +84,7 @@ $(document).ready(function () {
|
|
|
71
84
|
showBulkActionsButton();
|
|
72
85
|
} else {
|
|
73
86
|
$(".js-check-all-proposal").closest('tr').removeClass('selected');
|
|
74
|
-
hideBulkActionsButton();
|
|
87
|
+
window.hideBulkActionsButton();
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
selectedProposalsCountUpdate();
|
|
@@ -96,12 +109,12 @@ $(document).ready(function () {
|
|
|
96
109
|
showBulkActionsButton();
|
|
97
110
|
$(this).closest('tr').addClass('selected');
|
|
98
111
|
} else {
|
|
99
|
-
hideBulkActionsButton();
|
|
112
|
+
window.hideBulkActionsButton();
|
|
100
113
|
$(this).closest('tr').removeClass('selected');
|
|
101
114
|
}
|
|
102
115
|
|
|
103
116
|
if ($('.js-check-all-proposal:checked').length === 0) {
|
|
104
|
-
hideBulkActionsButton();
|
|
117
|
+
window.hideBulkActionsButton();
|
|
105
118
|
}
|
|
106
119
|
|
|
107
120
|
$('.js-bulk-action-form').find(".js-proposal-id-"+proposal_id).prop('checked', checked);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<div id="proposal-costs" class="card card--secondary" data-toggler=".expanded-text">
|
|
2
|
+
<div class="card__content">
|
|
3
|
+
<div class="mb-s">
|
|
4
|
+
<div class="data-title">
|
|
5
|
+
<h3 class="data-title__over">
|
|
6
|
+
<%= t("decidim.proposals.proposals.show.estimated_cost") %>
|
|
7
|
+
</h3>
|
|
8
|
+
<div>
|
|
9
|
+
<strong class="data-title__main">
|
|
10
|
+
<%= cost %>
|
|
11
|
+
</strong>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="data-title__sub">
|
|
14
|
+
<%= execution_period %>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
<div id="execution-cost-short" class="text-toggle__short">
|
|
19
|
+
<%= cost_report_short %>
|
|
20
|
+
<% if needs_text_toggle? %>
|
|
21
|
+
<button class="muted-link" data-toggle="proposal-costs">
|
|
22
|
+
<%= t("decidim.proposals.proposals.show.read_more") %>
|
|
23
|
+
</button>
|
|
24
|
+
<% end %>
|
|
25
|
+
</div>
|
|
26
|
+
<% if needs_text_toggle? %>
|
|
27
|
+
<div id="execution-cost-long" class="text-toggle__long">
|
|
28
|
+
<%= cost_report %>
|
|
29
|
+
<button class="muted-link" data-toggle="proposal-costs">
|
|
30
|
+
<%= t("decidim.proposals.proposals.show.read_less") %>
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
<% end %>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "cell/partial"
|
|
4
|
+
|
|
5
|
+
module Decidim
|
|
6
|
+
module Proposals
|
|
7
|
+
# This cell renders the cost report for a proposal.
|
|
8
|
+
class CostReportCell < Decidim::ViewModel
|
|
9
|
+
include ActionView::Helpers::NumberHelper
|
|
10
|
+
include Decidim::SanitizeHelper
|
|
11
|
+
include Decidim::LayoutHelper
|
|
12
|
+
include ProposalCellsHelper
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def cost
|
|
17
|
+
number_to_currency(model.cost)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def cost_report
|
|
21
|
+
decidim_sanitize(translated_attribute(model.cost_report).html_safe)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def needs_text_toggle?
|
|
25
|
+
cost_report != cost_report_short
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cost_report_short
|
|
29
|
+
decidim_sanitize(
|
|
30
|
+
html_truncate(
|
|
31
|
+
translated_attribute(model.cost_report).html_safe,
|
|
32
|
+
length: 200
|
|
33
|
+
)
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def execution_period
|
|
38
|
+
decidim_sanitize(translated_attribute(model.execution_period).html_safe)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -27,7 +27,7 @@ module Decidim
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def has_badge?
|
|
30
|
-
|
|
30
|
+
published_state? || withdrawn?
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def has_link_to_resource?
|
|
@@ -94,6 +94,14 @@ module Decidim
|
|
|
94
94
|
def can_be_followed?
|
|
95
95
|
!model.withdrawn?
|
|
96
96
|
end
|
|
97
|
+
|
|
98
|
+
def has_image?
|
|
99
|
+
model.attachments.first.present? && model.attachments.first.file.content_type.start_with?("image") && model.component.settings.allow_card_image
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def resource_image_path
|
|
103
|
+
model.attachments.first.url if has_image?
|
|
104
|
+
end
|
|
97
105
|
end
|
|
98
106
|
end
|
|
99
107
|
end
|
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
<figure>
|
|
2
|
-
<
|
|
3
|
-
<strong>
|
|
4
|
-
<%= t("filed_as", scope: "decidim.proposals.proposals.tags") %>
|
|
5
|
-
</strong>
|
|
6
|
-
</figcaption>
|
|
7
|
-
|
|
8
|
-
<ul>
|
|
2
|
+
<ul class="tags tags--proposal tags--list">
|
|
9
3
|
<% if category.present? %>
|
|
10
4
|
<li>
|
|
11
|
-
<%= link_to translated_attribute(category.name), resource_locator(model).index(filter: { category_id: category.id }) %>
|
|
5
|
+
<%= link_to translated_attribute(category.name), resource_locator(model).index(filter: { category_id: [category.id.to_s] }) %>
|
|
12
6
|
<% if previous_category.present? && show_previous_category? %>
|
|
13
7
|
|
|
14
8
|
<small class="text-small">
|
|
15
|
-
<%= t("changed_from", scope: "decidim.proposals.proposals.tags",
|
|
9
|
+
<%= t("changed_from", scope: "decidim.proposals.proposals.tags", previous_name: "#{previous_category.translated_name}").html_safe %>
|
|
16
10
|
</small>
|
|
17
11
|
<% end %>
|
|
18
12
|
</li>
|
|
19
13
|
<% end %>
|
|
20
14
|
|
|
21
15
|
<% if has_visible_scopes?(model) %>
|
|
22
|
-
<li
|
|
16
|
+
<li>
|
|
17
|
+
<%= link_to translated_attribute(scope.name), resource_locator(model).index(filter: { scope_id: [scope.id] }) %>
|
|
18
|
+
<% if previous_scope.present? && show_previous_scope? %>
|
|
19
|
+
|
|
20
|
+
<small class="text-small">
|
|
21
|
+
<%= t("changed_from", scope: "decidim.proposals.proposals.tags", previous_name: "#{translated_attribute(previous_scope.name)}").html_safe %>
|
|
22
|
+
</small>
|
|
23
|
+
<% end %>
|
|
24
|
+
</li>
|
|
23
25
|
<% end %>
|
|
24
26
|
</ul>
|
|
25
27
|
</figure>
|
|
@@ -11,6 +11,7 @@ module Decidim
|
|
|
11
11
|
property :category
|
|
12
12
|
property :previous_category
|
|
13
13
|
property :scope
|
|
14
|
+
property :previous_scope
|
|
14
15
|
|
|
15
16
|
def show
|
|
16
17
|
render if has_category_or_scopes?
|
|
@@ -22,6 +23,10 @@ module Decidim
|
|
|
22
23
|
options[:show_previous_category].to_s != "false"
|
|
23
24
|
end
|
|
24
25
|
|
|
26
|
+
def show_previous_scope?
|
|
27
|
+
options[:show_previous_scope].to_s != "false"
|
|
28
|
+
end
|
|
29
|
+
|
|
25
30
|
def has_category_or_scopes?
|
|
26
31
|
category.present? || has_visible_scopes?(model)
|
|
27
32
|
end
|
|
@@ -23,16 +23,19 @@ module Decidim
|
|
|
23
23
|
def call
|
|
24
24
|
return broadcast(:invalid) if form.invalid?
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
store_initial_proposal_state
|
|
27
|
+
|
|
28
|
+
transaction do
|
|
29
|
+
answer_proposal
|
|
30
|
+
notify_proposal_answer
|
|
31
|
+
end
|
|
29
32
|
|
|
30
33
|
broadcast(:ok)
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
private
|
|
34
37
|
|
|
35
|
-
attr_reader :form, :proposal
|
|
38
|
+
attr_reader :form, :proposal, :initial_has_state_published, :initial_state
|
|
36
39
|
|
|
37
40
|
def answer_proposal
|
|
38
41
|
Decidim.traceability.perform_action!(
|
|
@@ -40,55 +43,30 @@ module Decidim
|
|
|
40
43
|
proposal,
|
|
41
44
|
form.current_user
|
|
42
45
|
) do
|
|
43
|
-
|
|
44
|
-
state:
|
|
45
|
-
answer:
|
|
46
|
-
answered_at: Time.current
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
attributes = {
|
|
47
|
+
state: form.state,
|
|
48
|
+
answer: form.answer,
|
|
49
|
+
answered_at: Time.current,
|
|
50
|
+
cost: form.cost,
|
|
51
|
+
cost_report: form.cost_report,
|
|
52
|
+
execution_period: form.execution_period
|
|
53
|
+
}
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
return if (proposal.previous_changes.keys & %w(state)).empty?
|
|
55
|
+
attributes[:state_published_at] = Time.current if !initial_has_state_published && form.publish_answer?
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
publish_event(
|
|
56
|
-
"decidim.events.proposals.proposal_accepted",
|
|
57
|
-
Decidim::Proposals::AcceptedProposalEvent
|
|
58
|
-
)
|
|
59
|
-
elsif proposal.rejected?
|
|
60
|
-
publish_event(
|
|
61
|
-
"decidim.events.proposals.proposal_rejected",
|
|
62
|
-
Decidim::Proposals::RejectedProposalEvent
|
|
63
|
-
)
|
|
64
|
-
elsif proposal.evaluating?
|
|
65
|
-
publish_event(
|
|
66
|
-
"decidim.events.proposals.proposal_evaluating",
|
|
67
|
-
Decidim::Proposals::EvaluatingProposalEvent
|
|
68
|
-
)
|
|
57
|
+
proposal.update!(attributes)
|
|
69
58
|
end
|
|
70
59
|
end
|
|
71
60
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
event: event,
|
|
75
|
-
event_class: event_class,
|
|
76
|
-
resource: proposal,
|
|
77
|
-
affected_users: proposal.notifiable_identities,
|
|
78
|
-
followers: proposal.followers - proposal.notifiable_identities
|
|
79
|
-
)
|
|
80
|
-
end
|
|
61
|
+
def notify_proposal_answer
|
|
62
|
+
return if !initial_has_state_published && !form.publish_answer?
|
|
81
63
|
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
NotifyProposalAnswer.call(proposal, initial_state)
|
|
65
|
+
end
|
|
84
66
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
else
|
|
89
|
-
Decidim::Gamification.increment_score(coauthorship.author, :accepted_proposals)
|
|
90
|
-
end
|
|
91
|
-
end
|
|
67
|
+
def store_initial_proposal_state
|
|
68
|
+
@initial_has_state_published = proposal.published_state?
|
|
69
|
+
@initial_state = proposal.state
|
|
92
70
|
end
|
|
93
71
|
end
|
|
94
72
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
module Admin
|
|
6
|
+
# A command with all the business logic to assign proposals to a given
|
|
7
|
+
# valuator.
|
|
8
|
+
class AssignProposalsToValuator < Rectify::Command
|
|
9
|
+
# Public: Initializes the command.
|
|
10
|
+
#
|
|
11
|
+
# form - A form object with the params.
|
|
12
|
+
def initialize(form)
|
|
13
|
+
@form = form
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Executes the command. Broadcasts these events:
|
|
17
|
+
#
|
|
18
|
+
# - :ok when everything is valid.
|
|
19
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
|
20
|
+
#
|
|
21
|
+
# Returns nothing.
|
|
22
|
+
def call
|
|
23
|
+
return broadcast(:invalid) unless form.valid?
|
|
24
|
+
|
|
25
|
+
assign_proposals
|
|
26
|
+
broadcast(:ok)
|
|
27
|
+
rescue ActiveRecord::RecordInvalid
|
|
28
|
+
broadcast(:invalid)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
attr_reader :form
|
|
34
|
+
|
|
35
|
+
def assign_proposals
|
|
36
|
+
transaction do
|
|
37
|
+
form.proposals.flat_map do |proposal|
|
|
38
|
+
find_assignment(proposal) || assign_proposal(proposal)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def find_assignment(proposal)
|
|
44
|
+
Decidim::Proposals::ValuationAssignment.find_by(
|
|
45
|
+
proposal: proposal,
|
|
46
|
+
valuator_role: form.valuator_role
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def assign_proposal(proposal)
|
|
51
|
+
Decidim.traceability.create!(
|
|
52
|
+
Decidim::Proposals::ValuationAssignment,
|
|
53
|
+
form.current_user,
|
|
54
|
+
proposal: proposal,
|
|
55
|
+
valuator_role: form.valuator_role
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -39,6 +39,7 @@ module Decidim
|
|
|
39
39
|
create_proposal
|
|
40
40
|
create_attachment if process_attachments?
|
|
41
41
|
create_gallery if process_gallery?
|
|
42
|
+
link_author_meeeting if form.created_in_meeting?
|
|
42
43
|
send_notification
|
|
43
44
|
end
|
|
44
45
|
|
|
@@ -73,6 +74,10 @@ module Decidim
|
|
|
73
74
|
}
|
|
74
75
|
end
|
|
75
76
|
|
|
77
|
+
def link_author_meeeting
|
|
78
|
+
proposal.link_resources(form.author, "proposals_from_meeting")
|
|
79
|
+
end
|
|
80
|
+
|
|
76
81
|
def send_notification
|
|
77
82
|
Decidim::EventsManager.publish(
|
|
78
83
|
event: "decidim.events.proposals.proposal_published",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Decidim
|
|
4
|
+
module Proposals
|
|
5
|
+
module Admin
|
|
6
|
+
# A command to notify about the change of the published state for a proposal.
|
|
7
|
+
class NotifyProposalAnswer < Rectify::Command
|
|
8
|
+
# Public: Initializes the command.
|
|
9
|
+
#
|
|
10
|
+
# proposal - The proposal to write the answer for.
|
|
11
|
+
# initial_state - The proposal state before the current process.
|
|
12
|
+
def initialize(proposal, initial_state)
|
|
13
|
+
@proposal = proposal
|
|
14
|
+
@initial_state = initial_state.to_s
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Executes the command. Broadcasts these events:
|
|
18
|
+
#
|
|
19
|
+
# - :noop when the answer is not published or the state didn't changed.
|
|
20
|
+
# - :ok when everything is valid.
|
|
21
|
+
#
|
|
22
|
+
# Returns nothing.
|
|
23
|
+
def call
|
|
24
|
+
if proposal.published_state? && state_changed?
|
|
25
|
+
transaction do
|
|
26
|
+
increment_score
|
|
27
|
+
notify_followers
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
broadcast(:ok)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
attr_reader :proposal, :initial_state
|
|
37
|
+
|
|
38
|
+
def state_changed?
|
|
39
|
+
initial_state != proposal.state.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def notify_followers
|
|
43
|
+
if proposal.accepted?
|
|
44
|
+
publish_event(
|
|
45
|
+
"decidim.events.proposals.proposal_accepted",
|
|
46
|
+
Decidim::Proposals::AcceptedProposalEvent
|
|
47
|
+
)
|
|
48
|
+
elsif proposal.rejected?
|
|
49
|
+
publish_event(
|
|
50
|
+
"decidim.events.proposals.proposal_rejected",
|
|
51
|
+
Decidim::Proposals::RejectedProposalEvent
|
|
52
|
+
)
|
|
53
|
+
elsif proposal.evaluating?
|
|
54
|
+
publish_event(
|
|
55
|
+
"decidim.events.proposals.proposal_evaluating",
|
|
56
|
+
Decidim::Proposals::EvaluatingProposalEvent
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def publish_event(event, event_class)
|
|
62
|
+
Decidim::EventsManager.publish(
|
|
63
|
+
event: event,
|
|
64
|
+
event_class: event_class,
|
|
65
|
+
resource: proposal,
|
|
66
|
+
affected_users: proposal.notifiable_identities,
|
|
67
|
+
followers: proposal.followers - proposal.notifiable_identities
|
|
68
|
+
)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def increment_score
|
|
72
|
+
if proposal.accepted?
|
|
73
|
+
proposal.coauthorships.find_each do |coauthorship|
|
|
74
|
+
Decidim::Gamification.increment_score(coauthorship.user_group || coauthorship.author, :accepted_proposals)
|
|
75
|
+
end
|
|
76
|
+
elsif initial_state == "accepted"
|
|
77
|
+
proposal.coauthorships.find_each do |coauthorship|
|
|
78
|
+
Decidim::Gamification.decrement_score(coauthorship.user_group || coauthorship.author, :accepted_proposals)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|