Re-jigger articles
There's now a base Article class, and then FullArticle and Articles classes which are what react-router routes to
This commit is contained in:
parent
348703077b
commit
4d9923854d
2 changed files with 97 additions and 36 deletions
|
|
@ -11,7 +11,7 @@ import 'highlight.js/styles/github-gist.css';
|
||||||
|
|
||||||
import { Container, Row, Column } from './skeleton';
|
import { Container, Row, Column } from './skeleton';
|
||||||
|
|
||||||
import { Articles, RoutedArticle } from './Article';
|
import { Articles, FullArticle } from './Article';
|
||||||
import { Footer } from './Footer';
|
import { Footer } from './Footer';
|
||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
import { NavList, TagNav, HistoryNav } from './Nav';
|
import { NavList, TagNav, HistoryNav } from './Nav';
|
||||||
|
|
@ -38,10 +38,10 @@ class App extends Component {
|
||||||
|
|
||||||
{ /* Article routes */ }
|
{ /* Article routes */ }
|
||||||
<Route path="/page/:page" component={Articles} />
|
<Route path="/page/:page" component={Articles} />
|
||||||
<Route path="/:year/:month/:title" component={RoutedArticle} />
|
<Route path="/:year/:month/:slug" component={FullArticle} />
|
||||||
|
|
||||||
{ /* 404 fallback */ }
|
{ /* 404 fallback */ }
|
||||||
<Route component={FourOhFour} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</Column>
|
</Column>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
@ -82,7 +82,7 @@ class About extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FourOhFour extends Component {
|
class NotFound extends Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<article>
|
<article>
|
||||||
|
|
|
||||||
103
src/Article.js
103
src/Article.js
|
|
@ -1,30 +1,52 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import Icon from 'react-fontawesome';
|
import Icon from 'react-fontawesome';
|
||||||
import Markdown from 'react-markdown';
|
import Markdown from 'react-markdown';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import slugify from 'slugify';
|
||||||
|
|
||||||
import { ListLink } from './Nav';
|
import { ListLink } from './Nav';
|
||||||
|
|
||||||
|
|
||||||
class Article extends Component {
|
class Article extends Component {
|
||||||
render() {
|
render() {
|
||||||
let postLink = "";
|
let body = "";
|
||||||
|
let readMore = "";
|
||||||
|
if (this.props.blurb) {
|
||||||
|
body = this.props.article.blurb;
|
||||||
|
readMore = (<Link to={ this.postLink() }>read more</Link>);
|
||||||
|
} else {
|
||||||
|
body = this.props.article.body;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article>
|
<article>
|
||||||
<header>
|
<header>
|
||||||
<a className="post-title" href={ postLink }>
|
<Link className="post-title" to={ this.postLink() }>
|
||||||
<h1>{ this.props.title }</h1>
|
<h1>{ this.props.article.title }</h1>
|
||||||
</a>
|
</Link>
|
||||||
{ this.meta() }
|
{ this.meta() }
|
||||||
</header>
|
</header>
|
||||||
<section>
|
<section>
|
||||||
<Markdown source={ this.content() } />
|
<Markdown source={ body } />
|
||||||
<a href={ postLink }>omg read more</a>
|
{ readMore }
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
postLink() {
|
||||||
|
let date = new Date(this.props.article.date);
|
||||||
|
let year = date.getUTCFullYear();
|
||||||
|
let month = date.getUTCMonth() + 1;
|
||||||
|
|
||||||
|
let slug = this.props.article.slug;
|
||||||
|
if (!slug) {
|
||||||
|
slug = slugify(this.props.article.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `/${year}/${month}/${slug}`;
|
||||||
|
}
|
||||||
|
|
||||||
meta() {
|
meta() {
|
||||||
// TODO: Fill this in with real metadata.
|
// TODO: Fill this in with real metadata.
|
||||||
// Also should this be hidden for pages? That will require some CSS tweaks
|
// Also should this be hidden for pages? That will require some CSS tweaks
|
||||||
|
|
@ -35,7 +57,7 @@ class Article extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="post-meta">
|
<div className="post-meta">
|
||||||
<time>{ time_text } { this.props.date }</time>
|
<time>{ time_text } { this.props.article.date }</time>
|
||||||
<div className="post-tags"> <Icon name="tags" />
|
<div className="post-tags"> <Icon name="tags" />
|
||||||
<ul>
|
<ul>
|
||||||
<ListLink name="tag1" href="" />
|
<ListLink name="tag1" href="" />
|
||||||
|
|
@ -63,29 +85,67 @@ class Article extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Goofball article for routing testing
|
|
||||||
class RoutedArticle extends Component {
|
class FullArticle extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.props = props;
|
this.props = props;
|
||||||
this.params = props.match.params;
|
this.params = props.match.params;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
body: '',
|
article: null
|
||||||
title: 'default title',
|
|
||||||
date: 'default date',
|
|
||||||
tags: [],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fetchArticle() {
|
||||||
|
fetch('/site.json')
|
||||||
|
.then((resp) => resp.json())
|
||||||
|
.then((blob) => {
|
||||||
|
let found = false;
|
||||||
|
for (let post of blob.posts) {
|
||||||
|
let slug = post.slug;
|
||||||
|
if (!slug) {
|
||||||
|
slug = slugify(post.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('title compare:', slug, this.params.slug);
|
||||||
|
if (slug === this.params.slug) {
|
||||||
|
this.setState({article: post})
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
console.log('article not found');
|
||||||
|
/* TODO: return 404 */
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.fetchArticle();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(props) {
|
||||||
|
this.params = props.match.params;
|
||||||
|
this.fetchArticle();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (this.state.article) {
|
||||||
return (
|
return (
|
||||||
<Article title={this.state.title} date={this.state.date} />
|
<Article
|
||||||
|
article={this.state.article}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<p>Loading...</p>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Articles extends Component {
|
class Articles extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
@ -115,9 +175,6 @@ class Articles extends Component {
|
||||||
let posts = blob.posts.slice(offset, offset + this.per_page);
|
let posts = blob.posts.slice(offset, offset + this.per_page);
|
||||||
|
|
||||||
this.setState({articles: posts});
|
this.setState({articles: posts});
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
console.log("Oh no! " + error);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,18 +188,22 @@ class Articles extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
if (this.state.articles.length > 0) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.state.articles.map(article =>
|
{this.state.articles.map(article =>
|
||||||
<Article
|
<Article
|
||||||
key={article.title}
|
key={article.title}
|
||||||
title={article.title}
|
article={article}
|
||||||
date="1970-01-01"
|
blurb
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return <p>Loading...</p>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Article, Articles, RoutedArticle };
|
export { Article, FullArticle, Articles };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue