decidim-proposals 0.20.1 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/proposals/admin/proposals.es6 +24 -11
  3. data/app/cells/decidim/proposals/cost_report/show.erb +35 -0
  4. data/app/cells/decidim/proposals/cost_report_cell.rb +42 -0
  5. data/app/cells/decidim/proposals/proposal_m_cell.rb +9 -1
  6. data/app/cells/decidim/proposals/proposal_tags/show.erb +12 -10
  7. data/app/cells/decidim/proposals/proposal_tags_cell.rb +5 -0
  8. data/app/commands/decidim/proposals/admin/answer_proposal.rb +24 -46
  9. data/app/commands/decidim/proposals/admin/assign_proposals_to_valuator.rb +61 -0
  10. data/app/commands/decidim/proposals/admin/create_proposal.rb +5 -0
  11. data/app/commands/decidim/proposals/admin/notify_proposal_answer.rb +85 -0
  12. data/app/commands/decidim/proposals/admin/publish_answers.rb +67 -0
  13. data/app/commands/decidim/proposals/admin/unassign_proposals_from_valuator.rb +62 -0
  14. data/app/commands/decidim/proposals/admin/update_proposal_scope.rb +75 -0
  15. data/app/controllers/concerns/decidim/proposals/admin/filterable.rb +82 -0
  16. data/app/controllers/decidim/proposals/admin/proposal_answers_controller.rb +16 -6
  17. data/app/controllers/decidim/proposals/admin/proposal_notes_controller.rb +8 -9
  18. data/app/controllers/decidim/proposals/admin/proposals_controller.rb +105 -29
  19. data/app/controllers/decidim/proposals/admin/valuation_assignments_controller.rb +58 -0
  20. data/app/controllers/decidim/proposals/collaborative_drafts_controller.rb +19 -3
  21. data/app/controllers/decidim/proposals/proposals_controller.rb +42 -7
  22. data/app/controllers/decidim/proposals/versions_controller.rb +4 -1
  23. data/app/events/decidim/proposals/admin/update_proposal_scope_event.rb +11 -0
  24. data/app/forms/decidim/proposals/admin/proposal_answer_form.rb +27 -2
  25. data/app/forms/decidim/proposals/admin/valuation_assignment_form.rb +37 -0
  26. data/app/forms/decidim/proposals/proposal_wizard_create_step_form.rb +8 -0
  27. data/app/helpers/decidim/proposals/admin/filterable_helper.rb +17 -0
  28. data/app/helpers/decidim/proposals/admin/proposal_bulk_actions_helper.rb +35 -0
  29. data/app/helpers/decidim/proposals/admin/proposal_rankings_helper.rb +63 -0
  30. data/app/helpers/decidim/proposals/admin/proposals_helper.rb +122 -0
  31. data/app/helpers/decidim/proposals/application_helper.rb +36 -25
  32. data/app/helpers/decidim/proposals/collaborative_draft_helper.rb +9 -9
  33. data/app/helpers/decidim/proposals/proposal_cells_helper.rb +1 -1
  34. data/app/helpers/decidim/proposals/proposals_helper.rb +18 -0
  35. data/app/models/decidim/proposals/proposal.rb +163 -16
  36. data/app/models/decidim/proposals/valuation_assignment.rb +24 -0
  37. data/app/permissions/decidim/proposals/admin/permissions.rb +77 -11
  38. data/app/presenters/decidim/proposals/admin_log/proposal_presenter.rb +1 -1
  39. data/app/presenters/decidim/proposals/admin_log/valuation_assignment_presenter.rb +51 -0
  40. data/app/presenters/decidim/proposals/admin_log/value_types/valuator_role_user_presenter.rb +19 -0
  41. data/app/presenters/decidim/proposals/collaborative_draft_presenter.rb +2 -28
  42. data/app/presenters/decidim/proposals/log/valuation_assignment_presenter.rb +22 -0
  43. data/app/presenters/decidim/proposals/proposal_presenter.rb +26 -1
  44. data/app/services/decidim/proposals/collaborative_draft_search.rb +18 -10
  45. data/app/services/decidim/proposals/proposal_search.rb +33 -40
  46. data/app/types/decidim/proposals/proposal_input_filter.rb +29 -0
  47. data/app/types/decidim/proposals/proposal_input_sort.rb +28 -0
  48. data/app/types/decidim/proposals/proposal_type.rb +35 -4
  49. data/app/types/decidim/proposals/proposals_type.rb +14 -17
  50. data/app/views/decidim/proposals/admin/proposal_answers/_form.html.erb +35 -0
  51. data/app/views/decidim/proposals/admin/proposal_notes/_form.html.erb +1 -1
  52. data/app/views/decidim/proposals/admin/proposal_notes/_proposal_notes.html.erb +1 -1
  53. data/app/views/decidim/proposals/admin/proposals/_bulk-actions.html.erb +8 -2
  54. data/app/views/decidim/proposals/admin/proposals/_form.html.erb +1 -1
  55. data/app/views/decidim/proposals/admin/proposals/_proposal-tr.html.erb +25 -17
  56. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_assign_to_valuator.html.erb +15 -0
  57. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_dropdown.html.erb +21 -1
  58. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_publish_answers.html.erb +14 -0
  59. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_scope-change.html.erb +25 -0
  60. data/app/views/decidim/proposals/admin/proposals/bulk_actions/_unassign_from_valuator.html.erb +15 -0
  61. data/app/views/decidim/proposals/admin/proposals/index.html.erb +16 -7
  62. data/app/views/decidim/proposals/admin/proposals/publish_answers.js.erb +12 -0
  63. data/app/views/decidim/proposals/admin/proposals/show.html.erb +186 -0
  64. data/app/views/decidim/proposals/admin/proposals/update_category.js.erb +3 -2
  65. data/app/views/decidim/proposals/admin/proposals/update_scope.js.erb +27 -0
  66. data/app/views/decidim/proposals/collaborative_drafts/_filters.html.erb +3 -3
  67. data/app/views/decidim/proposals/proposals/_edit_form_fields.html.erb +1 -1
  68. data/app/views/decidim/proposals/proposals/_filters.html.erb +12 -12
  69. data/app/views/decidim/proposals/proposals/_proposal_badge.html.erb +1 -4
  70. data/app/views/decidim/proposals/proposals/_proposal_preview.html.erb +1 -1
  71. data/app/views/decidim/proposals/proposals/_vote_button.html.erb +1 -1
  72. data/app/views/decidim/proposals/proposals/index.html.erb +1 -1
  73. data/app/views/decidim/proposals/proposals/new.html.erb +1 -1
  74. data/app/views/decidim/proposals/proposals/show.html.erb +17 -23
  75. data/config/locales/ar.yml +69 -17
  76. data/config/locales/ca.yml +113 -18
  77. data/config/locales/cs.yml +123 -31
  78. data/config/locales/de.yml +38 -18
  79. data/config/locales/el.yml +1 -0
  80. data/config/locales/en.yml +112 -17
  81. data/config/locales/es-MX.yml +112 -17
  82. data/config/locales/es-PY.yml +112 -17
  83. data/config/locales/es.yml +113 -18
  84. data/config/locales/eu.yml +38 -18
  85. data/config/locales/fi-plain.yml +113 -18
  86. data/config/locales/fi.yml +113 -18
  87. data/config/locales/fr.yml +38 -18
  88. data/config/locales/gl.yml +38 -18
  89. data/config/locales/hu.yml +112 -17
  90. data/config/locales/id-ID.yml +38 -18
  91. data/config/locales/is-IS.yml +25 -15
  92. data/config/locales/it.yml +38 -18
  93. data/config/locales/nl.yml +43 -18
  94. data/config/locales/no.yml +66 -18
  95. data/config/locales/pl.yml +38 -18
  96. data/config/locales/pt-BR.yml +39 -19
  97. data/config/locales/pt.yml +39 -19
  98. data/config/locales/ru.yml +25 -17
  99. data/config/locales/sv.yml +39 -18
  100. data/config/locales/tr-TR.yml +38 -18
  101. data/config/locales/uk.yml +25 -17
  102. data/db/migrate/20200203111239_add_proposal_valuation_assignments.rb +12 -0
  103. data/db/migrate/20200210135152_add_costs_to_proposals.rb +9 -0
  104. data/db/migrate/20200212120110_sync_proposals_state_with_amendments_state.rb +28 -0
  105. data/db/migrate/20200227175922_add_state_published_at_to_proposals.rb +7 -0
  106. data/db/migrate/20200306123652_publish_existing_proposals_state.rb +15 -0
  107. data/lib/decidim/proposals.rb +1 -0
  108. data/lib/decidim/proposals/admin_engine.rb +7 -3
  109. data/lib/decidim/proposals/component.rb +39 -19
  110. data/lib/decidim/proposals/engine.rb +1 -1
  111. data/lib/decidim/proposals/test/factories.rb +55 -0
  112. data/lib/decidim/proposals/valuatable.rb +21 -0
  113. data/lib/decidim/proposals/version.rb +1 -1
  114. metadata +53 -36
  115. data/app/views/decidim/proposals/admin/proposal_answers/edit.html.erb +0 -22
  116. data/app/views/decidim/proposals/admin/proposal_notes/index.html.erb +0 -3
  117. data/app/views/decidim/proposals/admin/shared/_info_proposal.html.erb +0 -20
  118. data/app/views/decidim/proposals/proposal_widgets/show.html.erb +0 -4
