code:
import { useBackend } from '../backend';
import { Button, Dimmer, Section, Stack } from '../components';
import { multiline } from 'common/string';
import { Window } from '../layouts';

const STORY_VALUE_SHIT = 0;
const STORY_VALUE_NONE = 1;
const STORY_VALUE_MEH = 2;
const STORY_VALUE_OKAY = 3;
const STORY_VALUE_AMAZING = 4;
// STORY_VALUE_LEGENDARY = 5; (not actually used)

const MemoryQuality = (props, context) => {
  const { act } = useBackend(context);
  const {
    quality,
  } = props;

  if (quality === STORY_VALUE_SHIT) {
    return (
      <Button
        icon="poop"
        color="transparent"
        tooltip={multiline`
          This memory is not interesting at all! It does not make for
          good art and is unlikely to pass to future generations.
        `} />
    );
  }
  if (quality === STORY_VALUE_NONE) {
    return (
      <Button
        icon="star"
        color="transparent"
        tooltipPosition="right"
        tooltip={multiline`
          This memory pretty bland. It would make for some pretty
          mediocre art and is not likely to pass to future generations.
  `} />
    );
  }
  if (quality === STORY_VALUE_MEH) {
    return (
      <Button
        icon="star"
        style={{
          "background": "linear-gradient(to right, #964B30, #D68B60, #B66B30, #D68B60, #964B30);",
        }}
        tooltipPosition="right"
        tooltip={multiline`
          This memory is not super interesting. It could turn into
          an okay story but don't bet on it.
    `} />
    );
  }
  if (quality === STORY_VALUE_OKAY) {
    return (
      <Button
        icon="star"
        style={{
          "background": "linear-gradient(to right, #636363, #a3a3a3, #6e6e6e, #a3a3a3, #636363);",
        }}
        tooltipPosition="right"
        tooltip={multiline`
          This memory is pretty okay! Some good stories could be told
          from this and it might even come back in future generations.
      `} />
    );
  }
  if (quality === STORY_VALUE_AMAZING) {
    return (
      <Button
        icon="star"
        style={{
          "background": "linear-gradient(to right, #AA771C, #BCB68A, #B38728, #BCB68A, #AA771C);",
        }}
        tooltipPosition="right"
        tooltip={multiline`
          This memory is great! You could tell a great story from it,
          and it would have a good chanced pass to future generations!
      `} />
    );
  }
  return (
    <Button
      icon="crown"
      style={{
        "background": "linear-gradient(to right, #56A5B3, #75D4E2, #56A5B3, #75D4E2, #56A5B3)",
      }}
      tooltipPosition="right"
      tooltip={multiline`
        This memory is the stuff of legends! It would make for
        legendary art and is likely to pass to future generations.
      `} />
  );
};

