Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 102 additions & 68 deletions apps/cyberstorm-remix/app/p/team/Team.tsx
Original file line number Diff line number Diff line change
@@ -1,131 +1,165 @@
import {
getPublicEnvVariables,
getSessionTools,
} from "cyberstorm/security/publicEnvVariables";
import { useLoaderData, useOutletContext } from "react-router";
import { Await, useLoaderData, useOutletContext } from "react-router";
import "./Team.css";
import { PackageSearch } from "~/commonComponents/PackageSearch/PackageSearch";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace ·Await,·useLoaderData,·useOutletContext·}·from·"react-router";⏎import·"./Team.css";⏎import·{·PackageSearch·}·from·"~/commonComponents/PackageSearch/PackageSearch with ⏎··NimbusAwaitErrorElement,⏎··NimbusDefaultRouteErrorBoundary,⏎}·from·"cyberstorm/utils/errors/NimbusErrorBoundary
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";

import { DapperTs } from "@thunderstore/dapper-ts";

import { PackageOrderOptions } from "../../commonComponents/PackageSearch/components/PackageOrder";
import { type OutletContextShape } from "../../root";
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";
import type { Route } from "./+types/Team";
import "./Team.css";
import { throwUserFacingPayloadResponse } from "cyberstorm/utils/errors/userFacingErrorResponse";
import { handleLoaderError } from "cyberstorm/utils/errors/handleLoaderError";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace handleLoaderError·}·from·"cyberstorm/utils/errors/handleLoaderError with getLoaderTools·}·from·"cyberstorm/utils/getLoaderTools
import { createNotFoundMapping } from "cyberstorm/utils/errors/loaderMappings";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace createNotFoundMapping·}·from·"cyberstorm/utils/errors/loaderMapping with parseIntegerSearchParam·}·from·"cyberstorm/utils/searchParamsUtil
import { SkeletonBox } from "@thunderstore/cyberstorm";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace keletonBox·}·from·"@thunderstore/cyberstorm with uspense·}·from·"react
import { Suspense } from "react";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace Suspense·}·from·"react with Await,·useLoaderData,·useOutletContext·}·from·"react-router
import {
NimbusAwaitErrorElement,
NimbusDefaultRouteErrorBoundary,
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
Comment on lines +13 to +16

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace ⏎··NimbusAwaitErrorElement,⏎··NimbusDefaultRouteErrorBoundary,⏎}·from·"cyberstorm/utils/errors/NimbusErrorBoundary"; with ·PackageSearch·}·from·"~/commonComponents/PackageSearch/PackageSearch";⏎import·{·PageHeader·}·from·"~/commonComponents/PageHeader/PageHeader";⏎⏎import·{·SkeletonBox·}·from·"@thunderstore/cyberstorm";⏎
import { getLoaderTools } from "cyberstorm/utils/getLoaderTools";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace getLoaderTools·}·from·"cyberstorm/utils/getLoaderTools with PackageOrderOptions·}·from·"../../commonComponents/PackageSearch/components/PackageOrder
import { parseIntegerSearchParam } from "cyberstorm/utils/searchParamsUtils";

Check failure

Code scanning / ESLint

Ensure code is properly formatted, use insertion, deletion, or replacement to obtain desired formatting. Error

Replace parseIntegerSearchParam·}·from·"cyberstorm/utils/searchParamsUtil with type·OutletContextShape·}·from·"../../root";⏎import·type·{·Route·}·from·"./+types/Team";⏎import·"./Team.cs

const teamNotFoundMappings = [
createNotFoundMapping(
"Team not found.",
"We could not find the requested team.",
404
),
];

export async function loader({ params, request }: Route.LoaderArgs) {
if (params.communityId && params.namespaceId) {
const publicEnvVariables = getPublicEnvVariables(["VITE_API_URL"]);
const dapper = new DapperTs(() => {
return {
apiHost: publicEnvVariables.VITE_API_URL,
sessionId: undefined,
};
});
const { dapper } = getLoaderTools();
const searchParams = new URL(request.url).searchParams;
const ordering =
searchParams.get("ordering") ?? PackageOrderOptions.Updated;
const page = searchParams.get("page");
const page = parseIntegerSearchParam(searchParams.get("page"));
const search = searchParams.get("search");
const includedCategories = searchParams.get("includedCategories");
const excludedCategories = searchParams.get("excludedCategories");
const section = searchParams.get("section");
const nsfw = searchParams.get("nsfw");
const deprecated = searchParams.get("deprecated");
const filters = await dapper.getCommunityFilters(params.communityId);

return {
teamId: params.namespaceId,
filters: filters,
listings: await dapper.getPackageListings(
try {
const filters = await dapper.getCommunityFilters(params.communityId);
const listings = await dapper.getPackageListings(
{
kind: "namespace",
communityId: params.communityId,
namespaceId: params.namespaceId,
},
ordering ?? "",
page === null ? undefined : Number(page),
page,
search ?? "",
includedCategories?.split(",") ?? undefined,
excludedCategories?.split(",") ?? undefined,
section ? (section === "all" ? "" : section) : "",
nsfw === "true" ? true : false,
deprecated === "true" ? true : false
),
};
nsfw === "true",
deprecated === "true"
);
const dataPromise = Promise.all([filters, listings]);

return {
teamId: params.namespaceId,
filtersAndListings: await dataPromise,
};
} catch (error) {
handleLoaderError(error, { mappings: teamNotFoundMappings });
}
}
throw new Response("Community not found", { status: 404 });
throwUserFacingPayloadResponse({
headline: "Community not found.",
description: "We could not find the requested community.",
category: "not_found",
status: 404,
});
}

