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

Changed to slug-based routing.

This commit is contained in:
Chung Leong
2018-12-23 21:32:28 +01:00
parent acd296c9f0
commit 1beee9bdc1
9 changed files with 93 additions and 77 deletions

View File

@@ -1,7 +1,7 @@
import { createElement } from 'react'; import { createElement } from 'react';
import { hydrate, render } from 'react-dom'; import { hydrate, render } from 'react-dom';
import { FrontEnd } from 'front-end'; import { FrontEnd } from 'front-end';
import { routes } from 'routing'; import { routes, setPageType } from 'routing';
import WordpressDataSource from 'wordpress-data-source'; import WordpressDataSource from 'wordpress-data-source';
import RouteManager from 'relaks-route-manager'; import RouteManager from 'relaks-route-manager';
import { harvest } from 'relaks-harvest'; import { harvest } from 'relaks-harvest';
@@ -28,6 +28,9 @@ if (typeof(window) === 'object') {
basePath: pageBasePath, basePath: pageBasePath,
preloadingDelay: 2000, preloadingDelay: 2000,
}); });
routeManager.addEventListener('beforechange', (evt) => {
evt.postponeDefault(setPageType(dataSource, evt.params));
});
routeManager.activate(); routeManager.activate();
await routeManager.start(); await routeManager.start();

View File

