mumuki-laboratory 7.6.2 → 7.8.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 +203 -2
- data/Rakefile +9 -0
- data/app/assets/javascripts/mumuki_laboratory/application.js +0 -1
- data/app/assets/javascripts/mumuki_laboratory/application/alias-modes.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/assets-loader.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +82 -47
- data/app/assets/javascripts/mumuki_laboratory/application/button.js +90 -1
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +28 -25
- data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +8 -9
- data/app/assets/javascripts/mumuki_laboratory/application/confirmation.js +2 -2
- data/app/assets/javascripts/mumuki_laboratory/application/console.js +41 -43
- data/app/assets/javascripts/mumuki_laboratory/application/csrf-token.js +9 -12
- data/app/assets/javascripts/mumuki_laboratory/application/custom-editor.js +46 -8
- data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +15 -16
- data/app/assets/javascripts/mumuki_laboratory/application/editors.js +104 -0
- data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +5 -4
- data/app/assets/javascripts/mumuki_laboratory/application/exercise.js +32 -0
- data/app/assets/javascripts/mumuki_laboratory/application/inputs.js +4 -2
- data/app/assets/javascripts/mumuki_laboratory/application/interval.js +2 -4
- data/app/assets/javascripts/mumuki_laboratory/application/kids.js +74 -37
- data/app/assets/javascripts/mumuki_laboratory/application/load-analytics.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/load-error-svg.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/messages.js +2 -2
- data/app/assets/javascripts/mumuki_laboratory/application/multiple-choice.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/multiple-scenarios.js +3 -6
- data/app/assets/javascripts/mumuki_laboratory/application/pin.js +3 -5
- data/app/assets/javascripts/mumuki_laboratory/application/progress.js +27 -6
- data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +60 -0
- data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +12 -5
- data/app/assets/javascripts/mumuki_laboratory/application/submission.js +122 -55
- data/app/assets/javascripts/mumuki_laboratory/application/submissions-store.js +93 -0
- data/app/assets/javascripts/mumuki_laboratory/application/sync-mode.js +75 -0
- data/app/assets/javascripts/mumuki_laboratory/application/timer.js +5 -6
- data/app/assets/javascripts/mumuki_laboratory/application/tooltip.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/upload.js +1 -1
- data/app/assets/javascripts/mumuki_laboratory/application/user.js +1 -1
- data/app/assets/stylesheets/mumuki_laboratory/application/_modules.scss +1 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_discussion.scss +43 -5
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_gs-board.scss +3 -0
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids.scss +3 -4
- data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kindergarten.scss +55 -0
- data/app/controllers/application_controller.rb +1 -0
- data/app/controllers/assets_controller.rb +2 -0
- data/app/controllers/concerns/with_authorization.rb +4 -0
- data/app/controllers/concerns/with_user_discussion_validation.rb +14 -0
- data/app/controllers/discussions_controller.rb +6 -14
- data/app/controllers/discussions_messages_controller.rb +10 -1
- data/app/controllers/exercise_solutions_controller.rb +4 -2
- data/app/helpers/application_helper.rb +9 -5
- data/app/helpers/discussions_helper.rb +37 -23
- data/app/helpers/exercise_input_helper.rb +1 -1
- data/app/helpers/{locale_helper.rb → globals_helper.rb} +6 -2
- data/app/helpers/icons_helper.rb +3 -3
- data/app/mailers/user_mailer.rb +24 -11
- data/app/views/book/show.html.erb +1 -1
- data/app/views/book_discussions/index.html.erb +3 -3
- data/app/views/discussions/_message.html.erb +20 -8
- data/app/views/discussions/index.html.erb +0 -1
- data/app/views/discussions/new.html.erb +33 -0
- data/app/views/discussions/show.html.erb +18 -46
- data/app/views/exercise_solutions/_contextualization_results_container.html.erb +1 -1
- data/app/views/exercise_solutions/_results_title.html.erb +2 -2
- data/app/views/exercises/_read_only.html.erb +33 -6
- data/app/views/exercises/show.html.erb +2 -0
- data/app/views/layouts/_copyright.html.erb +1 -1
- data/app/views/layouts/_discussions.html.erb +21 -3
- data/app/views/layouts/_main.html.erb +1 -2
- data/app/views/layouts/_progress.html.erb +1 -1
- data/app/views/layouts/_progress_bar.html.erb +7 -1
- data/app/views/layouts/_test_results.html.erb +1 -1
- data/app/views/layouts/application.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/editors/_custom.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/forms/_kids_form.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/forms/_problem_form.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/layouts/_input_bottom.html.erb +1 -1
- data/app/views/layouts/exercise_inputs/layouts/_input_kindergarten.html.erb +40 -0
- data/app/views/layouts/exercise_inputs/layouts/{_input_kids.html.erb → _input_primary.html.erb} +1 -1
- data/app/views/layouts/exercise_inputs/layouts/_input_right.html.erb +1 -1
- data/app/views/layouts/modals/_kids_context.html.erb +1 -8
- data/app/views/user_mailer/1st_reminder.html.erb +1 -1
- data/app/views/user_mailer/1st_reminder.text.erb +1 -1
- data/app/views/user_mailer/2nd_reminder.html.erb +1 -1
- data/app/views/user_mailer/2nd_reminder.text.erb +1 -1
- data/app/views/user_mailer/3rd_reminder.html.erb +1 -1
- data/app/views/user_mailer/3rd_reminder.text.erb +1 -1
- data/app/views/user_mailer/no_submissions_reminder.html.erb +1 -1
- data/app/views/user_mailer/no_submissions_reminder.text.erb +1 -1
- data/config/routes.rb +2 -1
- data/lib/mumuki/laboratory/controllers.rb +1 -0
- data/lib/mumuki/laboratory/controllers/incognito_mode.rb +28 -0
- data/lib/mumuki/laboratory/controllers/results_rendering.rb +1 -2
- data/lib/mumuki/laboratory/locales/en.yml +14 -6
- data/lib/mumuki/laboratory/locales/es-CL.yml +292 -0
- data/lib/mumuki/laboratory/locales/es.yml +13 -5
- data/lib/mumuki/laboratory/locales/pt.yml +12 -6
- data/lib/mumuki/laboratory/version.rb +1 -1
- data/spec/controllers/confirmations_controller_spec.rb +1 -1
- data/spec/controllers/discussions_messages_controller_spec.rb +73 -0
- data/spec/controllers/exercise_solutions_controller_spec.rb +41 -6
- data/spec/dummy/db/schema.rb +13 -1
- data/spec/features/chapter_spec.rb +17 -0
- data/spec/features/discussion_flow_spec.rb +190 -0
- data/spec/features/exercise_flow_spec.rb +48 -3
- data/spec/features/home_public_flow_spec.rb +16 -0
- data/spec/features/menu_bar_spec.rb +88 -7
- data/spec/helpers/breadcrumbs_helper_spec.rb +1 -1
- data/spec/javascripts/bridge-spec.js +5 -0
- data/spec/javascripts/csrf-token-spec.js +7 -0
- data/spec/javascripts/editors-spec.js +54 -0
- data/spec/javascripts/elipsis-spec.js +25 -0
- data/spec/javascripts/exercise-spec.js +22 -0
- data/spec/javascripts/global-spec.js +6 -0
- data/spec/javascripts/results-renderers-spec.js +17 -0
- data/spec/javascripts/spec-helper.js +34 -0
- data/spec/javascripts/speech-bubble-renderer-spec.js +11 -0
- data/spec/javascripts/submissions-store-spec.js +44 -0
- data/spec/javascripts/sync-mode-spec.js +15 -0
- data/spec/javascripts/timeout-spec.js +5 -0
- data/spec/javascripts/timer-spec.js +5 -0
- data/spec/mailers/user_mailer_spec.rb +18 -3
- data/spec/teaspoon_env.rb +193 -0
- metadata +50 -11
- data/app/helpers/version_helper.rb +0 -5
- data/app/views/layouts/modals/_new_discussion.html.erb +0 -27
- data/vendor/assets/javascripts/hotjar.js +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf3186d3e4ad3367ccf34396dfde31138bb255456b8cf5e5593a76e908545434
|
4
|
+
data.tar.gz: 7e3aa354499be05940fe21355f7e4a45ae933dab0a989cd8db99b48e564c8f12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e91791ad61d5843960950276383f74330b0eec046f475400c21fdb89af80f044fa3902a7a86e82d1dc3e130f30716c62e23d79f5ea87c8416c9140e550414819
|
7
|
+
data.tar.gz: 528f209da31776d4c01be41b92c2218bcbb6dc98175809a05062c3b077e1dc0ca8951b034e44a9a0f3cca93bbba371fd0f14da18bb56e15fac9ddb3b2e211455
|
data/README.md
CHANGED
@@ -135,6 +135,21 @@ rails s
|
|
135
135
|
bundle exec rspec
|
136
136
|
```
|
137
137
|
|
138
|
+
## Running JS tests
|
139
|
+
|
140
|
+
> You need first to download [geckodriver](https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-linux64.tar.gz), uncrompress
|
141
|
+
> it and add it to your path
|
142
|
+
|
143
|
+
```bash
|
144
|
+
MOZ_HEADLESS=1 bundle exec rake teaspoon
|
145
|
+
```
|
146
|
+
|
147
|
+
## Running `eslint`
|
148
|
+
|
149
|
+
```bash
|
150
|
+
yarn run lint
|
151
|
+
```
|
152
|
+
|
138
153
|
## JavaScript API Docs
|
139
154
|
|
140
155
|
In order to be customized by runners, Laboratory exposes the following selectors and methods
|
@@ -158,7 +173,9 @@ which are granted to be safe and stable.
|
|
158
173
|
* `.mu-kids-submit-button`
|
159
174
|
* `.mu-multiple-scenarios`
|
160
175
|
* `.mu-scenarios`
|
176
|
+
* `.mu-submit-button`
|
161
177
|
* `#mu-actual-state-text`
|
178
|
+
* `#mu-${languageName}-custom-editor`
|
162
179
|
* `#mu-custom-editor-default-value`
|
163
180
|
* `#mu-custom-editor-extra`
|
164
181
|
* `#mu-custom-editor-test`
|
@@ -170,7 +187,6 @@ which are granted to be safe and stable.
|
|
170
187
|
* `.mu-kids-gbs-board-initial`: Use `.mu-initial-state` instead
|
171
188
|
* `.mu-state-final`: Use `.mu-final-state` instead
|
172
189
|
* `.mu-state-initial`: Use `.mu-initial-state` instead
|
173
|
-
* `#kids-context`: Use `.mu-kids-context` instead
|
174
190
|
* `#kids-results-aborted`: Use `.mu-kids-results-aborted` instead
|
175
191
|
* `#kids-results`: Use `.mu-kids-results` instead
|
176
192
|
|
@@ -178,6 +194,8 @@ which are granted to be safe and stable.
|
|
178
194
|
|
179
195
|
* `mumuki.bridge.Laboratory`
|
180
196
|
* `.runTests`
|
197
|
+
* `mumuki.CustomEditor`
|
198
|
+
* `addSource`
|
181
199
|
* `mumuki.editor`
|
182
200
|
* `formatContent`
|
183
201
|
* `reset`
|
@@ -191,10 +209,15 @@ which are granted to be safe and stable.
|
|
191
209
|
* `scaleBlocksArea`
|
192
210
|
* `scaleState`
|
193
211
|
* `showResult`
|
212
|
+
* `showContext`
|
194
213
|
* `mumuki.renderers`
|
195
214
|
* `SpeechBubbleRenderer`
|
196
215
|
* `renderSpeechBubbleResultItem`
|
197
216
|
* `mumuki.locale`
|
217
|
+
* `mumuki.exercise`
|
218
|
+
* `id`: the `id` of the currently loaded exercise, if any
|
219
|
+
* `layout`: the `layout` of the currently loaded exercise, if any
|
220
|
+
* `mumuki.incognitoUser`: whether the current user is an incognito user
|
198
221
|
* `mumuki.MultipleScenarios`
|
199
222
|
* `scenarios`
|
200
223
|
* `currentScenarioIndex`
|
@@ -205,6 +228,9 @@ which are granted to be safe and stable.
|
|
205
228
|
* `setUpDeleteFiles`
|
206
229
|
* `setUpDeleteFile`
|
207
230
|
* `updateButtonsVisibility`
|
231
|
+
* `mumuki.submission`
|
232
|
+
* `processSolution`
|
233
|
+
* `registerContentSyncer`
|
208
234
|
* `mumuki.version`
|
209
235
|
|
210
236
|
### Bridge Response Format
|
@@ -213,7 +239,6 @@ which are granted to be safe and stable.
|
|
213
239
|
{
|
214
240
|
"status": "passed|passed_with_warnings|failed",
|
215
241
|
"guide_finished_by_solution": "boolean",
|
216
|
-
"class_for_progress_list_item": "string",
|
217
242
|
"html": "string",
|
218
243
|
"remaining_attempts_html": "string" ,
|
219
244
|
"title_html": "string", // kids-only
|
@@ -243,6 +268,182 @@ which are granted to be safe and stable.
|
|
243
268
|
2. Laboratory Kids Layout Initialization
|
244
269
|
3. Runner Editor HTML
|
245
270
|
|
271
|
+
## Custom editors
|
272
|
+
|
273
|
+
Mumuki provides several editor types: code editors, multiple choice, file upload, and so on.
|
274
|
+
However, some runners will require custom editors in order to provide better ways of entering
|
275
|
+
solutions.
|
276
|
+
|
277
|
+
The process to do so is not difficult, but tricky, since there are a few hooks you need to implement. Let's look at them:
|
278
|
+
|
279
|
+
### 1. Before state: adding layout assets
|
280
|
+
|
281
|
+
If you need to provide a custom editor, chances are that you also need to provide assets to augment the layout, e.g. providing ways
|
282
|
+
to render some custom components on descriptions or corollaries. That code will be included first.
|
283
|
+
|
284
|
+
In order to do that, add to your runner the layout html, css and js code. Layout code has no further requirements. It can customize any public selector previously.
|
285
|
+
|
286
|
+
Although it is not required, it is recommended that your layout code works with any of the mumuki layouts:
|
287
|
+
|
288
|
+
* `input_right`
|
289
|
+
* `input_bottom`
|
290
|
+
* `input_primary`
|
291
|
+
* `input_kindergarten`
|
292
|
+
|
293
|
+
:warning: Not all the selectors will be available to all layouts.
|
294
|
+
|
295
|
+
Then expose code in the `MetadataHook`:
|
296
|
+
|
297
|
+
```ruby
|
298
|
+
class ... < Mumukit::Hook
|
299
|
+
def metadata
|
300
|
+
{
|
301
|
+
layout_assets_urls: {
|
302
|
+
js: [
|
303
|
+
'assets/....'
|
304
|
+
],
|
305
|
+
css: [
|
306
|
+
'assets/....'
|
307
|
+
],
|
308
|
+
html: [
|
309
|
+
'assets/....'
|
310
|
+
]
|
311
|
+
}
|
312
|
+
}
|
313
|
+
end
|
314
|
+
end
|
315
|
+
```
|
316
|
+
|
317
|
+
Finally, it is _recommended_ that you layout code calls `mumuki.assetsLoadedFor('layout')` when fully loaded.
|
318
|
+
|
319
|
+
That's it!
|
320
|
+
|
321
|
+
### 2. Adding custom editor assets
|
322
|
+
|
323
|
+
The process for registering custom editors is more involving.
|
324
|
+
|
325
|
+
#### 2.1 Add your assets and expose them
|
326
|
+
|
327
|
+
Add your js, css and html assets to your runner, and expose them in `MetadataHook`:
|
328
|
+
|
329
|
+
```ruby
|
330
|
+
class ... < Mumukit::Hook
|
331
|
+
def metadata
|
332
|
+
{
|
333
|
+
editor_assets_urls: {
|
334
|
+
js: [
|
335
|
+
'assets/....'
|
336
|
+
],
|
337
|
+
css: [
|
338
|
+
'assets/....'
|
339
|
+
],
|
340
|
+
html: [
|
341
|
+
'assets/....'
|
342
|
+
]
|
343
|
+
}
|
344
|
+
}
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
These assets will only be loaded when the editor `custom` is used.
|
350
|
+
|
351
|
+
#### 2.2 Add your components to the custom editor
|
352
|
+
|
353
|
+
Using JavaScript, append your components the custom-editor root, which can be found using the following selectors:
|
354
|
+
|
355
|
+
* `mu-${languageName}-custom-editor`
|
356
|
+
* `#mu-${languageName}-custom-editor`
|
357
|
+
* `.mu-${languageName}-custom-editor`
|
358
|
+
|
359
|
+
```javascript
|
360
|
+
$('#mu-mylang-custom-editor').append(/* ... */)
|
361
|
+
```
|
362
|
+
|
363
|
+
#### 2.3 Extract the test
|
364
|
+
|
365
|
+
If necessary, read the test definition from `#mu-custom-editor-test`, and plump into your custom components
|
366
|
+
|
367
|
+
```javascript
|
368
|
+
const test = $('#mu-custom-editor-test').val()
|
369
|
+
//...use test...
|
370
|
+
```
|
371
|
+
|
372
|
+
#### 2.4 Exposing your content
|
373
|
+
|
374
|
+
Before sending a submission, mumuki needs to be able to your read you editor components
|
375
|
+
contents. There are two different approaches:
|
376
|
+
|
377
|
+
* Register a syncer that writes `#mu-custom-editor-value` or any other custom editor selectors
|
378
|
+
* Add one or more content sources
|
379
|
+
|
380
|
+
```javascript
|
381
|
+
// simplest method - you can register just one
|
382
|
+
mumuki.editors.registerContentSyncer(() => {
|
383
|
+
// ... write here your custom component content...
|
384
|
+
$('#mu-custom-editor-value').val(/* ... */);
|
385
|
+
});
|
386
|
+
|
387
|
+
// alternate method
|
388
|
+
// you can register many sources
|
389
|
+
mumuki.editors.addCustomSource({
|
390
|
+
getContent() {
|
391
|
+
return { name: "solution[content]", value: /* ... */ } ;
|
392
|
+
}
|
393
|
+
});
|
394
|
+
```
|
395
|
+
|
396
|
+
#### 2.5 Optional: Sending your solution to the server programmatically
|
397
|
+
|
398
|
+
Your solution will be automatically sent to the client when the submit button is pressed. However,
|
399
|
+
if you need to trigger submission process programmatically, call `mumuki.submission.processSolution`:
|
400
|
+
|
401
|
+
```javascript
|
402
|
+
mumuki.submission.processSolution({solution: {content: /* ... */}});
|
403
|
+
```
|
404
|
+
|
405
|
+
#### 2.6 Optional: customizing your submit button
|
406
|
+
|
407
|
+
You can alternatively override the default submit button UI and behaviour, by replacing it with a custom component. In order to
|
408
|
+
do that, override the `.mu-submit-button` or the kids-specific `.mu-kids-submit-button`:
|
409
|
+
|
410
|
+
```javascript
|
411
|
+
$(".mu-submit-button").html(/* ... */);
|
412
|
+
```
|
413
|
+
|
414
|
+
However, doing this is tricky, since you will need to manually update the UI and connecting to the server. See:
|
415
|
+
|
416
|
+
* `mumuki.kids.showResult`
|
417
|
+
* `mumuki.bridge.Laboratory.runTests`
|
418
|
+
* `mumuki.updateProgressBarAndShowModal`
|
419
|
+
|
420
|
+
#### 2.7 Register kids scalers
|
421
|
+
|
422
|
+
Kids layouts have some special areas:
|
423
|
+
|
424
|
+
* _state area_: its display initial and/or final states of the exercise
|
425
|
+
* _blocks area_: a workspace that contains the building blocks of the solution - which are not necessary programming or blockly blocks, actually
|
426
|
+
|
427
|
+
If you want to support kids layouts, you **need** to register scalers that will be called when device is resized. Skip this step otherwise.
|
428
|
+
|
429
|
+
```javascript
|
430
|
+
mumuki.kids.registerStateScaler(($state, fullMargin, preferredWidth, preferredHeight) => {
|
431
|
+
// ... resize your components ...
|
432
|
+
});
|
433
|
+
|
434
|
+
mumuki.kids.registerBlocksAreaScaler(($blocks) => {
|
435
|
+
// ... resize your components ...
|
436
|
+
});
|
437
|
+
```
|
438
|
+
|
439
|
+
#### 2.8 Notify when your assets have been loaded
|
440
|
+
|
441
|
+
In order to remove loading spinners, you will need to call `mumuki.assetsLoadedFor` when your code is ready.
|
442
|
+
|
443
|
+
```javascript
|
444
|
+
mumuki.assetsLoadedFor('editor');
|
445
|
+
```
|
446
|
+
|
246
447
|
## Transparent Navigation API Docs
|
247
448
|
|
248
449
|
In order to be able to link content, laboratory exposes slug-based routes that will redirect to the actual
|
data/Rakefile
CHANGED
@@ -27,6 +27,15 @@ require 'rspec/core/rake_task'
|
|
27
27
|
desc "Run all specs in spec directory (excluding plugin specs)"
|
28
28
|
RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
|
29
29
|
|
30
|
+
desc "Force development environment, required by javascript specs"
|
31
|
+
task :development do
|
32
|
+
ENV['RACK_ENV'] = 'development'
|
33
|
+
ENV['RAILS_ENV'] = 'development'
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Run the javascript specs"
|
37
|
+
task teaspoon: [:development, "app:teaspoon"]
|
38
|
+
|
30
39
|
task default: :spec
|
31
40
|
|
32
41
|
|
@@ -1,68 +1,103 @@
|
|
1
|
-
|
1
|
+
/**
|
2
|
+
* @typedef {"errored"|"failed"|"passed_with_warnings"|"passed"|"pending"|"aborted"} SubmissionStatus
|
3
|
+
*/
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
+
/**
|
6
|
+
* @typedef {{
|
7
|
+
* status: SubmissionStatus,
|
8
|
+
* test_results: [{status: SubmissionStatus, title: string}]
|
9
|
+
* }} SubmissionClientResult
|
10
|
+
*/
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
12
|
+
/**
|
13
|
+
* @typedef {{
|
14
|
+
* status: SubmissionStatus,
|
15
|
+
* class_for_progress_list_item?: string,
|
16
|
+
* guide_finished_by_solution?: boolean
|
17
|
+
* }} SubmissionResult
|
18
|
+
*/
|
9
19
|
|
10
|
-
|
11
|
-
|
12
|
-
|
20
|
+
/**
|
21
|
+
* @typedef {object} Solution
|
22
|
+
*/
|
13
23
|
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
/**
|
25
|
+
* @typedef {{
|
26
|
+
* "solution[content]"?:string,
|
27
|
+
* solution?: Solution,
|
28
|
+
* client_result?: SubmissionClientResult
|
29
|
+
* }} Submission
|
30
|
+
*/
|
17
31
|
|
18
|
-
|
19
|
-
|
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' + window.location.search,
|
27
|
-
data: solution
|
28
|
-
});
|
29
|
-
|
30
|
-
return $.ajax(request).done(function (result) {
|
31
|
-
lastSubmission = { content: solution, result: result };
|
32
|
-
});
|
33
|
-
}
|
32
|
+
/**
|
33
|
+
* @typedef {{submission?: Submission, result?: SubmissionResult}} SubmissionAndResult
|
34
|
+
*/
|
34
35
|
|
35
|
-
|
36
|
-
lastSubmission = {};
|
37
|
-
});
|
38
|
-
|
39
|
-
Laboratory.prototype = {
|
36
|
+
mumuki.bridge = (() => {
|
40
37
|
|
38
|
+
class Laboratory {
|
41
39
|
// ==========
|
42
40
|
// Public API
|
43
41
|
// ==========
|
44
42
|
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
/**
|
44
|
+
* Runs tests for the current exercise using the given submission
|
45
|
+
* content.
|
46
|
+
*
|
47
|
+
* @param {object} content the content object
|
48
|
+
* */
|
49
|
+
runTests(content) {
|
48
50
|
return this._submitSolution({ solution: content });
|
49
|
-
}
|
51
|
+
}
|
50
52
|
|
51
53
|
// ===========
|
52
54
|
// Private API
|
53
55
|
// ===========
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
|
57
|
+
/**
|
58
|
+
* Sends a solution object
|
59
|
+
*
|
60
|
+
* @param {Submission} submission the submission object
|
61
|
+
* @returns {JQuery.Promise<SubmissionResult>}
|
62
|
+
*/
|
63
|
+
_submitSolution(submission) {
|
64
|
+
const lastSubmission = mumuki.SubmissionsStore.getSubmissionResultFor(mumuki.exercise.id, submission);
|
65
|
+
if (lastSubmission) {
|
66
|
+
return $.Deferred().resolve(lastSubmission);
|
58
67
|
} else {
|
59
|
-
return
|
68
|
+
return this._sendNewSolution(submission).done((result) => {
|
69
|
+
mumuki.SubmissionsStore.setSubmissionResultFor(mumuki.exercise.id, {submission, result});
|
70
|
+
});
|
60
71
|
}
|
61
|
-
}
|
62
|
-
};
|
72
|
+
}
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
|
74
|
+
/**
|
75
|
+
* @param {Submission} submission the submission object
|
76
|
+
* @returns {JQuery.Promise<SubmissionResult>}
|
77
|
+
*/
|
78
|
+
_sendNewSolution(submission){
|
79
|
+
var token = new mumuki.CsrfToken();
|
80
|
+
var request = token.newRequest({
|
81
|
+
type: 'POST',
|
82
|
+
url: window.location.origin + window.location.pathname + '/solutions' + window.location.search,
|
83
|
+
data: submission
|
84
|
+
});
|
85
|
+
return $.ajax(request).then((result) => this._preRenderResult(result));
|
86
|
+
}
|
67
87
|
|
68
|
-
|
88
|
+
/**
|
89
|
+
* Pre-renders some html parts of submission UI, adding them to the given result
|
90
|
+
*
|
91
|
+
* @param {SubmissionResult} result
|
92
|
+
* @returns {SubmissionResult}
|
93
|
+
*/
|
94
|
+
_preRenderResult(result) {
|
95
|
+
result.class_for_progress_list_item = mumuki.renderers.progressListItemClassForStatus(result.status, true)
|
96
|
+
return result;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
return {
|
101
|
+
Laboratory
|
102
|
+
};
|
103
|
+
})();
|