export async function clientLoader({
request,
params,
}: Route.ClientLoaderArgs) {
if (params.communityId && params.namespaceId) {
const tools = getSessionTools();
const dapper = new DapperTs(() => {
return {
apiHost: tools?.getConfig().apiHost,
sessionId: tools?.getConfig().sessionId,
};
});
const { dapper } = getLoaderTools();
const searchParams = new URL(request.url).searchParams;
const ordering =
searchParams.get("ordering") ?? PackageOrderOptions.Updated;
const page = searchParams.get("page");
const page = parseIntegerSearchParam(searchParams.get("page"));
const search = searchParams.get("search");
const includedCategories = searchParams.get("includedCategories");
const excludedCategories = searchParams.get("excludedCategories");
const section = searchParams.get("section");
const nsfw = searchParams.get("nsfw");
const deprecated = searchParams.get("deprecated");
const filters = dapper.getCommunityFilters(params.communityId);
return {
teamId: params.namespaceId,
filters: filters,
listings: dapper.getPackageListings(
const filters = dapper
.getCommunityFilters(params.communityId)
.catch((error) =>
handleLoaderError(error, { mappings: teamNotFoundMappings })
);
const listings = dapper
.getPackageListings(
{
kind: "namespace",
communityId: params.communityId,
namespaceId: params.namespaceId,
},
ordering ?? "",
page === null ? undefined : Number(page),
page,
search ?? "",
includedCategories?.split(",") ?? undefined,
excludedCategories?.split(",") ?? undefined,
section ? (section === "all" ? "" : section) : "",
nsfw === "true" ? true : false,
deprecated === "true" ? true : false
),
};
nsfw === "true",
deprecated === "true"
)
.catch((error) =>
handleLoaderError(error, { mappings: teamNotFoundMappings })
);
const dataPromise = Promise.all([filters, listings]);

return { teamId: params.namespaceId, filtersAndListings: dataPromise };
}
throw new Response("Community not found", { status: 404 });
throwUserFacingPayloadResponse({
headline: "Community not found.",
description: "We could not find the requested community.",
category: "not_found",
status: 404,
});
}

/**
* Displays the team package listing and delegates streaming data to PackageSearch.
*/
export default function Team() {
const { filters, listings, teamId } = useLoaderData<
typeof loader | typeof clientLoader
>();
const data = useLoaderData<typeof loader | typeof clientLoader>();

const outletContext = useOutletContext() as OutletContextShape;

return (
<>
<section className="team">
<PageHeader headingLevel="1" headingSize="3">
Mods uploaded by {teamId}
</PageHeader>
<>
<PackageSearch
listings={listings}
filters={filters}
config={outletContext.requestConfig}
currentUser={outletContext.currentUser}
dapper={outletContext.dapper}
/>
</>
</section>
</>
<section className="team">
<PageHeader headingLevel="1" headingSize="3">
Mods uploaded by {data.teamId}
</PageHeader>
<Suspense fallback={<SkeletonBox />}>
<Await
resolve={data.filtersAndListings}
errorElement={<NimbusAwaitErrorElement />}
>
{([filters, listings]) => {
return (
<PackageSearch
listings={listings}
filters={filters}
config={outletContext.requestConfig}
currentUser={outletContext.currentUser}
dapper={outletContext.dapper}
/>
);
}}
</Await>
</Suspense>
</section>
);
}

export function ErrorBoundary() {
return <NimbusDefaultRouteErrorBoundary />;
}
37 changes: 33 additions & 4 deletions apps/cyberstorm-remix/app/settings/teams/Teams.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import {
NimbusErrorBoundary,
NimbusErrorBoundaryFallback,
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";
import { useReducer, useState } from "react";
import type { MetaFunction } from "react-router";
import { useOutletContext, useRevalidator } from "react-router";
Expand All @@ -21,6 +26,7 @@ import {
type RequestConfig,
type TeamCreateRequestData,
UserFacingError,
formatUserFacingError,
teamCreate,
} from "@thunderstore/thunderstore-api";
import {
Expand Down Expand Up @@ -66,7 +72,10 @@ export default function Teams() {
const currentUser = outletContext.currentUser;

return (
<>
<NimbusErrorBoundary
fallback={TeamsSettingsFallback}
onRetry={({ reset }) => reset()}
>
<PageHeader headingLevel="1" headingSize="2">
Teams
</PageHeader>
Expand All @@ -81,7 +90,6 @@ export default function Teams() {
{currentUser?.teams_full?.length ? (
<NewTable
titleRowContent={<Heading csLevel="3">Teams</Heading>}
// csModifiers={["alignLastColumnRight"]}
headers={[
{ value: "Team Name", disableSort: false },
{ value: "Role", disableSort: false },
Expand Down Expand Up @@ -125,7 +133,28 @@ export default function Teams() {
</div>
</div>
</section>
</>
</NimbusErrorBoundary>
);
}

/**
* Presents fallback messaging when the teams settings view crashes.
*/
function TeamsSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
const {
title = "Teams failed to load",
description = "Reload the teams tab or return to settings.",
retryLabel = "Reload",
...rest
} = props;

return (
<NimbusErrorBoundaryFallback
{...rest}
title={title}
description={description}
retryLabel={retryLabel}
/>
);
}

Expand Down Expand Up @@ -179,7 +208,7 @@ function CreateTeamForm(props: { config: () => RequestConfig }) {
onSubmitError: (error) => {
toast.addToast({
csVariant: "danger",
children: `Error occurred: ${error.message || "Unknown error"}`,
children: formatUserFacingError(error),
duration: 8000,
});
},
Expand Down
Loading
Loading