@@ -9,7 +9,8 @@ class ArchivePage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let month = Moment(route.params.month); let slug = route.params.slugs[0];
let month = Moment(slug);
let props = { let props = {
route, route,
month, month,

View File

@@ -8,7 +8,7 @@ class CategoryPage extends AsyncComponent {
async renderAsync(meanwhile) { async renderAsync(meanwhile) {
let { wp, route } = this.props; let { wp, route } = this.props;
let slug = route.params.category; let slug = route.params.slugs[0];
let props = { let props = {
route, route,
}; };
@@ -32,7 +32,7 @@ class CategoryPageSync extends PureComponent {
<span>Categories > </span> <span>Categories > </span>
<span>{title}</span> <span>{title}</span>
</h4> </h4>
<PostList route={route} posts={posts} /> <PostList route={route} category={category} posts={posts} />
</div> </div>
); );
} }

View File

@@ -14,9 +14,8 @@ class PagePage extends AsyncComponent {
let props = { let props = {
route, route,
}; };
let slug = route.params.page; let slugs = route.params.slugs;
let url = '/wp/v2/pages/'; props.pages = await wp.fetchMultiple({ url: '/wp/v2/pages/', slugs });
props.page = await wp.fetchOne({ url, slug });
return <PagePageSync {...props} />; return <PagePageSync {...props} />;
} }
} }
@@ -24,10 +23,10 @@ class PagePage extends AsyncComponent {
class PagePageSync extends PureComponent { class PagePageSync extends PureComponent {
render() { render() {
let { page } = this.props; let { pages } = this.props;
let activePage = _.last(pages);
let title = _.get(page, 'title.rendered', ''); let title = _.get(page, 'title.rendered', '');
let content = _.get(page, 'content.rendered', ''); let content = _.get(page, 'content.rendered', '');
console.log(page);
return ( return (
<div className="page"> <div className="page">
<h1><HTML text={title} /></h1> <h1><HTML text={title} /></h1>

View File

@@ -1,3 +1,5 @@
let _ = require('lodash');
class Route { class Route {
constructor(routeManager) { constructor(routeManager) {
this.routeManager = routeManager; this.routeManager = routeManager;
@@ -10,71 +12,72 @@ class Route {
return this.routeManager.change(url, options); return this.routeManager.change(url, options);
} }
find(name, params) { find(slugs) {
return this.routeManager.find(name, params); return this.routeManager.find('page', { slugs });
}
extractID(url) {
var si = url.lastIndexOf('/');
var ei;
if (si === url.length - 1) {
ei = si;
si = url.lastIndexOf('/', ei - 1);
}
var text = url.substring(si + 1, ei);
return parseInt(text);
} }
} }
let routes = { let routes = {
'welcome': {
path: '/',
load: async (match) => {
match.params.module = await import('pages/welcome-page' /* webpackChunkName: "welcome" */);
}
},
'welcome-post': {
path: '/posts/${post}',
params: { post: String },
load: async (match) => {
match.params.module = await import('pages/welcome-post-page' /* webpackChunkName: "welcome-post" */);
}
},
'page': { 'page': {
path: '/pages/${page}', path: {
params: { page: String }, from(path, params) {
load: async (match) => { params.slugs = path.split('/').filter(Boolean);
match.params.module = await import('pages/page-page' /* webpackChunkName: "page" */); return true;
},
to(params) {
if (params.slugs instanceof Array) {
return `/${params.slugs.join('/')}`;
} else {
return `/`;
}
} }
}, },
'category': { load: (match) => {
path: '/categories/${category}', let type = match.params.pageType;
params: { category: String }, if (type) {
load: async (match) => { match.params.module = require(`pages/${type}-page`);
match.params.module = await import('pages/category-page' /* webpackChunkName: "category" */);
} }
},
'category-post': {
path: '/categories/${category}/${post}',
params: { category: String, post: String },
load: async (match) => {
match.params.module = await import('pages/category-post-page' /* webpackChunkName: "category-post" */);
}
},
'archive': {
path: '/archive/${month}',
params: { month: String },
load: async (match) => {
match.params.module = await import('pages/archive-page' /* webpackChunkName: "archive" */);
}
},
'archive-post': {
path: '/archive/${month}/${post}',
params: { month: String, post: String },
load: async (match) => {
match.params.module = await import('pages/archive-page' /* webpackChunkName: "archive-post" */);
} }
}, },
}; };
export { Route, routes }; async function setPageType(dataSource, params) {
let type;
let slugs = params.slugs;
if (slugs.length > 0) {
let rootSlugType = await getSlugType(dataSource, slugs[0]);
if (rootSlugType === 'page') {
type = 'page';
} else if (rootSlugType === 'category') {
if (slugs.length === 1) {
type = 'category';
} else if (slugs.length === 2) {
type = 'category-post';
}
} else if (rootSlugType === 'archive') {
if (slugs.length === 1 || slugs.length === 2) {
type = 'archive';
} else if (slugs.length === 3) {
type = 'archive-post';
}
}
}
params.pageType = type || 'welcome';
}
async function getSlugType(dataSource, slug) {
let options = {}; // { minimum: '100%' };
let pages = await dataSource.fetchList('/wp/v2/pages/?parent=0', options);
if (_.some(pages, { slug })) {
return 'page';
}
let categories = await dataSource.fetchList('/wp/v2/categories/', options);
if (_.some(categories, { slug })) {
return 'category';
}
if (/^\d{4}\-\d{2}$/.test(slug)) {
return 'archive';
}
}
export { Route, routes, setPageType };

View File

@@ -7,13 +7,23 @@ class PostListView extends PureComponent {
static displayName = 'PostListView'; static displayName = 'PostListView';
render() { render() {
let { post, author } = this.props; let { route, category, post, author, month } = this.props;
let title = _.get(post, 'title.rendered', ''); let title = _.get(post, 'title.rendered', '');
let excerpt = _.get(post, 'excerpt.rendered', ''); let excerpt = _.get(post, 'excerpt.rendered', '');
excerpt = cleanExcerpt(excerpt); 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);
return ( return (
<div className="post-list-view"> <div className="post-list-view">
<h2><HTML text={title} /></h2> <h2>
<a href={url}><HTML text={title} /></a>
</h2>
<p><HTML text={excerpt} /></p> <p><HTML text={excerpt} /></p>
</div> </div>
); );

View File

@@ -7,16 +7,16 @@ class PostList extends PureComponent {
static displayName = 'PostList' static displayName = 'PostList'
render() { render() {
let { posts, authors } = this.props; let { route, posts, category, month, authors } = this.props;
if (!posts) { if (!posts) {
return null; return null;
} }
return ( return (
<div className="posts"> <div className="posts">
{ {
posts.map((post) => { posts.map((post, i) => {
let author = _.find(authors, { id: post.author_id }); let author = _.find(authors, { id: post.author_id });
return <PostListView post={post} author={author} /> return <PostListView route={route} category={category} post={post} author={author} key={i} />
}) })
} }
</div> </div>

View File

@@ -137,7 +137,7 @@ class SideNavSync extends PureComponent {
let name = _.get(category, 'name', ''); let name = _.get(category, 'name', '');
let description = _.get(category, 'description', ''); let description = _.get(category, 'description', '');
let slug = _.get(category, 'slug', ''); let slug = _.get(category, 'slug', '');
let url = route.find('category', { category: slug }); let url = route.find([ slug ]);
return ( return (
<li key={i}> <li key={i}>
<a href={url} title={description}>{name}</a> <a href={url} title={description}>{name}</a>
@@ -190,7 +190,7 @@ class SideNavSync extends PureComponent {
let { route } = this.props; let { route } = this.props;
let url; let url;
if (!_.isEmpty(monthEntry.posts) || _.isUndefined(monthEntry.posts)) { if (!_.isEmpty(monthEntry.posts) || _.isUndefined(monthEntry.posts)) {
url = route.find('archive', { month: monthEntry.slug }); url = route.find([ monthEntry.slug ]);
} }
return ( return (
<li key={i}> <li key={i}>

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/'); props.pages = await wp.fetchList('/wp/v2/pages/?parent=0');
return <TopNavSync {...props} />; return <TopNavSync {...props} />;
} }
} }
@@ -66,7 +66,7 @@ class TopNavSync extends PureComponent {
let { route } = this.props; let { route } = this.props;
let title = _.get(page, 'title.rendered'); let title = _.get(page, 'title.rendered');
let slug = _.get(page, 'slug'); let slug = _.get(page, 'slug');
let url = route.find('page', { page: slug }); let url = route.find([ slug ]);
return ( return (
<div className="button" key={i}> <div className="button" key={i}>
<a href={url}>{title}</a> <a href={url}>{title}</a>