mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Vending - Tank Dispenser
vending vault controller turbine computer uplink fix for turbine computer transfer valve timer thermomachine teleporter Tank Tank Dispenser
This commit is contained in:
committed by
Aleksej Komarov
parent
8b63e1acf7
commit
775c318d92
@@ -1,54 +1,59 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, NumberInput, ProgressBar, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Tank = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Tank = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<ProgressBar
|
||||
value={data.tankPressure / 1013}
|
||||
ranges={{
|
||||
good: [0.35, Infinity],
|
||||
average: [0.15, 0.35],
|
||||
bad: [-Infinity, 0.15],
|
||||
}}>
|
||||
{data.tankPressure + ' kPa'}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure Regulator">
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={data.ReleasePressure === data.minReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'min',
|
||||
})} />
|
||||
<NumberInput
|
||||
animated
|
||||
value={parseFloat(data.releasePressure)}
|
||||
width="65px"
|
||||
unit="kPa"
|
||||
minValue={data.minReleasePressure}
|
||||
maxValue={data.maxReleasePressure}
|
||||
onChange={(e, value) => act('pressure', {
|
||||
pressure: value,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={data.ReleasePressure === data.maxReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'max',
|
||||
})} />
|
||||
<Button
|
||||
icon="undo"
|
||||
content=""
|
||||
disabled={data.ReleasePressure === data.defaultReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'reset',
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<ProgressBar
|
||||
value={data.tankPressure / 1013}
|
||||
ranges={{
|
||||
good: [0.35, Infinity],
|
||||
average: [0.15, 0.35],
|
||||
bad: [-Infinity, 0.15],
|
||||
}}>
|
||||
{data.tankPressure + ' kPa'}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure Regulator">
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={data.ReleasePressure === data.minReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'min',
|
||||
})} />
|
||||
<NumberInput
|
||||
animated
|
||||
value={parseFloat(data.releasePressure)}
|
||||
width="65px"
|
||||
unit="kPa"
|
||||
minValue={data.minReleasePressure}
|
||||
maxValue={data.maxReleasePressure}
|
||||
onChange={(e, value) => act('pressure', {
|
||||
pressure: value,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={data.ReleasePressure === data.maxReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'max',
|
||||
})} />
|
||||
<Button
|
||||
icon="undo"
|
||||
content=""
|
||||
disabled={data.ReleasePressure === data.defaultReleasePressure}
|
||||
onClick={() => act('pressure', {
|
||||
pressure: 'reset',
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const TankDispenser = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const TankDispenser = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Plasma"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={data.plasma ? 'square' : 'square-o'}
|
||||
content="Dispense"
|
||||
disabled={!data.plasma}
|
||||
onClick={() => act('plasma')} />
|
||||
)}>
|
||||
{data.plasma}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Oxygen"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={data.oxygen ? 'square' : 'square-o'}
|
||||
content="Dispense"
|
||||
disabled={!data.oxygen}
|
||||
onClick={() => act('oxygen')} />
|
||||
)}>
|
||||
{data.oxygen}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Plasma"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={data.plasma ? 'square' : 'square-o'}
|
||||
content="Dispense"
|
||||
disabled={!data.plasma}
|
||||
onClick={() => act('plasma')} />
|
||||
)}>
|
||||
{data.plasma}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Oxygen"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={data.oxygen ? 'square' : 'square-o'}
|
||||
content="Dispense"
|
||||
disabled={!data.oxygen}
|
||||
onClick={() => act('oxygen')} />
|
||||
)}>
|
||||
{data.oxygen}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Teleporter = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Teleporter = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
calibrated,
|
||||
calibrating,
|
||||
@@ -12,58 +13,62 @@ export const Teleporter = props => {
|
||||
target,
|
||||
} = data;
|
||||
return (
|
||||
<Section>
|
||||
{!power_station && (
|
||||
<Box color="bad" textAlign="center">
|
||||
No power station linked.
|
||||
</Box>
|
||||
) || (!teleporter_hub && (
|
||||
<Box color="bad" textAlign="center">
|
||||
No hub linked.
|
||||
</Box>
|
||||
)) || (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Current Regime"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Change Regime"
|
||||
onClick={() => act('regimeset')} />
|
||||
)}>
|
||||
{regime_set}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Current Target"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Set Target"
|
||||
onClick={() => act('settarget')} />
|
||||
)}>
|
||||
{target}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Calibration"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Calibrate Hub"
|
||||
onClick={() => act('calibrate')} />
|
||||
)}>
|
||||
{calibrating && (
|
||||
<Box color="average">
|
||||
In Progress
|
||||
</Box>
|
||||
) || (calibrated && (
|
||||
<Box color="good">
|
||||
Optimal
|
||||
</Box>
|
||||
) || (
|
||||
<Box color="bad">
|
||||
Sub-Optimal
|
||||
</Box>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Section>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section>
|
||||
{!power_station && (
|
||||
<Box color="bad" textAlign="center">
|
||||
No power station linked.
|
||||
</Box>
|
||||
) || (!teleporter_hub && (
|
||||
<Box color="bad" textAlign="center">
|
||||
No hub linked.
|
||||
</Box>
|
||||
)) || (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Current Regime"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Change Regime"
|
||||
onClick={() => act('regimeset')} />
|
||||
)}>
|
||||
{regime_set}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Current Target"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Set Target"
|
||||
onClick={() => act('settarget')} />
|
||||
)}>
|
||||
{target}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Calibration"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="tools"
|
||||
content="Calibrate Hub"
|
||||
onClick={() => act('calibrate')} />
|
||||
)}>
|
||||
{calibrating && (
|
||||
<Box color="average">
|
||||
In Progress
|
||||
</Box>
|
||||
) || (calibrated && (
|
||||
<Box color="good">
|
||||
Optimal
|
||||
</Box>
|
||||
) || (
|
||||
<Box color="bad">
|
||||
Sub-Optimal
|
||||
</Box>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,76 +2,79 @@ import { toFixed } from 'common/math';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { AnimatedNumber, Button, LabeledList, NumberInput, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const ThermoMachine = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const ThermoMachine = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Fragment>
|
||||
<Section title="Status">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Temperature">
|
||||
<AnimatedNumber
|
||||
value={data.temperature}
|
||||
format={value => toFixed(value, 2)} />
|
||||
{' K'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber
|
||||
value={data.pressure}
|
||||
format={value => toFixed(value, 2)} />
|
||||
{' kPa'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Controls"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={data.on ? 'power-off' : 'times'}
|
||||
content={data.on ? 'On' : 'Off'}
|
||||
selected={data.on}
|
||||
onClick={() => act('power')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Target Temperature">
|
||||
<NumberInput
|
||||
animated
|
||||
value={Math.round(data.target)}
|
||||
unit="K"
|
||||
width="62px"
|
||||
minValue={Math.round(data.min)}
|
||||
maxValue={Math.round(data.max)}
|
||||
step={5}
|
||||
stepPixelSize={3}
|
||||
onDrag={(e, value) => act('target', {
|
||||
target: value,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Presets">
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section title="Status">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Temperature">
|
||||
<AnimatedNumber
|
||||
value={data.temperature}
|
||||
format={value => toFixed(value, 2)} />
|
||||
{' K'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Pressure">
|
||||
<AnimatedNumber
|
||||
value={data.pressure}
|
||||
format={value => toFixed(value, 2)} />
|
||||
{' kPa'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Controls"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={data.target === data.min}
|
||||
title="Minimum temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.min,
|
||||
})} />
|
||||
<Button
|
||||
icon="sync"
|
||||
disabled={data.target === data.initial}
|
||||
title="Room Temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.initial,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={data.target === data.max}
|
||||
title="Maximum Temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.max,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Fragment>
|
||||
icon={data.on ? 'power-off' : 'times'}
|
||||
content={data.on ? 'On' : 'Off'}
|
||||
selected={data.on}
|
||||
onClick={() => act('power')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Target Temperature">
|
||||
<NumberInput
|
||||
animated
|
||||
value={Math.round(data.target)}
|
||||
unit="K"
|
||||
width="62px"
|
||||
minValue={Math.round(data.min)}
|
||||
maxValue={Math.round(data.max)}
|
||||
step={5}
|
||||
stepPixelSize={3}
|
||||
onDrag={(e, value) => act('target', {
|
||||
target: value,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Presets">
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={data.target === data.min}
|
||||
title="Minimum temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.min,
|
||||
})} />
|
||||
<Button
|
||||
icon="sync"
|
||||
disabled={data.target === data.initial}
|
||||
title="Room Temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.initial,
|
||||
})} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={data.target === data.max}
|
||||
title="Maximum Temperature"
|
||||
onClick={() => act('target', {
|
||||
target: data.max,
|
||||
})} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Timer = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const Timer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
minutes,
|
||||
seconds,
|
||||
@@ -11,42 +12,46 @@ export const Timer = props => {
|
||||
loop,
|
||||
} = data;
|
||||
return (
|
||||
<Section
|
||||
title="Timing Unit"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section
|
||||
title="Timing Unit"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Button
|
||||
icon={'sync'}
|
||||
content={loop ? 'Repeating' : 'Repeat'}
|
||||
selected={loop}
|
||||
onClick={() => act('repeat')} />
|
||||
<Button
|
||||
icon={"clock-o"}
|
||||
content={timing ? 'Stop' : 'Start'}
|
||||
selected={timing}
|
||||
onClick={() => act('time')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<Button
|
||||
icon={'sync'}
|
||||
content={loop ? 'Repeating' : 'Repeat'}
|
||||
selected={loop}
|
||||
onClick={() => act('repeat')} />
|
||||
icon="fast-backward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: -30 })} />
|
||||
<Button
|
||||
icon={"clock-o"}
|
||||
content={timing ? 'Stop' : 'Start'}
|
||||
selected={timing}
|
||||
onClick={() => act('time')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
<Button
|
||||
icon="fast-backward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: -30 })} />
|
||||
<Button
|
||||
icon="backward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: -1 })} />
|
||||
{' '}
|
||||
{String(minutes).padStart(2, '0')}:
|
||||
{String(seconds).padStart(2, '0')}
|
||||
{' '}
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: 1 })} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: 30 })} />
|
||||
</Section>
|
||||
icon="backward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: -1 })} />
|
||||
{' '}
|
||||
{String(minutes).padStart(2, '0')}:
|
||||
{String(seconds).padStart(2, '0')}
|
||||
{' '}
|
||||
<Button
|
||||
icon="forward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: 1 })} />
|
||||
<Button
|
||||
icon="fast-forward"
|
||||
disabled={timing}
|
||||
onClick={() => act('input', { adjust: 30 })} />
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, NoticeBox, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const TransferValve = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const TransferValve = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
tank_one,
|
||||
tank_two,
|
||||
@@ -11,78 +12,80 @@ export const TransferValve = props => {
|
||||
valve,
|
||||
} = data;
|
||||
return (
|
||||
<Fragment>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Valve Status">
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Valve Status">
|
||||
<Button
|
||||
icon={valve ? "unlock" : "lock"}
|
||||
content={valve ? "Open" : "Closed"}
|
||||
disabled={!tank_one || !tank_two}
|
||||
onClick={() => act('toggle')} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Valve Attachment"
|
||||
buttons={(
|
||||
<Button
|
||||
icon={valve ? "unlock" : "lock"}
|
||||
content={valve ? "Open" : "Closed"}
|
||||
disabled={!tank_one || !tank_two}
|
||||
onClick={() => act('toggle')} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section
|
||||
title="Valve Attachment"
|
||||
buttons={(
|
||||
<Button
|
||||
textAlign="center"
|
||||
width="30px"
|
||||
icon={"cog"}
|
||||
disabled={(!attached_device)}
|
||||
onClick={() => act('device')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
{attached_device ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={attached_device}
|
||||
disabled={!attached_device}
|
||||
onClick={() => act('remove_device')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Assembly
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Attachment One">
|
||||
<LabeledList>
|
||||
{tank_one ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={tank_one}
|
||||
disabled={!tank_one}
|
||||
onClick={() => act('tankone')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Tank
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Attachment Two">
|
||||
<LabeledList>
|
||||
{tank_two ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={tank_two}
|
||||
disabled={!tank_two}
|
||||
onClick={() => act('tanktwo')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Tank
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Fragment>
|
||||
textAlign="center"
|
||||
width="30px"
|
||||
icon={"cog"}
|
||||
disabled={(!attached_device)}
|
||||
onClick={() => act('device')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
{attached_device ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={attached_device}
|
||||
disabled={!attached_device}
|
||||
onClick={() => act('remove_device')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Assembly
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Attachment One">
|
||||
<LabeledList>
|
||||
{tank_one ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={tank_one}
|
||||
disabled={!tank_one}
|
||||
onClick={() => act('tankone')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Tank
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Attachment Two">
|
||||
<LabeledList>
|
||||
{tank_two ? (
|
||||
<LabeledList.Item label="Attachment">
|
||||
<Button
|
||||
icon={"wrench"}
|
||||
content={tank_two}
|
||||
disabled={!tank_two}
|
||||
onClick={() => act('tanktwo')} />
|
||||
</LabeledList.Item>
|
||||
) : (
|
||||
<NoticeBox textAlign="center">
|
||||
Insert Tank
|
||||
</NoticeBox>
|
||||
)}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,64 +1,69 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const TurbineComputer = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const TurbineComputer = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const operational = Boolean(data.compressor
|
||||
&& !data.compressor_broke
|
||||
&& data.turbine
|
||||
&& !data.turbine_broke);
|
||||
return (
|
||||
<Section
|
||||
title="Status"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Button
|
||||
icon={data.online ? 'power-off' : 'times'}
|
||||
content={data.online ? 'Online' : 'Offline'}
|
||||
selected={data.online}
|
||||
disabled={!operational}
|
||||
onClick={() => act('toggle_power')} />
|
||||
<Button
|
||||
icon="sync"
|
||||
content="Reconnect"
|
||||
onClick={() => act('reconnect')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
{!operational && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Compressor Status"
|
||||
color={(!data.compressor || data.compressor_broke)
|
||||
? 'bad'
|
||||
: 'good'}>
|
||||
{data.compressor_broke
|
||||
? data.compressor ? 'Offline' : 'Missing'
|
||||
: 'Online'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Turbine Status"
|
||||
color={(!data.turbine || data.turbine_broke)
|
||||
? 'bad'
|
||||
: 'good'}>
|
||||
{data.turbine_broke
|
||||
? data.turbine ? 'Offline' : 'Missing'
|
||||
: 'Online'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) || (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Turbine Speed">
|
||||
{data.rpm} RPM
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Internal Temp">
|
||||
{data.temp} K
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Generated Power">
|
||||
{data.power}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Section>
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section
|
||||
title="Status"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Button
|
||||
icon={data.online ? 'power-off' : 'times'}
|
||||
content={data.online ? 'Online' : 'Offline'}
|
||||
selected={data.online}
|
||||
disabled={!operational}
|
||||
onClick={() => act('toggle_power')} />
|
||||
<Button
|
||||
icon="sync"
|
||||
content="Reconnect"
|
||||
onClick={() => act('reconnect')} />
|
||||
</Fragment>
|
||||
)}>
|
||||
{!operational && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item
|
||||
label="Compressor Status"
|
||||
color={(!data.compressor || data.compressor_broke)
|
||||
? 'bad'
|
||||
: 'good'}>
|
||||
{data.compressor_broke
|
||||
? data.compressor ? 'Offline' : 'Missing'
|
||||
: 'Online'}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item
|
||||
label="Turbine Status"
|
||||
color={(!data.turbine || data.turbine_broke)
|
||||
? 'bad'
|
||||
: 'good'}>
|
||||
{data.turbine_broke
|
||||
? data.turbine ? 'Offline' : 'Missing'
|
||||
: 'Online'}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) || (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Turbine Speed">
|
||||
{data.rpm} RPM
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Internal Temp">
|
||||
{data.temp} K
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Generated Power">
|
||||
{data.power}
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
)}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,6 +2,8 @@ import { decodeHtmlEntities } from 'common/string';
|
||||
import { Component, Fragment } from 'inferno';
|
||||
import { act } from '../byond';
|
||||
import { Box, Button, Input, Section, Table, Tabs } from '../components';
|
||||
import { useBackend } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
// It's a class because we need to store state in the form of the current
|
||||
// hovered item, and current search terms
|
||||
@@ -27,9 +29,7 @@ export class Uplink extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { state } = this.props;
|
||||
const { config, data } = state;
|
||||
const { ref } = config;
|
||||
const { act, data } = useBackend(this.context);
|
||||
const {
|
||||
compact_mode,
|
||||
lockable,
|
||||
@@ -38,84 +38,90 @@ export class Uplink extends Component {
|
||||
} = data;
|
||||
const { hoveredItem, currentSearch } = this.state;
|
||||
return (
|
||||
<Section
|
||||
title={(
|
||||
<Box
|
||||
inline
|
||||
color={telecrystals > 0 ? 'good' : 'bad'}>
|
||||
{telecrystals} TC
|
||||
</Box>
|
||||
)}
|
||||
buttons={(
|
||||
<Fragment>
|
||||
Search
|
||||
<Input
|
||||
value={currentSearch}
|
||||
onInput={(e, value) => this.setSearchText(value)}
|
||||
ml={1}
|
||||
mr={1} />
|
||||
<Button
|
||||
icon={compact_mode ? 'list' : 'info'}
|
||||
content={compact_mode ? 'Compact' : 'Detailed'}
|
||||
onClick={() => act(ref, 'compact_toggle')} />
|
||||
{!!lockable && (
|
||||
<Button
|
||||
icon="lock"
|
||||
content="Lock"
|
||||
onClick={() => act(ref, 'lock')} />
|
||||
<Window
|
||||
theme="syndicate"
|
||||
resizable>
|
||||
<Window.Content scrollable>
|
||||
<Section
|
||||
title={(
|
||||
<Box
|
||||
inline
|
||||
color={telecrystals > 0 ? 'good' : 'bad'}>
|
||||
{telecrystals} TC
|
||||
</Box>
|
||||
)}
|
||||
</Fragment>
|
||||
)}>
|
||||
{currentSearch.length > 0 ? (
|
||||
<table className="Table">
|
||||
<ItemList
|
||||
compact
|
||||
items={categories
|
||||
.flatMap(category => {
|
||||
return category.items || [];
|
||||
})
|
||||
.filter(item => {
|
||||
const searchTerm = currentSearch.toLowerCase();
|
||||
const searchableString = String(item.name + item.desc)
|
||||
.toLowerCase();
|
||||
return searchableString.includes(searchTerm);
|
||||
buttons={(
|
||||
<Fragment>
|
||||
Search
|
||||
<Input
|
||||
value={currentSearch}
|
||||
onInput={(e, value) => this.setSearchText(value)}
|
||||
ml={1}
|
||||
mr={1} />
|
||||
<Button
|
||||
icon={compact_mode ? 'list' : 'info'}
|
||||
content={compact_mode ? 'Compact' : 'Detailed'}
|
||||
onClick={() => act('compact_toggle')} />
|
||||
{!!lockable && (
|
||||
<Button
|
||||
icon="lock"
|
||||
content="Lock"
|
||||
onClick={() => act('lock')} />
|
||||
)}
|
||||
</Fragment>
|
||||
)}>
|
||||
{currentSearch.length > 0 ? (
|
||||
<table className="Table">
|
||||
<ItemList
|
||||
compact
|
||||
items={categories
|
||||
.flatMap(category => {
|
||||
return category.items || [];
|
||||
})
|
||||
.filter(item => {
|
||||
const searchTerm = currentSearch.toLowerCase();
|
||||
const searchableString = String(item.name + item.desc)
|
||||
.toLowerCase();
|
||||
return searchableString.includes(searchTerm);
|
||||
})}
|
||||
hoveredItem={hoveredItem}
|
||||
onBuyMouseOver={item => this.setHoveredItem(item)}
|
||||
onBuyMouseOut={item => this.setHoveredItem({})}
|
||||
onBuy={item => act('buy', {
|
||||
item: item.name,
|
||||
})} />
|
||||
</table>
|
||||
) : (
|
||||
<Tabs vertical>
|
||||
{categories.map(category => {
|
||||
const { name, items } = category;
|
||||
if (items === null) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={name}
|
||||
label={`${name} (${items.length})`}>
|
||||
{() => (
|
||||
<ItemList
|
||||
compact={compact_mode}
|
||||
items={items}
|
||||
hoveredItem={hoveredItem}
|
||||
telecrystals={telecrystals}
|
||||
onBuyMouseOver={item => this.setHoveredItem(item)}
|
||||
onBuyMouseOut={item => this.setHoveredItem({})}
|
||||
onBuy={item => act('buy', {
|
||||
item: item.name,
|
||||
})} />
|
||||
)}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
hoveredItem={hoveredItem}
|
||||
onBuyMouseOver={item => this.setHoveredItem(item)}
|
||||
onBuyMouseOut={item => this.setHoveredItem({})}
|
||||
onBuy={item => act(ref, 'buy', {
|
||||
item: item.name,
|
||||
})} />
|
||||
</table>
|
||||
) : (
|
||||
<Tabs vertical>
|
||||
{categories.map(category => {
|
||||
const { name, items } = category;
|
||||
if (items === null) {
|
||||
return;
|
||||
}
|
||||
return (
|
||||
<Tabs.Tab
|
||||
key={name}
|
||||
label={`${name} (${items.length})`}>
|
||||
{() => (
|
||||
<ItemList
|
||||
compact={compact_mode}
|
||||
items={items}
|
||||
hoveredItem={hoveredItem}
|
||||
telecrystals={telecrystals}
|
||||
onBuyMouseOver={item => this.setHoveredItem(item)}
|
||||
onBuyMouseOut={item => this.setHoveredItem({})}
|
||||
onBuy={item => act(ref, 'buy', {
|
||||
item: item.name,
|
||||
})} />
|
||||
)}
|
||||
</Tabs.Tab>
|
||||
);
|
||||
})}
|
||||
</Tabs>
|
||||
)}
|
||||
</Section>
|
||||
</Tabs>
|
||||
)}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,38 @@
|
||||
import { toFixed } from 'common/math';
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, LabeledList, ProgressBar, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const VaultController = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const VaultController = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Section
|
||||
title="Lock Status: "
|
||||
buttons={(
|
||||
<Button
|
||||
content={data.doorstatus ? 'Locked' : 'Unlocked'}
|
||||
icon={data.doorstatus ? 'lock' : 'unlock'}
|
||||
disabled={data.stored < data.max}
|
||||
onClick={() => act('togglelock')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Charge">
|
||||
<ProgressBar
|
||||
value={data.stored / data.max}
|
||||
ranges={{
|
||||
good: [1, Infinity],
|
||||
average: [0.30, 1],
|
||||
bad: [-Infinity, 0.30],
|
||||
}}>
|
||||
{toFixed(data.stored / 1000) + ' / '
|
||||
<Window>
|
||||
<Window.Content>
|
||||
<Section
|
||||
title="Lock Status: "
|
||||
buttons={(
|
||||
<Button
|
||||
content={data.doorstatus ? 'Locked' : 'Unlocked'}
|
||||
icon={data.doorstatus ? 'lock' : 'unlock'}
|
||||
disabled={data.stored < data.max}
|
||||
onClick={() => act('togglelock')} />
|
||||
)}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Charge">
|
||||
<ProgressBar
|
||||
value={data.stored / data.max}
|
||||
ranges={{
|
||||
good: [1, Infinity],
|
||||
average: [0.30, 1],
|
||||
bad: [-Infinity, 0.30],
|
||||
}}>
|
||||
{toFixed(data.stored / 1000) + ' / '
|
||||
+ toFixed(data.max / 1000) + ' kW'}
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</ProgressBar>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,9 +2,95 @@ import { classes } from 'common/react';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Section, Table } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Vending = props => {
|
||||
const { act, data } = useBackend(props);
|
||||
export const VendingRow = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
product,
|
||||
productStock,
|
||||
custom,
|
||||
} = props;
|
||||
|
||||
const free = (
|
||||
!data.onstation
|
||||
|| product.price === 0
|
||||
|| (
|
||||
!product.premium
|
||||
&& data.department
|
||||
&& data.user
|
||||
&& data.department === data.user.department
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<Table.Row>
|
||||
<Table.Cell collapsing>
|
||||
{product.base64 ? (
|
||||
<img
|
||||
src={`data:image/jpeg;base64,${product.img}`}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'horizontal-align': 'middle',
|
||||
}} />
|
||||
) : (
|
||||
<span
|
||||
className={classes([
|
||||
'vending32x32',
|
||||
product.path,
|
||||
])}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'horizontal-align': 'middle',
|
||||
}} />
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell bold>
|
||||
{product.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing textAlign="center">
|
||||
<Box
|
||||
color={custom
|
||||
? 'good'
|
||||
: productStock <= 0
|
||||
? 'bad'
|
||||
: productStock <= (product.max_amount / 2)
|
||||
? 'average'
|
||||
: 'good'}>
|
||||
{productStock} in stock
|
||||
</Box>
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing textAlign="center">
|
||||
{custom && (
|
||||
<Button
|
||||
content={data.access ? 'FREE' : product.price + ' cr'}
|
||||
onClick={() => act('dispense', {
|
||||
'item': product.name,
|
||||
})} />
|
||||
) || (
|
||||
<Button
|
||||
disabled={(
|
||||
productStock === 0
|
||||
|| (
|
||||
!free && (
|
||||
!data.user
|
||||
|| product.price > data.user.cash
|
||||
)
|
||||
)
|
||||
)}
|
||||
content={free ? 'FREE' : product.price + ' cr'}
|
||||
onClick={() => act('vend', {
|
||||
'ref': product.ref,
|
||||
})} />
|
||||
)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
);
|
||||
};
|
||||
|
||||
export const Vending = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
let inventory;
|
||||
let custom = false;
|
||||
if (data.vending_machine_input) {
|
||||
@@ -23,104 +109,39 @@ export const Vending = props => {
|
||||
];
|
||||
}
|
||||
return (
|
||||
<Fragment>
|
||||
{!!data.onstation && (
|
||||
<Section title="User">
|
||||
{data.user && (
|
||||
<Box>
|
||||
Welcome, <b>{data.user.name}</b>,
|
||||
{' '}
|
||||
<b>{data.user.job || "Unemployed"}</b>!
|
||||
<br />
|
||||
Your balance is <b>{data.user.cash} credits</b>.
|
||||
</Box>
|
||||
) || (
|
||||
<Box color="light-gray">
|
||||
No registered ID card!<br />
|
||||
Please contact your local HoP!
|
||||
</Box>
|
||||
)}
|
||||
<Window resizable>
|
||||
<Window.Content scrollable>
|
||||
{!!data.onstation && (
|
||||
<Section title="User">
|
||||
{data.user && (
|
||||
<Box>
|
||||
Welcome, <b>{data.user.name}</b>,
|
||||
{' '}
|
||||
<b>{data.user.job || "Unemployed"}</b>!
|
||||
<br />
|
||||
Your balance is <b>{data.user.cash} credits</b>.
|
||||
</Box>
|
||||
) || (
|
||||
<Box color="light-gray">
|
||||
No registered ID card!<br />
|
||||
Please contact your local HoP!
|
||||
</Box>
|
||||
)}
|
||||
</Section>
|
||||
)}
|
||||
<Section title="Products" >
|
||||
<Table>
|
||||
{inventory.map(product => (
|
||||
<VendingRow
|
||||
key={product.name}
|
||||
custom={custom}
|
||||
product={product}
|
||||
productStock={data.stock[product.name]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
</Section>
|
||||
)}
|
||||
<Section title="Products" >
|
||||
<Table>
|
||||
{inventory.map((product => {
|
||||
const free = (
|
||||
!data.onstation
|
||||
|| product.price === 0
|
||||
|| (
|
||||
!product.premium
|
||||
&& data.department
|
||||
&& data.user
|
||||
&& data.department === data.user.department
|
||||
)
|
||||
);
|
||||
return (
|
||||
<Table.Row key={product.name}>
|
||||
<Table.Cell collapsing>
|
||||
{product.base64 ? (
|
||||
<img
|
||||
src={`data:image/jpeg;base64,${product.img}`}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'horizontal-align': 'middle',
|
||||
}} />
|
||||
) : (
|
||||
<span
|
||||
className={classes([
|
||||
'vending32x32',
|
||||
product.path,
|
||||
])}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'horizontal-align': 'middle',
|
||||
}} />
|
||||
)}
|
||||
</Table.Cell>
|
||||
<Table.Cell bold>
|
||||
{product.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing textAlign="center">
|
||||
<Box
|
||||
color={custom
|
||||
? 'good'
|
||||
: data.stock[product.name] <= 0
|
||||
? 'bad'
|
||||
: data.stock[product.name] <= (product.max_amount / 2)
|
||||
? 'average'
|
||||
: 'good'}>
|
||||
{data.stock[product.name]} in stock
|
||||
</Box>
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing textAlign="center">
|
||||
{custom && (
|
||||
<Button
|
||||
content={data.access ? 'FREE' : product.price + ' cr'}
|
||||
onClick={() => act('dispense', {
|
||||
'item': product.name,
|
||||
})} />
|
||||
) || (
|
||||
<Button
|
||||
disabled={(
|
||||
data.stock[product.namename] === 0
|
||||
|| (
|
||||
!free && (
|
||||
!data.user
|
||||
|| product.price > data.user.cash
|
||||
)
|
||||
)
|
||||
)}
|
||||
content={free ? 'FREE' : product.price + ' cr'}
|
||||
onClick={() => act('vend', {
|
||||
'ref': product.ref,
|
||||
})} />
|
||||
)}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
);
|
||||
}))}
|
||||
</Table>
|
||||
</Section>
|
||||
</Fragment>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user