mumuki-laboratory 8.1.1 → 8.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/mumuki_laboratory/application/bridge.js +1 -1
  3. data/app/assets/javascripts/mumuki_laboratory/application/button.js +2 -2
  4. data/app/assets/javascripts/mumuki_laboratory/application/codemirror-builder.js +2 -2
  5. data/app/assets/javascripts/mumuki_laboratory/application/codemirror.js +5 -5
  6. data/app/assets/javascripts/mumuki_laboratory/application/console.js +2 -2
  7. data/app/assets/javascripts/mumuki_laboratory/application/discussions.js +7 -7
  8. data/app/assets/javascripts/mumuki_laboratory/application/editors.js +1 -1
  9. data/app/assets/javascripts/mumuki_laboratory/application/elipsis.js +1 -1
  10. data/app/assets/javascripts/mumuki_laboratory/application/events.js +2 -2
  11. data/app/assets/javascripts/mumuki_laboratory/application/exercise.js +2 -2
  12. data/app/assets/javascripts/mumuki_laboratory/application/gamification.js +13 -3
  13. data/app/assets/javascripts/mumuki_laboratory/application/inputs.js +1 -1
  14. data/app/assets/javascripts/mumuki_laboratory/application/kids.js +4 -4
  15. data/app/assets/javascripts/mumuki_laboratory/application/kindergarten.js +7 -7
  16. data/app/assets/javascripts/mumuki_laboratory/application/messages.js +6 -6
  17. data/app/assets/javascripts/mumuki_laboratory/application/mu-modal-carrousel.js +1 -1
  18. data/app/assets/javascripts/mumuki_laboratory/application/multiple-choice.js +1 -1
  19. data/app/assets/javascripts/mumuki_laboratory/application/multiple-files.js +3 -3
  20. data/app/assets/javascripts/mumuki_laboratory/application/multiple-scenarios.js +1 -1
  21. data/app/assets/javascripts/mumuki_laboratory/application/pin.js +1 -1
  22. data/app/assets/javascripts/mumuki_laboratory/application/primary.js +1 -1
  23. data/app/assets/javascripts/mumuki_laboratory/application/progress.js +1 -1
  24. data/app/assets/javascripts/mumuki_laboratory/application/results-renderer.js +1 -1
  25. data/app/assets/javascripts/mumuki_laboratory/application/speech-bubble-renderer.js +4 -4
  26. data/app/assets/javascripts/mumuki_laboratory/application/submission.js +2 -2
  27. data/app/assets/javascripts/mumuki_laboratory/application/submissions-store.js +3 -3
  28. data/app/assets/javascripts/mumuki_laboratory/application/sync-mode.js +2 -2
  29. data/app/assets/javascripts/mumuki_laboratory/application/timer.js +1 -1
  30. data/app/assets/stylesheets/mumuki_laboratory/application/_layout.scss +7 -7
  31. data/app/controllers/concerns/with_user_discussion_validation.rb +6 -0
  32. data/app/controllers/discussions_controller.rb +0 -6
  33. data/app/helpers/links_helper.rb +2 -2
  34. data/app/views/layouts/_copyright.html.erb +1 -1
  35. data/app/views/layouts/application.html.erb +16 -14
  36. data/app/views/layouts/embedded.html.erb +14 -11
  37. data/lib/mumuki/laboratory/locales/es-CL.yml +1 -1
  38. data/lib/mumuki/laboratory/locales/es.yml +2 -2
  39. data/lib/mumuki/laboratory/locales/pt.yml +1 -1
  40. data/lib/mumuki/laboratory/version.rb +1 -1
  41. data/spec/controllers/discussions_controller_spec.rb +19 -0
  42. data/spec/dummy/db/schema.rb +2 -1
  43. metadata +102 -102
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5feda4ed95a66abdfc68c218f1d2b5752fe6fdd8d8da0a18cc7c968d90550bbd
4
- data.tar.gz: '080a983c6f384a8568ba2c8e7f092fcab9afe2a82b728bdfcc1e66fb8256377f'
3
+ metadata.gz: d366cf0d6d349759281213746e2c6a6f1a998db2d07efa9dc45b02480487108e
4
+ data.tar.gz: 0c890e15fa8b8f3164372b7c8f6844b17e85ded1686bb1c4d0947d9a08b7cd6a
5
5
  SHA512:
6
- metadata.gz: f95a1a2057a7946e2f26589a50076ec7e3c0e3d538a3feeb75da6a7cd1e030598a048dbb2e8918f1dcf39aa6565bc22fec237c66c88ee6842503c4d0bf94947c
7
- data.tar.gz: 006504d33b8cb9ea871cff01be16fbc9f4b9f89e8cab63f11e1bfcc41cb4384cf1aff2e6e501e053d9279a1dd3a2009ae0b6a5c242012ab311b0a1e1ed9702a5
6
+ metadata.gz: 4ff7d88d695024cbd9feac650c31b77055291f280791b262ddf6c6477f54a2e7ef0d858bbe4668594e88b755dd5ab1934ac7b8acc045acf02360ddae9dca8d7f
7
+ data.tar.gz: 555cfdee07fa9e97d62507360fda991dfd6bf16668093d6af44ab6f6ee79dcf22ab57aaf08d49a2e434767bd3a7dadfb8316321b22d3efa0e0b0f19f5ad7c1e0
@@ -113,7 +113,7 @@ 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.progressListItemClassForStatus(result.status, true);
117
117
  return result;
118
118
  }
119
119
  }
@@ -36,7 +36,7 @@ mumuki.Button = class {
36
36
  e.preventDefault();
37
37
  main();
38
38
  };
39
- this.$button.on('click', this.main)
39
+ this.$button.on('click', this.main);
40
40
  }
41
41
 
42
42
  // ==============
@@ -80,7 +80,7 @@ mumuki.Button = class {
80
80
 
81
81
  this.enable();
82
82
 
83
- this.$button.on('click', this.main)
83
+ this.$button.on('click', this.main);
84
84
  }
