mumuki-laboratory 7.4.1 → 7.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +34 -18
  3. data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +19 -2
  4. data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +31 -0
  5. data/app/assets/javascripts/mumuki_laboratory/application/interval.js +17 -0
  6. data/app/assets/javascripts/mumuki_laboratory/application/kids.js +6 -17
  7. data/app/assets/javascripts/mumuki_laboratory/application/messages.js +1 -1
  8. data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +99 -0
  9. data/app/assets/javascripts/mumuki_laboratory/application/timer.js +1 -1
  10. data/app/assets/stylesheets/mumuki_laboratory/application.scss +1 -0
  11. data/app/assets/stylesheets/mumuki_laboratory/application/_layout.scss +0 -4
  12. data/app/assets/stylesheets/mumuki_laboratory/application/_locked.scss +29 -0
  13. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_editor.scss +0 -23
  14. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_exercise_results.scss +11 -0
  15. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_kids.scss +1 -1
  16. data/app/assets/stylesheets/mumuki_laboratory/application/modules/_overlap.scss +21 -2
  17. data/app/assets/stylesheets/mumuki_laboratory/application/modules/popover.scss +1 -1
  18. data/app/controllers/application_controller.rb +25 -2
  19. data/app/controllers/concerns/users_controller_template.rb +6 -1
  20. data/app/controllers/invitations_controller.rb +1 -0
  21. data/app/controllers/login_controller.rb +1 -0
  22. data/app/helpers/application_helper.rb +1 -5
  23. data/app/helpers/contextualization_result_helper.rb +7 -7
  24. data/app/helpers/discussions_helper.rb +1 -1
  25. data/app/helpers/exercise_input_helper.rb +1 -1
  26. data/app/helpers/links_helper.rb +1 -1
  27. data/app/helpers/overlapped_buttons_helper.rb +17 -0
  28. data/app/views/book/show.html.erb +14 -6
  29. data/app/views/errors/gone.html.erb +4 -1
  30. data/app/views/exercise_solutions/_expectations.html.erb +2 -2
  31. data/app/views/exercise_solutions/_kids_results_button.html.erb +1 -1
  32. data/app/views/exercises/_read_only.html.erb +1 -1
  33. data/app/views/exercises/show.html.erb +19 -15
  34. data/app/views/layouts/_exercise_skipped.html.erb +28 -0
  35. data/app/views/layouts/_kids.html.erb +1 -1
  36. data/app/views/layouts/_test_results.html.erb +11 -8
  37. data/app/views/layouts/exercise_inputs/editors/_code.html.erb +8 -7
  38. data/app/views/layouts/exercise_inputs/editors/_multiple_files.html.erb +8 -9
  39. data/app/views/layouts/exercise_inputs/forms/_interactive_form.html.erb +2 -2
  40. data/app/views/layouts/exercise_inputs/forms/_playground_form.html.erb +1 -1
  41. data/app/views/layouts/exercise_inputs/forms/_problem_form.html.erb +1 -1
  42. data/app/views/layouts/modals/_kids_results.html.erb +1 -1
  43. data/app/views/user_mailer/1st_reminder.html.erb +1 -1
  44. data/app/views/user_mailer/1st_reminder.text.erb +1 -1
  45. data/app/views/user_mailer/2nd_reminder.html.erb +1 -1
  46. data/app/views/user_mailer/2nd_reminder.text.erb +1 -1
  47. data/app/views/user_mailer/3rd_reminder.html.erb +1 -1
  48. data/app/views/user_mailer/3rd_reminder.text.erb +1 -1
  49. data/app/views/user_mailer/no_submissions_reminder.html.erb +1 -1
  50. data/app/views/user_mailer/no_submissions_reminder.text.erb +1 -1
  51. data/app/views/users/_user_form.html.erb +1 -1
  52. data/config/initializers/session_store.rb +1 -1
  53. data/lib/mumuki/laboratory/controllers.rb +1 -0
  54. data/lib/mumuki/laboratory/controllers/authorization.rb +0 -4
  55. data/lib/mumuki/laboratory/controllers/disabling.rb +5 -0
  56. data/lib/mumuki/laboratory/controllers/dynamic_errors.rb +16 -1
  57. data/lib/mumuki/laboratory/controllers/results_rendering.rb +15 -17
  58. data/lib/mumuki/laboratory/locales/en.yml +12 -2
  59. data/lib/mumuki/laboratory/locales/es.yml +13 -2
  60. data/lib/mumuki/laboratory/locales/pt.yml +13 -2
  61. data/lib/mumuki/laboratory/version.rb +1 -1
  62. data/spec/controllers/exercise_solutions_controller_spec.rb +29 -14
  63. data/spec/controllers/users_api_controller_spec.rb +1 -0
  64. data/spec/controllers/users_controller_spec.rb +21 -0
  65. data/spec/dummy/db/schema.rb +10 -1
  66. data/spec/dummy/db/seeds.rb +8 -0
  67. data/spec/features/disable_user_flow_spec.rb +34 -0
  68. data/spec/features/disabled_organization_flow_spec.rb +69 -0
  69. data/spec/features/exercise_flow_spec.rb +20 -11
  70. data/spec/features/home_public_flow_spec.rb +34 -2
  71. data/spec/helpers/test_results_rendering_spec.rb +50 -28
  72. data/spec/login_helper.rb +1 -1
  73. data/spec/spec_helper.rb +2 -0
  74. metadata +33 -7
  75. data/app/helpers/reset_button_helper.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6e6b25c694e8a00a86fcf06f05f35ab974c9602230eba187884aa16bfdb7168
4
- data.tar.gz: 2648860bd2387704e371d55cb08696dd82b419ee87fbf2df395017aadf7aeccc
3
+ metadata.gz: 56fcb30522c5c040911bbfc58f2f6e522aa5983f09b09d76cad1e60c8bd2efdd
4
+ data.tar.gz: aeec9a44afdf74ea1d21e9f6b4bb548f12c22f7db55fa6470b478372ba7efcb5
5
5
  SHA512:
6
- metadata.gz: 371db2b5ab6ac40992b65373f2f06a269f022bd6c269c1da24ce26cb1f9c1b7b23049b9994403189d66ea6cf5d56160b2ac452679728c1ace52c295bbb64d4d3
7
- data.tar.gz: 07bdd0405cb1903d7eaf5508d963ef8fa89ed57ad30bfc8023b831c1146d7060a60cf95b1b1cc13a1518e71119cfa76df4ea4f9666c4cb3eb86e41821d7dd5d1
6
+ metadata.gz: a98ee53e368aefbfc98cb99f8f4164c4e43d0e3c0be8e06c04cf39f48d4b78edf4ef5afaec4bdf94bd341121e0616c38f1ca9419eed8ae530fd395c5a75fd2b6
7
+ data.tar.gz: 8c17f74141875921e42b6e8972d37c9c3e53d81646223e83a647c6d5e1f2a14acde33da7ff00b4f80c88a3ffe411378daacbf8580fd44f75efde2a510f971297
data/README.md CHANGED
@@ -178,6 +178,12 @@ which are granted to be safe and stable.
178
178
 
179
179
  * `mumuki.bridge.Laboratory`
180
180
  * `.runTests`
181
+ * `mumuki.editor`
182
+ * `formatContent`
183
+ * `reset`
184
+ * `toggleFullscreen`
185
+ * `mumuki.elipsis`
186
+ * `replaceHtml`
181
187
  * `mumuki.kids`
182
188
  * `registerBlocksAreaScaler`
183
189
  * `registerStateScaler`
@@ -185,6 +191,9 @@ which are granted to be safe and stable.
185
191
  * `scaleBlocksArea`
186
192
  * `scaleState`
187
193
  * `showResult`
194
+ * `mumuki.renderers`
195
+ * `SpeechBubbleRenderer`
196
+ * `renderSpeechBubbleResultItem`
188
197
  * `mumuki.locale`
189
198
  * `mumuki.MultipleScenarios`
190
199
  * `scenarios`
@@ -200,22 +209,29 @@ which are granted to be safe and stable.
200
209
 
201
210
  ### Bridge Response Format
202
211
 
203
- ```json
212
+ ```javascript
204
213
  {
205
- "status": "failed",
206
- "guide_finished_by_solution": false,
207
- "class_for_progress_list_item":"progress-list-item text-center danger active",
208
- "html":"...",
209
- "title_html":"...",
210
- "button_html":"...",
211
- "expectations_html":"...",
212
- "remaining_attempts_html":null,
213
- "test_results":[
214
- {
215
- "title":null,
216
- "status":"failed",
217
- "result":"..."
218
- }
214
+ "status": "passed|passed_with_warnings|failed",
215
+ "guide_finished_by_solution": "boolean",
216
+ "class_for_progress_list_item": "string",
217
+ "html": "string",
218
+ "remaining_attempts_html": "string" ,
219
+ "title_html": "string", // kids-only
220
+ "button_html": "string", // kids-only
221
+ "expectations": [ // kids-only
222
+ {
223
+ "status": "passed|failed",
224
+ "explanation": "string"
225
+ }
226
+ ],
227
+ "tips": [ "string" ], // kids-only
228
+ "test_results": [ // kids-only
229
+ {
230
+ "title": "string",
231
+ "status": "passed|failed",
232
+ "result": "string",
233
+ "summary": "string"
234
+ }
219
235
  ]
220
236
  }
221
237
  ```
@@ -463,7 +479,7 @@ POST /organization/:id/courses/
463
479
 
464
480
  ```json
465
481
  {
466
- "name":"....",
482
+ "name": "....",
467
483
  }
468
484
  ```
469
485
 
@@ -539,7 +555,7 @@ Sample response body:
539
555
  ```json
540
556
  {
541
557
  "organizations": [
542
- { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url":"http://..." },
558
+ { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url": "http://..." },
543
559
  { "name": "alcal", "contact_email": "b@b.com", "locale": "en-US", "login_methods": ["facebook", "github"], "books": ["book"], "public": false }
544
560
  ]
545
561
  }
@@ -555,7 +571,7 @@ get /organizations/:name
555
571
  Sample response body:
556
572
 
557
573
  ```json
558
- { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url":"http://..." }
574
+ { "name": "academy", "contact_email": "a@a.com", "locale": "es-AR", "login_methods": ["facebook"], "books": ["libro"], "public": true, "logo_url": "http://..." }
559
575
  ```
560
576
  **Minimal permission**: `janitor` of the organization.
561
577
 
@@ -23,6 +23,14 @@ var mumuki = mumuki || {};
23
23
  })
24
24
  }
25
25
 
26
+ function formatContent() {
27
+ mumuki.page.editors.each(function (_, editor) {
28
+ editor.setSelection({line: 0, ch: 0}, {line: editor.lineCount()})
29
+ editor.indentSelection("smart")
30
+ editor.setSelection({line: 0})
31
+ });
32
+ }
33
+
26
34
  function toggleFullscreen() {
27
35
  $('body').toggleClass('fullscreen');
28
36
  $('.editor-resize .fa-stack-1x').toggleClass('fa-expand').toggleClass('fa-compress');
@@ -61,7 +69,9 @@ var mumuki = mumuki || {};
61
69
  }
62
70
 
63
71
  mumuki.editor = mumuki.editor || {};
72
+ mumuki.editor.reset = resetEditor;
64
73
  mumuki.editor.toggleFullscreen = toggleFullscreen;
74
+ mumuki.editor.formatContent = formatContent;
65
75
  mumuki.editor.indentWithSpaces = indentWithSpaces;
66
76
  mumuki.editor.syncContent = syncContent;
67
77
 
@@ -75,12 +85,19 @@ var mumuki = mumuki || {};
75
85
  updateCodeMirrorLanguage();
76
86
  onSelectUpdateCodeMirror();
77
87
 
78
- $('.editor-reset').click(function () {
79
- resetEditor();
88
+ $('.editor-reset').click(function (event) {
89
+ event.stopPropagation();
90
+ const selection = confirm(this.getAttribute('data-confirm'));
91
+ if(selection) resetEditor();
80
92
  });
93
+
81
94
  $('.editor-resize').click(function () {
82
95
  toggleFullscreen();
83
96
  });
97
+
98
+ $('.editor-format').click(function (){
99
+ formatContent();
100
+ });
84
101
  });
