decidim-proposals 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_proposals_manifest.js +1 -0
  3. data/app/assets/images/decidim/gamification/badges/accepted_proposals.svg +1 -234
  4. data/app/assets/images/decidim/gamification/badges/proposal_votes.svg +1 -95
  5. data/app/assets/images/decidim/gamification/badges/proposals.svg +1 -229
  6. data/app/assets/images/decidim/proposals/icon.svg +1 -3
  7. data/app/assets/javascripts/decidim/proposals/admin/proposals_form.js.es6 +0 -5
  8. data/app/assets/javascripts/decidim/proposals/admin/proposals_picker.js.es6 +35 -0
  9. data/app/cells/decidim/proposals/collaborative_draft_link_to_proposal_cell.rb +1 -1
  10. data/app/cells/decidim/proposals/collaborative_draft_m/footer.erb +1 -1
  11. data/app/cells/decidim/proposals/collaborative_draft_m_cell.rb +1 -1
  12. data/app/cells/decidim/proposals/highlighted_proposals_for_component/show.erb +3 -3
  13. data/app/cells/decidim/proposals/highlighted_proposals_for_component_cell.rb +1 -1
  14. data/app/cells/decidim/proposals/irreversible_action_modal/show.erb +2 -2
  15. data/app/cells/decidim/proposals/irreversible_action_modal_cell.rb +1 -1
  16. data/app/cells/decidim/proposals/participatory_text_proposal/buttons.erb +1 -1
  17. data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +1 -1
  18. data/app/cells/decidim/proposals/proposal_m/footer.erb +4 -1
  19. data/app/cells/decidim/proposals/proposal_m_cell.rb +28 -8
  20. data/app/cells/decidim/proposals/proposal_tags/show.erb +8 -2
  21. data/app/cells/decidim/proposals/proposals_picker/proposals.erb +12 -0
  22. data/app/cells/decidim/proposals/proposals_picker/show.erb +14 -0
  23. data/app/cells/decidim/proposals/proposals_picker_cell.rb +72 -0
  24. data/app/commands/decidim/proposals/admin/create_proposal.rb +1 -1
  25. data/app/commands/decidim/proposals/admin/create_proposal_note.rb +15 -0
  26. data/app/commands/decidim/proposals/admin/update_proposal.rb +1 -1
  27. data/app/commands/decidim/proposals/create_collaborative_draft.rb +1 -1
  28. data/app/commands/decidim/proposals/create_proposal.rb +1 -1
  29. data/app/commands/decidim/proposals/gallery_methods.rb +2 -51
  30. data/app/commands/decidim/proposals/update_proposal.rb +1 -1
  31. data/app/controllers/concerns/decidim/proposals/admin/picker.rb +21 -0
  32. data/app/controllers/concerns/decidim/proposals/orderable.rb +1 -1
  33. data/app/controllers/decidim/proposals/proposals_controller.rb +4 -5
  34. data/app/controllers/decidim/proposals/versions_controller.rb +8 -18
  35. data/app/events/decidim/proposals/admin/proposal_note_created_event.rb +27 -0
  36. data/app/forms/decidim/proposals/admin/participatory_text_proposal_form.rb +13 -0
  37. data/app/forms/decidim/proposals/admin/preview_participatory_text_form.rb +2 -2
  38. data/app/forms/decidim/proposals/admin/proposal_base_form.rb +129 -0
  39. data/app/forms/decidim/proposals/admin/proposal_form.rb +2 -120
  40. data/app/forms/decidim/proposals/proposal_form.rb +4 -0
  41. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +5 -1
  42. data/app/helpers/decidim/proposals/admin/filterable_helper.rb +2 -2
  43. data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +2 -2
  44. data/app/helpers/decidim/proposals/admin/proposals_picker_helper.rb +30 -0
  45. data/app/helpers/decidim/proposals/application_helper.rb +6 -6
  46. data/app/helpers/decidim/proposals/control_version_helper.rb +1 -37
  47. data/app/helpers/decidim/proposals/proposal_endorsements_helper.rb +0 -145
  48. data/app/helpers/decidim/proposals/proposal_votes_helper.rb +2 -2
  49. data/app/helpers/decidim/proposals/proposal_wizard_helper.rb +24 -7
  50. data/app/helpers/decidim/proposals/proposals_helper.rb +6 -0
  51. data/app/models/decidim/proposals/proposal.rb +4 -14
  52. data/app/permissions/decidim/proposals/permissions.rb +1 -22
  53. data/app/presenters/decidim/proposals/proposal_presenter.rb +14 -2
  54. data/app/queries/decidim/proposals/metrics/accepted_proposals_metric_manage.rb +1 -2
  55. data/app/queries/decidim/proposals/metrics/endorsements_metric_manage.rb +15 -12
  56. data/app/queries/decidim/proposals/metrics/proposal_participants_metric_measure.rb +5 -4
  57. data/app/queries/decidim/proposals/metrics/proposals_metric_manage.rb +2 -8
  58. data/app/queries/decidim/proposals/metrics/votes_metric_manage.rb +3 -9
  59. data/app/services/decidim/proposals/diff_renderer.rb +2 -0
  60. data/app/services/decidim/proposals/proposal_builder.rb +1 -1
  61. data/app/services/decidim/proposals/proposal_search.rb +2 -2
  62. data/app/types/decidim/proposals/proposal_input_sort.rb +1 -7
  63. data/app/types/decidim/proposals/proposal_type.rb +1 -11
  64. data/app/types/decidim/proposals/proposals_type.rb +10 -0
  65. data/app/validators/proposal_length_validator.rb +38 -0
  66. data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +9 -1
  67. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +2 -2
  68. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +3 -23
  69. data/app/views/decidim/proposals/admin/proposals/index.html.erb +1 -1
  70. data/app/views/decidim/proposals/admin/proposals/show.html.erb +1 -1
  71. data/app/views/decidim/proposals/collaborative_drafts/_edit_form_fields.html.erb +6 -4
  72. data/app/views/decidim/proposals/collaborative_drafts/_filters.html.erb +9 -7
  73. data/app/views/decidim/proposals/collaborative_drafts/_new_collaborative_draft_button.html.erb +4 -4
  74. data/app/views/decidim/proposals/collaborative_drafts/_reject_request_access_form.html.erb +1 -1
  75. data/app/views/decidim/proposals/collaborative_drafts/_wizard_aside.html.erb +4 -2
  76. data/app/views/decidim/proposals/collaborative_drafts/compare.html.erb +2 -0
  77. data/app/views/decidim/proposals/collaborative_drafts/complete.html.erb +2 -0
  78. data/app/views/decidim/proposals/collaborative_drafts/edit.html.erb +3 -1
  79. data/app/views/decidim/proposals/collaborative_drafts/index.html.erb +4 -2
  80. data/app/views/decidim/proposals/collaborative_drafts/new.html.erb +4 -0
  81. data/app/views/decidim/proposals/collaborative_drafts/show.html.erb +29 -30
  82. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +5 -3
  83. data/app/views/decidim/proposals/proposals/_endorsements_card_row.html.erb +0 -16
  84. data/app/views/decidim/proposals/proposals/_filters.html.erb +12 -10
  85. data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +1 -11
  86. data/app/views/decidim/proposals/proposals/_proposal_similar.html.erb +2 -2
  87. data/app/views/decidim/proposals/proposals/_proposals.html.erb +14 -0
  88. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +13 -6
  89. data/app/views/decidim/proposals/proposals/_wizard_aside.html.erb +4 -2
  90. data/app/views/decidim/proposals/proposals/_wizard_header.html.erb +4 -3
  91. data/app/views/decidim/proposals/proposals/compare.html.erb +2 -0
  92. data/app/views/decidim/proposals/proposals/complete.html.erb +2 -0
  93. data/app/views/decidim/proposals/proposals/edit.html.erb +3 -1
  94. data/app/views/decidim/proposals/proposals/edit_draft.html.erb +2 -0
  95. data/app/views/decidim/proposals/proposals/index.html.erb +5 -10
  96. data/app/views/decidim/proposals/proposals/new.html.erb +5 -1
  97. data/app/views/decidim/proposals/proposals/participatory_texts/_index.html.erb +1 -1
  98. data/app/views/decidim/proposals/proposals/participatory_texts/_proposal_vote_button.html.erb +10 -3
  99. data/app/views/decidim/proposals/proposals/participatory_texts/_view_index.html.erb +1 -1
  100. data/app/views/decidim/proposals/proposals/preview.html.erb +7 -8
  101. data/app/views/decidim/proposals/proposals/show.html.erb +52 -34
  102. data/app/views/decidim/proposals/versions/index.html.erb +14 -32
  103. data/app/views/decidim/proposals/versions/show.html.erb +16 -34
  104. data/config/locales/ar.yml +8 -64
  105. data/config/locales/bg-BG.yml +237 -0
  106. data/config/locales/ca.yml +68 -61
  107. data/config/locales/cs.yml +78 -68
  108. data/config/locales/da-DK.yml +1 -0
  109. data/config/locales/de.yml +142 -58
  110. data/config/locales/el.yml +875 -0
  111. data/config/locales/en.yml +74 -67
  112. data/config/locales/es-MX.yml +68 -61
  113. data/config/locales/es-PY.yml +68 -61
  114. data/config/locales/es.yml +68 -61
  115. data/config/locales/et-EE.yml +1 -0
  116. data/config/locales/eu.yml +5 -43
  117. data/config/locales/fi-plain.yml +68 -61
  118. data/config/locales/fi.yml +109 -102
  119. data/config/locales/fr-CA.yml +876 -0
  120. data/config/locales/fr.yml +128 -60
  121. data/config/locales/ga-IE.yml +1 -0
  122. data/config/locales/gl.yml +5 -43
  123. data/config/locales/hr-HR.yml +1 -0
  124. data/config/locales/hu.yml +38 -61
  125. data/config/locales/id-ID.yml +5 -42
  126. data/config/locales/is-IS.yml +1 -27
  127. data/config/locales/it.yml +136 -76
  128. data/config/locales/ja-JP.yml +886 -0
  129. data/config/locales/lt-LT.yml +1 -0
  130. data/config/locales/lv-LV.yml +858 -0
  131. data/config/locales/mt-MT.yml +1 -0
  132. data/config/locales/nl.yml +114 -59
  133. data/config/locales/no.yml +11 -64
  134. data/config/locales/pl.yml +170 -60
  135. data/config/locales/pt-BR.yml +6 -47
  136. data/config/locales/pt.yml +419 -331
  137. data/config/locales/ro-RO.yml +840 -0
  138. data/config/locales/ru.yml +1 -40
  139. data/config/locales/sk-SK.yml +896 -0
  140. data/config/locales/sk.yml +869 -0
  141. data/config/locales/sl.yml +26 -0
  142. data/config/locales/sr-CS.yml +126 -0
  143. data/config/locales/sv.yml +228 -156
  144. data/config/locales/tr-TR.yml +5 -43
  145. data/config/locales/uk.yml +1 -40
  146. data/db/migrate/20181003074440_fix_user_groups_ids_in_proposals_endorsements.rb +4 -0
  147. data/db/migrate/20191206154128_add_endorsements_counter_cache_to_proposals.rb +7 -0
  148. data/db/migrate/20200120215928_move_proposal_endorsements_to_core_endorsements.rb +52 -0
  149. data/db/migrate/20200730131631_move_proposal_endorsed_event_notifications_to_resource_endorsed_event.rb +20 -0
  150. data/lib/decidim/proposals/component.rb +8 -4
  151. data/lib/decidim/proposals/engine.rb +1 -5
  152. data/lib/decidim/proposals/test/capybara_proposals_picker.rb +49 -0
  153. data/lib/decidim/proposals/test/factories.rb +3 -12
  154. data/lib/decidim/proposals/version.rb +1 -1
  155. metadata +55 -34
  156. data/app/assets/javascripts/decidim/proposals/identity_selector_dialog.js.es6 +0 -56
  157. data/app/cells/decidim/proposals/endorsers_list/show.erb +0 -17
  158. data/app/cells/decidim/proposals/endorsers_list_cell.rb +0 -31
  159. data/app/commands/decidim/proposals/attachment_methods.rb +0 -43
  160. data/app/commands/decidim/proposals/endorse_proposal.rb +0 -59
  161. data/app/commands/decidim/proposals/unendorse_proposal.rb +0 -40
  162. data/app/controllers/decidim/proposals/proposal_endorsements_controller.rb +0 -60
  163. data/app/models/decidim/proposals/proposal_endorsement.rb +0 -37
  164. data/app/views/decidim/proposals/proposal_endorsements/_identity.html.erb +0 -9
  165. data/app/views/decidim/proposals/proposal_endorsements/identities.html.erb +0 -12
  166. data/app/views/decidim/proposals/proposal_endorsements/update_buttons_and_counters.js.erb +0 -20
  167. data/app/views/decidim/proposals/proposals/_endorsement_button.html.erb +0 -11
  168. data/app/views/decidim/proposals/proposals/_endorsement_identities_cabin.html.erb +0 -13
  169. data/app/views/decidim/proposals/versions/_version.html.erb +0 -20
