Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import "./Members.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlus, faTrashCan } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useReducer, useState } from "react";
import { useLoaderData, useOutletContext, useRevalidator } from "react-router";

import {
Modal,
NewAvatar,
Expand All @@ -13,50 +15,26 @@ import {
type SelectOption,
useToast,
} from "@thunderstore/cyberstorm";
import { type LoaderFunctionArgs } from "react-router";
import { useLoaderData, useOutletContext, useRevalidator } from "react-router";
import { TableSort } from "@thunderstore/cyberstorm/src/newComponents/Table/Table";
import {
ApiError,
type RequestConfig,
teamAddMember,
type TeamAddMemberRequestData,
teamEditMember,
teamRemoveMember,
} from "@thunderstore/thunderstore-api";
import { type OutletContextShape } from "../../../../../root";
import { TableSort } from "@thunderstore/cyberstorm/src/newComponents/Table/Table";
import { ApiAction } from "@thunderstore/ts-api-react-actions";
import { DapperTs } from "@thunderstore/dapper-ts";
import { getSessionTools } from "cyberstorm/security/publicEnvVariables";

import { type OutletContextShape } from "app/root";
import { makeTeamSettingsTabLoader } from "cyberstorm/utils/dapperClientLoaders";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import { useReducer, useState } from "react";
import "./Members.css";

// REMIX TODO: Add check for "user has permission to see this page"
export async function clientLoader({ params }: LoaderFunctionArgs) {
if (params.namespaceId) {
try {
const tools = getSessionTools();
const config = tools?.getConfig();
const dapper = new DapperTs(() => {
return {
apiHost: config.apiHost,
sessionId: config.sessionId,
};
});
return {
teamName: params.namespaceId,
members: await dapper.getTeamMembers(params.namespaceId),
};
} catch (error) {
if (error instanceof ApiError) {
throw new Response("Team members not found", { status: 404 });
} else {
throw error;
}
}
}
throw new Response("Team not found", { status: 404 });
}
export const clientLoader = makeTeamSettingsTabLoader(
async (dapper, teamName) => ({
members: await dapper.getTeamMembers(teamName),
})
);

export function HydrateFallback() {
return <div style={{ padding: "32px" }}>Loading...</div>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,25 @@
import { type LoaderFunctionArgs } from "react-router";
import { useReducer } from "react";
import { useLoaderData, useOutletContext, useRevalidator } from "react-router";

import { NewButton, NewTextInput, useToast } from "@thunderstore/cyberstorm";
import {
ApiError,
teamDetailsEdit,
type TeamDetailsEditRequestData,
} from "@thunderstore/thunderstore-api";
import { type OutletContextShape } from "~/root";
import "./Profile.css";
import { DapperTs } from "@thunderstore/dapper-ts";
import { getSessionTools } from "cyberstorm/security/publicEnvVariables";

import { type OutletContextShape } from "app/root";
import { makeTeamSettingsTabLoader } from "cyberstorm/utils/dapperClientLoaders";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import { useReducer } from "react";
import { NewButton, NewTextInput, useToast } from "@thunderstore/cyberstorm";
import "./Profile.css";

export async function clientLoader({ params }: LoaderFunctionArgs) {
if (params.namespaceId) {
try {
const tools = getSessionTools();
const dapper = new DapperTs(() => {
return {
apiHost: tools?.getConfig().apiHost,
sessionId: tools?.getConfig().sessionId,
};
});
return {
team: await dapper.getTeamDetails(params.namespaceId),
};
} catch (error) {
if (error instanceof ApiError) {
throw new Response("Team not found", { status: 404 });
} else {
// REMIX TODO: Add sentry
throw error;
}
}
}
throw new Response("Team not found", { status: 404 });
}
export const clientLoader = makeTeamSettingsTabLoader(
async (dapper, teamName) => ({
// TODO: for hygienie we shouldn't use this public endpoint but
// have an endpoint that confirms user permissions and returns
// possibly sensitive information.
team: await dapper.getTeamDetails(teamName),
})
);

export function HydrateFallback() {
return <div style={{ padding: "32px" }}>Loading...</div>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import "./ServiceAccounts.css";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useReducer, useState } from "react";
import { useLoaderData, useOutletContext, useRevalidator } from "react-router";

import {
NewAlert,
NewButton,
Expand All @@ -9,52 +13,24 @@ import {
Heading,
CodeBox,
} from "@thunderstore/cyberstorm";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlus } from "@fortawesome/free-solid-svg-icons";
import { type LoaderFunctionArgs } from "react-router";
import { useLoaderData, useOutletContext, useRevalidator } from "react-router";
import { TableSort } from "@thunderstore/cyberstorm/src/newComponents/Table/Table";
import {
ApiError,
type RequestConfig,
teamAddServiceAccount,
type TeamServiceAccountAddRequestData,
} from "@thunderstore/thunderstore-api";
import { TableSort } from "@thunderstore/cyberstorm/src/newComponents/Table/Table";
import { type OutletContextShape } from "../../../../../root";
import { useReducer, useState } from "react";
import { DapperTs } from "@thunderstore/dapper-ts";
import { getSessionTools } from "cyberstorm/security/publicEnvVariables";

import { type OutletContextShape } from "app/root";
import { makeTeamSettingsTabLoader } from "cyberstorm/utils/dapperClientLoaders";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import { ServiceAccountRemoveModal } from "./ServiceAccountRemoveModal";
import "./ServiceAccounts.css";

// REMIX TODO: Add check for "user has permission to see this page"
export async function clientLoader({ params }: LoaderFunctionArgs) {
if (params.namespaceId) {
try {
const tools = getSessionTools();
const config = tools?.getConfig();
const dapper = new DapperTs(() => {
return {
apiHost: config?.apiHost,
sessionId: config?.sessionId,
};
});
return {
teamName: params.namespaceId,
serviceAccounts: await dapper.getTeamServiceAccounts(
params.namespaceId
),
};
} catch (error) {
if (error instanceof ApiError) {
throw new Response("Team not found", { status: 404 });
} else {
throw error;
}
}
}
throw new Response("Team not found", { status: 404 });
}
export const clientLoader = makeTeamSettingsTabLoader(
async (dapper, teamName) => ({
serviceAccounts: await dapper.getTeamServiceAccounts(teamName),
})
);

export function HydrateFallback() {
return <div style={{ padding: "32px" }}>Loading...</div>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { faTrashCan } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useReducer, useState } from "react";
import { useLoaderData, useNavigate, useOutletContext } from "react-router";

import "./Settings.css";
import {
NewAlert,
Expand All @@ -8,36 +13,31 @@
NewTextInput,
useToast,
} from "@thunderstore/cyberstorm";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faTrashCan } from "@fortawesome/free-solid-svg-icons";
import { useNavigate, useOutletContext, useParams } from "react-router";

import { type OutletContextShape } from "~/root";
import {
type RequestConfig,
teamDisband,
type TeamDisbandRequestData,
teamRemoveMember,
} from "@thunderstore/thunderstore-api";
import { ApiAction } from "@thunderstore/ts-api-react-actions";
import { NotLoggedIn } from "~/commonComponents/NotLoggedIn/NotLoggedIn";

import { NotLoggedIn } from "app/commonComponents/NotLoggedIn/NotLoggedIn";
import { type OutletContextShape } from "app/root";
import { makeTeamSettingsTabLoader } from "cyberstorm/utils/dapperClientLoaders";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import { useReducer, useState } from "react";

// REMIX TODO: Make sure user is redirected of this page, if the user is not logged in
export const clientLoader = makeTeamSettingsTabLoader(
// TODO: add end point for checking can leave/disband status.
async (dapper, teamName) => ({})

Check failure

Code scanning / ESLint

Disallow unused variables Error

'dapper' is defined but never used.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two comments are valid but they will be addressed in an upcoming PR so ICBA to fix them here.

Check failure

Code scanning / ESLint

Disallow unused variables Error

'teamName' is defined but never used.
);

export default function Settings() {
const params = useParams();
const { teamName } = useLoaderData<typeof clientLoader>();
const outletContext = useOutletContext() as OutletContextShape;

if (
!outletContext.currentUser ||
!outletContext.currentUser.username ||
!params.namespaceId
)
if (!outletContext.currentUser || !outletContext.currentUser.username)
return <NotLoggedIn />;

if (!params.namespaceId) return <p>Team not found</p>;

const toast = useToast();

const navigate = useNavigate();
Expand Down Expand Up @@ -69,7 +69,7 @@
</p>
<LeaveTeamForm
userName={outletContext.currentUser.username}
teamName={params.namespaceId}
teamName={teamName}
toast={toast}
config={outletContext.requestConfig}
updateTrigger={moveToTeams}
Expand All @@ -88,14 +88,14 @@
<NewAlert csVariant="danger">
You cannot currently disband this team as it has packages.
</NewAlert>
<p>You are about to disband the team {params.namespaceId}.</p>
<p>You are about to disband the team {teamName}.</p>
<p>
Be aware you can currently only disband teams with no packages. If
you need to archive a team with existing pages, contact Mythic#0001
on the Thunderstore Discord.
</p>
<DisbandTeamForm
teamName={params.namespaceId}
teamName={teamName}
updateTrigger={moveToTeams}
config={outletContext.requestConfig}
toast={toast}
Expand Down
38 changes: 38 additions & 0 deletions apps/cyberstorm-remix/cyberstorm/utils/dapperClientLoaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { type LoaderFunctionArgs } from "react-router";

import { DapperTs } from "@thunderstore/dapper-ts";
import { ApiError, type GenericApiError } from "@thunderstore/thunderstore-api";

import { getSessionTools } from "cyberstorm/security/publicEnvVariables";

export function makeTeamSettingsTabLoader<T>(
dataFetcher: (dapper: DapperTs, teamName: string) => Promise<T>
) {
return async function clientLoader({ params }: LoaderFunctionArgs) {
const teamName = params.namespaceId!;

try {
const dapper = setupDapper();
const data = await dataFetcher(dapper, teamName);
return { teamName, ...data };
} catch (error) {
if (error instanceof ApiError) {
const status = error.response.status;
const statusText =
(error.responseJson as GenericApiError)?.detail ??
error.response.statusText;
throw new Response(statusText, { status, statusText });
}
throw error;
}
};
}

const setupDapper = () => {
const tools = getSessionTools();
const config = tools?.getConfig();
return new DapperTs(() => ({
apiHost: config?.apiHost,
sessionId: config?.sessionId,
}));
};
Loading