mumuki-classroom 8.5.0 → 9.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/initializers/inflections.rb +3 -0
- data/lib/mumuki/classroom/event.rb +1 -0
- data/lib/mumuki/classroom/event/progress_transfer.rb +31 -0
- data/lib/mumuki/classroom/event/progress_transfer/base.rb +111 -0
- data/lib/mumuki/classroom/event/progress_transfer/copy.rb +9 -0
- data/lib/mumuki/classroom/event/progress_transfer/move.rb +9 -0
- data/lib/mumuki/classroom/models/assignment.rb +4 -1
- data/lib/mumuki/classroom/models/concerns/with_submission_process.rb +3 -20
- data/lib/mumuki/classroom/models/failed_submission.rb +4 -1
- data/lib/mumuki/classroom/models/guide_progress.rb +4 -0
- data/lib/mumuki/classroom/models/reporting.rb +1 -1
- data/lib/mumuki/classroom/models/sorting.rb +1 -1
- data/lib/mumuki/classroom/models/student.rb +18 -2
- data/lib/mumuki/classroom/sinatra/teachers.rb +12 -2
- data/lib/mumuki/classroom/version.rb +1 -1
- data/lib/tasks/mumuki/progress_transfers.rake +17 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a46d4bfcc9b123f3585dace449a4878c5aab314061e52d2e9017e873494e994
|
4
|
+
data.tar.gz: 7ebaaa89a846bcf12ce895de21e51dd9040700236e9248fdad6c4a5798dc5c50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b64c14a1d833934f6e55ad40522a401e54bae94549fcae8f8ff5fb3f1b5233ebcfc2493bea5ec901bf613341bedc45601c496d64465c21e9cd1522b7438ddd2
|
7
|
+
data.tar.gz: 04e82d680eac93fda5c027accdb5a9e71d4bfe6bce83caa10b08894bab9ad25f47aebd378618c0f19570b5372ee399cf5e0c1f9d2bb339bab383a88c8938b1b9
|
@@ -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
|
@@ -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))
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
@@ -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:
|
4
|
+
version: 9.1.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: 2021-
|
11
|
+
date: 2021-04-30 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:
|
89
|
+
version: 9.1.1
|
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:
|
96
|
+
version: 9.1.1
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: mumukit-login
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -222,10 +222,15 @@ files:
|
|
222
222
|
- LICENSE
|
223
223
|
- README.md
|
224
224
|
- Rakefile
|
225
|
+
- config/initializers/inflections.rb
|
225
226
|
- lib/mumuki/classroom.rb
|
226
227
|
- lib/mumuki/classroom/collection.rb
|
227
228
|
- lib/mumuki/classroom/engine.rb
|
228
229
|
- lib/mumuki/classroom/event.rb
|
230
|
+
- lib/mumuki/classroom/event/progress_transfer.rb
|
231
|
+
- lib/mumuki/classroom/event/progress_transfer/base.rb
|
232
|
+
- lib/mumuki/classroom/event/progress_transfer/copy.rb
|
233
|
+
- lib/mumuki/classroom/event/progress_transfer/move.rb
|
229
234
|
- lib/mumuki/classroom/event/user_changed.rb
|
230
235
|
- lib/mumuki/classroom/locales/en.yml
|
231
236
|
- lib/mumuki/classroom/locales/es-CL.yml
|
@@ -281,6 +286,7 @@ files:
|
|
281
286
|
- lib/mumuki/profile.rb
|
282
287
|
- lib/mumuki/views/threads.html.erb
|
283
288
|
- lib/tasks/mumuki/messages.rake
|
289
|
+
- lib/tasks/mumuki/progress_transfers.rake
|
284
290
|
- lib/tasks/mumuki/resubmissions.rake
|
285
291
|
- lib/tasks/mumuki/students.rake
|
286
292
|
- lib/tasks/mumuki/submissions.rake
|