Skip to content

Commit 299df54

Browse files
committed
Add UploadPackageForm
1 parent c5b5ed4 commit 299df54

File tree

9 files changed

+242
-71
lines changed

9 files changed

+242
-71
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.root {
2+
display: flex;
3+
flex-direction: column;
4+
gap: var(--gap--48);
5+
}
6+
7+
.line {
8+
border-bottom: var(--border-width--px) solid var(--color-surface--4);
9+
}
10+
11+
.submit {
12+
display: flex;
13+
flex-direction: row;
14+
gap: var(--gap--16);
15+
}
+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"use client";
2+
3+
import styles from "./UploadPackageForm.module.css";
4+
import {
5+
ApiForm,
6+
uploadPackageFormSchema,
7+
} from "@thunderstore/ts-api-react-forms";
8+
import {
9+
FormSubmitButton,
10+
FormMultiSelectSearch,
11+
FormSelectSearch,
12+
useFormToaster,
13+
CreateTeamForm,
14+
FormSwitch,
15+
} from "@thunderstore/cyberstorm-forms";
16+
import { TextInput, Dialog, Button } from "@thunderstore/cyberstorm";
17+
import { SettingItem } from "@thunderstore/cyberstorm/src/components/SettingItem/SettingItem";
18+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
19+
import { faPlus } from "@fortawesome/free-solid-svg-icons";
20+
import { packageUpload } from "@thunderstore/thunderstore-api";
21+
22+
const options = [
23+
{ label: "Asd", value: "asd" },
24+
{ label: "Asd2", value: "asd2" },
25+
{ label: "Asd3", value: "asd3" },
26+
{ label: "Asd4", value: "asd4" },
27+
{ label: "Asd5", value: "asd5" },
28+
{ label: "Asd6", value: "asd6" },
29+
{ label: "Asd7", value: "asd7" },
30+
{ label: "Asd8", value: "asd8" },
31+
{ label: "Asd9", value: "asd9" },
32+
{ label: "Asd10", value: "asd10" },
33+
{ label: "Asd11", value: "asd11" },
34+
{ label: "Asd12", value: "asd12" },
35+
{ label: "Asd13", value: "asd13" },
36+
{ label: "Asd14", value: "asd14" },
37+
];
38+
39+
interface UploadPackageFormProps {
40+
teams: {
41+
name: string;
42+
}[];
43+
}
44+
45+
export function UploadPackageForm(props: UploadPackageFormProps) {
46+
const toaster = useFormToaster({
47+
successMessage: "Package submitted",
48+
});
49+
50+
// Parse categories to the right format for form
51+
function communityCategoriesParse(
52+
selected: {
53+
label: string;
54+
value: string;
55+
}[],
56+
onChange: (selected: { [key: string]: string[] }) => void
57+
) {
58+
const communityCategories: { [key: string]: string[] } = {};
59+
selected.map((x) => (communityCategories[x.value] = [x.value]));
60+
onChange(communityCategories);
61+
}
62+
63+
// Parse communities to the right format for form
64+
function communitiesParse(
65+
selected: {
66+
label: string;
67+
value: string;
68+
}[],
69+
onChange: (selected: string[]) => void
70+
) {
71+
onChange(selected.map((x) => x.value));
72+
}
73+
74+
return (
75+
<ApiForm
76+
{...toaster}
77+
schema={uploadPackageFormSchema}
78+
endpoint={packageUpload}
79+
formProps={{ className: styles.root }}
80+
>
81+
<div className={styles.root}>
82+
<SettingItem
83+
title="Upload file"
84+
description="Upload your package as a ZIP file."
85+
content={<TextInput />}
86+
/>
87+
<div className={styles.line} />
88+
<SettingItem
89+
title="Team"
90+
description="No teams available?"
91+
additionalLeftColumnContent={
92+
<Dialog.Root
93+
title="Create Team"
94+
trigger={
95+
<Button.Root colorScheme="primary" paddingSize="large">
96+
<Button.ButtonLabel>Create team</Button.ButtonLabel>
97+
<Button.ButtonIcon>
98+
<FontAwesomeIcon icon={faPlus} />
99+
</Button.ButtonIcon>
100+
</Button.Root>
101+
}
102+
>
103+
<CreateTeamForm />
104+
</Dialog.Root>
105+
}
106+
content={
107+
<FormSelectSearch
108+
name="team"
109+
schema={uploadPackageFormSchema}
110+
options={props.teams.map((t) => t.name)}
111+
placeholder="Choose a team..."
112+
/>
113+
}
114+
/>
115+
<SettingItem
116+
title="Communities"
117+
description="Select communities you want your package to be listed under. Current community is selected by default."
118+
content={
119+
<FormMultiSelectSearch
120+
name="communities"
121+
schema={uploadPackageFormSchema}
122+
options={options}
123+
placeholder="Choose community..."
124+
onChangeParse={communitiesParse}
125+
/>
126+
}
127+
/>
128+
<SettingItem
129+
title="Categories"
130+
description="Select descriptive categories to help people discover your package."
131+
content={
132+
<FormMultiSelectSearch
133+
name="community_categories"
134+
schema={uploadPackageFormSchema}
135+
options={options}
136+
placeholder="Choose categories..."
137+
onChangeParse={communityCategoriesParse}
138+
/>
139+
}
140+
/>
141+
<div className={styles.line} />
142+
<SettingItem
143+
title="Contains NSFW content"
144+
description='A "NSFW" -tag will be applied to your package.'
145+
content={
146+
<FormSwitch
147+
schema={uploadPackageFormSchema}
148+
name="has_nsfw_content"
149+
/>
150+
}
151+
/>
152+
<div className={styles.line} />
153+
<SettingItem
154+
title="Submit"
155+
description='Double-check your selections and hit "Submit" when you are ready!'
156+
content={
157+
<div className={styles.submit}>
158+
<Button.Root colorScheme="danger">
159+
<Button.ButtonLabel>Reset</Button.ButtonLabel>
160+
</Button.Root>
161+
<FormSubmitButton text="Submit" />
162+
</div>
163+
}
164+
/>
165+
</div>
166+
</ApiForm>
167+
);
168+
}
169+
170+
UploadPackageForm.displayName = "UploadPackageForm";