85
85
 
86
86
  // =============
@@ -38,7 +38,7 @@
38
38
  mumuki.editor.toggleFullscreen();
39
39
  },
40
40
  'Tab': function (cm) {
41
- mumuki.editor.indentWithSpaces(cm)
41
+ mumuki.editor.indentWithSpaces(cm);
42
42
  }
43
43
  }
44
44
  });
@@ -53,7 +53,7 @@
53
53
  'Cmd-Enter': submitMessage,
54
54
  'Ctrl-Enter': submitMessage,
55
55
  'Tab': function (cm) {
56
- mumuki.editor.indentWithSpaces(cm)
56
+ mumuki.editor.indentWithSpaces(cm);
57
57
  }
58
58
  }
59
59
  });
@@ -23,14 +23,14 @@ mumuki.page.editors = [];
23
23
  function resetEditor() {
24
24
  mumuki.page.dynamicEditors.forEach(function (e) {
25
25
  setDefaultContent(e, $('#default_content').val());
26
- })
26
+ });
27
27
  }
28
28
 
29
29
  function formatContent() {
30
30
  mumuki.page.editors.each(function (_, editor) {
31
- editor.setSelection({line: 0, ch: 0}, {line: editor.lineCount()})
32
- editor.indentSelection("smart")
33
- editor.setSelection({line: 0})
31
+ editor.setSelection({line: 0, ch: 0}, {line: editor.lineCount()});
32
+ editor.indentSelection("smart");
33
+ editor.setSelection({line: 0});
34
34
  });
35
35
  }
36
36
 
@@ -56,7 +56,7 @@ mumuki.page.editors = [];
56
56
  if (language !== undefined) {
57
57
  mumuki.page.dynamicEditors.forEach(function (e) {
58
58
  setEditorLanguage(e, language);
59
- })
59
+ });
60
60
  }
61
61
  }
62
62
 
@@ -32,7 +32,7 @@
32
32
  function clearConsole() {
33
33
  $('.jquery-console-message-error').remove();
34
34
  $('.jquery-console-message-value').remove();
35
- $('.jquery-console-prompt-box:not(:last)').remove()
35
+ $('.jquery-console-prompt-box:not(:last)').remove();
36
36
  }
37
37
 
38
38
  class QueryConsole {
@@ -134,7 +134,7 @@
134
134
  url: self._requestUrl,
135
135
  type: 'POST',
136
136
  data: self._requestData
137
- })
137
+ });
138
138
  }
139
139
  get _requestUrl() {
140
140
  return this.console.endpoint;
@@ -34,33 +34,33 @@ mumuki.load(() => {
34
34
  },
35
35
  token: new mumuki.CsrfToken(),
36
36
  tokenRequest: function (data) {
37
- return $.ajax(Forum.token.newRequest(data))
37
+ return $.ajax(Forum.token.newRequest(data));
38
38
  },
39
39
  discussionPost: function (url) {
40
40
  return Forum.tokenRequest({
41
41
  url: url,
42
42
  method: 'POST',
43
43
  xhrFields: {withCredentials: true}
44
- })
44
+ });
45
45
  },
46
46
  discussionSubscription: function (url) {
47
- Forum.discussionPostAndToggle(url, $subscriptionSpans)
47
+ Forum.discussionPostAndToggle(url, $subscriptionSpans);
48
48
  },
49
49
  discussionUpvote: function (url) {
50
- Forum.discussionPostAndToggle(url, $upvoteSpans)
50
+ Forum.discussionPostAndToggle(url, $upvoteSpans);
51
51
  },
52
52
  discussionPostAndToggle: function (url, elem) {
53
- Forum.discussionPost(url).done(Forum.toggleButton(elem))
53
+ Forum.discussionPost(url).done(Forum.toggleButton(elem));
54
54
  },
55
55
  discussionMessageToggleApprove: function (url, elem) {
56
56
  Forum.discussionPost(url).done(function () {
57
57
  elem.toggleClass("selected");
58
- })
58
+ });
59
59
  },
60
60
  discussionMessageToggleNotActuallyAQuestion: function (url, elem) {
61
61
  Forum.discussionPost(url).done(function () {
62
62
  elem.toggleClass("selected");
63
- })
63
+ });
64
64
  },
65
65
  discussionsToggleCheckbox: function (elem) {
66
66
  const key = elem.attr('name');
@@ -99,6 +99,6 @@ mumuki.editors = {
99
99
  * @param {CustomEditorSource} source
100
100
  */
101
101
  addCustomSource(source) {
102
- mumuki.CustomEditor.addSource(source)
102
+ mumuki.CustomEditor.addSource(source);
103
103
  }
104
104
  };
@@ -21,7 +21,7 @@ mumuki.elipsis = (() => {
21
21
  $elipsis.each((it, e) => {
22
22
  let $e = $(e);
23
23
  $e.html(mumuki.elipsis($e.html()));
24
- })
24
+ });
25
25
  };
26
26
 
27
27
  mumuki.load(() => {
@@ -34,7 +34,7 @@ mumuki.events = {
34
34
  */
35
35
  fire(eventName, value = null) {
36
36
  if (this._handlers[eventName]) {
37
- this._handlers[eventName].forEach(it => it(value))
37
+ this._handlers[eventName].forEach(it => it(value));
38
38
  }
39
39
  },
40
40
 
@@ -48,4 +48,4 @@ mumuki.events = {
48
48
  this._handlers[eventName] = [];
49
49
  }
50
50
  }
51
- }
51
+ };
@@ -63,6 +63,6 @@ mumuki.exercise = {
63
63
  this._current = null;
64
64
  }
65
65
  }
66
- }
66
+ };
67
67
 
68
- mumuki.load(() => mumuki.exercise.load())
68
+ mumuki.load(() => mumuki.exercise.load());
@@ -108,12 +108,22 @@ mumuki.gamification = (() => {
108
108
  }
109
109
 
110
110
  updateLevel() {
111
- const $muLevelProgress = $('#mu-level-progress');
112
-
113
111
  $('#mu-solve-more-exercises span').text(this.exercisesToNextLevel());
114
112
  $('.mu-level-number').html(this.currentLevel());
115
- $('.mu-level-tooltip').attr("title", (_, value) => `${value} ${this.currentLevel()}`);
116
113
 
114
+ this.updateTooltip();
115
+ this.animateProgressIfAny();
116
+ }
117
+
118
+ updateTooltip() {
119
+ const $muLevelTooltip = $('.mu-level-tooltip');
120
+
121
+ $muLevelTooltip.attr("data-original-title", `${$muLevelTooltip.attr("level")} ${this.currentLevel()}`);
122
+ $muLevelTooltip.attr("title", "");
123
+ }
124
+
125
+ animateProgressIfAny() {
126
+ const $muLevelProgress = $('#mu-level-progress');
117
127
  if (this.currentLevelProgress() === 0) {
118
128
  $muLevelProgress.attr("display", "none");
119
129
  }
@@ -7,7 +7,7 @@ mumuki.onInputsReady = (() => {
7
7
  if ($(inputsSelector).length === 0) return;
8
8
 
9
9
  callback(event);
10
- })
10
+ });
11
11
  }
12
12
 
13
13
  return onInputsReady;
@@ -61,11 +61,11 @@ mumuki.Kids = class {
61
61
  // ==================
62
62
 
63
63
  _showSuccessPopup() {
64
- this._mustImplementThisMethod()
64
+ this._mustImplementThisMethod();
65
65
  }
66
66
 
67
67
  _showFailurePopup() {
68
- this._mustImplementThisMethod()
68
+ this._mustImplementThisMethod();
69
69
  }
70
70
 
71
71
  // ====================
@@ -141,7 +141,7 @@ mumuki.Kids = class {
141
141
  // ============
142
142
 
143
143
  _mustImplementThisMethod() {
144
- throw new Error('TODO: implement method')
144
+ throw new Error('TODO: implement method');
145
145
  }
146
146
 
147
147
  // ============
@@ -214,4 +214,4 @@ mumuki.Kids = class {
214
214
  $blockSvg.height($blocks.height());
215
215
  }
216
216
 
217
- }
217
+ };
@@ -103,27 +103,27 @@ mumuki.load(() => {
103
103
  this._action('play', 'stop', true, (speech) => {
104
104
  mumuki.presenterCharacter.playAnimation('talk', mumuki.kids.$bubbleCharacterAnimation);
105
105
  speech.speak(msg);
106
- })
106
+ });
107
107
  },
108
108
  stop() {
109
- this._action('stop', 'play', false, (speech) => speech.cancel())
109
+ this._action('stop', 'play', false, (speech) => speech.cancel());
110
110
  },
111
111
  _action(add, remove, isPlaying, callback) {
112
112
  callback(window.speechSynthesis);
113
- const $button = $('.mu-kindergarten-play-description')
113
+ const $button = $('.mu-kindergarten-play-description');
114
114
  $button.find(`.mu-kindergarten-${add}`).addClass('hidden');
115
115
  $button.find(`.mu-kindergarten-${remove}`).removeClass('hidden');
116
116
  this._isPlaying = isPlaying;
117
117
  },
118
118
  verifyBrowserSupport() {
119
119
  if (!window.speechSynthesis) {
120
- const $button = $('.mu-kindergarten-play-description')
120
+ const $button = $('.mu-kindergarten-play-description');
121
121
  $button.prop('disabled', true);
122
122
  $button.css('cursor', 'not-allowed');
123
- this._action('play', 'stop', false)
123
+ this._action('play', 'stop', false);
124
124
  }
125
125
  }
126
- }
126
+ };
127
127
 
128
128
  }
129
129
 
@@ -143,7 +143,7 @@ mumuki.load(() => {
143
143
  const $hintMedia = $('.mu-kindergarten-hint-media');
144
144
  if (!$hintMedia.get(0)) $button.addClass('hidden');
145
145
  },
146
- }
146
+ };
147
147
  }
148
148
 
