Add cell list to plugin detail page

Also add mod counts in parenthesis.
This commit is contained in:
Tyler Hallada 2022-03-14 21:55:52 -04:00
parent e7e392a7b7
commit a590dbd02c
6 changed files with 91 additions and 54 deletions

View File

@ -10,7 +10,7 @@ type Props = {
cells: CellCoord[]; cells: CellCoord[];
}; };
const ModCellList: React.FC<Props> = ({ cells }) => { const CellList: React.FC<Props> = ({ cells }) => {
return ( return (
cells && ( cells && (
<> <>
@ -44,4 +44,4 @@ const ModCellList: React.FC<Props> = ({ cells }) => {
); );
}; };
export default ModCellList; export default CellList;

View File

@ -34,7 +34,7 @@ const CellModList: React.FC<Props> = ({ mods, counts }) => {
return ( return (
mods && ( mods && (
<> <>
<h2>Mods</h2> <h2>Mods ({modsWithCounts.length})</h2>
<ul className={styles["mod-list"]}> <ul className={styles["mod-list"]}>
{modsWithCounts {modsWithCounts
.sort((a, b) => b.unique_downloads - a.unique_downloads) .sort((a, b) => b.unique_downloads - a.unique_downloads)

View File

@ -362,7 +362,12 @@ const Map: React.FC = () => {
]); ]);
useEffect(() => { useEffect(() => {
if (router.query.plugin && typeof router.query.plugin === "string" && fetchedPlugin && fetchedPlugin.cells) { if (
router.query.plugin &&
typeof router.query.plugin === "string" &&
fetchedPlugin &&
fetchedPlugin.cells
) {
const cells = []; const cells = [];
const cellSet = new Set<number>(); const cellSet = new Set<number>();
for (const cell of fetchedPlugin.cells) { for (const cell of fetchedPlugin.cells) {

View File

@ -3,7 +3,7 @@ import Head from "next/head";
import React from "react"; import React from "react";
import useSWRImmutable from "swr/immutable"; import useSWRImmutable from "swr/immutable";
import ModCellList from "./ModCellList"; import CellList from "./CellList";
import styles from "../styles/ModData.module.css"; import styles from "../styles/ModData.module.css";
export interface CellCoord { export interface CellCoord {
@ -160,7 +160,7 @@ const ModData: React.FC<Props> = ({
<strong>Unique Downloads:</strong>{" "} <strong>Unique Downloads:</strong>{" "}
{numberFmt.format(unique_downloads)} {numberFmt.format(unique_downloads)}
</div> </div>
<ModCellList cells={data.cells} /> <CellList cells={data.cells} />
</> </>
); );
} }

View File

@ -2,12 +2,20 @@ import React, { useEffect } from "react";
import useSWRImmutable from "swr/immutable"; import useSWRImmutable from "swr/immutable";
import { useAppDispatch, useAppSelector } from "../lib/hooks"; import { useAppDispatch, useAppSelector } from "../lib/hooks";
import { setFetchedPlugin, PluginFile, PluginsByHashWithMods, Cell } from "../slices/plugins"; import {
setFetchedPlugin,
PluginFile,
PluginsByHashWithMods,
} from "../slices/plugins";
import PluginModList from "./PluginModList"; import PluginModList from "./PluginModList";
import CellList from "./CellList";
import type { CellCoord } from "./ModData";
import PluginData, { Plugin as PluginProps } from "./PluginData"; import PluginData, { Plugin as PluginProps } from "./PluginData";
import styles from "../styles/PluginData.module.css"; import styles from "../styles/PluginData.module.css";
const jsonFetcher = async (url: string): Promise<PluginsByHashWithMods | null> => { const jsonFetcher = async (
url: string
): Promise<PluginsByHashWithMods | null> => {
const res = await fetch(url); const res = await fetch(url);
if (!res.ok) { if (!res.ok) {
@ -20,18 +28,34 @@ const jsonFetcher = async (url: string): Promise<PluginsByHashWithMods | null> =
return res.json(); return res.json();
}; };
const buildPluginProps = (data?: PluginsByHashWithMods | null, plugin?: PluginFile): PluginProps => { const buildPluginProps = (
data?: PluginsByHashWithMods | null,
plugin?: PluginFile
): PluginProps => {
const dataPlugin = data && data.plugins.length > 0 && data.plugins[0]; const dataPlugin = data && data.plugins.length > 0 && data.plugins[0];
return { return {
hash: (plugin && plugin.hash) || (dataPlugin && dataPlugin.hash.toString(36)) || "", hash:
(plugin && plugin.hash) ||
(dataPlugin && dataPlugin.hash.toString(36)) ||
"",
size: plugin?.size || (dataPlugin && dataPlugin.size) || 0, size: plugin?.size || (dataPlugin && dataPlugin.size) || 0,
author: plugin?.parsed?.header.author || (dataPlugin && dataPlugin.author) || undefined, author:
description: plugin?.parsed?.header.description || (dataPlugin && dataPlugin.description) || undefined, plugin?.parsed?.header.author ||
masters: plugin?.parsed?.header.masters || (dataPlugin && dataPlugin.masters) || [], (dataPlugin && dataPlugin.author) ||
undefined,
description:
plugin?.parsed?.header.description ||
(dataPlugin && dataPlugin.description) ||
undefined,
masters:
plugin?.parsed?.header.masters ||
(dataPlugin && dataPlugin.masters) ||
[],
file_name: plugin?.filename || (dataPlugin && dataPlugin.file_name) || "", file_name: plugin?.filename || (dataPlugin && dataPlugin.file_name) || "",
cell_count: plugin?.parsed?.cells.length || (data && data.cells.length) || 0, cell_count:
} plugin?.parsed?.cells.length || (data && data.cells.length) || 0,
} };
};
type Props = { type Props = {
hash: string; hash: string;
@ -53,7 +77,7 @@ const PluginDetail: React.FC<Props> = ({ hash, counts }) => {
if (data) { if (data) {
dispatch(setFetchedPlugin(data)); dispatch(setFetchedPlugin(data));
} }
}, [dispatch, data, fetchedPlugin]) }, [dispatch, data, fetchedPlugin]);
if (!plugin && error && error.status === 404) { if (!plugin && error && error.status === 404) {
return <h3>Plugin could not be found.</h3>; return <h3>Plugin could not be found.</h3>;
@ -67,11 +91,22 @@ const PluginDetail: React.FC<Props> = ({ hash, counts }) => {
return ( return (
<> <>
<PluginData <PluginData plugin={buildPluginProps(data, plugin)} counts={counts} />
plugin={buildPluginProps(data, plugin)} {data && (
counts={counts} <PluginModList mods={data.mods} files={data.files} counts={counts} />
)}
<CellList
cells={
(plugin?.parsed?.cells.filter(
(cell) =>
cell.x !== undefined &&
cell.y !== undefined &&
cell.world_form_id === 60
) as CellCoord[]) ||
data?.cells ||
[]
}
/> />
{data && <PluginModList mods={data.mods} files={data.files} counts={counts} />}
</> </>
); );
}; };

View File

@ -37,7 +37,7 @@ const PluginModList: React.FC<Props> = ({ mods, files, counts }) => {
return ( return (
mods && ( mods && (
<> <>
<h2>Mods</h2> <h2>Mods ({modsWithCounts.length})</h2>
<ul className={styles["mod-list"]}> <ul className={styles["mod-list"]}>
{modsWithCounts {modsWithCounts
.sort((a, b) => b.unique_downloads - a.unique_downloads) .sort((a, b) => b.unique_downloads - a.unique_downloads)
@ -96,42 +96,39 @@ const PluginModList: React.FC<Props> = ({ mods, files, counts }) => {
{numberFmt.format(mod.unique_downloads)} {numberFmt.format(mod.unique_downloads)}
</div> </div>
<ul className={styles["file-list"]}> <ul className={styles["file-list"]}>
{files.filter(file => file.mod_id === mod.id).map(file => ( {files
<li key={file.id}> .filter((file) => file.mod_id === mod.id)
<div> .map((file) => (
<strong>File:</strong>{" "} <li key={file.id}>
{file.name}
</div>
{file.mod_version && (
<div> <div>
<strong>Version:</strong>{" "} <strong>File:</strong> {file.name}
{file.mod_version}
</div> </div>
)} {file.mod_version && (
{file.version && file.mod_version !== file.version && ( <div>
<strong>Version:</strong> {file.mod_version}
</div>
)}
{file.version && file.mod_version !== file.version && (
<div>
<strong>File Version:</strong> {file.version}
</div>
)}
{file.category && (
<div>
<strong>Category:</strong> {file.category}
</div>
)}
<div> <div>
<strong>File Version:</strong>{" "} <strong>Size:</strong> {formatBytes(file.size)}
{file.version}
</div> </div>
)} {file.uploaded_at && (
{file.category && ( <div>
<div> <strong>Uploaded:</strong>{" "}
<strong>Category:</strong>{" "} {format(new Date(file.uploaded_at), "d MMM y")}
{file.category} </div>
</div> )}
)} </li>
<div> ))}
<strong>Size:</strong>{" "}
{formatBytes(file.size)}
</div>
{file.uploaded_at && (
<div>
<strong>Uploaded:</strong>{" "}
{format(new Date(file.uploaded_at), "d MMM y")}
</div>
)}
</li>
))}
</ul> </ul>
</li> </li>
))} ))}