Diff for: packages/cyberstorm-forms/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export { FormMultiSelectSearch } from "./components/FormMultiSelectSearch";
55
export { FormSwitch } from "./components/FormSwitch";
66
export { FormTextInput } from "./components/FormTextInput";
77
export { CreateTeamForm } from "./forms/CreateTeamForm";
8+
export { UploadPackageForm } from "./forms/UploadPackageForm";

Diff for: packages/cyberstorm/src/components/Layout/Developers/PackageUpload/PackageUploadLayout.module.css

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
.root {
2+
display: flex;
3+
flex-direction: column;
4+
gap: var(--gap--48);
5+
}
6+
17
.line {
2-
margin: var(--space--24) 0;
38
border-bottom: var(--border-width--px) solid var(--color-surface--4);
49
}
510

Diff for: packages/cyberstorm/src/components/Layout/Developers/PackageUpload/PackageUploadLayout.tsx

+10-69
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
"use client";
2-
import styles from "./PackageUploadLayout.module.css";
32
import { Title } from "../../../Title/Title";
43
import { BreadCrumbs } from "../../../BreadCrumbs/BreadCrumbs";
54
import { PackageUploadLink } from "../../../Links/Links";
6-
import { SettingItem } from "../../../SettingItem/SettingItem";
7-
import { TextInput } from "../../../TextInput/TextInput";
8-
import * as Button from "../../../Button/";
9-
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
10-
import { faPlus } from "@fortawesome/free-solid-svg-icons";
115
import { BaseLayout } from "../../BaseLayout/BaseLayout";
12-
import { CreateTeamForm } from "@thunderstore/cyberstorm-forms";
13-
import { Dialog } from "../../../..";
6+
import { UploadPackageForm } from "@thunderstore/cyberstorm-forms";
7+
import { useDapper } from "@thunderstore/dapper";
8+
import { usePromise } from "@thunderstore/use-promise";
149