149
149
  get context() {
@@ -1,7 +1,7 @@
1
1
  mumuki.load(() => {
2
2
  var Chat = {
3
3
  $body: function () {
4
- return $('body')
4
+ return $('body');
5
5
  },
6
6
  $newMessageModal: function () {
7
7
  return $('.new-message-modal');
@@ -18,7 +18,7 @@ mumuki.load(() => {
18
18
  $('.notifications-box').toggleClass('notifications-box-empty', !data.has_messages);
19
19
  $('.pending-messages-filter').removeClass('pending-messages-filter');
20
20
  $('button.btn-submit').removeClass('disabled');
21
- $('.pending-messages-text').remove()
21
+ $('.pending-messages-text').remove();
22
22
  },
23
23
  readMessages: function (url) {
24
24
  Chat.tokenRequest({
@@ -26,10 +26,10 @@ mumuki.load(() => {
26
26
  method: 'POST',
27
27
  success: Chat.setMessages,
28
28
  xhrFields: {withCredentials: true}
29
- })
29
+ });
30
30
  },
31
31
  tokenRequest: function (data) {
32
- $.ajax(Chat.token.newRequest(data))
32
+ $.ajax(Chat.token.newRequest(data));
33
33
  },
34
34
  getMessages: function () {
35
35
  if ($('.badge-messages').length == 0) {
@@ -74,7 +74,7 @@ mumuki.load(() => {
74
74
  success: success,
75
75
  error: error,
76
76
  xhrFields: {withCredentials: true}
77
- })
77
+ });
78
78
  },
79
79
  openNewMessageModal: function () {
80
80
  Chat.$newMessageModal().modal({backdrop: false, keyboard: false});
@@ -89,5 +89,5 @@ mumuki.load(() => {
89
89
  Chat.setMessagesInterval();
90
90
  mumuki.Chat = Chat;
91
91
 
92
- })
92
+ });
93
93
 
@@ -41,7 +41,7 @@ mumuki.ModalCarrousel = (() => {
41
41
 
42
42
  _hidePreviousButtonIfFirstSlide() {
43
43
  const $prev = $('.mu-kids-modal-button.mu-previous');
44
- this._addClassIf($prev, 'hidden', () => this._activeSlide().is(':first-child'))
44
+ this._addClassIf($prev, 'hidden', () => this._activeSlide().is(':first-child'));
45
45
  }
46
46
 
47
47
  _showFirstSlide() {
@@ -1,7 +1,7 @@
1
1
  mumuki.load(() => {
2
2
  function dumpChoices(_evt) {
3
3
  var indexes = $('.solution-choice:checked').map(function () {
4
- return $(this).data('index')
4
+ return $(this).data('index');
5
5
  }).get().join(':');
6
6
  $('#solution_content').attr('value', indexes);
7
7
  }
@@ -103,11 +103,11 @@ mumuki.load(() => {
103
103
  }
104
104
 
105
105
  get highlightModes() {
106
- return this._getDataFromHiddenInput('#highlight-modes')
106
+ return this._getDataFromHiddenInput('#highlight-modes');
107
107
  }
108
108
 
109
109
  get locales() {
110
- return this._getDataFromHiddenInput('#multifile-locales')
110
+ return this._getDataFromHiddenInput('#multifile-locales');
111
111
  }
112
112
 
113
113
  setUpAddFile() {
@@ -131,7 +131,7 @@ mumuki.load(() => {
131
131
 
132
132
  this._setVisibility(this._addFileButton, filesCount < this.MAX_TABS);
133
133
  this.files.toArray().forEach(file => {
134
- this._setVisibility(file.deleteButton, file.name !== this.mainFile && filesCount > 1)
134
+ this._setVisibility(file.deleteButton, file.name !== this.mainFile && filesCount > 1);
135
135
  });
136
136
  }
137
137
 
@@ -73,7 +73,7 @@ mumuki.MultipleScenarios = (() => {
73
73
  if (this.validScenarioIndex(newScenarioIndex)) {
74
74
  this.setActiveIndex(newScenarioIndex);
75
75
  }
76
- })
76
+ });
77
77
  }
78
78
 
79
79
  createControls () {
@@ -11,5 +11,5 @@ mumuki.pin = (() => {
11
11
  smoothScrollToElement(scrollPin);
12
12
  }
13
13
  }
14
- }
14
+ };
15
15
  })();
@@ -83,7 +83,7 @@ mumuki.load(() => {
83
83
  this._$texts.hide();
84
84
  this.$characterSpeechBubbleNormal.children('.' + $tab.data('target')).show();
85
85
  this._updateSpeechParagraphs();
86
- })
86
+ });
87
87
  }
88
88
  });
89
89
 
@@ -17,7 +17,7 @@ mumuki.progress = (() => {
17
17
  function updateWholeProgressBar(f) {
18
18
  $('.progress-list-item').each((_, it) => {
19
19
  const $anchor = $(it);
20
- $anchor.attr('class', f($anchor))
20
+ $anchor.attr('class', f($anchor));
21
21
  });
22
22
  }
23
23
 
@@ -49,7 +49,7 @@ mumuki.renderers.results = (() => {
49
49
  classForStatus,
50
50
  iconForStatus,
51
51
  progressListItemClassForStatus
52
- }
52
+ };
53
53
  })();
54
54
 
55
55
  /** @deprecated use {@code mumuki.renderers.results.classForStatus} instead */
@@ -20,7 +20,7 @@ mumuki.renderers.speechBubble = (()=> {
20
20
 
21
21
  _chooseResultItem() {
22
22
  if (this._responseStatus() !== 'passed' && this._hasTips()) {
23
- this._appendFirstTip()
23
+ this._appendFirstTip();
24
24
  } else if (this._responseStatus() === 'failed') {
25
25
  this._appendFirstFailedTestResultSummary();
26
26
  } else if (this._responseStatus() === 'passed_with_warnings') {
@@ -29,7 +29,7 @@ mumuki.renderers.speechBubble = (()=> {
29
29
  }
30
30
 
31
31
  _appendFirstFailedTestResultSummary() {
32
- const failedTestResult = this._failedTestResults()[0]
32
+ const failedTestResult = this._failedTestResults()[0];
33
33
  if (failedTestResult && failedTestResult.summary) {
34
34
  this._appendResultItem(mumuki.renderers.renderSpeechBubbleResultItem(failedTestResult.summary));
35
35
  }
@@ -67,7 +67,7 @@ mumuki.renderers.speechBubble = (()=> {
67
67
  }
68
68
 
69
69
  _hasTips() {
70
- return this.responseData.tips && this.responseData.tips.length
70
+ return this.responseData.tips && this.responseData.tips.length;
71
71
  }
72
72
 
73
73
  _failedTestResults() {
@@ -97,7 +97,7 @@ mumuki.renderers.speechBubble = (()=> {
97
97
  return {
98
98
  SpeechBubbleRenderer,
99
99
  renderSpeechBubbleResultItem
100
- }
100
+ };
101
101
  })();
102
102
 
103
103
  /** @deprecated use {@code mumuki.renderers.speechBubble.SpeechBubbleRenderer} instead */
@@ -101,7 +101,7 @@ mumuki.submission = (() => {
101
101
  });
102
102
  mumuki.kids.showResult(data);
103
103
  });
104
- }
104
+ };
105
105
  }
106
106
 
107
107
  /** Processor for non-kids layouts */
@@ -118,7 +118,7 @@ mumuki.submission = (() => {
118
118
  $(document).renderMuComponents();
119
119
  resultsBox.done(data, submitButton);
120
120
  });
121
- }
121
+ };
122
122
  }
123
123
 
124
124
  /** Selects the most appropriate solution processor */
