decidim-conferences 0.23.5 → 0.24.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/conferences/conference_speaker/show.erb +1 -1
  3. data/app/cells/decidim/conferences/media_link/show.erb +1 -1
  4. data/app/cells/decidim/conferences/media_link_cell.rb +1 -0
  5. data/app/commands/decidim/conferences/admin/create_conference_speaker.rb +40 -18
  6. data/app/commands/decidim/conferences/admin/create_partner.rb +33 -14
  7. data/app/commands/decidim/conferences/admin/invite_user_to_join_conference.rb +1 -1
  8. data/app/commands/decidim/conferences/admin/update_conference_speaker.rb +41 -17
  9. data/app/commands/decidim/conferences/admin/update_partner.rb +30 -10
  10. data/app/controllers/decidim/conferences/admin/imports_controller.rb +14 -0
  11. data/app/controllers/decidim/conferences/admin/moderations/reports_controller.rb +14 -0
  12. data/app/forms/decidim/conferences/admin/conference_form.rb +3 -2
  13. data/app/forms/decidim/conferences/admin/conference_speaker_form.rb +1 -1
  14. data/app/forms/decidim/conferences/admin/media_link_form.rb +1 -1
  15. data/app/forms/decidim/conferences/admin/partner_form.rb +2 -1
  16. data/app/models/decidim/conference_meeting.rb +1 -1
  17. data/app/models/decidim/conference_speaker.rb +1 -1
  18. data/app/models/decidim/conference_speaker_conference_meeting.rb +2 -2
  19. data/app/models/decidim/conferences/conference_meeting_registration_type.rb +2 -2
  20. data/app/models/decidim/conferences/registration_type.rb +1 -1
  21. data/app/permissions/decidim/conferences/permissions.rb +1 -1
  22. data/app/presenters/decidim/conferences/conference_stats_presenter.rb +1 -1
  23. data/app/views/decidim/conferences/admin/conference_invites/index.html.erb +1 -1
  24. data/app/views/decidim/conferences/admin/conference_registrations/index.html.erb +1 -1
  25. data/app/views/decidim/conferences/admin/partners/_form.html.erb +1 -1
  26. data/app/views/layouts/decidim/admin/conference.html.erb +2 -1
  27. data/config/locales/ar.yml +6 -4
  28. data/config/locales/ca.yml +50 -3
  29. data/config/locales/cs.yml +51 -4
  30. data/config/locales/de.yml +16 -3
  31. data/config/locales/el.yml +6 -4
  32. data/config/locales/en.yml +50 -3
  33. data/config/locales/es-MX.yml +50 -3
  34. data/config/locales/es-PY.yml +50 -3
  35. data/config/locales/es.yml +50 -3
  36. data/config/locales/eu.yml +6 -4
  37. data/config/locales/fi-plain.yml +50 -3
  38. data/config/locales/fi.yml +50 -3
  39. data/config/locales/fr-CA.yml +16 -3
  40. data/config/locales/fr.yml +16 -3
  41. data/config/locales/gl.yml +35 -4
  42. data/config/locales/hu.yml +6 -4
  43. data/config/locales/id-ID.yml +6 -4
  44. data/config/locales/it.yml +6 -4
  45. data/config/locales/ja.yml +12 -4
  46. data/config/locales/lv.yml +6 -4
  47. data/config/locales/nl.yml +50 -3
  48. data/config/locales/no.yml +6 -4
  49. data/config/locales/pl.yml +16 -3
  50. data/config/locales/pt-BR.yml +6 -4
  51. data/config/locales/pt.yml +6 -4
  52. data/config/locales/ro-RO.yml +16 -3
  53. data/config/locales/sk.yml +6 -4
  54. data/config/locales/sv.yml +50 -3
  55. data/config/locales/tr-TR.yml +13 -4
  56. data/config/locales/zh-CN.yml +6 -4
  57. data/db/migrate/20210310134942_add_followable_counter_cache_to_conferences.rb +16 -0
  58. data/lib/decidim/api/conference_media_link_type.rb +18 -0
  59. data/lib/decidim/api/conference_partner_type.rb +19 -0
  60. data/lib/decidim/api/conference_speaker_type.rb +23 -0
  61. data/lib/decidim/api/conference_type.rb +42 -0
  62. data/lib/decidim/conferences.rb +1 -0
  63. data/lib/decidim/conferences/admin_engine.rb +3 -1
  64. data/lib/decidim/conferences/api.rb +10 -0
  65. data/lib/decidim/conferences/engine.rb +7 -1
  66. data/lib/decidim/conferences/participatory_space.rb +25 -25
  67. data/lib/decidim/conferences/query_extensions.rb +43 -0
  68. data/lib/decidim/conferences/test/factories.rb +6 -6
  69. data/lib/decidim/conferences/version.rb +1 -1
  70. metadata +21 -16
  71. data/app/types/decidim/conferences/conference_media_link_type.rb +0 -19
  72. data/app/types/decidim/conferences/conference_partner_type.rb +0 -20
  73. data/app/types/decidim/conferences/conference_speaker_type.rb +0 -24
  74. data/app/types/decidim/conferences/conference_type.rb +0 -45
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ee7cca7520230899db84d694fb32e531293328d58361977d5b99117e5c3c3616
4
- data.tar.gz: 388fafe3b51dba6f6f5cf11b17a1808edc5e7f80701d1a216480c1a663c31467
3
+ metadata.gz: 2d72cf762e147a1d86a4f26e60252c6bdde45f72901c2335d7daaa391fdc1ff9
4
+ data.tar.gz: 42b7e84dadcf37b9e9c3dec1898aaeea067b421f5296dc7686de2c8d038e3a24
5
5
  SHA512:
6
- metadata.gz: 377e17031d95b8e7f308d98ec98758a0cb422493e536cdf3ddbdb8d80082b910059b5f43fbd7542426bc68d2e255fd11586736a15d20c4c79089bad5be0976e3
7
- data.tar.gz: 0e576c273b6b1cfdec7b8c652de6c8adc3c2a40327ba0396556d7b34f89f5c508ffd115a7374015d89c9f6a01d217a0281f447360fa2c64df5e0687c583b082d
6
+ metadata.gz: 4ec7796e843fc8aa190acd65dfd8f74c9e2375f95f3e03b6abc2fa30b1113a87433acaec813e059076b77acbf82e0fe930aed463134892053dcb79cffeabe9a3
7
+ data.tar.gz: 1840f5f37445b48a3ca91202e0808497fa861ae982f64cde79df44b317dc91c6c1032af99219f7c8829491b2925f72a66eb3321839856a9c8c7a1c56fb51ea61
@@ -70,7 +70,7 @@
70
70
  <hr class="reset mt-none mb-s">
71
71
  <div class="row">
72
72
  <div class="column medium-12">
73
- <div class="bio-acts">Speaking at</div>
73
+ <div class="bio-acts"><%= t("conferences.conference_speaker.show.speaking_at", scope: "decidim") %></div>
74
74
 
75
75
  <ul class="list-reset">
76
76
  <% meetings.each do |meeting| %>
@@ -2,7 +2,7 @@
2
2
  <%= icon "external-link", role: "img", "aria-hidden": true %>
3
3
  <div>
4
4
  <%= link_to model.link, target: "_blank" do %>
5
- <strong><%= translated_attribute(model.title) %> </strong>
5
+ <strong><%= decidim_html_escape translated_attribute(model.title) %> </strong>
6
6
  <% end %>
7
7
  <div class="text-small"><%= l(model.date, format: :decidim_short_with_month_name_short) %> · <%= model.link %></div>
8
8
  </div>
@@ -5,6 +5,7 @@ module Decidim
5
5
  # This cell renders the media link card for an instance of a MediaLink
6
6
  class MediaLinkCell < Decidim::ViewModel
7
7
  include Decidim::LayoutHelper
8
+ include Decidim::SanitizeHelper
8
9
 
9
10
  def show
10
11
  render
@@ -25,18 +25,52 @@ module Decidim
25
25
  def call
26
26
  return broadcast(:invalid) if form.invalid?
27
27
 
28
- transaction do
29
- create_conference_speaker!
30
- link_meetings(@conference_speaker)
31
- end
28
+ # We are going to assign the attributes only to handle the validation of the avatar before accessing
29
+ # `create_conference_speaker!` which uses `create!`, and this will render an ActiveRecord::RecordInvalid error
30
+ # After we assign and check if the object is valid, we will not save the model to let it be handled the old way
31
+ # If there is an error we add the error to the form
32
+ # We are using this method to assign the conference because if we are trying to assign all at once, there will be thrown a
33
+ # Delegation error
34
+
35
+ if conference_speaker_with_attributes.valid?
32
36
 
33
- broadcast(:ok)
37
+ transaction do
38
+ create_conference_speaker!
39
+ link_meetings(@conference_speaker)
40
+ end
41
+ broadcast(:ok)
42
+ else
43
+ form.errors.add(:avatar, conference_speaker_with_attributes.errors[:avatar]) if conference_speaker_with_attributes.errors.include? :avatar
44
+
45
+ broadcast(:invalid)
46
+ end
34
47
  end
