decidim-meetings 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/admin/decidim_meetings_manifest.js +1 -0
  3. data/app/assets/images/decidim/meetings/icon.svg +5 -1
  4. data/app/assets/javascripts/decidim/meetings/admin/registrations_form.js.es6 +21 -0
  5. data/app/commands/decidim/meetings/admin/close_meeting.rb +17 -9
  6. data/app/commands/decidim/meetings/admin/create_meeting.rb +13 -1
  7. data/app/commands/decidim/meetings/admin/update_meeting.rb +47 -21
  8. data/app/commands/decidim/meetings/admin/update_registrations.rb +60 -0
  9. data/app/commands/decidim/meetings/join_meeting.rb +73 -0
  10. data/app/commands/decidim/meetings/leave_meeting.rb +39 -0
  11. data/app/controllers/decidim/meetings/admin/registrations_controller.rb +43 -0
  12. data/app/controllers/decidim/meetings/registrations_controller.rb +46 -0
  13. data/app/events/decidim/meetings/close_meeting_event.rb +30 -0
  14. data/app/events/decidim/meetings/meeting_registrations_enabled_event.rb +39 -0
  15. data/app/events/decidim/meetings/meeting_registrations_over_percentage_event.rb +43 -0
  16. data/app/events/decidim/meetings/upcoming_meeting_event.rb +30 -0
  17. data/app/events/decidim/meetings/update_meeting_event.rb +30 -0
  18. data/app/forms/decidim/meetings/admin/meeting_form.rb +1 -1
  19. data/app/forms/decidim/meetings/admin/meeting_registrations_form.rb +32 -0
  20. data/app/helpers/decidim/meetings/application_helper.rb +1 -0
  21. data/app/jobs/decidim/meetings/upcoming_meeting_notification_job.rb +33 -0
  22. data/app/mailers/decidim/meetings/registration_mailer.rb +46 -0
  23. data/app/models/decidim/meetings/abilities/current_user_ability.rb +43 -0
  24. data/app/models/decidim/meetings/meeting.rb +42 -0
  25. data/app/models/decidim/meetings/registration.rb +13 -0
  26. data/app/serializers/decidim/meetings/registration_serializer.rb +18 -0
  27. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +3 -3
  28. data/app/views/decidim/meetings/admin/meetings/index.html.erb +1 -0
  29. data/app/views/decidim/meetings/admin/registrations/_form.html.erb +33 -0
  30. data/app/views/decidim/meetings/admin/registrations/edit.html.erb +8 -0
  31. data/app/views/decidim/meetings/meetings/_filters.html.erb +2 -2
  32. data/app/views/decidim/meetings/meetings/_registration_confirm.html.erb +15 -0
  33. data/app/views/decidim/meetings/meetings/show.html.erb +15 -1
  34. data/app/views/decidim/meetings/registration_mailer/confirmation.html.erb +3 -0
  35. data/config/locales/ca.yml +74 -0
  36. data/config/locales/en.yml +72 -4
  37. data/config/locales/es.yml +75 -1
  38. data/config/locales/eu.yml +78 -3
  39. data/config/locales/fi.yml +84 -0
  40. data/config/locales/fr.yml +83 -8
  41. data/config/locales/it.yml +87 -0
  42. data/config/locales/nl.yml +169 -0
  43. data/config/locales/pl.yml +113 -0
  44. data/config/locales/uk.yml +178 -0
  45. data/db/migrate/20170810120836_add_registration_attributes_to_meetings.rb +9 -0
  46. data/db/migrate/20170810131100_create_registrations.rb +14 -0
  47. data/lib/decidim/meetings/admin_engine.rb +9 -0
  48. data/lib/decidim/meetings/engine.rb +8 -0
  49. data/lib/decidim/meetings/feature.rb +39 -9
  50. data/lib/decidim/meetings/test/factories.rb +11 -0
  51. metadata +65 -13
  52. data/config/i18n-tasks.yml +0 -10
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Admin
6
+ # This class holds a Form to update meeting registrations from Decidim's admin panel.
7
+ class MeetingRegistrationsForm < Decidim::Form
8
+ include TranslatableAttributes
9
+
10
+ mimic :meeting
11
+
12
+ attribute :registrations_enabled, Boolean
13
+ attribute :available_slots, Integer
14
+ translatable_attribute :registration_terms, String
15
+
16
+ validates :registration_terms, translatable_presence: true, if: ->(form) { form.registrations_enabled? }
17
+ validates :available_slots, numericality: { greater_than_or_equal_to: 0 }, if: ->(form) { form.registrations_enabled? }
18
+ validate :available_slots_greater_than_or_equal_to_registrations_count, if: ->(form) { form.registrations_enabled? && form.available_slots.positive? }
19
+
20
+ private
21
+
22
+ def available_slots_greater_than_or_equal_to_registrations_count
23
+ errors.add(:available_slots, :invalid) if available_slots < meeting.registrations.count
24
+ end
25
+
26
+ def meeting
27
+ @meeting ||= context[:meeting]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -9,6 +9,7 @@ module Decidim
9
9
  include Decidim::MapHelper
