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,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
class AssignProposalValuatorsJob < ApplicationJob
|
6
|
+
queue_as :default
|
7
|
+
attr_reader :resource
|
8
|
+
|
9
|
+
def perform(data)
|
10
|
+
@resource = data[:resource]
|
11
|
+
|
12
|
+
return if valuator_roles.blank?
|
13
|
+
|
14
|
+
unless data[:event_class] == "Decidim::Proposals::Admin::UpdateProposalCategoryEvent"
|
15
|
+
return unless data[:extra][:participatory_space]
|
16
|
+
return if data[:extra][:type] == "admin"
|
17
|
+
end
|
18
|
+
|
19
|
+
valuator_roles.each do |valuator_role|
|
20
|
+
Decidim::Proposals::Admin::AssignProposalsToValuator.call(form(valuator_role)) do
|
21
|
+
on(:ok) do
|
22
|
+
Rails.logger.info("Automatically assigned valuator #{valuator_role.user.name} to proposal ##{resource.id}")
|
23
|
+
end
|
24
|
+
on(:invalid) do
|
25
|
+
Rails.logger.warn("Couldn't automatically assign valuator #{valuator_role.user.name} to proposal ##{resource.id}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def form(valuator_role)
|
32
|
+
Decidim::Proposals::Admin::ValuationAssignmentForm.from_params(
|
33
|
+
id: valuator_role.id,
|
34
|
+
proposal_ids: [resource.id]
|
35
|
+
).with_context(
|
36
|
+
current_component: resource.component,
|
37
|
+
current_user: resource.organization.users.first # first admin for the traceability
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
# get valuators from categories
|
42
|
+
def valuator_roles
|
43
|
+
@valuator_roles ||= category.valuator_roles
|
44
|
+
end
|
45
|
+
|
46
|
+
def category
|
47
|
+
@category ||= resource.category
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module CategoryOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_many :category_valuators,
|
10
|
+
class_name: "Decidim::ReportingProposals::CategoryValuator",
|
11
|
+
foreign_key: :decidim_category_id,
|
12
|
+
dependent: :destroy
|
13
|
+
|
14
|
+
def valuator_roles
|
15
|
+
category_valuators.map(&:valuator_role)
|
16
|
+
end
|
17
|
+
|
18
|
+
def valuator_users
|
19
|
+
category_valuators.map(&:user)
|
20
|
+
end
|
21
|
+
|
22
|
+
def valuator_names
|
23
|
+
valuator_users.map(&:name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module ParticipatorySpaceRoleConfig
|
6
|
+
module ValuatorOverride
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
def accepted_components
|
11
|
+
[:proposals, :reporting_proposals]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/app/models/concerns/decidim/reporting_proposals/participatory_space_user_role_override.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
module ParticipatorySpaceUserRoleOverride
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
has_many :category_valuators,
|
10
|
+
class_name: "Decidim::ReportingProposals::CategoryValuator",
|
11
|
+
foreign_key: :valuator_role_id,
|
12
|
+
dependent: :destroy
|
13
|
+
|
14
|
+
# there is a bug in decidim that does not clean records from ValuationAssignment when removing Space roles
|
15
|
+
# This is a workaround to clean them manually
|
16
|
+
# It might be possible that we need to change this when this is solved:
|
17
|
+
# https://github.com/decidim/decidim/issues/10353
|
18
|
+
has_many :proposal_valuation_assignments,
|
19
|
+
class_name: "Decidim::Proposals::ValuationAssignment",
|
20
|
+
foreign_key: :valuator_role_id,
|
21
|
+
dependent: :destroy
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module ReportingProposals
|
5
|
+
class CategoryValuator < ApplicationRecord
|
6
|
+
self.table_name = "decidim_reporting_proposals_category_valuators"
|
7
|
+
|
8
|
+
belongs_to :category,
|
9
|
+
foreign_key: "decidim_category_id",
|
10
|
+
class_name: "Decidim::Category"
|
11
|
+
|
12
|
+
belongs_to :valuator_role,
|
13
|
+
polymorphic: true
|
14
|
+
|
15
|
+
delegate :user, to: :valuator_role
|
16
|
+
|
17
|
+
validate :category_belongs_to_same_participatory_space
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def category_belongs_to_same_participatory_space
|
22
|
+
return if category.participatory_space == valuator_role.participatory_space
|
23
|
+
|
24
|
+
errors.add(:category, :invalid)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/app/overrides/decidim/proposals/admin/proposals/_proposal-tr/add_valuators_name.html.erb.deface
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
<!-- replace "erb[loud]:contains('proposal.valuation_assignments.count')" -->
|
2
|
+
|
3
|
+
<% count = proposal.valuation_assignments.count %>
|
4
|
+
<% if count.zero? %>
|
5
|
+
0
|
6
|
+
<% else %>
|
7
|
+
<%= proposal.valuation_assignments.first&.valuator_role&.user&.name %>
|
8
|
+
<%= "(+#{(count - 1)})" if count > 1 %>
|
9
|
+
<% end %>
|
data/app/overrides/decidim/proposals/proposals/_proposal_similar/add_distance_badge.html.erb.deface
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
<!-- insert_before ".card__header" -->
|
2
|
+
|
3
|
+
<% if geocoding_comparison? %>
|
4
|
+
<span class="label secondary float-right"><%= icon("location") %> <%= t("away", scope: "decidim.reporting_proposals.proposals.compare.geocoding", meters: distance(1000 * @proposal.distance_from([proposal.latitude, proposal.longitude], :km))) %></span>
|
5
|
+
<% end %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!-- replace ".section-heading" -->
|
2
|
+
|
3
|
+
<% if geocoding_comparison? && action_name == "compare" %>
|
4
|
+
<h2 class="section-heading">
|
5
|
+
<%= t("title", scope: "decidim.reporting_proposals.proposals.compare.geocoding") %>
|
6
|
+
<%= "(#{@similar_proposals.count})" if @similar_proposals.present? %>
|
7
|
+
</h2>
|
8
|
+
<p><%= t("description", scope: "decidim.reporting_proposals.proposals.compare.geocoding", meters: distance) %></p>
|
9
|
+
<% else %>
|
10
|
+
<h2 class="section-heading">
|
11
|
+
<%= proposal_wizard_step_title action_name %>
|
12
|
+
<%= "(#{@similar_proposals.count})" if @similar_proposals.present? %>
|
13
|
+
</h2>
|
14
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<!-- replace "erb[loud]:contains('javascript_pack_tag')" -->
|
2
|
+
|
3
|
+
<% if reporting_proposal? %>
|
4
|
+
<%= javascript_pack_tag "decidim_reporting_proposals" %>
|
5
|
+
<%= stylesheet_pack_tag "decidim_reporting_proposals" %>
|
6
|
+
<% else %>
|
7
|
+
<%= javascript_pack_tag "decidim_proposals" %>
|
8
|
+
<% end %>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<!-- replace "erb[loud]:contains('javascript_pack_tag')" -->
|
2
|
+
|
3
|
+
<% if reporting_proposal? %>
|
4
|
+
<%= javascript_pack_tag "decidim_reporting_proposals" %>
|
5
|
+
<%= stylesheet_pack_tag "decidim_reporting_proposals" %>
|
6
|
+
<% else %>
|
7
|
+
<%= javascript_pack_tag "decidim_proposals" %>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<!-- remove ".hashtags__container" -->
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<!-- replace "erb[loud]:contains('javascript_pack_tag')" -->
|
2
|
+
|
3
|
+
<% if reporting_proposal? %>
|
4
|
+
<%= javascript_pack_tag "decidim_reporting_proposals" %>
|
5
|
+
<%= stylesheet_pack_tag "decidim_reporting_proposals" %>
|
6
|
+
<% else %>
|
7
|
+
<%= javascript_pack_tag "decidim_proposals" %>
|
8
|
+
<% end %>
|
@@ -0,0 +1 @@
|
|
1
|
+
import "src/decidim/reporting_proposals/proposal_extra_validations.js"
|
@@ -0,0 +1 @@
|
|
1
|
+
import "stylesheets/decidim/reporting_proposals/list_component_admin.scss";
|
@@ -0,0 +1 @@
|
|
1
|
+
import "stylesheets/decidim/reporting_proposals/manage_component_admin.scss";
|
File without changes
|
@@ -0,0 +1,89 @@
|
|
1
|
+
$(() => {
|
2
|
+
|
3
|
+
const $title = $('input[name="proposal[title]"]');
|
4
|
+
const $body = $('[name="proposal[body]"]');
|
5
|
+
let quill;
|
6
|
+
try {
|
7
|
+
quill = window.Quill.find(document.querySelector(".editor-container"));
|
8
|
+
} catch (e) {
|
9
|
+
console.log("Quill not found");
|
10
|
+
}
|
11
|
+
const $form = $title.closest("form");
|
12
|
+
|
13
|
+
const findError = ($field, prop) => {
|
14
|
+
let $closest = $field.closest("label");
|
15
|
+
if (!$closest.length) {
|
16
|
+
$closest = $field.closest(".editor");
|
17
|
+
}
|
18
|
+
// console.log("findError", $closest, $field, prop);
|
19
|
+
let search = `.form-error.${prop}`;
|
20
|
+
if (!prop) {
|
21
|
+
search = ".form-error"
|
22
|
+
}
|
23
|
+
let $error = $closest.find(search);
|
24
|
+
if ($error.length === 0) {
|
25
|
+
$error = $(`<span class="${search.replace(/\./g, " ")}"></span>`).appendTo($closest);
|
26
|
+
}
|
27
|
+
return $error;
|
28
|
+
};
|
29
|
+
|
30
|
+
const clearErrors = ($field, prop) => {
|
31
|
+
findError($field, prop).remove();
|
32
|
+
};
|
33
|
+
|
34
|
+
const addError = ($field, options, prop) => {
|
35
|
+
// console.log("addError", $field, options, prop)
|
36
|
+
let $error = findError($field, prop);
|
37
|
+
$error.addClass("is-visible");
|
38
|
+
if (options && options[prop]) {
|
39
|
+
$error.html(options[prop].error);
|
40
|
+
}
|
41
|
+
else {$error.html(Decidim.ProposalRules.genericError);}
|
42
|
+
};
|
43
|
+
|
44
|
+
const validate = ($field, value, options) => {
|
45
|
+
// console.log("validate", $field, value, options);
|
46
|
+
|
47
|
+
// validate caps if needed
|
48
|
+
const minLen = $field.attr("minlength");
|
49
|
+
|
50
|
+
if (options && options.caps.enabled) {
|
51
|
+
if (value.charAt(0) !== value.charAt(0).toUpperCase()) {
|
52
|
+
addError($field, options, "caps");
|
53
|
+
return false;
|
54
|
+
}
|
55
|
+
}
|
56
|
+
if (minLen && value.length < minLen) {
|
57
|
+
addError($field);
|
58
|
+
return false;
|
59
|
+
}
|
60
|
+
return true;
|
61
|
+
}
|
62
|
+
|
63
|
+
if ($title.length > 0) {
|
64
|
+
$title.change(() => {
|
65
|
+
clearErrors($title, "caps");
|
66
|
+
});
|
67
|
+
if (quill) {
|
68
|
+
// on change quill
|
69
|
+
quill.on("text-change", () => {
|
70
|
+
clearErrors($body, "caps");
|
71
|
+
clearErrors($body);
|
72
|
+
});
|
73
|
+
} else {
|
74
|
+
$body.change(() => {
|
75
|
+
clearErrors($body, "caps");
|
76
|
+
});
|
77
|
+
}
|
78
|
+
$form.on("submit", (ev) => {
|
79
|
+
if (!validate($title, $title.val(), Decidim.ProposalRules.title)) {
|
80
|
+
ev.preventDefault();
|
81
|
+
}
|
82
|
+
if (!validate($body, quill
|
83
|
+
? quill.getText()
|
84
|
+
: $body.val(), Decidim.ProposalRules.body)) {
|
85
|
+
ev.preventDefault();
|
86
|
+
}
|
87
|
+
});
|
88
|
+
}
|
89
|
+
});
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import attachGeocoding from "src/decidim/geocoding/attach_input"
|
2
|
+
|
3
|
+
$(() => {
|
4
|
+
const $checkbox = $("input:checkbox[name$='[has_no_address]']");
|
5
|
+
const $hasAdressInput = $("input[name$='[has_address]']");
|
6
|
+
const $addressInput = $("#address_input");
|
7
|
+
const $addressInputField = $("input[name='proposal[address]']");
|
8
|
+
const $map = $("#address_map");
|
9
|
+
let latFieldName = "proposal[latitude]";
|
10
|
+
let longFieldName = "proposal[longitude]";
|
11
|
+
const $labelInput = $("label[for='proposal_address']");
|
12
|
+
const $buttonLocation = $(".user-device-location button");
|
13
|
+
|
14
|
+
$map.hide();
|
15
|
+
|
16
|
+
// Handle no address checkbox in reverse, mandatory by default instead of default decidim
|
17
|
+
if ($checkbox.length > 0) {
|
18
|
+
const toggleInput = () => {
|
19
|
+
$hasAdressInput.val($checkbox[0].checked
|
20
|
+
? 0
|
21
|
+
: 1);
|
22
|
+
|
23
|
+
if ($checkbox[0].checked) {
|
24
|
+
const $formError = $labelInput.find('span.form-error[style="display: block;"]');
|
25
|
+
|
26
|
+
$map.hide();
|
27
|
+
$addressInputField.prop("disabled", true);
|
28
|
+
$addressInputField.removeClass("is-invalid-input");
|
29
|
+
$labelInput.removeClass("is-invalid-label");
|
30
|
+
$buttonLocation.prop("disabled", true);
|
31
|
+
$buttonLocation.removeClass("loading-spinner");
|
32
|
+
$formError.attr("style", "display:none;");
|
33
|
+
|
34
|
+
} else {
|
35
|
+
if ($(`input[name='${latFieldName}']`).val()) {
|
36
|
+
$map.show();
|
37
|
+
}
|
38
|
+
$addressInputField.prop("disabled", false);
|
39
|
+
$buttonLocation.prop("disabled", false);
|
40
|
+
}
|
41
|
+
}
|
42
|
+
toggleInput();
|
43
|
+
$checkbox.on("change", toggleInput);
|
44
|
+
}
|
45
|
+
|
46
|
+
if ($addressInput.length > 0) {
|
47
|
+
const ctrl = $("[data-decidim-map]").data("map-controller");
|
48
|
+
ctrl.setEventHandler("coordinates", (ev) => {
|
49
|
+
$(`input[name='${latFieldName}']`).val(ev.lat);
|
50
|
+
$(`input[name='${longFieldName}']`).val(ev.lng);
|
51
|
+
});
|
52
|
+
|
53
|
+
attachGeocoding($addressInputField, null, (coordinates) => {
|
54
|
+
$map.show();
|
55
|
+
// Remove previous marker when user updates address in address field
|
56
|
+
ctrl.removeMarker();
|
57
|
+
ctrl.addMarker({
|
58
|
+
latitude: coordinates[0],
|
59
|
+
longitude: coordinates[1],
|
60
|
+
address: $addressInputField.val()
|
61
|
+
});
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
});
|
@@ -0,0 +1,54 @@
|
|
1
|
+
$(() => {
|
2
|
+
const info = ($target, msg) => {
|
3
|
+
const $label = $target.closest("label")
|
4
|
+
$label.find(".form-error").remove();
|
5
|
+
if (msg) {
|
6
|
+
$('<span class="form-error"/>').text(msg).appendTo($label).show();
|
7
|
+
}
|
8
|
+
};
|
9
|
+
|
10
|
+
const setLocating = ($button, enable) => {
|
11
|
+
if (enable) {
|
12
|
+
$button.addClass("loading-spinner");
|
13
|
+
$button.attr("disabled", true);
|
14
|
+
} else {
|
15
|
+
$button.removeClass("loading-spinner");
|
16
|
+
$button.attr("disabled", false);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
$(".user-device-location button").on("click", (e) => {
|
21
|
+
const $this = $(e.target);
|
22
|
+
if ($this.is(":disabled")) {
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
|
26
|
+
const $input = $(`#${e.target.dataset.input}`);
|
27
|
+
const errorNoLocation = e.target.dataset.errorNoLocation;
|
28
|
+
const errorUnsupported = e.target.dataset.errorUnsupported;
|
29
|
+
const url = e.target.dataset.url;
|
30
|
+
|
31
|
+
if (navigator.geolocation) {
|
32
|
+
setLocating($this, true);
|
33
|
+
navigator.geolocation.getCurrentPosition((position) => {
|
34
|
+
const coordinates = [position.coords.latitude, position.coords.longitude];
|
35
|
+
// reverse geolocation
|
36
|
+
$.post(url, { latitude: coordinates[0], longitude: coordinates[1] }, (data) => {
|
37
|
+
$input.val(data.address)
|
38
|
+
})
|
39
|
+
setLocating($this, false);
|
40
|
+
$input.trigger(
|
41
|
+
"geocoder-suggest-coordinates.decidim",
|
42
|
+
[coordinates]
|
43
|
+
);
|
44
|
+
}, (evt) => {
|
45
|
+
info($input, `${errorNoLocation} ${evt.message}`);
|
46
|
+
$this.attr("disabled", false);
|
47
|
+
}, {
|
48
|
+
enableHighAccuracy: true
|
49
|
+
});
|
50
|
+
} else {
|
51
|
+
info($input, errorUnsupported);
|
52
|
+
}
|
53
|
+
});
|
54
|
+
});
|
@@ -0,0 +1,49 @@
|
|
1
|
+
$(() => {
|
2
|
+
$('input[type="file"]').each((_i, el) => {
|
3
|
+
const $input = $(el);
|
4
|
+
const $inputField = $input.closest(".row.column");
|
5
|
+
const $button = $inputField.find("button:first");
|
6
|
+
const $checkbox = $inputField.find("input:checkbox[name$='[has_no_image]']");
|
7
|
+
const $formError = $inputField.find("span.form-error")
|
8
|
+
const $labelInput = $("label[for='proposal_add_photos']")
|
9
|
+
|
10
|
+
const removeErrors = () => {
|
11
|
+
$input.removeClass("is-invalid-input");
|
12
|
+
$formError.removeClass("is-visible");
|
13
|
+
$labelInput.removeClass("is-invalid-label");
|
14
|
+
};
|
15
|
+
|
16
|
+
const toggleInput = () => {
|
17
|
+
if ($checkbox[0].checked) {
|
18
|
+
removeErrors();
|
19
|
+
$input.prop("disabled", true);
|
20
|
+
$button.prop("disabled", true);
|
21
|
+
} else {
|
22
|
+
$input.prop("disabled", false);
|
23
|
+
$button.prop("disabled", false);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
$input.attr("accept", "image/*");
|
28
|
+
|
29
|
+
$button.on("click", () => {
|
30
|
+
console.log("click button")
|
31
|
+
$input.attr("capture", "camera");
|
32
|
+
$input.click();
|
33
|
+
$input.removeAttr("capture", "camera");
|
34
|
+
});
|
35
|
+
|
36
|
+
$input.on("click", () => {
|
37
|
+
console.log("click", $input);
|
38
|
+
$input.one("blur", () => {
|
39
|
+
console.log("blur", $input);
|
40
|
+
removeErrors();
|
41
|
+
});
|
42
|
+
});
|
43
|
+
|
44
|
+
if ($checkbox.length > 0) {
|
45
|
+
$checkbox.on("change", toggleInput);
|
46
|
+
toggleInput();
|
47
|
+
}
|
48
|
+
});
|
49
|
+
});
|
@@ -0,0 +1,34 @@
|
|
1
|
+
.input-group.has-tribute {
|
2
|
+
position: relative;
|
3
|
+
|
4
|
+
.tribute-container {
|
5
|
+
margin-top: 2.3rem;
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
.user-device-location {
|
10
|
+
button {
|
11
|
+
max-height: 3rem;
|
12
|
+
|
13
|
+
&.loading-spinner {
|
14
|
+
position: relative;
|
15
|
+
margin: 0 !important;
|
16
|
+
|
17
|
+
&::before {
|
18
|
+
position: absolute;
|
19
|
+
top: 6px;
|
20
|
+
left: 12px;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
@media only screen and (max-width: 596px) {
|
26
|
+
display: block !important;
|
27
|
+
margin-top: 1rem;
|
28
|
+
margin-bottom: -.5rem;
|
29
|
+
|
30
|
+
button {
|
31
|
+
border-radius: 4px !important;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|