(3) Drop modals from V2: Delete Organization Modal (#5232)

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
This commit is contained in:
Tuval Simha 2024-07-25 11:45:16 +03:00 committed by GitHub
parent f9f2e387f4
commit 0c31db6b72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 142 additions and 98 deletions

View file

@ -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>
);
};

View file

@ -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';

View file

@ -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 {

View file

@ -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>
);
}

View file

@ -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

View file

@ -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

View 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"
/>
)}
</>
);
},
};