github-to-canvas 0.0.58 → 0.1.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: 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,