1510
/**
1611
* Cyberstorm PackageUpload Layout
1712
*/
13+
1814
export function PackageUploadLayout() {
15+
const dapper = useDapper();
16+
const user = usePromise(dapper.getCurrentUser, []);
17+
// TODO: Somehow grab categories from all the selected communities and pass them on
18+
// const communities = usePromise(dapper.getCommunities, []);
19+
// const filters = usePromise(dapper.getCommunityFilters, [communityId])
1920
return (
2021
<BaseLayout
2122
breadCrumb={
@@ -24,67 +25,7 @@ export function PackageUploadLayout() {
2425
</BreadCrumbs>
2526
}
2627
header={<Title text="Upload Package" />}
27-
mainContent={
28-
<>
29-
<SettingItem
30-
title="Upload file"
31-
description="Upload your package as a ZIP file."
32-
content={<TextInput />}
33-
/>
34-
<div className={styles.line} />
35-
<SettingItem
36-
title="Team"
37-
description="No teams available?"
38-
additionalLeftColumnContent={
39-
<Dialog.Root
40-
title="Create Team"
41-
trigger={
42-
<Button.Root colorScheme="primary" paddingSize="large">
43-
<Button.ButtonLabel>Create team</Button.ButtonLabel>
44-
<Button.ButtonIcon>
45-
<FontAwesomeIcon icon={faPlus} />
46-
</Button.ButtonIcon>
47-
</Button.Root>
48-
}
49-
>
50-
<CreateTeamForm />
51-
</Dialog.Root>
52-
}
53-
content={<TextInput />}
54-
/>
55-
<SettingItem
56-
title="Communities"
57-
description="Select communities you want your package to be listed under. Current community is selected by default."
58-
content={<TextInput />}
59-
/>
60-
<SettingItem
61-
title="Categories"
62-
description="Select descriptive categories to help people discover your package."
63-
content={<TextInput />}
64-
/>
65-
<div className={styles.line} />
66-
<SettingItem
67-
title="Contains NSFW content"
68-
description='A "NSFW" -tag will be applied to your package.'
69-
content=""
70-
/>
71-
<div className={styles.line} />
72-
<SettingItem
73-
title="Submit"
74-
description='Double-check your selections and hit "Submit" when you are ready!'
75-
content={
76-
<div className={styles.submit}>
77-
<Button.Root colorScheme="danger">
78-
<Button.ButtonLabel>Reset</Button.ButtonLabel>
79-
</Button.Root>
80-
<Button.Root colorScheme="accent">
81-
<Button.ButtonLabel>Submit</Button.ButtonLabel>
82-
</Button.Root>
83-
</div>
84-
}
85-
/>
86-
</>
87-
}
28+
mainContent={<UploadPackageForm teams={user.teams} />}
8829
/>
8930
);
9031
}

Diff for: packages/thunderstore-api/src/fetch/packageUpload.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { RequestConfig } from "../index";
2+
import { apiFetch2 } from "../apiFetch";
3+
4+
export type PackageUploadApiArgs = {
5+
// author_name: string;
6+
// upload_uuid: string;
7+
team: string;
8+
community_categories: { [key: string]: string[] };
9+
communities: string[];
10+
has_nsfw_content: boolean;
11+
};
12+
13+
export function packageUpload(
14+
config: RequestConfig,
15+
data: PackageUploadApiArgs
16+
) {
17+
const path = "api/experimental/submission/submit/";
18+
19+
// TODO: Add these datas in form
20+
const todoData = { ...data, upload_uuid: "123", author_name: "root" };
21+
22+
return apiFetch2({
23+
config,
24+
path,
25+
method: "POST",
26+
body: JSON.stringify(todoData),
27+
});
28+
}

Diff for: packages/thunderstore-api/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ export * from "./fetch/teamDetails";
1717
export * from "./fetch/teamMembers";
1818
export * from "./fetch/teamServiceAccounts";
1919
export * from "./fetch/teamCreate";
20+
export * from "./fetch/packageUpload";
2021
export * from "./errors";

Diff for: packages/ts-api-react-forms/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export { ApiForm } from "./ApiForm";
22
export { getErrorFormKey, handleFormApiErrors } from "./errors";
33
export { useApiForm } from "./useApiForm";
44
export type { UseApiFormReturn, UseApiFormArgs } from "./useApiForm";
5-
export { createTeamFormSchema } from "./schema";
5+
export { createTeamFormSchema, uploadPackageFormSchema } from "./schema";

Diff for: packages/ts-api-react-forms/src/schema.ts

+10
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,13 @@ export const createTeamFormSchema = z.object({
55
.string({ required_error: "Team name is required" })
66
.min(1, { message: "Team name is required" }),
77
});
8+
9+
// TODO: Add these manually at the form
10+
// author_name: z.string(),
11+
// upload_uuid: z.string(),
12+
export const uploadPackageFormSchema = z.object({
13+
team: z.string(),
14+
community_categories: z.record(z.array(z.string())),
15+
communities: z.array(z.string()).nonempty(),
16+
has_nsfw_content: z.boolean(),
17+
});

0 commit comments

Comments
 (0)