diff --git a/assets/stylesheets/course/index.css b/assets/stylesheets/course/index.css
index 473a258..7e8c2c3 100644
--- a/assets/stylesheets/course/index.css
+++ b/assets/stylesheets/course/index.css
@@ -1 +1,65 @@
@import './card';
+
+@block course {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ @element title {
+ margin-bottom: calc(var(--grid-gutter));
+ }
+
+ @element overview {
+ font-family: var(--font-medium);
+
+ @media (--breakpoint-desktop) {
+ float: right;
+ border-radius: var(--border-radius);
+ box-shadow: var(--card-box-shadow);
+ width: 228px;
+ margin: 0 0 var(--grid-gutter) var(--grid-gutter);
+ }
+ }
+
+ @element overview-title {
+ border-bottom: 1px solid var(--color-sidebar-seperator);
+ padding: calc(var(--grid-gutter) / 2) 0;
+ margin: 0;
+ line-height: 1.31;
+ font-weight: normal;
+ text-transform: uppercase;
+ text-align: center;
+ }
+
+ @element overview-item {
+ display: flex;
+ align-items: center;
+ padding: calc(var(--grid-gutter) / 2);
+ border-bottom: 1px solid var(--color-sidebar-seperator);
+
+ line-height: 1.54;
+ font-size: 0.8em;
+ }
+
+ @element overview-icon {
+ flex: 0 0 auto;
+ width: 24px;
+ height: 24px;
+ padding-right: calc(var(--grid-gutter) / 2);
+ }
+
+ @element overview-value {
+ flex: 1 0 auto;
+ }
+
+ @element overview-cta-wrapper {
+ padding: calc(var(--grid-gutter) / 2) 0;
+ text-align: center;
+ }
+ @element overview-cta {
+ margin: 0;
+ }
+ @element cta {
+ margin-bottom: 0;
+ }
+}
diff --git a/assets/stylesheets/global/table-of-contents.css b/assets/stylesheets/global/table-of-contents.css
index 87822bd..7ca8088 100644
--- a/assets/stylesheets/global/table-of-contents.css
+++ b/assets/stylesheets/global/table-of-contents.css
@@ -1,38 +1,45 @@
-.table-of-contents {
- & ul {
+:root {
+ --toc-gap-left: calc(var(--grid-gutter) / 2)
+}
+@block table-of-contents {
+ @element list {
list-style: none;
- margin: var(--grid-gutter) 0;
+ margin: 0;
padding: 0;
- padding-left: calc(var(--grid-gutter) * 2);
+ padding-left: var(--toc-gap-left);
+ }
- & li {
- margin: 0 0 var(--grid-gutter);
- padding: 0;
- }
+ @element item {
+ margin: 0 0 calc(var(--grid-gutter) / 4);
+ padding: 0;
+ font-size: 0.9em;
+ line-height: 1.8;
+ }
- & a {
- display: block;
+ @element link {
+ display: block;
+ color: var(--color-text-grey);
- &.active {
- position: relative;
- font-weight: bold;
+ &.active {
+ position: relative;
+ font-family: var(--font-medium);
+ color: var(--color-text-default);
- &:before,
- &:after {
- position: absolute;
- top: 0;
- }
- &:before {
- content: '';
- left: calc(var(--grid-gutter) * 3 * -1);
- bottom: 0;
- width: 3px;
- background: var(--color-course-active);
- }
- &:after {
- content: '👁';
- left: calc(var(--grid-gutter) * 2 * -1);
- }
+ &:before,
+ &:after {
+ position: absolute;
+ top: 0;
+ }
+ &:before {
+ content: '';
+ left: calc(var(--toc-gap-left) * 3 * -1);
+ bottom: 0;
+ width: 3px;
+ background: var(--color-course-active);
+ }
+ &:after {
+ content: '👁';
+ left: calc(var(--toc-gap-left) * 2 * -1);
}
}
}
diff --git a/assets/stylesheets/layout/layout-sidebar.css b/assets/stylesheets/layout/layout-sidebar.css
index 4781d98..619a21a 100644
--- a/assets/stylesheets/layout/layout-sidebar.css
+++ b/assets/stylesheets/layout/layout-sidebar.css
@@ -18,7 +18,7 @@
}
@element sidebar-header {
- padding: 1em var(--grid-gutter);
+ padding: calc(var(--grid-gutter) / 2) var(--grid-gutter);
border-bottom: 1px solid var(--color-sidebar-seperator);
}
@@ -35,7 +35,10 @@
}
@element content {
- padding: var(--grid-gutter) 0;
+ display: flex;
+ flex-direction: column;
+ align-self: stretch;
+ padding-top: calc(var(--grid-gutter) / 2);
@media (--breakpoint-desktop) {
flex: 0 1 auto;
diff --git a/assets/stylesheets/lesson/index.css b/assets/stylesheets/lesson/index.css
index 80e9fb9..5cadc5a 100644
--- a/assets/stylesheets/lesson/index.css
+++ b/assets/stylesheets/lesson/index.css
@@ -1,8 +1,22 @@
.lesson-module {
- margin-top: calc(var(--grid-gutter) * 3);
+ margin-top: var(--grid-gutter);
& img {
width: 100%;
height: auto;
}
}
+
+@block lesson {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ @element title {
+ margin-bottom: calc(var(--grid-gutter));
+ }
+
+ @element cta {
+ margin-bottom: 0;
+ }
+}
diff --git a/public/images/icon-duration.svg b/public/images/icon-duration.svg
new file mode 100644
index 0000000..fa1cf23
--- /dev/null
+++ b/public/images/icon-duration.svg
@@ -0,0 +1,7 @@
+
diff --git a/public/images/icon-skill-level.svg b/public/images/icon-skill-level.svg
new file mode 100644
index 0000000..a12fbe0
--- /dev/null
+++ b/public/images/icon-skill-level.svg
@@ -0,0 +1,6 @@
+
diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css
index 6b20ae8..288da96 100644
--- a/public/stylesheets/style.css
+++ b/public/stylesheets/style.css
@@ -793,7 +793,7 @@ input[type="reset"]:focus,
}
.layout-sidebar__sidebar-header {
- padding: 1em 22px;
+ padding: 11px 22px;
border-bottom: 1px solid #eeeeee;
}
@@ -810,7 +810,16 @@ input[type="reset"]:focus,
}
.layout-sidebar__content {
- padding: 22px 0;
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -ms-flex-item-align: stretch;
+ align-self: stretch;
+ padding-top: 11px;
}
@media (min-width: 700px) {
@@ -1138,44 +1147,50 @@ display: flex;
height: auto;
}
-.table-of-contents ul {
- list-style: none;
- margin: 22px 0;
- padding: 0;
- padding-left: 44px;
+.table-of-contents {}
+
+.table-of-contents__list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ padding-left: 11px;
}
-.table-of-contents ul li {
- margin: 0 0 22px;
- padding: 0;
+.table-of-contents__item {
+ margin: 0 0 5.5px;
+ padding: 0;
+ font-size: 0.9em;
+ line-height: 1.8;
}
-.table-of-contents ul a {
- display: block;
+.table-of-contents__link {
+ display: block;
+ color: #8091a5;
}
-.table-of-contents ul a.active {
+.table-of-contents__link.active {
position: relative;
- font-weight: bold;
+ font-family: 'robotomedium', Helvetica, sans-serif;
+ color: #2a3039;
}
-.table-of-contents ul a.active:before,
- .table-of-contents ul a.active:after {
+.table-of-contents__link.active:before,
+ .table-of-contents__link.active:after {
position: absolute;
top: 0;
}
-.table-of-contents ul a.active:before {
+.table-of-contents__link.active:before {
content: '';
- left: -66px;
+ left: -33px;
bottom: 0;
width: 3px;
background: #536171;
}
-.table-of-contents ul a.active:after {
+.table-of-contents__link.active:after {
content: '👁';
- left: -44px;
+ left: -22px;
}
.sidebar-menu {}
@@ -1475,6 +1490,91 @@ github.com style (c) Vasily Polovnyov
letter-spacing: 2px;
}
+.course {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-box-pack: justify;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+}
+
+.course__title {
+ margin-bottom: 22px;
+}
+
+.course__overview {
+ font-family: 'robotomedium', Helvetica, sans-serif;
+}
+
+@media (min-width: 700px) {
+
+ .course__overview {
+ float: right;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .1);
+ box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .1);
+ width: 228px;
+ margin: 0 0 22px 22px;
+ }
+}
+
+.course__overview-title {
+ border-bottom: 1px solid #eeeeee;
+ padding: 11px 0;
+ margin: 0;
+ line-height: 1.31;
+ font-weight: normal;
+ text-transform: uppercase;
+ text-align: center;
+}
+
+.course__overview-item {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-align: center;
+ -ms-flex-align: center;
+ align-items: center;
+ padding: 11px;
+ border-bottom: 1px solid #eeeeee;
+
+ line-height: 1.54;
+ font-size: 0.8em;
+}
+
+.course__overview-icon {
+ -webkit-box-flex: 0;
+ -ms-flex: 0 0 auto;
+ flex: 0 0 auto;
+ width: 24px;
+ height: 24px;
+ padding-right: 11px;
+}
+
+.course__overview-value {
+ -webkit-box-flex: 1;
+ -ms-flex: 1 0 auto;
+ flex: 1 0 auto;
+}
+
+.course__overview-cta-wrapper {
+ padding: 11px 0;
+ text-align: center;
+}
+
+.course__overview-cta {
+ margin: 0;
+}
+
+.course__cta {
+ margin-bottom: 0;
+}
+
.module-hero-image {}
.module-hero-image__wrapper {
@@ -1646,10 +1746,31 @@ github.com style (c) Vasily Polovnyov
}
.lesson-module {
- margin-top: 66px
+ margin-top: 22px
}
.lesson-module img {
width: 100%;
height: auto;
}
+
+.lesson {
+ display: -webkit-box;
+ display: -ms-flexbox;
+ display: flex;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -webkit-box-pack: justify;
+ -ms-flex-pack: justify;
+ justify-content: space-between;
+}
+
+.lesson__title {
+ margin-bottom: 22px;
+}
+
+.lesson__cta {
+ margin-bottom: 0;
+}
diff --git a/routes/courses.js b/routes/courses.js
index 6141015..3e92480 100644
--- a/routes/courses.js
+++ b/routes/courses.js
@@ -48,7 +48,14 @@ router.get('/:cslug/lessons/:lslug', async function (req, res, next) {
const lessons = course.fields.lessons
const lessonIndex = lessons.findIndex((lesson) => lesson.fields.slug === req.params.lslug)
const lesson = lessons[lessonIndex]
- res.render('course', {title: `${course.fields.title} | ${lesson.fields.title}`, course, lesson, lessons, lessonIndex})
+ const nextLesson = lessons[lessonIndex + 1] || null
+ res.render('course', {
+ title: `${course.fields.title} | ${lesson.fields.title}`,
+ course,
+ lesson,
+ lessons,
+ nextLesson
+ })
})
module.exports = router
diff --git a/views/course.pug b/views/course.pug
index 31e9bc7..517c2ad 100644
--- a/views/course.pug
+++ b/views/course.pug
@@ -7,22 +7,35 @@ block content
section.layout-sidebar__sidebar
.layout-sidebar__sidebar-header
h2.layout-sidebar__sidebar-title Table of contents
- .table-of-contents
- ul
- li
- a.active(href=`/courses/${course.fields.slug}`) Course overview
- each l in course.fields.lessons
- if l.fields
- li
- a(href=`/courses/${course.fields.slug}/lessons/${l.fields.slug}${queryString}`) #{l.fields.title}
+ .layout-sidebar__sidebar-content
+ .table-of-contents
+ .table-of-contents__list
+ .table-of-contents__item
+ a.table-of-contents__link.active(href=`/courses/${course.fields.slug}`) Course overview
+ each l in course.fields.lessons
+ if l.fields
+ .table-of-contents__item
+ a.table-of-contents__link(href=`/courses/${course.fields.slug}/lessons/${l.fields.slug}${queryString}`) #{l.fields.title}
section.layout-sidebar__content
- h1= course.fields.title
-
if lesson
- +lesson(lesson)
- if lessonIndex + 1< lessons.length
- if lessons[lessonIndex + 1].fields
- a.cta(href=`/courses/${course.fields.slug}/lessons/${lessons[lessonIndex + 1].fields.slug}${queryString}`) View next lesson
+ +lesson(lesson, course, nextLesson)
else
- p !{helpers.markdown(course.fields.description)}
- a.cta(href=`/courses/${course.fields.slug}/lessons/${course.fields.lessons[0].fields.slug}${queryString}`) Start course
+ .course
+ .course__content
+ h1.course__title= course.fields.title
+ .course__overview
+ h3.course__overview-title Overview
+ if course.fields.duration
+ .course__overview-item
+ img.course__overview-icon(src='/images/icon-duration.svg')
+ .course__overview-value Duration: #{course.fields.duration}min
+ if course.fields.skillLevel
+ .course__overview-item
+ img.course__overview-icon(src='/images/icon-skill-level.svg')
+ .course__overview-value Skill level: #{course.fields.skillLevel}
+ .course__overview-cta-wrapper
+ a.course__overview-cta.cta(href=`/courses/${course.fields.slug}/lessons/${course.fields.lessons[0].fields.slug}${queryString}`) Start course
+ .course__description !{helpers.markdown(course.fields.description)}
+ .course__footer
+ a.course__cta.cta(href=`/courses/${course.fields.slug}/lessons/${course.fields.lessons[0].fields.slug}${queryString}`) Start course
+ //pre= helpers.dump(course)
diff --git a/views/mixins/_lesson.pug b/views/mixins/_lesson.pug
index 8b660a1..649928c 100644
--- a/views/mixins/_lesson.pug
+++ b/views/mixins/_lesson.pug
@@ -2,23 +2,27 @@ include _lessonModuleCodeSnippet
include _lessonModuleCopy
include _lessonModuleImage
-mixin lesson(lesson)
+mixin lesson(lesson, course, nextLesson)
.lesson
- h2.lesson__tilte #{lesson.fields.title}
- div.lesson__short-description !{helpers.markdown(lesson.fields.description)}
- if lesson.fields.image
- img.lesson__image(src=`${lesson.fields.image.fields.file.url}` alt=`${lesson.fields.image.fields.title}`)
- each module in lesson.fields.modules
- if module.sys.contentType
- case module.sys.contentType.sys.id
- when 'lessonModuleCodeSnippets'
- +lessonModuleCodeSnippet(module)
- when 'lessonModuleCopy'
- +lessonModuleCopy(module)
- when 'lessonModuleImage'
- +lessonModuleImage(module)
- else
- h2 ️️⚠️ Invalid lesson module
- p
- span Could not determine type of
- strong #{module.sys.id}
+ .lesson_content
+ h1.lesson__title #{lesson.fields.title}
+ div.lesson__short-description !{helpers.markdown(lesson.fields.description)}
+ if lesson.fields.image
+ img.lesson__image(src=`${lesson.fields.image.fields.file.url}` alt=`${lesson.fields.image.fields.title}`)
+ each module in lesson.fields.modules
+ if module.sys.contentType
+ case module.sys.contentType.sys.id
+ when 'lessonModuleCodeSnippets'
+ +lessonModuleCodeSnippet(module)
+ when 'lessonModuleCopy'
+ +lessonModuleCopy(module)
+ when 'lessonModuleImage'
+ +lessonModuleImage(module)
+ else
+ h2 ️️⚠️ Invalid lesson module
+ p
+ span Could not determine type of
+ strong #{module.sys.id}
+ .lesson_footer
+ if nextLesson
+ a.lesson__cta.cta(href=`/courses/${course.fields.slug}/lessons/${nextLesson.fields.slug}${queryString}`) View next lesson
diff --git a/views/mixins/_lessonModuleCodeSnippet.pug b/views/mixins/_lessonModuleCodeSnippet.pug
index 75a8e9c..ab71713 100644
--- a/views/mixins/_lessonModuleCodeSnippet.pug
+++ b/views/mixins/_lessonModuleCodeSnippet.pug
@@ -1,6 +1,5 @@
mixin lessonModuleCodeSnippet(module)
.lesson-module.lesson-module-code
- h1.lesson-module__title #{module.fields.title}
if module.fields.curl
pre.lesson-module-code__curl
code.shell= module.fields.curl
diff --git a/views/mixins/_lessonModuleCopy.pug b/views/mixins/_lessonModuleCopy.pug
index 4b41ab3..717cfe0 100644
--- a/views/mixins/_lessonModuleCopy.pug
+++ b/views/mixins/_lessonModuleCopy.pug
@@ -1,4 +1,3 @@
mixin lessonModuleCopy(module)
.lesson-module.lesson-module-copy
- h3.lesson-module-copy__title #{module.fields.title}
.lesson-module-copy__copy !{helpers.markdown(module.fields.copy)}
diff --git a/views/mixins/_lessonModuleImage.pug b/views/mixins/_lessonModuleImage.pug
index 4c176bd..f14daa3 100644
--- a/views/mixins/_lessonModuleImage.pug
+++ b/views/mixins/_lessonModuleImage.pug
@@ -1,6 +1,5 @@
mixin lessonModuleImage(module)
.lesson-module.lesson-module-image
- h2.lesson-module-image__title #{module.fields.title}
if module.fields.file && module.fields.file.url
img.lesson-module-image__image(src=module.fields.file.url alt=module.fields.title)
else