@@ -31,7 +31,7 @@ module Decidim
31
31
 
32
32
  def action_string
33
33
  case action
34
- when "answer", "create", "update"
34
+ when "answer", "create", "update", "publish_answer"
35
35
  "decidim.proposals.admin_log.proposal.#{action}"
36
36
  else
37
37
  super
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module AdminLog
6
+ # This class holds the logic to present a `Decidim::Proposals::ValuationAssignment`
7
+ # for the `AdminLog` log.
8
+ #
9
+ # Usage should be automatic and you shouldn't need to call this class
10
+ # directly, but here's an example:
11
+ #
12
+ # action_log = Decidim::ActionLog.last
13
+ # view_helpers # => this comes from the views
14
+ # ValuationAssignmentPresenter.new(action_log, view_helpers).present
15
+ class ValuationAssignmentPresenter < Decidim::Log::BasePresenter
16
+ private
17
+
18
+ def resource_presenter
19
+ @resource_presenter ||= Decidim::Proposals::Log::ValuationAssignmentPresenter.new(action_log.resource, h, action_log.extra["resource"])
20
+ end
21
+
22
+ def diff_fields_mapping
23
+ {
24
+ valuator_role_id: "Decidim::Proposals::AdminLog::ValueTypes::ValuatorRoleUserPresenter"
25
+ }
26
+ end
27
+
28
+ def action_string
29
+ case action
30
+ when "create", "delete"
31
+ "decidim.proposals.admin_log.valuation_assignment.#{action}"
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ def i18n_labels_scope
38
+ "activemodel.attributes.valuation_assignment.admin_log"
39
+ end
40
+
41
+ def has_diff?
42
+ %w(create delete).include?(action) || super
43
+ end
44
+
45
+ def i18n_params
46
+ super.merge(proposal_title: h.translated_attribute(action_log.extra["proposal_title"]))
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module AdminLog
6
+ module ValueTypes
7
+ class ValuatorRoleUserPresenter < Decidim::Log::ValueTypes::DefaultPresenter
8
+ def present
9
+ return unless value
10
+
11
+ role = Decidim::Proposals::ValuationAssignment.find_by(valuator_role_id: value).valuator_role
12
+ user = role.user
13
+ user.try(:name)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,12 +5,7 @@ module Decidim
5
5
  #
6
6
  # Decorator for collaborative drafts
7
7
  #
8
- class CollaborativeDraftPresenter < SimpleDelegator
9
- include Rails.application.routes.mounted_helpers
10
- include ActionView::Helpers::UrlHelper
11
- include ActionView::Helpers::SanitizeHelper
12
- include Decidim::SanitizeHelper
13
-
8
+ class CollaborativeDraftPresenter < ProposalPresenter
14
9
  def author
15
10
  coauthorship = __getobj__.coauthorships.first
16
11
  @author ||= if coauthorship.user_group
@@ -20,32 +15,11 @@ module Decidim
20
15
  end
21
16
  end
22
17
 
23
- def collaborative_draft
24
- __getobj__
25
- end
18
+ alias collaborative_draft proposal
26
19
 
27
20
  def collaborative_draft_path
28
21
  Decidim::ResourceLocatorPresenter.new(collaborative_draft).path
29
22
  end
30
-
31
- def title(links: false, extras: true, html_escape: false)
32
- text = collaborative_draft.title
33
- text = decidim_html_escape(text) if html_escape
34
-
35
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(text)
36
- renderer.render(links: links, extras: extras).html_safe
37
- end
38
-
39
- def body(links: false, extras: true, strip_tags: false)
40
- text = collaborative_draft.body
41
- text = strip_tags(text) if strip_tags
42
-
43
- renderer = Decidim::ContentRenderers::HashtagRenderer.new(text)
44
- text = renderer.render(links: links, extras: extras).html_safe
45
-
46
- text = Decidim::ContentRenderers::LinkRenderer.new(text).render if links
47
- text
48
- end
49
23
  end
