mumuki-classroom 8.4.0 → 9.0.2

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: 34c409b08fca1dfb53bd67f795d783315412ac34f6d5b315f5920fca2ece5aa7
4
- data.tar.gz: e22381ef42e1ff0e69d8bb86e5ef151516c9857181811228da899bb4b09b6325
3
+ metadata.gz: 660f61a9eaed9fae3598fe7ab0ee1f904e48d7a80f2ed9c6f890f7a31c9952aa
4
+ data.tar.gz: c71104874c5a96c15aa3b5bfbfb32406ad8bb813d5c47c5f43a24e6ae4ea277d
5
5
  SHA512:
6
- metadata.gz: 278e5cb886cd1d8fabb95130d608abef7ce04dd4699fc9a7c1352bc3a4ddffb63a2a55242567b38132aedc89ede30e33985aac10f025da03248c49c263364768
7
- data.tar.gz: 32832897987ee4c328d21a4e379ce3e60202844f5df3dc9dec5e9090a60eb653edc0e7498e016ab1c1ef14fc29580fb435fc1c71ee32f46b121ef6552a3cae4f
6
+ metadata.gz: a84f7b331909322a868e040644f7e573fab48978ab04a8f493097515eadb311866435c65297d64ee9beea49f739eee7ca9406c9606cfc04f05ba6bb75f9cda5c
7
+ data.tar.gz: 722219c2b000e2c68a3695cc1c1e692c310beffb3bb764cbd4b30516a4d7f69aff8a269324960c0c023eb75565b8057497800254650caa9fca84f9d144256926
@@ -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
@@ -17,8 +17,8 @@ module Reporting
17
17
  main_pipeline << {'$match': query}
18
18
  main_pipeline.concat searching.pipeline
19
19
  main_pipeline.concat sorting.pipeline
20
- main_pipeline << {'$project': projection}
21
20
  main_pipeline << {'$sort': sorting.order_by(ordering)}
21
+ main_pipeline << {'$project': projection}
22
22
  end
23
23
 
24
24
  end
@@ -2,7 +2,7 @@ module Sorting
2
2
 
3
3
  def self.aggregate(collection, query, paginated_params, query_params)
4
4
  reporting_pipeline = Reporting.build_pipeline(collection, query, paginated_params, query_params, projection)
5
- query = collection.collection.aggregate(pipeline paginated_params, reporting_pipeline).first
5
+ query = collection.collection.aggregate(pipeline(paginated_params, reporting_pipeline), allow_disk_use: true).first # Must allow disk use for sorting large collections by non-index
6
6
  query_results(query)
7
7
  end
8
8
 
@@ -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,8 +1,18 @@
1
1
  class Mumuki::Classroom::App < Sinatra::Application
2
2
  Mumukit::Platform.map_organization_routes!(self) do
3
+ helpers do
4
+ def list_teachers(matcher)
5
+ authorize! :headmaster
6
+ {teachers: Mumuki::Classroom::Teacher.where(matcher).as_json}
7
+ end
8
+ end
9
+
10
+ get '/teachers' do
11
+ list_teachers with_organization
12
+ end
13
+
3
14
  get '/courses/:course/teachers' do
4
- authorize! :headmaster
5
- {teachers: Mumuki::Classroom::Teacher.where(with_organization_and_course).as_json}
15
+ list_teachers with_organization_and_course
6
16
  end
7
17
 
8
18
  post '/courses/:course/teachers' do
@@ -1,5 +1,5 @@
1
1
  module Mumuki
2
2
  module Classroom
3
- VERSION = '8.4.0'
3
+ VERSION = '9.0.2'
4
4
  end
5
5
  end
@@ -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.4.0
4
+ version: 9.0.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: 2021-01-29 00:00:00.000000000 Z
11
+ date: 2021-03-26 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.4.0
89
+ version: 9.0.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.4.0
96
+ version: 9.0.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
@@ -226,6 +226,10 @@ files:
226
226
  - lib/mumuki/classroom/collection.rb
227
227
  - lib/mumuki/classroom/engine.rb
228
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
229
233
  - lib/mumuki/classroom/event/user_changed.rb
230
234
  - lib/mumuki/classroom/locales/en.yml
231
235
  - lib/mumuki/classroom/locales/es-CL.yml
@@ -281,6 +285,7 @@ files:
281
285
  - lib/mumuki/profile.rb
282
286
  - lib/mumuki/views/threads.html.erb
283
287
  - lib/tasks/mumuki/messages.rake
288
+ - lib/tasks/mumuki/progress_transfers.rake
284
289
  - lib/tasks/mumuki/resubmissions.rake
285
290
  - lib/tasks/mumuki/students.rake
286
291
  - lib/tasks/mumuki/submissions.rake