Skip to content
This repository has been archived by the owner on Apr 7, 2023. It is now read-only.

Commit

Permalink
Continued porting to React
Browse files Browse the repository at this point in the history
  • Loading branch information
Colin McLeod committed Jan 12, 2016
1 parent ab00194 commit 653cb30
Show file tree
Hide file tree
Showing 39 changed files with 1,856 additions and 1,411 deletions.
49 changes: 42 additions & 7 deletions src/app/Coriolis.jsx
Expand Up @@ -8,13 +8,15 @@ import Header from './components/Header';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';
import OutfittingPage from './pages/OutfittingPage';
import ComparisonPage from './pages/ComparisonPage';
import ShipyardPage from './pages/ShipyardPage';

export default class Coriolis extends React.Component {

static childContextTypes = {
language: React.PropTypes.object.isRequired,
route: React.PropTypes.object
sizeRatio: React.PropTypes.number.isRequired,
route: React.PropTypes.object.isRequired
};

constructor() {
Expand All @@ -24,19 +26,21 @@ export default class Coriolis extends React.Component {
this._closeMenu = this._closeMenu.bind(this);
this._showModal = this._showModal.bind(this);
this._hideModal = this._hideModal.bind(this);
this._onLanguageChange = this._onLanguageChange.bind(this)
this._onLanguageChange = this._onLanguageChange.bind(this);
this._onSizeRatioChange = this._onSizeRatioChange.bind(this)
this._keyDown = this._keyDown.bind(this);

this.state = {
page: null,
language: getLanguage(Persist.getLangCode()),
route: null
route: null,
sizeRatio: Persist.getSizeRatio()
};

Router('', (r) => this._setPage(ShipyardPage, r));
Router('/outfit/:ship/:code?', (r) => this._setPage(OutfittingPage, r));
// Router('/compare/:name', compare);
// Router('/comparison/:code', comparison);
Router('/compare/:name?', (r) => this._setPage(ComparisonPage, r));
Router('/comparison/:code', (r) => this._setPage(ComparisonPage, r));
Router('/about', (r) => this._setPage(AboutPage, r));
Router('*', (r) => this._setPage(null, r));
}
Expand All @@ -54,6 +58,10 @@ export default class Coriolis extends React.Component {
this.setState({ language: getLanguage(Persist.getLangCode()) });
}

_onSizeRatioChange(sizeRatio) {
this.setState({ sizeRatio });
}

_keyDown(e) {
switch (e.keyCode) {
case 27:
Expand All @@ -63,36 +71,59 @@ export default class Coriolis extends React.Component {
}
}

/**
* Opens the modal display with the specified content
* @param {React.Component} content Modal Content
*/
_showModal(content) {
let modal = <div className='modal-bg' onClick={(e) => this._hideModal() }>{content}</div>;
this.setState({ modal });
}

/**
* Hides any open modal
*/
_hideModal() {
if (this.state.modal) {
this.setState({ modal: null });
}
}

/**
* Sets the open menu state
* @param {string|object} currentMenu The reference to the current menu
*/
_openMenu(currentMenu) {
if (this.state.currentMenu != currentMenu) {
this.setState({ currentMenu });
}
}

/**
* Closes the open menu
*/
_closeMenu() {
if (this.state.currentMenu) {
this.setState({ currentMenu: null });
}
}

/**
* Creates the context to be passed down to pages / components containing
* language, sizeRatio and route references
* @return {object} Context to be passed down
*/
getChildContext() {
return {
language: this.state.language,
route: this.state.route
route: this.state.route,
sizeRatio: this.state.sizeRatio
};
}

/**
* Adds necessary listeners and starts Routing
*/
componentWillMount() {
// Listen for appcache updated event, present refresh to update view
if (window.applicationCache) {
Expand All @@ -107,7 +138,7 @@ export default class Coriolis extends React.Component {
window.addEventListener('resize', InterfaceEvents.windowResized);
document.addEventListener('keydown', this._keyDown);
Persist.addListener('language', this._onLanguageChange);
Persist.addListener('language', this._onLanguageChange);
Persist.addListener('sizeRatio', this._onSizeRatioChange);
InterfaceEvents.addListener('openMenu', this._openMenu);
InterfaceEvents.addListener('closeMenu', this._closeMenu);
InterfaceEvents.addListener('showModal', this._showModal);
Expand All @@ -116,6 +147,10 @@ export default class Coriolis extends React.Component {
Router.start();
}

/**
* Renders the main app
* @return {React.Component} The main app
*/
render() {
return (
<div onClick={this._closeMenu}>
Expand Down
102 changes: 102 additions & 0 deletions src/app/components/ComparisonTable.jsx
@@ -0,0 +1,102 @@
import React from 'react';
import TranslatedComponent from './TranslatedComponent';
import Link from './Link';
import cn from 'classnames';
import { SizeMap } from '../shipyard/Constants';


export default class ComparisonTable extends TranslatedComponent {

static propTypes = {
facets: React.PropTypes.array.isRequired,
builds: React.PropTypes.array.isRequired,
onSort: React.PropTypes.func.isRequired,
predicate: React.PropTypes.string.isRequired, // Used only to test again prop changes for shouldRender
desc: React.PropTypes.bool.isRequired, // Used only to test again prop changes for shouldRender
}

constructor(props, context) {
super(props, context);
this._buildHeaders = this._buildHeaders.bind(this);

this.state = this._buildHeaders(props.facets, props.onSort, context.language.translate);
}

_buildHeaders(facets, onSort, translate) {
let header = [
<th key='ship' rowSpan='2' className='sortable' onClick={onSort.bind(null, 'name')}>{translate('ship')}</th>,
<th key='build' rowSpan='2' className='sortable' onClick={onSort.bind(null, 'buildName')}>{translate('build')}</th>
];
let subHeader = [];

for (let f of facets) {
if (f.active) {
let p = f.props;
let pl = p.length;
header.push(<th key={f.title} rowSpan={pl === 1 ? 2 : 1} colSpan={pl} className={cn({ sortable: pl === 1 })} onClick={pl === 1 ? onSort.bind(null, p[0]) : null }>
{translate(f.title)}
</th>);

if (pl > 1) {
for (let i = 0; i < pl; i++) {
subHeader.push(<th key={p[i]} className={cn('sortable', { lft: i === 0 } )} onClick={onSort.bind(null, p[i])} >{translate(f.lbls[i])}</th>);
}
}
}
}

return { header, subHeader };
}

_buildRow(build, facets, formats, units) {
let url = `/outfit/${build.id}/${build.toString()}?bn=${build.buildName}`;
let cells = [
<td key='s' className='tl'><Link href={url}>{build.name}</Link></td>,
<td key='bn' className='tl'><Link href={url}>{build.buildName}</Link></td>
];

for (let f of facets) {
if (f.active) {
for (let p of f.props) {
cells.push(<td key={p}>{formats[f.fmt](build[p])}{f.unit ? units[f.unit] : null}</td>);
}
}
}

return <tr key={build.id + build.buildName} className='tr'>{cells}</tr>;
}

componentWillReceiveProps(nextProps, nextContext) {
// If facets or language has changed re-render header
if (nextProps.facets != this.props.facets || nextContext.language != this.context.language) {
this.setState(this._buildHeaders(nextProps.facets, nextProps.onSort, nextContext.language.translate));
}
}

render() {
let { builds, facets } = this.props;
let { header, subHeader } = this.state;
let { formats, units } = this.context.language;

let buildsRows = new Array(builds.length);

for (let i = 0, l = buildsRows.length; i < l; i++) {
buildsRows[i] = this._buildRow(builds[i], facets, formats, units);
}

return (
<div className='scroll-x'>
<table id='comp-tbl'>
<thead>
<tr className='main'>{header}</tr>
<tr>{subHeader}</tr>
</thead>
<tbody>
{buildsRows}
</tbody>
</table>
</div>
);

}
}

0 comments on commit 653cb30

Please sign in to comment.