senkyoshi 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -2
- data/lib/senkyoshi/canvas_course.rb +15 -9
- data/lib/senkyoshi/models/assessment.rb +4 -93
- data/lib/senkyoshi/models/attachment.rb +21 -0
- data/lib/senkyoshi/models/content.rb +39 -18
- data/lib/senkyoshi/models/content_file.rb +21 -4
- data/lib/senkyoshi/models/external_url.rb +9 -0
- data/lib/senkyoshi/models/file.rb +22 -21
- data/lib/senkyoshi/models/gradebook.rb +5 -8
- data/lib/senkyoshi/models/module_item.rb +3 -1
- data/lib/senkyoshi/models/qti.rb +215 -0
- data/lib/senkyoshi/models/question.rb +3 -3
- data/lib/senkyoshi/models/question_bank.rb +46 -0
- data/lib/senkyoshi/models/questions/fill_in_blank.rb +3 -1
- data/lib/senkyoshi/models/questions/fill_in_blank_plus.rb +3 -1
- data/lib/senkyoshi/models/questions/matching.rb +8 -3
- data/lib/senkyoshi/models/questions/multiple_choice.rb +12 -0
- data/lib/senkyoshi/models/questions/numerical.rb +4 -1
- data/lib/senkyoshi/models/questions/true_false.rb +1 -1
- data/lib/senkyoshi/models/resource.rb +8 -6
- data/lib/senkyoshi/models/scorm_package.rb +51 -34
- data/lib/senkyoshi/models/staff_info.rb +49 -31
- data/lib/senkyoshi/models/survey.rb +10 -0
- data/lib/senkyoshi/models/wikipage.rb +55 -9
- data/lib/senkyoshi/version.rb +1 -2
- data/lib/senkyoshi/xml_parser.rb +60 -31
- data/lib/senkyoshi.rb +14 -8
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13edfb731484992561073e292a28f75a15bfaa5d
|
4
|
+
data.tar.gz: 528e83f4e9f0a60f88a40cd8d503e35b07fa8655
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 470eafc042455cf9221aac1dca5544fb2ad335c5c9ab5f4fc5c368bd270c6ee40d25ffcb4991f5625351f21ead8220f3178315bf9076d2c455f1d421b9debb1d
|
7
|
+
data.tar.gz: 57c7176e3b952dbf02dff18ba3546ac02a2ebe35b72bafd3f8b52f220cb9cf759f21c25ab9518d10ebadaafa4fe1eb6f739888badba46d5909de7f39a403cc12
|
data/README.md
CHANGED
@@ -57,13 +57,13 @@ Create a `senkyoshi.yml` and add credentials
|
|
57
57
|
|
58
58
|
Run the rake task to convert from .zip to .imscc
|
59
59
|
```sh
|
60
|
-
rake imscc
|
60
|
+
rake senkyoshi:imscc
|
61
61
|
```
|
62
62
|
This will take all your files in your source folder and convert them to your outputs folder
|
63
63
|
|
64
64
|
Run converting files in parallel
|
65
65
|
```sh
|
66
|
-
time rake imscc -m
|
66
|
+
time rake senkyoshi:imscc -m
|
67
67
|
```
|
68
68
|
|
69
69
|
Delete entire outputs folder
|
@@ -71,6 +71,11 @@ Delete entire outputs folder
|
|
71
71
|
rake clean
|
72
72
|
```
|
73
73
|
|
74
|
+
Upload to canvas to process
|
75
|
+
```sh
|
76
|
+
rake senkyoshi:upload
|
77
|
+
```
|
78
|
+
|
74
79
|
## Development
|
75
80
|
|
76
81
|
After checking out the repo, run `bundle install` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -3,11 +3,16 @@ require "senkyoshi/config"
|
|
3
3
|
require "senkyoshi/models/scorm_package"
|
4
4
|
require "rest-client"
|
5
5
|
|
6
|
+
require "openssl"
|
7
|
+
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
|
8
|
+
|
6
9
|
module Senkyoshi
|
7
10
|
##
|
8
11
|
# This class represents a canvas course for which we are uploading data to
|
9
12
|
##
|
10
13
|
class CanvasCourse
|
14
|
+
attr_reader :scorm_packages
|
15
|
+
|
11
16
|
##
|
12
17
|
# A new canvas course accepts the metadata for a course
|
13
18
|
# and the pandarus course resourse
|
@@ -48,14 +53,12 @@ module Senkyoshi
|
|
48
53
|
##
|
49
54
|
def self.from_metadata(metadata, blackboard_export = nil)
|
50
55
|
course_name = metadata[:name] || metadata[:title]
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
},
|
58
|
-
)
|
56
|
+
canvas_course = client.create_new_course(
|
57
|
+
Senkyoshi.account_id,
|
58
|
+
course: {
|
59
|
+
name: course_name,
|
60
|
+
},
|
61
|
+
)
|
59
62
|
CanvasCourse.new(metadata, canvas_course, blackboard_export)
|
60
63
|
end
|
61
64
|
|
@@ -76,6 +79,7 @@ module Senkyoshi
|
|
76
79
|
assignment__external_tool_tag_attributes__: {
|
77
80
|
url: url,
|
78
81
|
},
|
82
|
+
assignment__points_possible__: scorm_package["points_possible"],
|
79
83
|
}
|
80
84
|
|
81
85
|
CanvasCourse.client.create_assignment(
|
@@ -101,7 +105,9 @@ module Senkyoshi
|
|
101
105
|
},
|
102
106
|
SharedAuthorization: Senkyoshi.scorm_shared_auth,
|
103
107
|
) do |resp|
|
104
|
-
JSON.parse(resp.body)["response"]
|
108
|
+
result = JSON.parse(resp.body)["response"]
|
109
|
+
result["points_possible"] = scorm_package.points_possible
|
110
|
+
result
|
105
111
|
end
|
106
112
|
end
|
107
113
|
end
|
@@ -1,99 +1,10 @@
|
|
1
|
-
require "senkyoshi/models/
|
2
|
-
require "senkyoshi/models/assignment"
|
3
|
-
require "senkyoshi/models/question"
|
4
|
-
require "senkyoshi/models/resource"
|
1
|
+
require "senkyoshi/models/qti"
|
5
2
|
|
6
3
|
module Senkyoshi
|
7
|
-
class Assessment <
|
8
|
-
def initialize
|
9
|
-
@title = ""
|
10
|
-
@description = ""
|
11
|
-
@quiz_type = "assignment"
|
12
|
-
@points_possible = 0
|
13
|
-
@items = []
|
14
|
-
@group_name = ""
|
15
|
-
@workflow_state = "published"
|
16
|
-
@available = true
|
17
|
-
end
|
18
|
-
|
4
|
+
class Assessment < QTI
|
19
5
|
def iterate_xml(data, pre_data)
|
20
|
-
|
21
|
-
|
22
|
-
@title = data.at("assessment").attributes["title"].value
|
23
|
-
@points_possible = data.at("qmd_absolutescore_max").text
|
24
|
-
@description = data.at("presentation_material").
|
25
|
-
at("mat_formattedtext").text
|
26
|
-
@group_name = data.at("bbmd_assessmenttype").text
|
27
|
-
case @group_name.downcase
|
28
|
-
when "survey"
|
29
|
-
@quiz_type = "survey"
|
30
|
-
end
|
31
|
-
data.at("section").children.map do |item|
|
32
|
-
@items.push(item) if item.name == "item"
|
33
|
-
end
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
def canvas_conversion(course, resources)
|
38
|
-
if @items.count > 0
|
39
|
-
assessment = CanvasCc::CanvasCC::Models::Assessment.new
|
40
|
-
assessment.identifier = @id
|
41
|
-
course = create_assignment_group(course, resources)
|
42
|
-
assignment = create_assignment
|
43
|
-
assignment.quiz_identifier_ref = assessment.identifier
|
44
|
-
course.assignments << assignment
|
45
|
-
assessment = setup_assessment(assessment, assignment, resources)
|
46
|
-
course.assessments << assessment
|
47
|
-
end
|
48
|
-
course
|
49
|
-
end
|
50
|
-
|
51
|
-
def setup_assessment(assessment, assignment, resources)
|
52
|
-
assessment.title = @title
|
53
|
-
assessment.description = fix_html(@description, resources)
|
54
|
-
assessment.available = @available
|
55
|
-
assessment.quiz_type = @quiz_type
|
56
|
-
assessment.points_possible = @points_possible
|
57
|
-
assessment = create_items(assessment, resources)
|
58
|
-
assessment.assignment = assignment
|
59
|
-
assessment
|
60
|
-
end
|
61
|
-
|
62
|
-
def create_items(assessment, resources)
|
63
|
-
@items = @items - ["", nil]
|
64
|
-
questions = @items.map do |item|
|
65
|
-
Question.from(item)
|
66
|
-
end
|
67
|
-
assessment.items = []
|
68
|
-
questions.each do |item|
|
69
|
-
assessment = item.canvas_conversion(assessment, resources)
|
70
|
-
end
|
71
|
-
assessment
|
72
|
-
end
|
73
|
-
|
74
|
-
def create_assignment_group(course, resources)
|
75
|
-
group = course.assignment_groups.detect { |a| a.title == @group_name }
|
76
|
-
if group
|
77
|
-
@group_id = group.identifier
|
78
|
-
else
|
79
|
-
@group_id = Senkyoshi.create_random_hex
|
80
|
-
assignment_group = AssignmentGroup.new(@group_name, @group_id)
|
81
|
-
course = assignment_group.canvas_conversion(course, resources)
|
82
|
-
end
|
83
|
-
course
|
84
|
-
end
|
85
|
-
|
86
|
-
def create_assignment
|
87
|
-
assignment = CanvasCc::CanvasCC::Models::Assignment.new
|
88
|
-
assignment.identifier = Senkyoshi.create_random_hex
|
89
|
-
assignment.assignment_group_identifier_ref = @group_id
|
90
|
-
assignment.title = @title
|
91
|
-
assignment.position = 1
|
92
|
-
assignment.submission_types << "online_quiz"
|
93
|
-
assignment.grading_type = "points"
|
94
|
-
assignment.workflow_state = @workflow_state
|
95
|
-
assignment.points_possible = @points_possible
|
96
|
-
assignment
|
6
|
+
@quiz_type = "assignment"
|
7
|
+
super
|
97
8
|
end
|
98
9
|
end
|
99
10
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "senkyoshi/models/content"
|
2
|
+
require "senkyoshi/models/module_item"
|
3
|
+
|
4
|
+
module Senkyoshi
|
5
|
+
class Attachment < Content
|
6
|
+
def iterate_xml(xml, pre_data)
|
7
|
+
super
|
8
|
+
@module_item = ModuleItem.new(
|
9
|
+
@title,
|
10
|
+
@module_type,
|
11
|
+
@files.first.name,
|
12
|
+
@url,
|
13
|
+
).canvas_conversion
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def canvas_conversion(course, _resource)
|
18
|
+
create_module(course)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "senkyoshi/models/resource"
|
2
|
+
require "senkyoshi/models/content_file"
|
2
3
|
|
3
4
|
module Senkyoshi
|
4
5
|
class Content < Resource
|
@@ -8,11 +9,11 @@ module Senkyoshi
|
|
8
9
|
"x-bb-assignment" => "Assignment",
|
9
10
|
"x-bbpi-selfpeer-type1" => "Assignment",
|
10
11
|
"x-bb-document" => "WikiPage",
|
11
|
-
"x-bb-file" => "
|
12
|
-
"x-bb-audio" => "
|
13
|
-
"x-bb-image" => "
|
14
|
-
"x-bb-video" => "
|
15
|
-
"x-bb-externallink" => "
|
12
|
+
"x-bb-file" => "Attachment",
|
13
|
+
"x-bb-audio" => "Attachment",
|
14
|
+
"x-bb-image" => "Attachment",
|
15
|
+
"x-bb-video" => "Attachment",
|
16
|
+
"x-bb-externallink" => "ExternalUrl",
|
16
17
|
"x-bb-blankpage" => "WikiPage",
|
17
18
|
"x-bb-lesson" => "WikiPage",
|
18
19
|
"x-bb-folder" => "WikiPage",
|
@@ -21,11 +22,28 @@ module Senkyoshi
|
|
21
22
|
"x-bb-syllabus" => "WikiPage",
|
22
23
|
}.freeze
|
23
24
|
|
24
|
-
|
25
|
+
MODULE_TYPES = {
|
26
|
+
"Senkyoshi::Attachment" => "Attachment",
|
27
|
+
"Senkyoshi::Assignment" => "Assignment",
|
28
|
+
"Senkyoshi::ExternalUrl" => "ExternalUrl",
|
29
|
+
"Senkyoshi::WikiPage" => "WikiPage",
|
30
|
+
"Senkyoshi::Quiz" => "Quizzes::Quiz",
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
attr_accessor(:title, :body, :id, :files, :url)
|
34
|
+
attr_reader(:extendeddata)
|
25
35
|
|
26
|
-
def self.from(xml, pre_data)
|
36
|
+
def self.from(xml, pre_data, resource_xids)
|
27
37
|
type = xml.xpath("/CONTENT/CONTENTHANDLER/@value").first.text
|
28
38
|
type.slice! "resource/"
|
39
|
+
xml.xpath("//FILES/FILE").each do |file|
|
40
|
+
file_name = ContentFile.clean_xid file.at("NAME").text
|
41
|
+
is_attachment = CONTENT_TYPES[type] == "Attachment"
|
42
|
+
if !resource_xids.include?(file_name) && is_attachment
|
43
|
+
type = "x-bb-document"
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
29
47
|
if content_type = CONTENT_TYPES[type]
|
30
48
|
content_class = Senkyoshi.const_get content_type
|
31
49
|
content = content_class.new
|
@@ -35,25 +53,33 @@ module Senkyoshi
|
|
35
53
|
|
36
54
|
def iterate_xml(xml, pre_data)
|
37
55
|
@points = pre_data[:points] || 0
|
56
|
+
@parent_title = pre_data[:parent_title]
|
38
57
|
@title = xml.xpath("/CONTENT/TITLE/@value").first.text
|
39
58
|
@url = xml.at("URL")["value"]
|
40
59
|
@body = xml.xpath("/CONTENT/BODY/TEXT").first.text
|
60
|
+
@extendeddata = xml.at("/CONTENT/EXTENDEDDATA/ENTRY")
|
61
|
+
if @extendeddata
|
62
|
+
@extendeddata = @extendeddata.text
|
63
|
+
end
|
41
64
|
@type = xml.xpath("/CONTENT/RENDERTYPE/@value").first.text
|
42
65
|
@parent_id = pre_data[:parent_id]
|
43
|
-
|
44
|
-
bb_type.slice! "resource/"
|
45
|
-
@module_type = CONTENT_TYPES[bb_type]
|
66
|
+
@module_type = MODULE_TYPES[self.class.name]
|
46
67
|
@id = xml.xpath("/CONTENT/@id").first.text
|
47
68
|
if pre_data[:assignment_id] && !pre_data[:assignment_id].empty?
|
48
69
|
@id = pre_data[:assignment_id]
|
49
70
|
end
|
50
|
-
@module_item = set_module if @module_type
|
51
71
|
@files = xml.xpath("//FILES/FILE").map do |file|
|
52
72
|
ContentFile.new(file)
|
53
73
|
end
|
74
|
+
@module_item = set_module if @module_type
|
54
75
|
self
|
55
76
|
end
|
56
77
|
|
78
|
+
def set_module
|
79
|
+
module_item = ModuleItem.new(@title, @module_type, @id, @url)
|
80
|
+
module_item.canvas_conversion
|
81
|
+
end
|
82
|
+
|
57
83
|
def get_pre_data(xml, file_name)
|
58
84
|
id = xml.xpath("/CONTENT/@id").first.text
|
59
85
|
parent_id = xml.xpath("/CONTENT/PARENTID/@value").first.text
|
@@ -64,12 +90,6 @@ module Senkyoshi
|
|
64
90
|
}
|
65
91
|
end
|
66
92
|
|
67
|
-
def set_module
|
68
|
-
@module_type = "Quizzes::Quiz" if @module_type == "Quiz"
|
69
|
-
module_item = ModuleItem.new(@title, @module_type, @id)
|
70
|
-
module_item.canvas_conversion
|
71
|
-
end
|
72
|
-
|
73
93
|
def canvas_conversion(course, _resources = nil)
|
74
94
|
course
|
75
95
|
end
|
@@ -81,7 +101,8 @@ module Senkyoshi
|
|
81
101
|
if cc_module
|
82
102
|
cc_module.module_items << @module_item
|
83
103
|
else
|
84
|
-
|
104
|
+
title = @parent_title || @title
|
105
|
+
cc_module = Module.new(title, @parent_id)
|
85
106
|
cc_module = cc_module.canvas_conversion
|
86
107
|
cc_module.module_items << @module_item
|
87
108
|
course.canvas_modules << cc_module
|
@@ -2,17 +2,34 @@ require "senkyoshi/models/resource"
|
|
2
2
|
|
3
3
|
module Senkyoshi
|
4
4
|
class ContentFile < Resource
|
5
|
-
|
5
|
+
attr_reader(:id, :name, :linkname)
|
6
6
|
|
7
7
|
def initialize(xml)
|
8
8
|
@id = xml.xpath("./@id").first.text
|
9
|
-
@name = xml.xpath("./NAME").first.text
|
10
9
|
@linkname = xml.xpath("./LINKNAME/@value").first.text
|
10
|
+
@name = ContentFile.clean_xid xml.xpath("./NAME").first.text
|
11
11
|
end
|
12
12
|
|
13
|
-
|
13
|
+
##
|
14
|
+
# Remove leading slash if necessary so that ContentFile.name will match
|
15
|
+
# the Senkyoshi.xid
|
16
|
+
##
|
17
|
+
def self.clean_xid(xid)
|
18
|
+
if xid.start_with? "/"
|
19
|
+
xid[1..-1]
|
20
|
+
else
|
21
|
+
xid
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.correct_linkname(canvas_file)
|
26
|
+
canvas_file.file_path.split("/").last
|
27
|
+
end
|
28
|
+
|
29
|
+
def canvas_conversion(canvas_file = nil)
|
30
|
+
path = canvas_file ? canvas_file.file_path : @linkname
|
14
31
|
query = "?canvas_download=1&canvas_qs_wrap=1"
|
15
|
-
href = "$IMS_CC_FILEBASE$/#{
|
32
|
+
href = "$IMS_CC_FILEBASE$/#{path}#{query}"
|
16
33
|
%{
|
17
34
|
<a
|
18
35
|
class="instructure_scribd_file instructure_file_link"
|
@@ -3,23 +3,23 @@ require "senkyoshi/exceptions"
|
|
3
3
|
|
4
4
|
module Senkyoshi
|
5
5
|
class SenkyoshiFile < Resource
|
6
|
-
attr_accessor(:
|
7
|
-
@@dir = nil
|
6
|
+
attr_accessor(:xid, :location, :path)
|
8
7
|
|
9
8
|
FILE_BLACKLIST = [
|
10
9
|
"*.dat",
|
11
10
|
].freeze
|
12
11
|
|
13
12
|
def initialize(zip_entry)
|
14
|
-
path = zip_entry.name
|
15
|
-
id = File.basename(path)
|
16
|
-
xid = id[/__(xid-[0-9]+_[0-9]+)/, 1]
|
17
|
-
name = id.gsub(/__xid-[0-9]+_[0-9]+/, "")
|
18
|
-
|
13
|
+
@path = strip_xid zip_entry.name
|
19
14
|
@location = extract_file(zip_entry) # Location of file on local filesystem
|
20
|
-
|
21
|
-
|
22
|
-
@xid = xid
|
15
|
+
|
16
|
+
base_name = File.basename(zip_entry.name)
|
17
|
+
@xid = base_name[/__(xid-[0-9]+_[0-9]+)/, 1] ||
|
18
|
+
Senkyoshi.create_random_hex
|
19
|
+
end
|
20
|
+
|
21
|
+
def strip_xid(name)
|
22
|
+
name.gsub(/__xid-[0-9]+_[0-9]+/, "")
|
23
23
|
end
|
24
24
|
|
25
25
|
def matches_xid?(xid)
|
@@ -27,9 +27,9 @@ module Senkyoshi
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def extract_file(entry)
|
30
|
-
|
30
|
+
@dir ||= Dir.mktmpdir
|
31
31
|
|
32
|
-
name = "#{
|
32
|
+
name = "#{@dir}/#{entry.name}"
|
33
33
|
path = File.dirname(name)
|
34
34
|
FileUtils.mkdir_p path unless Dir.exist? path
|
35
35
|
entry.extract(name)
|
@@ -38,9 +38,9 @@ module Senkyoshi
|
|
38
38
|
|
39
39
|
def canvas_conversion(course, _resources = nil)
|
40
40
|
file = CanvasCc::CanvasCC::Models::CanvasFile.new
|
41
|
-
file.identifier = @
|
41
|
+
file.identifier = @xid
|
42
42
|
file.file_location = @location
|
43
|
-
file.file_path =
|
43
|
+
file.file_path = @path
|
44
44
|
file.hidden = false
|
45
45
|
|
46
46
|
course.files << file
|
@@ -50,8 +50,8 @@ module Senkyoshi
|
|
50
50
|
##
|
51
51
|
# Remove temporary files
|
52
52
|
##
|
53
|
-
def
|
54
|
-
FileUtils.rm_r
|
53
|
+
def cleanup
|
54
|
+
FileUtils.rm_r @dir unless @dir.nil?
|
55
55
|
end
|
56
56
|
|
57
57
|
##
|
@@ -64,14 +64,15 @@ module Senkyoshi
|
|
64
64
|
##
|
65
65
|
# Determine whether or not a file is a metadata file or not
|
66
66
|
##
|
67
|
-
def self.metadata_file?(
|
67
|
+
def self.metadata_file?(entry_names, file)
|
68
68
|
if File.extname(file.name) == ".xml"
|
69
69
|
# Detect and skip metadata files.
|
70
|
-
|
70
|
+
non_meta_file = File.join(
|
71
71
|
File.dirname(file.name),
|
72
72
|
File.basename(file.name, ".xml"),
|
73
73
|
)
|
74
|
-
|
74
|
+
|
75
|
+
entry_names.include?(non_meta_file)
|
75
76
|
else
|
76
77
|
false
|
77
78
|
end
|
@@ -89,9 +90,9 @@ module Senkyoshi
|
|
89
90
|
##
|
90
91
|
# Determine if a file should be included in course files or not
|
91
92
|
##
|
92
|
-
def self.valid_file?(
|
93
|
+
def self.valid_file?(entry_names, scorm_paths, file)
|
93
94
|
return false if SenkyoshiFile.blacklisted? file
|
94
|
-
return false if SenkyoshiFile.metadata_file?
|
95
|
+
return false if SenkyoshiFile.metadata_file? entry_names, file
|
95
96
|
return false if SenkyoshiFile.belongs_to_scorm_package? scorm_paths, file
|
96
97
|
true
|
97
98
|
end
|
@@ -3,16 +3,13 @@ module Senkyoshi
|
|
3
3
|
def get_pre_data(data, _)
|
4
4
|
categories = get_categories(data)
|
5
5
|
data.search("OUTCOMEDEFINITIONS").children.map do |outcome|
|
6
|
-
content_id = outcome.at("CONTENTID").attributes["value"].value
|
7
|
-
assignment_id = outcome.at("ASIDATAID").attributes["value"].value
|
8
6
|
category_id = outcome.at("CATEGORYID").attributes["value"].value
|
9
|
-
category = categories[category_id]
|
10
|
-
points = outcome.at("POINTSPOSSIBLE").attributes["value"].value
|
11
7
|
{
|
12
|
-
category:
|
13
|
-
points:
|
14
|
-
content_id:
|
15
|
-
assignment_id:
|
8
|
+
category: categories[category_id],
|
9
|
+
points: outcome.at("POINTSPOSSIBLE").attributes["value"].value,
|
10
|
+
content_id: outcome.at("CONTENTID").attributes["value"].value,
|
11
|
+
assignment_id: outcome.at("ASIDATAID").attributes["value"].value,
|
12
|
+
due_at: outcome.at("DUE").attributes["value"].value,
|
16
13
|
}
|
17
14
|
end
|
18
15
|
end
|
@@ -2,12 +2,13 @@ require "senkyoshi/models/resource"
|
|
2
2
|
|
3
3
|
module Senkyoshi
|
4
4
|
class ModuleItem < Resource
|
5
|
-
def initialize(title, type, identifierref)
|
5
|
+
def initialize(title, type, identifierref, url)
|
6
6
|
@title = title
|
7
7
|
@identifier = Senkyoshi.create_random_hex
|
8
8
|
@content_type = type
|
9
9
|
@identifierref = identifierref
|
10
10
|
@workflow_state = "active"
|
11
|
+
@url = url
|
11
12
|
end
|
12
13
|
|
13
14
|
def canvas_conversion(*)
|
@@ -17,6 +18,7 @@ module Senkyoshi
|
|
17
18
|
item.content_type = @content_type
|
18
19
|
item.identifierref = @identifierref
|
19
20
|
item.workflow_state = @workflow_state
|
21
|
+
item.url = @url
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|