mumuki-laboratory 8.3.0 → 9.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +1 -1
  3. data/app/assets/javascripts/mumuki_laboratory/application/upload.js +69 -14
  4. data/app/assets/stylesheets/mumuki_laboratory/application.scss +1 -0
  5. data/app/assets/stylesheets/mumuki_laboratory/application/_codemirror-themes.scss +1 -0
  6. data/app/assets/stylesheets/mumuki_laboratory/application/_layout.scss +3 -0
  7. data/app/assets/stylesheets/mumuki_laboratory/application/_modules.scss +1 -0
  8. data/app/assets/stylesheets/mumuki_laboratory/application/codemirror-themes/_mu-light.scss +3 -0
  9. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_content_show.scss +15 -2
  10. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_discussion.scss +31 -8
  11. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_medal.scss +1 -1
  12. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_user_menu.scss +35 -0
  13. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_user_profile.scss +11 -0
  14. data/app/controllers/api/base_controller.rb +0 -1
  15. data/app/controllers/api/courses_controller.rb +1 -1
  16. data/app/controllers/api/organizations_controller.rb +5 -2
  17. data/app/controllers/api/roles_controller.rb +4 -0
  18. data/app/controllers/api/users_controller.rb +6 -1
  19. data/app/controllers/application_controller.rb +1 -1
  20. data/app/controllers/concerns/with_authorization.rb +1 -16
  21. data/app/controllers/concerns/with_user_params.rb +4 -0
  22. data/app/controllers/discussions_messages_controller.rb +0 -1
  23. data/app/controllers/exam_authorization_requests_controller.rb +26 -0
  24. data/app/controllers/exam_registrations_controller.rb +6 -0
  25. data/app/controllers/users_controller.rb +8 -5
  26. data/app/helpers/application_helper.rb +4 -0
  27. data/app/helpers/breadcrumbs_helper.rb +4 -0
  28. data/app/helpers/content_view_helper.rb +19 -0
  29. data/app/helpers/exercise_input_helper.rb +8 -17
  30. data/app/helpers/icons_helper.rb +3 -11
  31. data/app/helpers/links_helper.rb +2 -2
  32. data/app/helpers/menu_bar_helper.rb +3 -3
  33. data/app/helpers/overlapped_buttons_helper.rb +10 -6
  34. data/app/helpers/progress_bar_helper.rb +2 -2
  35. data/app/helpers/user_menu_helper.rb +18 -0
  36. data/app/views/chapters/show.html.erb +17 -16
  37. data/app/views/complements/show.html.erb +1 -1
  38. data/app/views/discussions/_message.html.erb +7 -7
  39. data/app/views/exam_authorization_requests/show.html.erb +17 -0
  40. data/app/views/exam_registrations/show.html.erb +37 -0
  41. data/app/views/exams/show.html.erb +1 -1
  42. data/app/views/{layouts → exercises}/_exercise_skipped.html.erb +0 -0
  43. data/app/views/exercises/_exercise_title_icons.html.erb +4 -0
  44. data/app/views/exercises/show.html.erb +5 -8
  45. data/app/views/{layouts → guides}/_guide.html.erb +3 -3
  46. data/app/views/guides/_guide_container.html.erb +24 -0
  47. data/app/views/{layouts → guides}/_guide_title_icons.html.erb +1 -3
  48. data/app/views/layouts/_progress_bar.html.erb +9 -7
  49. data/app/views/layouts/_progress_listing.html.erb +5 -5
  50. data/app/views/layouts/_user_menu.html.erb +21 -0
  51. data/app/views/layouts/application.html.erb +1 -6
  52. data/app/views/layouts/exercise_inputs/editors/_upload.html.erb +11 -2
  53. data/app/views/lessons/show.html.erb +1 -1
  54. data/app/views/notifications/_discussion.html.erb +1 -0
  55. data/app/views/notifications/_dropdown.html.erb +13 -0
  56. data/app/views/notifications/_exam_authorization_request.html.erb +1 -0
  57. data/app/views/notifications/_exam_registration.html.erb +1 -0
  58. data/app/views/notifications/_message.html.erb +1 -0
  59. data/app/views/users/_user_form.html.erb +10 -8
  60. data/app/views/users/discussions.html.erb +28 -0
  61. data/app/views/users/edit.html.erb +1 -1
  62. data/app/views/users/messages.html.erb +27 -0
  63. data/app/views/users/show.html.erb +4 -51
  64. data/app/views/users/terms.html.erb +2 -2
  65. data/config/routes.rb +6 -0
  66. data/lib/mumuki/laboratory/controllers/notifications.rb +3 -22
  67. data/lib/mumuki/laboratory/locales/en.yml +35 -18
  68. data/lib/mumuki/laboratory/locales/es-CL.yml +26 -9
  69. data/lib/mumuki/laboratory/locales/es.yml +31 -15
  70. data/lib/mumuki/laboratory/locales/pt.yml +28 -11
  71. data/lib/mumuki/laboratory/version.rb +1 -1
  72. data/spec/controllers/exam_authorization_requests_controller_spec.rb +40 -0
  73. data/spec/controllers/exam_registrations_controller_spec.rb +19 -0
  74. data/spec/controllers/organizations_api_controller_spec.rb +16 -9
  75. data/spec/dummy/db/schema.rb +24 -0
  76. data/spec/features/exercise_flow_spec.rb +3 -3
  77. data/spec/features/login_flow_spec.rb +1 -1
  78. data/spec/features/menu_bar_spec.rb +24 -24
  79. data/spec/features/notifications_flow_spec.rb +46 -0
  80. data/spec/features/profile_flow_spec.rb +6 -9
  81. data/spec/features/terms_flow_spec.rb +30 -0
  82. data/spec/javascripts/bridge-spec.js +2 -2
  83. data/spec/javascripts/csrf-token-spec.js +2 -2
  84. data/spec/javascripts/editors-spec.js +7 -9
  85. data/spec/javascripts/elipsis-spec.js +4 -4
  86. data/spec/javascripts/events-spec.js +7 -7
  87. data/spec/javascripts/exercise-spec.js +7 -8
  88. data/spec/javascripts/global-spec.js +3 -3
  89. data/spec/javascripts/i18n-spec.js +23 -20
  90. data/spec/javascripts/kids-button-spec.js +6 -8
  91. data/spec/javascripts/results-renderers-spec.js +5 -5
  92. data/spec/javascripts/speech-bubble-renderer-spec.js +2 -3
  93. data/spec/javascripts/submissions-store-spec.js +14 -14
  94. data/spec/javascripts/sync-mode-spec.js +3 -3
  95. data/spec/javascripts/timeout-spec.js +2 -2
  96. data/spec/javascripts/timer-spec.js +2 -2
  97. data/spec/javascripts/upload-spec.js +80 -0
  98. metadata +129 -103
  99. data/app/views/layouts/_guide_container.html.erb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 222bd258be2916956f315e5195ed53f60ff730f176852e7d52ae17194e789f06
