-
Notifications
You must be signed in to change notification settings - Fork 314
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ab096cc
commit 2fd883f
Showing
12 changed files
with
1,086 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
{ | ||
"presets": [ | ||
"env" | ||
"env", | ||
"react" | ||
], | ||
"plugins": [ | ||
"transform-class-properties" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
.pointers { | ||
& .pointer, | ||
& .post { | ||
padding: 0.5em 0; | ||
} | ||
|
||
& .pointer { | ||
cursor: move; | ||
} | ||
|
||
& .post { | ||
color: #7b7b7b; | ||
} | ||
} | ||
|
||
.delete-pointer, | ||
.add-pointer { | ||
cursor: pointer; | ||
float: right; | ||
} | ||
|
||
.pointer-results { | ||
margin-top: 1em; | ||
} | ||
|
||
.pointer-result { | ||
padding: 0.5em 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
import { Pointers } from './pointers'; | ||
|
||
ReactDOM.render( | ||
<Pointers/>, | ||
document.getElementById( 'ordering-app' ) | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
// External | ||
import React, { Component } from 'react'; | ||
import apiFetch from '@wordpress/api-fetch'; | ||
import { debounce } from '../utils/debounce'; | ||
import { pluck } from '../utils/pluck'; | ||
|
||
apiFetch.use( apiFetch.createRootURLMiddleware( window.epOrdering.restApiRoot ) ); | ||
|
||
/** | ||
* Pointer component | ||
*/ | ||
export class Pointers extends Component { | ||
|
||
titleInput = null; | ||
|
||
/** | ||
* Initializes the component with initial state set by WP | ||
* | ||
* @param props | ||
*/ | ||
constructor( props ) { | ||
super( props ); | ||
|
||
// We need to know the title of the page and react to changes since this is the query we search for | ||
this.titleInput = document.getElementById( 'title' ); | ||
|
||
this.state = { | ||
pointers: window.epOrdering.pointers, | ||
posts: window.epOrdering.posts, | ||
title: this.titleInput.value, | ||
defaultResults: {}, | ||
searchText: '', | ||
searchResults: {}, | ||
}; | ||
|
||
this.titleInput.addEventListener( 'keyup', debounce( this.handleTitleChange, 200 ) ); | ||
|
||
this.getDefaultResults(); | ||
} | ||
|
||
handleTitleChange = () => { | ||
this.setState( { title: this.titleInput.value } ); | ||
}; | ||
|
||
getDefaultResults = () => { | ||
let searchTerm = this.state.title; | ||
|
||
apiFetch( { | ||
path: `/elasticpress/v1/pointer_search?s=${searchTerm}`, | ||
} ).then( result => { | ||
|
||
let { defaultResults } = this.state; | ||
|
||
defaultResults[ searchTerm ] = result; | ||
|
||
this.setState( { defaultResults } ); | ||
} ); | ||
}; | ||
|
||
removePointer = ( pointer ) => { | ||
let { pointers } = this.state; | ||
|
||
delete pointers[ pointers.indexOf( pointer ) ]; | ||
|
||
this.setState( { pointers } ); | ||
}; | ||
|
||
getMergedPosts = () => { | ||
let merged = this.state.defaultResults[ this.state.title ].slice(); | ||
let pointers = this.state.pointers; | ||
|
||
let setIds = {}; | ||
merged.map( item => { | ||
setIds[ item.ID ] = item; | ||
} ); | ||
|
||
pointers.map( pointer => { | ||
// Remove the original if a duplicate | ||
if ( setIds[ pointer.ID ] ) { | ||
delete merged[ merged.indexOf( setIds[ pointer.ID ] ) ]; | ||
} | ||
|
||
// Insert into proper location | ||
merged.splice( parseInt( pointer.order, 10 ) - 1, 0, pointer ); | ||
} ); | ||
|
||
return merged; | ||
}; | ||
|
||
doSearch = debounce( () => { | ||
let searchTerm = this.state.searchText; | ||
|
||
// Set loading state | ||
let { searchResults } = this.state; | ||
searchResults[ searchTerm ] = false; | ||
this.setState( { searchResults } ); | ||
|
||
apiFetch( { | ||
path: `/elasticpress/v1/pointer_search?s=${searchTerm}` | ||
} ).then( result => { | ||
let { searchResults } = this.state; | ||
|
||
searchResults[ searchTerm ] = result; | ||
|
||
this.setState( { searchResults } ); | ||
} ); | ||
}, 200 ); | ||
|
||
addPointer = ( post ) => { | ||
const id = post.ID; | ||
const { posts, pointers } = this.state; | ||
|
||
if ( ! posts[ id ] ) { | ||
posts[ id ] = post; | ||
this.setState( { posts } ); | ||
} | ||
|
||
const merged = this.getMergedPosts(); | ||
|
||
pointers.push( { | ||
ID: id, | ||
order: merged.length + 1, | ||
} ); | ||
|
||
this.setState( { pointers } ); | ||
}; | ||
|
||
/** | ||
* Renders the component | ||
* | ||
* @returns {*} | ||
*/ | ||
render() { | ||
const { posts, defaultResults } = this.state; | ||
|
||
if ( ! defaultResults[ this.state.title ] ) { | ||
return ( | ||
<div className="loading"> | ||
<div className="spinner is-active"></div> | ||
<span>Loading Result Preview...</span> | ||
</div> | ||
); | ||
} | ||
|
||
const mergedPosts = this.getMergedPosts(); | ||
const renderedIds = pluck( this.state.pointers, 'ID' ); | ||
|
||
const searchResults = this.state.searchResults[ this.state.searchText ] ? | ||
this.state.searchResults[ this.state.searchText ].filter( item => -1 === renderedIds.indexOf( item.ID ) ) : | ||
false; | ||
|
||
return ( | ||
<div> | ||
<div className="pointers"> | ||
{mergedPosts.map( ( item ) => { | ||
if ( item.order ) { | ||
// is pointer | ||
const referencedPost = posts[ item.ID ]; | ||
|
||
return ( | ||
<div className="pointer" key={item.ID}> | ||
<strong className="title">{referencedPost.post_title}</strong> | ||
<span className="dashicons dashicons-trash delete-pointer" onClick={ e => { e.preventDefault(); this.removePointer( item ); } }> | ||
<span className="screen-reader-text">Remove Post</span> | ||
</span> | ||
</div> | ||
); | ||
} else { | ||
// is default post | ||
return ( | ||
<div className="post" key={item.ID}> | ||
<strong className="title">{item.post_title}</strong> | ||
</div> | ||
); | ||
} | ||
} )} | ||
</div> | ||
|
||
<hr/> | ||
|
||
<div className="pointer-search"> | ||
<input | ||
type="text" | ||
className="widefat search-pointers" | ||
placeholder="Search for Post" | ||
value={ this.state.searchText } | ||
onChange={ e => { | ||
this.setState( { searchText: e.target.value } ); | ||
this.doSearch(); | ||
} }/> | ||
|
||
<div className="pointer-results"> | ||
{ this.searchResults( searchResults ) } | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
searchResults = ( searchResults ) => { | ||
if ( '' === this.state.searchText ) { | ||
return; | ||
} | ||
|
||
if ( false === searchResults ) { | ||
return ( | ||
<div> | ||
<div className="spinner"></div> | ||
Loading... | ||
</div> | ||
); | ||
} | ||
|
||
if ( 0 === searchResults.length ) { | ||
return ( | ||
<div>No results found.</div> | ||
); | ||
} | ||
|
||
return searchResults.map( result => { | ||
return ( | ||
<div className="pointer-result" key={result.ID}> | ||
<span className="title">{result.post_title}</span> | ||
<span className="dashicons dashicons-plus add-pointer" onClick={ e => { e.preventDefault(); this.addPointer( result ); } }> | ||
<span className="screen-reader-text">Add Post</span> | ||
</span> | ||
</div> | ||
); | ||
} ); | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Simple throttling function for waiting a set amount of time after the last keypress | ||
* So we don't overload the server with too many requests at once | ||
* | ||
* @param func | ||
* @param wait | ||
* @returns {Function} | ||
*/ | ||
export function debounce( func, wait ) { | ||
let timeout; | ||
|
||
return function() { | ||
const context = this, args = arguments; | ||
|
||
/** | ||
* | ||
*/ | ||
const later = function() { | ||
timeout = null; | ||
func.apply( context, args ); | ||
}; | ||
|
||
clearTimeout( timeout ); | ||
|
||
timeout = setTimeout( later, wait ); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* Array pluck | ||
* | ||
* @param array | ||
* @param key | ||
* | ||
* @returns array | ||
*/ | ||
export function pluck( array, key ) { | ||
return array.map( o => o[ key ] ); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.