Skip to content

Instantly share code, notes, and snippets.

@christianalfoni
Last active March 24, 2025 10:52
Show Gist options
  • Save christianalfoni/5f7d05fa611a07d3d9f9e37368b7e7fb to your computer and use it in GitHub Desktop.
Save christianalfoni/5f7d05fa611a07d3d9f9e37368b7e7fb to your computer and use it in GitHub Desktop.
Refactor of component using constructor pattern and state machine
import {
Alert,
Button,
Card,
CardBanner,
CardBody,
CardHeader,
HStack,
VStack,
} from '@client/component-library'
import type {
UploadModelError,
UploadModelResponse,
} from '@shared/api-types/models'
import { uploadModelErrorSchema } from '@shared/api-types/models'
import { paths } from '@shared/utils/paths'
import { isAxiosError } from 'axios'
import { useState } from 'react'
import { InputFormField } from 'src/components/common/FormFields/InputFormField'
import { TextAreaFormField } from 'src/components/common/FormFields/TextAreaFormField'
import { CUSTOM_MODELS_LINK } from 'src/constants'
import { getUploadModelCodeSnippets } from 'src/utils/codeViewerSnippets'
import { APIReferenceSection } from './APIReferenceSection'
import { UploadJobProgress } from './UploadJobProgress'
import { useUploadModel } from './useUploadModel'
const HF_BASE_URL = 'https://huggingface.co/'
export const UploadModelPage = () => {
const [modelSource, setModelSource] = useState<string>()
const [modelName, setModelName] = useState<string>()
const [hasChangedModelNameManually, setHasChangedModelNameManually] =
useState(false)
const [modelDescription, setModelDescription] = useState<string>()
const [huggingfaceToken, setHuggingfaceToken] = useState<string>()
const [error, setError] = useState<UploadModelError | null>(null)
const [successPayload, setSuccessPayload] =
useState<UploadModelResponse | null>(null)
const [uploadJobId, setUploadJobId] = useState<string | null>(null)
const [uploadJobInProgress, setUploadJobInProgress] = useState(false)
const { mutate: uploadModel, isPending: isRequestingUpload } =
useUploadModel()
const isSourceHuggingface = modelSource?.startsWith(HF_BASE_URL)
const hasMissingFields =
!modelName || !modelSource || (isSourceHuggingface && !huggingfaceToken)
const handleUploadModel = (ev: React.FormEvent<HTMLFormElement>) => {
ev.preventDefault()
if (hasMissingFields) return
setError(null)
setSuccessPayload(null)
setUploadJobId(null)
setUploadJobInProgress(false)
uploadModel(
{
model_name: modelName,
model_source: modelSource,
description: modelDescription,
...(isSourceHuggingface && { hf_token: huggingfaceToken }),
},
{
onSuccess(response) {
setSuccessPayload(response)
if (response.data?.job_id) {
setUploadJobInProgress(true)
setUploadJobId(response.data.job_id)
} else {
// Reset the form
setHasChangedModelNameManually(false)
setModelName('')
setModelSource('')
setHuggingfaceToken('')
setModelDescription('')
}
},
onError(error) {
if (isAxiosError(error)) {
const customError = uploadModelErrorSchema.safeParse(
error.response?.data
)
if (customError.success) {
setError(customError.data)
return
}
}
setError({
type: 'unknown_error',
message:
'Unexpected error. Please contact support if the problem persists.',
})
},
}
)
}
const showOpenModelButton =
successPayload?.model_name || error?.message === 'Model name already exists'
const resultModelName = successPayload?.model_name || modelName
return (
<VStack gap={6}>
<Card>
<CardHeader headerText="Upload Custom Model" />
{error && (
<CardBanner
content={
<Alert variant="error" squareCorners dismissible>
{error.message}
</Alert>
}
/>
)}
{successPayload && (
<CardBanner
content={
<Alert
variant={
successPayload.message ===
'Model uploaded and processed successfully'
? 'success'
: 'info'
}
squareCorners
dismissible
>
{successPayload.message}
</Alert>
}
/>
)}
<CardBody>
<HStack>
<VStack className="flex-1" gap={0}>
<form onSubmit={handleUploadModel} className="w-[508px]">
<InputFormField
className="w-full"
label="Model Source"
description="Paste a huggingface URL, an S3 URL or a type in a model name in the format: 'organization/model'"
value={modelSource}
onChange={(ev) => {
const value = ev.target.value
setModelSource(value)
if (!hasChangedModelNameManually) {
// If the user did not touch the name, we automatically generate it
let orgAndName = value
if (value.startsWith(HF_BASE_URL)) {
orgAndName = value.replace(HF_BASE_URL, '')
}
setModelName(orgAndName.split('/').join('-'))
}
}}
placeholder={HF_BASE_URL + 'org/model'}
/>
<HStack fullWidth>
<InputFormField
label="Model Name"
className="w-full"
value={modelName}
onChange={(ev) => {
setModelName(ev.target.value)
setHasChangedModelNameManually(true)
}}
/>
{isSourceHuggingface && (
<InputFormField
label="Hugging Face Token"
description="You hugging Face token is required to download the model."
value={huggingfaceToken}
onChange={(ev) => setHuggingfaceToken(ev.target.value)}
placeholder="hf_abc..."
/>
)}
</HStack>
<TextAreaFormField
label="Description"
value={modelDescription}
onChange={(ev) => setModelDescription(ev.target.value)}
/>
<HStack>
<Button
disabled={hasMissingFields}
busy={isRequestingUpload || uploadJobInProgress}
variant="filled"
type="submit"
>
Upload Model
</Button>
{showOpenModelButton && resultModelName && (
<Button href={paths.model({ name: resultModelName })}>
Open Model
</Button>
)}
</HStack>
</form>
</VStack>
{uploadJobId && (
<UploadJobProgress
jobId={uploadJobId}
onJobCompleted={(newModelName) => {
setUploadJobInProgress(false)
setSuccessPayload({
message: 'Model uploaded and processed successfully',
model_name: newModelName,
})
setError(null)
}}
onJobFailed={(errorMessage) => {
setUploadJobInProgress(false)
setError({
type: 'upload_error',
message: `Model processing failed: ${errorMessage}`,
})
setSuccessPayload(null)
}}
/>
)}
</HStack>
</CardBody>
</Card>
<APIReferenceSection
codeTemplates={getUploadModelCodeSnippets({
modelName: modelName || '<model_name>',
modelSource: modelSource || '<model_source>',
description: modelDescription,
...(isSourceHuggingface && {
hfToken: huggingfaceToken || '<hf_token>',
}),
})}
docsLink={CUSTOM_MODELS_LINK}
/>
</VStack>
)
}
import {
Alert,
Button,
Card,
CardBanner,
CardBody,
CardHeader,
HStack,
VStack,
} from "@client/component-library";
import type {
UploadModelError,
UploadModelResponse,
} from "@shared/api-types/models";
import { uploadModelErrorSchema } from "@shared/api-types/models";
import { paths } from "@shared/utils/paths";
import { isAxiosError } from "axios";
import { useState } from "react";
import { InputFormField } from "src/components/common/FormFields/InputFormField";
import { TextAreaFormField } from "src/components/common/FormFields/TextAreaFormField";
import { CUSTOM_MODELS_LINK } from "src/constants";
import { getUploadModelCodeSnippets } from "src/utils/codeViewerSnippets";
import { APIReferenceSection } from "./APIReferenceSection";
import { UploadJobProgress } from "./UploadJobProgress";
import { useUploadModel } from "./useUploadModel";
const HF_BASE_URL = "https://huggingface.co/";
export const UploadModelPage = () => {
const [modelSource, setModelSource] = useState<string>();
const [modelName, setModelName] = useState<string>();
const [hasChangedModelNameManually, setHasChangedModelNameManually] =
useState(false);
const [modelDescription, setModelDescription] = useState<string>();
const [huggingfaceToken, setHuggingfaceToken] = useState<string>();
const [error, setError] = useState<UploadModelError | null>(null);
const [successPayload, setSuccessPayload] =
useState<UploadModelResponse | null>(null);
const [uploadJobId, setUploadJobId] = useState<string | null>(null);
const [uploadJobInProgress, setUploadJobInProgress] = useState(false);
const { mutate: uploadModel, isPending: isRequestingUpload } =
useUploadModel();
const isSourceHuggingface = modelSource?.startsWith(HF_BASE_URL);
const hasMissingFields =
!modelName || !modelSource || (isSourceHuggingface && !huggingfaceToken);
const showOpenModelButton =
successPayload?.model_name ||
error?.message === "Model name already exists";
const resultModelName = successPayload?.model_name || modelName;
return (
<VStack gap={6}>
<Card>
<CardHeader headerText="Upload Custom Model" />
{error && (
<CardBanner
content={
<Alert variant="error" squareCorners dismissible>
{error.message}
</Alert>
}
/>
)}
{successPayload && (
<CardBanner
content={
<Alert
variant={
successPayload.message ===
"Model uploaded and processed successfully"
? "success"
: "info"
}
squareCorners
dismissible
>
{successPayload.message}
</Alert>
}
/>
)}
<CardBody>
<HStack>
<VStack className="flex-1" gap={0}>
<form onSubmit={handleUploadModel} className="w-[508px]">
<InputFormField
className="w-full"
label="Model Source"
description="Paste a huggingface URL, an S3 URL or a type in a model name in the format: 'organization/model'"
value={modelSource}
onChange={handleSourceChange}
placeholder={HF_BASE_URL + "org/model"}
/>
<HStack fullWidth>
<InputFormField
label="Model Name"
className="w-full"
value={modelName}
onChange={handleNameChange}
/>
{isSourceHuggingface && (
<InputFormField
label="Hugging Face Token"
description="You hugging Face token is required to download the model."
value={huggingfaceToken}
onChange={handleHuggingFaceTokenChange}
placeholder="hf_abc..."
/>
)}
</HStack>
<TextAreaFormField
label="Description"
value={modelDescription}
onChange={handleDescriptionChange}
/>
<HStack>
<Button
disabled={hasMissingFields}
busy={isRequestingUpload || uploadJobInProgress}
variant="filled"
type="submit"
>
Upload Model
</Button>
{showOpenModelButton && resultModelName && (
<Button href={paths.model({ name: resultModelName })}>
Open Model
</Button>
)}
</HStack>
</form>
</VStack>
{uploadJobId && (
<UploadJobProgress
jobId={uploadJobId}
onJobCompleted={handleJobCompleted}
onJobFailed={handleJobFailed}
/>
)}
</HStack>
</CardBody>
</Card>
<APIReferenceSection
codeTemplates={getUploadModelCodeSnippets({
modelName: modelName || "<model_name>",
modelSource: modelSource || "<model_source>",
description: modelDescription,
...(isSourceHuggingface && {
hfToken: huggingfaceToken || "<hf_token>",
}),
})}
docsLink={CUSTOM_MODELS_LINK}
/>
</VStack>
);
function handleJobFailed(errorMessage: string) {
setUploadJobInProgress(false);
setError({
type: "upload_error",
message: `Model processing failed: ${errorMessage}`,
});
setSuccessPayload(null);
}
function handleJobCompleted(newModelName: string) {
setUploadJobInProgress(false);
setSuccessPayload({
message: "Model uploaded and processed successfully",
model_name: newModelName,
});
setError(null);
}
function handleDescriptionChange(ev: React.ChangeEvent<HTMLTextAreaElement>) {
setModelDescription(ev.target.value);
}
function handleHuggingFaceTokenChange(
ev: React.ChangeEvent<HTMLInputElement>
) {
setHuggingfaceToken(ev.target.value);
}
function handleNameChange(ev: React.ChangeEvent<HTMLInputElement>) {
setModelName(ev.target.value);
setHasChangedModelNameManually(true);
}
function handleSourceChange(ev: React.ChangeEvent<HTMLInputElement>) {
const value = ev.target.value;
setModelSource(value);
if (!hasChangedModelNameManually) {
// If the user did not touch the name, we automatically generate it
let orgAndName = value;
if (value.startsWith(HF_BASE_URL)) {
orgAndName = value.replace(HF_BASE_URL, "");
}
setModelName(orgAndName.split("/").join("-"));
}
}
function handleUploadModel(ev: React.FormEvent<HTMLFormElement>) {
ev.preventDefault();
if (hasMissingFields) return;
setError(null);
setSuccessPayload(null);
setUploadJobId(null);
setUploadJobInProgress(false);
uploadModel(
{
model_name: modelName,
model_source: modelSource,
description: modelDescription,
...(isSourceHuggingface && { hf_token: huggingfaceToken }),
},
{
onSuccess(response) {
setSuccessPayload(response);
if (response.data?.job_id) {
setUploadJobInProgress(true);
setUploadJobId(response.data.job_id);
} else {
// Reset the form
setHasChangedModelNameManually(false);
setModelName("");
setModelSource("");
setHuggingfaceToken("");
setModelDescription("");
}
},
onError(error) {
if (isAxiosError(error)) {
const customError = uploadModelErrorSchema.safeParse(
error.response?.data
);
if (customError.success) {
setError(customError.data);
return;
}
}
setError({
type: "unknown_error",
message:
"Unexpected error. Please contact support if the problem persists.",
});
},
}
);
}
};
import {
Alert,
Button,
Card,
CardBanner,
CardBody,
CardHeader,
HStack,
VStack,
} from "@client/component-library";
import type {
UploadModelError,
UploadModelResponse,
} from "@shared/api-types/models";
import { uploadModelErrorSchema } from "@shared/api-types/models";
import { paths } from "@shared/utils/paths";
import { isAxiosError } from "axios";
import { useState } from "react";
import { InputFormField } from "src/components/common/FormFields/InputFormField";
import { TextAreaFormField } from "src/components/common/FormFields/TextAreaFormField";
import { CUSTOM_MODELS_LINK } from "src/constants";
import { getUploadModelCodeSnippets } from "src/utils/codeViewerSnippets";
import { APIReferenceSection } from "./APIReferenceSection";
import { UploadJobProgress } from "./UploadJobProgress";
import { useUploadModel } from "./useUploadModel";
const HF_BASE_URL = "https://huggingface.co/";
type Model = {
name: string;
source: string;
description: string;
huggingfaceToken: string;
hasChangedNameManually: boolean;
};
type IDLE = {
current: "IDLE";
model: Model;
updateSource(ev: React.ChangeEvent<HTMLInputElement>): void;
updateName(ev: React.ChangeEvent<HTMLInputElement>): void;
updateDescription(ev: React.ChangeEvent<HTMLTextAreaElement>): void;
updateHuggingfaceToken(ev: React.ChangeEvent<HTMLTextAreaElement>): void;
upload(): void;
};
type UPLOADING = {
current: "UPLOADING";
model: Model;
};
type MODEL_EXISTS = {
current: "MODEL_EXISTS";
model: Model;
};
type JOB_REQUIRED = {
current: "JOB_REQUIRED";
model: Model;
jobId: string;
jobCompleted(newModelName: string): void;
jobFailed(errorMessage: string): void;
};
type JOB_COMPLETED = {
current: "JOB_COMPLETED";
model: Model;
};
type ERROR = {
current: "ERROR";
model: Model;
type: string;
message: string;
};
type State =
| IDLE
| UPLOADING
| MODEL_EXISTS
| JOB_REQUIRED
| JOB_COMPLETED
| ERROR;
export const UploadModelPage = () => {
const [state, setState] = useState<State>(IDLE());
const { mutate: uploadModel, isPending: isRequestingUpload } =
useUploadModel();
const showOpenModelButton =
state.current === "JOB_COMPLETED" || state.current === "MODEL_EXISTS";
return (
<VStack gap={6}>
<Card>
<CardHeader headerText="Upload Custom Model" />
{state.current === "ERROR" && (
<CardBanner
content={
<Alert variant="error" squareCorners dismissible>
{error.message}
</Alert>
}
/>
)}
{state.current === "MODEL_EXISTS" && (
<CardBanner
content={
<Alert variant="info" squareCorners dismissible>
Model name already exists
</Alert>
}
/>
)}
{state.current === "JOB_COMPLETED" && (
<CardBanner
content={
<Alert variant="success" squareCorners dismissible>
Model uploaded and processed successfully
</Alert>
}
/>
)}
<CardBody>
<HStack>
<VStack className="flex-1" gap={0}>
<form
onSubmit={state.current === "IDLE" ? state.upload : undefined}
className="w-[508px]"
>
<InputFormField
className="w-full"
label="Model Source"
description="Paste a huggingface URL, an S3 URL or a type in a model name in the format: 'organization/model'"
value={state.model.source}
{...(state.current === "IDLE"
? {
onChange: state.updateSource,
placeholder: HF_BASE_URL + "org/model",
}
: {
disabled: true,
})}
/>
<HStack fullWidth>
<InputFormField
label="Model Name"
className="w-full"
value={modelName}
{...(state.current === "IDLE"
? {
onChange: state.updatedName,
}
: {
disabled: true,
})}
/>
{isSourceHuggingface && (
<InputFormField
label="Hugging Face Token"
description="You hugging Face token is required to download the model."
value={huggingfaceToken}
{...(state.current === "IDLE"
? {
onChange: state.updateHuggingfaceToken,
placeholder: "hf_abc...",
}
: {
disabled: true,
})}
/>
)}
</HStack>
<TextAreaFormField
label="Description"
value={modelDescription}
{...(state.current === "IDLE"
? {
onChange: state.updateDescription,
}
: {
disabled: true,
})}
/>
<HStack>
<Button
disabled={
state.current !== "IDLE" ||
hasModelMissingFields(state.model)
}
busy={
state.current === "UPLOADING" ||
state.current === "JOB_REQUIRED"
}
variant="filled"
type="submit"
>
Upload Model
</Button>
{showOpenModelButton && (
<Button href={paths.model({ name: state.model.name })}>
Open Model
</Button>
)}
</HStack>
</form>
</VStack>
{state.current === "JOB_REQUIRED" && (
<UploadJobProgress
jobId={state.jobId}
onJobCompleted={state.jobCompleted}
onJobFailed={state.jobFailed}
/>
)}
</HStack>
</CardBody>
</Card>
<APIReferenceSection
codeTemplates={getUploadModelCodeSnippets({
modelName: state.model.name || "<model_name>",
modelSource: state.model.source || "<model_source>",
description: state.model.description,
...(isSourceHuggingface(state.model) && {
hfToken: state.model.huggingfaceToken || "<hf_token>",
}),
})}
docsLink={CUSTOM_MODELS_LINK}
/>
</VStack>
);
function IDLE(
model: Model = {
name: "",
source: "",
description: "",
hunggingfaceToken: "",
}
): IDLE {
return {
current: "IDLE",
model,
updateSource(ev) {
const source = ev.target.value;
let name = model.name;
// If the user did not touch the name while changing the source, we generate the name
if (!model.hasChangedNameManually) {
if (source.startsWith(HF_BASE_URL)) {
name = value.replace(HF_BASE_URL, "");
}
name = orgAndName.split("/").join("-");
}
setState(IDLE({ ...model, source, name }));
},
updateName(ev) {
setState(
IDLE({
...model,
name: ev.target.value,
hasChangedNameManually: true,
})
);
},
updateDescription(ev) {
setState(IDLE({ ...model, description: ev.target.value }));
},
updateHuggingfaceToken(ev) {
setState(IDLE({ ...model, huggingfaceToken: ev.target.value }));
},
upload() {
if (hasModelMissingFields(model)) return;
setState(UPLOADING(model));
},
};
}
function UPLOADING(model: Model): UPLOADING {
uploadModel(
{
model_name: model.name,
model_source: model.source,
description: model.description,
...(isSourceHuggingface(model) && { hf_token: model.huggingfaceToken }),
},
{
onSuccess(response) {
const jobId = response.data?.job_id;
setState(jobId ? JOB_REQUIRED(model, jobId) : MODEL_EXISTS(model));
},
onError(error) {
if (isAxiosError(error)) {
const customError = uploadModelErrorSchema.safeParse(
error.response?.data
);
if (customError.success) {
setState(ERROR(model, customError.data));
return;
}
}
setState(
ERROR(model, {
type: "unknown_error",
message:
"Unexpected error. Please contact support if the problem persists.",
})
);
},
}
);
return {
current: "UPLOADING",
model,
};
}
function MODEL_EXISTS(model: Model): MODEL_EXISTS {
return {
current: "MODEL_EXISTS",
model,
};
}
function JOB_REQUIRED(model: Model, jobId: string): JOB_REQUIRED {
return {
current: "JOB_REQUIRED",
model,
jobId,
jobCompleted(newModelName) {
setState(JOB_COMPLETED(model, newModelName));
},
jobFailed(errorMessage) {
setState(
ERROR(model, {
type: "upload_error",
message: `Model processing failed: ${errorMessage}`,
})
);
},
};
}
function JOB_COMPLETED(model: Model, newModelName: string): JOB_COMPLETED {
return {
current: "JOB_COMPLETED",
model: { ...model, name: newModelName },
};
}
function ERROR(
model: Model,
error: { type: string; message: string }
): ERROR {
return {
current: "ERROR",
model,
type: error.type,
message: error.message,
};
}
function isSourceHuggingFace(model: Model) {
return model.source.startsWith(HF_BASE_URL);
}
function hasModelMissingFields(model: Model) {
return (
!model.name ||
!model.source ||
(isSourceHuggingface(model) && !model.huggingfaceToken)
);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment