mumuki-laboratory 5.0.12 → 5.1.0

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