50
24
  end
51
25
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ module Log
6
+ class ValuationAssignmentPresenter < Decidim::Log::ResourcePresenter
7
+ private
8
+
9
+ # Private: Presents resource name.
10
+ #
11
+ # Returns an HTML-safe String.
12
+ def present_resource_name
13
+ if resource.present?
14
+ Decidim::Proposals::ProposalPresenter.new(resource.proposal).title
15
+ else
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,7 +8,6 @@ module Decidim
8
8
  class ProposalPresenter < SimpleDelegator
9
9
  include Rails.application.routes.mounted_helpers
10
10
  include ActionView::Helpers::UrlHelper
11
- include ActionView::Helpers::SanitizeHelper
12
11
  include Decidim::SanitizeHelper
13
12
 
14
13
  def author
@@ -56,6 +55,32 @@ module Decidim
56
55
  text = Decidim::ContentRenderers::LinkRenderer.new(text).render if links
57
56
  text
58
57
  end
58
+
59
+ # Returns the proposal versions, hiding not published answers
60
+ #
61
+ # Returns an Array.
62
+ def versions
63
+ version_state_published = false
64
+ pending_state_change = nil
65
+
66
+ proposal.versions.map do |version|
67
+ state_published_change = version.changeset["state_published_at"]
68
+ version_state_published = state_published_change.last.present? if state_published_change
69
+
70
+ if version_state_published
71
+ version.changeset["state"] = pending_state_change if pending_state_change
72
+ pending_state_change = nil
73
+ elsif version.changeset["state"]
74
+ pending_state_change = version.changeset.delete("state")
75
+ end
76
+
77
+ next if version.event == "update" && Decidim::Proposals::DiffRenderer.new(version).diff.empty?
78
+
79
+ version
80
+ end.compact
81
+ end
82
+
83
+ delegate :count, to: :versions, prefix: true
59
84
  end
60
85
  end
61
86
  end
@@ -22,16 +22,24 @@ module Decidim
22
22
 
23
23
  # Handle the state filter
24
24
  def search_state
25
- case state
26
- when "open"
27
- query.open
28
- when "withdrawn"
29
- query.withdrawn
30
- when "published"
31
- query.published
32
- else
33
- query
34
- end
25
+ return query if state.member?("all")
26
+
27
+ open_drafts = state.member?("open") ? query.open : nil
28
+ withdrawn = state.member?("withdrawn") ? query.withdrawn : nil
29
+ published = state.member?("published") ? query.published : nil
30
+
31
+ query
32
+ .where(id: open_drafts)
33
+ .or(query.where(id: withdrawn))
34
+ .or(query.where(id: published))
35
+ end
36
+
37
+ def search_category_id
38
+ super
39
+ end
40
+
41
+ def search_scope_id
42
+ super
35
43
  end
