mumuki-laboratory 9.3.0 → 9.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) 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/faqs.js +6 -6
  4. data/app/assets/javascripts/mumuki_laboratory/application/toast.js +12 -1
  5. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_discussion.scss +0 -25
  6. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_faqs.scss +4 -3
  7. data/app/controllers/discussions_controller.rb +29 -2
  8. data/app/controllers/exam_authorization_requests_controller.rb +7 -1
  9. data/app/helpers/discussions_helper.rb +26 -2
  10. data/app/views/discussions/_description_message.html.erb +1 -1
  11. data/app/views/discussions/_message.html.erb +1 -1
  12. data/app/views/discussions/_new_message.html.erb +1 -1
  13. data/app/views/discussions/new.html.erb +1 -1
  14. data/app/views/discussions/show.html.erb +6 -0
  15. data/app/views/exam_authorization_requests/_approved.html.erb +1 -1
  16. data/app/views/exam_authorization_requests/_pending.html.erb +2 -2
  17. data/app/views/exam_registrations/show.html.erb +3 -2
  18. data/app/views/exercises/_read_only.html.erb +5 -6
  19. data/app/views/faqs/index.html.erb +1 -1
  20. data/app/views/layouts/_discussions.html.erb +3 -3
  21. data/app/views/layouts/_main.html.erb +4 -10
  22. data/app/views/layouts/_toast.html.erb +7 -0
  23. data/app/views/users/activity.html.erb +8 -6
  24. data/app/views/users/exam_authorizations.html.erb +1 -1
  25. data/config/routes.rb +2 -0
  26. data/lib/mumuki/laboratory/locales/en.yml +13 -5
  27. data/lib/mumuki/laboratory/locales/es-CL.yml +12 -3
  28. data/lib/mumuki/laboratory/locales/es.yml +12 -4
  29. data/lib/mumuki/laboratory/locales/pt.yml +12 -4
  30. data/lib/mumuki/laboratory/version.rb +1 -1
  31. data/lib/tasks/exams.rake +15 -0
  32. data/spec/controllers/discussions_controller_spec.rb +42 -0
  33. data/spec/dummy/db/schema.rb +3 -3
  34. data/spec/features/discussion_flow_spec.rb +38 -14
  35. data/spec/features/user_activity_flow_spec.rb +30 -10
  36. data/spec/helpers/with_navigation_spec.rb +22 -0
  37. metadata +114 -112
@@ -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 %>
@@ -5,7 +5,7 @@
5
5
  <div class="row">
6
6
  <%= render partial: 'layouts/user_menu' %>
7
7
 
8
- <div class="col-md-9">
8
+ <div class="col-md-9 mu-tab-body">
9
9
  <div class="mu-user-header">
10
10
  <h1><%= t(:activity) %></h1>
11
11
  </div>
@@ -17,11 +17,13 @@
17
17
  stats: exercises_activity_stats
18
18
  } %>
19
19
 
20
- <%= render partial: 'activity_indicator',
21
- locals: {
22
- title: t(:forum),
23
- stats: messages_activity_stats
24
- } %>
20
+ <% if Organization.current.forum_enabled? %>
21
+ <%= render partial: 'activity_indicator',
22
+ locals: {
23
+ title: t(:forum),
24
+ stats: messages_activity_stats
25
+ } %>
26
+ <% end %>
25
27
  </div>
26
28
  <div class="col-lg-4 mu-tab-body">
27
29
  <div class="nav nav-pills flex-column">
@@ -22,7 +22,7 @@
22
22
  <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#<%= "exam_authorization_collapse_item_#{index}" %>" aria-expanded="false" aria-controls="<%= "exam_authorization_collapse_item_#{index}" %>">
23
23
  <span class="fa fa-fw fa-<%= it.icon[:class] %> text-<%= it.icon[:type] %>" data-bs-toggle="tooltip" title="<%= t(it.status).humanize %>"></span>
24
24
  <span class="divider-vertical"></span>
