github-to-canvas 0.0.58 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef90c29bdb5096d81deb8c51acdf5e53ff2c58da6c968f220d9be7df5eef795a
4
- data.tar.gz: dfdd350bcc6877d9e3c2d42b76096c6b6ac8abe9f4e96c77d48726cf5aa51748
3
+ metadata.gz: cae13e5551446c7306ce3d8d90a12fa47a3caedbcebdc749b1852456b558c695
4
+ data.tar.gz: 2501db731b91ab03fafae8a42eeaed104228cab7f5dcffaf21723558e9ac03f3
5
5
  SHA512:
6
- metadata.gz: 82c2f07ef261dccdabc60c938b0165a92d5f9853e2c1cb1f80783784918ea177b5c681093c6e4004211beee622e060afa2b760cc1f8ba56718b6513044008032
7
- data.tar.gz: 71d0b3e3de82994df654e595a6d9e0a9f6bc8c6c3d81e404f7991cac47795109ec73f2d6f04a853e624e4bf7c83c3b7c7cb092220e8d9175331139478f058ef7
6
+ metadata.gz: daf5758513ab73925cb7b7f402112ead3e9c0b3bcb4a59d6f227d5eb04ab710c7c9ecf06d3edf9326172d5758a8625a158e508f6eb68e740f8c5efd8cf31bc31
7
+ data.tar.gz: 38cf70d8025eed5b8128e7885bb21ac9c8a25b94c89a0bd2fb00df7421ecc80df02615c26e335cb86bdce16d1d5653898617332a31249ce0478050b5a89f3818
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'optparse'
3
3
  require 'github-to-canvas'
4
+
4
5
  options = {}
5
6
  OptionParser.new do |opts|
6
7
  opts.banner = <<-EOBANNER
@@ -29,23 +30,40 @@ OptionParser.new do |opts|
29
30
  Run these commands from inside a local GitHub repository. This gem is built for Flatiron School's internal use.
30
31
  Some default behaviors assume this, like the default Canvas API path.
31
32
 
32
- Example usage:
33
+ Create and Update Canvas Lessons From Inside a Local GitHub Repo Folder:
34
+
35
+ github-to-canvas --create-lesson 154 -> Creates a lesson in course 154, derives the name and type from the local repo
36
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" -> Creates a lesson in course 154 with the provided name, derives the type from the local repo
37
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" --type assignment -> Creates an assignment in course 154 with the provided name
38
+ github-to-canvas --create-lesson 154 --name "Fetch Lab" --branch solution -> Creates a lesson in course 154 with the provided name, uses the repository's solution branch and derives the type from the local repo
39
+ github-to-canvas --align -> Patches existing lessons in Canvas based on the .canvas file
40
+ github-to-canvas --align --fis-links -> Patches existing lessons in Canvas based on the .canvas file, adds additional Flatiron School specific HTML and meta-data
41
+ github-to-canvas --align --remove-header-and-footer -> Patches existing lessons in Canvas based on the .canvas file, removes top lesson header before converting to HTML
42
+
43
+ Get Info on a Canvas Course, Lesson or GitHub Repo:
44
+
45
+ github-to-canvas --query COURSE -> Displays a course's modules and their lessons in course order as YAML
46
+ github-to-canvas --map YAML -> Uses a YAML file created with --query to retrieve repositories that were associated with Canvas lessons using --fis-links. Returns an updated YAML.
47
+ github-to-canvas --read-from-canvas CANVAS_LESSON_URL -> Retrieves a lesson's contents and information from Canvas
48
+ github-to-canvas --read-from-github GITHUB_URL -> Retrieves the provided GitHub markdown file, converted into HTML
49
+
50
+ Create and Update Canvas Lessons Using Remote GitHub Repositories:
51
+
52
+ github-to-canvas --create-from-github GITHUB_URL --course COURSE_ID --type TYPE -> Creates a lesson in the provided course using the remote GitHub URL. Source must be from a public repo.
53
+ github-to-canvas --align-from-github GITHUB_URL --course COURSE_ID --id LESSON_ID --type TYPE -> Updates a lesson in the provided course using the remote GitHub URL. Source must be from a public repo.
33
54
 
