decidim-core 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/decidim_core_manifest.js +2 -0
  3. data/app/assets/javascripts/decidim/map.js.es6.erb +95 -0
  4. data/app/assets/stylesheets/decidim/map.css +3 -0
  5. data/app/assets/stylesheets/decidim/modules/_layout.scss +2 -4
  6. data/app/assets/stylesheets/decidim/modules/_margins.scss +3 -2
  7. data/app/assets/stylesheets/decidim/modules/_process-header.scss +15 -2
  8. data/app/assets/stylesheets/decidim/modules/_process-phase.scss +4 -1
  9. data/app/assets/stylesheets/decidim/utils/_settings.scss +3 -3
  10. data/app/commands/decidim/create_report.rb +90 -0
  11. data/app/controllers/concerns/decidim/devise_controllers.rb +26 -0
  12. data/app/controllers/concerns/decidim/payload_info.rb +23 -0
  13. data/app/controllers/concerns/decidim/user_profile.rb +2 -1
  14. data/app/controllers/decidim/application_controller.rb +25 -1
  15. data/app/controllers/decidim/authorizations_controller.rb +10 -2
  16. data/app/controllers/decidim/cookie_policy_controller.rb +5 -0
  17. data/app/controllers/decidim/devise/confirmations_controller.rb +1 -9
  18. data/app/controllers/decidim/devise/invitations_controller.rb +1 -9
  19. data/app/controllers/decidim/devise/omniauth_registrations_controller.rb +1 -10
  20. data/app/controllers/decidim/devise/passwords_controller.rb +1 -9
  21. data/app/controllers/decidim/devise/registrations_controller.rb +2 -15
  22. data/app/controllers/decidim/devise/sessions_controller.rb +9 -15
  23. data/{lib → app/controllers}/decidim/features/base_controller.rb +5 -1
  24. data/app/controllers/decidim/participatory_process_groups_controller.rb +22 -0
  25. data/app/controllers/decidim/participatory_process_steps_controller.rb +2 -0
  26. data/app/controllers/decidim/participatory_processes_controller.rb +14 -3
  27. data/app/controllers/decidim/reports_controller.rb +33 -0
  28. data/app/controllers/decidim/static_map_controller.rb +18 -0
  29. data/app/forms/decidim/report_form.rb +12 -0
  30. data/app/helpers/decidim/application_helper.rb +0 -2
  31. data/app/helpers/decidim/feature_reference_helper.rb +22 -0
  32. data/app/helpers/decidim/map_helper.rb +41 -0
  33. data/app/helpers/decidim/organization_scopes_helper.rb +41 -0
  34. data/app/helpers/decidim/replace_buttons_helper.rb +42 -0
  35. data/app/helpers/decidim/resource_helper.rb +2 -1
  36. data/app/helpers/decidim/translations_helper.rb +1 -1
  37. data/app/mailers/decidim/reported_mailer.rb +35 -0
  38. data/app/middleware/decidim/current_organization.rb +29 -3
  39. data/app/models/decidim/abilities/everyone.rb +1 -0
  40. data/app/models/decidim/moderation.rb +13 -0
  41. data/app/models/decidim/newsletter.rb +1 -0
  42. data/app/models/decidim/organization.rb +2 -0
  43. data/app/models/decidim/participatory_process.rb +11 -0
  44. data/app/models/decidim/participatory_process_group.rb +15 -0
  45. data/app/models/decidim/participatory_process_step.rb +1 -1
  46. data/app/models/decidim/report.rb +23 -0
  47. data/app/services/decidim/public_processes.rb +42 -0
  48. data/app/services/decidim/resource_search.rb +17 -1
  49. data/app/services/decidim/static_map_generator.rb +49 -0
  50. data/app/uploaders/decidim/application_uploader.rb +4 -1
  51. data/app/uploaders/decidim/official_image_footer_uploader.rb +2 -2
  52. data/app/uploaders/decidim/official_image_header_uploader.rb +1 -1
  53. data/app/validators/geocoding_validator.rb +22 -0
  54. data/app/views/decidim/authorizations/new.html.erb +1 -1
  55. data/app/views/decidim/participatory_process_groups/_participatory_process_group.html.erb +22 -0
  56. data/app/views/decidim/participatory_process_groups/show.html.erb +11 -0
  57. data/app/views/decidim/participatory_processes/index.html.erb +1 -1
  58. data/app/views/decidim/participatory_processes/show.html.erb +18 -5
  59. data/app/views/decidim/reported_mailer/hide.html.erb +5 -0
  60. data/app/views/decidim/reported_mailer/report.html.erb +5 -0
  61. data/app/views/decidim/shared/_address_details.html.erb +9 -0
  62. data/app/views/decidim/shared/_flag_modal.html.erb +20 -0
  63. data/app/views/decidim/shared/_share_modal.html.erb +5 -5
  64. data/app/views/decidim/shared/_static_map.html.erb +17 -0
  65. data/app/views/devise/mailer/invite_collaborator.html.erb +17 -0
  66. data/app/views/devise/mailer/invite_collaborator.text.erb +15 -0
  67. data/app/views/layouts/decidim/_application.html.erb +5 -12
  68. data/app/views/layouts/decidim/{_social_meta.html.erb → _head.html.erb} +13 -0
  69. data/app/views/layouts/decidim/_head_extra.html.erb +7 -0
  70. data/app/views/layouts/decidim/_process_header.html.erb +15 -9
  71. data/app/views/layouts/decidim/_process_header_steps.html.erb +3 -3
  72. data/app/views/layouts/decidim/{_header.html.erb → _wrapper.html.erb} +47 -10
  73. data/app/views/pages/home/_highlighted_processes.html.erb +2 -2
  74. data/config/i18n-tasks.yml +3 -0
  75. data/config/locales/ca.yml +40 -1
  76. data/config/locales/en.yml +40 -1
  77. data/config/locales/es.yml +40 -1
  78. data/config/locales/eu.yml +235 -1
  79. data/config/locales/fi.yml +375 -0
  80. data/config/routes.rb +4 -0
  81. data/db/migrate/20170215115407_add_organization_custom_reference.rb +11 -0
  82. data/db/migrate/20170220110740_remove_steps_short_description.rb +21 -0
  83. data/db/migrate/20170221094835_add_scopes_to_processes.rb +6 -0
  84. data/db/migrate/20170228142440_add_participatory_process_groups.rb +15 -0
  85. data/db/migrate/20170306144354_add_secondary_hosts_to_organizations.rb +5 -0
  86. data/db/migrate/20170307084957_create_reports.rb +15 -0
  87. data/db/migrate/20170308091316_create_moderations.rb +12 -0
  88. data/db/migrate/20170313095436_add_available_authorizations_to_organization.rb +10 -0
  89. data/db/seeds.rb +20 -10
  90. data/lib/decidim/core.rb +12 -1
  91. data/lib/decidim/core/api.rb +1 -0
  92. data/lib/decidim/core/api/decidim_type.rb +12 -0
  93. data/lib/decidim/core/api/process_step_type.rb +0 -6
  94. data/lib/decidim/core/api/user_type.rb +4 -0
  95. data/lib/decidim/core/engine.rb +27 -0
  96. data/lib/decidim/core/test.rb +5 -0
  97. data/lib/decidim/core/test/factories.rb +52 -3
  98. data/lib/decidim/core/test/shared_examples/comments_examples.rb +215 -0
  99. data/lib/decidim/core/test/shared_examples/has_reference.rb +30 -0
  100. data/lib/decidim/core/test/shared_examples/manage_moderations_examples.rb +75 -0
  101. data/lib/decidim/core/test/shared_examples/reportable.rb +44 -0
  102. data/lib/decidim/core/test/shared_examples/reports_examples.rb +64 -0
  103. data/lib/decidim/core/version.rb +2 -2
  104. data/lib/decidim/has_reference.rb +50 -0
  105. data/lib/decidim/query_extensions.rb +4 -0
  106. data/lib/decidim/reportable.rb +46 -0
  107. data/vendor/assets/javascripts/leaflet-svg-icon.js +179 -0
  108. data/vendor/assets/javascripts/leaflet-tilelayer-here.js +166 -0
  109. data/vendor/assets/javascripts/leaflet.js +9 -0
  110. data/vendor/assets/javascripts/leaflet.markercluster.js +7 -0
  111. data/vendor/assets/javascripts/quill.min.js +8 -8
  112. data/vendor/assets/javascripts/quill.min.js.map +1 -1
  113. data/vendor/assets/stylesheets/MarkerCluster.Default.css +60 -0
  114. data/vendor/assets/stylesheets/MarkerCluster.css +14 -0
  115. data/vendor/assets/stylesheets/leaflet.css +624 -0
  116. data/vendor/assets/stylesheets/quill.bubble.css +75 -4
  117. data/vendor/assets/stylesheets/quill.core.css +21 -2
  118. data/vendor/assets/stylesheets/quill.snow.css +29 -3
  119. metadata +107 -27
  120. data/app/views/layouts/decidim/_footer.html.erb +0 -36
  121. data/app/views/layouts/decidim/_meta.html.erb +0 -4