85
102
 
86
103
  }(mumuki));
@@ -0,0 +1,31 @@
1
+ // This module defines three client-side-only special sections, and allows them to be replaced
2
+ // by adding the `mu-elipsis` class, or by calling `mumuki.elipsis()`:
3
+ //
4
+ // * <elipsis-for-student@ ...code... @elipsis-for-student> : replaces code with an elipsis
5
+ // * <hidden-for-student@ ...code... @hidden-for-student> : completely hides code
6
+ // * <description-for-student[...text...]@ ...code... @description-for-student> : replaces code a message sourrounded by elipsis
7
+ //
8
+ //
9
+ // This module assumes the strings are already markdown-like escaped code strings, not plain code
10
+ (function (mumuki) {
11
+
12
+ function elipsis(code) {
13
+ return code
14
+ .replace(/&lt;elipsis-for-student@[\s\S]*?@elipsis-for-student&gt;/g, ' ... ')
15
+ .replace(/&lt;hidden-for-student@[\s\S]*?@hidden-for-student&gt;/g, '')
16
+ .replace(/&lt;description-for-student\[([^\]]*)\]@[\s\S]*?@description-for-student&gt;/g, ' ... $1 ... ');
17
+ }
18
+
19
+ mumuki.elipsis = elipsis;
20
+ mumuki.elipsis.replaceHtml = () => {
21
+ let $elipsis = $('.mu-elipsis');
22
+ $elipsis.each((it, e) => {
23
+ let $e = $(e);
24
+ $e.html(mumuki.elipsis($e.html()));
25
+ })
26
+ };
27
+
28
+ mumuki.load(() => {
29
+ mumuki.elipsis.replaceHtml();
30
+ });
31
+ })(mumuki);
@@ -0,0 +1,17 @@
1
+ var mumuki = mumuki || {};
2
+
3
+ (function (mumuki) {
4
+ // When using Turbolinks, intervals loaded inside <body> aren't destroyed on page changes
5
+ // Use this function instead if you want the behaviour of a regular setInterval
6
+ mumuki.setInterval = function (intervalFunction, milliseconds) {
7
+ const interval = setInterval.apply(this, [intervalFunction, milliseconds]);
8
+
9
+ // Using one to avoid calling clearInterval on every page chance.
10
+ $(document).one('turbolinks:before-cache turbolinks:before-render', function () {
11
+ clearInterval(interval);
12
+ });
13
+
14
+ return interval;
15
+ }.bind(this);
16
+
17
+ }(mumuki));
@@ -169,28 +169,17 @@ mumuki.load(function () {
169
169
  $bubble.find('.mu-kids-character-speech-bubble-failed').hide();
170
170
  $bubble.find('.mu-kids-discussion-link').remove();
171
171
  Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
172
- mumuki.kids._getOverlay().hide();
172
+ mumuki.kids._getOverlay().hide()
173
173
  },
174
174
 
175
175
  _showMessageOnCharacterBubble: function (data) {
176
- var $bubble = mumuki.kids._getCharacterBubble();
177
- $bubble.find('.mu-kids-character-speech-bubble-tabs').hide();
178
- $bubble.find('.mu-kids-character-speech-bubble-normal').hide();
179
- $bubble.find('.mu-kids-character-speech-bubble-failed').show().html(data.title_html);
180
- $bubble.addClass(data.status);
181
- if (data.status === 'passed_with_warnings') {
182
- $bubble.find('.mu-kids-character-speech-bubble-failed').append(data.expectations_html);
183
- }
184
- if (this._shouldDisplayDiscussionsLink(data.status)) {
185
- $bubble.append(discussionsLinkHtml);
186
- }
176
+ const renderer = new mumuki.renderers.SpeechBubbleRenderer(mumuki.kids._getCharacterBubble());
177
+ renderer.setDiscussionsLinkHtml(discussionsLinkHtml);
178
+ renderer.setResponseData(data);
179
+ renderer.render();
187
180
  mumuki.kids._getOverlay().show();
188
181
  },
189
182
 
190
- _shouldDisplayDiscussionsLink: function (status) {
191
- return ['failed', 'passed_with_warnings'].some(it => it === status);
192
- },
193
-
194
183
  _showOnSuccessPopup: function (data) {
195
184
  mumuki.kids._updateSubmissionResult(data.html);
196
185
  mumuki.presenterCharacter.playAnimation('success_l', mumuki.kids._getCharacterImage());
@@ -313,7 +302,7 @@ mumuki.load(function () {
313
302
  });
314
303
 
315
304
  if (paragraphCount > 1) {
316
- nextSpeechBlinking = setInterval(() => $nextSpeech.fadeTo('slow', 0.1).fadeTo('slow', 1.0), 1000);
305
+ nextSpeechBlinking = mumuki.setInterval(() => $nextSpeech.fadeTo('slow', 0.1).fadeTo('slow', 1.0), 1000);
317
306
  }
318
307
 
319
308
  $nextSpeech.click(showNextParagraph);
@@ -45,7 +45,7 @@ mumuki.load(function () {
45
45
  });
46
46
  },
47
47
  setMessagesInterval: function () {
48
- setInterval(Chat.getMessages, 60000);
48
+ mumuki.setInterval(Chat.getMessages, 60000);
49
49
  },
50
50
  submitMessagesForm: function (url, readUrl, errorUrl) {
51
51
  var $container = $('.mu-view-messages');
@@ -0,0 +1,99 @@
1
+ ((mumuki)=> {
2
+
3
+ function renderSpeechBubbleResultItem(item) {
4
+ return `
5
+ <div class="results-item">
6
+ <ul class="results-list">
7
+ <li>${item}</li>
8
+ </ul>
9
+ </div>`;
10
+ }
11
+
12
+ // A mumuki.renderers.SpeechBubbleRenderer allows to configure a kids speech bubble
13
+ // with the data of a test response from bridge
14
+ class SpeechBubbleRenderer {
15
+ constructor($bubble) {
16
+ this.$bubble = $bubble;
17
+ this.$failedArea = $bubble.find('.mu-kids-character-speech-bubble-failed');
18
+ }
19
+
20
+ _chooseResultItem() {
21
+ if (this._responseStatus() !== 'passed' && this._hasTips()) {
22
+ this._appendFirstTip()
23
+ } else if (this._responseStatus() === 'failed') {
24
+ this._appendFirstFailedTestResultSummary();
25
+ } else if (this._responseStatus() === 'passed_with_warnings') {
26
+ this._appendFirstExpectationResult();
27
+ }
28
+ }
29
+
30
+ _appendFirstFailedTestResultSummary() {
31
+ const failedTestResult = this._failedTestResults()[0]
32
+ if (failedTestResult && failedTestResult.summary) {
33
+ this._appendResultItem(mumuki.renderers.renderSpeechBubbleResultItem(failedTestResult.summary));
34
+ }
35
+ }
36
+
37
+ _appendFirstExpectationResult() {
38
+ this._appendResultItem(mumuki.renderers.renderSpeechBubbleResultItem(this.responseData.expectations[0].explanation));
39
+ }
40
+
41
+ _appendFirstTip() {
42
+ this._appendResultItem(mumuki.renderers.renderSpeechBubbleResultItem(this.responseData.tips[0]));
43
+ }
44
+
45
+ _appendResultItem(item) {
46
+ this._addClass('with-result-item');
47
+ this.$failedArea.append(item);
48
+ }
49
+
50
+ _addClass(klass) {
51
+ this.$bubble.addClass(klass);
52
+ }
53
+
54
+ _appendDiscussionsLinkHtml() {
55
+ if (this._shouldDisplayDiscussionsLink()) {
56
+ this.$bubble.append(this.discussionsLinkHtml);
57
+ }
58
+ }
59
+
60
+ _shouldDisplayDiscussionsLink() {
61
+ return ['failed', 'passed_with_warnings'].some(it => it === this._responseStatus());
62
+ }
63
+
64
+ _responseStatus() {
65
+ return this.responseData.status;
66
+ }
67
+
68
+ _hasTips() {
69
+ return this.responseData.tips && this.responseData.tips.length
70
+ }
71
+
72
+ _failedTestResults() {
73
+ return this.responseData.test_results.filter((it) => it.status === 'failed');
74
+ }
75
+
76
+ setDiscussionsLinkHtml(discussionsLinkHtml) {
77
+ this.discussionsLinkHtml = discussionsLinkHtml;
78
+ }
79
+
80
+ setResponseData(responseData) {
81
+ this.responseData = responseData;
82
+ }
83
+
84
+ // Entry point of the renderer. It just updates the UI, not returning anything
85
+ // Configure the renderer with `setDiscussionsLinkHtml` and `setResponseData` first.
86
+ render() {
87
+ this.$bubble.find('.mu-kids-character-speech-bubble-tabs').hide();
88
+ this.$bubble.find('.mu-kids-character-speech-bubble-normal').hide();
89
+ this.$failedArea.show().html(this.responseData.title_html);
90
+ this._addClass(this._responseStatus());
91
+ this._chooseResultItem();
92
+ this._appendDiscussionsLinkHtml();
93
+ }
94
+ }
95
+
96
+ mumuki.renderers = mumuki.renderers || {};
97
+ mumuki.renderers.SpeechBubbleRenderer = SpeechBubbleRenderer;
98
+ mumuki.renderers.renderSpeechBubbleResultItem = renderSpeechBubbleResultItem;
99
+ })(mumuki)
@@ -8,7 +8,7 @@ var mumuki = mumuki || {};
8
8
  var duration = moment.duration(diffTime, 'milliseconds');
9
9
  var intervalDuration = 1000;
10
10
 
11
- var interval = setInterval(function () {
11
+ var interval = mumuki.setInterval(function () {
12
12
  duration = moment.utc(duration - intervalDuration);
13
13
  if(duration.valueOf() <= 0) {
14
14
  clearInterval(interval);
@@ -6,6 +6,7 @@ $da-font-path: asset-path('assets');
6
6
  @import "codemirror/codemirror.min";
7
7
  @import "codemirror/show-hint.min";
8
8
  @import "application/vendor";
9
+ @import "application/locked";
9
10
  @import "application/tooltip";
10
11
  @import "application/hovers";
11
12
  @import "application/mixins";
@@ -107,10 +107,6 @@ h1 {
107
107
  margin-bottom: 20px;
108
108
  }
109
109
 
110
- .chapter {
111
- margin: 35px 0;
112
- }
113
-
114
110
  pre {
115
111
  font-size: 14px;
116
112
  line-height: 1.4;
@@ -0,0 +1,29 @@
1
+ .chapter-container {
2
+ position: relative;
3
+ }
4
+
5
+ .chapter {
6
+ position: relative;
7
+
8
+ margin: 35px 0;
9
+ padding-bottom: 15px;
10
+
11
+ &.mu-locked {
12
+ opacity: 20%;
13
+
14
+ user-select: none;
15
+ pointer-events: none;
16
+ }
17
+ }
18
+
19
+ .mu-lock {
20
+ position: absolute;
21
+
22
+ width: 100%;
23
+ height: 100%;
24
+
25
+ transform: translateY(20%);
26
+
27
+ top: 0px;
28
+ left: 0px;
29
+ }
@@ -13,25 +13,6 @@ $multifile-inactive-tab-border-color: #ECF0F1;
13
13
  max-height: none;
14
14
  }
15
15
 
16
- .submission-reset {
17
- padding: 5px;
18
- cursor: pointer;
19
- }
20
-
21
- .editor-resize {
22
- position: absolute;
23
- padding: 5px;
24
- cursor: pointer;
25
- z-index: 10;
26
- top: 0;
27
- right: 0;
28
- font-size: 0.5em;
29
- &.multiple-files {
30
- top: 43px;
31
- }
32
- }
33
-
34
-
35
16
  body:not(.fullscreen) {
36
17
  .CodeMirror-wrap,
37
18
  .CodeMirror-scroll {
@@ -69,10 +50,6 @@ body.fullscreen {
69
50
  overflow-y: scroll;
70
51
  overflow-x: auto;
71
52
  }
72
- .submission-reset,
73
- .editor-resize {
74
- margin-right: 15px;
75
- }
76
53
  }
77
54
  }
78
55