mumuki-classroom 8.1.0 → 8.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a692a947703253a96c48e054b3be2717ee3a41d89e1b8cf460e33e963917ccf8
4
- data.tar.gz: 3c2038e677ae7b0b7a26f0c4222c6048827b5aee9357fb0d8e55e22fe8a99fbd
3
+ metadata.gz: b9478687b7b21f32f26aacddb48094ab88ac960c625ae104321a913fd980083f
4
+ data.tar.gz: d140d89d369715662e25dfddb1338a823e378402e26c9e491f167897c5ad65b7
5
5
  SHA512:
6
- metadata.gz: 64cfbb4d62cb084aae93ec4d7ce63475c421704fd7cbe255e5d814e1dd2c60b2874706830be942dd8b7c910d504dcfcac1d49fc57d40bde9be96d92d94b544ea
7
- data.tar.gz: 782fd2d5896ac77519c4fa11027d0927d20981cca11e1425de4ae9613e18a3f78ec6b6bcbede7d76d2e9cae7dc8638bb45646a6deea4df868fe8a32b1359018a
6
+ metadata.gz: 24e65c6cf9f54f4a3a0b826221ff5979d329c790390f9fe950a684d1606c9bb78943ba3e6e6d4dd9937f1341e2dbcd16b34b8040b6ea4c63f15fffa521d45c23
7
+ data.tar.gz: d50f24e931da4ce4986fc7736c38653fe36bc0db32f447c974f4e16a7b43bde545f853ed8797572d0784921f1cdf398ccd33ae2379fa26a553912e0ad63308ad
@@ -2,3 +2,4 @@ module Mumuki::Classroom::Event
2
2
  end
3
3
 
4
4
  require_relative './event/user_changed'
