From 252b2a3f87d6a5639cba43da60da1655d3b8c9f1 Mon Sep 17 00:00:00 2001 From: Oksamies Date: Wed, 22 Nov 2023 15:55:30 +0200 Subject: [PATCH 1/4] Fix CreateTeam forms UI problems --- .../src/components/FormTextInput.tsx | 2 +- .../src/forms/CreateTeamForm.module.css | 7 ++++--- .../src/components/Dialog/Dialog.module.css | 18 ------------------ .../src/components/Dialog/Dialog.tsx | 11 +---------- .../PackageDependencyList.tsx | 1 - 5 files changed, 6 insertions(+), 33 deletions(-) diff --git a/packages/cyberstorm-forms/src/components/FormTextInput.tsx b/packages/cyberstorm-forms/src/components/FormTextInput.tsx index 73ca1052e..24b40c3df 100644 --- a/packages/cyberstorm-forms/src/components/FormTextInput.tsx +++ b/packages/cyberstorm-forms/src/components/FormTextInput.tsx @@ -31,7 +31,7 @@ export function FormTextInput< {...field} ref={field.ref} placeholder={placeholder} - color={isDirty ? (invalid ? "red" : "green") : undefined} + color={isDirty || invalid ? (invalid ? "red" : "green") : undefined} disabled={isSubmitting || disabled} /> {error && {error.message}} diff --git a/packages/cyberstorm-forms/src/forms/CreateTeamForm.module.css b/packages/cyberstorm-forms/src/forms/CreateTeamForm.module.css index f3f6e0c92..ed4104103 100644 --- a/packages/cyberstorm-forms/src/forms/CreateTeamForm.module.css +++ b/packages/cyberstorm-forms/src/forms/CreateTeamForm.module.css @@ -1,13 +1,14 @@ .root { display: flex; flex-direction: column; - gap: 2rem; } .dialog { display: flex; flex-direction: column; gap: 1.5rem; + padding: var(--space--32); + border-top: var(--border-width--px) solid var(--color-surface--5); } .dialogText { @@ -22,6 +23,6 @@ flex-direction: row-reverse; gap: 1rem; justify-content: space-between; - padding-top: var(--space--16); - border-top: var(--border); + padding: var(--space--16) var(--space--24); + border-top: var(--border-width--px) solid var(--color-surface--5); } diff --git a/packages/cyberstorm/src/components/Dialog/Dialog.module.css b/packages/cyberstorm/src/components/Dialog/Dialog.module.css index 74349fa37..7430631c6 100644 --- a/packages/cyberstorm/src/components/Dialog/Dialog.module.css +++ b/packages/cyberstorm/src/components/Dialog/Dialog.module.css @@ -31,24 +31,6 @@ overflow: auto; } -.bodyPadding > * { - padding-right: var(--space--32); - padding-left: var(--space--32); -} - -.bodyPadding > :first-child { - padding-top: var(--space--16); -} - -.bodyPadding > :last-child { - padding: var(--space--16) var(--space--24); - border-top: var(--border); -} - -.bodyPadding > :nth-last-child(2) { - padding-bottom: var(--space--32); -} - .header { display: flex; flex-direction: row-reverse; diff --git a/packages/cyberstorm/src/components/Dialog/Dialog.tsx b/packages/cyberstorm/src/components/Dialog/Dialog.tsx index 127340592..f0f7b997d 100644 --- a/packages/cyberstorm/src/components/Dialog/Dialog.tsx +++ b/packages/cyberstorm/src/components/Dialog/Dialog.tsx @@ -12,7 +12,6 @@ interface DialogProps extends PropsWithChildren { defaultOpen?: boolean; trigger?: ReactNode; title?: string; - disableDialogContentStyles?: boolean; showHeaderBorder?: boolean; } @@ -25,7 +24,6 @@ export function Dialog(props: DialogProps) { defaultOpen = false, trigger, title = undefined, - disableDialogContentStyles = false, showHeaderBorder = false, } = props; @@ -72,14 +70,7 @@ export function Dialog(props: DialogProps) { {title ?
{title}
: null} -
- {children} -
+
{children}
diff --git a/packages/cyberstorm/src/components/Layout/PackageDetailLayout/PackageDependencyList/PackageDependencyList.tsx b/packages/cyberstorm/src/components/Layout/PackageDetailLayout/PackageDependencyList/PackageDependencyList.tsx index 8c64f763a..0cba4def9 100644 --- a/packages/cyberstorm/src/components/Layout/PackageDetailLayout/PackageDependencyList/PackageDependencyList.tsx +++ b/packages/cyberstorm/src/components/Layout/PackageDetailLayout/PackageDependencyList/PackageDependencyList.tsx @@ -84,7 +84,6 @@ export function PackageDependencyList(props: PackageDependencyListProps) { headerIcon={} headerRightContent={ Date: Wed, 22 Nov 2023 15:56:46 +0200 Subject: [PATCH 2/4] Add parsing of error fields to cs forms --- packages/thunderstore-api/src/apiFetch.ts | 7 +++++-- packages/thunderstore-api/src/errors.ts | 15 ++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/thunderstore-api/src/apiFetch.ts b/packages/thunderstore-api/src/apiFetch.ts index 7a01c7ae6..26e9255f2 100644 --- a/packages/thunderstore-api/src/apiFetch.ts +++ b/packages/thunderstore-api/src/apiFetch.ts @@ -16,15 +16,18 @@ export async function apiFetch2(args: apiFetchArgs) { const url = getUrl(args.config, args.path, args.query); const response = await fetch(url, { + method: args.method ? args.method : "GET", headers: { ...BASE_HEADERS, ...getAuthHeaders(args.config), }, - body: args.body, + ...(args.method === "GET" || args.method === "HEAD" || args.method === null + ? {} + : { body: args.body }), }); if (!response.ok) { - throw ApiError.createFromResponse(response); + throw await ApiError.createFromResponse(response); } return response.json(); diff --git a/packages/thunderstore-api/src/errors.ts b/packages/thunderstore-api/src/errors.ts index e5352ddbc..d8a280fae 100644 --- a/packages/thunderstore-api/src/errors.ts +++ b/packages/thunderstore-api/src/errors.ts @@ -3,17 +3,22 @@ export function isApiError(e: Error | ApiError | unknown): e is ApiError { } export class ApiError extends Error { - constructor(message?: string) { + response: { [key: string]: string[] } | undefined; + + constructor(message?: string, response?: { [key: string]: string[] }) { super(message); + this.response = response; } - static createFromResponse(response: Response): ApiError { + static async createFromResponse(response: Response): Promise { // TODO: Implement response parsing for known error scenarios - return new ApiError(`${response.status}: ${response.statusText}`); + return new ApiError( + `${response.status}: ${response.statusText}`, + await response.json() + ); } getFieldErrors(): { [key: string]: string[] } { - // TODO: Implement - return {}; + return { ...this.response }; } } From 8e66b57c6df974adb276fb6a0698aa76d26de601 Mon Sep 17 00:00:00 2001 From: Mythic Date: Thu, 23 Nov 2023 17:09:23 +0200 Subject: [PATCH 3/4] Improve apiFetch2 --- packages/thunderstore-api/src/apiFetch.ts | 9 ++------- packages/thunderstore-api/src/fetch/teamCreate.ts | 6 ++++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/thunderstore-api/src/apiFetch.ts b/packages/thunderstore-api/src/apiFetch.ts index 26e9255f2..581ebb46a 100644 --- a/packages/thunderstore-api/src/apiFetch.ts +++ b/packages/thunderstore-api/src/apiFetch.ts @@ -8,22 +8,18 @@ const BASE_HEADERS = { export type apiFetchArgs = { config: RequestConfig; path: string; - method: RequestInit["method"]; query?: string; - body?: RequestInit["body"]; + request?: Omit; }; export async function apiFetch2(args: apiFetchArgs) { const url = getUrl(args.config, args.path, args.query); const response = await fetch(url, { - method: args.method ? args.method : "GET", + ...(args.request ?? {}), headers: { ...BASE_HEADERS, ...getAuthHeaders(args.config), }, - ...(args.method === "GET" || args.method === "HEAD" || args.method === null - ? {} - : { body: args.body }), }); if (!response.ok) { @@ -41,7 +37,6 @@ export function apiFetch(config: RequestConfig, path: string, query?: string) { config, path, query, - method: "GET", }); } diff --git a/packages/thunderstore-api/src/fetch/teamCreate.ts b/packages/thunderstore-api/src/fetch/teamCreate.ts index a16ddfc69..c63731d9c 100644 --- a/packages/thunderstore-api/src/fetch/teamCreate.ts +++ b/packages/thunderstore-api/src/fetch/teamCreate.ts @@ -11,7 +11,9 @@ export function createTeam(config: RequestConfig, data: CreateTeamApiArgs) { return apiFetch2({ config, path, - method: "POST", - body: JSON.stringify(data), + request: { + method: "POST", + body: JSON.stringify(data), + }, }); } From 362c3a96548bc06845a8813b3e9c387a801066a5 Mon Sep 17 00:00:00 2001 From: Mythic Date: Thu, 23 Nov 2023 17:30:24 +0200 Subject: [PATCH 4/4] Improve API error parsing --- packages/thunderstore-api/src/errors.ts | 59 ++++++++++++++++++++----- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/packages/thunderstore-api/src/errors.ts b/packages/thunderstore-api/src/errors.ts index d8a280fae..41c07674f 100644 --- a/packages/thunderstore-api/src/errors.ts +++ b/packages/thunderstore-api/src/errors.ts @@ -1,24 +1,61 @@ +type JSONValue = + | string + | number + | boolean + | { [x: string]: JSONValue } + | JSONValue[]; + export function isApiError(e: Error | ApiError | unknown): e is ApiError { return e instanceof ApiError; } export class ApiError extends Error { - response: { [key: string]: string[] } | undefined; + response: Response; + responseJson?: JSONValue; - constructor(message?: string, response?: { [key: string]: string[] }) { - super(message); - this.response = response; + constructor(args: { + message: string; + response: Response; + responseJson?: JSONValue; + }) { + super(args.message); + this.responseJson = args.responseJson; + this.response = args.response; } static async createFromResponse(response: Response): Promise { - // TODO: Implement response parsing for known error scenarios - return new ApiError( - `${response.status}: ${response.statusText}`, - await response.json() - ); + let responseJson: JSONValue | undefined; + try { + responseJson = await response.json(); + } catch (e) { + responseJson = undefined; + } + + return new ApiError({ + message: `${response.status}: ${response.statusText}`, + response: response, + responseJson: responseJson, + }); } - getFieldErrors(): { [key: string]: string[] } { - return { ...this.response }; + getFieldErrors(): { [key: string | "root"]: string[] } { + if (typeof this.responseJson !== "object") + return { root: ["Unknown error occurred"] }; + if (Array.isArray(this.responseJson)) { + return { + root: this.responseJson.map((x) => x.toString()), + }; + } else { + return Object.fromEntries( + Object.entries(this.responseJson).map(([key, val]) => { + return [ + key, + Array.isArray(val) + ? val.map((x) => x.toString()) + : [val.toString()], + ]; + }) + ); + } } }