25
- <span><strong><%= it.exam_registration.description %></strong> - <small><%= l(it.exam.start_time, format: :long) %></small></span>
25
+ <span><strong><%= it.exam_registration.description %></strong> - <small><%= l(it.exam.start_time.in_time_zone(-3), format: :long) %></small></span>
26
26
  </button>
27
27
  </h2>
28
28
  <div id="<%= "exam_authorization_collapse_item_#{index}" %>" class="accordion-collapse collapse" aria-labelledby="<%= "exam_authorization_accordion_item_#{index}" %>" data-bs-parent="#exam_authorization_accordion">
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
 
@@ -168,7 +168,6 @@ en:
168
168
  kids_default_success: You did it great!
169
169
  language: Language
170
170
  last_name: Last Name
171
- last_seen: "Seen by %{name}"
172
171
  last_submission_date: Last submission
173
172
  latest_exercises: Latest exercises
174
173
  learning: Learning
@@ -186,18 +185,24 @@ en:
186
185
  male: Male
187
186
  manual_evaluation_pending: Thanks for submitting your solution! It will be revised by the course teachers soon
188
187
  medal: Medal
189
- message_count:
190
- one: 1 message
191
- other: '%{count} messages'
192
188
  message: Message
193
189
  message_deleted: This message was deleted because it %{motive}, which violates the %{forum_terms}.
194
190
  messages: Messages
195
191
  messages_error: Previous messages are unavailable. Please try again later.
196
- moderation: Mentoring
197
192
  messages_pluralized:
198
193
  one: Message
199
194
  other: Messages
195
+ moderation: Mentoring
200
196
  moderator: Mentor
197
+ moderator_take_care:
198
+ i_will: I'll take care of it
199
+ i_wont: I won't take care of it
200
+ moderator_is: "%{moderator} is taking care of it"
201
+ status_changed: The discussion status changed. Please refresh the page.
202
+ someone_else_will: Someone else already marked they'll take care of it.
203
+ you_are: You're taking care of it
204
+ you_will_confirmation: You'll take care of this discussion. If you change your mind, click the button again.
205
+ you_wont_confirmation: You won't take care of this discussion.
201
206
  more_messages: More
202
207
  my_account: My account
203
208
  my_doubts: My doubts
@@ -255,6 +260,9 @@ en:
255
260
  progress: Progresss
256
261
  read: Read
257
262
  refresh_or_wait: Please press F5 if results are not displayed after a few seconds
263
+ reply_count:
264
+ one: 1 reply
265
+ other: '%{count} replies'
258
266
  requires_attention: Requires attention
259
267
  reset_query: Clear current search filters
260
268
  responses_count_asc: By less validated replies
@@ -186,9 +186,6 @@ es-CL:
186
186
  male: Hombre
187
187
  manual_evaluation_pending: ¡Gracias por enviar tu solución! Tus docentes la corregirán pronto
188
188
  medal: Medalla
189
- message_count:
190
- one: 1 mensaje
191
- other: '%{count} mensajes'
192
189
  message: Mensaje
193
190
  message_deleted: Este mensaje fue eliminado porque %{motive}, lo cual infringe las %{forum_terms}.
194
191
  messages: Mensajes
@@ -200,6 +197,15 @@ es-CL:
200
197
  minutes: minutos
201
198
  moderation: Mentoría
202
199
  moderator: Mentor
200
+ moderator_take_care:
201
+ i_will: Yo me ocupo
202
+ i_wont: Mejor no me ocupo
203
+ moderator_is: "%{moderator} se está ocupando"
204
+ status_changed: La consulta cambió de estado. Por favor, actualiza la página.
205
+ someone_else_will: Alguien más ya marcó que se va a ocupar.
206
+ you_are: Te estás ocupando
207
+ you_will_confirmation: Te vas a ocupar de esta consulta. Si cambias de parecer, toca nuevamente el botón.
208
+ you_wont_confirmation: No te vas a ocupar de esta consulta.
203
209
  more_messages: Ver mensajes anteriores