export const MemoryPanel = (props, context) => {
  const { act, data } = useBackend(context);
  const memories = data.memories || [];
  return (
    <Window
      title="Memory Panel"
      width={400}
      height={500}>
      <Window.Content>
        <Section
          maxHeight="32px"
          title="Memories"
          buttons={(
            <Button
              color="transparent"
              tooltip={multiline`
                These are your memories. You gain them from doing notable things
                and you can use them in art!
              `}
              tooltipPosition="bottom-start"
              icon="info" />
          )} />
        {!memories && (
          <Dimmer fontSize="28px" align="center">
            You have no memories!
          </Dimmer>
        ) || (
          <Stack vertical>
            {memories.map(memory => (
              <Stack.Item key={memory.name}>
                <Section>
                  <MemoryQuality quality={memory.quality} /> {memory.name}
                </Section>
              </Stack.Item>
            ))}
          </Stack>
        )}
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend, useSharedState } from '../backend';
import { Button, LabeledList, NoticeBox, Section, Tabs } from '../components';
import { Window } from '../layouts';

export const Microscope = (props, context) => {
  const { act, data } = useBackend(context);
  const [tab, setTab] = useSharedState(context, 'tab', 1);
  const {
    has_dish,
    cell_lines = [],
    viruses = [],
  } = data;
  return (
    <Window>
      <Window.Content scrollable>
        <Section>
          <LabeledList>
            <LabeledList.Item label="Dish Sample">
              <Button
                icon="eject"
                content="Eject"
                disabled={!has_dish}
                onClick={() => act('eject_petridish')} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
        <Tabs>
          <Tabs.Tab
            icon="microscope"
            lineHeight="23px"
            selected={tab === 1}
            onClick={() => setTab(1)}>
            Micro-Organisms ({cell_lines.length})
          </Tabs.Tab>
          <Tabs.Tab
            icon="microscope"
            lineHeight="23px"
            selected={tab === 2}
            onClick={() => setTab(2)}>
            Viruses ({viruses.length})
          </Tabs.Tab>
        </Tabs>
        {tab === 1 && (
          <Organisms cell_lines={cell_lines} />
        )}
        {tab === 2 && (
          <Viruses viruses={viruses} />
        )}
      </Window.Content>
    </Window>
  );
};

const Organisms = (props, context) => {
  const { cell_lines } = props;
  const { act, data } = useBackend(context);
  if (!cell_lines.length) {
    return (
      <NoticeBox>
        No micro-organisms found
      </NoticeBox>
    );
  }
  return cell_lines.map(cell_line => {
    return (
      <Section
        key={cell_line.desc}
        title={cell_line.desc}>
        <LabeledList>
          <LabeledList.Item label="Growth Rate">
            {cell_line.growth_rate}
          </LabeledList.Item>
          <LabeledList.Item label="Virus Suspectibility">
            {cell_line.suspectibility}
          </LabeledList.Item>
          <LabeledList.Item label="Required Reagents">
            {cell_line.requireds}
          </LabeledList.Item>
          <LabeledList.Item label="Supplementary Reagents">
            {cell_line.supplementaries}
          </LabeledList.Item>
          <LabeledList.Item label="Suppresive reagents">
            {cell_line.suppressives}
          </LabeledList.Item>
        </LabeledList>
      </Section>
    );
  });
};

const Viruses = (props, context) => {
  const { viruses } = props;
  const { act } = useBackend(context);
  if (!viruses.length) {
    return (
      <NoticeBox>
        No viruses found
      </NoticeBox>
    );
  }
  return viruses.map(virus => {
    return (
      <Section
        key={virus.desc}
        title={virus.desc} />
    );
  });
};

repo_name: AnalWerewolf/sundown

license: mit


code:
import { useBackend } from '../backend';
import { Button, Section, Stack } from '../components';
import { Window } from '../layouts';

export const MinigamesMenu = (props, context) => {
  const { act } = useBackend(context);
  return (
    <Window
      title="Minigames Menu"
      width={450}
      height={200}>
      <Window.Content>
        <Section title="Select Minigame" textAlign="center">
          <Stack>
            <Stack.Item grow>
              <Button
                content="CTF"
                fluid={1}
                fontSize={3}
                textAlign="center"
                lineHeight="3"
                onClick={() => act('ctf')}
              />
            </Stack.Item>
            <Stack.Item grow>
              <Button
                content="Mafia"
                fluid={1}
                fontSize={3}
                textAlign="center"
                lineHeight="3"
                onClick={() => act('mafia')}
              />
            </Stack.Item>
          </Stack>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { classes } from 'common/react';
import { useBackend } from '../backend';
import { Box, Button, Section, Table } from '../components';
import { Window } from '../layouts';

export const MiningVendor = (props, context) => {
  const { act, data } = useBackend(context);
  let inventory = [
    ...data.product_records,
  ];
  return (
    <Window
      width={425}
      height={600}>
      <Window.Content scrollable>

          {data.user && (
            <Box>
              Welcome, {data.user.name || "Unknown"},
              {' '}
              {data.user.job || "Unemployed"}!

              Your balance is {data.user.points} mining points.
            </Box>
          ) || (
            <Box color="light-gray">
              No registered ID card!

              Please contact your local HoP!
            </Box>
          )}

            {inventory.map((product => {
              return (

                    {' '}{product.name}

                    <Button
                      style={{
                        'min-width': '95px',
                        'text-align': 'center',
                      }}
                      disabled={!data.user
                        || product.price > data.user.points}
                      content={product.price + ' points'}
                      onClick={() => act('purchase', {
                        'ref': product.ref,
                      })} />

              );
            }))}

      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Dropdown, Flex, Input, LabeledList, ProgressBar, Section } from '../components';
import { Window } from '../layouts';
import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox';

export const Mule = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    on,
    cell,
    cellPercent,
    load,
    mode,
    modeStatus,
    haspai,
    autoReturn,
    autoPickup,
    reportDelivery,
    destination,
    home,
    id,
    destinations = [],
  } = data;
  const locked = data.locked && !data.siliconUser;
  return (
    <Window
      width={350}
      height={425}>
      <Window.Content>
        <InterfaceLockNoticeBox />
        <Section
          title="Status"
          minHeight="110px"
          buttons={!locked && (
            <Button
              icon={on ? 'power-off' : 'times'}
              content={on ? 'On' : 'Off'}
              selected={on}
              onClick={() => act('power')} />
          )}>
          <ProgressBar
            value={cell ? (cellPercent / 100) : 0}
            color={cell ? 'good' : 'bad'} />
          <Flex mt={1}>
            <Flex.Item grow={1} basis={0}>
              <LabeledList>
                <LabeledList.Item label="Mode" color={modeStatus}>
                  {mode}
                </LabeledList.Item>
              </LabeledList>
            </Flex.Item>
            <Flex.Item grow={1} basis={0}>
              <LabeledList>
                <LabeledList.Item
                  label="Load"
                  color={load ? 'good' : 'average'}>
                  {load || 'None'}
                </LabeledList.Item>
              </LabeledList>
            </Flex.Item>
          </Flex>

        {!locked && (
          <Section
            title="Controls"
            buttons={(
              <>
                {!!load && (
                  <Button
                    icon="eject"
                    content="Unload"
                    onClick={() => act('unload')} />
                )}
                {!!haspai && (
                  <Button
                    icon="eject"
                    content="Eject PAI"
                    onClick={() => act('ejectpai')} />
                )}
              </>
            )}>
            <LabeledList>
              <LabeledList.Item label="ID">
                <Input
                  value={id}
                  onChange={(e, value) => act('setid', { value })} />
              </LabeledList.Item>
              <LabeledList.Item label="Destination">
                <Dropdown
                  over
                  selected={destination || 'None'}
                  options={destinations}
                  width="150px"
                  onSelected={value => act('destination', { value })} />
                <Button
                  icon="stop"
                  content="Stop"
                  onClick={() => act('stop')} />
                <Button
                  icon="play"
                  content="Go"
                  onClick={() => act('go')} />
              </LabeledList.Item>
              <LabeledList.Item label="Home">
                <Dropdown
                  over
                  selected={home}
                  options={destinations}
                  width="150px"
                  onSelected={value => act('destination', { value })} />
                <Button
                  icon="home"
                  content="Go Home"
                  onClick={() => act('home')} />
              </LabeledList.Item>
              <LabeledList.Item label="Settings">
                <Button.Checkbox
                  checked={autoReturn}
                  content="Auto-Return"
                  onClick={() => act('autored')} />

                <Button.Checkbox
                  checked={autoPickup}
                  content="Auto-Pickup"
                  onClick={() => act('autopick')} />

                <Button.Checkbox
                  checked={reportDelivery}
                  content="Report Delivery"
                  onClick={() => act('report')} />
              </LabeledList.Item>
            </LabeledList>

        )}
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from "../backend";
import { Box, Button, Flex, Section } from "../components";
import { Window } from "../layouts";

export const NoticeBoard = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    allowed,
    items = {},
  } = data;

  return (
    <Window
      width={425}
      height={176}>
      <Window.Content backgroundColor="#704D25">
        {!items.length ? (
          <Section>
            <Box color="white" align="center">
              The notice board is empty!
            </Box>
          </Section>
        ) : (
          items.map((item, index) => (
            <Flex
              key={item.ref}
              color="black"
              backgroundColor="white"
              style={{ padding: "2px 2px 0 2px" }}
              mb={0.5}>
              <Flex.Item align="center" grow={1}>
                <Box align="center">
                  {item.name}
                </Box>
              </Flex.Item>
              <Flex.Item>
                <Button
                  icon="eye"
                  onClick={() => act("examine", { ref: item.ref })}
                />
                <Button
                  icon="eject"
                  disabled={!allowed}
                  onClick={() => act("remove", { ref: item.ref })}
                />
              </Flex.Item>
            </Flex>
          )))}
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Section, Button } from '../components';
import { Window } from '../layouts';

export const NotificationPreferences = (props, context) => {
  const { act, data } = useBackend(context);
  const ignoresPreSort = data.ignore || [];
  const ignores = ignoresPreSort.sort((a, b) => {
    const descA = a.desc.toLowerCase();
    const descB = b.desc.toLowerCase();
    if (descA < descB) {
      return -1;
    }
    if (descA > descB) {
      return 1;
    }
    return 0;
  });
  return (
    <Window
      title="Notification Preferences"
      width={270}
      height={360}>
      <Window.Content scrollable>
        <Section title="Ghost Role Notifications">
          {ignores.map(ignore => (
            <Button
              fluid
              key={ignore.key}
              icon={ignore.enabled ? 'times' : 'check'}
              content={ignore.desc}
              color={ignore.enabled ? 'bad' : 'good'}
              onClick={() => act('toggle_ignore', { key: ignore.key })} />
          ))}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, ProgressBar, Section, AnimatedNumber } from '../components';
import { Window } from '../layouts';

export const NtnetRelay = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    enabled,
    dos_capacity,
    dos_overload,
    dos_crashed,
  } = data;
  return (
    <Window
      title="NtNet Quantum Relay"
      width={400}
      height={300}>
      <Window.Content>
        <Section
          title="Network Buffer"
          buttons={(
            <Button
              icon="power-off"
              selected={enabled}
              content={enabled ? 'ENABLED' : 'DISABLED'}
              onClick={() => act('toggle')}
            />
          )}>
          {!dos_crashed ? (
            <ProgressBar
              value={dos_overload}
              minValue={0}
              maxValue={dos_capacity}>
              <AnimatedNumber value={dos_overload} /> GQ
              {' / '}
              {dos_capacity} GQ
            </ProgressBar>
          ) : (
            <Box fontFamily="monospace">
              <Box fontSize="20px">
                NETWORK BUFFER OVERFLOW
              </Box>
              <Box fontSize="16px">
                OVERLOAD RECOVERY MODE
              </Box>
              <Box>
                This system is suffering temporary outage due to overflow
                of traffic buffers. Until buffered traffic is processed,
                all further requests will be dropped. Frequent occurences
                of this error may indicate insufficient hardware capacity
                of your network. Please contact your network planning
                department for instructions on how to resolve this issue.
              </Box>
              <Box fontSize="20px" color="bad">
                ADMINISTRATOR OVERRIDE
              </Box>
              <Box fontSize="16px" color="bad">
                CAUTION - DATA LOSS MAY OCCUR
              </Box>
              <Button
                icon="signal"
                content="PURGE BUFFER"
                mt={1}
                color="bad"
                onClick={() => act('restart')} />
            </Box>
          )}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { NtosWindow } from '../layouts';
import { AiRestorerContent } from './AiRestorer';

export const NtosAiRestorer = () => {
  return (
    <NtosWindow
      width={370}
      height={400}>
      <NtosWindow.Content scrollable>
        <AiRestorerContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { resolveAsset } from '../assets';
import { useBackend } from '../backend';
import { AnimatedNumber, Box, Button, Grid, LabeledList, ProgressBar, Section } from '../components';
import { NtosWindow } from '../layouts';

export const NtosArcade = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <NtosWindow
      width={450}
      height={350}>
      <NtosWindow.Content>
        <Section
          title="Outbomb Cuban Pete Ultra"
          textAlign="center">
          <Box>
            <Grid>
              <Grid.Column size={2}>
                <Box m={1} />
                <LabeledList>
                  <LabeledList.Item
                    label="Player Health">
                    <ProgressBar
                      value={data.PlayerHitpoints}
                      minValue={0}
                      maxValue={30}
                      ranges={{
                        olive: [31, Infinity],
                        good: [20, 31],
                        average: [10, 20],
                        bad: [-Infinity, 10],
                      }}>
                      {data.PlayerHitpoints}HP
                    </ProgressBar>
                  </LabeledList.Item>
                  <LabeledList.Item
                    label="Player Magic">
                    <ProgressBar
                      value={data.PlayerMP}
                      minValue={0}
                      maxValue={10}
                      ranges={{
                        purple: [11, Infinity],
                        violet: [3, 11],
                        bad: [-Infinity, 3],
                      }}>
                      {data.PlayerMP}MP
                    </ProgressBar>
                  </LabeledList.Item>
                </LabeledList>
                <Box my={1} mx={4} />
                <Section
                  backgroundColor={
                    data.PauseState === 1 ? "#1b3622" : "#471915"
                  }>
                  {data.Status}
                </Section>
              </Grid.Column>
              <Grid.Column>
                <ProgressBar
                  value={data.Hitpoints}
                  minValue={0}
                  maxValue={45}
                  ranges={{
                    good: [30, Infinity],
                    average: [5, 30],
                    bad: [-Infinity, 5],
                  }}>
                  <AnimatedNumber value={data.Hitpoints} />
                  HP
                </ProgressBar>
                <Box m={1} />
                <Section
                  inline
                  width="156px"
                  textAlign="center">
                  <img src={resolveAsset(data.BossID)} />
                </Section>
              </Grid.Column>
            </Grid>
            <Box my={1} mx={4} />
            <Button
              icon="fist-raised"
              tooltip="Go in for the kill!"
              tooltipPosition="top"
              disabled={data.GameActive === 0 || data.PauseState === 1}
              onClick={() => act('Attack')}
              content="Attack!" />
            <Button
              icon="band-aid"
              tooltip="Heal yourself!"
              tooltipPosition="top"
              disabled={data.GameActive === 0 || data.PauseState === 1}
              onClick={() => act('Heal')}
              content="Heal!" />
            <Button
              icon="magic"
              tooltip="Recharge your magic!"
              tooltipPosition="top"
              disabled={data.GameActive === 0 || data.PauseState === 1}
              onClick={() => act('Recharge_Power')}
              content="Recharge!" />
          </Box>
          <Box>
            <Button
              icon="sync-alt"
              tooltip="One more game couldn't hurt."
              tooltipPosition="top"
              disabled={data.GameActive === 1}
              onClick={() => act('Start_Game')}
              content="Begin Game" />
            <Button
              icon="ticket-alt"
              tooltip="Claim at your local Arcade Computer for Prizes!"
              tooltipPosition="top"
              disabled={data.GameActive === 1}
              onClick={() => act('Dispense_Tickets')}
              content="Claim Tickets" />
          </Box>
          <Box color={data.TicketCount >= 1 ? 'good' : 'normal'}>
            Earned Tickets: {data.TicketCount}
          </Box>
        </Section>
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { filter, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { toFixed } from 'common/math';
import { useBackend } from '../backend';
import { LabeledList, ProgressBar, Section } from '../components';
import { getGasColor, getGasLabel } from '../constants';
import { NtosWindow } from '../layouts';

export const NtosAtmos = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    AirTemp,
    AirPressure,
  } = data;
  const gases = flow([
    filter(gas => gas.percentage >= 0.01),
    sortBy(gas => -gas.percentage),
  ])(data.AirData || []);
  const gasMaxPercentage = Math.max(1, ...gases.map(gas => gas.percentage));
  return (
    <NtosWindow
      width={300}
      height={350}>
      <NtosWindow.Content scrollable>

          <LabeledList>
            <LabeledList.Item label="Temperature">
              {AirTemp}°C
            </LabeledList.Item>
            <LabeledList.Item label="Pressure">
              {AirPressure} kPa
            </LabeledList.Item>
          </LabeledList>

          <LabeledList>
            {gases.map(gas => (
              <LabeledList.Item
                key={gas.name}
                label={getGasLabel(gas.name)}>
                <ProgressBar
                  color={getGasColor(gas.name)}
                  value={gas.percentage}
                  minValue={0}
                  maxValue={gasMaxPercentage}>
                  {toFixed(gas.percentage, 2) + '%'}
                </ProgressBar>
              </LabeledList.Item>
            ))}
          </LabeledList>

      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend, useSharedState } from '../backend';
import { Box, Button, Dropdown, Input, NoticeBox, NumberInput, Section, Stack, Tabs } from '../components';
import { NtosWindow } from '../layouts';
import { AccessList } from './common/AccessList';

export const NtosCard = (props, context) => {
  return (
    <NtosWindow
      width={500}
      height={670}>
      <NtosWindow.Content scrollable>
        <NtosCardContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};

export const NtosCardContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    authenticatedUser,
    regions = [],
    access_on_card = [],
    has_id,
    have_id_slot,
    wildcardSlots,
    wildcardFlags,
    trimAccess,
    accessFlags,
    accessFlagNames,
    showBasic,
    templates = {},
  } = data;

  if (!have_id_slot) {
    return (
      <NoticeBox>
        This program requires an ID slot in order to function
      </NoticeBox>
    );
  }

  const [
    selectedTab,
  ] = useSharedState(context, "selectedTab", "login");

  return (
    <>
      <Stack>
        <Stack.Item>
          <IDCardTabs />
        </Stack.Item>
        <Stack.Item width="100%">
          {(selectedTab === "login") && (
            <IDCardLogin />
          ) || (selectedTab === "modify") && (
            <IDCardTarget />
          )}
        </Stack.Item>
      </Stack>
      {(!!has_id && !!authenticatedUser) && (
        <Section
          title="Templates"
          mt={1}
          buttons={
            <Button
              icon="question-circle"
              tooltip={
                "Will attempt to apply all access for the template to the ID card.\n"
              + "Does not use wildcards unless the template specifies them."
              }
              tooltipPosition="left" />
          } >
          <TemplateDropdown templates={templates} />
        </Section>)}
      <Stack mt={1}>
        <Stack.Item grow>
          {(!!has_id && !!authenticatedUser) && (
            <Box>
              <AccessList
                accesses={regions}
                selectedList={access_on_card}
                wildcardFlags={wildcardFlags}
                wildcardSlots={wildcardSlots}
                trimAccess={trimAccess}
                accessFlags={accessFlags}
                accessFlagNames={accessFlagNames}
                showBasic={!!showBasic}
                extraButtons={
                  <Button.Confirm
                    content="Terminate Employment"
                    confirmContent="Fire Employee?"
                    color="bad"
                    onClick={() => act('PRG_terminate')} />
                }
                accessMod={(ref, wildcard) => act('PRG_access', {
                  access_target: ref,
                  access_wildcard: wildcard,
                })} />
            </Box>
          )}
        </Stack.Item>
      </Stack>
    </>
  );
};

const IDCardTabs = (props, context) => {
  const [
    selectedTab,
    setSelectedTab,
  ] = useSharedState(context, "selectedTab", "login");

  return (
    <Tabs vertical fill>
      <Tabs.Tab
        minWidth={"100%"}
        altSelection
        selected={"login" === selectedTab}
        color={("login" === selectedTab) ? "green" : "default"}
        onClick={() => setSelectedTab("login")}>
        Login ID
      </Tabs.Tab>
      <Tabs.Tab
        minWidth={"100%"}
        altSelection
        selected={"modify" === selectedTab}
        color={("modify" === selectedTab) ? "green" : "default"}
        onClick={() => setSelectedTab("modify")}>
        Target ID
      </Tabs.Tab>
    </Tabs>
  );
};

export const IDCardLogin = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    authenticatedUser,
    has_id,
    have_printer,
    authIDName,
  } = data;

  return (
    <Section
      title="Login"
      buttons={(
        <>
          <Button
            icon="print"
            content="Print"
            disabled={!have_printer || !has_id}
            onClick={() => act('PRG_print')} />
          <Button
            icon={authenticatedUser ? "sign-out-alt" : "sign-in-alt"}
            content={authenticatedUser ? "Log Out" : "Log In"}
            color={authenticatedUser ? "bad" : "good"}
            onClick={() => {
              act(authenticatedUser ? 'PRG_logout' : 'PRG_authenticate');
            }} />
        </>
      )}>
      <Stack wrap="wrap">
        <Stack.Item width="100%">
          <Button
            fluid
            ellipsis
            icon="eject"
            content={authIDName}
            onClick={() => act('PRG_ejectauthid')} />
        </Stack.Item>
        <Stack.Item width="100%" mt={1} ml={0}>
          Login: {authenticatedUser || "-----"}
        </Stack.Item>
      </Stack>
    </Section>
  );
};

const IDCardTarget = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    authenticatedUser,
    id_rank,
    id_owner,
    has_id,
    id_name,
    id_age,
  } = data;

  return (
    <Section title="Modify ID">
      <Button
        width="100%"
        ellipsis
        icon="eject"
        content={id_name}
        onClick={() => act('PRG_ejectmodid')} />
      {!!(has_id && authenticatedUser) && (
        <>
          <Stack mt={1}>
            <Stack.Item align="center">
              Details:
            </Stack.Item>
            <Stack.Item grow={1} mr={1} ml={1}>
              <Input
                width="100%"
                value={id_owner}
                onInput={(e, value) => act('PRG_edit', {
                  name: value,
                })} />
            </Stack.Item>
            <Stack.Item>
              <NumberInput
                value={id_age || 0}
                unit="Years"
                minValue={17}
                maxValue={85}
                onChange={(e, value) => { act('PRG_age', {
                  id_age: value,
                });
                }} />
            </Stack.Item>
          </Stack>
          <Stack>
            <Stack.Item align="center">
              Assignment:
            </Stack.Item>
            <Stack.Item grow={1} ml={1}>
              <Input
                fluid
                mt={1}
                value={id_rank}
                onInput={(e, value) => act('PRG_assign', {
                  assignment: value,
                })} />
            </Stack.Item>
          </Stack>
        </>
      )}
    </Section>
  );
};

const TemplateDropdown = (props, context) => {
  const { act } = useBackend(context);
  const {
    templates,
  } = props;

  const templateKeys = Object.keys(templates);

  if (!templateKeys.length) {
    return;
  }

  return (
    <Stack>
      <Stack.Item grow>
        <Dropdown
          width="100%"
          displayText={"Select a template..."}
          options={
            templateKeys.map(path => {
              return templates[path];
            })
          }
          onSelected={sel => act("PRG_template", {
            name: sel,
          })} />
      </Stack.Item>
    </Stack>
  );
};


code:
import { CargoContent } from './Cargo.js';
import { NtosWindow } from '../layouts';

export const NtosCargo = (props, context) => {
  return (
    <NtosWindow
      width={800}
      height={500}>
      <NtosWindow.Content scrollable>
        <CargoContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, ProgressBar, Section } from '../components';
import { NtosWindow } from '../layouts';

export const NtosConfiguration = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    PC_device_theme,
    power_usage,
    battery_exists,
    battery = {},
    disk_size,
    disk_used,
    hardware = [],
  } = data;
  return (
    <NtosWindow
      theme={PC_device_theme}
      width={420}
      height={630}>
      <NtosWindow.Content scrollable>
        <Section
          title="Power Supply"
          buttons={(
            <Box
              inline
              bold
              mr={1}>
              Power Draw: {power_usage}W
            </Box>
          )}>
          <LabeledList>
            <LabeledList.Item
              label="Battery Status"
              color={!battery_exists && 'average'}>
              {battery_exists ? (
                <ProgressBar
                  value={battery.charge}
                  minValue={0}
                  maxValue={battery.max}
                  ranges={{
                    good: [battery.max / 2, Infinity],
                    average: [battery.max / 4, battery.max / 2],
                    bad: [-Infinity, battery.max / 4],
                  }}>
                  {battery.charge} / {battery.max}
                </ProgressBar>
              ) : 'Not Available'}
            </LabeledList.Item>
          </LabeledList>

          <ProgressBar
            value={disk_used}
            minValue={0}
            maxValue={disk_size}
            color="good">
            {disk_used} GQ / {disk_size} GQ
          </ProgressBar>

          {hardware.map(component => (
            <Section
              key={component.name}
              title={component.name}
              level={2}
              buttons={(
                <>
                  {!component.critical && (
                    <Button.Checkbox
                      content="Enabled"
                      checked={component.enabled}
                      mr={1}
                      onClick={() => act('PC_toggle_component', {
                        name: component.name,
                      })} />
                  )}
                  <Box
                    inline
                    bold
                    mr={1}>
                    Power Usage: {component.powerusage}W
                  </Box>
                </>
              )}>
              {component.desc}

          ))}

      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { map } from 'common/collections';
import { useBackend } from '../backend';
import { Button, Section, Table } from '../components';
import { NtosWindow } from '../layouts';

export const NtosCrewManifest = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    have_printer,
    manifest = {},
  } = data;
  return (
    <NtosWindow
      width={400}
      height={480}>
      <NtosWindow.Content scrollable>
        <Section
          title="Crew Manifest"
          buttons={(
            <Button
              icon="print"
              content="Print"
              disabled={!have_printer}
              onClick={() => act('PRG_print')} />
          )}>
          {map((entries, department) => (
            <Section
              key={department}
              level={2}
              title={department}>
              <Table>
                {entries.map(entry => (
                  <Table.Row
                    key={entry.name}
                    className="candystripe">
                    <Table.Cell bold>
                      {entry.name}
                    </Table.Cell>
                    <Table.Cell>
                      ({entry.rank})
                    </Table.Cell>
                  </Table.Row>
                ))}
              </Table>
            </Section>
          ))(manifest)}
        </Section>
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend, useSharedState } from '../backend';
import { Box, Button, LabeledList, NoticeBox, ProgressBar, Section, Stack, Tabs } from '../components';
import { NtosWindow } from '../layouts';

export const NtosCyborgRemoteMonitor = (props, context) => {
  return (
    <NtosWindow
      width={600}
      height={800}>
      <NtosWindow.Content>
        <NtosCyborgRemoteMonitorContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};

export const ProgressSwitch = param => {
  switch (param) {
    case -1:
      return '_';
    case 0:
      return 'Connecting';
    case 25:
      return 'Starting Transfer';
    case 50:
      return 'Downloading';
    case 75:
      return 'Downloading';
    case 100:
      return 'Formatting';
  }
};

export const NtosCyborgRemoteMonitorContent = (props, context) => {
  const { act, data } = useBackend(context);
  const [tab_main, setTab_main] = useSharedState(context, 'tab_main', 1);
  const {
    card,
    cyborgs = [],
    DL_progress,
  } = data;
  const storedlog = data.borglog || [];

  if (!cyborgs.length) {
    return (
      <NoticeBox>
        No cyborg units detected.
      </NoticeBox>
    );
  }

  return (
    <Stack fill vertical>
      <Stack.Item>
        <Tabs>
          <Tabs.Tab
            icon="robot"
            lineHeight="23px"
            selected={tab_main === 1}
            onClick={() => setTab_main(1)}>
            Cyborgs
          </Tabs.Tab>
          <Tabs.Tab
            icon="clipboard"
            lineHeight="23px"
            selected={tab_main === 2}
            onClick={() => setTab_main(2)}>
            Stored Log File
          </Tabs.Tab>
        </Tabs>
      </Stack.Item>
      {tab_main === 1 && (
        <>
          {!card && (
            <Stack.Item>
              <NoticeBox>
                Certain features require an ID card login.
              </NoticeBox>
            </Stack.Item>
          )}
          <Stack.Item grow={1}>
            <Section fill scrollable>
              {cyborgs.map(cyborg => (
                <Section
                  key={cyborg.ref}
                  title={cyborg.name}
                  buttons={(
                    <Button
                      icon="terminal"
                      content="Send Message"
                      color="blue"
                      disabled={!card}
                      onClick={() => act('messagebot', {
                        ref: cyborg.ref,
                      })} />
                  )}>
                  <LabeledList>
                    <LabeledList.Item label="Status">
                      <Box color={cyborg.status
                        ? 'bad'
                        : cyborg.locked_down
                          ? 'average'
                          : 'good'}>
                        {cyborg.status
                          ? "Not Responding"
                          : cyborg.locked_down
                            ? "Locked Down"
                            : cyborg.shell_discon
                              ? "Nominal/Disconnected"
                              : "Nominal"}
                      </Box>
                    </LabeledList.Item>
                    <LabeledList.Item label="Condition">
                      <Box color={cyborg.integ <= 25
                        ? 'bad'
                        : cyborg.integ <= 75
                          ? 'average'
                          : 'good'}>
                        {cyborg.integ === 0
                          ? "Hard Fault"
                          : cyborg.integ <= 25
                            ? "Functionality Disrupted"
                            : cyborg.integ <= 75
                              ? "Functionality Impaired"
                              : "Operational"}
                      </Box>
                    </LabeledList.Item>
                    <LabeledList.Item label="Charge">
                      <Box color={cyborg.charge <= 30
                        ? 'bad'
                        : cyborg.charge <= 70
                          ? 'average'
                          : 'good'}>
                        {typeof cyborg.charge === 'number'
                          ? cyborg.charge + "%"
                          : "Not Found"}
                      </Box>
                    </LabeledList.Item>
                    <LabeledList.Item label="Model">
                      {cyborg.module}
                    </LabeledList.Item>
                    <LabeledList.Item label="Upgrades">
                      {cyborg.upgrades}
                    </LabeledList.Item>
                  </LabeledList>
                </Section>
              ))}
            </Section>
          </Stack.Item>
        </>
      )}
      {tab_main === 2 && (
        <>
          <Stack.Item>
            <Section>
              Scan a cyborg to download stored logs.
              <ProgressBar
                value={DL_progress/100}>
                {ProgressSwitch(DL_progress)}
              </ProgressBar>
            </Section>
          </Stack.Item>
          <Stack.Item
            grow={1}>
            <Section
              fill
              scrollable
              backgroundColor="black">
              {storedlog.map(log => (
                <Box
                  mb={1}
                  key={log}
                  color="green">
                  {log}
                </Box>
              ))}
            </Section>
          </Stack.Item>
        </>
      )}
    </Stack>
  );
};


code:
import { NtosWindow } from '../layouts';
import { NtosCyborgRemoteMonitorContent } from './NtosCyborgRemoteMonitor';

export const NtosCyborgRemoteMonitorSyndicate = (props, context) => {
  return (
    <NtosWindow
      width={600}
      height={800}
      theme="syndicate">
      <NtosWindow.Content scrollable>
        <NtosCyborgRemoteMonitorContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Section, Table } from '../components';
import { NtosWindow } from '../layouts';

export const NtosFileManager = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    PC_device_theme,
    usbconnected,
    files = [],
    usbfiles = [],
  } = data;
  return (
    <NtosWindow theme={PC_device_theme}>
      <NtosWindow.Content scrollable>

          <FileTable
            files={files}
            usbconnected={usbconnected}
            onUpload={file => act('PRG_copytousb', { name: file })}
            onDelete={file => act('PRG_deletefile', { name: file })}
            onRename={(file, newName) => act('PRG_renamefile', {
              name: file,
              new_name: newName,
            })}
            onDuplicate={file => act('PRG_clone', { file: file })}
            onToggleSilence={file => act('PRG_togglesilence', { name: file })} />

        {usbconnected && (

            <FileTable
              usbmode
              files={usbfiles}
              usbconnected={usbconnected}
              onUpload={file => act('PRG_copyfromusb', { name: file })}
              onDelete={file => act('PRG_usbdeletefile', { name: file })}
              onRename={(file, newName) => act('PRG_usbrenamefile', {
                name: file,
                new_name: newName,
              })}
              onDuplicate={file => act('PRG_clone', { file: file })} />

        )}
      </NtosWindow.Content>
    </NtosWindow>
  );
};

const FileTable = props => {
  const {
    files = [],
    usbconnected,
    usbmode,
    onUpload,
    onDelete,
    onRename,
    onToggleSilence,
  } = props;
  return (

          File

          Type

          Size

      {files.map(file => (

            {!file.undeletable ? (
              <Button.Input
                fluid
                content={file.name}
                currentValue={file.name}
                tooltip="Rename"
                onCommit={(e, value) => onRename(file.name, value)} />
            ) : (
              file.name
            )}

            {file.type}

            {file.size}

            {!!file.alert_able && (
              <Button
                icon={file.alert_silenced ? 'bell-slash' : 'bell'}
                color={file.alert_silenced ? 'red' : 'default'}
                tooltip={file.alert_silenced ? 'Unmute Alerts' : 'Mute Alerts'}
                onClick={() => onToggleSilence(file.name)} />
            )}
            {!file.undeletable && (
              <>
                <Button.Confirm
                  icon="trash"
                  confirmIcon="times"
                  confirmContent=""
                  tooltip="Delete"
                  onClick={() => onDelete(file.name)} />
                {!!usbconnected && (
                  usbmode ? (
                    <Button
                      icon="download"
                      tooltip="Download"
                      onClick={() => onUpload(file.name)} />
                  ) : (
                    <Button
                      icon="upload"
                      tooltip="Upload"
                      onClick={() => onUpload(file.name)} />
                  )
                )}
              </>
            )}

      ))}

  );
};


code:
import { useBackend } from '../backend';
import { Button, Section, Table, NoticeBox, Dimmer, Box } from '../components';
import { NtosWindow } from '../layouts';

export const NtosJobManager = (props, context) => {
  return (
    <NtosWindow
      width={400}
      height={620}>
      <NtosWindow.Content scrollable>
        <NtosJobManagerContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};

export const NtosJobManagerContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    authed,
    cooldown,
    slots = [],
    prioritized = [],
  } = data;
  if (!authed) {
    return (
      <NoticeBox>
        Current ID does not have access permissions to change job slots.
      </NoticeBox>
    );
  }
  return (

      {cooldown > 0 && (
        <Dimmer>
          <Box
            bold
            textAlign="center"
            fontSize="20px">
            On Cooldown: {cooldown}s
          </Box>
        </Dimmer>
      )}

            Prioritized

            Slots

        {slots.map(slot => (

              <Button.Checkbox
                fluid
                content={slot.title}
                disabled={slot.total <= 0}
                checked={slot.total > 0 && prioritized.includes(slot.title)}
                onClick={() => act('PRG_priority', {
                  target: slot.title,
                })} />

              {slot.current} / {slot.total}

              <Button
                content="Open"
                disabled={!slot.status_open}
                onClick={() => act('PRG_open_job', {
                  target: slot.title,
                })} />
              <Button
                content="Close"
                disabled={!slot.status_close}
                onClick={() => act('PRG_close_job', {
                  target: slot.title,
                })} />

        ))}

  );
};


