From ba1d3eef8ce38a14395b33be13601e33737142a4 Mon Sep 17 00:00:00 2001
From: Letter N <24603524+LetterN@users.noreply.github.com>
Date: Tue, 21 Jul 2020 15:02:32 +0800
Subject: [PATCH] new! ui
---
tgui/packages/tgui/interfaces/Biogenerator.js | 188 ++++++++++++++++++
tgui/packages/tgui/interfaces/MafiaPanel.js | 107 ++++++++++
.../NtosCyborgRemoteMonitorSyndicate.js | 15 ++
.../packages/tgui/interfaces/SeedExtractor.js | 89 +++++++++
4 files changed, 399 insertions(+)
create mode 100644 tgui/packages/tgui/interfaces/Biogenerator.js
create mode 100644 tgui/packages/tgui/interfaces/MafiaPanel.js
create mode 100644 tgui/packages/tgui/interfaces/NtosCyborgRemoteMonitorSyndicate.js
create mode 100644 tgui/packages/tgui/interfaces/SeedExtractor.js
diff --git a/tgui/packages/tgui/interfaces/Biogenerator.js b/tgui/packages/tgui/interfaces/Biogenerator.js
new file mode 100644
index 0000000000..7142cb045b
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/Biogenerator.js
@@ -0,0 +1,188 @@
+import { classes } from 'common/react';
+import { createSearch } from 'common/string';
+import { Fragment } from 'inferno';
+import { useBackend, useLocalState } from '../backend';
+import { Box, Button, Dimmer, Flex, Icon, Input, Section, Table, Tabs, NoticeBox, NumberInput } from '../components';
+import { formatMoney } from '../format';
+import { Window } from '../layouts';
+
+const MAX_SEARCH_RESULTS = 25;
+
+export const Biogenerator = (props, context) => {
+ const { data } = useBackend(context);
+ const {
+ beaker,
+ processing,
+ } = data;
+ return (
+
+ {!!processing && (
+
+
+ {' Processing...'}
+
+ )}
+
+ {!beaker && (
+ No Container
+ )}
+ {!!beaker && (
+
+ )}
+
+
+ );
+};
+
+export const BiogeneratorContent = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ biomass,
+ can_process,
+ categories = [],
+ } = data;
+ const [
+ searchText,
+ setSearchText,
+ ] = useLocalState(context, 'searchText', '');
+ const [
+ selectedCategory,
+ setSelectedCategory,
+ ] = useLocalState(context, 'category', categories[0]?.name);
+ const testSearch = createSearch(searchText, item => {
+ return item.name;
+ });
+ const items = searchText.length > 0
+ // Flatten all categories and apply search to it
+ && categories
+ .flatMap(category => category.items || [])
+ .filter(testSearch)
+ .filter((item, i) => i < MAX_SEARCH_RESULTS)
+ // Select a category and show all items in it
+ || categories
+ .find(category => category.name === selectedCategory)
+ ?.items
+ // If none of that results in a list, return an empty list
+ || [];
+ return (
+
+ );
+};
+
+const ItemList = (props, context) => {
+ const { act } = useBackend(context);
+ const [
+ hoveredItem,
+ setHoveredItem,
+ ] = useLocalState(context, 'hoveredItem', {});
+ const hoveredCost = hoveredItem && hoveredItem.cost || 0;
+ // Append extra hover data to items
+ const items = props.items.map(item => {
+ const [
+ amount,
+ setAmount,
+ ] = useLocalState(context, "amount" + item.name, 1);
+ const notSameItem = hoveredItem && hoveredItem.name !== item.name;
+ const notEnoughHovered = props.biomass - hoveredCost
+ * hoveredItem.amount < item.cost * amount;
+ const disabledDueToHovered = notSameItem && notEnoughHovered;
+ const disabled = props.biomass < item.cost * amount || disabledDueToHovered;
+ return {
+ ...item,
+ disabled,
+ amount,
+ setAmount,
+ };
+ });
+ return items.map(item => (
+
+
+
+ {' '}{item.name}
+
+
+ item.setAmount(value)} />
+
+
+
+
+ ));
+};
diff --git a/tgui/packages/tgui/interfaces/MafiaPanel.js b/tgui/packages/tgui/interfaces/MafiaPanel.js
new file mode 100644
index 0000000000..3412cfed11
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/MafiaPanel.js
@@ -0,0 +1,107 @@
+import { useBackend } from '../backend';
+import { Flex, Button, LabeledList, Section, Box, Table, TimeDisplay } from '../components';
+import { Fragment } from 'inferno';
+import { Window } from '../layouts';
+import { FlexItem } from '../components/Flex';
+
+export const MafiaPanel = (props, context) => {
+ const { act, data } = useBackend(context);
+ const {
+ players,
+ actions,
+ phase,
+ role_info,
+ admin_controls,
+ timeleft,
+ all_roles } = data;
+ return (
+
+
+
+ {!!role_info && (
+
+
+
+
+
+
+
+
+ You are a {role_info.role}
+
+
+
+
+ {role_info.desc}
+
+
+ {!!role_info.action_log && role_info.action_log.map(log_line => (
+
+
+ {role_info.action_log}
+
+
+ ))}
+
+ )}
+
+
+ {!!actions && actions.map(action => {
+ return (
+
+
+ );
+ })}
+ { !!admin_controls && (
+
+
+
+
+
+
+
+ )}
+
+
+
+ {!!players && players.map(player => { return (
+
+ {player.votes !== undefined
+ && (Votes : {player.votes} )}
+ {
+ !!player.actions && player.actions.map(action => {
+ return (
+ ); })
+ }
+ );
+ })}
+
+
+
+
+ {!!all_roles && all_roles.map(r => (
+
+
+ {r}
+
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/NtosCyborgRemoteMonitorSyndicate.js b/tgui/packages/tgui/interfaces/NtosCyborgRemoteMonitorSyndicate.js
new file mode 100644
index 0000000000..07a0038544
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/NtosCyborgRemoteMonitorSyndicate.js
@@ -0,0 +1,15 @@
+import { Fragment } from 'inferno';
+import { useBackend } from '../backend';
+import { Box, Button, LabeledList, NoticeBox, Section } from '../components';
+import { NtosWindow } from '../layouts';
+import { NtosCyborgRemoteMonitorContent } from './NtosCyborgRemoteMonitor';
+
+export const NtosCyborgRemoteMonitorSyndicate = (props, context) => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/SeedExtractor.js b/tgui/packages/tgui/interfaces/SeedExtractor.js
new file mode 100644
index 0000000000..3dbdd6da06
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/SeedExtractor.js
@@ -0,0 +1,89 @@
+import { sortBy } from 'common/collections';
+import { flow } from 'common/fp';
+import { toTitleCase } from 'common/string';
+import { useBackend } from '../backend';
+import { Button, Section, Table } from '../components';
+import { Window } from '../layouts';
+
+/**
+ * This method takes a seed string and splits the values
+ * into an object
+ */
+const splitSeedString = text => {
+ const re = /([^;=]+)=([^;]+)/g;
+ const ret = {};
+ let m;
+ do {
+ m = re.exec(text);
+ if (m) {
+ ret[m[1]] = m[2] + '';
+ }
+ } while (m);
+ return ret;
+};
+
+/**
+ * This method splits up the string "name" we get for the seeds
+ * and creates an object from it include the value that is the
+ * ammount
+ *
+ * @returns {any[]}
+ */
+const createSeeds = seedStrings => {
+ const objs = Object.keys(seedStrings).map(key => {
+ const obj = splitSeedString(key);
+ obj.amount = seedStrings[key];
+ obj.key = key;
+ obj.name = toTitleCase(obj.name.replace('pack of ', ''));
+ return obj;
+ });
+ return flow([
+ sortBy(item => item.name),
+ ])(objs);
+};
+
+export const SeedExtractor = (props, context) => {
+ const { act, data } = useBackend(context);
+ const seeds = createSeeds(data.seeds);
+ return (
+
+
+
+
+
+ Name
+ Lifespan
+ Endurance
+ Maturation
+ Production
+ Yield
+ Potency
+ Instability
+ Stock
+
+ {seeds.map(item => (
+
+ {item.name}
+ {item.lifespan}
+ {item.endurance}
+ {item.maturation}
+ {item.production}
+ {item.yield}
+ {item.potency}
+ {item.instability}
+
+
+
+ ))}
+
+
+
+
+ );
+};