@@ -14,7 +14,7 @@ module Decidim
14
14
  @author ||= if official?
15
15
  Decidim::Proposals::OfficialAuthorPresenter.new
16
16
  else
17
- coauthorship = coauthorships.first
17
+ coauthorship = coauthorships.includes(:author, :user_group).first
18
18
  coauthorship.user_group&.presenter || coauthorship.author.presenter
19
19
  end
20
20
  end
@@ -45,9 +45,17 @@ module Decidim
45
45
  renderer.render(links: links, extras: extras).html_safe
46
46
  end
47
47
 
48
+ def id_and_title(links: false, extras: true, html_escape: false)
49
+ "##{proposal.id} - #{title(links: links, extras: extras, html_escape: html_escape)}"
50
+ end
51
+
48
52
  def body(links: false, extras: true, strip_tags: false)
49
53
  text = proposal.body
50
- text = strip_tags(text) if strip_tags
54
+
55
+ if strip_tags
56
+ text = text.gsub(%r{<\/p>}, "\n\n")
57
+ text = strip_tags(text)
58
+ end
51
59
 
52
60
  renderer = Decidim::ContentRenderers::HashtagRenderer.new(text)
53
61
  text = renderer.render(links: links, extras: extras).html_safe
@@ -81,6 +89,10 @@ module Decidim
81
89
  end