code:
import { useBackend } from '../backend';
import { Button, ColorBox, Section, Table } from '../components';
import { NtosWindow } from '../layouts';

export const NtosMain = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    device_theme,
    programs = [],
    has_light,
    light_on,
    comp_light_color,
    removable_media = [],
    cardholder,
    login = [],
  } = data;
  return (
    <NtosWindow
      title={device_theme === 'syndicate'
        && 'Syndix Main Menu'
        || 'NtOS Main Menu'}
      theme={device_theme}
      width={400}
      height={500}>
      <NtosWindow.Content scrollable>
        {!!has_light && (

            <Button
              width="144px"
              icon="lightbulb"
              selected={light_on}
              onClick={() => act('PC_toggle_light')}>
              Flashlight: {light_on ? 'ON' : 'OFF'}
            </Button>
            <Button
              ml={1}
              onClick={() => act('PC_light_color')}>
              Color:
              <ColorBox ml={1} color={comp_light_color} />
            </Button>

        )}
        {!!cardholder && (
          <Section
            title="User Login"
            buttons={(
              <Button
                icon="eject"
                content="Eject ID"
                disabled={!login.IDName}
                onClick={() => act('PC_Eject_Disk', { name: "ID" })}
              />
            )}>

                ID Name: {login.IDName}

                Assignment: {login.IDJob}

        )}
        {!!removable_media.length && (

              {removable_media.map(device => (

                    <Button
                      fluid
                      color="transparent"
                      icon="eject"
                      content={device}
                      onClick={() => act('PC_Eject_Disk', { name: device })}
                    />

              ))}

        )}

            {programs.map(program => (

                  <Button
                    fluid
                    color={program.alert ? 'yellow' : 'transparent'}
                    icon={program.icon}
                    content={program.desc}
                    onClick={() => act('PC_runprogram', {
                      name: program.name,
                    })} />

                  {!!program.running && (
                    <Button
                      color="transparent"
                      icon="times"
                      tooltip="Close program"
                      tooltipPosition="left"
                      onClick={() => act('PC_killprogram', {
                        name: program.name,
                      })} />
                  )}

            ))}

      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Dimmer, Icon, Input, Section, Stack } from '../components';
