mumuki-laboratory 7.12.1 → 8.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +1 -1
  3. data/app/assets/javascripts/mumuki_laboratory/application/button.js +2 -2
  4. data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +2 -2
  5. data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +5 -5
  6. data/app/assets/javascripts/mumuki_laboratory/application/console.js +2 -2
  7. data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +7 -7
  8. data/app/assets/javascripts/mumuki_laboratory/application/editors.js +1 -1
  9. data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +1 -1
  10. data/app/assets/javascripts/mumuki_laboratory/application/events.js +2 -2
  11. data/app/assets/javascripts/mumuki_laboratory/application/exercise.js +2 -2
  12. data/app/assets/javascripts/mumuki_laboratory/application/gamification.js +99 -11
  13. data/app/assets/javascripts/mumuki_laboratory/application/inputs.js +1 -1
  14. data/app/assets/javascripts/mumuki_laboratory/application/kids.js +20 -8
  15. data/app/assets/javascripts/mumuki_laboratory/application/kindergarten.js +16 -57
  16. data/app/assets/javascripts/mumuki_laboratory/application/messages.js +6 -6
  17. data/app/assets/javascripts/mumuki_laboratory/application/mu-modal-carrousel.js +63 -0
  18. data/app/assets/javascripts/mumuki_laboratory/application/multiple-choice.js +1 -1
  19. data/app/assets/javascripts/mumuki_laboratory/application/multiple-files.js +3 -3
  20. data/app/assets/javascripts/mumuki_laboratory/application/multiple-scenarios.js +1 -1
  21. data/app/assets/javascripts/mumuki_laboratory/application/number-counter.js +18 -0
  22. data/app/assets/javascripts/mumuki_laboratory/application/pin.js +1 -1
  23. data/app/assets/javascripts/mumuki_laboratory/application/primary.js +3 -2
  24. data/app/assets/javascripts/mumuki_laboratory/application/progress.js +1 -1
  25. data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +1 -1
  26. data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +4 -4
  27. data/app/assets/javascripts/mumuki_laboratory/application/submission.js +3 -3
  28. data/app/assets/javascripts/mumuki_laboratory/application/submissions-store.js +3 -3
  29. data/app/assets/javascripts/mumuki_laboratory/application/sync-mode.js +2 -2
  30. data/app/assets/javascripts/mumuki_laboratory/application/timer.js +1 -1
  31. data/app/assets/stylesheets/mumuki_laboratory/application/_layout.scss +7 -7
  32. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids_results.scss +117 -0
  33. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kindergarten.scss +45 -131
  34. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_terms.scss +9 -12
  35. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_user_profile.scss +31 -3
  36. data/app/controllers/api/courses_controller.rb +1 -2
  37. data/app/controllers/api/organizations_controller.rb +2 -3
  38. data/app/controllers/api/users_controller.rb +2 -4
  39. data/app/controllers/application_controller.rb +41 -8
  40. data/app/controllers/assets_controller.rb +1 -0
  41. data/app/controllers/book_discussions_controller.rb +1 -1
  42. data/app/controllers/chapters_controller.rb +1 -0
  43. data/app/controllers/concerns/with_user_discussion_validation.rb +6 -0
  44. data/app/controllers/discussions_controller.rb +4 -6
  45. data/app/controllers/exercises_controller.rb +1 -0
  46. data/app/controllers/guides_controller.rb +2 -0
  47. data/app/controllers/invitations_controller.rb +2 -2
  48. data/app/controllers/lessons_controller.rb +1 -0
  49. data/app/controllers/login_controller.rb +1 -0
  50. data/app/controllers/users_controller.rb +9 -1
  51. data/app/helpers/assistance_box_helper.rb +7 -5
  52. data/app/helpers/gamification_helper.rb +5 -0
  53. data/app/helpers/links_helper.rb +2 -2
  54. data/app/views/exercise_solutions/_assistant_rules_box.html.erb +13 -0
  55. data/app/views/exercise_solutions/_contextualization_results_container.html.erb +9 -0
  56. data/app/views/exercise_solutions/_kids_level_up.html.erb +11 -0
  57. data/app/views/exercise_solutions/_results.html.erb +19 -19
  58. data/app/views/exercise_solutions/_results_title.html.erb +5 -0
  59. data/app/views/exercises/show.html.erb +4 -1
  60. data/app/views/layouts/_copyright.html.erb +1 -1
  61. data/app/views/layouts/_kindergarten.html.erb +1 -1
  62. data/app/views/layouts/_organizations_listing.html.erb +8 -12
  63. data/app/views/layouts/application.html.erb +23 -15
  64. data/app/views/layouts/embedded.html.erb +14 -11
  65. data/app/views/layouts/modals/_guide_corollary.html.erb +1 -1
  66. data/app/views/layouts/modals/_kids_context.html.erb +1 -1
  67. data/app/views/layouts/modals/_kids_results.html.erb +16 -6
  68. data/app/views/layouts/modals/_kindergarten_context.html.erb +15 -15
  69. data/app/views/layouts/modals/_kindergarten_results.html.erb +20 -7
  70. data/app/views/layouts/modals/_kindergarten_results_aborted.html.erb +4 -4
  71. data/app/views/layouts/modals/_level_up.html.erb +27 -0
  72. data/app/views/users/_edit_user_form.html.erb +1 -1
  73. data/app/views/users/_user_form.html.erb +12 -2
  74. data/app/views/users/terms.html.erb +12 -0
  75. data/config/routes.rb +8 -8
  76. data/lib/mumuki/laboratory.rb +18 -5
  77. data/lib/mumuki/laboratory/controllers.rb +2 -0
  78. data/lib/mumuki/laboratory/controllers/action_redirector.rb +21 -0
  79. data/lib/mumuki/laboratory/controllers/immersive_navigation.rb +7 -0
  80. data/lib/mumuki/laboratory/controllers/results_rendering.rb +1 -0
  81. data/lib/mumuki/laboratory/events/events.rb +0 -33
  82. data/lib/mumuki/laboratory/locales/en.yml +5 -0
  83. data/lib/mumuki/laboratory/locales/es-CL.yml +6 -1
  84. data/lib/mumuki/laboratory/locales/es.yml +7 -2
  85. data/lib/mumuki/laboratory/locales/pt.yml +6 -1
  86. data/lib/mumuki/laboratory/version.rb +1 -1
  87. data/spec/capybara_helper.rb +5 -1
  88. data/spec/controllers/discussions_controller_spec.rb +19 -0
  89. data/spec/controllers/exercise_solutions_controller_spec.rb +1 -1
  90. data/spec/dummy/db/schema.rb +2 -1
  91. data/spec/features/immersive_redirection_spec.rb +181 -0
  92. data/spec/features/profile_flow_spec.rb +35 -3
  93. data/spec/features/terms_flow_spec.rb +155 -0
  94. metadata +110 -101
  95. data/app/helpers/organization_list_helper.rb +0 -5
  96. data/spec/features/choose_organization_spec.rb +0 -74