@@ -96,7 +96,7 @@ mumuki.SubmissionsStore = (() => {
96
96
  _keyFor(exerciseId) {
97
97
  return `/exercise/${exerciseId}/submission`;
98
98
  }
99
- };
99
+ }();
100
100
 
101
101
  return SubmissionsStore;
102
102
  })();
@@ -106,5 +106,5 @@ mumuki.load(() => {
106
106
  if (e.detail[0]) {
107
107
  mumuki.SubmissionsStore.clear();
108
108
  }
109
- })
110
- })
109
+ });
110
+ });
@@ -65,11 +65,11 @@ mumuki.syncMode = (() => {
65
65
 
66
66
  /** @type {ClientSyncMode|ServerSyncMode}*/
67
67
  _current: null
68
- }
68
+ };
69
69
  })();
70
70
 
71
71
  mumuki.load(() => {
72
72
  mumuki.syncMode._selectSyncMode();
73
73
  mumuki.syncMode._current.syncProgress();
74
74
  mumuki.syncMode._current.syncEditorContent();
75
- })
75
+ });
@@ -16,5 +16,5 @@ mumuki.startTimer = (() => {
16
16
  }
17
17
  }, intervalDuration);
18
18
  }
19
- return startTimer
19
+ return startTimer;
20
20
  })();
@@ -25,13 +25,13 @@ body {
25
25
  margin-bottom: 110px;
26
26
  }
27
27
 
