coursegen 0.8.1 → 0.9.3
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 +4 -4
- data/.github/workflows/pr.yml +19 -0
- data/.gitignore +3 -0
- data/Gemfile.lock +80 -57
- data/README.md +285 -69
- data/Rakefile +10 -1
- data/coursegen.gemspec +26 -26
- data/lib/coursegen.rb +5 -2
- data/lib/coursegen/cli.rb +49 -14
- data/lib/coursegen/course/data/citem.rb +10 -1
- data/lib/coursegen/course/data/data_adaptor.rb +16 -6
- data/lib/coursegen/course/data/section.rb +1 -1
- data/lib/coursegen/course/helpers/bootstrap_markup.rb +15 -15
- data/lib/coursegen/course/helpers/content_helpers.rb +158 -94
- data/lib/coursegen/course/helpers/formatting_helpers.rb +6 -10
- data/lib/coursegen/course/helpers/ical_feed_helpers.rb +2 -1
- data/lib/coursegen/course/helpers/lecture_helpers.rb +3 -2
- data/lib/coursegen/course/helpers/list_of.rb +40 -20
- data/lib/coursegen/course/helpers/list_of_helpers.rb +20 -14
- data/lib/coursegen/course/helpers/logging_helpers.rb +13 -12
- data/lib/coursegen/course/helpers/navigation_helpers.rb +62 -23
- data/lib/coursegen/course/helpers/sidebar_helpers.rb +19 -18
- data/lib/coursegen/course/helpers/table_helpers.rb +5 -4
- data/lib/coursegen/course/schedule/scheduler.rb +52 -19
- data/lib/coursegen/templates.rb +30 -23
- data/lib/coursegen/version.rb +3 -1
- data/spec/lectures_spec.rb +60 -50
- data/spec/play_spec.rb +24 -12
- data/spec/scheduler_spec.rb +87 -27
- data/tech_debt.md +5 -0
- data/templates/Rules +14 -19
- data/templates/cg_config.rb +105 -21
- data/templates/content/bootstrap/css/custom.css +87 -151
- data/templates/content/bootstrap/css/full-width-pics.css +8 -64
- data/templates/content/bootstrap/css/postit.css +7 -0
- data/templates/content/bootstrap/css/toasty.css +3 -0
- data/templates/content/content/index.md.erb +1 -1
- data/templates/content/content/intro/course_toc.md.erb +0 -1
- data/templates/content/content/intro/welcome.md.erb +1 -3
- data/templates/content/content/lectures/part1/02_here_we_go.md.erb +22 -1
- data/templates/content/content/lectures/part2/01_start_part2.md.erb +2 -1
- data/templates/content/content/lectures/part2/02_continue_part2.md.erb +3 -2
- data/templates/layouts/banner.html.erb +4 -4
- data/templates/layouts/body_footer.html +3 -4
- data/templates/layouts/body_header.html.erb +25 -7
- data/templates/layouts/bottom_includes.html.erb +21 -10
- data/templates/layouts/course.html.erb +7 -21
- data/templates/layouts/helpful_box.html +1 -1
- data/templates/layouts/nav-menus.html.erb +16 -36
- data/templates/layouts/sidebar.html.erb +9 -8
- data/templates/layouts/slides.html.erb +69 -0
- data/templates/layouts/top_includes.html.erb +24 -23
- metadata +36 -28
- data/.DS_Store +0 -0
- data/.vscode/settings.json +0 -2
- data/templates/.DS_Store +0 -0
- data/templates/Guardfile +0 -9
- data/templates/content/bootstrap/css/tipuesearch.css +0 -163
- data/templates/content/bootstrap/js/tipuesearch.js +0 -379
- data/templates/content/bootstrap/js/tipuesearch.min.js +0 -12
- data/templates/content/bootstrap/js/tipuesearch_content.js +0 -13
- data/templates/content/bootstrap/js/tipuesearch_set.js +0 -23
- data/templates/layouts/main_navbar.html.erb +0 -21
data/Rakefile
CHANGED
data/coursegen.gemspec
CHANGED
@@ -1,37 +1,37 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'coursegen/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'coursegen'
|
8
7
|
spec.version = Coursegen::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
8
|
+
spec.authors = ['Pito Salas']
|
9
|
+
spec.email = ['pitosalas@gmail.com']
|
10
|
+
spec.summary = 'Use Nanoc to build courses and deploy them to S3'
|
11
|
+
spec.description = 'Use Nanoc to build courses and deploy them to S3'
|
12
|
+
spec.homepage = ''
|
13
|
+
spec.license = 'MIT'
|
15
14
|
|
16
15
|
spec.files = `git ls-files -z`.split("\x0")
|
17
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
18
|
+
spec.require_paths = ['lib']
|
20
19
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
|
24
|
-
|
25
|
-
spec.add_dependency
|
26
|
-
spec.add_dependency
|
27
|
-
spec.add_dependency
|
28
|
-
spec.add_dependency
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
31
|
-
spec.add_dependency
|
32
|
-
spec.add_dependency
|
33
|
-
spec.add_dependency
|
34
|
-
spec.add_dependency
|
35
|
-
spec.add_dependency
|
36
|
-
spec.add_dependency
|
20
|
+
spec.add_development_dependency 'bundler'
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_development_dependency 'rspec'
|
23
|
+
|
24
|
+
spec.add_dependency 'activesupport'
|
25
|
+
spec.add_dependency 'adsf'
|
26
|
+
spec.add_dependency 'byebug'
|
27
|
+
spec.add_dependency 'cri'
|
28
|
+
spec.add_dependency 'guard'
|
29
|
+
spec.add_dependency 'guard-shell'
|
30
|
+
spec.add_dependency 'icalendar'
|
31
|
+
spec.add_dependency 'kramdown'
|
32
|
+
spec.add_dependency 'nanoc'
|
33
|
+
spec.add_dependency 'nokogiri'
|
34
|
+
spec.add_dependency 'rubytree'
|
35
|
+
spec.add_dependency 'thor'
|
36
|
+
spec.add_dependency 'tzinfo'
|
37
37
|
end
|
data/lib/coursegen.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
|
3
5
|
require 'coursegen/version'
|
@@ -25,7 +27,8 @@ require 'coursegen/course/helpers/list_of'
|
|
25
27
|
require 'coursegen/course/helpers/ical_feed_helpers'
|
26
28
|
require 'coursegen/course/lib/helpers_'
|
27
29
|
|
28
|
-
|
30
|
+
# Coursegen is a course curriculum site generator based on nanoc, with
|
31
|
+
# support for sections, lectures, code examples, homeworks, course
|
32
|
+
# calendar and lots more.
|
29
33
|
module Coursegen
|
30
|
-
# Your code goes here...
|
31
34
|
end
|
data/lib/coursegen/cli.rb
CHANGED
@@ -1,46 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thor'
|
2
4
|
require 'coursegen/templates'
|
3
5
|
require 'nanoc'
|
4
6
|
require './cg_config.rb' if File.exist? 'cg_config.rb'
|
5
7
|
|
6
8
|
module CourseGen
|
9
|
+
# Class CLI provides a command line utility for creating, building, and
|
10
|
+
# deploying a Coursegen site.
|
7
11
|
class CLI < Thor
|
8
12
|
include Thor::Actions
|
9
13
|
|
10
|
-
|
14
|
+
# New creates a new nanoc site.
|
15
|
+
#
|
16
|
+
# By default, the new site does not contain any course template.
|
17
|
+
# To generate a course template within the newly created nanoc site,
|
18
|
+
# run: `cg prepare`.
|
19
|
+
#
|
20
|
+
# See: https://nanoc.ws/doc/reference/commands/#create-site
|
21
|
+
desc 'new COURSE',
|
22
|
+
'Create a new course by calling nanoc. Argument is name of the COURSE'
|
11
23
|
def new(course)
|
12
24
|
run("nanoc create-site #{course}")
|
13
25
|
end
|
14
26
|
|
15
|
-
|
27
|
+
# Prepare generates a new course template within a nanoc site.
|
28
|
+
desc 'prepare',
|
29
|
+
'Update with the latest coursegen code and templates.'
|
16
30
|
def prepare
|
17
31
|
check_valid_directory
|
18
32
|
tplt = CourseGen::Templates.new
|
19
33
|
tplt.generate_all
|
20
34
|
end
|
21
35
|
|
22
|
-
|
36
|
+
# Compile builds the course site and outputs it to a local directory.
|
37
|
+
#
|
38
|
+
# By default, it outputs the course site to ./output.
|
39
|
+
#
|
40
|
+
# See: https://nanoc.ws/doc/reference/commands/#compile
|
41
|
+
desc 'compile',
|
42
|
+
'build the course and put resultant site into output directory'
|
23
43
|
def compile
|
24
|
-
run
|
44
|
+
run 'nanoc compile'
|
25
45
|
end
|
26
46
|
|
27
|
-
|
47
|
+
# Serve starts a static web server that serves the course site.
|
48
|
+
#
|
49
|
+
# By default, the web server serves from ./output.
|
50
|
+
#
|
51
|
+
# See: https://nanoc.ws/doc/reference/commands/#view
|
52
|
+
desc 'serve',
|
53
|
+
'start local web server to test the course web site'
|
28
54
|
def serve
|
29
|
-
run
|
55
|
+
run 'nanoc view'
|
30
56
|
end
|
31
57
|
|
32
|
-
|
58
|
+
# Reset removes all generated contents.
|
59
|
+
desc 'reset',
|
60
|
+
'reset all generated content to bring the course back to a base state.'
|
33
61
|
def reset
|
34
|
-
run
|
35
|
-
run
|
62
|
+
run 'rm -frd tmp'
|
63
|
+
run 'rm -frd output'
|
36
64
|
end
|
37
65
|
|
38
|
-
|
66
|
+
# View opens an browser to the running course site.
|
67
|
+
desc 'view',
|
68
|
+
'view course site locally in browser'
|
39
69
|
def view
|
40
|
-
run
|
70
|
+
run 'open http://0.0.0.0:3000'
|
41
71
|
end
|
42
72
|
|
43
|
-
|
73
|
+
# Deploy deploys the course site to AWS S3.
|
74
|
+
#
|
75
|
+
# Note: `s3cmd` needs to be properly setup before this can work. Refer
|
76
|
+
# to README.md for detailed instructions.
|
77
|
+
desc 'deploy',
|
78
|
+
'Deploy course to S3'
|
44
79
|
def deploy
|
45
80
|
run "s3cmd sync --delete-removed output/ s3://#{AWS_BUCKET}/"
|
46
81
|
end
|
@@ -48,9 +83,9 @@ module CourseGen
|
|
48
83
|
no_commands do
|
49
84
|
def check_valid_directory
|
50
85
|
if CourseGen::Templates.new.valid_cg_directory?
|
51
|
-
say
|
86
|
+
say 'Valid cg directory'
|
52
87
|
else
|
53
|
-
error
|
88
|
+
error 'Invalid cg directory'
|
54
89
|
end
|
55
90
|
end
|
56
91
|
end
|
@@ -6,7 +6,8 @@ require 'active_support/inflector'
|
|
6
6
|
#
|
7
7
|
class CItem
|
8
8
|
attr_reader :order, :section, :subsection, :subsection_citem, :title,
|
9
|
-
:type, :identifier, :short_name, :status, :nitem, :css_class,
|
9
|
+
:type, :identifier, :short_name, :status, :nitem, :css_class,
|
10
|
+
:homework, :hwref, :desc, :cat, :assigned, :slides, :lectref, :reading, :due
|
10
11
|
attr_accessor :lecture_number, :lecture_date, :start_time, :end_time
|
11
12
|
|
12
13
|
# Callable with nitem=nil to create a mock
|
@@ -53,6 +54,7 @@ class CItem
|
|
53
54
|
|
54
55
|
def schedule_start_date_time
|
55
56
|
return if @lecture_date.nil?
|
57
|
+
|
56
58
|
# schedule = Toc.instance.section(@section).schedule
|
57
59
|
# lecture_date + schedule.start_time
|
58
60
|
lecture_date + @start_time
|
@@ -60,6 +62,7 @@ class CItem
|
|
60
62
|
|
61
63
|
def schedule_end_date_time
|
62
64
|
return if @lecture_date.nil?
|
65
|
+
|
63
66
|
# schedule = Toc.instance.section(@section).schedule
|
64
67
|
# lecture_date + schedule.end_time
|
65
68
|
lecture_date + @end_time
|
@@ -85,7 +88,13 @@ class CItem
|
|
85
88
|
@homework = @nitem[:homework]
|
86
89
|
@desc = @nitem[:desc]
|
87
90
|
@cat = @nitem[:cat]
|
91
|
+
@hwref = @nitem[:hwref]
|
88
92
|
@assigned = @nitem[:assigned]
|
93
|
+
@slides = @nitem[:slides]
|
94
|
+
@lectref = @nitem[:lectref]
|
95
|
+
@reading = @nitem[:reading]
|
96
|
+
@due = @nitem[:due]
|
97
|
+
|
89
98
|
end
|
90
99
|
|
91
100
|
def parse_identifier(ident)
|
@@ -5,8 +5,8 @@ class DataAdaptor
|
|
5
5
|
end
|
6
6
|
|
7
7
|
# column_selector is one of: :number, :date, :title, :homework
|
8
|
-
COL_NAMES = {number:
|
9
|
-
homework:
|
8
|
+
COL_NAMES = { number: '#', date: 'lecture date', title: 'title',
|
9
|
+
homework: 'homework', desc: 'description', cat: 'category', hwref: 'homework', lectref: 'topics', reading: 'reading' }
|
10
10
|
|
11
11
|
def column_name(column_selector)
|
12
12
|
COL_NAMES[column_selector]
|
@@ -30,6 +30,8 @@ class DataAdaptor
|
|
30
30
|
citem.identifier
|
31
31
|
when :desc
|
32
32
|
citem.desc
|
33
|
+
when :due
|
34
|
+
citem.due
|
33
35
|
when :homework
|
34
36
|
citem.homework
|
35
37
|
when :assigned
|
@@ -39,13 +41,21 @@ class DataAdaptor
|
|
39
41
|
when :end_date_time
|
40
42
|
citem.schedule_end_date_time
|
41
43
|
when :full_desc
|
42
|
-
desc = citem.desc ||
|
43
|
-
hw = citem.homework ||
|
44
|
-
desc +
|
44
|
+
desc = citem.desc || ''
|
45
|
+
hw = citem.homework || ''
|
46
|
+
desc + '. HW: ' + hw
|
45
47
|
when :cat
|
46
48
|
citem.cat
|
49
|
+
when :lectref
|
50
|
+
citem.lectref
|
51
|
+
when :hwref
|
52
|
+
citem.hwref
|
53
|
+
when :reading
|
54
|
+
citem.reading
|
55
|
+
when :order
|
56
|
+
citem.order
|
47
57
|
else
|
48
|
-
|
58
|
+
'error!'
|
49
59
|
end
|
50
60
|
end
|
51
61
|
end
|
@@ -60,7 +60,7 @@ class Section
|
|
60
60
|
def lookup_citem_by_identifier identifier
|
61
61
|
res = @citems.select { |i| i.identifier.to_s == identifier }
|
62
62
|
fail "TOC#lookup_citem_by_identifier failed to find: '#{identifier}'" if res.length != 1
|
63
|
-
|
63
|
+
byebug if res.length != 1
|
64
64
|
res[0]
|
65
65
|
end
|
66
66
|
|
@@ -1,32 +1,32 @@
|
|
1
|
+
# Class BootstrapMarkup provides methods for using Bootstrap specific HTML
|
2
|
+
# markups.
|
1
3
|
class BootstrapMarkup
|
2
4
|
def initialize
|
3
|
-
@str =
|
5
|
+
@str = ''
|
4
6
|
end
|
5
7
|
|
6
|
-
def table_begin(css_class =
|
7
|
-
puts css_class.class
|
8
|
+
def table_begin(css_class = 'table-condensed')
|
8
9
|
@str << "<table class=\"table x #{css_class}\">"
|
9
|
-
puts @str
|
10
10
|
end
|
11
11
|
|
12
12
|
def table_end
|
13
|
-
@str <<
|
13
|
+
@str << '</table>'
|
14
14
|
end
|
15
15
|
|
16
16
|
def headers_begin
|
17
|
-
@str <<
|
17
|
+
@str << '<thead><tr>'
|
18
18
|
end
|
19
19
|
|
20
20
|
def headers_end
|
21
|
-
@str <<
|
21
|
+
@str << '</tr></thead>'
|
22
22
|
end
|
23
23
|
|
24
24
|
def header_begin
|
25
|
-
@str <<
|
25
|
+
@str << '<th>'
|
26
26
|
end
|
27
27
|
|
28
28
|
def header_end
|
29
|
-
@str <<
|
29
|
+
@str << '</th>'
|
30
30
|
end
|
31
31
|
|
32
32
|
def header_content(str)
|
@@ -34,27 +34,27 @@ class BootstrapMarkup
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def row_begin
|
37
|
-
@str <<
|
37
|
+
@str << '<tr>'
|
38
38
|
end
|
39
39
|
|
40
40
|
def row_end
|
41
|
-
@str <<
|
41
|
+
@str << '</tr>'
|
42
42
|
end
|
43
43
|
|
44
44
|
def cell_begin
|
45
|
-
@str <<
|
45
|
+
@str << '<td>'
|
46
46
|
end
|
47
47
|
|
48
48
|
def cell_end
|
49
|
-
@str <<
|
49
|
+
@str << '</td>'
|
50
50
|
end
|
51
51
|
|
52
52
|
def bigcell_begin
|
53
|
-
@str <<
|
53
|
+
@str << '<td colspan="3"><h5>'
|
54
54
|
end
|
55
55
|
|
56
56
|
def bigcell_end
|
57
|
-
@str <<
|
57
|
+
@str << '</h5></td>'
|
58
58
|
end
|
59
59
|
|
60
60
|
def cell_content(str)
|
@@ -1,23 +1,22 @@
|
|
1
|
-
#
|
2
|
-
require 'byebug'
|
1
|
+
# ContentHelpers is used to annotate content.
|
3
2
|
module ContentHelpers
|
4
3
|
def include_topic(item_symbol)
|
5
|
-
incorporated_topic = lookup_nitem(
|
4
|
+
incorporated_topic = lookup_nitem('topics', item_symbol.to_s)
|
6
5
|
items[incorporated_topic.identifier.to_s].compiled_content
|
7
6
|
end
|
8
7
|
|
9
8
|
def include_page(item_symbol)
|
10
|
-
incorporated_topic = lookup_nitem(
|
9
|
+
incorporated_topic = lookup_nitem('pages', item_symbol.to_s)
|
11
10
|
items[incorporated_topic.identifier.to_s].compiled_content
|
12
11
|
end
|
13
12
|
|
14
13
|
def include_background(item_symbol)
|
15
|
-
incorporated_topic = lookup_nitem(
|
14
|
+
incorporated_topic = lookup_nitem('background', item_symbol.to_s)
|
16
15
|
items[incorporated_topic.identifier.to_s].compiled_content
|
17
16
|
end
|
18
17
|
|
19
18
|
def include_intro(item_symbol)
|
20
|
-
incorporated_topic = lookup_nitem(
|
19
|
+
incorporated_topic = lookup_nitem('intro', item_symbol.to_s)
|
21
20
|
items[incorporated_topic.identifier.to_s].compiled_content
|
22
21
|
end
|
23
22
|
|
@@ -47,69 +46,94 @@ module ContentHelpers
|
|
47
46
|
" *#{string}*{: style=\"color: red\"} "
|
48
47
|
end
|
49
48
|
|
50
|
-
def ir(string)
|
49
|
+
def ir(string)
|
50
|
+
italic_red(string)
|
51
|
+
end
|
51
52
|
|
52
|
-
def
|
53
|
+
def callout1(title, body)
|
53
54
|
<<~HTMLSTRING
|
54
|
-
<div class="well well-sm">
|
55
|
+
<div class="well well-sm callout">
|
55
56
|
<span class="themebg label label-primary">#{title}</span>#{body}
|
56
57
|
</div>
|
57
58
|
HTMLSTRING
|
58
59
|
end
|
59
60
|
|
60
|
-
def
|
61
|
+
def callout2(title, body)
|
61
62
|
<<~HTMLSTRING
|
62
|
-
<div class="border border-primary rounded p-2 m-3">
|
63
|
+
<div class="callout border border-primary rounded p-2 m-3">
|
63
64
|
<span class="badge badge-pill badge-primary">#{title}</span>#{body}
|
64
65
|
</div>
|
65
66
|
HTMLSTRING
|
66
67
|
end
|
67
68
|
|
69
|
+
def callout(title, body, style=:big)
|
70
|
+
if (style == :big)
|
71
|
+
%(<div class="jumbotron py-1 border border-primary border-rounded-lg">
|
72
|
+
<h1 class="display-5">#{title}</h1>
|
73
|
+
<p class="lead">#{body}</p></div>)
|
74
|
+
elsif (style == :small)
|
75
|
+
<<~HTMLSTRING
|
76
|
+
<div class="callout border border-primary rounded p-2 m-3">
|
77
|
+
<span class="badge badge-pill badge-primary">#{title}</span>#{body}
|
78
|
+
</div>
|
79
|
+
HTMLSTRING
|
80
|
+
end
|
81
|
+
"error in callout call."
|
82
|
+
end
|
83
|
+
|
84
|
+
def iconbadge1(icon, tooltip)
|
85
|
+
%(<img src="/bootstrap/bootstrap-icons-1.0.0/#{icon}.svg" title="#{tooltip}" class="iconbadge">)
|
86
|
+
end
|
87
|
+
|
88
|
+
def iconbadge(icon, tooltip)
|
89
|
+
%(<svg class="bi iconbadge" title="#{tooltip}" data-placement="top" data-title="#{tooltip}" data-toggle="tooltip" fill="blue"><use xlink:href="/bootstrap/bootstrap-icons-1.0.0/bootstrap-icons.svg##{icon}"/></svg>)
|
90
|
+
end
|
91
|
+
|
68
92
|
def textbadge(text, tooltip)
|
69
93
|
%(<span class="label label-info" data-toggle="tooltip" data-placement="top" title="#{tooltip}">#{text}</span>)
|
70
94
|
end
|
71
95
|
|
72
|
-
def
|
96
|
+
def iconbadge2(icon, tooltip)
|
73
97
|
%(<span class="fas fa-#{icon} themefg" data-toggle="tooltip" data-placement="top" title="#{tooltip}"></span>)
|
74
98
|
end
|
75
99
|
|
76
100
|
def pdfbadge
|
77
|
-
iconbadge(
|
101
|
+
iconbadge('file-earmark-richtext-fill', 'Submit a pdf file')
|
78
102
|
end
|
79
103
|
|
80
104
|
def codebadge
|
81
|
-
iconbadge(
|
105
|
+
iconbadge('file-code-fill', 'Work on code in your portfolio')
|
82
106
|
end
|
83
107
|
|
84
108
|
def cloudbadge
|
85
|
-
iconbadge(
|
109
|
+
iconbadge('cloud-fill', 'Work on code in your portfolio')
|
86
110
|
end
|
87
111
|
|
88
112
|
def zipbadge
|
89
|
-
iconbadge(
|
113
|
+
iconbadge('file-earmark-zip-fill', 'Submit work as an attachment')
|
90
114
|
end
|
91
115
|
|
92
116
|
def partbadge
|
93
|
-
iconbadge(
|
117
|
+
iconbadge('heart-half', 'Graded for participation only - pass/fail')
|
94
118
|
end
|
95
119
|
|
96
120
|
def timebadge
|
97
|
-
iconbadge(
|
121
|
+
iconbadge('alarm-fill', 'Must be submitted first thing on day of class')
|
98
122
|
end
|
99
123
|
|
100
124
|
def teambadge
|
101
|
-
iconbadge(
|
125
|
+
iconbadge('people-fill', 'Team Deliverable')
|
102
126
|
end
|
103
127
|
|
104
128
|
def include_image_old(filename_string, extra_class: nil)
|
105
|
-
css_class =
|
106
|
-
css_class +=
|
129
|
+
css_class = 'img-responsive'
|
130
|
+
css_class += ' img-' + extra_class unless extra_class.nil?
|
107
131
|
<<-HTMLSTRING
|
108
132
|
<img src="#{filename_string}" class=\"%s\" />" % css_class
|
109
133
|
HTMLSTRING
|
110
134
|
end
|
111
135
|
|
112
|
-
def include_image(filename_string, extra:
|
136
|
+
def include_image(filename_string, extra: '')
|
113
137
|
<<~HTMLSTRING
|
114
138
|
<div class="row">
|
115
139
|
<div class="col-md-offset-2 col-md-8">
|
@@ -119,13 +143,13 @@ module ContentHelpers
|
|
119
143
|
HTMLSTRING
|
120
144
|
end
|
121
145
|
|
122
|
-
def image(filename_string, extra:
|
123
|
-
|
124
|
-
|
146
|
+
def image(filename_string, extra: '')
|
147
|
+
<<~HTMLSTRING
|
148
|
+
<img src="/content/topics/images/#{filename_string}" class="img-responsive img-thumbnail" #{extra}/>
|
125
149
|
HTMLSTRING
|
126
150
|
end
|
127
151
|
|
128
|
-
def important(string =
|
152
|
+
def important(string = ':')
|
129
153
|
<<-HTMLSTRING
|
130
154
|
<div class="cg-important">
|
131
155
|
#{string}
|
@@ -133,26 +157,26 @@ module ContentHelpers
|
|
133
157
|
HTMLSTRING
|
134
158
|
end
|
135
159
|
|
136
|
-
def nb(string =
|
160
|
+
def nb(string = ':')
|
137
161
|
<<-HTMLSTRING
|
138
162
|
<div class="label label-info">#{string}</div>
|
139
163
|
HTMLSTRING
|
140
164
|
end
|
141
165
|
|
142
|
-
def tbd(string =
|
166
|
+
def tbd(string = '')
|
143
167
|
"*[TO BE DETERMINED#{string}]*{: style=\"color: red\"}"
|
144
168
|
end
|
145
169
|
|
146
|
-
def deliverable(string, append =
|
170
|
+
def deliverable(string, append = '')
|
147
171
|
"*Deliverable:*{: style=\"color: red\"} #{string + append} "
|
148
172
|
end
|
149
173
|
|
150
174
|
def deliverable_po(string)
|
151
|
-
deliverable(string,
|
175
|
+
deliverable(string, ' *(graded for participation only)*')
|
152
176
|
end
|
153
177
|
|
154
178
|
def deliverable_popdf(string)
|
155
|
-
deliverable(string,
|
179
|
+
deliverable(string, ' *(pdf with name and hw number, graded for participation only)*')
|
156
180
|
end
|
157
181
|
|
158
182
|
def team_deliverable(string)
|
@@ -168,54 +192,84 @@ module ContentHelpers
|
|
168
192
|
end
|
169
193
|
|
170
194
|
def homework_hdr(show_legend: :on)
|
171
|
-
body =
|
195
|
+
body = '## Homework due for today'
|
172
196
|
legend = "\n**Legend**: #{partbadge}: Participation (pass/fail) | #{pdfbadge}: PDF | #{teambadge}: Team | #{zipbadge}: Attachment"
|
173
197
|
body += legend if show_legend == :on
|
174
198
|
body
|
175
199
|
end
|
176
200
|
|
177
|
-
def carousel(filenames)
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
end
|
193
|
-
|
194
|
-
def carousel_new(filenames)
|
195
|
-
|
196
|
-
end
|
197
|
-
|
198
|
-
def carousel_work(filenames)
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
201
|
+
# def carousel(filenames)
|
202
|
+
# body = %(<div id="myCarousel" class="carousel slide" style="width: 500px; margin: 0 auto;">
|
203
|
+
# <div class="carousel-inner" style="margin: 20px; ">)
|
204
|
+
# counter = 0
|
205
|
+
# filenames.each do |nam|
|
206
|
+
# body << counter == 0 ? %(div class="item active">) : body << %(<div class="item">~
|
207
|
+
# body << %~<img src=")
|
208
|
+
# body << "/content/images/#{nam}"
|
209
|
+
# body << %(" class="img-polaroid" alt=""></div>)
|
210
|
+
# counter += 1
|
211
|
+
# end
|
212
|
+
# body << %(</div> <a class="left carousel-control" href="#myCarousel" data-slide="prev"></a>
|
213
|
+
# <a class="right carousel-control" href="#myCarousel" data-slide="next"></a>
|
214
|
+
# </div>)
|
215
|
+
# body
|
216
|
+
# end
|
217
|
+
|
218
|
+
# def carousel_new(filenames)
|
219
|
+
# carousel_work(filenames.map { |filename| "/content/topics/images/" + filename })
|
220
|
+
# end
|
221
|
+
|
222
|
+
# def carousel_work(filenames)
|
223
|
+
# body = %(<div id="myCarousel" class="carousel slide" data-ride="carousel" style="width: 500px; margin: 0 auto;">
|
224
|
+
# <div class="carousel-inner" role="listbox" style="margin: 20px; ">)
|
225
|
+
# counter = 0
|
226
|
+
# filenames.each do |nam|
|
227
|
+
# ci = counter == 0 ? %(<div class="item active">) : %(<div class="item">)
|
228
|
+
# body << ci
|
229
|
+
# body << %(<img src=")
|
230
|
+
# body << nam
|
231
|
+
# body << %("/>"></div>)
|
232
|
+
# counter += 1
|
233
|
+
# end
|
234
|
+
# body << %(</div> <a class="left carousel-control" role="button" href="#myCarousel" data-slide="prev">
|
235
|
+
# <span class="glyphicon glyphicon-chevron-left"></span>
|
236
|
+
# <span class="sr-only">Previous</span>
|
237
|
+
# </a>
|
238
|
+
# <a class="right carousel-control" role="button" href="#myCarousel" data-slide="next">
|
239
|
+
# <span class="glyphicon glyphicon-chevron-right"></span>
|
240
|
+
# <span class="sr-only">Next</span>
|
241
|
+
# </a>
|
242
|
+
# </div>)
|
243
|
+
# body
|
244
|
+
# end
|
245
|
+
|
246
|
+
def carousel_v4(filenames)
|
247
|
+
body = <<~HEREDOC
|
248
|
+
<div id="carouselExampleControls" class="carousel slide" data-ride="carousel">
|
249
|
+
<div class="carousel-inner">
|
250
|
+
HEREDOC
|
251
|
+
count = 0
|
252
|
+
filenames.each do |fname|
|
253
|
+
active = count == 0 ? 'active' : ''
|
254
|
+
body << <<~HEREDOC
|
255
|
+
<div class="carousel-item #{active}">
|
256
|
+
<img class="d-block w-80" src="/content/topics/images/#{fname}">
|
257
|
+
</div>
|
258
|
+
HEREDOC
|
259
|
+
count += 1
|
209
260
|
end
|
210
|
-
body <<
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
<
|
217
|
-
|
218
|
-
|
261
|
+
body << <<~HEREDOC
|
262
|
+
</div>
|
263
|
+
<a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
|
264
|
+
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
265
|
+
<span class="sr-only">Previous</span>
|
266
|
+
</a>
|
267
|
+
<a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
|
268
|
+
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
269
|
+
<span class="sr-only">Next</span>
|
270
|
+
</a>
|
271
|
+
</div>
|
272
|
+
HEREDOC
|
219
273
|
body
|
220
274
|
end
|
221
275
|
|
@@ -244,13 +298,13 @@ module ContentHelpers
|
|
244
298
|
end
|
245
299
|
|
246
300
|
def include_ruby(name)
|
247
|
-
filename = Dir.pwd +
|
301
|
+
filename = Dir.pwd + '/content/content/topics/scripts/' + name.to_s + '.rb'
|
248
302
|
filecontents = File.new(filename).read
|
249
303
|
ruby_string filecontents
|
250
304
|
end
|
251
305
|
|
252
306
|
def include_python(name)
|
253
|
-
filename = Dir.pwd +
|
307
|
+
filename = Dir.pwd + '/content/content/topics/robotcode/' + name.to_s + '.py'
|
254
308
|
filecontents = File.new(filename).read
|
255
309
|
ruby_string filecontents
|
256
310
|
end
|
@@ -259,11 +313,9 @@ module ContentHelpers
|
|
259
313
|
"\n~~~~~~"
|
260
314
|
end
|
261
315
|
|
262
|
-
def code_end(lang =
|
316
|
+
def code_end(lang = '')
|
263
317
|
str = "~~~~~~\n"
|
264
|
-
if [
|
265
|
-
str += "{: .language-#{lang}}"
|
266
|
-
end
|
318
|
+
str += "{: .language-#{lang}}" if %w[ruby css java html].include? lang
|
267
319
|
str
|
268
320
|
end
|
269
321
|
|
@@ -272,52 +324,64 @@ module ContentHelpers
|
|
272
324
|
end
|
273
325
|
|
274
326
|
def include_code(name)
|
275
|
-
filename = Dir.pwd +
|
327
|
+
filename = Dir.pwd + '/content/content/topics/scripts/' + name
|
276
328
|
filecontents = File.new(filename).read
|
277
329
|
code_string filecontents
|
278
330
|
end
|
279
331
|
|
280
|
-
def
|
281
|
-
"<
|
332
|
+
def source_begin(language)
|
333
|
+
"<pre class=\"#{language}\">"
|
334
|
+
end
|
335
|
+
|
336
|
+
def source_end
|
337
|
+
'</pre>'
|
338
|
+
end
|
339
|
+
|
340
|
+
def postit_begin(title)
|
341
|
+
'<div class="postit">' + '<h5>' + title + '</h5>'
|
282
342
|
end
|
283
343
|
|
284
344
|
def postit_end
|
285
|
-
|
345
|
+
'</div>'
|
286
346
|
end
|
287
347
|
|
288
348
|
def ul_begin
|
289
|
-
|
349
|
+
'<ul>'
|
290
350
|
end
|
291
351
|
|
292
352
|
def ul_end
|
293
|
-
|
353
|
+
'</ul>'
|
294
354
|
end
|
295
355
|
|
296
|
-
def ul
|
356
|
+
def ul(body)
|
297
357
|
"<ul>#{body}</ul>"
|
298
358
|
end
|
299
359
|
|
300
|
-
def
|
301
|
-
|
302
|
-
|
360
|
+
def slide
|
361
|
+
'<slide_break></slide_break>'
|
362
|
+
end
|
363
|
+
|
364
|
+
def list_items(*items)
|
365
|
+
items.reduce('') do |s, i|
|
366
|
+
if i.start_with?('<ul>')
|
303
367
|
s + i
|
304
368
|
else
|
305
|
-
s +
|
369
|
+
s + '<li>' + i + '</li>'
|
306
370
|
end
|
307
371
|
end
|
308
372
|
end
|
309
373
|
|
310
374
|
def lab_note(title)
|
311
|
-
"<
|
375
|
+
"<h3 style=\"font-family:'Permanent Marker'; font-szie:18px; color: red;\">#{title}</h3>"
|
312
376
|
end
|
313
377
|
|
314
378
|
def toasty(header, *items)
|
315
|
-
str = %
|
379
|
+
str = %(<div class="border border-info rounded w-75 mx-auto p-2 m-3">
|
316
380
|
<h5>#{header}</h5><ul>)
|
317
381
|
items.each do |itm|
|
318
|
-
str +=
|
382
|
+
str += '<li>' + itm + '</li>'
|
319
383
|
end
|
320
|
-
str +=
|
384
|
+
str += '</ul></div>'
|
321
385
|
str
|
322
386
|
end
|
323
387
|
end
|