From 7badbf804a9c1c1fb1ea121be3fb608f632dc751 Mon Sep 17 00:00:00 2001 From: Tuval Simha Date: Thu, 25 Jul 2024 10:35:22 +0300 Subject: [PATCH] (2) Drop modals from V2: Delete Project Modal (#5231) Co-authored-by: Kamil Kisiela --- .../components/v2/modals/delete-project.tsx | 75 ------------- .../web/app/src/components/v2/modals/index.ts | 1 - packages/web/app/src/lib/urql-cache.ts | 2 +- .../web/app/src/pages/project-settings.tsx | 102 +++++++++++++++++- .../src/stories/delete-project.stories.tsx | 33 ++++++ 5 files changed, 135 insertions(+), 78 deletions(-) delete mode 100644 packages/web/app/src/components/v2/modals/delete-project.tsx create mode 100644 packages/web/app/src/stories/delete-project.stories.tsx diff --git a/packages/web/app/src/components/v2/modals/delete-project.tsx b/packages/web/app/src/components/v2/modals/delete-project.tsx deleted file mode 100644 index ec23b1e7e..000000000 --- a/packages/web/app/src/components/v2/modals/delete-project.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { ReactElement } from 'react'; -import { useMutation } from 'urql'; -import { Button } from '@/components/ui/button'; -import { Heading } from '@/components/ui/heading'; -import { Modal } from '@/components/v2'; -import { graphql } from '@/gql'; -import { TrashIcon } from '@radix-ui/react-icons'; -import { useRouter } from '@tanstack/react-router'; - -export const DeleteProjectMutation = graphql(` - mutation deleteProject($selector: ProjectSelectorInput!) { - deleteProject(selector: $selector) { - selector { - organization - project - } - deletedProject { - __typename - id - } - } - } -`); - -export const DeleteProjectModal = (props: { - isOpen: boolean; - toggleModalOpen: () => void; - organizationId: string; - projectId: string; -}): ReactElement => { - const { isOpen, toggleModalOpen } = props; - const [, mutate] = useMutation(DeleteProjectMutation); - const router = useRouter(); - - return ( - - - Delete project -

- Are you sure you wish to delete this project? This action is irreversible! -

-
- - -
-
- ); -}; diff --git a/packages/web/app/src/components/v2/modals/index.ts b/packages/web/app/src/components/v2/modals/index.ts index ba1f6e62c..2930e4322 100644 --- a/packages/web/app/src/components/v2/modals/index.ts +++ b/packages/web/app/src/components/v2/modals/index.ts @@ -1,5 +1,4 @@ export { ChangePermissionsModal } from './change-permissions'; export { ConnectSchemaModal } from './connect-schema'; export { DeleteOrganizationModal } from './delete-organization'; -export { DeleteProjectModal } from './delete-project'; export { TransferOrganizationOwnershipModal } from './transfer-organization-ownership'; diff --git a/packages/web/app/src/lib/urql-cache.ts b/packages/web/app/src/lib/urql-cache.ts index 48c41f844..c9d7f70c1 100644 --- a/packages/web/app/src/lib/urql-cache.ts +++ b/packages/web/app/src/lib/urql-cache.ts @@ -12,9 +12,9 @@ import type { DeleteCollectionMutationType } from '@/components/target/laborator import type { DeleteOperationMutationType } from '@/components/target/laboratory/delete-operation-modal'; import type { CreateAccessToken_CreateTokenMutation } from '@/components/target/settings/registry-access-token'; import type { DeleteOrganizationDocument } from '@/components/v2/modals/delete-organization'; -import { type DeleteProjectMutation } from '@/components/v2/modals/delete-project'; import { graphql } from '@/gql'; import type { CreateOrganizationMutation } from '@/pages/organization-new'; +import type { DeleteProjectMutation } from '@/pages/project-settings'; import { CollectionsQuery } from '@/pages/target-laboratory'; import { TokensDocument, diff --git a/packages/web/app/src/pages/project-settings.tsx b/packages/web/app/src/pages/project-settings.tsx index 396f1c85a..964fbf7b9 100644 --- a/packages/web/app/src/pages/project-settings.tsx +++ b/packages/web/app/src/pages/project-settings.tsx @@ -16,6 +16,14 @@ import { CardHeader, CardTitle, } from '@/components/ui/card'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; import { DocsLink } from '@/components/ui/docs-note'; import { HiveLogo } from '@/components/ui/icon'; import { Meta } from '@/components/ui/meta'; @@ -23,7 +31,6 @@ import { Subtitle, Title } from '@/components/ui/page'; import { QueryError } from '@/components/ui/query-error'; import { useToast } from '@/components/ui/use-toast'; import { Input } from '@/components/v2/input'; -import { DeleteProjectModal } from '@/components/v2/modals'; import { graphql, useFragment } from '@/gql'; import { ProjectType } from '@/gql/graphql'; import { canAccessProject, ProjectAccessScope, useProjectAccess } from '@/lib/access/project'; @@ -431,3 +438,96 @@ export function ProjectSettingsPage(props: { organizationId: string; projectId: ); } + +export const DeleteProjectMutation = graphql(` + mutation deleteProject($selector: ProjectSelectorInput!) { + deleteProject(selector: $selector) { + selector { + organization + project + } + deletedProject { + __typename + id + } + } + } +`); + +export function DeleteProjectModal(props: { + isOpen: boolean; + toggleModalOpen: () => void; + organizationId: string; + projectId: string; +}) { + const { organizationId, projectId } = props; + const [, mutate] = useMutation(DeleteProjectMutation); + const { toast } = useToast(); + const router = useRouter(); + + const handleDelete = async () => { + const { error } = await mutate({ + selector: { + organization: organizationId, + project: projectId, + }, + }); + + if (error) { + toast({ + variant: 'destructive', + title: 'Failed to delete project', + description: error.message, + }); + } else { + toast({ + title: 'Project deleted', + description: 'The project has been successfully deleted.', + }); + props.toggleModalOpen(); + void router.navigate({ + to: '/$organizationId', + params: { + organizationId, + }, + }); + } + }; + + return ( + + ); +} + +export function DeleteProjectModalContent(props: { + isOpen: boolean; + toggleModalOpen: () => void; + handleDelete: () => void; +}) { + return ( + + + + Delete project + + + Every target and its published schema, reported data, and settings associated with this + project will be permanently deleted. + + This action is irreversible! + + + + + + + ); +} diff --git a/packages/web/app/src/stories/delete-project.stories.tsx b/packages/web/app/src/stories/delete-project.stories.tsx new file mode 100644 index 000000000..0bc853de8 --- /dev/null +++ b/packages/web/app/src/stories/delete-project.stories.tsx @@ -0,0 +1,33 @@ +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; +import { DeleteProjectModalContent } from '@/pages/project-settings'; +import { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Modals/Delete Project Modal', + component: DeleteProjectModalContent, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => { + const [openModal, setOpenModal] = useState(false); + const toggleModalOpen = () => setOpenModal(!openModal); + + return ( + <> + + {openModal && ( + console.log('Delete')} + isOpen={openModal} + toggleModalOpen={toggleModalOpen} + key="delete-project-modal" + /> + )} + + ); + }, +};