decidim-reporting_proposals 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +32 -0
- data/.erb-lint.yml +30 -0
- data/.eslintignore +3 -0
- data/.eslintrc.json +239 -0
- data/.github/workflows/codeql-analysis.yml +74 -0
- data/.github/workflows/lint.yml +45 -0
- data/.github/workflows/test_integration.yml +125 -0
- data/.github/workflows/test_unit.yml +51 -0
- data/.gitignore +27 -0
- data/.rspec +3 -0
- data/.rubocop.yml +3 -0
- data/.rubocop_rails.yml +87 -0
- data/.rubocop_ruby.yml +1754 -0
- data/.ruby-version +1 -0
- data/.simplecov +13 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +40 -0
- data/Gemfile.lock +815 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +166 -0
- data/Rakefile +40 -0
- data/app/cells/decidim/reporting_proposals/edit_note_modal/show.erb +20 -0
- data/app/cells/decidim/reporting_proposals/edit_note_modal_cell.rb +37 -0
- data/app/commands/concerns/decidim/reporting_proposals/admin/create_category_override.rb +32 -0
- data/app/commands/concerns/decidim/reporting_proposals/admin/update_category_override.rb +32 -0
- data/app/commands/concerns/decidim/reporting_proposals/create_report_override.rb +19 -0
- data/app/commands/decidim/reporting_proposals/admin/update_proposal.rb +46 -0
- data/app/commands/decidim/reporting_proposals/admin/update_proposal_note.rb +36 -0
- data/app/commands/decidim/reporting_proposals/create_reporting_proposal.rb +68 -0
- data/app/controllers/concerns/decidim/reporting_proposals/admin/categories_controller_override.rb +16 -0
- data/app/controllers/concerns/decidim/reporting_proposals/admin/needs_header_snippets.rb +50 -0
- data/app/controllers/concerns/decidim/reporting_proposals/admin/proposal_answer_templates_controller_override.rb +18 -0
- data/app/controllers/concerns/decidim/reporting_proposals/admin/proposal_answers_controller_override.rb +35 -0
- data/app/controllers/concerns/decidim/reporting_proposals/admin/proposals_controller_override.rb +28 -0
- data/app/controllers/concerns/decidim/reporting_proposals/needs_proposal_extra_validations_snippets.rb +51 -0
- data/app/controllers/concerns/decidim/reporting_proposals/proposals_controller_override.rb +113 -0
- data/app/controllers/decidim/reporting_proposals/admin/application_controller.rb +18 -0
- data/app/controllers/decidim/reporting_proposals/admin/proposal_notes_controller.rb +38 -0
- data/app/controllers/decidim/reporting_proposals/admin/proposals_controller.rb +61 -0
- data/app/controllers/decidim/reporting_proposals/application_controller.rb +11 -0
- data/app/controllers/decidim/reporting_proposals/geolocation_controller.rb +32 -0
- data/app/forms/concerns/decidim/reporting_proposals/admin/category_form_override.rb +19 -0
- data/app/forms/concerns/decidim/reporting_proposals/form_builder_override.rb +48 -0
- data/app/forms/concerns/decidim/reporting_proposals/map_builder_override.rb +60 -0
- data/app/forms/decidim/reporting_proposals/admin/proposal_photo_form.rb +23 -0
- data/app/forms/decidim/reporting_proposals/proposal_form.rb +33 -0
- data/app/helpers/concerns/decidim/reporting_proposals/admin/proposals_helper_override.rb +63 -0
- data/app/helpers/concerns/decidim/reporting_proposals/proposal_wizard_helper_override.rb +61 -0
- data/app/jobs/decidim/reporting_proposals/assign_proposal_valuators_job.rb +51 -0
- data/app/models/concerns/decidim/reporting_proposals/category_override.rb +28 -0
- data/app/models/concerns/decidim/reporting_proposals/participatory_space_role_config/valuator_override.rb +17 -0
- data/app/models/concerns/decidim/reporting_proposals/participatory_space_user_role_override.rb +25 -0
- data/app/models/decidim/reporting_proposals/category_valuator.rb +28 -0
- data/app/overrides/decidim/admin/categories/_form/add_valuators_field.html.erb.deface +3 -0
- data/app/overrides/decidim/admin/categories/index/add_table_column_name.html.erb.deface +3 -0
- data/app/overrides/decidim/admin/categories/index/add_valuators.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposal_notes/_proposal_notes/add_edit_link.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposal_notes/_proposal_notes/add_links_to_note.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposals/_proposal-tr/add_td_hide_action.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposals/_proposal-tr/add_valuators_name.html.erb.deface +9 -0
- data/app/overrides/decidim/proposals/admin/proposals/_proposal-tr/replace_td_title.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposals/show/add_photo_management.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposals/show/add_send_email_btn.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/admin/proposals/show/remove_photos.html.erb.deface +4 -0
- data/app/overrides/decidim/proposals/admin/proposals/show/replace_valuators.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/_proposal_similar/add_distance_badge.html.erb.deface +5 -0
- data/app/overrides/decidim/proposals/proposals/_wizard_header/replace_title.html.erb.deface +14 -0
- data/app/overrides/decidim/proposals/proposals/edit/add_user_group.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/edit/replace_javascript.html.erb.deface +8 -0
- data/app/overrides/decidim/proposals/proposals/edit/replace_partial_edit_form_fields.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/edit_draft/add_user_group.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/edit_draft/replace_javascript.html.erb.deface +8 -0
- data/app/overrides/decidim/proposals/proposals/edit_draft/replace_partial_edit_form_fields.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/index/add_additional_button.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/new/remove_title.html.erb.deface +1 -0
- data/app/overrides/decidim/proposals/proposals/new/replace_body.html.erb.deface +3 -0
- data/app/overrides/decidim/proposals/proposals/new/replace_javascript.html.erb.deface +8 -0
- data/app/overrides/decidim/proposals/proposals/show/add_additional_button.html.erb.deface +3 -0
- data/app/overrides/layouts/decidim/_process_header_steps/always_show_new_proposals.html.erb.deface +3 -0
- data/app/packs/entrypoints/decidim_reporting_proposals.js +6 -0
- data/app/packs/entrypoints/decidim_reporting_proposals_camera.js +2 -0
- data/app/packs/entrypoints/decidim_reporting_proposals_geocoding.js +2 -0
- data/app/packs/entrypoints/decidim_reporting_proposals_js_validations.js +1 -0
- data/app/packs/entrypoints/decidim_reporting_proposals_list_component_admin.js +1 -0
- data/app/packs/entrypoints/decidim_reporting_proposals_manage_component_admin.js +1 -0
- data/app/packs/images/.keep +0 -0
- data/app/packs/src/decidim/reporting_proposals/proposal_extra_validations.js +89 -0
- data/app/packs/src/decidim/reporting_proposals/proposals/add_proposal.js +66 -0
- data/app/packs/src/decidim/reporting_proposals/reverse_geocoding.js +54 -0
- data/app/packs/src/decidim/reporting_proposals/user_camera_inputs.js +49 -0
- data/app/packs/stylesheets/decidim/reporting_proposals/geocoding_addons.scss +34 -0
- data/app/packs/stylesheets/decidim/reporting_proposals/list_component_admin.scss +27 -0
- data/app/packs/stylesheets/decidim/reporting_proposals/manage_component_admin.scss +31 -0
- data/app/packs/stylesheets/decidim/reporting_proposals/proposals/add_proposal.scss +12 -0
- data/app/packs/stylesheets/decidim/reporting_proposals/user_camera_inputs.scss +19 -0
- data/app/permissions/concerns/decidim/reporting_proposals/admin/permissions_override.rb +27 -0
- data/app/permissions/decidim/reporting_proposals/admin/permissions.rb +79 -0
- data/app/permissions/decidim/reporting_proposals/permissions.rb +17 -0
- data/app/queries/decidim/reporting_proposals/nearby_proposals.rb +57 -0
- data/app/serializers/decidim/reporting_proposals/proposal_serializer_override.rb +77 -0
- data/app/validators/concerns/decidim/reporting_proposals/component_validator_override.rb +25 -0
- data/app/views/decidim/proposals/admin/proposal_notes/_editing_note.html.erb +18 -0
- data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes_body.html.erb +6 -0
- data/app/views/decidim/proposals/admin/proposals/_send_email_button.html.erb +4 -0
- data/app/views/decidim/proposals/proposals/_additional_button.html.erb +6 -0
- data/app/views/decidim/reporting_proposals/admin/categories/_column_valuators.html.erb +1 -0
- data/app/views/decidim/reporting_proposals/admin/categories/_valuators.html.erb +1 -0
- data/app/views/decidim/reporting_proposals/admin/categories/_valuators_field.html.erb +7 -0
- data/app/views/decidim/reporting_proposals/admin/proposals/_photo_form.html.erb +24 -0
- data/app/views/decidim/reporting_proposals/admin/proposals/_photo_gallery.html.erb +21 -0
- data/app/views/decidim/reporting_proposals/admin/proposals/_photos.html.erb +14 -0
- data/app/views/decidim/reporting_proposals/admin/proposals/_proposal_td_hide.html.erb +20 -0
- data/app/views/decidim/reporting_proposals/admin/proposals/_proposal_td_title.html.erb +41 -0
- data/app/views/decidim/reporting_proposals/proposals/_additional_button_for_show.html.erb +6 -0
- data/app/views/decidim/reporting_proposals/proposals/_new_proposal_fields.html.erb +7 -0
- data/app/views/decidim/reporting_proposals/proposals/_reporting_proposal_fields.html.erb +113 -0
- data/app/views/decidim/reporting_proposals/proposals/_user_group.html.erb +5 -0
- data/bin/rails +6 -0
- data/bin/webpack-dev-server +6 -0
- data/codecov.yml +11 -0
- data/config/assets.rb +13 -0
- data/config/i18n-tasks.yml +13 -0
- data/config/locales/ca.yml +366 -0
- data/config/locales/de.yml +366 -0
- data/config/locales/en.yml +426 -0
- data/config/locales/es.yml +366 -0
- data/crowdin.yml +45 -0
- data/db/migrate/20221219151846_create_decidim_categories_valuators.rb +17 -0
- data/decidim-reporting_proposals.gemspec +34 -0
- data/lib/decidim/api/reporting_proposals_type.rb +10 -0
- data/lib/decidim/reporting_proposals/admin.rb +8 -0
- data/lib/decidim/reporting_proposals/admin_engine.rb +31 -0
- data/lib/decidim/reporting_proposals/component.rb +490 -0
- data/lib/decidim/reporting_proposals/config.rb +53 -0
- data/lib/decidim/reporting_proposals/engine.rb +96 -0
- data/lib/decidim/reporting_proposals/test/factories.rb +13 -0
- data/lib/decidim/reporting_proposals/version.rb +15 -0
- data/lib/decidim/reporting_proposals.rb +13 -0
- data/package-lock.json +7844 -0
- data/package.json +195 -0
- metadata +319 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
.table__title-block {
|
2
|
+
display: flex;
|
3
|
+
align-items: flex-start;
|
4
|
+
}
|
5
|
+
|
6
|
+
.table__title-icon {
|
7
|
+
width: 20px;
|
8
|
+
padding: 3px;
|
9
|
+
margin-right: 5px;
|
10
|
+
float: left;
|
11
|
+
}
|
12
|
+
|
13
|
+
.table__list-title {
|
14
|
+
display: flex;
|
15
|
+
flex-direction: column;
|
16
|
+
align-items: start;
|
17
|
+
}
|
18
|
+
|
19
|
+
.table__list-title a {
|
20
|
+
text-align: start;
|
21
|
+
}
|
22
|
+
|
23
|
+
.help-text-overdue {
|
24
|
+
font-style: italic;
|
25
|
+
font-size: .8125rem;
|
26
|
+
text-align: start;
|
27
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
.global-settings,
|
2
|
+
.step-settings {
|
3
|
+
.readonly_container {
|
4
|
+
display: none;
|
5
|
+
}
|
6
|
+
}
|
7
|
+
|
8
|
+
.proposal-photo.gallery__item {
|
9
|
+
position: relative;
|
10
|
+
margin: 0 0 1rem;
|
11
|
+
border: 1px solid rgba(0, 0, 0, .2);
|
12
|
+
border-radius: 0;
|
13
|
+
background-color: white;
|
14
|
+
color: #202734;
|
15
|
+
}
|
16
|
+
|
17
|
+
.proposal-photo .thumbnail {
|
18
|
+
margin-bottom: 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
.delete-proposal__button {
|
22
|
+
position: absolute;
|
23
|
+
right: 0;
|
24
|
+
top: 7px;
|
25
|
+
width: 2rem;
|
26
|
+
height: 2rem;
|
27
|
+
background: rgba(var(--primary-rgb), .8);
|
28
|
+
color: #fff;
|
29
|
+
border-radius: 50%;
|
30
|
+
text-align: center;
|
31
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
button.user-device-camera {
|
2
|
+
border-radius: 4px !important;
|
3
|
+
max-height: 3rem;
|
4
|
+
}
|
5
|
+
|
6
|
+
.has_no_image {
|
7
|
+
margin-top: -1rem;
|
8
|
+
text-align: right;
|
9
|
+
}
|
10
|
+
|
11
|
+
@media only screen and (max-width: 596px) {
|
12
|
+
.gallery__container .input-group .input-group-button {
|
13
|
+
display: block;
|
14
|
+
}
|
15
|
+
|
16
|
+
.has_no_image {
|
17
|
+
margin-top: -.5rem;
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module Admin
|
6
|
+
module PermissionsOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
private
|
11
|
+
|
12
|
+
def valuator_can_unassign_valuator_from_proposals?
|
13
|
+
can_unassign_valuator_from_proposals? if user == context.fetch(:valuator, nil)
|
14
|
+
|
15
|
+
can_add_valuators?
|
16
|
+
end
|
17
|
+
|
18
|
+
def can_add_valuators?
|
19
|
+
return unless permission_action.action == :assign_to_valuator && permission_action.subject == :proposals
|
20
|
+
|
21
|
+
toggle_allow(Decidim::ReportingProposals.valuators_assign_other_valuators)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module Admin
|
6
|
+
class Permissions < Decidim::Proposals::Admin::Permissions
|
7
|
+
def permissions
|
8
|
+
return permission_action if permission_action.scope != :admin
|
9
|
+
return permission_action unless user
|
10
|
+
return permission_action if current_organization != user.organization
|
11
|
+
|
12
|
+
hide_content_action?
|
13
|
+
edit_photos_action?
|
14
|
+
edit_proposal_note?
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def current_organization
|
21
|
+
context[:proposal].try(:organization) || context[:current_organization]
|
22
|
+
end
|
23
|
+
|
24
|
+
def component_settings
|
25
|
+
context[:component_settings] || component.try(:settings)
|
26
|
+
end
|
27
|
+
|
28
|
+
def component
|
29
|
+
context[:proposal].try(:component) || context[:current_component]
|
30
|
+
end
|
31
|
+
|
32
|
+
def user_author_note?
|
33
|
+
context[:proposal_note].try(:author) == user
|
34
|
+
end
|
35
|
+
|
36
|
+
def hide_content_action?
|
37
|
+
return unless permission_action.action == :hide_proposal && permission_action.subject == :proposals
|
38
|
+
|
39
|
+
toggle_allow((admin_hide_proposals_enabled? && user_allowed_or_assigned?) || user_administrator?)
|
40
|
+
end
|
41
|
+
|
42
|
+
def edit_photos_action?
|
43
|
+
return unless permission_action.action == :edit_photos && permission_action.subject == :proposals
|
44
|
+
|
45
|
+
toggle_allow(admin_proposal_photo_editing_enabled? && (user_allowed_or_assigned? || user_administrator?))
|
46
|
+
end
|
47
|
+
|
48
|
+
def edit_proposal_note?
|
49
|
+
return unless permission_action.action == :edit_note && permission_action.subject == :proposal_note
|
50
|
+
|
51
|
+
toggle_allow(user_author_note?)
|
52
|
+
end
|
53
|
+
|
54
|
+
def admin_proposal_photo_editing_enabled?
|
55
|
+
Decidim::ReportingProposals.allow_proposal_photo_editing.present? &&
|
56
|
+
component_settings.try(:proposal_photo_editing_enabled)
|
57
|
+
end
|
58
|
+
|
59
|
+
def admin_hide_proposals_enabled?
|
60
|
+
Decidim::ReportingProposals.allow_admins_to_hide_proposals.present?
|
61
|
+
end
|
62
|
+
|
63
|
+
def user_allowed_or_assigned?
|
64
|
+
user.admin? || (user_is_valuator? && valuator_assigned_to_proposal?)
|
65
|
+
end
|
66
|
+
|
67
|
+
def user_administrator?
|
68
|
+
process = Decidim::ParticipatoryProcess.where(organization: context[:proposal].try(:organization))
|
69
|
+
|
70
|
+
admin = Decidim::User.where(id: Decidim::ParticipatoryProcessUserRole
|
71
|
+
.where(participatory_process: process, role: :admin)
|
72
|
+
.select(user.id))
|
73
|
+
|
74
|
+
admin.exists? ? user : nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
class Permissions < Decidim::DefaultPermissions
|
6
|
+
def permissions
|
7
|
+
return permission_action unless user
|
8
|
+
|
9
|
+
return Decidim::ReportingProposals::Admin::Permissions.new(user, permission_action, context).permissions if permission_action.scope == :admin
|
10
|
+
|
11
|
+
allow! if permission_action.action == :locate && permission_action.subject == :geolocation
|
12
|
+
|
13
|
+
permission_action
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
# Class used to retrieve similar proposals.
|
6
|
+
class NearbyProposals < Rectify::Query
|
7
|
+
# Syntactic sugar to initialize the class and return the queried objects.
|
8
|
+
#
|
9
|
+
# components - Decidim::CurrentComponent
|
10
|
+
# proposal - Decidim::Proposals::Proposal
|
11
|
+
def self.for(components, proposal)
|
12
|
+
new(components, proposal).query
|
13
|
+
end
|
14
|
+
|
15
|
+
# Initializes the class.
|
16
|
+
#
|
17
|
+
# components - Decidim::CurrentComponent
|
18
|
+
# proposal - Decidim::Proposals::Proposal
|
19
|
+
def initialize(components, proposal)
|
20
|
+
@components = components
|
21
|
+
@proposal = proposal
|
22
|
+
@radius = proposal.component.settings.geocoding_comparison_radius
|
23
|
+
@newer_than = proposal.component.settings.geocoding_comparison_newer_than
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves similar proposals by distance
|
27
|
+
def query
|
28
|
+
return Decidim::Proposals::Proposal.none if query_ids.blank?
|
29
|
+
|
30
|
+
Decidim::Proposals::Proposal
|
31
|
+
.where(id: query_ids)
|
32
|
+
.order([Arel.sql("array_position(ARRAY[?], id)"), query_ids])
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# we won't return directly this query due a problem with the method "count" in the geocoder gem
|
38
|
+
# see https://github.com/alexreisner/geocoder#note-on-rails-41-and-greater
|
39
|
+
def query_ids
|
40
|
+
base_query
|
41
|
+
.near([@proposal.latitude, @proposal.longitude], @radius.to_f / 1000, units: :km)
|
42
|
+
.limit(Decidim::Proposals.similarity_limit).map(&:id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def base_query
|
46
|
+
@base_query = Decidim::Proposals::Proposal
|
47
|
+
.where(component: @components)
|
48
|
+
.published
|
49
|
+
.not_hidden
|
50
|
+
|
51
|
+
return @base_query if @newer_than.zero?
|
52
|
+
|
53
|
+
@base_query.where("published_at > ?", @newer_than.days.ago)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module ProposalSerializerOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
include ActionView::Helpers::DateHelper
|
10
|
+
include Decidim::Proposals::Admin::ProposalsHelper
|
11
|
+
|
12
|
+
def serialize
|
13
|
+
{
|
14
|
+
id: proposal.id,
|
15
|
+
category: {
|
16
|
+
id: proposal.category.try(:id),
|
17
|
+
name: proposal.category.try(:name) || empty_translatable
|
18
|
+
},
|
19
|
+
scope: {
|
20
|
+
id: proposal.scope.try(:id),
|
21
|
+
name: proposal.scope.try(:name) || empty_translatable
|
22
|
+
},
|
23
|
+
participatory_space: {
|
24
|
+
id: proposal.participatory_space.id,
|
25
|
+
url: Decidim::ResourceLocatorPresenter.new(proposal.participatory_space).url
|
26
|
+
},
|
27
|
+
component: { id: component.id },
|
28
|
+
title: proposal.title,
|
29
|
+
body: proposal.body,
|
30
|
+
address: proposal.address,
|
31
|
+
latitude: proposal.latitude,
|
32
|
+
longitude: proposal.longitude,
|
33
|
+
state: proposal.state.to_s,
|
34
|
+
reference: proposal.reference,
|
35
|
+
answer: ensure_translatable(proposal.answer),
|
36
|
+
answer_time: answer_time,
|
37
|
+
supports: proposal.proposal_votes_count,
|
38
|
+
endorsements: {
|
39
|
+
total_count: proposal.endorsements.size,
|
40
|
+
user_endorsements: user_endorsements
|
41
|
+
},
|
42
|
+
comments: proposal.comments_count,
|
43
|
+
attachments: proposal.attachments.size,
|
44
|
+
followers: proposal.follows.size,
|
45
|
+
published_at: proposal.published_at,
|
46
|
+
url: url,
|
47
|
+
meeting_urls: meetings,
|
48
|
+
related_proposals: related_proposals,
|
49
|
+
is_amend: proposal.emendation?,
|
50
|
+
original_proposal: {
|
51
|
+
title: proposal&.amendable&.title,
|
52
|
+
url: original_proposal_url
|
53
|
+
}
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def answer_time
|
58
|
+
if unanswered_proposals_overdue?(proposal)
|
59
|
+
time_ago_in_words(last_day_to_answer(proposal),
|
60
|
+
scope: "decidim.reporting_proposals.admin.answer_overdue.datetime.distance_in_words")
|
61
|
+
elsif evaluating_proposals_overdue?(proposal)
|
62
|
+
time_ago_in_words(last_day_to_evaluate(proposal),
|
63
|
+
scope: "decidim.reporting_proposals.admin.answer_overdue.datetime.distance_in_words")
|
64
|
+
elsif grace_period_unanswered?(proposal)
|
65
|
+
time_ago_in_words(last_day_to_answer(proposal),
|
66
|
+
scope: "decidim.reporting_proposals.admin.answer_pending.datetime.distance_in_words")
|
67
|
+
elsif grace_period_evaluating?(proposal)
|
68
|
+
time_ago_in_words(last_day_to_evaluate(proposal),
|
69
|
+
scope: "decidim.reporting_proposals.admin.evaluate_pending.datetime.distance_in_words")
|
70
|
+
elsif proposal.accepted? || proposal.rejected?
|
71
|
+
"#{I18n.t("decidim.reporting_proposals.admin.resolution_time")}: #{time_elapsed_to_answer(proposal)}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
# Exposes the proposal resource so users can view and create them.
|
6
|
+
module ComponentValidatorOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# The actual validator method. It is called when ActiveRecord iterates
|
11
|
+
# over all the validators.
|
12
|
+
def validate_each(record, attribute, component)
|
13
|
+
unless component
|
14
|
+
record.errors[attribute] << :blank
|
15
|
+
return
|
16
|
+
end
|
17
|
+
manifests = [options[:manifest].to_s]
|
18
|
+
manifests << "reporting_proposals" if manifests.first == "proposals"
|
19
|
+
|
20
|
+
record.errors[attribute] << :invalid unless component.manifest_name.to_s.in?(manifests)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<% if note.author == current_user %>
|
2
|
+
<%= cell("decidim/reporting_proposals/edit_note_modal", note, modal_id: "editNoteModal#{note.id}", note: note, proposal: proposal) %>
|
3
|
+
<button type="button" class="link-alt m-xs"
|
4
|
+
data-open="<%= current_user.present? ? "editNoteModal#{note.id}" : "loginModal" %>"
|
5
|
+
title="<%= t("modal.title", scope: "decidim.reporting_proposals.admin.proposal_notes") %>"
|
6
|
+
aria-controls="<%= current_user.present? ? "editNoteModal#{note.id}" : "loginModal" %>"
|
7
|
+
aria-haspopup="true"
|
8
|
+
tabindex="0"
|
9
|
+
style="color:#97a2b2; cursor: pointer">
|
10
|
+
<%= icon "pencil", aria_hidden: true, class: "action-icon--preview", role: "img", "aria-hidden": true %>
|
11
|
+
</button>
|
12
|
+
<% end %>
|
13
|
+
<% if note.created_at != note.updated_at %>
|
14
|
+
<span class="text-muted">
|
15
|
+
<%= t("update.edited", scope: "decidim.reporting_proposals.admin.proposal_notes") %>
|
16
|
+
<%= l note.updated_at, format: :short %>
|
17
|
+
</span>
|
18
|
+
<% end %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% note.body.split("\n").each_with_index do |paragraph, index| %>
|
2
|
+
<%= Decidim::ContentRenderers::LinkRenderer.new(paragraph.gsub(URI.regexp, '<a href="\0" target="_blank">\0</a>')).render.html_safe %>
|
3
|
+
<% unless index == note.body.split("\n").size - 1 %>
|
4
|
+
<br>
|
5
|
+
<% end %>
|
6
|
+
<% end %>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% if current_component.settings.try(:additional_buttons_show) &&
|
2
|
+
current_component.settings.additional_button_text.present? &&
|
3
|
+
current_component.settings.additional_button_link.present? %>
|
4
|
+
<%= link_to translated_attribute(component_settings.additional_button_text),
|
5
|
+
component_settings.additional_button_link, class: "title-action__action button small ml-s" %>
|
6
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<th><%= t("valuators_column", scope: "decidim.reporting_proposals.admin.categories.index") %></th>
|
@@ -0,0 +1 @@
|
|
1
|
+
<td><%= category.valuator_names.join(", ") %></td>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%= decidim_form_for(@photo_form, url: decidim_admin_reporting_proposals.add_photos_path(id: proposal.id),
|
2
|
+
method: :post,
|
3
|
+
html: { multipart: true, class: "form edit_proposal proposal_form_admin" }) do |f| %>
|
4
|
+
<div class="row column gallery__container">
|
5
|
+
<fieldset>
|
6
|
+
<legend><%= t(".gallery_legend") %></legend>
|
7
|
+
<% if proposal.photos.any? %>
|
8
|
+
<div class="gallery row">
|
9
|
+
<% proposal.photos.each do |photo| %>
|
10
|
+
<div class="callout gallery__item">
|
11
|
+
<%= f.hidden_field :photos, multiple: true, value: photo.id, id: "photo-#{photo.id}" %>
|
12
|
+
</div>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
<div class="row column">
|
17
|
+
<%= f.file_field :add_photos, multiple: true %>
|
18
|
+
</div>
|
19
|
+
<div class="actions">
|
20
|
+
<%= f.submit t(".action") %>
|
21
|
+
</div>
|
22
|
+
</fieldset>
|
23
|
+
</div>
|
24
|
+
<% end %>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<% if proposal.photos.any? %>
|
2
|
+
<div class="row column">
|
3
|
+
<strong><%= t(".photos") %>:</strong>
|
4
|
+
<div id="photos" class="gallery row flex--fsc proposal-<%= proposal.id %>">
|
5
|
+
<% proposal.photos.each do |photo| %>
|
6
|
+
<div class="proposal-photo gallery__item" id="photo-<%= photo.id %>">
|
7
|
+
<%= link_to photo.big_url, target: "_blank", rel: "noopener" do %>
|
8
|
+
<%= image_tag photo.thumbnail_url, class: "thumbnail", alt: strip_tags(translated_attribute(photo.title)) %>
|
9
|
+
<% if admin_allowed_to? :edit_photos, :proposals, extra_context = { proposal: proposal }, chain = [::Decidim::ReportingProposals::Admin::Permissions] %>
|
10
|
+
<%= icon_link_to "x",
|
11
|
+
decidim_admin_reporting_proposals.remove_photo_path(id: proposal.id, photo_id: photo.id),
|
12
|
+
t(".delete_image"),
|
13
|
+
method: :delete,
|
14
|
+
class: "delete-proposal__button", style: "color:white;" %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
<% end %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% if proposal.photos.any? || component_settings.attachments_allowed? %>
|
2
|
+
<div class="card">
|
3
|
+
<div class="card-divider">
|
4
|
+
<h2 class="card-title"><%= t(".title") %></h2>
|
5
|
+
</div>
|
6
|
+
<div class="card-section">
|
7
|
+
<%= render partial: "decidim/reporting_proposals/admin/proposals/photo_gallery" %>
|
8
|
+
|
9
|
+
<% if admin_allowed_to? :edit_photos, :proposals, extra_context = { proposal: proposal }, chain = [::Decidim::ReportingProposals::Admin::Permissions] %>
|
10
|
+
<%= render partial: "decidim/reporting_proposals/admin/proposals/photo_form" %>
|
11
|
+
<% end %>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% if admin_allowed_to?(:hide_proposal, :proposals, extra_context = { proposal: proposal }, chain = [::Decidim::ReportingProposals::Admin::Permissions]) %>
|
2
|
+
<% if proposal.reported? %>
|
3
|
+
<%= icon_link_to "trash", decidim_admin_reporting_proposals.hide_proposal_path(id: proposal),
|
4
|
+
t("actions.hide", scope: "decidim.moderations"), method: :put, class: "action-icon" %>
|
5
|
+
<% else %>
|
6
|
+
<%= cell("decidim/flag_modal", proposal, modal_id: "flagModal#{proposal.id}") %>
|
7
|
+
<button type="button" class="link-alt"
|
8
|
+
data-open="<%= current_user.present? ? "flagModal#{proposal.id}" : "loginModal" %>"
|
9
|
+
title="<%= t("report", scope: "decidim.proposals.proposals.show") %>"
|
10
|
+
aria-controls="<%= current_user.present? ? "flagModal#{proposal.id}" : "loginModal" %>"
|
11
|
+
aria-haspopup="true"
|
12
|
+
tabindex="0"
|
13
|
+
style="color:#97a2b2; cursor: pointer">
|
14
|
+
<%= icon "flag", aria_hidden: true, class: "action-icon--preview", role: "img", "aria-hidden": true %>
|
15
|
+
<span class="show-for-sr">
|
16
|
+
<%= t("report", scope: "decidim.proposals.proposals.show") %>
|
17
|
+
</span>
|
18
|
+
</button>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<div class="table__title-block">
|
2
|
+
<span class="table__title-icon">
|
3
|
+
<% if unanswered_proposals_overdue?(proposal) || evaluating_proposals_overdue?(proposal) %>
|
4
|
+
<%= icon "datetime", class: "text-alert" %>
|
5
|
+
<% elsif grace_period_unanswered?(proposal) || grace_period_evaluating?(proposal) %>
|
6
|
+
<%= icon "timer", class: "text-warning" %>
|
7
|
+
<% end %>
|
8
|
+
</span>
|
9
|
+
<div class="table__list-title">
|
10
|
+
<%= link_to(
|
11
|
+
decidim_html_escape(present(proposal).title).html_safe,
|
12
|
+
proposal_path(proposal)
|
13
|
+
) %>
|
14
|
+
<% if unanswered_proposals_overdue?(proposal) %>
|
15
|
+
<div class="help-text-overdue text-alert">
|
16
|
+
<%= time_ago_in_words(last_day_to_answer(proposal),
|
17
|
+
scope: "decidim.reporting_proposals.admin.answer_overdue.datetime.distance_in_words") %>
|
18
|
+
</div>
|
19
|
+
<% elsif evaluating_proposals_overdue?(proposal) %>
|
20
|
+
<div class="help-text-overdue text-alert">
|
21
|
+
<%= time_ago_in_words(last_day_to_evaluate(proposal),
|
22
|
+
scope: "decidim.reporting_proposals.admin.answer_overdue.datetime.distance_in_words") %>
|
23
|
+
</div>
|
24
|
+
<% elsif grace_period_unanswered?(proposal) %>
|
25
|
+
<div class="help-text-overdue text-warning">
|
26
|
+
<%= time_ago_in_words(last_day_to_answer(proposal),
|
27
|
+
scope: "decidim.reporting_proposals.admin.answer_pending.datetime.distance_in_words") %>
|
28
|
+
</div>
|
29
|
+
<% elsif grace_period_evaluating?(proposal) %>
|
30
|
+
<div class="help-text-overdue text-warning">
|
31
|
+
<%= time_ago_in_words(last_day_to_evaluate(proposal),
|
32
|
+
scope: "decidim.reporting_proposals.admin.evaluate_pending.datetime.distance_in_words") %>
|
33
|
+
</div>
|
34
|
+
<% elsif proposal.accepted? || proposal.rejected? %>
|
35
|
+
<div class="help-text-overdue text-success">
|
36
|
+
<%= t("decidim.reporting_proposals.admin.resolution_time") %>:
|
37
|
+
<%= time_elapsed_to_answer(proposal) %>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
</div>
|
41
|
+
</div>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<% if current_component.settings.try(:additional_buttons_for_show_proposal_show) &&
|
2
|
+
current_component.settings.additional_button_for_show_proposal_text.present? &&
|
3
|
+
current_component.settings.additional_button_for_show_proposal_link.present? %>
|
4
|
+
<%= link_to translated_attribute(component_settings.additional_button_for_show_proposal_text),
|
5
|
+
component_settings.additional_button_for_show_proposal_link, class: "title-action__action button small ml-s" %>
|
6
|
+
<% end %>
|