@@ -87,155 +87,69 @@ $modal-footer-height: 95px;
87
87
  }
88
88
  }
89
89
 
90
- .mu-kindergarten-context {
90
+ .modal-content.kindergarten {
91
+ $width-lg: 800px;
92
+ $height-lg: $width-lg * 0.625;
91
93
 
92
- .modal-dialog {
94
+ width: $width-lg;
95
+ height: $height-lg;
93
96
 
94
- height: 100vh;
95
- width: 100vw;
96
- margin: 0;
97
+ top: calc(50vh - #{$height-lg} / 2);
97
98
 
98
- .modal-content {
99
- position: absolute;
100
-
101
- $width-lg: 800px;
102
- $height-lg: $width-lg * 0.625;
103
-
104
- width: $width-lg;
105
- height: $height-lg;
106
-
107
- top: calc(50vh - #{$height-lg} / 2);
108
- left: calc(50vw - #{$width-lg} / 2);
109
-
110
- @media (orientation: landscape) and (max-height: $height-lg + 50px) {
111
- $height-sm: 85vh;
112
- $width-sm: $height-sm / 0.625;
99
+ @media (orientation: landscape) and (max-height: $height-lg + 50px) {
100
+ $height-sm: 85vh;
101
+ $width-sm: $height-sm / 0.625;
113
102
 
114
- width: $width-sm;
115
- height: $height-sm;
103
+ width: $width-sm;
104
+ height: $height-sm;
116
105
 
117
- top: calc(50vh - #{$height-sm} / 2);
118
- left: calc(50vw - #{$width-sm} / 2);
119
- }
120
-
121
- @media (orientation: portrait) {
122
- $height-sm: 85vh;
123
- $width-sm: 85vw;
124
-
125
- width: $width-sm;
126
- height: $height-sm;
127
-
128
- top: calc(50vh - #{$height-sm} / 2);
129
- left: calc(50vw - #{$width-sm} / 2);
130
- }
106
+ top: calc(50vh - #{$height-sm} / 2);
107
+ left: calc(50vw - #{$width-sm} / 2);
108
+ }
131
109
 
132
- $border-width: 16px;
133
- border-width: $border-width;
134
- border-style: solid;
135
- border-color: $mu-color-link;
136
- border-radius: $border-width;
137
- box-shadow: none;
110
+ @media (orientation: portrait) {
111
+ $height-sm: 85vh;
112
+ $width-sm: 85vw;
138
113
 
139
- .modal-header,
140
- .modal-footer {
141
- text-align: center;
142
- text-transform: uppercase;
143
- }
114
+ width: $width-sm;
115
+ height: $height-sm;
144
116
 
145
- .modal-body {
146
- height: 100%;
147
- div, p {
148
- height: 100%;
149
- .mu-kindergarten-context-image-slides {
150
- img:not(.active) {
151
- display: none;
152
- }
153
- }
154
- img {
155
- width: 100%;
156
- height: 100%;
157
- object-position: center;
158
- object-fit: contain;
159
- }
160
- }
161
- }
117
+ top: calc(50vh - #{$height-sm} / 2);
118
+ left: calc(50vw - #{$width-sm} / 2);
119
+ }
162
120
 
163
- .mu-kindergarten-modal-button {
164
- $diameter: 64px;
165
- position: absolute;
166
- border-radius: 50%;
167
- height: $diameter;
168
- width: $diameter;
169
- color: white;
170
- font-weight: bold;
171
- border: none;
172
- padding: 0;
173
- background: $mu-color-link;
174
- &.mu-next,
175
- &.mu-close {
176
- top: - $diameter / 2 - $border-width / 2;
177
- right: - $diameter / 2 - $border-width / 2;
178
- }
179
- &.mu-previous {
180
- top: - $diameter / 2 - $border-width / 2;
181
- left: - $diameter / 2 - $border-width / 2;
182
- }
183
- }
121
+ .modal-header,
122
+ .modal-footer {
123
+ text-align: center;
124
+ text-transform: uppercase;
125
+ }
184
126
 
185
- $mu-statuses-colors: (
186
- 'broken': $mu-color-broken,
187
- 'danger': $mu-color-danger,
188
- 'success': $mu-color-success,
189
- 'warning': $mu-color-warning,
190
- 'passed': $mu-color-success,
191
- 'passed-with-warnings': $mu-color-warning,
192
- 'failed': $mu-color-danger,
193
- 'errored': $mu-color-broken,
194
- 'aborted': $mu-color-broken,
195
- 'pending': $mu-color-info
196
- );
197
-
198
- @each $class, $color in $mu-statuses-colors {
199
- &.#{$class} {
200
- border-color: $color;
201
- .mu-kindergarten-modal-button {
202
- background: $color;
203
- }
204
- }
205
- .submission-results {
206
- width: 100%;
207
- height: 100%;
208
- .mu-kids-callout-#{$class},
209
- p {
210
- display: none;
211
- }
212
- .mu-kids-default-#{$class} {
213
- width: 100%;
214
- height: 100%;
215
- img {
216
- width: 100%;
217
- height: 100%;
218
- object-position: center;
219
- object-fit: contain;
220
- }
221
- }
222
- }
223
- }
127
+ .modal-body.mu-kids-context-body {
128
+ height: 100%;
129
+ div img, p img {
130
+ width: 100%;
131
+ height: 100%;
132
+ object-position: center;
133
+ object-fit: contain;
224
134
  }
225
135
  }
226
136
  }
227
137
 
228
- #kids-results.mu-kindergarten-context {
138
+ #kids-results.mu-kids-modal-border {
229
139
  .modal-body{
230
140
  height: calc(100% - #{$modal-header-height} - #{$modal-footer-height});
231
141
  }
232
142
  }
233
- #kids-results-aborted.mu-kindergarten-context {
234
- .modal-body{
235
- height: calc(100% - #{$modal-header-height});
236
- }
237
- h4.modal-header {
238
- margin: 0;
143
+
144
+ #kids-results-aborted.mu-kids-modal-border {
145
+ .modal-content.kindergarten {
146
+ .modal-body {
147
+ height: calc(100% - #{$modal-header-height});
148
+ }
149
+
150
+ h4.modal-header {
151
+ margin: 0;
152
+ }
239
153
  }
240
154
  }
241
155
 
@@ -1,12 +1,3 @@
1
- summary.terms-summary {
2
- font-size: 29px;
3
- outline: 0;
4
- cursor: pointer;
5
- .terms-summary-title {
6
- display: inline;
7
- }
8
- }
9
-
10
1
  .terms-card {
11
2
  position: relative;
12
3
  display: -ms-flexbox;
@@ -38,7 +29,13 @@ summary.terms-summary {
38
29
  padding: 1.25rem;
39
30
  }
40
31
 
41
- .terms-acceptance-btn {
42
- margin-top: 10px;
43
- display: block
32
+ .terms-acceptance {
33
+ margin-top: 30px;
34
+
35
+ .terms-acceptance-btn {
36
+ margin-top: 10px;
37
+ display: block
38
+ }
44
39
  }
40
+
41
+
@@ -31,7 +31,37 @@
31
31
  }
32
32
  }
33
33
 
34
- .mu-profile-info {
34
+ .mu-profile-info-left {
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ text-align: center;
39
+
40
+ .mu-level-progress {
41
+ position: relative;
42
+ top: -275px;
43
+ margin-bottom: -275px;
44
+ }
45
+ }
46
+
47
+ .mu-level {
48
+ .mu-level-number {
49
+ position: absolute;
50
+ margin-top: 11px;
51
+ margin-left: -86px;
52
+ width: 87px;
53
+
54
+ text-align: center;
55
+ font-size: 1.5em;
56
+ font-weight: bold;
57
+ color: white;
58
+
59
+ user-select: none;
60
+ pointer-events: none;
61
+ }
62
+ }
63
+
64
+ .mu-profile-info-right {
35
65
  font-size: 20px;
36
66
  margin-top: 5px;
37
67
  div {
@@ -40,6 +70,4 @@
40
70
  font-style: italic;
41
71
  }
42
72
  }
43
-
44
-
45
73
  }
@@ -5,7 +5,6 @@ module Api
5
5
 
6
6
  def create
7
7
  @course.save!
8
- @course.notify!
9
8
  render json: @course
10
9
  end
11
10
 
@@ -23,4 +22,4 @@ module Api
23
22
  @course.slug
24
23
  end
25
24
  end
26
- end
25
+ end
@@ -14,13 +14,12 @@ module Api
14
14
  end
15
15
 
16
16
  def create
17
- @organization.save_and_notify!
17
+ @organization.save!
18
18
  render json: @organization.to_resource_h
19
19
  end
20
20
 
21
21
  def update
22
- @organization.update_and_notify! organization_params
23
-
22
+ @organization.update! organization_params
24
23
  render json: @organization.to_resource_h
25
24
  end
26
25
  end
@@ -4,14 +4,12 @@ module Api
4
4
  before_action :authorize_janitor!
5
5
 
6
6
  def create
7
- @user.save!
8
- @user.notify!
7
+ @user.save_and_notify!
9
8
  render json: @user.to_resource_h
10
9
  end
11
10
 
12
11
  def update
13
- @user.update! user_params.except([:email, :permissions, :uid])
14
- @user.notify!
12
+ @user.update_and_notify! user_params.except([:email, :permissions, :uid])
15
13
  render json: @user.to_resource_h
16
14
  end
17
15
  end
@@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base
12
12
  include Mumuki::Laboratory::Controllers::DynamicErrors
13
13
  include Mumuki::Laboratory::Controllers::EmbeddedMode
14
14
  include Mumuki::Laboratory::Controllers::IncognitoMode
15
+ include Mumuki::Laboratory::Controllers::ActionRedirector
15
16
 
16
17
  before_action :set_current_organization!
17
18
  before_action :set_locale!
@@ -24,6 +25,7 @@ class ApplicationController < ActionController::Base
24
25
  before_action :authorize_if_private!
25
26
  before_action :validate_active_organization!
26
27
  before_action :validate_user_profile!, if: :current_user?
28
+ before_action :validate_accepted_role_terms!, if: :current_user?
27
29
 
28
30
  before_action :visit_organization!, if: :current_user?
29
31
 
@@ -36,23 +38,26 @@ class ApplicationController < ActionController::Base
36
38
  :has_notifications?,
37
39
  :subject,
38
40
  :should_choose_organization?,
41
+ :current_immersive_organizations,
39
42
  :theme_stylesheet_url,
40
- :extension_javascript_url
43
+ :extension_javascript_url,
44
+ :current_immersive_path
41
45
 
42
46
  def immersive_context_wrong?
43
47
  current_immersive_context != Organization.current
44
48
  end
45
49
 
46
50
  def redirect_to_proper_context!
47
- # TODO: redirect to subject (if it exists on the immersive context)
48
- redirect_to current_immersive_context.url_for('/')
51
+ redirect_to current_immersive_path_for(*current_immersive_context_and_content)
49
52
  end
50
53
 
51
54
  def should_choose_organization?
52
55
  return false unless current_user?
56
+ current_immersive_organizations.multiple?
57
+ end
53
58
 
54
- # TODO: replace `nil` with `subject` to consider exercise, guide, etc
55
- current_user.immersive_organizations_at(nil).size > 1
59
+ def current_immersive_organizations
60
+ current_user.immersive_organizations_with_content_at(subject)
56
61
  end
57
62
 
58
63
  # ensures contents are accessible to current user
@@ -66,7 +71,6 @@ class ApplicationController < ActionController::Base
66
71
  Organization.current.validate_active!
67
72
  end
68
73
 
69
-
70
74
  # required by Mumukit::Login
71
75
  def login_button(options = {})
72
76
  login_form.button_html I18n.t(:sign_in), options[:class]
@@ -82,11 +86,31 @@ class ApplicationController < ActionController::Base
82
86
  Mumuki::Domain::Workspace.new(current_user, Organization.current)
83
87
  end
84
88
 
89
+ def current_immersive_path(context)
90
+ current_immersive_path_for context, subject&.navigable_content_in(context)
91
+ end
92
+
93
+ def current_immersive_path_for(context, content)
94
+ resource = content ? polymorphic_path(content) : default_immersive_path_for(context)
95
+ context.url_for resource
96
+ end
97
+
85
98
  private
86
99
 
100
+ def default_immersive_path_for(context)
101
+ subject.present? ? root_path : inorganic_path_for(request)
102
+ end
103
+
104
+ def inorganic_path_for(request)
105
+ Mumukit::Platform.organization_mapping.inorganic_path_for(request)
106
+ end
107
+
87
108
  def current_immersive_context
88
- # TODO: replace `nil` with `subject` to consider exercise, guide, etc
89
- current_user&.current_immersive_context_at(nil) || Organization.current
109
+ current_immersive_context_and_content&.first || Organization.current
110
+ end
111
+
112
+ def current_immersive_context_and_content
113
+ current_user&.current_immersive_context_and_content_at(subject) || [Organization.current, nil]
90
114
  end
91
115
 
92
116
  def from_sessions?
@@ -99,11 +123,20 @@ class ApplicationController < ActionController::Base
99
123
 
100
124
  def validate_user_profile!
101
125
  unless current_user.profile_completed?
126
+ save_location_before! :profile_completion
102
127
  flash.notice = I18n.t :please_fill_profile_data
103
128
  redirect_to edit_user_path
104
129
  end
105
130
  end
106
131
 
132
+ def validate_accepted_role_terms!
133
+ if current_user&.has_role_terms_to_accept?
134
+ save_location_before! :terms_acceptance
135
+ flash.notice = I18n.t :accept_terms_to_continue
136
+ redirect_to terms_user_path
137
+ end
138
+ end
139
+
107
140
  def set_locale!
108
141
  I18n.locale = Organization.current.locale
109
142
  end
@@ -3,6 +3,7 @@ class AssetsController < ApplicationController
3
3
  protect_from_forgery except: [:theme_stylesheet, :extension_javascript]
4
4
  skip_before_action :authorize_if_private!
5
5
  skip_before_action :validate_user_profile!
6
+ skip_before_action :validate_accepted_role_terms!
6
7
  skip_before_action :validate_active_organization!
7
8
 
8
9
  def theme_stylesheet
@@ -2,7 +2,7 @@ class BookDiscussionsController < DiscussionsController
2
2
  def terms
3
3
  @forum_terms ||= Term.forum_related_terms
4
4
  end
5
-
5
+
6
6
  private
7
7
 
8
8
  def set_debatable