36
44
 
37
45
  # Filters drafts by the name of the classes they are linked to. By default,
@@ -12,7 +12,9 @@ module Decidim
12
12
  def initialize(options = {})
13
13
  @component = options[:component]
14
14
  @current_user = options[:current_user]
15
- super(Proposal.all, options)
15
+
16
+ base = options[:state]&.member?("withdrawn") ? Proposal.withdrawn : Proposal.except_withdrawn
17
+ super(base, options)
16
18
  end
17
19
 
18
20
  # Handle the search_text filter
@@ -24,31 +26,16 @@ module Decidim
24
26
 
25
27
  # Handle the origin filter
26
28
  def search_origin
27
- case origin
28
- when "official"
29
- query
30
- .where.not(coauthorships_count: 0)
31
- .joins(:coauthorships)
32
- .where(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
33
- when "citizens"
34
- query
35
- .where.not(coauthorships_count: 0)
36
- .joins(:coauthorships)
37
- .where.not(decidim_coauthorships: { decidim_author_type: "Decidim::Organization" })
38
- when "user_group"
39
- query
40
- .where.not(coauthorships_count: 0)
41
- .joins(:coauthorships)
42
- .where(decidim_coauthorships: { decidim_author_type: "Decidim::UserBaseEntity" })
43
- .where.not(decidim_coauthorships: { decidim_user_group_id: nil })
44
- when "meeting"
45
- query
46
- .where.not(coauthorships_count: 0)
47
- .joins(:coauthorships)
48
- .where(decidim_coauthorships: { decidim_author_type: "Decidim::Meetings::Meeting" })
49
- else # Assume 'all'
50
- query
51
- end
29
+ official = origin.member?("official") ? query.official_origin : nil
30
+ citizens = origin.member?("citizens") ? query.citizens_origin : nil
31
+ user_group = origin.member?("user_group") ? query.user_group_origin : nil
32
+ meeting = origin.member?("meeting") ? query.meeting_origin : nil
33
+
34
+ query
35
+ .where(id: official)
36
+ .or(query.where(id: citizens))
37
+ .or(query.where(id: user_group))
38
+ .or(query.where(id: meeting))
52
39
  end
53
40
 
54
41
  # Handle the activity filter
@@ -71,20 +58,18 @@ module Decidim
71
58
 
72
59
  # Handle the state filter
73
60
  def search_state
74
- case state
75
- when "accepted"
76
- query.accepted
77
- when "rejected"
78
- query.rejected
79
- when "evaluating"
80
- query.evaluating
81
- when "withdrawn"
82
- query.withdrawn
83
- when "except_rejected"
84
- query.except_rejected.except_withdrawn
85
- else # Assume 'not_withdrawn'
86
- query.except_withdrawn
87
- end
61
+ return query if state.member? "withdrawn"
62
+
63
+ accepted = state.member?("accepted") ? query.accepted : nil
64
+ rejected = state.member?("rejected") ? query.rejected : nil
65
+ evaluating = state.member?("evaluating") ? query.evaluating : nil
66
+ not_answered = state.member?("not_answered") ? query.state_not_published : nil
67
+
68
+ query
69
+ .where(id: accepted)
70
+ .or(query.where(id: rejected))
71
+ .or(query.where(id: evaluating))
72
+ .or(query.where(id: not_answered))
88
73
  end
89
74
 
90
75
  # Handle the amendment type filter
@@ -99,6 +84,14 @@ module Decidim
99
84
  end
100
85
  end
101
86
 
87
+ def search_category_id
88
+ super
89
+ end
90
+
91
+ def search_scope_id
92
+ super
93
+ end
94
+
102
95
  # Filters Proposals by the name of the classes they are linked to. By default,
103
96
  # returns all Proposals. When a `related_to` param is given, then it camelcases item
104
97
  # to find the real class name and checks the links for the Proposals.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ class ProposalInputFilter < Decidim::Core::BaseInputFilter
6
+ include Decidim::Core::HasPublishableInputFilter
7
+
8
+ graphql_name "ProposalFilter"
9
+ description "A type used for filtering proposals inside a participatory space.
10
+
11
+ A typical query would look like:
12
+
13
+ ```
14
+ {
15
+ participatoryProcesses {
16
+ components {
17
+ ...on Proposals {
18
+ proposals(filter:{ publishedBefore: \"2020-01-01\" }) {
19
+ id
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ ```
26
+ "
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Proposals
5
+ class ProposalInputSort < Decidim::Core::BaseInputSort
6
+ include Decidim::Core::HasPublishableInputSort
7
+
8
+ graphql_name "ProposalSort"
9
+ description "A type used for sorting proposals"
10
+
11
+ 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
+ argument :vote_count,
20
+ type: String,
21
+ description: "Sort by number of votes, valid values are ASC or DESC. Will be ignored if votes are hidden",
22
+ required: false,
23
+ prepare: ->(value, _ctx) do
24
+ { proposal_votes_count: value }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -8,24 +8,55 @@ module Decidim
8
8
 
9
9
  interfaces [
10
10
  -> { Decidim::Comments::CommentableInterface },
11
- -> { Decidim::Core::AuthorableInterface },
11
+ -> { Decidim::Core::CoauthorableInterface },
12
12
  -> { Decidim::Core::CategorizableInterface },
13
13
  -> { Decidim::Core::ScopableInterface },
14
- -> { Decidim::Core::AttachableInterface }
14
+ -> { Decidim::Core::AttachableInterface },
15
+ -> { Decidim::Core::FingerprintInterface },
16
+ -> { Decidim::Core::AmendableInterface },
17
+ -> { Decidim::Core::AmendableEntityInterface },
18
+ -> { Decidim::Core::TraceableInterface },
19
+ -> { Decidim::Core::TimestampsInterface }
15
20
  ]
16
21
 
17
22
  field :id, !types.ID
18
23
  field :title, !types.String, "This proposal's title"
19
24
  field :body, types.String, "This proposal's body"
20
- field :state, types.String, "The state in which proposal is in"
21
25
  field :address, types.String, "The physical address (location) of this proposal"
22
- field :reference, types.String, "This proposa'ls unique reference"
26
+ field :coordinates, Decidim::Core::CoordinatesType, "Physical coordinates for this proposal" do
27
+ resolve ->(proposal, _args, _ctx) {
28
+ [proposal.latitude, proposal.longitude]
29
+ }
30
+ end
31
+ field :reference, types.String, "This proposal's unique reference"
32
+ field :state, types.String, "The answer status in which proposal is in"
33
+ field :answer, Decidim::Core::TranslatedFieldType, "The answer feedback for the status for this proposal"
34
+
35
+ field :answeredAt, Decidim::Core::DateTimeType do
36
+ description "The date and time this proposal was answered"
37
+ property :answered_at
38
+ end
23
39
 
24
40
  field :publishedAt, Decidim::Core::DateTimeType do
25
41
  description "The date and time this proposal was published"
26
42
  property :published_at
27
43
  end
28
44
 
45
+ field :participatoryTextLevel, types.String do
46
+ description "If it is a participatory text, the level indicates the type of paragraph"
47
+ property :participatory_text_level
48
+ end
49
+ field :position, types.Int, "Position of this proposal in the participatory text"
50
+
51
+ field :official, types.Boolean, "Whether this proposal is official or not", property: :official?
52
+ field :createdInMeeting, types.Boolean, "Whether this proposal comes from a meeting or not", property: :official_meeting?
53
+ field :meeting, Decidim::Meetings::MeetingType do
54
+ description "If the proposal comes from a meeting, the related meeting"
55
+ resolve ->(proposal, _, _) {
56
+ proposal.authors.first if proposal.official_meeting?
57
+ }
58
+ end
59
+
29
60
  field :endorsements, !types[Decidim::Core::AuthorInterface], "The endorsements of this proposal." do
30
61
  resolve ->(proposal, _, _) {
31
62
  proposal.endorsements.map(&:normalized_author)