204
210
  my_account: Mi cuenta
205
211
  my_doubts: Mis consultas
@@ -262,6 +268,9 @@ es-CL:
262
268
  read: Leído
263
269
  read_messages: Ver mensajes
264
270
  refresh_or_wait: Si no se muestra automáticamente en unos segundos, presiona F5
271
+ reply_count:
272
+ one: 1 respuesta
273
+ other: '%{count} respuestas'
265
274
  reset_query: Borrar los filtros de búsqueda actuales
266
275
  restart: Reiniciar
267
276
  results_hidden: ¡Tu solución fue enviada con éxito!
@@ -179,7 +179,6 @@ es:
179
179
  language: Lenguaje
180
180
  languages: Lenguajes
181
181
  last_name: Apellido
182
- last_seen: "Visto por %{name}"
183
182
  last_submission_date: Última solución
184
183
  latest_exercises: Últimos ejercicios
185
184
  learning: Aprendizaje
@@ -197,9 +196,6 @@ es:
197
196
  male: Hombre
198
197
  manual_evaluation_pending: ¡Gracias por enviar tu solución! Tus docentes la corregirán pronto
199
198
  medal: Medalla
200
- message_count:
201
- one: 1 mensaje
202
- other: '%{count} mensajes'
203
199
  message: Mensaje
204
200
  message_deleted: Este mensaje fue eliminado porque %{motive}, lo cual infringe las %{forum_terms}.
205
201
  messages: Mensajes
@@ -211,6 +207,15 @@ es:
211
207
  minutes: minutos
212
208
  moderation: Mentoría
213
209
  moderator: Mentor
210
+ moderator_take_care:
211
+ i_will: Yo me ocupo
212
+ i_wont: Mejor no me ocupo
213
+ moderator_is: "%{moderator} se está ocupando"
214
+ status_changed: La consulta cambió de estado. Por favor, actualizá la página.
215
+ someone_else_will: Alguien más ya marcó que se va a ocupar.
216
+ you_are: Te estás ocupando
217
+ you_will_confirmation: Te vas a ocupar de esta consulta. Si cambiás de parecer, tocá nuevamente el botón.
218
+ you_wont_confirmation: No te vas a ocupar de esta consulta.
214
219
  more_messages: Ver mensajes anteriores
215
220
  my_account: Mi cuenta
216
221
  my_doubts: Mis consultas
@@ -274,6 +279,9 @@ es:
274
279
  read: Leido
275
280
  read_messages: Ver mensajes
276
281
  refresh_or_wait: Si no se muestra automáticamente en unos segundos, presioná F5
282
+ reply_count:
283
+ one: 1 respuesta
284
+ other: '%{count} respuestas'
277
285
  requires_attention: Requiere atención
278
286
  reset_query: Borrar los filtros de búsqueda actuales
279
287
  responses_count_asc: Con menos respuestas validadas
@@ -172,7 +172,6 @@ pt:
172
172
  language: Linguagem
173
173
  languages: Linguagens
174
174
  last_name: Sobrenome
175
- last_seen: "Visto por %{name}"
176
175
  last_submission_date: Última solução
177
176
  latest_exercises: Últimos exercícios
178
177
  learning: Aprendendo
@@ -190,9 +189,6 @@ pt:
190
189
  male: Masculino
191
190
  manual_evaluation_pending: Obrigado por enviar sua solução! Seus professores irão corrigi-lo em breve
192
191
  medal: Medalha
193
- message_count:
194
- one: 1 mensagem
195
- other: '%{count} mensagens'
196
192
  message: Mensagem
197
193
  message_deleted: Esta mensagem foi excluída porque %{motive}, o que viola as %{forum_terms}.
198
194
  messages: Mensagens
@@ -205,6 +201,15 @@ pt:
205
201
  minutes: minutos
206
202
  moderation: Mentoria
207
203
  moderator: Mentor
