mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
Merge pull request #563 from storytold/feature/create-beta-key
create beta key page
This commit is contained in:
5 files changed
+186
-1
No files matched your search
@@ -0,0 +1,22 @@
|
||||
import MakeRequest from "../MakeRequest";
|
||||
|
||||
export interface CreateBetaKeyRequest {
|
||||
maybe_referrer_username: string;
|
||||
number_of_keys: number;
|
||||
uuid_idempotency_token: string;
|
||||
}
|
||||
|
||||
export interface CreateBetaKeyResponse {
|
||||
beta_keys: string[];
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export const CreateBetaKey = MakeRequest<
|
||||
string,
|
||||
CreateBetaKeyRequest,
|
||||
CreateBetaKeyResponse,
|
||||
{}
|
||||
>({
|
||||
method: "POST",
|
||||
routingFunction: () => "/v1/beta_keys/new",
|
||||
});
|
||||
@@ -116,7 +116,10 @@ export default function PageHeader({
|
||||
>
|
||||
<div>
|
||||
{titleH2 ? (
|
||||
<h2 className="fw-bold">{title}</h2>
|
||||
<h2 className="fw-bold d-flex align-items-center">
|
||||
{icon}
|
||||
{title}
|
||||
</h2>
|
||||
) : (
|
||||
<h1 className="fw-bold d-flex align-items-center">
|
||||
{icon}
|
||||
|
||||
@@ -244,6 +244,10 @@ styles with important tags:
|
||||
padding-left: var(--bs-gutter-x, 1rem);
|
||||
}
|
||||
|
||||
.narrow-container {
|
||||
max-width: 900px !important;
|
||||
}
|
||||
|
||||
.py-6 {
|
||||
padding-top: 1.6rem !important;
|
||||
padding-bottom: 0.4rem !important;
|
||||
|
||||
@@ -135,6 +135,7 @@ import DashboardPage from "./pages/dashboard/DashboardPage";
|
||||
import DevUploadAlt from "./pages/dev_upload/DevUploadAlt";
|
||||
import { ModerationTokenInfoPage } from "./pages/moderation/ModerationTokenInfoPage";
|
||||
import StyleVideo from "./pages/style-video";
|
||||
import CreateBetaKeyPage from "./pages/beta_key/CreateBetaKeyPage";
|
||||
|
||||
interface Props {
|
||||
sessionWrapper: SessionWrapper;
|
||||
@@ -1124,6 +1125,10 @@ class PageContainer extends React.Component<
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/beta-key/create">
|
||||
<CreateBetaKeyPage />
|
||||
</Route>
|
||||
|
||||
{/*
|
||||
// <Route path="/engine-compositor">
|
||||
// <EngineCompositor
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
import { Button, Container, Panel, TempInput } from "components/common";
|
||||
import PageHeader from "components/layout/PageHeader";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { CreateBetaKey } from "@storyteller/components/src/api/beta_key/CreateBetaKey";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { faBan, faKey } from "@fortawesome/pro-solid-svg-icons";
|
||||
import {
|
||||
GetUserByUsername,
|
||||
GetUserByUsernameIsErr,
|
||||
GetUserByUsernameIsOk,
|
||||
UserLookupError,
|
||||
} from "@storyteller/components/src/api/user/GetUserByUsername";
|
||||
import { useSession } from "hooks";
|
||||
|
||||
export default function CreateBetaKeyPage() {
|
||||
const [username, setUsername] = useState("");
|
||||
const [numberOfKeys, setNumberOfKeys] = useState(1);
|
||||
const [alertMessage, setAlertMessage] = useState<string | null>(null);
|
||||
const [alertType, setAlertType] = useState<"success" | "danger" | null>(null);
|
||||
const [generatedKeys, setGeneratedKeys] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { canBanUsers } = useSession();
|
||||
|
||||
const getUser = useCallback(async (username: string) => {
|
||||
const response = await GetUserByUsername(username);
|
||||
if (GetUserByUsernameIsOk(response)) {
|
||||
return true;
|
||||
} else if (GetUserByUsernameIsErr(response)) {
|
||||
switch (response) {
|
||||
case UserLookupError.NotFound:
|
||||
setAlertMessage("Failed to create beta key(s). Username not found.");
|
||||
setAlertType("danger");
|
||||
setGeneratedKeys([]);
|
||||
break;
|
||||
default:
|
||||
setAlertMessage("Failed to create beta key(s). Username not found.");
|
||||
setAlertType("danger");
|
||||
setGeneratedKeys([]);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleCreateBetaKey = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const userExists = await getUser(username);
|
||||
if (!userExists) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await CreateBetaKey("", {
|
||||
maybe_referrer_username: username,
|
||||
number_of_keys: numberOfKeys,
|
||||
uuid_idempotency_token: uuidv4(),
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
setAlertMessage(
|
||||
`Successfully created ${response.beta_keys.length} beta key(s):`
|
||||
);
|
||||
setAlertType("success");
|
||||
setGeneratedKeys(response.beta_keys);
|
||||
} else {
|
||||
setAlertMessage("Failed to create beta key(s).");
|
||||
setAlertType("danger");
|
||||
setGeneratedKeys([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating beta keys:", error);
|
||||
setAlertMessage("An error occurred while creating beta key(s).");
|
||||
setAlertType("danger");
|
||||
setGeneratedKeys([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!canBanUsers()) {
|
||||
return (
|
||||
<Container type="panel" className="narrow-container">
|
||||
<PageHeader
|
||||
titleIcon={faBan}
|
||||
title="No Access"
|
||||
subText="Sorry, this page is for moderators and developers only."
|
||||
panel={true}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Container type="panel" className="narrow-container">
|
||||
<PageHeader
|
||||
titleIcon={faKey}
|
||||
title="Create Beta Key"
|
||||
subText="For moderators and developers only."
|
||||
/>
|
||||
<Panel padding={true}>
|
||||
<div className="d-flex flex-column gap-3">
|
||||
<TempInput
|
||||
label="Username"
|
||||
placeholder="Username of key owner"
|
||||
value={username}
|
||||
onChange={e => setUsername(e.target.value)}
|
||||
required={true}
|
||||
/>
|
||||
<TempInput
|
||||
label="Number of Keys"
|
||||
placeholder="Number of keys"
|
||||
type="number"
|
||||
value={numberOfKeys}
|
||||
onChange={e => setNumberOfKeys(Number(e.target.value))}
|
||||
defaultValue={1}
|
||||
required={true}
|
||||
/>
|
||||
<div className="mt-2 d-flex justify-content-end gap-2">
|
||||
<Button
|
||||
label="View Beta Keys"
|
||||
variant="secondary"
|
||||
disabled={true}
|
||||
/>
|
||||
<Button
|
||||
label="Create Beta Key(s)"
|
||||
onClick={handleCreateBetaKey}
|
||||
isLoading={loading}
|
||||
disabled={username.length === 0 || numberOfKeys <= 0}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
{alertMessage && (
|
||||
<div className={`alert alert-${alertType} mt-5 fw-semibold p-3`}>
|
||||
{alertMessage}
|
||||
{generatedKeys.length > 0 && (
|
||||
<div className="mt-2 fw-medium">
|
||||
<ul>
|
||||
{generatedKeys.map((key, index) => (
|
||||
<li key={index}>{key}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user