mirror of
https://github.com/EDCD/coriolis.git
synced 2025-12-10 07:05:35 +00:00
Update material button
This commit is contained in:
134
src/app/components/EDEngineerButton.jsx
Normal file
134
src/app/components/EDEngineerButton.jsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import React from 'react';
|
||||
import autoBind from 'auto-bind';
|
||||
import Persist from '../stores/Persist';
|
||||
import PropTypes from 'prop-types';
|
||||
import { getBlueprintUuid, getExperimentalUuid } from 'ed-forge/lib/data/blueprints';
|
||||
import { Loader, MatIcon } from '../components/SvgIcons';
|
||||
import request from 'superagent';
|
||||
import { chain, entries } from 'lodash';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
|
||||
const STATE = {
|
||||
READY: 0,
|
||||
LOADING: 1,
|
||||
ERROR: 2,
|
||||
DONE: 3,
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export default class EDEngineerButton extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {Object} props React Component properties
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
autoBind(this);
|
||||
|
||||
const { ship } = props;
|
||||
const uuids = chain(ship.getModules())
|
||||
.filter((m) => m.getBlueprint())
|
||||
.map((m) => {
|
||||
const uuids = [getBlueprintUuid(m.getBlueprint(), m.getBlueprintGrade())];
|
||||
const exp = m.getExperimental();
|
||||
if (exp) {
|
||||
uuids.push(getExperimentalUuid(exp));
|
||||
}
|
||||
return uuids;
|
||||
})
|
||||
.flatMap()
|
||||
.groupBy()
|
||||
.mapValues((v) => v.length)
|
||||
.value();
|
||||
|
||||
this.state = {
|
||||
status: STATE.READY,
|
||||
uuids,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the shopping list
|
||||
*/
|
||||
_sendToEDEngineer() {
|
||||
const { uuids } = this.state;
|
||||
this.setState({ status: STATE.LOADING });
|
||||
request.get('http://localhost:44405/commanders')
|
||||
.then((data) => {
|
||||
const [cmdr] = JSON.parse(data.text);
|
||||
return Promise.all(
|
||||
entries(uuids).map(
|
||||
(entry) => {
|
||||
const [uuid, n] = entry;
|
||||
return new Promise((resolve, reject) => {
|
||||
request.patch(`http://localhost:44405/${cmdr}/shopping-list`)
|
||||
.field('uuid', uuid)
|
||||
.field('size', n)
|
||||
.end((err, res) => {
|
||||
console.log('request goes out!');
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
})
|
||||
.then(() => this.setState({ status: STATE.DONE }))
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
this.setState({ status: STATE.ERROR });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for browser compatibility of sending to ED Engineer.
|
||||
* @returns {boolean} True if browser is compatible
|
||||
*/
|
||||
_browserIsCompatible() {
|
||||
// !== Firefox 1.0+
|
||||
// TODO: Double check if this really doesn't work in firefox
|
||||
return typeof InstallTrigger === 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
render() {
|
||||
const { termtip, tooltip } = this.context;
|
||||
const hide = tooltip.bind(null, null);
|
||||
const { status } = this.state;
|
||||
|
||||
let msg = 'PHRASE_FIREFOX_EDENGINEER';
|
||||
if (this._browserIsCompatible()) {
|
||||
switch (status) {
|
||||
case STATE.READY: msg = 'Send to EDEngineer'; break;
|
||||
case STATE.LOADING: msg = 'Sending...'; break;
|
||||
case STATE.ERROR: msg = 'Error sending to EDEngineer'; break;
|
||||
case STATE.DONE: msg = 'Success! Clicking sends again.'; break;
|
||||
}
|
||||
}
|
||||
|
||||
return (<button
|
||||
disabled={!this._browserIsCompatible()}
|
||||
onClick={status !== STATE.LOADING && this._sendToEDEngineer}
|
||||
onMouseOver={termtip.bind(null, msg)}
|
||||
onMouseOut={hide}
|
||||
>
|
||||
{status === STATE.LOADING ?
|
||||
<Loader className="lg" /> :
|
||||
<MatIcon className="lg" />
|
||||
}
|
||||
</button>);
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import TranslatedComponent from './TranslatedComponent';
|
||||
import request from 'superagent';
|
||||
import Persist from '../stores/Persist';
|
||||
|
||||
/**
|
||||
* Permalink modal
|
||||
*/
|
||||
export default class ModalShoppingList extends TranslatedComponent {
|
||||
static propTypes = {
|
||||
ship: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param {Object} props React Component properties
|
||||
*/
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
matsList: '',
|
||||
mats: {},
|
||||
failed: false,
|
||||
cmdrName: Persist.getCmdr().selected,
|
||||
cmdrs: Persist.getCmdr().cmdrs,
|
||||
matsPerGrade: Persist.getRolls(),
|
||||
blueprints: []
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* React component did mount
|
||||
*/
|
||||
componentDidMount() {
|
||||
this.renderMats();
|
||||
if (this.checkBrowserIsCompatible()) {
|
||||
this.getCommanders();
|
||||
this.registerBPs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all blueprints needed to make a build.
|
||||
*/
|
||||
registerBPs() {
|
||||
const ship = this.props.ship;
|
||||
let blueprints = [];
|
||||
for (const module of ship.costList) {
|
||||
if (module.type === 'SHIP') {
|
||||
continue;
|
||||
}
|
||||
if (module.m && module.m.blueprint) {
|
||||
if (!module.m.blueprint.grade || !module.m.blueprint.grades) {
|
||||
continue;
|
||||
}
|
||||
if (module.m.blueprint.special) {
|
||||
console.log(module.m.blueprint.special);
|
||||
blueprints.push({ uuid: module.m.blueprint.special.uuid, number: 1 });
|
||||
}
|
||||
for (const g in module.m.blueprint.grades) {
|
||||
if (!module.m.blueprint.grades.hasOwnProperty(g)) {
|
||||
continue;
|
||||
}
|
||||
if (g > module.m.blueprint.grade) {
|
||||
continue;
|
||||
}
|
||||
blueprints.push({ uuid: module.m.blueprint.grades[g].uuid, number: this.state.matsPerGrade[g] });
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState({ blueprints });
|
||||
}
|
||||
|
||||
/**
|
||||
* Check browser isn't firefox.
|
||||
* @return {boolean} true if compatible, false if not.
|
||||
*/
|
||||
checkBrowserIsCompatible() {
|
||||
// Firefox 1.0+
|
||||
return typeof InstallTrigger === 'undefined';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of commanders from EDEngineer.
|
||||
*/
|
||||
getCommanders() {
|
||||
request
|
||||
.get('http://localhost:44405/commanders')
|
||||
.end((err, res) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return this.setState({ failed: true });
|
||||
}
|
||||
const cmdrs = JSON.parse(res.text);
|
||||
if (!this.state.cmdrName) {
|
||||
this.setState({ cmdrName: cmdrs[0] });
|
||||
}
|
||||
this.setState({ cmdrs }, () => {
|
||||
Persist.setCmdr({ selected: this.state.cmdrName, cmdrs });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all blueprints to ED Engineer
|
||||
* @param {Event} event React event
|
||||
*/
|
||||
sendToEDEng(event) {
|
||||
event.preventDefault();
|
||||
let translate = this.context.language.translate;
|
||||
const target = event.target;
|
||||
target.disabled = this.state.blueprints.length > 0;
|
||||
if (this.state.blueprints.length === 0) {
|
||||
target.innerText = translate('No modded components.');
|
||||
target.disabled = true;
|
||||
setTimeout(() => {
|
||||
target.innerText = translate('Send to EDEngineer');
|
||||
target.disabled = false;
|
||||
}, 3000);
|
||||
} else {
|
||||
target.innerText = translate('Sending...');
|
||||
}
|
||||
let countSent = 0;
|
||||
let countTotal = this.state.blueprints.length;
|
||||
|
||||
for (const i of this.state.blueprints) {
|
||||
request
|
||||
.patch(`http://localhost:44405/${this.state.cmdrName}/shopping-list`)
|
||||
.field('uuid', i.uuid)
|
||||
.field('size', i.number)
|
||||
.end(err => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
if (err.message !== 'Bad Request') {
|
||||
this.setState({ failed: true });
|
||||
}
|
||||
}
|
||||
countSent++;
|
||||
if (countSent === countTotal) {
|
||||
target.disabled = false;
|
||||
target.innerText = translate('Send to EDEngineer');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert mats object to string
|
||||
*/
|
||||
renderMats() {
|
||||
const ship = this.props.ship;
|
||||
let mats = {};
|
||||
for (const module of ship.costList) {
|
||||
if (module.type === 'SHIP') {
|
||||
continue;
|
||||
}
|
||||
if (module.m && module.m.blueprint) {
|
||||
if (!module.m.blueprint.grade || !module.m.blueprint.grades) {
|
||||
continue;
|
||||
}
|
||||
for (const g in module.m.blueprint.grades) {
|
||||
if (!module.m.blueprint.grades.hasOwnProperty(g)) {
|
||||
continue;
|
||||
}
|
||||
if (g > module.m.blueprint.grade) {
|
||||
continue;
|
||||
}
|
||||
for (const i in module.m.blueprint.grades[g].components) {
|
||||
if (!module.m.blueprint.grades[g].components.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
if (mats[i]) {
|
||||
mats[i] += module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
||||
} else {
|
||||
mats[i] = module.m.blueprint.grades[g].components[i] * this.state.matsPerGrade[g];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let matsString = '';
|
||||
for (const i in mats) {
|
||||
if (!mats.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
if (mats[i] === 0) {
|
||||
delete mats[i];
|
||||
continue;
|
||||
}
|
||||
matsString += `${i}: ${mats[i]}\n`;
|
||||
}
|
||||
this.setState({ matsList: matsString, mats });
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for changing roll amounts
|
||||
* @param {SyntheticEvent} e React Event
|
||||
*/
|
||||
changeHandler(e) {
|
||||
let grade = e.target.id;
|
||||
let newState = this.state.matsPerGrade;
|
||||
newState[grade] = parseInt(e.target.value);
|
||||
this.setState({ matsPerGrade: newState });
|
||||
Persist.setRolls(newState);
|
||||
this.renderMats();
|
||||
this.registerBPs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for changing cmdr name
|
||||
* @param {SyntheticEvent} e React Event
|
||||
*/
|
||||
cmdrChangeHandler(e) {
|
||||
let cmdrName = e.target.value;
|
||||
this.setState({ cmdrName }, () => {
|
||||
Persist.setCmdr({ selected: this.state.cmdrName, cmdrs: this.state.cmdrs });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the modal
|
||||
* @return {React.Component} Modal Content
|
||||
*/
|
||||
render() {
|
||||
let translate = this.context.language.translate;
|
||||
this.changeHandler = this.changeHandler.bind(this);
|
||||
const compatible = this.checkBrowserIsCompatible();
|
||||
this.cmdrChangeHandler = this.cmdrChangeHandler.bind(this);
|
||||
this.sendToEDEng = this.sendToEDEng.bind(this);
|
||||
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
|
||||
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
|
||||
<label>{translate('Grade 1 rolls ')}</label>
|
||||
<input id={1} type={'number'} min={0} defaultValue={this.state.matsPerGrade[1]} onChange={this.changeHandler} />
|
||||
<br/>
|
||||
<label>{translate('Grade 2 rolls ')}</label>
|
||||
<input id={2} type={'number'} min={0} defaultValue={this.state.matsPerGrade[2]} onChange={this.changeHandler} />
|
||||
<br/>
|
||||
<label>{translate('Grade 3 rolls ')}</label>
|
||||
<input id={3} type={'number'} min={0} value={this.state.matsPerGrade[3]} onChange={this.changeHandler} />
|
||||
<br/>
|
||||
<label>{translate('Grade 4 rolls ')}</label>
|
||||
<input id={4} type={'number'} min={0} value={this.state.matsPerGrade[4]} onChange={this.changeHandler} />
|
||||
<br/>
|
||||
<label>{translate('Grade 5 rolls ')}</label>
|
||||
<input id={5} type={'number'} min={0} value={this.state.matsPerGrade[5]} onChange={this.changeHandler} />
|
||||
<div>
|
||||
<textarea className='cb json' readOnly value={this.state.matsList} />
|
||||
</div>
|
||||
<label hidden={!compatible} className={'l cap'}>{translate('CMDR Name')}</label>
|
||||
<br/>
|
||||
<select hidden={!compatible} className={'cmdr-select l cap'} onChange={this.cmdrChangeHandler} defaultValue={this.state.cmdrName}>
|
||||
{this.state.cmdrs.map(e => <option key={e}>{e}</option>)}
|
||||
</select>
|
||||
<br/>
|
||||
<p hidden={!this.state.failed} id={'failed'} className={'l'}>{translate('PHRASE_FAIL_EDENGINEER')}</p>
|
||||
<p hidden={compatible} id={'browserbad'} className={'l'}>{translate('PHRASE_FIREFOX_EDENGINEER')}</p>
|
||||
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send to EDEngineer')}</button>
|
||||
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@
|
||||
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Farthest possible range with full cargo, a full fuel tank, and jumping as far as possible each time",
|
||||
"HELP_MODIFICATIONS_MENU": "Click on a number to enter a new value, or drag along the bar for small changes",
|
||||
"PHRASE_FAIL_EDENGINEER": "Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)",
|
||||
"PHRASE_FIREFOX_EDENGINEER": "Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.",
|
||||
"PHRASE_FIREFOX_EDENGINEER": "Send to EDEngineer is incompatible with Firefox.",
|
||||
"am": "Auto Field-Maintenance Unit",
|
||||
"bh": "Bulkheads",
|
||||
"bl": "Beam Laser",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
// import Perf from 'react-addons-perf';
|
||||
import { Ships } from 'coriolis-data/dist';
|
||||
import cn from 'classnames';
|
||||
import Page from './Page';
|
||||
import Router from '../Router';
|
||||
@@ -27,10 +26,10 @@ import UtilitySlotSection from '../components/UtilitySlotSection';
|
||||
import OutfittingSubpages from '../components/OutfittingSubpages';
|
||||
import ModalExport from '../components/ModalExport';
|
||||
import ModalPermalink from '../components/ModalPermalink';
|
||||
import ModalShoppingList from '../components/ModalShoppingList';
|
||||
import ModalOrbis from '../components/ModalOrbis';
|
||||
import autoBind from 'auto-bind';
|
||||
import { assign } from 'lodash';
|
||||
import EDEngineerButton from '../components/EDEngineerButton';
|
||||
|
||||
const SHOW_BY_DEFAULT = {
|
||||
'cabincapacity': true,
|
||||
@@ -394,13 +393,6 @@ export default class OutfittingPage extends Page {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the shopping list
|
||||
*/
|
||||
_genShoppingList() {
|
||||
this.context.showModal(<ModalShoppingList ship={this.state.ship} />);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Key Down
|
||||
* @param {Event} e Keyboard Event
|
||||
@@ -594,13 +586,7 @@ export default class OutfittingPage extends Page {
|
||||
>
|
||||
<OrbisIcon className="lg" />
|
||||
</button>
|
||||
<button
|
||||
// onClick={this._genShoppingList}
|
||||
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')}
|
||||
onMouseOut={hide}
|
||||
>
|
||||
<MatIcon className="lg" />
|
||||
</button>
|
||||
<EDEngineerButton ship={ship} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user