mumuki-laboratory 8.6.0 → 8.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92a4fb878a7767d1fe4b760252213ae327d8e5ae82bab805065eddb85b3baa36
4
- data.tar.gz: e45d454449b183f1f4c200152a25f2df58ef385c1c07949e3fda7be94e6de57c
3
+ metadata.gz: 824e346e9d3113f3b3d48c8ed7e23c846e26a54fb5ed7e4c4bb5a9307323b4d7
4
+ data.tar.gz: e28b9bdf65007abda370a36b760adeaf7989ab9e4c94c52ebaa09bcd3f14fb79
5
5
  SHA512:
6
- metadata.gz: 9113399868c37c29fc38521c88b1f4acd2477b6094469c97be54983eb46753245e79ea7d4a56cb641ade8746b05323ecdeef276321aeb70e19ceca123d232566
7
- data.tar.gz: 1f101adea0a26968fe86fc9f7d5084e4cd821ab9b17ca528762bb55573a0be5eeb98e2eba0e5affa83da30168f046c6ea1b7e7cd6654beed0eeb599ea0aaaa73
6
+ metadata.gz: 46a32c31bb80eca3fa50fc45c37875a36894cf3fbc2192f339c138763afeac44a811ab336650460a7e7f150323601d92cab90c91e967668916462d21026eb72a
7
+ data.tar.gz: c9ecc5bd9523a72129d3914317fa29c596038b99f3733de72fc71c27b5c1be3295d9f79ddff39d3cf39c8cfb22bd873581442c4c9121680cdd68901990a11b54
@@ -1,17 +1,72 @@
1
+ mumuki.upload = (() => {
2
+ class FileUploader {
3
+ constructor(file) {
4
+ this.file = file;
5
+ }
6
+
7
+ uploadFileIfValid() {
8
+ if (!this.file) return;
9
+
10
+ let maxFileSize = $('#mu-upload-input').attr("mu-upload-file-limit");
11
+ if (this.file.size > maxFileSize) {
12
+ return mumuki.upload.ui.showFileExceedsMaxSize();
13
+ }
14
+
15
+ mumuki.upload.ui.allowSubmissionFor(this.file.name);
16
+
17
+ const reader = new FileReader();
18
+ reader.onload = function (e) {
19
+ const contents = e.target.result;
20
+ $('#solution_content').html(contents);
21
+ };
22
+ reader.readAsText(this.file);
23
+
24
+ return reader;
25
+ }
26
+ }
27
+
28
+ class UI {
29
+ constructor() {
30
+ this.$uploadFileLimitExceeded = $('#mu-upload-file-limit-exceeded');
31
+ this.$uploadLabel = $('#mu-upload-label span');
32
+ this.$uploadLabelText = this.$uploadLabel.text();
33
+ this.$uploadIcon = $('#mu-upload-icon');
34
+ this.$btnSubmit = $('.btn-submit');
35
+ }
36
+
37
+ showFileExceedsMaxSize() {
38
+ this.$uploadFileLimitExceeded.removeClass('hidden');
39
+ this.$uploadLabel.text(this.$uploadLabelText);
40
+ this.$uploadIcon.addClass('fa-upload').removeClass('fa-file-alt');
41
+ this.$btnSubmit.addClass('disabled');
42
+ }
43
+
44
+ allowSubmissionFor(filename) {
45
+ this.$uploadFileLimitExceeded.addClass('hidden');
46
+ this.$uploadLabel.text(filename);
47
+ this.$uploadIcon.removeClass('fa-upload').addClass('fa-file-alt');
48
+ this.$btnSubmit.removeClass('disabled');
49
+ }
50
+ }
51
+
52
+ function _setUI() {
53
+ mumuki.upload.ui = new UI();
54
+ }
55
+
56
+ return {
57
+ FileUploader,
58
+ UI,
59
+
60
+ _setUI,
61
+
62
+ /** @type {UI} */
63
+ ui: null
64
+ };
65
+ })();
66
+
1
67
  mumuki.load(() => {
2
- $('#upload-input').change(function (evt) {
3
- var file = evt.target.files[0];
4
- if (!file) return;
5
-
6
- var reader = new FileReader();
7
- reader.onload = function (e) {
8
- var contents = e.target.result;
9
- $('#solution_content').html(contents);
10
- $(evt.target).val("");
11
- $('form.new_solution').submit();
12
- };
13
- reader.readAsText(file);
14
- return false;
68
+ $('#mu-upload-input').change(function (evt) {
69
+ if (!mumuki.upload.ui) mumuki.upload._setUI();
70
+ return new mumuki.upload.FileUploader(evt.target.files[0]).uploadFileIfValid();
15
71
  });
16
72
  });
17
-
@@ -1,3 +1,3 @@
1
- .chapter-description p {
1
+ .chapter-description {
2
2
  display: inline-block;
3
3
  }
@@ -53,12 +53,11 @@ module ExerciseInputHelper
53
53
  waiting_text = t(options.waiting_t) if options.waiting_t.present?
54
54
  %Q{
55
55
  <div class="btn-submit-container">
56
- <#{options.tag} for="#{options.for}"
57
- class="btn btn-success btn-block btn-submit #{options.classes}"
56
+ <button class="btn btn-success btn-block btn-submit #{options.classes}"
58
57
  data-waiting="#{waiting_text}">
59
- #{fa_icon options.fa_icon}
58
+ #{fa_icon 'play'}
60
59
  #{text} #{remaining_attempts_text(assignment)}
61
- </#{options.tag}>
60
+ </button>
62
61
  </div>
63
62
  }.html_safe
64
63
  end
@@ -92,26 +91,18 @@ module ExerciseInputHelper
92
91
 
93
92
  def submit_button_options(exercise)
94
93
  if exercise.upload?
95
- struct for: 'upload-input',
96
- tag: :label,
94
+ struct classes: 'disabled',
97
95
  waiting_t: :uploading_solution,
98
- fa_icon: :upload,
99
- t: :upload_solution
96
+ t: :create_submission
100
97
  elsif exercise.hidden?
101
- struct tag: :button,
102
- classes: 'submission_control',
98
+ struct classes: 'submission_control',
103
99
  waiting_t: :working,
104
- fa_icon: :play,
105
100
  t: :continue_exercise
106
101
  elsif exercise.input_kids?
107
- struct tag: :button,
108
- classes: 'submission_control',
109
- fa_icon: :play
102
+ struct classes: 'submission_control'
110
103
  else
111
- struct tag: :button,
112
- classes: 'submission_control',
104
+ struct classes: 'submission_control',
113
105
  waiting_t: :sending_solution,
114
- fa_icon: :play,
115
106
  t: :create_submission
116
107
  end
117
108
  end
@@ -1,4 +1,13 @@
1
1
  <div class="form-group">
2
- <textarea id="solution_content" type="text" name="solution[content]" style="display: none"></textarea>
3
- <input id="upload-input" type="file" class="upload submission-control" size="5120" accept=".<%= @exercise.language.extension %>" />
2
+ <% @max_file_size = 256000 %>
3
+
4
+ <textarea id="solution_content" type="text" name="solution[content]" class="hidden"></textarea>
5
+ <input id="mu-upload-input" type="file" class="upload submission-control hidden" mu-upload-file-limit=<%= @max_file_size %> accept=".<%= @exercise.language.extension %>" />
6
+ <div>
7
+ <label id="mu-upload-label" for="mu-upload-input" class="btn btn-success">
8
+ <%= fa_icon(:upload, text: t(:select_file), id: "mu-upload-icon") %>
9
+ </label>
10
+ <div id="mu-upload-file-limit-exceeded" class="hidden">
11
+ <%= fa_icon("exclamation-triangle", text: t(:file_exceeds_max_size, size_kb: (@max_file_size / 1000))) %></div>
12
+ </div>
4
13
  </div>
@@ -1,5 +1,5 @@
1
1
  <%= content_for :breadcrumbs do %>
2
- <% if current_user? %>
2
+ <% if current_logged_user? %>
3
3
  <%= breadcrumbs @user %>
4
4
  <% else %>
5
5
  <%= header_breadcrumbs %>
@@ -111,6 +111,7 @@ en:
111
111
  failed: Oops, something went wrong
112
112
  feedback: Feedback
113
113
  female: Female
114
+ file_exceeds_max_size: "File size should not exceed %{size_kb}kb. Please select another file."
114
115
  finish: Finish
115
116
  first_name: First Name
116
117
  forbidden_explanation: Please verify you have logged in with the right account
@@ -233,6 +234,7 @@ en:
233
234
  running: running
234
235
  save: Save
235
236
  see_context: Watch exercise introduction animation
237
+ select_file: Select file
236
238
  sending_solution: Sending solution
237
239
  show: Show
238
240
  sign_in: Sign in
@@ -289,13 +291,12 @@ en:
289
291
  unprepared_organization_explanation: This path hasn't started yet.
290
292
  unsubscribe: Unsubscribe
291
293
  unsubscribed_successfully: You have successfully unsubscribed from reminders.
292
- upload_solution: Upload Solution
293
294
  uploading_solution: "Uploading solution"
294
295
  upvote: Upvote
295
296
  upvotes_count_desc: Most voted
296
297
  upvotes_count_asc: Least voted
297
298
  user: User
298
- user_data_updated: Your data was updated successfuly
299
+ user_data_updated: Your data was updated successfully
299
300
  username: Username
300
301
  view_details: View details
301
302
  want_permissions: The next user requires permissions
@@ -109,6 +109,7 @@ es-CL:
109
109
  failed: Tu solución no pasó las pruebas
110
110
  feedback: Problemas que encontramos
111
111
  female: Mujer
112
+ file_exceeds_max_size: "El tamaño de archivo no debe exceder %{size_kb}kb. Por favor selecciona otro archivo."
112
113
  finish: Terminar
113
114
  first_name: Nombre
114
115
  forbidden_explanation: ¿Puede que hayas ingresado con una cuenta incorrecta?
@@ -167,7 +168,7 @@ es-CL:
167
168
  messages_error: Los mensajes anteriores no están disponibles en este momento. ¡Vuelve a intentar más tarde!
168
169
  minute: minuto
169
170
  minutes: minutos
170
- moderation: Moderación
171
+ moderation: Mentoría
171
172
  moderator: Mentor
172
173
  more_messages: Ver mensajes anteriores
173
174
  my_doubts: Mis consultas
@@ -236,6 +237,7 @@ es-CL:
236
237
  running: procesando
237
238
  save: Guardar
238
239
  see_context: Mira la animación del principio
240
+ select_file: Seleccionar archivo
239
241
  send: Enviar
240
242
  sending_solution: Enviando solución
241
243
  show: Mostrar
@@ -297,7 +299,6 @@ es-CL:
297
299
  unprepared_organization_explanation: ¡Este recorrido aún no ha comenzado!
298
300
  unsubscribe: Dejar de recibir notificaciones
299
301
  unsubscribed_successfully: Te desuscribiste exitosamente de los recordatorios.
300
- upload_solution: "Subir solución"
301
302
  uploading_solution: "Subiendo solución"
302
303
  upvote: Es útil
303
304
  upvotes_count_desc: Más útiles
@@ -117,6 +117,7 @@ es:
117
117
  failed: Tu solución no pasó las pruebas
118
118
  feedback: Problemas que encontramos
119
119
  female: Mujer
120
+ file_exceeds_max_size: "El tamaño de archivo no debe exceder %{size_kb}kb. Por favor seleccioná otro archivo."
120
121
  finish: Terminar
121
122
  first_name: Nombre
122
123
  forbidden_explanation: ¿Puede que hayas ingresado con una cuenta incorrecta?
@@ -251,6 +252,7 @@ es:
251
252
  running: procesando
252
253
  save: Guardar
253
254
  see_context: Mirá la animación del principio
255
+ select_file: Seleccionar archivo
254
256
  send: Enviar
255
257
  sending_solution: Enviando solución
256
258
  show: Mostrar
@@ -313,7 +315,6 @@ es:
313
315
  unprepared_organization_explanation: Este recorrido aún no ha comenzado
314
316
  unsubscribe: Dejar de recibir notificaciones
315
317
  unsubscribed_successfully: Te desuscribiste exitosamente de los recordatorios.
316
- upload_solution: "Subir solución"
317
318
  uploading_solution: "Subiendo solución"
318
319
  upvote: Es útil
319
320
  upvotes_count_desc: Más útiles
@@ -113,6 +113,7 @@ pt:
113
113
  failed: Sua solução não passou as provas
114
114
  feedback: Problemas que encontramos
115
115
  female: Feminino
116
+ file_exceeds_max_size: "O tamanho do arquivo não deve exceder %{size_kb}kb. Selecione outro arquivo."
116
117
  finish: Terminar
117
118
  first_name: Nome
118
119
  forbidden_explanation: Você poderia ter entrado com uma conta incorreta?
@@ -240,6 +241,7 @@ pt:
240
241
  running: processamento
241
242
  save: Salvar
242
243
  see_context: Veja a animação desde o início
244
+ select_file: Selecione o arquivo
243
245
  send: Enviar
244
246
  sending_solution: Solução de envio
245
247
  show: Mostrar
@@ -296,7 +298,6 @@ pt:
296
298
  unmeet_expectations: Objetivos que não foram atendidos
297
299
  unprepared_organization_explanation: Este curso ainda não começou
298
300
  unsubscribe: Cancelar subscrição
299
- upload_solution: Carregar solução
300
301
  uploading_solution: Uploading solution
301
302
  user: Usuário
302
303
  user_data_updated: Os seus dados foram atualizados corretamente
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Laboratory
3
- VERSION = '8.6.0'
3
+ VERSION = '8.6.1'
4
4
  end
5
5
  end
@@ -95,9 +95,8 @@ feature 'Profile Flow', organization_workspace: :test do
95
95
  visit "/user/edit"
96
96
  fill_in('user_first_name', with: 'first_name')
97
97
 
98
- # Match :first is used because there are two buttons: mobile and desktop.
99
98
  click_on(button_options)
100
- expect(page).to have_text('Your data was updated successfuly')
99
+ expect(page).to have_text('Your data was updated successfully')
101
100
  expect(page).to have_text('Profile')
102
101
  end
103
102
  end
@@ -153,5 +153,35 @@ feature 'Terms Flow', organization_workspace: :test do
153
153
  end
154
154
  end
155
155
 
156
+ context 'with incognito mode' do
157
+ before { test_organization.update! incognito_mode_enabled: true }
158
+
159
+ describe 'visit user terms path' do
160
+ let(:terms_path) { '/user/terms' }
161
+ let(:expected_terms) { general_terms_scopes }
162
+
163
+ it_behaves_like 'has expected terms'
164
+ end
165
+
166
+ scenario 'visit any other path' do
167
+ visit '/'
168
+
169
+ expect(page).to have_text('Start Practicing')
170
+ end
171
+
172
+ context 'visit forum' do
173
+ let(:terms_path) { '/discussions/terms' }
174
+
175
+ context 'with enabled forum' do
176
+ before { test_organization.update! forum_enabled: true }
177
+
178
+ scenario 'visit forum' do
179
+ visit '/discussions/terms'
180
+ expect(page).to have_text('You may have mistyped the address or the page may have moved')
181
+ end
182
+ end
183
+ end
184
+ end
185
+
156
186
  end
157
187
 
@@ -0,0 +1,80 @@
1
+ describe('upload', () => {
2
+ const fileSizeLimit = 20;
3
+
4
+ fixture.set(`
5
+ <textarea id="solution_content" type="text" name="solution[content]" class="hidden"></textarea>
6
+ <input id="mu-upload-input" type="file" class="upload submission-control hidden" mu-upload-file-limit=${fileSizeLimit} accept=".txt" />
7
+ <label id="mu-upload-label" for="mu-upload-input" class="btn btn-success"></label>
8
+ <button class="btn btn-success btn-block btn-submit disabled"></button>
9
+ <div id="mu-upload-file-limit-exceeded" class="hidden"></div>
10
+ `);
11
+
12
+ beforeEach(() => {
13
+ mumuki.upload._setUI();
14
+ });
15
+
16
+ function reader(file, done) {
17
+ let fileReader = new mumuki.upload.FileUploader(file).uploadFileIfValid();
18
+ if (fileReader) {
19
+ fileReader.addEventListener('load', () => done());
20
+ fileReader.addEventListener('error', done);
21
+ return fileReader;
22
+ } else {
23
+ done();
24
+ }
25
+ }
26
+
27
+ describe('no file is uploaded', () => {
28
+ beforeEach((done) => {
29
+ reader(null, done);
30
+ });
31
+
32
+ it('loads no solution', function () {
33
+ expect($('#solution_content').html()).toEqual('');
34
+ });
35
+
36
+ it('does not allow submitting', function () {
37
+ expect($('.btn-submit').hasClass('disabled')).toBe(true);
38
+ });
39
+
40
+ it('does not exceed max file size', function () {
41
+ expect($('#mu-upload-file-limit-exceeded').hasClass('hidden')).toBe(true);
42
+ });
43
+ });
44
+
45
+ describe('small file is uploaded', () => {
46
+ beforeEach((done) => {
47
+ reader(new File(["short solution"], "short.txt"), done);
48
+ });
49
+
50
+ it('loads solution', function () {
51
+ expect($('#solution_content').html()).toEqual('short solution');
52
+ });
53
+
54
+ it('allows submitting', function () {
55
+ expect($('.btn-submit').hasClass('disabled')).toBe(false);
56
+ });
57
+
58
+ it('does not exceed max file size', function () {
59
+ expect($('#mu-upload-file-limit-exceeded').hasClass('hidden')).toBe(true);
60
+ });
61
+ });
62
+
63
+ describe('large file is uploaded', () => {
64
+ beforeEach((done) => {
65
+ reader(new File(["solution that is too long to be allowed"], "long.txt"), done);
66
+ });
67
+
68
+ it('loads no solution', function () {
69
+ expect($('#solution_content').html()).toEqual('');
70
+ });
71
+
72
+ it('does not allow submitting', function () {
73
+ expect($('.btn-submit').hasClass('disabled')).toBe(true);
74
+ });
75
+
76
+ it('exceeds max file size', function () {
77
+ expect($('#mu-upload-file-limit-exceeded').hasClass('hidden')).toBe(false);
78
+ });
79
+ });
80
+ });
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: 8.6.0
4
+ version: 8.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-12 00:00:00.000000000 Z
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -810,6 +810,7 @@ files:
810
810
  - spec/javascripts/sync-mode-spec.js
811
811
  - spec/javascripts/timeout-spec.js
812
812
  - spec/javascripts/timer-spec.js
813
+ - spec/javascripts/upload-spec.js
813
814
  - spec/login_helper.rb
814
815
  - spec/mailers/previews/user_mailer_preview.rb
815
816
  - spec/mailers/user_mailer_spec.rb
@@ -859,7 +860,7 @@ homepage: https://mumuki.io
859
860
  licenses:
860
861
  - AGPL-3.0
861
862
  metadata: {}
862
- post_install_message:
863
+ post_install_message:
863
864
  rdoc_options: []
864
865
  require_paths:
865
866
  - lib
@@ -874,9 +875,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
874
875
  - !ruby/object:Gem::Version
875
876
  version: '0'
876
877
  requirements: []
877
- rubyforge_project:
878
+ rubyforge_project:
878
879
  rubygems_version: 2.7.6
879
- signing_key:
880
+ signing_key:
880
881
  specification_version: 4
881
882
  summary: Code assement web application for the Mumuki Platform.
882
883
  test_files:
@@ -987,6 +988,7 @@ test_files:
987
988
  - spec/javascripts/editors-spec.js
988
989
  - spec/javascripts/exercise-spec.js
989
990
  - spec/javascripts/elipsis-spec.js
991
+ - spec/javascripts/upload-spec.js
990
992
  - spec/javascripts/spec-helper.js
991
993
  - spec/javascripts/submissions-store-spec.js
992
994
  - spec/javascripts/gamification-spec.js