1
0
mirror of https://github.com/trambarhq/relaks-wordpress-example.git synced 2025-09-25 06:51:30 +02:00

Cleaned up code a bit.

This commit is contained in:
Chung Leong
2019-01-27 15:02:54 +01:00
parent d2808c145b
commit fe55ecb7b9
13 changed files with 128 additions and 146 deletions

View File

@@ -24,11 +24,9 @@ services:
WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_PASSWORD: wordpress
restart: always restart: always
node: node:
image: node:8 image: wordpress-example
volumes: volumes:
- ..:/opt/example
- web_cache:/var/cache/nginx - web_cache:/var/cache/nginx
command: [ node, /opt/example/server/index.js ]
environment: environment:
WORDPRESS_HOST: wordpress WORDPRESS_HOST: wordpress
NGINX_HOST: nginx NGINX_HOST: nginx

View File

@@ -14,10 +14,7 @@ class ArchivePage extends AsyncComponent {
let { wp, route } = this.props; let { wp, route } = this.props;
let { date } = route.params; let { date } = route.params;
let month = Moment(`${date.year}-${_.padStart(date.month, 2, '0')}`); let month = Moment(`${date.year}-${_.padStart(date.month, 2, '0')}`);
let props = { let props = { route, month };
route,
month,
};
meanwhile.show(<ArchivePageSync {...props} />); meanwhile.show(<ArchivePageSync {...props} />);
let after = month.toISOString(); let after = month.toISOString();
let before = month.clone().endOf('month').toISOString(); let before = month.clone().endOf('month').toISOString();
@@ -33,7 +30,7 @@ class ArchivePageSync extends PureComponent {
render() { render() {
let { route, posts, month } = this.props; let { route, posts, month } = this.props;
let monthLabel = month.format('MMMM YYYY'); let monthLabel = month.format('MMMM YYYY');
let trail = [ { label: 'Archive' }, { label: monthLabel } ]; let trail = [ { label: 'Archives' }, { label: monthLabel } ];
return ( return (
<div className="page"> <div className="page">
<Breadcrumb trail={trail} /> <Breadcrumb trail={trail} />

View File

@@ -12,15 +12,22 @@ class CategoryPage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let { categorySlugs } = route.params; let { categorySlug } = route.params;
let props = { let props = { route };
route,
};
meanwhile.show(<CategoryPageSync {...props} />); meanwhile.show(<CategoryPageSync {...props} />);
props.categories = await wp.fetchMultiple('/wp/v2/categories/', categorySlugs); props.category = await wp.fetchOne('/wp/v2/categories/', categorySlug);
props.parentCategories = [];
let parentID = props.category.parent;
while (parentID) {
let parentCategory = await wp.fetchOne('/wp/v2/categories/', parentID);
if (!parentCategory) {
break;
}
props.parentCategories.push(parentCategory);
parentID = parentCategory.parent;
}
meanwhile.show(<CategoryPageSync {...props} />); meanwhile.show(<CategoryPageSync {...props} />);
let category = _.last(props.categories); props.posts = await wp.fetchList(`/wp/v2/posts/?categories=${props.category.id}`);
props.posts = await wp.fetchList(`/wp/v2/posts/?categories=${category.id}`);
return <CategoryPageSync {...props} />; return <CategoryPageSync {...props} />;
} }
} }
@@ -29,18 +36,15 @@ class CategoryPageSync extends PureComponent {
static displayName = 'CategoryPageSync'; static displayName = 'CategoryPageSync';
render() { render() {
let { route, posts, categories } = this.props; let { route, posts, category, parentCategories } = this.props;
let trail = [ { label: 'Categories' } ]; let trail = [ { label: 'Categories' } ];
let category = _.last(categories); let categoryLabel = _.get(category, 'name', '');
for (let c of categories) { for (let parentCategory of parentCategories) {
let label = _.get(c, 'name', ''); let label = _.get(parentCategory, 'name', '');
if (c !== category) { let url = route.getObjectURL(parentCategory);
let url = route.getObjectURL(c); trail.push({ label, url });
trail.push({ label, url });
} else {
trail.push({ label });
}
} }
trail.push({ label: categoryLabel });
return ( return (
<div className="page"> <div className="page">
<Breadcrumb trail={trail} /> <Breadcrumb trail={trail} />
@@ -59,6 +63,7 @@ if (process.env.NODE_ENV !== 'production') {
}; };
CategoryPageSync.propTypes = { CategoryPageSync.propTypes = {
category: PropTypes.object, category: PropTypes.object,
parentCategories: PropTypes.arrayOf(PropTypes.object),
posts: PropTypes.arrayOf(PropTypes.object), posts: PropTypes.arrayOf(PropTypes.object),
route: PropTypes.instanceOf(Route), route: PropTypes.instanceOf(Route),
}; };

View File

@@ -14,15 +14,21 @@ class PagePage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let { pageSlugs } = route.params; let { pageSlug } = route.params;
let props = { let props = { route };
route,
};
meanwhile.show(<PagePageSync {...props} />); meanwhile.show(<PagePageSync {...props} />);
props.pages = await wp.fetchMultiple('/wp/v2/pages/', pageSlugs); props.page = await wp.fetchOne('/wp/v2/pages/', pageSlug);
meanwhile.show(<PagePageSync {...props} />); props.parentPages = [];
let page = _.last(props.pages); let parentID = props.page.parent;
props.childPages = await wp.fetchList(`/wp/v2/pages/?parent=${page.id}`, { minimum: '100%' }); while (parentID) {
let parentPage = await wp.fetchOne('/wp/v2/pages/', parentID);
if (!parentPage) {
break;
}
props.parentPages.push(parentPage);
parentID = parentPage.parent;
}
props.childPages = await wp.fetchList(`/wp/v2/pages/?parent=${props.page.id}`);
return <PagePageSync {...props} />; return <PagePageSync {...props} />;
} }
} }
@@ -31,15 +37,12 @@ class PagePageSync extends PureComponent {
static displayName = 'PagePageSync'; static displayName = 'PagePageSync';
render() { render() {
let { route, pages, childPages, transform } = this.props; let { route, page, parentPages, childPages, transform } = this.props;
let page = _.last(pages);
let trail = []; let trail = [];
for (let p of pages) { for (let parentPage of parentPages) {
if (p !== page) { let title = _.get(parentPage, 'title.rendered', '');
let title = _.get(page, 'title.rendered', ''); let url = route.getObjectURL(parentPage);
let url = route.getObjectURL(p); trail.push({ label: <HTML text={title} />, url })
trail.push({ label: <HTML text={title} />, url })
}
} }
return ( return (
<div className="page"> <div className="page">

View File

@@ -15,14 +15,11 @@ class PostPage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let { postSlug } = route.params; let { postSlug } = route.params;
let props = { let props = { route };
route,
};
meanwhile.show(<PostPageSync {...props} />); meanwhile.show(<PostPageSync {...props} />);
props.post = await wp.fetchOne('/wp/v2/posts/', postSlug); props.post = await wp.fetchOne('/wp/v2/posts/', postSlug);
meanwhile.show(<PostPageSync {...props} />); meanwhile.show(<PostPageSync {...props} />);
let allCategories = await wp.fetchList('/wp/v2/categories/', { minimum: '100%' }); props.categories = await this.findCategoryChain(props.post.categories);
props.categories = findMatchingCategories(allCategories, props.post.categories, route.history);
meanwhile.show(<PostPageSync {...props} />); meanwhile.show(<PostPageSync {...props} />);
props.author = await wp.fetchOne('/wp/v2/users/', props.post.author); props.author = await wp.fetchOne('/wp/v2/users/', props.post.author);
if (!wp.ssr) { if (!wp.ssr) {
@@ -31,6 +28,64 @@ class PostPage extends AsyncComponent {
} }
return <PostPageSync {...props} />; return <PostPageSync {...props} />;
} }
async findCategoryChain(ids) {
let { wp, route } = this.props;
let allCategories = await wp.fetchList('/wp/v2/categories/', { minimum: '100%' });
// add categories, including their parents as well
let applicable = [];
let include = (id) => {
let category = _.find(allCategories, { id })
if (category) {
if (!_.includes(applicable, category)) {
applicable.push(category);
}
// add parent category as well
include(category.parent);
}
};
for (let id of ids) {
include(id);
}
// see how recently a category was visited
let historyIndex = (c) => {
return _.findLastIndex(route.history, { params: { categorySlug: c.slug }});
};
// see how deep a category is
let depth = (c) => {
if (c.parent) {
let parent = _.find(allCategories, { id: c.parent });
if (parent) {
return depth(parent) + 1;
}
}
return 0;
};
// order applicable categories based on how recently it was visited,
// how deep it is, and alphabetically; the first criteria makes our
// breadcrumb works more sensibly
applicable = _.orderBy(applicable, [ historyIndex, depth, 'name' ], [ 'desc', 'desc', 'asc' ]);
let anchorCategory = _.first(applicable);
let trail = [];
if (anchorCategory) {
// add category and its ancestors
for (let c = anchorCategory; c; c = _.find(applicable, { id: c.parent })) {
trail.unshift(c);
}
// add applicable child categories
for (let c = anchorCategory; c; c = _.find(applicable, { parent: c.id })) {
if (c !== anchorCategory) {
trail.push(c);
}
}
}
return trail;
}
} }
class PostPageSync extends PureComponent { class PostPageSync extends PureComponent {
@@ -54,61 +109,6 @@ class PostPageSync extends PureComponent {
} }
} }
function includeCategory(list, id, allCategories) {
let category = _.find(allCategories, { id })
if (category) {
if (!_.includes(list, category)) {
list.push(category);
}
// add parent category as well
includeCategory(list, category.parent, allCategories);
}
}
function findMatchingCategories(allCategories, ids, history) {
let applicable = [];
for (let id of ids) {
includeCategory(applicable, id, allCategories);
}
let historyIndex = (c) => {
return _.findLastIndex(history, (route) => {
if (route.params.categorySlugs) {
return _.includes(route.params.categorySlugs, c.slug);
}
});
};
let depth = (c) => {
if (c.parent) {
let parent = _.find(allCategories, { id: c.parent });
if (parent) {
return depth(parent) + 1;
}
}
return 0;
};
// order applicable categories based on how recently it was visited,
// how deep it is, and alphabetically
applicable = _.orderBy(applicable, [ historyIndex, depth, 'name' ], [ 'desc', 'desc', 'asc' ]);
let anchorCategory = _.first(applicable);
let trail = [];
if (anchorCategory) {
// add category and its ancestors
for (let c = anchorCategory; c; c = _.find(applicable, { id: c.parent })) {
trail.unshift(c);
}
// add applicable child categories
for (let c = anchorCategory; c; c = _.find(applicable, { parent: c.id })) {
if (c !== anchorCategory) {
trail.push(c);
}
}
}
return trail;
}
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');

View File

@@ -12,14 +12,12 @@ class SearchPage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let { search } = route.params; let { search } = route.params;
let props = { let props = { route };
route,
};
meanwhile.show(<SearchPageSync {...props} />); meanwhile.show(<SearchPageSync {...props} />);
props.categories = await wp.fetchList('/wp/v2/categories/'); props.categories = await wp.fetchList('/wp/v2/categories/');
if (search) { if (search) {
let url = `/wp/v2/posts/?search=${encodeURIComponent(search)}'`; let s = encodeURIComponent(search);
props.posts = await wp.fetchList(url); props.posts = await wp.fetchList(`/wp/v2/posts/?search=${s}`);
} else { } else {
props.posts = null; props.posts = null;
} }

View File

@@ -13,9 +13,7 @@ class TagPage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let { tagSlug } = route.params; let { tagSlug } = route.params;
let props = { let props = { route };
route,
};
meanwhile.show(<TagPageSync {...props} />); meanwhile.show(<TagPageSync {...props} />);
props.tag = await wp.fetchOne('/wp/v2/tags/', tagSlug); props.tag = await wp.fetchOne('/wp/v2/tags/', tagSlug);
meanwhile.show(<TagPageSync {...props} />); meanwhile.show(<TagPageSync {...props} />);

View File

@@ -10,11 +10,8 @@ class WelcomePage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let props = { let props = { route };
route,
};
meanwhile.show(<WelcomePageSync {...props} />); meanwhile.show(<WelcomePageSync {...props} />);
props.categories = await wp.fetchList('/wp/v2/categories/');
props.posts = await wp.fetchList('/wp/v2/posts/'); props.posts = await wp.fetchList('/wp/v2/posts/');
return <WelcomePageSync {...props} />; return <WelcomePageSync {...props} />;
} }
@@ -24,10 +21,10 @@ class WelcomePageSync extends PureComponent {
static displayName = 'WelcomePageSync'; static displayName = 'WelcomePageSync';
render() { render() {
let { route, categories, posts } = this.props; let { route, posts } = this.props;
return ( return (
<div className="page"> <div className="page">
<PostList categories={categories} route={route} posts={posts} minimum={40} /> <PostList route={route} posts={posts} minimum={40} />
</div> </div>
); );
} }

View File

@@ -61,7 +61,7 @@ class Route {
// get the site URL and see what the page's URL would be if it // get the site URL and see what the page's URL would be if it
// were on WordPress itself // were on WordPress itself
let siteURL = await this.getSiteURL(); let siteURL = await this.getSiteURL();
let link = _.trimEnd(siteURL + path, '/') + '/'; let link = _.trimEnd(siteURL + path, '/');
// see if it's a search // see if it's a search
let search = query.s; let search = query.s;
@@ -85,31 +85,29 @@ class Route {
if (postID) { if (postID) {
let post = await this.dataSource.fetchOne('/wp/v2/posts/', postID); let post = await this.dataSource.fetchOne('/wp/v2/posts/', postID);
if (post) { if (post) {
let postSlug = post.slug; return { pageType: 'post', postSlug: post.slug, siteURL };
return { pageType: 'post', postSlug, siteURL };
} }
} }
// see if it's pointing to a page // see if it's pointing to a page
let allPages = await this.dataSource.fetchList('/wp/v2/pages/', { minimum: '100%' }); let allPages = await this.dataSource.fetchList('/wp/v2/pages/', { minimum: '100%' });
let pageSlugs = findMatchingSlugs(allPages, link); let page = _.find(allPages, { link });
if (pageSlugs) { if (page) {
return { pageType: 'page', pageSlugs, siteURL }; return { pageType: 'page', pageSlug: page.slug, siteURL };
} }
// see if it's pointing to a category // see if it's pointing to a category
let allCategories = await this.dataSource.fetchList('/wp/v2/categories/', { minimum: '100%' }); let allCategories = await this.dataSource.fetchList('/wp/v2/categories/', { minimum: '100%' });
let categorySlugs = findMatchingSlugs(allCategories, link); let category = _.find(allCategories, { link });
if (categorySlugs) { if (category) {
return { pageType: 'category', categorySlugs, siteURL }; return { pageType: 'category', categorySlug: category.slug, siteURL };
} }
// see if it's pointing to a tag // see if it's pointing to a tag
let allTags = await this.dataSource.fetchList('/wp/v2/tags/', { minimum: '100%' }); let allTags = await this.dataSource.fetchList('/wp/v2/tags/', { minimum: '100%' });
let tagSlugs = findMatchingSlugs(allTags, link); let tag = _.find(allTags, { link });
if (tagSlugs) { if (tag) {
let tagSlug = tagSlugs[0]; return { pageType: 'tag', tagSlug: tag.slug, siteURL };
return { pageType: 'tag', tagSlug, siteURL };
} }
// see if it's pointing to a post // see if it's pointing to a post
@@ -187,20 +185,6 @@ function findPostID(path) {
} }
} }
function findMatchingSlugs(objects, link) {
let matches = [];
for (let object of objects) {
let objectLink = _.trimEnd(object.link, '/') + '/';
if (_.startsWith(link, objectLink)) {
matches.push(object);
}
}
if (matches.length > 0) {
let slugs = _.map(_.sortBy(matches, 'link.length'), 'slug');
return slugs;
}
}
let routes = { let routes = {
'page': { path: '*' }, 'page': { path: '*' },
}; };

View File

@@ -33,7 +33,7 @@ if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
PageView.propTypes = { PageView.propTypes = {
category: PropTypes.object, page: PropTypes.object,
transform: PropTypes.func, transform: PropTypes.func,
}; };
} }

