refactoring for TGUI3, part 2

halfway there
This commit is contained in:
sarcoph
2022-03-01 15:16:53 -09:00
parent 21e555a14f
commit 8723c7304f
27 changed files with 797 additions and 595 deletions
@@ -56,7 +56,7 @@
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Launchpad", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user)
+1 -1
View File
@@ -280,7 +280,7 @@
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "Launchpad", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui = new(user, src, ui_key, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
// ui.set_style("syndicate")
ui.open()
+27 -14
View File
@@ -7,45 +7,58 @@ import { useBackend } from '../backend';
export const CargoExpress = (props, context) => {
const { config, data, act } = useBackend(context);
const { ref } = config;
const supplies = data.supplies || {};
const { data, act } = useBackend(context);
const {
siliconUser,
locked,
points,
usingBeacon,
hasBeacon,
beaconName,
beaconzone,
printMsg,
canBuyBeacon,
message,
} = data;
const supplies = Object.values(data.supplies);
return (
<Window>
<Window.Content>
<InterfaceLockNoticeBox
siliconUser={data.siliconUser}
locked={data.locked}
siliconUser={siliconUser}
locked={locked}
onLockStatusChange={() => act('lock')}
accessText="a QM-level ID card" />
{!data.locked && (
{!locked && (
<Fragment>
<Section
title="Cargo Express"
buttons={(
<Box inline bold>
<AnimatedNumber value={Math.round(data.points)} /> credits
<AnimatedNumber value={Math.round(points)} /> credits
</Box>
)}>
<LabeledList>
<LabeledList.Item label="Landing Location">
<Button
content="Cargo Bay"
selected={!data.usingBeacon}
selected={!usingBeacon}
onClick={() => act('LZCargo')} />
<Button
selected={data.usingBeacon}
disabled={!data.hasBeacon}
selected={usingBeacon}
disabled={!hasBeacon}
onClick={() => act('LZBeacon')}>
{data.beaconzone} ({data.beaconName})
{beaconzone} ({beaconName})
</Button>
<Button
content={data.printMsg}
disabled={!data.canBuyBeacon}
content={printMsg}
disabled={!canBuyBeacon}
onClick={() => act('printBeacon')} />
</LabeledList.Item>
<LabeledList.Item label="Notice">
{data.message}
{message}
</LabeledList.Item>
</LabeledList>
</Section>
+10 -9
View File
@@ -7,8 +7,7 @@ import { PackagingControls } from './ChemMaster/PackagingControls';
import { useBackend } from '../backend';
export const ChemMaster = (props, context) => {
const { config, data, act } = useBackend(context);
const { ref } = config;
const { data, act } = useBackend(context);
const {
screen,
beakerContents = [],
@@ -19,7 +18,9 @@ export const ChemMaster = (props, context) => {
isPillBottleLoaded,
pillBottleCurrentAmount,
pillBottleMaxAmount,
mode,
} = data;
if (screen === "analyze") {
return <AnalysisResults />;
}
@@ -28,7 +29,7 @@ export const ChemMaster = (props, context) => {
<Window.Content>
<Section
title="Beaker"
buttons={!!data.isBeakerLoaded && (
buttons={!!isBeakerLoaded && (
<Fragment>
<Box inline color="label" mr={2}>
<AnimatedNumber
@@ -39,7 +40,7 @@ export const ChemMaster = (props, context) => {
<Button
icon="eject"
content="Eject"
onClick={() => act(ref, 'eject')} />
onClick={() => act('eject')} />
</Fragment>
)}>
{!isBeakerLoaded && (
@@ -69,10 +70,10 @@ export const ChemMaster = (props, context) => {
Mode:
</Box>
<Button
color={data.mode ? 'good' : 'bad'}
icon={data.mode ? 'exchange-alt' : 'times'}
content={data.mode ? 'Transfer' : 'Destroy'}
onClick={() => act(ref, 'toggleMode')} />
color={mode ? 'good' : 'bad'}
icon={mode ? 'exchange-alt' : 'times'}
content={mode ? 'Transfer' : 'Destroy'}
onClick={() => act('toggleMode')} />
</Fragment>
)}>
{bufferContents.length === 0 && (
@@ -104,7 +105,7 @@ export const ChemMaster = (props, context) => {
<Button
icon="eject"
content="Eject"
onClick={() => act(ref, 'ejectPillBottle')} />
onClick={() => act('ejectPillBottle')} />
</Fragment>
)} />
)}
@@ -2,8 +2,7 @@ import { useBackend } from '../../backend';
import { Button, ColorBox, LabeledList, Section } from '../../components';
export const AnalysisResults = (props, context) => {
const { config, data, act } = useBackend(context);
const { ref } = config;
const { data, act } = useBackend(context);
const { analyzeVars, fermianalyze } = data;
return (
<Section
@@ -12,7 +11,7 @@ export const AnalysisResults = (props, context) => {
<Button
icon="arrow-left"
content="Back"
onClick={() => act(ref, 'goScreen', {
onClick={() => act('goScreen', {
screen: 'home',
})} />
)}>
@@ -1,9 +1,10 @@
import { act } from '../../byond';
import { useBackend } from '../../backend';
import { AnimatedNumber, Button, Table } from '../../components';
export const ChemicalBufferEntry = (props, context) => {
const { state, chemical, transferTo } = props;
const { ref } = state.config;
const { act } = useBackend(context);
const { chemical, transferTo } = props;
return (
<Table.Row key={chemical.id}>
<Table.Cell color="label">
@@ -15,28 +16,28 @@ export const ChemicalBufferEntry = (props, context) => {
<Table.Cell collapsing>
<Button
content="1"
onClick={() => act(ref, 'transfer', {
onClick={() => act('transfer', {
id: chemical.id,
amount: 1,
to: transferTo,
})} />
<Button
content="5"
onClick={() => act(ref, 'transfer', {
onClick={() => act('transfer', {
id: chemical.id,
amount: 5,
to: transferTo,
})} />
<Button
content="10"
onClick={() => act(ref, 'transfer', {
onClick={() => act('transfer', {
id: chemical.id,
amount: 10,
to: transferTo,
})} />
<Button
content="All"
onClick={() => act(ref, 'transfer', {
onClick={() => act('transfer', {
id: chemical.id,
amount: 1000,
to: transferTo,
@@ -44,7 +45,7 @@ export const ChemicalBufferEntry = (props, context) => {
<Button
icon="ellipsis-h"
title="Custom amount"
onClick={() => act(ref, 'transfer', {
onClick={() => act('transfer', {
id: chemical.id,
amount: -1,
to: transferTo,
@@ -52,7 +53,7 @@ export const ChemicalBufferEntry = (props, context) => {
<Button
icon="question"
title="Analyze"
onClick={() => act(ref, 'analyze', {
onClick={() => act('analyze', {
id: chemical.id,
})} />
</Table.Cell>
@@ -1,4 +1,5 @@
import { Component } from 'inferno';
import { useBackend } from '../../backend';
import { act } from '../../byond';
import { Box, Button, LabeledList, NumberInput } from '../../components';
@@ -16,14 +17,14 @@ export class PackagingControls extends Component {
}
render() {
const { state, props } = this;
const { ref } = props.state.config;
const { props, context } = this;
const { data, act } = useBackend(context);
const {
pillAmount, patchAmount, bottleAmount, packAmount, vialAmount, dartAmount,
} = this.state;
const {
condi, chosenPillStyle, pillStyles = [],
} = props.state.data;
} = data;
return (
<LabeledList>
{!condi && (
@@ -35,7 +36,7 @@ export class PackagingControls extends Component {
selected={pill.id === chosenPillStyle}
textAlign="center"
color="transparent"
onClick={() => act(ref, 'pillStyle', { id: pill.id })}>
onClick={() => act('pillStyle', { id: pill.id })}>
<Box mx={-1} className={pill.className} />
</Button>
))}
@@ -50,7 +51,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
pillAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'pill',
amount: pillAmount,
volume: 'auto',
@@ -65,7 +66,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
patchAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'patch',
amount: patchAmount,
volume: 'auto',
@@ -80,7 +81,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
bottleAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'bottle',
amount: bottleAmount,
volume: 'auto',
@@ -95,7 +96,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
vialAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'hypoVial',
amount: vialAmount,
volume: 'auto',
@@ -110,7 +111,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
dartAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'smartDart',
amount: dartAmount,
volume: 'auto',
@@ -125,7 +126,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
packAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'condimentPack',
amount: packAmount,
volume: 'auto',
@@ -140,7 +141,7 @@ export class PackagingControls extends Component {
onChangeAmount={(e, value) => this.setState({
bottleAmount: value,
})}
onCreate={() => act(ref, 'create', {
onCreate={() => act('create', {
type: 'condimentBottle',
amount: bottleAmount,
volume: 'auto',
@@ -14,9 +14,13 @@ export const EightBallVote = (props, context) => {
if (!shaking) {
return (
<NoticeBox>
No question is currently being asked.
</NoticeBox>
<Window>
<Window.Content>
<NoticeBox>
No question is currently being asked.
</NoticeBox>
</Window.Content>
</Window>
);
}
@@ -1,67 +0,0 @@
import { useBackend } from '../backend';
import { Button, Grid, Input, Section } from '../components';
import { Window } from '../layouts';
import { LaunchpadButtonPad } from './Launchpad/LaunchpadButtonPad';
import { LaunchTarget } from './Launchpad/LaunchTarget';
export const LaunchpadControl = (props, context) => {
const { topLevel } = props;
const { act, data } = useBackend(context);
const { pad_name } = data;
return (
<Window>
<Window.Content>
<Section
title={(
<Input
value={pad_name}
width="170px"
onChange={(e, value) => act('rename', {
name: value,
})}
/>
)}
level={topLevel ? 1 : 2}
buttons={(
<Button
icon="times"
content="Remove"
color="bad"
onClick={() => act('remove')} />
)}>
<Grid>
<Grid.Column>
<Section title="Controls" level={2}>
<LaunchpadButtonPad state={props.state} />
</Section>
</Grid.Column>
<Grid.Column>
<LaunchTarget data={data} act={act} />
</Grid.Column>
</Grid>
<Grid>
<Grid.Column>
<Button
fluid
icon="upload"
content="Launch"
textAlign="center"
onClick={() => act('launch')} />
</Grid.Column>
<Grid.Column>
<Button
fluid
icon="download"
content="Pull"
textAlign="center"
onClick={() => act('pull')} />
</Grid.Column>
</Grid>
</Section>
</Window.Content>
</Window>
);
};
@@ -1,7 +1,10 @@
import { useBackend } from '../../backend';
import { Box, NumberInput, Section } from '../../components';
export const LaunchTarget = (data, act) => {
export const LaunchTarget = (props, context) => {
const { act, data } = useBackend(context);
const { x, y, range } = data;
return (
<Section title="Target" level={2}>
<Box fontSize="26px">
@@ -1,54 +0,0 @@
import { useBackend } from '../../backend';
import { Box, Button, Grid, NoticeBox, Section } from '../../components';
import { LaunchpadControl } from '../Launchpad';
export const LaunchpadConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
launchpads = [], selected_id,
} = data;
if (launchpads.length <= 0) {
return (
<NoticeBox>
No Pads Connected
</NoticeBox>
);
}
return (
<Section>
<Grid>
<Grid.Column size={0.6}>
<Box
style={{
'border-right': '2px solid rgba(255, 255, 255, 0.1)',
}}
minHeight="190px"
mr={1}>
{launchpads.map(launchpad => (
<Button
fluid
key={launchpad.name}
content={launchpad.name}
selected={selected_id === launchpad.id}
color="transparent"
onClick={() => act('select_pad', { id: launchpad.id })} />
))}
</Box>
</Grid.Column>
<Grid.Column>
{selected_id ? (
<LaunchpadControl state={props.state} />
) : (
<Box>
Please select a pad
</Box>
)}
</Grid.Column>
</Grid>
</Section>
);
};
@@ -0,0 +1,62 @@
import { useBackend } from '../../backend';
import { Button, Grid, Input, Section } from '../../components';
import { LaunchpadButtonPad } from './LaunchpadButtonPad';
import { LaunchTarget } from './LaunchTarget';
export const LaunchpadControl = (props, context) => {
const { topLevel } = props;
const { act, data } = useBackend(context);
const { pad_name } = data;
return (
<Section
title={(
<Input
value={pad_name}
width="170px"
onChange={(e, value) => act('rename', {
name: value,
})}
/>
)}
level={topLevel ? 1 : 2}
buttons={(
<Button
icon="times"
content="Remove"
color="bad"
onClick={() => act('remove')} />
)}>
<Grid>
<Grid.Column>
<Section title="Controls" level={2}>
<LaunchpadButtonPad state={props.state} />
</Section>
</Grid.Column>
<Grid.Column>
<LaunchTarget />
</Grid.Column>
</Grid>
<Grid>
<Grid.Column>
<Button
fluid
icon="upload"
content="Launch"
textAlign="center"
onClick={() => act('launch')} />
</Grid.Column>
<Grid.Column>
<Button
fluid
icon="download"
content="Pull"
textAlign="center"
onClick={() => act('pull')} />
</Grid.Column>
</Grid>
</Section>
);
};
@@ -1,32 +0,0 @@
import { useBackend } from '../../backend';
import { NoticeBox } from '../../components';
import { LaunchpadControl } from '../Launchpad';
export const LaunchpadRemote = (props, context) => {
const { data } = useBackend(context);
const {
has_pad, pad_closed,
} = data;
if (!has_pad) {
return (
<NoticeBox>
No Launchpad Connected
</NoticeBox>
);
}
if (pad_closed) {
return (
<NoticeBox>
Launchpad Closed
</NoticeBox>
);
}
return (
<LaunchpadControl topLevel state={props.state} />
);
};
@@ -0,0 +1,62 @@
import { useBackend } from '../backend';
import { Box, Button, Grid, NoticeBox, Section } from '../components';
import { Window } from '../layouts';
import { LaunchpadControl } from './Launchpad/LaunchpadControl';
export const LaunchpadConsole = (props, context) => {
const { act, data } = useBackend(context);
const {
launchpads = [], selected_id,
} = data;
if (launchpads.length <= 0) {
return (
<Window>
<Window.Content>
<NoticeBox>
No Pads Connected
</NoticeBox>
</Window.Content>
</Window>
);
}
return (
<Window>
<Window.Content>
<Section>
<Grid>
<Grid.Column size={0.6}>
<Box
style={{
'border-right': '2px solid rgba(255, 255, 255, 0.1)',
}}
minHeight="190px"
mr={1}>
{launchpads.map(launchpad => (
<Button
fluid
key={launchpad.name}
content={launchpad.name}
selected={selected_id === launchpad.id}
color="transparent"
onClick={() => act('select_pad', { id: launchpad.id })} />
))}
</Box>
</Grid.Column>
<Grid.Column>
{selected_id ? (
<LaunchpadControl />
) : (
<Box>
Please select a pad
</Box>
)}
</Grid.Column>
</Grid>
</Section>
</Window.Content>
</Window>
);
};
@@ -0,0 +1,41 @@
import { useBackend } from '../backend';
import { NoticeBox } from '../components';
import { Window } from '../layouts';
import { LaunchpadControl } from './Launchpad/LaunchpadControl';
export const LaunchpadRemote = (props, context) => {
const { data } = useBackend(context);
const {
has_pad, pad_closed,
} = data;
if (!has_pad) {
return (
<Window>
<Window.Content>
<NoticeBox>
No Launchpad Connected
</NoticeBox>
</Window.Content>
</Window>
);
}
if (pad_closed) {
return (
<Window>
<Window.Content>
<NoticeBox>
Launchpad Closed
</NoticeBox>
</Window.Content>
</Window>
);
}
return (
<LaunchpadControl topLevel />
);
};
@@ -19,9 +19,13 @@ export const NaniteChamberControl = (props, context) => {
if (status_msg) {
return (
<NoticeBox textAlign="center">
{status_msg}
</NoticeBox>
<Window>
<Window.Content>
<NoticeBox textAlign="center">
{status_msg}
</NoticeBox>
</Window.Content>
</Window>
);
}
@@ -7,7 +7,6 @@ import { NaniteCloudBackupList } from './NaniteCloudControl/NaniteCloudBackupLis
import { NaniteDiskBox } from './NaniteCloudControl/NaniteDiskBox';
export const NaniteCloudControl = (props, context) => {
const { state } = props;
const { act, data } = useBackend(context);
const {
has_disk,
@@ -27,7 +26,7 @@ export const NaniteCloudControl = (props, context) => {
disabled={!has_disk}
onClick={() => act('eject')} />
)}>
<NaniteDiskBox state={state} />
<NaniteDiskBox />
</Section>
<Section
title="Cloud Storage"
@@ -57,11 +56,11 @@ export const NaniteCloudControl = (props, context) => {
</Fragment>
)
)}>
{!data.current_view ? (
<NaniteCloudBackupList state={state} />
{/* {!data.current_view ? (
<NaniteCloudBackupList />
) : (
<NaniteCloudBackupDetails state={state} />
)}
<NaniteCloudBackupDetails />
)} */}
</Section>
</Window.Content>
</Window>
@@ -1,9 +1,9 @@
import { useBackend } from '../../backend';
import { NoticeBox } from '../../components';
import { NaniteInfoBox } from "./NaniteInfoBox";
export const NaniteDiskBox = (props, context) => {
const { state } = props;
const { data } = state;
const { act, data } = useBackend(context);
const {
has_disk, has_program, disk,
} = data;
@@ -1,7 +1,7 @@
import { map } from 'common/collections';
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Button, LabeledList, NoticeBox, Section, Tabs } from '../components';
import { useBackend, useLocalState } from '../backend';
import { Button, Flex, LabeledList, NoticeBox, Section, Table, Tabs } from '../components';
import { Window } from '../layouts';
export const NaniteProgramHub = (props, context) => {
@@ -13,6 +13,12 @@ export const NaniteProgramHub = (props, context) => {
has_program,
programs = {},
} = data;
const [activeCategoryKey, setActiveCategoryKey]
= useLocalState(context, 'category', Object.keys(programs)[0]);
const activeCategory = programs[activeCategoryKey];
return (
<Window>
<Window.Content>
@@ -66,56 +72,62 @@ export const NaniteProgramHub = (props, context) => {
</Fragment>
)}>
{programs !== null ? (
<Tabs vertical>
{map((cat_contents, category) => {
const progs = cat_contents || [];
// Backend was sending stupid data that would have been
// annoying to fix
const tabLabel = category.substring(0, category.length - 8);
return (
<Tabs.Tab
key={category}
label={tabLabel}>
{detail_view ? (
progs.map(program => (
<Section
key={program.id}
title={program.name}
level={2}
buttons={(
<Button
icon="download"
content="Download"
disabled={!has_disk}
onClick={() => act('download', {
program_id: program.id,
})} />
)}>
{program.desc}
</Section>
))
) : (
<LabeledList>
{progs.map(program => (
<LabeledList.Item
key={program.id}
label={program.name}
buttons={(
<Button
icon="download"
content="Download"
disabled={!has_disk}
onClick={() => act('download', {
program_id: program.id,
})} />
)} />
))}
</LabeledList>
)}
</Tabs.Tab>
);
})(programs)}
</Tabs>
<Flex direction="row">
<Flex.Item>
<Tabs vertical>
{map((cat_contents, category) => {
const progs = cat_contents || [];
const tabLabel = category.substring(0, category.length - 8);
return (
<Tabs.Tab
key={category}
selected={activeCategoryKey===category}
onClick={() => setActiveCategoryKey(category)}>
{tabLabel}
</Tabs.Tab>
);
})(programs)}
</Tabs>
</Flex.Item>
<Flex.Item grow={1} basis={0}>
{detail_view ? (
activeCategory.map(program => (
<Section
key={program.id}
title={program.name}
level={2}
buttons={(
<Button
icon="download"
content="Download"
disabled={!has_disk}
onClick={() => act('download', {
program_id: program.id,
})} />
)}>
{program.desc}
</Section>
))
) : (
<LabeledList>
{activeCategory.map(program => (
<LabeledList.Item
key={program.id}
label={program.name}
buttons={(
<Button
icon="download"
content="Download"
disabled={!has_disk}
onClick={() => act('download', {
program_id: program.id,
})} />
)} />
))}
</LabeledList>
)}
</Flex.Item>
</Flex>
) : (
<NoticeBox>
No nanite programs are currently researched.
@@ -125,4 +137,4 @@ export const NaniteProgramHub = (props, context) => {
</Window.Content>
</Window>
);
};
};
@@ -19,9 +19,13 @@ export const NaniteProgrammer = (props, context) => {
if (!has_disk) {
return (
<NoticeBox textAlign="center">
Insert a nanite program disk
</NoticeBox>
<Window>
<Window.Content>
<NoticeBox textAlign="center">
Insert a nanite program disk
</NoticeBox>
</Window.Content>
</Window>
);
}
@@ -25,9 +25,13 @@ export const NaniteRemote = (props, context) => {
if (locked) {
return (
<NoticeBox>
This interface is locked.
</NoticeBox>
<Window>
<Window.Content>
<NoticeBox>
This interface is locked.
</NoticeBox>
</Window.Content>
</Window>
);
}
@@ -1,5 +1,5 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { useBackend, useLocalState } from '../backend';
import { AnimatedNumber, Button, LabeledList, NoticeBox, ProgressBar, Section, Tabs } from '../components';
import { Window } from '../layouts';
@@ -29,13 +29,28 @@ export const OperatingComputer = (props, context) => {
procedures = [],
patient = {},
} = data;
const [tab, setTab] = useLocalState(context, 'tab', 'state');
return (
<Window>
<Window.Content>
<Tabs>
<Tabs.Tab
key="state"
label="Patient State">
selected={tab==='state'}
onClick={() => setTab('state')}>
Patient State
</Tabs.Tab>
<Tabs.Tab
key="procedures"
selected={tab==='procedures'}
onClick={() => setTab('procedures')}>
Surgery Procedures
</Tabs.Tab>
</Tabs>
{tab === 'state' && (
<Fragment>
{!table && (
<NoticeBox>
No Table Detected
@@ -124,27 +139,117 @@ export const OperatingComputer = (props, context) => {
)}
</Section>
</Section>
</Tabs.Tab>
<Tabs.Tab
key="procedures"
label="Surgery Procedures">
<Section title="Advanced Surgery Procedures">
<Button
icon="download"
content="Sync Research Database"
onClick={() => act('sync')} />
{surgeries.map(surgery => (
<Section
title={surgery.name}
key={surgery.name}
level={2}>
{surgery.desc}
</Section>
))}
</Section>
</Tabs.Tab>
</Tabs>
</Fragment>
)}
{tab === 'procedures' && (
<Section title="Advanced Surgery Procedures">
<Button
icon="download"
content="Sync Research Database"
onClick={() => act('sync')} />
{surgeries.map(surgery => (
<Section
title={surgery.name}
key={surgery.name}
level={2}>
{surgery.desc}
</Section>
))}
</Section>
)}
</Window.Content>
</Window>
);
};
/*
{!table && (
<NoticeBox>
No Table Detected
</NoticeBox>
)}
<Section>
<Section
title="Patient State"
level={2}>
{patient ? (
<LabeledList>
<LabeledList.Item
label="State"
color={patient.statstate}>
{patient.stat}
</LabeledList.Item>
<LabeledList.Item label="Blood Type">
{patient.blood_type}
</LabeledList.Item>
<LabeledList.Item label="Health">
<ProgressBar
value={patient.health}
minValue={patient.minHealth}
maxValue={patient.maxHealth}
color={patient.health >= 0 ? 'good' : 'average'}
content={(
<AnimatedNumber value={patient.health} />
)} />
</LabeledList.Item>
{damageTypes.map(type => (
<LabeledList.Item key={type.type} label={type.label}>
<ProgressBar
value={patient[type.type] / patient.maxHealth}
color="bad"
content={(
<AnimatedNumber value={patient[type.type]} />
)} />
</LabeledList.Item>
))}
</LabeledList>
) : (
'No Patient Detected'
)}
</Section>
<Section
title="Initiated Procedures"
level={2}>
{procedures.length ? (
procedures.map(procedure => (
<Section
key={procedure.name}
title={procedure.name}
level={3}>
<LabeledList>
<LabeledList.Item label="Next Step">
{procedure.next_step}
{procedure.chems_needed && (
<Fragment>
<b>
Required Chemicals:
</b>
<br />
{procedure.chems_needed}
</Fragment>
)}
</LabeledList.Item>
{!!data.alternative_step && (
<LabeledList.Item label="Alternative Step">
{procedure.alternative_step}
{procedure.alt_chems_needed && (
<Fragment>
<b>
Required Chemicals:
</b>
<br />
{procedure.alt_chems_needed}
</Fragment>
)}
</LabeledList.Item>
)}
</LabeledList>
</Section>
))
) : (
'No Active Procedures'
)}
</Section>
</Section>
*/
@@ -1,17 +1,18 @@
import { map } from 'common/collections';
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { Box, Button, Dimmer, Icon, LabeledList, Section, Tabs } from '../components';
import { Box, Button, Dimmer, Flex, Icon, LabeledList, Section, Tabs } from '../components';
import { Window } from '../layouts';
export const PersonalCrafting = (props, context) => {
const { state } = props;
const { act, data } = useBackend(context);
const {
busy,
display_craftable_only,
display_compact,
category,
subcategory,
} = data;
const craftingRecipes = map((subcategory, category) => {
@@ -25,6 +26,10 @@ export const PersonalCrafting = (props, context) => {
firstSubcatName,
};
})(data.crafting_recipes || {});
const currentCategory = craftingRecipes.find(recipeTab => {
return recipeTab.category === category;
});
// Shows an overlay when crafting an item
const busyBox = !!busy && (
@@ -59,44 +64,45 @@ export const PersonalCrafting = (props, context) => {
</Fragment>
)}>
<Tabs>
{craftingRecipes.map(recipe => (
{craftingRecipes.map(recipeTab => (
<Tabs.Tab
key={recipe.category}
label={recipe.category}
key={recipeTab.category}
onClick={() => act('set_category', {
category: recipe.category,
category: recipeTab.category,
subcategory: recipeTab.firstSubcatName,
// Backend expects "0" or "" to indicate no subcategory
subcategory: recipe.firstSubcatName,
})}>
{() => !recipe.hasSubcats && (
<CraftingList
craftables={recipe.subcategory}
state={state} />
) || (
<Tabs vertical>
{map((value, name) => {
if (name === "has_subcats") {
return;
}
return (
<Tabs.Tab
label={name}
onClick={() => act('set_category', {
subcategory: name,
})}>
{() => (
<CraftingList
craftables={value}
state={state} />
)}
</Tabs.Tab>
);
})(recipe.subcategory)}
</Tabs>
)}
})}
selected={category===recipeTab.category}>
{recipeTab.category}
</Tabs.Tab>
))}
</Tabs>
{!currentCategory.hasSubcats && (
<CraftingList craftables={currentCategory.subcategory} />
)
|| (
<Flex direction="row">
<Flex.Item>
<Tabs vertical>
{map((_, subcatName) => (subcatName !== 'has_subcats' && (
<Tabs.Tab
key={subcatName}
onClick={() => act('set_category', {
subcategory: subcatName,
})}
selected={subcategory===subcatName}>
{subcatName}
</Tabs.Tab>
)
))(currentCategory.subcategory)}
{/* {JSON.stringify(currentCategory.subcategory, null, 2)} */}
</Tabs>
</Flex.Item>
<Flex.Item grow={1} basis={0}>
<CraftingList craftables={currentCategory.subcategory[subcategory]} />
</Flex.Item>
</Flex>
)}
</Section>
</Window.Content>
</Window>
@@ -114,6 +120,7 @@ const CraftingList = (props, context) => {
display_compact,
display_craftable_only,
} = data;
return craftables.map(craftable => {
if (display_craftable_only && !craftability[craftable.ref]) {
return null;
@@ -1,5 +1,5 @@
import { classes } from 'common/react';
import { useBackend } from '../backend';
import { useBackend, useLocalState } from '../backend';
import { Box, Button, ColorBox, Flex, LabeledList, Section, Tabs } from '../components';
import { Window } from '../layouts';
@@ -64,6 +64,11 @@ export const RapidPipeDispenser = (props, context) => {
mode,
} = data;
const previews = data.preview_rows.flatMap(row => row.previews);
const [tab, setTab] = useLocalState(context, 'tab', categories[0].cat_name);
const activeCategory = categories.find(category => {
return category.cat_name === tab;
});
return (
<Window>
<Window.Content>
@@ -164,23 +169,24 @@ export const RapidPipeDispenser = (props, context) => {
fluid
key={category.cat_name}
icon={ICON_BY_CATEGORY_NAME[category.cat_name]}
label={category.cat_name}>
{() => category.recipes.map(recipe => (
<Button.Checkbox
key={recipe.pipe_index}
fluid
ellipsis
checked={recipe.selected}
content={recipe.pipe_name}
title={recipe.pipe_name}
onClick={() => act('pipe_type', {
pipe_type: recipe.pipe_index,
category: category.cat_name,
})} />
))}
onClick={() => setTab(category.cat_name)}>
{category.cat_name}
</Tabs.Tab>
))}
</Tabs>
{activeCategory.recipes.map(recipe => (
<Button.Checkbox
key={recipe.pipe_index}
fluid
ellipsis
checked={recipe.selected}
content={recipe.pipe_name}
title={recipe.pipe_name}
onClick={() => act('pipe_type', {
pipe_type: recipe.pipe_index,
category: activeCategory.cat_name,
})} />
))}
</Section>
</Flex.Item>
</Flex>
@@ -1,6 +1,6 @@
import { map } from 'common/collections';
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { useBackend, useLocalState } from '../backend';
import { Button, LabeledList, Section, Table, Tabs } from '../components';
import { Window } from '../layouts';
@@ -10,191 +10,209 @@ export const ShuttleManipulator = (props, context) => {
const templateObject = data.templates || {};
const selected = data.selected || {};
const existingShuttle = data.existing_shuttle || {};
const [tab, setTab] = useLocalState(context, 'tab', 'status');
const [activeTemplate, setActiveTemplate]
= useLocalState(context, 'template', Object.keys(templateObject)[0]);
return (
<Window>
<Window.Content>
<Tabs>
<Tabs.Tab
key="status"
label="Status">
<Section>
<Table>
{shuttles.map(shuttle => (
<Table.Row key={shuttle.id}>
<Table.Cell>
<Button
content="JMP"
key={shuttle.id}
onClick={() => act('jump_to', {
type: 'mobile',
id: shuttle.id,
})} />
</Table.Cell>
<Table.Cell>
<Button
content="Fly"
key={shuttle.id}
disabled={!shuttle.can_fly}
onClick={() => act('fly', {
id: shuttle.id,
})} />
</Table.Cell>
<Table.Cell>
{shuttle.name}
</Table.Cell>
<Table.Cell>
{shuttle.id}
</Table.Cell>
<Table.Cell>
{shuttle.status}
</Table.Cell>
<Table.Cell>
{shuttle.mode}
{!!shuttle.timer && (
<Fragment>
({shuttle.timeleft})
<Button
content="Fast Travel"
key={shuttle.id}
disabled={!shuttle.can_fast_travel}
onClick={() => act('fast_travel', {
id: shuttle.id,
})} />
</Fragment>
)}
</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
selected={tab==='status'}
onClick={() => setTab('status')}>
Status
</Tabs.Tab>
<Tabs.Tab
key="templates"
label="Templates">
<Section>
<Tabs>
{map((template, templateId) => {
const templates = template.templates || [];
return (
<Tabs.Tab
key={templateId}
label={template.port_id}>
{templates.map(actualTemplate => {
const isSelected = (
actualTemplate.shuttle_id === selected.shuttle_id
);
// Whoever made the structure being sent is an asshole
return (
<Section
title={actualTemplate.name}
level={2}
key={actualTemplate.shuttle_id}
buttons={(
<Button
content={isSelected ? 'Selected' : 'Select'}
selected={isSelected}
onClick={() => act('select_template', {
shuttle_id: actualTemplate.shuttle_id,
})} />
)}>
{(!!actualTemplate.description
|| !!actualTemplate.admin_notes
) && (
<LabeledList>
{!!actualTemplate.description && (
<LabeledList.Item label="Description">
{actualTemplate.description}
</LabeledList.Item>
)}
{!!actualTemplate.admin_notes && (
<LabeledList.Item label="Admin Notes">
{actualTemplate.admin_notes}
</LabeledList.Item>
)}
</LabeledList>
)}
</Section>
);
})}
</Tabs.Tab>
);
})(templateObject)}
</Tabs>
</Section>
selected={tab==='templates'}
onClick={() => setTab('templates')}>
Templates
</Tabs.Tab>
<Tabs.Tab
key="modification"
label="Modification">
<Section>
{selected ? (
<Fragment>
<Section
level={2}
title={selected.name}>
{(!!selected.description || !!selected.admin_notes) && (
<LabeledList>
{!!selected.description && (
<LabeledList.Item label="Description">
{selected.description}
</LabeledList.Item>
)}
{!!selected.admin_notes && (
<LabeledList.Item label="Admin Notes">
{selected.admin_notes}
</LabeledList.Item>
)}
</LabeledList>
)}
</Section>
{existingShuttle ? (
<Section
level={2}
title={'Existing Shuttle: ' + existingShuttle.name}>
<LabeledList>
<LabeledList.Item
label="Status"
buttons={(
<Button
content="Jump To"
onClick={() => act('jump_to', {
type: 'mobile',
id: existingShuttle.id,
})} />
)}>
{existingShuttle.status}
{!!existingShuttle.timer && (
<Fragment>
({existingShuttle.timeleft})
</Fragment>
)}
</LabeledList.Item>
</LabeledList>
</Section>
) : (
<Section
level={2}
title="Existing Shuttle: None" />
)}
<Section
level={2}
title="Status">
<Button
content="Preview"
onClick={() => act('preview', {
shuttle_id: selected.shuttle_id,
})} />
<Button
content="Load"
color="bad"
onClick={() => act('load', {
shuttle_id: selected.shuttle_id,
})} />
</Section>
</Fragment>
) : 'No shuttle selected'}
</Section>
selected={tab==='modification'}
onClick={() => setTab('modification')}>
Modification
</Tabs.Tab>
</Tabs>
{tab === 'status' && (
<Section>
<Table>
{shuttles.map(shuttle => (
<Table.Row key={shuttle.id}>
<Table.Cell>
<Button
content="JMP"
key={shuttle.id}
onClick={() => act('jump_to', {
type: 'mobile',
id: shuttle.id,
})} />
</Table.Cell>
<Table.Cell>
<Button
content="Fly"
key={shuttle.id}
disabled={!shuttle.can_fly}
onClick={() => act('fly', {
id: shuttle.id,
})} />
</Table.Cell>
<Table.Cell>
{shuttle.name}
</Table.Cell>
<Table.Cell>
{shuttle.id}
</Table.Cell>
<Table.Cell>
{shuttle.status}
</Table.Cell>
<Table.Cell>
{shuttle.mode}
{!!shuttle.timer && (
<Fragment>
({shuttle.timeleft})
<Button
content="Fast Travel"
key={shuttle.id}
disabled={!shuttle.can_fast_travel}
onClick={() => act('fast_travel', {
id: shuttle.id,
})} />
</Fragment>
)}
</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
)}
{tab === 'templates' && (
<Section>
<Tabs>
{map((template, templateId) => {
const templates = template.templates || [];
return (
<Tabs.Tab
key={templateId}
selected={activeTemplate===templateId}
onClick={() => setActiveTemplate(templateId)}>
{template.port_id}
</Tabs.Tab>
);
})(templateObject)}
</Tabs>
{() => {
const actualTemplate = templateObject[activeTemplate];
const isSelected = (
actualTemplate.shuttle_id === selected.shuttle_id
);
return (
<Section
title={actualTemplate.name}
level={2}
key={actualTemplate.shuttle_id}
buttons={(
<Button
content={isSelected ? 'Selected' : 'Select'}
selected={isSelected}
onClick={() => act('select_template', {
shuttle_id: actualTemplate.shuttle_id,
})} />
)}>
{(!!actualTemplate.description
|| !!actualTemplate.admin_notes
) && (
<LabeledList>
{!!actualTemplate.description && (
<LabeledList.Item label="Description">
{actualTemplate.description}
</LabeledList.Item>
)}
{!!actualTemplate.admin_notes && (
<LabeledList.Item label="Admin Notes">
{actualTemplate.admin_notes}
</LabeledList.Item>
)}
</LabeledList>
)}
</Section>
);
}}
</Section>
)}
{tab === 'modification' && (
<Section>
{selected ? (
<Fragment>
<Section
level={2}
title={selected.name}>
{(!!selected.description || !!selected.admin_notes) && (
<LabeledList>
{!!selected.description && (
<LabeledList.Item label="Description">
{selected.description}
</LabeledList.Item>
)}
{!!selected.admin_notes && (
<LabeledList.Item label="Admin Notes">
{selected.admin_notes}
</LabeledList.Item>
)}
</LabeledList>
)}
</Section>
{existingShuttle ? (
<Section
level={2}
title={'Existing Shuttle: ' + existingShuttle.name}>
<LabeledList>
<LabeledList.Item
label="Status"
buttons={(
<Button
content="Jump To"
onClick={() => act('jump_to', {
type: 'mobile',
id: existingShuttle.id,
})} />
)}>
{existingShuttle.status}
{!!existingShuttle.timer && (
<Fragment>
({existingShuttle.timeleft})
</Fragment>
)}
</LabeledList.Item>
</LabeledList>
</Section>
) : (
<Section
level={2}
title="Existing Shuttle: None" />
)}
<Section
level={2}
title="Status">
<Button
content="Preview"
onClick={() => act('preview', {
shuttle_id: selected.shuttle_id,
})} />
<Button
content="Load"
color="bad"
onClick={() => act('load', {
shuttle_id: selected.shuttle_id,
})} />
</Section>
</Fragment>
) : 'No shuttle selected'}
</Section>
)}
</Window.Content>
</Window>
);
@@ -1,5 +1,5 @@
import { Fragment } from 'inferno';
import { useBackend } from '../backend';
import { useBackend, useLocalState } from '../backend';
import { Button, LabeledList, NoticeBox, Section, Tabs, Input } from '../components';
import { Window } from '../layouts';
@@ -13,6 +13,8 @@ export const TelecommsLogBrowser = (props, context) => {
selected_logs,
} = data;
const operational = (selected && selected.status);
const [tab, setTab] = useLocalState(context, 'tab', 'servers');
return (
<Window>
<Window.Content>
@@ -94,84 +96,91 @@ export const TelecommsLogBrowser = (props, context) => {
<Tabs>
<Tabs.Tab
key="servers"
label="Servers">
<Section>
{(servers && servers.length) ? (
<LabeledList>
{servers.map(server => {
return (
<LabeledList.Item
key={server.name}
label={`${server.ref}`}
buttons={(
<Button
content="Connect"
selected={data.selected
&& (server.ref === data.selected.ref)}
onClick={() => act('viewmachine', {
'value': server.id,
})} />
)}>
{`${server.name} (${server.id})`}
</LabeledList.Item>
);
})}
</LabeledList>
) : (
'404 Servers not found. Have you tried scanning the network?'
)}
</Section>
selected={tab === 'servers'}
onClick={() => setTab('servers')}>
Servers
</Tabs.Tab>
<Tabs.Tab
key="messages"
label="Messages"
disabled={!operational}>
<Section title="Logs">
{(operational && selected_logs) ? (
selected_logs.map(logs => {
return (
<Section
level={4}
key={logs.ref}>
<LabeledList>
<LabeledList.Item
label="Filename"
buttons={(
<Button
content="Delete"
onClick={() => act('delete', {
'value': logs.ref,
})} />
)}>
{logs.name}
</LabeledList.Item>
<LabeledList.Item label="Data type">
{logs.input_type}
</LabeledList.Item>
{logs.source && (
<LabeledList.Item label="Source">
{/* eslint-disable-next-line max-len */}
{`[${logs.source.name}] (Job: [${logs.source.job}])`}
</LabeledList.Item>
)}
{logs.race && (
<LabeledList.Item label="Class">
{logs.race}
</LabeledList.Item>
)}
<LabeledList.Item label="Contents">
{logs.message}
</LabeledList.Item>
</LabeledList>
</Section>
);
})
) : (
"No server selected!"
)}
</Section>
disabled={!operational}
selected={tab === 'messages'}
onClick={() => setTab('messages')}>
Messages
</Tabs.Tab>
</Tabs>
{tab === 'servers' && (
<Section>
{(servers && servers.length) ? (
<LabeledList>
{servers.map(server => {
return (
<LabeledList.Item
key={server.name}
label={`${server.ref}`}
buttons={(
<Button
content="Connect"
selected={data.selected
&& (server.ref === data.selected.ref)}
onClick={() => act('viewmachine', {
'value': server.id,
})} />
)}>
{`${server.name} (${server.id})`}
</LabeledList.Item>
);
})}
</LabeledList>
) : (
'404 Servers not found. Have you tried scanning the network?'
)}
</Section>
)}
{tab === 'messages' && (
<Section title="Logs">
{(operational && selected_logs) ? (
selected_logs.map(logs => {
return (
<Section
level={4}
key={logs.ref}>
<LabeledList>
<LabeledList.Item
label="Filename"
buttons={(
<Button
content="Delete"
onClick={() => act('delete', {
'value': logs.ref,
})} />
)}>
{logs.name}
</LabeledList.Item>
<LabeledList.Item label="Data type">
{logs.input_type}
</LabeledList.Item>
{logs.source && (
<LabeledList.Item label="Source">
{`[${logs.source.name}] (Job: [${logs.source.job}])`}
</LabeledList.Item>
)}
{logs.race && (
<LabeledList.Item label="Class">
{logs.race}
</LabeledList.Item>
)}
<LabeledList.Item label="Contents">
{logs.message}
</LabeledList.Item>
</LabeledList>
</Section>
);
})
) : (
"No server selected!"
)}
</Section>
)}
</Window.Content>
</Window>
);
File diff suppressed because one or more lines are too long