28
- .footer {
29
- position: absolute;
30
- bottom: 0;
31
- width: 100%;
32
- height: 110px;
33
- .container {
34
- margin-top: 33px;
28
+ .mu-footer {
29
+ &.container {
30
+ margin-top: 45px;
31
+ }
32
+ .mu-footer-terms {
33
+ font-size: 15px;
34
+ text-align: center;
35
35
  }
36
36
  }
37
37
 
@@ -2,12 +2,18 @@ module WithUserDiscussionValidation
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
+ # users are not allowed to access discussions during exams
6
+ before_action :validate_not_blocked_in_forum!
5
7
  # discussions are not enabled for all organizations nor all users
6
8
  before_action :validate_user_can_discuss!
7
9
  end
8
10
 
9
11
  private
10
12
 
13
+ def validate_not_blocked_in_forum!
14
+ raise Mumuki::Domain::BlockedForumError if current_user&.currently_in_exam?
15
+ end
16
+
11
17
  def validate_user_can_discuss!
12
18
  raise Mumuki::Domain::NotFoundError unless current_user&.can_discuss_here?
13
19
  end
@@ -1,8 +1,6 @@
1
1
  class DiscussionsController < ApplicationController
2
2
  include Mumuki::Laboratory::Controllers::Content
3
3
  include WithUserDiscussionValidation
4
- # users are not allowed to access discussions during exams
5
- before_action :validate_not_in_exam!
6
4
 
7
5
  before_action :set_debatable, except: [:subscription]
8
6
  before_action :authenticate!, only: [:update, :create]
@@ -74,8 +72,4 @@ class DiscussionsController < ApplicationController
74
72
  def discussion_filter_params
75
73
  @filter_params ||= params.permit(Discussion.permitted_query_params)
76
74
  end
77
-
78
- def validate_not_in_exam!
79
- raise Mumuki::Domain::BlockedForumError if current_user&.currently_in_exam?
80
- end
81
75
  end
@@ -52,11 +52,11 @@ module LinksHelper
52
52
  end
53
53
 
54
54
  def link_to_profile_terms
55
- link_to t(:terms_and_conditions).downcase, terms_user_path, target: '_blank'
55
+ link_to t(:terms_and_conditions), terms_user_path, target: '_blank'
56
56
  end
57
57
 
58
58
  def link_to_forum_terms
59
- link_to t(:forum_terms).downcase, discussions_terms_path, target: '_blank'
59
+ link_to t(:forum_terms), discussions_terms_path, target: '_blank'
60
60
  end
61
61
 
62
62
  def turbolinks_enable_for(exercise)
@@ -1,2 +1,2 @@
1
- &copy; Copyright 2015-<%= DateTime.now.year %>
1
+ &copy; 2015-<%= DateTime.now.year %>
2
2
  <a href="http://mumuki.org/" class="mu-org-link"><span class="da da-mumuki-circle"></span> Mumuki</a>
@@ -20,7 +20,7 @@
20
20
  <div class="mu-navbar-avatar">
21
21
  <% if current_logged_user? %>
22
22
  <% if in_gamified_context? %>
23
- <i class="fa fa-star fa-fw fa-2x navbar-icon mu-level-tooltip" data-toggle="tooltip" data-placement="bottom" title="<%= t(:level) %>"></i>
23
+ <i class="fa fa-star fa-fw fa-2x navbar-icon mu-level-tooltip" data-toggle="tooltip" data-placement="bottom" level="<%= t(:level) %>"></i>
24
24
  <span class="mu-level-number"></span>
25
25
  <% end %>
26
26
  <div class="dropdown">
@@ -52,30 +52,32 @@
52
52
 
53
53
  <% content_for :footer do %>
54
54
  <footer class="footer">
55
- <div class="<%= exercise_container_type %>">
56
- <hr>
57
-
58
- <div class="row">
59
- <div class="col-md-12">
55
+ <div class="mu-footer <%= exercise_container_type %>">
56
+ <div class="mu-footer-row">
57
+ <div class="mu-footer-authoring">
60
58
  <%= yield :authoring %>
61
59
  </div>
62
60
  </div>
63
61
 
64
- <div id="footer-copyright" class="row">
65
- <div class="col-md-4 text-left">
66
- <p>
67
- <%= render partial: 'layouts/copyright' %>
68
- </p>
62
+ <div class="mu-footer-row">
63
+ <div class="mu-footer-copyright">
64
+ <%= render partial: 'layouts/copyright' %>
69
65
  </div>
70
66
 
71
- <div class="col-md-4 text-center">
72
- <%= login_form.footer_html %>
67
+ <div class="mu-footer-terms">
68
+ <div><%= link_to_profile_terms %></div>
69
+ <% if current_user&.can_discuss_here? %>
70
+ <div><%= link_to_forum_terms %></div>
71
+ <% end %>
73
72
  </div>
74
73
 
75
- <div id="footer-social" class="col-md-4 text-right" lang="en">
74
+ <%= login_form.footer_html %>
75
+
76
+ <div id="footer-social" class="mu-footer-social" lang="en">
76
77
  <%= render partial: 'layouts/social_media' %>
77
78
  </div>
78
79
  </div>
80
+
79
81
  </div>
80
82
  </footer>
81
83
  <% end %>
@@ -1,22 +1,25 @@
1
1
  <% content_for :footer do %>
2
2
  <footer class="footer">
3
- <div class="<%= exercise_container_type %>">
4
- <hr>
5
-
6
- <div class="row">
7
- <div class="col-md-12">
3
+ <div class="mu-footer <%= exercise_container_type %>">
4
+ <div class="mu-footer-row">
5
+ <div class="mu-footer-authoring">
8
6
  <%= yield :authoring %>
9
7
  </div>
10
8
  </div>
11
9
 
12
- <div id="footer-copyright" class="row hidden-xs hidden-sm">
13
- <div class="col-sm-8 text-left">
14
- <p>
15
- <%= render partial: 'layouts/copyright' %>
16
- </p>
10
+ <div class="mu-footer-row">
11
+ <div class="mu-footer-copyright">
12
+ <%= render partial: 'layouts/copyright' %>
13
+ </div>
14
+
15
+ <div class="mu-footer-terms">
16
+ <div><%= link_to_profile_terms %></div>
17
+ <% if current_user&.can_discuss_here? %>
18
+ <div><%= link_to_forum_terms %></div>
19
+ <% end %>
17
20
  </div>
18
21
 
19
- <div id="footer-social" class="col-sm-4 text-right" lang="en">
22
+ <div id="footer-social" class="mu-footer-social" lang="en">
20
23
  <%= render partial: 'layouts/social_media' %>
21
24
  </div>
22
25
  </div>
@@ -104,7 +104,7 @@ es-CL:
104
104
  first_name: Nombre
105
105
  forbidden_explanation: ¿Puede que hayas ingresado con una cuenta incorrecta?
106
106
  format: Dar formato
107
- forum_terms_link: Si tienes alguna duda, consulta las %{terms_link}
107
+ forum_terms_link: Si tienes alguna duda, accede a las %{terms_link}
108
108
  fullscreen: "Pantalla completa"
109
109
  gender: Género
110
110
  get_messages: "Ver mensajes"
@@ -112,8 +112,8 @@ es:
112
112
  first_name: Nombre
113
113
  forbidden_explanation: ¿Puede que hayas ingresado con una cuenta incorrecta?
114
114
  format: Dar formato
115
- forum_terms: Reglas del foro
116
- forum_terms_link: Si tenés alguna duda, consultá las %{terms_link}
115
+ forum_terms: Reglas del espacio de consultas
116
+ forum_terms_link: Si tenés alguna duda, accedé a las %{terms_link}
117
117
  fullscreen: "Pantalla completa"
118
118
  gender: Género
119
119
  get_messages: "Ver mensajes"
@@ -108,7 +108,7 @@ pt:
108
108
  first_name: Nome
109
109
  forbidden_explanation: Você poderia ter entrado com uma conta incorreta?
110
110
  format: Formato
111
- forum_terms: Regras do fórum
111
+ forum_terms: Regras do espaço de consulta
112
112
  forum_terms_link: Se você tiver alguma dúvida, consulte as %{terms_link}
113
113
  fullscreen: Tela completa
114
114
  gender: Gênero
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Laboratory
3
- VERSION = '8.1.1'
3
+ VERSION = '8.1.2'
4
4
  end
5
5
  end
@@ -26,6 +26,25 @@ describe DiscussionsController, organization_workspace: :test do
26
26
  end
27
27
  end
28
28
 
29
+ describe 'index' do
30
+ context 'when user is banned from forum' do
31
+ before { user.update! banned_from_forum: true }
32
+ before { get :index, params: exercise_params }
33
+
34
+ it { expect(response.status).to eq 404 }
35
+ end
36
+
37
+ context 'when user has exam in progress' do
38
+ let!(:exam) { create(:exam) }
39
+ before { exam.authorize! user }
40
+ before { exam.start! user }
41
+
42
+ before { get :index, params: exercise_params }
43
+
44
+ it { expect(response.status).to eq 403 }
45
+ end
46
+ end
47
+
29
48
  describe 'post' do
30
49
  before { allow_any_instance_of(DiscussionsController).to receive(:discussion_params).and_return title: 'A title' }
31
50
  before { post :create, params: exercise_params }
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 20201027152806) do
13
+ ActiveRecord::Schema.define(version: 20201130163114) do
14
14
 
15
15
  # These are extensions that must be enabled in order to support this database
16
16
  enable_extension "plpgsql"
@@ -433,6 +433,7 @@ ActiveRecord::Schema.define(version: 20201027152806) do
433
433
  t.datetime "privacy_terms_accepted_at"
434
434
  t.datetime "legal_terms_accepted_at"
435
435
  t.datetime "forum_terms_accepted_at"
436
+ t.boolean "banned_from_forum"
436
437
  t.index ["avatar_type", "avatar_id"], name: "index_users_on_avatar_type_and_avatar_id"
437
438
  t.index ["disabled_at"], name: "index_users_on_disabled_at"
438
439
  t.index ["last_organization_id"], name: "index_users_on_last_organization_id"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-laboratory
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.1
4
+ version: 8.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franco Bulgarelli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-06 00:00:00.000000000 Z
11
+ date: 2020-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '1.23'
117
+ version: '1.24'
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '1.23'
124
+ version: '1.24'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: muvment
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -849,121 +849,121 @@ required_rubygems_version: !ruby/object:Gem::Requirement
849
849
  - !ruby/object:Gem::Version
850
850
  version: '0'
851
851
  requirements: []
852
- rubygems_version: 3.1.2
852
+ rubygems_version: 3.0.3
853
853
  signing_key:
854
854
  specification_version: 4
855
855
  summary: Code assement web application for the Mumuki Platform.
856
856
  test_files:
857
- - spec/javascripts/gamification-spec.js
857
+ - spec/controllers/guide_progress_controller_spec.rb
858
+ - spec/controllers/discussions_controller_spec.rb
859
+ - spec/controllers/organizations_api_controller_spec.rb
860
+ - spec/controllers/chapters_controller_spec.rb
861
+ - spec/controllers/invitations_controller_spec.rb
862
+ - spec/controllers/messages_controller_spec.rb
863
+ - spec/controllers/courses_api_controller_spec.rb
864
+ - spec/controllers/confirmations_controller_spec.rb
865
+ - spec/controllers/students_api_controller_spec.rb
866
+ - spec/controllers/api_clients_controller.rb
867
+ - spec/controllers/exercise_solutions_controller_spec.rb
868
+ - spec/controllers/discussions_messages_controller_spec.rb
869
+ - spec/controllers/users_api_controller_spec.rb
870
+ - spec/controllers/users_controller_spec.rb
871
+ - spec/spec_helper.rb
872
+ - spec/api_helper.rb
873
+ - spec/mailers/user_mailer_spec.rb
874
+ - spec/mailers/previews/user_mailer_preview.rb
875
+ - spec/javascripts/elipsis-spec.js
858
876
  - spec/javascripts/csrf-token-spec.js
859
- - spec/javascripts/results-renderers-spec.js
860
- - spec/javascripts/bridge-spec.js
877
+ - spec/javascripts/global-spec.js
878
+ - spec/javascripts/events-spec.js
879
+ - spec/javascripts/gamification-spec.js
880
+ - spec/javascripts/sync-mode-spec.js
881
+ - spec/javascripts/exercise-spec.js
882
+ - spec/javascripts/timer-spec.js
861
883
  - spec/javascripts/editors-spec.js
862
884
  - spec/javascripts/spec-helper.js
885
+ - spec/javascripts/speech-bubble-renderer-spec.js
863
886
  - spec/javascripts/submissions-store-spec.js
887
+ - spec/javascripts/results-renderers-spec.js
888
+ - spec/javascripts/bridge-spec.js
864
889
  - spec/javascripts/timeout-spec.js
865
- - spec/javascripts/timer-spec.js
866
- - spec/javascripts/events-spec.js
867
- - spec/javascripts/exercise-spec.js
868
- - spec/javascripts/speech-bubble-renderer-spec.js
869
- - spec/javascripts/elipsis-spec.js
870
- - spec/javascripts/sync-mode-spec.js
871
- - spec/javascripts/global-spec.js
872
- - spec/spec_helper.rb
873
- - spec/dummy/config/locales/en.yml
874
- - spec/dummy/config/spring.rb
875
- - spec/dummy/config/database.travis.yml
876
- - spec/dummy/config/secrets.yml
877
- - spec/dummy/config/puma.rb
878
- - spec/dummy/config/environment.rb
879
- - spec/dummy/config/application.rb
880
- - spec/dummy/config/database.yml
881
- - spec/dummy/config/rabbit.yml
882
- - spec/dummy/config/boot.rb
883
- - spec/dummy/config/routes.rb
884
- - spec/dummy/config/cable.yml
885
- - spec/dummy/config/environments/test.rb
886
- - spec/dummy/config/environments/development.rb
887
- - spec/dummy/config/initializers/wrap_parameters.rb
888
- - spec/dummy/config/initializers/assets.rb
889
- - spec/dummy/config/initializers/cookies_serializer.rb
890
- - spec/dummy/config/initializers/filter_parameter_logging.rb
891
- - spec/dummy/config.ru
892
- - spec/dummy/public/medal/outline.svg
893
- - spec/dummy/public/character/animations.json
894
- - spec/dummy/public/error/403.svg
895
- - spec/dummy/public/error/410.svg
896
- - spec/dummy/public/error/timeout_3.svg
897
- - spec/dummy/public/error/401.svg
898
- - spec/dummy/public/error/500.svg
899
- - spec/dummy/public/error/404.svg
900
- - spec/dummy/public/error/timeout_2.svg
901
- - spec/dummy/public/error/timeout_1.svg
902
- - spec/dummy/bin/yarn
903
- - spec/dummy/bin/rails
904
- - spec/dummy/bin/setup
905
- - spec/dummy/bin/update
906
- - spec/dummy/bin/rake
907
- - spec/dummy/bin/bundle
908
- - spec/dummy/db/seeds.rb
909
- - spec/dummy/db/schema.rb
910
- - spec/dummy/package.json
911
- - spec/dummy/Rakefile
912
- - spec/evaluation_helper.rb
913
- - spec/helpers/page_title_helper_spec.rb
914
- - spec/helpers/test_results_rendering_spec.rb
915
- - spec/helpers/with_choices_spec.rb
916
- - spec/helpers/authors_helper_spec.rb
917
890
  - spec/helpers/avatar_helper_spec.rb
918
- - spec/helpers/icons_helper_spec.rb
919
- - spec/helpers/email_helper_spec.rb
920
- - spec/helpers/application_helper_spec.rb
921
- - spec/helpers/breadcrumbs_helper_spec.rb
922
891
  - spec/helpers/with_navigation_spec.rb
923
892
  - spec/helpers/exercise_input_helper_spec.rb
924
- - spec/login_helper.rb
925
- - spec/mailers/previews/user_mailer_preview.rb
926
- - spec/mailers/user_mailer_spec.rb
927
- - spec/controllers/guide_progress_controller_spec.rb
928
- - spec/controllers/students_api_controller_spec.rb
929
- - spec/controllers/messages_controller_spec.rb
930
- - spec/controllers/users_api_controller_spec.rb
931
- - spec/controllers/chapters_controller_spec.rb
932
- - spec/controllers/users_controller_spec.rb
933
- - spec/controllers/discussions_messages_controller_spec.rb
934
- - spec/controllers/courses_api_controller_spec.rb
935
- - spec/controllers/organizations_api_controller_spec.rb
936
- - spec/controllers/api_clients_controller.rb
937
- - spec/controllers/discussions_controller_spec.rb
938
- - spec/controllers/exercise_solutions_controller_spec.rb
939
- - spec/controllers/confirmations_controller_spec.rb
940
- - spec/controllers/invitations_controller_spec.rb
941
- - spec/capybara_helper.rb
942
- - spec/teaspoon_env.rb
893
+ - spec/helpers/authors_helper_spec.rb
894
+ - spec/helpers/with_choices_spec.rb
895
+ - spec/helpers/application_helper_spec.rb
896
+ - spec/helpers/breadcrumbs_helper_spec.rb
897
+ - spec/helpers/email_helper_spec.rb
898
+ - spec/helpers/page_title_helper_spec.rb
899
+ - spec/helpers/test_results_rendering_spec.rb
900
+ - spec/helpers/icons_helper_spec.rb
901
+ - spec/features/complements_flow_spec.rb
902
+ - spec/features/progressive_tips_spec.rb
903
+ - spec/features/runner_assets_spec.rb
943
904
  - spec/features/disable_user_flow_spec.rb
944
- - spec/features/invitations_flow_spec.rb
945
- - spec/features/topic_flow_spec.rb
946
- - spec/features/guide_reset_spec.rb
947
- - spec/features/discussion_flow_spec.rb
948
905
  - spec/features/links_flow_spec.rb
949
- - spec/features/not_found_private_flow_spec.rb
950
906
  - spec/features/not_found_public_flow_spec.rb
951
- - spec/features/exercise_flow_spec.rb
952
907
  - spec/features/standard_flow_spec.rb
953
- - spec/features/menu_bar_spec.rb
954
- - spec/features/dynamic_exam_spec.rb
908
+ - spec/features/exercise_flow_spec.rb
909
+ - spec/features/disabled_organization_flow_spec.rb
955
910
  - spec/features/immersive_redirection_spec.rb
956
- - spec/features/runner_assets_spec.rb
957
- - spec/features/progressive_tips_spec.rb
958
- - spec/features/chapter_spec.rb
959
- - spec/features/terms_flow_spec.rb
960
- - spec/features/login_flow_spec.rb
961
- - spec/features/home_public_flow_spec.rb
911
+ - spec/features/topic_flow_spec.rb
912
+ - spec/features/home_private_flow_spec.rb
962
913
  - spec/features/profile_flow_spec.rb
963
- - spec/features/lessons_flow_spec.rb
964
- - spec/features/disabled_organization_flow_spec.rb
965
- - spec/features/complements_flow_spec.rb
914
+ - spec/features/home_public_flow_spec.rb
915
+ - spec/features/menu_bar_spec.rb
916
+ - spec/features/not_found_private_flow_spec.rb
917
+ - spec/features/chapter_spec.rb
918
+ - spec/features/discussion_flow_spec.rb
919
+ - spec/features/invitations_flow_spec.rb
966
920
  - spec/features/exams_flow_spec.rb
967
921
  - spec/features/guides_flow_spec.rb
968
- - spec/features/home_private_flow_spec.rb
969
- - spec/api_helper.rb
922
+ - spec/features/dynamic_exam_spec.rb
923
+ - spec/features/terms_flow_spec.rb
924
+ - spec/features/lessons_flow_spec.rb
925
+ - spec/features/login_flow_spec.rb
926
+ - spec/features/guide_reset_spec.rb
927
+ - spec/evaluation_helper.rb
928
+ - spec/login_helper.rb
929
+ - spec/dummy/db/seeds.rb
930
+ - spec/dummy/db/schema.rb
931
+ - spec/dummy/public/character/animations.json
932
+ - spec/dummy/public/error/500.svg
933
+ - spec/dummy/public/error/timeout_2.svg
934
+ - spec/dummy/public/error/401.svg
935
+ - spec/dummy/public/error/timeout_3.svg
936
+ - spec/dummy/public/error/410.svg
937
+ - spec/dummy/public/error/404.svg
938
+ - spec/dummy/public/error/timeout_1.svg
939
+ - spec/dummy/public/error/403.svg
940
+ - spec/dummy/public/medal/outline.svg
941
+ - spec/dummy/package.json
942
+ - spec/dummy/config/initializers/filter_parameter_logging.rb
943
+ - spec/dummy/config/initializers/wrap_parameters.rb
944
+ - spec/dummy/config/initializers/cookies_serializer.rb
945
+ - spec/dummy/config/initializers/assets.rb
946
+ - spec/dummy/config/database.yml
947
+ - spec/dummy/config/routes.rb
948
+ - spec/dummy/config/cable.yml
949
+ - spec/dummy/config/spring.rb
950
+ - spec/dummy/config/boot.rb
951
+ - spec/dummy/config/puma.rb
952
+ - spec/dummy/config/environments/development.rb
953
+ - spec/dummy/config/environments/test.rb
954
+ - spec/dummy/config/database.travis.yml
955
+ - spec/dummy/config/rabbit.yml
956
+ - spec/dummy/config/secrets.yml
957
+ - spec/dummy/config/locales/en.yml
958
+ - spec/dummy/config/application.rb
959
+ - spec/dummy/config/environment.rb
960
+ - spec/dummy/Rakefile
961
+ - spec/dummy/bin/setup
962
+ - spec/dummy/bin/rake
963
+ - spec/dummy/bin/bundle
964
+ - spec/dummy/bin/update
965
+ - spec/dummy/bin/yarn
966
+ - spec/dummy/bin/rails
967
+ - spec/dummy/config.ru
968
+ - spec/teaspoon_env.rb
969
+ - spec/capybara_helper.rb