import { NtosWindow } from '../layouts';

// byond defines for the program state
const CLIENT_ONLINE = 2;
const CLIENT_AWAY = 1;
const CLIENT_OFFLINE = 0;

const STATUS2TEXT = {
  0: "Offline",
  1: "Away",
  2: "Online",
};

const NoChannelDimmer = (props, context) => {
  const { act, data } = useBackend(context);
  const { owner } = data;
  return (
    <Dimmer>
      <Stack align="baseline" vertical>
        <Stack.Item>
          <Stack ml={-2}>
            <Stack.Item>
              <Icon
                color="green"
                name="grin-beam"
                size={10}
              />
            </Stack.Item>
            <Stack.Item mt={-8}>
              <Icon
                name="comment-dots"
                size={10}
              />
            </Stack.Item>
            <Stack.Item ml={-1}>
              <Icon
                color="green"
                name="smile"
                size={10}
              />
            </Stack.Item>
          </Stack>
        </Stack.Item>
        <Stack.Item fontSize="18px">
          Click a channel to start chatting!
        </Stack.Item>
        <Stack.Item fontSize="15px">
          (If you're new, you may wannaa set your name in the bottom left!)
        </Stack.Item>
      </Stack>
    </Dimmer>
  );
};

export const NtosNetChat = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    title,
    can_admin,
    adminmode,
    authed,
    username,
    active_channel,
    is_operator,
    strong,
    selfref,
    all_channels = [],
    clients = [],
    messages = [],
  } = data;
  const in_channel = (active_channel !== null);
  const authorized = (authed || adminmode);
  // this list has cliented ordered from their status. online > away > offline
  const displayed_clients = clients.sort((clientA, clientB) => {
    if (clientA.operator) {
      return -1;
    }
    if (clientB.operator) {
      return 1;
    }
    return clientB.status - clientA.status;
  });
  const client_color = (client) => {
    if (client.operator) {
      return "green";
    }
    switch (client.status) {
      case CLIENT_ONLINE:
        return "white";
      case CLIENT_AWAY:
        return "yellow";
      case CLIENT_OFFLINE:
      default:
        return "label";
    }
  };
  // client from this computer!
  const this_client = clients.find(client => client.ref === selfref);
  return (
    <NtosWindow
      width={900}
      height={675}>
      <NtosWindow.Content>
        <Stack fill>
          <Stack.Item>
            <Section fill>
              <Stack vertical fill>
                <Stack.Item grow>
                  <Button.Input
                    fluid
                    content="New Channel..."
                    onCommit={(e, value) => act('PRG_newchannel', {
                      new_channel_name: value,
                    })} />
                  {all_channels.map(channel => (
                    <Button
                      fluid
                      key={channel.chan}
                      content={channel.chan}
                      selected={channel.id === active_channel}
                      color="transparent"
                      onClick={() => act('PRG_joinchannel', {
                        id: channel.id,
                      })} />
                  ))}
                </Stack.Item>
                <Stack.Item>
                  <Box>
                    Username:
                  </Box>
                  <Button.Input
                    fluid
                    mt={1}
                    content={username + '...'}
                    currentValue={username}
                    onCommit={(e, value) => act('PRG_changename', {
                      new_name: value,
                    })} />
                  {!!can_admin && (
                    <Button
                      fluid
                      bold
                      content={"ADMIN MODE: " + (adminmode ? 'ON' : 'OFF')}
                      color={adminmode ? 'bad' : 'good'}
                      onClick={() => act('PRG_toggleadmin')} />
                  )}
                </Stack.Item>
              </Stack>
            </Section>
          </Stack.Item>
          <Stack.Divider />
          <Stack.Item grow={5}>
            <Stack vertical fill>
              <Stack.Item grow>
                <Section scrollable fill>
                  {in_channel && (
                    authorized ? (
                      messages.map(message => (
                        <Box
                          key={message.msg}>
                          {message.msg}
                        </Box>
                      ))
                    ) : (
                      <Box
                        textAlign="center">
                        <Icon
                          name="exclamation-triangle"
                          mt={4}
                          fontSize="40px" />
                        <Box
                          mt={1}
                          bold
                          fontSize="18px">
                          THIS CHANNEL IS PASSWORD PROTECTED
                        </Box>
                        <Box mt={1}>
                          INPUT PASSWORD TO ACCESS
                        </Box>
                      </Box>
                    )
                  ) || (
                    <NoChannelDimmer />
                  )}
                </Section>
              </Stack.Item>
              {!!in_channel && (
                <Input
                  backgroundColor={(this_client && this_client.muted) && "red"}
                  height="22px"
                  placeholder={(this_client && this_client.muted)
                    && "You are muted!" || "Message "+title}
                  fluid
                  selfClear
                  mt={1}
                  onEnter={(e, value) => act('PRG_speak', {
                    message: value,
                  })} />
              )}
            </Stack>
          </Stack.Item>
          {!!in_channel && (
            <>
              <Stack.Divider />
              <Stack.Item grow={1}>
                <Stack vertical fill>
                  <Stack.Item grow>
                    <Section scrollable fill>
                      <Stack vertical>
                        {displayed_clients.map(client => (
                          <Stack height="18px" fill key={client.name}>
                            <Stack.Item
                              basis={0}
                              grow
                              color={client_color(client)}>
                              {client.name}
                            </Stack.Item>
                            {client !== this_client && (
                              <>
                                <Stack.Item>
                                  <Button
                                    disabled={this_client.muted}
                                    compact
                                    icon="bullhorn"
                                    tooltip={!this_client.muted
                                      && "Ping" || "You are muted!"}
                                    tooltipPosition="left"
                                    onClick={() => act('PRG_ping_user', {
                                      ref: client.ref,
                                    })} />
                                </Stack.Item>
                                {!!is_operator && (
                                  <Stack.Item>
                                    <Button
                                      compact
                                      icon={!client.muted
                                        && "volume-up" || "volume-mute"}
                                      color={!client.muted
                                        && "green" || "red"}
                                      tooltip={!client.muted
                                        && "Mute this User" || "Unmute this User"}
                                      tooltipPosition="left"
                                      onClick={() => act('PRG_mute_user', {
                                        ref: client.ref,
                                      })} />
                                  </Stack.Item>
                                )}
                              </>
                            )}
                          </Stack>
                        ))}
                      </Stack>
                    </Section>
                  </Stack.Item>
                  <Section>
                    <Stack.Item mb="8px">
                      Settings for {title}:
                    </Stack.Item>
                    <Stack.Item>
                      {!!(in_channel && authorized) && (
                        <>
                          <Button.Input
                            fluid
                            content="Save log..."
                            defaultValue="new_log"
                            onCommit={(e, value) => act('PRG_savelog', {
                              log_name: value,
                            })} />
                          <Button.Confirm
                            fluid
                            content="Leave Channel"
                            onClick={() => act('PRG_leavechannel')} />
                        </>
                      )}
                      {!!(is_operator && authed) && (
                        <>
                          <Button.Confirm
                            fluid
                            disabled={strong}
                            content="Delete Channel"
                            onClick={() => act('PRG_deletechannel')} />
                          <Button.Input
                            fluid
                            disabled={strong}
                            content="Rename Channel..."
                            onCommit={(e, value) => act('PRG_renamechannel', {
                              new_name: value,
                            })} />
                          <Button.Input
                            fluid
                            content="Set Password..."
                            onCommit={(e, value) => act('PRG_setpassword', {
                              new_password: value,
                            })} />
                        </>
                      )}
                    </Stack.Item>
                  </Section>
                </Stack>
              </Stack.Item>
            </>
          )}
        </Stack>
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NoticeBox, Section } from '../components';
import { NtosWindow } from '../layouts';

