mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-10 15:15:34 +00:00
2.0.1 Beta
This commit is contained in:
@@ -9,7 +9,7 @@ import cn from 'classnames';
|
||||
* @return {boolean} If matches
|
||||
*/
|
||||
function isActive(href) {
|
||||
return encodeURI(href) == (window.location.pathname + window.location.search);
|
||||
return href == (window.location.pathname + window.location.search);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -22,13 +22,12 @@ export default class ActiveLink extends Link {
|
||||
* @return {React.Component} The active link
|
||||
*/
|
||||
render() {
|
||||
let action = this.handler.bind(this);
|
||||
let className = this.props.className;
|
||||
if (isActive(this.props.href)) {
|
||||
className = cn(className, 'active');
|
||||
}
|
||||
|
||||
return <a {...this.props} className={className} onTouchTap={action}>{this.props.children}</a>;
|
||||
return <a {...this.props} className={className} onClick={this.handler}>{this.props.children}</a>;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { stopCtxPropagation } from '../utils/UtilityFunctions';
|
||||
import cn from 'classnames';
|
||||
import { MountFixed, MountGimballed, MountTurret } from './SvgIcons';
|
||||
|
||||
const PRESS_THRESHOLD = 5000; // mouse/touch down threshold
|
||||
|
||||
/**
|
||||
* Available modules menu
|
||||
*/
|
||||
@@ -31,20 +33,19 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
this._hideDiff = this._hideDiff.bind(this);
|
||||
this._diffMove = this._diffMove.bind(this);
|
||||
this.state = { list: this._initList(props, context) };
|
||||
this.state = this._initState(props, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the list of available moduels
|
||||
* @param {Object} props React Component properties
|
||||
* @param {Object} context React Component context
|
||||
* @return {Array} Array of React Components
|
||||
* @return {Object} list: Array of React Components, currentGroup Component if any
|
||||
*/
|
||||
_initList(props, context) {
|
||||
_initState(props, context) {
|
||||
let translate = context.language.translate;
|
||||
let { m, warning, shipMass, onSelect, modules } = props;
|
||||
let list;
|
||||
let list, currentGroup;
|
||||
let buildGroup = this._buildGroup.bind(
|
||||
this,
|
||||
translate,
|
||||
@@ -62,14 +63,19 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
} else {
|
||||
list = [];
|
||||
// At present time slots with grouped options (Hardpoints and Internal) can be empty
|
||||
list.push(<div className={'empty-c upp'} key={'empty'} onClick={onSelect.bind(null, null)} >{translate('empty')}</div>);
|
||||
list.push(<div className='empty-c upp' key='empty' onClick={onSelect.bind(null, null)} >{translate('empty')}</div>);
|
||||
for (let g in modules) {
|
||||
list.push(<div ref={g} key={g} className={'select-group cap'}>{translate(g)}</div>);
|
||||
if (m && g == m.grp) {
|
||||
list.push(<div ref={(elem) => this.groupElem = elem} key={g} className={'select-group cap'}>{translate(g)}</div>);
|
||||
} else {
|
||||
list.push(<div key={g} className={'select-group cap'}>{translate(g)}</div>);
|
||||
}
|
||||
|
||||
list.push(buildGroup(g, modules[g]));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
return { list, currentGroup };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +103,22 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
active,
|
||||
disabled
|
||||
});
|
||||
let eventHandlers;
|
||||
|
||||
if (disabled || active) {
|
||||
eventHandlers = {};
|
||||
} else {
|
||||
let showDiff = this._showDiff.bind(this, mountedModule, m);
|
||||
let select = onSelect.bind(null, m);
|
||||
|
||||
eventHandlers = {
|
||||
onMouseEnter: this._over.bind(this, showDiff),
|
||||
onTouchStart: this._touchStart.bind(this, showDiff),
|
||||
onTouchEnd: this._touchEnd.bind(this, select),
|
||||
onMouseLeave: this._hideDiff,
|
||||
onClick: select
|
||||
};
|
||||
}
|
||||
|
||||
switch(m.mount) {
|
||||
case 'F': mount = <MountFixed className={'lg'} />; break;
|
||||
@@ -108,19 +130,10 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
elems.push(<br key={m.grp + i} />);
|
||||
}
|
||||
|
||||
let showDiff = disabled || active ? null : this._showDiff.bind(this, mountedModule, m);
|
||||
|
||||
elems.push(
|
||||
<li
|
||||
key={m.id}
|
||||
className={classes}
|
||||
onMouseEnter={showDiff}
|
||||
onTouchStart={showDiff}
|
||||
onMouseLeave={this._hideDiff}
|
||||
onClick={disabled ? null : onSelect.bind(null, m)}
|
||||
>
|
||||
<li key={m.id} className={classes} {...eventHandlers}>
|
||||
{mount}
|
||||
<span>{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}</span>
|
||||
{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}
|
||||
</li>
|
||||
);
|
||||
prevClass = m.class;
|
||||
@@ -135,22 +148,46 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
* mounted module and the hovered modules
|
||||
* @param {Object} mm The module mounet currently
|
||||
* @param {Object} m The hovered module
|
||||
* @param {SyntheticEvent} event Event
|
||||
* @param {DOMRect} rect DOMRect for target element
|
||||
*/
|
||||
_showDiff(mm, m, event) {
|
||||
event.preventDefault();
|
||||
_showDiff(mm, m, rect) {
|
||||
if (this.props.diffDetails) {
|
||||
this.context.tooltip(this.props.diffDetails(m, mm), event.currentTarget.getBoundingClientRect());
|
||||
this.touchTimeout = null;
|
||||
this.context.tooltip(this.props.diffDetails(m, mm), rect);
|
||||
}
|
||||
}
|
||||
|
||||
_touchStart(event) {
|
||||
/**
|
||||
* Mouse over diff handler
|
||||
* @param {Function} showDiff diff tooltip callback
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
_over(showDiff, event) {
|
||||
event.preventDefault();
|
||||
console.log(Object.assign({}, event));
|
||||
showDiff(event.currentTarget.getBoundingClientRect());
|
||||
}
|
||||
|
||||
_diffMove(event) {
|
||||
console.log(Object.assign({}, event));
|
||||
/**
|
||||
* Toucch Start - Show diff after press, otherwise treat as tap
|
||||
* @param {Function} showDiff diff tooltip callback
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
_touchStart(showDiff, event) {
|
||||
let rect = event.currentTarget.getBoundingClientRect();
|
||||
this.touchTimeout = setTimeout(showDiff.bind(this, rect), PRESS_THRESHOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Touch End - Select module on tap
|
||||
* @param {Function} select Select module callback
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
_touchEnd(select, event) {
|
||||
if (this.touchTimeout !== null) { // If timeout has not fired (been nulled out) yet
|
||||
select();
|
||||
}
|
||||
event.preventDefault();
|
||||
this._hideDiff();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,18 +195,17 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
_hideDiff(event) {
|
||||
event.preventDefault();
|
||||
clearTimeout(this.touchTimeout);
|
||||
this.touchTimeout = null;
|
||||
this.context.tooltip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to mounted (if it exists) component on mount
|
||||
* Scroll to mounted (if it exists) module group on mount
|
||||
*/
|
||||
componentDidMount() {
|
||||
let m = this.props.m;
|
||||
|
||||
if (!(this.props.modules instanceof Array) && m && m.grp) {
|
||||
findDOMNode(this).scrollTop = this.refs[m.grp].offsetTop; // Scroll to currently selected group
|
||||
if (this.groupElem) { // Scroll to currently selected group
|
||||
findDOMNode(this).scrollTop = this.groupElem.offsetTop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +215,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
* @param {Object} nextContext Incoming/Next conext
|
||||
*/
|
||||
componentWillReceiveProps(nextProps, nextContext) {
|
||||
this.setState({ list: this._initList(nextProps, nextContext) });
|
||||
this.setState(this._initState(nextProps, nextContext));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,9 +228,6 @@ export default class AvailableModulesMenu extends TranslatedComponent {
|
||||
className={cn('select', this.props.className)}
|
||||
onScroll={this._hideDiff}
|
||||
onClick={(e) => e.stopPropagation() }
|
||||
onTouchStart={this._touchStart}
|
||||
onTouchEnd={this._hideDiff}
|
||||
onTouchCancel={this._hideDiff}
|
||||
onContextMenu={stopCtxPropagation}
|
||||
>
|
||||
{this.state.list}
|
||||
|
||||
@@ -40,18 +40,21 @@ export default class BarChart extends TranslatedComponent {
|
||||
|
||||
static defaultProps = {
|
||||
colors: ['#7b6888', '#6b486b', '#3182bd', '#a05d56', '#d0743c'],
|
||||
labels: null,
|
||||
unit: ''
|
||||
};
|
||||
|
||||
static PropTypes = {
|
||||
data: React.PropTypes.array.isRequired,
|
||||
width: React.PropTypes.number.isRequired,
|
||||
format: React.PropTypes.string.isRequired,
|
||||
label: React.PropTypes.string.isRequired,
|
||||
unit: React.PropTypes.string.isRequired,
|
||||
colors: React.PropTypes.array,
|
||||
data: React.PropTypes.array.isRequired,
|
||||
desc: React.PropTypes.bool,
|
||||
format: React.PropTypes.string.isRequired,
|
||||
labels: React.PropTypes.array,
|
||||
predicate: React.PropTypes.string,
|
||||
desc: React.PropTypes.bool
|
||||
properties: React.PropTypes.array,
|
||||
title: React.PropTypes.string.isRequired,
|
||||
unit: React.PropTypes.string.isRequired,
|
||||
width: React.PropTypes.number.isRequired
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,25 +79,30 @@ export default class BarChart extends TranslatedComponent {
|
||||
|
||||
/**
|
||||
* Generate and Show tooltip
|
||||
* @param {Object} build Ship build
|
||||
* @param {string} property Property to display
|
||||
* @param {Object} build Ship build
|
||||
* @param {string} property Property to display
|
||||
* @param {number} propertyIndex Property Label index
|
||||
*/
|
||||
_showTip(build, property) {
|
||||
let { unit, format } = this.props;
|
||||
_showTip(build, property, propertyIndex) {
|
||||
let { unit, format, labels } = this.props;
|
||||
let { scale, y0, y1 } = this.state;
|
||||
let { formats } = this.context.language;
|
||||
let { translate, formats } = this.context.language;
|
||||
let fontSize = parseFloat(window.getComputedStyle(document.getElementById('coriolis')).getPropertyValue('font-size') || 16);
|
||||
let val = build[property];
|
||||
let lblStr = labels ? translate(labels[propertyIndex]) + ': ' : '';
|
||||
let valStr = formats[format](val) + ' ' + unit;
|
||||
let width = (valStr.length / 1.7) * fontSize;
|
||||
let midPoint = width / 2;
|
||||
let valMidPoint = scale(val) / 2;
|
||||
let y = y0(bName(build)) + y1(property) - fontSize - 5;
|
||||
let width = ((lblStr.length + valStr.length) / 1.8) * fontSize;
|
||||
let midPoint = width / 2;
|
||||
|
||||
let tooltip = <g>
|
||||
<g transform={`translate(${Math.max(0, valMidPoint - midPoint)},${y})`}>
|
||||
<rect className='primary-disabled' height={fontSize} width={width} />
|
||||
<text x={midPoint} y={fontSize} dy='-0.4em' style={{ textAnchor: 'middle', fontSize: '0.7em' }}>{valStr}</text>
|
||||
<text x={midPoint} y={fontSize} dy={fontSize / -4} style={{ textAnchor: 'middle', fontSize: '0.7em' }}>
|
||||
<tspan style={{ textTransform: 'capitalize' }}>{lblStr}</tspan>
|
||||
<tspan>{valStr}</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<path className='primary-disabled' d='M0,0L5,5L10,0Z' dy='1em' transform={`translate(${Math.max(0, valMidPoint - 5)},${y + fontSize})`} />
|
||||
</g>;
|
||||
@@ -173,12 +181,12 @@ export default class BarChart extends TranslatedComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
let { label, unit, width, data, properties } = this.props;
|
||||
let { title, unit, width, data, properties } = this.props;
|
||||
let { innerWidth, outerHeight, innerHeight, y0, y1, scale, color, tooltip } = this.state;
|
||||
|
||||
let bars = data.map((build, i) =>
|
||||
<g key={i} transform={`translate(0,${y0(bName(build))})`}>
|
||||
{ properties.map((p) =>
|
||||
{ properties.map((p, propIndex) =>
|
||||
<rect
|
||||
key={p}
|
||||
x={0}
|
||||
@@ -186,7 +194,7 @@ export default class BarChart extends TranslatedComponent {
|
||||
width={scale(build[p])}
|
||||
height={y1.rangeBand()}
|
||||
fill={color(p)}
|
||||
onMouseOver={this._showTip.bind(this, build, p)}
|
||||
onMouseOver={this._showTip.bind(this, build, p, propIndex)}
|
||||
onMouseOut={this._hideTip}
|
||||
/>
|
||||
)}
|
||||
@@ -199,7 +207,7 @@ export default class BarChart extends TranslatedComponent {
|
||||
{tooltip}
|
||||
<g className='x axis' ref={(elem) => d3.select(elem).call(this.xAxis)} transform={`translate(0,${innerHeight})`}>
|
||||
<text className='cap' y='30' dy='.1em' x={innerWidth / 2} style={{ textAnchor: 'middle' }}>
|
||||
<tspan>{label}</tspan>
|
||||
<tspan>{title}</tspan>
|
||||
{ unit ? <tspan className='metric'>{` (${unit})`}</tspan> : null }
|
||||
</text>
|
||||
</g>
|
||||
|
||||
@@ -38,8 +38,8 @@ export default class ComparisonTable extends TranslatedComponent {
|
||||
*/
|
||||
_buildHeaders(facets, onSort, translate) {
|
||||
let header = [
|
||||
<th key='ship' rowSpan='2' className='sortable' onTouchTap={onSort.bind(null, 'name')}>{translate('ship')}</th>,
|
||||
<th key='build' rowSpan='2' className='sortable' onTouchTap={onSort.bind(null, 'buildName')}>{translate('build')}</th>
|
||||
<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 = [];
|
||||
|
||||
@@ -47,13 +47,13 @@ export default class ComparisonTable extends TranslatedComponent {
|
||||
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 })} onTouchTap={pl === 1 ? onSort.bind(null, p[0]) : null }>
|
||||
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 })} onTouchTap={onSort.bind(null, p[i])} >{translate(f.lbls[i])}</th>);
|
||||
subHeader.push(<th key={p[i]} className={cn('sortable', { lft: i === 0 })} onClick={onSort.bind(null, p[i])} >{translate(f.lbls[i])}</th>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { Ships } from 'coriolis-data';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import Persist from '../stores/Persist';
|
||||
import Ship from '../shipyard/Ship';
|
||||
import { Insurance } from '../shipyard/Constants';
|
||||
@@ -46,7 +46,6 @@ export default class CostSection extends TranslatedComponent {
|
||||
retrofitName,
|
||||
shipDiscount,
|
||||
moduleDiscount,
|
||||
total: props.ship.totalCost,
|
||||
insurance: Insurance[Persist.getInsurance()],
|
||||
tab: Persist.getCostTab(),
|
||||
buildOptions: Persist.getBuildsNamesFor(props.ship.id),
|
||||
@@ -108,6 +107,7 @@ export default class CostSection extends TranslatedComponent {
|
||||
let moduleDiscount = Persist.getModuleDiscount();
|
||||
this.props.ship.applyDiscounts(shipDiscount, moduleDiscount);
|
||||
this.state.retrofitShip.applyDiscounts(shipDiscount, moduleDiscount);
|
||||
this._updateRetrofit(this.props.ship, this.state.retrofitShip);
|
||||
this.setState({ shipDiscount, moduleDiscount });
|
||||
}
|
||||
|
||||
@@ -137,32 +137,28 @@ export default class CostSection extends TranslatedComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* On build save
|
||||
* @param {string} shipId Ship Id
|
||||
* @param {string} name Build name
|
||||
* @param {string} code Serialized ship 'code'
|
||||
* On builds changed check to see if the retrofit ship needs
|
||||
* to be updated
|
||||
*/
|
||||
_onBuildSaved(shipId, name, code) {
|
||||
if(this.state.retrofitName == name) {
|
||||
this.state.retrofitShip.buildFrom(code); // Repopulate modules from saved build
|
||||
this._updateRetrofit(this.props.ship, this.state.retrofitShip);
|
||||
} else {
|
||||
this.setState({ buildOptions: Persist.getBuildsNamesFor(this.props.shipId) });
|
||||
}
|
||||
}
|
||||
_onBuildsChanged() {
|
||||
let update = false;
|
||||
let ship = this.props.ship;
|
||||
let { retrofitName, retrofitShip } = this.state;
|
||||
|
||||
/**
|
||||
* On build deleted
|
||||
* @param {string} shipId Ship Id
|
||||
* @param {string} name Build name
|
||||
* @param {string} code Serialized ship 'code'
|
||||
*/
|
||||
_onBuildDeleted(shipId, name, code) {
|
||||
if(this.state.retrofitName == name) {
|
||||
this.state.retrofitShip.buildWith(Ships[shipId].defaults); // Retrofit ship becomes stock build
|
||||
if(!Persist.hasBuild(ship.id, retrofitName)) {
|
||||
retrofitShip.buildWith(Ships[ship.id].defaults); // Retrofit ship becomes stock build
|
||||
this.setState({ retrofitName: null });
|
||||
update = true;
|
||||
} else if (Persist.getBuild(ship.id, retrofitName) != retrofitShip.toString()) {
|
||||
retrofitShip.buildFrom(Persist.getBuild(ship.id, retrofitName)); // Repopulate modules from saved build
|
||||
update = true;
|
||||
}
|
||||
this.setState({ buildOptions: Persist.getBuildsNamesFor(shipId) });
|
||||
|
||||
if (update) { // Update retrofit comparison
|
||||
this._updateRetrofit(ship, retrofitShip);
|
||||
}
|
||||
// Update list of retrofit base build options
|
||||
this.setState({ buildOptions: Persist.getBuildsNamesFor(ship.id) });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +167,7 @@ export default class CostSection extends TranslatedComponent {
|
||||
*/
|
||||
_toggleCost(item) {
|
||||
this.props.ship.setCostIncluded(item, !item.incCost);
|
||||
this.setState({ total: this.props.ship.totalCost });
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +282,7 @@ export default class CostSection extends TranslatedComponent {
|
||||
*/
|
||||
_costsTab() {
|
||||
let { ship } = this.props;
|
||||
let { total, shipDiscount, moduleDiscount, insurance } = this.state;
|
||||
let { shipDiscount, moduleDiscount, insurance } = this.state;
|
||||
let { translate, formats, units } = this.context.language;
|
||||
let rows = [];
|
||||
|
||||
@@ -295,9 +291,9 @@ export default class CostSection extends TranslatedComponent {
|
||||
if (item.m && item.m.cost) {
|
||||
let toggle = this._toggleCost.bind(this, item);
|
||||
rows.push(<tr key={i} className={cn('highlight', { disabled: !item.incCost })}>
|
||||
<td className='ptr' style={{ width: '1em' }} onTouchTap={toggle}>{item.m.class + item.m.rating}</td>
|
||||
<td className='le ptr shorten cap' onTouchTap={toggle}>{slotName(translate, item)}</td>
|
||||
<td className='ri ptr' onTouchTap={toggle}>{formats.int(item.discountedCost)}{units.CR}</td>
|
||||
<td className='ptr' style={{ width: '1em' }} onClick={toggle}>{item.m.class + item.m.rating}</td>
|
||||
<td className='le ptr shorten cap' onClick={toggle}>{slotName(translate, item)}</td>
|
||||
<td className='ri ptr' onClick={toggle}>{formats.int(item.discountedCost)}{units.CR}</td>
|
||||
</tr>);
|
||||
}
|
||||
}
|
||||
@@ -306,23 +302,23 @@ export default class CostSection extends TranslatedComponent {
|
||||
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
|
||||
<thead>
|
||||
<tr className='main'>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={this._sortCostBy.bind(this,'m')}>
|
||||
<th colSpan='2' className='sortable le' onClick={this._sortCostBy.bind(this,'m')}>
|
||||
{translate('component')}
|
||||
{shipDiscount < 1 && <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('ship')} -${formats.pct1(1 - shipDiscount)}]`}</u>}
|
||||
{moduleDiscount < 1 && <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.pct1(1 - moduleDiscount)}]`}</u>}
|
||||
</th>
|
||||
<th className='sortable le' onTouchTap={this._sortCostBy.bind(this, 'cr')} >{translate('credits')}</th>
|
||||
<th className='sortable le' onClick={this._sortCostBy.bind(this, 'cr')} >{translate('credits')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows}
|
||||
<tr className='ri'>
|
||||
<td colSpan='2' className='lbl' >{translate('total')}</td>
|
||||
<td className='val'>{formats.int(total)}{units.CR}</td>
|
||||
<td className='val'>{formats.int(ship.totalCost)}{units.CR}</td>
|
||||
</tr>
|
||||
<tr className='ri'>
|
||||
<td colSpan='2' className='lbl'>{translate('insurance')}</td>
|
||||
<td className='val'>{formats.int(total * insurance)}{units.CR}</td>
|
||||
<td className='val'>{formats.int(ship.totalCost * insurance)}{units.CR}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -346,12 +342,12 @@ export default class CostSection extends TranslatedComponent {
|
||||
if (retrofitCosts.length) {
|
||||
for (let i = 0, l = retrofitCosts.length; i < l; i++) {
|
||||
let item = retrofitCosts[i];
|
||||
rows.push(<tr key={i} className={cn('highlight', { disabled: !item.retroItem.incCost })} onTouchTap={this._toggleRetrofitCost.bind(this, item)}>
|
||||
<td style={{ width: '1em' }}>{item.sellClassRating}</td>
|
||||
<td className='le shorten cap'>{translate(item.sellName)}</td>
|
||||
<td style={{ width: '1em' }}>{item.buyClassRating}</td>
|
||||
<td className='le shorten cap'>{translate(item.buyName)}</td>
|
||||
<td colSpan='2' className={cn('ri', item.retroItem.incCost ? item.netCost > 0 ? 'warning' : 'secondary-disabled' : 'disabled')}>{int(item.netCost)}{units.CR}</td>
|
||||
rows.push(<tr key={i} className={cn('highlight', { disabled: !item.retroItem.incCost })} onClick={this._toggleRetrofitCost.bind(this, item)}>
|
||||
<td className='ptr' style={{ width: '1em' }}>{item.sellClassRating}</td>
|
||||
<td className='le ptr shorten cap'>{translate(item.sellName)}</td>
|
||||
<td className='ptr' style={{ width: '1em' }}>{item.buyClassRating}</td>
|
||||
<td className='le ptr shorten cap'>{translate(item.buyName)}</td>
|
||||
<td colSpan='2' className={cn('ri ptr', item.retroItem.incCost ? item.netCost > 0 ? 'warning' : 'secondary-disabled' : 'disabled')}>{int(item.netCost)}{units.CR}</td>
|
||||
</tr>);
|
||||
}
|
||||
} else {
|
||||
@@ -363,11 +359,11 @@ export default class CostSection extends TranslatedComponent {
|
||||
<table style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr className='main'>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={this._sortRetrofitBy.bind(this, 'sellName')}>{translate('sell')}</th>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={this._sortRetrofitBy.bind(this, 'buyName')}>{translate('buy')}</th>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={this._sortRetrofitBy.bind(this, 'cr')}>
|
||||
<th colSpan='2' className='sortable le' onClick={this._sortRetrofitBy.bind(this, 'sellName')}>{translate('sell')}</th>
|
||||
<th colSpan='2' className='sortable le' onClick={this._sortRetrofitBy.bind(this, 'buyName')}>{translate('buy')}</th>
|
||||
<th colSpan='2' className='sortable le' onClick={this._sortRetrofitBy.bind(this, 'cr')}>
|
||||
{translate('net cost')}
|
||||
{moduleDiscount < 1 && <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.rPct(1 - moduleDiscount)}]`}</u>}
|
||||
{moduleDiscount < 1 && <u className='cap optional-hide' style={{ marginLeft: '0.5em' }}>{`[${translate('modules')} -${formats.pct1(1 - moduleDiscount)}]`}</u>}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -473,10 +469,10 @@ export default class CostSection extends TranslatedComponent {
|
||||
<table style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr className='main'>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={this._sortAmmoBy.bind(this, 'm')} >{translate('module')}</th>
|
||||
<th colSpan='1' className='sortable le' onTouchTap={this._sortAmmoBy.bind(this, 'max')} >{translate('qty')}</th>
|
||||
<th colSpan='1' className='sortable le' onTouchTap={this._sortAmmoBy.bind(this, 'cost')} >{translate('unit cost')}</th>
|
||||
<th className='sortable le' onTouchTap={this._sortAmmoBy.bind(this, 'total')}>{translate('total cost')}</th>
|
||||
<th colSpan='2' className='sortable le' onClick={this._sortAmmoBy.bind(this, 'm')} >{translate('module')}</th>
|
||||
<th colSpan='1' className='sortable le' onClick={this._sortAmmoBy.bind(this, 'max')} >{translate('qty')}</th>
|
||||
<th colSpan='1' className='sortable le' onClick={this._sortAmmoBy.bind(this, 'cost')} >{translate('unit cost')}</th>
|
||||
<th className='sortable le' onClick={this._sortAmmoBy.bind(this, 'total')}>{translate('total cost')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -583,8 +579,7 @@ export default class CostSection extends TranslatedComponent {
|
||||
this.listeners = [
|
||||
Persist.addListener('discounts', this._onDiscountChanged.bind(this)),
|
||||
Persist.addListener('insurance', this._onInsuranceChanged.bind(this)),
|
||||
Persist.addListener('buildSaved', this._onBuildSaved.bind(this)),
|
||||
Persist.addListener('buildDeleted', this._onBuildDeleted.bind(this))
|
||||
Persist.addListener('builds', this._onBuildsChanged.bind(this)),
|
||||
];
|
||||
this._updateAmmoCosts(this.props.ship);
|
||||
this._updateRetrofit(this.props.ship, this.state.retrofitShip);
|
||||
@@ -613,7 +608,6 @@ export default class CostSection extends TranslatedComponent {
|
||||
if (nextProps.ship != this.props.ship || nextProps.code != this.props.code) {
|
||||
this._updateAmmoCosts(nextProps.ship);
|
||||
this._updateRetrofit(nextProps.ship, retrofitShip);
|
||||
this.setState({ total: nextProps.ship.totalCost });
|
||||
this._sortCost(nextProps.ship);
|
||||
}
|
||||
}
|
||||
@@ -673,9 +667,9 @@ export default class CostSection extends TranslatedComponent {
|
||||
<table className='tabs'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width:'33%' }} className={cn({ active: tab == 'costs' })} onTouchTap={this._showTab.bind(this, 'costs')} >{translate('costs')}</th>
|
||||
<th style={{ width:'33%' }} className={cn({ active: tab == 'retrofit' })} onTouchTap={this._showTab.bind(this, 'retrofit')} >{translate('retrofit costs')}</th>
|
||||
<th style={{ width:'34%' }} className={cn({ active: tab == 'ammo' })} onTouchTap={this._showTab.bind(this, 'ammo')} >{translate('reload costs')}</th>
|
||||
<th style={{ width:'33%' }} className={cn({ active: tab == 'costs' })} onClick={this._showTab.bind(this, 'costs')} >{translate('costs')}</th>
|
||||
<th style={{ width:'33%' }} className={cn({ active: tab == 'retrofit' })} onClick={this._showTab.bind(this, 'retrofit')} >{translate('retrofit costs')}</th>
|
||||
<th style={{ width:'34%' }} className={cn({ active: tab == 'ammo' })} onClick={this._showTab.bind(this, 'ammo')} >{translate('reload costs')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
@@ -91,39 +91,39 @@ export default class HardpointsSlotSection extends SlotSection {
|
||||
_getSectionMenu(translate) {
|
||||
let _fill = this._fill;
|
||||
|
||||
return <div className='select hardpoint' onTouchTap={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
return <div className='select hardpoint' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={this._empty}>{translate('empty all')}</li>
|
||||
<li className='lc' onClick={this._empty}>{translate('empty all')}</li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('pl')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'pl', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'pl', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'pl', 'T')}><MountTurret className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'pl', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'pl', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'pl', 'T')}><MountTurret className='lg'/></li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('ul')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'ul', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'ul', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'ul', 'T')}><MountTurret className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'ul', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'ul', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'ul', 'T')}><MountTurret className='lg'/></li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('bl')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'bl', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'bl', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'bl', 'T')}><MountTurret className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'bl', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'bl', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'bl', 'T')}><MountTurret className='lg'/></li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('mc')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'mc', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'mc', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'mc', 'T')}><MountTurret className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'mc', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'mc', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'mc', 'T')}><MountTurret className='lg'/></li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('c')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'c', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'c', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'c', 'T')}><MountTurret className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'c', 'F')}><MountFixed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'c', 'G')}><MountGimballed className='lg'/></li>
|
||||
<li className='c' onClick={_fill.bind(this, 'c', 'T')}><MountTurret className='lg'/></li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@ import Link from './Link';
|
||||
import ActiveLink from './ActiveLink';
|
||||
import cn from 'classnames';
|
||||
import { Cogs, CoriolisLogo, Hammer, Rocket, StatsBars } from './SvgIcons';
|
||||
import { Ships } from 'coriolis-data';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import Persist from '../stores/Persist';
|
||||
import { toDetailedExport } from '../shipyard/Serializer';
|
||||
import ModalDeleteAll from './ModalDeleteAll';
|
||||
import ModalExport from './ModalExport';
|
||||
import ModalImport from './ModalImport';
|
||||
import Slider from './Slider';
|
||||
import { outfitURL } from '../utils/UrlGenerators';
|
||||
|
||||
const SIZE_MIN = 0.65;
|
||||
const SIZE_RANGE = 0.55;
|
||||
@@ -181,11 +182,11 @@ export default class Header extends TranslatedComponent {
|
||||
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={outfitURL(s)} className='block'>{Ships[s].properties.name}</ActiveLink>);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='menu-list dbl no-wrap' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
<div className='menu-list dbl no-wrap' onClick={ (e) => e.stopPropagation() }>
|
||||
{shipList}
|
||||
</div>
|
||||
);
|
||||
@@ -203,7 +204,7 @@ export default class Header extends TranslatedComponent {
|
||||
let shipBuilds = [];
|
||||
let buildNameOrder = Object.keys(builds[shipId]).sort();
|
||||
for (let buildName of buildNameOrder) {
|
||||
let href = ['/outfit/', shipId, '/', builds[shipId][buildName], '?bn=', buildName].join('');
|
||||
let href = outfitURL(shipId, builds[shipId][buildName], buildName);
|
||||
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>);
|
||||
@@ -211,7 +212,7 @@ export default class Header extends TranslatedComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='menu-list' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
<div className='menu-list' onClick={ (e) => e.stopPropagation() }>
|
||||
<div className='dbl'>{buildList}</div>
|
||||
</div>
|
||||
);
|
||||
@@ -237,10 +238,10 @@ export default class Header extends TranslatedComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='menu-list' onTouchTap={ (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/all' className='block cap'>{translate('compare all')}</Link>
|
||||
<Link href='/compare' className='block cap'>{translate('create new')}</Link>
|
||||
</div>
|
||||
);
|
||||
@@ -255,14 +256,14 @@ export default class Header extends TranslatedComponent {
|
||||
let tips = Persist.showTooltips();
|
||||
|
||||
return (
|
||||
<div className='menu-list no-wrap cap' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
<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' onTouchTap={this._toggleTooltips} >
|
||||
<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>
|
||||
@@ -285,10 +286,10 @@ export default class Header extends TranslatedComponent {
|
||||
<hr />
|
||||
<ul>
|
||||
{translate('builds')} & {translate('comparisons')}
|
||||
<li><a href="#" className='block' onTouchTap={this._showBackup.bind(this)}>{translate('backup')}</a></li>
|
||||
<li><a href="#" className='block' onTouchTap={this._showDetailedExport.bind(this)}>{translate('detailed export')}</a></li>
|
||||
<li><a href="#" className='block' onTouchTap={this._showImport.bind(this)}>{translate('import')}</a></li>
|
||||
<li><a href="#" onTouchTap={this._showDeleteAll.bind(this)}>{translate('delete all')}</a></li>
|
||||
<li><Link href="#" className='block' onClick={this._showBackup.bind(this)}>{translate('backup')}</Link></li>
|
||||
<li><Link href="#" className='block' onClick={this._showDetailedExport.bind(this)}>{translate('detailed export')}</Link></li>
|
||||
<li><Link href="#" className='block' onClick={this._showImport.bind(this)}>{translate('import')}</Link></li>
|
||||
<li><Link href="#" onClick={this._showDeleteAll.bind(this)}>{translate('delete all')}</Link></li>
|
||||
</ul>
|
||||
<hr />
|
||||
<table style={{ width: 300, backgroundColor: 'transparent' }}>
|
||||
@@ -299,7 +300,7 @@ 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' onTouchTap={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>
|
||||
@@ -313,13 +314,13 @@ export default class Header extends TranslatedComponent {
|
||||
* 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());
|
||||
let update = () => this.forceUpdate();
|
||||
Persist.addListener('language', update);
|
||||
Persist.addListener('insurance', update);
|
||||
Persist.addListener('discounts', update);
|
||||
Persist.addListener('deletedAll', update);
|
||||
Persist.addListener('builds', update);
|
||||
Persist.addListener('tooltips', update);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,36 +348,36 @@ export default class Header extends TranslatedComponent {
|
||||
let hasBuilds = Persist.hasBuilds();
|
||||
|
||||
if (this.props.appCacheUpdate) {
|
||||
return <div id="app-update" onTouchTap={() => window.location.reload() }>{translate('PHRASE_UPDATE_RDY')}</div>;
|
||||
return <div id="app-update" onClick={() => window.location.reload() }>{translate('PHRASE_UPDATE_RDY')}</div>;
|
||||
}
|
||||
|
||||
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' })} onTouchTap={this._openShips}>
|
||||
<div className={cn('menu-header', { selected: openedMenu == 's' })} onClick={this._openShips}>
|
||||
<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 })} onTouchTap={hasBuilds && this._openBuilds}>
|
||||
<div className={cn('menu-header', { selected: openedMenu == 'b', disabled: !hasBuilds })} onClick={hasBuilds && this._openBuilds}>
|
||||
<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 })} onTouchTap={hasBuilds && this._openComp}>
|
||||
<div className={cn('menu-header', { selected: openedMenu == 'comp', disabled: !hasBuilds })} onClick={hasBuilds && this._openComp}>
|
||||
<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' })} onTouchTap={this._openSettings}>
|
||||
<div className={cn('menu-header', { selected: openedMenu == 'settings' })} onClick={this._openSettings}>
|
||||
<Cogs className='xl warning'/><span className='menu-item-label'>{translate('settings')}</span>
|
||||
</div>
|
||||
{openedMenu == 'settings' ? this._getSettingsMenu() : null}
|
||||
|
||||
@@ -132,12 +132,12 @@ export default class InternalSlotSection extends SlotSection {
|
||||
* @return {React.Component} Section menu
|
||||
*/
|
||||
_getSectionMenu(translate) {
|
||||
return <div className='select' onTouchTap={e => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
return <div className='select' onClick={e => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={this._empty}>{translate('empty all')}</li>
|
||||
<li className='lc' onTouchTap={this._fillWithCargo}>{translate('cargo')}</li>
|
||||
<li className='lc' onTouchTap={this._fillWithCells}>{translate('scb')}</li>
|
||||
<li className='lc' onTouchTap={this._fillWithArmor}>{translate('hr')}</li>
|
||||
<li className='lc' onClick={this._empty}>{translate('empty all')}</li>
|
||||
<li className='lc' onClick={this._fillWithCargo}>{translate('cargo')}</li>
|
||||
<li className='lc' onClick={this._fillWithCells}>{translate('scb')}</li>
|
||||
<li className='lc' onClick={this._fillWithArmor}>{translate('hr')}</li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import d3 from 'd3';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
|
||||
const RENDER_POINTS = 20; // Only render 20 points on the graph
|
||||
const MARGIN = { top: 15, right: 15, bottom: 35, left: 60 };
|
||||
const MARGIN = { top: 15, right: 20, bottom: 35, left: 60 };
|
||||
|
||||
/**
|
||||
* Line Chart
|
||||
@@ -47,7 +47,7 @@ export default class LineChart extends TranslatedComponent {
|
||||
this._moveTip = this._moveTip.bind(this);
|
||||
|
||||
let markerElems = [];
|
||||
let detailElems = [<text key={'lbl'} className='label x' y='1.25em'/>];
|
||||
let detailElems = [<text key='lbl' className='text-tip x' y='1.25em'/>];
|
||||
let xScale = d3.scale.linear();
|
||||
let xAxisScale = d3.scale.linear();
|
||||
let yScale = d3.scale.linear();
|
||||
@@ -60,7 +60,7 @@ export default class LineChart extends TranslatedComponent {
|
||||
for(let i = 0, l = series ? series.length : 1; i < l; i++) {
|
||||
let yAccessor = series ? function(d) { return yScale(d[1][this]); }.bind(series[i]) : (d) => yScale(d[1]);
|
||||
seriesLines.push(d3.svg.line().x((d) => xScale(d[0])).y(yAccessor));
|
||||
detailElems.push(<text key={i} className='label y' y={1.25 * (i + 2) + 'em'}/>);
|
||||
detailElems.push(<text key={i} className='text-tip y' y={1.25 * (i + 2) + 'em'}/>);
|
||||
markerElems.push(<circle key={i} className='marker' r='4' />);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ export default class LineChart extends TranslatedComponent {
|
||||
seriesLines,
|
||||
detailElems,
|
||||
markerElems,
|
||||
tipHeight: 2 + (1.25 * (series ? series.length : 0.75))
|
||||
tipHeight: 2 + (1.2 * (series ? series.length : 0.8))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ export default class LineChart extends TranslatedComponent {
|
||||
|
||||
xPos = xScale(x0); // Clamp xPos
|
||||
|
||||
tips.selectAll('text.label.y').text(function(d, i) {
|
||||
tips.selectAll('text.text-tip.y').text(function(d, i) {
|
||||
let yVal = series ? y0[series[i]] : y0;
|
||||
yTotal += yVal;
|
||||
return (series ? translate(series[i]) : '') + ' ' + formats.f2(yVal);
|
||||
@@ -110,8 +110,8 @@ export default class LineChart extends TranslatedComponent {
|
||||
|
||||
tipWidth += 8;
|
||||
tips.attr('transform', 'translate(' + xPos + ',' + tipY + ')');
|
||||
tips.selectAll('text.label').attr('x', flip ? -12 : 12).style('text-anchor', flip ? 'end' : 'start');
|
||||
tips.selectAll('text.label.x').text(formats.f2(x0)).append('tspan').attr('class', 'metric').text(' ' + xUnit);
|
||||
tips.selectAll('text.text-tip').attr('x', flip ? -12 : 12).style('text-anchor', flip ? 'end' : 'start');
|
||||
tips.selectAll('text.text-tip.x').text(formats.f2(x0)).append('tspan').attr('class', 'metric').text(' ' + xUnit);
|
||||
tips.selectAll('rect').attr('width', tipWidth + 4).attr('x', flip ? -tipWidth - 12 : 8).attr('y', 0).style('text-anchor', flip ? 'end' : 'start');
|
||||
this.markersContainer.selectAll('circle').attr('cx', xPos).attr('cy', (d, i) => yScale(series ? y0[series[i]] : y0));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,15 @@ import { shallowEqual } from '../utils/UtilityFunctions';
|
||||
*/
|
||||
export default class Link extends React.Component {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {Object} props React Component properties
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handler = this.handler.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a component should be rerendered
|
||||
* @param {object} nextProps Next properties
|
||||
@@ -21,18 +30,15 @@ export default class Link extends React.Component {
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
handler(event) {
|
||||
if (event.getModifierState &&
|
||||
(event.getModifierState('Shift') ||
|
||||
event.getModifierState('Alt') ||
|
||||
event.getModifierState('Control') ||
|
||||
event.getModifierState('Meta') ||
|
||||
event.button > 1)) {
|
||||
if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey || event.button > 1) {
|
||||
return;
|
||||
}
|
||||
event.nativeEvent && event.preventDefault && event.preventDefault();
|
||||
event.preventDefault();
|
||||
|
||||
if (this.props.href) {
|
||||
Router.go(encodeURI(this.props.href));
|
||||
if (this.props.onClick) {
|
||||
this.props.onClick(event);
|
||||
} else if (this.props.href) {
|
||||
Router.go(this.props.href);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +47,7 @@ export default class Link extends React.Component {
|
||||
* @return {React.Component} A href element
|
||||
*/
|
||||
render() {
|
||||
let action = this.handler.bind(this);
|
||||
return <a {...this.props} onTouchTap={action}>{this.props.children}</a>;
|
||||
return <a {...this.props} onClick={this.handler}>{this.props.children}</a>;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
import { Ships } from 'coriolis-data';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import Persist from '../stores/Persist';
|
||||
|
||||
/**
|
||||
@@ -96,39 +96,47 @@ export default class ModalCompare extends TranslatedComponent {
|
||||
let translate = this.context.language.translate;
|
||||
|
||||
let availableBuilds = unusedBuilds.map((build, i) =>
|
||||
<tr key={i} onTouchTap={this._addBuild.bind(this, i)}>
|
||||
<tr key={i} onClick={this._addBuild.bind(this, i)}>
|
||||
<td className='tl'>{build.name}</td>
|
||||
<td className='tl'>{build.buildName}</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
let selectedBuilds = usedBuilds.map((build, i) =>
|
||||
<tr key={i} onTouchTap={this._removeBuild.bind(this, i)}>
|
||||
<tr key={i} onClick={this._removeBuild.bind(this, i)}>
|
||||
<td className='tl'>{build.name}</td><
|
||||
td className='tl'>{build.buildName}</td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
return <div className='modal' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||
<h3>{translate('PHRASE_SELECT_BUILDS')}</h3>
|
||||
<div id='build-select'>
|
||||
<table>
|
||||
<thead><tr><th colSpan='2'>{translate('available')}</th></tr></thead>
|
||||
<tbody>
|
||||
{availableBuilds}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className='build-section'>
|
||||
<h1>{translate('available')}</h1>
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
{availableBuilds}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h1>⇆</h1>
|
||||
<table>
|
||||
<thead><tr><th colSpan='2'>{translate('added')}</th></tr></thead>
|
||||
<tbody>
|
||||
{selectedBuilds}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className='build-section'>
|
||||
<h1>{translate('added')}</h1>
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
{selectedBuilds}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<button className='cap' onTouchTap={this._selectBuilds.bind(this)}>{translate('Ok')}</button>
|
||||
<button className='r cap' onTouchTap={() => this.context.hideModal()}>{translate('Cancel')}</button>
|
||||
<button className='cap' onClick={this._selectBuilds.bind(this)}>{translate('Ok')}</button>
|
||||
<button className='r cap' onClick={() => this.context.hideModal()}>{translate('Cancel')}</button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ export default class ModalDeleteAll extends TranslatedComponent {
|
||||
render() {
|
||||
let translate = this.context.language.translate;
|
||||
|
||||
return <div className='modal' onTouchTap={(e) => e.stopPropagation()}>
|
||||
return <div className='modal' onClick={(e) => e.stopPropagation()}>
|
||||
<h2>{translate('delete all')}</h2>
|
||||
<p className='cen'>{translate('PHRASE_CONFIRMATION')}</p>
|
||||
<button className='l cap' onTouchTap={this._deleteAll.bind(this)}>{translate('yes')}</button>
|
||||
<button className='r cap' onTouchTap={this.context.hideModal}>{translate('no')}</button>
|
||||
<button className='l cap' onClick={this._deleteAll.bind(this)}>{translate('yes')}</button>
|
||||
<button className='r cap' onClick={this.context.hideModal}>{translate('no')}</button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,17 @@ export default class ModalExport extends TranslatedComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Focus on textarea and select all
|
||||
*/
|
||||
componentDidMount() {
|
||||
let e = findDOMNode(this.refs.exportField);
|
||||
if (e) {
|
||||
e.focus();
|
||||
e.select();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the modal
|
||||
* @return {React.Component} Modal Content
|
||||
@@ -52,13 +64,13 @@ export default class ModalExport extends TranslatedComponent {
|
||||
description = <div>{translate(this.props.description)}</div>;
|
||||
}
|
||||
|
||||
return <div className='modal' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||
<h2>{translate(this.props.title || 'Export')}</h2>
|
||||
{description}
|
||||
<div>
|
||||
<textarea className='cb json' onFocus={ (e) => e.target.select() } readOnly value={this.state.exportJson} />
|
||||
<textarea className='cb json' ref='exportField' readOnly value={this.state.exportJson} />
|
||||
</div>
|
||||
<button className='r dismiss cap' onTouchTap={this.context.hideModal}>{translate('close')}</button>
|
||||
<button className='r dismiss cap' onClick={this.context.hideModal}>{translate('close')}</button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import React from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import cn from 'classnames';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
import Router from '../Router';
|
||||
import Persist from '../stores/Persist';
|
||||
import { Ships } from 'coriolis-data';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import Ship from '../shipyard/Ship';
|
||||
import { ModuleNameToGroup, Insurance } from '../shipyard/Constants';
|
||||
import * as ModuleUtils from '../shipyard/ModuleUtils';
|
||||
import { fromDetailedBuild } from '../shipyard/Serializer';
|
||||
import { Download } from './SvgIcons';
|
||||
import { outfitURL } from '../utils/UrlGenerators';
|
||||
|
||||
const textBuildRegex = new RegExp('^\\[([\\w \\-]+)\\]\n');
|
||||
const lineRegex = new RegExp('^([\\dA-Z]{1,2}): (\\d)([A-I])[/]?([FGT])?([SD])? ([\\w\\- ]+)');
|
||||
@@ -24,15 +27,6 @@ function isEmptySlot(slot) {
|
||||
return slot.maxClass == this && slot.m === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal ignore case utility function. Must be bound to a string
|
||||
* @param {string} str String
|
||||
* @return {Boolean} True if equal
|
||||
*/
|
||||
function equalsIgnoreCase(str) {
|
||||
return str.toLowerCase() == this.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a build is valid
|
||||
* @param {string} shipId Ship ID
|
||||
@@ -273,7 +267,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
let builds = {};
|
||||
builds[shipId] = {};
|
||||
builds[shipId]['Imported ' + buildName] = ship.toString();
|
||||
this.setState({ builds });
|
||||
this.setState({ builds, singleBuild: true });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,6 +285,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
errorMsg: null,
|
||||
importValid: false,
|
||||
insurance: null,
|
||||
singleBuild: false,
|
||||
importString,
|
||||
});
|
||||
|
||||
@@ -312,6 +307,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
this._importDetailedArray(importData);
|
||||
} else if (importData.ship && typeof importData.name !== undefined) { // Using JSON from a single ship build export
|
||||
this._importDetailedArray([importData]); // Convert to array with singleobject
|
||||
this.setState({ singleBuild: true });
|
||||
} else { // Using Backup JSON
|
||||
this._importBackup(importData);
|
||||
}
|
||||
@@ -330,6 +326,16 @@ export default class ModalImport extends TranslatedComponent {
|
||||
_process() {
|
||||
let builds = null, comparisons = null;
|
||||
|
||||
// If only importing a single build go straight to the outfitting page
|
||||
if (this.state.singleBuild) {
|
||||
builds = this.state.builds;
|
||||
let shipId = Object.keys(builds)[0];
|
||||
let name = Object.keys(builds[shipId])[0];
|
||||
Router.go(outfitURL(shipId, builds[shipId][name], name));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (this.state.builds) {
|
||||
builds = {}; // Create new builds object such that orginal name retained, but can be renamed
|
||||
for (let shipId in this.state.builds) {
|
||||
@@ -412,6 +418,14 @@ export default class ModalImport extends TranslatedComponent {
|
||||
this._process();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* If textarea is shown focus on mount
|
||||
*/
|
||||
componentDidMount() {
|
||||
if (!this.props.builds && findDOMNode(this.refs.importField)) {
|
||||
findDOMNode(this.refs.importField).focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the import modal
|
||||
@@ -425,7 +439,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
if (!state.processed) {
|
||||
importStage = (
|
||||
<div>
|
||||
<textarea className='cb json' onChange={this._validateImport} defaultValue={this.state.importString} placeholder={translate('PHRASE_IMPORT')} />
|
||||
<textarea className='cb json' ref='importField' onChange={this._validateImport} defaultValue={this.state.importString} placeholder={translate('PHRASE_IMPORT')} />
|
||||
<button id='proceed' className='l cap' onClick={this._process} disabled={!state.importValid} >{translate('proceed')}</button>
|
||||
<div className='l warning' style={{ marginLeft:'3em' }}>{state.errorMsg}</div>
|
||||
</div>
|
||||
@@ -508,7 +522,7 @@ export default class ModalImport extends TranslatedComponent {
|
||||
);
|
||||
}
|
||||
|
||||
return <div className='modal' onTouchTap={ (e) => e.stopPropagation() } onClick={ (e) => e.stopPropagation() }>
|
||||
return <div className='modal' onClick={ (e) => e.stopPropagation() } onClick={ (e) => e.stopPropagation() }>
|
||||
<h2 >{translate('import')}</h2>
|
||||
{importStage}
|
||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||
|
||||
@@ -40,7 +40,7 @@ export default class ModalPermalink extends TranslatedComponent {
|
||||
render() {
|
||||
let translate = this.context.language.translate;
|
||||
|
||||
return <div className='modal' onTouchTap={ (e) => e.stopPropagation() }>
|
||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||
<h2>{translate('permalink')}</h2>
|
||||
<br/>
|
||||
<h3>{translate('URL')}</h3>
|
||||
@@ -49,7 +49,7 @@ export default class ModalPermalink extends TranslatedComponent {
|
||||
<h3 >{translate('shortened')}</h3>
|
||||
<input value={this.state.shortenedUrl} readOnly size={25} onFocus={ (e) => e.target.select() }/>
|
||||
<br/><br/>
|
||||
<button className={'r dismiss cap'} onTouchTap={this.context.hideModal}>{translate('close')}</button>
|
||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ export default class PowerBands extends TranslatedComponent {
|
||||
height={state.barHeight}
|
||||
x={Math.floor(Math.max(wattScale(b.retractedSum) - wattScale(b.retracted), 0))}
|
||||
y={1}
|
||||
onTouchTap={this._selectRet.bind(this, i)}
|
||||
onClick={this._selectRet.bind(this, i)}
|
||||
className={getClass(ret[i], b.retractedSum, available)}
|
||||
/>);
|
||||
|
||||
@@ -223,7 +223,7 @@ export default class PowerBands extends TranslatedComponent {
|
||||
height={state.barHeight}
|
||||
x={wattScale(b.retractedSum) - (wattScale(b.retracted) / 2)}
|
||||
y={state.retY}
|
||||
onTouchTap={this._selectRet.bind(this, i)}
|
||||
onClick={this._selectRet.bind(this, i)}
|
||||
className='primary-bg'>{retLbl}</text>
|
||||
);
|
||||
}
|
||||
@@ -238,7 +238,7 @@ export default class PowerBands extends TranslatedComponent {
|
||||
height={state.barHeight}
|
||||
x={Math.floor(Math.max(wattScale(b.deployedSum) - wattScale(b.retracted) - wattScale(b.deployed), 0))}
|
||||
y={state.barHeight + 1}
|
||||
onTouchTap={this._selectDep.bind(this, i)}
|
||||
onClick={this._selectDep.bind(this, i)}
|
||||
className={getClass(dep[i], b.deployedSum, available)}
|
||||
/>);
|
||||
|
||||
@@ -250,7 +250,7 @@ export default class PowerBands extends TranslatedComponent {
|
||||
height={state.barHeight}
|
||||
x={wattScale(b.deployedSum) - ((wattScale(b.retracted) + wattScale(b.deployed)) / 2)}
|
||||
y={state.depY}
|
||||
onTouchTap={this._selectDep.bind(this, i)}
|
||||
onClick={this._selectDep.bind(this, i)}
|
||||
className='primary-bg'>{depLbl}</text>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,23 +119,23 @@ export default class PowerManagement extends TranslatedComponent {
|
||||
let retractedElem = null, deployedElem = null;
|
||||
|
||||
if (slot.enabled) {
|
||||
retractedElem = <td className='ptr upp' onTouchTap={toggleEnabled}>{POWER[ship.getSlotStatus(slot, false)]}</td>;
|
||||
deployedElem = <td className='ptr upp' onTouchTap={toggleEnabled}>{POWER[ship.getSlotStatus(slot, true)]}</td>;
|
||||
retractedElem = <td className='ptr upp' onClick={toggleEnabled}>{POWER[ship.getSlotStatus(slot, false)]}</td>;
|
||||
deployedElem = <td className='ptr upp' onClick={toggleEnabled}>{POWER[ship.getSlotStatus(slot, true)]}</td>;
|
||||
} else {
|
||||
retractedElem = <td className='ptr disabled upp' colSpan='2' onTouchTap={toggleEnabled}>{translate('disabled')}</td>;
|
||||
retractedElem = <td className='ptr disabled upp' colSpan='2' onClick={toggleEnabled}>{translate('disabled')}</td>;
|
||||
}
|
||||
|
||||
powerRows.push(<tr key={i} className={cn('highlight', { disabled: !slot.enabled })}>
|
||||
<td className='ptr' style={{ width: '1em' }} onTouchTap={toggleEnabled}>{m.class + m.rating}</td>
|
||||
<td className='ptr le shorten cap' onTouchTap={toggleEnabled}>{slotName(translate, slot)}</td>
|
||||
<td className='ptr' onTouchTap={toggleEnabled}><u>{translate(slot.type)}</u></td>
|
||||
<td className='ptr' style={{ width: '1em' }} onClick={toggleEnabled}>{m.class + m.rating}</td>
|
||||
<td className='ptr le shorten cap' onClick={toggleEnabled}>{slotName(translate, slot)}</td>
|
||||
<td className='ptr' onClick={toggleEnabled}><u>{translate(slot.type)}</u></td>
|
||||
<td>
|
||||
<span className='flip ptr btn' onTouchTap={this._priority.bind(this, slot, -1)}>►</span>
|
||||
<span className='flip ptr btn' onClick={this._priority.bind(this, slot, -1)}>►</span>
|
||||
{' ' + (slot.priority + 1) + ' '}
|
||||
<span className='ptr btn' onTouchTap={this._priority.bind(this, slot, 1)}>►</span>
|
||||
<span className='ptr btn' onClick={this._priority.bind(this, slot, 1)}>►</span>
|
||||
</td>
|
||||
<td className='ri ptr' style={{ width: '3.25em' }} onTouchTap={toggleEnabled}>{pwr(m.power)}</td>
|
||||
<td className='ri ptr' style={{ width: '3em' }} onTouchTap={toggleEnabled}><u>{pct(m.power / ship.powerAvailable)}</u></td>
|
||||
<td className='ri ptr' style={{ width: '3.25em' }} onClick={toggleEnabled}>{pwr(m.power)}</td>
|
||||
<td className='ri ptr' style={{ width: '3em' }} onClick={toggleEnabled}><u>{pct(m.power / ship.powerAvailable)}</u></td>
|
||||
{retractedElem}
|
||||
{deployedElem}
|
||||
</tr>);
|
||||
@@ -200,12 +200,12 @@ export default class PowerManagement extends TranslatedComponent {
|
||||
<table style={{ width: '100%' }}>
|
||||
<thead>
|
||||
<tr className='main'>
|
||||
<th colSpan='2' className='sortable le' onTouchTap={sortOrder.bind(this, 'n')} >{translate('module')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onTouchTap={sortOrder.bind(this, 't')} >{translate('type')}</th>
|
||||
<th style={{ width: '4em' }} className='sortable' onTouchTap={sortOrder.bind(this, 'pri')} >{translate('pri')}</th>
|
||||
<th colSpan='2' className='sortable' onTouchTap={sortOrder.bind(this, 'pwr')} >{translate('PWR')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onTouchTap={sortOrder.bind(this, 'r')} >{translate('ret')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onTouchTap={sortOrder.bind(this, 'd')} >{translate('dep')}</th>
|
||||
<th colSpan='2' className='sortable le' onClick={sortOrder.bind(this, 'n')} >{translate('module')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onClick={sortOrder.bind(this, 't')} >{translate('type')}</th>
|
||||
<th style={{ width: '4em' }} className='sortable' onClick={sortOrder.bind(this, 'pri')} >{translate('pri')}</th>
|
||||
<th colSpan='2' className='sortable' onClick={sortOrder.bind(this, 'pwr')} >{translate('PWR')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onClick={sortOrder.bind(this, 'r')} >{translate('ret')}</th>
|
||||
<th style={{ width: '3em' }} className='sortable' onClick={sortOrder.bind(this, 'd')} >{translate('dep')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@@ -24,8 +24,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
let u = language.units;
|
||||
let formats = language.formats;
|
||||
let round = formats.round;
|
||||
let int = formats.int;
|
||||
let { time, int } = formats;
|
||||
let armourDetails = null;
|
||||
let sgClassNames = cn({ warning: ship.sgSlot && !ship.shieldStrength, muted: !ship.sgSlot });
|
||||
let sgRecover = '-';
|
||||
let sgRecharge = '-';
|
||||
let hide = tooltip.bind(null, null);
|
||||
|
||||
if (ship.armourMultiplier > 1 || ship.armourAdded) {
|
||||
@@ -35,6 +38,11 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
})</u>;
|
||||
}
|
||||
|
||||
if (ship.shieldStrength) {
|
||||
sgRecover = time(ship.calcShieldRecovery());
|
||||
sgRecharge = time(ship.calcShieldRecharge());
|
||||
}
|
||||
|
||||
return <div id='summary'>
|
||||
<table id='summaryTable'>
|
||||
<thead>
|
||||
@@ -43,20 +51,23 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
<th onMouseEnter={termtip.bind(null, 'maneuverability')} onMouseLeave={hide} rowSpan={2}>{translate('MNV')}</th>
|
||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canThrust() }) }>{translate('speed')}</th>
|
||||
<th rowSpan={2} className={ cn({ 'bg-warning-disabled': !ship.canBoost() }) }>{translate('boost')}</th>
|
||||
<th onMouseOver={termtip.bind(null, 'damage per second')} onMouseOut={hide} rowSpan={2}>{translate('DPS')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'damage per second')} onMouseLeave={hide} rowSpan={2}>{translate('DPS')}</th>
|
||||
<th rowSpan={2}>{translate('armour')}</th>
|
||||
<th rowSpan={2}>{translate('shields')}</th>
|
||||
<th colSpan={3}>{translate('shields')}</th>
|
||||
<th colSpan={3}>{translate('mass')}</th>
|
||||
<th rowSpan={2}>{translate('cargo')}</th>
|
||||
<th rowSpan={2}>{translate('fuel')}</th>
|
||||
<th colSpan={3}>{translate('jump range')}</th>
|
||||
<th colSpan={3}>{translate('total range')}</th>
|
||||
<th onMouseOver={termtip.bind(null, 'mass lock factor')} onMouseOut={hide} rowSpan={2}>{translate('MLF')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'PHRASE_FASTEST_RANGE')} onMouseLeave={hide} colSpan={3}>{translate('fastest range')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'mass lock factor')} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th className='lft'>{translate('strength')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECOVER', { cap: 0 })} onMouseLeave={hide}>{translate('recover')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'PHRASE_SG_RECHARGE', { cap: 0 })} onMouseLeave={hide}>{translate('recharge')}</th>
|
||||
<th className='lft'>{translate('hull')}</th>
|
||||
<th>{translate('unladen')}</th>
|
||||
<th>{translate('laden')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'PHRASE_UNLADEN', { cap: 0 })} onMouseLeave={hide}>{translate('unladen')}</th>
|
||||
<th onMouseEnter={termtip.bind(null, 'PHRASE_LADEN', { cap: 0 })} onMouseLeave={hide}>{translate('laden')}</th>
|
||||
<th className='lft'>{translate('max')}</th>
|
||||
<th>{translate('full tank')}</th>
|
||||
<th>{translate('laden')}</th>
|
||||
@@ -73,7 +84,9 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
<td>{ ship.canBoost() ? <span>{int(ship.topBoost)} {u['m/s']}</span> : <span className='warning'>0 <Warning/></span> }</td>
|
||||
<td>{round(ship.totalDps)}</td>
|
||||
<td>{int(ship.armour)} {armourDetails}</td>
|
||||
<td>{int(ship.shieldStrength)} {u.MJ} { ship.shieldMultiplier > 1 && ship.shieldStrength > 0 ? <u>({formats.rPct(ship.shieldMultiplier)})</u> : null }</td>
|
||||
<td className={sgClassNames}>{int(ship.shieldStrength)} {u.MJ} { ship.shieldMultiplier > 1 && ship.shieldStrength > 0 ? <u>({formats.rPct(ship.shieldMultiplier)})</u> : null }</td>
|
||||
<td className={sgClassNames}>{sgRecover}</td>
|
||||
<td className={sgClassNames}>{sgRecharge}</td>
|
||||
<td>{ship.hullMass} {u.T}</td>
|
||||
<td>{round(ship.unladenMass)} {u.T}</td>
|
||||
<td>{round(ship.ladenMass)} {u.T}</td>
|
||||
@@ -83,8 +96,8 @@ export default class ShipSummaryTable extends TranslatedComponent {
|
||||
<td>{round(ship.fullTankRange)} {u.LY}</td>
|
||||
<td>{round(ship.ladenRange)} {u.LY}</td>
|
||||
<td>{round(ship.maxJumpCount)}</td>
|
||||
<td>{round(ship.unladenTotalRange)} {u.LY}</td>
|
||||
<td>{round(ship.ladenTotalRange)} {u.LY}</td>
|
||||
<td>{round(ship.unladenFastestRange)} {u.LY}</td>
|
||||
<td>{round(ship.ladenFastestRange)} {u.LY}</td>
|
||||
<td>{ship.masslock}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -98,7 +98,7 @@ export default class Slider extends React.Component {
|
||||
*/
|
||||
_updateDimensions() {
|
||||
this.setState({
|
||||
outerWidth: findDOMNode(this).offsetWidth
|
||||
outerWidth: findDOMNode(this).getBoundingClientRect().width
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ export default class Slot extends TranslatedComponent {
|
||||
* @param {SyntheticEvent} event Event
|
||||
*/
|
||||
_contextMenu(event) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.props.onSelect(null,null);
|
||||
}
|
||||
|
||||
@@ -95,7 +97,7 @@ export default class Slot extends TranslatedComponent {
|
||||
// TODO: implement touch dragging
|
||||
|
||||
return (
|
||||
<div className={cn('slot', dropClass, { selected })} onTouchTap={onOpen} onContextMenu={this._contextMenu} onDragOver={dragOver}>
|
||||
<div className={cn('slot', dropClass, { selected })} onClick={onOpen} onContextMenu={this._contextMenu} onDragOver={dragOver}>
|
||||
<div className='details-container'>
|
||||
<div className='sz'>{this._getMaxClassLabel(translate)}</div>
|
||||
{slotDetails}
|
||||
|
||||
@@ -177,7 +177,7 @@ export default class SlotSection extends TranslatedComponent {
|
||||
|
||||
return (
|
||||
<div id={this.sectionId} className={'group'} onDragLeave={this._dragOverNone}>
|
||||
<div className={cn('section-menu', { selected: sectionMenuOpened })} onTouchTap={open} onContextMenu={ctx}>
|
||||
<div className={cn('section-menu', { selected: sectionMenuOpened })} onClick={open} onContextMenu={ctx}>
|
||||
<h1>{translate(this.sectionName)} <Equalizer/></h1>
|
||||
{sectionMenuOpened ? this._getSectionMenu(translate) : null }
|
||||
</div>
|
||||
|
||||
@@ -43,7 +43,7 @@ export default class StandardSlot extends TranslatedComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn('slot', { selected: this.props.selected })} onTouchTap={this.props.onOpen}>
|
||||
<div className={cn('slot', { selected: this.props.selected })} onClick={this.props.onOpen}>
|
||||
<div className={cn('details-container', { warning: warning && warning(slot.m) })}>
|
||||
<div className={'sz'}>{slot.maxClass}</div>
|
||||
<div>
|
||||
|
||||
@@ -172,7 +172,7 @@ export default class StandardSlotSection extends SlotSection {
|
||||
let bh = ship.bulkheads;
|
||||
|
||||
slots[0] = (
|
||||
<div key='bh' className={cn('slot', { selected: currentMenu === bh })} onTouchTap={open.bind(this, bh)}>
|
||||
<div key='bh' className={cn('slot', { selected: currentMenu === bh })} onClick={open.bind(this, bh)}>
|
||||
<div className={'details-container'}>
|
||||
<div className={'details'}>
|
||||
<div className={'sz'}>8</div>
|
||||
@@ -184,21 +184,21 @@ export default class StandardSlotSection extends SlotSection {
|
||||
</div>
|
||||
</div>
|
||||
{currentMenu === bh &&
|
||||
<div className='select' onTouchTap={ e => e.stopPropagation() }>
|
||||
<div className='select' onClick={ e => e.stopPropagation() }>
|
||||
<ul>
|
||||
<li onTouchTap={selBulkhead.bind(this, 0)} onMouseOver={this._bhDiff.bind(this, 0)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 0 })}>
|
||||
<li onClick={selBulkhead.bind(this, 0)} onMouseOver={this._bhDiff.bind(this, 0)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 0 })}>
|
||||
{translate('Lightweight Alloy')}
|
||||
</li>
|
||||
<li onTouchTap={selBulkhead.bind(this, 1)} onMouseOver={this._bhDiff.bind(this, 1)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 1 })}>
|
||||
<li onClick={selBulkhead.bind(this, 1)} onMouseOver={this._bhDiff.bind(this, 1)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 1 })}>
|
||||
{translate('Reinforced Alloy')}
|
||||
</li>
|
||||
<li onTouchTap={selBulkhead.bind(this, 2)} onMouseOver={this._bhDiff.bind(this, 2)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 2 })}>
|
||||
<li onClick={selBulkhead.bind(this, 2)} onMouseOver={this._bhDiff.bind(this, 2)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 2 })}>
|
||||
{translate('Military Grade Composite')}
|
||||
</li>
|
||||
<li onTouchTap={selBulkhead.bind(this, 3)} onMouseOver={this._bhDiff.bind(this, 3)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 3 })}>
|
||||
<li onClick={selBulkhead.bind(this, 3)} onMouseOver={this._bhDiff.bind(this, 3)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 3 })}>
|
||||
{translate('Mirrored Surface Composite')}
|
||||
</li>
|
||||
<li onTouchTap={selBulkhead.bind(this, 4)} onMouseOver={this._bhDiff.bind(this, 4)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 4 })}>
|
||||
<li onClick={selBulkhead.bind(this, 4)} onMouseOver={this._bhDiff.bind(this, 4)} onMouseLeave={this._hideDiff} className={cn('lc', { active: bh.index == 4 })}>
|
||||
{translate('Reactive Surface Composite')}
|
||||
</li>
|
||||
</ul>
|
||||
@@ -294,19 +294,19 @@ export default class StandardSlotSection extends SlotSection {
|
||||
_getSectionMenu(translate) {
|
||||
let _fill = this._fill;
|
||||
|
||||
return <div className='select' onTouchTap={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={this._optimizeStandard}>{translate('Optimize')}</li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'E')}>E</li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'D')}>D</li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'C')}>C</li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'B')}>B</li>
|
||||
<li className='c' onTouchTap={_fill.bind(this, 'A')}>A</li>
|
||||
<li className='lc' onClick={this._optimizeStandard}>{translate('Optimize')}</li>
|
||||
<li className='c' onClick={_fill.bind(this, 'E')}>E</li>
|
||||
<li className='c' onClick={_fill.bind(this, 'D')}>D</li>
|
||||
<li className='c' onClick={_fill.bind(this, 'C')}>C</li>
|
||||
<li className='c' onClick={_fill.bind(this, 'B')}>B</li>
|
||||
<li className='c' onClick={_fill.bind(this, 'A')}>A</li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('builds / roles')}</div>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={this._optimizeCargo}>{translate('Trader')}</li>
|
||||
<li className='lc' onTouchTap={this._optimizeExplorer}>{translate('Explorer')}</li>
|
||||
<li className='lc' onClick={this._optimizeCargo}>{translate('Trader')}</li>
|
||||
<li className='lc' onClick={this._optimizeExplorer}>{translate('Explorer')}</li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -91,21 +91,21 @@ export default class UtilitySlotSection extends SlotSection {
|
||||
_getSectionMenu(translate) {
|
||||
let _use = this._use;
|
||||
|
||||
return <div className='select' onTouchTap={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={this._empty}>{translate('empty all')}</li>
|
||||
<li className='lc' onClick={this._empty}>{translate('empty all')}</li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('sb')}</div>
|
||||
<ul>
|
||||
<li className='c' onTouchTap={_use.bind(this, 'sb', 'E', null)}>E</li>
|
||||
<li className='c' onTouchTap={_use.bind(this, 'sb', 'D', null)}>D</li>
|
||||
<li className='c' onTouchTap={_use.bind(this, 'sb', 'C', null)}>C</li>
|
||||
<li className='c' onTouchTap={_use.bind(this, 'sb', 'B', null)}>B</li>
|
||||
<li className='c' onTouchTap={_use.bind(this, 'sb', 'A', null)}>A</li>
|
||||
<li className='c' onClick={_use.bind(this, 'sb', 'E', null)}>E</li>
|
||||
<li className='c' onClick={_use.bind(this, 'sb', 'D', null)}>D</li>
|
||||
<li className='c' onClick={_use.bind(this, 'sb', 'C', null)}>C</li>
|
||||
<li className='c' onClick={_use.bind(this, 'sb', 'B', null)}>B</li>
|
||||
<li className='c' onClick={_use.bind(this, 'sb', 'A', null)}>A</li>
|
||||
</ul>
|
||||
<div className='select-group cap'>{translate('cm')}</div>
|
||||
<ul>
|
||||
<li className='lc' onTouchTap={_use.bind(this, 'cm', null, 'Heat Sink Launcher')}>{translate('Heat Sink Launcher')}</li>
|
||||
<li className='lc' onClick={_use.bind(this, 'cm', null, 'Heat Sink Launcher')}>{translate('Heat Sink Launcher')}</li>
|
||||
</ul>
|
||||
</div>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user