Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #136 from creative-commoners/pulls/1.0/react-router
API Implement react-router in frontend example app
- Loading branch information
Showing
18 changed files
with
421 additions
and
38 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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,4 +1,2 @@ | ||
// Components that are only used on the frontend view | ||
require('legacy/CKANRegistryDisplay-loader.js'); | ||
require('components/CKANDropdownFilter'); | ||
require('components/CKANTextFilter'); | ||
// An example React app that consumes a CKAN registry | ||
require('legacy/CKANExampleApp-loader.js'); |
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,108 @@ | ||
/* global document */ | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { BrowserRouter, Route, Redirect } from 'react-router-dom'; | ||
import CKANRegistryDisplay from 'components/CKANRegistryDisplay'; | ||
import CKANRegistryDetailView from 'components/CKANRegistryDetailView'; | ||
|
||
/** | ||
* An example React app showing how you could build a frontend for the CKAN registry | ||
* on the current page. | ||
* | ||
* This app has two main components: | ||
* - CKANRegistryDisplay: renders the display of the resource data and filters | ||
* - CKANRegistryDetailView: renders a detailed view of the selected resource entry | ||
* | ||
* The react-router-dom package controls the routing between these components in this | ||
* example. | ||
*/ | ||
class CKANExampleApp extends Component { | ||
/** | ||
* Returns a title to display for each page | ||
* | ||
* @returns {string} | ||
*/ | ||
getTitle() { | ||
return `${this.props.name} / ${this.props.resourceName}`; | ||
} | ||
|
||
/** | ||
* Renders the header section, containing the page title | ||
* | ||
* @returns {HTMLElement} | ||
*/ | ||
renderHeader() { | ||
return ( | ||
<section className="ckan-registry__header"> | ||
<h2 className="ckan-registry__title">{ this.getTitle() }</h2> | ||
</section> | ||
); | ||
} | ||
|
||
/** | ||
* Renders the content container and content components conditional on the | ||
* current route matching | ||
* | ||
* @returns {HTMLElement} | ||
*/ | ||
renderContent() { | ||
const { basePath } = this.props; | ||
|
||
return ( | ||
<div className="ckan-registry__content"> | ||
<Route | ||
path={basePath} | ||
exact | ||
render={props => <CKANRegistryDisplay {...props} basePath={basePath} />} | ||
/> | ||
|
||
<Route | ||
path={`${basePath}/view/:item`} | ||
render={props => <CKANRegistryDetailView {...props} basePath={basePath} />} | ||
/> | ||
|
||
<Route | ||
path={`${basePath}/view`} | ||
exact | ||
render={() => <Redirect to={basePath} />} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
/** | ||
* Returns a routed/routable app with a header and a content section | ||
* | ||
* @returns {BrowserRouter} | ||
*/ | ||
render() { | ||
return ( | ||
<BrowserRouter> | ||
<div className="ckan-registry"> | ||
{ this.renderHeader() } | ||
{ this.renderContent() } | ||
</div> | ||
</BrowserRouter> | ||
); | ||
} | ||
} | ||
|
||
CKANExampleApp.propTypes = { | ||
basePath: PropTypes.string, | ||
name: PropTypes.string, | ||
resourceName: PropTypes.string, | ||
spec: PropTypes.shape({ | ||
dataset: PropTypes.string, | ||
endpoint: PropTypes.string, | ||
identifier: PropTypes.string, | ||
}), | ||
}; | ||
|
||
CKANExampleApp.defaultProps = { | ||
basePath: '/', | ||
name: '', | ||
resourceName: '', | ||
spec: {}, | ||
}; | ||
|
||
export default CKANExampleApp; |
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,21 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
const CKANRegistryDetailView = ({ basePath, match }) => ( | ||
<div className="ckan-registry__detail"> | ||
<h3>Details of { match.params.item } </h3> | ||
<p>Watch this space!</p> | ||
<Link to={basePath}>< Back</Link> | ||
</div> | ||
); | ||
|
||
CKANRegistryDetailView.propTypes = { | ||
basePath: PropTypes.string, | ||
}; | ||
|
||
CKANRegistryDetailView.defaultProps = { | ||
basePath: '/', | ||
}; | ||
|
||
export default CKANRegistryDetailView; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import Enzyme, { shallow } from 'enzyme'; | ||
import Adapter from 'enzyme-adapter-react-15.4/build/index'; | ||
import CKANExampleApp from '../CKANExampleApp'; | ||
|
||
Enzyme.configure({ adapter: new Adapter() }); | ||
|
||
describe('CKANExampleApp', () => { | ||
describe('getTitle()', () => { | ||
it('concatenates the dataset and resource name', () => { | ||
const wrapper = shallow( | ||
<CKANExampleApp name="Ministry of Silly Walks" resourceName="Lunging" /> | ||
); | ||
|
||
expect(wrapper.instance().getTitle()).toBe('Ministry of Silly Walks / Lunging'); | ||
}); | ||
}); | ||
}); |
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,19 @@ | ||
/* global window */ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import CKANExampleApp from 'components/CKANExampleApp'; | ||
|
||
window.document.addEventListener('DOMContentLoaded', () => { | ||
const registries = document.querySelectorAll('.ckan-registry-holder'); | ||
|
||
[...registries].forEach(element => { | ||
// Prevents processing the same container more than once | ||
if (element.classList.contains('loaded')) { | ||
return; | ||
} | ||
element.classList.add('loaded'); | ||
|
||
const configuration = JSON.parse(element.dataset.configuration); | ||
ReactDOM.render(<CKANExampleApp {...configuration} />, element); | ||
}); | ||
}); |
This file was deleted.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<?php | ||
|
||
namespace SilverStripe\CKANRegistry\Page; | ||
|
||
use PageController; | ||
use SilverStripe\CKANRegistry\Model\Resource; | ||
use SilverStripe\ORM\DataObject; | ||
|
||
class CKANRegistryPageController extends PageController | ||
{ | ||
private static $url_handlers = [ | ||
// Route all requests for this page, including sub-URLs, to the index action. | ||
// The frontend components should take care of handling sub-URL routing from here. | ||
'view/$Item' => 'index', | ||
]; | ||
|
||
/** | ||
* Loads model data encapsulated as JSON in order to power front end technologies used to render that | ||
* data. Includes critical info such as the CKAN site to query (e.g. which domain, datastore, etc.) | ||
* but also can be extended to be used for configuring the component used to show this (e.g. React.js | ||
* or Vue.js component configuration). | ||
* | ||
* @param DataObject $holder | ||
* @return array | ||
*/ | ||
public function getCKANClientConfig(DataObject $holder = null) | ||
{ | ||
if (!$holder) { | ||
$holder = $this->data(); | ||
} | ||
|
||
/** @var Resource $resource */ | ||
$resource = $holder->getComponent('DataResource'); | ||
|
||
$config = [ | ||
'spec' => [ | ||
'endpoint' => $resource->Endpoint, | ||
'dataset' => $resource->DataSet, | ||
'identifier' => $resource->Identifier, | ||
], | ||
'name' => $resource->Name, | ||
'resourceName' => $resource->ResourceName, | ||
'basePath' => $this->getBasePath($holder), | ||
]; | ||
|
||
$this->extend('updateCKANClientConfig', $config); | ||
|
||
return $config; | ||
} | ||
|
||
/** | ||
* Returns the base path for the resource's page with a leading slash | ||
* | ||
* @param DataObject $holder | ||
* @return string | ||
*/ | ||
public function getBasePath(DataObject $holder = null) | ||
{ | ||
if (!$holder) { | ||
return '/'; | ||
} | ||
|
||
$link = $holder->RelativeLink(); | ||
return '/' . trim($link, '/'); | ||
} | ||
} |
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,5 @@ | ||
<% require javascript('silverstripe/admin: client/dist/js/i18n.js') %> | ||
<% require javascript('silverstripe/ckan-registry: client/lang') %> | ||
<% require javascript('silverstripe/ckan-registry: client/dist/js/bundle.js') %> | ||
<div class="ckan-registry" data-configuration="$CKANClientConfig"> | ||
<div class="ckan-registry-holder" data-configuration="$Record.CKANClientConfig.JSON"> | ||
</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
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.