Continued porting to react, approaching beta

This commit is contained in:
Colin McLeod
2016-01-21 22:06:05 -08:00
parent 653cb30dd9
commit 8227a4e361
86 changed files with 3810 additions and 2030 deletions

View File

@@ -7,7 +7,6 @@ import ActiveLink from './ActiveLink';
import cn from 'classnames';
import { Cogs, CoriolisLogo, Hammer, Rocket, StatsBars } from './SvgIcons';
import { Ships } from 'coriolis-data';
import InterfaceEvents from '../utils/InterfaceEvents';
import Persist from '../stores/Persist';
import { toDetailedExport } from '../shipyard/Serializer';
import ModalDeleteAll from './ModalDeleteAll';
@@ -18,8 +17,16 @@ import Slider from './Slider';
const SIZE_MIN = 0.65;
const SIZE_RANGE = 0.55;
/**
* Coriolis App Header section / menus
*/
export default class Header extends TranslatedComponent {
/**
* Constructor
* @param {Object} props React Component properties
* @param {Object} context React Component context
*/
constructor(props, context) {
super(props);
this.shipOrder = Object.keys(Ships).sort();
@@ -44,64 +51,114 @@ export default class Header extends TranslatedComponent {
for (let name in Discounts) {
this.discountOptions.push(<option key={name} value={Discounts[name]}>{name}</option>);
}
}
/**
* Update insurance level
* @param {SyntheticEvent} e Event
*/
_setInsurance(e) {
Persist.setInsurance(e.target.value);
}
/**
* Update the Module discount
* @param {SyntheticEvent} e Event
*/
_setModuleDiscount(e) {
Persist.setModuleDiscount(e.target.value * 1);
}
/**
* Update the Ship discount
* @param {SyntheticEvent} e Event
*/
_setShipDiscount(e) {
Persist.setShipDiscount(e.target.value * 1);
}
_setLanguage(e){
/**
* Update the current language
* @param {SyntheticEvent} e Event
*/
_setLanguage(e) {
Persist.setLangCode(e.target.value);
}
/**
* Toggle tooltips setting
*/
_toggleTooltips() {
Persist.showTooltips(!Persist.showTooltips());
}
/**
* Show delete all modal
* @param {SyntheticEvent} e Event
*/
_showDeleteAll(e) {
e.preventDefault();
InterfaceEvents.showModal(<ModalDeleteAll />);
this.context.showModal(<ModalDeleteAll />);
};
/**
* Show export modal with backup data
* @param {SyntheticEvent} e Event
*/
_showBackup(e) {
let translate = this.context.language.translate;
e.preventDefault();
InterfaceEvents.showModal(<ModalExport
this.context.showModal(<ModalExport
title={translate('backup')}
description={translate('PHRASE_BACKUP_DESC')}
data={Persist.getAll()}
/>);
};
_showDetailedExport(e){
/**
* Show export modal with detailed export
* @param {SyntheticEvent} e Event
*/
_showDetailedExport(e) {
let translate = this.context.language.translate;
e.preventDefault();
InterfaceEvents.showModal(<ModalExport
this.context.showModal(<ModalExport
title={translate('detailed export')}
description={translate('PHRASE_EXPORT_DESC')}
data={toDetailedExport(Persist.getBuilds())}
/>);
}
/**
* Show import modal
* @param {SyntheticEvent} e Event
*/
_showImport(e) {
e.preventDefault();
InterfaceEvents.showModal(<ModalImport/>);
this.context.showModal(<ModalImport/>);
}
_setTextSize(size) {
Persist.setSizeRatio((size * SIZE_RANGE) + SIZE_MIN);
/**
* Update the app scale / size ratio
* @param {number} scale scale Size Ratio
*/
_setTextSize(scale) {
Persist.setSizeRatio((scale * SIZE_RANGE) + SIZE_MIN);
}
/**
* Reset the app scale / size ratio
*/
_resetTextSize() {
Persist.setSizeRatio(1);
}
/**
* Open a menu
* @param {SyntheticEvent} event Event
* @param {string} menu Menu name
*/
_openMenu(event, menu) {
event.stopPropagation();
@@ -109,23 +166,31 @@ export default class Header extends TranslatedComponent {
menu = null;
}
InterfaceEvents.openMenu(menu);
this.context.openMenu(menu);
}
/**
* Generate the ships menu
* @return {React.Component} Menu
*/
_getShipsMenu() {
let shipList = [];
for (let s in Ships) {
shipList.push(<ActiveLink key={s} href={'/outfit/' + s} className={'block'}>{Ships[s].properties.name}</ActiveLink>);
shipList.push(<ActiveLink key={s} href={'/outfit/' + s} className='block'>{Ships[s].properties.name}</ActiveLink>);
}
return (
<div className={'menu-list dbl no-wrap'} onClick={ (e) => e.stopPropagation() }>
<div className='menu-list dbl no-wrap' onClick={ (e) => e.stopPropagation() }>
{shipList}
</div>
);
}
/**
* Generate the builds menu
* @return {React.Component} Menu
*/
_getBuildsMenu() {
let builds = Persist.getBuilds();
let buildList = [];
@@ -135,19 +200,23 @@ export default class Header extends TranslatedComponent {
let buildNameOrder = Object.keys(builds[shipId]).sort();
for (let buildName of buildNameOrder) {
let href = ['/outfit/', shipId, '/', builds[shipId][buildName], '?bn=', buildName].join('');
shipBuilds.push(<li key={shipId + '-' + buildName} ><ActiveLink href={href} className={'block'}>{buildName}</ActiveLink></li>);
shipBuilds.push(<li key={shipId + '-' + buildName} ><ActiveLink href={href} className='block'>{buildName}</ActiveLink></li>);
}
buildList.push(<ul key={shipId}>{Ships[shipId].properties.name}{shipBuilds}</ul>);
}
}
return (
<div className={'menu-list'} onClick={ (e) => e.stopPropagation() }>
<div className={'dbl'}>{buildList}</div>
<div className='menu-list' onClick={ (e) => e.stopPropagation() }>
<div className='dbl'>{buildList}</div>
</div>
);
}
/**
* Generate the comparison menu
* @return {React.Component} Menu
*/
_getComparisonsMenu() {
let comparisons;
let translate = this.context.language.translate;
@@ -157,69 +226,68 @@ export default class Header extends TranslatedComponent {
let comps = Object.keys(Persist.getComparisons()).sort();
for (let name of comps) {
comparisons.push(<ActiveLink key={name} href={'/compare/' + name} className={'block name'}>{name}</ActiveLink>);
comparisons.push(<ActiveLink key={name} href={'/compare/' + name} className='block name'>{name}</ActiveLink>);
}
} else {
comparisons = <span className={'cap'}>{translate('none created')}</span>;
comparisons = <span className='cap'>{translate('none created')}</span>;
}
return (
<div className={'menu-list'} onClick={ (e) => e.stopPropagation() } style={{ whiteSpace: 'nowrap' }}>
<div className='menu-list' onClick={ (e) => e.stopPropagation() } style={{ whiteSpace: 'nowrap' }}>
{comparisons}
<hr />
<Link href='/compare/all' ui-sref="compare({name: 'all'})" className={'block cap'}>{translate('compare all')}</Link>
<Link href='/compare' className={'block cap'}>{translate('create new')}</Link>
<Link href='/compare/all' ui-sref="compare({name: 'all'})" className='block cap'>{translate('compare all')}</Link>
<Link href='/compare' className='block cap'>{translate('create new')}</Link>
</div>
);
}
/**
* Generate the settings menu
* @return {React.Component} Menu
*/
_getSettingsMenu() {
let translate = this.context.language.translate;
let tips = Persist.showTooltips();
return (
<div className={'menu-list no-wrap cap'} onClick={ (e) => e.stopPropagation() }>
<ul>
{translate('language')}
<li>
<select className={'cap'} value={Persist.getLangCode()} onChange={this._setLanguage}>
{this.languageOptions}
</select>
</li>
</ul><br/>
<ul>
{translate('insurance')}
<li>
<select className={'cap'} value={Persist.getInsurance()} onChange={this._setInsurance}>
{this.insuranceOptions}
</select>
</li>
</ul><br/>
<ul>
{translate('ship')} {translate('discount')}
<li>
<select className={'cap'} value={Persist.getShipDiscount()} onChange={this._setShipDiscount}>
{this.discountOptions}
</select>
</li>
</ul><br/>
<ul>
{translate('module')} {translate('discount')}
<li>
<select className={'cap'} value={Persist.getModuleDiscount()} onChange={this._setModuleDiscount} >
{this.discountOptions}
</select>
</li>
</ul>
<div className='menu-list no-wrap cap' onClick={ (e) => e.stopPropagation() }>
<div style={{ lineHeight: '2em' }}>
{translate('language')}
<select className='cap' value={Persist.getLangCode()} onChange={this._setLanguage}>
{this.languageOptions}
</select>
<br/>
<span className='cap ptr' onClick={this._toggleTooltips} >
{translate('tooltips')}
<div className={cn({ disabled: !tips, 'primary-disabled': tips })} style={{ marginLeft: '0.5em', display: 'inline-block' }}>{(tips ? '✔' : '✖')}</div>
</span>
<br/>
{translate('insurance')}
<select className='cap' value={Persist.getInsurance()} onChange={this._setInsurance}>
{this.insuranceOptions}
</select>
<br/>
{translate('ship')} {translate('discount')}
<select className='cap' value={Persist.getShipDiscount()} onChange={this._setShipDiscount}>
{this.discountOptions}
</select>
<br/>
{translate('module')} {translate('discount')}
<select className='cap' value={Persist.getModuleDiscount()} onChange={this._setModuleDiscount} >
{this.discountOptions}
</select>
</div>
<hr />
<ul>
{translate('builds')} & {translate('comparisons')}
<li><a href="#" className={'block'} onClick={this._showBackup.bind(this)}>{translate('backup')}</a></li>
<li><a href="#" className={'block'} onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</a></li>
<li><a href="#" className={'block'} onClick={this._showImport.bind(this)}>{translate('import')}</a></li>
<li><a href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</a></li>
<li><a href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</a></li>
<li><a href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</a></li>
<li><a href="#" onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</a></li>
</ul>
<hr />
<table style={{width: 300, backgroundColor: 'transparent'}}>
<table style={{ width: 300, backgroundColor: 'transparent' }}>
<tbody>
<tr>
<td style={{ width: '1em', verticalAlign: 'top' }}><u>A</u></td>
@@ -227,22 +295,34 @@ export default class Header extends TranslatedComponent {
<td style={{ width: 20 }}><span style={{ fontSize: 30 }}>A</span></td>
</tr>
<tr>
<td colSpan='3' style={{ textAlign: 'center', cursor: 'pointer' }} className={'primary-disabled cap'} onClick={this._resetTextSize.bind(this)}>{translate('reset')}</td>
<td colSpan='3' style={{ textAlign: 'center', cursor: 'pointer' }} className='primary-disabled cap' onClick={this._resetTextSize.bind(this)}>{translate('reset')}</td>
</tr>
</tbody>
</table>
<hr />
<Link href="/about" className={'block'}>{translate('about')}</Link>
<Link href="/about" className='block'>{translate('about')}</Link>
</div>
);
}
componentWillMount(){
/**
* Add listeners on mount
*/
componentWillMount() {
Persist.addListener('language', () => this.forceUpdate());
Persist.addListener('insurance', () => this.forceUpdate());
Persist.addListener('discounts', () => this.forceUpdate());
Persist.addListener('deletedAll', () => this.forceUpdate());
Persist.addListener('buildSaved', () => this.forceUpdate());
Persist.addListener('buildDeleted', () => this.forceUpdate());
Persist.addListener('tooltips', () => this.forceUpdate());
}
/**
* Update state based on property and context changes
* @param {Object} nextProps Incoming/Next properties
* @param {Object} nextContext Incoming/Next conext
*/
componentWillReceiveProps(nextProps, nextContext) {
if(this.context.language != nextContext.language) {
let translate = nextContext.language.translate;
@@ -253,6 +333,10 @@ export default class Header extends TranslatedComponent {
}
}
/**
* Render the header
* @return {React.Component} Header
*/
render() {
let translate = this.context.language.translate;
let openedMenu = this.props.currentMenu;
@@ -264,32 +348,32 @@ export default class Header extends TranslatedComponent {
return (
<header>
<Link className={'l'} href="/" style={{marginRight: '1em'}} title="Home"><CoriolisLogo className={'icon xl'} /></Link>
<Link className='l' href="/" style={{ marginRight: '1em' }} title="Home"><CoriolisLogo className='icon xl' /></Link>
<div className={'l menu'}>
<div className={cn('menu-header', {selected: openedMenu == 's'})} onClick={ (e) => this._openMenu(e,'s') } >
<Rocket className={'warning'} /><span className={'menu-item-label'}>{' ' + translate('ships')}</span>
<div className='l menu'>
<div className={cn('menu-header', { selected: openedMenu == 's' })} onClick={ (e) => this._openMenu(e,'s') } >
<Rocket className='warning' /><span className='menu-item-label'>{' ' + translate('ships')}</span>
</div>
{openedMenu == 's' ? this._getShipsMenu() : null}
</div>
<div className={'l menu'}>
<div className={cn('menu-header', {selected: openedMenu == 'b', disabled: !hasBuilds})} onClick={ hasBuilds ? (e) => this._openMenu(e,'b') : null }>
<Hammer className={cn('warning', { 'warning-disabled': !hasBuilds})} /><span className={'menu-item-label'}>{' ' + translate('builds')}</span>
<div className='l menu'>
<div className={cn('menu-header', { selected: openedMenu == 'b', disabled: !hasBuilds })} onClick={ hasBuilds ? (e) => this._openMenu(e,'b') : null }>
<Hammer className={cn('warning', { 'warning-disabled': !hasBuilds })} /><span className='menu-item-label'>{' ' + translate('builds')}</span>
</div>
{openedMenu == 'b' ? this._getBuildsMenu() : null}
</div>
<div className={'l menu'}>
<div className={cn('menu-header', {selected: openedMenu == 'comp', disabled: !hasBuilds})} onClick={ hasBuilds ? (e) => this._openMenu(e,'comp') : null }>
<StatsBars className={cn('warning', { 'warning-disabled': !hasBuilds})} /><span className={'menu-item-label'}>{' ' + translate('compare')}</span>
<div className='l menu'>
<div className={cn('menu-header', { selected: openedMenu == 'comp', disabled: !hasBuilds })} onClick={ hasBuilds ? (e) => this._openMenu(e,'comp') : null }>
<StatsBars className={cn('warning', { 'warning-disabled': !hasBuilds })} /><span className='menu-item-label'>{' ' + translate('compare')}</span>
</div>
{openedMenu == 'comp' ? this._getComparisonsMenu() : null}
</div>
<div className={'r menu'}>
<div className={cn('menu-header', {selected: openedMenu == 'settings'})}onClick={ (e) => this._openMenu(e,'settings') }>
<Cogs className={'xl warning'}/><span className={'menu-item-label'}>{translate('settings')}</span>
<div className='r menu'>
<div className={cn('menu-header', { selected: openedMenu == 'settings' })}onClick={ (e) => this._openMenu(e,'settings') }>
<Cogs className='xl warning'/><span className='menu-item-label'>{translate('settings')}</span>
</div>
{openedMenu == 'settings' ? this._getSettingsMenu() : null}
</div>