82
90
 
83
91
  delegate :count, to: :versions, prefix: true
92
+
93
+ def resource_manifest
94
+ proposal.class.resource_manifest
95
+ end
84
96
  end
85
97
  end
86
98
  end
@@ -16,8 +16,7 @@ module Decidim
16
16
  spaces = Decidim.participatory_space_manifests.flat_map do |manifest|
17
17
  manifest.participatory_spaces.call(@organization).public_spaces
18
18
  end
19
- components = Decidim::Component.where(participatory_space: spaces).published
20
- @query = Decidim::Proposals::Proposal.where(component: components).joins(:component)
19
+ @query = Decidim::Proposals::Proposal.where(component: visible_component_ids_from_spaces(spaces)).joins(:component)
21
20
  .left_outer_joins(:category)
22
21
  @query = @query.where("decidim_proposals_proposals.created_at <= ?", end_time).accepted
23
22
  @query = @query.group("decidim_categorizations.id", :participatory_space_type, :participatory_space_id)
@@ -9,9 +9,6 @@ module Decidim
9
9
  end
10
10
 
11
11
  def save
12
- return @registry if @registry
13
-
14
- @registry = []
15
12
  cumulative.each do |key, cumulative_value|
16
13
  next if cumulative_value.zero?
17
14
 
