import React from 'react';
import PropTypes from 'prop-types';
import TranslatedComponent from './TranslatedComponent';
import cn from 'classnames';
import { ListModifications, Modified } from './SvgIcons';
import AvailableModulesMenu from './AvailableModulesMenu';
import ModificationsMenu from './ModificationsMenu';
import { stopCtxPropagation, wrapCtxMenu } from '../utils/UtilityFunctions';
import { blueprintTooltip } from '../utils/BlueprintFunctions';
import { Module } from 'ed-forge';
import { TYPES } from 'ed-forge/lib/src/data/slots';
import autoBind from 'auto-bind';
import { toPairs } from 'lodash';
const HARDPOINT_SLOT_LABELS = {
1: 'S',
2: 'M',
3: 'L',
4: 'H',
};
/**
* Abstract Slot
*/
export default class Slot extends TranslatedComponent {
static propTypes = {
currentMenu: PropTypes.any,
hideSearch: PropTypes.bool,
m: PropTypes.instanceOf(Module),
warning: PropTypes.func,
drag: PropTypes.func,
drop: PropTypes.func,
dropClass: PropTypes.string,
propsToShow: PropTypes.object.isRequired,
onPropToggle: PropTypes.func.isRequired,
};
/**
* Constructor
* @param {Object} props React Component properties
*/
constructor(props) {
super(props);
autoBind(this);
this.state = { menuIndex: 0 };
}
/**
* Opens a menu while setting state.
* @param {Object} newMenuIndex New menu index
* @param {Event} event Event object
*/
_openMenu(newMenuIndex, event) {
const slotName = this.props.m.getSlot();
if (
this.props.currentMenu === slotName &&
newMenuIndex === this.state.menuIndex
) {
this.context.closeMenu();
} {
this.setState({ menuIndex: newMenuIndex });
this.context.openMenu(slotName);
}
// If we don't stop event propagation, the underlying divs also might
// get clicked which would open up other menus
event.stopPropagation();
}
/**
* Generate the slot contents
* @return {React.Component} Slot contents
*/
_getSlotDetails() {
const { m, propsToShow } = this.props;
let { termtip, tooltip, language } = this.context;
const { translate, units, formats } = language;
if (m.isEmpty()) {
return
{translate(
m.isOnSlot(TYPES.MILITARY) ? 'emptyrestricted' : 'empty'
)}
;
} else {
let classRating = m.getClassRating();
let { drag, drop } = this.props;
// Modifications tooltip shows blueprint and grade, if available
let modTT = translate('modified');
const blueprint = m.getBlueprint();
const experimental = m.getExperimental();
const grade = m.getBlueprintGrade();
if (blueprint) {
modTT = `${translate(blueprint)} ${translate('grade')}: ${grade}`;
if (experimental) {
modTT += `, ${translate(experimental)}`;
}
modTT = (
{modTT}
{blueprintTooltip(language, m)}
);
}
let mass = m.get('mass') || m.get('cargo') || m.get('fuel') || 0;
return (
{classRating} {translate(m.readMeta('type'))}
{blueprint && (
)}
{propsToShow.mass ?
{formats.round(mass)}
{units.T}
: null}
{toPairs(propsToShow).sort().map(([prop, show]) => {
const { unit, value } = m.getFormatted(prop, true);
// Don't show mass again; it's already shown on the top right
// corner of a slot
if (!show || isNaN(value) || prop == 'mass') {
return null;
} else {
return (
{translate(prop)}: {formats.round(value)}{unit}
);
}
})}
{(m.getApplicableBlueprints() || []).length > 0 ? (
) : null}
);
}
}
/**
* Get the label for the slot size/class
* Should be overriden if necessary
* @return {string} label
*/
_getMaxClassLabel() {
const { m } = this.props;
let size = m.getSizeNum();
switch (true) {
case m.getSlot() === 'armour':
return '';
case size === 0:
// This can also happen for armour but that case was handled above
return 'U';
case m.isOnSlot(TYPES.HARDPOINT):
return HARDPOINT_SLOT_LABELS[size];
default:
return size;
}
}
/**
* Empty slot on right-click
* @param {SyntheticEvent} event Event
*/
_contextMenu(event) {
event.stopPropagation();
event.preventDefault();
const { m } = this.props;
m.reset();
if (this.props.currentMenu === m.getSlot()) {
this.context.closeMenu();
} else {
this.forceUpdate();
}
}
/**
* Render the slot
* @return {React.Component} The slot
*/
render() {
let language = this.context.language;
let translate = language.translate;
let {
currentMenu, m, dropClass, dragOver, warning, hideSearch, propsToShow,
onPropToggle,
} = this.props;
const { menuIndex } = this.state;
// TODO: implement touch dragging
const selected = currentMenu === m.getSlot();
return (
{this._getMaxClassLabel(translate)}
{this._getSlotDetails()}
{selected && menuIndex === 0 &&
{
m.setItem(item);
this.context.closeMenu();
}}
warning={warning}
/>}
{selected && menuIndex === 1 &&
}
);
}
}