34
- github-to-canvas --create-lesson 154 -> Creates a lesson in course 154, derives the name and type from the local repo
35
- github-to-canvas --create-lesson 154 --name "Fetch Lab" -> Creates a lesson in course 154 with the provided name, derives the type from the local repo
36
- github-to-canvas --create-lesson 154 --name "Fetch Lab" --type assignment -> Creates an assignment in course 154 with the provided name
37
- github-to-canvas --create-lesson 154 --name "Fetch Lab" --branch solution -> Creates a lesson in course 154 with the provided name, uses the repository's solution branch and derives the type from the local repo
38
- github-to-canvas --align -> Patches existing lessons in Canvas based on the .canvas file
39
- github-to-canvas --align --fis-links -> Patches existing lessons in Canvas based on the .canvas file, adds additional Flatiron School specific HTML and meta-data
40
- github-to-canvas --align --remove-header-and-footer -> Patches existing lessons in Canvas based on the .canvas file, removes top lesson header before converting to HTML
41
- github-to-canvas --info COURSE -> Displays a course's lesson and assignment names
55
+ Create and Update Canvas Courses From YAML:
56
+
57
+ github-to-canvas --build-course YAML_FILE -> Uses the provided YAML file to create a course, add modules and populate them with lessons using remote GitHub repositories
58
+ github-to-canvas --add-to-course YAML_FILE --course -> Uses a YAML file to a modules and lessons to an existing course.
59
+ github-to-canvas --update-course YAML_FILE -> Uses a YAML file to update lessons using their associated GitHub repositories (ignores module/course structure in YAML file)
42
60
 
43
61
  EOBANNER
44
62
 
45
63
  opts.on("-cCOURSE", "--create-lesson COURSE",
46
64
  "Creates a new canvas lesson, converting the local repository's README.md to HTML. Adds .canvas file to remote repository") do |course|
47
65
  options[:create_lesson] = true
48
- options[:course] = course
66
+ options[:course_id] = course
49
67
  end
50
68
  opts.on("-bBRANCH", "--branch BRANCH",
51
69
  "Sets the repository branch used for lesson creation") do |branch|
@@ -93,8 +111,8 @@ OptionParser.new do |opts|
93
111
  options[:remove_header_and_footer] = true
94
112
  end
95
113
  opts.on("--course COURSE",
96
- "For align functionality only - updates the HTML content of a lesson using the provided course ID. Use with --id.") do |course|
97
- options[:course] = course
114
+ "For align functionality only - updates the HTML content of a lesson using the provided course ID. Use with --id.") do |course_id|
115
+ options[:course_id] = course_id
98
116
  end
99
117
  opts.on("--id ID",
100
118
  "For align functionality only - updates the HTML content of a lesson using the provided assignment or page ID. Use with --course.") do |id|
@@ -108,30 +126,134 @@ OptionParser.new do |opts|
108
126
  "Displays a course's lessons and assignments") do |course|
109
127
  options[:query] = course
110
128
  end