@@ -22,10 +19,8 @@ module Decidim
22
19
  participatory_space_type: space_type, participatory_space_id: space_id,
23
20
  related_object_type: "Decidim::Proposals::Proposal", related_object_id: proposal_id)
24
21
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
25
- @registry << record
22
+ record.save!
26
23
  end
27
- @registry.each(&:save!)
28
- @registry
29
24
  end
30
25
 
31
26
  private
@@ -35,19 +30,27 @@ module Decidim
35
30
 
36
31
  components = Decidim::Component.where(participatory_space: retrieve_participatory_spaces).published
37
32
  proposals = Decidim::Proposals::Proposal.where(component: components).except_withdrawn
38
- @query = Decidim::Proposals::ProposalEndorsement.joins(proposal: :component)
39
- .left_outer_joins(proposal: :category)
40
- .where(proposal: proposals)
41
- @query = @query.where("decidim_proposals_proposal_endorsements.created_at <= ?", end_time)
33
+ join_components = "INNER JOIN decidim_components ON decidim_components.manifest_name = 'proposals' AND proposals.decidim_component_id = decidim_components.id"
34
+ join_categories = <<~EOJOINCATS
35
+ LEFT OUTER JOIN decidim_categorizations
36
+ ON (proposals.id = decidim_categorizations.categorizable_id
37
+ AND decidim_categorizations.categorizable_type = 'Decidim::Proposals::Proposal')
38
+ EOJOINCATS
39
+ @query = Decidim::Endorsement.joins("INNER JOIN decidim_proposals_proposals proposals ON resource_id = proposals.id")
40
+ .joins(join_components)
41
+ .joins(join_categories)
42
+ .where(resource_id: proposals.pluck(:id))
43
+ .where(resource_type: Decidim::Proposals::Proposal.name)
44
+ @query = @query.where("decidim_endorsements.created_at <= ?", end_time)
42
45
  @query = @query.group("decidim_categorizations.id",
43
46
  :participatory_space_type,
44
47
  :participatory_space_id,
45
- :decidim_proposal_id)
48
+ :resource_id)
46
49
  @query
