Last active
May 22, 2017 12:17
-
-
Save ace411/e08e037eeac39d8bc0e5432e8ba15926 to your computer and use it in GitHub Desktop.
Using the fauxton client with Bingo MVC and ReactJS
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
<!doctype HTML> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>{{ title }}</title> | |
<link rel="stylesheet" href="{{ stylesheet }}" type="text/css"> | |
</head> | |
<body> | |
<h1 align="center">{{ title }}</h1> | |
<section class="entry-detail-container" id="entry-details"></section> | |
<section class="entry-form-container" id="entry-form"></section> | |
<script src="https://unpkg.com/react@15/dist/react.min.js"></script> | |
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script> | |
<script src="{{ script }}"></script> | |
</body> | |
</html> |
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
<?php | |
/** | |
* Controller for the CouchDB-React-Bingo project | |
* | |
* @package The Bingo Framework | |
* @author Lochemem Bruno Michael | |
*/ | |
namespace App\Controllers; | |
class Basketball | |
{ | |
use \Core\Controller; | |
/** | |
* Renders the basketball/index page | |
*/ | |
public function indexAction() | |
{ | |
echo $this->container['Views']->mustacheRender('basketball', [ | |
'title' => 'NBA Player Statistics', | |
'script' => '/js/react-main.js', | |
'stylesheet' => '/css/main.css' | |
]); | |
} | |
/** | |
* Render the basketball/add-data page | |
* This action is built to interact with the data entry form on the index page via AJAX | |
*/ | |
public function addDataAction() | |
{ | |
$input = file_get_contents('php://input'); //get the input from the user | |
$input = json_decode($input, true); | |
print_r($this->container['CouchDb']->createDoc($input)); | |
} | |
/** | |
* Render the basketball/get-data page | |
* This action is fashioned to get all the document data from the CouchDB database | |
*/ | |
public function getDataAction() | |
{ | |
print_r($this->container['CouchDb']->getAllDocs()); | |
} | |
} |
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
{ | |
"name": "chemem/bingo-framework", | |
"description": "A simple PHP MVC framework", | |
"type": "project", | |
"license": "MIT", | |
"authors": [ | |
{ | |
"name": "Lochemem Bruno Michael", | |
"email": "[email protected]" | |
} | |
], | |
"require": { | |
"php": ">=5.6.0", | |
"chemem/fauxton-client": "dev-master" | |
}, | |
"require-dev": { | |
"mustache/mustache": "*", | |
"phpunit/phpunit": "*", | |
"michelf/php-markdown": "*", | |
"kriswallsmith/assetic": "*", | |
"pimple/pimple": "*" | |
}, | |
"suggest": { | |
"chemem/fauxton-client": "Helps with CouchDB NoSQL interactions", | |
"leafo/lessphp": "Compile LESS files to CSS without using third-party compilers", | |
"leafo/scssphp": "Compile SCSS files to CSS without using third-party compilers", | |
"patchwork/jsqueeze": "Minify JS files", | |
"naxtet/CssMin": "Minify CSS files" | |
}, | |
"scripts": { | |
"bundle-all": "@php cli/bingo-cli.php -ball", | |
"bundle-js": "@php cli/bingo-cli.php -bjs", | |
"bundle-less": "@php cli/bingo-cli.php -bless", | |
"bundle-css": "@php cli/bingo-cli.php -bcss", | |
"bundle-scss": "@php cli/bingo-cli.php -bscss", | |
"split-js": "@php cli/bingo-cli.php -spjs", | |
"split-css": "@php cli/bingo-cli.php -spcss", | |
"split-scss": "@php cli/bingo-cli.php -spscss", | |
"split-less": "@php cli/bingo-cli.php -spless", | |
"filter-js": "@php cli/bingo-cli.php -fjs", | |
"filter-less": "@php cli/bingo-cli.php -fless", | |
"filter-css": "@php cli/bingo-cli.php -fcss", | |
"filter-scss": "@php cli/bingo-cli.php -fscss" | |
}, | |
"config": { | |
"prepend-autoloader": false, | |
"vendor-dir": "packages" | |
}, | |
"autoload": { | |
"psr-4": { | |
"Core\\": "Core/", | |
"App\\": "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
<?php | |
/** | |
* Configuration options for the Bingo Framework | |
* | |
* @package Bingo Framework | |
* @author Lochemem Bruno Michael | |
* | |
*/ | |
namespace App; | |
class Config | |
{ | |
/** | |
* Database user-name parameter | |
* | |
* @var string DB_USER | |
* | |
*/ | |
const DB_USER = '<couchdb-username>'; | |
/** | |
* Database database host parameter | |
* | |
* @var string DB_HOST | |
* | |
*/ | |
const DB_HOST = 'localhost'; | |
/** | |
* Database user-password parameter | |
* | |
* @var string DB_PASS | |
* | |
*/ | |
const DB_PASS = '<couchdb-password>'; | |
/** | |
* Database name parameter | |
* | |
* @var string DB_NAME | |
* | |
*/ | |
const DB_NAME = 'nba_info'; | |
/** | |
* Show errors or convert them into readable logs | |
* Set to false in production | |
* | |
* @var bool SHOW_ERRORS | |
* | |
*/ | |
const SHOW_ERRORS = true; | |
/** | |
* Set the error type for the configuration | |
* Options are: json, text-html | |
* | |
* @var string ERROR_TYPE | |
* | |
*/ | |
const ERROR_TYPE = 'text-html'; | |
/** | |
* Dependency directory | |
* @see composer.json for the name of the root dependency folder | |
* | |
* @var string DEP_ROOT | |
* | |
*/ | |
const DEP_ROOT = 'packages'; | |
/** | |
* Cache directory for | |
* | |
* @var string CACHE_DIR | |
* | |
*/ | |
const CACHE_DIR = 'cache'; | |
/** | |
* | |
* Cache all the bundled assets | |
* | |
* @var bool ASSET_CACHE | |
* | |
*/ | |
const ASSET_CACHE = true; | |
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
<?php | |
/** | |
* Model for the CouchDB-React-Bingo project | |
* Abstracts the interaction with the fauxton-client package | |
* | |
* @package The Bingo Framework | |
* @author Lochemem Bruno Michael | |
* | |
*/ | |
namespace App\Models; | |
use \App\Config; | |
final class CouchBasketball | |
{ | |
protected $db; | |
protected $doc; | |
public function __construct($db, $doc) | |
{ | |
$this->db = $db; | |
$this->doc = $doc; | |
} | |
/** | |
* Create the database if it does not exist | |
* Use this only if you do not want to create the database via the Fauxton interface | |
* | |
* @return array $db->createDatabase(Config::DB_NAME) Database information | |
*/ | |
public function createDatabase() | |
{ | |
if (in_array(Config::DB_NAME, $this->db->showAllDatabases())) { | |
return false; | |
} | |
return $this->db->createDatabase(Config::DB_NAME); | |
} | |
/** | |
* Get all the documents from the specified database | |
* | |
* @return string $doc->getDocsByKey($params) CouchDB JSON documents | |
*/ | |
public function getAllDocs() | |
{ | |
$rows = $this->doc->showAllDocuments(Config::DB_NAME)->rows; | |
$keys = []; | |
for ($x = 0; $x < count($rows); $x++) { | |
$keys[$x] = $rows[$x]->key; | |
} | |
$this->doc::setReturnType(true); | |
return $this->doc->getDocsByKey(Config::DB_NAME, ['keys' => $keys]); | |
} | |
/** | |
* Create a document | |
* | |
* @param array $doc An array of document information | |
* @return array $doc->createDocument($params) CouchDB document details | |
*/ | |
public function createDoc(array $docBody) | |
{ | |
$docId = $this->doc->generateId()->uuids[0]; | |
return $this->doc->createDocument($docId, Config::DB_NAME, $docBody); | |
} | |
} |
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
<?php | |
/** | |
* Public file for the Bingo Framework | |
* Adding routes for the various controllers and views happens here | |
* | |
* @package The Bingo Framework | |
* @author Lochemem Bruno Michael | |
* | |
*/ | |
require dirname(__DIR__) . '/packages/autoload.php'; | |
set_error_handler('Core\Error::errorHandler'); | |
set_exception_handler('Core\Error::exceptionHandler'); | |
$router = new Core\Router(); | |
$router->inject('Views', function ($c) { | |
return new \Core\Views; | |
}); | |
$router->inject('CouchDb', function ($c) { | |
$db = new \Chemem\Fauxton\DatabaseActions; | |
$doc = new \Chemem\Fauxton\DocumentActions; | |
$doc->setReturnType(false); | |
$db->useFauxtonLogin(\App\Config::DB_USER, \App\Config::DB_PASS); | |
return new \App\Models\CouchBasketball($db, $doc); | |
}); | |
$router->addRoute('{controller}/{action}'); | |
$router->dispatch($_SERVER['QUERY_STRING']); |
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
body { | |
padding: 0; | |
margin: 0; | |
font-family: Verdana; | |
} | |
/** | |
* Entry form styles | |
*/ | |
.entry-form, .entry-list { | |
width: 50%; | |
height: auto; | |
display: flex; | |
flex-flow: column; | |
flex-direction: column; | |
margin-left: 25%; | |
margin-right: 25%; | |
border: 1px solid dashed; | |
} | |
.entry-form-input, .entry-form-button { | |
width: 100%; | |
border: none; | |
font-size: 18px; | |
position: relative; | |
margin-top: 5px; | |
margin-bottom: 5px; | |
padding-top: 5px; | |
padding-bottom: 5px; | |
} | |
.entry-form-input:focus { | |
outline: none; | |
border-bottom: 2px solid black; | |
} | |
.entry-form-button { | |
cursor: pointer; | |
font-size: 21px; | |
background: royalblue; | |
} | |
/** | |
* Entry list styles | |
*/ | |
.entry-list { | |
margin: 0; | |
padding: 0; | |
flex-wrap: nowrap; | |
} | |
.entry-list-node { | |
margin-top: 1%; | |
margin-bottom: 1%; | |
} |
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
"use strict"; | |
(function () { | |
const reactElement = React.createElement; | |
function ajaxRequest(method, data) { | |
data = (typeof data !== 'undefined') ? data : ''; //data to be sent | |
return new Promise((resolve, reject) => { | |
const ajax = new XMLHttpRequest; | |
if (method === 'POST') { | |
ajax.open('POST', '/basketball/add-data', true); //add data if method is post | |
} else { | |
ajax.open('GET', '/basketball/get-data', true); //pull data if method is get | |
} | |
ajax.onreadystatechange = () => { | |
if (ajax.readyState === 4) { | |
resolve(ajax.response); | |
} | |
}; | |
ajax.onerror = () => { | |
reject(ajax.status); | |
} | |
ajax.send(data); | |
}); | |
} | |
class EntryForm extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
player_name: '', | |
player_team: '', | |
player_scoring_avg: '' | |
}; | |
this.setPlayerName = this.setPlayerName.bind(this); | |
this.setPlayerTeam = this.setPlayerTeam.bind(this); | |
this.setPlayerScoringAvg = this.setPlayerScoringAvg.bind(this); | |
this.submitData = this.submitData.bind(this); | |
} | |
setPlayerName(event) { | |
this.setState({player_name: event.target.value}); | |
} | |
setPlayerTeam(event) { | |
this.setState({player_team: event.target.value}); | |
} | |
setPlayerScoringAvg(event) { | |
this.setState({player_scoring_avg: event.target.value}); | |
} | |
submitData(event) { | |
event.preventDefault(); | |
ajaxRequest('POST', JSON.stringify(this.state)) | |
.then((response) => { | |
console.log(response); | |
}, (error) => { | |
console.log(error); | |
}); | |
} | |
render() { | |
const renderData = { | |
playerName: { | |
placeholder: this.props.placeholder.name, | |
className: this.props.class.name, | |
onChange: this.setPlayerName, | |
value: this.state.playerName, | |
type: this.props.type.name | |
}, | |
playerTeam: { | |
placeholder: this.props.placeholder.team, | |
className: this.props.class.team, | |
onChange: this.setPlayerTeam, | |
value: this.state.playerTeam, | |
type: this.props.type.team | |
}, | |
playerScoringAvg: { | |
placeholder: this.props.placeholder.avg, | |
className: this.props.class.avg, | |
onChange: this.setPlayerScoringAvg, | |
value: this.state.playerScoringAvg, | |
type: this.props.type.avg | |
}, | |
submit: { | |
className: this.props.class.submit, | |
type: this.props.type.submit, | |
onClick: this.submitData, | |
value: 'Submit' | |
} | |
}; | |
return reactElement('form', {className: 'entry-form'}, | |
reactElement('input', renderData.playerName), | |
reactElement('input', renderData.playerTeam), | |
reactElement('input', renderData.playerScoringAvg), | |
reactElement('input', renderData.submit) | |
); | |
} | |
} | |
class DatabaseInfo extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = {player_data: []}; | |
} | |
componentDidMount() { | |
ajaxRequest('GET') | |
.then((response) => { | |
this.setState({player_data: JSON.parse(response).rows}); | |
}, (error) => { | |
console.log(error); | |
}); | |
} | |
render() { | |
return reactElement('ul', {className: this.props.class.ul}, this.state.player_data.map((index) => { | |
return reactElement('li', {className: this.props.class.li}, index.doc.player_name + ' ' + index.doc.player_scoring_avg + ' PPG') | |
})); | |
} | |
} | |
ReactDOM.render( | |
reactElement(DatabaseInfo, { | |
class: { | |
ul: 'entry-list', | |
li: 'entry-list-node' | |
} | |
}), | |
document.getElementById('entry-details') | |
); | |
ReactDOM.render( | |
reactElement(EntryForm, { | |
placeholder: { | |
name: 'Player name..', | |
team: 'Player team..', | |
avg: 'Player Scoring average' | |
}, | |
type: { | |
name: 'text', | |
team: 'text', | |
avg: 'number', | |
submit: 'submit' | |
}, | |
class: { | |
avg: 'entry-form-input', | |
name: 'entry-form-input', | |
team: 'entry-form-input', | |
submit: 'entry-form-button' | |
} | |
}), | |
document.getElementById('entry-form') | |
); | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment