decidim-meetings 0.10.1 → 0.11.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/config/admin/decidim_meetings_manifest.js +1 -0
  4. data/app/assets/javascripts/decidim/meetings/admin/meetings_form.js.es6 +78 -0
  5. data/app/assets/javascripts/decidim/meetings/admin/registrations_form.js.es6 +9 -7
  6. data/app/cells/decidim/meetings/meeting_cell.rb +71 -0
  7. data/app/cells/decidim/meetings/meeting_list_item/show.erb +14 -0
  8. data/app/cells/decidim/meetings/meeting_list_item_cell.rb +26 -0
  9. data/app/cells/decidim/meetings/meeting_m/header.erb +5 -0
  10. data/app/cells/decidim/meetings/meeting_m/show.erb +21 -0
  11. data/app/cells/decidim/meetings/meeting_m_cell.rb +17 -0
  12. data/app/commands/decidim/meetings/admin/copy_meeting.rb +82 -0
  13. data/app/commands/decidim/meetings/admin/create_meeting.rb +3 -1
  14. data/app/commands/decidim/meetings/admin/export_meeting_registrations.rb +44 -0
  15. data/app/commands/decidim/meetings/admin/update_meeting.rb +1 -0
  16. data/app/commands/decidim/meetings/admin/update_registrations.rb +1 -0
  17. data/app/commands/decidim/meetings/join_meeting.rb +1 -1
  18. data/app/commands/decidim/meetings/leave_meeting.rb +1 -1
  19. data/app/controllers/decidim/meetings/admin/application_controller.rb +3 -3
  20. data/app/controllers/decidim/meetings/admin/attachment_collections_controller.rb +2 -2
  21. data/app/controllers/decidim/meetings/admin/attachments_controller.rb +1 -1
  22. data/app/controllers/decidim/meetings/admin/invites_controller.rb +1 -1
  23. data/app/controllers/decidim/meetings/admin/meeting_closes_controller.rb +1 -1
  24. data/app/controllers/decidim/meetings/admin/meeting_copies_controller.rb +43 -0
  25. data/app/controllers/decidim/meetings/admin/meetings_controller.rb +10 -2
  26. data/app/controllers/decidim/meetings/admin/registrations_controller.rb +6 -5
  27. data/app/controllers/decidim/meetings/application_controller.rb +2 -2
  28. data/app/controllers/decidim/meetings/meeting_widgets_controller.rb +1 -1
  29. data/app/controllers/decidim/meetings/meetings_controller.rb +2 -2
  30. data/app/controllers/decidim/meetings/registrations_controller.rb +1 -1
  31. data/app/forms/decidim/meetings/admin/meeting_copy_form.rb +54 -0
  32. data/app/forms/decidim/meetings/admin/meeting_form.rb +17 -6
  33. data/app/forms/decidim/meetings/admin/meeting_registrations_form.rb +10 -1
  34. data/app/forms/decidim/meetings/admin/meeting_service_form.rb +23 -0
  35. data/app/helpers/decidim/meetings/admin/application_helper.rb +4 -0
  36. data/app/mailers/decidim/meetings/admin/invite_join_meeting_mailer.rb +1 -1
  37. data/app/models/decidim/meetings/abilities/current_user_ability.rb +6 -6
  38. data/app/models/decidim/meetings/meeting.rb +14 -8
  39. data/app/presenters/decidim/meetings/admin_log/meeting_presenter.rb +1 -1
  40. data/app/services/decidim/meetings/meeting_search.rb +2 -2
  41. data/app/types/decidim/meetings/meeting_type.rb +38 -0
  42. data/app/types/decidim/meetings/meetings_type.rb +32 -0
  43. data/app/views/decidim/meetings/admin/invite_join_meeting_mailer/invite.html.erb +1 -1
  44. data/app/views/decidim/meetings/admin/invites/new.html.erb +3 -3
  45. data/app/views/decidim/meetings/admin/meeting_closes/_form.html.erb +2 -3
  46. data/app/views/decidim/meetings/admin/meeting_closes/edit.html.erb +2 -2
  47. data/app/views/decidim/meetings/admin/meeting_copies/_form.html.erb +42 -0
  48. data/app/views/decidim/meetings/admin/meeting_copies/new.html.erb +7 -0
  49. data/app/views/decidim/meetings/admin/meetings/_form.html.erb +15 -11
  50. data/app/views/decidim/meetings/admin/meetings/_service.html.erb +48 -0
  51. data/app/views/decidim/meetings/admin/meetings/_services.html.erb +25 -0
  52. data/app/views/decidim/meetings/admin/meetings/edit.html.erb +2 -3
  53. data/app/views/decidim/meetings/admin/meetings/index.html.erb +13 -9
  54. data/app/views/decidim/meetings/admin/meetings/new.html.erb +2 -2
  55. data/app/views/decidim/meetings/admin/registrations/_form.html.erb +7 -2
  56. data/app/views/decidim/meetings/admin/registrations/edit.html.erb +2 -3
  57. data/app/views/decidim/meetings/meetings/_filters.html.erb +2 -2
  58. data/app/views/decidim/meetings/meetings/_filters_small_view.html.erb +1 -1
  59. data/app/views/decidim/meetings/meetings/_meetings.html.erb +1 -18
  60. data/app/views/decidim/meetings/meetings/_registration_confirm.html.erb +2 -2
  61. data/app/views/decidim/meetings/meetings/index.html.erb +3 -3
  62. data/app/views/decidim/meetings/meetings/show.html.erb +21 -4
  63. data/app/views/decidim/participatory_processes/participatory_process_groups/_highlighted_meetings.html.erb +2 -2
  64. data/app/views/decidim/participatory_spaces/_highlighted_meetings.html.erb +4 -4
  65. data/app/views/decidim/participatory_spaces/_meeting.html.erb +1 -14
  66. data/app/views/devise/mailer/join_meeting.html.erb +1 -1
  67. data/app/views/devise/mailer/join_meeting.text.erb +1 -1
  68. data/config/locales/ca.yml +35 -12
  69. data/config/locales/en.yml +35 -12
  70. data/config/locales/es.yml +35 -12
  71. data/config/locales/eu.yml +35 -12
  72. data/config/locales/fi.yml +35 -12
  73. data/config/locales/fr.yml +35 -12
  74. data/config/locales/gl.yml +35 -12
  75. data/config/locales/it.yml +35 -12
  76. data/config/locales/nl.yml +73 -50
  77. data/config/locales/pl.yml +35 -12
  78. data/config/locales/pt-BR.yml +35 -12
  79. data/config/locales/pt.yml +35 -12
  80. data/config/locales/ru.yml +0 -3
  81. data/config/locales/sv.yml +35 -12
  82. data/config/locales/uk.yml +0 -3
  83. data/db/migrate/20180305133634_rename_features_to_components_at_meetings.rb +11 -0
  84. data/db/migrate/20180326082611_add_fields_for_registrations.rb +7 -0
  85. data/db/migrate/20180407110934_add_services_to_meetings.rb +7 -0
  86. data/lib/decidim/meetings.rb +2 -1
  87. data/lib/decidim/meetings/admin_engine.rb +1 -0
  88. data/lib/decidim/meetings/{feature.rb → component.rb} +27 -19
  89. data/lib/decidim/meetings/engine.rb +27 -4
  90. data/lib/decidim/meetings/test/factories.rb +10 -3
  91. data/lib/decidim/meetings/version.rb +1 -1
  92. data/lib/decidim/meetings/view_model.rb +12 -0
  93. metadata +65 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af15356a0775587dafbbe85ec142bad0254de2e64b0ec7942d02f0017f6a277e
4
- data.tar.gz: 302e490194ad6fab38fa2972ae3740ee3ccc80dc5e233b32ecd4271f1f4248b2
3
+ metadata.gz: 78ef16119c8770f9e30d4a67843a4434786bc7ebe0f01f7b3ec2a9b2ace0b78b
4
+ data.tar.gz: eea9c4856d06311e2b8460c567b77e3313b031b8dbd4c3cd18ad8fd861701b71
5
5
  SHA512:
6
- metadata.gz: 8d68956fe6f5a33ede48d63bde34477536f1c54da2d4d191139ba07c712dc4271bb4559be14c11af2ebbb7d521c533905d8712924b8c7813ecdf342741e8166b
7
- data.tar.gz: e66603e2596a854be786a30a6034810d1ed83e3f17b67a8aa1ae64e495aea7481cb90289674ab82151dbd053dee7c61c9a2b5ceae6c1c8bdef53c5a397ecee16
6
+ metadata.gz: 8ac788f4aac781643df90446878cbe08e0f7a269f385ee3405df4cac4cbdc080751d89d021db90f064bf2be179e91079a39caa3ee56688d4733695de3f7078bf
7
+ data.tar.gz: 688d3ca57dcf0958c823b7ffb268e53186dfc5daa72e06838eaac9fe379c187cecbfbf8b376b7f4f476219bbbad33fc65523307c3dec308b83ffe2c49bcee0c9
data/README.md CHANGED
@@ -4,7 +4,7 @@ The Meetings module adds meeting to any participatory process. It adds a CRUD en
4
4
 