export const NtosNetDos = (props, context) => {
  return (
    <NtosWindow
      width={400}
      height={250}
      theme="syndicate">
      <NtosWindow.Content>
        <NtosNetDosContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};

export const NtosNetDosContent = (props, context) => {
  const { act, data } = useBackend(context);

  const {
    relays = [],
    focus,
    target,
    speed,
    overload,
    capacity,
    error,
  } = data;

  if (error) {
    return (
      <>
        <NoticeBox>
          {error}
        </NoticeBox>
        <Button
          fluid
          content="Reset"
          textAlign="center"
          onClick={() => act('PRG_reset')}
        />
      </>
    );
  }

  const generate10String = length => {
    let outString = "";
    const factor = (overload / capacity);
    while (outString.length < length) {
      if (Math.random() > factor) {
        outString += "0";
      } else {
        outString += "1";
      }
    }
    return outString;
  };

  const lineLength = 45;

  if (target) {
    return (

        <Box>
          CURRENT SPEED: {speed} GQ/s
        </Box>
        <Box>
          {/* I don't care anymore */}
          {generate10String(lineLength)}
        </Box>
        <Box>
          {generate10String(lineLength)}
        </Box>
        <Box>
          {generate10String(lineLength)}
        </Box>
        <Box>
          {generate10String(lineLength)}
        </Box>
        <Box>
          {generate10String(lineLength)}
        </Box>

    );
  }

  return (

      <LabeledList>
        <LabeledList.Item label="Target">
          {relays.map(relay => (
            <Button
              key={relay.id}
              content={relay.id}
              selected={focus === relay.id}
              onClick={() => act('PRG_target_relay', {
                targid: relay.id,
              })}
            />
          ))}
        </LabeledList.Item>
      </LabeledList>
      <Button
        fluid
        bold
        content="EXECUTE"
        color="bad"
        textAlign="center"
        disabled={!focus}
        mt={1}
        onClick={() => act('PRG_execute')}
      />

  );
};


code:
import { scale, toFixed } from 'common/math';
import { useBackend, useLocalState } from '../backend';
import { Box, Button, Stack, Icon, LabeledList, NoticeBox, ProgressBar, Section, Tabs } from '../components';
import { flow } from 'common/fp';
import { filter, sortBy } from 'common/collections';
import { NtosWindow } from '../layouts';

export const NtosNetDownloader = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    PC_device_theme,
    disk_size,
    disk_used,
    downloadcompletion,
    downloading,
    downloadname,
    downloadsize,
    error,
    emagged,
    categories,
    programs,
  } = data;
  const all_categories = ['All'].concat(categories);
  const downloadpercentage = toFixed(
    scale(downloadcompletion, 0, downloadsize) * 100
  );
  const [
    selectedCategory,
    setSelectedCategory,
  ] = useLocalState(context, 'category', all_categories[0]);
  const items = flow([
    // This filters the list to only contain programs with category
    selectedCategory !== all_categories[0]
    && filter(program => program.category === selectedCategory),
    // This filters the list to only contain verified programs
    (!emagged && PC_device_theme === "ntos")
    && filter(program => program.verifiedsource === 1),
    // This sorts all programs in the lists by name and compatibility
    sortBy(
      program => -program.compatible,
      program => program.filedesc),
  ])(programs);
  const disk_free_space = downloading
    ? disk_size - toFixed(disk_used + downloadcompletion)
    : disk_size - disk_used;
  return (
    <NtosWindow
      theme={PC_device_theme}
      width={600}
      height={600}>
      <NtosWindow.Content scrollable>
        {!!error && (
          <NoticeBox>
            <Box mb={1}>
              {error}
            </Box>
            <Button
              content="Reset"
              onClick={() => act('PRG_reseterror')} />
          </NoticeBox>
        )}

          <LabeledList>
            <LabeledList.Item
              label="Hard drive"
              buttons={(!!downloading) && (
                <Button
                  icon="spinner"
                  iconSpin={1}
                  tooltipPosition="left"
                  tooltip={!!downloading && (
                    `Download: ${downloadname}.prg (${downloadpercentage}%)`
                  )} />
              ) || (!!downloadname && (
                <Button
                  color="good"
                  icon="download"
                  tooltipPosition="left"
                  tooltip={`${downloadname}.prg downloaded`} />
              ))}>
              <ProgressBar
                value={downloading ? disk_used + downloadcompletion : disk_used}
                minValue={0}
                maxValue={disk_size}>
                <Box textAlign="left">
                  {`${disk_free_space} GQ free of ${disk_size} GQ`}
                </Box>
              </ProgressBar>
            </LabeledList.Item>
          </LabeledList>

        <Stack>
          <Stack.Item minWidth="105px" shrink={0} basis={0}>
            <Tabs vertical>
              {all_categories.map(category => (
                <Tabs.Tab
                  key={category}
                  selected={category === selectedCategory}
                  onClick={() => setSelectedCategory(category)}>
                  {category}
                </Tabs.Tab>
              ))}
            </Tabs>
          </Stack.Item>
          <Stack.Item grow={1} basis={0}>
            {items?.map(program => (
              <Program
                key={program.filename}
                program={program} />
            ))}
          </Stack.Item>
        </Stack>
      </NtosWindow.Content>
    </NtosWindow>
  );
};

const Program = (props, context) => {
  const { program } = props;
  const { act, data } = useBackend(context);
  const {
    PC_device_theme,
    disk_size,
    disk_used,
    downloading,
    downloadname,
    downloadcompletion,
  } = data;
  const disk_free = disk_size - disk_used;
  return (

      <Stack align="baseline">
        <Stack.Item grow={1} blod>
          <Icon name={program.icon} mr={1} />
          {program.filedesc}
        </Stack.Item>
        <Stack.Item shrink={0} width="48px" textAlign="right" color="label" nowrap>
          {program.size} GQ
        </Stack.Item>
        <Stack.Item shrink={0} width="134px" textAlign="right">
          {(downloading && program.filename === downloadname) && (
            <ProgressBar
              width="101px"
              height="23px"
              color="good"
              minValue={0}
              maxValue={program.size}
              value={downloadcompletion} />
          ) || (
            (!program.installed
              && program.compatible
              && program.access
              && program.size < disk_free) && (
              <Button
                bold
                icon="download"
                content="Download"
                disabled={downloading}
                tooltipPosition="left"
                tooltip={!!downloading && ('Awaiting download completion...')}
                onClick={() => act('PRG_downloadfile', {
                  filename: program.filename,
                })} />
            ) || (
              <Button
                bold
                icon={program.installed ? 'check' : 'times'}
                color={
                  program.installed ? 'good'
                    : !program.compatible ? 'bad' : 'grey'
                }
                content={
                  program.installed ? 'Installed'
                    : !program.compatible ? 'Incompatible'
                      : !program.access ? 'No Access' : 'No Space'
                } />
            )
          )}
        </Stack.Item>
      </Stack>
      <Box mt={1} italic color="label">
        {program.fileinfo}
      </Box>
      {(!program.verifiedsource && PC_device_theme === "ntos") && (
        <NoticeBox mt={1} mb={0} danger fontSize="12px">
          Unverified source. Please note that Nanotrasen does not recommend
          download and usage of software from non-official servers.
        </NoticeBox>
      )}

  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NoticeBox, NumberInput, Section } from '../components';
import { NtosWindow } from '../layouts';

export const NtosNetMonitor = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    ntnetrelays,
    ntnetstatus,
    config_softwaredownload,
    config_peertopeer,
    config_communication,
    config_systemcontrol,
    idsalarm,
    idsstatus,
    ntnetmaxlogs,
    maxlogs,
    minlogs,
    ntnetlogs = [],
  } = data;
  return (
    <NtosWindow>
      <NtosWindow.Content scrollable>
        <NoticeBox>
          WARNING: Disabling wireless transmitters when using
          a wireless device may prevent you from reenabling them!
        </NoticeBox>
        <Section
          title="Wireless Connectivity"
          buttons={(
            <Button.Confirm
              icon={ntnetstatus ? 'power-off' : 'times'}
              content={ntnetstatus ? 'ENABLED' : 'DISABLED'}
              selected={ntnetstatus}
              onClick={() => act('toggleWireless')} />
          )}>
          {ntnetrelays ? (
            <LabeledList>
              <LabeledList.Item label="Active NTNet Relays">
                {ntnetrelays}
              </LabeledList.Item>
            </LabeledList>
          ) : "No Relays Connected"}

          <LabeledList>
            <LabeledList.Item
              label="Software Downloads"
              buttons={(
                <Button
                  icon={config_softwaredownload ? 'power-off' : 'times'}
                  content={config_softwaredownload ? 'ENABLED' : 'DISABLED'}
                  selected={config_softwaredownload}
                  onClick={() => act('toggle_function', { id: "1" })} />
              )} />
            <LabeledList.Item
              label="Peer to Peer Traffic"
              buttons={(
                <Button
                  icon={config_peertopeer ? 'power-off' : 'times'}
                  content={config_peertopeer ? 'ENABLED' : 'DISABLED'}
                  selected={config_peertopeer}
                  onClick={() => act('toggle_function', { id: "2" })} />
              )} />
            <LabeledList.Item
              label="Communication Systems"
              buttons={(
                <Button
                  icon={config_communication ? 'power-off' : 'times'}
                  content={config_communication ? 'ENABLED' : 'DISABLED'}
                  selected={config_communication}
                  onClick={() => act('toggle_function', { id: "3" })} />
              )} />
            <LabeledList.Item
              label="Remote System Control"
              buttons={(
                <Button
                  icon={config_systemcontrol ? 'power-off' : 'times'}
                  content={config_systemcontrol ? 'ENABLED' : 'DISABLED'}
                  selected={config_systemcontrol}
                  onClick={() => act('toggle_function', { id: "4" })} />
              )} />
          </LabeledList>

          {!!idsalarm && (
            <>
              <NoticeBox>
                NETWORK INCURSION DETECTED
              </NoticeBox>
              <Box italics>
                Abnormal activity has been detected in the network.
                Check system logs for more information
              </Box>
            </>
          )}
          <LabeledList>
            <LabeledList.Item
              label="IDS Status"
              buttons={(
                <>
                  <Button
                    icon={idsstatus ? 'power-off' : 'times'}
                    content={idsstatus ? 'ENABLED' : 'DISABLED'}
                    selected={idsstatus}
                    onClick={() => act('toggleIDS')} />
                  <Button
                    icon="sync"
                    content="Reset"
                    color="bad"
                    onClick={() => act('resetIDS')} />
                </>
              )} />
            <LabeledList.Item
              label="Max Log Count"
              buttons={(
                <NumberInput
                  value={ntnetmaxlogs}
                  minValue={minlogs}
                  maxValue={maxlogs}
                  width="39px"
                  onChange={(e, value) => act('updatemaxlogs', {
                    new_number: value,
                  })}
                />
              )} />
          </LabeledList>
          <Section
            title="System Log"
            level={2}
            buttons={(
              <Button.Confirm
                icon="trash"
                content="Clear Logs"
                onClick={() => act('purgelogs')} />
            )}>
            {ntnetlogs.map(log => (
              <Box key={log.entry} className="candystripe">
                {log.entry}
              </Box>
            ))}

      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { resolveAsset } from '../assets';
import { useBackend, useLocalState } from '../backend';
import { Button, NoticeBox, Section, Stack, Tabs } from '../components';
import { NtosWindow } from '../layouts';

export const NtosPortraitPrinter = (props, context) => {
  const { act, data } = useBackend(context);
  const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0);
  const [listIndex, setListIndex] = useLocalState(context, 'listIndex', 0);
  const {
    library,
    library_secure,
    library_private,
  } = data;
  const TABS = [
    {
      name: 'Common Portraits',
      asset_prefix: "library",
      list: library,
    },
    {
      name: 'Secure Portraits',
      asset_prefix: "library_secure",
      list: library_secure,
    },
    {
      name: 'Private Portraits',
      asset_prefix: "library_private",
      list: library_private,
    },
  ];
  const tab2list = TABS[tabIndex].list;
  const current_portrait_title = tab2list[listIndex]["title"];
  const current_portrait_asset_name = TABS[tabIndex].asset_prefix + "_" + tab2list[listIndex]["md5"];
  return (
    <NtosWindow
      title="Art Galaxy"
      width={400}
      height={406}>
      <NtosWindow.Content>
        <Stack vertical fill>
          <Stack.Item>
            <Section fitted>
              <Tabs fluid textAlign="center">
                {TABS.map((tabObj, i) => !!tabObj.list && (
                  <Tabs.Tab
                    key={i}
                    selected={i === tabIndex}
                    onClick={() => {
                      setListIndex(0);
                      setTabIndex(i);
                    }}>
                    {tabObj.name}
                  </Tabs.Tab>
                ))}
              </Tabs>
            </Section>
          </Stack.Item>
          <Stack.Item grow={2}>
            <Section fill>
              <Stack
                height="100%"
                align="center"
                justify="center"
                direction="column">
                <Stack.Item>
                  <img
                    src={resolveAsset(current_portrait_asset_name)}
                    height="128px"
                    width="128px"
                    style={{
                      'vertical-align': 'middle',
                      '-ms-interpolation-mode': 'nearest-neighbor',
                    }} />
                </Stack.Item>
                <Stack.Item className="Section__titleText">
                  {current_portrait_title}
                </Stack.Item>
              </Stack>
            </Section>
          </Stack.Item>
          <Stack.Item>
            <Stack>
              <Stack.Item grow={3}>
                <Section height="100%">
                  <Stack justify="space-between">
                    <Stack.Item grow={1}>
                      <Button
                        icon="angle-double-left"
                        disabled={listIndex === 0}
                        onClick={() => setListIndex(0)}
                      />
                    </Stack.Item>
                    <Stack.Item grow={3}>
                      <Button
                        disabled={listIndex === 0}
                        icon="chevron-left"
                        onClick={() => setListIndex(listIndex-1)}
                      />
                    </Stack.Item>
                    <Stack.Item grow={3}>
                      <Button
                        icon="check"
                        content="Print Portrait"
                        onClick={() => act("select", {
                          tab: tabIndex+1,
                          selected: listIndex+1,
                        })}
                      />
                    </Stack.Item>
                    <Stack.Item grow={1}>
                      <Button
                        icon="chevron-right"
                        disabled={listIndex === tab2list.length-1}
                        onClick={() => setListIndex(listIndex+1)}
                      />
                    </Stack.Item>
                    <Stack.Item>
                      <Button
                        icon="angle-double-right"
                        disabled={listIndex === tab2list.length-1}
                        onClick={() => setListIndex(tab2list.length-1)}
                      />
                    </Stack.Item>
                  </Stack>
                </Section>
              </Stack.Item>
            </Stack>
            <Stack.Item mt={1} mb={-1}>
              <NoticeBox info>
                Printing a canvas costs 10 paper from
                the printer installed in your machine.
              </NoticeBox>
            </Stack.Item>
          </Stack.Item>
        </Stack>
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { NtosWindow } from '../layouts';
import { PowerMonitorContent } from './PowerMonitor';

export const NtosPowerMonitor = () => {
  return (
    <NtosWindow
      width={550}
      height={700}>
      <NtosWindow.Content scrollable>
        <PowerMonitorContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { classes } from 'common/react';
import { resolveAsset } from '../assets';
import { useBackend } from '../backend';
import { Box, Button, Flex, Icon, NoticeBox, Section } from '../components';
import { NtosWindow } from '../layouts';

export const NtosRadar = (props, context) => {
  return (
    <NtosWindow
      width={800}
      height={600}
      theme="ntos">
      <NtosRadarContent sig_err={"Signal Lost"} />
    </NtosWindow>
  );
};

export const NtosRadarContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    selected,
    object = [],
    target = [],
    scanning,
  } = data;
  const { sig_err } = props;
  return (
    <Flex
      direction={"row"}
      hight="100%">
      <Flex.Item
        position="relative"
        width={20.5}
        hight="100%">
        <NtosWindow.Content scrollable>

            <Button
              icon="redo-alt"
              content={scanning?"Scanning...":"Scan"}
              color="blue"
              disabled={scanning}
              onClick={() => act('scan')} />
            {!object.length && !scanning && (

                No trackable signals found

            )}
            {!scanning && object.map(object => (

 {
                  act('selecttarget', {
                    ref: object.ref,
                  });
                }}>
                {object.name}

            ))}

        </NtosWindow.Content>
      </Flex.Item>
      <Flex.Item
        style={{
          'background-image': 'url("'
            + resolveAsset('ntosradarbackground.png')
            + '")',
          'background-position': 'center',
          'background-repeat': 'no-repeat',
          'top': '20px',
        }}
        position="relative"
        m={1.5}
        width={45}
        height={45}>
        {Object.keys(target).length === 0
          ? !!selected && (
            <NoticeBox
              position="absolute"
              top={20.6}
              left={1.35}
              width={42}
              fontSize="30px"
              textAlign="center">
              {sig_err}
            </NoticeBox>
          )
          : !!target.userot && (
            <Box as="img"
              src={resolveAsset(target.arrowstyle)}
              position="absolute"
              top="20px"
              left="243px"
              style={{
                'transform': `rotate(${target.rot}deg)`,
              }} />
          ) || (
            <Icon
              name={target.pointer}
              position="absolute"
              size={2}
              color={target.color}
              top={((target.locy * 10) + 19) + 'px'}
              left={((target.locx * 10) + 16) + 'px'} />
          )}
      </Flex.Item>
    </Flex>
  );
};


code:
import { NtosWindow } from '../layouts';
import { NtosRadarContent } from './NtosRadar';

export const NtosRadarSyndicate = (props, context) => {
  return (
    <NtosWindow
      width={800}
      height={600}
      theme="syndicate">
      <NtosRadarContent sig_err={"Out of Range"} />
    </NtosWindow>
  );
};


code:
import { RequestKioskContent } from './RequestKiosk';
import { NtosWindow } from '../layouts';

export const NtosRequestKiosk = (props, context) => {
  return (
    <NtosWindow
      width={550}
      height={600}>
      <NtosWindow.Content scrollable>
        <RequestKioskContent />
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { Section, Button, LabeledList } from '../components';
import { useBackend } from '../backend';
import { NtosWindow } from '../layouts';

export const NtosRevelation = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <NtosWindow
      width={400}
      height={250}
      theme="syndicate">
      <NtosWindow.Content>
        <Section>
          <Button.Input
            fluid
            content="Obfuscate Name..."
            onCommit={(e, value) => act('PRG_obfuscate', {
              new_name: value,
            })}
            mb={1} />
          <LabeledList>
            <LabeledList.Item
              label="Payload Status"
              buttons={(
                <Button
                  content={data.armed ? 'ARMED' : 'DISARMED'}
                  color={data.armed ? 'bad' : 'average'}
                  onClick={() => act('PRG_arm')} />
              )} />
          </LabeledList>
          <Button
            fluid
            bold
            content="ACTIVATE"
            textAlign="center"
            color="bad"
            disabled={!data.armed} />
        </Section>
      </NtosWindow.Content>
    </NtosWindow>
  );
};


code:
import { useBackend } from '../backend';
import { Button, LabeledList, ProgressBar, Section, Stack } from '../components';
import { NtosWindow } from '../layouts';

const getMuleByRef = (mules, ref) => {
  return mules?.find(mule => mule.mule_ref === ref);
};

export const NtosRoboControl = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    bots,
    id_owner,
    has_id,
  } = data;
  return (
    <NtosWindow
      width={550}
      height={550}>
      <NtosWindow.Content scrollable>
        <Section title="Robot Control Console">
          <LabeledList>
            <LabeledList.Item label="Id Card">
              {id_owner}
              {!!has_id && (
                <Button
                  ml={2}
                  icon="eject"
                  content="Eject"
                  onClick={() => act('ejectcard')} />
              )}
            </LabeledList.Item>
            <LabeledList.Item label="Bots in range">
              {data.botcount}
            </LabeledList.Item>
          </LabeledList>
        </Section>
        {bots?.map(robot => (
          <RobotInfo
            key={robot.bot_ref}
            robot={robot} />
        ))}
      </NtosWindow.Content>
    </NtosWindow>
  );
};