10
10
  include Decidim::Meetings::MapHelper
11
11
  include Decidim::Meetings::MeetingsHelper
12
+ include Decidim::Comments::CommentsHelper
12
13
  end
13
14
  end
14
15
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class UpcomingMeetingNotificationJob < ApplicationJob
6
+ queue_as :decidim_events
7
+
8
+ def perform(meeting_id, checksum)
9
+ meeting = Decidim::Meetings::Meeting.find(meeting_id)
10
+ send_notification(meeting) if verify_checksum(meeting, checksum)
11
+ end
12
+
13
+ def self.generate_checksum(meeting)
14
+ Digest::MD5.hexdigest("#{meeting.id}-#{meeting.start_time}")
15
+ end
16
+
17
+ private
18
+
19
+ def send_notification(meeting)
20
+ Decidim::EventsManager.publish(
21
+ event: "decidim.events.meetings.upcoming_meeting",
22
+ event_class: Decidim::Meetings::UpcomingMeetingEvent,
23
+ resource: meeting,
24
+ recipient_ids: meeting.followers.pluck(:id)
25
+ )
26
+ end
27
+
28
+ def verify_checksum(meeting, checksum)
29
+ self.class.generate_checksum(meeting) == checksum
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # A custom mailer for sending notifications to users when
6
+ # they join a meeting.
7
+ class RegistrationMailer < Decidim::ApplicationMailer
8
+ include Decidim::TranslationsHelper
9
+ include ActionView::Helpers::SanitizeHelper
10
+
11
+ helper Decidim::ResourceHelper
12
+ helper Decidim::TranslationsHelper
13
+
14
+ def confirmation(user, meeting)
15
+ with_user(user) do
16
+ @user = user
17
+ @meeting = meeting
18
+ @organization = @meeting.organization
19
+ @locator = Decidim::ResourceLocatorPresenter.new(@meeting)
20
+
21
+ add_calendar_attachment
22
+
23
+ subject = I18n.t("confirmation.subject", scope: "decidim.meetings.mailer.registration_mailer")
24
+ mail(to: user.email, subject: subject)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def add_calendar_attachment
31
+ calendar = Icalendar::Calendar.new
32
+ calendar.event do |event|
33
+ event.dtstart = Icalendar::Values::DateTime.new(@meeting.start_time)
34
+ event.dtend = Icalendar::Values::DateTime.new(@meeting.end_time)
35
+ event.summary = translated_attribute @meeting.title
36
+ event.description = strip_tags(translated_attribute(@meeting.description))
37
+ event.location = @meeting.address
38
+ event.geo = [@meeting.latitude, @meeting.longitude]
39
+ event.url = @locator.url
40
+ end
41
+
42
+ attachments["meeting-calendar-info.ics"] = calendar.to_ical
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Abilities
6
+ # Defines the abilities related to meetings for a logged in user.
7
+ # Intended to be used with `cancancan`.
8
+ class CurrentUserAbility
9
+ include CanCan::Ability
10
+
11
+ attr_reader :user, :context
12
+
13
+ def initialize(user, context)
14
+ return unless user
15
+
16
+ @user = user
17
+ @context = context
18
+
19
+ can :join, Meeting do |meeting|
20
+ authorized?(:join) && meeting.registrations_enabled?
21
+ end
22
+
23
+ can :leave, Meeting, &:registrations_enabled?
24
+ end
25
+
26
+ private
27
+
28
+ def authorized?(action)
29
+ return unless feature
30
+
31
+ ActionAuthorizer.new(user, feature, action).authorize.ok?
32
+ end
33
+
34
+ def feature
35
+ feature = context.fetch(:current_feature, nil)
36
+ return nil unless feature && feature.manifest.name == :meetings
37
+
38
+ feature
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -11,6 +11,10 @@ module Decidim
11
11
  include Decidim::HasReference
12
12
  include Decidim::HasScope
13
13
  include Decidim::HasCategory
14
+ include Decidim::Followable
15
+ include Decidim::Comments::Commentable
16
+
17
+ has_many :registrations, class_name: "Decidim::Meetings::Registration", foreign_key: "decidim_meeting_id"
14
18
 
15
19
  feature_manifest_name "meetings"
16
20
 
@@ -21,6 +25,44 @@ module Decidim
21
25
  def closed?
22
26
  closed_at.present?
23
27
  end
28
+
29
+ def has_available_slots?
30
+ return true if available_slots.zero?
31
+ available_slots > registrations.count
32
+ end
33
+
34
+ def remaining_slots
35
+ available_slots - registrations.count
36
+ end
37
+
38
+ def has_registration_for?(user)
39
+ registrations.where(user: user).any?
40
+ end
41
+
42
+ # Public: Overrides the `commentable?` Commentable concern method.
43
+ def commentable?
44
+ feature.settings.comments_enabled?
45
+ end
46
+
47
+ # Public: Overrides the `accepts_new_comments?` Commentable concern method.
48
+ def accepts_new_comments?
49
+ commentable? && !feature.current_settings.comments_blocked
50
+ end
51
+
52
+ # Public: Overrides the `comments_have_alignment?` Commentable concern method.
53
+ def comments_have_alignment?
54
+ true
55
+ end
56
+
57
+ # Public: Overrides the `comments_have_votes?` Commentable concern method.
58
+ def comments_have_votes?
59
+ true
60
+ end
61
+
62
+ # Public: Override Commentable concern method `users_to_notify_on_comment_created`
63
+ def users_to_notify_on_comment_created
64
+ followers
65
+ end
24
66
  end
25
67
  end
