[MIRROR] Work on phasing out tgui collections.ts (#10059)

Co-authored-by: ShadowLarkens <shadowlarkens@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-02-03 03:15:50 -07:00
committed by GitHub
parent d887a54728
commit 56759cb95b
32 changed files with 296 additions and 267 deletions

View File

@@ -82,7 +82,7 @@
/obj/item/stack/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Stack", name)
ui = new(user, src, "MaterialStack", name)
ui.open()
/obj/item/stack/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)

View File

@@ -4,12 +4,10 @@
* @license MIT
*/
import { map } from 'common/collections';
export const selectChat = (state) => state.chat;
export const selectChatPages = (state) =>
map(state.chat.pages, (id: string) => state.chat.pageById[id]);
state.chat.pages.map((id: string) => state.chat.pageById[id]);
export const selectCurrentChatPage = (state) =>
state.chat.pageById[state.chat.currentPageId];

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Button, Section, Table } from 'tgui-core/components';
@@ -35,11 +34,20 @@ export const ShuttleList = (props) => {
const { shuttles, overmap_ships } = data;
shuttles.sort((a, b) => a.name.localeCompare(b.name));
overmap_ships.sort((a, b) => {
let a_cmp = a.name?.toLowerCase() || a.name || a.ref;
let b_cmp = a.name?.toLowerCase() || a.name || a.ref;
return a_cmp.localeCompare(b_cmp);
});
return (
<Section noTopPadding>
<Section title="Classic Shuttles">
<Table>
{sortBy(shuttles, (f: Shuttle) => f.name).map((shuttle) => (
{shuttles.map((shuttle) => (
<Table.Row key={shuttle.ref}>
<Table.Cell collapsing>
<Button
@@ -66,10 +74,7 @@ export const ShuttleList = (props) => {
</Section>
<Section title="Overmap Ships">
<Table>
{sortBy(
overmap_ships,
(f: OvermapShip) => f.name?.toLowerCase() || f.name || f.ref,
).map((ship) => (
{overmap_ships.map((ship) => (
<Table.Row key={ship.ref}>
<Table.Cell collapsing>
<Button onClick={() => act('adminobserve', { ref: ship.ref })}>

View File

@@ -1,14 +1,15 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Button, LabeledList, Section, Stack } from 'tgui-core/components';
import { Data, species, styles } from './types';
import { Data, species } from './types';
export const AppearanceChangerSpecies = (props) => {
const { act, data } = useBackend<Data>();
const { species, specimen } = data;
const sortedSpecies = sortBy(species || [], (val: species) => val.specimen);
const sortedSpecies = (species || []).sort((a: species, b: species) =>
a.specimen.localeCompare(b.specimen),
);
return (
<Section title="Species" fill scrollable>
@@ -65,6 +66,10 @@ export const AppearanceChangerEars = (props) => {
const { ear_style, ear_styles } = data;
ear_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Stack vertical fill>
<Stack.Item grow>
@@ -75,17 +80,15 @@ export const AppearanceChangerEars = (props) => {
>
-- Not Set --
</Button>
{sortBy(ear_styles, (e: styles) => e.name.toLowerCase()).map(
(ear) => (
<Button
key={ear.instance}
onClick={() => act('ear', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
),
)}
{ear_styles.map((ear) => (
<Button
key={ear.instance}
onClick={() => act('ear', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
))}
</Section>
</Stack.Item>
<Stack.Item grow>
@@ -96,17 +99,15 @@ export const AppearanceChangerEars = (props) => {
>
-- Not Set --
</Button>
{sortBy(ear_styles, (e: styles) => e.name.toLowerCase()).map(
(ear) => (
<Button
key={ear.instance}
onClick={() => act('ear_secondary', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
),
)}
{ear_styles.map((ear) => (
<Button
key={ear.instance}
onClick={() => act('ear_secondary', { ref: ear.instance })}
selected={ear.name === ear_style}
>
{ear.name}
</Button>
))}
</Section>
</Stack.Item>
</Stack>
@@ -118,6 +119,10 @@ export const AppearanceChangerTails = (props) => {
const { tail_style, tail_styles } = data;
tail_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Section title="Tails" fill scrollable>
<Button
@@ -126,7 +131,7 @@ export const AppearanceChangerTails = (props) => {
>
-- Not Set --
</Button>
{sortBy(tail_styles, (e: styles) => e.name.toLowerCase()).map((tail) => (
{tail_styles.map((tail) => (
<Button
key={tail.instance}
onClick={() => act('tail', { ref: tail.instance })}
@@ -143,6 +148,9 @@ export const AppearanceChangerWings = (props) => {
const { act, data } = useBackend<Data>();
const { wing_style, wing_styles } = data;
wing_styles.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Section title="Wings" fill scrollable>
@@ -152,7 +160,7 @@ export const AppearanceChangerWings = (props) => {
>
-- Not Set --
</Button>
{sortBy(wing_styles, (e: styles) => e.name.toLowerCase()).map((wing) => (
{wing_styles.map((wing) => (
<Button
key={wing.instance}
onClick={() => act('wing', { ref: wing.instance })}

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { NanoMap } from 'tgui/components';
@@ -32,9 +31,8 @@ export const AtmosControl = (props) => {
export const AtmosControlContent = (props) => {
const { act, data, config } = useBackend<Data>();
let sortedAlarms = sortBy(data.alarms || [], (alarm: alarm) => alarm.name);
// sortedAlarms = sortedAlarms.slice(1, 3);
const { alarms } = data;
alarms.sort((a, b) => a.name.localeCompare(b.name));
const [tabIndex, setTabIndex] = useState(0);
const [zoom, setZoom] = useState(1);
@@ -44,7 +42,7 @@ export const AtmosControlContent = (props) => {
if (tabIndex === 0) {
body = (
<Section title="Alarms">
{sortedAlarms.map((alarm) => (
{alarms.map((alarm) => (
<Button
key={alarm.name}
color={
@@ -64,7 +62,7 @@ export const AtmosControlContent = (props) => {
body = (
<Box height="526px" mb="0.5rem" overflow="hidden">
<NanoMap zoomScale={data.zoomScale} onZoom={(v) => setZoom(v)}>
{sortedAlarms
{alarms
.filter((x) => ~~x.z === ~~config.mapZLevel)
.map((cm) => (
<NanoMap.Marker

View File

@@ -1,4 +1,3 @@
import { filter, sortBy } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
@@ -10,7 +9,6 @@ import {
Section,
Stack,
} from 'tgui-core/components';
import { flow } from 'tgui-core/fp';
import { BooleanLike, classes } from 'tgui-core/react';
import { createSearch } from 'tgui-core/string';
@@ -57,31 +55,24 @@ export const selectCameras = (
networkFilter: string = '',
): camera[] => {
const testSearch = createSearch(searchText, (camera: camera) => camera.name);
return flow([
(cameras: camera[]) =>
// Null camera filter
filter(cameras, (camera) => notEmpty(camera?.name)),
(cameras: camera[]) => {
// Optional search term
return cameras
.filter((camera) => notEmpty(camera?.name))
.filter((camera) => {
if (!searchText) {
return cameras;
return true;
} else {
return filter(cameras, testSearch);
return testSearch(camera);
}
},
(cameras: camera[]) => {
// Optional network filter
})
.filter((camera) => {
if (!networkFilter) {
return cameras;
return true;
} else {
return filter(cameras, (camera) =>
camera.networks.includes(networkFilter),
);
return camera.networks.includes(networkFilter);
}
},
// Slightly expensive, but way better than sorting in BYOND
(cameras: camera[]) => sortBy(cameras, (camera) => camera.name),
])(cameras);
})
.sort((a, b) => a.name.localeCompare(b.name));
};
export const CameraConsole = (props) => {

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Box, LabeledList, Section } from 'tgui-core/components';
import { decodeHtmlEntities, toTitleCase } from 'tgui-core/string';
@@ -16,28 +15,29 @@ export const CommunicatorWeatherTab = (props) => {
<Section title="Weather">
<Section title="Current Conditions">
<LabeledList>
{filter(
aircontents,
(i: AirContent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
).map((item: AirContent) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
item.val,
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
{aircontents
.filter(
(i: AirContent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
)
.map((item: AirContent) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
item.val,
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
</LabeledList>
</Section>
<Section title="Weather Reports">

View File

@@ -1,11 +1,9 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Box, Icon, Tabs } from 'tgui-core/components';
import { flow } from 'tgui-core/fp';
import { CrewMonitorCrew } from './CrewMonitorCrew';
import { CrewMonitorMapView } from './CrewMonitorMapView';
import { crewmember, Data } from './types';
import { Data } from './types';
export const CrewMonitorContent = (props: {
tabIndex: number;
@@ -17,19 +15,12 @@ export const CrewMonitorContent = (props: {
const { crewmembers = [] } = data;
const crew: crewmember[] = flow([
(crewmembers: crewmember[]) => sortBy(crewmembers, (cm) => cm.name),
(crewmembers: crewmember[]) => sortBy(crewmembers, (cm) => cm?.x),
(crewmembers: crewmember[]) => sortBy(crewmembers, (cm) => cm?.y),
(crewmembers: crewmember[]) => sortBy(crewmembers, (cm) => cm?.realZ),
])(crewmembers);
const tab: React.JSX.Element[] = [];
// Data view
// Please note, if you ever change the zoom values,
// you MUST update styles/components/Tooltip.scss
// and change the @for scss to match.
tab[0] = <CrewMonitorCrew crew={crew} />;
tab[0] = <CrewMonitorCrew crew={crewmembers} />;
tab[1] = <CrewMonitorMapView zoom={props.zoom} onZoom={props.onZoom} />;

View File

@@ -88,7 +88,13 @@ export function getSortedCrew(
return flow([
(shownCrew: crewmember[]) => {
if (sortType === 'name') {
const sorted = shownCrew.sort((a, b) => a.name.localeCompare(b.name));
const sorted = shownCrew.sort(
(a, b) =>
a.name.localeCompare(b.name) ||
a.realZ - b.realZ ||
a.x - b.x ||
a.y - b.y,
);
if (nameSortOrder) {
return sorted.reverse();
}
@@ -100,7 +106,9 @@ export function getSortedCrew(
(shownCrew: crewmember[]) => {
if (sortType === 'damage') {
const sorted = shownCrew.sort(
(a, b) => getTotalDamage(a) - getTotalDamage(b),
(a, b) =>
getTotalDamage(a) - getTotalDamage(b) ||
a.name.localeCompare(b.name),
);
if (damageSortOrder) {
return sorted.reverse();
@@ -112,29 +120,13 @@ export function getSortedCrew(
},
(shownCrew: crewmember[]) => {
if (sortType === 'location') {
const sorted = shownCrew.sort((a, b) => a.x - b.x);
if (locationSortOrder) {
return sorted.reverse();
}
return sorted;
} else {
return shownCrew;
}
},
(shownCrew: crewmember[]) => {
if (sortType === 'location') {
const sorted = shownCrew.sort((a, b) => a.y - b.y);
if (locationSortOrder) {
return sorted.reverse();
}
return sorted;
} else {
return shownCrew;
}
},
(shownCrew: crewmember[]) => {
if (sortType === 'location') {
const sorted = shownCrew.sort((a, b) => a.realZ - b.realZ);
const sorted = shownCrew.sort(
(a, b) =>
a.realZ - b.realZ ||
a.x - b.x ||
a.y - b.y ||
a.name.localeCompare(b.name),
);
if (locationSortOrder) {
return sorted.reverse();
}

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Button, Section } from 'tgui-core/components';
@@ -13,13 +12,13 @@ export const FileCabinet = (props) => {
const { contents } = data;
// Wow, the filing cabinets sort themselves in 2320.
const sortedContents = sortBy(contents || [], (val: content) => val.name);
contents.sort((a, b) => a.name.localeCompare(b.name));
return (
<Window width={350} height={300}>
<Window.Content scrollable>
<Section>
{sortedContents.map((item) => (
{contents.map((item) => (
<Button
key={item.ref}
fluid

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { flow } from 'tgui-core/fp';
import { createSearch } from 'tgui-core/string';
@@ -27,7 +26,7 @@ export function selectRecords(records: record[], searchText = ''): record[] {
if (!searchText) {
return records;
} else {
return filter(records, (record) => {
return records.filter((record) => {
return nameSearch(record) || idSearch(record) || dnaSearch(record);
});
}

View File

@@ -1,6 +1,5 @@
// Currently not used!
import { map, sortBy } from 'common/collections';
import { vecLength, vecSubtract } from 'common/vector';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
@@ -16,7 +15,7 @@ import { flow } from 'tgui-core/fp';
import { clamp } from 'tgui-core/math';
import { BooleanLike } from 'tgui-core/react';
const coordsToVec = (coords) => map(coords.split(', '), parseFloat);
const coordsToVec = (coords: string) => coords.split(', ').map(parseFloat);
type Data = {
currentArea: string;
@@ -31,16 +30,25 @@ type Data = {
type signal = {
entrytag: string;
coords: string;
dist: number;
dist?: number;
degrees: number;
};
function sortSignal(a: signal, b: signal) {
if (a.dist === undefined && b.dist === undefined) return 0;
if (a.dist === undefined) return 1;
if (b.dist === undefined) return -1;
if (a.dist < b.dist) return -1;
if (a.dist > b.dist) return 1;
else return a.entrytag.localeCompare(b.entrytag);
}
export const Gps = (props) => {
const { act, data } = useBackend<Data>();
const { currentArea, currentCoords, globalmode, power, tag, updating } = data;
const signals: signal[] = flow([
(signals: signal[]) =>
map(signals, (signal, index) => {
signals.map((signal, index) => {
// Calculate distance to the target. BYOND distance is capped to 127,
// that's why we roll our own calculations here.
const dist =
@@ -55,14 +63,7 @@ export const Gps = (props) => {
);
return { ...signal, dist, index };
}),
(signals: signal[]) =>
sortBy(
signals,
// Signals with distance metric go first
(signal) => signal.dist === undefined,
// Sort alphabetically
(signal) => signal.entrytag,
),
(signals: signal[]) => signals.sort((a, b) => sortSignal(a, b)),
])(data.signals || []);
return (
<Window title="Global Positioning System" width={470} height={700}>

View File

@@ -1,5 +1,4 @@
/* eslint react/no-danger: "off" */
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button, LabeledList, Section } from 'tgui-core/components';
@@ -24,6 +23,8 @@ export const GuestPass = (props) => {
const { area, giver, giveName, reason, duration, mode, log, uid } = data;
area.sort((a, b) => a.area_name.localeCompare(b.area_name));
return (
<Window width={500} height={520}>
<Window.Content scrollable>
@@ -80,7 +81,7 @@ export const GuestPass = (props) => {
Issue Pass
</Button.Confirm>
<Section title="Access">
{sortBy(area, (a: area) => a.area_name).map((a) => (
{area.map((a) => (
<Button.Checkbox
checked={a.on}
key={a.area}

View File

@@ -1,4 +1,3 @@
import { filter, sortBy } from 'common/collections';
import { useBackend, useSharedState } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import {
@@ -95,17 +94,18 @@ const ICPrinterCategories = (props) => {
'',
);
const selectedCategory = filter(
categories,
const selectedCategory = categories.filter(
(cat: category) => cat.name === categoryTarget,
)[0];
categories.sort((a, b) => a.name.localeCompare(b.name));
return (
<Section fill title="Circuits">
<Stack fill>
<Stack.Item mr={2} basis="20%">
<Tabs vertical>
{sortBy(categories, (cat: category) => cat.name).map((cat) => (
{categories.map((cat) => (
<Tabs.Tab
selected={categoryTarget === cat.name}
onClick={() => setcategoryTarget(cat.name)}
@@ -120,8 +120,9 @@ const ICPrinterCategories = (props) => {
{selectedCategory ? (
<Section fill scrollable>
<LabeledList>
{sortBy(selectedCategory.items, (item: item) => item.name).map(
(item) => (
{selectedCategory.items
.sort((a, b) => a.name.localeCompare(b.name))
.map((item) => (
<LabeledList.Item
key={item.name}
label={item.name}
@@ -138,8 +139,7 @@ const ICPrinterCategories = (props) => {
>
{item.desc}
</LabeledList.Item>
),
)}
))}
</LabeledList>
</Section>
) : (

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { Fragment } from 'react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
@@ -276,13 +275,21 @@ export const IdentificationComputerRegions = (props: { actName: string }) => {
const { regions } = data;
if (regions) {
regions.sort((a, b) => a.name.localeCompare(b.name));
for (let region of regions) {
region.accesses.sort((a, b) => a.desc.localeCompare(b.desc));
}
}
return (
<Stack wrap="wrap">
{regions &&
sortBy(regions, (r) => r.name).map((region) => (
regions.map((region) => (
<Stack.Item mb={1} basis="content" grow key={region.name}>
<Section title={region.name} height="100%">
{sortBy(region.accesses, (a) => a.desc).map((access) => (
{region.accesses.map((access) => (
<Box key={access.ref}>
<Button
fluid

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend, useSharedState } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import {
@@ -579,7 +578,7 @@ const prepareSearch = (
if (!searchText) {
return laws;
} else {
return filter(laws, testSearch);
return laws.filter(testSearch);
}
},
])(laws);

View File

@@ -1,8 +1,18 @@
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button, Collapsible, Section, Table } from 'tgui-core/components';
import {
Box,
Button,
Collapsible,
Input,
Section,
Stack,
Table,
} from 'tgui-core/components';
import { createSearch } from 'tgui-core/string';
type Data = { amount: number; recipes: recipe[] };
type Data = { amount: number; recipes: Record<string, recipe>[] };
type recipe = {
res_amount: number;
@@ -11,27 +21,49 @@ type recipe = {
ref: string;
};
export const Stack = (props) => {
export const MaterialStack = (props) => {
const { data } = useBackend<Data>();
const { amount, recipes } = data;
const [searchText, setSearchText] = useState('');
return (
<Window width={400} height={600}>
<Window.Content scrollable>
<Section title={'Amount: ' + amount}>
<RecipeList recipes={recipes} />
<Stack vertical>
<Stack.Item>
<Input
fluid
placeholder="Search for recipe..."
value={searchText}
onInput={(e, val) => setSearchText(val)}
/>
</Stack.Item>
<Stack.Item>
<RecipeList recipes={recipes} searchText={searchText} />
</Stack.Item>
</Stack>
</Section>
</Window.Content>
</Window>
);
};
const RecipeList = (props: { recipes: recipe[] }) => {
const { recipes } = props;
const RecipeList = (props: {
recipes: Record<string, recipe>[];
searchText: string;
}) => {
const { recipes, searchText } = props;
const sortedKeys = Object.keys(recipes).sort();
const searcher = createSearch(searchText, (recipe: string) => {
return recipe;
});
const filteredKeys = sortedKeys.filter(searcher);
// Shunt all categories to the top.
// We're not using this for now, keeping it here in case someone really hates color coding later.
// let nonCategories = sortedKeys.filter(item => recipes[item].ref !== undefined);
@@ -41,7 +73,7 @@ const RecipeList = (props: { recipes: recipe[] }) => {
// let newSortedKeys = nonCategories.concat(categories);
return sortedKeys.map((title, index) => {
return filteredKeys.map((title, index) => {
// if (title === "--DIVIDER--") {
// return (
// <Box mt={1} mb={1}>
@@ -54,7 +86,7 @@ const RecipeList = (props: { recipes: recipe[] }) => {
return (
<Collapsible key={index} ml={1} mb={-0.7} color="label" title={title}>
<Box ml={1}>
<RecipeList recipes={recipe} />
<RecipeList recipes={recipe} searchText={searchText} />
</Box>
</Collapsible>
);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { flow } from 'tgui-core/fp';
import { createSearch } from 'tgui-core/string';
@@ -23,7 +22,7 @@ export function prepareSearch<T extends SearchObject>(
if (!searchText) {
return objects as any;
} else {
return filter(objects, testSearch) as any;
return objects.filter(testSearch) as any;
}
},
])(objects);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { NtosWindow } from 'tgui/layouts';
import { Button, LabeledList, Section, Table } from 'tgui-core/components';
@@ -63,8 +62,7 @@ const WarrantList = (props) => {
const { allwarrants = [] } = data;
const ourWarrants = filter(
allwarrants,
const ourWarrants = allwarrants.filter(
(w: warrant) => w.arrestsearch === type,
);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Box, LabeledList } from 'tgui-core/components';
import { decodeHtmlEntities } from 'tgui-core/string';
@@ -38,28 +37,29 @@ export const pda_atmos_scan = (props) => {
return (
<Box>
<LabeledList>
{filter(
aircontents,
(i: aircontent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
).map((item) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
item.val,
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
{aircontents
.filter(
(i: aircontent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
)
.map((item) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
item.val,
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
</LabeledList>
</Box>
);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { ReactNode, useEffect, useRef, useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Box, Button, Image, LabeledList, Section } from 'tgui-core/components';
@@ -290,8 +289,9 @@ const ActiveConversationASCII = (props: {
return (
<Box>
{filter(messages, (im: message) => im.target === active_conversation).map(
(im, i) => (
{messages
.filter((im: message) => im.target === active_conversation)
.map((im, i) => (
<Box
key={i}
className={
@@ -300,8 +300,7 @@ const ActiveConversationASCII = (props: {
>
{im.sent ? 'You:' : 'Them:'} {decodeHtmlEntities(im.message)}
</Box>
),
)}
))}
</Box>
);
};

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
@@ -96,12 +95,12 @@ export const PersonalCrafting = (props) => {
const shownRecipes: uiRecipe[] = flow([
(recipes: uiRecipe[]) =>
filter(recipes, (recipe) => recipe.category === tab),
recipes.filter((recipe) => recipe.category === tab),
(recipes: uiRecipe[]) => {
if (!searchText) {
return recipes;
} else {
return filter(recipes, testSearch);
return recipes.filter(testSearch);
}
},
])(recipes);

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import {
@@ -33,6 +32,7 @@ export const PowerMonitorFocus = (props: { focus: sensor }) => {
...history.supply,
...history.demand,
);
// Process area data
const areas: area[] = flow([
(areas: area[]) =>
@@ -45,24 +45,24 @@ export const PowerMonitorFocus = (props: { focus: sensor }) => {
if (sortByField !== 'name') {
return areas;
} else {
return sortBy(areas, (area) => area.name);
return areas.sort((a, b) => a.name.localeCompare(b.name));
}
},
(areas: area[]) => {
if (sortByField !== 'charge') {
return areas;
} else {
return sortBy(areas, (area) => -area.charge);
return areas.sort((a, b) => b.charge - a.charge);
}
},
(areas: area[]) => {
if (sortByField !== 'draw') {
return areas;
} else {
return sortBy(
areas,
(area) => -powerRank(area.load),
(area) => -parseFloat(area.load),
return areas.sort(
(a, b) =>
powerRank(b.load) - powerRank(a.load) ||
parseFloat(b.load) - parseFloat(a.load),
);
}
},
@@ -70,17 +70,18 @@ export const PowerMonitorFocus = (props: { focus: sensor }) => {
if (sortByField !== 'problems') {
return areas;
} else {
return sortBy(
areas,
(area) => area.eqp,
(area) => area.lgt,
(area) => area.env,
(area) => area.charge,
(area) => area.name,
return areas.sort(
(a, b) =>
a.eqp - b.eqp ||
a.lgt - b.lgt ||
a.env - b.env ||
a.charge - b.charge ||
a.name.localeCompare(b.name),
);
}
},
])(focus.areas);
return (
<>
<Section

View File

@@ -1,4 +1,4 @@
import { binaryInsertWith, sortBy } from 'common/collections';
import { binaryInsertWith } from 'common/collections';
import { ReactNode, useState } from 'react';
import { useBackend } from 'tgui/backend';
import {
@@ -25,8 +25,13 @@ const binaryInsertPreference = (
value: PreferenceChild,
) => binaryInsertWith(collection, value, (child) => child.name);
function sortPref(k: [string, PreferenceChild[]]) {
k[1].sort((a, b) => a.name.localeCompare(b.name));
return k;
}
const sortByName = (array: [string, PreferenceChild[]][]) =>
sortBy(array, ([name]) => name);
array.map((k, _) => sortPref(k)).sort((a, b) => a[0].localeCompare(b[0]));
export const GamePreferencesPage = (props) => {
const { act, data } = useBackend<PreferencesMenuData>();

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import {
ComponentType,
createElement,
@@ -6,6 +5,7 @@ import {
useEffect,
useState,
} from 'react';
import React from 'react';
import { sendAct, useBackend } from 'tgui/backend';
import {
Box,
@@ -21,8 +21,12 @@ import { BooleanLike } from 'tgui-core/react';
import { createSetPreference, PreferencesMenuData } from '../../data';
import { ServerPreferencesFetcher } from '../../ServerPreferencesFetcher';
export const sortChoices = (array: [string, ReactNode][]) =>
sortBy(array, ([name]) => name);
function sortNode(...node: [string, ReactNode][]) {
node.sort((a, b) => a[0].localeCompare(b[0]));
return node;
}
export const sortChoices = (array: [string, ReactNode][]) => sortNode(...array);
export type Feature<
TReceiving,

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend, useSharedState } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { Box, Button, LabeledList, Section, Tabs } from 'tgui-core/components';
@@ -194,8 +193,9 @@ const ResearchServerData = (props: { server: server }) => {
))}
</Section>
<Section title="Designs">
{filter(server.designs, (design: techDes) => !!design.name).map(
(design) => (
{server.designs
.filter((design: techDes) => !!design.name)
.map((design) => (
<LabeledList.Item
label={design.name}
key={design.name}
@@ -215,8 +215,7 @@ const ResearchServerData = (props: { server: server }) => {
</Button.Confirm>
}
/>
),
)}
))}
</Section>
</>
);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { flow } from 'tgui-core/fp';
import { createSearch } from 'tgui-core/string';
@@ -33,14 +32,14 @@ export function robotSpriteSearcher(
if (!searchText) {
return sprites;
} else {
return filter(sprites, testSearch);
return sprites.filter(testSearch);
}
},
(sprites: spriteOption[]) => {
if (!subtypes.length) {
return sprites;
} else {
return filter(sprites, (sprite) => subtypes.includes(sprite.type));
return sprites.filter((sprite) => subtypes.includes(sprite.type));
}
},
])(sprites);

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import {
@@ -39,13 +38,15 @@ export const SeedStorage = (props) => {
const { seeds } = data;
const sortedSeeds = sortBy(seeds, (seed: seed) => seed.name.toLowerCase());
seeds.sort((a, b) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
);
return (
<Window width={600} height={760}>
<Window.Content scrollable>
<Section title="Seeds">
{sortedSeeds.map((seed) => (
{seeds.map((seed) => (
<Stack mt={-1} key={seed.name + seed.uid}>
<Stack.Item basis="60%">
<Collapsible title={toTitleCase(seed.name) + ' #' + seed.uid}>

View File

@@ -1,8 +1,6 @@
import { filter, sortBy } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Box, Button, Section, Stack } from 'tgui-core/components';
import { flow } from 'tgui-core/fp';
import { Data, supplyPack } from './types';
@@ -13,15 +11,19 @@ export const SupplyConsoleMenuOrder = (props) => {
const [activeCategory, setActiveCategory] = useState<string | null>(null);
const viewingPacks: supplyPack[] = flow([
(supply_packs: supplyPack[]) =>
filter(supply_packs, (val) => val.group === activeCategory),
(supply_packs: supplyPack[]) =>
filter(supply_packs, (val) => !val.contraband || !!contraband),
(supply_packs: supplyPack[]) => sortBy(supply_packs, (val) => val.name),
(supply_packs: supplyPack[]) =>
sortBy(supply_packs, (val) => val.cost > supply_points),
])(supply_packs);
function sortPack(a: supplyPack, b: supplyPack) {
if (a.cost < supply_points && b.cost > supply_points) return -1;
if (a.cost > supply_points && b.cost < supply_points) return 1;
return a.name.localeCompare(b.name);
}
const viewingPacks: supplyPack[] = supply_packs
.filter(
(pack) =>
(pack.group === activeCategory && !pack.contraband) || !!contraband,
)
.sort((a, b) => sortPack(a, b));
// const viewingPacks = sortBy(val => val.name)(supply_packs).filter(val => val.group === activeCategory);

View File

@@ -1,4 +1,3 @@
import { sortBy } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import {
@@ -73,6 +72,10 @@ export const TelesciConsoleContent = (props) => {
lastTeleData,
} = data;
if (sectorOptions) {
sectorOptions.sort();
}
return (
<Section
title="Telepad Controls"
@@ -120,7 +123,7 @@ export const TelesciConsoleContent = (props) => {
</LabeledList.Item>
<LabeledList.Item label="Sector">
{sectorOptions &&
sortBy(sectorOptions, (v) => v).map((z) => (
sectorOptions.map((z) => (
<Button
key={z}
icon="check-circle"

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useState } from 'react';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
@@ -208,7 +207,7 @@ export const prepareSearch = (
if (!searchText) {
return products;
} else {
return filter(products, testSearch);
return products.filter(testSearch);
}
},
])(products);

View File

@@ -1,4 +1,3 @@
import { filter } from 'common/collections';
import { useBackend } from 'tgui/backend';
import { Window } from 'tgui/layouts';
import { LabeledList, Section } from 'tgui-core/components';
@@ -47,28 +46,29 @@ export const pAIAtmos = (props) => {
<Window.Content scrollable>
<Section>
<LabeledList>
{filter(
aircontents,
(i: aircontent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
).map((item: aircontent) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
parseFloat(item.val),
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
{aircontents
.filter(
(i: aircontent) =>
i.val !== '0' ||
i.entry === 'Pressure' ||
i.entry === 'Temperature',
)
.map((item: aircontent) => (
<LabeledList.Item
key={item.entry}
label={item.entry}
color={getItemColor(
parseFloat(item.val),
item.bad_low,
item.poor_low,
item.poor_high,
item.bad_high,
)}
>
{item.val}
{decodeHtmlEntities(item.units)}
</LabeledList.Item>
))}
</LabeledList>
</Section>
</Window.Content>