From 044fea2d33c81e4ef90d5f32c5d577f823d3e1bd Mon Sep 17 00:00:00 2001 From: Felix Linker Date: Sun, 26 Dec 2021 16:16:36 +0100 Subject: [PATCH] Update material button --- src/app/components/EDEngineerButton.jsx | 134 ++++++++++++ src/app/components/ModalShoppingList.jsx | 262 ----------------------- src/app/i18n/en.json | 2 +- src/app/pages/OutfittingPage.jsx | 18 +- 4 files changed, 137 insertions(+), 279 deletions(-) create mode 100644 src/app/components/EDEngineerButton.jsx delete mode 100644 src/app/components/ModalShoppingList.jsx diff --git a/src/app/components/EDEngineerButton.jsx b/src/app/components/EDEngineerButton.jsx new file mode 100644 index 00000000..4bf4d536 --- /dev/null +++ b/src/app/components/EDEngineerButton.jsx @@ -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 (); + } +} diff --git a/src/app/components/ModalShoppingList.jsx b/src/app/components/ModalShoppingList.jsx deleted file mode 100644 index 0b92c710..00000000 --- a/src/app/components/ModalShoppingList.jsx +++ /dev/null @@ -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
e.stopPropagation() }> -

{translate('PHRASE_SHOPPING_MATS')}

- - -
- - -
- - -
- - -
- - -
-