47
50
  end
48
51
 
49
52
  def quantity
50
- @quantity ||= query.where("decidim_proposals_proposal_endorsements.created_at >= ?", start_time).count
53
+ @quantity ||= query.where("decidim_endorsements.created_at >= ?", start_time).count
51
54
  end
52
55
  end
53
56
  end
@@ -59,11 +59,12 @@ module Decidim
59
59
  end
60
60
 
61
61
  def retrieve_endorsements(from_start = false)
62
- @endorsements ||= Decidim::Proposals::ProposalEndorsement.joins(:proposal).where(proposal: retrieve_proposals)
63
- .where("decidim_proposals_proposal_endorsements.created_at <= ?", end_time)
64
- .where(decidim_author_type: "Decidim::UserBaseEntity")
62
+ @endorsements ||= Decidim::Endorsement.joins("INNER JOIN decidim_proposals_proposals proposals ON resource_id = proposals.id")
63
+ .where(resource: retrieve_proposals)
64
+ .where("decidim_endorsements.created_at <= ?", end_time)
65
+ .where(decidim_author_type: "Decidim::UserBaseEntity")
65
66
 
66
- return @endorsements.where("decidim_proposals_proposal_endorsements.created_at >= ?", start_time) if from_start
67
+ return @endorsements.where("decidim_endorsements.created_at >= ?", start_time) if from_start
67
68
 
68
69
  @endorsements
69
70
  end
@@ -9,9 +9,6 @@ module Decidim
9
9
  end
10
10
 
11
11
  def save
12
- return @registry if @registry
13
-
14
- @registry = []
15
12
  cumulative.each do |key, cumulative_value|
16
13
  next if cumulative_value.zero?
17
14
 
@@ -21,10 +18,8 @@ module Decidim
21
18
  organization: @organization, decidim_category_id: category_id,
22
19
  participatory_space_type: space_type, participatory_space_id: space_id)
23
20
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
24
- @registry << record
21
+ record.save!
25
22
  end
26
- @registry.each(&:save!)
27
- @registry
28
23
  end
29
24
 
30
25
  private
@@ -35,8 +30,7 @@ module Decidim
35
30
  spaces = Decidim.participatory_space_manifests.flat_map do |manifest|
36
31
  manifest.participatory_spaces.call(@organization)
37
32
  end
38
- components = Decidim::Component.where(participatory_space: spaces).published
39
- @query = Decidim::Proposals::Proposal.where(component: components).joins(:component)
33
+ @query = Decidim::Proposals::Proposal.where(component: visible_component_ids_from_spaces(spaces)).joins(:component)
40
34
  .left_outer_joins(:category)
41
35
  @query = @query.where("decidim_proposals_proposals.published_at <= ?", end_time).except_withdrawn.not_hidden
42
36
  @query = @query.group("decidim_categorizations.decidim_category_id",
@@ -9,9 +9,6 @@ module Decidim
9
9
  end
10
10
 
11
11
  def save
12
- return @registry if @registry
13
-
14
- @registry = []
15
12
  cumulative.each do |key, cumulative_value|
16
13
  next if cumulative_value.zero?
17
14
 
@@ -22,10 +19,8 @@ module Decidim
22
19
  participatory_space_type: space_type, participatory_space_id: space_id,
23
20
  related_object_type: "Decidim::Proposals::Proposal", related_object_id: proposal_id)
24
21
  record.assign_attributes(cumulative: cumulative_value, quantity: quantity_value)
25
- @registry << record
22
+ record.save!
26
23
  end
27
- @registry.each(&:save!)
28
- @registry
29
24
  end
30
25
 
31
26
  private
@@ -36,11 +31,10 @@ module Decidim
36
31
  spaces = Decidim.participatory_space_manifests.flat_map do |manifest|
