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",
|
"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",
|
"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_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",
|
"am": "Auto Field-Maintenance Unit",
|
||||||
"bh": "Bulkheads",
|
"bh": "Bulkheads",
|
||||||
"bl": "Beam Laser",
|
"bl": "Beam Laser",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
// import Perf from 'react-addons-perf';
|
// import Perf from 'react-addons-perf';
|
||||||
import { Ships } from 'coriolis-data/dist';
|
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import Page from './Page';
|
import Page from './Page';
|
||||||
import Router from '../Router';
|
import Router from '../Router';
|
||||||
@@ -27,10 +26,10 @@ import UtilitySlotSection from '../components/UtilitySlotSection';
|
|||||||
import OutfittingSubpages from '../components/OutfittingSubpages';
|
import OutfittingSubpages from '../components/OutfittingSubpages';
|
||||||
import ModalExport from '../components/ModalExport';
|
import ModalExport from '../components/ModalExport';
|
||||||
import ModalPermalink from '../components/ModalPermalink';
|
import ModalPermalink from '../components/ModalPermalink';
|
||||||
import ModalShoppingList from '../components/ModalShoppingList';
|
|
||||||
import ModalOrbis from '../components/ModalOrbis';
|
import ModalOrbis from '../components/ModalOrbis';
|
||||||
import autoBind from 'auto-bind';
|
import autoBind from 'auto-bind';
|
||||||
import { assign } from 'lodash';
|
import { assign } from 'lodash';
|
||||||
|
import EDEngineerButton from '../components/EDEngineerButton';
|
||||||
|
|
||||||
const SHOW_BY_DEFAULT = {
|
const SHOW_BY_DEFAULT = {
|
||||||
'cabincapacity': true,
|
'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
|
* Handle Key Down
|
||||||
* @param {Event} e Keyboard Event
|
* @param {Event} e Keyboard Event
|
||||||
@@ -594,13 +586,7 @@ export default class OutfittingPage extends Page {
|
|||||||
>
|
>
|
||||||
<OrbisIcon className="lg" />
|
<OrbisIcon className="lg" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<EDEngineerButton ship={ship} />
|
||||||
// onClick={this._genShoppingList}
|
|
||||||
onMouseOver={termtip.bind(null, 'PHRASE_SHOPPING_MATS')}
|
|
||||||
onMouseOut={hide}
|
|
||||||
>
|
|
||||||
<MatIcon className="lg" />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user