111
- opts.on("--remote",
112
- "Retrieves a Canvas lesson. Requires --course and --id") do |remote|
113
- options[:remote] = true
129
+ opts.on("--map YAML_FILE",
130
+ "REQUIRES -f or --file Associates canvas lessons with repositories. Use query to create required YAML file") do |file|
131
+ options[:map] = file
132
+ end
133
+ opts.on("--read-from-canvas CANVAS_URL",
134
+ "Retrieves an existing Canvas lesson using the provided URL") do |url|
135
+ options[:read_from_canvas] = url
136
+ end
137
+ opts.on("--read-from-github GITHUB_URL",
138
+ "Converts an existing GitHub Readme to HTML using the provided URL. URL must be for a GitHub markdown file") do |url|
139
+ options[:read_from_github] = url
140
+ end
141
+ opts.on("--create-from-github GITHUB_URL",
142
+ "Creates a new Canvas lesson from a remote GitHub Readme. --course and --type options required") do |url|
143
+ options[:create_from_github] = url
144
+ end
145
+ opts.on("--create-quiz-from-github GITHUB_URL",
146
+ "Creates a new Canvas quiz from a remote GitHub YAML file. --course option required") do |url|
147
+ options[:quiz_from_github] = url
148
+ end
149
+ opts.on("--align-from-github GITHUB_URL",
150
+ "Aligns an existing Canvas lesson using a remote GitHub Readme. --course, --id, and --type options required") do |url|
151
+ options[:align_from_github] = url
152
+ end
153
+ opts.on("--build-course YAML_FILE",
154
+ "Creates Canvas course using provided YAML file") do |file|
155
+ options[:build_course] = file
156
+ end
157
+ opts.on("--add-to-course YAML_FILE",
158
+ "Creates Canvas course using provided YAML file") do |file|
159
+ options[:add_to_course] = file
160
+ end
161
+ opts.on("--update-course-lessons YAML_FILE",
162
+ "Updates all lessons in a course using remote repos in provided YAML file") do |file|
163
+ options[:update_course_lessons] = file
114
164
  end
115
-
116
165
 
117
166
  end.parse!
118
167
 
119
168
  if options[:version]
120
- GithubToCanvas.new(mode: 'version', course: nil)
169
+ GithubToCanvas.new(mode: 'version', course_id: nil)
170
+ abort
171
+ end
172
+
173
+ if options[:read_from_canvas]
174
+ GithubToCanvas.new(mode: 'canvas_read', filepath: options[:read_from_canvas])
175
+ abort
176
+ end
177
+
178
+ if options[:read_from_github]
179
+ GithubToCanvas.new(mode: 'github_read', filepath: options[:read_from_github])
180
+ abort
181
+ end
182
+
183
+ if options[:create_from_github]
184
+ if options[:course_id] && options[:type]
185
+ GithubToCanvas.new(mode: 'github_create',
186
+ filepath: options[:create_from_github],
187
+ course_id: options[:course_id],
188
+ type: options[:type],
189
+ remove_header_and_footer: !!options[:remove_header_and_footer],
190
+ forkable: !!options[:forkable],
191
+ fis_links: !!options[:fis])
192
+ else
193
+ puts 'Canvas course ID and lesson type required. Example: github-to-canvas --create-from-github URL --course ID --type TYPE'
194
+ end
195
+ abort
196
+ end
197
+
198
+ if options[:align_from_github]
199
+ if options[:course_id] && options[:type] && options[:id]
200
+ GithubToCanvas.new(mode: 'github_align',
201
+ filepath: options[:align_from_github],
202
+ course_id: options[:course_id],
203
+ type: options[:type],
204
+ id: options[:id],
205
+ remove_header_and_footer: !!options[:remove_header_and_footer],
206
+ forkable: !!options[:forkable],
207
+ fis_links: !!options[:fis])
208
+ else
209
+ puts 'Canvas course ID, lesson ID, and type required. Example: github-to-canvas --create-from-github URL --course COURSE_ID --id LESSON_ID --type TYPE'
210
+ end
211
+ abort
121
212
  end
122
213
 
123
214
  if options[:query]
124
- GithubToCanvas.new(mode: 'query', course: options[:query], id: options[:id])
215
+ GithubToCanvas.new(mode: 'query', course_id: options[:query], id: options[:id])
216
+ abort
217
+ end
218
+
219
+ if options[:map]
220
+ GithubToCanvas.new(mode: 'map', file_to_convert: options[:map])
221
+ abort
125
222
  end
126
223
 