5
+ require_relative './event/progress_transfer'
@@ -0,0 +1,31 @@
1
+ class Mumuki::Classroom::Event::ProgressTransfer
2
+ attr_reader :body
3
+
4
+ def initialize(body)
5
+ @body = body
6
+ end
7
+
8
+ def execute!
9
+ transfer_type.new(progress_item, source_organization, destination_organization).execute!
10
+ end
11
+
12
+ def source_organization
13
+ Organization.locate! body[:from]
14
+ end
15
+
16
+ def destination_organization
17
+ Organization.locate! body[:to]
18
+ end
19
+
20
+ def progress_item
21
+ Indicator.find(body[:item_id])
22
+ end
23
+
24
+ def transfer_type
25
+ self.class.const_get(body[:transfer_type].camelize)
26
+ end
27
+ end
28
+
29
+ require_relative 'progress_transfer/base'
30
+ require_relative 'progress_transfer/copy'
31
+ require_relative 'progress_transfer/move'
@@ -0,0 +1,111 @@
1
+ class Mumuki::Classroom::Event::ProgressTransfer::Base
2
+ attr_reader :indicator, :source_organization
3
+
4
+ def initialize(indicator, source_organization, destination_organization)
5
+ @indicator = indicator
6
+ @source_organization = source_organization
7
+ @destination_organization = destination_organization
8
+ end
9
+
10
+ def execute!
11
+ raise ActiveRecord::RecordNotFound, "Mumuki::Classroom::Student not found" unless old_student && new_student
12
+
13
+ new_student.destroy_progress_for_guide!(indicator.content)
14
+ destination_organization.switch!
15
+
16
+ indicator.assignments.each do |assignment|
17
+ transfer_sibling_for(assignment)&.update! organization: destination_organization.name,
18
+ course: new_course,
19
+ guide: guide_h
20
+ end
21
+
22
+ transfer_guide_progress!
23
+ update_student!(old_student)
24
+ update_student!(new_student)
25
+ end
26
+
27
+ private
28
+
29
+ def update_student!(student)
30
+ student.update_all_stats
31
+ student.update_last_assignment_for
32
+ end
33
+
34
+ def destination_organization
35
+ @destination_organization
36
+ end
37
+
38
+ def transfer_guide_progress!
39
+ transfer_item.update!(guide: guide_h,
40
+ student: new_student.dup,
41
+ organization: destination_organization.name,
42
+ course: new_course)
43
+ end
44
+
45
+ def guide_progress
46
+ Mumuki::Classroom::GuideProgress.find_by(guide_progress_query)
47
+ end
48
+
49
+ def classroom_sibling_for(assignment)
50
+ Mumuki::Classroom::Assignment.classroom_sibling_for(assignment, source_organization.name)
51
+ end
52
+
53
+ def new_student
54
+ @new_student ||= student_for destination_organization.name
55
+ end
56
+
57
+ def old_student
58
+ @old_student ||= student_for source_organization
59
+ end
60
+
61
+ def student_for(organization)
62
+ Mumuki::Classroom::Student.last_updated_student_by organization: organization, uid: user.uid
63
+ end
64
+
65
+ def new_course
66
+ new_student.course
67
+ end
68
+
69
+ def old_course
70
+ old_student.course
71
+ end
72
+
73
+ def guide_progress_query
74
+ {
75
+ organization: source_organization,
76
+ course: old_course,
77
+ 'guide.slug': guide.slug,
78
+ 'student.uid': user.uid
79
+ }
80
+ end
81
+
82
+ def user
83
+ indicator.user
84
+ end
85
+
86
+ def guide
87
+ indicator.content
88
+ end
89
+
90
+ def guide_parent
91
+ guide.usage_in_organization
92
+ end
93
+
94
+ def guide_h
95
+ @guide_h ||= guide.as_json(
96
+ only: [:slug, :name],
97
+ include: {
98
+ language: {
99
+ only: [:name, :devicon]
100
+ }
101
+ }
102
+ ).merge(
103
+ parent: {
104
+ type: guide_parent.class.to_s,
105
+ name: guide.name,
106
+ position: guide_parent.number,
107
+ chapter: guide.chapter.as_json(only: [:id], methods: [:name])
108
+ }
109
+ )
110
+ end
111
+ end
@@ -0,0 +1,9 @@
1
+ class Mumuki::Classroom::Event::ProgressTransfer::Copy < Mumuki::Classroom::Event::ProgressTransfer::Base
2
+ def transfer_sibling_for(assignment)
3
+ classroom_sibling_for(assignment).dup
4
+ end
5
+
6
+ def transfer_item
7
+ guide_progress.dup
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class Mumuki::Classroom::Event::ProgressTransfer::Move < Mumuki::Classroom::Event::ProgressTransfer::Base
2
+ def transfer_sibling_for(assignment)
3
+ classroom_sibling_for(assignment)
4
+ end
5
+
6
+ def transfer_item
7
+ guide_progress
8
+ end
9
+ end
@@ -143,6 +143,9 @@ class Mumuki::Classroom::Assignment < Mumuki::Classroom::Document
143
143
  stats[:failed] += stats.delete(:errored) || 0
144
144
  stats.slice(*empty_stats.keys)
145
145
  end
146
- end
147
146
 
147
+ def classroom_sibling_for(assignment, organization)
148
+ find_by(organization: organization, 'student.uid': assignment.user.uid, 'exercise.eid': assignment.exercise.bibliotheca_id)
149
+ end
150
+ end
148
151
  end
@@ -22,7 +22,7 @@ module WithSubmissionProcess
22
22
  end
23
23
 
24
24
  def find_student_from(json)
25
- Mumuki::Classroom::Student.find_by(organization: organization(json), course: course_slug(json), uid: uid(json)).as_json
25
+ Mumuki::Classroom::Student.find_by(organization: organization(json), course: course_slug(json), uid: uid(json))
26
26
  end
27
27
 
28
28
  def update_student_progress(json)
@@ -99,15 +99,7 @@ module WithSubmissionProcess
99
99
  end
100
100
 
101
101
  def student_from(json)
102
- student = json[:student]
103
-
104
- {uid: student[:uid],
105
- name: student[:name],
106
- email: student[:email],
107
- image_url: student[:image_url],
108
- social_id: student[:social_id],
109
- last_name: student[:last_name],
110
- first_name: student[:first_name]}.compact
102
+ json[:student].as_submission_json
111
103
  end
112
104
 
113
105
  def guide_from(json)
@@ -134,15 +126,6 @@ module WithSubmissionProcess
134
126
  end
