1
0
mirror of https://github.com/trambarhq/relaks-wordpress-example.git synced 2025-09-24 22:41:31 +02:00

Fixed routing.

Loading data for page.
Added rudimentary slug handling to data source.
This commit is contained in:
Chung Leong
2018-12-23 01:58:36 +01:00
parent 47a8742623
commit 861a89bc8e
14 changed files with 191 additions and 35 deletions

View File

@@ -2,10 +2,10 @@ version: "2"
services:
db:
image: mysql:5.7
ports:
- 3306:3306
volumes:
- db_data:/var/lib/mysql
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
@@ -16,8 +16,6 @@ services:
depends_on:
- db
image: wordpress:latest
ports:
- 8888:80
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
@@ -25,8 +23,6 @@ services:
restart: always
node:
image: node:8
ports:
- 8080:80
volumes:
- ..:/opt/example
- ./cache:/var/cache/nginx
@@ -45,7 +41,7 @@ services:
- ./nginx:/etc/nginx/conf.d
- ./cache:/var/cache/nginx
ports:
- "8000:80"
- 8000:80
restart: always
volumes:
db_data:

View File

@@ -7,7 +7,7 @@ import RouteManager from 'relaks-route-manager';
import { harvest } from 'relaks-harvest';
import Relaks from 'relaks';
const pageBasePath = '/';
const pageBasePath = '';
if (typeof(window) === 'object') {
async function initialize(evt) {

View File

@@ -0,0 +1,15 @@
import React, { PureComponent } from 'react';
import { AsyncComponent } from 'relaks';
class ArchivePage extends AsyncComponent {
static displayName = 'ArchivePage';
async renderAsync(meanwhile) {
return <div>Archive</div>;
}
}
export {
ArchivePage as default,
ArchivePage,
};

View File

View File

@@ -1,8 +1,8 @@
import React, { PureComponent } from 'react';
import { AsyncComponent } from 'relaks';
class CategoryStoryPage extends AsyncComponent {
static displayName = 'CategoryStoryPage';
class CategoryPostPage extends AsyncComponent {
static displayName = 'CategoryPostPage';
async renderAsync(meanwhile) {
return <div>Category > Story</div>;
@@ -10,6 +10,6 @@ class CategoryStoryPage extends AsyncComponent {
}
export {
CategoryStoryPage as default,
CategoryStoryPage,
CategoryPostPage as default,
CategoryPostPage,
};

57
src/pages/page-page.jsx Normal file
View File

@@ -0,0 +1,57 @@
import _ from 'lodash';
import React, { PureComponent } from 'react';
import { AsyncComponent } from 'relaks';
import { Route } from 'routing';
import WordPress from 'wordpress';
import HTML from 'widgets/html';
class PagePage extends AsyncComponent {
static displayName = 'PagePage';
async renderAsync(meanwhile) {
let { wp, route } = this.props;
let props = {
route,
};
let slug = route.params.page;
let url = '/wp/v2/pages/';
props.page = await wp.fetchOne({ url, slug });
return <PagePageSync {...props} />;
}
}
class PagePageSync extends PureComponent {
render() {
let { page } = this.props;
let title = _.get(page, 'title.rendered', '');
let content = _.get(page, 'content.rendered', '');
console.log(page);
return (
<div className="page">
<h1><HTML text={title} /></h1>
<HTML text={content} />
</div>
);
}
}
if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types');
PagePage.propTypes = {
wp: PropTypes.instanceOf(WordPress).isRequired,
route: PropTypes.instanceOf(Route).isRequired,
};
PagePageSync.propTypes = {
page: PropTypes.object,
route: PropTypes.instanceOf(Route).isRequired,
};
}
export {
PagePage as default,
PagePage,
PagePageSync,
};

View File

View File

@@ -27,24 +27,52 @@ class Route {
}
let routes = {
'welcome-page': {
'welcome': {
path: '/',
load: async (match) => {
match.params.module = await import('pages/welcome-page' /* webpackChunkName: "welcome" */);
}
},
'category-page': {
path: '/${category}/',
'welcome-post': {
path: '/posts/${post}',
params: { post: String },
load: async (match) => {
match.params.module = await import('pages/welcome-post-page' /* webpackChunkName: "welcome-post" */);
}
},
'page': {
path: '/pages/${page}',
params: { page: String },
load: async (match) => {
match.params.module = await import('pages/page-page' /* webpackChunkName: "page" */);
}
},
'category': {
path: '/categories/${category}',
params: { category: String },
load: async (match) => {
match.params.module = await import('pages/category-page' /* webpackChunkName: "category" */);
}
},
'story-page': {
path: '/${category}/${slug}/',
params: { category: String, slug: String },
'category-post': {
path: '/categories/${category}/${post}',
params: { category: String, post: String },
load: async (match) => {
match.params.module = await import('pages/category-story-page' /* webpackChunkName: "category-story" */);
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" */);
}
},
};

View File

@@ -168,11 +168,12 @@ A {
}
.page-container {
padding-top: 11em;
padding-top: 11.5em;
padding-bottom: 1em;
padding-left: 1em;
padding-right: 1em;
margin-left: 18em;
min-height: 100vh;
background-color: #ffffff;
.page {

36
src/widgets/html.jsx Normal file
View File

@@ -0,0 +1,36 @@
import React from 'react';
function HTML(props) {
let text = props.text;
if (!text) {
return null;
}
if (isHTML(text)) {
let markup = { __html: text };
return <span dangerouslySetInnerHTML={markup} />
} else {
return text;
}
}
function isHTML(text) {
if (text.indexOf('<') !== -1) {
return true;
}
if (text.indexOf('&') !== -1) {
return true;
}
return false;
}
if (process.env.NODE_ENV !== 'production') {
const PropTypes = require('prop-types');
HTML.propTypes = {
text: PropTypes.string,
};
}
export {
HTML as default,
HTML,
};

View File

@@ -134,10 +134,11 @@ class SideNavSync extends PureComponent {
}
renderCategory(category, i) {
let { route } = this.props;
let name = _.get(category, 'name', '');
let description = _.get(category, 'description', '');
let slug = _.get(category, 'slug', '');
let url = '';
let url = route.find('category', { category: slug });
return (
<li key={i}>
<a href={url} title={description}>{name}</a>
@@ -187,9 +188,10 @@ class SideNavSync extends PureComponent {
}
renderMonth(monthEntry, i) {
let { route } = this.props;
let url;
if (!_.isEmpty(monthEntry.posts) || _.isUndefined(monthEntry.posts)) {
url = '#';
url = route.find('archive', { month: monthEntry.slug });
}
return (
<li key={i}>

View File

@@ -66,7 +66,7 @@ class TopNavSync extends PureComponent {
let { route } = this.props;
let title = _.get(page, 'title.rendered');
let slug = _.get(page, 'slug');
let url = '';
let url = route.find('page', { page: slug });
return (
<div className="button" key={i}>
<a href={url}>{title}</a>
@@ -80,7 +80,7 @@ class TopNavSync extends PureComponent {
return (
<div className="search-bar">
<span className="input-container">
<input type="text" value={search} />
<input type="text" value={search} readOnly />
<i className="fa fa-search" />
</span>
</div>

View File

@@ -120,12 +120,26 @@ prototype.notifyChanges = function(changed) {
/**
* Fetch one object at the URL.
*
* @param {String} url
* @param {String|Object} url
* @param {Object|undefined} options
*
* @return {Promise<Object>}
*/
prototype.fetchOne = function(url, options) {
if (url instanceof Object) {
var pageURL = attachSlug(url.url, url.slug);
var pageOptions = {
afterDelete: 'remove',
afterInsert: 'ignore',
afterUpdate: 'replace',
};
for (var key in options) {
pageOptions[key] = options[key];
}
return this.fetchPage(pageURL, 1, pageOptions).then(function(objects) {
return objects[0] || null;
});
}
var _this = this;
var absURL = this.resolveURL(url);
var props = {
@@ -2138,6 +2152,21 @@ function attachPageNumber(url, page) {
return url + sep + 'page=' + page;
}
function attachSlug(url, slug) {
var qi = url.indexOf('?');
var sep = (qi === -1) ? '?' : '&';
return url + sep + 'slug=' + encodeURI(slug);
}
function attachSlugs(url, slugs) {
var qi = url.indexOf('?');
var sep = (qi === -1) ? '?' : '&';
var pairs = slugs.map(function(slug) {
return 'slug[]=' + encodeURI(slug);
});
return url + sep + pairs.join('&');
}
function omitSearchString(url) {
var qi = url.lastIndexOf('?');
if (qi !== -1) {

View File

@@ -16,6 +16,7 @@ var clientConfig = {
entry: './main',
output: {
path: Path.resolve('./server/www'),
publicPath: '/',
filename: 'app.js',
},
resolve: {
@@ -106,16 +107,7 @@ if (isDevServer) {
// config dev-server to support client-side routing
clientConfig.devServer = {
inline: true,
historyApiFallback: {
rewrites: [
{
from: /.*/,
to: function(context) {
return context.parsedUrl.pathname.replace(/.*\/(.*)$/, '/$1');
}
}
]
}
historyApiFallback: true,
};
}