mirror of
https://github.com/graphql-hive/console
synced 2026-05-23 17:18:23 +00:00
(3) Drop modals from V2: Delete Organization Modal (#5232)
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
This commit is contained in:
parent
f9f2e387f4
commit
0c31db6b72
7 changed files with 142 additions and 98 deletions
|
|
@ -1,78 +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 { FragmentType, graphql } from '@/gql';
|
||||
import { TrashIcon } from '@radix-ui/react-icons';
|
||||
import { useRouter } from '@tanstack/react-router';
|
||||
|
||||
export const DeleteOrganizationDocument = graphql(`
|
||||
mutation deleteOrganization($selector: OrganizationSelectorInput!) {
|
||||
deleteOrganization(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
}
|
||||
organization {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const DeleteOrganizationModal_OrganizationFragment = graphql(`
|
||||
fragment DeleteOrganizationModal_OrganizationFragment on Organization {
|
||||
id
|
||||
cleanId
|
||||
}
|
||||
`);
|
||||
|
||||
export const DeleteOrganizationModal = (props: {
|
||||
isOpen: boolean;
|
||||
toggleModalOpen: () => void;
|
||||
organization: FragmentType<typeof DeleteOrganizationModal_OrganizationFragment>;
|
||||
organizationId: string;
|
||||
}): ReactElement => {
|
||||
const { isOpen, toggleModalOpen } = props;
|
||||
const [, mutate] = useMutation(DeleteOrganizationDocument);
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={isOpen}
|
||||
onOpenChange={toggleModalOpen}
|
||||
className="flex flex-col items-center gap-5"
|
||||
>
|
||||
<TrashIcon className="h-16 w-auto text-red-500 opacity-70" />
|
||||
<Heading>Delete organization</Heading>
|
||||
<p className="text-sm text-gray-500">
|
||||
Are you sure you wish to delete this organization? This action is irreversible!
|
||||
</p>
|
||||
|
||||
<div className="flex w-full gap-2">
|
||||
<Button type="button" size="lg" className="w-full justify-center" onClick={toggleModalOpen}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
size="lg"
|
||||
className="w-full justify-center"
|
||||
variant="destructive"
|
||||
onClick={async () => {
|
||||
await mutate({
|
||||
selector: {
|
||||
organization: props.organizationId,
|
||||
},
|
||||
});
|
||||
void router.navigate({
|
||||
to: '/',
|
||||
});
|
||||
toggleModalOpen();
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
export { ChangePermissionsModal } from './change-permissions';
|
||||
export { ConnectSchemaModal } from './connect-schema';
|
||||
export { DeleteOrganizationModal } from './delete-organization';
|
||||
export { TransferOrganizationOwnershipModal } from './transfer-organization-ownership';
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ import type { CreateOperationMutationType } from '@/components/target/laboratory
|
|||
import type { DeleteCollectionMutationType } from '@/components/target/laboratory/delete-collection-modal';
|
||||
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 { graphql } from '@/gql';
|
||||
import type { CreateOrganizationMutation } from '@/pages/organization-new';
|
||||
import type { DeleteOrganizationDocument } from '@/pages/organization-settings';
|
||||
import type { DeleteProjectMutation } from '@/pages/project-settings';
|
||||
import { CollectionsQuery } from '@/pages/target-laboratory';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,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 { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form';
|
||||
import { GitHubIcon, SlackIcon } from '@/components/ui/icon';
|
||||
|
|
@ -21,10 +29,7 @@ import { Meta } from '@/components/ui/meta';
|
|||
import { Subtitle, Title } from '@/components/ui/page';
|
||||
import { QueryError } from '@/components/ui/query-error';
|
||||
import { useToast } from '@/components/ui/use-toast';
|
||||
import {
|
||||
DeleteOrganizationModal,
|
||||
TransferOrganizationOwnershipModal,
|
||||
} from '@/components/v2/modals';
|
||||
import { TransferOrganizationOwnershipModal } from '@/components/v2/modals';
|
||||
import { Tag } from '@/components/v2/tag';
|
||||
import { env } from '@/env/frontend';
|
||||
import { FragmentType, graphql, useFragment } from '@/gql';
|
||||
|
|
@ -224,7 +229,6 @@ const SettingsPageRenderer_OrganizationFragment = graphql(`
|
|||
...CanAccessOrganization_MemberFragment
|
||||
isOwner
|
||||
}
|
||||
...DeleteOrganizationModal_OrganizationFragment
|
||||
...TransferOrganizationOwnershipModal_OrganizationFragment
|
||||
}
|
||||
`);
|
||||
|
|
@ -552,7 +556,6 @@ const SettingsPageRenderer = (props: {
|
|||
organizationId={props.organizationId}
|
||||
isOpen={isDeleteModalOpen}
|
||||
toggleModalOpen={toggleDeleteModalOpen}
|
||||
organization={organization}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -613,3 +616,90 @@ export function OrganizationSettingsPage(props: { organizationId: string }) {
|
|||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export const DeleteOrganizationDocument = graphql(`
|
||||
mutation deleteOrganization($selector: OrganizationSelectorInput!) {
|
||||
deleteOrganization(selector: $selector) {
|
||||
selector {
|
||||
organization
|
||||
}
|
||||
organization {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export function DeleteOrganizationModal(props: {
|
||||
isOpen: boolean;
|
||||
toggleModalOpen: () => void;
|
||||
organizationId: string;
|
||||
}) {
|
||||
const { organizationId } = props;
|
||||
const [, mutate] = useMutation(DeleteOrganizationDocument);
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
|
||||
const handleDelete = async () => {
|
||||
const { error } = await mutate({
|
||||
selector: {
|
||||
organization: organizationId,
|
||||
},
|
||||
});
|
||||
if (error) {
|
||||
toast({
|
||||
variant: 'destructive',
|
||||
title: 'Failed to delete organization',
|
||||
description: error.message,
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: 'Organization deleted',
|
||||
description: 'The organization has been successfully deleted.',
|
||||
});
|
||||
props.toggleModalOpen();
|
||||
void router.navigate({
|
||||
to: '/',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DeleteOrganizationModalContent
|
||||
isOpen={props.isOpen}
|
||||
toggleModalOpen={props.toggleModalOpen}
|
||||
handleDelete={handleDelete}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function DeleteOrganizationModalContent(props: {
|
||||
isOpen: boolean;
|
||||
toggleModalOpen: () => void;
|
||||
handleDelete: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={props.isOpen} onOpenChange={props.toggleModalOpen}>
|
||||
<DialogContent className="w-4/5 max-w-[520px] md:w-3/5">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete organization</DialogTitle>
|
||||
<DialogDescription>
|
||||
Every project created under this organization will be deleted as well.
|
||||
</DialogDescription>
|
||||
<DialogDescription>
|
||||
<span className="font-bold">This action is irreversible!</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter className="gap-2">
|
||||
<Button variant="outline" onClick={props.toggleModalOpen}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={props.handleDelete}>
|
||||
Delete
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -513,12 +513,12 @@ export function DeleteProjectModalContent(props: {
|
|||
<DialogContent className="w-4/5 max-w-[520px] md:w-3/5">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete project</DialogTitle>
|
||||
<DialogDescription>
|
||||
Every target and its published schema, reported data, and settings associated with this
|
||||
project will be permanently deleted.
|
||||
</DialogDescription>
|
||||
<DialogDescription className="font-bold">This action is irreversible!</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
Every target and its published schema, reported data, and settings associated with this
|
||||
project will be permanently deleted.
|
||||
</DialogDescription>
|
||||
<DialogDescription className="font-bold">This action is irreversible!</DialogDescription>
|
||||
<DialogFooter className="gap-2">
|
||||
<Button variant="outline" onClick={props.toggleModalOpen}>
|
||||
Cancel
|
||||
|
|
|
|||
|
|
@ -1355,14 +1355,14 @@ export function DeleteTargetModalContent(props: {
|
|||
<DialogContent className="w-4/5 max-w-[520px] md:w-3/5">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete target</DialogTitle>
|
||||
<DialogDescription>
|
||||
Every published schema, reported data, and settings associated with this target will be
|
||||
permanently deleted.
|
||||
</DialogDescription>
|
||||
<DialogDescription>
|
||||
<span className="font-bold">This action is irreversible!</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
Every published schema, reported data, and settings associated with this target will be
|
||||
permanently deleted.
|
||||
</DialogDescription>
|
||||
<DialogDescription>
|
||||
<span className="font-bold">This action is irreversible!</span>
|
||||
</DialogDescription>
|
||||
<DialogFooter className="gap-2">
|
||||
<Button variant="outline" onClick={props.toggleModalOpen}>
|
||||
Cancel
|
||||
|
|
|
|||
33
packages/web/app/src/stories/delete-organization.stories.tsx
Normal file
33
packages/web/app/src/stories/delete-organization.stories.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { DeleteOrganizationModalContent } from '@/pages/organization-settings';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
const meta: Meta<typeof DeleteOrganizationModalContent> = {
|
||||
title: 'Modals/Delete Organization Modal',
|
||||
component: DeleteOrganizationModalContent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof DeleteOrganizationModalContent>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: () => {
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const toggleModalOpen = () => setOpenModal(!openModal);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={toggleModalOpen}>Open Modal</Button>
|
||||
{openModal && (
|
||||
<DeleteOrganizationModalContent
|
||||
isOpen={openModal}
|
||||
toggleModalOpen={toggleModalOpen}
|
||||
handleDelete={() => console.log('Delete')}
|
||||
key="delete-organization-modal"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
};
|
||||
Loading…
Reference in a new issue