diff --git a/server/nginx/default.conf b/server/nginx/default.conf
index 8630c67..60eb017 100644
--- a/server/nginx/default.conf
+++ b/server/nginx/default.conf
@@ -25,13 +25,11 @@ server {
proxy_cache_min_uses 1;
proxy_cache_valid 200 301 302 120m;
proxy_cache_valid 404 1m;
- proxy_hide_header Cache-Control;
- proxy_ignore_headers Cache-Control Expires Set-Cookie;
+ add_header Access-Control-Allow-Origin *;
add_header Cache-Control "public,max-age=0";
add_header X-Cache-Date $upstream_http_date;
add_header X-Cache-Status $upstream_cache_status;
- add_header Access-Control-Allow-Origin *;
}
}
diff --git a/server/page-renderer.js b/server/page-renderer.js
index ecb48a4..72bd9df 100644
--- a/server/page-renderer.js
+++ b/server/page-renderer.js
@@ -10,6 +10,7 @@ const HTML_TEMPLATE = `${__dirname}/client/index.html`;
async function generate(path, target) {
// retrieve cached JSON through Nginx
+ console.log(`Regenerating page: ${path}`);
let host = `http://${NGINX_HOST}`;
// create a fetch() that remembers the URLs used
let sourceURLs = [];
diff --git a/src/main.js b/src/main.js
index ba759c2..25a2b64 100644
--- a/src/main.js
+++ b/src/main.js
@@ -31,7 +31,7 @@ if (typeof(window) === 'object') {
});
routeManager.addEventListener('beforechange', (evt) => {
let route = new Route(routeManager, dataSource);
- evt.postponeDefault(route.setPageType(evt.params));
+ evt.postponeDefault(route.setParameters(evt));
});
routeManager.activate();
await routeManager.start();
@@ -57,7 +57,6 @@ if (typeof(window) === 'object') {
let mtime = await res.text();
if (mtime !== mtimeLast) {
if (mtimeLast) {
- console.log('changed');
dataSource.invalidate();
}
mtimeLast = mtime;
@@ -84,7 +83,7 @@ if (typeof(window) === 'object') {
});
routeManager.addEventListener('beforechange', (evt) => {
let route = new Route(routeManager, dataSource);
- evt.postponeDefault(route.setPageType(evt.params));
+ evt.postponeDefault(route.setParameters(evt));
});
routeManager.activate();
await routeManager.start(options.path);
diff --git a/src/pages/archive-page.jsx b/src/pages/archive-page.jsx
index af3841a..fff76e8 100644
--- a/src/pages/archive-page.jsx
+++ b/src/pages/archive-page.jsx
@@ -12,22 +12,16 @@ class ArchivePage extends AsyncComponent {
async renderAsync(meanwhile) {
let { wp, route } = this.props;
- let { monthSlug, categorySlug } = route.params;
- let month = Moment(monthSlug);
+ let { date } = route.params;
+ let month = Moment(`${date.year}-${date.month}`);
let props = {
route,
month,
};
+ meanwhile.show();
let after = month.toISOString();
let before = month.clone().endOf('month').toISOString();
- meanwhile.show();
- props.categories = await wp.fetchList('/wp/v2/categories/');
- meanwhile.show();
let url = `/wp/v2/posts/?after=${after}&before=${before}`;
- if (categorySlug) {
- let category = _.find(props.categories, { slug: categorySlug });
- url = `/wp/v2/posts/?after=${after}&before=${before}&categories=${category.id}`;
- }
props.posts = await wp.fetchList(url);
return ;
}
@@ -37,23 +31,13 @@ class ArchivePageSync extends PureComponent {
static displayName = 'ArchivePageSync';
render() {
- let { route, categories, posts, month } = this.props;
- let { monthSlug, categorySlug } = route.params;
+ let { route, posts, month } = this.props;
let monthLabel = month.format('MMMM YYYY');
- let monthURL = route.find([ monthSlug ]);
- let trail = [ { label: 'Archive' } ];
- if (categorySlug) {
- let category = _.find(categories, { slug: categorySlug });
- let categoryLabel = _.get(category, 'name', '');
- trail.push({ label: monthLabel, url: monthURL });
- trail.push({ label: categoryLabel });
- } else {
- trail.push({ label: monthLabel });
- }
+ let trail = [ { label: 'Archive' }, { label: monthLabel } ];
return (
);
}
@@ -67,7 +51,6 @@ if (process.env.NODE_ENV !== 'production') {
route: PropTypes.instanceOf(Route),
};
ArchivePageSync.propTypes = {
- category: PropTypes.object,
posts: PropTypes.arrayOf(PropTypes.object),
month: PropTypes.instanceOf(Moment),
route: PropTypes.instanceOf(Route),
diff --git a/src/pages/category-page.jsx b/src/pages/category-page.jsx
index 16d84b9..df275cc 100644
--- a/src/pages/category-page.jsx
+++ b/src/pages/category-page.jsx
@@ -1,3 +1,4 @@
+import _ from 'lodash';
import React, { PureComponent } from 'react';
import { AsyncComponent } from 'relaks';
import { Route } from 'routing';
@@ -11,14 +12,14 @@ class CategoryPage extends AsyncComponent {
async renderAsync(meanwhile) {
let { wp, route } = this.props;
- let { categorySlug } = route.params;
+ let { categorySlugs } = route.params;
let props = {
route,
};
meanwhile.show();
- props.categories = await wp.fetchList('/wp/v2/categories/');
+ props.categories = await wp.fetchMultiple('/wp/v2/categories/', categorySlugs);
meanwhile.show();
- let category = _.find(props.categories, { slug: categorySlug });
+ let category = _.last(props.categories);
props.posts = await wp.fetchList(`/wp/v2/posts/?categories=${category.id}`);
return ;
}
@@ -29,13 +30,17 @@ class CategoryPageSync extends PureComponent {
render() {
let { route, posts, categories } = this.props;
- let { categorySlug } = route.params;
- let category = _.find(categories, { slug: categorySlug });
- let categoryLabel = _.get(category, 'name', '');
- let trail = [
- { label: 'Categories' },
- { label: categoryLabel },
- ];
+ let trail = [ { label: 'Categories' } ];
+ let category = _.last(categories);
+ for (let c of categories) {
+ let label = _.get(c, 'name', '');
+ if (c !== category) {
+ let url = route.getObjectURL(c);
+ trail.push({ label, url });
+ } else {
+ trail.push({ label });
+ }
+ }
return (
diff --git a/src/pages/page-page.jsx b/src/pages/page-page.jsx
index 22eb5cf..2a5ea2e 100644
--- a/src/pages/page-page.jsx
+++ b/src/pages/page-page.jsx
@@ -14,15 +14,15 @@ class PagePage extends AsyncComponent {
async renderAsync(meanwhile) {
let { wp, route } = this.props;
- let { pageSlug, parentPageSlugs } = route.params;
+ let { pageSlugs } = route.params;
let props = {
route,
};
- props.page = await wp.fetchOne('/wp/v2/pages/', pageSlug);
meanwhile.show(
);
- props.parentPages = await wp.fetchMultiple('/wp/v2/pages/', parentPageSlugs);
+ props.pages = await wp.fetchMultiple('/wp/v2/pages/', pageSlugs);
meanwhile.show(
);
- props.childPages = await wp.fetchList(`/wp/v2/pages/?parent=${props.page.id}`, { minimum: '100%' });
+ let page = _.last(props.pages);
+ props.childPages = await wp.fetchList(`/wp/v2/pages/?parent=${page.id}`, { minimum: '100%' });
return
;
}
}
@@ -31,25 +31,21 @@ class PagePageSync extends PureComponent {
static displayName = 'PagePageSync';
render() {
- let { route, page, parentPages, childPages, transform } = this.props;
+ let { route, pages, childPages, transform } = this.props;
+ let page = _.last(pages);
let trail = [];
- let parents = [];
- if (parentPages) {
- for (let parentPage of parentPages) {
- parents.push(parentPage);
-
- let title = _.get(parentPage, 'title.rendered', '');
- let slugs = _.map(parents, 'slug');
- let url = route.find(slugs);
+ for (let p of pages) {
+ if (p !== page) {
+ let title = _.get(page, 'title.rendered', '');
+ let url = route.getObjectURL(p);
trail.push({ label:
, url })
}
- parents.push(page);
}
return (
);
}
diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx
index 3c11d4d..b1bf4ea 100644
--- a/src/pages/post-page.jsx
+++ b/src/pages/post-page.jsx
@@ -14,20 +14,16 @@ class PostPage extends AsyncComponent {
async renderAsync(meanwhile) {
let { wp, route } = this.props;
- let { monthSlug, categorySlug, postSlug } = route.params;
+ let { postSlug } = route.params;
let props = {
route,
};
- if (monthSlug) {
- props.month = Moment(monthSlug);
- }
meanwhile.show();
- if (categorySlug) {
- props.category = await wp.fetchOne('/wp/v2/categories/', categorySlug);
- meanwhile.show();
- }
props.post = await wp.fetchOne('/wp/v2/posts/', postSlug);
meanwhile.show();
+ let allCategories = await wp.fetchList('/wp/v2/categories/', { minimum: '100%' });
+ props.categories = findMatchingCategories(allCategories, props.post.categories, route.history);
+ meanwhile.show();
props.author = await wp.fetchOne('/wp/v2/users/', props.post.author);
if (!wp.ssr) {
meanwhile.show();
@@ -41,36 +37,78 @@ class PostPageSync extends PureComponent {
static displayName = 'PostPageSync';
render() {
- let { route, month, category, post, author, comments } = this.props;
- let { monthSlug, categorySlug } = route.params;
- let trail = [];
- if (monthSlug) {
- let monthLabel = month.format('MMMM YYYY');
- let monthURL = route.find([ monthSlug ]);
- trail.push({ label: 'Archive' });
- trail.push({ label: monthLabel, url: monthURL });
- }
- if (categorySlug) {
- let categoryLabel = _.get(category, 'name', '');
- let categoryURL;
- if (monthSlug) {
- categoryURL = route.find([ monthSlug, categorySlug ]);
- } else {
- trail.push({ label: 'Categories' });
- categoryURL = route.find([ categorySlug ]);
- }
- trail.push({ label: categoryLabel, url: categoryURL });
+ let { route, categories, post, author, comments } = this.props;
+ let trail = [ { label: 'Categories' } ];
+ for (let c of categories) {
+ let label = _.get(c, 'name', '');
+ let url = route.getObjectURL(c);
+ trail.push({ label, url });
}
return (
);
}
}
+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') {
const PropTypes = require('prop-types');
@@ -79,11 +117,10 @@ if (process.env.NODE_ENV !== 'production') {
route: PropTypes.instanceOf(Route),
};
PostPageSync.propTypes = {
- category: PropTypes.object,
+ categories: PropTypes.arrayOf(PropTypes.object),
post: PropTypes.object,
author: PropTypes.object,
comments: PropTypes.arrayOf(PropTypes.object),
- month: PropTypes.instanceOf(Moment),
route: PropTypes.instanceOf(Route),
};
}
diff --git a/src/routing.js b/src/routing.js
index cf13506..548c79d 100644
--- a/src/routing.js
+++ b/src/routing.js
@@ -16,77 +16,113 @@ class Route {
return this.routeManager.change(url, options);
}
- find(params) {
- if (params instanceof Array) {
- let slugs = params;
- return this.routeManager.find('page', { slugs });
- } else {
- return this.routeManager.find('page', params);
- }
+ getRootURL() {
+ return this.composeURL({ path: '/' });
}
- async setPageType(params) {
- let slugs = params.slugs;
- if (slugs.length > 0) {
- let slugType1 = await this.getSlugType(slugs[0]);
- if (slugType1 === 'page') {
- params.pageType = 'page';
- params.pageSlug = _.last(slugs);
- params.parentPageSlugs = _.slice(slugs, 0, -1);
- } else if (slugType1 === 'category') {
- if (slugs.length === 1) {
- params.pageType = 'category';
- params.categorySlug = slugs[0];
- } else if (slugs.length === 2) {
- params.pageType = 'post';
- params.categorySlug = slugs[0];
- params.postSlug = slugs[1];
- }
- } else if (slugType1 === 'archive') {
- if (slugs.length === 1) {
- params.pageType = 'archive';
- params.monthSlug = slugs[0];
- } else if (slugs.length === 2) {
- let slugType2 = await this.getSlugType(slugs[1]);
- if (slugType2 === 'category') {
- params.pageType = 'archive';
- params.monthSlug = slugs[0];
- params.categorySlug = slugs[1];
- } else {
- params.pageType = 'post';
- params.monthSlug = slugs[0];
- params.postSlug = slugs[1];
- }
- } else if (slugs.length === 3) {
- params.pageType = 'post';
- params.monthSlug = slugs[0];
- params.categorySlug = slugs[1];
- params.postSlug = slugs[2];
- }
- }
- }
- if (!params.pageType) {
- if (params.search !== undefined) {
- params.pageType = 'search';
- } else {
- params.pageType = 'welcome';
- }
- }
+ getSearchURL(search) {
+ return this.composeURL({ path: '/', query: { s: search } });
}
- async getSlugType(slug) {
- let options = { minimum: '100%' };
- let pages = await this.dataSource.fetchList('/wp/v2/pages/?parent=0', options);
- if (_.some(pages, { slug })) {
- return 'page';
+ getArchiveURL(date) {
+ let { year, month } = date;
+ return this.composeURL({ path: `/date/${year}/${month}/` });
+ }
+
+ getObjectURL(object) {
+ let { siteURL } = this.params;
+ let url = object.link;
+ if (!_.startsWith(url, siteURL)) {
+ throw new Error(`Object URL does not match site URL`);
}
- let categories = await this.dataSource.fetchList('/wp/v2/categories/', options);
- if (_.some(categories, { slug })) {
- return 'category';
+ let path = url.substr(siteURL.length);
+ return this.composeURL({ path });
+ }
+
+
+
+ composeURL(urlParts) {
+ let context = _.clone(this.routeManager.context);
+ this.routeManager.rewrite('to', urlParts, context);
+ return this.routeManager.compose(urlParts);
+ }
+
+ async setParameters(evt) {
+ let params = await this.getParameters(evt.path, evt.query);
+ params.module = require(`pages/${params.pageType}-page`);
+ _.assign(evt.params, params);
+ }
+
+ async getParameters(path, query) {
+ // get the site URL and see what the page's URL would be if it
+ // were on WordPress itself
+ let siteURL = await this.getSiteURL();
+ let link = siteURL + path;
+ console.log(link);
+
+ // see if it's a search
+ let search = query.s;
+ if (search) {
+ return { pageType: 'search', search, siteURL };
}
- if (/^\d{4}\-\d{2}$/.test(slug)) {
- return 'archive';
+
+ // see if it's pointing to the root page
+ if (path === '/') {
+ return { pageType: 'welcome', siteURL };
}
+
+ // see if it's pointing to an archive
+ let date = findDate(path);
+ if (date) {
+ return { pageType: 'archive', date, siteURL };
+ }
+
+ // see if it's pointing to a post by ID
+ let postID = findPostID(path);
+ if (postID) {
+ let post = await this.dataSource.fetchOne('/wp/v2/posts/', postID);
+ if (post) {
+ let postSlug = post.slug;
+ return { pageType: 'post', postSlug, siteURL };
+ }
+ }
+
+ // see if it's pointing to a page
+ let allPages = await this.dataSource.fetchList('/wp/v2/pages/', { minimum: '100%' });
+ let pageSlugs = findMatchingSlugs(allPages, link);
+ if (pageSlugs) {
+ return { pageType: 'page', pageSlugs, siteURL };
+ }
+
+ // see if it's pointing to a category
+ let allCategories = await this.dataSource.fetchList('/wp/v2/categories/', { minimum: '100%' });
+ let categorySlugs = findMatchingSlugs(allCategories, link);
+ if (categorySlugs) {
+ return { pageType: 'category', categorySlugs, siteURL };
+ }
+
+ // see if it's pointing to a tag
+ let allTags = await this.dataSource.fetchList('/wp/v2/tags/', { minimum: '100%' });
+ let tagSlugs = findMatchingSlugs(allTags, link);
+ if (tagSlugs) {
+ let tagSlug = tagSlugs[0];
+ return { pageType: 'tag', tagSlug, siteURL };
+ }
+
+ // see if it's pointing to a post
+ let postSlug = _.last(_.filter(_.split(path, '/')));
+ let post = await this.dataSource.fetchOne('/wp/v2/posts/', postSlug);
+ if (post) {
+ return { pageType: 'post', postSlug, siteURL };
+ }
+
+ // go to the welcome page if we can't find a match
+ return { pageType: 'welcome', siteURL };
+ }
+
+ async getSiteURL() {
+ let site = await this.dataSource.fetchOne('/');
+ return _.trimEnd(site.url, '/');
}
async preloadPage(params) {
@@ -126,31 +162,44 @@ class Route {
}
}
-let routes = {
- 'page': {
- path: {
- from(path, params) {
- params.slugs = path.split('/').filter(Boolean);
- return true;
- },
- to(params) {
- if (params.slugs instanceof Array) {
- return `/${params.slugs.join('/')}`;
- } else {
- return `/`;
- }
- }
- },
- query: {
- search: '${search}',
- },
- load: (match) => {
- let type = match.params.pageType;
- if (type) {
- match.params.module = require(`pages/${type}-page`);
- }
+function findDate(path) {
+ if (_.startsWith(path, '/date/')) {
+ path = path.substr(5);
+ }
+ let m = /^\/(\d{4})\/(\d+)\/?/.exec(path);
+ if (m) {
+ return {
+ year: parseInt(m[1]),
+ month: parseInt(m[2]),
+ };
+ }
+}
+
+function findPostID(path) {
+ if (_.startsWith(path, '/archives/')) {
+ let id = parseInt(path.substr(10));
+ if (id === id) {
+ return id;
}
- },
+ }
+}
+
+function findMatchingSlugs(objects, link) {
+ let matches = [];
+ for (let object of objects) {
+ let objectLink = _.trimEnd(object.link, '/') + '/';
+ if (_.startsWith(objectLink, link)) {
+ matches.push(object);
+ }
+ }
+ if (matches.length > 0) {
+ let slugs = _.map(_.sortBy(matches, 'link.length'), 'slug');
+ return slugs;
+ }
+}
+
+let routes = {
+ 'page': { path: '*' },
};
export {
diff --git a/src/style.scss b/src/style.scss
index 25f17cb..4d0fb22 100644
--- a/src/style.scss
+++ b/src/style.scss
@@ -30,6 +30,7 @@ A {
background-color: #66023c;
overflow: hidden;
color: #cccccc;
+ padding: 0 1em 0 1em;
A {
opacity: 0.5;
@@ -44,6 +45,10 @@ A {
}
}
+ UL {
+ margin-left: -1em;
+ }
+
.categories {
LI {
margin-top: 0.2em;
diff --git a/src/widgets/page-list-view.jsx b/src/widgets/page-list-view.jsx
index b1b9784..2efe169 100644
--- a/src/widgets/page-list-view.jsx
+++ b/src/widgets/page-list-view.jsx
@@ -8,11 +8,9 @@ class PageListView extends PureComponent {
static displayName = 'PageListView';
render() {
- let { route, parentPages, page } = this.props;
+ let { route, page } = this.props;
let title = _.get(page, 'title.rendered', '');
- let parentSlugs = _.map(parentPages, 'slug');
- let slugs = _.concat(parentSlugs, page.slug);
- let url = route.find(slugs);
+ let url = route.getObjectURL(page);
return (
@@ -26,7 +24,6 @@ if (process.env.NODE_ENV !== 'production') {
PageListView.propTypes = {
page: PropTypes.object,
- parentPages: PropTypes.arrayOf(PropTypes.object),
route: PropTypes.instanceOf(Route).isRequired,
};
}
diff --git a/src/widgets/page-list.jsx b/src/widgets/page-list.jsx
index 160409c..f27ae6b 100644
--- a/src/widgets/page-list.jsx
+++ b/src/widgets/page-list.jsx
@@ -8,7 +8,7 @@ class PageList extends PureComponent {
static displayName = 'PageList'
render() {
- let { route, pages, parentPages } = this.props;
+ let { route, pages } = this.props;
if (!pages) {
return null;
}
@@ -18,7 +18,7 @@ class PageList extends PureComponent {
pages.map((page) => {
return (
-
+
);
})
@@ -44,7 +44,6 @@ if (process.env.NODE_ENV !== 'production') {
PageList.propTypes = {
pages: PropTypes.arrayOf(PropTypes.object),
- parentPages: PropTypes.arrayOf(PropTypes.object),
route: PropTypes.instanceOf(Route).isRequired,
};
}
diff --git a/src/widgets/post-list-view.jsx b/src/widgets/post-list-view.jsx
index 4a175a2..602c5cd 100644
--- a/src/widgets/post-list-view.jsx
+++ b/src/widgets/post-list-view.jsx
@@ -9,18 +9,11 @@ class PostListView extends PureComponent {
static displayName = 'PostListView';
render() {
- let { route, category, post, month } = this.props;
+ let { route, post } = this.props;
let title = _.get(post, 'title.rendered', '');
let excerpt = _.get(post, 'excerpt.rendered', '');
excerpt = cleanExcerpt(excerpt);
- let slugs = [ post.slug ];
- if (category) {
- slugs.unshift(category.slug);
- }
- if (month) {
- slugs.unshift(month.format('YYYY-MM'));
- }
- let url = route.find(slugs);
+ let url = route.getObjectURL(post);
return (
@@ -44,9 +37,7 @@ if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types');
PostListView.propTypes = {
- category: PropTypes.object,
post: PropTypes.object,
- month: PropTypes.instanceOf(Moment),
route: PropTypes.instanceOf(Route).isRequired,
};
}
diff --git a/src/widgets/post-list.jsx b/src/widgets/post-list.jsx
index 1937e1e..a5cddfa 100644
--- a/src/widgets/post-list.jsx
+++ b/src/widgets/post-list.jsx
@@ -9,7 +9,7 @@ class PostList extends PureComponent {
static displayName = 'PostList'
render() {
- let { route, posts, categories, month, authors } = this.props;
+ let { route, posts } = this.props;
if (!posts) {
return null;
}
@@ -17,9 +17,7 @@ class PostList extends PureComponent {
{
posts.map((post) => {
- let author = _.find(authors, { id: post.author_id });
- let category = _.find(categories, { id: post.categories[0] });
- return
+ return
})
}
@@ -62,8 +60,6 @@ if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types');
PostList.propTypes = {
- categories: PropTypes.arrayOf(PropTypes.object),
- month: PropTypes.instanceOf(Moment),
route: PropTypes.instanceOf(Route),
minimum: PropTypes.number,
maximum: PropTypes.number,
diff --git a/src/widgets/post-view.jsx b/src/widgets/post-view.jsx
index 39e0ce2..c6a4fbb 100644
--- a/src/widgets/post-view.jsx
+++ b/src/widgets/post-view.jsx
@@ -8,7 +8,7 @@ class PostView extends PureComponent {
static displayName = 'PostView';
render() {
- let { category, post, author, transform } = this.props;
+ let { post, author, transform } = this.props;
let title = _.get(post, 'title.rendered', '');
let content = _.get(post, 'content.rendered', '');
let date = _.get(post, 'date_gmt');
@@ -35,7 +35,6 @@ if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types');
PostView.propTypes = {
- category: PropTypes.object,
post: PropTypes.object,
author: PropTypes.object,
transform: PropTypes.func,
diff --git a/src/widgets/side-nav.jsx b/src/widgets/side-nav.jsx
index e00f887..00e2bb9 100644
--- a/src/widgets/side-nav.jsx
+++ b/src/widgets/side-nav.jsx
@@ -11,21 +11,13 @@ class SideNav extends AsyncComponent {
constructor(props) {
super(props);
let { route } = this.props;
- let { monthSlug } = route.params;
- let selectedYear;
- if (monthSlug) {
- selectedYear = parseInt(monthSlug.substr(0, 4));
- } else {
- selectedYear = Moment().year();
- }
- this.state = {
- selectedYear
- };
+ let { date } = route.params;
+ let selectedYear = _.get(date, 'year', Moment().year());
+ this.state = { selectedYear };
}
async renderAsync(meanwhile) {
let { wp, route } = this.props;
- let { monthSlug } = route.params;
let { selectedYear } = this.state;
let props = {
route,
@@ -68,7 +60,10 @@ class SideNav extends AsyncComponent {
let monthEntry = {
month: m + 1,
label: start.format('MMMM'),
- slug: start.format('YYYY-MM'),
+ date: {
+ year: start.year(),
+ month: start.month() + 1,
+ },
post: undefined,
start,
end,
@@ -96,15 +91,7 @@ class SideNav extends AsyncComponent {
// load the posts of each categories
props.categoryPosts = [];
for (let category of props.categories) {
- let url;
- if (monthSlug) {
- let month = Moment(monthSlug);
- let after = month.toISOString();
- let before = month.endOf('month').toISOString();
- url = `/wp/v2/posts/?after=${after}&before=${before}&categories=${category.id}`;
- } else {
- url = `/wp/v2/posts/?categories=${category.id}`;
- }
+ let url = `/wp/v2/posts/?categories=${category.id}`;
let posts = await wp.fetchList(url);
props.categoryPosts = _.clone(props.categoryPosts);
props.categoryPosts.push(posts);
@@ -125,7 +112,9 @@ class SideNavSync extends PureComponent {
render() {
return (
+
Categories
{this.renderCategories()}
+ Archives
{this.renderArchive()}
)
@@ -136,6 +125,8 @@ class SideNavSync extends PureComponent {
if (!categories) {
return null;
}
+ // only top-level categories
+ categories = _.filter(categories, { parent: 0 });
// don't show categories with no post
categories = _.filter(categories, 'count');
// list category with more posts first
@@ -153,20 +144,16 @@ class SideNavSync extends PureComponent {
renderCategory(category, i) {
let { route, categoryPosts } = this.props;
- let { monthSlug, categorySlug } = route.params;
+ let { categorySlugs } = route.params;
let name = _.get(category, 'name', '');
let description = _.get(category, 'description', '');
- let slugs = [ category.slug ];
- if (monthSlug) {
- slugs.unshift(monthSlug);
- }
- let url = route.find(slugs);
+ let url = route.getObjectURL(category);
let posts = (categoryPosts) ? categoryPosts[i] : undefined;
if (_.isEmpty(posts) && !_.isUndefined(posts)) {
url = undefined;
}
let className;
- if (categorySlug === category.slug) {
+ if (category.slug === _.last(categorySlugs)) {
className = 'selected';
}
return (
@@ -216,13 +203,13 @@ class SideNavSync extends PureComponent {
renderMonth(monthEntry, i) {
let { route } = this.props;
- let { monthSlug } = route.params;
- let url = route.find([ monthEntry.slug ]);
+ let { date } = route.params;
+ let url = route.getArchiveURL(monthEntry.date);
if (_.isEmpty(monthEntry.posts) && !_.isUndefined(monthEntry.posts)) {
url = undefined;
}
let className;
- if (monthSlug === monthEntry.slug) {
+ if (_.isEqual(monthEntry.date, date)) {
className = 'selected';
}
return (
diff --git a/src/widgets/top-nav.jsx b/src/widgets/top-nav.jsx
index a6141ce..8ff923e 100644
--- a/src/widgets/top-nav.jsx
+++ b/src/widgets/top-nav.jsx
@@ -46,7 +46,7 @@ class TopNavSync extends PureComponent {
let { route, system } = this.props;
let name = _.get(system, 'name', '');
let description = _.get(system, 'description', '');
- let url = route.find({});
+ let url = route.getRootURL();
return (
@@ -76,8 +76,7 @@ class TopNavSync extends PureComponent {
renderPageLinkButton(page, i) {
let { route } = this.props;
let title = _.get(page, 'title.rendered');
- let slug = _.get(page, 'slug');
- let url = route.find([ slug ]);
+ let url = route.getObjectURL(page);
return (
{title}
@@ -101,7 +100,7 @@ class TopNavSync extends PureComponent {
performSearch = (evt) => {
let { search } = this.state;
let { route } = this.props;
- let url = route.find({ search });
+ let url = route.getSearchURL(search);
let options = {
replace: (route.params.pageType === 'search')
};