From 479397e57085df6369ababa23c21e4de7002bb6b Mon Sep 17 00:00:00 2001 From: Tuval Simha Date: Fri, 19 Jul 2024 15:38:49 +0300 Subject: [PATCH] Drop modals from V2: Create target modal (#5227) --- .../src/components/layouts/organization.tsx | 4 +- .../app/src/components/layouts/project.tsx | 6 +- .../web/app/src/components/layouts/target.tsx | 2 +- .../settings/oidc-integration-section.tsx | 2 +- .../src/components/target/explorer/common.tsx | 2 +- .../target/explorer/super-graph-metadata.tsx | 2 +- .../target/history/errors-and-changes.tsx | 2 +- .../target/settings/cdn-access-tokens.tsx | 2 +- .../web/app/src/components/ui/activities.tsx | 2 +- .../app/src/components/ui/create-target.tsx | 182 ++++++++++++++++++ .../src/components/{v2 => ui}/hive-link.tsx | 2 +- .../app/src/components/{v2 => ui}/icon.tsx | 0 packages/web/app/src/components/ui/input.tsx | 2 +- .../web/app/src/components/ui/user-menu.tsx | 4 +- .../web/app/src/components/v2/copy-value.tsx | 2 +- .../web/app/src/components/v2/inline-code.tsx | 2 +- packages/web/app/src/components/v2/modal.tsx | 2 +- .../components/v2/modals/create-target.tsx | 123 ------------ .../web/app/src/components/v2/modals/index.ts | 1 - .../transfer-organization-ownership.tsx | 2 +- packages/web/app/src/components/v2/select.tsx | 2 +- packages/web/app/src/lib/urql-cache.ts | 2 +- packages/web/app/src/pages/auth.tsx | 2 +- packages/web/app/src/pages/dev.tsx | 2 +- packages/web/app/src/pages/index.tsx | 2 +- .../web/app/src/pages/organization-join.tsx | 2 +- .../web/app/src/pages/organization-new.tsx | 2 +- .../app/src/pages/organization-settings.tsx | 2 +- .../web/app/src/pages/project-settings.tsx | 2 +- .../app/src/pages/target-checks-single.tsx | 2 +- .../app/src/pages/target-history-version.tsx | 2 +- .../web/app/src/pages/target-laboratory.tsx | 2 +- .../app/src/stories/create-target.stories.tsx | 61 ++++++ 33 files changed, 275 insertions(+), 156 deletions(-) create mode 100644 packages/web/app/src/components/ui/create-target.tsx rename packages/web/app/src/components/{v2 => ui}/hive-link.tsx (86%) rename packages/web/app/src/components/{v2 => ui}/icon.tsx (100%) delete mode 100644 packages/web/app/src/components/v2/modals/create-target.tsx create mode 100644 packages/web/app/src/stories/create-target.stories.tsx diff --git a/packages/web/app/src/components/layouts/organization.tsx b/packages/web/app/src/components/layouts/organization.tsx index 00a0714cb..c6494a0ec 100644 --- a/packages/web/app/src/components/layouts/organization.tsx +++ b/packages/web/app/src/components/layouts/organization.tsx @@ -2,8 +2,6 @@ import { ReactElement, ReactNode } from 'react'; import { useQuery } from 'urql'; import { Button } from '@/components/ui/button'; import { UserMenu } from '@/components/ui/user-menu'; -import { HiveLink } from '@/components/v2/hive-link'; -import { PlusIcon } from '@/components/v2/icon'; import { CreateProjectModal } from '@/components/v2/modals'; import { Tabs } from '@/components/v2/tabs'; import { env } from '@/env/frontend'; @@ -19,6 +17,8 @@ import { useLastVisitedOrganizationWriter } from '@/lib/last-visited-org'; import { Link } from '@tanstack/react-router'; import { ProPlanBilling } from '../organization/billing/ProPlanBillingWarm'; import { RateLimitWarn } from '../organization/billing/RateLimitWarn'; +import { HiveLink } from '../ui/hive-link'; +import { PlusIcon } from '../ui/icon'; import { QueryError } from '../ui/query-error'; import { OrganizationSelector } from './organization-selectors'; diff --git a/packages/web/app/src/components/layouts/project.tsx b/packages/web/app/src/components/layouts/project.tsx index 0e5525bb9..b966b3931 100644 --- a/packages/web/app/src/components/layouts/project.tsx +++ b/packages/web/app/src/components/layouts/project.tsx @@ -2,9 +2,6 @@ import { ReactElement, ReactNode } from 'react'; import { useQuery } from 'urql'; import { Button } from '@/components/ui/button'; import { UserMenu } from '@/components/ui/user-menu'; -import { HiveLink } from '@/components/v2/hive-link'; -import { PlusIcon } from '@/components/v2/icon'; -import { CreateTargetModal } from '@/components/v2/modals'; import { Tabs } from '@/components/v2/tabs'; import { graphql } from '@/gql'; import { canAccessProject, ProjectAccessScope, useProjectAccess } from '@/lib/access/project'; @@ -12,6 +9,9 @@ import { useToggle } from '@/lib/hooks'; import { useLastVisitedOrganizationWriter } from '@/lib/last-visited-org'; import { Link } from '@tanstack/react-router'; import { ProjectMigrationToast } from '../project/migration-toast'; +import { CreateTargetModal } from '../ui/create-target'; +import { HiveLink } from '../ui/hive-link'; +import { PlusIcon } from '../ui/icon'; import { ProjectSelector } from './project-selector'; export enum Page { diff --git a/packages/web/app/src/components/layouts/target.tsx b/packages/web/app/src/components/layouts/target.tsx index da2e4abf1..5246e0284 100644 --- a/packages/web/app/src/components/layouts/target.tsx +++ b/packages/web/app/src/components/layouts/target.tsx @@ -2,8 +2,8 @@ import { ReactElement, ReactNode } from 'react'; import { LinkIcon } from 'lucide-react'; import { useQuery } from 'urql'; import { Button } from '@/components/ui/button'; +import { HiveLink } from '@/components/ui/hive-link'; import { UserMenu } from '@/components/ui/user-menu'; -import { HiveLink } from '@/components/v2/hive-link'; import { ConnectSchemaModal } from '@/components/v2/modals'; import { Tabs } from '@/components/v2/tabs'; import { graphql } from '@/gql'; diff --git a/packages/web/app/src/components/organization/settings/oidc-integration-section.tsx b/packages/web/app/src/components/organization/settings/oidc-integration-section.tsx index 2630be697..9ae97d8a6 100644 --- a/packages/web/app/src/components/organization/settings/oidc-integration-section.tsx +++ b/packages/web/app/src/components/organization/settings/oidc-integration-section.tsx @@ -12,13 +12,13 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog'; +import { AlertTriangleIcon, KeyIcon } from '@/components/ui/icon'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Separator } from '@/components/ui/separator'; import { Switch } from '@/components/ui/switch'; import { useToast } from '@/components/ui/use-toast'; import { Tag } from '@/components/v2'; -import { AlertTriangleIcon, KeyIcon } from '@/components/v2/icon'; import { env } from '@/env/frontend'; import { DocumentType, FragmentType, graphql, useFragment } from '@/gql'; import { useClipboard } from '@/lib/hooks'; diff --git a/packages/web/app/src/components/target/explorer/common.tsx b/packages/web/app/src/components/target/explorer/common.tsx index ab8f2b0d8..e21066220 100644 --- a/packages/web/app/src/components/target/explorer/common.tsx +++ b/packages/web/app/src/components/target/explorer/common.tsx @@ -1,8 +1,8 @@ import React, { ReactElement, ReactNode, useMemo } from 'react'; import { clsx } from 'clsx'; +import { PulseIcon, UsersIcon } from '@/components/ui/icon'; import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import { PulseIcon, UsersIcon } from '@/components/v2/icon'; import { Markdown } from '@/components/v2/markdown'; import { FragmentType, graphql, useFragment } from '@/gql'; import { formatNumber, toDecimal } from '@/lib/hooks'; diff --git a/packages/web/app/src/components/target/explorer/super-graph-metadata.tsx b/packages/web/app/src/components/target/explorer/super-graph-metadata.tsx index 804a14b72..1b92d1d38 100644 --- a/packages/web/app/src/components/target/explorer/super-graph-metadata.tsx +++ b/packages/web/app/src/components/target/explorer/super-graph-metadata.tsx @@ -1,6 +1,6 @@ import { useMemo } from 'react'; +import { PackageIcon } from '@/components/ui/icon'; import { Tooltip } from '@/components/v2'; -import { PackageIcon } from '@/components/v2/icon'; import { FragmentType, graphql, useFragment } from '@/gql'; import { TooltipProvider } from '@radix-ui/react-tooltip'; import { Link } from '@tanstack/react-router'; diff --git a/packages/web/app/src/components/target/history/errors-and-changes.tsx b/packages/web/app/src/components/target/history/errors-and-changes.tsx index 8c3bc0910..a0f013d7d 100644 --- a/packages/web/app/src/components/target/history/errors-and-changes.tsx +++ b/packages/web/app/src/components/target/history/errors-and-changes.tsx @@ -13,6 +13,7 @@ import { } from '@/components/ui/accordion'; import { Button } from '@/components/ui/button'; import { Heading } from '@/components/ui/heading'; +import { PulseIcon } from '@/components/ui/icon'; import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { Table, @@ -24,7 +25,6 @@ import { TableRow, } from '@/components/ui/table'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import { PulseIcon } from '@/components/v2/icon'; import { FragmentType, graphql, useFragment } from '@/gql'; import { CriticalityLevel } from '@/gql/graphql'; import { CheckCircledIcon, InfoCircledIcon } from '@radix-ui/react-icons'; diff --git a/packages/web/app/src/components/target/settings/cdn-access-tokens.tsx b/packages/web/app/src/components/target/settings/cdn-access-tokens.tsx index 39348bec2..505a7ab61 100644 --- a/packages/web/app/src/components/target/settings/cdn-access-tokens.tsx +++ b/packages/web/app/src/components/target/settings/cdn-access-tokens.tsx @@ -6,9 +6,9 @@ import { z } from 'zod'; import { Button } from '@/components/ui/button'; import { CardDescription } from '@/components/ui/card'; import { Heading } from '@/components/ui/heading'; +import { AlertTriangleIcon, TrashIcon } from '@/components/ui/icon'; import { SubPageLayout, SubPageLayoutHeader } from '@/components/ui/page-content-layout'; import { DocsLink, Input, Modal, Table, Tag, TBody, Td, TimeAgo, Tr } from '@/components/v2'; -import { AlertTriangleIcon, TrashIcon } from '@/components/v2/icon'; import { InlineCode } from '@/components/v2/inline-code'; import { FragmentType, graphql, useFragment } from '@/gql'; import { TargetAccessScope } from '@/gql/graphql'; diff --git a/packages/web/app/src/components/ui/activities.tsx b/packages/web/app/src/components/ui/activities.tsx index cadbda30b..fa37cebd1 100644 --- a/packages/web/app/src/components/ui/activities.tsx +++ b/packages/web/app/src/components/ui/activities.tsx @@ -1,6 +1,6 @@ import { ReactElement, ReactNode } from 'react'; import { useQuery } from 'urql'; -import { EditIcon, PlusIcon, TrashIcon, UserPlusMinusIcon } from '@/components/v2/icon'; +import { EditIcon, PlusIcon, TrashIcon, UserPlusMinusIcon } from '@/components/ui/icon'; import { DocumentType, graphql, useFragment } from '@/gql'; import { Link } from './link'; import { Subtitle, Title } from './page'; diff --git a/packages/web/app/src/components/ui/create-target.tsx b/packages/web/app/src/components/ui/create-target.tsx new file mode 100644 index 000000000..aae39401d --- /dev/null +++ b/packages/web/app/src/components/ui/create-target.tsx @@ -0,0 +1,182 @@ +import { ReactElement } from 'react'; +import { useForm, UseFormReturn } from 'react-hook-form'; +import { useMutation } from 'urql'; +import { z } from 'zod'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { useToast } from '@/components/ui/use-toast'; +import { graphql } from '@/gql'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useRouter } from '@tanstack/react-router'; + +export const CreateTarget_CreateTargetMutation = graphql(` + mutation CreateTarget_CreateTarget($input: CreateTargetInput!) { + createTarget(input: $input) { + ok { + selector { + organization + project + target + } + createdTarget { + id + cleanId + name + } + } + error { + message + inputErrors { + name + } + } + } + } +`); + +const formSchema = z.object({ + targetName: z + .string({ + required_error: 'Target name is required', + }) + .min(2, { + message: 'Target name must be at least 2 characters long', + }) + .max(50, { + message: 'Target name must be at most 50 characters long', + }) + .regex( + /^([a-z]|[0-9]|\s|\.|,|_|-|\/|&)+$/i, + 'Target name restricted to alphanumerical characters, spaces and . , _ - / &', + ), +}); + +type CreateTargetModalProps = { + isOpen: boolean; + toggleModalOpen: () => void; + organizationId: string; + projectId: string; +}; + +export const CreateTargetModal = ({ ...props }: CreateTargetModalProps): ReactElement => { + const { organizationId, projectId } = props; + const [_, mutate] = useMutation(CreateTarget_CreateTargetMutation); + const router = useRouter(); + const { toast } = useToast(); + + const form = useForm>({ + mode: 'onChange', + resolver: zodResolver(formSchema), + defaultValues: { + targetName: '', + }, + }); + + async function onSubmit(values: z.infer) { + const { data, error } = await mutate({ + input: { + project: props.projectId, + organization: props.organizationId, + name: values.targetName, + }, + }); + + if (data?.createTarget.ok) { + props.toggleModalOpen(); + void router.navigate({ + to: '/$organizationId/$projectId/$targetId', + params: { + organizationId, + projectId, + targetId: data.createTarget.ok.createdTarget.cleanId, + }, + }); + toast({ + variant: 'default', + title: 'Target created', + description: `Your target "${data.createTarget.ok.createdTarget.name}" has been created`, + }); + } else if (data?.createTarget.error?.inputErrors.name) { + form.setError('targetName', { + message: data?.createTarget.error?.inputErrors.name, + }); + } else { + toast({ + variant: 'destructive', + title: 'Failed to create target', + description: error?.message || data?.createTarget.error?.message, + }); + } + } + + return ( + + ); +}; + +type CreateTargetModalContentProps = { + isOpen: boolean; + toggleModalOpen: () => void; + onSubmit: (values: z.infer) => void | Promise; + form: UseFormReturn>; +}; + +export const CreateTargetModalContent = ({ + ...props +}: CreateTargetModalContentProps): ReactElement => { + return ( + + +
+ + + Create a new target + + A project is built on top of Targets, which are just your environments. + + +
+ { + return ( + + + + + + + ); + }} + /> +
+ + + +
+ +
+
+ ); +}; diff --git a/packages/web/app/src/components/v2/hive-link.tsx b/packages/web/app/src/components/ui/hive-link.tsx similarity index 86% rename from packages/web/app/src/components/v2/hive-link.tsx rename to packages/web/app/src/components/ui/hive-link.tsx index 0f1967d29..ec6118f7b 100644 --- a/packages/web/app/src/components/v2/hive-link.tsx +++ b/packages/web/app/src/components/ui/hive-link.tsx @@ -1,7 +1,7 @@ import { ReactElement } from 'react'; import clsx from 'clsx'; -import { HiveLogo } from '@/components/v2/icon'; import { Link } from '@tanstack/react-router'; +import { HiveLogo } from './icon'; export const HiveLink = ({ className }: { className?: string }): ReactElement => { return ( diff --git a/packages/web/app/src/components/v2/icon.tsx b/packages/web/app/src/components/ui/icon.tsx similarity index 100% rename from packages/web/app/src/components/v2/icon.tsx rename to packages/web/app/src/components/ui/icon.tsx diff --git a/packages/web/app/src/components/ui/input.tsx b/packages/web/app/src/components/ui/input.tsx index 592dcb3d1..981806ea3 100644 --- a/packages/web/app/src/components/ui/input.tsx +++ b/packages/web/app/src/components/ui/input.tsx @@ -9,7 +9,7 @@ const Input = React.forwardRef( { const post = useNotifications(); diff --git a/packages/web/app/src/components/v2/modal.tsx b/packages/web/app/src/components/v2/modal.tsx index 661130f68..63fb4636a 100644 --- a/packages/web/app/src/components/v2/modal.tsx +++ b/packages/web/app/src/components/v2/modal.tsx @@ -1,6 +1,6 @@ import { createContext, ReactElement, ReactNode, useState } from 'react'; import clsx from 'clsx'; -import { XIcon } from '@/components/v2/icon'; +import { XIcon } from '@/components/ui/icon'; import { Close, Content, diff --git a/packages/web/app/src/components/v2/modals/create-target.tsx b/packages/web/app/src/components/v2/modals/create-target.tsx deleted file mode 100644 index 8704d29ab..000000000 --- a/packages/web/app/src/components/v2/modals/create-target.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { ReactElement } from 'react'; -import { useFormik } from 'formik'; -import { useMutation } from 'urql'; -import * as Yup from 'yup'; -import { Button } from '@/components/ui/button'; -import { Heading } from '@/components/ui/heading'; -import { Input, Modal } from '@/components/v2'; -import { graphql } from '@/gql'; -import { useRouter } from '@tanstack/react-router'; - -export const CreateTarget_CreateTargetMutation = graphql(` - mutation CreateTarget_CreateTarget($input: CreateTargetInput!) { - createTarget(input: $input) { - ok { - selector { - organization - project - target - } - createdTarget { - id - cleanId - name - } - } - error { - message - inputErrors { - name - } - } - } - } -`); - -export const CreateTargetModal = (props: { - isOpen: boolean; - toggleModalOpen: () => void; - organizationId: string; - projectId: string; -}): ReactElement => { - const { isOpen, toggleModalOpen } = props; - const [mutation, mutate] = useMutation(CreateTarget_CreateTargetMutation); - const router = useRouter(); - - const { handleSubmit, values, handleChange, handleBlur, isSubmitting, errors, touched } = - useFormik({ - initialValues: { name: '' }, - validationSchema: Yup.object().shape({ - name: Yup.string().required('Target name is required'), - }), - async onSubmit(values) { - const { projectId, organizationId } = props; - const { data } = await mutate({ - input: { - project: projectId, - organization: organizationId, - name: values.name, - }, - }); - if (data?.createTarget.ok) { - toggleModalOpen(); - const targetId = data.createTarget.ok.createdTarget.cleanId; - void router.navigate({ - to: '/$organizationId/$projectId/$targetId', - params: { - organizationId, - projectId, - targetId, - }, - }); - } - }, - }); - - return ( - -
- Create a new target -

- A project is build on top of Targets, which are just your environments. -

- - {touched.name && (errors.name || mutation.error) && ( -
{errors.name || mutation.error?.message}
- )} - {mutation.data?.createTarget.error?.inputErrors.name && ( -
- {mutation.data.createTarget.error.inputErrors.name} -
- )} -
- - -
-
-
- ); -}; diff --git a/packages/web/app/src/components/v2/modals/index.ts b/packages/web/app/src/components/v2/modals/index.ts index 06c779981..88257e223 100644 --- a/packages/web/app/src/components/v2/modals/index.ts +++ b/packages/web/app/src/components/v2/modals/index.ts @@ -2,7 +2,6 @@ export { ChangePermissionsModal } from './change-permissions'; export { ConnectSchemaModal } from './connect-schema'; export { CreateAccessTokenModal } from './create-access-token'; export { CreateProjectModal } from './create-project'; -export { CreateTargetModal } from './create-target'; export { DeleteOrganizationModal } from './delete-organization'; export { DeleteProjectModal } from './delete-project'; export { DeleteTargetModal } from './delete-target'; diff --git a/packages/web/app/src/components/v2/modals/transfer-organization-ownership.tsx b/packages/web/app/src/components/v2/modals/transfer-organization-ownership.tsx index 32c0cb8ea..6ed14f4f2 100644 --- a/packages/web/app/src/components/v2/modals/transfer-organization-ownership.tsx +++ b/packages/web/app/src/components/v2/modals/transfer-organization-ownership.tsx @@ -5,8 +5,8 @@ import { useMutation, useQuery } from 'urql'; import * as Yup from 'yup'; import { Button } from '@/components/ui/button'; import { Heading } from '@/components/ui/heading'; +import { ArrowDownIcon, CheckIcon } from '@/components/ui/icon'; import { Input, Modal } from '@/components/v2'; -import { ArrowDownIcon, CheckIcon } from '@/components/v2/icon'; import { FragmentType, graphql, useFragment } from '@/gql'; import { useNotifications } from '@/lib/hooks'; import { Combobox as HeadlessCombobox, Transition as HeadlessTransition } from '@headlessui/react'; diff --git a/packages/web/app/src/components/v2/select.tsx b/packages/web/app/src/components/v2/select.tsx index 14ae010ae..a36b56ebd 100644 --- a/packages/web/app/src/components/v2/select.tsx +++ b/packages/web/app/src/components/v2/select.tsx @@ -1,6 +1,6 @@ import { ComponentProps, ReactElement } from 'react'; import clsx from 'clsx'; -import { ArrowDownIcon } from '@/components/v2/icon'; +import { ArrowDownIcon } from '@/components/ui/icon'; export function Select({ options, diff --git a/packages/web/app/src/lib/urql-cache.ts b/packages/web/app/src/lib/urql-cache.ts index 3ecc36b30..6e919ca80 100644 --- a/packages/web/app/src/lib/urql-cache.ts +++ b/packages/web/app/src/lib/urql-cache.ts @@ -8,9 +8,9 @@ import type { DeleteChannelsButton_DeleteChannelsMutation } from '@/components/p import type { CreateOperationMutationType } from '@/components/target/laboratory/create-operation-modal'; import type { DeleteCollectionMutationType } from '@/components/target/laboratory/delete-collection-modal'; import type { DeleteOperationMutationType } from '@/components/target/laboratory/delete-operation-modal'; +import { CreateTarget_CreateTargetMutation } from '@/components/ui/create-target'; import type { CreateAccessToken_CreateTokenMutation } from '@/components/v2/modals/create-access-token'; import type { CreateProjectMutation } from '@/components/v2/modals/create-project'; -import type { CreateTarget_CreateTargetMutation } from '@/components/v2/modals/create-target'; import type { DeleteOrganizationDocument } from '@/components/v2/modals/delete-organization'; import { type DeleteProjectMutation } from '@/components/v2/modals/delete-project'; import { type DeleteTargetMutation } from '@/components/v2/modals/delete-target'; diff --git a/packages/web/app/src/pages/auth.tsx b/packages/web/app/src/pages/auth.tsx index 22f98546c..a66d0b738 100644 --- a/packages/web/app/src/pages/auth.tsx +++ b/packages/web/app/src/pages/auth.tsx @@ -1,8 +1,8 @@ import { BookIcon } from 'lucide-react'; import { SiGithub } from 'react-icons/si'; import { useSessionContext } from 'supertokens-auth-react/recipe/session'; +import { HiveLogo } from '@/components/ui/icon'; import { Meta } from '@/components/ui/meta'; -import { HiveLogo } from '@/components/v2/icon'; import { Outlet } from '@tanstack/react-router'; function ExternalLink(props: { href: string; children: React.ReactNode }) { diff --git a/packages/web/app/src/pages/dev.tsx b/packages/web/app/src/pages/dev.tsx index 6bbe6f394..2f2afd4d0 100644 --- a/packages/web/app/src/pages/dev.tsx +++ b/packages/web/app/src/pages/dev.tsx @@ -1,5 +1,5 @@ import { GraphiQL } from 'graphiql'; -import { HiveLogo } from '@/components/v2/icon'; +import { HiveLogo } from '@/components/ui/icon'; import { createGraphiQLFetcher } from '@graphiql/toolkit'; import 'graphiql/graphiql.css'; import { Helmet } from 'react-helmet-async'; diff --git a/packages/web/app/src/pages/index.tsx b/packages/web/app/src/pages/index.tsx index a2aec427f..1640bbadc 100644 --- a/packages/web/app/src/pages/index.tsx +++ b/packages/web/app/src/pages/index.tsx @@ -1,8 +1,8 @@ import { useEffect } from 'react'; import { useQuery } from 'urql'; +import { HiveLogo } from '@/components/ui/icon'; import { Meta } from '@/components/ui/meta'; import { QueryError } from '@/components/ui/query-error'; -import { HiveLogo } from '@/components/v2/icon'; import { graphql } from '@/gql'; import { useLastVisitedOrganizationReader, diff --git a/packages/web/app/src/pages/organization-join.tsx b/packages/web/app/src/pages/organization-join.tsx index 6206ef2b5..d84e01e3d 100644 --- a/packages/web/app/src/pages/organization-join.tsx +++ b/packages/web/app/src/pages/organization-join.tsx @@ -4,10 +4,10 @@ import { useMutation, useQuery } from 'urql'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; import { DottedBackground } from '@/components/ui/dotted-background'; +import { HiveLogo } from '@/components/ui/icon'; import { Meta } from '@/components/ui/meta'; import { useToast } from '@/components/ui/use-toast'; import { DataWrapper } from '@/components/v2/data-wrapper'; -import { HiveLogo } from '@/components/v2/icon'; import { graphql } from '@/gql'; import { Link, useRouter } from '@tanstack/react-router'; diff --git a/packages/web/app/src/pages/organization-new.tsx b/packages/web/app/src/pages/organization-new.tsx index 435eb4d4b..9ecebec9a 100644 --- a/packages/web/app/src/pages/organization-new.tsx +++ b/packages/web/app/src/pages/organization-new.tsx @@ -14,11 +14,11 @@ import { } from '@/components/ui/card'; import { DottedBackground } from '@/components/ui/dotted-background'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form'; +import { HiveLogo } from '@/components/ui/icon'; import { Input } from '@/components/ui/input'; import { Meta } from '@/components/ui/meta'; import { Spinner } from '@/components/ui/spinner'; import { useToast } from '@/components/ui/use-toast'; -import { HiveLogo } from '@/components/v2/icon'; import { graphql } from '@/gql'; import { zodResolver } from '@hookform/resolvers/zod'; import { Link, useRouter } from '@tanstack/react-router'; diff --git a/packages/web/app/src/pages/organization-settings.tsx b/packages/web/app/src/pages/organization-settings.tsx index 5d3b48112..56ff6fbb6 100644 --- a/packages/web/app/src/pages/organization-settings.tsx +++ b/packages/web/app/src/pages/organization-settings.tsx @@ -15,12 +15,12 @@ import { } from '@/components/ui/card'; import { DocsLink } from '@/components/ui/docs-note'; import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form'; +import { GitHubIcon, SlackIcon } from '@/components/ui/icon'; import { Input } from '@/components/ui/input'; 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 { GitHubIcon, SlackIcon } from '@/components/v2/icon'; import { DeleteOrganizationModal, TransferOrganizationOwnershipModal, diff --git a/packages/web/app/src/pages/project-settings.tsx b/packages/web/app/src/pages/project-settings.tsx index be52c46c5..396f1c85a 100644 --- a/packages/web/app/src/pages/project-settings.tsx +++ b/packages/web/app/src/pages/project-settings.tsx @@ -17,11 +17,11 @@ import { CardTitle, } from '@/components/ui/card'; import { DocsLink } from '@/components/ui/docs-note'; +import { HiveLogo } from '@/components/ui/icon'; 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 { HiveLogo } from '@/components/v2/icon'; import { Input } from '@/components/v2/input'; import { DeleteProjectModal } from '@/components/v2/modals'; import { graphql, useFragment } from '@/gql'; diff --git a/packages/web/app/src/pages/target-checks-single.tsx b/packages/web/app/src/pages/target-checks-single.tsx index d1b81126d..71d0515f2 100644 --- a/packages/web/app/src/pages/target-checks-single.tsx +++ b/packages/web/app/src/pages/target-checks-single.tsx @@ -13,6 +13,7 @@ import { Button } from '@/components/ui/button'; import { DocsLink } from '@/components/ui/docs-note'; import { EmptyList } from '@/components/ui/empty-list'; import { Heading } from '@/components/ui/heading'; +import { AlertTriangleIcon, DiffIcon } from '@/components/ui/icon'; import { Meta } from '@/components/ui/meta'; import { Subtitle, Title } from '@/components/ui/page'; import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; @@ -23,7 +24,6 @@ import { Textarea } from '@/components/ui/textarea'; import { TimeAgo } from '@/components/ui/time-ago'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { DiffEditor } from '@/components/v2/diff-editor'; -import { AlertTriangleIcon, DiffIcon } from '@/components/v2/icon'; import { FragmentType, graphql, useFragment } from '@/gql'; import { CriticalityLevel, ProjectType } from '@/gql/graphql'; import { cn } from '@/lib/utils'; diff --git a/packages/web/app/src/pages/target-history-version.tsx b/packages/web/app/src/pages/target-history-version.tsx index 7b87af575..d5f400b03 100644 --- a/packages/web/app/src/pages/target-history-version.tsx +++ b/packages/web/app/src/pages/target-history-version.tsx @@ -6,12 +6,12 @@ import { CompositionErrorsSection, NoGraphChanges, } from '@/components/target/history/errors-and-changes'; +import { DiffIcon } from '@/components/ui/icon'; import { Subtitle, Title } from '@/components/ui/page'; import { Spinner } from '@/components/ui/spinner'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { DiffEditor } from '@/components/v2'; -import { DiffIcon } from '@/components/v2/icon'; import { FragmentType, graphql, useFragment } from '@/gql'; import { CriticalityLevel, ProjectType } from '@/gql/graphql'; import { cn } from '@/lib/utils'; diff --git a/packages/web/app/src/pages/target-laboratory.tsx b/packages/web/app/src/pages/target-laboratory.tsx index 265ae7989..586dc1108 100644 --- a/packages/web/app/src/pages/target-laboratory.tsx +++ b/packages/web/app/src/pages/target-laboratory.tsx @@ -29,12 +29,12 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; +import { PlusIcon, SaveIcon, ShareIcon } from '@/components/ui/icon'; import { Link } from '@/components/ui/link'; import { Meta } from '@/components/ui/meta'; import { Subtitle, Title } from '@/components/ui/page'; import { QueryError } from '@/components/ui/query-error'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; -import { PlusIcon, SaveIcon, ShareIcon } from '@/components/v2/icon'; import { ToggleGroup, ToggleGroupItem } from '@/components/v2/toggle-group'; import { graphql } from '@/gql'; import { TargetAccessScope } from '@/gql/graphql'; diff --git a/packages/web/app/src/stories/create-target.stories.tsx b/packages/web/app/src/stories/create-target.stories.tsx new file mode 100644 index 000000000..e43e583d6 --- /dev/null +++ b/packages/web/app/src/stories/create-target.stories.tsx @@ -0,0 +1,61 @@ +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { Button } from '@/components/ui/button'; +import { CreateTargetModalContent } from '@/components/ui/create-target'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Modals/Create Target Modal', + component: CreateTargetModalContent, +}; + +export default meta; +type Story = StoryObj; + +const formSchema = z.object({ + targetName: z + .string({ + required_error: 'Target name is required', + }) + .min(2, { + message: 'Target name must be at least 2 characters long', + }) + .max(50, { + message: 'Target name must be at most 50 characters long', + }) + .regex( + /^([a-z]|[0-9]|\s|\.|,|_|-|\/|&)+$/i, + 'Target name restricted to alphanumerical characters, spaces and . , _ - / &', + ), +}); + +export const Default: Story = { + render: () => { + const form = useForm>({ + mode: 'onChange', + resolver: zodResolver(formSchema), + defaultValues: { + targetName: '', + }, + }); + const [openModal, setOpenModal] = useState(false); + const toggleModalOpen = () => setOpenModal(!openModal); + + return ( + <> + + {openModal && ( + console.log('Submit')} + toggleModalOpen={toggleModalOpen} + key="create-target-modal" + /> + )} + + ); + }, +};