37
32
  manifest.participatory_spaces.call(@organization).public_spaces
38
33
  end
39
- components = Decidim::Component.where(participatory_space: spaces).published
40
- proposals = Decidim::Proposals::Proposal.where(component: components).except_withdrawn.not_hidden
34
+ proposal_ids = Decidim::Proposals::Proposal.where(component: visible_component_ids_from_spaces(spaces.pluck(:id))).except_withdrawn.not_hidden.pluck(:id)
41
35
  @query = Decidim::Proposals::ProposalVote.joins(proposal: :component)
42
36
  .left_outer_joins(proposal: :category)
43
- .where(proposal: proposals)
37
+ .where(proposal: proposal_ids)
44
38
  @query = @query.where("decidim_proposals_proposal_votes.created_at <= ?", end_time)
45
39
  @query = @query.group("decidim_categorizations.id",
46
40
  :participatory_space_type,
@@ -21,6 +21,8 @@ module Decidim
21
21
 
22
22
  # Parses the values before parsing the changeset.
23
23
  def parse_changeset(attribute, values, type, diff)
24
+ return parse_scope_changeset(attribute, values, type, diff) if type == :scope
25
+
24
26
  values = parse_values(attribute, values)
25
27
 
26
28
  diff.update(
@@ -68,7 +68,7 @@ module Decidim
68
68
  "decidim_component_id",
69
69
  "reference",
70
70
  "proposal_votes_count",
71
- "proposal_endorsements_count",
71
+ "endorsements_count",
72
72
  "proposal_notes_count"
73
73
  ).merge(
74
74
  "category" => original_proposal.category
@@ -20,8 +20,8 @@ module Decidim
20
20
  # Handle the search_text filter
21
21
  def search_search_text
22
22
  query
23
- .where("title ILIKE ?", "%#{search_text}%")
24
- .or(query.where("body ILIKE ?", "%#{search_text}%"))
23
+ .where("decidim_proposals_proposals.title ILIKE ?", "%#{search_text}%")
24
+ .or(query.where("decidim_proposals_proposals.body ILIKE ?", "%#{search_text}%"))
25
25
  end
26
26
 
27
27
  # Handle the origin filter
@@ -4,18 +4,12 @@ module Decidim
4
4
  module Proposals
5
5
  class ProposalInputSort < Decidim::Core::BaseInputSort
6
6
  include Decidim::Core::HasPublishableInputSort
7
+ include Decidim::Core::HasEndorsableInputSort
7
8
 
8
9
  graphql_name "ProposalSort"
9
10
  description "A type used for sorting proposals"
10
11
 
11
12
  argument :id, String, "Sort by ID, valid values are ASC or DESC", required: false
12
- argument :endorsement_count,
13
- type: String,
14
- description: "Sort by number of endorsements, valid values are ASC or DESC",
15
- required: false,
16
- prepare: ->(value, _ctx) do
17
- { proposal_endorsements_count: value }
18
- end
19
13
  argument :vote_count,
20
14
  type: String,
21
15
  description: "Sort by number of votes, valid values are ASC or DESC. Will be ignored if votes are hidden",
@@ -16,6 +16,7 @@ module Decidim
16
16
  -> { Decidim::Core::AmendableInterface },
17
17
  -> { Decidim::Core::AmendableEntityInterface },
18
18
  -> { Decidim::Core::TraceableInterface },
19
+ -> { Decidim::Core::EndorsableInterface },
19
20
  -> { Decidim::Core::TimestampsInterface }
20
21
  ]
21
22
 
@@ -57,17 +58,6 @@ module Decidim
57
58
  }
58
59
  end
59
60
 
60
- field :endorsements, !types[Decidim::Core::AuthorInterface], "The endorsements of this proposal." do
61
- resolve ->(proposal, _, _) {
62
- proposal.endorsements.map(&:normalized_author)
63
- }
64
- end
65
-
66
- field :endorsementsCount, types.Int do
67
- description "The total amount of endorsements the proposal has received"
68
- property :proposal_endorsements_count
69
- end
70
-
71
61
  field :voteCount, types.Int do
72
62
  description "The total amount of votes the proposal has received"