26
68
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # The data store for a Registration in the Decidim::Meetings component.
6
+ class Registration < Meetings::ApplicationRecord
7
+ belongs_to :meeting, foreign_key: "decidim_meeting_id", class_name: "Decidim::Meetings::Meeting"
8
+ belongs_to :user, foreign_key: "decidim_user_id", class_name: "Decidim::User"
9
+
10
+ validates :user, uniqueness: { scope: :meeting }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ class RegistrationSerializer < Decidim::Exporters::Serializer
6
+ # Serializes a registration
7
+ def serialize
8
+ {
9
+ id: resource.id,
10
+ user: {
11
+ name: resource.user.name,
12
+ email: resource.user.email
13
+ }
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -34,14 +34,14 @@
34
34
  </div>
35
35
  </div>
36
36
  <div class="row" >
37
- <% if current_participatory_process.has_subscopes? %>
37
+ <% if current_participatory_space.has_subscopes? %>
38
38
  <div class="columns xlarge-6" >
39
- <%= form.scopes_select :decidim_scope_id, prompt: I18n.t("decidim.scopes.global"), remote_path: decidim.scopes_search_path(root: current_participatory_process.scope) %>
39
+ <%= form.scopes_select :decidim_scope_id, prompt: I18n.t("decidim.scopes.global"), remote_path: decidim.scopes_search_path(root: current_participatory_space.scope) %>
40
40
  </div>
41
41
  <% end %>
42
42
 
43
43
  <div class="columns xlarge-6" >
44
- <%= form.categories_select :decidim_category_id, current_participatory_process.categories, prompt: "", disable_parents: false %>
44
+ <%= form.categories_select :decidim_category_id, current_participatory_space.categories, prompt: "", disable_parents: false %>
45
45
  </div>
46
46
  </div>
47
47
  </div>
@@ -50,6 +50,7 @@
50
50
 
51
51
  <% if can? :update, current_feature %>
52
52
  <%= icon_link_to "pencil", edit_meeting_path(meeting), t("actions.edit", scope: "decidim.meetings"), class: "action-icon--edit" %>
53
+ <%= icon_link_to "people", edit_meeting_registrations_path(meeting), t("actions.registrations", scope: "decidim.meetings"), class: "action-icon--registrations" %>
53
54
  <% end %>
54
55
 
55
56
  <% if can? :update, current_feature %>
@@ -0,0 +1,33 @@
1
+ <div class="card">
2
+ <div class="card-divider">
3
+ <h2 class="card-title">
4
+ <%= title %>
5
+ <span class="exports dropdown tiny button button--simple button--title" data-toggle="export-dropdown"><%= t "actions.export", scope: "decidim.admin" %></span>
6
+ <div class="dropdown-pane" id="export-dropdown" data-dropdown data-auto-focus="true" data-close-on-click="true">
7
+ <ul class="vertical menu add-features">
8
+ <% %w{csv json}.each do |format| %>
9
+ <li class="exports--format--<%= format %> exports--registrations"><%= link_to t("decidim.admin.exports.export_as", name: t("decidim.#{current_feature.manifest.name}.admin.exports.registrations"), export_format: format.upcase), export_meeting_registrations_path(meeting_id: meeting, format: format) %></li>
10
+ <% end %>
11
+ </ul>
12
+ </div>
13
+ </h2>
14
+ </div>
15
+
16
+ <div class="card-section">
17
+ <div class="row column">
18
+ <%= form.check_box :registrations_enabled %>
19
+ </div>
20
+
21
+ <div class="row column">
22
+ <p><%= t(".registrations_count", count: meeting.registrations.count) %></p>
23
+ <%= form.number_field :available_slots %>
24
+ <p class="help-text"><%= t(".available_slots_help") %></p>
25
+ </div>
26
+
27
+ <div class="row column">
28
+ <%= form.translated :editor, :registration_terms %>
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <%= javascript_include_tag "decidim/meetings/admin/registrations_form" %>
@@ -0,0 +1,8 @@
1
+ <%= decidim_form_for(@form, url: meeting_registrations_path, html: { class: "form edit_meeting_registrations" }) do |f| %>
2
+ <%= render partial: 'form', object: f %>
3
+
4
+ <div class="button--double form-general-submit">
5
+ <%= f.submit t(".save") %>
6
+ </div>
7
+ <% end %>
8
+
@@ -16,8 +16,8 @@
16
16
  <%= form.collection_radio_buttons :date, [["upcoming", t(".upcoming")], ["past", t(".past")]], :first, :last, legend_title: t(".date") %>
17
17
  <% end %>
18
18
 
19
- <% if current_participatory_process.has_subscopes? %>
20
- <%= form.scopes_select :scope_id, legend_title: t(".scopes"), label: false, prompt: t('.scope_prompt'), remote_path: decidim.scopes_search_path(root: current_participatory_process.scope, include_root: true), multiple: true %>
19
+ <% if current_participatory_space.has_subscopes? %>
20
+ <%= form.scopes_select :scope_id, legend_title: t(".scopes"), label: false, prompt: t('.scope_prompt'), remote_path: decidim.scopes_search_path(root: current_participatory_space.scope, include_root: true), multiple: true %>
21
21
  <% end %>
22
22
 
23
23
  <% if current_feature.categories.any? %>
@@ -0,0 +1,15 @@
1
+ <div class="reveal" data-reveal id="meeting-registration-confirm">
2
+ <div class="row">
3
+ <div class="columns medium-10 medium-offset-1 help-text">
4
+ <%== translated_attribute(meeting.registration_terms) %>
5
+ </div>
6
+ </div>
7
+ <div class="row">
8
+ <div class="columns medium-8 medium-offset-2">
9
+ <%= button_to t('.confirm'), meeting_registration_path(meeting), class: "button expanded" %>
10
+ </div>
11
+ </div>
12
+ <div class="text-center">
13
+ <button class="link" data-close><%= t('.cancel') %></button>
14
+ </div>
15
+ </div>
@@ -20,7 +20,17 @@
20
20
  <div class="extra__time">
21
21
  <%= meeting.start_time.strftime("%H:%M") %> - <%= meeting.end_time.strftime("%H:%M") %>
22
22
  </div>
23
- </div>
23
+ <% if !meeting.closed? && meeting.registrations_enabled? %>
24
+ <% if meeting.has_registration_for? current_user %>
25
+ <%= action_authorized_button_to :leave, t('.going'), meeting_registration_path(meeting), method: :delete, class: "button expanded button--sc success" %>
26
+ <% else %>
27
+ <%= action_authorized_button_to :join, meeting.has_available_slots? ? t('.join') : t('.no_slots_available'), "", class: "button expanded button--sc", disabled: !meeting.has_available_slots?, data: { toggle: current_user.present? ? "meeting-registration-confirm" : "loginModal" } %>
28
+ <% end %>
29
+ <% if meeting.available_slots.positive? %>
30
+ <span><%= t(".remaining_slots", count: meeting.remaining_slots) %></span>
31
+ <% end %>
32
+ <% end %>
33
+ <%= render partial: "decidim/shared/follow_button", locals: { followable: meeting } %>
24
34
  </div>
25
35
  <% if meeting.closed? %>
26
36
  <div class="card card--secondary extra definition-data">
@@ -45,6 +55,7 @@
45
55
  </div>
46
56
  </div>
47
57
  <% end %>
58
+ </div>
48
59
  <%= feature_reference(meeting) %>
49
60
  <%= render partial: "decidim/shared/share_modal" %>
50
61
  <%= embed_modal_for meeting_meeting_widget_url(meeting, format: :js) %>
@@ -66,6 +77,9 @@
66
77
  </div>
67
78
  </div>
68
79
  <%= attachments_for meeting %>
80
+ <%= comments_for meeting %>
81
+
82
+ <%= render partial: "registration_confirm" %>
69
83
 
70
84
  <%= javascript_include_tag "decidim/proposals/social_share" %>
71
85
  <%= stylesheet_link_tag "decidim/proposals/social_share" %>
@@ -0,0 +1,3 @@
1
+ <p><%= t(".confirmed_html", title: translated_attribute(@meeting.title), url: @locator.url) %></p>
2
+
3
+ <p><%= t(".details") %></p>
@@ -1,3 +1,4 @@
1
+ ---
1
2
  ca:
2
3
  activemodel:
3
4
  attributes:
@@ -20,7 +21,16 @@ ca:
20
21
  decidim:
21
22
  features:
22
23
  meetings:
24
+ actions:
25
+ join: Inscriu-t'hi
23
26
  name: Trobades
27
+ settings:
28
+ global:
29
+ announcement: Avís
30
+ comments_enabled: Comentaris habilitats
31
+ step:
32
+ announcement: Avís
33
+ comments_blocked: Comentaris bloquejats
24
34
  meetings:
25
35
  actions:
26
36
  attachments: Adjunts
@@ -30,8 +40,11 @@ ca:
30
40
  edit: Edita
31
41
  new: Nova
32
42
  preview: Previsualitzar
43
+ registrations: Inscripcions
33
44
  title: Accions
34
45
  admin:
46
+ exports:
47
+ registrations: Inscripcions
35
48
  meeting_closes:
36
49
  edit:
37
50
  close: Tancar
@@ -58,6 +71,47 @@ ca:
58
71
  models:
59
72
  meeting:
60
73
  name: Trobada
74
+ registrations:
75
+ edit:
76
+ save: Desa
77
+ form:
78
+ available_slots_help: Deixeu-lo a 0 si teniu espais il·limitats disponibles.
79
+ registrations_count:
80
+ one: Hi ha hagut 1 inscripció.
81
+ other: Hi ha hagut %{count} inscripcions.
82
+ update:
83
+ invalid: S'ha produït un problema en desar la configuració de la inscripció.
84
+ success: La configuració de les inscripcions de la trobada s'ha desat correctament.
85
+ events:
86
+ close_meeting_event:
87
+ email_intro: 'La trobada de "%{resource_title}" ha estat tancada. Podeu llegir les conclusions a la seva pàgina:'
88
+ email_outro: Has rebut aquesta notificació, perquè estàs seguint la trobada "%{resource_title}". Pots deixar-la de seguir des del seu enllaç.
89
+ email_subject: S'ha tancat la trobada "%{resource_title}"
90
+ notification_title: La trobada de <a href="%{resource_path}">%{resource_title}</a> s'ha tancat.
91
+ meeting_registrations_enabled:
92
+ email_intro: 'La trobada "%{resource_title}" ha activat inscripcions. Pots registrar-te a la seva pàgina:'
93
+ email_outro: Has rebut aquesta notificació perquè estàs seguint la trobada "%{resource_title}". Pots deixar-la de seguir a l'enllaç anterior.
94
+ email_subject: La trobada de "%{resource_title}" ha permès inscripcions.
95
+ notification_title: La trobada <a href="%{resource_path}">%{resource_title}</a> ha activat inscripcions.
96
+ meeting_registrations_over_percentage:
97
+ email_intro: La disponibilitat d'espais a la trobada "%{resource_title}" està per sobre del %{percentage}%.
98
+ email_outro: Has rebut aquesta notificació perquè ets un administrador de l'espai participatiu d'aquesta trobada.
99
+ email_subject: L'espai ocupat per la trobada "%{resource_title}" està per sobre del %{percentage}%
100
+ notification_title: L'espai ocupat per la trobada <a href="%{resource_path}">%{resource_title}</a> està per sobre del %{percentage}%.
101
+ upcoming_meeting_event:
102
+ email_intro: En menys de 48 hores s'iniciarà la trobada "%{resource_title}".
103
+ email_outro: Has rebut aquesta notificació perquè estàs seguint la trobada "%{resource_title}". Pots deixar-la de seguir a l'enllaç anterior.
104
+ email_subject: En menys de 48 hores s'iniciarà la trobada "%{resource_title}".
105
+ notification_title: La trobada <a href="%{resource_path}">%{resource_title}</a> començarà en menys de 48 hores.
106
+ update_meeting_event:
107
+ email_intro: 'La trobada de "%{resource_title}" ha estat actualitzada. Pots llegir-ne la nova versió a la seva pàgina:'
108
+ email_outro: Has rebut aquesta notificació perquè estàs seguint la trobada "%{resource_title}". Pots deixar-la de seguir des de l'enllaç anterior.
109
+ email_subject: La trobada "%{resource_title}" s'ha actualitzat
110
+ notification_title: La trobada <a href="%{resource_path}">%{resource_title}</a> ha estat actualitzada.
111
+ mailer:
112
+ registration_mailer:
113
+ confirmation:
114
+ subject: La teva inscripció a la trobada ha estat confirmada
61
115
  meetings:
62
116
  filters:
63
117
  category: Categoria
@@ -78,11 +132,20 @@ ca:
78
132
  meetings:
79
133
  no_meetings_warning: No hi ha trobades que coincideixin amb el criteri de cerca o no hi ha cap trobada programada.
80
134
  upcoming_meetings_warning: Actualment no hi ha trobades programades, però pots veure les anteriors trobades.
135
+ registration_confirm:
136
+ cancel: Cancel·lar
137
+ confirm: Confirmar
81
138
  show:
82
139
  attendees: Nombre d'assistents
83
140
  contributions: Nombre d'aportacions
141
+ going: Inscrit
142
+ join: Inscriu-te a la reunió
84
143
  meeting_report: Informe de la trobada
144
+ no_slots_available: No hi ha lloc disponible
85
145
  organizations: Llista d'organitzacions que han atès
146
+ remaining_slots:
147
+ one: 1 espai reservat restant
148
+ other: "%{count} inscripcions restants"
86
149
  models:
87
150
  meeting:
88
151
  fields:
@@ -92,6 +155,17 @@ ca:
92
155
  start_time: Data d'inici
93
156
  title: Títol
94
157
  read_more: "(Llegeix més)"
158
+ registration_mailer:
159
+ confirmation:
160
+ confirmed_html: La teva inscripció a la trobada <a href="%{url}">%{title}</a> ha estat confirmada.
161
+ details: A l'arxiu adjunt trobaràs els detalls de la reunió.
162
+ registrations:
163
+ create:
164
+ invalid: Hi ha hagut un problema en inscriure's a aquesta reunió.
165
+ success: T'has inscrit a la reunió amb èxit.
166
+ destroy:
167
+ invalid: Hi ha hagut un problema en sortir d'aquesta trobada.
168
+ success: Heu deixat la trobada amb èxit.
95
169
  resource_links:
96
170
  meetings_through_proposals:
97
171
  meeting_results: 'Resultats relacionats:'
@@ -21,12 +21,16 @@ en:
21
21
  decidim:
22
22
  features:
23
23
  meetings:
24
+ actions:
25
+ join: Join
24
26
  name: Meetings
25
27
  settings:
26
28
  global:
27
29
  announcement: Announcement
30
+ comments_enabled: Comments enabled
28
31
  step:
29
32
  announcement: Announcement
33
+ comments_blocked: Comments blocked
30
34
  meetings:
31
35
  actions:
32
36
  attachments: Attachments
@@ -36,8 +40,11 @@ en:
36
40
  edit: Edit
37
41
  new: New
38
42
  preview: Preview
43
+ registrations: Registrations
39
44
  title: Actions
40
45
  admin:
46
+ exports:
47
+ registrations: Registrations
41
48
  meeting_closes:
42
49
  edit:
43
50
  close: Close
@@ -64,6 +71,48 @@ en:
64
71
  models:
65
72
  meeting:
66
73
  name: Meeting
74
+ registrations:
75
+ edit:
76
+ save: Save
77
+ form:
78
+ available_slots_help: Leave it to 0 if you have unlimited slots available.
79
+ registrations_count:
80
+ one: There has been 1 registration.
81
+ other: There has been %{count} registrations.
82
+ zero: There has not been registrations yet.
83
+ update:
84
+ invalid: There's been a problem saving the registration settings.
85
+ success: Meeting registrations settings successfully saved.
86
+ events:
87
+ close_meeting_event:
88
+ email_intro: 'The "%{resource_title}" meeting was closed. You can read the conclusions from its page:'
89
+ email_outro: You have received this notification because you are following the "%{resource_title}" meeting. You can unfollow it from the previous link.
90
+ email_subject: The "%{resource_title}" meeting was closed
91
+ notification_title: The <a href="%{resource_path}">%{resource_title}</a> meeting was closed.
92
+ meeting_registrations_enabled:
93
+ email_intro: 'The "%{resource_title}" meeting has enabled registrations. You can register yourself on its page:'
94
+ email_outro: You have received this notification because you are following the "%{resource_title}" meeting. You can unfollow it from the previous link.
95
+ email_subject: The "%{resource_title}" meeting has enabled registrations.
96
+ notification_title: The <a href="%{resource_path}">%{resource_title}</a> meeting has enabled registrations.
97
+ meeting_registrations_over_percentage:
98
+ email_intro: The "%{resource_title}" meeting occupied slots are over %{percentage}%.
99
+ email_outro: You have received this notification because you are an admin of the meeting's participatory space.
100
+ email_subject: The "%{resource_title}" meeting occupied slots are over %{percentage}%
101
+ notification_title: The <a href="%{resource_path}">%{resource_title}</a> meeting occupied slots are over %{percentage}%.
102
+ upcoming_meeting_event:
103
+ email_intro: The "%{resource_title}" meeting will start in less than 48h.
104
+ email_outro: You have received this notification because you are following the "%{resource_title}" meeting. You can unfollow it from the previous link.
105
+ email_subject: The "%{resource_title}" meeting will start in less than 48h.
106
+ notification_title: The <a href="%{resource_path}">%{resource_title}</a> meeting will start in less than 48h.
107
+ update_meeting_event:
108
+ email_intro: 'The "%{resource_title}" meeting was updated. You can read the new version from its page:'
109
+ email_outro: You have received this notification because you are following the "%{resource_title}" meeting. You can unfollow it from the previous link.
110
+ email_subject: The "%{resource_title}" meeting was updated
111
+ notification_title: The <a href="%{resource_path}">%{resource_title}</a> meeting was updated.
112
+ mailer:
113
+ registration_mailer:
114
+ confirmation:
115
+ subject: Your meeting's registration has been confirmed
67
116
  meetings:
68
117
  filters:
69
118
  category: Category
@@ -82,15 +131,23 @@ en:
82
131
  index:
83
132
  view_meeting: View meeting
84
133
  meetings:
85
- no_meetings_warning: No meetings match your search criteria or there isn't
86
- any meeting scheduled.
87
- upcoming_meetings_warning: Currently, there are no scheduled meetings, but
88
- here you can find all the past meetings listed.
134
+ no_meetings_warning: No meetings match your search criteria or there isn't any meeting scheduled.
135
+ upcoming_meetings_warning: Currently, there are no scheduled meetings, but here you can find all the past meetings listed.
136
+ registration_confirm:
137
+ cancel: Cancel
138
+ confirm: Confirm
89
139
  show:
90
140
  attendees: Attendees count
91
141
  contributions: Contributions count
142
+ going: Going
143
+ join: Join meeting
92
144
  meeting_report: Meeting report
145
+ no_slots_available: No slots available
93
146
  organizations: Attending organizations
147
+ remaining_slots:
148
+ one: 1 slot remaining
149
+ other: "%{count} slots remaining"
150
+ zero: No slots remaining
94
151
  models:
95
152
  meeting:
96
153
  fields:
@@ -100,6 +157,17 @@ en:
100
157
  start_time: Start date
101
158
  title: Title
102
159
  read_more: "(read more)"
160
+ registration_mailer:
161
+ confirmation:
162
+ confirmed_html: Your registration for the meeting <a href="%{url}">%{title}</a> has been confirmed.
163
+ details: You will find the meeting's details in the attachment.
164
+ registrations:
165
+ create:
166
+ invalid: There's been a problem joining this meeting.
167
+ success: You have joined the meeting successfully.
168
+ destroy:
169
+ invalid: There's been a problem leaving this meeting.
170
+ success: You have left the meeting successfully.
103
171
  resource_links:
104
172
  meetings_through_proposals:
105
173
  meeting_results: 'Related results:'