decidim-accountability 0.27.9 → 0.28.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/cells/decidim/accountability/content_blocks/highlighted_results_cell.rb +3 -8
- data/app/cells/decidim/accountability/highlighted_results/show.erb +3 -1
- data/app/cells/decidim/accountability/highlighted_results_for_component/show.erb +19 -19
- data/app/cells/decidim/accountability/highlighted_results_for_component_cell.rb +29 -6
- data/app/cells/decidim/accountability/project/show.erb +11 -0
- data/app/cells/decidim/accountability/project/timeline.erb +22 -0
- data/app/cells/decidim/accountability/project_cell.rb +75 -0
- data/app/cells/decidim/accountability/result_activity_cell.rb +1 -4
- data/app/cells/decidim/accountability/result_card_cell.rb +21 -0
- data/app/cells/decidim/accountability/result_cell.rb +2 -2
- data/app/cells/decidim/accountability/result_l/extra_data.erb +3 -0
- data/app/cells/decidim/accountability/result_l_cell.rb +30 -0
- data/app/cells/decidim/accountability/result_metadata/project_aside.erb +6 -0
- data/app/cells/decidim/accountability/result_metadata/show_footer.erb +11 -0
- data/app/cells/decidim/accountability/result_metadata/versions.erb +1 -0
- data/app/cells/decidim/accountability/result_metadata_cell.rb +136 -0
- data/app/cells/decidim/accountability/results/show.erb +7 -0
- data/app/cells/decidim/accountability/results_cell.rb +14 -0
- data/app/cells/decidim/accountability/status/show.erb +9 -0
- data/app/cells/decidim/accountability/status/status.erb +16 -0
- data/app/cells/decidim/accountability/status_cell.rb +91 -0
- data/app/commands/decidim/accountability/admin/import_projects_to_accountability.rb +37 -0
- data/app/controllers/concerns/decidim/accountability/admin/filterable.rb +2 -2
- data/app/controllers/decidim/accountability/admin/import_results_controller.rb +18 -6
- data/app/controllers/decidim/accountability/admin/projects_import_controller.rb +31 -0
- data/app/controllers/decidim/accountability/admin/results_controller.rb +4 -5
- data/app/controllers/decidim/accountability/admin/statuses_controller.rb +3 -3
- data/app/controllers/decidim/accountability/admin/timeline_entries_controller.rb +3 -3
- data/app/controllers/decidim/accountability/results_controller.rb +20 -2
- data/app/events/decidim/accountability/proposal_linked_event.rb +18 -1
- data/app/events/decidim/accountability/result_progress_updated_event.rb +18 -2
- data/app/forms/decidim/accountability/admin/import_results_form.rb +22 -0
- data/app/forms/decidim/accountability/admin/result_import_projects_form.rb +51 -0
- data/app/helpers/decidim/accountability/admin/application_helper.rb +1 -0
- data/app/helpers/decidim/accountability/application_helper.rb +43 -2
- data/app/helpers/decidim/accountability/breadcrumb_helper.rb +10 -0
- data/app/jobs/decidim/accountability/admin/import_projects_job.rb +72 -0
- data/app/mailers/decidim/accountability/import_projects_mailer.rb +25 -0
- data/app/models/decidim/accountability/result.rb +1 -1
- data/app/packs/entrypoints/decidim_accountability.js +4 -1
- data/app/packs/entrypoints/decidim_accountability_admin_imports.js +3 -0
- data/app/packs/images/decidim/accountability/breadcrumb_arrow.svg +3 -0
- data/app/packs/src/decidim/accountability/admin/imports.js +15 -0
- data/app/packs/stylesheets/accountability.scss +169 -0
- data/app/permissions/decidim/accountability/admin/permissions.rb +17 -6
- data/app/presenters/decidim/accountability/admin_log/result_presenter.rb +2 -2
- data/app/presenters/decidim/accountability/admin_log/status_presenter.rb +2 -2
- data/app/presenters/decidim/accountability/admin_log/timeline_entry_presenter.rb +2 -2
- data/app/queries/decidim/accountability/metrics/results_metric_manage.rb +1 -1
- data/app/services/decidim/accountability/results_calculator.rb +1 -1
- data/app/services/decidim/accountability/results_csv_importer.rb +2 -2
- data/app/views/decidim/accountability/admin/import_results/new.html.erb +27 -23
- data/app/views/decidim/accountability/admin/projects_import/new.html.erb +45 -0
- data/app/views/decidim/accountability/admin/results/_form.html.erb +46 -46
- data/app/views/decidim/accountability/admin/results/edit.html.erb +18 -7
- data/app/views/decidim/accountability/admin/results/index.html.erb +102 -91
- data/app/views/decidim/accountability/admin/results/new.html.erb +18 -8
- data/app/views/decidim/accountability/admin/shared/_subnav.html.erb +1 -1
- data/app/views/decidim/accountability/admin/statuses/_form.html.erb +15 -17
- data/app/views/decidim/accountability/admin/statuses/edit.html.erb +16 -6
- data/app/views/decidim/accountability/admin/statuses/index.html.erb +33 -36
- data/app/views/decidim/accountability/admin/statuses/new.html.erb +16 -6
- data/app/views/decidim/accountability/admin/timeline_entries/_form.html.erb +12 -14
- data/app/views/decidim/accountability/admin/timeline_entries/edit.html.erb +17 -6
- data/app/views/decidim/accountability/admin/timeline_entries/index.html.erb +35 -34
- data/app/views/decidim/accountability/admin/timeline_entries/new.html.erb +17 -6
- data/app/views/decidim/accountability/import_projects_mailer/import.html.erb +2 -0
- data/app/views/decidim/accountability/results/_home_categories.html.erb +28 -73
- data/app/views/decidim/accountability/results/_linked_results.html.erb +3 -12
- data/app/views/decidim/accountability/results/_project.html.erb +29 -0
- data/app/views/decidim/accountability/results/_projects_aside.html.erb +40 -0
- data/app/views/decidim/accountability/results/_scope_filters.html.erb +27 -27
- data/app/views/decidim/accountability/results/_search.html.erb +15 -9
- data/app/views/decidim/accountability/results/_stats_box.html.erb +3 -3
- data/app/views/decidim/accountability/results/home.html.erb +34 -8
- data/app/views/decidim/accountability/results/index.html.erb +15 -15
- data/app/views/decidim/accountability/results/index.js.erb +3 -0
- data/app/views/decidim/accountability/results/show.html.erb +9 -10
- data/app/views/decidim/accountability/versions/show.html.erb +13 -10
- data/app/views/decidim/participatory_spaces/_result.html.erb +4 -4
- data/config/assets.rb +2 -2
- data/config/locales/ar.yml +23 -61
- data/config/locales/bg.yml +0 -96
- data/config/locales/ca.yml +54 -31
- data/config/locales/cs.yml +58 -29
- data/config/locales/da.yml +1 -36
- data/config/locales/de.yml +59 -36
- data/config/locales/el.yml +62 -29
- data/config/locales/en.yml +55 -31
- data/config/locales/es-MX.yml +52 -29
- data/config/locales/es-PY.yml +52 -29
- data/config/locales/es.yml +55 -32
- data/config/locales/eu.yml +53 -30
- data/config/locales/fi-plain.yml +51 -28
- data/config/locales/fi.yml +54 -31
- data/config/locales/fr-CA.yml +51 -28
- data/config/locales/fr.yml +52 -29
- data/config/locales/ga-IE.yml +0 -4
- data/config/locales/gl.yml +0 -41
- data/config/locales/hu.yml +41 -29
- data/config/locales/id-ID.yml +1 -30
- data/config/locales/is-IS.yml +0 -32
- data/config/locales/it.yml +0 -43
- data/config/locales/ja.yml +55 -39
- data/config/locales/kaa.yml +20 -1
- data/config/locales/ko.yml +0 -188
- data/config/locales/lb.yml +1 -42
- data/config/locales/lt.yml +60 -41
- data/config/locales/lv.yml +1 -36
- data/config/locales/nl.yml +0 -41
- data/config/locales/no.yml +8 -49
- data/config/locales/pl.yml +17 -61
- data/config/locales/pt-BR.yml +41 -29
- data/config/locales/pt.yml +0 -42
- data/config/locales/ro-RO.yml +39 -66
- data/config/locales/ru.yml +1 -30
- data/config/locales/si-LK.yml +0 -4
- data/config/locales/sk.yml +1 -40
- data/config/locales/sl.yml +0 -11
- data/config/locales/sq-AL.yml +82 -7
- data/config/locales/sr-CS.yml +1 -30
- data/config/locales/sv.yml +36 -51
- data/config/locales/th-TH.yml +0 -140
- data/config/locales/tr-TR.yml +9 -75
- data/config/locales/uk.yml +1 -28
- data/config/locales/zh-CN.yml +1 -36
- data/config/locales/zh-TW.yml +52 -43
- data/lib/decidim/accountability/admin_engine.rb +3 -2
- data/lib/decidim/accountability/component.rb +4 -99
- data/lib/decidim/accountability/engine.rb +9 -1
- data/lib/decidim/accountability/result_serializer.rb +1 -1
- data/lib/decidim/accountability/seeds.rb +115 -0
- data/lib/decidim/accountability/test/factories.rb +18 -29
- data/lib/decidim/accountability/version.rb +1 -1
- data/lib/decidim/api/result_type.rb +1 -0
- metadata +62 -51
- data/app/cells/decidim/accountability/content_blocks/highlighted_results/elements.erb +0 -5
- data/app/cells/decidim/accountability/content_blocks/highlighted_results/heading.erb +0 -1
- data/app/cells/decidim/accountability/result_m/data.erb +0 -23
- data/app/cells/decidim/accountability/result_m/footer.erb +0 -22
- data/app/cells/decidim/accountability/result_m/tags.erb +0 -1
- data/app/cells/decidim/accountability/result_m_cell.rb +0 -37
- data/app/events/decidim/accountability/base_result_event.rb +0 -29
- data/app/packs/stylesheets/decidim/accountability/_accountability.scss +0 -4
- data/app/packs/stylesheets/decidim/accountability/accountability/_cards.scss +0 -11
- data/app/packs/stylesheets/decidim/accountability/accountability/_categories.scss +0 -121
- data/app/packs/stylesheets/decidim/accountability/accountability/_lines_breadcrumb.scss +0 -37
- data/app/packs/stylesheets/decidim/accountability/accountability/_results.scss +0 -148
- data/app/views/decidim/accountability/admin/results/proposals_picker.html.erb +0 -1
- data/app/views/decidim/accountability/result_widgets/show.html.erb +0 -2
- data/app/views/decidim/accountability/results/_home_header.html.erb +0 -23
- data/app/views/decidim/accountability/results/_results_leaf.html.erb +0 -47
- data/app/views/decidim/accountability/results/_results_parent.html.erb +0 -32
- data/app/views/decidim/accountability/results/_show_leaf.html.erb +0 -81
- data/app/views/decidim/accountability/results/_show_parent.html.erb +0 -30
- data/app/views/decidim/accountability/results/_stats.html.erb +0 -15
- data/app/views/decidim/accountability/results/_timeline.html.erb +0 -30
- data/app/views/decidim/accountability/versions/index.html.erb +0 -12
- data/config/locales/he-IL.yml +0 -219
- data/decidim-accountability.gemspec +0 -38
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when an admin imports projects from
|
7
|
+
# one component to accountability.
|
8
|
+
class ImportProjectsToAccountability < Decidim::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
|
+
def call
|
17
|
+
return broadcast(:invalid) unless @form.valid?
|
18
|
+
|
19
|
+
ImportProjectsJob.perform_later(projects.pluck(:id), @form.current_component, @form.current_user)
|
20
|
+
broadcast(:ok, projects.count)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def projects
|
26
|
+
Decidim::Budgets::Project.joins(:budget).selected.where(
|
27
|
+
budget: { component: origin_component }
|
28
|
+
).reject { |item| @form.project_already_copied?(item) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def origin_component
|
32
|
+
@form.origin_component
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -39,7 +39,7 @@ module Decidim
|
|
39
39
|
}
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
42
|
+
# Cannot user `super` here, because it does not belong to a superclass
|
43
43
|
# but to a concern.
|
44
44
|
def dynamically_translated_filters
|
45
45
|
[:scope_id_eq, :category_id_eq, :status_id_eq]
|
@@ -50,7 +50,7 @@ module Decidim
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def translated_status_id_eq(id)
|
53
|
-
translated_attribute(statuses.find_by(id:
|
53
|
+
translated_attribute(statuses.find_by(id:).name)
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
@@ -5,18 +5,30 @@ module Decidim
|
|
5
5
|
module Admin
|
6
6
|
# This controller allows an admin to import results from a csv file for the Accountability component
|
7
7
|
class ImportResultsController < Admin::ApplicationController
|
8
|
+
before_action :ensure_permissions
|
9
|
+
|
8
10
|
def new
|
9
|
-
@
|
11
|
+
@form = form(Admin::ImportResultsForm).instance
|
10
12
|
end
|
11
13
|
|
12
14
|
def create
|
13
|
-
@
|
14
|
-
|
15
|
+
@form = form(Admin::ImportResultsForm).from_params(params, current_component:)
|
16
|
+
|
17
|
+
if @form.valid?
|
18
|
+
Decidim::Accountability::Admin::ImportResultsCsvJob.perform_later(current_user, current_component, @form.local_file_path)
|
19
|
+
|
20
|
+
flash[:notice] = I18n.t("imports.create.success", scope: "decidim.accountability.admin")
|
21
|
+
redirect_to import_results_path(current_participatory_space, current_component)
|
22
|
+
else
|
23
|
+
flash[:alert] = I18n.t("imports.create.invalid", scope: "decidim.accountability.admin")
|
24
|
+
render action: "new"
|
25
|
+
end
|
26
|
+
end
|
15
27
|
|
16
|
-
|
28
|
+
private
|
17
29
|
|
18
|
-
|
19
|
-
|
30
|
+
def ensure_permissions
|
31
|
+
enforce_permission_to :create, :result
|
20
32
|
end
|
21
33
|
end
|
22
34
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
module Admin
|
6
|
+
# This controller allows an admin to import results from a csv file for the Accountability component
|
7
|
+
class ProjectsImportController < Admin::ApplicationController
|
8
|
+
def new
|
9
|
+
enforce_permission_to :create, :import_projects
|
10
|
+
@form = form(Admin::ResultImportProjectsForm).instance
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
enforce_permission_to :create, :import_projects
|
15
|
+
@form = form(Admin::ResultImportProjectsForm).from_params(params, accountability_component: current_component)
|
16
|
+
Admin::ImportProjectsToAccountability.call(@form) do
|
17
|
+
on(:ok) do |projects|
|
18
|
+
flash[:notice] = I18n.t("projects_import.new.success", scope: "decidim.accountability.admin", count: projects)
|
19
|
+
redirect_to results_path
|
20
|
+
end
|
21
|
+
|
22
|
+
on(:invalid) do
|
23
|
+
flash[:alert] = I18n.t("projects_import.create.invalid", scope: "decidim.accountability.admin")
|
24
|
+
render action: "new"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -7,14 +7,13 @@ module Decidim
|
|
7
7
|
class ResultsController < Admin::ApplicationController
|
8
8
|
include Decidim::ApplicationHelper
|
9
9
|
include Decidim::SanitizeHelper
|
10
|
-
include Decidim::Proposals::Admin::Picker if Decidim::Accountability.enable_proposal_linking
|
11
10
|
include Decidim::Accountability::Admin::Filterable
|
12
11
|
|
13
12
|
helper_method :results, :parent_result, :parent_results, :statuses, :present
|
14
13
|
|
15
14
|
def collection
|
16
15
|
parent_id = params[:parent_id].presence
|
17
|
-
@collection ||= Result.where(component: current_component, parent_id:
|
16
|
+
@collection ||= Result.where(component: current_component, parent_id:).page(params[:page]).per(15)
|
18
17
|
end
|
19
18
|
|
20
19
|
def new
|
@@ -43,13 +42,13 @@ module Decidim
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def edit
|
46
|
-
enforce_permission_to
|
45
|
+
enforce_permission_to(:update, :result, result:)
|
47
46
|
|
48
47
|
@form = form(ResultForm).from_model(result)
|
49
48
|
end
|
50
49
|
|
51
50
|
def update
|
52
|
-
enforce_permission_to
|
51
|
+
enforce_permission_to(:update, :result, result:)
|
53
52
|
|
54
53
|
@form = form(ResultForm).from_params(params)
|
55
54
|
|
@@ -67,7 +66,7 @@ module Decidim
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def destroy
|
70
|
-
enforce_permission_to
|
69
|
+
enforce_permission_to(:destroy, :result, result:)
|
71
70
|
|
72
71
|
DestroyResult.call(result, current_user) do
|
73
72
|
on(:ok) do
|
@@ -32,13 +32,13 @@ module Decidim
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def edit
|
35
|
-
enforce_permission_to
|
35
|
+
enforce_permission_to(:update, :status, status:)
|
36
36
|
|
37
37
|
@form = form(StatusForm).from_model(status)
|
38
38
|
end
|
39
39
|
|
40
40
|
def update
|
41
|
-
enforce_permission_to
|
41
|
+
enforce_permission_to(:update, :status, status:)
|
42
42
|
|
43
43
|
@form = form(StatusForm).from_params(params)
|
44
44
|
|
@@ -56,7 +56,7 @@ module Decidim
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def destroy
|
59
|
-
enforce_permission_to
|
59
|
+
enforce_permission_to(:destroy, :status, status:)
|
60
60
|
|
61
61
|
Decidim.traceability.perform_action!("delete", status, current_user) do
|
62
62
|
status.destroy!
|
@@ -33,13 +33,13 @@ module Decidim
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def edit
|
36
|
-
enforce_permission_to
|
36
|
+
enforce_permission_to(:update, :timeline_entry, timeline_entry:)
|
37
37
|
|
38
38
|
@form = form(TimelineEntryForm).from_model(timeline_entry)
|
39
39
|
end
|
40
40
|
|
41
41
|
def update
|
42
|
-
enforce_permission_to
|
42
|
+
enforce_permission_to(:update, :timeline_entry, timeline_entry:)
|
43
43
|
|
44
44
|
@form = form(TimelineEntryForm).from_params(params)
|
45
45
|
|
@@ -57,7 +57,7 @@ module Decidim
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def destroy
|
60
|
-
enforce_permission_to
|
60
|
+
enforce_permission_to(:destroy, :timeline_entry, timeline_entry:)
|
61
61
|
|
62
62
|
Decidim.traceability.perform_action!("delete", timeline_entry, current_user) do
|
63
63
|
timeline_entry.destroy!
|
@@ -8,7 +8,7 @@ module Decidim
|
|
8
8
|
helper Decidim::TraceabilityHelper
|
9
9
|
helper Decidim::Accountability::BreadcrumbHelper
|
10
10
|
|
11
|
-
helper_method :results, :result, :first_class_categories, :count_calculator
|
11
|
+
helper_method :results, :result, :first_class_categories, :count_calculator, :nav_paths
|
12
12
|
|
13
13
|
def show
|
14
14
|
raise ActionController::RoutingError, "Not Found" unless result
|
@@ -20,7 +20,7 @@ module Decidim
|
|
20
20
|
@results ||= begin
|
21
21
|
parent_id = params[:parent_id].presence
|
22
22
|
search.result.where(
|
23
|
-
parent_id: [parent_id] + Result.where(parent_id:
|
23
|
+
parent_id: [parent_id] + Result.where(parent_id:).pluck(:id)
|
24
24
|
).page(params[:page]).per(12)
|
25
25
|
end
|
26
26
|
end
|
@@ -29,6 +29,24 @@ module Decidim
|
|
29
29
|
@result ||= search_collection.includes(:timeline_entries).find_by(id: params[:id])
|
30
30
|
end
|
31
31
|
|
32
|
+
def next_result
|
33
|
+
return if search_collection.size < 2
|
34
|
+
|
35
|
+
search_collection.order(:start_date, :id).where(Decidim::Accountability::Result.arel_table[:id].gt(result.id)).first
|
36
|
+
end
|
37
|
+
|
38
|
+
def prev_result
|
39
|
+
return if search_collection.size < 2
|
40
|
+
|
41
|
+
search_collection.order(:start_date, :id).where(Decidim::Accountability::Result.arel_table[:id].lt(result.id)).last
|
42
|
+
end
|
43
|
+
|
44
|
+
def nav_paths
|
45
|
+
return {} if result.blank?
|
46
|
+
|
47
|
+
{ prev_path: prev_result, next_path: next_result }.compact_blank.transform_values { |result| result_path(result) }
|
48
|
+
end
|
49
|
+
|
32
50
|
def search_collection
|
33
51
|
Result.where(component: current_component)
|
34
52
|
end
|
@@ -2,7 +2,24 @@
|
|
2
2
|
|
3
3
|
module Decidim
|
4
4
|
module Accountability
|
5
|
-
class ProposalLinkedEvent <
|
5
|
+
class ProposalLinkedEvent < Decidim::Events::SimpleEvent
|
6
|
+
i18n_attributes :proposal_title, :proposal_path
|
7
|
+
|
8
|
+
def proposal_path
|
9
|
+
@proposal_path ||= Decidim::ResourceLocatorPresenter.new(proposal).path
|
10
|
+
end
|
11
|
+
|
12
|
+
def proposal_title
|
13
|
+
@proposal_title ||= translated_attribute(proposal.title)
|
14
|
+
end
|
15
|
+
|
16
|
+
def proposal
|
17
|
+
@proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id])
|
18
|
+
end
|
19
|
+
|
20
|
+
def resource_text
|
21
|
+
translated_attribute(resource.description)
|
22
|
+
end
|
6
23
|
end
|
7
24
|
end
|
8
25
|
end
|
@@ -2,12 +2,28 @@
|
|
2
2
|
|
3
3
|
module Decidim
|
4
4
|
module Accountability
|
5
|
-
class ResultProgressUpdatedEvent <
|
6
|
-
i18n_attributes :progress
|
5
|
+
class ResultProgressUpdatedEvent < Decidim::Events::SimpleEvent
|
6
|
+
i18n_attributes :proposal_title, :proposal_path, :progress
|
7
|
+
|
8
|
+
def proposal_path
|
9
|
+
@proposal_path ||= Decidim::ResourceLocatorPresenter.new(proposal).path
|
10
|
+
end
|
11
|
+
|
12
|
+
def proposal_title
|
13
|
+
@proposal_title ||= translated_attribute(proposal.title)
|
14
|
+
end
|
15
|
+
|
16
|
+
def proposal
|
17
|
+
@proposal ||= resource.linked_resources(:proposals, "included_proposals").find_by(id: extra[:proposal_id])
|
18
|
+
end
|
7
19
|
|
8
20
|
def progress
|
9
21
|
extra[:progress]
|
10
22
|
end
|
23
|
+
|
24
|
+
def resource_text
|
25
|
+
translated_attribute(resource.description)
|
26
|
+
end
|
11
27
|
end
|
12
28
|
end
|
13
29
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
module Admin
|
6
|
+
class ImportResultsForm < Decidim::Form
|
7
|
+
include Decidim::HasUploadValidations
|
8
|
+
include Decidim::ProcessesFileLocally
|
9
|
+
|
10
|
+
attribute :file, Decidim::Attributes::Blob
|
11
|
+
|
12
|
+
validates :file, presence: true, file_content_type: { allow: ["text/csv"] }
|
13
|
+
|
14
|
+
def local_file_path
|
15
|
+
process_file_locally(file) do |file_path|
|
16
|
+
file_path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
module Admin
|
6
|
+
# A form object to be used when admin users want to import a collection of projects
|
7
|
+
# from another component into Accountability component.
|
8
|
+
class ResultImportProjectsForm < Decidim::Form
|
9
|
+
attribute :origin_component_id, Integer
|
10
|
+
attribute :import_all_selected_projects, Boolean
|
11
|
+
|
12
|
+
validates :origin_component_id, presence: true
|
13
|
+
validates :import_all_selected_projects, allow_nil: false, acceptance: true
|
14
|
+
validates :origin_projects_count, numericality: { greater_than: 0 }, if: ->(form) { form.origin_component_id }
|
15
|
+
|
16
|
+
def origin_component
|
17
|
+
@origin_component ||= origin_components.find_by(id: origin_component_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def origin_components_collection
|
21
|
+
origin_components.map do |component|
|
22
|
+
[component.name[I18n.locale.to_s], component.id]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def origin_components
|
27
|
+
@budgets_component ||= current_participatory_space.components.where(manifest_name: "budgets")
|
28
|
+
end
|
29
|
+
|
30
|
+
def selected_projects_count(component)
|
31
|
+
projects = Decidim::Budgets::Project.joins(:budget).selected.where(
|
32
|
+
budget: { component: }
|
33
|
+
)
|
34
|
+
projects.reject { |project| project_already_copied?(project) }.count
|
35
|
+
end
|
36
|
+
|
37
|
+
def project_already_copied?(original_project)
|
38
|
+
original_project.linked_resources(:results, "included_projects").any? do |result|
|
39
|
+
result.component == current_component
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def origin_projects_count
|
46
|
+
selected_projects_count(origin_component_id)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -22,6 +22,10 @@ module Decidim
|
|
22
22
|
"class=active" if scope.to_s == current_scope.to_s
|
23
23
|
end
|
24
24
|
|
25
|
+
def component_name
|
26
|
+
(defined?(current_component) && translated_attribute(current_component&.name).presence) || t("decidim.components.accountability.name")
|
27
|
+
end
|
28
|
+
|
25
29
|
def categories_label
|
26
30
|
translated_attribute(component_settings.categories_label).presence || t("results.home.categories_label", scope: "decidim.accountability")
|
27
31
|
end
|
@@ -35,7 +39,7 @@ module Decidim
|
|
35
39
|
if text
|
36
40
|
pluralize(count, text)
|
37
41
|
else
|
38
|
-
t("results.count.results_count", scope: "decidim.accountability", count:
|
42
|
+
t("results.count.results_count", scope: "decidim.accountability", count:)
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
@@ -44,9 +48,46 @@ module Decidim
|
|
44
48
|
if text
|
45
49
|
pluralize(count, text)
|
46
50
|
else
|
47
|
-
t("results.count.results_count", scope: "decidim.accountability", count:
|
51
|
+
t("results.count.results_count", scope: "decidim.accountability", count:)
|
48
52
|
end
|
49
53
|
end
|
54
|
+
|
55
|
+
def filter_items_for(participatory_space:, category:)
|
56
|
+
[
|
57
|
+
{
|
58
|
+
url: url_for(filter: { with_category: category.try(:id) }),
|
59
|
+
text: t("results.filters.all", scope: "decidim.accountability"),
|
60
|
+
icon: "apps-2-line",
|
61
|
+
active: current_scope.blank?,
|
62
|
+
sr_text: Decidim::Scope.model_name.human(count: 2)
|
63
|
+
},
|
64
|
+
*(
|
65
|
+
if participatory_space.scope
|
66
|
+
[{
|
67
|
+
url: url_for(filter: { with_scope: participatory_space.scope.id, with_category: category.try(:id) }),
|
68
|
+
text: translated_attribute(participatory_space.scope.name),
|
69
|
+
icon: resource_type_icon_key(participatory_space.scope.class),
|
70
|
+
active: participatory_space.scope.id.to_s == current_scope.to_s,
|
71
|
+
sr_text: Decidim::Scope.model_name.human(count: 1)
|
72
|
+
}]
|
73
|
+
end
|
74
|
+
),
|
75
|
+
*participatory_space.subscopes.map do |scope|
|
76
|
+
{
|
77
|
+
url: url_for(filter: { with_scope: scope.id, with_category: category.try(:id) }),
|
78
|
+
text: translated_attribute(scope.name),
|
79
|
+
icon: resource_type_icon_key(scope.class),
|
80
|
+
active: scope.id.to_s == current_scope.to_s,
|
81
|
+
sr_text: Decidim::Scope.model_name.human(count: 1)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
]
|
85
|
+
end
|
86
|
+
|
87
|
+
def apply_accountability_pack_tags
|
88
|
+
append_stylesheet_pack_tag("decidim_accountability", media: "all")
|
89
|
+
append_javascript_pack_tag("decidim_accountability")
|
90
|
+
end
|
50
91
|
end
|
51
92
|
end
|
52
93
|
end
|
@@ -22,6 +22,16 @@ module Decidim
|
|
22
22
|
|
23
23
|
@category ||= current_participatory_space.categories.find(category_id.is_a?(Array) ? category_id.first : category_id)
|
24
24
|
end
|
25
|
+
|
26
|
+
def parent_categories(category)
|
27
|
+
return [] if category&.parent.blank?
|
28
|
+
|
29
|
+
[*parent_categories(category.parent), category.parent]
|
30
|
+
end
|
31
|
+
|
32
|
+
def categories_hierarchy
|
33
|
+
parent_categories(category)
|
34
|
+
end
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
module Admin
|
6
|
+
class ImportProjectsJob < ApplicationJob
|
7
|
+
queue_as :default
|
8
|
+
|
9
|
+
def perform(projects, component, user)
|
10
|
+
projects.map do |id|
|
11
|
+
original_project = Decidim::Budgets::Project.find_by(id:)
|
12
|
+
|
13
|
+
new_result = create_result_from_project!(original_project, statuses(component).first, component, user)
|
14
|
+
new_result.link_resources([original_project], "included_projects")
|
15
|
+
new_result.link_resources(
|
16
|
+
original_project.linked_resources(:proposals, "included_proposals"),
|
17
|
+
"included_proposals"
|
18
|
+
)
|
19
|
+
|
20
|
+
copy_attachments(original_project, new_result)
|
21
|
+
end.compact
|
22
|
+
Decidim::Accountability::ImportProjectsMailer.import(user, component, projects.count).deliver_now
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def create_result_from_project!(project, status, component, user)
|
28
|
+
params = {
|
29
|
+
title: project.title,
|
30
|
+
description: project.description,
|
31
|
+
category: project.category,
|
32
|
+
scope: project.scope || project.budget.scope,
|
33
|
+
component:,
|
34
|
+
status:,
|
35
|
+
progress: status&.progress || 0
|
36
|
+
}
|
37
|
+
@result = Decidim.traceability.create!(
|
38
|
+
Result,
|
39
|
+
user,
|
40
|
+
params,
|
41
|
+
visibility: "all"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def copy_attachments(project, result)
|
46
|
+
project.attachments.each do |attachment|
|
47
|
+
new_attachment = Decidim::Attachment.new(
|
48
|
+
{
|
49
|
+
# Attached to needs to be always defined before the file is set
|
50
|
+
attached_to: result
|
51
|
+
}.merge(
|
52
|
+
attachment.attributes.slice("content_type", "description", "file_size", "title", "weight")
|
53
|
+
)
|
54
|
+
)
|
55
|
+
|
56
|
+
if attachment.file.attached?
|
57
|
+
new_attachment.file = attachment.file.blob
|
58
|
+
else
|
59
|
+
new_attachment.attached_uploader(:file).remote_url = attachment.attached_uploader(:file)
|
60
|
+
end
|
61
|
+
|
62
|
+
new_attachment.save!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def statuses(component)
|
67
|
+
Decidim::Accountability::Status.where(component:).order(:progress)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Accountability
|
5
|
+
# This mailer sends a notification email containing the result of importing
|
6
|
+
# Cprojects to the results.
|
7
|
+
class ImportProjectsMailer < Decidim::ApplicationMailer
|
8
|
+
# Public: Sends a notification email with the result of projects import selected projects to Accountability
|
9
|
+
#
|
10
|
+
# user - The user to be notified.
|
11
|
+
#
|
12
|
+
# Returns nothing.
|
13
|
+
def import(user, component, projects)
|
14
|
+
@user = user
|
15
|
+
@organization = user.organization
|
16
|
+
@component = component
|
17
|
+
@projects = projects
|
18
|
+
|
19
|
+
with_user(user) do
|
20
|
+
mail(to: "#{user.name} <#{user.email}>", subject: I18n.t("decidim.accountability.import_projects_mailer.import.subject"))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -96,7 +96,7 @@ module Decidim
|
|
96
96
|
|
97
97
|
private
|
98
98
|
|
99
|
-
# Private: When a row uses weight 1 and there
|
99
|
+
# Private: When a row uses weight 1 and there is more than one, weight should not be considered
|
100
100
|
# Handle special case when all children weight are nil
|
101
101
|
def children_use_weighted_progress?
|
102
102
|
return false if children.pluck(:weight).all?(&:nil?)
|
@@ -0,0 +1,3 @@
|
|
1
|
+
<svg width="24" height="43" viewBox="0 0 24 43" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<path d="M23.6979 35.6924C24.0211 36.0156 24.0211 36.5396 23.6979 36.8628L18.4312 42.1296C18.108 42.4527 17.5841 42.4527 17.2608 42.1296C16.9376 41.8064 16.9376 41.2824 17.2608 40.9592L21.9424 36.2776L17.2608 31.5961C16.9376 31.2729 16.9376 30.7489 17.2608 30.4257C17.584 30.1025 18.108 30.1025 18.4312 30.4257L23.6979 35.6924ZM2.4247 0V20.9346H0.769531V0.000447832L2.4247 0ZM16.9402 35.45H23.1127V37.1052H16.9402V35.45ZM2.4247 20.9346C2.4247 28.9512 8.92354 35.45 16.9402 35.45V37.1052C8.00938 37.1052 0.769531 29.8654 0.769531 20.9346H2.4247Z" fill="currentColor" />
|
3
|
+
</svg>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
const toggleInfo = (val) => {
|
2
|
+
document.querySelectorAll(".help-text").forEach((toBeHidden) => {
|
3
|
+
if (val === toBeHidden.id && toBeHidden.classList.value.includes("hide")) {
|
4
|
+
toBeHidden.classList.remove("hide")
|
5
|
+
} else {
|
6
|
+
toBeHidden.classList.add("hide")
|
7
|
+
}
|
8
|
+
});
|
9
|
+
};
|
10
|
+
export default () => {
|
11
|
+
const item = document.querySelector("#result_import_projects_origin_component_id");
|
12
|
+
item.addEventListener(("change"), (event) => {
|
13
|
+
toggleInfo(`component_${event.target.value}`);
|
14
|
+
});
|
15
|
+
};
|