127
- if options[:remote]
128
- if !options[:course] || !options[:id]
129
- puts "Both --course and --id required when using --remote"
130
- abort
224
+ if options[:build_course]
225
+ GithubToCanvas.new(mode: 'build_course',
226
+ file_to_convert: options[:build_course],
227
+ fis_links: !!options[:fis],
228
+ remove_header_and_footer: !!options[:remove_header_and_footer],
229
+ forkable: !!options[:forkable])
230
+ abort
231
+ end
232
+
233
+ if options[:add_to_course]
234
+ if options[:course_id]
235
+ GithubToCanvas.new(mode: 'add_to_course',
236
+ course_id: options[:course_id],
237
+ file_to_convert: options[:add_to_course],
238
+ fis_links: !!options[:fis],
239
+ remove_header_and_footer: !!options[:remove_header_and_footer],
240
+ forkable: !!options[:forkable])
241
+ else
242
+ puts '--course required'
131
243
  end
132
- GithubToCanvas.new(mode: 'remote', course: options[:course], id: options[:id])
244
+ abort
245
+ end
246
+
247
+ if options[:update_course_lessons]
248
+ GithubToCanvas.new(mode: 'update_course_lessons',
249
+ file_to_convert: options[:update_course_lessons],
250
+ fis_links: !!options[:fis],
251
+ remove_header_and_footer: !!options[:remove_header_and_footer],
252
+ forkable: !!options[:forkable])
253
+ abort
133
254
  end
134
255
 
256
+
135
257
  if !options[:type]
136
258
  if Dir.glob("**/*/").empty?
137
259
  options[:type] = "page"
@@ -174,7 +296,7 @@ end
174
296
 
175
297
  if options[:create_lesson]
