decidim-meetings 0.13.1 → 0.14.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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_meetings_manifest.js +1 -0
  3. data/app/assets/javascripts/decidim/meetings/admin/registrations_invite_form.es6 +25 -0
  4. data/app/cells/decidim/meetings/join_meeting_button/show.erb +2 -0
  5. data/app/cells/decidim/meetings/meeting_cell.rb +1 -1
  6. data/app/commands/decidim/meetings/admin/invite_user_to_join_meeting.rb +57 -8
  7. data/app/commands/decidim/meetings/admin/validate_registration_code.rb +51 -0
  8. data/app/commands/decidim/meetings/decline_invitation.rb +45 -0
  9. data/app/commands/decidim/meetings/join_meeting.rb +8 -3
  10. data/app/controllers/decidim/meetings/admin/attachment_collections_controller.rb +0 -4
  11. data/app/controllers/decidim/meetings/admin/attachments_controller.rb +0 -4
  12. data/app/controllers/decidim/meetings/admin/invites_controller.rb +14 -5
  13. data/app/controllers/decidim/meetings/admin/registrations_controller.rb +20 -0
  14. data/app/controllers/decidim/meetings/registrations_controller.rb +16 -0
  15. data/app/events/decidim/meetings/registration_code_validated_event.rb +15 -0
  16. data/app/forms/decidim/meetings/admin/close_meeting_form.rb +1 -1
  17. data/app/forms/decidim/meetings/admin/meeting_registration_invite_form.rb +9 -2
  18. data/app/forms/decidim/meetings/admin/validate_registration_code_form.rb +33 -0
  19. data/app/mailers/decidim/meetings/registration_mailer.rb +2 -1
  20. data/app/models/decidim/meetings/invite.rb +38 -0
  21. data/app/models/decidim/meetings/meeting.rb +6 -0
  22. data/app/models/decidim/meetings/registration.rb +18 -0
  23. data/app/permissions/decidim/meetings/admin/permissions.rb +2 -2
  24. data/app/permissions/decidim/meetings/permissions.rb +8 -1
  25. data/app/presenters/decidim/meetings/admin_log/invite_presenter.rb +35 -0
  26. data/app/presenters/decidim/meetings/invite_presenter.rb +26 -0
  27. data/app/queries/decidim/meetings/admin/invites.rb +59 -0
  28. data/app/serializers/decidim/meetings/data_portability_invite_serializer.rb +35 -0
  29. data/app/serializers/decidim/meetings/data_portability_registration_serializer.rb +1 -0
  30. data/app/serializers/decidim/meetings/registration_serializer.rb +1 -0
  31. data/app/views/decidim/meetings/admin/invite_join_meeting_mailer/invite.html.erb +1 -0
  32. data/app/views/decidim/meetings/admin/invites/_form.html.erb +34 -5
  33. data/app/views/decidim/meetings/admin/invites/index.html.erb +99 -0
  34. data/app/views/decidim/meetings/admin/meeting_copies/new.html.erb +1 -1
  35. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +2 -3
  36. data/app/views/decidim/meetings/admin/meetings/index.html.erb +2 -0
  37. data/app/views/decidim/meetings/admin/registrations/_form.html.erb +1 -1
  38. data/app/views/decidim/meetings/admin/registrations/edit.html.erb +24 -0
  39. data/app/views/decidim/meetings/meetings/_meetings.html.erb +1 -1
  40. data/app/views/decidim/meetings/meetings/index.js.erb +0 -1
  41. data/app/views/decidim/meetings/meetings/show.html.erb +9 -0
  42. data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +2 -0
  43. data/app/views/decidim/participatory_spaces/_meeting.html.erb +1 -1
  44. data/app/views/devise/mailer/join_meeting.html.erb +1 -0
  45. data/app/views/devise/mailer/join_meeting.text.erb +4 -0
  46. data/config/locales/ca.yml +53 -5
  47. data/config/locales/en.yml +53 -5
  48. data/config/locales/es-PY.yml +52 -4
  49. data/config/locales/es.yml +53 -5
  50. data/config/locales/eu.yml +52 -4
  51. data/config/locales/fi.yml +164 -116
  52. data/config/locales/fr.yml +53 -5
  53. data/config/locales/gl.yml +52 -4
  54. data/config/locales/hu.yml +391 -0
  55. data/config/locales/it.yml +52 -4
  56. data/config/locales/nl.yml +52 -4
  57. data/config/locales/pl.yml +52 -4
  58. data/config/locales/pt-BR.yml +56 -8
  59. data/config/locales/pt.yml +52 -4
  60. data/config/locales/ru.yml +57 -9
  61. data/config/locales/sv.yml +135 -87
  62. data/config/locales/uk.yml +56 -8
  63. data/db/migrate/20180607142020_create_decidim_meetings_invites.rb +15 -0
  64. data/db/migrate/20180615160839_add_code_to_decidim_meetings_registrations.rb +7 -0
  65. data/db/migrate/20180711111023_add_validated_at_to_decidim_meetings_registrations.rb +7 -0
  66. data/lib/decidim/meetings.rb +1 -0
  67. data/lib/decidim/meetings/admin_engine.rb +3 -1
  68. data/lib/decidim/meetings/component.rb +2 -0
  69. data/lib/decidim/meetings/engine.rb +1 -0
  70. data/lib/decidim/meetings/registrations.rb +14 -0
  71. data/lib/decidim/meetings/registrations/code_generator.rb +39 -0
  72. data/lib/decidim/meetings/test/factories.rb +20 -4
  73. data/lib/decidim/meetings/version.rb +1 -1
  74. metadata +30 -14
  75. data/app/views/decidim/meetings/admin/invites/new.html.erb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 335c7c37ff53d307c70692c3818be204327a00fa07eddd813a5c8c6595c6afb2
