Skip to content
Draft
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
156 changes: 156 additions & 0 deletions frontend/src/components/Environments/ReuseEnvironment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import {
Button,
FormControl,
FormErrorMessage,
FormLabel,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalFooter,
ModalHeader,
ModalOverlay,
Textarea,
} from "@chakra-ui/react"
import { useMutation, useQueryClient } from "@tanstack/react-query"
import { type SubmitHandler, useForm } from "react-hook-form"
import { getRouteApi } from "@tanstack/react-router"

import { ProjectsService, type Environment } from "../../client"
import type { ApiError } from "../../client/core/ApiError"
import useCustomToast from "../../hooks/useCustomToast"
import { handleError } from "../../utils"

interface ReuseEnvProps {
isOpen: boolean
onClose: () => void
environment: Environment
}

interface EnvPost {
path: string
title: string
description: string
targetProjectOwner: string
targetProjectName: string
}

const ReuseEnvironment = ({ isOpen, onClose }: ReuseEnvProps) => {
const queryClient = useQueryClient()
const showToast = useCustomToast()
const routeApi = getRouteApi("/_layout/$userName/$projectName")
const { userName, projectName } = routeApi.useParams()
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm<EnvPost>({
mode: "onBlur",
criteriaMode: "all",
defaultValues: {
path: "",
title: "",
description: "",
},
})
const mutation = useMutation({
mutationFn: (data: Environment) =>
ProjectsService.postProjectEnvironment({
requestBody: data,
ownerName: userName,
projectName: projectName,
}),
onSuccess: () => {
showToast("Success!", "Environment added successfully.", "success")
reset()
onClose()
},
onError: (err: ApiError) => {
handleError(err, showToast)
},
onSettled: () => {
queryClient.invalidateQueries({
queryKey: ["projects", userName, projectName, "datasets"],
})
},
})
const onSubmit: SubmitHandler<Environment> = (data) => {
mutation.mutate(data)
}

return (
<>
<Modal
isOpen={isOpen}
onClose={onClose}
size={{ base: "sm", md: "md" }}
isCentered
>
<ModalOverlay />
<ModalContent as="form" onSubmit={handleSubmit(onSubmit)}>
<ModalHeader>Reuse environment</ModalHeader>
<ModalCloseButton />
<ModalBody pb={6}>
<FormControl isRequired isInvalid={!!errors.path}>
<FormLabel htmlFor="path">
Path (relative to project folder)
</FormLabel>
<Input
id="path"
{...register("path", {
required: "Path is required",
})}
placeholder="Ex: data/my-data.parquet"
type="text"
/>
{errors.path && (
<FormErrorMessage>{errors.path.message}</FormErrorMessage>
)}
</FormControl>
<FormControl mt={4} isRequired isInvalid={!!errors.title}>
<FormLabel htmlFor="title">Title</FormLabel>
<Input
id="title"
{...register("title")}
placeholder="Title"
type="text"
/>
{errors.title && (
<FormErrorMessage>{errors.title.message}</FormErrorMessage>
)}
</FormControl>
<FormControl mt={4} isRequired isInvalid={!!errors.description}>
<FormLabel htmlFor="description">Description</FormLabel>
<Textarea
id="description"
{...register("description", {
required: "Description is required",
})}
placeholder="Description"
/>
{errors.description && (
<FormErrorMessage>
{errors.description.message}
</FormErrorMessage>
)}
</FormControl>
</ModalBody>
<ModalFooter gap={3}>
<Button
variant="primary"
type="submit"
isLoading={isSubmitting || mutation.isPending}
>
Save
</Button>
<Button onClick={onClose}>Cancel</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
)
}

export default ReuseEnvironment
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface EnvCardProps {

const EnvCard = ({ environment }: EnvCardProps) => {
const viewEnvModal = useDisclosure()

const reuseEnvModal = useDisclosure()
return (
<>
<Card key={environment.name} p={6} variant="elevated">
Expand Down Expand Up @@ -119,6 +119,9 @@ const EnvCard = ({ environment }: EnvCardProps) => {
) : (
""
)}
<Button variant="primary" size="xs" onClick={reuseEnvModal.onOpen}>
Reuse
</Button>
<ViewEnvironment
environment={environment}
isOpen={viewEnvModal.isOpen}
Expand Down