135
127
 
136
128
  def submission_from(json)
137
- {sid: json[:sid],
138
- status: json[:status],
139
- result: json[:result],
140
- content: json[:content],
141
- feedback: json[:feedback],
142
- created_at: json[:created_at],
143
- test_results: json[:test_results],
144
- submissions_count: json[:submissions_count],
145
- expectation_results: json[:expectation_results],
146
- origin_ip: json[:origin_ip]}.compact
129
+ Mumuki::Classroom::FailedSubmission.new(json).as_assignment_submission
147
130
  end
148
131
  end
@@ -4,7 +4,7 @@ class Mumuki::Classroom::FailedSubmission < Mumuki::Classroom::Document
4
4
 
5
5
  include Mongoid::Attributes::Dynamic
6
6
 
7
- field :created_at, type: Time
7
+ include Mongoid::Timestamps::Created
8
8
 
9
9
  create_index 'organization': 1, 'submitter.uid': 1
10
10
  create_index({'guide.slug': 1, 'exercise.eid': 1}, {name: 'ExBibIdIndex'})
@@ -13,4 +13,7 @@ class Mumuki::Classroom::FailedSubmission < Mumuki::Classroom::Document
13
13
  scope :find_by_uid, -> (uid) { where 'submitter.uid': uid }
14
14
 
15
15
 
16
+ def as_assignment_submission
17
+ as_json(only: %i(sid status result content feedback created_at test_results submissions_count expectation_results origin_ip)).compact
18
+ end
16
19
  end
@@ -52,6 +52,10 @@ class Mumuki::Classroom::GuideProgress < Mumuki::Classroom::Document
52
52
  def uid_field
53
53
  'student.uid'.to_sym
54
54
  end
55
+
56
+ def progresses_for(progress_item, student)
57
+ where(organization: progress_item.organization, course: student.course, slug: progress_item.content.slug, 'student.uid': student.uid)
58
+ end
55
59
  end
56
60
 
57
61
  end
@@ -16,11 +16,23 @@ class Mumuki::Classroom::Student < Mumuki::Classroom::Document
16
16
  end
17
17
 
18
18
  def destroy_cascade!
19
- Mumuki::Classroom::GuideProgress.destroy_all_by!(sub_student_query uid)
20
- Mumuki::Classroom::Assignment.destroy_all_by!(sub_student_query uid)
19
+ destroy_progress!
21
20
  destroy!
22
21
  end
23
22
 
23
+ def destroy_progress!
24
+ destroy_progress_for_query!(sub_student_query uid)
25
+ end
26
+
27
+ def destroy_progress_for_guide!(guide)
28
+ destroy_progress_for_query!(sub_student_query(uid).merge 'guide.slug': guide.slug)
29
+ end
30
+
31
+ def destroy_progress_for_query!(query)
32
+ Mumuki::Classroom::GuideProgress.destroy_all_by!(query)
33
+ Mumuki::Classroom::Assignment.destroy_all_by!(query)
34
+ end
35
+
24
36
  def update_all_stats
25
37
  all_stats = Mumuki::Classroom::Assignment.stats_by(sub_student_query uid)
26
38
  update_attributes!(stats: all_stats)
@@ -52,6 +64,10 @@ class Mumuki::Classroom::Student < Mumuki::Classroom::Document
52
64
  update_attributes!(last_assignment: Mumuki::Classroom::GuideProgress.last_assignment_by(sub_student_query uid))
53
65
  end
54
66
 
67
+ def as_submission_json
68
+ as_json(only: %i(uid name email image_url social_id last_name first_name)).compact
69
+ end
70
+
55
71
  class << self
56
72
  def report(criteria, &block)
57
73
  where(criteria).select(&block).as_json(only: [:first_name, :last_name, :email, :created_at, :detached_at])
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Classroom
3
- VERSION = '8.1.0'
3
+ VERSION = '8.6.0'
4
4
  end
5
5
  end
@@ -4,7 +4,7 @@
4
4
  <div class="thread">
5
5
  <li class="solution self">
6
6
  <a onclick="toggleCollapse('toggle-<%= index %>')">