4
- data.tar.gz: 52848d0551a08d2b240c11bcbaaa519f9f46ec53f39eb63707c2e4445d8838fd
3
+ metadata.gz: 143339c8a41808d05f02ab73f1fdca0af63fc60ea551919cc9517a32f751bbaf
4
+ data.tar.gz: ff671495cc3183f10369a19ecf2f7a61579763ec38ba8c805be4ff4ce05f2cae
5
5
  SHA512:
6
- metadata.gz: 32caac25b60f8a284a41b80eb47b29b5e691871a73c13afc08862390a48de2589de5ff9881641d21d7d1d57dc333161bb7ea71f015a7eed63ad9969a3188c6b4
7
- data.tar.gz: a9b1a3e956e83d7d9e3c9a789e2dfd26239a835bb14371e3bb174c51051366b95f53a4d941bc8d684ac894af840118b914412992fafe723d8f0646fff441ac1f
6
+ metadata.gz: '028d85237ce58717b6f5323da6fb8c12aab1fa52e67564b34962f314b7cc3dc2a6fe0a91f5799ae9f847e27fedb0ff0de7e7caf3a1ccbfbfcceb0065e18e5652'
7
+ data.tar.gz: 509abcb9e65fa3e5eedb5808e3dca0a87f8a9d51607a157511fb258460dd1ea3b8d227b72db6a04ff7a2ed95d47fd78742d6de83a4f6471812ee8c9a87bd97cd
@@ -1,4 +1,5 @@
1
1
  //= link decidim/meetings/admin/meetings_form.js
2
2
  //= link decidim/meetings/admin/registrations_form.js
3
+ //= link decidim/meetings/admin/registrations_invite_form.js
3
4
  //= link decidim/meetings/admin/meetings_form.js
4
5
  //= link decidim/meetings/admin/agendas.js
