mumuki-laboratory 8.6.0 → 8.6.1

Sign up to get free protection for your applications and to get access to all the features.
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