Files
CHOMPStation2/tgui/packages/tgui_ch/interfaces/ShuttleControl.jsx
CHOMPStation2 85ca379bb2 [MIRROR] [TGUI 5.0 Prep] JS to JSX (#7414)
Co-authored-by: Selis <sirlionfur@hotmail.de>
Co-authored-by: Selis <selis@xynolabs.com>
2023-12-13 23:23:03 +01:00

472 lines
14 KiB
JavaScript

import { toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Flex, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
/* Helpers */
const getDockingStatus = (docking_status, docking_override) => {
let main = 'ERROR';
let color = 'bad';
let showsOverride = false;
if (docking_status === 'docked') {
main = 'DOCKED';
color = 'good';
} else if (docking_status === 'docking') {
main = 'DOCKING';
color = 'average';
showsOverride = true;
} else if (docking_status === 'undocking') {
main = 'UNDOCKING';
color = 'average';
showsOverride = true;
} else if (docking_status === 'undocked') {
main = 'UNDOCKED';
color = '#676767';
}
if (showsOverride && docking_override) {
main = main + '-MANUAL';
}
return <Box color={color}>{main}</Box>;
};
/* Templates */
const ShuttleControlSharedShuttleStatus = (props, context) => {
const { act, data } = useBackend(context);
const { engineName = 'Bluespace Drive' } = props;
const {
shuttle_status,
shuttle_state,
has_docking,
docking_status,
docking_override,
docking_codes,
} = data;
return (
<Section title="Shuttle Status">
<Box color="label" mb={1}>
{shuttle_status}
</Box>
<LabeledList>
<LabeledList.Item label={engineName}>
{(shuttle_state === 'idle' && (
<Box color="#676767" bold>
IDLE
</Box>
)) ||
(shuttle_state === 'warmup' && (
<Box color="#336699">SPINNING UP</Box>
)) ||
(shuttle_state === 'in_transit' && (
<Box color="#336699">ENGAGED</Box>
)) || <Box color="bad">ERROR</Box>}
</LabeledList.Item>
{(has_docking && (
<Fragment>
<LabeledList.Item label="Docking Status">
{getDockingStatus(docking_status, docking_override)}
</LabeledList.Item>
<LabeledList.Item label="Docking Codes">
<Button icon="pen" onClick={() => act('set_codes')}>
{docking_codes || 'Not Set'}
</Button>
</LabeledList.Item>
</Fragment>
)) ||
null}
</LabeledList>
</Section>
);
};
const ShuttleControlSharedShuttleControls = (props, context) => {
const { act, data } = useBackend(context);
const { can_launch, can_cancel, can_force } = data;
return (
<Section title="Controls">
<Flex spacing={1}>
<Flex.Item grow={1}>
<Button
onClick={() => act('move')}
disabled={!can_launch}
icon="rocket"
fluid>
Launch Shuttle
</Button>
</Flex.Item>
<Flex.Item grow={1}>
<Button
onClick={() => act('cancel')}
disabled={!can_cancel}
icon="ban"
fluid>
Cancel Launch
</Button>
</Flex.Item>
<Flex.Item grow={1}>
<Button
onClick={() => act('force')}
color="bad"
disabled={!can_force}
icon="exclamation-triangle"
fluid>
Force Launch
</Button>
</Flex.Item>
</Flex>
</Section>
);
};
const ShuttleControlConsoleDefault = (props, context) => {
const { act, data } = useBackend(context);
return (
<Fragment>
<ShuttleControlSharedShuttleStatus />
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
const ShuttleControlConsoleMulti = (props, context) => {
const { act, data } = useBackend(context);
const { can_cloak, can_pick, legit, cloaked, destination_name } = data;
return (
<Fragment>
<ShuttleControlSharedShuttleStatus />
<Section title="Multishuttle Controls">
<LabeledList>
{(can_cloak && (
<LabeledList.Item label={legit ? 'ATC Inhibitor' : 'Cloaking'}>
<Button
selected={cloaked}
icon={cloaked ? 'eye' : 'eye-o'}
onClick={() => act('toggle_cloaked')}>
{cloaked ? 'Enabled' : 'Disabled'}
</Button>
</LabeledList.Item>
)) ||
null}
<LabeledList.Item label="Current Destination">
<Button
icon="taxi"
disabled={!can_pick}
onClick={() => act('pick')}>
{destination_name}
</Button>
</LabeledList.Item>
</LabeledList>
</Section>
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
const ShuttleControlConsoleExploration = (props, context) => {
const { act, data } = useBackend(context);
const { can_pick, destination_name, fuel_usage, fuel_span, remaining_fuel } =
data;
return (
<Fragment>
<ShuttleControlSharedShuttleStatus engineName="Engines" />
<Section title="Jump Controls">
<LabeledList>
<LabeledList.Item label="Current Destination">
<Button
icon="taxi"
disabled={!can_pick}
onClick={() => act('pick')}>
{destination_name}
</Button>
</LabeledList.Item>
{(fuel_usage && (
<Fragment>
<LabeledList.Item label="Est. Delta-V Budget" color={fuel_span}>
{remaining_fuel} m/s
</LabeledList.Item>
<LabeledList.Item label="Avg. Delta-V Per Maneuver">
{fuel_usage} m/s
</LabeledList.Item>
</Fragment>
)) ||
null}
</LabeledList>
</Section>
<ShuttleControlSharedShuttleControls />
</Fragment>
);
};
/* Ugh. Just ugh. */
const ShuttleControlConsoleWeb = (props, context) => {
const { act, data } = useBackend(context);
const {
autopilot,
can_rename,
shuttle_state,
is_moving,
skip_docking,
docking_status,
docking_override,
shuttle_location,
can_cloak,
cloaked,
can_autopilot,
routes,
is_in_transit,
travel_progress,
time_left,
doors,
sensors,
} = data;
return (
<Fragment>
{(autopilot && (
<Section title="AI PILOT (CLASS D) ACTIVE">
<Box inline italic>
This vessel will start and stop automatically. Ensure that all
non-cycling capable hatches and doors are closed, as the automated
system may not be able to control them. Docking and flight controls
are locked. To unlock, disable the automated flight system.
</Box>
</Section>
)) ||
null}
<Section
title="Shuttle Status"
buttons={
(can_rename && (
<Button icon="pen" onClick={() => act('rename_command')}>
Rename
</Button>
)) ||
null
}>
<LabeledList>
<LabeledList.Item label="Engines">
{(shuttle_state === 'idle' && (
<Box color="#676767" bold>
IDLE
</Box>
)) ||
(shuttle_state === 'warmup' && (
<Box color="#336699">SPINNING UP</Box>
)) ||
(shuttle_state === 'in_transit' && (
<Box color="#336699">ENGAGED</Box>
)) || <Box color="bad">ERROR</Box>}
</LabeledList.Item>
{(!is_moving && (
<Fragment>
<LabeledList.Item label="Current Location">
{toTitleCase(shuttle_location)}
</LabeledList.Item>
{(!skip_docking && (
<LabeledList.Item
label="Docking Status"
buttons={
<Fragment>
<Button
selected={docking_status === 'docked'}
disabled={
docking_status !== 'undocked' &&
docking_status !== 'docked'
}
onClick={() => act('dock_command')}>
Dock
</Button>
<Button
selected={docking_status === 'undocked'}
disabled={
docking_status !== 'docked' &&
docking_status !== 'undocked'
}
onClick={() => act('undock_command')}>
Undock
</Button>
</Fragment>
}>
<Box bold inline>
{getDockingStatus(docking_status, docking_override)}
</Box>
</LabeledList.Item>
)) ||
null}
{(can_cloak && (
<LabeledList.Item label="Cloaking">
<Button
selected={cloaked}
icon={cloaked ? 'eye' : 'eye-o'}
onClick={() => act('toggle_cloaked')}>
{cloaked ? 'Enabled' : 'Disabled'}
</Button>
</LabeledList.Item>
)) ||
null}
{(can_autopilot && (
<LabeledList.Item label="Autopilot">
<Button
selected={autopilot}
icon={autopilot ? 'eye' : 'eye-o'}
onClick={() => act('toggle_autopilot')}>
{autopilot ? 'Enabled' : 'Disabled'}
</Button>
</LabeledList.Item>
)) ||
null}
</Fragment>
)) ||
null}
</LabeledList>
{(!is_moving && (
<Section level={2} title="Available Destinations">
<LabeledList>
{(routes.length &&
routes.map((route) => (
<LabeledList.Item label={route.name} key={route.name}>
<Button
icon="rocket"
onClick={() =>
act('traverse', { traverse: route.index })
}>
{route.travel_time}
</Button>
</LabeledList.Item>
))) || (
<LabeledList.Item label="Error" color="bad">
No routes found.
</LabeledList.Item>
)}
</LabeledList>
</Section>
)) ||
null}
</Section>
{(is_in_transit && (
<Section title="Transit ETA">
<LabeledList>
<LabeledList.Item label="Distance from target">
<ProgressBar
color="good"
minValue={0}
maxValue={100}
value={travel_progress}>
{time_left}s
</ProgressBar>
</LabeledList.Item>
</LabeledList>
</Section>
)) ||
null}
{(Object.keys(doors).length && (
<Section title="Hatch Status">
<LabeledList>
{Object.keys(doors).map((key) => {
let door = doors[key];
return (
<LabeledList.Item label={key} key={key}>
{(door.open && (
<Box inline color="bad">
Open
</Box>
)) || (
<Box inline color="good">
Closed
</Box>
)}
&nbsp;-&nbsp;
{(door.bolted && (
<Box inline color="good">
Bolted
</Box>
)) || (
<Box inline color="bad">
Unbolted
</Box>
)}
</LabeledList.Item>
);
})}
</LabeledList>
</Section>
)) ||
null}
{(Object.keys(sensors).length && (
<Section title="Sensors">
<LabeledList>
{Object.keys(sensors).map((key) => {
let sensor = sensors[key];
if (sensor.reading === -1) {
return (
<LabeledList.Item label={key} color="bad">
Unable to get sensor air reading.
</LabeledList.Item>
);
}
return (
<LabeledList.Item label={key} key={key}>
<LabeledList>
<LabeledList.Item label="Pressure">
{sensor.pressure}kPa
</LabeledList.Item>
<LabeledList.Item label="Temperature">
{sensor.temp}&deg;C
</LabeledList.Item>
<LabeledList.Item label="Oxygen">
{sensor.oxygen}%
</LabeledList.Item>
<LabeledList.Item label="Nitrogen">
{sensor.nitrogen}%
</LabeledList.Item>
<LabeledList.Item label="Carbon Dioxide">
{sensor.carbon_dioxide}%
</LabeledList.Item>
<LabeledList.Item label="Phoron">
{sensor.phoron}%
</LabeledList.Item>
{(sensor.other && (
<LabeledList.Item label="Other">
{sensor.other}%
</LabeledList.Item>
)) ||
null}
</LabeledList>
</LabeledList.Item>
);
})}
</LabeledList>
</Section>
)) ||
null}
</Fragment>
);
};
// This may look tempting to convert to require() or some kind of dynamic call
// Don't do it. XSS abound.
const SubtemplateList = {
'ShuttleControlConsoleDefault': <ShuttleControlConsoleDefault />,
'ShuttleControlConsoleMulti': <ShuttleControlConsoleMulti />,
'ShuttleControlConsoleExploration': <ShuttleControlConsoleExploration />,
'ShuttleControlConsoleWeb': <ShuttleControlConsoleWeb />,
};
export const ShuttleControl = (props, context) => {
const { act, data } = useBackend(context);
const { subtemplate } = data;
return (
<Window
width={470}
height={subtemplate === 'ShuttleControlConsoleWeb' ? 560 : 370}
resizable>
<Window.Content>{SubtemplateList[subtemplate]}</Window.Content>
</Window>
);
};