mumuki-laboratory 9.4.1 → 9.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +15 -0
  3. data/app/assets/javascripts/mumuki_laboratory/application/toast.js +12 -1
  4. data/app/controllers/application_controller.rb +10 -0
  5. data/app/controllers/concerns/with_certificate_render.rb +1 -1
  6. data/app/controllers/discussions_controller.rb +29 -2
  7. data/app/controllers/exam_authorization_requests_controller.rb +8 -0
  8. data/app/helpers/discussions_helper.rb +16 -0
  9. data/app/helpers/exam_registration_helper.rb +13 -0
  10. data/app/mailers/user_mailer.rb +1 -1
  11. data/app/views/certificates/_certificate.html.erb +1 -1
  12. data/app/views/discussions/show.html.erb +6 -0
  13. data/app/views/exam_authorization_requests/_approved.html.erb +2 -1
  14. data/app/views/exam_authorization_requests/_pending.html.erb +1 -0
  15. data/app/views/exam_registrations/show.html.erb +18 -15
  16. data/app/views/exercises/_read_only.html.erb +3 -4
  17. data/app/views/layouts/_discussions.html.erb +3 -3
  18. data/app/views/layouts/_main.html.erb +4 -10
  19. data/app/views/layouts/_toast.html.erb +7 -0
  20. data/app/views/user_mailer/certificate.html.erb +10 -14
  21. data/config/routes.rb +2 -0
  22. data/lib/mumuki/laboratory/locales/en.yml +17 -5
  23. data/lib/mumuki/laboratory/locales/es-CL.yml +16 -3
  24. data/lib/mumuki/laboratory/locales/es.yml +16 -4
  25. data/lib/mumuki/laboratory/locales/pt.yml +16 -4
  26. data/lib/mumuki/laboratory/version.rb +1 -1
  27. data/lib/tasks/messages.rake +3 -5
  28. data/spec/controllers/discussions_controller_spec.rb +42 -0
  29. data/spec/controllers/exam_authorization_requests_controller_spec.rb +53 -3
  30. data/spec/controllers/organizations_api_controller_spec.rb +3 -1
  31. data/spec/dummy/db/schema.rb +3 -3
  32. data/spec/features/discussion_flow_spec.rb +38 -14
  33. metadata +101 -99
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 57bb3a9beabe4c776c88430fb3d6b0f2cc00328da5657f8f4c72bf568cf0d5df
4
- data.tar.gz: 2375d1c0b8eeda4ac72f71d4b36ed83fc759fc3db1be5db69bb48d331d386aa0
3
+ metadata.gz: c293191e2ef2aff563714e0b4e41dee7b9cab1199a4d6c29ff3ebae6defa0250
4
+ data.tar.gz: e38d0255b8b7c89353b78402a6cc0ce575b9efb7a7495b6eb9e676102f8ea8d6
5
5
  SHA512:
6
- metadata.gz: 81d9b2bc3d633cc66105cd4f9052fb13c170bde9aeffb25878ea5e7e3d62a40c0db3824f6da132c82491d1d914ee869aee35a580ce323aa648845ff3b263929c
7
- data.tar.gz: ec9fc1503a59f7caccaf5e0fac8f92bc93556ee08538904b8d92f30e8d965868fdf01c30df91594cdd2a2853e2d85229c97845d37e3e9a9b0344948ef84ce947
6
+ metadata.gz: a7c471ef8b0c0beecc9e93342605c92b2930ac437ddffa2227e04c8e16faa1f5e15faffde3cc23d0a846c9ee88e6d5b84846b1373806bbba5d4b9864a80cc297
7
+ data.tar.gz: 5e289be54ff6b18f84f974e2e4de07cadbab5f570263443b109dee3cf5f799d1ab705407923ded30e76be92b48568faa07403b20442d2a20989df474d36093b2
@@ -1,6 +1,7 @@
1
1
  mumuki.load(() => {
2
2
  var $subscriptionButtons = $('.discussion-subscription > button');
3
3
  var $upvoteButtons = $('.discussion-upvote > button');
4
+ var $responsibleButton = $('.discussion-responsible > button');
4
5
  let $messagePreviewButton = $('.discussion-new-message-preview-button.preview');
5
6
  let $messageEditButton = $('.discussion-new-message-preview-button.edit');
6
7
  let $newMessageContent = $('.discussion-new-message-content');
@@ -53,9 +54,23 @@ mumuki.load(() => {
53
54
  discussionUpvote: function (url) {
54
55
  Forum.discussionPostAndToggle(url, $upvoteButtons);
55
56
  },
57
+ discussionResponsible: function (url) {
58
+ Forum.discussionPostToggleAndRenderToast(url, $responsibleButton);
59
+ $('.responsible-moderator-badge').toggleClass('d-none');
60
+ },
56
61
  discussionPostAndToggle: function (url, elem) {
57
62
  Forum.discussionPost(url).done(Forum.toggleButton(elem));
58
63
  },
64
+ discussionPostToggleAndRenderToast: function (url, elem) {
65
+ Forum.discussionPost(url)
66
+ .done(function (response) {
67
+ Forum.toggleButton(elem);
68
+ mumuki.toast.addToast(response);
69
+ })
70
+ .fail(function (response) {
71
+ mumuki.toast.addToast(response.responseText);
72
+ });
73
+ },
59
74
  discussionMessageToggleApprove: function (url, elem) {
60
75
  Forum.discussionPost(url).done(function () {
61
76
  elem.toggleClass("selected");
@@ -1,3 +1,14 @@
1
+ mumuki.toast = {
2
+ load() {
3
+ document.querySelectorAll('.toast').forEach((toast) => new bootstrap.Toast(toast).show());
4
+ },
5
+
6
+ addToast(content) {
7
+ $('.toast-container').html(content);
8
+ mumuki.toast.load();
9
+ }
10
+ };
11
+
1
12
  mumuki.load(() => {
2
- document.querySelectorAll('.toast').forEach((toast) => new bootstrap.Toast(toast).show());
13
+ mumuki.toast.load();
3
14
  });
@@ -16,6 +16,7 @@ class ApplicationController < ActionController::Base
16
16
 
17
17
  before_action :set_current_organization!
18
18
  before_action :set_locale!
19
+ before_action :set_time_zone!
19
20
 
20
21
  before_action :ensure_user_enabled!, if: :current_user?
21
22
  before_action :validate_active_organization!
@@ -30,6 +31,7 @@ class ApplicationController < ActionController::Base
30
31
  before_action :visit_organization!, if: :current_user?
31
32
 
32
33
  after_action :leave_organization!
34
+ after_action :unset_time_zone!
33
35
 
34
36
  helper_method :current_workspace,
35
37
  :login_button,
@@ -143,6 +145,14 @@ class ApplicationController < ActionController::Base
143
145
  I18n.locale = Organization.current.locale
144
146
  end
145
147
 
148
+ def set_time_zone!
149
+ Time.zone = Organization.current.time_zone
150
+ end
151
+
152
+ def unset_time_zone!
153
+ Time.zone = nil
154
+ end
155
+
146
156
  def subject #TODO may be used to remove breadcrumbs duplication
147
157
  nil
148
158
  end
@@ -10,7 +10,7 @@ module WithCertificateRender
10
10
  end
11
11
 
12
12
  def qr_for(certificate)
13
- qr = RQRCode::QRCode.new(verify_certificate_url certificate.code).as_svg(color: '0B465D')
13
+ qr = RQRCode::QRCode.new(verify_certificate_url certificate.organization, certificate.code).as_svg(color: '0B465D')
14
14
  "data:image/svg+xml,#{URI.encode(qr)}"
15
15
  end
16
16
 
@@ -2,10 +2,11 @@ class DiscussionsController < ApplicationController
2
2
  include Mumuki::Laboratory::Controllers::Content
3
3
  include WithUserDiscussionValidation
4
4
 
5
- before_action :set_debatable, except: [:subscription]
5
+ before_action :set_debatable, except: [:subscription, :responsible]
6
6
  before_action :authenticate!, only: [:update, :create]
7
7
  before_action :discussion_filter_params, only: :index
8
8
  before_action :read_discussion, only: :show
9
+ before_action :authorize_moderator!, only: [:responsible]
9
10
 
10
11
  helper_method :discussion_filter_params
11
12
 
@@ -19,7 +20,6 @@ class DiscussionsController < ApplicationController
19
20
  end
20
21
 
21
22
  def show
22
- @discussion.update_last_moderator_access! current_user
23
23
  end
24
24
 
25
25
  def update
@@ -37,6 +37,20 @@ class DiscussionsController < ApplicationController
37
37
  head :ok
38
38
  end
39
39
 
40
+ def responsible
41
+ if subject.can_toggle_responsible? current_user
42
+ subject.toggle_responsible! current_user
43
+
44
+ set_flash_responsible_confirmation!
45
+ status = :ok
46
+ else
47
+ set_flash_responsible_alert!
48
+ status = :conflict
49
+ end
50
+
51
+ render :partial => 'layouts/toast', status: status
52
+ end
53
+
40
54
  def create
41
55
  discussion = @debatable.discuss! current_user, discussion_params
42
56
  redirect_to [@debatable, discussion]
@@ -57,6 +71,19 @@ class DiscussionsController < ApplicationController
57
71
  @debatable = Discussion.debatable_for(@debatable_class, params)
58
72
  end
59
73
 
74
+ def set_flash_responsible_confirmation!
75
+ subject.any_responsible? ?
76
+ flash.now.notice = I18n.t('moderator_take_care.you_will_confirmation') :
77
+ flash.now.notice = I18n.t('moderator_take_care.you_wont_confirmation')
78
+
79
+ end
80
+
81
+ def set_flash_responsible_alert!
82
+ subject.any_responsible? ?
83
+ flash.now.alert = I18n.t('moderator_take_care.someone_else_will') :
84
+ flash.now.alert = I18n.t('moderator_take_care.status_changed')
85
+ end
86
+
60
87
  def subject
61
88
  @discussion ||= Discussion.find_by(id: params[:id])
62
89
  end
@@ -1,4 +1,7 @@
1
1
  class ExamAuthorizationRequestsController < ApplicationController
2
+
3
+ before_action :verify_registration_opened!, on: [:create, :update]
4
+
2
5
  def create
3
6
  authorization_request = ExamAuthorizationRequest.find_or_create_by! create_authorization_request_params do |it|
4
7
  it.assign_attributes authorization_request_params
@@ -25,4 +28,9 @@ class ExamAuthorizationRequestsController < ApplicationController
25
28
  .require(:exam_authorization_request).permit(:exam_id, :exam_registration_id)
26
29
  .merge(user: current_user, organization: Organization.current)
27
30
  end
31
+
32
+ def verify_registration_opened!
33
+ exam_registration = ExamRegistration.find(authorization_request_params[:exam_registration_id])
34
+ raise Mumuki::Domain::GoneError if exam_registration.end_time.past?
35
+ end
28
36
  end
@@ -196,6 +196,22 @@ module DiscussionsHelper
196
196
  content_tag :a, discussion_user_name(user)
197
197
  end
198
198
 
199
+ def responsible_moderator_text_for(discussion, user)
200
+ if discussion.responsible?(user)
201
+ t('moderator_take_care.you_are')
202
+ else
203
+ t('moderator_take_care.moderator_is', moderator: discussion_user_name(discussion.responsible_moderator_by))
204
+ end
205
+ end
206
+
207
+ def responsible_icon
208
+ fa_icon 'hand-paper', text: t('moderator_take_care.i_will')
209
+ end
210
+
211
+ def not_responsible_icon
212
+ fa_icon 'hand-rock', type: :regular, text: t('moderator_take_care.i_wont')
213
+ end
214
+
199
215
  def subscription_icon
200
216
  fa_icon :bell, text: t(:subscribe)
201
217
  end
@@ -0,0 +1,13 @@
1
+ module ExamRegistrationHelper
2
+ def exam_registration_view
3
+ if @registration.end_time.past?
4
+ { icon: :times_circle, class: :danger, t: :exam_registration_finished_html }
5
+ else
6
+ { icon: :info_circle, class: :info, t: :exam_registration_explanation_html }
7
+ end
8
+ end
9
+
10
+ def current_time_zone_html
11
+ %Q{(<span class="select-date-timezone">#{Organization.current&.time_zone}</span>)}.html_safe
12
+ end
13
+ end
@@ -23,7 +23,7 @@ class UserMailer < ApplicationMailer
23
23
  def certificate(certificate)
24
24
  with_locale certificate.user, certificate.organization do
25
25
  attachments[certificate.filename] = pdf_for(certificate)
26
- mail to: certificate.user.email, subject: t(:certificate)
26
+ mail to: certificate.user.email, subject: certificate.description
27
27
  end
28
28
  end
29
29
 
@@ -38,7 +38,7 @@
38
38
  <div class="mu-certificate-box">
39
39
  <img src="<%= certificate.background_image_url %>" class="background-image"/>
40
40
  <%= render inline: certificate.template_html_erb, locals: certificate.template_locals %>
41
- <a href="<%= verify_certificate_path certificate.code %>" target="_blank">
41
+ <a href="<%= verify_certificate_url certificate.organization, certificate.code %>" target="_blank">
42
42
  <div><img class="qr-code" src="<%= qr_for certificate %>"/></div>
43
43
  </a>
44
44
  </div>
@@ -15,6 +15,12 @@
15
15
  <h3 class="flex-grow-1 me-3"><%= t :messages %></h3>
16
16
  <% if current_user && @discussion.persisted? %>
17
17
  <span class="d-flex">
18
+ <% if @discussion.can_toggle_responsible?(current_user) %>
19
+ <div class="discussion-responsible me-1">
20
+ <%= btn_toggle responsible_icon, not_responsible_icon, @discussion.any_responsible?, class: 'btn-sm',
21
+ onclick: "mumuki.Forum.discussionResponsible('#{responsible_discussion_url(@discussion)}')" %>
22
+ </div>
23
+ <% end %>
18
24
  <% if @discussion.subscribable? %>
19
25
  <div class="discussion-subscription me-1">
20
26
  <%= btn_toggle subscription_icon, unsubscription_icon, current_user.subscribed_to?(@discussion), class: 'btn-sm',
@@ -1 +1,2 @@
1
- <%= t :exam_authorization_request_approved_html, date: l(authorization_request.exam.start_time, format: :long) %>
1
+ <%= t :exam_authorization_request_approved_html, date: l(authorization_request.exam.start_time, format: :long),
2
+ location: Organization.current.time_zone %>
@@ -1,4 +1,5 @@
1
1
  <%= t :exam_authorization_pending_explanation_html,
2
2
  date: l(authorization_request.exam.start_time, format: :long),
3
3
  end_time: l(authorization_request.exam_registration.end_time, format: :long),
4
+ location: Organization.current.time_zone,
4
5
  edit_path: url_for(authorization_request.exam_registration) %>
@@ -12,25 +12,28 @@
12
12
 
13
13
  <div class="row">
14
14
  <div class="col-lg-12">
15
- <div class="bs-callout bs-callout-info">
16
- <h4 class="text-info">
17
- <strong><%= fa_icon :info_circle %> <%= t :important_info %></strong>
18
- </h4>
15
+ <div class="bs-callout bs-callout-<%= exam_registration_view[:class] %>">
16
+ <h4 class="text-<%= exam_registration_view[:class] %>">
17
+ <strong><%= fa_icon exam_registration_view[:icon] %> <%= t :important_info %></strong>
18
+ </h4>
19
19
  <p>
20
- <%= t :exam_registration_explanation_html, date: l(@registration.end_time, format: :long) %>
20
+ <%= t exam_registration_view[:t], date: l(@registration.end_time, format: :long), location: Organization.current.time_zone %>
21
21
  </p>
22
22
  </div>
23
- <%= form_for @authorization_request, html: {class: 'mu-form'} do |f| %>
24
- <%= f.hidden_field :exam_registration_id, value: @registration.id %>
25
- <%= f.label :exam_id, t(:exam_registration_choose_exam) %>
26
- <% @registration.exams.each do |exam| %>
27
- <div class="form-check">
28
- <%= f.radio_button(:exam_id, exam.id, id: exam.id, required: true, class: 'form-check-input mu-read-only-input',
29
- checked: @authorization_request.exam_id == exam.id) %>
30
- <%= label_tag exam.id, l(exam.start_time, format: :long), class: 'form-check-label' %>
31
- </div>
23
+ <% unless @registration.end_time.past? %>
24
+ <%= form_for @authorization_request, html: {class: 'mu-form'} do |f| %>
25
+ <%= f.hidden_field :exam_registration_id, value: @registration.id %>
26
+ <%= f.label :exam_id, t(:exam_registration_choose_exam) %>
27
+ <% @registration.exams.each do |exam| %>
28
+ <div class="form-check">
29
+ <%= f.radio_button(:exam_id, exam.id, id: exam.id, required: true, class: 'form-check-input mu-read-only-input',
30
+ checked: @authorization_request.exam_id == exam.id) %>
31
+ <%= label_tag exam.id, "#{l(exam.start_time, format: :long)} #{current_time_zone_html}".html_safe, class: 'form-check-label' %>
32
+ </div>
33
+ <% end %>
34
+ <button class="btn btn-complementary"> <%= t :save %> </button>
32
35
  <% end %>
33
- <button class="btn btn-complementary"> <%= t :save %> </button>
34
36
  <% end %>
35
37
  </div>
36
38
  </div>
39
+
@@ -31,11 +31,10 @@
31
31
  <span><%= discussion_info(@discussion) unless @discussion.new_record? %></span>
32
32
  </span>
33
33
  </div>
34
- <% if @discussion.last_moderator_access_visible_for?(current_user) %>
34
+ <% if @discussion.current_responsible_visible_for?(current_user) %>
35
35
  <h5 class="my-2 me-3">
36
- <span class="badge bg-primary text-wrap">
37
- <%= t :last_seen, name: discussion_user_name(@discussion.last_moderator_access_by) %>
38
- <%= t :time_since, time: time_ago_in_words(@discussion.last_moderator_access_at) %>
36
+ <span class="badge bg-primary text-wrap responsible-moderator-badge">
37
+ <%= responsible_moderator_text_for(@discussion, current_user) %>
39
38
  </span>
40
39
  </h5>
41
40
  <% end %>
@@ -58,11 +58,11 @@
58
58
  </span>
59
59
  <span class="d-none d-lg-inline"><%= discussion.exercise.guide.name %> -</span>
60
60
  <span><%= discussion.exercise.name %></span>
61
- <% if discussion.last_moderator_access_visible_for?(current_user) %>
61
+ <% if discussion.current_responsible_visible_for?(current_user) %>
62
62
  <div class="float-end discussion-moderator-access" >
63
- <%= profile_picture_for(discussion.last_moderator_access_by, height: 32) %>
63
+ <%= profile_picture_for(discussion.responsible_moderator_by, height: 32) %>
64
64
  <span class="moderator-initials">
65
- <%= discussion.last_moderator_access_by.name_initials %>
65
+ <%= discussion.responsible_moderator_by.name_initials %>
66
66
  </span>
67
67
  </div>
68
68
  <% end %>
@@ -28,17 +28,11 @@
28
28
 
29
29
  <%= yield :navbar %>
30
30
 
31
- <div class="<%= exercise_container_type %><%= ' mb-5' unless input_kids? %>" id="wrap">
32
- <div class="toast-container bottom-0 start-0 p-3">
33
- <% if notice %>
34
- <%= toast_notice(notice) %>
35
- <% elsif alert %>
36
- <%= toast_alert(alert) %>
37
- <% elsif info %>
38
- <%= toast_info(info) %>
39
- <% end %>
40
- </div>
31
+ <div class="toast-container bottom-0 start-0 p-3">
32
+ <%= render partial: 'layouts/toast' %>
33
+ </div>
41
34
 
35
+ <div class="<%= exercise_container_type %><%= ' mb-5' unless input_kids? %>" id="wrap">
42
36
  <%= yield %>
43
37
  </div>
44
38
 
@@ -0,0 +1,7 @@
1
+ <% if notice %>
2
+ <%= toast_notice(notice) %>
3
+ <% elsif alert %>
4
+ <%= toast_alert(alert) %>
5
+ <% elsif info %>
6
+ <%= toast_info(info) %>
7
+ <% end %>
@@ -76,20 +76,7 @@
76
76
  <table border="0" cellpadding="0" cellspacing="0" class="muMailCaptionRightContentOuter" width="100%">
77
77
  <tbody><tr>
78
78
  <td valign="top" class="muMailCaptionRightContentInner" style="padding:0 9px ;">
79
- <table align="left" border="0" cellpadding="0" cellspacing="0" class="muMailCaptionRightImageContentContainer" width="264">
80
- <tbody><tr>
81
- <td class="muMailCaptionRightImageContent" align="center" valign="top">
82
-
83
-
84
-
85
- <img alt="" src="https://gallery.mailchimp.com/046b6c670d9f80ebd6c5d075b/images/225fe60f-780a-451e-90aa-afb01f88a1b4.png" width="159" style="max-width:159px;" class="muMailImage">
86
-
87
-
88
-
89
- </td>
90
- </tr>
91
- </tbody></table>
92
- <table class="muMailCaptionRightTextContentContainer" align="right" border="0" cellpadding="0" cellspacing="0" width="264">
79
+ <table class="muMailCaptionRightTextContentContainer" align="center" border="0" cellpadding="0" cellspacing="0" width="264">
93
80
  <tbody><tr>
94
81
  <td valign="top" class="muMailTextContent">
95
82
  <h3 class="null" style="text-align: center;"><br>
@@ -115,6 +102,15 @@
115
102
  <tbody class="muMailButtonBlockOuter">
116
103
  <tr>
117
104
  <td style="padding-top:0; padding-right:18px; padding-bottom:18px; padding-left:18px;" valign="top" align="center" class="muMailButtonBlockInner">
105
+ <table border="0" cellpadding="0" cellspacing="0" class="muMailButtonContentContainer" style="border-collapse: separate !important;border-radius: 3px;background-color: #FF5B81;">
106
+ <tbody>
107
+ <tr>
108
+ <td align="center" valign="middle" class="muMailButtonContent" style="font-family: Helvetica; font-size: 18px; padding: 18px;">
109
+ <a class="muMailButton " title=<%= t :my_profile %> href=<%= @organization.url_for('/user') %> target="_self" style="font-weight: bold;letter-spacing: -0.5px;line-height: 100%;text-align: center;text-decoration: none;color: #FFFFFF;"><%= t :my_profile %></a>
110
+ </td>
111
+ </tr>
112
+ </tbody>
113
+ </table>
118
114
  </td>
119
115
  </tr>
120
116
  </tbody>
data/config/routes.rb CHANGED
@@ -12,6 +12,8 @@ Rails.application.routes.draw do
12
12
  end
13
13
  end
14
14
 
15
+ post '/discussions/:id/responsible' => 'discussions#responsible', as: :responsible_discussion
16
+
15
17
  get '/discussions/terms' => 'book_discussions#terms'
16
18
  concerns :debatable, controller: 'book_discussions', only: :index
17
19
 
@@ -108,14 +108,15 @@ en:
108
108
  error_500: 500 error
109
109
  error_description: This is known as a <span class="error-link">%{error}</span>.
110
110
  errored: Oops, your solution didn't work
111
- exam_authorization_pending_explanation_html: You have until <strong>%{end_time}</strong> to register. After that date, your request will be processed and you will receive a confirmation. <br> Don't forget to check the notifications!
112
- exam_authorization_request_approved_html: Your request was approved, don't forget to log in at <strong>%{date}</strong>. Good luck!
111
+ exam_authorization_pending_explanation_html: You have until <strong>%{end_time}</strong> (%{location} time) to register. After that date, your request will be processed and you will receive a confirmation. <br> Don't forget to check the notifications!
112
+ exam_authorization_request_approved_html: Your request was approved, don't forget to log in at <strong>%{date}</strong> (%{location} time). Good luck!
113
113
  exam_authorization_request_created: Your registration to the exam has been saved!
114
114
  exam_authorization_request_rejected: Your request was rejected because you didn't meet the requirements.
115
115
  exam_authorization_request_saved: Your registration to the exam has been updated!
116
116
  exam_authorization_request_updated: Your registration to %{description} has been updated
117
117
  exam_registration_choose_exam: Choose date and time to attend to the exam
118
- exam_registration_explanation_html: You have until <strong>%{date}</strong> to register. After that date, your request will be processed and you will receive a confirmation. <br> Don't forget to check the notifications!
118
+ exam_registration_explanation_html: You have until <strong>%{date}</strong> (%{location} time) to register. After that date, your request will be processed and you will receive a confirmation. <br> Don't forget to check the notifications!
119
+ exam_registration_finished_html: Registration for this exam ended on <strong>%{date}</strong> (%{location} time)
119
120
  exam_registration_open: Registrations open for %{description}!
120
121
  exam_registration_to: Registration to %{description}
121
122
  exams_will_be_here: Your exams in the organization will appear here.
@@ -168,7 +169,6 @@ en:
168
169
  kids_default_success: You did it great!
169
170
  language: Language
170
171
  last_name: Last Name
171
- last_seen: "Seen by %{name}"
172
172
  last_submission_date: Last submission
173
173
  latest_exercises: Latest exercises
174
174
  learning: Learning
@@ -190,11 +190,20 @@ en:
190
190
  message_deleted: This message was deleted because it %{motive}, which violates the %{forum_terms}.
191
191
  messages: Messages
192
192
  messages_error: Previous messages are unavailable. Please try again later.
193
- moderation: Mentoring
194
193
  messages_pluralized:
195
194
  one: Message
196
195
  other: Messages
196
+ moderation: Mentoring
197
197
  moderator: Mentor
198
+ moderator_take_care:
199
+ i_will: I'll take care of it
200
+ i_wont: I won't take care of it
201
+ moderator_is: "%{moderator} is taking care of it"
202
+ status_changed: The discussion status changed. Please refresh the page.
203
+ someone_else_will: Someone else already marked they'll take care of it.
204
+ you_are: You're taking care of it
205
+ you_will_confirmation: You'll take care of this discussion. If you change your mind, click the button again.
206
+ you_wont_confirmation: You won't take care of this discussion.
198
207
  more_messages: More
199
208
  my_account: My account
200
209
  my_doubts: My doubts
@@ -208,6 +217,9 @@ en:
208
217
  need_help: I need help!
209
218
  never: never
210
219
  new: New
220
+ new_certificate_mailer_title: 'Congratulations'
221
+ new_certificate_mailer_p1: 'Your new certificate is ready'
222
+ new_certificate_mailer_p2: 'You can find it attached to this email or you can view it in your Mumuki profile'
211
223
  new_message_placeholder: Write a message for your teacher...
212
224
  new_message_received: You have a new message from %{sender}
213
225
  next_exercise: Next
@@ -108,14 +108,15 @@ es-CL:
108
108
  internal_server_error: ¡Ups! Algo no anduvo bien
109
109
  not_found: ¡Ups! La página no existe
110
110
  errored: ¡Ups! Tu solución no se puede ejecutar
111
- exam_authorization_pending_explanation_html: Tienes tiempo hasta el <strong>%{end_time}</strong> para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No olvides revisar las notificaciones!
112
- exam_authorization_request_approved_html: Tu solicitud fue aprobada, no olvides conectarte el <strong>%{date}</strong>. ¡Buena suerte!
111
+ exam_authorization_pending_explanation_html: Tienes tiempo hasta el <strong>%{end_time}</strong> (hora de %{location}) para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No olvides revisar las notificaciones!
112
+ exam_authorization_request_approved_html: Tu solicitud fue aprobada, no olvides conectarte el <strong>%{date}</strong> (hora de %{location}). ¡Buena suerte!
113
113
  exam_authorization_request_created: ¡Tu inscripción al exámen se registró exitosamente!
114
114
  exam_authorization_request_rejected: Tu solicitud fue rechazada porque no cumpliste con los requisitos para rendir el examen.
115
115
  exam_authorization_request_saved: ¡Tu inscripción al exámen se modificó exitosamente!
116
116
  exam_authorization_request_updated: Hay novedades sobre tu inscripción a %{description}
117
117
  exam_registration_choose_exam: Seleccioná día y horario en el que te gustaría rendir el exámen
118
- exam_registration_explanation_html: Tienes tiempo hasta el <strong>%{date}</strong> para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No olvides revisar las notificaciones!
118
+ exam_registration_explanation_html: Tienes tiempo hasta el <strong>%{date}</strong> (hora de %{location}) para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No olvides revisar las notificaciones!
119
+ exam_registration_finished_html: La inscripción a este examen finalizó el <strong>%{date}</strong> (hora de %{location})
119
120
  exam_registration_open: ¡Ya puedes inscribirte a %{description}!
120
121
  exam_registration_to: Inscripción a %{description}
121
122
  exams_will_be_here: Tus exámenes en esta organización aparecerán acá
@@ -197,6 +198,15 @@ es-CL:
197
198
  minutes: minutos
198
199
  moderation: Mentoría
199
200
  moderator: Mentor
201
+ moderator_take_care:
202
+ i_will: Yo me ocupo
203
+ i_wont: Mejor no me ocupo
204
+ moderator_is: "%{moderator} se está ocupando"
205
+ status_changed: La consulta cambió de estado. Por favor, actualiza la página.
206
+ someone_else_will: Alguien más ya marcó que se va a ocupar.
207
+ you_are: Te estás ocupando
208
+ you_will_confirmation: Te vas a ocupar de esta consulta. Si cambias de parecer, toca nuevamente el botón.
209
+ you_wont_confirmation: No te vas a ocupar de esta consulta.
200
210
  more_messages: Ver mensajes anteriores
201
211
  my_account: Mi cuenta
202
212
  my_doubts: Mis consultas
@@ -211,6 +221,9 @@ es-CL:
211
221
  new: Nuevo
212
222
  new_discussion: Nueva consulta
213
223
  new_message: ¿Tienes dudas? ¡Levanta la mano!
224
+ new_certificate_mailer_title: 'Felicitaciones'
225
+ new_certificate_mailer_p1: 'Ya está listo tu nuevo certificado'
226
+ new_certificate_mailer_p2: 'Podés descargarlo desde el adjunto de este mail o bien visualizarlo en tu perfil de Mumuki'
214
227
  new_message_placeholder: Escribe el mensaje para tu docente acá...
215
228
  new_message_received: Tienes un nuevo mensaje de %{sender}
216
229
  next_exercise: Siguiente
@@ -116,14 +116,15 @@ es:
116
116
  internal_server_error: ¡Ups! Algo no anduvo bien
117
117
  not_found: ¡Ups! La página no existe
118
118
  errored: ¡Ups! Tu solución no se puede ejecutar
119
- exam_authorization_pending_explanation_html: Tenés tiempo hasta el <strong>%{end_time}</strong> para cambiar el turno haciendo click <strong><a href="%{edit_path}">acá</a></strong>. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No te olvides de revisar las notificaciones!
120
- exam_authorization_request_approved_html: Tu solicitud fue aprobada, no olvides conectarte el <strong>%{date}</strong>. ¡Buena suerte!
119
+ exam_authorization_pending_explanation_html: Tenés tiempo hasta el <strong>%{end_time}</strong> (hora de %{location}) para cambiar el turno haciendo click <strong><a href="%{edit_path}">acá</a></strong>. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No te olvides de revisar las notificaciones!
120
+ exam_authorization_request_approved_html: Tu solicitud fue aprobada, no olvides conectarte el <strong>%{date}</strong> (hora de %{location}). ¡Buena suerte!
121
121
  exam_authorization_request_created: ¡Tu inscripción al exámen se registró exitosamente!
122
122
  exam_authorization_request_rejected: Tu solicitud fue rechazada porque no cumpliste con los requisitos para rendir el examen.
123
123
  exam_authorization_request_saved: ¡Tu inscripción al exámen se modificó exitosamente!
124
124
  exam_authorization_request_updated: Hay novedades sobre tu inscripción a %{description}
125
125
  exam_registration_choose_exam: Seleccioná día y horario en el que te gustaría rendir el exámen
126
- exam_registration_explanation_html: Tenés tiempo hasta el <strong>%{date}</strong> para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No te olvides de revisar las notificaciones!
126
+ exam_registration_explanation_html: Tenés tiempo hasta el <strong>%{date}</strong> (hora de %{location}) para inscribirte. Pasada esa fecha, tu solicitud será evaluada y recibirás una confirmación. <br> ¡No te olvides de revisar las notificaciones!
127
+ exam_registration_finished_html: La inscripción a este examen finalizó el <strong>%{date}</strong> (hora de %{location})
127
128
  exam_registration_open: ¡Ya podés inscribirte a %{description}!
128
129
  exam_registration_to: Inscripción a %{description}
129
130
  exams_will_be_here: Tus exámenes en esta organización aparecerán acá
@@ -179,7 +180,6 @@ es:
179
180
  language: Lenguaje
180
181
  languages: Lenguajes
181
182
  last_name: Apellido
182
- last_seen: "Visto por %{name}"
183
183
  last_submission_date: Última solución
184
184
  latest_exercises: Últimos ejercicios
185
185
  learning: Aprendizaje
@@ -208,6 +208,15 @@ es:
208
208
  minutes: minutos
209
209
  moderation: Mentoría
210
210
  moderator: Mentor
211
+ moderator_take_care:
212
+ i_will: Yo me ocupo
213
+ i_wont: Mejor no me ocupo
214
+ moderator_is: "%{moderator} se está ocupando"
215
+ status_changed: La consulta cambió de estado. Por favor, actualizá la página.
216
+ someone_else_will: Alguien más ya marcó que se va a ocupar.
217
+ you_are: Te estás ocupando
218
+ you_will_confirmation: Te vas a ocupar de esta consulta. Si cambiás de parecer, tocá nuevamente el botón.
219
+ you_wont_confirmation: No te vas a ocupar de esta consulta.
211
220
  more_messages: Ver mensajes anteriores
212
221
  my_account: Mi cuenta
213
222
  my_doubts: Mis consultas
@@ -220,6 +229,9 @@ es:
220
229
  need_help: No entiendo, ¡necesito ayuda!
221
230
  never: nunca
222
231
  new: Nuevo
232
+ new_certificate_mailer_title: 'Felicitaciones'
233
+ new_certificate_mailer_p1: 'Ya está listo tu nuevo certificado'
234
+ new_certificate_mailer_p2: 'Podés descargarlo desde el adjunto de este mail o bien visualizarlo en tu perfil de Mumuki'
223
235
  new_discussion: Nueva consulta
224
236
  new_message: ¿Tenés dudas? ¡Levantá la mano!
225
237
  new_message_placeholder: Escribí el mensaje para tu docente acá...
@@ -111,14 +111,15 @@ pt:
111
111
  error_500: erro 500
112
112
  error_description: Isto é o que é conhecido como <span class = "error-link"> %{error} </ span>.
113
113
  errored: Opa! Sua solução não pode ser executada
114
- exam_authorization_pending_explanation_html: Você tem tempo até <strong>%{date}</strong> para se inscrever. Após essa data, sua inscrição será avaliada e você receberá uma confirmação. <br> Não se esqueça de verificar as notificações!
115
- exam_authorization_request_approved_html: Sua solicitação foi aprovada, não se esqueça de conectar em <strong>%{date}</strong>. Boa sorte!
114
+ exam_authorization_pending_explanation_html: Você tem tempo até <strong>%{date}</strong> (horário de %{location}) para se inscrever. Após essa data, sua inscrição será avaliada e você receberá uma confirmação. <br> Não se esqueça de verificar as notificações!
115
+ exam_authorization_request_approved_html: Sua solicitação foi aprovada, não se esqueça de conectar em <strong>%{date}</strong> (horário de %{location}). Boa sorte!
116
116
  exam_authorization_request_created: Seu registro de exame foi salvo com sucesso!
117
117
  exam_authorization_request_rejected: Sua solicitação foi rejeitada porque você não atendeu aos requisitos.
118
118
  exam_authorization_request_saved: Seu registro de exame foi modificado com sucesso!
119
119
  exam_authorization_request_updated: Há notícias sobre seu registro para %{description}
120
120
  exam_registration_choose_exam: Selecione o dia e a hora em que gostaria de fazer o exame
121
- exam_registration_explanation_html: Você tem tempo até <strong>%{date}</strong> para se inscrever. Após essa data, sua inscrição será avaliada e você receberá uma confirmação. <br> Não se esqueça de verificar as notificações!
121
+ exam_registration_explanation_html: Você tem tempo até <strong>%{date}</strong> (horário de %{location}) para se inscrever. Após essa data, sua inscrição será avaliada e você receberá uma confirmação. <br> Não se esqueça de verificar as notificações!
122
+ exam_registration_finished_html: A inscrição para este exame terminou na <strong>%{date}</strong> (horário de %{location})
122
123
  exam_registration_open: "¡Inscrições abertas para %{description}!"
123
124
  exam_registration_to: Inscrição a %{description}
124
125
  exams_will_be_here: Seus Examesca nesta organização aparecerão aqui
@@ -172,7 +173,6 @@ pt:
172
173
  language: Linguagem
173
174
  languages: Linguagens
174
175
  last_name: Sobrenome
175
- last_seen: "Visto por %{name}"
176
176
  last_submission_date: Última solução
177
177
  latest_exercises: Últimos exercícios
178
178
  learning: Aprendendo
@@ -202,6 +202,15 @@ pt:
202
202
  minutes: minutos
203
203
  moderation: Mentoria
204
204
  moderator: Mentor
205
+ moderator_take_care:
206
+ i_will: Eu cuidarei disso
207
+ i_wont: Eu não vou cuidar
208
+ moderator_is: "%{moderator} está cuidando"
209
+ status_changed: A consulta mudou de estado. Por favor, atualize para ver a consulta atualizada.
210
+ someone_else_will: Alguém já marcou que vai cuidar disso.
211
+ you_are: Você está cuidando
212
+ you_will_confirmation: Você vai cuidar dessa consulta. Se mudar de ideia, clique no botão novamente.
213
+ you_wont_confirmation: Você não vai cuidar dessa consulta.
205
214
  more_messages: Ver as mensagens anteriores
206
215
  my_account: Minha conta
207
216
  my_doubts: Minhas duvidas
@@ -214,6 +223,9 @@ pt:
214
223
  need_help: Não entendo, preciso de ajuda!
215
224
  never: nunca
216
225
  new: Novo
226
+ new_certificate_mailer_title: 'Parabéns'
227
+ new_certificate_mailer_p1: 'Seu novo certificado está pronto'
228
+ new_certificate_mailer_p2: 'Você pode baixá-lo do anexo deste e-mail ou visualizá-lo em seu perfil Mumuki'
217
229
  new_message: Você tem dúvidas? Levante a mão!
218
230
  new_message_placeholder: Escreva sua mensagem para o seu professor aqui ...
219
231
  new_message_received: Você tem uma nova mensagem de %{sender}
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Laboratory
3
- VERSION = '9.4.1'
3
+ VERSION = '9.7.1'
4
4
  end
5
5
  end
@@ -6,11 +6,9 @@ namespace :laboratory do
6
6
  logger.info 'Listening to messages'
7
7
 
8
8
  Mumukit::Nuntius::Consumer.start 'teacher-messages', 'teacher-messages' do |_delivery_info, _properties, body|
9
- begin
10
- Message.import_from_resource_h!(body)
11
- rescue ActiveRecord::RecordInvalid => e
12
- logger.info e
13
- end
9
+ ApplicationRecord.with_pg_retry { Message.import_from_resource_h!(body) }
10
+ rescue ActiveRecord::RecordInvalid => e
11
+ logger.info e
14
12
  end
15
13
  end
16
14
  end
@@ -62,6 +62,48 @@ describe DiscussionsController, organization_workspace: :test do
62
62
  end
63
63
  end
64
64
 
65
+ describe 'responsible' do
66
+ let(:discussion) { create(:discussion, {organization: Organization.current}) }
67
+
68
+ describe 'user wants to be responsible' do
69
+ before { post :responsible, params: {id: discussion.id} }
70
+
71
+ it { expect(response.status).to eq 403 }
72
+ it { expect(discussion.reload.responsible? user).to be false }
73
+ end
74
+
75
+ describe 'moderator' do
76
+ let(:moderator) { create(:user, permissions: {student: '*', moderator: '*'}) }
77
+ before { set_current_user! moderator }
78
+
79
+ describe 'wants to be responsible' do
80
+ before { post :responsible, params: {id: discussion.id} }
81
+
82
+ it { expect(response.status).to eq 200 }
83
+ it { expect(discussion.reload.responsible? moderator).to be true }
84
+ end
85
+
86
+ describe 'wants to be responsible but changes their mind' do
87
+ before { 2.times{ post :responsible, params: {id: discussion.id} } }
88
+
89
+ it { expect(response.status).to eq 200 }
90
+ it { expect(discussion.reload.responsible? moderator).to be false }
91
+ end
92
+
93
+ describe 'wants to be responsible but someone else already is' do
94
+ let(:another_moderator) { create(:user, permissions: {student: '*', moderator: '*'}) }
95
+ before do
96
+ discussion.toggle_responsible! another_moderator
97
+ post :responsible, params: {id: discussion.id}
98
+ end
99
+
100
+ it { expect(response.status).to eq 409 }
101
+ it { expect(discussion.reload.responsible? moderator).to be false }
102
+ it { expect(discussion.reload.responsible? another_moderator).to be true }
103
+ end
104
+ end
105
+ end
106
+
65
107
  describe 'when the minimal role for discussions is teacher' do
66
108
  before { Organization.current.tap { |it| it.forum_discussions_minimal_role = 'teacher' }.save! }
67
109
 
@@ -10,14 +10,64 @@ describe ExamAuthorizationRequestsController, type: :controller, organization_wo
10
10
  describe 'create' do
11
11
  let!(:notification) { create(:notification, target: exam_registration, user: user) }
12
12
 
13
- before do
13
+ def do_post
14
14
  post :create, params: {
15
15
  exam_authorization_request: { exam_id: exam.id, exam_registration_id: exam_registration.id }
16
16
  }
17
17
  end
18
18
 
19
+ before { do_post }
20
+
21
+ describe 'called once' do
22
+ it { expect(response.status).to eq 302 }
23
+ it { expect(exam_registration.authorization_requests.size).to be 1 }
24
+ it { expect(notification.reload.read).to be_truthy }
25
+ end
26
+
27
+ describe 'called twice' do
28
+ before { do_post }
29
+ it { expect(response.status).to eq 302 }
30
+ it { expect(exam_registration.authorization_requests.size).to be 1 }
31
+ it { expect(notification.reload.read).to be_truthy }
32
+ end
33
+ end
34
+
35
+ describe 'update' do
36
+ let(:exam_authorization_request) { create :exam_authorization_request, exam: exam, exam_registration: exam_registration, user: user }
37
+
38
+ before do
39
+ put :update, params: {
40
+ id: exam_authorization_request.id,
41
+ exam_authorization_request: { exam_id: exam.id, exam_registration_id: exam_registration.id }
42
+ }
43
+ end
44
+
19
45
  it { expect(response.status).to eq 302 }
20
- it { expect(exam_registration.authorization_requests.length).to be 1 }
21
- it { expect(notification.reload.read).to be_truthy }
46
+ it { expect(exam_registration.authorization_requests.size).to be 1 }
47
+ end
48
+
49
+ describe 'fails if exam_registration time ended' do
50
+ let(:exam_registration) { create(:exam_registration, exams: [exam], end_time: 2.minutes.ago) }
51
+ let(:exam_authorization_request) { create :exam_authorization_request, exam: exam, exam_registration: exam_registration, user: user }
52
+
53
+ describe 'create' do
54
+ before do
55
+ post :create, params: {
56
+ exam_authorization_request: { exam_id: exam.id, exam_registration_id: exam_registration.id }
57
+ }
58
+ end
59
+ it { expect(response.status).to eq 410 }
60
+ end
61
+
62
+ describe 'update' do
63
+ before do
64
+ put :update, params: {
65
+ id: exam_authorization_request.id,
66
+ exam_authorization_request: { exam_id: exam.id, exam_registration_id: exam_registration.id }
67
+ }
68
+ end
69
+ it { expect(response.status).to eq 410 }
70
+ end
22
71
  end
72
+
23
73
  end
@@ -198,6 +198,7 @@ describe Api::OrganizationsController, type: :controller, organization_workspace
198
198
  terms_of_service: 'A TOS',
199
199
  public: false,
200
200
  login_methods: ['facebook', 'user_pass'],
201
+ time_zone: 'UTC',
201
202
  book: book }
202
203
  let(:updated_organizaton) { organization.reload }
203
204
  let(:update_json) { {contact_email: 'second_email@gmail.com', immersive: true, locale: 'en'} }
@@ -214,7 +215,8 @@ describe Api::OrganizationsController, type: :controller, organization_workspace
214
215
  description: "a great org",
215
216
  locale: 'en',
216
217
  contact_email: "second_email@gmail.com",
217
- terms_of_service: 'A TOS'
218
+ terms_of_service: 'A TOS',
219
+ time_zone: 'UTC'
218
220
  },
219
221
  settings: {
220
222
  login_methods: ["facebook", "user_pass"],
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 20210330175706) do
13
+ ActiveRecord::Schema.define(version: 20210518100153) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -151,8 +151,8 @@ ActiveRecord::Schema.define(version: 20210330175706) do
151
151
  t.integer "messages_count", default: 0
152
152
  t.integer "validated_messages_count", default: 0
153
153
  t.boolean "requires_moderator_response", default: true
154
- t.string "last_moderator_access_by_id"
155
- t.datetime "last_moderator_access_at"
154
+ t.string "responsible_moderator_by_id"
155
+ t.datetime "responsible_moderator_at"
156
156
  t.bigint "status_updated_by_id"
157
157
  t.datetime "status_updated_at"
158
158
  t.index ["initiator_id"], name: "index_discussions_on_initiator_id"
@@ -174,6 +174,7 @@ feature 'Discussion Flow', organization_workspace: :test do
174
174
  expect(page).to have_text(problem_2.name)
175
175
  expect(page).to have_text('Open')
176
176
  expect(page).to have_text('Messages')
177
+ expect(page).to_not have_text('I\'ll take care')
177
178
  expect(page).not_to have_text('Preview')
178
179
  expect(page).to have_text(problem_2_discussion_message.content)
179
180
  expect(page).not_to have_text(another_problem_2_discussion_message.content)
@@ -188,20 +189,43 @@ feature 'Discussion Flow', organization_workspace: :test do
188
189
  context 'for moderator' do
189
190
  before { set_current_user! moderator }
190
191
 
191
- scenario 'newly created discussion' do
192
- visit current_path
193
- expect(page).to have_text(problem_2.name)
194
- expect(page).to have_text('Open')
195
- expect(page).to have_text('Messages')
196
- expect(page).to have_text('Preview')
197
- expect(page).to have_text(problem_2_discussion_message.content)
198
- expect(page).to have_text(another_problem_2_discussion_message.content)
199
- expect(page).to have_xpath("//div[@class='discussion-actions']")
200
- expect(page).to have_text('Includes inappropriate content')
201
- expect(page).to have_text('Shares the correct solution')
202
- expect(page).to have_text('Discloses personal information')
203
- expect(page).to have_text('included inappropriate content')
204
- expect(page).to have_text ("Deleted by #{moderator.name}")
192
+ context 'on a newly created discussion' do
193
+ scenario do
194
+ visit current_path
195
+ expect(page).to have_text(problem_2.name)
196
+ expect(page).to have_text('Open')
197
+ expect(page).to have_text('Messages')
198
+ expect(page).to have_text('I\'ll take care')
199
+ expect(page).to have_text('Preview')
200
+ expect(page).to have_text(problem_2_discussion_message.content)
201
+ expect(page).to have_text(another_problem_2_discussion_message.content)
202
+ expect(page).to have_xpath("//div[@class='discussion-actions']")
203
+ expect(page).to have_text('Includes inappropriate content')
204
+ expect(page).to have_text('Shares the correct solution')
205
+ expect(page).to have_text('Discloses personal information')
206
+ expect(page).to have_text('included inappropriate content')
207
+ expect(page).to have_text ("Deleted by #{moderator.name}")
208
+ end
209
+ end
210
+
211
+ context 'on a discussion where they are responsible' do
212
+ before { problem_2_discussions.first.toggle_responsible! moderator }
213
+
214
+ scenario do
215
+ visit current_path
216
+ expect(page).to have_text('I won\'t take care')
217
+ end
218
+ end
219
+
220
+ context 'on a discussion where someone else is responsible' do
221
+ let(:another_moderator) { create(:user, permissions: {moderator: '*', student: '*'}) }
222
+ before { problem_2_discussions.first.toggle_responsible! another_moderator }
223
+
224
+ scenario do
225
+ visit current_path
226
+ expect(page).not_to have_text('I\'ll take care')
227
+ expect(page).not_to have_text('I won\'t take care')
228
+ end
205
229
  end
206
230
  end
207
231
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-laboratory
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.4.1
4
+ version: 9.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-08 00:00:00.000000000 Z
11
+ date: 2021-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 9.4.0
33
+ version: 9.7.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 9.4.0
40
+ version: 9.7.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mumukit-bridge
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -553,6 +553,7 @@ files:
553
553
  - app/helpers/editor_helper.rb
554
554
  - app/helpers/editor_tabs_helper.rb
555
555
  - app/helpers/email_helper.rb
556
+ - app/helpers/exam_registration_helper.rb
556
557
  - app/helpers/exercise_input_helper.rb
557
558
  - app/helpers/gamification_helper.rb
558
559
  - app/helpers/globals_helper.rb
@@ -648,6 +649,7 @@ files:
648
649
  - app/views/layouts/_terms_acceptance_disclaimer.html.erb
649
650
  - app/views/layouts/_test_results.html.erb
650
651
  - app/views/layouts/_timer.html.erb
652
+ - app/views/layouts/_toast.html.erb
651
653
  - app/views/layouts/_user_menu.html.erb
652
654
  - app/views/layouts/application.html.erb
653
655
  - app/views/layouts/embedded.html.erb
@@ -960,134 +962,134 @@ signing_key:
960
962
  specification_version: 4
961
963
  summary: Code assement web application for the Mumuki Platform.
962
964
  test_files:
963
- - spec/controllers/users_controller_spec.rb
964
- - spec/controllers/discussions_messages_controller_spec.rb
965
965
  - spec/controllers/exercise_solutions_controller_spec.rb
966
- - spec/controllers/certificates_controller_spec.rb
967
- - spec/controllers/guide_progress_controller_spec.rb
966
+ - spec/controllers/courses_api_controller_spec.rb
968
967
  - spec/controllers/users_api_controller_spec.rb
968
+ - spec/controllers/exam_authorization_requests_controller_spec.rb
969
969
  - spec/controllers/chapters_controller_spec.rb
970
+ - spec/controllers/users_controller_spec.rb
971
+ - spec/controllers/confirmations_controller_spec.rb
970
972
  - spec/controllers/exam_registrations_controller_spec.rb
973
+ - spec/controllers/discussions_messages_controller_spec.rb
974
+ - spec/controllers/organizations_api_controller_spec.rb
975
+ - spec/controllers/discussions_controller_spec.rb
976
+ - spec/controllers/guide_progress_controller_spec.rb
977
+ - spec/controllers/certificates_controller_spec.rb
971
978
  - spec/controllers/messages_controller_spec.rb
972
- - spec/controllers/courses_api_controller_spec.rb
973
- - spec/controllers/invitations_controller_spec.rb
974
- - spec/controllers/exam_authorization_requests_controller_spec.rb
975
- - spec/controllers/confirmations_controller_spec.rb
976
979
  - spec/controllers/api_clients_controller.rb
977
- - spec/controllers/discussions_controller_spec.rb
978
- - spec/controllers/organizations_api_controller_spec.rb
980
+ - spec/controllers/invitations_controller_spec.rb
979
981
  - spec/controllers/students_api_controller_spec.rb
980
- - spec/capybara_helper.rb
981
- - spec/evaluation_helper.rb
982
- - spec/mailers/previews/user_mailer_preview.rb
983
- - spec/mailers/user_mailer_spec.rb
984
- - spec/spec_helper.rb
985
- - spec/api_helper.rb
986
- - spec/features/not_found_public_flow_spec.rb
987
- - spec/features/invitations_flow_spec.rb
988
- - spec/features/immersive_redirection_spec.rb
989
- - spec/features/runner_assets_spec.rb
990
- - spec/features/certificate_programs_flow_spec.rb
991
- - spec/features/chapters_flow_spec.rb
992
- - spec/features/links_flow_spec.rb
993
- - spec/features/login_flow_spec.rb
994
- - spec/features/standard_flow_spec.rb
995
- - spec/features/complements_flow_spec.rb
996
- - spec/features/profile_flow_spec.rb
997
- - spec/features/progressive_tips_spec.rb
998
- - spec/features/exams_flow_spec.rb
999
- - spec/features/guide_reset_spec.rb
1000
- - spec/features/disable_user_flow_spec.rb
1001
- - spec/features/discussion_flow_spec.rb
1002
- - spec/features/home_private_flow_spec.rb
1003
- - spec/features/menu_bar_spec.rb
1004
- - spec/features/exercise_flow_spec.rb
1005
- - spec/features/topic_flow_spec.rb
1006
- - spec/features/disabled_organization_flow_spec.rb
1007
- - spec/features/notifications_flow_spec.rb
1008
- - spec/features/user_activity_flow_spec.rb
1009
- - spec/features/terms_flow_spec.rb
1010
- - spec/features/guides_flow_spec.rb
1011
- - spec/features/lessons_flow_spec.rb
1012
- - spec/features/home_public_flow_spec.rb
1013
- - spec/features/not_found_private_flow_spec.rb
1014
- - spec/features/dynamic_exam_spec.rb
1015
- - spec/javascripts/spec-helper.js
982
+ - spec/javascripts/elipsis-spec.js
983
+ - spec/javascripts/exercise-spec.js
1016
984
  - spec/javascripts/results-renderers-spec.js
1017
- - spec/javascripts/i18n-spec.js
1018
- - spec/javascripts/timeout-spec.js
985
+ - spec/javascripts/speech-bubble-renderer-spec.js
986
+ - spec/javascripts/kids-button-spec.js
987
+ - spec/javascripts/sync-mode-spec.js
1019
988
  - spec/javascripts/global-spec.js
1020
- - spec/javascripts/csrf-token-spec.js
1021
- - spec/javascripts/submissions-store-spec.js
989
+ - spec/javascripts/upload-spec.js
990
+ - spec/javascripts/timer-spec.js
1022
991
  - spec/javascripts/events-spec.js
992
+ - spec/javascripts/i18n-spec.js
993
+ - spec/javascripts/csrf-token-spec.js
994
+ - spec/javascripts/bridge-spec.js
1023
995
  - spec/javascripts/gamification-spec.js
1024
- - spec/javascripts/sync-mode-spec.js
1025
- - spec/javascripts/elipsis-spec.js
1026
- - spec/javascripts/kids-button-spec.js
1027
- - spec/javascripts/upload-spec.js
996
+ - spec/javascripts/timeout-spec.js
1028
997
  - spec/javascripts/editors-spec.js
1029
- - spec/javascripts/bridge-spec.js
1030
- - spec/javascripts/exercise-spec.js
1031
- - spec/javascripts/timer-spec.js
1032
- - spec/javascripts/speech-bubble-renderer-spec.js
1033
- - spec/helpers/breadcrumbs_helper_spec.rb
1034
- - spec/helpers/email_helper_spec.rb
1035
- - spec/helpers/authors_helper_spec.rb
1036
- - spec/helpers/avatar_helper_spec.rb
1037
- - spec/helpers/with_choices_spec.rb
1038
- - spec/helpers/icons_helper_spec.rb
1039
- - spec/helpers/with_navigation_spec.rb
1040
- - spec/helpers/exercise_input_helper_spec.rb
1041
- - spec/helpers/page_title_helper_spec.rb
1042
- - spec/helpers/application_helper_spec.rb
1043
- - spec/helpers/user_activity_helper_spec.rb
1044
- - spec/helpers/certificate_helper_spec.rb
1045
- - spec/helpers/test_results_rendering_spec.rb
1046
- - spec/dummy/db/schema.rb
1047
- - spec/dummy/db/seeds.rb
1048
- - spec/dummy/config.ru
998
+ - spec/javascripts/submissions-store-spec.js
999
+ - spec/javascripts/spec-helper.js
1000
+ - spec/spec_helper.rb
1001
+ - spec/dummy/bin/setup
1002
+ - spec/dummy/bin/rails
1049
1003
  - spec/dummy/bin/yarn
1050
1004
  - spec/dummy/bin/update
1051
- - spec/dummy/bin/rake
1052
- - spec/dummy/bin/setup
1053
1005
  - spec/dummy/bin/bundle
1054
- - spec/dummy/bin/rails
1006
+ - spec/dummy/bin/rake
1007
+ - spec/dummy/config/routes.rb
1008
+ - spec/dummy/config/database.yml
1009
+ - spec/dummy/config/environment.rb
1010
+ - spec/dummy/config/locales/en.yml
1011
+ - spec/dummy/config/application.rb
1012
+ - spec/dummy/config/cable.yml
1055
1013
  - spec/dummy/config/rabbit.yml
1056
1014
  - spec/dummy/config/spring.rb
1015
+ - spec/dummy/config/secrets.yml
1057
1016
  - spec/dummy/config/puma.rb
1058
- - spec/dummy/config/routes.rb
1059
- - spec/dummy/config/boot.rb
1060
- - spec/dummy/config/initializers/assets.rb
1061
1017
  - spec/dummy/config/initializers/wrap_parameters.rb
1062
1018
  - spec/dummy/config/initializers/filter_parameter_logging.rb
1019
+ - spec/dummy/config/initializers/assets.rb
1063
1020
  - spec/dummy/config/initializers/cookies_serializer.rb
1064
- - spec/dummy/config/locales/en.yml
1065
- - spec/dummy/config/secrets.yml
1066
- - spec/dummy/config/cable.yml
1067
- - spec/dummy/config/environment.rb
1068
1021
  - spec/dummy/config/environments/development.rb
1069
1022
  - spec/dummy/config/environments/test.rb
1070
- - spec/dummy/config/database.yml
1071
- - spec/dummy/config/application.rb
1023
+ - spec/dummy/config/boot.rb
1024
+ - spec/dummy/config.ru
1072
1025
  - spec/dummy/package.json
1073
- - spec/dummy/Rakefile
1026
+ - spec/dummy/public/character/animations.json
1074
1027
  - spec/dummy/public/character/kibi/failure.svg
1075
- - spec/dummy/public/character/kibi/jump.svg
1076
- - spec/dummy/public/character/kibi/success_l.svg
1077
- - spec/dummy/public/character/kibi/passed_with_warnings.svg
1078
1028
  - spec/dummy/public/character/kibi/success2_l.svg
1029
+ - spec/dummy/public/character/kibi/passed_with_warnings.svg
1030
+ - spec/dummy/public/character/kibi/success_l.svg
1079
1031
  - spec/dummy/public/character/kibi/context.svg
1080
- - spec/dummy/public/character/magnifying_glass/apparition.svg
1032
+ - spec/dummy/public/character/kibi/jump.svg
1081
1033
  - spec/dummy/public/character/magnifying_glass/loop.svg
1082
- - spec/dummy/public/character/animations.json
1034
+ - spec/dummy/public/character/magnifying_glass/apparition.svg
1083
1035
  - spec/dummy/public/error/timeout_1.svg
1084
- - spec/dummy/public/error/timeout_2.svg
1085
1036
  - spec/dummy/public/error/500.svg
1086
- - spec/dummy/public/error/403.svg
1087
- - spec/dummy/public/error/401.svg
1088
1037
  - spec/dummy/public/error/timeout_3.svg
1089
1038
  - spec/dummy/public/error/404.svg
1039
+ - spec/dummy/public/error/timeout_2.svg
1040
+ - spec/dummy/public/error/401.svg
1090
1041
  - spec/dummy/public/error/410.svg
1042
+ - spec/dummy/public/error/403.svg
1091
1043
  - spec/dummy/public/medal/outline.svg
1044
+ - spec/dummy/db/seeds.rb
1045
+ - spec/dummy/db/schema.rb
1046
+ - spec/dummy/Rakefile
1047
+ - spec/capybara_helper.rb
1048
+ - spec/evaluation_helper.rb
1049
+ - spec/mailers/previews/user_mailer_preview.rb
1050
+ - spec/mailers/user_mailer_spec.rb
1051
+ - spec/api_helper.rb
1092
1052
  - spec/teaspoon_env.rb
1053
+ - spec/helpers/certificate_helper_spec.rb
1054
+ - spec/helpers/email_helper_spec.rb
1055
+ - spec/helpers/exercise_input_helper_spec.rb
1056
+ - spec/helpers/avatar_helper_spec.rb
1057
+ - spec/helpers/user_activity_helper_spec.rb
1058
+ - spec/helpers/with_choices_spec.rb
1059
+ - spec/helpers/application_helper_spec.rb
1060
+ - spec/helpers/with_navigation_spec.rb
1061
+ - spec/helpers/test_results_rendering_spec.rb
1062
+ - spec/helpers/breadcrumbs_helper_spec.rb
1063
+ - spec/helpers/page_title_helper_spec.rb
1064
+ - spec/helpers/authors_helper_spec.rb
1065
+ - spec/helpers/icons_helper_spec.rb
1093
1066
  - spec/login_helper.rb
1067
+ - spec/features/not_found_public_flow_spec.rb
1068
+ - spec/features/login_flow_spec.rb
1069
+ - spec/features/disable_user_flow_spec.rb
1070
+ - spec/features/links_flow_spec.rb
1071
+ - spec/features/home_public_flow_spec.rb
1072
+ - spec/features/immersive_redirection_spec.rb
1073
+ - spec/features/exercise_flow_spec.rb
1074
+ - spec/features/disabled_organization_flow_spec.rb
1075
+ - spec/features/home_private_flow_spec.rb
1076
+ - spec/features/discussion_flow_spec.rb
1077
+ - spec/features/runner_assets_spec.rb
1078
+ - spec/features/progressive_tips_spec.rb
1079
+ - spec/features/exams_flow_spec.rb
1080
+ - spec/features/chapters_flow_spec.rb
1081
+ - spec/features/notifications_flow_spec.rb
1082
+ - spec/features/lessons_flow_spec.rb
1083
+ - spec/features/invitations_flow_spec.rb
1084
+ - spec/features/certificate_programs_flow_spec.rb
1085
+ - spec/features/profile_flow_spec.rb
1086
+ - spec/features/dynamic_exam_spec.rb
1087
+ - spec/features/guide_reset_spec.rb
1088
+ - spec/features/topic_flow_spec.rb
1089
+ - spec/features/guides_flow_spec.rb
1090
+ - spec/features/terms_flow_spec.rb
1091
+ - spec/features/user_activity_flow_spec.rb
1092
+ - spec/features/standard_flow_spec.rb
1093
+ - spec/features/complements_flow_spec.rb
1094
+ - spec/features/not_found_private_flow_spec.rb
1095
+ - spec/features/menu_bar_spec.rb