204
+ moderator_take_care:
205
+ i_will: Eu cuidarei disso
206
+ i_wont: Eu não vou cuidar
207
+ moderator_is: "%{moderator} está cuidando"
208
+ status_changed: A consulta mudou de estado. Por favor, atualize para ver a consulta atualizada.
209
+ someone_else_will: Alguém já marcou que vai cuidar disso.
210
+ you_are: Você está cuidando
211
+ you_will_confirmation: Você vai cuidar dessa consulta. Se mudar de ideia, clique no botão novamente.
212
+ you_wont_confirmation: Você não vai cuidar dessa consulta.
208
213
  more_messages: Ver as mensagens anteriores
209
214
  my_account: Minha conta
210
215
  my_doubts: Minhas duvidas
@@ -265,6 +270,9 @@ pt:
265
270
  read: Ler
266
271
  read_messages: Ver mensagens
267
272
  refresh_or_wait: Se não mostrar automaticamente em alguns segundos, pressione F5
273
+ reply_count:
274
+ one: 1 resposta
275
+ other: '%{count} respostas'
268
276
  requires_attention: Requer atenção
269
277
  reset_query: Limpar filtros de pesquisa atuais
270
278
  restart: Reiniciar
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Laboratory
3
- VERSION = '9.3.0'
3
+ VERSION = '9.5.1'
4
4
  end
5
5
  end
@@ -0,0 +1,15 @@
1
+ logger = ::Logger.new(STDOUT)
2
+
3
+ namespace :laboratory do
4
+ namespace :exams do
5
+ task authorize_requests: :environment do
6
+ logger.info "Exam Authorization Requests task"
7
+ ExamRegistration.should_process.find_each do |exam_registration|
8
+ logger.info "Processing exam registration '#{exam_registration.description}'"
9
+ exam_registration.process_requests!
10
+ rescue
11
+ logger.error "Something wrong happened while processing '#{exam_registration.description}'"
12
+ end
13
+ end
14
+ end
15
+ 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,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
@@ -2,6 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  feature 'User Activity Flow', organization_workspace: :test do
4
4
  let(:user) { create(:user) }
5
+ let(:organization) { Organization.locate!('test') }
6
+
5
7
  before { set_current_user!(user) }
6
8
 
7
9
  let(:fake_stats) { double('stats') }
@@ -30,21 +32,39 @@ feature 'User Activity Flow', organization_workspace: :test do
30
32
  expect(page).to have_text('solved')
31
33
  end
32
34
 
33
- scenario 'displays messages count' do
34
- expect(page).to have_text('12')
35
- expect(page).to have_text('messages')
36
- end
37
-
38
- scenario 'displays validated messages count' do
39
- expect(page).to have_text('6')
40
- expect(page).to have_text('validated')
41
- end
42
-
43
35
  scenario 'displays recent weeks' do
44
36
  expect(page).to have_text 'Week of 2020-10-12'
45
37
  expect(page).to have_text 'Week of 2020-10-05'
46
38
  expect(page).to have_text 'Week of 2020-09-28'
47
39
  end
40
+
41
+ context 'on organization with no forum' do
42
+ scenario 'does not display messages count' do
43
+ expect(page).to_not have_text('messages')
44
+ end
45
+
46
+ scenario 'does not display validated messages count' do
47
+ expect(page).to_not have_text('validated')
48
+ end
49
+ end
50
+
51
+ context 'on organization with forum' do
52
+ before do
53
+ organization.update! forum_enabled: true
54
+ visit activity_user_path
55
+ end
56
+
57
+ scenario 'displays messages count' do
58
+ expect(page).to have_text('12')
59
+ expect(page).to have_text('messages')
60
+ end
61
+
62
+ scenario 'displays validated messages count' do
63
+ expect(page).to have_text('6')
64
+ expect(page).to have_text('validated')
65
+ end
66
+ end
67
+
48
68
  end
49
69
 
50
70
  context 'selecting a specific week' do