@@ -0,0 +1,215 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ RSpec.shared_examples "comments" do
4
+ let!(:organization) { create(:organization) }
5
+ let!(:user) { create(:user, :confirmed, organization: organization) }
6
+ let!(:comments) {
7
+ 3.times.map do
8
+ create(:comment, commentable: commentable)
9
+ end
10
+ }
11
+ let(:authenticated) { false }
12
+
13
+ def visit_commentable_path
14
+ if authenticated
15
+ login_as user, scope: :user
16
+ end
17
+ visit resource_path
18
+ end
19
+
20
+ before do
21
+ switch_to_host(organization.host)
22
+ end
23
+
24
+ it "user should see a list of comments" do
25
+ visit_commentable_path
26
+
27
+ expect(page).to have_selector("#comments")
28
+ expect(page).to have_selector("article.comment", count: comments.length)
29
+
30
+ within "#comments" do
31
+ comments.each do |comment|
32
+ expect(page).to have_content comment.author.name
33
+ expect(page).to have_content comment.body
34
+ end
35
+ end
36
+ end
37
+
38
+ it "user should be able to sort the comments" do
39
+ comment = create(:comment, commentable: commentable, body: "Most Rated Comment")
40
+ create(:comment_vote, comment: comment, author: user, weight: 1)
41
+
42
+ visit_commentable_path
43
+
44
+ within ".order-by" do
45
+ page.find('.dropdown.menu .is-dropdown-submenu-parent').hover
46
+ end
47
+
48
+ click_link "Best rated"
49
+
50
+ within "#comments" do
51
+ expect(page.find('.comment', match: :first)).to have_content "Most Rated Comment"
52
+ end
53
+ end
54
+
55
+ context "when not authenticated" do
56
+ it "user should not see the form to add comments" do
57
+ visit_commentable_path
58
+ expect(page).not_to have_selector(".add-comment form")
59
+ end
60
+ end
61
+
62
+ context "when authenticated" do
63
+ let(:authenticated) { true }
64
+
65
+ it "user sees the form to add comments" do
66
+ visit_commentable_path
67
+
68
+ expect(page).to have_selector(".add-comment form")
69
+ end
70
+
71
+ context "when user adds a new comment" do
72
+ before do
73
+ visit_commentable_path
74
+
75
+ expect(page).to have_selector(".add-comment form")
76
+
77
+ within ".add-comment form" do
78
+ fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: "This is a new comment"
79
+ click_button "Send"
80
+ end
81
+ end
82
+
83
+ it "user visualize the comment" do
84
+ within "#comments" do
85
+ expect(page).to have_content user.name
86
+ expect(page).to have_content "This is a new comment"
87
+ end
88
+ end
89
+
90
+ it "commentable's author receives notificatione" do
91
+ if commentable.respond_to? :author
92
+ wait_for_email subject: "new comment"
93
+ login_as commentable.author, scope: :user
94
+ visit last_email_first_link
95
+
96
+ within "#comments" do
97
+ expect(page).to have_content user.name
98
+ expect(page).to have_content "This is a new comment"
99
+ end
100
+ else
101
+ expect {
102
+ wait_for_email subject: "new comment"
103
+ }.to raise_error StandardError
104
+ end
105
+ end
106
+ end
107
+
108
+ context "when the user has verified organizations" do
109
+ let(:user_group) { create(:user_group, :verified) }
110
+
111
+ before do
112
+ create(:user_group_membership, user: user, user_group: user_group)
113
+ end
114
+
115
+ it "user can add a new comment as a user group" do
116
+ visit_commentable_path
117
+
118
+ expect(page).to have_selector(".add-comment form")
119
+
120
+ within ".add-comment form" do
121
+ fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: "This is a new comment"
122
+ select user_group.name, from: "Comment as"
123
+ click_button "Send"
124
+ end
125
+
126
+ within "#comments" do
127
+ expect(page).to have_content user_group.name
128
+ expect(page).to have_content "This is a new comment"
129
+ end
130
+ end
131
+ end
132
+
133
+ context "when a user replies a coment" do
134
+ let!(:comment_author) { create(:user, :confirmed, organization: organization) }
135
+ let!(:comment) { create(:comment, commentable: commentable, author: comment_author) }
136
+
137
+ before do
138
+ visit_commentable_path
139
+
140
+ expect(page).to have_selector(".comment__reply")
141
+
142
+ within "#comments #comment_#{comment.id}" do
143
+ click_button "Reply"
144
+ find("textarea").set("This is a reply")
145
+ click_button "Send"
146
+ end
147
+ end
148
+
149
+ it "user visualize the reply" do
150
+ within "#comments #comment_#{comment.id}" do
151
+ expect(page).to have_content "This is a reply"
152
+ end
153
+ end
154
+
155
+ it "comment's author receives notification" do
156
+ wait_for_email subject: "new reply"
157
+ login_as comment.author, scope: :user
158
+ visit last_email_first_link
159
+
160
+ within "#comments #comment_#{comment.id}" do
161
+ expect(page).to have_content "This is a reply"
162
+ end
163
+ end
164
+ end
165
+
166
+ context "when arguable option is enabled" do
167
+ before do
168
+ expect_any_instance_of(commentable.class).to receive(:comments_have_alignment?).and_return(true)
169
+ end
170
+
171
+ it "user can comment in favor" do
172
+ visit_commentable_path
173
+
174
+ expect(page).to have_selector(".add-comment form")
175
+
176
+ page.find('.opinion-toggle--ok').click
177
+
178
+ within ".add-comment form" do
179
+ fill_in "add-comment-#{commentable.commentable_type}-#{commentable.id}", with: "I am in favor about this!"
180
+ click_button "Send"
181
+ end
182
+
183
+ within "#comments" do
184
+ expect(page).to have_selector 'span.success.label', text: "In favor"
185
+ end
186
+ end
187
+ end
188
+
189
+ context "when votable option is enabled" do
190
+ before do
191
+ expect_any_instance_of(commentable.class).to receive(:comments_have_votes?).and_return(true)
192
+ end
193
+
194
+ it "user can upvote a comment" do
195
+ visit_commentable_path
196
+
197
+ within "#comment_#{comments[0].id}" do
198
+ expect(page).to have_selector('.comment__votes--up', text: /0/)
199
+ page.find('.comment__votes--up').click
200
+ expect(page).to have_selector('.comment__votes--up', text: /1/)
201
+ end
202
+ end
203
+
204
+ it "user can downvote a comment" do
205
+ visit_commentable_path
206
+
207
+ within "#comment_#{comments[0].id}" do
208
+ expect(page).to have_selector('.comment__votes--down', text: /0/)
209
+ page.find('.comment__votes--down').click
210
+ expect(page).to have_selector('.comment__votes--down', text: /1/)
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ shared_examples_for "has reference" do
3
+ context "when the reference is nil" do
4
+ before do
5
+ subject[:reference] = nil
6
+ end
7
+
8
+ it "generates a valid reference" do
9
+ expect(subject.reference).to match(/[A-z]+/)
10
+ end
11
+ end
12
+
13
+ context "when the reference is already set" do
14
+ before do
15
+ subject[:reference] = "ARBITRARYREF"
16
+ end
17
+
18
+ it "keeps the pre-existing reference" do
19
+ expect(subject.reference).to eq("ARBITRARYREF")
20
+ end
21
+ end
22
+
23
+ context "when saving" do
24
+ it "stores the reference" do
25
+ subject.reference = nil
26
+ subject.save!
27
+ expect(subject.reload.reference).to_not be_blank
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,75 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ RSpec.shared_examples "manage moderations" do
4
+ let!(:moderations) do
5
+ reportables.first(reportables.length - 1).map do |reportable|
6
+ moderation = create(:moderation, reportable: reportable, report_count: 1)
7
+ create(:report, moderation: moderation)
8
+ moderation
9
+ end
10
+ end
11
+ let!(:moderation) { moderations.first }
12
+ let!(:hidden_moderations) do
13
+ reportables.last(1).map do |reportable|
14
+ moderation = create(:moderation, reportable: reportable, report_count: 3, hidden_at: Time.current)
15
+ create_list(:report, 3, moderation: moderation)
16
+ moderation
17
+ end
18
+ end
19
+
20
+ before do
21
+ visit decidim_admin.participatory_process_path(participatory_process)
22
+ click_link "Moderations"
23
+ end
24
+
25
+ context "listing moderations" do
26
+ it "user can review them" do
27
+ click_link "Moderations"
28
+
29
+ moderations.each do |moderation|
30
+ within "tr[data-id=\"#{moderation.id}\"]" do
31
+ expect(page).to have_content moderation.reportable.reported_content
32
+ expect(page).to have_content moderation.reports.first.reason
33
+ end
34
+ end
35
+ end
36
+
37
+ it "user can un-report a resource" do
38
+ click_link "Moderations"
39
+
40
+ within "tr[data-id=\"#{moderation.id}\"]" do
41
+ click_link "Unreport"
42
+ end
43
+
44
+ within ".flash" do
45
+ expect(page).to have_content("Resource successfully unreported")
46
+ end
47
+ end
48
+
49
+ it "user can hide a resource" do
50
+ click_link "Moderations"
51
+
52
+ within "tr[data-id=\"#{moderation.id}\"]" do
53
+ click_link "Hide"
54
+ end
55
+
56
+ within ".flash" do
57
+ expect(page).to have_content("Resource successfully hidden")
58
+ end
59
+
60
+ expect(page).to have_no_content(moderation.reportable.reported_content)
61
+ end
62
+ end
63
+
64
+ context "listing hidden resources" do
65
+ it "user can review them" do
66
+ click_link "Hidden"
67
+
68
+ hidden_moderations.each do |moderation|
69
+ within "tr[data-id=\"#{moderation.id}\"]" do
70
+ expect(page).to have_content moderation.reportable.reported_content
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
3
+
4
+ shared_examples_for "reportable" do
5
+ let(:user) { create(:user, organization: subject.organization) }
6
+ let(:participatory_process) { subject.feature.participatory_process }
7
+ let(:moderation) { create(:moderation, reportable: subject, participatory_process: participatory_process, report_count: 1) }
8
+ let!(:report) { create(:report, moderation: moderation, user: user) }
9
+
10
+ describe "#reported_by?" do
11
+ context "when the resource has not been reported by the given user" do
12
+ let!(:report) { nil }
13
+
14
+ it { expect(subject.reported_by?(user)).to be_falsey }
15
+ end
16
+
17
+ context "when the resource has been reported" do
18
+ it { expect(subject.reported_by?(user)).to be_truthy }
19
+ end
20
+ end
21
+
22
+ context "#hidden?" do
23
+ context "when the resource has not been hidden" do
24
+ it { expect(subject).not_to be_hidden }
25
+ end
26
+
27
+ context "when the resource has been hidden" do
28
+ let(:moderation) { create(:moderation, reportable: subject, participatory_process: participatory_process, report_count: 1, hidden_at: Time.current) }
29
+ it { expect(subject).to be_hidden }
30
+ end
31
+ end
32
+
33
+ context "#reported?" do
34
+ context "when the report count is equal to 0" do
35
+ let(:moderation) { create(:moderation, reportable: subject, participatory_process: participatory_process, report_count: 0) }
36
+ let!(:report) { nil }
37
+ it { expect(subject).not_to be_reported }
38
+ end
39
+
40
+ context "when the report count is greater than 0" do
41
+ it { expect(subject).to be_reported }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ RSpec.shared_examples "reports" do
4
+ context "when the user is not logged in" do
5
+ it "should be given the option to sign in" do
6
+ visit reportable_path
7
+
8
+ expect(page).to have_selector('.author-data__extra')
9
+
10
+ within ".author-data__extra", match: :first do
11
+ page.find('button').click
12
+ end
13
+
14
+ expect(page).to have_css('#loginModal', visible: true)
15
+ end
16
+ end
17
+
18
+ context "when the user is logged in" do
19
+ before do
20
+ login_as user, scope: :user
21
+ end
22
+
23
+ context "and the user has not reported the resource yet" do
24
+ it "reports the resource" do
25
+ visit reportable_path
26
+
27
+ expect(page).to have_selector('.author-data__extra')
28
+
29
+ within ".author-data__extra", match: :first do
30
+ page.find('button').click
31
+ end
32
+
33
+ expect(page).to have_css('.flag-modal', visible: true)
34
+
35
+ within ".flag-modal" do
36
+ click_button "Report"
37
+ end
38
+
39
+ expect(page).to have_content "report has been created"
40
+ end
41
+ end
42
+
43
+ context "and the user has reported the resource previously" do
44
+ before do
45
+ moderation = create(:moderation, reportable: reportable, participatory_process: participatory_process)
46
+ create(:report, moderation: moderation, user: user, reason: "spam")
47
+ end
48
+
49
+ it "cannot report it twice" do
50
+ visit reportable_path
51
+
52
+ expect(page).to have_selector('.author-data__extra')
53
+
54
+ within ".author-data__extra", match: :first do
55
+ page.find('button').click
56
+ end
57
+
58
+ expect(page).to have_css('.flag-modal', visible: true)
59
+
60
+ expect(page).to have_content "already reported"
61
+ end
62
+ end
63
+ end
64
+ end
@@ -2,11 +2,11 @@
2
2
  # This holds Decidim's version and the Rails version on which it depends.
3
3
  module Decidim
4
4
  def self.version
5
- "0.0.5"
5
+ "0.0.6"
6
6
  end
7
7
 
8
8
  def self.rails_version
9
- ["~> 5.0.0", ">= 5.0.0.1"]
9
+ ["~> 5.0.2"]
10
10
  end
11
11
 
12
12
  def self.add_default_gemspec_properties(spec)