mirror of
https://github.com/mgerb/mywebsite
synced 2026-01-11 02:12:53 +00:00
too many changes - load posts now
This commit is contained in:
1
client/assets/css/dracula.css
Normal file
1
client/assets/css/dracula.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.hljs{display:block;overflow-x:auto;padding:0.5em;background:#282a36}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-section,.hljs-link{color:#8be9fd}.hljs-function .hljs-keyword{color:#ff79c6}.hljs,.hljs-subst{color:#f8f8f2}.hljs-string,.hljs-title,.hljs-name,.hljs-type,.hljs-attribute,.hljs-symbol,.hljs-bullet,.hljs-addition,.hljs-variable,.hljs-template-tag,.hljs-template-variable{color:#f1fa8c}.hljs-comment,.hljs-quote,.hljs-deletion,.hljs-meta{color:#6272a4}.hljs-keyword,.hljs-selector-tag,.hljs-literal,.hljs-title,.hljs-section,.hljs-doctag,.hljs-type,.hljs-name,.hljs-strong{font-weight:bold}.hljs-emphasis{font-style:italic}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
.Footer{
|
.Footer {
|
||||||
height: 5em;
|
height: 5em;
|
||||||
line-height: 5em;
|
line-height: 5em;
|
||||||
background-color: #F1F1F1;
|
background-color: #F1F1F1;
|
||||||
border-top: solid;
|
border-top: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: #DADADA;
|
border-color: #DADADA;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
.Preview{
|
.Preview {
|
||||||
flex: 1;
|
.post + .post {
|
||||||
-webkit-flex: 1;
|
margin-top: 2em;
|
||||||
|
}
|
||||||
.post + .post{
|
.date {
|
||||||
margin-top: 2em;
|
margin: 0;
|
||||||
}
|
opacity: 0.7;
|
||||||
|
font-weight: 300;
|
||||||
.date{
|
}
|
||||||
margin: 0;
|
.intro {
|
||||||
opacity: 0.7;
|
margin-bottom: 0.5em;
|
||||||
font-weight: 300;
|
}
|
||||||
}
|
p {
|
||||||
|
font-weight: 300;
|
||||||
.intro{
|
}
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p{
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +1,64 @@
|
|||||||
$transitionDuration: .4s;
|
$transitionDuration: 0.4s;
|
||||||
|
.Sidebar {
|
||||||
.Sidebar{
|
background: #fff;
|
||||||
background: #fff;
|
width: 300px;
|
||||||
width: 300px;
|
padding-right: 1em;
|
||||||
padding-right: 1em;
|
padding-left: 1em;
|
||||||
padding-left: 1em;
|
img {
|
||||||
|
width: 100%;
|
||||||
img{
|
height: auto;
|
||||||
width: 100%;
|
border-radius: 0.5em;
|
||||||
height: auto;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2{
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.toggler{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
min-height: 100%;
|
|
||||||
padding-top: 1em;
|
|
||||||
|
|
||||||
transform: translateX(300px);
|
|
||||||
-webkit-transform: translateX(300px);
|
|
||||||
transition: transform $transitionDuration ease-out;
|
|
||||||
-webkit-transition: transform $transitionDuration ease-out;
|
|
||||||
|
|
||||||
&.open {
|
|
||||||
transform: translateX(0px);
|
|
||||||
-webkit-transform: translateX(0px);
|
|
||||||
border-left: 1px solid #EAEAEA;
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
content: " ";
|
|
||||||
display: block;
|
|
||||||
background: rgba(0,0,0,0.4);
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
width: 100vw;
|
|
||||||
top: 0;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.toggler{
|
|
||||||
transform: rotate(450deg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
h2 {
|
||||||
a.toggler{
|
text-align: center;
|
||||||
display: block;
|
margin-bottom: 0.5em;
|
||||||
width: 2em;
|
}
|
||||||
height: 2em;
|
a.toggler {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -3em;
|
top: 0;
|
||||||
top: .5em;
|
right: 0;
|
||||||
cursor: pointer;
|
min-height: 100%;
|
||||||
color: white;
|
padding-top: 1em;
|
||||||
transform: rotate(0deg);
|
transform: translateX(300px);
|
||||||
|
-webkit-transform: translateX(300px);
|
||||||
transition: transform $transitionDuration ease-out;
|
transition: transform $transitionDuration ease-out;
|
||||||
-webkit-transition: transform $transitionDuration ease-out;
|
-webkit-transition: transform $transitionDuration ease-out;
|
||||||
|
&.open {
|
||||||
&:hover{
|
transform: translateX(0px);
|
||||||
color: #3598db;
|
-webkit-transform: translateX(0px);
|
||||||
|
border-left: 1px solid #EAEAEA;
|
||||||
|
&:before {
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100vw;
|
||||||
|
top: 0;
|
||||||
|
right: 100%;
|
||||||
|
}
|
||||||
|
a.toggler {
|
||||||
|
transform: rotate(450deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.toggler {
|
||||||
|
display: block;
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
position: absolute;
|
||||||
|
left: -3em;
|
||||||
|
top: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform $transitionDuration ease-out;
|
||||||
|
-webkit-transition: transform $transitionDuration ease-out;
|
||||||
|
&:hover {
|
||||||
|
color: #3598db;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,69 +1,82 @@
|
|||||||
@import './utils.scss';
|
@import './utils.scss';
|
||||||
|
html {
|
||||||
html{
|
|
||||||
font-family: 'Roboto Slab', serif;
|
font-family: 'Roboto Slab', serif;
|
||||||
}
|
}
|
||||||
|
body {
|
||||||
body{
|
max-width: 100%;
|
||||||
position: relative;
|
overflow-x: hidden;
|
||||||
-webkit-font-smoothing: subpixel-antialiased;
|
position: relative;
|
||||||
|
-webkit-font-smoothing: subpixel-antialiased;
|
||||||
}
|
}
|
||||||
|
h1,
|
||||||
h1, h2, h3, h4, h5, h6{
|
h2,
|
||||||
margin: 0;
|
h3,
|
||||||
font-weight: 500;
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
p {
|
||||||
p{
|
font-weight: 300;
|
||||||
font-weight: 300;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*:before,
|
*:after,
|
||||||
*:after {
|
*:before {
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
a {
|
||||||
a{
|
background-color: transparent;
|
||||||
background-color: transparent;
|
color: #3598db;
|
||||||
color: #3598db;
|
text-decoration: none;
|
||||||
text-decoration: none;
|
&:hover {
|
||||||
|
color: #3598db;
|
||||||
&:hover{
|
}
|
||||||
color: #3598db;
|
}
|
||||||
}
|
code,
|
||||||
|
pre code{
|
||||||
|
white-space: pre-wrap;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Layout {
|
.Layout {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
.Footer,
|
||||||
.Header, .Main, .Footer {
|
.Header,
|
||||||
display: flex;
|
.Main {
|
||||||
padding-right: calc(50% - 997px / 2);
|
display: flex;
|
||||||
padding-left: calc(50% - 997px / 2);
|
padding-right: calc(50% - 997px / 2);
|
||||||
&:before, &:after { content: " "; width: 1em; }
|
padding-left: calc(50% - 997px / 2);
|
||||||
}
|
&:after,
|
||||||
|
&:before {
|
||||||
|
content: " ";
|
||||||
|
width: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.Main {
|
||||||
.Main{
|
padding-top: 1em;
|
||||||
padding-top: 1em;
|
|
||||||
flex: 1;
|
|
||||||
}
|
}
|
||||||
|
.Content {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
.Header{
|
img{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: url("../images/header.jpg");
|
height: auto;
|
||||||
background-size: cover;
|
}
|
||||||
height: 30em;
|
}
|
||||||
border-bottom: solid;
|
.Header {
|
||||||
border-width: 1px;
|
width: 100%;
|
||||||
border-color: #DADADA;
|
background: url("../images/header.jpg");
|
||||||
|
background-size: cover;
|
||||||
h1{
|
height: 30em;
|
||||||
text-align: center;
|
border-bottom: solid;
|
||||||
}
|
border-width: 1px;
|
||||||
|
border-color: #DADADA;
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/* Effect 1: Brackets */
|
/* Effect 1: Brackets */
|
||||||
.link{
|
.link {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
&:before {
|
||||||
&:before{
|
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -16,10 +15,9 @@
|
|||||||
-webkit-transition: all 0.2s ease-in-out 0s;
|
-webkit-transition: all 0.2s ease-in-out 0s;
|
||||||
transition: all 0.2s ease-in-out 0s;
|
transition: all 0.2s ease-in-out 0s;
|
||||||
}
|
}
|
||||||
|
&:hover:before {
|
||||||
&:hover:before{
|
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
-webkit-transform: scaleX(1);
|
-webkit-transform: scaleX(1);
|
||||||
transform: scaleX(1);
|
transform: scaleX(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import Index from './pages/Index';
|
|||||||
class Main extends React.Component{
|
class Main extends React.Component{
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<div>{React.cloneElement(this.props.children, this.props)}</div>
|
<div>{React.cloneElement(this.props.children, this.props)}</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,8 @@ ReactDOM.render((
|
|||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Route path="/" component={App}>
|
<Route path="/" component={App}>
|
||||||
<IndexRoute component={Index}/>
|
<IndexRoute component={Index}/>
|
||||||
<Route path="/:page" component={Index}/>
|
<Route path="/:page(/:category)(/:post)" component={Index}/>
|
||||||
</Route>
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
</Provider>
|
||||||
),document.getElementById('app'));
|
),document.getElementById('app'));
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import '../../assets/scss/Footer.scss';
|
|||||||
|
|
||||||
export default class Footer extends React.Component{
|
export default class Footer extends React.Component{
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<div class="Footer">Site created and maintained by Mitchell Gerber</div>
|
<div class="Footer">
|
||||||
);
|
Site created and maintained by Mitchell Gerber
|
||||||
}
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export default class Header extends React.Component{
|
export default class Header extends React.Component{
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<header class="Header" />
|
<header class="Header" />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import marked from 'marked';
|
||||||
|
import highlight from 'highlight.js';
|
||||||
|
|
||||||
|
marked.setOptions({
|
||||||
|
header: true,
|
||||||
|
highlight: (code) => {
|
||||||
|
return highlight.highlightAuto(code).value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default class Post extends React.Component{
|
export default class Post extends React.Component{
|
||||||
|
|
||||||
|
render(){
|
||||||
render(){
|
return(
|
||||||
return(
|
<div class="Preview" dangerouslySetInnerHTML={{__html : marked(this.props.content)}}>
|
||||||
<div></div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,39 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Link from 'react-router';
|
import {Link} from 'react-router';
|
||||||
|
|
||||||
import '../../assets/scss/Preview.scss';
|
import '../../assets/scss/Preview.scss';
|
||||||
|
|
||||||
export default class Preview extends React.Component{
|
export default class Preview extends React.Component{
|
||||||
|
|
||||||
insertPosts(posts){
|
insertPosts(posts){
|
||||||
let elements = [];
|
let elements = [];
|
||||||
for (let i in posts){
|
for (let i in posts){
|
||||||
elements.push(
|
elements.push(
|
||||||
<div class="post" key={i}>
|
<div class="post" key={i}>
|
||||||
<div class="date">{posts[i].date}</div>
|
<div class="date">
|
||||||
<div class="intro" dangerouslySetInnerHTML={this.decodeHtml(posts[i].title.toString())}></div>
|
{posts[i].date}
|
||||||
<div dangerouslySetInnerHTML={this.decodeHtml(posts[i].intro.toString())}></div>
|
</div>
|
||||||
<p><a class="link" href="#">continue reading...</a></p>
|
<h2 class="intro" >{posts[i].title.toString()}</h2>
|
||||||
</div>
|
<p>{posts[i].intro.toString()}</p>
|
||||||
);
|
<p>
|
||||||
}
|
<Link class="link" to={`/post/${posts[i].category}/${posts[i].filename}`}>
|
||||||
|
continue reading...
|
||||||
return elements;
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeHtml(html) {
|
return elements;
|
||||||
var txt = document.createElement("textarea");
|
}
|
||||||
txt.innerHTML = html;
|
|
||||||
return {__html : txt.value};
|
|
||||||
}
|
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
const posts = this.props.posts;
|
const posts = this.props.posts;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="Preview">
|
<div class="Preview">
|
||||||
{posts.length > 0 ? this.insertPosts(posts): ""}
|
{posts.length > 0 ? this.insertPosts(posts): ""}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,39 +6,61 @@ import '../../assets/scss/Sidebar.scss';
|
|||||||
|
|
||||||
export default class Sidebar extends React.Component{
|
export default class Sidebar extends React.Component{
|
||||||
|
|
||||||
constructor(){
|
constructor(){
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
toggler: ""
|
toggler: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onToggle = this.onToggle.bind(this);
|
this.onToggle = this.onToggle.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
onToggle(){
|
onToggle(){
|
||||||
let temp = this.state.toggler;
|
let temp = this.state.toggler;
|
||||||
temp = temp === "open" ? "" : "open";
|
temp = temp === "open" ? "" : "open";
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
toggler: temp
|
toggler: temp
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<div class={"Sidebar " + this.state.toggler}>
|
<div class={"Sidebar " + this.state.toggler}>
|
||||||
<a onClick={this.onToggle} class="toggler"><i class="fa fa-2x fa-navicon" aria-hidden="true" /></a>
|
<a onClick={this.onToggle} class="toggler">
|
||||||
<h2>About Me</h2>
|
<i
|
||||||
<img src={me}/>
|
class="fa fa-2x fa-navicon"
|
||||||
<p>My name is Mitchell and I have a passion for software development. I am currently a software engineer and enjoy working on personal projects in my free time.</p>
|
aria-hidden="true" />
|
||||||
|
</a>
|
||||||
|
<h2>
|
||||||
|
About Me
|
||||||
|
</h2>
|
||||||
|
<img src={me}/>
|
||||||
|
<p>
|
||||||
|
My name is Mitchell and I have a passion for software development. I am currently a software engineer and enjoy working on personal projects in my free time.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3>Contact Me</h3>
|
<h3>
|
||||||
<p><i class="fa fa-envelope" aria-hidden="true"></i><a class="link" href="mailto:mgerb42@gmail.com"> eMail</a></p>
|
Contact Me
|
||||||
<p><i class="fa fa-linkedin-square" aria-hidden="true"></i><a class="link" href="https://www.linkedin.com/in/mitchell-gerber-125391b3" target="_blank"> LinkedIn</a></p>
|
</h3>
|
||||||
<p><i class="fa fa-github" aria-hidden="true"></i><a class="link" href="https://github.com/mgerb" target="_blank"> GitHub</a></p>
|
<p>
|
||||||
<p><i class="fa fa-wpforms" aria-hidden="true"></i><a href="/resume" class="link"> Resume</a></p>
|
<i class="fa fa-envelope" aria-hidden="true"></i>
|
||||||
</div>
|
<a class="link" href="mailto:mgerb42@gmail.com"> eMail</a>
|
||||||
);
|
</p>
|
||||||
}
|
<p>
|
||||||
|
<i class="fa fa-linkedin-square" aria-hidden="true"></i>
|
||||||
|
<a class="link" href="https://www.linkedin.com/in/mitchell-gerber-125391b3" target="_blank"> LinkedIn</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-github" aria-hidden="true"></i>
|
||||||
|
<a class="link" href="https://github.com/mgerb" target="_blank"> GitHub</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-wpforms" aria-hidden="true"> </i>
|
||||||
|
<a href="/resume" class="link"> Resume</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,27 +5,46 @@ import Header from '../components/Header';
|
|||||||
import Preview from '../components/Preview';
|
import Preview from '../components/Preview';
|
||||||
import Footer from '../components/Footer';
|
import Footer from '../components/Footer';
|
||||||
import Sidebar from '../components/Sidebar';
|
import Sidebar from '../components/Sidebar';
|
||||||
|
import Post from '../components/Post';
|
||||||
|
|
||||||
//css
|
//css
|
||||||
import '../../assets/css/normalize.css';
|
import '../../assets/css/normalize.css';
|
||||||
import '../../assets/scss/main.scss';
|
import '../../assets/scss/main.scss';
|
||||||
import 'font-awesome/css/font-awesome.min.css';
|
import 'font-awesome/css/font-awesome.min.css';
|
||||||
|
import '../../assets/css/dracula.css';
|
||||||
|
|
||||||
export default class Index extends React.Component{
|
export default class Index extends React.Component {
|
||||||
componentDidMount(){
|
componentDidMount() {
|
||||||
this.props.actions.fetchPreview();
|
this.props.actions.fetchPreview();
|
||||||
|
this.page = this.props.params.page;
|
||||||
|
this.page === 'post' ? this.props.actions.fetchPost(this.props.params.category, this.props.params.post) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
|
||||||
return(
|
componentWillReceiveProps(nextProps){
|
||||||
<div class="Layout">
|
if(this.props.params !== nextProps.params){
|
||||||
<Header/>
|
const params = nextProps.params;
|
||||||
<div class="Main">
|
this.page = params.page;
|
||||||
<Preview posts={this.props.redux.preview.posts}/>
|
|
||||||
<Sidebar />
|
if(typeof params.post !== 'undefined' && typeof params.category !== 'undefined'){
|
||||||
</div>
|
this.props.actions.fetchPost(params.category, params.post);
|
||||||
<Footer/>
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div class="Layout" >
|
||||||
|
<Header />
|
||||||
|
<div class="Main">
|
||||||
|
<div class="Content">
|
||||||
|
{typeof this.page === 'undefined' ? <Preview posts={this.props.redux.preview.posts} /> : ""}
|
||||||
|
{this.page === 'post' ? <Post content={this.props.redux.post}/> : ""}
|
||||||
</div>
|
</div>
|
||||||
);
|
<Sidebar />
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,41 @@
|
|||||||
import * as types from "./constants";
|
import * as types from "./constants";
|
||||||
|
import marked from 'marked';
|
||||||
|
|
||||||
function initPreview(posts){
|
function initPreview(posts) {
|
||||||
return{
|
return {
|
||||||
type: types.INIT_PREVIEW,
|
type: types.INIT_PREVIEW,
|
||||||
posts
|
posts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadPost(post){
|
||||||
|
return {
|
||||||
|
type: types.LOAD_POST,
|
||||||
|
post
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//using redux-thunk we can modify actions before they get called
|
//using redux-thunk we can modify actions before they get called
|
||||||
//in this case we can send the http request here rather in the react component
|
//in this case we can send the http request here rather in the react component
|
||||||
export function fetchPreview(){
|
export function fetchPreview() {
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
return fetch('/public/metadata.json')
|
return fetch('/public/metadata.json')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => {
|
.then(json => {
|
||||||
dispatch(initPreview(json));
|
dispatch(initPreview(json));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchPost(category, post) {
|
||||||
|
return (dispatch) => {
|
||||||
|
return fetch(`/public/posts/${category}/${post}.md`)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(response => {
|
||||||
|
dispatch(loadPost(response));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
//constants
|
//constants
|
||||||
export const INIT_PREVIEW = 'INIT_PREVIEW';
|
export const INIT_PREVIEW = 'INIT_PREVIEW';
|
||||||
export const FILTER_PREVIEW = 'FILTER_PREVIEW';
|
export const FILTER_PREVIEW = 'FILTER_PREVIEW';
|
||||||
|
export const LOAD_POST = 'LOAD_POST';
|
||||||
|
|||||||
@@ -1,20 +1,29 @@
|
|||||||
//just using one reducer - use combineReducers from redux to modularize things
|
//just using one reducer - use combineReducers from redux to modularize things
|
||||||
import {combineReducers} from 'redux';
|
import {
|
||||||
import {routerReducer} from 'react-router-redux';
|
combineReducers
|
||||||
|
} from 'redux';
|
||||||
|
import {
|
||||||
|
routerReducer
|
||||||
|
} from 'react-router-redux';
|
||||||
|
|
||||||
//import typs
|
//import typs
|
||||||
import * as types from './constants';
|
import * as types from './constants';
|
||||||
|
|
||||||
//defaults -
|
//defaults -
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
preview: {posts: []},
|
preview: {
|
||||||
filteredPreview: {posts: []}
|
posts: []
|
||||||
|
},
|
||||||
|
filteredPreview: {
|
||||||
|
posts: []
|
||||||
|
},
|
||||||
|
post: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
//default reducer
|
//default reducer
|
||||||
function reducer(state = defaultState, action){
|
function reducer(state = defaultState, action) {
|
||||||
//every reducer gets called when an action is called - we check for the type to modify our state accordingly
|
//every reducer gets called when an action is called - we check for the type to modify our state accordingly
|
||||||
switch (action.type){
|
switch (action.type) {
|
||||||
case types.INIT_PREVIEW:
|
case types.INIT_PREVIEW:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
preview: Object.assign({}, state.preview, action.posts)
|
preview: Object.assign({}, state.preview, action.posts)
|
||||||
@@ -22,9 +31,14 @@ function reducer(state = defaultState, action){
|
|||||||
case types.FILTER_PREVIEW:
|
case types.FILTER_PREVIEW:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
filteredPreview: Object.assign({}, state.filteredPreview, action.posts)
|
filteredPreview: Object.assign({}, state.filteredPreview, action.posts)
|
||||||
|
});
|
||||||
|
case types.LOAD_POST:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
post: action.post
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//return present state if no actions get called
|
//return present state if no actions get called
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -34,4 +48,4 @@ const allReducers = combineReducers({
|
|||||||
routing: routerReducer
|
routing: routerReducer
|
||||||
});
|
});
|
||||||
|
|
||||||
export default allReducers;
|
export default allReducers;
|
||||||
|
|||||||
@@ -36,13 +36,12 @@ function parse_dir(dir, folder_name){
|
|||||||
} else {
|
} else {
|
||||||
const file = fs.readFileSync(dir+post, 'utf8');
|
const file = fs.readFileSync(dir+post, 'utf8');
|
||||||
const tokens = marked.lexer(file, null);
|
const tokens = marked.lexer(file, null);
|
||||||
const path = dir + post;
|
|
||||||
const temp = {
|
const temp = {
|
||||||
path: path.slice(1, path.length),
|
filename: post.slice(0, post.length - 3),
|
||||||
category: folder_name,
|
category: folder_name,
|
||||||
date: post.slice(0, 10),
|
date: post.slice(0, 10),
|
||||||
title: marked('<h2>' + tokens[0].text + '</h2>'),
|
title: tokens[0].text,
|
||||||
intro: marked(tokens[1].text)
|
intro: tokens[1].text
|
||||||
}
|
}
|
||||||
json.posts.push(temp);
|
json.posts.push(temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,4 +42,4 @@ Now as easy as that sounds, you have a Node web application running on your mach
|
|||||||
|
|
||||||
Express organizes everything nicely in the [Model View Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) software pattern. Folders are split up into views, routes, and public files. If you are implementing a database, you would also create a "models" folder. There is also a folder which contains Node modules. When you use NPM to install new modules this is where they will be located.
|
Express organizes everything nicely in the [Model View Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) software pattern. Folders are split up into views, routes, and public files. If you are implementing a database, you would also create a "models" folder. There is also a folder which contains Node modules. When you use NPM to install new modules this is where they will be located.
|
||||||
|
|
||||||
Node is a very powerful tool that I plan on exploring more in the future. As development of this site continues, I plan to submit more content similar to this.
|
Node is a very powerful tool that I plan on exploring more in the future. As development of this site continues, I plan to submit more content similar to this.
|
||||||
Reference in New Issue
Block a user