mumuki-laboratory 8.1.3 → 8.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -8
- data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +2 -1
- data/app/assets/javascripts/mumuki_laboratory/application/button.js +2 -4
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +2 -2
- data/app/assets/javascripts/mumuki_laboratory/application/i18n.js +73 -0
- data/app/assets/javascripts/mumuki_laboratory/application/kids.js +22 -1
- data/app/assets/javascripts/mumuki_laboratory/application/kindergarten.js +6 -1
- data/app/assets/javascripts/mumuki_laboratory/application/primary.js +5 -3
- data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +28 -1
- data/app/assets/javascripts/mumuki_laboratory/application/submission.js +72 -48
- data/app/assets/stylesheets/mumuki_laboratory/application.scss +1 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/_codemirror-themes.scss +1 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/codemirror-themes/_mu-light.scss +3 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids.scss +4 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids_results.scss +1 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_overlap.scss +0 -4
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_terms.scss +4 -0
- data/app/controllers/chapters_controller.rb +9 -5
- data/app/controllers/guide_container_controller.rb +2 -7
- data/app/helpers/assignment_result_helper.rb +1 -1
- data/app/helpers/contextualization_result_helper.rb +0 -8
- data/app/helpers/discussions_helper.rb +12 -4
- data/app/helpers/editor_tabs_helper.rb +1 -1
- data/app/helpers/icons_helper.rb +1 -1
- data/app/helpers/links_helper.rb +1 -1
- data/app/helpers/menu_bar_helper.rb +9 -1
- data/app/helpers/overlapped_buttons_helper.rb +13 -5
- data/app/views/book/show.html.erb +1 -1
- data/app/views/book_discussions/index.html.erb +3 -1
- data/app/views/chapters/show.html.erb +21 -9
- data/app/views/complements/show.html.erb +1 -1
- data/app/views/discussions/_message.html.erb +2 -2
- data/app/views/discussions/index.html.erb +11 -4
- data/app/views/exams/show.html.erb +1 -1
- data/app/views/exercise_solutions/_kids_level_up.html.erb +1 -1
- data/app/views/exercises/_exercise_assignment.html.erb +1 -1
- data/app/views/exercises/_read_only.html.erb +1 -1
- data/app/views/exercises/show.html.erb +2 -2
- data/app/views/layouts/_discussions.html.erb +0 -4
- data/app/views/layouts/_guide.html.erb +9 -36
- data/app/views/layouts/_guide_container.html.erb +28 -0
- data/app/views/layouts/_guide_title_icons.html.erb +9 -0
- data/app/views/layouts/_kids.html.erb +4 -4
- data/app/views/layouts/_kindergarten.html.erb +5 -5
- data/app/views/layouts/_social_media.html.erb +4 -4
- data/app/views/layouts/_timer.html.erb +1 -1
- data/app/views/layouts/application.html.erb +7 -5
- data/app/views/layouts/exercise_inputs/editors/_code.html.erb +1 -6
- data/app/views/layouts/exercise_inputs/editors/_multiple_files.html.erb +4 -9
- data/app/views/layouts/exercise_inputs/forms/_problem_form.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/layouts/_input_kindergarten.html.erb +1 -1
- data/app/views/layouts/modals/_guide_corollary.html.erb +13 -3
- data/app/views/layouts/modals/_kids_results.html.erb +2 -2
- data/app/views/layouts/modals/_kindergarten_context.html.erb +3 -3
- data/app/views/layouts/modals/_kindergarten_results.html.erb +3 -3
- data/app/views/layouts/modals/_kindergarten_results_aborted.html.erb +2 -2
- data/app/views/layouts/modals/_level_up.html.erb +1 -1
- data/app/views/lessons/show.html.erb +1 -1
- data/app/views/users/_edit_user_form.html.erb +1 -1
- data/app/views/users/_term.html.erb +1 -1
- data/app/views/users/_user_form.html.erb +1 -1
- data/lib/mumuki/laboratory/controllers/results_rendering.rb +2 -1
- data/lib/mumuki/laboratory/engine.rb +1 -1
- data/lib/mumuki/laboratory/locales/en.yml +6 -8
- data/lib/mumuki/laboratory/locales/es-CL.yml +6 -3
- data/lib/mumuki/laboratory/locales/es.yml +9 -10
- data/lib/mumuki/laboratory/locales/pt.yml +6 -8
- data/lib/mumuki/laboratory/version.rb +1 -1
- data/spec/controllers/exercise_solutions_controller_spec.rb +3 -2
- data/spec/dummy/db/schema.rb +50 -1
- data/spec/dummy/public/character/animations.json +1 -0
- data/{public → spec/dummy/public}/character/kibi/context.svg +0 -0
- data/{public → spec/dummy/public}/character/kibi/failure.svg +0 -0
- data/{public → spec/dummy/public}/character/kibi/jump.svg +0 -0
- data/spec/dummy/public/character/kibi/passed_with_warnings.svg +4 -0
- data/{public → spec/dummy/public}/character/kibi/success2_l.svg +0 -0
- data/{public → spec/dummy/public}/character/kibi/success_l.svg +0 -0
- data/{public → spec/dummy/public}/character/magnifying_glass/apparition.svg +0 -0
- data/{public → spec/dummy/public}/character/magnifying_glass/loop.svg +0 -0
- data/spec/features/chapters_flow_spec.rb +112 -0
- data/spec/features/login_flow_spec.rb +1 -1
- data/spec/features/terms_flow_spec.rb +2 -0
- data/spec/features/topic_flow_spec.rb +0 -1
- data/spec/helpers/icons_helper_spec.rb +3 -3
- data/spec/helpers/test_results_rendering_spec.rb +8 -8
- data/spec/helpers/with_navigation_spec.rb +14 -14
- data/spec/javascripts/bridge-spec.js +2 -2
- data/spec/javascripts/csrf-token-spec.js +2 -2
- data/spec/javascripts/editors-spec.js +7 -9
- data/spec/javascripts/elipsis-spec.js +4 -4
- data/spec/javascripts/events-spec.js +7 -7
- data/spec/javascripts/exercise-spec.js +7 -8
- data/spec/javascripts/gamification-spec.js +2 -2
- data/spec/javascripts/global-spec.js +3 -3
- data/spec/javascripts/i18n-spec.js +82 -0
- data/spec/javascripts/kids-button-spec.js +34 -0
- data/spec/javascripts/results-renderers-spec.js +5 -5
- data/spec/javascripts/speech-bubble-renderer-spec.js +2 -3
- data/spec/javascripts/submissions-store-spec.js +14 -14
- data/spec/javascripts/sync-mode-spec.js +3 -3
- data/spec/javascripts/timeout-spec.js +2 -2
- data/spec/javascripts/timer-spec.js +2 -2
- metadata +140 -117
- data/spec/dummy/config/database.travis.yml +0 -4
- data/spec/features/chapter_spec.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7c7290ee8af41b2af9f9d34977a9df9095fd3fb38a74e167bb1678b754cc001
|
4
|
+
data.tar.gz: 364699a1f019910da6ccc23d6970d20053a2ea36de3351fd32368c31395df89a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1f8f15e334cfc4599eab6b8872c829553fe2c92559bc5a22f796a23df711caf233317982ca0c057eaf8e8c0c9ddbc4209e1f3454ac9cfa379f79ce07a154265
|
7
|
+
data.tar.gz: f38ef6d9aef9f9d29ff14d9a091c60906438789b124334031bd102e605296fb8d844b5d2a2f97dd094e4586c4dd06a662c149d3f9d1ad6ad70cf5b5f4edf21d5
|
data/README.md
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
|
1
|
+
![Build status](https://github.com/mumuki/mumuki-laboratory/workflows/Test%20and%20deploy/badge.svg?branch=master)
|
2
2
|
[![Code Climate](https://codeclimate.com/github/mumuki/mumuki-laboratory/badges/gpa.svg)](https://codeclimate.com/github/mumuki/mumuki-laboratory)
|
3
|
-
[![Issue Count](https://codeclimate.com/github/mumuki/mumuki-laboratory/badges/issue_count.svg)](https://codeclimate.com/github/mumuki/mumuki-laboratory)
|
4
3
|
|
5
4
|
<img width="60%" src="https://raw.githubusercontent.com/mumuki/mumuki-laboratory/master/laboratory-screenshot.png"></img>
|
6
5
|
|
@@ -286,6 +285,7 @@ which are granted to be safe and stable.
|
|
286
285
|
* `updateButtonsVisibility`
|
287
286
|
* `mumuki.submission`
|
288
287
|
* `processSolution`
|
288
|
+
* `sendSolution`
|
289
289
|
* `registerContentSyncer`
|
290
290
|
* `mumuki.version`
|
291
291
|
|
@@ -482,16 +482,27 @@ mumuki.editors.addCustomSource({
|
|
482
482
|
});
|
483
483
|
```
|
484
484
|
|
485
|
-
#### 2.5 Optional:
|
485
|
+
#### 2.5 Optional: Triggering submission processing programmatically
|
486
486
|
|
487
|
-
Your solution will be automatically sent to the client when the submit button is pressed.
|
488
|
-
if you need to trigger submission process programmatically,
|
487
|
+
Your solution will be automatically sent to the client and processed when the submit button is pressed.
|
488
|
+
However, if you need to trigger the whole submission process programmatically,
|
489
|
+
call `mumuki.submission.processSolution`:
|
489
490
|
|
490
491
|
```javascript
|
491
492
|
mumuki.submission.processSolution({solution: {content: /* ... */}});
|
492
493
|
```
|
493
494
|
|
494
|
-
#### 2.6 Optional:
|
495
|
+
#### 2.6 Optional: Sending your solution to the server programmatically
|
496
|
+
|
497
|
+
Your solution will be automatically sent to the client when the submit button is pressed, as part of the
|
498
|
+
solution processing. However, if you just need to send your submission to the server programmatically,
|
499
|
+
call `mumuki.submission.sendSolution`:
|
500
|
+
|
501
|
+
```javascript
|
502
|
+
mumuki.submission.sendSolution({solution: {content: /* ... */}});
|
503
|
+
```
|
504
|
+
|
505
|
+
#### 2.7 Optional: customizing your submit button
|
495
506
|
|
496
507
|
You can alternatively override the default submit button UI and behaviour, by replacing it with a custom component. In order to
|
497
508
|
do that, override the `.mu-submit-button` or the kids-specific `.mu-kids-submit-button`:
|
@@ -506,7 +517,7 @@ However, doing this is tricky, since you will need to manually update the UI and
|
|
506
517
|
* `mumuki.bridge.Laboratory.runTests`
|
507
518
|
* `mumuki.updateProgressBarAndShowModal`
|
508
519
|
|
509
|
-
#### 2.
|
520
|
+
#### 2.8 Register kids scalers
|
510
521
|
|
511
522
|
Kids layouts have some special areas:
|
512
523
|
|
@@ -525,7 +536,7 @@ mumuki.kids.registerBlocksAreaScaler(($blocks) => {
|
|
525
536
|
});
|
526
537
|
```
|
527
538
|
|
528
|
-
#### 2.
|
539
|
+
#### 2.9 Notify when your assets have been loaded
|
529
540
|
|
530
541
|
In order to remove loading spinners, you will need to call `mumuki.assetsLoadedFor` when your code is ready.
|
531
542
|
|
@@ -113,7 +113,8 @@ mumuki.bridge = (() => {
|
|
113
113
|
* @returns {SubmissionResult}
|
114
114
|
*/
|
115
115
|
_preRenderResult(result) {
|
116
|
-
result.class_for_progress_list_item = mumuki.renderers.progressListItemClassForStatus(result.status, true);
|
116
|
+
result.class_for_progress_list_item = mumuki.renderers.results.progressListItemClassForStatus(result.status, true);
|
117
|
+
result.title_html = mumuki.renderers.results.translatedTitleHtml(result.status, result.in_gamified_context);
|
117
118
|
return result;
|
118
119
|
}
|
119
120
|
}
|
@@ -49,7 +49,6 @@ mumuki.Button = class {
|
|
49
49
|
*/
|
50
50
|
wait() {
|
51
51
|
this.$button.off('click');
|
52
|
-
|
53
52
|
this.setWaiting();
|
54
53
|
}
|
55
54
|
|
@@ -77,7 +76,6 @@ mumuki.Button = class {
|
|
77
76
|
*/
|
78
77
|
continue() {
|
79
78
|
this.$button.off('click');
|
80
|
-
|
81
79
|
this.enable();
|
82
80
|
|
83
81
|
this.$button.on('click', this.main);
|
@@ -106,11 +104,11 @@ mumuki.Button = class {
|
|
106
104
|
}
|
107
105
|
|
108
106
|
setWaitingText () {
|
109
|
-
this.$button.html('<i class="
|
107
|
+
this.$button.html('<i class="fas fa-sync-alt fa-spin"></i> ' + this.$button.attr('data-waiting'));
|
110
108
|
}
|
111
109
|
|
112
110
|
setRetryText() {
|
113
|
-
this.$button.html('<i class="
|
111
|
+
this.$button.html('<i class="fas fa-undo"></i>');
|
114
112
|
}
|
115
113
|
|
116
114
|
setOriginalContent () {
|
@@ -36,7 +36,7 @@ mumuki.page.editors = [];
|
|
36
36
|
|
37
37
|
function toggleFullscreen() {
|
38
38
|
$('body').toggleClass('fullscreen');
|
39
|
-
$('.editor-resize .
|
39
|
+
$('.editor-resize .fas').toggleClass('fa-expand fa-compress');
|
40
40
|
}
|
41
41
|
|
42
42
|
function indentWithSpaces(cm) {
|
@@ -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', '
|
65
|
+
editor.setOption('theme', 'mu-light ' + language);
|
66
66
|
}
|
67
67
|
|
68
68
|
function syncContent(){
|
@@ -0,0 +1,73 @@
|
|
1
|
+
mumuki.I18n = (() => {
|
2
|
+
|
3
|
+
const translations = {
|
4
|
+
'es': {
|
5
|
+
aborted: () => "Ups, no pudimos evaluar tu solución",
|
6
|
+
errored: () => "¡Ups! Tu solución no se puede ejecutar",
|
7
|
+
failed: () => "Tu solución no pasó las pruebas",
|
8
|
+
passed: () => "¡Muy bien! Tu solución pasó todas las pruebas",
|
9
|
+
passed_with_warnings: () => "Tu solución funcionó, pero hay cosas que mejorar",
|
10
|
+
pending: () => "Pendiente",
|
11
|
+
skipped: () => "Venís aprendiendo muy bien, por lo que aprobaste este ejercicio",
|
12
|
+
},
|
13
|
+
'es-CL': {
|
14
|
+
aborted: () => "Ups, no pudimos evaluar tu solución",
|
15
|
+
errored: () => "¡Ups! Tu solución no se puede ejecutar",
|
16
|
+
failed: () => "Tu solución no pasó las pruebas",
|
17
|
+
passed: () => "¡Muy bien! Tu solución pasó todas las pruebas",
|
18
|
+
passed_with_warnings: () => "Tu solución funcionó, pero hay cosas que mejorar",
|
19
|
+
pending: () => "Pendiente",
|
20
|
+
skipped: () => "Vienes aprendiendo muy bien, por lo que aprobaste este ejercicio",
|
21
|
+
},
|
22
|
+
'en': {
|
23
|
+
aborted: () => "Oops, we couldn't evaluate your solution",
|
24
|
+
errored: () => "Oops, your solution didn't work",
|
25
|
+
failed: () => "Oops, something went wrong",
|
26
|
+
passed: () => "Everything is in order! Your solution passed all our tests!",
|
27
|
+
passed_with_warnings: () => "It worked, but you can do better",
|
28
|
+
pending: () => "Pending",
|
29
|
+
skipped: () => "You are doing very well, so you've passed this exercise",
|
30
|
+
},
|
31
|
+
'pt': {
|
32
|
+
aborted: () => "Opa, não pudemos avaliar sua solução",
|
33
|
+
errored: () => "Opa! Sua solução não pode ser executada",
|
34
|
+
failed: () => "Sua solução não passou as provas",
|
35
|
+
passed: () => "Muito bem! Sua solução passou todos os testes",
|
36
|
+
passed_with_warnings: () => "Sua solução funcionou, mas há coisas para melhorar",
|
37
|
+
pending: () => "Pendente",
|
38
|
+
skipped: () => "Você está aprendendo muito bem e passou neste exercício",
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
return new class {
|
43
|
+
|
44
|
+
translate(key, data = {}) {
|
45
|
+
const translationValue = this._translationValue(key);
|
46
|
+
switch (typeof(translationValue)) {
|
47
|
+
case 'string': return translationValue;
|
48
|
+
case 'function': return translationValue(data);
|
49
|
+
default: return `Translation missing: ${mumuki.locale}, \`${key}\``;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
t(key, data = {}) {
|
54
|
+
return mumuki.I18n.translate(key, data);
|
55
|
+
}
|
56
|
+
|
57
|
+
register(translationsToOverride) {
|
58
|
+
const locales = Object.keys(translations);
|
59
|
+
locales.forEach((it) => translations[it] = Object.assign(translations[it], translationsToOverride[it]));
|
60
|
+
}
|
61
|
+
|
62
|
+
_prefixTranslationKey(key) {
|
63
|
+
this._prefix = $('[data-i18n-prefix]');
|
64
|
+
return this._prefix.get(0) ? `${this._prefix.data('i18n-prefix')}_${key}` : key;
|
65
|
+
}
|
66
|
+
|
67
|
+
_translationValue(key) {
|
68
|
+
let translationLocale = translations[mumuki.locale];
|
69
|
+
return translationLocale && (translationLocale[this._prefixTranslationKey(key)] || translationLocale[key]);
|
70
|
+
}
|
71
|
+
|
72
|
+
}
|
73
|
+
})();
|
@@ -1,3 +1,7 @@
|
|
1
|
+
mumuki.load(() => {
|
2
|
+
mumuki.isKidsExercise = () => $('.mu-kids-exercise').length > 0;
|
3
|
+
})
|
4
|
+
|
1
5
|
mumuki.Kids = class {
|
2
6
|
|
3
7
|
constructor() {
|
@@ -11,8 +15,9 @@ mumuki.Kids = class {
|
|
11
15
|
// ================
|
12
16
|
|
13
17
|
initialize() {
|
14
|
-
this.submitButton = new mumuki.submission.
|
18
|
+
this.submitButton = new mumuki.submission.KidsSubmitButton($('#kids-btn-retry'), $('.submission_control'));
|
15
19
|
this.resultActions = {};
|
20
|
+
this.$overlay = $('.mu-kids-overlay');
|
16
21
|
this.$states = $('.mu-kids-states');
|
17
22
|
this.$state = $('.mu-kids-state');
|
18
23
|
this.$blocks = $('.mu-kids-blocks');
|
@@ -27,6 +32,14 @@ mumuki.Kids = class {
|
|
27
32
|
this.$submissionResult = $('.submission-results');
|
28
33
|
mumuki.gamification.currentLevelProgression.registerLevelUpAction(this.levelUpAction);
|
29
34
|
mumuki.gamification.currentLevelProgression.registerGainedExperienceAction(this.gainedExperienceAction);
|
35
|
+
this.$resultsModal.on('hidden.bs.modal', this.resetExerciseIfSubmitless);
|
36
|
+
this.$resultsAbortedModal.on('hidden.bs.modal', this.resetExerciseIfSubmitless);
|
37
|
+
}
|
38
|
+
|
39
|
+
resetExerciseIfSubmitless() {
|
40
|
+
if ($('.mu-submitless-exercise').get(0)) {
|
41
|
+
mumuki.kids.submitButton.continue();
|
42
|
+
}
|
30
43
|
}
|
31
44
|
|
32
45
|
gainedExperienceAction() {
|
@@ -56,6 +69,14 @@ mumuki.Kids = class {
|
|
56
69
|
this.$resultsAbortedModal.modal();
|
57
70
|
}
|
58
71
|
|
72
|
+
showOverlay() {
|
73
|
+
this.$overlay.show();
|
74
|
+
}
|
75
|
+
|
76
|
+
hideOverlay() {
|
77
|
+
this.$overlay.hide();
|
78
|
+
}
|
79
|
+
|
59
80
|
// ==================
|
60
81
|
// == Hook Methods ==
|
61
82
|
// ==================
|
@@ -13,7 +13,7 @@ mumuki.load(() => {
|
|
13
13
|
this.$contextModalButton = new mumuki.Button($('#mu-kids-context .mu-kids-modal-button.mu-close'));
|
14
14
|
|
15
15
|
this.resultActions.passed = this._showSuccessPopup.bind(this);
|
16
|
-
this.resultActions.passed_with_warnings = this.
|
16
|
+
this.resultActions.passed_with_warnings = this._showPassedWithWarnings.bind(this);
|
17
17
|
this.resultActions.failed = this._showFailurePopup.bind(this);
|
18
18
|
this.resultActions.errored = this._showFailurePopup.bind(this);
|
19
19
|
this.resultActions.pending = this._showFailurePopup.bind(this);
|
@@ -50,6 +50,10 @@ mumuki.load(() => {
|
|
50
50
|
this.showNonAbortedPopup(data, 'success2_l');
|
51
51
|
}
|
52
52
|
|
53
|
+
_showPassedWithWarnings(data) {
|
54
|
+
this.showNonAbortedPopup(data, 'passed_with_warnings');
|
55
|
+
}
|
56
|
+
|
53
57
|
_showFailurePopup(data) {
|
54
58
|
this.showNonAbortedPopup(data, 'failure');
|
55
59
|
}
|
@@ -78,6 +82,7 @@ mumuki.load(() => {
|
|
78
82
|
|
79
83
|
restart() {
|
80
84
|
mumuki.presenterCharacter.playAnimation('talk', this.$bubbleCharacterAnimation);
|
85
|
+
this.hideOverlay();
|
81
86
|
}
|
82
87
|
|
83
88
|
// =======================
|
@@ -16,7 +16,6 @@ mumuki.load(() => {
|
|
16
16
|
super.initialize();
|
17
17
|
this.$characterSpeechBubble = $('.mu-kids-character-speech-bubble');
|
18
18
|
this.$characterSpeechBubbleNormal = this.$characterSpeechBubble.children('.mu-kids-character-speech-bubble-normal');
|
19
|
-
this.$overlay = $('.mu-kids-overlay');
|
20
19
|
this.$contextModalButton = new mumuki.Button($('.mu-kids-context .modal-footer button'));
|
21
20
|
|
22
21
|
this._paragraphHeight = undefined;
|
@@ -58,6 +57,10 @@ mumuki.load(() => {
|
|
58
57
|
this.showNonAbortedPopup(data, 'success2_l', 4000);
|
59
58
|
}
|
60
59
|
|
60
|
+
_showPassedWithWarnings(data) {
|
61
|
+
this.showNonAbortedPopup(data, 'passed_with_warnings', 4000);
|
62
|
+
}
|
63
|
+
|
61
64
|
_showFailurePopup(data) {
|
62
65
|
this._showOnCharacterBubble(data);
|
63
66
|
}
|
@@ -137,6 +140,7 @@ mumuki.load(() => {
|
|
137
140
|
const $bubble = this.$characterSpeechBubble;
|
138
141
|
Object.keys(this.resultActions).forEach($bubble.removeClass.bind($bubble));
|
139
142
|
mumuki.presenterCharacter.playAnimation('talk', this.$bubbleCharacterAnimation);
|
143
|
+
this.hideOverlay();
|
140
144
|
}
|
141
145
|
|
142
146
|
// =======================
|
@@ -150,7 +154,6 @@ mumuki.load(() => {
|
|
150
154
|
$bubble.find('.mu-kids-character-speech-bubble-failed').hide();
|
151
155
|
$bubble.find('.mu-kids-discussion-link').remove();
|
152
156
|
Object.keys(this.resultActions).forEach($bubble.removeClass.bind($bubble));
|
153
|
-
this.$overlay.hide();
|
154
157
|
}
|
155
158
|
|
156
159
|
_showMessageOnCharacterBubble(data) {
|
@@ -158,7 +161,6 @@ mumuki.load(() => {
|
|
158
161
|
renderer.setDiscussionsLinkHtml($('#mu-kids-discussion-link-html').html());
|
159
162
|
renderer.setResponseData(data);
|
160
163
|
renderer.render();
|
161
|
-
this.$overlay.show();
|
162
164
|
}
|
163
165
|
|
164
166
|
_showOnCharacterBubble(data) {
|
@@ -35,6 +35,32 @@ mumuki.renderers.results = (() => {
|
|
35
35
|
}
|
36
36
|
}
|
37
37
|
|
38
|
+
/**
|
39
|
+
* @param {SubmissionStatus} status
|
40
|
+
* @param {Boolean} isGamifiedContext
|
41
|
+
* @returns {string}
|
42
|
+
*/
|
43
|
+
function translatedTitleHtml(status, isGamifiedContext) {
|
44
|
+
return `
|
45
|
+
<h4 class="text-${classForStatus(status)} %>">
|
46
|
+
<strong><i class="fa-fw fas ${iconForStatus(status)}"></i> ${mumuki.I18n.t(status)}</strong>
|
47
|
+
${gamifiedContextHtml(isGamifiedContext)}
|
48
|
+
</h4>
|
49
|
+
`
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* @param {Boolean} isGamifiedContext
|
54
|
+
* @returns {string}
|
55
|
+
*/
|
56
|
+
function gamifiedContextHtml(isGamifiedContext) {
|
57
|
+
return (!isGamifiedContext) ? '' : `
|
58
|
+
<strong><small class="text-success">
|
59
|
+
<span class="mu-experience"></span>
|
60
|
+
</small></strong>
|
61
|
+
`
|
62
|
+
}
|
63
|
+
|
38
64
|
|
39
65
|
/**
|
40
66
|
* @param {SubmissionStatus} status
|
@@ -48,7 +74,8 @@ mumuki.renderers.results = (() => {
|
|
48
74
|
return {
|
49
75
|
classForStatus,
|
50
76
|
iconForStatus,
|
51
|
-
progressListItemClassForStatus
|
77
|
+
progressListItemClassForStatus,
|
78
|
+
translatedTitleHtml
|
52
79
|
};
|
53
80
|
})();
|
54
81
|
|
@@ -55,8 +55,50 @@ mumuki.submission = (() => {
|
|
55
55
|
this.preventClick();
|
56
56
|
}
|
57
57
|
}
|
58
|
+
|
59
|
+
solutionSender(bridge, solution) {
|
60
|
+
return bridge._submitSolution(solution);
|
61
|
+
}
|
62
|
+
|
63
|
+
solutionProcessor(bridge, $submissionsResults, solution) {
|
64
|
+
const resultsBox = new ResultsBox($submissionsResults);
|
65
|
+
this.disable();
|
66
|
+
this.setWaitingText();
|
67
|
+
resultsBox.waiting();
|
68
|
+
return this.solutionSender(bridge, solution)
|
69
|
+
.done((data) => resultsBox.success(data, this))
|
70
|
+
.fail(() => resultsBox.error(this))
|
71
|
+
.always((data) => {
|
72
|
+
$(document).renderMuComponents();
|
73
|
+
resultsBox.done(data, this);
|
74
|
+
});
|
75
|
+
}
|
58
76
|
}
|
59
77
|
|
78
|
+
class KidsSubmitButton extends SubmitButton {
|
79
|
+
|
80
|
+
wait() {
|
81
|
+
mumuki.kids.showOverlay();
|
82
|
+
super.wait();
|
83
|
+
}
|
84
|
+
|
85
|
+
continue() {
|
86
|
+
mumuki.kids.hideOverlay();
|
87
|
+
super.continue();
|
88
|
+
}
|
89
|
+
|
90
|
+
solutionProcessor(bridge, $submissionsResults, solution) {
|
91
|
+
this.wait();
|
92
|
+
return this.solutionSender(bridge, solution)
|
93
|
+
.then((data) => mumuki.kids.showResult(data))
|
94
|
+
.always((data) => {
|
95
|
+
this.ready(() => {
|
96
|
+
mumuki.kids.restart();
|
97
|
+
this.continue();
|
98
|
+
});
|
99
|
+
});
|
100
|
+
}
|
101
|
+
}
|
60
102
|
|
61
103
|
// ==========
|
62
104
|
// Processing
|
@@ -67,14 +109,28 @@ mumuki.submission = (() => {
|
|
67
109
|
* restoring buttons state.
|
68
110
|
*
|
69
111
|
* The actual implementation of this method depends on contextual {@link _solutionProcessor}, which can
|
70
|
-
* be configured using {@link _registerSolutionProcessor}. Currently there are only two available processors
|
71
|
-
*
|
72
|
-
* on the exercise DOM.
|
112
|
+
* be configured using {@link _registerSolutionProcessor}. Currently there are only two available processors
|
113
|
+
* which are automatically choosen depending on the exercise DOM.
|
73
114
|
*
|
74
115
|
* @param {Submission} solution
|
75
116
|
*/
|
76
117
|
function processSolution(solution) {
|
77
|
-
mumuki.submission._solutionProcessor(solution);
|
118
|
+
return mumuki.submission._solutionProcessor(solution);
|
119
|
+
}
|
120
|
+
|
121
|
+
/**
|
122
|
+
* Just sends solution to the server without any further processing afterwards.
|
123
|
+
*
|
124
|
+
* Consider using {@link processSolution} instead if you want the whole functionality (making buttons wait, sending to server, rendering results,
|
125
|
+
* restoring buttons state).
|
126
|
+
* The implementation of this method isn't contextual, it always sends the solution using bridge module.
|
127
|
+
*
|
128
|
+
* @see mumuki.bridge
|
129
|
+
*
|
130
|
+
* @param {Submission} solution
|
131
|
+
*/
|
132
|
+
function sendSolution(solution) {
|
133
|
+
return mumuki.submission._solutionSender(solution);
|
78
134
|
}
|
79
135
|
|
80
136
|
/**
|
@@ -84,53 +140,19 @@ mumuki.submission = (() => {
|
|
84
140
|
* and should normally not be called by runners editor, but is exposed
|
85
141
|
* for further non-standard customizations.
|
86
142
|
*
|
87
|
-
* @param {
|
143
|
+
* @param {SubmitButton} submitButton
|
144
|
+
* @param {$ElementType} $submissionsResults
|
145
|
+
* @param {mumuki.bridge} bridge
|
88
146
|
*/
|
89
|
-
function _registerSolutionProcessor(
|
90
|
-
mumuki.submission.
|
91
|
-
|
92
|
-
|
93
|
-
/** Processor for kids layouts */
|
94
|
-
function _kidsSolutionProcessor(bridge, submitButton) {
|
95
|
-
return (solution) => {
|
96
|
-
submitButton.wait();
|
97
|
-
bridge._submitSolution(solution).always(function (data) {
|
98
|
-
submitButton.ready(() => {
|
99
|
-
mumuki.kids.restart();
|
100
|
-
submitButton.continue();
|
101
|
-
});
|
102
|
-
mumuki.kids.showResult(data);
|
103
|
-
});
|
104
|
-
};
|
105
|
-
}
|
106
|
-
|
107
|
-
/** Processor for non-kids layouts */
|
108
|
-
function _classicSolutionProcessor(bridge, submitButton, resultsBox) {
|
109
|
-
return (solution) => {
|
110
|
-
submitButton.disable();
|
111
|
-
submitButton.setWaitingText();
|
112
|
-
resultsBox.waiting();
|
113
|
-
bridge._submitSolution(solution).done(function (data) {
|
114
|
-
resultsBox.success(data, submitButton);
|
115
|
-
}).fail(function () {
|
116
|
-
resultsBox.error(submitButton);
|
117
|
-
}).always(function (data) {
|
118
|
-
$(document).renderMuComponents();
|
119
|
-
resultsBox.done(data, submitButton);
|
120
|
-
});
|
121
|
-
};
|
147
|
+
function _registerSolutionProcessor(submitButton, $submissionsResults, bridge) {
|
148
|
+
mumuki.submission._solutionSender = submitButton.solutionSender.bind(submitButton, bridge);
|
149
|
+
mumuki.submission._solutionProcessor = submitButton.solutionProcessor.bind(submitButton, bridge, $submissionsResults);
|
122
150
|
}
|
123
151
|
|
124
152
|
/** Selects the most appropriate solution processor */
|
125
153
|
function _selectSolutionProcessor(submitButton, $submissionsResults) {
|
126
154
|
const bridge = new mumuki.bridge.Laboratory();
|
127
|
-
|
128
|
-
if ($('.mu-kids-exercise').length) {
|
129
|
-
processor = _kidsSolutionProcessor(bridge, submitButton);
|
130
|
-
} else {
|
131
|
-
processor = _classicSolutionProcessor(bridge, submitButton, new ResultsBox($submissionsResults));
|
132
|
-
}
|
133
|
-
mumuki.submission._registerSolutionProcessor(processor);
|
155
|
+
mumuki.submission._registerSolutionProcessor(submitButton, $submissionsResults, bridge);
|
134
156
|
}
|
135
157
|
|
136
158
|
|
@@ -143,8 +165,8 @@ mumuki.submission = (() => {
|
|
143
165
|
if (!$submissionsResults) return;
|
144
166
|
|
145
167
|
const $btnSubmit = $('.btn-submit');
|
146
|
-
const
|
147
|
-
|
168
|
+
const buttonClass = mumuki.isKidsExercise() ? KidsSubmitButton : SubmitButton;
|
169
|
+
const submitButton = new buttonClass($btnSubmit, $('.submission_control'));
|
148
170
|
mumuki.submission._selectSolutionProcessor(submitButton, $submissionsResults);
|
149
171
|
|
150
172
|
submitButton.start(() => {
|
@@ -154,7 +176,6 @@ mumuki.submission = (() => {
|
|
154
176
|
submitButton.checkAttemptsLeft();
|
155
177
|
});
|
156
178
|
|
157
|
-
|
158
179
|
/**
|
159
180
|
* This module contains methods for submitting solution in at high level, dealing with network communication,
|
160
181
|
* and layout-sensitive UI updates. It is intended to be both used internally by standard editors and by runners
|
@@ -171,10 +192,13 @@ mumuki.submission = (() => {
|
|
171
192
|
*/
|
172
193
|
return {
|
173
194
|
processSolution,
|
195
|
+
sendSolution,
|
196
|
+
|
174
197
|
_registerSolutionProcessor,
|
175
198
|
_selectSolutionProcessor,
|
176
199
|
|
177
200
|
animateTimeoutError,
|
178
201
|
SubmitButton,
|
202
|
+
KidsSubmitButton,
|
179
203
|
};
|
180
204
|
})();
|