decidim-budgets 0.13.1 → 0.14.1
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/cells/decidim/budgets/project_cell.rb +1 -1
- data/app/commands/decidim/budgets/admin/import_proposals_to_budgets.rb +76 -0
- data/app/controllers/decidim/budgets/admin/attachment_collections_controller.rb +0 -4
- data/app/controllers/decidim/budgets/admin/attachments_controller.rb +0 -4
- data/app/controllers/decidim/budgets/admin/proposals_imports_controller.rb +32 -0
- data/app/controllers/decidim/budgets/line_items_controller.rb +1 -1
- data/app/controllers/decidim/budgets/orders_controller.rb +1 -1
- data/app/forms/decidim/budgets/admin/project_form.rb +4 -1
- data/app/forms/decidim/budgets/admin/project_import_proposals_form.rb +35 -0
- data/app/models/decidim/budgets/project.rb +5 -0
- data/app/permissions/decidim/budgets/admin/permissions.rb +3 -1
- data/app/permissions/decidim/budgets/permissions.rb +18 -0
- data/app/views/decidim/budgets/admin/projects/index.html.erb +4 -1
- data/app/views/decidim/budgets/admin/proposals_imports/new.html.erb +27 -0
- data/app/views/decidim/budgets/line_items/update_budget.js.erb +6 -6
- data/app/views/decidim/budgets/projects/_project.html.erb +1 -1
- data/app/views/decidim/budgets/projects/show.html.erb +10 -1
- data/config/locales/ca.yml +10 -0
- data/config/locales/en.yml +10 -0
- data/config/locales/es-PY.yml +10 -0
- data/config/locales/es.yml +10 -0
- data/config/locales/eu.yml +10 -0
- data/config/locales/fi.yml +43 -33
- data/config/locales/fr.yml +10 -0
- data/config/locales/gl.yml +10 -0
- data/config/locales/hu.yml +153 -0
- data/config/locales/it.yml +10 -0
- data/config/locales/nl.yml +10 -0
- data/config/locales/pl.yml +10 -0
- data/config/locales/pt-BR.yml +15 -5
- data/config/locales/pt.yml +10 -0
- data/config/locales/ru.yml +13 -3
- data/config/locales/sv.yml +35 -25
- data/config/locales/uk.yml +54 -44
- data/lib/decidim/budgets/admin_engine.rb +4 -0
- data/lib/decidim/budgets/component.rb +2 -0
- data/lib/decidim/budgets/test/factories.rb +3 -3
- data/lib/decidim/budgets/version.rb +1 -1
- metadata +18 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c4245371508038885cb48f6ed330288461ea8554a24678fc0a250a928cbff4a
|
4
|
+
data.tar.gz: 00d30ac4b1662d12100a97767a53594f7412a15e71ce55d3827f841358c2665b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c3847ceb6895e9720c993cd147db952e1147b22c6293be831bb486680161edefc188602e4f774d74819b78fae0ab9207c7d67867874bc9d363e1c17c40b8c44
|
7
|
+
data.tar.gz: 4b71590a413f024134ceb00827291c1f51acaad882537e249d0e4adeef85e9f856ff2b5bee0563af2234caf1ce9def5f6c5ff87ba11fca1298d36aad68dd15a0
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when an admin imports proposals from
|
7
|
+
# one component to budget component.
|
8
|
+
class ImportProposalsToBudgets < 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
|
+
broadcast(:ok, create_projects_from_accepted_proposals)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :form
|
31
|
+
|
32
|
+
def create_projects_from_accepted_proposals
|
33
|
+
transaction do
|
34
|
+
proposals.map do |original_proposal|
|
35
|
+
next if proposal_already_copied?(original_proposal, target_component)
|
36
|
+
|
37
|
+
project = Decidim::Budgets::Project.new
|
38
|
+
project.title = project_localized(original_proposal.title)
|
39
|
+
project.description = project_localized(original_proposal.body)
|
40
|
+
project.budget = form.default_budget
|
41
|
+
project.category = original_proposal.category
|
42
|
+
project.component = target_component
|
43
|
+
project.save!
|
44
|
+
|
45
|
+
project.link_resources([original_proposal], "included_proposals")
|
46
|
+
end.compact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def proposals
|
51
|
+
Decidim::Proposals::Proposal.where(component: origin_component).where(state: "accepted")
|
52
|
+
end
|
53
|
+
|
54
|
+
def origin_component
|
55
|
+
@form.origin_component
|
56
|
+
end
|
57
|
+
|
58
|
+
def target_component
|
59
|
+
@form.current_component
|
60
|
+
end
|
61
|
+
|
62
|
+
def proposal_already_copied?(original_proposal, target_component)
|
63
|
+
original_proposal.linked_resources(:projects, "included_proposals").any? do |proposal|
|
64
|
+
proposal.component == target_component
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def project_localized(text)
|
69
|
+
Decidim.available_locales.inject({}) do |result, locale|
|
70
|
+
result.update(locale => text)
|
71
|
+
end.with_indifferent_access
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
module Admin
|
6
|
+
class ProposalsImportsController < Admin::ApplicationController
|
7
|
+
def new
|
8
|
+
enforce_permission_to :import_proposals, :projects
|
9
|
+
|
10
|
+
@form = form(Admin::ProjectImportProposalsForm).instance
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
enforce_permission_to :import_proposals, :projects
|
15
|
+
|
16
|
+
@form = form(Admin::ProjectImportProposalsForm).from_params(params)
|
17
|
+
Admin::ImportProposalsToBudgets.call(@form) do
|
18
|
+
on(:ok) do |projects|
|
19
|
+
flash[:notice] = I18n.t("proposals_imports.create.success", scope: "decidim.budgets.admin", number: projects.length)
|
20
|
+
redirect_to EngineRouter.admin_proxy(current_component).root_path
|
21
|
+
end
|
22
|
+
|
23
|
+
on(:invalid) do
|
24
|
+
flash[:alert] = I18n.t("proposals_imports.create.invalid", scope: "decidim.budgets.admin")
|
25
|
+
render action: "new"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -7,6 +7,7 @@ module Decidim
|
|
7
7
|
class ProjectForm < Decidim::Form
|
8
8
|
include TranslatableAttributes
|
9
9
|
include TranslationsHelper
|
10
|
+
include Decidim::ApplicationHelper
|
10
11
|
|
11
12
|
translatable_attribute :title, String
|
12
13
|
translatable_attribute :description, String
|
@@ -36,7 +37,9 @@ module Decidim
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def proposals
|
39
|
-
@proposals ||= Decidim.find_resource_manifest(:proposals).try(:resource_scope, current_component)
|
40
|
+
@proposals ||= Decidim.find_resource_manifest(:proposals).try(:resource_scope, current_component)
|
41
|
+
&.order(title: :asc)
|
42
|
+
&.map { |proposal| [present(proposal).title, proposal.id] }
|
40
43
|
end
|
41
44
|
|
42
45
|
# Finds the Category from the decidim_category_id.
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Budgets
|
5
|
+
module Admin
|
6
|
+
# A form object to be used when admin users want to import a collection of proposals
|
7
|
+
# from another component into projects component.
|
8
|
+
class ProjectImportProposalsForm < Decidim::Form
|
9
|
+
mimic :proposals_import
|
10
|
+
|
11
|
+
attribute :origin_component_id, Integer
|
12
|
+
attribute :default_budget, Integer
|
13
|
+
attribute :import_all_accepted_proposals, Boolean
|
14
|
+
|
15
|
+
validates :origin_component_id, :origin_component, :current_component, presence: true
|
16
|
+
validates :import_all_accepted_proposals, allow_nil: false, acceptance: true
|
17
|
+
validates :default_budget, presence: true, numericality: { greater_than: 0 }
|
18
|
+
|
19
|
+
def origin_component
|
20
|
+
@origin_component ||= origin_components.find_by(id: origin_component_id)
|
21
|
+
end
|
22
|
+
|
23
|
+
def origin_components
|
24
|
+
@origin_components ||= current_participatory_space.components.where(manifest_name: :proposals)
|
25
|
+
end
|
26
|
+
|
27
|
+
def origin_components_collection
|
28
|
+
origin_components.map do |component|
|
29
|
+
[component.name[I18n.locale.to_s], component.id]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -49,6 +49,11 @@ module Decidim
|
|
49
49
|
def confirmed_orders_count
|
50
50
|
orders.finished.count
|
51
51
|
end
|
52
|
+
|
53
|
+
# Public: Overrides the `allow_resource_permissions?` Resourceable concern method.
|
54
|
+
def allow_resource_permissions?
|
55
|
+
component.settings.resources_permissions_enabled
|
56
|
+
end
|
52
57
|
end
|
53
58
|
end
|
54
59
|
end
|
@@ -8,11 +8,13 @@ module Decidim
|
|
8
8
|
# The public part needs to be implemented yet
|
9
9
|
return permission_action if permission_action.scope != :admin
|
10
10
|
|
11
|
-
return permission_action
|
11
|
+
return permission_action unless [:project, :projects].include?(permission_action.subject)
|
12
12
|
|
13
13
|
case permission_action.action
|
14
14
|
when :create
|
15
15
|
permission_action.allow!
|
16
|
+
when :import_proposals
|
17
|
+
permission_action.allow!
|
16
18
|
when :update, :destroy
|
17
19
|
permission_action.allow! if project.present?
|
18
20
|
end
|
@@ -13,12 +13,30 @@ module Decidim
|
|
13
13
|
return permission_action if permission_action.subject != :project
|
14
14
|
|
15
15
|
case permission_action.action
|
16
|
+
when :vote
|
17
|
+
can_vote_project?(project || order&.projects&.first)
|
16
18
|
when :report
|
17
19
|
permission_action.allow!
|
18
20
|
end
|
19
21
|
|
20
22
|
permission_action
|
21
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def project
|
28
|
+
@project ||= context.fetch(:project, nil)
|
29
|
+
end
|
30
|
+
|
31
|
+
def order
|
32
|
+
@order ||= context.fetch(:order, nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
def can_vote_project?(a_project)
|
36
|
+
is_allowed = a_project && authorized?(:vote, resource: project)
|
37
|
+
|
38
|
+
toggle_allow(is_allowed)
|
39
|
+
end
|
22
40
|
end
|
23
41
|
end
|
24
42
|
end
|
@@ -2,7 +2,8 @@
|
|
2
2
|
<div class="card-divider">
|
3
3
|
<h2 class="card-title">
|
4
4
|
<%= t(".title") %>
|
5
|
-
<%= link_to t("actions.new", scope: "decidim.budgets"), new_project_path, class: "button tiny button--title" if allowed_to? :create, :project %>
|
5
|
+
<%= link_to t("actions.new", scope: "decidim.budgets"), new_project_path, class: "button tiny button--title new" if allowed_to? :create, :project %>
|
6
|
+
<%= link_to t("actions.import", scope: "decidim.budgets", name: t("models.project.name", scope: "decidim.budgets.admin")), new_proposals_import_path, class: "button tiny button--title" if allowed_to? :import_proposals, :project %>
|
6
7
|
</h2>
|
7
8
|
</div>
|
8
9
|
|
@@ -40,6 +41,8 @@
|
|
40
41
|
<%= icon_link_to "paperclip", project_attachments_path(project), t("actions.attachments", scope: "decidim.budgets"), class: "action-icon--attachments" %>
|
41
42
|
<% end %>
|
42
43
|
|
44
|
+
<%= resource_permissions_link(project) %>
|
45
|
+
|
43
46
|
<% if allowed_to? :destroy, :project, project: project %>
|
44
47
|
<%= icon_link_to "circle-x", project_path(project), t("actions.destroy", scope: "decidim.budgets"), method: :delete, class: "action-icon--remove", data: { confirm: t("actions.confirm_destroy", scope: "decidim.budgets") } %>
|
45
48
|
<% end %>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= decidim_form_for(@form, url: proposals_import_path, html: { class: "form import_proposals" }) do |f| %>
|
2
|
+
<% if @form.origin_components.any? %>
|
3
|
+
<div class="card">
|
4
|
+
<div class="card-divider">
|
5
|
+
<h2 class="card-title"><%= title %></h2>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="card-section">
|
9
|
+
<div class="row column">
|
10
|
+
<%= f.select :origin_component_id, @form.origin_components_collection, prompt: t(".select_component") %>
|
11
|
+
</div>
|
12
|
+
<div class="row column">
|
13
|
+
<%= f.number_field :default_budget %>
|
14
|
+
</div>
|
15
|
+
<div class="row column">
|
16
|
+
<%= f.check_box :import_all_accepted_proposals %>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="button--double form-general-submit">
|
22
|
+
<%= f.submit t(".create") %>
|
23
|
+
</div>
|
24
|
+
<% else %>
|
25
|
+
<p><%= t(".no_components") %></p>
|
26
|
+
<% end %>
|
27
|
+
<% end %>
|
@@ -5,20 +5,20 @@ var $projectItem = $('#project-<%= project.id %>-item');
|
|
5
5
|
var $projectBudgetButton = $('#project-<%= project.id %>-budget-button');
|
6
6
|
var $budgetConfirm = $('#budget-confirm');
|
7
7
|
|
8
|
-
morphdom($orderTotalBudget[0], '<%= j(render partial:
|
9
|
-
morphdom($orderSelectedProjects[0], '<%= j(render partial:
|
10
|
-
morphdom($orderProgress[0], '<%= j(render partial:
|
11
|
-
morphdom($budgetConfirm[0], '<%= j(render partial:
|
8
|
+
morphdom($orderTotalBudget[0], '<%= j(render partial: "decidim/budgets/projects/order_total_budget").strip.html_safe %>');
|
9
|
+
morphdom($orderSelectedProjects[0], '<%= j(render partial: "decidim/budgets/projects/order_selected_projects").strip.html_safe %>');
|
10
|
+
morphdom($orderProgress[0], '<%= j(render partial: "decidim/budgets/projects/order_progress").strip.html_safe %>');
|
11
|
+
morphdom($budgetConfirm[0], '<%= j(render partial: "decidim/budgets/projects/budget_confirm").strip.html_safe %>')
|
12
12
|
|
13
13
|
$("#order-progress").foundation();
|
14
14
|
$(".budget-summary__selected").foundation();
|
15
15
|
|
16
16
|
if ($projectItem.length > 0) {
|
17
|
-
morphdom($projectItem[0], '<%= j(render partial:
|
17
|
+
morphdom($projectItem[0], '<%= j(render partial: "decidim/budgets/projects/project", locals: { project: project }).strip.html_safe %>');
|
18
18
|
}
|
19
19
|
|
20
20
|
if ($projectBudgetButton.length > 0) {
|
21
|
-
morphdom($projectBudgetButton[0], '<%= j(render partial:
|
21
|
+
morphdom($projectBudgetButton[0], '<%= j(render partial: "decidim/budgets/projects/project_budget_button", locals: { project: project }).strip.html_safe %>');
|
22
22
|
}
|
23
23
|
|
24
24
|
window.DecidimBudgets.checkProgressPosition();
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<%= translated_attribute project.title %>
|
7
7
|
</h5>
|
8
8
|
<% end %>
|
9
|
-
<%= cell "decidim/tags", project, context: {extra_classes: ["tags--project"]} %>
|
9
|
+
<%= cell "decidim/tags", project, context: { extra_classes: ["tags--project"] } %>
|
10
10
|
</div>
|
11
11
|
</div>
|
12
12
|
<% if current_user.present? %>
|
@@ -3,6 +3,15 @@
|
|
3
3
|
description: translated_attribute(project.description)
|
4
4
|
) %>
|
5
5
|
|
6
|
+
<%
|
7
|
+
edit_link(
|
8
|
+
resource_locator(project).edit,
|
9
|
+
:update,
|
10
|
+
:project,
|
11
|
+
project: project
|
12
|
+
)
|
13
|
+
%>
|
14
|
+
|
6
15
|
<div class="row column view-header">
|
7
16
|
<% if current_user.present? && current_settings.votes_enabled? && current_participatory_space.can_participate?(current_user) %>
|
8
17
|
<%= render partial: "budget_summary", locals: { include_heading: false } %>
|
@@ -38,7 +47,7 @@
|
|
38
47
|
<div class="columns mediumlarge-8 mediumlarge-pull-4">
|
39
48
|
<div class="section">
|
40
49
|
<%= decidim_sanitize translated_attribute project.description %>
|
41
|
-
<%= cell "decidim/tags", project, context: {extra_classes: ["tags--project"]} %>
|
50
|
+
<%= cell "decidim/tags", project, context: { extra_classes: ["tags--project"] } %>
|
42
51
|
</div>
|
43
52
|
<%= linked_resources_for project, :proposals, "included_proposals" %>
|
44
53
|
<%= linked_resources_for project, :results, "included_projects" %>
|
data/config/locales/ca.yml
CHANGED
@@ -21,6 +21,7 @@ ca:
|
|
21
21
|
confirm_destroy: Segur que vols eliminar aquest projecte?
|
22
22
|
destroy: Esborrar
|
23
23
|
edit: Editar
|
24
|
+
import: Importa propostes a projectes
|
24
25
|
new: Nou projecte
|
25
26
|
preview: Previsualitzar
|
26
27
|
title: Accions
|
@@ -47,6 +48,14 @@ ca:
|
|
47
48
|
update:
|
48
49
|
invalid: Hi ha hagut un problema actualitzant aquest projecte
|
49
50
|
success: Projecte actualitzat correctament
|
51
|
+
proposals_imports:
|
52
|
+
create:
|
53
|
+
invalid: Hi ha hagut un problema en importar les propostes en projectes
|
54
|
+
success: "S'ha importat amb èxit %{number} propostes en projectes"
|
55
|
+
new:
|
56
|
+
create: Importa propostes a projectes
|
57
|
+
no_components: No hi ha cap component de propostes en aquest espai participatiu per importar les propostes a projectes.
|
58
|
+
select_component: Selecciona un component
|
50
59
|
admin_log:
|
51
60
|
project:
|
52
61
|
create: "%{user_name} ha creat el projecte %{resource_name} a l'espai %{space_name}"
|
@@ -121,6 +130,7 @@ ca:
|
|
121
130
|
announcement: Anunci
|
122
131
|
comments_enabled: Comentaris habilitats
|
123
132
|
projects_per_page: Projectes per pàgina
|
133
|
+
resources_permissions_enabled: Es poden establir permisos d'accions per a cada trobada
|
124
134
|
total_budget: Pressupost total
|
125
135
|
vote_threshold_percent: Percentatge del pressupost mínim per fer el vot
|
126
136
|
step:
|
data/config/locales/en.yml
CHANGED
@@ -22,6 +22,7 @@ en:
|
|
22
22
|
confirm_destroy: Are you sure you want to delete this project?
|
23
23
|
destroy: Delete
|
24
24
|
edit: Edit
|
25
|
+
import: Import proposals to projects
|
25
26
|
new: New project
|
26
27
|
preview: Preview
|
27
28
|
title: Actions
|
@@ -48,6 +49,14 @@ en:
|
|
48
49
|
update:
|
49
50
|
invalid: There's been a problem updating this project
|
50
51
|
success: Project successfully updated
|
52
|
+
proposals_imports:
|
53
|
+
create:
|
54
|
+
invalid: There's been a problem importing the proposals into projects
|
55
|
+
success: "%{number} proposals successfully imported into projects"
|
56
|
+
new:
|
57
|
+
create: Import proposals to projects
|
58
|
+
no_components: There are no other proposal components in this participatory space to import the proposals into projects.
|
59
|
+
select_component: Please select a component
|
51
60
|
admin_log:
|
52
61
|
project:
|
53
62
|
create: "%{user_name} created the %{resource_name} project in the %{space_name} space"
|
@@ -122,6 +131,7 @@ en:
|
|
122
131
|
announcement: Announcement
|
123
132
|
comments_enabled: Comments enabled
|
124
133
|
projects_per_page: Projects per page
|
134
|
+
resources_permissions_enabled: Actions permissions can be set for each meeting
|
125
135
|
total_budget: Total budget
|
126
136
|
vote_threshold_percent: Vote threshold percent
|
127
137
|
step:
|