176
298
  GithubToCanvas.new(mode: "create",
177
- course: options[:course],
299
+ course_id: options[:course_id],
178
300
  filepath: Dir.pwd,
179
301
  file_to_convert: options[:file_to_convert],
180
302
  branch: options[:branch],
@@ -189,7 +311,7 @@ end
189
311
 
190
312
  if options[:align]
191
313
  GithubToCanvas.new(mode: "align",
192
- course: options[:course],
314
+ course_id: options[:course_id],
193
315
  id: options[:id],
194
316
  filepath: Dir.pwd,
195
317
  file_to_convert: options[:file_to_convert],
@@ -1,56 +1,142 @@
1
+ require 'byebug'
1
2
  require_relative './github-to-canvas/create_canvas_lesson'
2
3
  require_relative './github-to-canvas/update_canvas_lesson'
4
+ require_relative './github-to-canvas/canvas_dotfile'
5
+ require_relative './github-to-canvas/repository_interface'
3
6
  require_relative './github-to-canvas/repository_converter'
4
7
  require_relative './github-to-canvas/github_interface'
5
8
  require_relative './github-to-canvas/canvas_interface'
6
- require_relative './github-to-canvas/canvas_dotfile'
9
+ require_relative './github-to-canvas/course_creation_interface'
10
+
7
11
  require_relative './github-to-canvas/version'
8
12
 
13
+ require 'yaml'
14
+
9
15
  class GithubToCanvas
10
16
 
11
- def initialize(mode:,
12
- course:nil,
13
- id:nil,
14
- filepath:Dir.pwd,
15
- file_to_convert:'README.md',
16
- branch:'master',
17
- name:File.basename(Dir.getwd),
18
- type:"page",
19
- save_to_github:false,
20
- fis_links:false,
21
- remove_header_and_footer:false,
22
- only_update_content: false,
23
- forkable: false)
24
-
25
- if mode == 'version'
17
+ def initialize(options)
18
+ case options[:mode]
19
+ when 'version'
26
20
  puts VERSION
27
- end
28
-
29
- if mode == 'query'
30
- CanvasInterface.get_course_info(course, id)
31
- end
32
-
33
- if mode == 'remote'
34
- lesson_data = CanvasInterface.get_lesson_info(course, id)
35
- if !lesson_data[1]
36
- puts "No lesson with id #{id} was found in course #{course}."
37
- else
38
- pp lesson_data[0]
39
- puts "\nLesson Type: #{lesson_data[1]}"
40
- end
21
+ when 'query'
22
+ CanvasInterface.get_course_info(options[:course_id], options[:id])
23
+ when 'map'
24
+ CanvasInterface.map_course_info(options[:file_to_convert])
25
+ when 'canvas_read'
26
+ puts CanvasInterface.read_lesson(options[:filepath])
27
+ when 'github_read'
28
+ markdown = GithubInterface.read_remote(options[:filepath])
29
+ puts RepositoryConverter.convert_to_html(markdown)
30
+ when 'create' # used with a local repo
31
+ html = RepositoryConverter.local_file_conversion(options)
32
+ name = RepositoryInterface.get_name(options[:filepath], html)
33
+ html = RepositoryConverter.adjust_converted_html(options, html)
34
+ response = CanvasInterface.create_lesson(options, name, html)
35
+ RepositoryInterface.local_repo_post_submission(options, response)
36
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
37
+ when 'align' # used with a local repo
38
+ html = RepositoryConverter.local_file_conversion(options)
39
+ name = RepositoryInterface.get_name(options[:filepath], html)
40
+ html = RepositoryConverter.adjust_converted_html(options, html)
41
+ CanvasInterface.update_all_related_lessons(options, name, html)
41
42
 
43
+ when 'github_create'
44
+ html = RepositoryConverter.remote_file_conversion(options)
45
+ name = RepositoryInterface.get_name(options[:filepath], html)
46
+ html = RepositoryConverter.adjust_converted_html(options, html)
42
47
 
43
- end
48
+ response = CanvasInterface.create_lesson(options, name, html)
49
+
50
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
51
+ when 'github_align'
52
+ html = RepositoryConverter.remote_file_conversion(options)
53
+ name = RepositoryInterface.get_name(options[:filepath], html)
54
+ html = RepositoryConverter.adjust_converted_html(options, html)
55
+ response = CanvasInterface.update_existing_lesson(options, name, html)
56
+ puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
57
+ when 'build_course'
58
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
59
+ # Create Course
60
+ created_course_info = CanvasInterface.create_course(course_yaml)
61
+ puts "Course created - #{created_course_info["id"]}"
44
62
 
45
- if mode == 'create'
46
- puts "github-to-canvas will now create a Canvas lesson based on the current repo"
47
- CreateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, forkable)
48
- end
63
+ course_yaml[:modules].each { |module_info|
64
+ # Create each module
65
+ created_module_info = CanvasInterface.create_module(created_course_info["id"], module_info)
66
+ puts "Module created - #{created_module_info['name']}"
67
+ module_info[:lessons].each { |lesson|
68
+ # Create each lesson
69
+ options[:type] = lesson["type"].downcase
70
+ options[:course_id] = created_course_info["id"]
71
+ options[:filepath] = lesson["repository"]
72
+
73
+
74
+ html = RepositoryConverter.remote_file_conversion(options)
75
+ # Add each lesson to it's module
76
+
77
+ html = RepositoryConverter.adjust_converted_html(options, html)
78
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
79
+ lesson = lesson.merge(created_lesson_info)
80
+
81
+ lesson["page_url"] = lesson["url"] if !lesson["page_url"]
82
+
83
+ response = CanvasInterface.add_to_module(created_course_info["id"], created_module_info, lesson)
84
+
85
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
86
+ sleep(1)
87
+ }
88
+ }
89
+ when 'add_to_course'
90
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
49
91
 
50
- if mode == 'align'
51
- puts "github-to-canvas will now align any existing Canvas lessons based on the current repo. NOTE: .canvas file must be present"
52
- UpdateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, only_update_content, id, forkable)
92
+ course_yaml[:modules].each { |module_info|
93
+ # Create each module
94
+ created_module_info = CanvasInterface.create_module(options[:course_id], module_info)
95
+ puts "Module created - #{created_module_info['name']}"
96
+ module_info[:lessons].each { |lesson|
97
+ # Create each lesson
98
+
99
+ options[:type] = lesson["type"].downcase
100
+ options[:filepath] = lesson["repository"]
101
+ html = RepositoryConverter.remote_file_conversion(options)
102
+ # Add each lesson to it's module
103
+ html = RepositoryConverter.adjust_converted_html(options, html)
104
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
105
+ lesson = lesson.merge(created_lesson_info)
106
+ response = CanvasInterface.add_to_module(options[:course_id], created_module_info, lesson)
107
+
108
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
109
+ sleep(1)
110
+ }
111
+ }
112
+ when 'update_course_lessons'
113
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
114
+ options[:course_id] = course_yaml[:id]
115
+ course_yaml[:modules].each { |module_info|
116
+ puts "Updating #{module_info[:name]}"
117
+ module_info[:lessons].each { |lesson|
118
+ if lesson["repository"] == ""
119
+ puts "No repository found for #{lesson['title']}"
120
+ next
121
+ end
122
+ options[:id] = lesson['id']
123
+ options[:type] = lesson["type"].downcase
124
+ options[:filepath] = lesson["repository"]
125
+ options[:branch] = 'master'
126
+ html = RepositoryConverter.remote_file_conversion(options)
127
+
128
+ html = RepositoryConverter.adjust_converted_html(options, html)
129
+ created_lesson_info = CanvasInterface.update_existing_lesson(options, lesson["title"], html)
130
+ lesson = lesson.merge(created_lesson_info)
131
+
132
+
133
+ puts "Lesson updated - #{lesson['title']}"
134
+ sleep(1)
135
+ }
136
+ }
137
+ else
138
+ puts VERSION
53
139
  end
