diff --git a/ChangeLog.md b/ChangeLog.md index 9b9e758b..a70fa2ee 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -23,6 +23,7 @@ * Offence section provides details of your build's damage distribution and per-weapon effectiveness. It also gives summary information for how long it will take for your build to wear down your opponent's shields and armour * Defence section provides details of your build's defences against your selected opponent. It provides details of the effectiveness of your resistances of both shields and armour, and effective strength of each as a result. It also provides key metrics around shield longevity and recovery times, as well as module protection * Fix power band marker to show safe power limit at 40% rather than 50% + * Restyle blueprint list to improve consistency with similar menus #2.2.19 * Power management panel now displays modules in descending order of power usage by default diff --git a/src/app/components/ModificationsMenu.jsx b/src/app/components/ModificationsMenu.jsx index d576419f..c0b452b4 100644 --- a/src/app/components/ModificationsMenu.jsx +++ b/src/app/components/ModificationsMenu.jsx @@ -15,6 +15,7 @@ export default class ModificationsMenu extends TranslatedComponent { static propTypes = { ship: React.PropTypes.object.isRequired, m: React.PropTypes.object.isRequired, + marker: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired }; @@ -25,7 +26,6 @@ export default class ModificationsMenu extends TranslatedComponent { */ constructor(props, context) { super(props); - this.state = this._initState(props, context); this._toggleBlueprintsMenu = this._toggleBlueprintsMenu.bind(this); this._toggleSpecialsMenu = this._toggleSpecialsMenu.bind(this); @@ -34,33 +34,59 @@ export default class ModificationsMenu extends TranslatedComponent { this._rollBest = this._rollBest.bind(this); this._rollExtreme = this._rollExtreme.bind(this); this._reset = this._reset.bind(this); + + this.state = { + blueprintMenuOpened: false, + specialMenuOpened: false + }; } /** - * Initialise state - * @param {Object} props React Component properties - * @param {Object} context React Component context + * Render the blueprints + * @param {Object} props React component properties + * @param {Object} context React component context * @return {Object} list: Array of React Components */ - _initState(props, context) { - let { m } = props; + _renderBlueprints(props, context) { + const { m } = props; const { language, tooltip, termtip } = context; const translate = language.translate; - // Set up the blueprints - let blueprints = []; + const blueprints = []; for (const blueprintName in Modifications.modules[m.grp].blueprints) { - for (const grade in Modifications.modules[m.grp].blueprints[blueprintName].grades) { + const blueprint = getBlueprint(blueprintName, m); + let blueprintGrades = []; + for (let grade in Modifications.modules[m.grp].blueprints[blueprintName].grades) { + // Grade is a string in the JSON so make it a number + grade = Number(grade); + const classes = cn('c', { + active: m.blueprint && blueprint.id === m.blueprint.id && grade === m.blueprint.grade + }); const close = this._blueprintSelected.bind(this, blueprintName, grade); const key = blueprintName + ':' + grade; - const blueprint = getBlueprint(blueprintName, m); const tooltipContent = blueprintTooltip(translate, blueprint.grades[grade], Modifications.modules[m.grp].blueprints[blueprintName].grades[grade].engineers); - blueprints.push(
{translate(blueprint.name + ' grade ' + grade)}
); + blueprintGrades.unshift(
  • {grade}
  • ); + } + if (blueprintGrades) { + blueprints.push(
    {translate(blueprint.name)}
    ); + blueprints.push(); } } + return blueprints; + } - // Set up the special effects - let specials = []; + /** + * Render the specials + * @param {Object} props React component properties + * @param {Object} context React component context + * @return {Object} list: Array of React Components + */ + _renderSpecials(props, context) { + const { m } = props; + const { language, tooltip, termtip } = context; + const translate = language.translate; + + const specials = []; if (Modifications.modules[m.grp].specials && Modifications.modules[m.grp].specials.length > 0) { const close = this._specialSelected.bind(this, null); specials.push(
    {translate('PHRASE_NO_SPECIAL')}
    ); @@ -69,24 +95,17 @@ export default class ModificationsMenu extends TranslatedComponent { specials.push(
    {translate(Modifications.specials[specialName].name)}
    ); } } - - // Set up the modifications - const modifications = this._setModifications(props); - - const blueprintMenuOpened = false; - const specialMenuOpened = false; - - return { blueprintMenuOpened, blueprints, modifications, specialMenuOpened, specials }; + return specials; } /** - * Initialise the modifications + * Render the modifications * @param {Object} props React Component properties * @return {Object} list: Array of React Components */ - _setModifications(props) { + _renderModifications(props) { const { m, onChange, ship } = props; - let modifications = []; + const modifications = []; for (const modName of Modifications.modules[m.grp].modifications) { if (!Modifications.modifications[modName].hidden) { const key = modName + (m.getModValue(modName) / 100 || 0); @@ -116,8 +135,7 @@ export default class ModificationsMenu extends TranslatedComponent { blueprint.grade = grade; m.blueprint = blueprint; - const blueprintMenuOpened = false; - this.setState({ blueprintMenuOpened }); + this.setState({ blueprintMenuOpened: false }); this.props.onChange(); } @@ -148,8 +166,7 @@ export default class ModificationsMenu extends TranslatedComponent { ship.recalculateEps(); } - const specialMenuOpened = false; - this.setState({ specialMenuOpened, modifications: this._setModifications(this.props) }); + this.setState({ specialMenuOpened: false }); this.props.onChange(); } @@ -181,7 +198,7 @@ export default class ModificationsMenu extends TranslatedComponent { let value = features[featureName][0]; this._setRollResult(ship, m, featureName, value); } - this.setState({ modifications: this._setModifications(this.props) }); + this.props.onChange(); } @@ -196,7 +213,7 @@ export default class ModificationsMenu extends TranslatedComponent { let value = features[featureName][0] + (Math.random() * (features[featureName][1] - features[featureName][0])); this._setRollResult(ship, m, featureName, value); } - this.setState({ modifications: this._setModifications(this.props) }); + this.props.onChange(); } @@ -210,7 +227,7 @@ export default class ModificationsMenu extends TranslatedComponent { let value = features[featureName][1]; this._setRollResult(ship, m, featureName, value); } - this.setState({ modifications: this._setModifications(this.props) }); + this.props.onChange(); } @@ -241,7 +258,7 @@ export default class ModificationsMenu extends TranslatedComponent { this._setRollResult(ship, m, featureName, value); } - this.setState({ modifications: this._setModifications(this.props) }); + this.props.onChange(); } @@ -253,7 +270,6 @@ export default class ModificationsMenu extends TranslatedComponent { ship.clearModifications(m); ship.clearBlueprint(m); - this.setState({ modifications: this._setModifications(this.props) }); this.props.onChange(); } @@ -291,8 +307,10 @@ export default class ModificationsMenu extends TranslatedComponent { specialLabel = translate('PHRASE_SELECT_SPECIAL'); } + const specials = this._renderSpecials(this.props, this.context); + const showBlueprintsMenu = blueprintMenuOpened; - const showSpecial = haveBlueprint && this.state.specials.length > 0 && !blueprintMenuOpened; + const showSpecial = haveBlueprint && specials.length && !blueprintMenuOpened; const showSpecialsMenu = specialMenuOpened; const showRolls = haveBlueprint && !blueprintMenuOpened && !specialMenuOpened; const showReset = !blueprintMenuOpened && !specialMenuOpened; @@ -304,12 +322,12 @@ export default class ModificationsMenu extends TranslatedComponent { onClick={(e) => e.stopPropagation() } onContextMenu={stopCtxPropagation} > - { haveBlueprint ? + { showBlueprintsMenu ? '' : haveBlueprint ?
    {blueprintLabel}
    :
    {translate('PHRASE_SELECT_BLUEPRINT')}
    } - { showBlueprintsMenu ? this.state.blueprints : null } + { showBlueprintsMenu ? this._renderBlueprints(this.props, this.context) : null } { showSpecial ?
    {specialLabel}
    : null } - { showSpecialsMenu ? this.state.specials : null } + { showSpecialsMenu ? specials : null } { showRolls || showReset ? @@ -329,7 +347,7 @@ export default class ModificationsMenu extends TranslatedComponent {
    : null } { showMods ? - { this.state.modifications } + { this._renderModifications(this.props) } : null } ); diff --git a/src/app/components/Slot.jsx b/src/app/components/Slot.jsx index 9959a16f..03964d35 100644 --- a/src/app/components/Slot.jsx +++ b/src/app/components/Slot.jsx @@ -79,7 +79,7 @@ export default class Slot extends TranslatedComponent { let language = this.context.language; let translate = language.translate; let { ship, m, dropClass, dragOver, onOpen, onChange, selected, eligible, onSelect, warning, availableModules } = this.props; - let slotDetails, menu; + let slotDetails, modificationsMarker, menu; if (!selected) { // If not selected then sure that modifications flag is unset @@ -88,8 +88,10 @@ export default class Slot extends TranslatedComponent { if (m) { slotDetails = this._getSlotDetails(m, translate, language.formats, language.units); // Must be implemented by sub classes + modificationsMarker = JSON.stringify(m); } else { slotDetails =
    {translate(eligible ? 'emptyrestricted' : 'empty')}
    ; + modificationsMarker = ''; } if (selected) { @@ -99,6 +101,7 @@ export default class Slot extends TranslatedComponent { onChange={onChange} ship={ship} m={m} + marker={modificationsMarker} />; } else { menu =