const RobotInfo = (props, context) => {
  const { robot } = props;
  const { act, data } = useBackend(context);
  const mules = data.mules || [];
  // Get a mule object
  const mule = !!robot.mule_check
    && getMuleByRef(mules, robot.bot_ref);
  // Color based on type of a robot
  const color = robot.mule_check === 1
    ? 'rgba(110, 75, 14, 1)'
    : 'rgba(74, 59, 140, 1)';
  return (
    <Section
      title={robot.name}
      style={{
        border: `4px solid ${color}`,
      }}
      buttons={mule && (
        <>
          <Button
            icon="play"
            tooltip="Go to Destination."
            onClick={() => act('go', {
              robot: mule.mule_ref,
            })} />
          <Button
            icon="pause"
            tooltip="Stop Moving."
            onClick={() => act('stop', {
              robot: mule.mule_ref,
            })} />
          <Button
            icon="home"
            tooltip="Travel Home."
            tooltipPosition="bottom-start"
            onClick={() => act('home', {
              robot: mule.mule_ref,
            })} />
        </>
      )}>
      <Stack>
        <Stack.Item grow={1} basis={0}>
          <LabeledList>
            <LabeledList.Item label="Model">
              {robot.model}
            </LabeledList.Item>
            <LabeledList.Item label="Location">
              {robot.locat}
            </LabeledList.Item>
            <LabeledList.Item label="Status">
              {robot.mode}
            </LabeledList.Item>
            {mule && (
              <>
                <LabeledList.Item label="Loaded Cargo">
                  {data.load || "N/A"}
                </LabeledList.Item>
                <LabeledList.Item label="Home">
                  {mule.home}
                </LabeledList.Item>
                <LabeledList.Item label="Destination">
                  {mule.dest || "N/A"}
                </LabeledList.Item>
                <LabeledList.Item label="Power">
                  <ProgressBar
                    value={mule.power}
                    minValue={0}
                    maxValue={100}
                    ranges={{
                      good: [60, Infinity],
                      average: [20, 60],
                      bad: [-Infinity, 20],
                    }} />
                </LabeledList.Item>
              </>
            )}
          </LabeledList>
        </Stack.Item>
        <Stack.Item width="150px">
          {mule && (
            <>
              <Button
                fluid
                content="Set Destination"
                onClick={() => act('destination', {
                  robot: mule.mule_ref,
                })} />
              <Button
                fluid
                content="Set ID"
                onClick={() => act('setid', {
                  robot: mule.mule_ref,
                })} />
              <Button
                fluid
                content="Set Home"
                onClick={() => act('sethome', {
                  robot: mule.mule_ref,
                })} />
              <Button
                fluid
                content="Unload Cargo"
                onClick={() => act('unload', {
                  robot: mule.mule_ref,
                })} />
              <Button.Checkbox
                fluid
                content="Auto Return"
                checked={mule.autoReturn}
                onClick={() => act('autoret', {
                  robot: mule.mule_ref,
                })} />
              <Button.Checkbox
                fluid
                content="Auto Pickup"
                checked={mule.autoPickup}
                onClick={() => act('autopick', {
                  robot: mule.mule_ref,
                })} />
              <Button.Checkbox
                fluid
                content="Delivery Report"
                checked={mule.reportDelivery}
                onClick={() => act('report', {
                  robot: mule.mule_ref,
                })} />
            </>
          )}
          {!mule && (
            <>
              <Button
                fluid
                content="Stop Patrol"
                onClick={() => act('patroloff', {
                  robot: robot.bot_ref,
                })} />
              <Button
                fluid
                content="Start Patrol"
                onClick={() => act('patrolon', {
                  robot: robot.bot_ref,
                })} />
              <Button
                fluid
                content="Summon"
                onClick={() => act('summon', {
                  robot: robot.bot_ref,
                })} />
              <Button
                fluid
                content="Eject PAi"
                onClick={() => act('ejectpai', {
                  robot: robot.bot_ref,
                })} />
            </>
          )}
        </Stack.Item>
      </Stack>
    </Section>
  );
};