Skip to content

Instantly share code, notes, and snippets.

@saltcod
Created February 10, 2020 12:31
Show Gist options
  • Save saltcod/7d15f78746e50b4b37e4de396c234365 to your computer and use it in GitHub Desktop.
Save saltcod/7d15f78746e50b4b37e4de396c234365 to your computer and use it in GitHub Desktop.
/* eslint-disable */
/* globals wp */
// @TODO: Need to change markup once it is finalized on FE.
const { __ } = wp.i18n;
const { InspectorControls, RichText } = wp.blockEditor;
const { PanelBody, RadioControl } = wp.components;
const { apiFetch } = wp;
const { Component } = wp.element;
const { addQueryArgs } = wp.url;
import { isEmpty } from "lodash";
/**
* Render post markup.
*
* @param page
* @param linkText
* @param linkURL
*
* @returns {*}
*/
function renderPost(post) {
// Later hook up proper post.thumbnails
const thumbnails = {
full: "https://placeimg.com/640/480/any"
};
return (
<article className="post-card">
<a
className="post-card__link"
href="javascript:;"
title={post.title.rendered}
aria-label={post.title.rendered}
>
{!isEmpty(thumbnails) && !isEmpty(thumbnails.full) && (
<div class="post-card__image-wrap">
<img
class="post-card__image"
src={thumbnails.full}
alt="placeholder image"
/>
</div>
)}
<div class="post-card__content">
<h2 class="post-card__title">{post.title.rendered}</h2>
</div>
<div class="post-card__date" itemprop="datePublished">
<time datetime={getFormattedDate(post.date)}>
{getFormattedDate(post.date)}
</time>
</div>
</a>
</article>
);
}
/**
* Get a properly formatted date from the post.date that WP gives
*
* @param {*} date the UTC string WP provides
*/
function getFormattedDate(date) {
const formattedDate = new Date(date);
const month = formattedDate.toLocaleString("default", { month: "long" });
const day = formattedDate.toLocaleString("default", { day: "numeric" });
const year = formattedDate.getFullYear();
return `${month} ${day}, ${year}`;
}
/**
* Editing interface in the admin
*
* @param attributes
* @param setAttributes
* @returns {*}
*/
class LatestPostsEdit extends Component {
constructor() {
super(...arguments);
this.state = {
categoriesList: [],
contentTypesList: [],
selectedPosts: [],
selectedContentType: "",
selectedCategory: ""
};
}
componentDidMount() {
this.termFetch();
// this.postFetch();
}
/**
* Fetch a list of categories and content types
* to populate our <select> dropdowns
*
* Urls:
* http://newbeauty.test/wp-json/wp/v2/posts?per_page=15&nb_content_type=7&category=2
* http://newbeauty.test/wp-json/wp/v2/categories
* http://newbeauty.test/wp-json/wp/v2/nb_content_type
*
*/
termFetch() {
const categoryRequest = apiFetch({
path: addQueryArgs("/wp/v2/categories", {
per_page: 20, // eslint-disable-line camelcase
type: "post"
})
});
categoryRequest.then(categories => {
this.setState({ categoriesList: categories });
});
const contentTypeRequest = apiFetch({
path: addQueryArgs("/wp/v2/nb_content_type", {
per_page: 20, // eslint-disable-line camelcase
type: "post"
})
});
contentTypeRequest.then(contentTypes => {
this.setState({ contentTypesList: contentTypes });
});
}
postFetch = () => {
// wp/v2/posts?per_page=15&nb_content_type=7&category=2
const postsRequest = apiFetch({
path: addQueryArgs("/wp/v2/posts", {
per_page: 3, // eslint-disable-line camelcase
type: "post",
category: this.state.selectedCategory,
nb_content_type: this.state.selectedContentType
})
});
postsRequest.then(posts => {
this.setState({ selectedPosts: posts });
setAttributes({ latestPosts: posts });
});
};
onCategoryChange = e => {
//this.setState({ selectedCategory: e.target.value }, {} => this.postFetch());
this.setState({ selectedCategory: e.target.value }, () => this.postFetch());
};
onContentTypeChange = e => {
this.setState({ selectedContentType: e.target.value }, () =>
this.postFetch()
);
};
render() {
const {
attributes: { title, latestPosts, layout },
setAttributes
} = this.props;
return (
<>
<InspectorControls>
<PanelBody title={__("Sorting and filtering")}>
<h3>
Select a content type and category to pull in the latest 3 posts
</h3>
<div className="components-base-control">
<p>Content type:</p>
<select onChange={this.onContentTypeChange}>
<option value selected disabled>
Select a type of content
</option>
{this.state.contentTypesList.map((type, index) => (
<option value={type.id} key={index}>
{type.name}
</option>
))}
</select>
</div>
<div className="components-base-control">
<p>Category:</p>
<select onChange={this.onCategoryChange}>
<option value selected disabled>
Select a category
</option>
{this.state.categoriesList.map((category, index) => (
<option value={category.id} key={index}>
{category.name}
</option>
))}
</select>
</div>
<RadioControl
label={__("Layout", "nu-alumni")}
selected={layout}
options={[
{ label: "Left aligned", value: "left" },
{ label: "Centered", value: "centered" }
]}
onChange={layout => {
setAttributes({ layout });
}}
/>
</PanelBody>
</InspectorControls>
<div>
<RichText
className="heading-accented -giant"
tagName="h2"
multiline={false}
placeholder={__("Title", "newbeauty")}
keepPlaceholderOnFocus="true"
value={title}
onChange={title => setAttributes({ title })}
/>
<div
className={
"category-articles__list " +
(layout == "left" ? "-left-align" : "-center-align")
}
>
<div className="category-articles__main">
{this.state.selectedPosts.length ? (
this.state.selectedPosts
.slice(0, 1)
.map(post => renderPost(post))
) : (
<p>
Select a content type and category in the sidebar on the
right.
</p>
)}
</div>
<div className="category-articles__norm">
{this.state.selectedPosts
.slice(1, 3)
.map(post => renderPost(post))}
</div>
</div>
</div>
</>
);
}
}
export default LatestPostsEdit;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment