mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
no thoughts, head segfaulted
This commit is contained in:
@@ -39,6 +39,10 @@ export const loadSourceMaps = async bundleDir => {
|
||||
};
|
||||
|
||||
export const retrace = stack => {
|
||||
if (typeof stack !== 'string') {
|
||||
logger.log('ERROR: Stack is not a string!', stack);
|
||||
return stack;
|
||||
}
|
||||
const header = stack.split(/\n\s.*at/)[0];
|
||||
const mappedStack = StackTraceParser.parse(stack)
|
||||
.map(frame => {
|
||||
|
||||
127
tgui/packages/tgui/interfaces/AtmosControlPanel.js
Normal file
127
tgui/packages/tgui/interfaces/AtmosControlPanel.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import { map, sortBy } from 'common/collections';
|
||||
import { flow } from 'common/fp';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Flex, Section, Table } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const AtmosControlPanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const groups = flow([
|
||||
map((group, i) => ({
|
||||
...group,
|
||||
// Generate a unique id
|
||||
id: group.area + i,
|
||||
})),
|
||||
sortBy(group => group.id),
|
||||
])(data.excited_groups);
|
||||
return (
|
||||
<Window
|
||||
title="SSAir Control Panel"
|
||||
width={900}
|
||||
height={500}
|
||||
resizable>
|
||||
<Section m={1}>
|
||||
<Flex
|
||||
justify="space-between"
|
||||
align="baseline">
|
||||
<Flex.Item>
|
||||
<Button
|
||||
onClick={() => act('toggle-freeze')}
|
||||
color={data.frozen === 1 ? 'good' : 'bad'}>
|
||||
{data.frozen === 1
|
||||
? 'Freeze Subsystem'
|
||||
: 'Unfreeze Subsystem'}
|
||||
</Button>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
Fire Cnt: {data.fire_count}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
Active Turfs: {data.active_size}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
Excited Groups: {data.excited_size}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
Hotspots: {data.hotspots_size}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
Superconductors: {data.conducting_size}
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button.Checkbox
|
||||
checked={data.showing_user}
|
||||
onClick={() => act('toggle_user_display')}>
|
||||
Personal View
|
||||
</Button.Checkbox>
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button.Checkbox
|
||||
checked={data.show_all}
|
||||
onClick={() => act('toggle_show_all')}>
|
||||
Display all
|
||||
</Button.Checkbox>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
<Box fillPositionedParent top="45px">
|
||||
<Window.Content scrollable>
|
||||
<Section>
|
||||
<Table>
|
||||
<Table.Row header>
|
||||
<Table.Cell>
|
||||
Area Name
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
Breakdown
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
Dismantle
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
Turfs
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
{data.display_max === 1 && "Max Share"}
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing>
|
||||
Display
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{groups.map(group => (
|
||||
<tr key={group.id}>
|
||||
<td>
|
||||
<Button
|
||||
content={group.area}
|
||||
onClick={() => act('move-to-target', {
|
||||
spot: group.jump_to,
|
||||
})} />
|
||||
</td>
|
||||
<td>
|
||||
{group.breakdown}
|
||||
</td>
|
||||
<td>
|
||||
{group.dismantle}
|
||||
</td>
|
||||
<td>
|
||||
{group.size}
|
||||
</td>
|
||||
<td>
|
||||
{data.display_max === 1 && group.max_share}
|
||||
</td>
|
||||
<td>
|
||||
<Button.Checkbox
|
||||
checked={group.should_show}
|
||||
onClick={() => act('toggle_show_group', {
|
||||
group: group.group,
|
||||
})} />
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</Table>
|
||||
</Section>
|
||||
</Window.Content>
|
||||
</Box>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import { createSearch } from 'common/string';
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import { Button, ByondUi, Input, Section } from '../components';
|
||||
import { refocusLayout, Window } from '../layouts';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
/**
|
||||
* Returns previous and next camera names relative to the currently
|
||||
@@ -123,12 +123,9 @@ export const CameraConsoleContent = (props, context) => {
|
||||
&& camera.name === activeCamera.name
|
||||
&& 'Button--selected',
|
||||
])}
|
||||
onClick={() => {
|
||||
refocusLayout();
|
||||
act('switch_camera', {
|
||||
name: camera.name,
|
||||
});
|
||||
}}>
|
||||
onClick={() => act('switch_camera', {
|
||||
name: camera.name,
|
||||
})}>
|
||||
{camera.name}
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -20,34 +20,36 @@ export const Cargo = (props, context) => {
|
||||
resizable>
|
||||
<Window.Content scrollable>
|
||||
<CargoStatus />
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
icon="list"
|
||||
selected={tab === 'catalog'}
|
||||
onClick={() => setTab('catalog')}>
|
||||
Catalog
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
icon="envelope"
|
||||
textColor={tab !== 'requests'
|
||||
&& requests.length > 0
|
||||
&& 'yellow'}
|
||||
selected={tab === 'requests'}
|
||||
onClick={() => setTab('requests')}>
|
||||
Requests ({requests.length})
|
||||
</Tabs.Tab>
|
||||
{!requestonly && (
|
||||
<Section fitted>
|
||||
<Tabs>
|
||||
<Tabs.Tab
|
||||
icon="shopping-cart"
|
||||
textColor={tab !== 'cart'
|
||||
&& cart.length > 0
|
||||
&& 'yellow'}
|
||||
selected={tab === 'cart'}
|
||||
onClick={() => setTab('cart')}>
|
||||
Checkout ({cart.length})
|
||||
icon="list"
|
||||
selected={tab === 'catalog'}
|
||||
onClick={() => setTab('catalog')}>
|
||||
Catalog
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
</Tabs>
|
||||
<Tabs.Tab
|
||||
icon="envelope"
|
||||
textColor={tab !== 'requests'
|
||||
&& requests.length > 0
|
||||
&& 'yellow'}
|
||||
selected={tab === 'requests'}
|
||||
onClick={() => setTab('requests')}>
|
||||
Requests ({requests.length})
|
||||
</Tabs.Tab>
|
||||
{!requestonly && (
|
||||
<Tabs.Tab
|
||||
icon="shopping-cart"
|
||||
textColor={tab !== 'cart'
|
||||
&& cart.length > 0
|
||||
&& 'yellow'}
|
||||
selected={tab === 'cart'}
|
||||
onClick={() => setTab('cart')}>
|
||||
Checkout ({cart.length})
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
</Tabs>
|
||||
</Section>
|
||||
{tab === 'catalog' && (
|
||||
<CargoCatalog />
|
||||
)}
|
||||
@@ -143,7 +145,7 @@ export const CargoCatalog = (props, context) => {
|
||||
</Fragment>
|
||||
)}>
|
||||
<Flex>
|
||||
<Flex.Item>
|
||||
<Flex.Item ml={-1} mr={1}>
|
||||
<Tabs vertical>
|
||||
{supplies.map(supply => (
|
||||
<Tabs.Tab
|
||||
|
||||
@@ -242,13 +242,14 @@ const CfStep2 = (props, context) => {
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell bold position="relative">
|
||||
Card Reader:
|
||||
Secondary Card Reader:
|
||||
<Tooltip
|
||||
content={multiline`
|
||||
Adds a slot that allows you to manipulate RFID cards.
|
||||
Please note that this is not necessary to allow the device
|
||||
to read your identification, it is just necessary to
|
||||
manipulate other cards.
|
||||
Adds a secondary RFID card reader, for manipulating or
|
||||
reading from a second standard RFID card.
|
||||
Please note that a primary card reader is necessary to
|
||||
allow the device to read your identification, but one
|
||||
is included in the base price.
|
||||
`}
|
||||
position="right" />
|
||||
</Table.Cell>
|
||||
|
||||
102
tgui/packages/tgui/interfaces/GhostPoolProtection.js
Normal file
102
tgui/packages/tgui/interfaces/GhostPoolProtection.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Button, Flex, Fragment, Section, NoticeBox } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const GhostPoolProtection = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
events_or_midrounds,
|
||||
spawners,
|
||||
station_sentience,
|
||||
silicons,
|
||||
minigames,
|
||||
} = data;
|
||||
return (
|
||||
<Window
|
||||
title="Ghost Pool Protection"
|
||||
width={400}
|
||||
height={270}>
|
||||
<Window.Content>
|
||||
<Flex grow={1} height="100%">
|
||||
<Section
|
||||
title="Options"
|
||||
buttons={
|
||||
<Fragment>
|
||||
<Button
|
||||
color="good"
|
||||
icon="plus-circle"
|
||||
content="Enable Everything"
|
||||
onClick={() => act("all_roles")} />
|
||||
<Button
|
||||
color="bad"
|
||||
icon="minus-circle"
|
||||
content="Disable Everything"
|
||||
onClick={() => act("no_roles")} />
|
||||
</Fragment>
|
||||
}>
|
||||
<NoticeBox danger>
|
||||
For people creating a sneaky event: If you
|
||||
toggle Station Created Sentience, people may
|
||||
catch on that admins have disabled roles for
|
||||
your event...
|
||||
</NoticeBox>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color={events_or_midrounds ? "good" : "bad"}
|
||||
icon="meteor"
|
||||
content="Events and Midround Rulesets"
|
||||
onClick={() => act("toggle_events_or_midrounds")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color={spawners ? "good" : "bad"}
|
||||
icon="pastafarianism"
|
||||
content="Ghost Role Spawners"
|
||||
onClick={() => act("toggle_spawners")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color={station_sentience ? "good" : "bad"}
|
||||
icon="user-astronaut"
|
||||
content="Station Created Sentience"
|
||||
onClick={() => act("toggle_station_sentience")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color={silicons ? "good" : "bad"}
|
||||
icon="robot"
|
||||
content="Silicons"
|
||||
onClick={() => act("toggle_silicons")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color={minigames ? "good" : "bad"}
|
||||
icon="gamepad"
|
||||
content="Minigames"
|
||||
onClick={() => act("toggle_minigames")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
color="orange"
|
||||
icon="check"
|
||||
content="Apply Changes"
|
||||
onClick={() => act("apply_settings")} />
|
||||
</Flex.Item>
|
||||
</Section>
|
||||
</Flex>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
97
tgui/packages/tgui/interfaces/MechpadConsole.js
Normal file
97
tgui/packages/tgui/interfaces/MechpadConsole.js
Normal file
@@ -0,0 +1,97 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, Divider, Flex, Grid, Input, NoticeBox, NumberInput, Section } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const MechpadControl = (props, context) => {
|
||||
const { topLevel } = props;
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
pad_name,
|
||||
connected_mechpad,
|
||||
} = 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')} />
|
||||
)}>
|
||||
{!connected_mechpad && (
|
||||
<Box color="bad" textAlign="center">
|
||||
No Pad Connected.
|
||||
</Box>
|
||||
) || (
|
||||
<Button
|
||||
fluid
|
||||
icon="upload"
|
||||
content="Launch"
|
||||
textAlign="center"
|
||||
onClick={() => act('launch')} />
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
export const MechpadConsole = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
mechpads = [],
|
||||
selected_id,
|
||||
} = data;
|
||||
return (
|
||||
<Window
|
||||
width={475}
|
||||
height={130}
|
||||
resizable>
|
||||
<Window.Content>
|
||||
{mechpads.length === 0 && (
|
||||
<NoticeBox>
|
||||
No Pads Connected
|
||||
</NoticeBox>
|
||||
) || (
|
||||
<Section>
|
||||
<Flex minHeight="70px">
|
||||
<Flex.Item width="140px" minHeight="70px">
|
||||
{mechpads.map(mechpad => (
|
||||
<Button
|
||||
fluid
|
||||
ellipsis
|
||||
key={mechpad.name}
|
||||
content={mechpad.name}
|
||||
selected={selected_id === mechpad.id}
|
||||
color="transparent"
|
||||
onClick={() => act('select_pad', {
|
||||
id: mechpad.id,
|
||||
})} />
|
||||
))}
|
||||
</Flex.Item>
|
||||
<Flex.Item minHeight="100%">
|
||||
<Divider vertical />
|
||||
</Flex.Item>
|
||||
<Flex.Item grow={1} basis={0} minHeight="100%">
|
||||
{selected_id && (
|
||||
<MechpadControl />
|
||||
) || (
|
||||
<Box>
|
||||
Please select a pad
|
||||
</Box>
|
||||
)}
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
@@ -28,6 +28,8 @@ export const NtosMain = (props, context) => {
|
||||
has_light,
|
||||
light_on,
|
||||
comp_light_color,
|
||||
removable_media = [],
|
||||
login = [],
|
||||
} = data;
|
||||
return (
|
||||
<NtosWindow
|
||||
@@ -56,6 +58,44 @@ export const NtosMain = (props, context) => {
|
||||
</Button>
|
||||
</Section>
|
||||
)}
|
||||
<Section
|
||||
title="User Login"
|
||||
buttons={(
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject ID"
|
||||
disabled={!login.IDName}
|
||||
onClick={() => act('PC_Eject_Disk', { name: "ID" })}
|
||||
/>
|
||||
)}>
|
||||
<Table>
|
||||
<Table.Row>
|
||||
ID Name: {login.IDName}
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
Assignment: {login.IDJob}
|
||||
</Table.Row>
|
||||
</Table>
|
||||
</Section>
|
||||
{!!removable_media.length && (
|
||||
<Section title="Media Eject">
|
||||
<Table>
|
||||
{removable_media.map(device => (
|
||||
<Table.Row key={device}>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
fluid
|
||||
color="transparent"
|
||||
icon="eject"
|
||||
content={device}
|
||||
onClick={() => act('PC_Eject_Disk', { name: device })}
|
||||
/>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table>
|
||||
</Section>
|
||||
)}
|
||||
<Section title="Programs">
|
||||
<Table>
|
||||
{programs.map(program => (
|
||||
|
||||
@@ -10,7 +10,7 @@ export const NtosRadar = (props, context) => {
|
||||
width={800}
|
||||
height={600}
|
||||
theme="ntos">
|
||||
<NtosRadarContent />
|
||||
<NtosRadarContent sig_err={"Signal Lost"} />
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
@@ -23,6 +23,7 @@ export const NtosRadarContent = (props, context) => {
|
||||
target = [],
|
||||
scanning,
|
||||
} = data;
|
||||
const { sig_err } = props;
|
||||
return (
|
||||
<Flex
|
||||
direction={"row"}
|
||||
@@ -89,7 +90,7 @@ export const NtosRadarContent = (props, context) => {
|
||||
width={42}
|
||||
fontSize="30px"
|
||||
textAlign="center">
|
||||
Signal Lost
|
||||
{sig_err}
|
||||
</NoticeBox>
|
||||
)
|
||||
: !!target.userot && (
|
||||
|
||||
@@ -7,7 +7,7 @@ export const NtosRadarSyndicate = (props, context) => {
|
||||
width={800}
|
||||
height={600}
|
||||
theme="syndicate">
|
||||
<NtosRadarContent />
|
||||
<NtosRadarContent sig_err={"Out of Range"} />
|
||||
</NtosWindow>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { classes, isFalsy } from "common/react";
|
||||
import { classes } from 'common/react';
|
||||
import { vecScale, vecSubtract } from 'common/vector';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { Component } from 'inferno';
|
||||
@@ -241,13 +241,11 @@ const PaperSheetView = (props, context) => {
|
||||
stamps,
|
||||
backgroundColor,
|
||||
readOnly,
|
||||
...rest
|
||||
} = props;
|
||||
const readonly = !isFalsy(readOnly);
|
||||
const stamp_list = stamps || [];
|
||||
const text_html = {
|
||||
__html: '<span class="paper-text">'
|
||||
+ setInputReadonly(value, readonly)
|
||||
+ setInputReadonly(value, readOnly)
|
||||
+ '</span>',
|
||||
};
|
||||
return (
|
||||
@@ -323,7 +321,12 @@ class PaperSheetStamper extends Component {
|
||||
handleMouseClick(e) {
|
||||
const pos = this.findStampPosition(e);
|
||||
const { act, data } = useBackend(this.context);
|
||||
act("stamp", { x: pos[0], y: pos[1], r: this.state.rotate });
|
||||
const stamp_obj = {
|
||||
x: pos[0], y: pos[1], r: this.state.rotate,
|
||||
stamp_class: this.props.stamp_class,
|
||||
stamp_icon_state: data.stamp_icon_state,
|
||||
};
|
||||
act("stamp", stamp_obj);
|
||||
this.setState({ x: pos[0], y: pos[1] });
|
||||
}
|
||||
|
||||
@@ -360,7 +363,7 @@ class PaperSheetStamper extends Component {
|
||||
onMouseMove={this.handleMouseMove.bind(this)}
|
||||
onwheel={this.handleWheel.bind(this)} {...rest}>
|
||||
<PaperSheetView
|
||||
readOnly={1}
|
||||
readOnly
|
||||
value={value}
|
||||
stamps={stamp_list} />
|
||||
<Stamp
|
||||
@@ -593,7 +596,7 @@ export const PaperSheet = (props, context) => {
|
||||
<PaperSheetView
|
||||
value={text}
|
||||
stamps={stamp_list}
|
||||
readOnly={1} />
|
||||
readOnly />
|
||||
);
|
||||
case 1:
|
||||
return (
|
||||
|
||||
182
tgui/packages/tgui/interfaces/Photocopier.js
Normal file
182
tgui/packages/tgui/interfaces/Photocopier.js
Normal file
@@ -0,0 +1,182 @@
|
||||
import { ProgressBar, NumberInput, Button, Section, Box, Flex } from '../components';
|
||||
import { useBackend } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Photocopier = (props, context) => {
|
||||
const { data } = useBackend(context);
|
||||
const {
|
||||
isAI,
|
||||
has_toner,
|
||||
has_item,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Window
|
||||
title="Photocopier"
|
||||
width={240}
|
||||
height={isAI ? 309 : 234}>
|
||||
<Window.Content>
|
||||
{has_toner ? (
|
||||
<Toner />
|
||||
) : (
|
||||
<Section title="Toner">
|
||||
<Box color="average">
|
||||
No inserted toner cartridge.
|
||||
</Box>
|
||||
</Section>
|
||||
)}
|
||||
{has_item ? (
|
||||
<Options />
|
||||
) : (
|
||||
<Section title="Options">
|
||||
<Box color="average">
|
||||
No inserted item.
|
||||
</Box>
|
||||
</Section>
|
||||
)}
|
||||
{!!isAI && (
|
||||
<AIOptions />
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const Toner = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
max_toner,
|
||||
current_toner,
|
||||
} = data;
|
||||
|
||||
const average_toner = max_toner * 0.66;
|
||||
const bad_toner = max_toner * 0.33;
|
||||
|
||||
return (
|
||||
<Section
|
||||
title="Toner"
|
||||
buttons={
|
||||
<Button
|
||||
disabled={!current_toner}
|
||||
onClick={() => act('remove_toner')}
|
||||
icon="eject">
|
||||
Eject
|
||||
</Button>
|
||||
}>
|
||||
<ProgressBar
|
||||
ranges={{
|
||||
good: [average_toner, max_toner],
|
||||
average: [bad_toner, average_toner],
|
||||
bad: [0, bad_toner],
|
||||
}}
|
||||
value={current_toner}
|
||||
minValue={0}
|
||||
maxValue={max_toner} />
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const Options = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
color_mode,
|
||||
is_photo,
|
||||
num_copies,
|
||||
has_enough_toner,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section title="Options">
|
||||
<Flex>
|
||||
<Flex.Item
|
||||
mt={0.4}
|
||||
width={11}
|
||||
color="label">
|
||||
Make copies:
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<NumberInput
|
||||
animate
|
||||
width={2.6}
|
||||
height={1.65}
|
||||
step={1}
|
||||
stepPixelSize={8}
|
||||
minValue={1}
|
||||
maxValue={10}
|
||||
value={num_copies}
|
||||
onDrag={(e, value) => act('set_copies', {
|
||||
num_copies: value,
|
||||
})} />
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
ml={0.2}
|
||||
icon="copy"
|
||||
textAlign="center"
|
||||
disabled={!has_enough_toner}
|
||||
onClick={() => act('make_copy')}>
|
||||
Copy
|
||||
</Button>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
{!!is_photo && (
|
||||
<Flex mt={0.5}>
|
||||
<Flex.Item
|
||||
mr={0.4}
|
||||
width="50%">
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
selected={color_mode === "Greyscale"}
|
||||
onClick={() => act('color_mode', {
|
||||
mode: "Greyscale",
|
||||
})}>
|
||||
Greyscale
|
||||
</Button>
|
||||
</Flex.Item>
|
||||
<Flex.Item
|
||||
ml={0.4}
|
||||
width="50%">
|
||||
<Button
|
||||
fluid
|
||||
textAlign="center"
|
||||
selected={color_mode === "Color"}
|
||||
onClick={() => act('color_mode', {
|
||||
mode: "Color",
|
||||
})}>
|
||||
Color
|
||||
</Button>
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
)}
|
||||
<Button
|
||||
mt={0.5}
|
||||
textAlign="center"
|
||||
icon="reply"
|
||||
fluid
|
||||
onClick={() => act('remove')}>
|
||||
Remove item
|
||||
</Button>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const AIOptions = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { can_AI_print } = data;
|
||||
|
||||
return (
|
||||
<Section title="AI Options">
|
||||
<Box>
|
||||
<Button
|
||||
fluid
|
||||
icon="images"
|
||||
textAlign="center"
|
||||
disabled={!can_AI_print}
|
||||
onClick={() => act('ai_photo')}>
|
||||
Print photo from database
|
||||
</Button>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -1,17 +1,25 @@
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Button, LabeledList, Section } from '../components';
|
||||
import { Box, Button, LabeledList, Section, NoticeBox } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export const Wires = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const { proper_name } = data;
|
||||
const wires = data.wires || [];
|
||||
const statuses = data.status || [];
|
||||
return (
|
||||
<Window
|
||||
width={350}
|
||||
height={150 + wires.length * 30}>
|
||||
height={150
|
||||
+ (wires.length * 30)
|
||||
+ (!!proper_name && 30)}>
|
||||
<Window.Content>
|
||||
{(!!proper_name && (
|
||||
<NoticeBox textAlign="center">
|
||||
{proper_name} Wire Configuration
|
||||
</NoticeBox>
|
||||
))}
|
||||
<Section>
|
||||
<LabeledList>
|
||||
{wires.map(wire => (
|
||||
|
||||
@@ -5,29 +5,15 @@
|
||||
*/
|
||||
|
||||
import { classes } from 'common/react';
|
||||
import { computeBoxProps, computeBoxClassName } from '../components/Box';
|
||||
|
||||
/**
|
||||
* Brings Layout__content DOM element back to focus.
|
||||
*
|
||||
* Commonly used to keep the content scrollable in IE.
|
||||
*/
|
||||
export const refocusLayout = () => {
|
||||
// IE8: Focus method is seemingly fucked.
|
||||
if (Byond.IS_LTE_IE8) {
|
||||
return;
|
||||
}
|
||||
const element = document.getElementById('Layout__content');
|
||||
if (element) {
|
||||
element.focus();
|
||||
}
|
||||
};
|
||||
import { computeBoxClassName, computeBoxProps } from '../components/Box';
|
||||
import { addScrollableNode, removeScrollableNode } from '../events';
|
||||
|
||||
export const Layout = props => {
|
||||
const {
|
||||
className,
|
||||
theme = 'nanotrasen',
|
||||
children,
|
||||
...rest
|
||||
} = props;
|
||||
return (
|
||||
<div className={'theme-' + theme}>
|
||||
@@ -35,7 +21,9 @@ export const Layout = props => {
|
||||
className={classes([
|
||||
'Layout',
|
||||
className,
|
||||
])}>
|
||||
...computeBoxClassName(rest),
|
||||
])}
|
||||
{...computeBoxProps(rest)}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,7 +39,6 @@ const LayoutContent = props => {
|
||||
} = props;
|
||||
return (
|
||||
<div
|
||||
id="Layout__content"
|
||||
className={classes([
|
||||
'Layout__content',
|
||||
scrollable && 'Layout__content--scrollable',
|
||||
@@ -64,4 +51,9 @@ const LayoutContent = props => {
|
||||
);
|
||||
};
|
||||
|
||||
LayoutContent.defaultHooks = {
|
||||
onComponentDidMount: node => addScrollableNode(node),
|
||||
onComponentWillUnmount: node => removeScrollableNode(node),
|
||||
};
|
||||
|
||||
Layout.Content = LayoutContent;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
export { Layout, refocusLayout } from './Layout';
|
||||
export { Layout } from './Layout';
|
||||
export { NtosWindow } from './NtosWindow';
|
||||
export { Pane } from './Pane';
|
||||
export { Window } from './Window';
|
||||
|
||||
Reference in New Issue
Block a user