Skip to content

Commit

Permalink
Improve perf on unit page, add SEO optimizations and another utility …
Browse files Browse the repository at this point in the history
…improvements (#258)

* Add IP passing to your backends

* Some fixes

* Unit page optimization

* Fixes
  • Loading branch information
petrvecera authored Oct 4, 2023
1 parent c398748 commit ec24e21
Show file tree
Hide file tree
Showing 17 changed files with 227 additions and 139 deletions.
4 changes: 4 additions & 0 deletions __tests__/pages/api/playerExport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe("playerExportAPIHandler", () => {
test("should return 400 if profileIDs param is missing", async () => {
const req = {
query: {},
headers: {},
};
const res = {
status: jest.fn().mockReturnThis(),
Expand All @@ -33,6 +34,7 @@ describe("playerExportAPIHandler", () => {
query: {
profileIDs: [1, 2, 3],
},
headers: {},
};
const res = {
status: jest.fn().mockReturnThis(),
Expand All @@ -48,6 +50,7 @@ describe("playerExportAPIHandler", () => {
query: {
profileIDs: JSON.stringify(Array(51).fill(1)),
},
headers: {},
};
const res = {
status: jest.fn().mockReturnThis(),
Expand All @@ -63,6 +66,7 @@ describe("playerExportAPIHandler", () => {
query: {
profileIDs: JSON.stringify(["1", "2"]),
},
headers: {},
};
const res = {
status: jest.fn().mockReturnThis(),
Expand Down
21 changes: 12 additions & 9 deletions __tests__/src/coh3stats-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ describe("coh3stats-api", () => {
// @ts-ignore
jest.spyOn(global, "fetch").mockImplementation(setupFetchStub(fakeData));

const result = await getPlayerCardInfo(12345);
const result = await getPlayerCardInfo(12345, false, "fake-ip");
expect(global.fetch).toBeCalledWith(
"https://us-east4-coh3-stats-prod.cloudfunctions.net/getPlayerCardInfoHttp?relicId=12345",
{ headers: { "X-Forwarded-For": "fake-ip", "c-edge-ip": "fake-ip" } },
);
expect(global.fetch).toHaveBeenCalledTimes(1);
expect(result).toEqual(fakeData);
Expand All @@ -48,7 +49,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 500));

try {
await getPlayerCardInfo(12345);
await getPlayerCardInfo(12345, false, "");
} catch (error) {
expect(error).toEqual(new Error("Error getting player card info: test error"));
}
Expand All @@ -65,7 +66,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 400));

try {
await getPlayerCardInfo(12345);
await getPlayerCardInfo(12345, false, "");
} catch (error) {
expect(error).toEqual(new Error("Error getting player card info"));
}
Expand Down Expand Up @@ -210,10 +211,11 @@ describe("coh3stats-api", () => {
.spyOn(global, "fetch")
.mockImplementation(setupFetchStub({ playerMatches: fakeMatchesData }));

const response = await getPlayerRecentMatches(12345);
const response = await getPlayerRecentMatches(12345, "fake-ip");

expect(global.fetch).toBeCalledWith(
"https://us-east4-coh3-stats-prod.cloudfunctions.net/getPlayerMatchesHttp?relicId=12345",
{ headers: { "X-Forwarded-For": "fake-ip", "c-edge-ip": "fake-ip" } },
);
expect(response[0].id).toBe(2);
expect(response[1].id).toBe(1);
Expand All @@ -228,7 +230,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 500));

try {
await getPlayerRecentMatches(12345);
await getPlayerRecentMatches(12345, "");
} catch (error) {
expect(error).toEqual(new Error("Error getting player recent matches: test error"));
}
Expand All @@ -245,7 +247,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 400));

try {
await getPlayerRecentMatches(12345);
await getPlayerRecentMatches(12345, "fake-ip");
} catch (error) {
expect(error).toEqual(new Error("Error getting player recent matches"));
}
Expand All @@ -260,11 +262,12 @@ describe("coh3stats-api", () => {
// @ts-ignore
jest.spyOn(global, "fetch").mockImplementation(setupFetchStub(fakeStreamData));

const response = await getTwitchStreams();
const response = await getTwitchStreams("fake-ip");

expect(response).toEqual("fake stream data");
expect(global.fetch).toBeCalledWith(
"https://us-east4-coh3-stats-prod.cloudfunctions.net/getTwitchStreamsHttp",
{ headers: { "X-Forwarded-For": "fake-ip", "c-edge-ip": "fake-ip" } },
);
});

Expand All @@ -277,7 +280,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 500));

try {
await getTwitchStreams();
await getTwitchStreams("fake-ip");
} catch (error) {
expect(error).toEqual(new Error("Error getting Twitch streams: test error"));
}
Expand All @@ -294,7 +297,7 @@ describe("coh3stats-api", () => {
.mockImplementation(setupFetchStub({ error: "test error" }, false, 400));

try {
await getTwitchStreams();
await getTwitchStreams("fake-ip");
} catch (error) {
expect(error).toEqual(new Error("Error getting Twitch streams"));
}
Expand Down
23 changes: 23 additions & 0 deletions __tests__/src/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
internalSlash,
getIconsPathOnCDN,
buildOriginHeaderValue,
parseFirstIPFromString,
} from "../../src/utils";

describe("getIconsPathOnCDN", () => {
Expand Down Expand Up @@ -169,3 +170,25 @@ describe("buildOriginHeaderValue", () => {
expect(originHeaderValue).toBe("");
});
});

describe("parseFirstIPFromString", () => {
test("should return the first IP address from a string - ipv6", () => {
const result = parseFirstIPFromString("2a00:20:51:5962:618f:cd63:d7ca:af4a, 188.114.102.170");
expect(result).toBe("2a00:20:51:5962:618f:cd63:d7ca:af4a");
});

test("should return the first IP address from a string - ipv4", () => {
const result = parseFirstIPFromString("82.35.144.199, 188.114.102.68");
expect(result).toBe("82.35.144.199");
});

test("should return empty string", () => {
const result = parseFirstIPFromString("");
expect(result).toBe("");
});

test("should return empty string / undefined", () => {
const result = parseFirstIPFromString(undefined);
expect(result).toBe("");
});
});
2 changes: 2 additions & 0 deletions components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import config from "../../config";

const useStyles = createStyles((theme) => ({
footer: {
// position: "fixed",
// bottom: 0,
marginTop: theme.spacing.xl,
paddingTop: `calc(${theme.spacing.xl} * 2)`,
paddingBottom: `calc(${theme.spacing.xl} * 2)`,
Expand Down
8 changes: 7 additions & 1 deletion components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,13 @@ export const Header: React.FC<HeaderProps> = () => {

const MobileView = (
<>
<Burger opened={opened} onClick={toggle} className={classes.burger} size="sm" />
<Burger
opened={opened}
onClick={toggle}
className={classes.burger}
size="sm"
aria-label="Toggle menu"
/>
<Drawer
opened={opened}
onClose={close}
Expand Down
114 changes: 58 additions & 56 deletions components/unitStats/unitTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import {
createStyles,
Table,
Expand Down Expand Up @@ -29,12 +29,13 @@ import {
IconSearch,
IconSelector,
} from "@tabler/icons-react";
import { EbpsType, SbpsType, WeaponType, getFactionIcon } from "../../src/unitStats";
import { CustomizableUnit, mapCustomizableUnit } from "../../src/unitStats/dpsCommon";
import { getFactionIcon } from "../../src/unitStats";
import { CustomizableUnit } from "../../src/unitStats/dpsCommon";
import { internalSlash } from "../../src/utils";
import Link from "next/link";
import { getExplorerUnitRoute } from "../../src/routes";
import { raceType } from "../../src/coh3/coh3-types";
import { useDebouncedValue } from "@mantine/hooks";

interface tableColSetup {
key: string;
Expand Down Expand Up @@ -76,7 +77,7 @@ const tableSetup: tableColSetup[] = [
{
key: "screen_name",
sortKey: "screen_name",
title: "Descr.",
title: "Description",
visible: true,
isIcon: false,
customVisual: false,
Expand Down Expand Up @@ -266,7 +267,11 @@ const getCellVisual = (colSetup: tableColSetup, unit: CustomizableUnit) => {
</Tooltip>
);
}
return <Text>{(unit as any)[colSetup.key]}</Text>;

let content = (unit as any)[colSetup.key];
content = content ? content : "-";

return <Text>{content}</Text>;
}

switch (colSetup.key) {
Expand Down Expand Up @@ -299,12 +304,10 @@ const useStyles = createStyles((theme) => ({
},
}));

const tableData: CustomizableUnit[] = [];
let tableData: CustomizableUnit[] = [];

interface inputProps {
sbpsData: SbpsType[];
ebpsData: EbpsType[];
weaponData: WeaponType[];
inputData: CustomizableUnit[];
}

interface ThProps {
Expand Down Expand Up @@ -421,6 +424,7 @@ const getTableHeader = (
sorted={sortBy === colSetup.sortKey}
reversed={reverseSortDirection}
onSort={() => setSorting(colSetup.sortKey)}
key={colSetup.key}
>
{colSetup.title}
</Th>,
Expand All @@ -440,7 +444,8 @@ const getTableCustomizing = (onTableLayoutChange: any) => {
onChange={() => onTableLayoutChange(setup)}
title={setup.title}
label={setup.title}
></Checkbox>,
key={setup.key}
/>,

// <SimpleGrid cols={2}>
// <div> {setup.title}</div>
Expand Down Expand Up @@ -518,30 +523,32 @@ const getTypeIcon = (type: string) => {
return internalSlash(icon);
};

export const UnitTable = ({ sbpsData, ebpsData, weaponData }: inputProps) => {
export const UnitTable = ({ inputData }: inputProps) => {
tableData = inputData;

const [search, setSearch] = useState("");
const [factionFilter, setFactionFilter] = useState([] as string[]);
const [typeFilter, setTypeFilter] = useState([] as string[]);

if (tableData.length == 0)
for (const sbps of sbpsData) {
const unit = mapCustomizableUnit(sbps, ebpsData, weaponData);
if (
sbps.ui.screenName != "No text found." &&
sbps.ui.symbolIconName != "" &&
sbps.faction != "british" &&
unit.cost_mp > 0
) {
tableData.push(unit);
}
}

// const [tableSetupData] = useState(tableSetup);
const [updateFlag, updateTable] = useState(true);
const [sortedData, setSortedData] = useState(tableData);
const [sortBy, setSortBy] = useState<keyof CustomizableUnit | null>(null);
const [reverseSortDirection, setReverseSortDirection] = useState(false);

const [debouncedSearch] = useDebouncedValue(search, 600);

useEffect(() => {
setSortedData(
sortData(tableData, {
sortBy,
reversed: reverseSortDirection,
search: debouncedSearch,
factionFilter,
typeFilter,
}),
);
}, [debouncedSearch]);

function toggleFilter(filterValue: string, filterList: string[]) {
const filterValueIndex = filterList.indexOf(filterValue);
if (filterValueIndex < 0) filterList.push(filterValue);
Expand Down Expand Up @@ -569,20 +576,6 @@ export const UnitTable = ({ sbpsData, ebpsData, weaponData }: inputProps) => {
);
};

const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { value } = event.currentTarget;
setSearch(value);
setSortedData(
sortData(tableData, {
sortBy,
reversed: reverseSortDirection,
search: value,
factionFilter,
typeFilter,
}),
);
};

const onTableLayoutChange = (colSetup: tableColSetup) => {
colSetup.visible = !colSetup.visible;
refresh();
Expand Down Expand Up @@ -653,30 +646,39 @@ export const UnitTable = ({ sbpsData, ebpsData, weaponData }: inputProps) => {
mb="md"
icon={<IconSearch size="0.9rem" stroke={1.5} />}
value={search}
onChange={handleSearchChange}
onChange={(event: { currentTarget: { value: any } }) => {
setSearch(event.currentTarget.value);
}}
/>
</Group>
</div>
<Table horizontalSpacing="md" verticalSpacing="xs" miw={700} sx={{ tableLayout: "fixed" }}>
<thead>
<tr>
<>{cols}</>
</tr>
</thead>
<tbody>
{rows.length > 0 ? (
rows
) : (
<tr key="no_row">
{/* <td colSpan={Object.keys(data[0]).length}>
<div style={{ minHeight: 7000 }}>
<Table
horizontalSpacing="md"
verticalSpacing="xs"
miw={700}
sx={{ tableLayout: "fixed" }}
>
<thead>
<tr>
<>{cols}</>
</tr>
</thead>
<tbody>
{rows.length > 0 ? (
rows
) : (
<tr key="no_row">
{/* <td colSpan={Object.keys(data[0]).length}>
<Text weight={500} align="center">
Nothing found
</Text>
</td> */}
</tr>
)}
</tbody>
</Table>
</tr>
)}
</tbody>
</Table>
</div>
</ScrollArea>
);
};
Loading

0 comments on commit ec24e21

Please sign in to comment.