54
140
  end
55
-
141
+
56
142
  end
@@ -5,21 +5,21 @@ class CanvasDotfile
5
5
  File.file?(".canvas")
6
6
  end
7
7
 
8
- def self.update_or_create(filepath, response, course, type)
8
+ def self.update_or_create(options, response)
9
9
  if self.exists?
10
- if type == "assignment" || type == "discussion"
11
- canvas_data = self.update_assignment_data(response, course, type)
10
+ if options[:type] == "assignment" || options[:type] == "discussion"
11
+ canvas_data = self.update_assignment_data(response, options[:course_id], options[:type])
12
12
  else
13
- canvas_data = self.update_page_data(response, course, type)
13
+ canvas_data = self.update_page_data(response, options[:course_id], options[:type])
14
14
  end
15
15
  else
16
- if type == "assignment" || type == "discussion"
17
- canvas_data = self.create_assignment_data(response, course, type)
16
+ if options[:type] == "assignment" || options[:type] == "discussion"
17
+ canvas_data = self.create_assignment_data(response, options[:course_id], options[:type])
18
18
  else
19
- canvas_data = self.create_page_data(response, course, type)
19
+ canvas_data = self.create_page_data(response, options[:course_id], options[:type])
20
20
  end
21
21
  end
22
- self.create_canvas_dotfile(filepath, canvas_data)
22
+ self.create_canvas_dotfile(options[:filepath], canvas_data)
23
23
  end
24
24
 
25
25
  def self.create_canvas_dotfile(filepath, canvas_data)
@@ -64,7 +64,7 @@ class CanvasDotfile
64
64
 
65
65
  def self.update_page_data(response, course, type)
66
66
  canvas_data = YAML.load(File.read(".canvas"))
67
- if canvas_data[:lessons].none? { |lesson| lesson[:page_id] == response['page_id'] && lesson[:course_id] == course.to_i && lesson[:canvas_url] == response['html_url']}
67
+ if canvas_data[:lessons].none? { |lesson| lesson[:id] == response['page_id'] && lesson[:course_id] == course.to_i && lesson[:canvas_url] == response['html_url']}
68
68
  lesson_data = {
69
69
  id: response['page_id'],
70
70
  course_id: course.to_i,