7
- <i class="fa fa-<%= threads.last == thread ? 'minus' : 'plus' %>-square-o toggle-<%= index %>"></i>
7
+ <i class="far fa-<%= threads.last == thread ? 'minus' : 'plus' %>-square toggle-<%= index %>"></i>
8
8
  <span>&nbsp;</span>
9
9
  <span> <%= I18n.t(:view_solution) %> </span>
10
10
  </a>
@@ -32,8 +32,8 @@
32
32
  function toggleCollapse(target) {
33
33
  var $target = $('#' + target);
34
34
  var $icon = $('i.' + target);
35
- $icon.toggleClass('fa-minus-square-o');
36
- $icon.toggleClass('fa-plus-square-o');
35
+ $icon.toggleClass('fa-minus-square');
36
+ $icon.toggleClass('fa-plus-square');
37
37
  $target.toggleClass('hidden');
38
38
  }
39
39
 
@@ -0,0 +1,17 @@
1
+ namespace :classroom do
2
+ namespace :progress_transfers do
3
+ task listen: :environment do
4
+ Mumukit::Nuntius::Logger.info 'Listening to student progress-transfers'
5
+
6
+ Mumukit::Nuntius::Consumer.negligent_start! 'progress-transfers' do |body|
7
+ begin
8
+ Mumuki::Classroom::Event::ProgressTransfer.new(body).execute!
9
+
10
+ Mumukit::Nuntius::Logger.info "Processing progress transfer #{body[:item_id]}"
11
+ rescue => e
12
+ Mumukit::Nuntius::Logger.warn "Mumuki::Classroom::ProgressTransfer failed #{e}. body was: #{body}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mumuki-classroom
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.0
4
+ version: 8.6.0
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-11-30 00:00:00.000000000 Z
11
+ date: 2021-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '8.1'
89
+ version: 8.6.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '8.1'
96
+ version: 8.6.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: mumukit-login
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '5.0'
131
+ version: '6.0'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '5.0'
138
+ version: '6.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: mongoid
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +192,26 @@ dependencies:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
194
  version: 0.18.0
195
+ - !ruby/object:Gem::Dependency
196
+ name: bundler
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '2.0'
202
+ - - "<"
203
+ - !ruby/object:Gem::Version
204
+ version: '2.2'
205
+ type: :development
206
+ prerelease: false
207
+ version_requirements: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - "~>"
210
+ - !ruby/object:Gem::Version
211
+ version: '2.0'
212
+ - - "<"
213
+ - !ruby/object:Gem::Version
214
+ version: '2.2'
195
215
  description: Teacher tools for Mumuki
196
216
  email:
197
217
  - franco@mumuki.org
@@ -206,6 +226,10 @@ files:
206
226
  - lib/mumuki/classroom/collection.rb
207
227
  - lib/mumuki/classroom/engine.rb
208
228
  - lib/mumuki/classroom/event.rb
229
+ - lib/mumuki/classroom/event/progress_transfer.rb
230
+ - lib/mumuki/classroom/event/progress_transfer/base.rb
231
+ - lib/mumuki/classroom/event/progress_transfer/copy.rb
232
+ - lib/mumuki/classroom/event/progress_transfer/move.rb
209
233
  - lib/mumuki/classroom/event/user_changed.rb
210
234
  - lib/mumuki/classroom/locales/en.yml
211
235
  - lib/mumuki/classroom/locales/es-CL.yml
@@ -261,6 +285,7 @@ files:
261
285
  - lib/mumuki/profile.rb
262
286
  - lib/mumuki/views/threads.html.erb
263
287
  - lib/tasks/mumuki/messages.rake
288
+ - lib/tasks/mumuki/progress_transfers.rake
264
289
  - lib/tasks/mumuki/resubmissions.rake
265
290
  - lib/tasks/mumuki/students.rake
266
291
  - lib/tasks/mumuki/submissions.rake
@@ -284,7 +309,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
309
  - !ruby/object:Gem::Version
285
310
  version: '0'
286
311
  requirements: []
287
- rubygems_version: 3.1.2
312
+ rubygems_version: 3.0.3
288
313
  signing_key:
289
314
  specification_version: 4
290
315
  summary: Teacher tools for Mumuki