35
48
 
36
49
  private
37
50
 
38
51
  attr_reader :form, :conference, :current_user
39
52
 
53
+ def conference_speaker_with_attributes
54
+ attrs = form.attributes.slice(
55
+ :full_name,
56
+ :twitter_handle,
57
+ :personal_url,
58
+ :avatar,
59
+ :remove_avatar,
60
+ :position,
61
+ :affiliation,
62
+ :short_bio
63
+ ).merge(
64
+ decidim_conference_id: conference.id,
65
+ conference: conference,
66
+ user: form.user
67
+ )
68
+ conference_speaker = conference.speakers.build
69
+ conference_speaker.conference = conference
70
+ conference_speaker.assign_attributes(attrs)
71
+ conference_speaker
72
+ end
73
+
40
74
  def create_conference_speaker!
41
75
  log_info = {
42
76
  resource: {
@@ -50,19 +84,7 @@ module Decidim
50
84
  @conference_speaker = Decidim.traceability.create!(
51
85
  Decidim::ConferenceSpeaker,
52
86
  current_user,
53
- form.attributes.slice(
54
- :full_name,
55
- :position,
56
- :affiliation,
57
- :short_bio,
58
- :twitter_handle,
59
- :personal_url,
60
- :avatar,
61
- :remove_avatar
62
- ).merge(
63
- conference: conference,
64
- user: form.user
65
- ),
87
+ conference_speaker_with_attributes.attributes,
66
88
  log_info
67
89
  )
68
90
  end
@@ -25,11 +25,17 @@ module Decidim
25
25
  def call
26
26
  return broadcast(:invalid) if form.invalid?
27
27
 
28
- transaction do
29
- create_partner!
30
- end
28
+ if conference_partner.valid?
29
+ transaction do
30
+ create_partner!
31
+ end
32
+
33
+ broadcast(:ok)
34
+ else
35
+ form.errors.add(:logo, conference_partner.errors[:logo]) if conference_partner.errors.include? :logo
31
36
 
32
- broadcast(:ok)
37
+ broadcast(:invalid)
38
+ end
33
39
  end
34
40
 
35
41
  private
@@ -49,19 +55,32 @@ module Decidim
49
55
  @partner = Decidim.traceability.create!(
50
56
  Decidim::Conferences::Partner,
51
57
  form.current_user,
52
- { conference: conference }.merge(
53
- form.attributes.slice(
54
- :name,
55
- :weight,
56
- :link,
57
- :partner_type,
58
- :logo,
59
- :remove_avatar
60
- )
61
- ),
58
+ attributes,
62
59
  log_info
63
60
  )
64
61
  end
62
+
63
+ def conference_partner
64
+ return @conference_partner if defined?(@conference_partner)
65
+
66
+ @conference_partner = conference.partners.build
67
+ @conference_partner.conference = conference
68
+ @conference_partner.assign_attributes(attributes)
69
+ @conference_partner
70
+ end
71
+
72
+ def attributes
73
+ { conference: conference }.merge(
74
+ form.attributes.slice(
75
+ :name,
76
+ :weight,
77
+ :link,
78
+ :partner_type,
79
+ :logo,
80
+ :remove_avatar
81
+ )
82
+ )
83
+ end
65
84
  end
66
85
  end
67
86
  end
@@ -37,7 +37,7 @@ module Decidim
37
37
 
38
38
  def already_invited?
39
39
  return false unless user.persisted?
40
- return false unless conference.conference_invites.where(user: user).exists?
40
+ return false unless conference.conference_invites.exists?(user: user)
41
41
 
42
42
  form.errors.add(:email, :already_invited)
43
43
  true
@@ -11,6 +11,7 @@ module Decidim
11
11
  # form - A form object with the params.
12
12
  # conference_speaker - The ConferenceSpeaker to update
13
13
  def initialize(form, conference_speaker)
14
+ form.avatar = conference_speaker.avatar if form.avatar.blank?
14
15
  @form = form
15
16
  @conference_speaker = conference_speaker
16
17
  end
@@ -25,18 +26,52 @@ module Decidim
25
26
  return broadcast(:invalid) if form.invalid?
26
27
  return broadcast(:invalid) unless conference_speaker
27
28
 
28
- transaction do
29
- update_conference_speaker!
30
- link_meetings(@conference_speaker)
31
- end
29
+ # We are going to assign the attributes only to handle the validation of the avatar before accessing
30
+ # `update_conference_speaker!` which uses `update!`. Without this step, the image validation may render
31
+ # an ActiveRecord::RecordInvalid error
32
+ # After we assign and check if the object is valid, we reload the model to let it be handled the old way
33
+ # If there is an error we add the error to the form
34
+ conference_speaker.assign_attributes(attributes)
35
+
36
+ if conference_speaker.valid?
37
+ conference_speaker.reload
32
38
 
33
- broadcast(:ok)
39
+ transaction do
40
+ update_conference_speaker!
41
+ link_meetings(@conference_speaker)
42
+ end
43
+ broadcast(:ok)
44
+ else
45
+ form.errors.add(:avatar, conference_speaker.errors[:avatar]) if conference_speaker.errors.include? :avatar
46
+
47
+ broadcast(:invalid)
48
+ end
34
49
  end
35
50
 
36
51
  private
37
52
 
38
53
  attr_reader :form, :conference_speaker
39
54
 
55
+ def attributes
56
+ form.attributes.slice(
57
+ :full_name,
58
+ :twitter_handle,
59
+ :personal_url,
60
+ :position,
61
+ :affiliation,
62
+ :short_bio
63
+ ).merge(
64
+ user: form.user
65
+ ).merge(uploader_attributes)
66
+ end
67
+
68
+ def uploader_attributes
69
+ {
70
+ avatar: form.avatar,
71
+ remove_avatar: form.remove_avatar
72
+ }.delete_if { |_k, val| val.is_a?(Decidim::ApplicationUploader) }
73
+ end
74
+
40
75
  def update_conference_speaker!
41
76
  log_info = {
42
77
  resource: {
@@ -50,18 +85,7 @@ module Decidim
50
85
  Decidim.traceability.update!(
51
86
  conference_speaker,
52
87
  form.current_user,
53
- form.attributes.slice(
54
- :full_name,
55
- :position,
56
- :affiliation,
57
- :short_bio,
58
- :twitter_handle,
59
- :personal_url,
60
- :avatar,
61
- :remove_avatar
62
- ).merge(
63
- user: form.user
64
- ),
88
+ attributes,
65
89
  log_info
66
90
  )
67
91
  end
@@ -11,6 +11,8 @@ module Decidim
11
11
  # form - A form object with the params.
12
12
  # conference_partner - The ConferencePartner to update
13
13
  def initialize(form, conference_partner)
14
+ form.logo = conference_partner.logo if form.logo.blank?
15
+
14
16
  @form = form
15
17
  @conference_partner = conference_partner
16
18
  end
@@ -25,14 +27,39 @@ module Decidim
25
27
  return broadcast(:invalid) if form.invalid?
26
28
  return broadcast(:invalid) unless conference_partner
27
29
 
28
- update_conference_partner!
29
- broadcast(:ok)
30
+ # We are going to assign the attributes only to handle the validation of the avatar before accessing
31
+ # `update_conference_partner!` which uses `update!`. Without this step, the image validation may render
32
+ # an ActiveRecord::RecordInvalid error
33
+ # After we assign and check if the object is valid, we reload the model to let it be handled the old way
34
+ # If there is an error we add the error to the form
35
+ conference_partner.assign_attributes(attributes)
36
+ if conference_partner.valid?
37
+ conference_partner.reload
38
+
39
+ update_conference_partner!
40
+ broadcast(:ok)
41
+ else
42
+ form.errors.add(:logo, conference_partner.errors[:logo]) if conference_partner.errors.include? :logo
43
+
44
+ broadcast(:invalid)
45
+ end
30
46
  end
31
47
 
32
48
  private
33
49
 
34
50
  attr_reader :form, :conference_partner
35
51
 
52
+ def attributes
53
+ form.attributes.slice(
54
+ :name,
55
+ :weight,
56
+ :partner_type,
57
+ :link,
58
+ :logo,
59
+ :remove_logo
60
+ )
61
+ end
62
+
36
63
  def update_conference_partner!
37
64
  log_info = {
38
65
  resource: {
@@ -46,14 +73,7 @@ module Decidim
46
73
  Decidim.traceability.update!(
47
74
  conference_partner,
48
75
  form.current_user,
49
- form.attributes.slice(
50
- :name,
51
- :weight,
52
- :partner_type,
53
- :link,
54
- :logo,
55
- :remove_logo
56
- ),
76
+ attributes,
57
77
  log_info
58
78
  )
59
79
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Conferences
5
+ module Admin
6
+ # This controller allows importing things.
7
+ # It is targeted for customizations for importing things that lives under
8
+ # an conference.
9
+ class ImportsController < Decidim::Admin::ImportsController
10
+ include Concerns::ConferenceAdmin
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Conferences
5
+ module Admin
6
+ module Moderations
7
+ # This controller allows admins to manage moderation reports in an conference.
8
+ class ReportsController < Decidim::Admin::Moderations::ReportsController
9
+ include Concerns::ConferenceAdmin
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -43,12 +43,13 @@ module Decidim
43
43
 
44
44
  validate :slug_uniqueness
45
45
 
46
+ validates :available_slots, presence: true, if: ->(form) { form.registrations_enabled? }
47
+ validates :available_slots, numericality: { greater_than_or_equal_to: 0 }, if: ->(form) { form.registrations_enabled? && form.available_slots.present? }
46
48
  validates :registration_terms, translatable_presence: true, if: ->(form) { form.registrations_enabled? }
47
- validates :available_slots, numericality: { greater_than_or_equal_to: 0 }, if: ->(form) { form.registrations_enabled? }
48
49
 
49
50
  validates :hero_image, passthru: { to: Decidim::Conference }
50
51
  validates :banner_image, passthru: { to: Decidim::Conference }
51
- validate :available_slots_greater_than_or_equal_to_registrations_count, if: ->(form) { form.registrations_enabled? && form.available_slots.positive? }
52
+ validate :available_slots_greater_than_or_equal_to_registrations_count, if: ->(form) { form.registrations_enabled? && form.available_slots.try(:positive?) }
52
53
 
53
54
  validates :start_date, presence: true, date: { before_or_equal_to: :end_date }
54
55
  validates :end_date, presence: true, date: { after_or_equal_to: :start_date }
@@ -43,7 +43,7 @@ module Decidim
43
43
  def personal_url
44
44
  return if super.blank?
45
45
 
46
- return "http://" + super unless super.match?(%r{\A(http|https)://}i)
46
+ return "http://#{super}" unless super.match?(%r{\A(http|https)://}i)
47
47
 
48
48
  super
49
49
  end
@@ -21,7 +21,7 @@ module Decidim
21
21
  def link
22
22
  return if super.blank?
23
23
 
24
- return "http://" + super unless super.match?(%r{\A(http|https)://}i)
24
+ return "http://#{super}" unless super.match?(%r{\A(http|https)://}i)
25
25
 
26
26
  super
27
27
  end
@@ -17,6 +17,7 @@ module Decidim
17
17
  attribute :remove_logo
18
18
 
19
19
  validates :name, :partner_type, presence: true, if: ->(form) { form.logo.present? }
20
+ validates :logo, presence: true, unless: ->(form) { form.logo.present? }
20
21
  validates :logo, passthru: {
21
22
  to: Decidim::Conferences::Partner,
22
23
  with: {
@@ -38,7 +39,7 @@ module Decidim
38
39
  def link
39
40
  return if super.blank?
40
41
 
41
- return "http://" + super unless super.match?(%r{\A(http|https)://}i)
42
+ return "http://#{super}" unless super.match?(%r{\A(http|https)://}i)
42
43
 
43
44
  super
44
45
  end
@@ -4,7 +4,7 @@ module Decidim
4
4
  # It represents a meeting of the conference
5
5
  class ConferenceMeeting < Decidim::Meetings::Meeting
6
6
  has_many :conference_speaker_conference_meetings, dependent: :destroy
7
- has_many :conference_speakers, through: :conference_speaker_conference_meetings, foreign_key: "conference_meeting_id", class_name: "Decidim::ConferenceSpeaker"
7
+ has_many :conference_speakers, through: :conference_speaker_conference_meetings, class_name: "Decidim::ConferenceSpeaker"
8
8
  has_many :conference_meeting_registration_types, dependent: :destroy
9
9
  has_many :registration_types, through: :conference_meeting_registration_types, foreign_key: "registration_type_id", class_name: "Decidim::Conferences::RegistrationType"
10
10
  end
@@ -14,7 +14,7 @@ module Decidim
14
14
  belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User", optional: true
15
15
  belongs_to :conference, foreign_key: "decidim_conference_id", class_name: "Decidim::Conference"
16
16
  has_many :conference_speaker_conference_meetings, dependent: :destroy
17
- has_many :conference_meetings, through: :conference_speaker_conference_meetings, foreign_key: "conference_speaker_id", class_name: "Decidim::ConferenceMeeting"
17
+ has_many :conference_meetings, through: :conference_speaker_conference_meetings, class_name: "Decidim::ConferenceMeeting"
18
18
 
19
19
  default_scope { order(full_name: :asc, created_at: :asc) }
20
20