refactors the frontend controller

closes #5192
- combines homepage, author, tag routes into one function (with different hash params)
- provides some abstraction for channels
This commit is contained in:
Austin Burdine 2015-05-05 00:21:29 -05:00
parent 2ac3b146b1
commit 8ac168794e
3 changed files with 76 additions and 123 deletions

View File

@ -143,56 +143,30 @@ function renderPost(req, res) {
};
}
frontendControllers = {
homepage: function (req, res, next) {
// Parse the page number
function renderChannel(channelOpts) {
channelOpts = channelOpts || {};
return function renderChannel(req, res, next) {
var pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1,
options = {
page: pageParam
};
},
hasSlug,
filter, filterKey;
// No negative pages, or page 1
if (isNaN(pageParam) || pageParam < 1 || (pageParam === 1 && req.route.path === '/page/:page/')) {
return res.redirect(config.paths.subdir + '/');
// Add the slug if it exists in the route
if (channelOpts.route.indexOf(':slug') !== -1) {
options[channelOpts.name] = req.params.slug;
hasSlug = true;
}
return getPostPage(options).then(function (page) {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > page.meta.pagination.pages) {
return res.redirect(page.meta.pagination.pages === 1 ? config.paths.subdir + '/' : (config.paths.subdir + '/page/' + page.meta.pagination.pages + '/'));
function createUrl(page) {
var url = config.paths.subdir + channelOpts.route;
if (hasSlug) {
url = url.replace(':slug', options[channelOpts.name]);
}
setReqCtx(req, page.posts);
// Render the page of posts
filters.doFilter('prePostsRender', page.posts, res.locals).then(function (posts) {
getActiveThemePaths().then(function (paths) {
var view = paths.hasOwnProperty('home.hbs') ? 'home' : 'index';
// If we're on a page then we always render the index
// template.
if (pageParam > 1) {
view = 'index';
}
setResponseContext(req, res);
res.render(view, formatPageResponse(posts, page));
});
});
}).catch(handleError(next));
},
tag: function (req, res, next) {
// Parse the page number
var pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1,
options = {
page: pageParam,
tag: req.params.slug
};
// Get url for tag page
function tagUrl(tag, page) {
var url = config.paths.subdir + '/' + config.routeKeywords.tag + '/' + tag + '/';
if (page && page > 1) {
url += 'page/' + page + '/';
}
@ -200,88 +174,47 @@ frontendControllers = {
return url;
}
// No negative pages, or page 1
if (isNaN(pageParam) || pageParam < 1 || (req.params.page !== undefined && pageParam === 1)) {
return res.redirect(tagUrl(options.tag));
return res.redirect(createUrl());
}
return getPostPage(options).then(function (page) {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > page.meta.pagination.pages) {
return res.redirect(tagUrl(options.tag, page.meta.pagination.pages));
return res.redirect(createUrl(page.meta.pagination.pages));
}
setReqCtx(req, page.posts);
if (page.meta.filters.tags) {
setReqCtx(req, page.meta.filters.tags[0]);
if (channelOpts.filter && page.meta.filters[channelOpts.filter]) {
filterKey = page.meta.filters[channelOpts.filter];
filter = (_.isArray(filterKey)) ? filterKey[0] : filterKey;
setReqCtx(req, filter);
}
// Render the page of posts
filters.doFilter('prePostsRender', page.posts, res.locals).then(function (posts) {
getActiveThemePaths().then(function (paths) {
var view = template.getThemeViewForTag(paths, options.tag),
// Format data for template
result = formatPageResponse(posts, page, {
tag: page.meta.filters.tags ? page.meta.filters.tags[0] : ''
});
var view = 'index',
result,
extra = {};
// If the resulting tag is '' then 404.
if (!result.tag) {
return next();
if (channelOpts.firstPageTemplate && paths.hasOwnProperty(channelOpts.firstPageTemplate + '.hbs')) {
view = (pageParam > 1) ? 'index' : channelOpts.firstPageTemplate;
} else if (channelOpts.slugTemplate) {
view = template.getThemeViewForChannel(paths, channelOpts.name, options[channelOpts.name]);
} else if (paths.hasOwnProperty(channelOpts.name + '.hbs')) {
view = channelOpts.name;
}
setResponseContext(req, res);
res.render(view, result);
});
});
}).catch(handleError(next));
},
author: function (req, res, next) {
// Parse the page number
var pageParam = req.params.page !== undefined ? parseInt(req.params.page, 10) : 1,
options = {
page: pageParam,
author: req.params.slug
};
// Get url for tag page
function authorUrl(author, page) {
var url = config.paths.subdir + '/' + config.routeKeywords.author + '/' + author + '/';
if (channelOpts.filter) {
extra[channelOpts.name] = (filterKey) ? filter : '';
if (page && page > 1) {
url += config.routeKeywords.page + '/' + page + '/';
}
if (!extra[channelOpts.name]) {
return next();
}
return url;
}
// No negative pages, or page 1
if (isNaN(pageParam) || pageParam < 1 || (req.params.page !== undefined && pageParam === 1)) {
return res.redirect(authorUrl(options.author));
}
return getPostPage(options).then(function (page) {
// If page is greater than number of pages we have, redirect to last page
if (pageParam > page.meta.pagination.pages) {
return res.redirect(authorUrl(options.author, page.meta.pagination.pages));
}
setReqCtx(req, page.posts);
if (page.meta.filters.author) {
setReqCtx(req, page.meta.filters.author);
}
// Render the page of posts
filters.doFilter('prePostsRender', page.posts, res.locals).then(function (posts) {
getActiveThemePaths().then(function (paths) {
var view = paths.hasOwnProperty('author.hbs') ? 'author' : 'index',
// Format data for template
result = formatPageResponse(posts, page, {
author: page.meta.filters.author ? page.meta.filters.author : ''
});
// If the resulting author is '' then 404.
if (!result.author) {
return next();
result = formatPageResponse(posts, page, extra);
} else {
result = formatPageResponse(posts, page);
}
setResponseContext(req, res);
@ -289,8 +222,27 @@ frontendControllers = {
});
});
}).catch(handleError(next));
},
};
}
frontendControllers = {
homepage: renderChannel({
name: 'home',
route: '/',
firstPageTemplate: 'home'
}),
tag: renderChannel({
name: 'tag',
route: '/' + config.routeKeywords.tag + '/:slug/',
filter: 'tags',
slugTemplate: true
}),
author: renderChannel({
name: 'author',
route: '/' + config.routeKeywords.author + '/:slug/',
filter: 'author',
slugTemplate: true
}),
preview: function (req, res, next) {
var params = {
uuid: req.params.uuid,

View File

@ -44,21 +44,21 @@ templates.getThemeViewForPost = function (themePaths, post) {
return view;
};
// Given a theme object and a tag slug this will return
// Given a theme object and a slug this will return
// which theme template page should be used.
// If no default or custom tag template exists then 'index'
// will be returned
// If no custom tag template exists but a default does then
// 'tag' will be returned
// If given a tag slug and a custom tag template
// If no custom template exists but a default does then
// the default will be returned
// If given a slug and a custom template
// exits it will return that view.
templates.getThemeViewForTag = function (themePaths, tag) {
var customTagView = 'tag-' + tag,
view = 'tag';
templates.getThemeViewForChannel = function (themePaths, channelName, slug) {
var customChannelView = channelName + '-' + slug,
view = channelName;
if (themePaths.hasOwnProperty(customTagView + '.hbs')) {
view = customTagView;
} else if (!themePaths.hasOwnProperty('tag.hbs')) {
if (themePaths.hasOwnProperty(customChannelView + '.hbs')) {
view = customChannelView;
} else if (!themePaths.hasOwnProperty(channelName + '.hbs')) {
view = 'index';
}

View File

@ -51,7 +51,7 @@ describe('Helpers Template', function () {
});
});
describe('getThemeViewForTag', function () {
describe('getThemeViewForChannel', function () {
var themePathsWithTagViews = {
assets: null,
'default.hbs': '/content/themes/casper/default.hbs',
@ -64,19 +64,20 @@ describe('Helpers Template', function () {
'default.hbs': '/content/themes/casper/default.hbs',
'index.hbs': '/content/themes/casper/index.hbs'
},
TAG_CUSTOM_EXISTS = 'design',
TAG_DEFAULT = 'development';
CHANNEL = 'tag',
CUSTOM_EXISTS = 'design',
DEFAULT = 'development';
it('will return correct view for a tag', function () {
var view = template.getThemeViewForTag(themePathsWithTagViews, TAG_CUSTOM_EXISTS);
var view = template.getThemeViewForChannel(themePathsWithTagViews, CHANNEL, CUSTOM_EXISTS);
view.should.exist;
view.should.eql('tag-design');
view = template.getThemeViewForTag(themePathsWithTagViews, TAG_DEFAULT);
view = template.getThemeViewForChannel(themePathsWithTagViews, CHANNEL, DEFAULT);
view.should.exist;
view.should.eql('tag');
view = template.getThemeViewForTag(themePaths, TAG_DEFAULT);
view = template.getThemeViewForChannel(themePaths, CHANNEL, DEFAULT);
view.should.exist;
view.should.eql('index');
});