5
5
  ## Usage
6
6
 
7
- Meetings will be available as a Feature for a Participatory Process.
7
+ Meetings will be available as a component for a Participatory Process.
8
8
 
9
9
  ## Installation
10
10
 
@@ -1 +1,2 @@
1
+ //= link decidim/meetings/admin/meetings_form.js
1
2
  //= link decidim/meetings/admin/registrations_form.js
@@ -0,0 +1,78 @@
1
+ ((exports) => {
2
+ const { AutoLabelByPositionComponent, AutoButtonsByPositionComponent, createDynamicFields, createSortList } = exports.DecidimAdmin;
3
+
4
+ const wrapperSelector = ".meeting-services";
5
+ const fieldSelector = ".meeting-service";
6
+
7
+ const autoLabelByPosition = new AutoLabelByPositionComponent({
8
+ listSelector: ".meeting-service:not(.hidden)",
9
+ labelSelector: ".card-title span:first",
10
+ onPositionComputed: (el, idx) => {
11
+ $(el).find("input[name$=\\[position\\]]").val(idx);
12
+ }
13
+ });
14
+
15
+ const autoButtonsByPosition = new AutoButtonsByPositionComponent({
16
+ listSelector: ".meeting-service:not(.hidden)",
17
+ hideOnFirstSelector: ".move-up-service",
18
+ hideOnLastSelector: ".move-down-service"
19
+ });
20
+
21
+ const createSortableList = () => {
22
+ createSortList(".meeting-services-list:not(.published)", {
23
+ handle: ".service-divider",
24
+ placeholder: '<div style="border-style: dashed; border-color: #000"></div>',
25
+ forcePlaceholderSize: true,
26
+ onSortUpdate: () => { autoLabelByPosition.run() }
27
+ });
28
+ };
29
+
30
+ const hideDeletedService = ($target) => {
31
+ const inputDeleted = $target.find("input[name$=\\[deleted\\]]").val();
32
+
33
+ if (inputDeleted === "true") {
34
+ $target.addClass("hidden");
35
+ $target.hide();
36
+ }
37
+ };
38
+
39
+ createDynamicFields({
40
+ placeholderId: "meeting-service-id",
41
+ wrapperSelector: wrapperSelector,
42
+ containerSelector: ".meeting-services-list",
43
+ fieldSelector: fieldSelector,
44
+ addFieldButtonSelector: ".add-service",
45
+ removeFieldButtonSelector: ".remove-service",
46
+ moveUpFieldButtonSelector: ".move-up-service",
47
+ moveDownFieldButtonSelector: ".move-down-service",
48
+ onAddField: () => {
49
+ createSortableList();
50
+
51
+ autoLabelByPosition.run();
52
+ autoButtonsByPosition.run();
53
+ },
54
+ onRemoveField: () => {
55
+ autoLabelByPosition.run();
56
+ autoButtonsByPosition.run();
57
+ },
58
+ onMoveUpField: () => {
59
+ autoLabelByPosition.run();
60
+ autoButtonsByPosition.run();
61
+ },
62
+ onMoveDownField: () => {
63
+ autoLabelByPosition.run();
64
+ autoButtonsByPosition.run();
65
+ }
66
+ });
67
+
68
+ createSortableList();
69
+
70
+ $(fieldSelector).each((idx, el) => {
71
+ const $target = $(el);
72
+
73
+ hideDeletedService($target);
74
+ });
75
+
76
+ autoLabelByPosition.run();
77
+ autoButtonsByPosition.run();
78
+ })(window);
@@ -1,21 +1,23 @@
1
1
  $(() => {
2
- const $form = $('.edit_meeting_registrations');
2
+ const $form = $(".edit_meeting_registrations");
3
3
 
4
4
  if ($form.length > 0) {
5
- const $registrationsEnabled = $form.find('#meeting_registrations_enabled');
6
- const $availableSlots = $form.find('#meeting_available_slots');
5
+ const $registrationsEnabled = $form.find("#meeting_registrations_enabled");
6
+ const $availableSlots = $form.find("#meeting_available_slots");
7
+ const $reservedSlots = $form.find("#meeting_reserved_slots");
7
8
 
8
9
  const toggleDisabledFields = () => {
9
- const enabled = $registrationsEnabled.prop('checked');
10
- $availableSlots.attr('disabled', !enabled);
10
+ const enabled = $registrationsEnabled.prop("checked");
11
+ $availableSlots.attr("disabled", !enabled);
12
+ $reservedSlots.attr("disabled", !enabled);
11
13
 
12
- $form.find('.editor-container').each((idx, node) => {
14
+ $form.find(".editor-container").each((idx, node) => {
13
15
  const quill = Quill.find(node);
14
16
  quill.enable(enabled);
15
17
  })
16
18
  };
17
19
 
18
- $registrationsEnabled.on('change', toggleDisabledFields);
20
+ $registrationsEnabled.on("change", toggleDisabledFields);
19
21
  toggleDisabledFields();
20
22
  }
21
23
  });
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This cell renders the meeting card for an instance of a Meeting
6
+ # the default size is the Medium Card (:m)
7
+ # also available the List Item Card (:list_item)
8
+ class MeetingCell < Decidim::Meetings::ViewModel
9
+ include Cell::ViewModel::Partial
10
+
11
+ def show
12
+ cell card_size, model
13
+ end
14
+
15
+ private
16
+
17
+ def title
18
+ translated_attribute model.title
19
+ end
20
+
21
+ def description
22
+ decidim_sanitize meeting_description(model)
23
+ end
24
+
25
+ def card_size
26
+ case @options[:size]
27
+ when :list_item
28
+ "decidim/meetings/meeting_list_item"
29
+ else
30
+ "decidim/meetings/meeting_m"
31
+ end
32
+ end
33
+
34
+ def resource_icon
35
+ icon "meetings", remove_icon_class: true, width: 40, height: 70
36
+ end
37
+
38
+ def resource_path
39
+ resource_locator(model).path
40
+ end
41
+
42
+ def current_component
43
+ model.component
44
+ end
45
+
46
+ def current_participatory_space
47
+ model.component.participatory_space
48
+ end
49
+
50
+ def component_settings
51
+ model.component.settings
52
+ end
53
+
54
+ def component_name
55
+ translated_attribute current_component.name
56
+ end
57
+
58
+ def component_type_name
59
+ model.class.model_name.human
60
+ end
61
+
62
+ def participatory_space_name
63
+ translated_attribute current_participatory_space.title
64
+ end
65
+
66
+ def participatory_space_type_name
67
+ translated_attribute current_participatory_space.model_name.human
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,14 @@
1
+ <div class="card--list__item">
2
+ <div class="card--list__text">
3
+ <div>
4
+ <%= link_to resource_path, class: "card__link" do %>
5
+ <h6 class="card--list__heading heading6">
6
+ <%= title %>
7
+ </h6>
8
+ <span class="text-medium">
9
+ <%= resource_date_time %>
10
+ </span>
11
+ <% end %>
12
+ </div>
13
+ </div>
14
+ </div>
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This cell renders the List Item Card (:list_item) meeting card
6
+ # for an instance of a Meeting
7
+ #
8
+ # This cell must be wrapped in a "<div class="card card--list"></div>"
9
+ class MeetingListItemCell < Decidim::Meetings::MeetingCell
10
+ def show
11
+ render
12
+ end
13
+
14
+ private
15
+
16
+ def resource_date_time
17
+ str = l model.start_time, format: :decidim_day_of_year
18
+ str += " - "
19
+ str += l model.start_time, format: :time_of_day
20
+ str += "-"
21
+ str += l model.end_time, format: :time_of_day
22
+ str
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ <%= link_to resource_path, class: "card__link" do %>
2
+ <h5 class="card__title">
3
+ <%= title %>
4
+ </h5>
5
+ <% end %>
@@ -0,0 +1,21 @@
1
+ <div class="column">
2
+ <article class="card card--meeting">
3
+ <div class="card__content">
4
+ <%= render :header %>
5
+
6
+ <%= render partial: "decidim/meetings/meetings/datetime.html", locals: { meeting: model } %>
7
+
8
+ <%= description %>
9
+
10
+ <%= render partial: "decidim/shared/tags.html", locals: { resource: model, tags_class_extra: "tags--meeting" } %>
11
+
12
+ <div class="address card__extra">
13
+ <div class="address__icon">
14
+ <%= resource_icon %>
15
+ </div>
16
+
17
+ <%= render partial: "decidim/shared/address_details.html", locals: { icon_name: "meetings", geolocalizable: model } %>
18
+ </div>
19
+ </div>
20
+ </article>
21
+ </div>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ # This cell renders the Medium (:m) meeting card
6
+ # for an given instance of a Meeting
7
+ class MeetingMCell < Decidim::Meetings::MeetingCell
8
+ def show
9
+ render
10
+ end
11
+
12
+ def header
13
+ render
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Admin
6
+ # A command with all the business logic when copying a meeting
7
+ # in the system.
8
+ class CopyMeeting < Rectify::Command
9
+ # Public: Initializes the command.
10
+ #
11
+ # form - A form object with the params.
12
+ # meeting - A meeting we want to duplicate
13
+ def initialize(form, meeting)
14
+ @form = form
15
+ @meeting = meeting
16
+ end
17
+
18
+ # Executes the command. Broadcasts these events:
19
+ #
20
+ # - :ok when everything is valid.
21
+ # - :invalid if the form wasn't valid and we couldn't proceed.
22
+ #
23
+ # Returns nothing.
24
+ def call
25
+ return broadcast(:invalid) if form.invalid?
26
+
27
+ transaction do
28
+ copy_meeting!
29
+ schedule_upcoming_meeting_notification
30
+ send_notification
31
+ end
32
+
33
+ broadcast(:ok, @copied_meeting)
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :form, :meeting
39
+
40
+ def copy_meeting!
41
+ @copied_meeting = Decidim.traceability.create!(
42
+ Meeting,
43
+ @form.current_user,
44
+ scope: @meeting.scope,
45
+ category: @meeting.category,
46
+ title: @form.title,
47
+ description: @form.description,
48
+ end_time: @form.end_time,
49
+ start_time: @form.start_time,
50
+ address: @form.address,
51
+ latitude: @form.latitude,
52
+ longitude: @form.longitude,
53
+ location: @form.location,
54
+ location_hints: @form.location_hints,
55
+ services: @form.services_to_persist.map { |service| { "title" => service.title, "description" => service.description } },
56
+ component: @meeting.component,
57
+ registrations_enabled: @meeting.registrations_enabled,
58
+ available_slots: @meeting.available_slots,
59
+ registration_terms: @meeting.registration_terms
60
+ )
61
+ end
62
+
63
+ def schedule_upcoming_meeting_notification
64
+ checksum = Decidim::Meetings::UpcomingMeetingNotificationJob.generate_checksum(@copied_meeting)
65
+
66
+ Decidim::Meetings::UpcomingMeetingNotificationJob
67
+ .set(wait_until: @copied_meeting.start_time - 2.days)
68
+ .perform_later(@copied_meeting.id, checksum)
69
+ end
70
+
71
+ def send_notification
72
+ Decidim::EventsManager.publish(
73
+ event: "decidim.events.meetings.meeting_created",
74
+ event_class: Decidim::Meetings::CreateMeetingEvent,
75
+ resource: @copied_meeting,
76
+ recipient_ids: @copied_meeting.participatory_space.followers.pluck(:id)
77
+ )
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -35,6 +35,7 @@ module Decidim
35
35
  category: @form.category,
36
36
  title: @form.title,
37
37
  description: @form.description,
38
+ services: @form.services_to_persist.map { |service| { "title" => service.title, "description" => service.description } },
38
39
  end_time: @form.end_time,
39
40
  start_time: @form.start_time,
40
41
  address: @form.address,
@@ -42,7 +43,8 @@ module Decidim
42
43
  longitude: @form.longitude,
43
44
  location: @form.location,
44
45
  location_hints: @form.location_hints,
45
- feature: @form.current_feature
46
+ registration_terms: @form.current_component.settings.default_registration_terms,
47
+ component: @form.current_component
46
48
  )
47
49
  end
48
50
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Meetings
5
+ module Admin
6
+ # This command is executed when the user exports the registrations of
7
+ # a Meeting from the admin panel.
8
+ class ExportMeetingRegistrations < Rectify::Command
9
+ # meeting - The current instance of the page to be closed.
10
+ # format - a string representing the export format
11
+ # current_user - the user performing the action
12
+ def initialize(meeting, format, current_user)
13
+ @meeting = meeting
14
+ @format = format
15
+ @current_user = current_user
16
+ end
17
+
18
+ # Exports the meeting registrations.
19
+ #
20
+ # Broadcasts :ok if successful, :invalid otherwise.
21
+ def call
22
+ broadcast(:ok, export_data)
23
+ end
24
+
25
+ private
26
+
27
+ attr_reader :current_user, :meeting, :format
28
+
29
+ def export_data
30
+ Decidim.traceability.perform_action!(
31
+ :export_registrations,
32
+ meeting,
33
+ current_user
34
+ ) do
35
+ Decidim::Exporters
36
+ .find_exporter(format)
37
+ .new(meeting.registrations, Decidim::Meetings::RegistrationSerializer)
38
+ .export
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end