View File

@@ -60,6 +60,7 @@ if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
PostList.propTypes = { PostList.propTypes = {
posts: PropTypes.arrayOf(PropTypes.object),
route: PropTypes.instanceOf(Route), route: PropTypes.instanceOf(Route),
minimum: PropTypes.number, minimum: PropTypes.number,
maximum: PropTypes.number, maximum: PropTypes.number,

View File

@@ -155,12 +155,12 @@ class SideNavSync extends PureComponent {
renderCategory(category, i) { renderCategory(category, i) {
let { route } = this.props; let { route } = this.props;
let { categorySlugs } = route.params; let { categorySlug } = route.params;
let name = _.get(category, 'name', ''); let name = _.get(category, 'name', '');
let description = _.get(category, 'description', ''); let description = _.get(category, 'description', '');
let url = route.getObjectURL(category); let url = route.getObjectURL(category);
let className; let className;
if (category.slug === _.last(categorySlugs)) { if (category.slug === categorySlug) {
className = 'selected'; className = 'selected';
} }
return ( return (

View File

@@ -15,7 +15,7 @@ class TopNav extends AsyncComponent {
meanwhile.show(<TopNavSync {...props} />); meanwhile.show(<TopNavSync {...props} />);
props.system = await wp.fetchOne('/'); props.system = await wp.fetchOne('/');
meanwhile.show(<TopNavSync {...props} />); meanwhile.show(<TopNavSync {...props} />);
props.pages = await wp.fetchList('/wp/v2/pages/?parent=0', { minimum: '100%' }); props.pages = await wp.fetchList('/wp/v2/pages/', { minimum: '100%' });
return <TopNavSync {...props} />; return <TopNavSync {...props} />;
} }
} }
@@ -61,6 +61,7 @@ class TopNavSync extends PureComponent {
renderPageLinkBar() { renderPageLinkBar() {
let { pages } = this.props; let { pages } = this.props;
pages = _.filter(pages, { parent: 0 });
pages = _.sortBy(pages, 'menu_order'); pages = _.sortBy(pages, 'menu_order');
return ( return (
<div className="page-bar"> <div className="page-bar">