* Production (#44) * test: Fix integration test * fix: Fix Editorial feature * chore(localization): move locales to i18n folder * feat(modules): add image caption and shadow * fix: clarify German translation🇩🇪 * chore(localization): fix typo (#47) * Split first paragraph into sections (#46) * feat(controls): add help text to API dropdown * fix(style): simplify header and fix mobile design * fix(style): simplify footer and fix mobile design * fix(style): update stylesheet and scripts file * test(e2e): adjust tests and make them fail on CI * language fixes * rename labels to use full api name * Refactor entry state toggle (#48) * chore(editorialFeatures): extract editorial features toggle * chore(refactor): rename function to make more contextual sense * Fix breadcrumb and add test for locales (#49) * test(unit): add test to check for locale consistency * fix(breadcrumb): translate lessons route * Change readme url to http from https (#52) * tests(e2e): expect only 2 courses * fix(cookies): fix variable naming and extend to two days maxAge * Change text on next lesson button (#54) * Retranslate advancedLabel * fix(translations): do not break on vim temp files. This is dedicated to JP * fix(analytics): use correct app-id * Add instructions to seed a space to readme (#61) * Change modal text; add link to model's repo to localization files (#57) * fix(links): link correct GH repository * fix(i18n): adjust view on github link label * fix(style): move GitHub link to the left * new screenshot * Update README.md (#63) * Update README.md * Update README.md * Https mistake and Heroku buton * fixup * fixup * feat(heroku): add app.json * docs(README): add linebreak * docs(README): minor adjustments * fix(tracking): add link click tracking to snowplow * Add translation for edit in the web app (#64) * chore(typo): fix error message (#67) * chore(update): remove image rendering on lessons (#65) * chore: Improve error page (#66) * chore: Improve error page * fix: Fix middlware order * fix: Remove console.log * fix: no more duplicate error messges (#71) * fix: Fix middlware order * fix: Remove console.log * feat: Uniq error meassages * fix: fix cli link (#72) * Add instructions to run app as Docker container (#68)
176 lines
4.8 KiB
JavaScript
176 lines
4.8 KiB
JavaScript
/**
|
|
* This module renders the settings page when `settings` route is requested
|
|
* it also saves the settings to a cookie
|
|
*/
|
|
const { createClient } = require('contentful')
|
|
const { initClients, getSpace } = require('./../services/contentful')
|
|
const { updateCookie } = require('../lib/cookies')
|
|
const { translate } = require('../i18n/i18n')
|
|
const { uniqWith, isEqual } = require('lodash')
|
|
const SETTINGS_NAME = 'theExampleAppSettings'
|
|
|
|
async function renderSettings (response, opts) {
|
|
// Get connected space to display the space name on top of the settings
|
|
let space = false
|
|
try {
|
|
space = await getSpace()
|
|
} catch (error) {
|
|
// We throw the error here, it will be handled by the error middleware
|
|
// We keep space false to ensure the "Connected to" box is not shown.
|
|
throw (error)
|
|
}
|
|
|
|
response.render('settings', {
|
|
title: translate('settingsLabel', response.locals.currentLocale.code),
|
|
errors: {},
|
|
hasErrors: false,
|
|
success: false,
|
|
space,
|
|
...opts
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Renders the settings page when `/settings` route is requested
|
|
*
|
|
* @param request - Object - Express request
|
|
* @param response - Object - Express response
|
|
* @param next - Function - Express callback
|
|
*
|
|
* @returns {undefined}
|
|
*/
|
|
module.exports.getSettings = async (request, response, next) => {
|
|
const { settings } = response.locals
|
|
await renderSettings(response, {
|
|
settings
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Save settings when POST request is triggered to the `/settings` route
|
|
* and render the settings page
|
|
*
|
|
* @param request - Object - Express request
|
|
* @param response - Object - Express response
|
|
* @param next - Function - Express callback
|
|
*
|
|
* @returns {undefined}
|
|
*/
|
|
module.exports.postSettings = async (request, response, next) => {
|
|
const currentLocale = response.locals.currentLocale
|
|
let errorList = []
|
|
const { spaceId, deliveryToken, previewToken, editorialFeatures } = request.body
|
|
const settings = {
|
|
spaceId,
|
|
deliveryToken,
|
|
previewToken,
|
|
editorialFeatures: !!editorialFeatures
|
|
}
|
|
|
|
// Validate required fields.
|
|
if (!spaceId) {
|
|
errorList.push({
|
|
field: 'spaceId',
|
|
message: translate('fieldIsRequiredLabel', currentLocale.code)
|
|
})
|
|
}
|
|
|
|
if (!deliveryToken) {
|
|
errorList.push({
|
|
field: 'deliveryToken',
|
|
message: translate('fieldIsRequiredLabel', currentLocale.code)
|
|
})
|
|
}
|
|
|
|
if (!previewToken) {
|
|
errorList.push({
|
|
field: 'previewToken',
|
|
message: translate('fieldIsRequiredLabel', currentLocale.code)
|
|
})
|
|
}
|
|
|
|
// Validate space and delivery access token.
|
|
if (spaceId && deliveryToken) {
|
|
try {
|
|
await createClient({
|
|
space: spaceId,
|
|
accessToken: deliveryToken
|
|
}).getSpace()
|
|
} catch (err) {
|
|
if (err.response.status === 401) {
|
|
errorList.push({
|
|
field: 'deliveryToken',
|
|
message: translate('deliveryKeyInvalidLabel', currentLocale.code)
|
|
})
|
|
} else if (err.response.status === 404) {
|
|
errorList.push({
|
|
field: 'spaceId',
|
|
message: translate('spaceOrTokenInvalid', currentLocale.code)
|
|
})
|
|
} else {
|
|
errorList.push({
|
|
field: 'deliveryToken',
|
|
message: `${translate('somethingWentWrongLabel', currentLocale.code)}: ${err.response.data.message}`
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// Validate space and CPA access token.
|
|
if (spaceId && previewToken) {
|
|
try {
|
|
await createClient({
|
|
space: spaceId,
|
|
accessToken: previewToken,
|
|
host: 'preview.contentful.com'
|
|
}).getSpace()
|
|
} catch (err) {
|
|
if (err.response.status === 401) {
|
|
errorList.push({
|
|
field: 'previewToken',
|
|
message: translate('previewKeyInvalidLabel', currentLocale.code)
|
|
})
|
|
} else if (err.response.status === 404) {
|
|
errorList.push({
|
|
field: 'spaceId',
|
|
message: translate('spaceOrTokenInvalid', currentLocale.code)
|
|
})
|
|
} else {
|
|
errorList.push({
|
|
field: 'previewToken',
|
|
message: `${translate('somethingWentWrongLabel', currentLocale.code)}: ${err.response.data.message}`
|
|
})
|
|
}
|
|
}
|
|
}
|
|
errorList = uniqWith(errorList, isEqual)
|
|
// If no errors, then cache the new settings in the cookie
|
|
if (!errorList.length) {
|
|
// Store new settings
|
|
updateCookie(response, SETTINGS_NAME, settings)
|
|
response.locals.settings = settings
|
|
|
|
// Reinit clients
|
|
initClients(settings)
|
|
}
|
|
|
|
// Generate error dictionary
|
|
// Format: { FIELD_NAME: [array, of, error, messages] }
|
|
const errors = errorList.reduce((errors, error) => {
|
|
return {
|
|
...errors,
|
|
[error.field]: [
|
|
...(errors[error.field] || []),
|
|
error.message
|
|
]
|
|
}
|
|
}, {})
|
|
|
|
await renderSettings(response, {
|
|
settings,
|
|
errors,
|
|
hasErrors: errorList.length > 0,
|
|
success: errorList.length === 0
|
|
})
|
|
}
|