4
- data.tar.gz: d3e1701ba286cdfa8d7b44ad529c85df6b9b6fdbe3912fa77dfafab35f9a4545
3
+ metadata.gz: 96b344d472912c433732e101f0754c229aa8c406e47a2ff54503a9625bb78f5a
4
+ data.tar.gz: b73fba56c2c87069b1e402ce010eaa17d296220c92df9cc241d92e9aa92eb909
5
5
  SHA512:
6
- metadata.gz: fb75e14d8e9da062677b7cfb5595ece2717f9b226f085c3432379c87a63acf80e905fda9d890a85bc3afd970d623029d729c86ffff35781fe5b6f1fc938ff92e
7
- data.tar.gz: 531e671791fec8e27fb3694a7315eb444d1e3d790ba3186789616562b2b7d6ad609bb7bc1221c94a741c207f2a573aeae9427a1e68aa3d4e3d272ae6f3ce3480
6
+ metadata.gz: b2557a3374e33d3a273b4df24cdd5eb3e46d0e997af5a862c6b6a6cd792a63c4a78e6c248927efeaf964d275139923cea0292a204b92448a965614c2b1f0f82f
7
+ data.tar.gz: 2667001640a346bd3517445621adb899599b52a44d7c40625a6ae67e7a46e7c5c2d935501358b5a28e5ebeb6aa7a0da58cc4af0cf74fb2a7706d738577d47837
@@ -62,7 +62,7 @@ mumuki.page.editors = [];
62
62
 
63
63
  function setEditorLanguage(editor, language) {
64
64
  editor.setOption("mode", language);
65
- editor.setOption('theme', 'default ' + language);
65
+ editor.setOption('theme', 'mu-light ' + language);
66
66
  }
67
67
 
