decidim-proposals 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/cells/decidim/proposals/participatory_text_proposal_cell.rb +3 -1
- data/app/cells/decidim/proposals/proposal_activity_cell.rb +9 -1
- data/app/commands/decidim/proposals/admin/discard_participatory_text.rb +40 -0
- data/app/commands/decidim/proposals/admin/import_participatory_text.rb +5 -1
- data/app/commands/decidim/proposals/admin/publish_participatory_text.rb +6 -18
- data/app/commands/decidim/proposals/admin/update_participatory_text.rb +56 -0
- data/app/commands/decidim/proposals/create_proposal.rb +21 -22
- data/app/commands/decidim/proposals/publish_collaborative_draft.rb +1 -0
- data/app/commands/decidim/proposals/publish_proposal.rb +25 -3
- data/app/commands/decidim/proposals/update_proposal.rb +19 -23
- data/app/controllers/concerns/decidim/proposals/orderable.rb +1 -1
- data/app/controllers/decidim/proposals/admin/participatory_texts_controller.rb +46 -14
- data/app/forms/decidim/proposals/admin/import_participatory_text_form.rb +1 -2
- data/app/forms/decidim/proposals/admin/proposal_form.rb +1 -1
- data/app/helpers/decidim/proposals/application_helper.rb +0 -4
- data/app/permissions/decidim/proposals/admin/permissions.rb +2 -4
- data/app/views/decidim/proposals/admin/participatory_texts/_article-preview.html.erb +1 -1
- data/app/views/decidim/proposals/admin/participatory_texts/_bulk-actions.html.erb +1 -0
- data/app/views/decidim/proposals/admin/participatory_texts/index.html.erb +8 -5
- data/app/views/decidim/proposals/proposals/show.html.erb +9 -0
- data/config/locales/ar-SA.yml +667 -0
- data/config/locales/ca.yml +28 -21
- data/config/locales/cs-CZ.yml +775 -0
- data/config/locales/de.yml +7 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/es-MX.yml +751 -0
- data/config/locales/es-PY.yml +7 -0
- data/config/locales/es.yml +21 -14
- data/config/locales/eu.yml +10 -3
- data/config/locales/fi-pl.yml +8 -1
- data/config/locales/fi.yml +11 -4
- data/config/locales/fr.yml +7 -0
- data/config/locales/gl.yml +7 -0
- data/config/locales/hu.yml +21 -14
- data/config/locales/id-ID.yml +7 -0
- data/config/locales/it.yml +8 -1
- data/config/locales/nl.yml +10 -3
- data/config/locales/pl.yml +8 -1
- data/config/locales/pt-BR.yml +7 -0
- data/config/locales/pt.yml +7 -0
- data/config/locales/ru.yml +6 -0
- data/config/locales/sv.yml +7 -0
- data/config/locales/tr-TR.yml +8 -0
- data/config/locales/uk.yml +6 -0
- data/db/migrate/20190215113158_use_md5_indexes.rb +17 -0
- data/lib/decidim/content_parsers/proposal_parser.rb +2 -2
- data/lib/decidim/proposals/admin_engine.rb +4 -2
- data/lib/decidim/proposals/markdown_to_proposals.rb +49 -4
- data/lib/decidim/proposals/proposal_serializer.rb +3 -2
- data/lib/decidim/proposals/version.rb +1 -1
- metadata +26 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f545c292413c69159509938ffa3e0a7a442eaec96770e465b405d709ab0db976
|
4
|
+
data.tar.gz: 90b940f6ce3c968772548d40a04a7c47d7491c340c2a407b78a6013ccdf903c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e12c387014c567aee0ca73e133357c74621e49dcd49b305ecda4bac2e231e215273d15b30a7d3e0e61772ba6dea2163b3baaf459781aa4a595ba100dcefcf086
|
7
|
+
data.tar.gz: 7dde2bc4a1920813acf8fee2bde644f1d7b80b58c056bab12f720ff2df246e376b401e83418d6a51475ba4190e1147f3beadb651a6be12bf90216fc38e5b5c3c
|
@@ -10,6 +10,7 @@ module Decidim
|
|
10
10
|
include ProposalCellsHelper
|
11
11
|
include Cell::ViewModel::Partial
|
12
12
|
include Messaging::ConversationHelper
|
13
|
+
include Decidim::SanitizeHelper
|
13
14
|
|
14
15
|
delegate :current_organization, to: :controller
|
15
16
|
|
@@ -30,7 +31,8 @@ module Decidim
|
|
30
31
|
|
31
32
|
def body
|
32
33
|
return unless model.participatory_text_level == "article"
|
33
|
-
present(model).body
|
34
|
+
formatted = simple_format(present(model).body)
|
35
|
+
decidim_sanitize(strip_links(formatted))
|
34
36
|
end
|
35
37
|
|
36
38
|
def current_user
|
@@ -12,7 +12,15 @@ module Decidim
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def resource_link_text
|
15
|
-
|
15
|
+
presenter.title
|
16
|
+
end
|
17
|
+
|
18
|
+
def description
|
19
|
+
presenter.body(links: true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def presenter
|
23
|
+
@presenter ||= Decidim::Proposals::ProposalPresenter.new(resource)
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic related with an admin discarding participatory text proposals.
|
7
|
+
class DiscardParticipatoryText < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A PreviewParticipatoryTextForm form object with the params.
|
11
|
+
def initialize(component)
|
12
|
+
@component = component
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
transaction do
|
23
|
+
discard_drafts
|
24
|
+
end
|
25
|
+
|
26
|
+
broadcast(:ok)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :form
|
32
|
+
|
33
|
+
def discard_drafts
|
34
|
+
proposals = Decidim::Proposals::Proposal.drafts.where(component: @component)
|
35
|
+
proposals.destroy_all
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -39,7 +39,11 @@ module Decidim
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def parse_participatory_text_doc(form)
|
42
|
-
|
42
|
+
return if form.document.blank?
|
43
|
+
|
44
|
+
document = form.document_text
|
45
|
+
document = Decidim::IoEncoder.to_standard_encoding(document)
|
46
|
+
markdown = DocToMarkdown.new(document, form.document_type).to_md
|
43
47
|
parser = MarkdownToProposals.new(form.current_component, form.current_user)
|
44
48
|
parser.parse(markdown)
|
45
49
|
end
|
@@ -5,7 +5,7 @@ module Decidim
|
|
5
5
|
module Admin
|
6
6
|
# A command with all the business logic when an admin imports proposals from
|
7
7
|
# a participatory text.
|
8
|
-
class PublishParticipatoryText <
|
8
|
+
class PublishParticipatoryText < UpdateParticipatoryText
|
9
9
|
# Public: Initializes the command.
|
10
10
|
#
|
11
11
|
# form - A PreviewParticipatoryTextForm form object with the params.
|
@@ -21,13 +21,13 @@ module Decidim
|
|
21
21
|
# Returns nothing.
|
22
22
|
def call
|
23
23
|
transaction do
|
24
|
-
@
|
24
|
+
@failures = {}
|
25
25
|
update_contents_and_resort_proposals(form)
|
26
26
|
publish_drafts
|
27
27
|
end
|
28
28
|
|
29
|
-
if @
|
30
|
-
broadcast(:invalid, @
|
29
|
+
if @failures.any?
|
30
|
+
broadcast(:invalid, @failures)
|
31
31
|
else
|
32
32
|
broadcast(:ok)
|
33
33
|
end
|
@@ -37,27 +37,15 @@ module Decidim
|
|
37
37
|
|
38
38
|
attr_reader :form
|
39
39
|
|
40
|
-
def update_contents_and_resort_proposals(form)
|
41
|
-
form.proposals.each do |prop_form|
|
42
|
-
proposal = Decidim::Proposals::Proposal.where(component: form.current_component).find(prop_form.id)
|
43
|
-
proposal.set_list_position(prop_form.position) if proposal.position != prop_form.position
|
44
|
-
proposal.title = prop_form.title
|
45
|
-
proposal.body = prop_form.body if proposal.participatory_text_level == Decidim::Proposals::ParticipatoryTextSection::LEVELS[:article]
|
46
|
-
|
47
|
-
add_failure(proposal) unless proposal.save
|
48
|
-
end
|
49
|
-
raise ActiveRecord::Rollback if @publish_failures.any?
|
50
|
-
end
|
51
|
-
|
52
40
|
def publish_drafts
|
53
41
|
Decidim::Proposals::Proposal.where(component: form.current_component).drafts.find_each do |proposal|
|
54
42
|
add_failure(proposal) unless proposal.update(published_at: Time.current)
|
55
43
|
end
|
56
|
-
raise ActiveRecord::Rollback if @
|
44
|
+
raise ActiveRecord::Rollback if @failures.any?
|
57
45
|
end
|
58
46
|
|
59
47
|
def add_failure(proposal)
|
60
|
-
@
|
48
|
+
@failures[proposal.id] = proposal.errors.full_messages
|
61
49
|
end
|
62
50
|
end
|
63
51
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Proposals
|
5
|
+
module Admin
|
6
|
+
# A command with all the business logic when an admin updates participatory text proposals.
|
7
|
+
class UpdateParticipatoryText < Rectify::Command
|
8
|
+
# Public: Initializes the command.
|
9
|
+
#
|
10
|
+
# form - A PreviewParticipatoryTextForm form object with the params.
|
11
|
+
def initialize(form)
|
12
|
+
@form = form
|
13
|
+
end
|
14
|
+
|
15
|
+
# Executes the command. Broadcasts these events:
|
16
|
+
#
|
17
|
+
# - :ok when everything is valid.
|
18
|
+
# - :invalid if the form wasn't valid and we couldn't proceed.
|
19
|
+
#
|
20
|
+
# Returns nothing.
|
21
|
+
def call
|
22
|
+
transaction do
|
23
|
+
@failures = {}
|
24
|
+
update_contents_and_resort_proposals(form)
|
25
|
+
end
|
26
|
+
|
27
|
+
if @failures.any?
|
28
|
+
broadcast(:invalid, @failures)
|
29
|
+
else
|
30
|
+
broadcast(:ok)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :form
|
37
|
+
|
38
|
+
def update_contents_and_resort_proposals(form)
|
39
|
+
form.proposals.each do |prop_form|
|
40
|
+
proposal = Decidim::Proposals::Proposal.where(component: form.current_component).find(prop_form.id)
|
41
|
+
proposal.set_list_position(prop_form.position) if proposal.position != prop_form.position
|
42
|
+
proposal.title = prop_form.title
|
43
|
+
proposal.body = prop_form.body if proposal.participatory_text_level == Decidim::Proposals::ParticipatoryTextSection::LEVELS[:article]
|
44
|
+
|
45
|
+
add_failure(proposal) unless proposal.save
|
46
|
+
end
|
47
|
+
raise ActiveRecord::Rollback if @failures.any?
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_failure(proposal)
|
51
|
+
@failures[proposal.id] = proposal.errors.full_messages
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -43,29 +43,28 @@ module Decidim
|
|
43
43
|
|
44
44
|
attr_reader :form, :proposal, :attachment
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
fields[:component] = form.component
|
52
|
-
|
53
|
-
fields
|
54
|
-
end
|
55
|
-
|
56
|
-
# This will be the PaperTrail version that is
|
57
|
-
# shown in the version control feature (1 of 1)
|
46
|
+
# Prevent PaperTrail from creating an additional version
|
47
|
+
# in the proposal multi-step creation process (step 1: create)
|
48
|
+
#
|
49
|
+
# A first version will be created in step 4: publish
|
50
|
+
# for diff rendering in the proposal version control
|
58
51
|
def create_proposal
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
52
|
+
PaperTrail.request(enabled: false) do
|
53
|
+
@proposal = Decidim.traceability.perform_action!(
|
54
|
+
:create,
|
55
|
+
Decidim::Proposals::Proposal,
|
56
|
+
@current_user,
|
57
|
+
visibility: "public-only"
|
58
|
+
) do
|
59
|
+
proposal = Proposal.new(
|
60
|
+
title: title_with_hashtags,
|
61
|
+
body: body_with_hashtags,
|
62
|
+
component: form.component
|
63
|
+
)
|
64
|
+
proposal.add_coauthor(@current_user, user_group: user_group)
|
65
|
+
proposal.save!
|
66
|
+
proposal
|
67
|
+
end
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
@@ -79,6 +79,7 @@ module Decidim
|
|
79
79
|
new_proposal = Proposal.new(proposal_attributes)
|
80
80
|
new_proposal.coauthorships = @collaborative_draft.coauthorships
|
81
81
|
new_proposal.category = @collaborative_draft.category
|
82
|
+
new_proposal.attachments = @collaborative_draft.attachments
|
82
83
|
new_proposal.save!
|
83
84
|
new_proposal
|
84
85
|
end
|
@@ -34,12 +34,34 @@ module Decidim
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
#
|
38
|
-
# in the
|
37
|
+
# This will be the PaperTrail version that is
|
38
|
+
# shown in the version control feature (1 of 1)
|
39
|
+
#
|
40
|
+
# For an attribute to appear in the new version it has to be reset
|
41
|
+
# and reassigned, as PaperTrail only keeps track of object CHANGES.
|
39
42
|
def publish_proposal
|
43
|
+
title = reset(:title)
|
44
|
+
body = reset(:body)
|
45
|
+
|
46
|
+
Decidim.traceability.perform_action!(
|
47
|
+
"publish",
|
48
|
+
@proposal,
|
49
|
+
@current_user,
|
50
|
+
visibility: "public-only"
|
51
|
+
) do
|
52
|
+
@proposal.update title: title, body: body, published_at: Time.current
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Reset the attribute to an empty string and return the old value
|
57
|
+
def reset(attribute)
|
58
|
+
attribute_value = @proposal[attribute]
|
40
59
|
PaperTrail.request(enabled: false) do
|
41
|
-
|
60
|
+
# rubocop:disable Rails/SkipsModelValidations
|
61
|
+
@proposal.update_attribute attribute, ""
|
62
|
+
# rubocop:enable Rails/SkipsModelValidations
|
42
63
|
end
|
64
|
+
attribute_value
|
43
65
|
end
|
44
66
|
|
45
67
|
def send_notification
|
@@ -53,41 +53,37 @@ module Decidim
|
|
53
53
|
|
54
54
|
attr_reader :form, :proposal, :current_user, :attachment
|
55
55
|
|
56
|
-
def proposal_attributes
|
57
|
-
fields = {}
|
58
|
-
|
59
|
-
fields[:title] = title_with_hashtags
|
60
|
-
fields[:body] = body_with_hashtags
|
61
|
-
fields[:category] = form.category
|
62
|
-
fields[:scope] = form.scope
|
63
|
-
fields[:address] = form.address
|
64
|
-
fields[:latitude] = form.latitude
|
65
|
-
fields[:longitude] = form.longitude
|
66
|
-
|
67
|
-
fields
|
68
|
-
end
|
69
|
-
|
70
56
|
# Prevent PaperTrail from creating an additional version
|
71
57
|
# in the proposal multi-step creation process (step 3: complete)
|
58
|
+
#
|
59
|
+
# A first version will be created in step 4: publish
|
60
|
+
# for diff rendering in the proposal control version
|
72
61
|
def update_draft
|
73
62
|
PaperTrail.request(enabled: false) do
|
74
|
-
@proposal.update(
|
63
|
+
@proposal.update(attributes)
|
75
64
|
@proposal.coauthorships.clear
|
76
65
|
@proposal.add_coauthor(current_user, user_group: user_group)
|
77
66
|
end
|
78
67
|
end
|
79
68
|
|
80
69
|
def update_proposal
|
81
|
-
@proposal
|
82
|
-
@proposal,
|
83
|
-
current_user,
|
84
|
-
proposal_attributes,
|
85
|
-
visibility: "public-only"
|
86
|
-
)
|
70
|
+
@proposal.update!(attributes)
|
87
71
|
@proposal.coauthorships.clear
|
88
72
|
@proposal.add_coauthor(current_user, user_group: user_group)
|
89
73
|
end
|
90
74
|
|
75
|
+
def attributes
|
76
|
+
{
|
77
|
+
title: title_with_hashtags,
|
78
|
+
body: body_with_hashtags,
|
79
|
+
category: form.category,
|
80
|
+
scope: form.scope,
|
81
|
+
address: form.address,
|
82
|
+
latitude: form.latitude,
|
83
|
+
longitude: form.longitude
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
91
87
|
def proposal_limit_reached?
|
92
88
|
proposal_limit = form.current_component.settings.proposal_limit
|
93
89
|
|
@@ -109,11 +105,11 @@ module Decidim
|
|
109
105
|
end
|
110
106
|
|
111
107
|
def current_user_proposals
|
112
|
-
Proposal.from_author(current_user).where(component: form.current_component).published.where.not(id: proposal.id)
|
108
|
+
Proposal.from_author(current_user).where(component: form.current_component).published.where.not(id: proposal.id).except_withdrawn
|
113
109
|
end
|
114
110
|
|
115
111
|
def user_group_proposals
|
116
|
-
Proposal.from_user_group(user_group).where(component: form.current_component).published.where.not(id: proposal.id)
|
112
|
+
Proposal.from_user_group(user_group).where(component: form.current_component).published.where.not(id: proposal.id).except_withdrawn
|
117
113
|
end
|
118
114
|
end
|
119
115
|
end
|
@@ -15,13 +15,13 @@ module Decidim
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def new_import
|
18
|
-
enforce_permission_to :
|
18
|
+
enforce_permission_to :manage, :participatory_texts
|
19
19
|
participatory_text = Decidim::Proposals::ParticipatoryText.find_by(component: current_component)
|
20
20
|
@import = form(Admin::ImportParticipatoryTextForm).from_model(participatory_text)
|
21
21
|
end
|
22
22
|
|
23
23
|
def import
|
24
|
-
enforce_permission_to :
|
24
|
+
enforce_permission_to :manage, :participatory_texts
|
25
25
|
@import = form(Admin::ImportParticipatoryTextForm).from_params(params)
|
26
26
|
|
27
27
|
Admin::ImportParticipatoryText.call(@import) do
|
@@ -37,23 +37,55 @@ module Decidim
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
# When `save_draft` param exists, proposals are only saved.
|
41
|
+
# When no `save_draft` param is set, proposals are saved and published.
|
42
|
+
def update
|
43
|
+
enforce_permission_to :manage, :participatory_texts
|
44
|
+
|
42
45
|
form_params = params.require(:preview_participatory_text).permit!
|
43
46
|
@preview_form = form(Admin::PreviewParticipatoryTextForm).from_params(proposals: form_params[:proposals_attributes]&.values)
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
if params.has_key?("save_draft")
|
49
|
+
UpdateParticipatoryText.call(@preview_form) do
|
50
|
+
on(:ok) do
|
51
|
+
flash[:notice] = I18n.t("participatory_texts.update.success", scope: "decidim.proposals.admin")
|
52
|
+
redirect_to participatory_texts_path(component_id: current_component.id, initiative_slug: "asdf")
|
53
|
+
end
|
54
|
+
|
55
|
+
on(:invalid) do |failures|
|
56
|
+
alert_msg = [I18n.t("participatory_texts.publish.invalid", scope: "decidim.proposals.admin")]
|
57
|
+
failures.each_pair { |id, msg| alert_msg << "ID:[#{id}] #{msg}" }
|
58
|
+
flash.now[:alert] = alert_msg.join("<br/>").html_safe
|
59
|
+
index
|
60
|
+
render action: "index"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
PublishParticipatoryText.call(@preview_form) do
|
65
|
+
on(:ok) do
|
66
|
+
flash[:notice] = I18n.t("participatory_texts.publish.success", scope: "decidim.proposals.admin")
|
67
|
+
redirect_to proposals_path
|
68
|
+
end
|
69
|
+
|
70
|
+
on(:invalid) do |failures|
|
71
|
+
alert_msg = [I18n.t("participatory_texts.publish.invalid", scope: "decidim.proposals.admin")]
|
72
|
+
failures.each_pair { |id, msg| alert_msg << "ID:[#{id}] #{msg}" }
|
73
|
+
flash.now[:alert] = alert_msg.join("<br/>").html_safe
|
74
|
+
index
|
75
|
+
render action: "index"
|
76
|
+
end
|
49
77
|
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Removes all the unpublished proposals (drafts).
|
82
|
+
def discard
|
83
|
+
enforce_permission_to :manage, :participatory_texts
|
50
84
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
index
|
56
|
-
render action: "index"
|
85
|
+
DiscardParticipatoryText.call(current_component) do
|
86
|
+
on(:ok) do
|
87
|
+
flash[:notice] = I18n.t("participatory_texts.discard.success", scope: "decidim.proposals.admin")
|
88
|
+
redirect_to participatory_texts_path(component_id: current_component.id, initiative_slug: "asdf")
|
57
89
|
end
|
58
90
|
end
|
59
91
|
end
|