@@ -0,0 +1,25 @@
1
+ ((exports) => {
2
+ const { createFieldDependentInputs } = exports.DecidimAdmin;
3
+
4
+ const $attendeeType = $('[name="meeting_registration_invite[existing_user]"');
5
+
6
+ createFieldDependentInputs({
7
+ controllerField: $attendeeType,
8
+ wrapperSelector: ".attendee-fields",
9
+ dependentFieldsSelector: ".attendee-fields--new-user",
10
+ dependentInputSelector: "input",
11
+ enablingCondition: () => {
12
+ return $("#meeting_registration_invite_existing_user_false").is(":checked")
13
+ }
14
+ });
15
+
16
+ createFieldDependentInputs({
17
+ controllerField: $attendeeType,
18
+ wrapperSelector: ".attendee-fields",
19
+ dependentFieldsSelector: ".attendee-fields--user-picker",
20
+ dependentInputSelector: "input",
21
+ enablingCondition: () => {
22
+ return $("#meeting_registration_invite_existing_user_true").is(":checked")
23
+ }
24
+ });
25
+ })(window);
@@ -3,6 +3,7 @@
3
3
  <%= action_authorized_button_to(
4
4
  :join,
5
5
  meeting_registration_path(model),
6
+ resource: model,
6
7
  method: :delete,
7
8
  class: "#{button_classes} secondary light",
8
9
  data: { disable: true }
@@ -16,6 +17,7 @@
16
17
  :join,
17
18
  i18n_join_text,
18
19
  "",
20
+ resource: model,
19
21
  class: button_classes,
20
22
  disabled: !model.has_available_slots?,
21
23
  data: { open: current_user.present? ? "meeting-registration-confirm-#{model.id}" : "loginModal" }
@@ -10,7 +10,7 @@ module Decidim
10
10
  include Cell::ViewModel::Partial
11
11
 
12
12
  def show
13
- cell card_size, model
13
+ cell card_size, model, options
14
14
  end
15
15
 
16
16
  private
@@ -24,7 +24,7 @@ module Decidim
24
24
  #
25
25
  # Returns nothing.
26
26
  def call
27
- return broadcast(:invalid) if form.invalid?
27
+ return broadcast(:invalid) if form.invalid? || already_invited?
28
28
 
29
29
  invite_user
30
30
 
@@ -35,22 +35,71 @@ module Decidim
35
35
 
36
36
  attr_reader :form, :invited_by, :meeting
37
37
 
38
+ def already_invited?
39
+ return false unless user.persisted?
40
+ return false unless meeting.invites.where(user: user).exists?
41
+
42
+ form.errors.add(:email, :already_invited)
43
+ true
44
+ end
45
+
46
+ def create_invitation!
47
+ log_info = {
48
+ resource: {
49
+ title: meeting.title
50
+ },
51
+ participatory_space: {
52
+ title: meeting.participatory_space.title
53
+ }
54
+ }
55
+
56
+ @invite = Decidim.traceability.create!(
57
+ Invite,
58
+ invited_by,
59
+ {
60
+ user: user,
61
+ meeting: meeting,
62
+ sent_at: Time.current
63
+ },
64
+ log_info
65
+ )
66
+ end
67
+
38
68
  def invite_user
39
69
  if user.persisted?
40
- InviteJoinMeetingMailer.invite(user, meeting, invited_by).deliver_later
70
+ create_invitation!
71
+
72
+ # The user has already been invited to sign up to another
73
+ # meeting or resource and has not yet accepted the invitation
74
+ if user.invited_to_sign_up?
75
+ invite_user_to_sign_up
76
+ else
77
+ InviteJoinMeetingMailer.invite(user, meeting, invited_by).deliver_later
78
+ end
41
79
  else
42
80
  user.name = form.name
43
81
  user.nickname = User.nicknamize(user.name, organization: user.organization)
44
- user.skip_reconfirmation!
45
- user.invite!(invited_by, invitation_instructions: "join_meeting", meeting: meeting)
82
+ invite_user_to_sign_up
83
+ create_invitation!
46
84
  end
47
85
  end
48
86
 
49
87
  def user
50
- @user ||= Decidim::User.find_or_initialize_by(
51
- organization: form.current_organization,
52
- email: form.email.downcase
53
- )
88
+ @user ||= begin
89
+ if form.existing_user
90
+ form.user
91
+ else
92
+ Decidim::User.find_or_initialize_by(
93
+ organization: form.current_organization,
94
+ email: form.email.downcase
95
+ )
96
+ end
97
+ end
98
+ end
99
+
100
+ def invite_user_to_sign_up
101
+ user.skip_reconfirmation!
102
+ user.invite!(invited_by, invitation_instructions: "join_meeting", meeting: meeting)
54
103
  end
55
104
  end
56
105
  end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Admin
6
+ # This command is executed when the admin validates a registration code in the admin panel.
7
+ class ValidateRegistrationCode < Rectify::Command
8
+ # Initializes a ValidateRegistrationCode Command.
9
+ #
10
+ # form - The form from which to get the data.
11
+ # meeting - The current instance of the meeting to be updated.
12
+ def initialize(form, meeting)
13
+ @form = form
14
+ @meeting = meeting
15
+ end
16
+
17
+ # Validates the registration code the meeting if valid.
18
+ #
19
+ # Broadcasts :ok if successful, :invalid otherwise.
20
+ def call
21
+ return broadcast(:invalid) if form.invalid?
22
+
23
+ validate_registration_code
24
+ send_notification
25
+
26
+ broadcast(:ok)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :form, :meeting
32
+
33
+ def validate_registration_code
34
+ form.registration.update!(validated_at: Time.current)
35
+ end
36
+
37
+ def send_notification
38
+ Decidim::EventsManager.publish(
39
+ event: "decidim.events.meetings.registration_code_validated",
40
+ event_class: Decidim::Meetings::RegistrationCodeValidatedEvent,
41
+ resource: meeting,
42
+ recipient_ids: [form.registration.user.id],
43
+ extra: {
44
+ registration: form.registration
45
+ }
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This command is executed when the user declines an invite to the meeting.
6
+ class DeclineInvitation < Rectify::Command
7
+ # Initializes a DeclineInvitation Command.
8
+ #
9
+ # meeting - The current instance of the meeting where user has been invited.
10
+ # user - The user that declines their invitation
11
+ def initialize(meeting, user)
12
+ @meeting = meeting
13
+ @user = user
14
+ end
15
+
16
+ # Creates a meeting registration if the meeting has registrations enabled
17
+ # and there are available slots.
18
+ #
19
+ # Broadcasts :ok if successful, :invalid otherwise.
20
+ def call
21
+ return broadcast(:invalid) unless can_decline_invitation?
22
+
23
+ decline_invitation
24
+
25
+ broadcast(:ok)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :meeting, :user
31
+
32
+ def decline_invitation
33
+ invitation.decline!
34
+ end
35
+
36
+ def can_decline_invitation?
37
+ meeting.registrations_enabled? && invitation.present?
38
+ end
39
+
40
+ def invitation
41
+ @invitation ||= meeting.invites.find_by(user: user)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -21,6 +21,7 @@ module Decidim
21
21
  meeting.with_lock do
22
22
  return broadcast(:invalid) unless can_join_meeting?
23
23
  create_registration
24
+ accept_invitation
24
25
  send_email_confirmation
25
26
  send_notification
26
27
  end
@@ -29,10 +30,14 @@ module Decidim
29
30
 
30
31
  private
31
32
 
32
- attr_reader :meeting, :user
33
+ attr_reader :meeting, :user, :registration
34
+
35
+ def accept_invitation
36
+ meeting.invites.find_by(user: user)&.accept!
37
+ end
33
38
 
34
39
  def create_registration
35
- Decidim::Meetings::Registration.create!(meeting: meeting, user: user)
40
+ @registration = Decidim::Meetings::Registration.create!(meeting: meeting, user: user)
36
41
  end
37
42
 
38
43
  def can_join_meeting?
@@ -40,7 +45,7 @@ module Decidim
40
45
  end
41
46
 
42
47
  def send_email_confirmation
43
- Decidim::Meetings::RegistrationMailer.confirmation(user, meeting).deliver_later
48
+ Decidim::Meetings::RegistrationMailer.confirmation(user, meeting, registration).deliver_later
44
49
  end
45
50
 
46
51
  def participatory_space_admins
@@ -19,10 +19,6 @@ module Decidim
19
19
  def meeting
20
20
  @meeting ||= meetings.find(params[:meeting_id])
21
21
  end
22
-
23
- def authorization_object
24
- meeting.component
25
- end
26
22
  end
27
23
  end
28
24
  end
@@ -20,10 +20,6 @@ module Decidim
20
20
  def meeting
21
21
  @meeting ||= meetings.find(params[:meeting_id])
22
22
  end
23
-
24
- def authorization_object
25
- meeting.component
26
- end
27
23
  end
28
24
  end
29
25
  end
@@ -8,26 +8,31 @@ module Decidim
8
8
  # Controller that allows inviting users to join a meeting.
9
9
  #
10
10
  class InvitesController < Admin::ApplicationController
11
- def new
12
- enforce_permission_to :invite_user, :meeting, meeting: meeting
11
+ helper_method :invites
12
+
13
+ def index
14
+ enforce_permission_to :read_invites, :meeting, meeting: meeting
15
+
16
+ @query = params[:q]
17
+ @status = params[:status]
13
18
 
14
19
  @form = form(MeetingRegistrationInviteForm).instance
15
20
  end
16
21
 
17
22
  def create
18
- enforce_permission_to :invite_user, :meeting, meeting: meeting
23
+ enforce_permission_to :invite_attendee, :meeting, meeting: meeting
19
24
 
20
25
  @form = form(MeetingRegistrationInviteForm).from_params(params)
21
26
 
22
27
  InviteUserToJoinMeeting.call(@form, meeting, current_user) do
23
28
  on(:ok) do
24
29
  flash[:notice] = I18n.t("invites.create.success", scope: "decidim.meetings.admin")
25
- redirect_to edit_meeting_registrations_path(meeting)
30
+ redirect_to meeting_registrations_invites_path(meeting)
26
31
  end
27
32
 
28
33
  on(:invalid) do
29
34
  flash.now[:alert] = I18n.t("invites.create.error", scope: "decidim.meetings.admin")
30
- render :new
35
+ render :index
31
36
  end
32
37
  end
33
38
  end
@@ -37,6 +42,10 @@ module Decidim
37
42
  def meeting
38
43
  @meeting ||= Meeting.where(component: current_component).find(params[:meeting_id])
39
44
  end
45
+
46
+ def invites
47
+ @invites ||= Decidim::Meetings::Admin::Invites.for(meeting.invites, @query, @status).page(params[:page]).per(15)
48
+ end
40
49
  end
41
50
  end
42
51
  end
@@ -9,6 +9,7 @@ module Decidim
9
9
  enforce_permission_to :update, :meeting, meeting: meeting
10
10
 
11
11
  @form = MeetingRegistrationsForm.from_model(meeting)
12
+ @validation_form = ValidateRegistrationCodeForm.new
12
13
  end
13
14
 
14
15
  def update
@@ -39,6 +40,25 @@ module Decidim
39
40
  end
40
41
  end
41
42
 
43
+ def validate_registration_code
44
+ enforce_permission_to :update, :meeting, meeting: meeting
45
+
46
+ @form = MeetingRegistrationsForm.from_model(meeting)
47
+ @validation_form = ValidateRegistrationCodeForm.from_params(params).with_context(current_organization: meeting.organization, meeting: meeting)
48
+
49
+ ValidateRegistrationCode.call(@validation_form, meeting) do
50
+ on(:ok) do
51
+ flash[:notice] = I18n.t("registrations.validate_registration_code.success", scope: "decidim.meetings.admin")
52
+ render action: "edit"
53
+ end
54
+
55
+ on(:invalid) do
56
+ flash.now[:alert] = I18n.t("registrations.validate_registration_code.invalid", scope: "decidim.meetings.admin")
57
+ render action: "edit"
58
+ end
59
+ end
60
+ end
61
+
42
62
  private
43
63
 
44
64
  def meeting
@@ -36,6 +36,22 @@ module Decidim
36
36
  end
37
37
  end
38
38
 
39
+ def decline_invitation
40
+ enforce_permission_to :decline_invitation, :meeting, meeting: meeting
41
+
42
+ DeclineInvitation.call(meeting, current_user) do
43
+ on(:ok) do
44
+ flash[:notice] = I18n.t("registrations.decline_invitation.success", scope: "decidim.meetings")
45
+ redirect_after_path
46
+ end
47
+
48
+ on(:invalid) do
49
+ flash.now[:alert] = I18n.t("registrations.decline_invitation.invalid", scope: "decidim.meetings")
50
+ redirect_after_path
51
+ end
52
+ end
53
+ end
54
+
39
55
  private
40
56
 
41
57
  def meeting
@@ -0,0 +1,15 @@
1
+ # frozen-string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class RegistrationCodeValidatedEvent < Decidim::Events::SimpleEvent
6
+ i18n_attributes :registration_code
7
+
8
+ private
9
+
10
+ def registration_code
11
+ extra["registration"]["code"]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -13,7 +13,7 @@ module Decidim
13
13
  attribute :attending_organizations, String
14
14
  attribute :proposal_ids, Array[Integer]
15
15
  attribute :proposals
16
- attribute :closed_at, DateTime, default: ->(_form, _attribute) { Time.current }
16
+ attribute :closed_at, Decidim::Attributes::TimeWithZone, default: ->(_form, _attribute) { Time.current }
17
17
 
18
18
  validates :closing_report, translatable_presence: true
19
19
  validates :attendees_count, presence: true, numericality: { greater_than_or_equal_to: 0 }