mumuki-laboratory 5.0.12 → 5.1.0

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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +339 -0
  3. data/app/assets/javascripts/application/bridge.js +36 -7
  4. data/app/assets/javascripts/application/kids.js +92 -7
  5. data/app/assets/javascripts/application/submission.js +2 -1
  6. data/app/assets/stylesheets/application/modules/_highlight.scss +8 -0
  7. data/app/assets/stylesheets/application/modules/_kids.scss +92 -27
  8. data/app/controllers/api/base_controller.rb +23 -0
  9. data/app/controllers/api/courses_controller.rb +26 -0
  10. data/app/controllers/api/organizations_controller.rb +28 -0
  11. data/app/controllers/api/roles_controller.rb +47 -0
  12. data/app/controllers/api/students_controller.rb +9 -0
  13. data/app/controllers/api/teachers_controller.rb +9 -0
  14. data/app/controllers/api/users_controller.rb +18 -0
  15. data/app/controllers/assets_controller.rb +2 -1
  16. data/app/controllers/concerns/on_base_organization_only.rb +11 -0
  17. data/app/controllers/concerns/organizations_controller_template.rb +34 -0
  18. data/app/controllers/concerns/users_controller_template.rb +28 -0
  19. data/app/controllers/concerns/with_api_errors.rb +37 -0
  20. data/app/controllers/concerns/with_authorization.rb +19 -0
  21. data/app/controllers/concerns/with_errors_filter.rb +32 -0
  22. data/app/helpers/reset_button_helper.rb +1 -1
  23. data/app/models/api_client.rb +27 -0
  24. data/app/models/api_client_spec.rb +6 -0
  25. data/app/models/concerns/with_assignments.rb +4 -1
  26. data/app/models/course.rb +4 -6
  27. data/app/models/exercise/challenge.rb +5 -6
  28. data/app/models/language.rb +1 -1
  29. data/app/models/organization.rb +4 -0
  30. data/app/models/user.rb +22 -1
  31. data/app/views/exercise_solutions/_kids_results_button.html.erb +11 -0
  32. data/app/views/exercise_solutions/_results.html.erb +1 -7
  33. data/app/views/exercise_solutions/_results_button.html.erb +7 -0
  34. data/app/views/layouts/_kids.html.erb +5 -2
  35. data/app/views/layouts/exercise_inputs/editors/_custom.html.erb +1 -0
  36. data/app/views/layouts/exercise_inputs/forms/_kids_form.html.erb +3 -0
  37. data/app/views/layouts/exercise_inputs/layouts/_input_kids.html.erb +3 -3
  38. data/app/views/layouts/modals/_kids_context.html.erb +0 -3
  39. data/app/views/layouts/modals/_kids_results.html.erb +2 -0
  40. data/config/routes.rb +23 -0
  41. data/db/migrate/20180129142749_add_api_client.rb +11 -0
  42. data/lib/mumuki/laboratory/controllers/results_rendering.rb +7 -1
  43. data/lib/mumuki/laboratory/extensions/string.rb +8 -0
  44. data/lib/mumuki/laboratory/locales/en.yml +4 -0
  45. data/lib/mumuki/laboratory/locales/es.yml +4 -0
  46. data/lib/mumuki/laboratory/locales/pt.yml +4 -0
  47. data/lib/mumuki/laboratory/mumukit/auth.rb +7 -0
  48. data/lib/mumuki/laboratory/version.rb +1 -1
  49. data/public/amarillo_exito.svg +11 -0
  50. data/public/amarillo_fracaso.svg +5 -0
  51. data/public/compass_rose.svg +1417 -0
  52. data/spec/controllers/api_clients_controller.rb +26 -0
  53. data/spec/controllers/confirmations_controller_spec.rb +1 -1
  54. data/spec/controllers/courses_api_controller_spec.rb +28 -0
  55. data/spec/controllers/exercise_solutions_controller_spec.rb +1 -1
  56. data/spec/controllers/messages_controller_spec.rb +1 -1
  57. data/spec/controllers/organizations_api_controller_spec.rb +235 -0
  58. data/spec/controllers/students_api_controller_spec.rb +101 -0
  59. data/spec/controllers/users_api_controller_spec.rb +56 -0
  60. data/spec/dummy/db/schema.rb +9 -0
  61. data/spec/factories/api_client_factory.rb +18 -0
  62. data/spec/factories/course_factory.rb +9 -0
  63. data/spec/features/chapter_spec.rb +1 -1
  64. data/spec/features/complements_flow_spec.rb +1 -1
  65. data/spec/features/exams_flow_spec.rb +1 -1
  66. data/spec/features/exercise_flow_spec.rb +1 -1
  67. data/spec/features/guide_reset_spec.rb +1 -1
  68. data/spec/features/guides_flow_spec.rb +1 -1
  69. data/spec/features/home_public_flow_spec.rb +1 -1
  70. data/spec/features/lessons_flow_spec.rb +1 -1
  71. data/spec/features/links_flow_spec.rb +1 -1
  72. data/spec/features/login_flow_spec.rb +1 -1
  73. data/spec/features/profile_flow_spec.rb +1 -1
  74. data/spec/features/standard_flow_spec.rb +1 -1
  75. data/spec/helpers/application_helper_spec.rb +1 -1
  76. data/spec/helpers/email_helper_spec.rb +1 -1
  77. data/spec/helpers/exercise_input_helper_spec.rb +1 -1
  78. data/spec/helpers/with_breadcrumbs_spec.rb +1 -1
  79. data/spec/helpers/with_navigation_spec.rb +1 -1
  80. data/spec/models/assignment_spec.rb +1 -1
  81. data/spec/models/book_import_spec.rb +1 -1
  82. data/spec/models/book_spec.rb +1 -1
  83. data/spec/models/course_spec.rb +1 -1
  84. data/spec/models/event_generation_spec.rb +1 -1
  85. data/spec/models/exam_spec.rb +1 -1
  86. data/spec/models/exercise_spec.rb +11 -3
  87. data/spec/models/guide_spec.rb +1 -1
  88. data/spec/models/interactive_spec.rb +1 -1
  89. data/spec/models/lesson_spec.rb +1 -1
  90. data/spec/models/message_spec.rb +1 -1
  91. data/spec/models/navigation_spec.rb +1 -1
  92. data/spec/models/organization_spec.rb +1 -1
  93. data/spec/models/problem_spec.rb +1 -1
  94. data/spec/models/question_spec.rb +1 -1
  95. data/spec/models/reading_spec.rb +1 -1
  96. data/spec/models/solution_spec.rb +1 -1
  97. data/spec/models/usage_spec.rb +1 -1
  98. data/spec/models/user_changed_spec.rb +1 -1
  99. data/spec/models/user_spec.rb +5 -5
  100. data/spec/spec_helper.rb +19 -3
  101. metadata +37 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d20a23b43e3c91f95ce461111eda22e97e96ab825aee08ec6a2b6186ddaa2869
4
- data.tar.gz: d20f260a0e52cfa8b7f5addb7b2206cd53b6cd018abfb2341777b23961a27022
3
+ metadata.gz: d22efc547d00b460a2f4e60d581454ee76f496d11deee257be13a766c3761fec
4
+ data.tar.gz: 14a468c0685dab2f527a3b8f3296b073c54ff20a3066fe4fb33c790efb2e272c
5
5
  SHA512:
6
- metadata.gz: d4b49d99b38e97e7991e46fcddc9312b9cad1e2868858776a4bf129ce8f8decdd006eb677b2d4ffbfd2b0b375dae2022ac32e9c90bfc878fb06ee344f263ef0f
7
- data.tar.gz: f28a32cf10fa13d7dbfabc6dbac25129fa633557fc5841d104e34c66a669bd24f77ac736a16e2093aff8470d45b5989dae3fa5a96fc8c0afa2fa4501b81b9a07
6
+ metadata.gz: 7af06b906467bf004ee6f37bbdca54d5467301090d84bb7e7f77ae2926cf66fac49030ccb10cf77779010df6859fa7f4f50e7634c9022349475fe8c27564d5e5
7
+ data.tar.gz: 609bc2c1250aecf90ba2ab188e2068824366603f5e32f9dc2573b1d402b0bd04b0822fd86d0ab351dbe4392c9c26f8f29c97da634e965c30e28d9547c108d5f7
data/README.md CHANGED
@@ -130,6 +130,345 @@ rails s
130
130
  bundle exec rspec
131
131
  ```
132
132
 
133
+ ## API Docs
134
+
135
+ Before using the API, you must create an `ApiClient` using `rails c`, which will generate a private JWT. Use it to authenticate API calls in any Platform application within a `Authorizaion: Bearer <TOKEN>`.
136
+
137
+ Before using the API, take a look to the roles hierarchy:
138
+
139
+ ![roles hierarchy](https://yuml.me/diagram/plain/class/[Owner]%5E-[Janitor],%20[Janitor]%5E-[Headmaster],%20[Headmaster]%5E-[Teacher],%20[Teacher]%5E-[Student],%20,%20[Owner]%5E-[Editor],%20[Editor]%5E-[Writer]).
140
+
141
+ Permissions are bound to a scope, that states in which context the operation can be performed. Scopes are simply two-level contexts, expressed as slugss `<first>/<second>`, without any explicit semantic. They exact meaning depends on the role:
142
+
143
+ * student: `organization/course`
144
+ * teacher and headmaster: `organization/course`
145
+ * writer and editor: `organization/content`
146
+ * janitor: `organization/_`
147
+ * owner: `_/_`
148
+
149
+ ### Users
150
+
151
+ #### Create single user
152
+
153
+ This is a generic user creation request.
154
+
155
+ **Minimal permission**: `janitor`
156
+
157
+ ```
158
+ POST /users
159
+ ```
160
+
161
+ Sample request body:
162
+
163
+ ```json
164
+ {
165
+ "first_name": "María",
166
+ "last_name": "Casas",
167
+ "email": "maryK345@foobar.edu.ar",
168
+ "permissions": {
169
+ "student": "cpt/*:rte/*",
170
+ "teacher": "ppp/2016-2q"
171
+ }
172
+ }
173
+ ```
174
+
175
+ #### Update single user
176
+
177
+ This is a way of updating user basic data. Permissions are ignored.
178
+
179
+ **Minimal permission**: `janitor`
180
+
181
+ ```
182
+ PUT /users/:uid
183
+ ```
184
+
185
+ Sample request body:
186
+
187
+ ```json
188
+ {
189
+ "first_name": "María",
190
+ "last_name": "Casas",
191
+ "email": "maryK345@foobar.edu.ar",
192
+ "uid": "maryK345@foobar.edu.ar"
193
+ }
194
+ ```
195
+
196
+ #### Add student to course
197
+
198
+ Creates the student if necessary, and updates her permissions.
199
+
200
+ **Minimal permission**: `janitor`
201
+
202
+ ```
203
+ POST /courses/:organization/:course/students
204
+ ```
205
+
206
+ ```json
207
+ {
208
+ "first_name": "María",
209
+ "last_name": "Casas",
210
+ "email": "maryK345@foobar.edu.ar",
211
+ "uid": "maryK345@foobar.edu.ar"
212
+ }
213
+ ```
214
+ **Response**
215
+ ```json
216
+ {
217
+ "uid": "maryK345@foobar.edu.ar",
218
+ "first_name": "María",
219
+ "last_name": "Casas",
220
+ "email": "maryK345@foobar.edu.ar"
221
+ }
222
+ ```
223
+ **Forbidden Response**
224
+ ```json
225
+ {
226
+ "status": 403,
227
+ "error": "Exception"
228
+ }
229
+ ```
230
+
231
+ #### Detach student from course
232
+
233
+ Remove student permissions from a course.
234
+
235
+ **Minimal permission**: `janitor`
236
+
237
+ ```
238
+ POST /courses/:organization/:course/students/:uid/detach
239
+ ```
240
+
241
+ **Response**: status code: 200
242
+
243
+
244
+ **Not Found Response**
245
+ ```json
246
+ {
247
+ "status": 404,
248
+ "error": "Couldn't find User"
249
+ }
250
+ ```
251
+
252
+ #### Attach student to course
253
+
254
+ Add student permissions to a course.
255
+
256
+ **Minimal permission**: `janitor`
257
+
258
+ ```
259
+ POST /courses/:organization/:course/students/:uid/attach
260
+ ```
261
+ **Response**: status code: 200
262
+
263
+ **Not Found Response**
264
+ ```json
265
+ {
266
+ "status": 404,
267
+ "error": "Couldn't find User"
268
+ }
269
+ ```
270
+
271
+
272
+ #### Add teacher to course
273
+
274
+ Creates the teacher if necessary, and updates her permissions.
275
+
276
+ **Minimal permission**: `headmaster`, `janitor`
277
+
278
+ ```
279
+ POST /course/:id/teachers
280
+ ```
281
+
282
+ ```json
283
+ {
284
+ "first_name": "Erica",
285
+ "last_name": "Gonzalez",
286
+ "email": "egonzalez@foobar.edu.ar",
287
+ "uid": "egonzalez@foobar.edu.ar"
288
+ }
289
+ ```
290
+
291
+ #### Add a batch of users to a course
292
+
293
+ Creates every user if necesssary, an updates permissions.
294
+
295
+ **Minimal permission**: `janitor`
296
+
297
+ ```
298
+ POST /course/:id/batches
299
+ ```
300
+
301
+ ```json
302
+ {
303
+ "students": [
304
+ {
305
+ "first_name": "Tupac",
306
+ "last_name": "Lincoln",
307
+ "email": "tliconln@foobar.edu.ar",
308
+ "uid": "tliconln@foobar.edu.ar"
309
+ }
310
+ ],
311
+ "teachers": [
312
+ {
313
+ "first_name": "Erica",
314
+ "last_name": "Gonzalez",
315
+ "email": "egonzalez@foobar.edu.ar",
316
+ "uid": "egonzalez@foobar.edu.ar"
317
+ }
318
+ ]
319
+ }
320
+ ```
321
+
322
+ #### Detach student from course
323
+
324
+ **Minimal permission**: `janitor`
325
+
326
+ ```
327
+ DELETE /course/:id/students/:uid
328
+ ```
329
+
330
+ #### Detach teacher from course
331
+
332
+ **Minimal permission**: `janitor`
333
+
334
+ ```
335
+ DELETE /course/:id/teachers/:uid
336
+ ```
337
+
338
+ #### Destroy single user
339
+
340
+ **Minimal permission**: `owner`
341
+
342
+ ```
343
+ DELETE /users/:uid
344
+ ```
345
+
346
+ ### Courses
347
+
348
+ #### Create single course
349
+
350
+ **Minimal permission**: `janitor`
351
+
352
+ ```
353
+ POST /organization/:id/courses/
354
+ ```
355
+
356
+ ```json
357
+ {
358
+ "name":"....",
359
+ }
360
+ ```
361
+
362
+ #### Archive single course
363
+
364
+ **Minimal permission**: `janitor`
365
+
366
+ ```
367
+ DELETE /organization/:id/courses/:id
368
+ ```
369
+
370
+ #### Destroy single course
371
+
372
+ **Minimal permission**: `owner`
373
+
374
+ ```
375
+ DELETE /courses/:id
376
+ ```
377
+
378
+
379
+ ### Organizations
380
+
381
+ #### Model
382
+
383
+ ### Mandatory fields
384
+ ```json
385
+ {
386
+ "name": "academy",
387
+ "contact_email": "issues@mumuki.io",
388
+ "books": [
389
+ "MumukiProject/mumuki-libro-metaprogramacion"
390
+ ],
391
+ "locale": "es-AR"
392
+ }
393
+ ```
394
+
395
+ ### Optional fields
396
+ ```json
397
+ {
398
+ "public": false,
399
+ "description": "...",
400
+ "login_methods": [
401
+ "facebook", "twitter", "google"
402
+ ],
403
+ "logo_url": "http://mumuki.io/logo-alt-large.png",
404
+ "terms_of_service": "Al usar Mumuki aceptás que las soluciones de tus ejercicios sean registradas para ser corregidas por tu/s docente/s...",
405
+ "theme_stylesheet": ".theme { color: red }",
406
+ "extension_javascript": "doSomething = function() { }"
407
+ }
408
+ ```
409
+
410
+ - If you set `null` to `public`, `login_methods`, the values will be `false` and `["user_pass"].
411
+ - If you set `null` to `description`, the value will be `null`.
412
+ - If you set `null` to the others, it will be inherited from an organization called `"base"` every time you query the API.
413
+
414
+
415
+ ### Generated fields
416
+ ```json
417
+ {
418
+ "theme_stylesheet_url": "stylesheets/academy-asjdf92j1jd8.css",
419
+ "extension_javascript_url": "javascripts/academy-jd912j8jdj19.js"
420
+ }
421
+ ```
422
+
423
+ #### List all organizations
424
+
425
+ ```
426
+ get /organizations
427
+ ```
428
+
429
+ Sample response body:
430
+
431
+ ```json
432
+ {
433
+ "organizations": [
434
+ { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url":"http://..." },
435
+ { "name": "alcal", "contact_email": "b@b.com", "locale": "en-US", "login_methods": ["facebook", "github"], "books": ["book"], "public": false }
436
+ ]
437
+ }
438
+ ```
439
+ **Minimal permission**: None for public organizations, `janitor` for user's private organizations.
440
+
441
+ #### Get single organization by name
442
+
443
+ ```
444
+ get /organizations/:name
445
+ ```
446
+
447
+ Sample response body:
448
+
449
+ ```json
450
+ { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url":"http://..." }
451
+ ```
452
+ **Minimal permission**: `janitor` of the organization.
453
+
454
+ #### Create organization
455
+
456
+ ```
457
+ post /organizations
458
+ ```
459
+ ... with at least the required fields.
460
+
461
+ **Minimal permission**: `owner` of that organization
462
+
463
+ #### Update organization
464
+
465
+ ```
466
+ put /organizations/:name
467
+ ```
468
+ ... with a partial update.
469
+
470
+ **Minimal permission**: `owner` of `:name`
471
+
133
472
 
134
473
  ## Authentication Powered by Auth0
135
474
 
@@ -1,19 +1,48 @@
1
1
  var mumuki = mumuki || {};
2
+
2
3
  (function (mumuki) {
4
+ var lastSubmission = {};
3
5
 
4
6
  function Laboratory(exerciseId){
5
7
  this.exerciseId = exerciseId;
6
8
  }
7
9
 
10
+ function asString(json){
11
+ return JSON.stringify(json);
12
+ }
13
+
14
+ function sameAsLastSolution(newSolution){
15
+ return asString(lastSubmission.content) === asString(newSolution);
16
+ }
17
+
18
+ function lastSubmissionFinishedSuccessfully(){
19
+ return lastSubmission.result && lastSubmission.result.status !== 'aborted';
20
+ }
21
+
22
+ function sendNewSolution(solution){
23
+ var token = new mumuki.CsrfToken();
24
+ var request = token.newRequest({
25
+ type: 'POST',
26
+ url: window.location.origin + window.location.pathname + '/solutions',
27
+ data: solution
28
+ });
29
+
30
+ return $.ajax(request).done(function (result) {
31
+ lastSubmission = { content: solution, result: result };
32
+ });
33
+ }
34
+
35
+ mumuki.load(function () {
36
+ lastSubmission = {};
37
+ });
38
+
8
39
  Laboratory.prototype = {
9
40
  runLocalTests: function (solution) {
10
- var token = new mumuki.CsrfToken();
11
- var request = token.newRequest({
12
- type: 'POST',
13
- url: window.location.origin + window.location.pathname + '/solutions',
14
- data: solution
15
- });
16
- return $.ajax(request)
41
+ if(lastSubmissionFinishedSuccessfully() && sameAsLastSolution(solution)){
42
+ return $.Deferred().resolve(lastSubmission.result);
43
+ } else {
44
+ return sendNewSolution(solution);
45
+ }
17
46
  },
18
47
  runTests: function(content) {
19
48
  return this.runLocalTests({ solution: content });
@@ -6,7 +6,7 @@ mumuki.load(function () {
6
6
 
7
7
  var gbsBoard = $('.mu-kids-state');
8
8
 
9
- var dimension = gbsBoard.height() - margin * 2;
9
+ var dimension = gbsBoard.height() * 1.25 - fullMargin;
10
10
  gbsBoard.width(dimension);
11
11
 
12
12
  var $muKidsExercise = $('.mu-kids-exercise');
@@ -50,7 +50,7 @@ mumuki.load(function () {
50
50
  }
51
51
 
52
52
  var $speechTabs = $('.mu-kids-character-speech-bubble-tabs > li:not(.separator)');
53
- var $bubble = $('.mu-kids-character-speech-bubble');
53
+ var $bubble = $('.mu-kids-character-speech-bubble').children('.mu-kids-character-speech-bubble-normal');
54
54
  var $texts = $bubble.children('.description, .hint');
55
55
 
56
56
  $speechTabs.each(function (i) {
@@ -91,19 +91,104 @@ mumuki.load(function () {
91
91
  if ($speechParagraphs.length - 1 === currentParagraphIndex) $nextSpeech.hide();
92
92
  }
93
93
 
94
- mumuki.getKidsResultsModal = function () {
95
- return $('#kids-results');
94
+ mumuki.kids = {
95
+
96
+ getResultsModal: function () {
97
+ return $('#kids-results');
98
+ },
99
+
100
+ getCharaterImage: function () {
101
+ return $('.mu-kids-character > img');
102
+ },
103
+
104
+ getCharacterBubble: function () {
105
+ return $('.mu-kids-character-speech-bubble');
106
+ },
107
+
108
+ getSubmissionResult: function () {
109
+ return $('.submission-results');
110
+ },
111
+
112
+ getOverlay: function () {
113
+ return $('.mu-kids-overlay');
114
+ },
115
+
116
+ showResult: function (data) { // This function is called by the custom runner
117
+ mumuki.updateProgressBarAndShowModal(data);
118
+ if (data.guide_finished_by_solution) return;
119
+ mumuki.kids.resultAction[data.status](data);
120
+ },
121
+
122
+ restart: function () { // This function is called by the custom runner
123
+ mumuki.kids._hideFailedMessage();
124
+ var $bubble = mumuki.kids.getCharacterBubble();
125
+ Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
126
+ mumuki.kids.getCharaterImage().attr('src', '/anim_amarillo.svg');
127
+ },
128
+
129
+ _hideFailedMessage: function () {
130
+ var $bubble = mumuki.kids.getCharacterBubble();
131
+ $bubble.find('.mu-kids-character-speech-bubble-tabs').show();
132
+ $bubble.find('.mu-kids-character-speech-bubble-normal').show();
133
+ $bubble.find('.mu-kids-character-speech-bubble-failed').hide();
134
+ Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
135
+ mumuki.kids.getOverlay().hide();
136
+ },
137
+
138
+ _showFailedMessage: function (data) {
139
+ var $bubble = mumuki.kids.getCharacterBubble();
140
+ $bubble.find('.mu-kids-character-speech-bubble-tabs').hide();
141
+ $bubble.find('.mu-kids-character-speech-bubble-normal').hide();
142
+ $bubble.find('.mu-kids-character-speech-bubble-failed').show().html(data.title_html);
143
+ $bubble.addClass(data.status);
144
+ mumuki.kids.getOverlay().show();
145
+ },
146
+
147
+ _showOnPopup: function (data) {
148
+ mumuki.kids.getSubmissionResult().html(data.html);
149
+ mumuki.kids.getCharaterImage().attr('src', '/amarillo_exito.svg');
150
+ mumuki.kids._showFailedMessage(data);
151
+ setTimeout(function () {
152
+ var results_kids_modal = mumuki.kids.getResultsModal();
153
+ if (results_kids_modal) {
154
+ results_kids_modal.modal({
155
+ backdrop: 'static',
156
+ keyboard: false
157
+ });
158
+ results_kids_modal.find('.modal-header').first().html(data.title_html);
159
+ results_kids_modal.find('.modal-footer').first().html(data.button_html);
160
+ }
161
+ }, 1000 * 4);
162
+ },
163
+
164
+ _showOnCharacterBubble: function (data) {
165
+ mumuki.kids.getCharaterImage().attr('src', '/amarillo_fracaso.svg');
166
+ mumuki.kids._showFailedMessage(data);
167
+ },
168
+
169
+ resultAction: {}
170
+
96
171
  };
97
172
 
98
173
  mumuki.showKidsResult = function (data) {
99
174
  mumuki.updateProgressBarAndShowModal(data);
100
175
  if (data.guide_finished_by_solution) return;
101
- $(".submission-results").html(data.html);
176
+ mumuki.kids.getSubmissionResult().html(data.html);
102
177
 
103
- var results_kids_modal = this.getKidsResultsModal();
178
+ var results_kids_modal = mumuki.kids.getResultsModal();
104
179
  if (results_kids_modal) {
105
180
  results_kids_modal.modal();
106
181
  results_kids_modal.find('.modal-header').first().html(data.title_html);
182
+ results_kids_modal.find('.modal-footer').first().html(data.button_html);
107
183
  }
108
- }
184
+ };
185
+
186
+ mumuki.kids.resultAction.passed = mumuki.kids._showOnPopup;
187
+ mumuki.kids.resultAction.aborted = mumuki.kids._showOnPopup;
188
+ mumuki.kids.resultAction.passed_with_warnings = mumuki.kids._showOnPopup;
189
+
190
+ mumuki.kids.resultAction.failed = mumuki.kids._showOnCharacterBubble;
191
+ mumuki.kids.resultAction.errored = mumuki.kids._showOnCharacterBubble;
192
+ mumuki.kids.resultAction.pending = mumuki.kids._showOnCharacterBubble;
193
+
109
194
  });