68
68
  function syncContent(){
@@ -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
-
@@ -15,3 +15,4 @@ $da-font-path: asset-path('assets');
15
15
  @import "application/modules";
16
16
  @import "application/errors";
17
17
  @import "application/alerts";
18
+ @import "application/codemirror-themes";
@@ -0,0 +1 @@
1
+ @import "codemirror-themes/mu-light";
@@ -122,6 +122,9 @@ hr {
122
122
 
123
123
  /* TODO: move to mumuki-styles */
124
124
  .mu-inline-block-left {
125
+ display: flex;
126
+ align-items: center;
127
+
125
128
  margin-left: 15px;
126
129
  }
127
130
 
@@ -27,4 +27,5 @@
27
27
  @import "modules/terms";
28
28
  @import "modules/timer";
29
29
  @import "modules/upload";
30
+ @import "modules/user_menu";
30
31
  @import "modules/user_profile";
@@ -0,0 +1,3 @@
1
+ .cm-s-mu-light .CodeMirror-code {
2
+ padding-right: 25px;
3
+ }
@@ -1,3 +1,16 @@
1
- .chapter-description p {
2
- display: inline-block;
1
+ .mu-chapter-description p {
2
+ display: inline-block
3
+ }
4
+
5
+ .mu-content-title-icons {
6
+ display: flex;
7
+ align-items: center;
8
+
9
+ font-size: 150%;
10
+ margin-left: 15px;
11
+ margin-right: 15px;
12
+
13
+ i {
14
+ margin-left: 5px;
15
+ }
3
16
  }
@@ -5,7 +5,7 @@ $discussion-toolbar-color: #f6f6fa;
5
5
  $message-divider-color: #ecf0f1;
6
6
  $discussion-button-color: #fafafa;
7
7
  $toolbar-filter-color: #808080;
8
- $moderator-star-color: #dd9900;
8
+ $moderator-badge-color: #dd9900;
9
9
 
10
10
  .discussions-list {
11
11
  margin: 30px 0;
@@ -177,8 +177,17 @@ $moderator-star-color: #dd9900;
177
177
  width: 100%;
178
178
  }
179
179
 
180
- .moderator-star {
181
- color: $moderator-star-color;
180
+ .moderator-badge {
181
+ position: relative;
182
+ top: -2px;
183
+ margin: 2px;
184
+ font-size: 12px;
185
+ text-transform: uppercase;
186
+ color: white;
187
+ background-color: $moderator-badge-color;
188
+ border: solid $moderator-badge-color 1px;
189
+ border-radius: 5px;
190
+ padding-inline: 5px;
182
191
  }
183
192
 
184
193
  .discussion-user-menu {
@@ -326,12 +335,15 @@ summary.discussion-summary {
326
335
  .actions {
327
336
  float: right;
328
337
  a {
329
- margin-left: 5px;
338
+ margin-left: 20px;
330
339
  cursor: pointer;
331
340
  }
332
341
  .discussion-message-approved {
333
342
  text-decoration: none;
334
- &.selected {
343
+ i {
344
+ transition: color 0.3s;
345
+ }
346
+ &:hover, &.selected {
335
347
  i {
336
348
  color: $brand-success;
337
349
  }
@@ -341,17 +353,20 @@ summary.discussion-summary {
341
353
  text-decoration: none;
342
354
  i {
343
355
  position: relative;
356
+ transition: color 0.3s;
344
357
  &:after {
345
358
  position: absolute;
346
- left: 6px;
359
+ left: 10px;
360
+ top: -6px;
347
361
  content: ' ';
348
- height: 19px;
362
+ height: 30px;
349
363
  width: 2px;
350
364
  transform: rotate(-45deg);
351
365
  background-color: #aaaaaa;
366
+ transition: background-color 0.3s;
352
367
  }
353
368
  }
354
- &.selected {
369
+ &:hover, &.selected {
355
370
  i {
356
371
  color: $brand-primary;
357
372
  &:after {
@@ -360,6 +375,14 @@ summary.discussion-summary {
360
375
  }
361
376
  }
362
377
  }
378
+ .discussion-delete-message {
379
+ i {
380
+ transition: color 0.3s;
381
+ &:hover {
382
+ color: black;
383
+ }
384
+ }
385
+ }
363
386
  i {
364
387
  color: #aaaaaa
365
388
  }
@@ -28,7 +28,7 @@
28
28
  left: 20px;
29
29
  top: 17px;
30
30
 
31
- margin-right: 30px;
31
+ margin-right: 40px;
32
32
  margin-bottom: 15px;
33
33
  }
34
34
 
@@ -0,0 +1,35 @@
1
+ .mu-user-menu {
2
+ display: flex;
3
+ }
4
+
5
+ .mu-user-menu-header {
6
+ font-size: 15px;
7
+ color: $mu-color-disabled;
8
+ text-transform: uppercase;
9
+ margin-bottom: 30px;
10
+ }
11
+
12
+ .mu-user-menu-item {
13
+ font-size: 17px;
14
+ margin-bottom: 5px;
15
+
16
+ a {
17
+ color: $brand-primary;
18
+ &.active {
19
+ font-weight: bold;
20
+ }
21
+ }
22
+ }
23
+
24
+ .mu-user-menu-divider {
25
+ &.vertical {
26
+ border-left: 2px solid $mu-color-separator;
27
+ }
28
+
29
+ &.horizontal {
30
+ border-top: 2px solid $mu-color-separator;
31
+
32
+ margin: 25px 0;
33
+ width: 100%
34
+ }
35
+ }
@@ -31,11 +31,19 @@
31
31
  }
32
32
  }
33
33
 
34
+ .mu-profile-info {
35
+ display: flex;
36
+ flex-wrap: wrap;
37
+
38
+ margin-top: 20px;
39
+ }
40
+
34
41
  .mu-profile-info-left {
35
42
  display: flex;
36
43
  flex-direction: column;
37
44
  align-items: center;
38
45
  text-align: center;
46
+ flex-grow: 1;
39
47
 
40
48
  .mu-level-progress {
41
49
  position: relative;
@@ -62,8 +70,11 @@
62
70
  }
63
71
 
64
72
  .mu-profile-info-right {
73
+ flex-grow: 2;
74
+
65
75
  font-size: 20px;
66
76
  margin-top: 5px;
77
+
67
78
  div {
68
79
  margin-bottom: 15px;
69
80
  .italic {
@@ -5,7 +5,6 @@ module Api
5
5
  protect_from_forgery with: :null_session
6
6
 
7
7
  include Mumuki::Laboratory::Controllers::DynamicErrors
8
- include WithAuthorization
9
8
  include Mumuki::Laboratory::Controllers::CurrentOrganization
10
9
 
11
10
  before_action :set_current_organization!
@@ -18,7 +18,7 @@ module Api
18
18
  @course = Course.new course_params
19
19
  end
20
20
 
21
- def protection_slug
21
+ def authorization_slug
22
22
  @course.slug
23
23
  end
24
24
  end
@@ -2,8 +2,7 @@ module Api
2
2
  class OrganizationsController < BaseController
3
3
  include OrganizationsControllerTemplate
4
4
 
5
- before_action :authorize_janitor!, only: [:show, :index]
6
- before_action :authorize_admin!, only: [:update, :create]
5
+ before_action :authorize_admin!
7
6
 
8
7
  def index
9
8
  render json: { organizations: Organization.accessible_as(current_user, :janitor) }
@@ -22,6 +21,10 @@ module Api
22
21
  @organization.update! organization_params
23
22
  render json: @organization.to_resource_h
24
23
  end
24
+
25
+ def authorization_slug
26
+ '_/_'
27
+ end
25
28
  end
26
29
 
27
30
  end
@@ -48,6 +48,10 @@ module Api
48
48
  def set_slug!
49
49
  @slug = Mumukit::Auth::Slug.join_s params.to_unsafe_h
50
50
  end
51
+
52
+ def authorization_slug
53
+ @slug
54
+ end
51
55
  end
52
56
 
53
57
  end
@@ -9,8 +9,13 @@ module Api
9
9
  end
10
10
 
11
11
  def update
12
- @user.update_and_notify! user_params.except([:email, :permissions, :uid])
12
+ @user.assign_attributes user_name_params
13
+ @user.verify_name!
13
14
  render json: @user.to_resource_h
14
15
  end
16
+
17
+ def authorization_slug
18
+ '_/_'
19
+ end
15
20
  end
16
21
  end
@@ -34,8 +34,8 @@ class ApplicationController < ActionController::Base
34
34
  helper_method :current_workspace,
35
35
  :login_button,
36
36
  :notifications_count,
37
- :user_notifications_path,
38
37
  :has_notifications?,
38
+ :notifications,
39
39
  :subject,
40
40
  :should_choose_organization?,
41
41
  :current_immersive_organizations,
@@ -1,27 +1,12 @@
1
1
  module WithAuthorization
2
2
  extend ActiveSupport::Concern
3
3
 
4
- def authorize_janitor!
5
- authorize! :janitor
6
- end
7
-
8
- def authorize_admin!
9
- authorize! :admin
10
- end
11
-
12
- def authorize_owner!
13
- authorize! :owner
14
- end
15
-
16
- def authorize_moderator!
17
- authorize! :moderator
18
- end
19
-
20
4
  def authorization_slug
21
5
  protection_slug || '_/_'
22
6
  end
23
7
 
24
8
  def protection_slug
9
+ warn "protection_slug is nil, which is not probably what you want" unless @slug
25
10
  @slug
26
11
  end
27
12
  end
@@ -5,6 +5,10 @@ module WithUserParams
5
5
  params.require(:user).permit(*permissible_params).to_h
6
6
  end
7
7
 
8
+ def user_name_params
9
+ params.require(:user).permit(:first_name, :last_name).to_h
10
+ end
11
+
8
12
  def permissible_params
9
13
  User.profile_fields
10
14
  end