feat(controls): styled custom header dropdown with helptext and smart positioning (#13)
This commit is contained in:
53
app.js
53
app.js
@@ -14,7 +14,7 @@ const categories = require('./routes/categories')
|
||||
const about = require('./routes/about')
|
||||
const settings = require('./routes/settings')
|
||||
const sitemap = require('./routes/sitemap')
|
||||
const {initClient} = require('./services/contentful')
|
||||
const { initClient, getSpace } = require('./services/contentful')
|
||||
const breadcrumb = require('./lib/breadcrumb')
|
||||
const app = express()
|
||||
|
||||
@@ -31,21 +31,58 @@ app.use(cookieParser())
|
||||
app.use(express.static(path.join(__dirname, 'public')))
|
||||
app.use(breadcrumb())
|
||||
|
||||
// Pass custom helpers to all our templates
|
||||
app.use(function (req, res, next) {
|
||||
// Pass our application state and custom helpers to all our templates
|
||||
app.use(async function (req, res, next) {
|
||||
// Inject ucstom helpers
|
||||
res.locals.helpers = helpers
|
||||
|
||||
// Express query string
|
||||
const qs = url.parse(req.url).query
|
||||
res.locals.queryString = qs ? `?${qs}` : ''
|
||||
res.locals.query = req.query
|
||||
res.locals.currentPath = req.path
|
||||
// Allow setting of credentials via query parameters
|
||||
|
||||
// Allow setting of API credentials via query parameters
|
||||
let settings = req.cookies.theExampleAppSettings
|
||||
|
||||
const { space_id, preview_access_token, delivery_access_token } = req.query
|
||||
if (space_id && preview_access_token && delivery_access_token) { // eslint-disable-line camelcase
|
||||
const settings = {space: space_id, cda: delivery_access_token, cpa: preview_access_token}
|
||||
settings = {space: space_id, cda: delivery_access_token, cpa: preview_access_token}
|
||||
res.cookie('theExampleAppSettings', settings, { maxAge: 900000, httpOnly: true })
|
||||
initClient(settings)
|
||||
} else {
|
||||
initClient(req.cookies.theExampleAppSettings)
|
||||
}
|
||||
|
||||
initClient(settings)
|
||||
res.locals.settings = settings
|
||||
|
||||
// Manage language and API type state and make it globally available
|
||||
const apis = [
|
||||
{
|
||||
id: 'cda',
|
||||
label: 'Delivery (published content)'
|
||||
},
|
||||
{
|
||||
id: 'cpa',
|
||||
label: 'Preview (draft content)'
|
||||
}
|
||||
]
|
||||
|
||||
res.locals.currentApi = apis
|
||||
.find((api) => api.id === (req.query.api || 'cda'))
|
||||
|
||||
// Get enabled locales from Contentful
|
||||
const space = await getSpace()
|
||||
res.locals.locales = space.locales
|
||||
|
||||
const defaultLocale = res.locals.locales
|
||||
.find((locale) => locale.default)
|
||||
|
||||
if (req.query.locale) {
|
||||
res.locals.currentLocale = space.locales
|
||||
.find((locale) => locale.code === req.query.locale)
|
||||
}
|
||||
|
||||
if (!res.locals.currentLocale) {
|
||||
res.locals.currentLocale = defaultLocale
|
||||
}
|
||||
|
||||
next()
|
||||
|
||||
@@ -27,22 +27,11 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
margin-bottom: calc(var(--grid-gutter) / 2);
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
flex: 0 1 auto;
|
||||
flex-direction: row;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
& div + div {
|
||||
margin: calc(var(--grid-gutter) / 2) 0 0;
|
||||
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
margin: 0 0 0 calc(var(--grid-gutter) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@element upper-second {
|
||||
@@ -56,14 +45,6 @@
|
||||
flex: 0 1 auto;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
& div + div {
|
||||
margin: calc(var(--grid-gutter) / 2) 0 0;
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
margin: 0 0 0 calc(var(--grid-gutter) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@element upper-link {
|
||||
@@ -73,6 +54,11 @@
|
||||
|
||||
@element upper-copy {
|
||||
display: inline-flex;
|
||||
margin: 0 0 calc(var(--grid-gutter) / 2);
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
margin: 0 calc(var(--grid-gutter) / 2) 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@element upper-icon {
|
||||
@@ -107,6 +93,10 @@
|
||||
height: auto;
|
||||
margin-right: calc(var(--grid-gutter) / 2);
|
||||
}
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
margin: 0 calc(var(--grid-gutter) / 2) 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@element logo {
|
||||
@@ -134,52 +124,98 @@
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
flex: 0 0 auto;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
@element controls_group {
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
|
||||
display: flex;
|
||||
margin: 0 0 calc(var(--grid-gutter) / 2);
|
||||
padding: 0 calc(var(--grid-gutter) / 2);
|
||||
|
||||
border: none;
|
||||
background: var(--color-palette-blue-medium);
|
||||
border-radius: var(--border-radius);
|
||||
color: inherit;
|
||||
|
||||
&:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
& form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
@media (--breakpoint-desktop) {
|
||||
margin: 0 calc(var(--grid-gutter) / 2) 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
@element controls_label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: var(--font-medium);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
& .group {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
padding: 0 calc(var(--grid-gutter) / 2);
|
||||
margin: 0;
|
||||
@element controls_dropdown {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
box-sizing: border-box;
|
||||
|
||||
border: none;
|
||||
background: var(--color-palette-blue-medium);
|
||||
border-radius: var(--border-radius);
|
||||
color: inherit;
|
||||
width: 260px;
|
||||
max-width: 90vw;
|
||||
margin: calc(var(--grid-gutter) / 2 - 4px) 0 0;
|
||||
|
||||
& + .group {
|
||||
margin-left: var(--grid-gutter)
|
||||
}
|
||||
opacity: 0;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.1);
|
||||
|
||||
& select,
|
||||
& label {
|
||||
flex: 0 0 auto;
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
transition: 0.3s opacity ease;
|
||||
pointer-events: none;
|
||||
|
||||
color: inherit;
|
||||
font-weight: normal;
|
||||
font-family: var(--font-medium);
|
||||
font-size: 0.8em;
|
||||
@modifier active {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
|
||||
& select {
|
||||
margin-top: 2px;
|
||||
}
|
||||
background-color: inherit;
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@element controls_help_text {
|
||||
padding: calc(var(--grid-gutter) / 2);
|
||||
color: var(--color-text-grey);
|
||||
}
|
||||
|
||||
@element controls_button {
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
border-radius: 0;
|
||||
background: var(--header-dropdown-bg);
|
||||
|
||||
color: var(--header-dropdown-btn-color);
|
||||
font-size: 1em;
|
||||
|
||||
&:hover {
|
||||
background: var(--header-dropdown-bg-hover);
|
||||
color: var(--header-dropdown-btn-color);
|
||||
}
|
||||
|
||||
@modifier active {
|
||||
background: var(--header-dropdown-bg-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,9 @@
|
||||
padding-top: calc(var(--grid-gutter) / 4);
|
||||
|
||||
@media (--breakpoint-desktop) {
|
||||
flex: 0 1 auto;
|
||||
width: var(--layout-sidebar-content-width);
|
||||
flex: 0 1 var(--layout-sidebar-content-width);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin-left: var(--grid-gutter);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,11 @@
|
||||
--cta-bg-hover: var(--color-palette-blue-medium);
|
||||
--cta-radius: 3px;
|
||||
|
||||
--header-dropdown-btn-color: #263545;
|
||||
--header-dropdown-bg: #fff;
|
||||
--header-dropdown-bg-active: #d3dce0;
|
||||
--header-dropdown-bg-hover: #e5ebed;
|
||||
|
||||
--module-copy-emphasized-bg: #8091a5;
|
||||
--module-copy-emphasized-color: #c3cfd5;
|
||||
--module-copy-emphasized-headlines-color: #fff;
|
||||
|
||||
@@ -15,4 +15,3 @@ function removeIvalidDataURL (content) {
|
||||
let regex = /data:\S+;base64\S*/gm
|
||||
return content.replace(regex, '#')
|
||||
}
|
||||
|
||||
|
||||
1
public/scripts/hoverintent.min.js
vendored
Executable file
1
public/scripts/hoverintent.min.js
vendored
Executable file
@@ -0,0 +1 @@
|
||||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.hoverintent=e()}}(function(){return function e(t,n,o){function r(u,f){if(!n[u]){if(!t[u]){var s="function"==typeof require&&require;if(!f&&s)return s(u,!0);if(i)return i(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var a=n[u]={exports:{}};t[u][0].call(a.exports,function(e){var n=t[u][1][e];return r(n||e)},a,a.exports,e,t,n,o)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u<o.length;u++)r(o[u]);return r}({1:[function(e,t,n){"use strict";var o=e("xtend");t.exports=function(e,t,n){function r(e,t){return p&&(p=clearTimeout(p)),d=0,n.call(e,t)}function i(e){c=e.clientX,a=e.clientY}function u(e,n){if(p&&(p=clearTimeout(p)),Math.abs(v-c)+Math.abs(l-a)<y.sensitivity)return d=1,t.call(e,n);v=c,l=a,p=setTimeout(function(){u(e,n)},y.interval)}function f(t){return p&&(p=clearTimeout(p)),e.removeEventListener("mousemove",i,!1),1!==d&&(v=t.clientX,l=t.clientY,e.addEventListener("mousemove",i,!1),p=setTimeout(function(){u(e,t)},y.interval)),this}function s(t){return p&&(p=clearTimeout(p)),e.removeEventListener("mousemove",i,!1),1===d&&(p=setTimeout(function(){r(e,t)},y.timeout)),this}var c,a,v,l,m={},d=0,p=0,y={sensitivity:7,interval:100,timeout:0};return m.options=function(e){return y=o({},y,e),m},m.remove=function(){e&&(e.removeEventListener("mouseover",f,!1),e.removeEventListener("mouseout",s,!1))},e&&(e.addEventListener("mouseover",f,!1),e.addEventListener("mouseout",s,!1)),m}},{xtend:2}],2:[function(e,t,n){function o(){for(var e={},t=0;t<arguments.length;t++){var n=arguments[t];for(var o in n)r.call(n,o)&&(e[o]=n[o])}return e}t.exports=o;var r=Object.prototype.hasOwnProperty},{}]},{},[1])(1)});
|
||||
@@ -1,4 +1,40 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Header dropdowns
|
||||
const controls = document.querySelectorAll('.header__controls_group')
|
||||
|
||||
controls.forEach((control) => {
|
||||
const ref = control.querySelector('.header__controls_label')
|
||||
const dropdownRef = control.querySelector('.header__controls_dropdown')
|
||||
|
||||
let popper = null
|
||||
|
||||
hoverintent(control, null, () => {
|
||||
if (popper) {
|
||||
dropdownRef.classList.remove('header__controls_dropdown--active')
|
||||
window.setTimeout(popper.destroy, 500)
|
||||
}
|
||||
}).options({
|
||||
sensitivity: 10,
|
||||
interval: 150,
|
||||
timeout: 300
|
||||
})
|
||||
|
||||
ref.addEventListener('click', (e) => {
|
||||
dropdownRef.classList.add('header__controls_dropdown--active')
|
||||
popper = new Popper(
|
||||
e.target,
|
||||
dropdownRef,
|
||||
{
|
||||
// popper options here
|
||||
}
|
||||
)
|
||||
})
|
||||
})
|
||||
// const apiRef =
|
||||
// const apiDropdownRef = document.querySelector('#control-api .header__controls_dropdown')
|
||||
|
||||
// const apiTooltip =
|
||||
|
||||
// Init highlight.js
|
||||
hljs.initHighlightingOnLoad()
|
||||
|
||||
|
||||
5
public/scripts/popper.min.js
vendored
Normal file
5
public/scripts/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -932,9 +932,11 @@ input[type="reset"]:focus,
|
||||
|
||||
.layout-sidebar__content {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 1 auto;
|
||||
flex: 0 1 auto;
|
||||
width: 732px;
|
||||
-ms-flex: 0 1 732px;
|
||||
flex: 0 1 732px;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin-left: 22px;
|
||||
}
|
||||
}
|
||||
@@ -1035,8 +1037,6 @@ input[type="reset"]:focus,
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
|
||||
margin-bottom: 11px;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
@@ -1053,17 +1053,6 @@ input[type="reset"]:focus,
|
||||
}
|
||||
}
|
||||
|
||||
.header__upper-first div + div {
|
||||
margin: 11px 0 0;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
.header__upper-first div + div {
|
||||
margin: 0 0 0 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.header__upper-second {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1 1 auto;
|
||||
@@ -1096,17 +1085,6 @@ input[type="reset"]:focus,
|
||||
}
|
||||
}
|
||||
|
||||
.header__upper-second div + div {
|
||||
margin: 11px 0 0;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
.header__upper-second div + div {
|
||||
margin: 0 0 0 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.header__upper-link {
|
||||
display: -webkit-inline-box;
|
||||
display: -ms-inline-flexbox;
|
||||
@@ -1120,6 +1098,14 @@ input[type="reset"]:focus,
|
||||
display: -webkit-inline-box;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
margin: 0 0 11px;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
.header__upper-copy {
|
||||
margin: 0 11px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header__upper-icon {
|
||||
@@ -1164,6 +1150,13 @@ input[type="reset"]:focus,
|
||||
margin-right: 11px;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
.header__title {
|
||||
margin: 0 11px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header__logo {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
@@ -1213,66 +1206,116 @@ input[type="reset"]:focus,
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
.header__controls form {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
.header__controls_group {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
|
||||
display: -webkit-box;
|
||||
|
||||
display: -ms-flexbox;
|
||||
|
||||
display: flex;
|
||||
margin: 0 0 11px;
|
||||
padding: 0 11px;
|
||||
|
||||
border: none;
|
||||
background: #3c80cf;
|
||||
border-radius: 4px;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.header__controls_group:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 700px) {
|
||||
|
||||
.header__controls form {
|
||||
-webkit-box-pack: end;
|
||||
-ms-flex-pack: end;
|
||||
justify-content: flex-end;
|
||||
.header__controls_group {
|
||||
margin: 0 11px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.header__controls form .group {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
padding: 0 11px;
|
||||
margin: 0;
|
||||
border: none;
|
||||
background: #3c80cf;
|
||||
border-radius: 4px;
|
||||
color: inherit;
|
||||
.header__controls_label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
font-family: 'robotomedium', Helvetica, sans-serif;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header__controls form .group + .group {
|
||||
margin-left: 22px;
|
||||
.header__controls_dropdown {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 260px;
|
||||
max-width: 90vw;
|
||||
margin: 7px 0 0;
|
||||
|
||||
opacity: 0;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
-webkit-box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .1);
|
||||
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, .1);
|
||||
|
||||
-webkit-transition: 0.3s opacity ease;
|
||||
|
||||
transition: 0.3s opacity ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.header__controls form .group select,
|
||||
.header__controls form .group label {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
color: inherit;
|
||||
font-weight: normal;
|
||||
font-family: 'robotomedium', Helvetica, sans-serif;
|
||||
font-size: 0.8em;
|
||||
background: transparent;
|
||||
border: none;
|
||||
.header__controls_dropdown--active {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.header__controls form .group select {
|
||||
margin-top: 2px;
|
||||
.header__controls_dropdown--active:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: -5px;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background-color: inherit;
|
||||
-webkit-transform: translateX(-50%) rotate(45deg);
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.header__controls_help_text {
|
||||
padding: 11px;
|
||||
color: #8091a5;
|
||||
}
|
||||
|
||||
.header__controls_button {
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
||||
border-radius: 0;
|
||||
background: #fff;
|
||||
|
||||
color: #263545;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.header__controls_button:hover {
|
||||
background: #e5ebed;
|
||||
color: #263545;
|
||||
}
|
||||
|
||||
.header__controls_button--active {
|
||||
background: #d3dce0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = express.Router()
|
||||
|
||||
/* GET the about landing page. */
|
||||
router.get('/', catchErrors(async function (req, res, next) {
|
||||
const landingPage = await getLandingPage('about', req.query.locale, req.query.api)
|
||||
const landingPage = await getLandingPage('about', res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
res.render('landingPage', { title: 'About', landingPage })
|
||||
}))
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ router.get('/', catchErrors(async function (req, res, next) {
|
||||
// we get all the entries with the content type `course`
|
||||
let courses = []
|
||||
let categories = []
|
||||
courses = await getCourses(req.query.locale, req.query.api)
|
||||
categories = await getCategories(req.query.locale, req.query.api)
|
||||
courses = await getCourses(res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
categories = await getCategories(res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
res.render('courses', { title: `All Courses (${courses.length})`, categories, courses })
|
||||
}))
|
||||
|
||||
@@ -22,7 +22,7 @@ router.get('/categories/:category', catchErrors(async function (req, res, next)
|
||||
try {
|
||||
categories = await getCategories()
|
||||
activeCategory = categories.find((category) => category.fields.slug === req.params.category)
|
||||
courses = await getCoursesByCategory(activeCategory.sys.id, req.query.locale, req.query.api)
|
||||
courses = await getCoursesByCategory(activeCategory.sys.id, res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
} catch (e) {
|
||||
console.log('Error ', e)
|
||||
}
|
||||
@@ -31,7 +31,7 @@ router.get('/categories/:category', catchErrors(async function (req, res, next)
|
||||
|
||||
/* GET course detail. */
|
||||
const courseRoute = catchErrors(async function (req, res, next) {
|
||||
let course = await getCourse(req.params.slug, req.query.locale, req.query.api)
|
||||
let course = await getCourse(req.params.slug, res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
const lessons = course.fields.lessons
|
||||
const lessonIndex = lessons.findIndex((lesson) => lesson.fields.slug === req.params.lslug)
|
||||
const lesson = lessons[lessonIndex]
|
||||
@@ -47,13 +47,13 @@ router.get('/:slug/lessons', courseRoute)
|
||||
|
||||
/* GET course lesson detail. */
|
||||
router.get('/:cslug/lessons/:lslug', catchErrors(async function (req, res, next) {
|
||||
let course = await getCourse(req.params.cslug, req.query.locale, req.query.api)
|
||||
let course = await getCourse(req.params.cslug, res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
const lessons = course.fields.lessons
|
||||
const lessonIndex = lessons.findIndex((lesson) => lesson.fields.slug === req.params.lslug)
|
||||
const lesson = lessons[lessonIndex]
|
||||
const nextLesson = lessons[lessonIndex + 1] || null
|
||||
const cookie = req.cookies.visitedLessons
|
||||
let visitedLessons = cookie || []
|
||||
let visitedLessons = cookie || []
|
||||
visitedLessons.push(lesson.sys.id)
|
||||
visitedLessons = [...new Set(visitedLessons)]
|
||||
res.cookie('visitedLessons', visitedLessons, { maxAge: 900000, httpOnly: true })
|
||||
|
||||
@@ -5,7 +5,7 @@ const router = express.Router()
|
||||
|
||||
/* GET the home landing page. */
|
||||
router.get('/', catchErrors(async function (req, res, next) {
|
||||
const landingPage = await getLandingPage('home', req.query.locale, req.query.api)
|
||||
const landingPage = await getLandingPage('home', res.locals.currentLocale.code, res.locals.currentLocale.id)
|
||||
let title = landingPage.fields.title
|
||||
if (!title || landingPage.fields.slug === 'home') {
|
||||
title = 'The Example App'
|
||||
|
||||
@@ -23,6 +23,11 @@ exports.initClient = (options) => {
|
||||
})
|
||||
}
|
||||
|
||||
exports.getSpace = assert((api = `cda`) => {
|
||||
const client = api === 'cda' ? cdaClient : cpaClient
|
||||
return client.getSpace()
|
||||
}, 'Space')
|
||||
|
||||
exports.getCourses = assert((locale = 'en-US', api = `cda`) => {
|
||||
// to get all the courses we request all the entries
|
||||
// with the content_type `course` from Contentful
|
||||
|
||||
@@ -30,17 +30,34 @@ html
|
||||
| View on Github
|
||||
|
||||
.header__controls
|
||||
form(action='' method='get')
|
||||
.group
|
||||
label(for='api') API:
|
||||
select(name='api' onChange='this.form.submit()')
|
||||
option(value='cda' selected=query.api === 'cda') Content Delivery API
|
||||
option(value='cpa' selected=query.api === 'cpa') Content Preview API
|
||||
.group
|
||||
label(for='locale') Locale:
|
||||
select(name='locale' onChange='this.form.submit()')
|
||||
option(value='en-US' selected=query.locale === 'en-US') English
|
||||
option(value='de-DE' selected=query.locale === 'de-DE') German
|
||||
.header__controls_group
|
||||
form(action='' method='get')
|
||||
.header__controls_label API: #{currentApi.label}
|
||||
.header__controls_dropdown
|
||||
.header__controls_help_text View the published or draft content by simply switching between the Deliver and Preview APIs.
|
||||
button.header__controls_button(
|
||||
type='submit'
|
||||
name='api'
|
||||
value='cda'
|
||||
class=`${currentApi.id === 'cda' ? 'header__controls_button--active' : ''}`
|
||||
) Delivery (published content)
|
||||
button.header__controls_button(
|
||||
type='submit'
|
||||
name='api'
|
||||
value='cpa'
|
||||
class=`${currentApi.id === 'cpa' ? 'header__controls_button--active' : ''}`
|
||||
) Preview (draft content)
|
||||
input(type='hidden' name='locale' value=currentLocale.code)
|
||||
|
||||
.header__controls_group
|
||||
form(action='' method='get')
|
||||
input(type='hidden' name='api' value=currentApi.id)
|
||||
.header__controls_label Locale: #{currentLocale.name}
|
||||
.header__controls_dropdown
|
||||
.header__controls_help_text Working with multiple languages? You can query the Content Delivery API for a specific locale.
|
||||
each locale in locales
|
||||
button.header__controls_button(type='submit' name='locale' value=locale.code class=`${locale.code === currentLocale.code ? 'header__controls_button--active' : ''}`)= `${locale.name} (${locale.code})`
|
||||
|
||||
.header__lower-wrapper
|
||||
.header__lower.layout-centered
|
||||
.header__logo
|
||||
@@ -93,4 +110,6 @@ html
|
||||
img(src='/images/icon-twitter.svg' alt='Our Twitter profile')
|
||||
script(src='/scripts/highlight.pack.js')
|
||||
script(src='/scripts/textFit.min.js')
|
||||
script(src='/scripts/popper.min.js')
|
||||
script(src='/scripts/hoverintent.min.js')
|
||||
script(src='/scripts/index.js')
|
||||
|
||||
Reference in New Issue
Block a user