73
63
  resolve ->(proposal, _args, _ctx) {
@@ -22,10 +22,20 @@ module Decidim
22
22
  class ProposalListHelper < Decidim::Core::ComponentListBase
23
23
  argument :order, ProposalInputSort, "Provides several methods to order the results"
24
24
  argument :filter, ProposalInputFilter, "Provides several methods to filter the results"
25
+
26
+ # only querying published posts
27
+ def query_scope
28
+ super.published
29
+ end
25
30
  end
26
31
 
27
32
  class ProposalFinderHelper < Decidim::Core::ComponentFinderBase
28
33
  argument :id, !types.ID, "The ID of the proposal"
34
+
35
+ # only querying published posts
36
+ def query_scope
37
+ super.published
38
+ end
29
39
  end
30
40
  end
31
41
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This validator takes care of ensuring the validated attributes are long enough
4
+ # and not too long. The difference to the Rails length validator is that this
5
+ # allows the minimum and maximum values to be lambdas allowing us to fetch the
6
+ # maximum length dynamically for each proposals component.
7
+ class ProposalLengthValidator < ActiveModel::EachValidator
8
+ def validate_each(record, attribute, value)
9
+ return if value.blank?
10
+
11
+ validate_min_length(record, attribute, value)
12
+ validate_max_length(record, attribute, value)
13
+ end
14
+
15
+ private
16
+
17
+ def validate_min_length(record, attribute, value)
18
+ min = options[:minimum] || nil
19
+ min = min.call(record) if min.respond_to?(:call)
20
+ if min && min.positive? && value.length < min
21
+ record.errors.add(
22
+ attribute,
23
+ options[:message] || :too_short
24
+ )
25
+ end
26
+ end
27
+
28
+ def validate_max_length(record, attribute, value)
29
+ max = options[:maximum] || nil
30
+ max = max.call(record) if max.respond_to?(:call)
31
+ if max && max.positive? && value.length > max
32
+ record.errors.add(
33
+ attribute,
34
+ options[:message] || :too_long
35
+ )
36
+ end
37
+ end
38
+ end
@@ -16,7 +16,7 @@
16
16
  <%= form.fields_for(:proposals) do |prop_form| %>
17
17
  <% proposal= @drafts[prop_form.index] %>
18
18
  <li class="accordion-item <%= proposal.article? ? "is-active" : nil %>" data-accordion-item>
19
- <a href="#" class="accordion-title flex--sbc"><%= preview_participatory_text_section_title(proposal) %><span class="mr-m"><%= icon "menu", class: "icon--small" %></span></a>
19
+ <a href="#" class="accordion-title flex--sbc"><%= preview_participatory_text_section_title(proposal) %><span class="mr-m"><%= icon "menu", class: "icon--small", role: "img", "aria-hidden": true %></span></a>
20
20
  <div class="accordion-content" data-tab-content>
21
21
  <%= render "article-preview", { form: prop_form, proposal: proposal } %>
22
22
  </div>
@@ -35,6 +35,14 @@
35
35
  <% end -%>
36
36
  <script>
37
37
  $(window).on("load", function() {
38
+ // Not all browsers submit the buttons as form data.
39
+ $('button[name="save_draft"]').on("click", function(ev) {
40
+ ev.preventDefault();
41
+
42
+ var $form = $(this).parents("form");
43
+ $form.append('<input type="hidden" name="save_draft" value="true" />');
44
+ $form.submit();
45
+ });
38
46
  $( "#participatory-text" ).on( "sortupdate",
39
47
  function( event, ui ) {
40
48
  $('#participatory-text li').each(function(idx, li) {
@@ -9,7 +9,7 @@
9
9
  <% proposal.notes.each do |note| %>
10
10
  <div class="card">
11
11
  <div class="card-divider">
12
- <article class="comment">
12
+ <div class="comment">
13
13
  <div class="comment__header">
14
14
  <div class="author-data">
15
15
  <div class="author-data__main">
@@ -23,7 +23,7 @@
23
23
  <div class="comment__content">
24
24
  <%= simple_format note.body %>
25
25
  </div>
26
- </article>
26
+ </div>
27
27
  </div>
28
28
  </div>
29
29
  <% end %>
@@ -5,7 +5,7 @@
5
5
 
6
6
  <div class="card-section">
7
7
  <div class="row column hashtags__container">
8
- <%= form.text_field :title, class: "js-hashtags", hashtaggable: true, value: form_presenter.title(extras: false).strip %>
8
+ <%= form.text_field :title, class: "js-hashtags", value: form_presenter.title(extras: false).strip %>
9
9
  </div>
10
10
 
11
11
  <div class="row column hashtags__container">
@@ -59,7 +59,7 @@
59
59
 
60
60
  <% if @form.categories&.any? %>
61
61
  <div class="row column">
62
- <%= form.categories_select :category_id, @form.categories, prompt: t(".select_a_category") %>
62
+ <%= form.categories_select :category_id, @form.categories, include_blank: t(".select_a_category") %>
63
63
  </div>
64
64
  <% end %>
65
65
 
@@ -70,27 +70,7 @@
70
70
  <% end %>
71
71
 
72
72
  <% if component_settings.attachments_allowed? %>
73
- <div class="row column gallery__container">
74
- <fieldset>
75
- <legend><%= t(".gallery_legend") %></legend>
76
-
77
- <% if @form.photos.any? %>
78
- <% @form.photos.each do |photo| %>
79
- <div class="callout gallery__item" data-closable>
80
- <%= image_tag photo.thumbnail_url, class: "thumbnail", alt: photo.file.file.filename %>
81
- <%= form.hidden_field :photos, multiple: true, value: photo.id, id: "photo-#{photo.id}" %>
82
- <button class="close-button" aria-label="Close" type="button" data-close>
83
- <span aria-hidden="true">&times;</span>
84
- </button>
85
- </div>
86
- <% end %>
87
- <% end %>
88
-
89
- <div class="row column">
90
- <%= form.file_field :add_photos, multiple: true, label: t(".add_images") %>
91
- </div>
92
- </fieldset>
93
- </div>
73
+ <%= render partial: "decidim/admin/shared/gallery", locals: { form: form } %>
94
74
  <% end %>
95
75
 
96
76
  <% if component_settings.attachments_allowed? %>
@@ -8,7 +8,7 @@
8
8
  <%= render partial: "bulk-actions" %>
9
9
  </h2>
10
10
  </div>
11
- <%= admin_filter_selector %>
11
+ <%= admin_filter_selector(:proposals) %>
12
12
  <div class="card-section">
13
13
  <div class="table-scroll">
14
14
  <table class="table-list">
@@ -51,7 +51,7 @@
51
51
  </div>
52
52
 
53
53
  <div class="row column">
54
- <strong><%= t ".endorsements_count" %>:</strong> <%= proposal.proposal_endorsements_count %>
54
+ <strong><%= t ".endorsements_count" %>:</strong> <%= proposal.endorsements_count %>
55
55
  </div>
56
56
 
57
57
  <div class="row column">
@@ -1,9 +1,11 @@
1
+ <%= form_required_explanation %>
2
+
1
3
  <div class="field hashtags__container">
2
- <%= form.text_field :title, class: "js-hashtags", hashtaggable: true, value: form_presenter.title %>
4
+ <%= form.text_field :title, class: "js-hashtags", value: form_presenter.title %>
3
5
  </div>
4
6
 
5
7
  <div class="field hashtags__container">
6
- <%= form.text_area :body, rows: 10, class: "js-hashtags", hashtaggable: true, value: form_presenter.body(extras: false).strip %>
8
+ <%= form.text_area :body, rows: 10, class: "js-hashtags", value: form_presenter.body(extras: false).strip %>
7
9
  </div>
8
10
 
9
11
  <% if @form.component_automatic_hashtags.any? %>
@@ -21,7 +23,7 @@
21
23
 
22
24
  <% if @form.component_suggested_hashtags.any? %>
23
25
  <div class="field">
24
- <%= form.label :suggested_hashtags %>
26
+ <%= form.label :suggested_hashtags, nil, for: nil %>
25
27
  <div class="checkboxes hashtags">
26
28
  <%= form.collection_check_boxes :suggested_hashtags, @form.component_suggested_hashtags.map {|hashtag| [hashtag.downcase, "##{hashtag}"]}, :first, :last do |option|
27
29
  option.label { option.check_box(checked: @form.suggested_hashtag_checked?(option.value)) + option.text }
@@ -42,7 +44,7 @@
42
44
 
43
45
  <% if @form.categories&.any? %>
44
46
  <div class="field">
45
- <%= form.categories_select :category_id, @form.categories, prompt: t("decidim.proposals.collaborative_drafts.edit.select_a_category") %>
47
+ <%= form.categories_select :category_id, @form.categories, include_blank: t("decidim.proposals.collaborative_drafts.edit.select_a_category") %>
46
48
  </div>
47
49
  <% end %>
48
50