diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history.tsx deleted file mode 100644 index 2744deb3f..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import * as React from 'react'; -import 'twin.macro'; -import { useRouteSelector } from '@/lib/hooks/use-route-selector'; -import { Page } from '@/components/common'; -import { TargetView } from '@/components/target/View'; -import { Versions } from '@/components/target/history/Versions'; - -const HistoryView: React.FC = () => { - const router = useRouteSelector(); - - return ( - - - - - - - - ); -}; - -export default function TargetHistory() { - return {() => }; -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history/[versionId].tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history/[versionId].tsx deleted file mode 100644 index b57b3df10..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/history/[versionId].tsx +++ /dev/null @@ -1,129 +0,0 @@ -import * as React from 'react'; -import tw, { styled } from 'twin.macro'; -import formatDate from 'date-fns/format'; -import { useQuery } from 'urql'; -import { Tooltip } from '@chakra-ui/react'; -import { useRouteSelector } from '@/lib/hooks/use-route-selector'; -import { CompareDocument, OrganizationFieldsFragment } from '@/graphql'; -import { Page } from '@/components/common'; -import { TextToggle } from '@/components/common/Toogle'; -import { DataWrapper } from '@/components/common/DataWrapper'; -import { TargetView } from '@/components/target/View'; -import { Compare, View } from '@/components/target/history/Compare'; -import { MarkAsValid } from '@/components/target/history/MarkAsValid'; -import { useTargetAccess, TargetAccessScope } from '@/lib/access/target'; - -const Value = tw.div`text-base text-gray-900 dark:text-white`; -const ValueLabel = tw.div`text-xs text-gray-500 dark:text-gray-400`; -const Status = styled.span(({ valid }: { valid?: boolean }) => [ - tw`mx-auto my-2 block w-2 h-2 rounded-full`, - valid ? tw`bg-emerald-400` : tw`bg-red-400`, -]); - -const VersionView: React.FC<{ - organization: OrganizationFieldsFragment; -}> = ({ organization }) => { - const router = useRouteSelector(); - const [view, setView] = React.useState(View.Text); - const [query] = useQuery({ - query: CompareDocument, - variables: { - organization: router.organizationId, - project: router.projectId, - target: router.targetId, - version: router.versionId, - }, - }); - const canModifyState = useTargetAccess({ - scope: TargetAccessScope.RegistryWrite, - member: organization.me, - redirect: false, - }); - - const version = query.data?.schemaVersion; - - return ( - - {() => ( - - {canModifyState && } - - > - } - > - - - - {formatDate(new Date(version.date), 'yyyy-MM-dd HH:mm')} - Published - - - - - {version.commit.commit} - Commit - - - - - {version.commit.author} - Author - - - - {version.commit.service && ( - - - {version.commit.service} - Service - - - )} - {version.valid && ( - - - - - - Status - - - )} - - - - - - - )} - - ); -}; - -export default function TargetHistory() { - return {({ organization }) => }; -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/index.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/index.tsx deleted file mode 100644 index 73e8d755f..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/index.tsx +++ /dev/null @@ -1,465 +0,0 @@ -import React, { useCallback } from 'react'; -import tw from 'twin.macro'; -import { - useDisclosure, - Modal, - Button, - ModalOverlay, - ModalContent, - ModalHeader, - ModalBody, - Code, - ModalFooter, - ModalCloseButton, - Alert, - AlertTitle, - AlertDescription, - Spinner, - Link, - InputGroup, - Input, - InputRightElement, - IconButton, - useColorModeValue, - Tooltip, - Editable, - EditablePreview, - EditableInput, -} from '@chakra-ui/react'; -import { VscPlug, VscClose, VscSync } from 'react-icons/vsc'; -import { useQuery, useMutation } from 'urql'; -import { useDebouncedCallback } from 'use-debounce'; -import { - SchemasDocument, - SchemasQuery, - ProjectFieldsFragment, - ProjectType, - TargetFieldsFragment, - OrganizationFieldsFragment, - CreateCdnTokenDocument, - SchemaSyncCdnDocument, - UpdateSchemaServiceNameDocument, -} from '@/graphql'; -import { Description, Page } from '@/components/common'; -import { DataWrapper } from '@/components/common/DataWrapper'; -import { GraphQLSDLBlock } from '@/components/common/GraphQLSDLBlock'; -import { TargetView } from '@/components/target/View'; -import { NoSchemasYet } from '@/components/target/NoSchemasYet'; -import { CopyValue } from '@/components/common/CopyValue'; -import { useTargetAccess, TargetAccessScope } from '@/lib/access/target'; - -const Block = tw.div`mb-8`; - -const SchemaServiceName: React.FC<{ - version: string; - schema: SchemasQuery['target']['latestSchemaVersion']['schemas']['nodes'][0]; - target: SchemasQuery['target']; - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ target, project, organization, schema, version }) => { - const [mutation, mutate] = useMutation(UpdateSchemaServiceNameDocument); - const hasAccess = useTargetAccess({ - scope: TargetAccessScope.RegistryWrite, - member: organization.me, - redirect: false, - }); - - const submit = useCallback( - (newName: string) => { - if (schema.service === newName) { - return; - } - - if (newName.trim().length === 0) { - return; - } - - mutate({ - input: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - version, - name: schema.service!, - newName, - }, - }); - }, - [mutate] - ); - - if ((project.type !== ProjectType.Federation && project.type !== ProjectType.Stitching) || !hasAccess) { - return <>{schema.service}>; - } - - return ( - - - - - ); -}; - -const Schemas: React.FC<{ - organization: OrganizationFieldsFragment; - project: ProjectFieldsFragment; - target: SchemasQuery['target']; - filterService?: string; -}> = ({ organization, project, target, filterService }) => { - const schemas = target.latestSchemaVersion?.schemas.nodes ?? []; - - if (!schemas.length) { - return ; - } - - if (project.type === ProjectType.Single) { - return ; - } - - return ( - <> - {schemas - .filter(schema => { - if (filterService && schema.service) { - return schema.service.toLowerCase().includes(filterService.toLowerCase()); - } - - return true; - }) - .map(schema => ( - - - } - /> - - ))} - > - ); -}; - -const SchemaView: React.FC<{ - organization: OrganizationFieldsFragment; - project: ProjectFieldsFragment; - target: TargetFieldsFragment; - filterService?: string; -}> = ({ organization, project, target, filterService }) => { - const [query] = useQuery({ - query: SchemasDocument, - variables: { - selector: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - }, - }, - requestPolicy: 'cache-and-network', - }); - - return ( - - {() => ( - - )} - - ); -}; - -const ConnectSchemaModal: React.FC<{ - target: TargetFieldsFragment; - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; - onClose(): void; - onOpen(): void; - isOpen: boolean; -}> = ({ target, project, organization, onClose, isOpen }) => { - const [generating, setGenerating] = React.useState(true); - const [mutation, mutate] = useMutation(CreateCdnTokenDocument); - - React.useEffect(() => { - if (!isOpen) { - setGenerating(true); - return; - } - - mutate({ - selector: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - }, - }).then(() => { - setTimeout(() => { - setGenerating(false); - }, 2000); - }); - }, [isOpen, setGenerating, mutate]); - - const description = `With high-availability and multi-zone CDN service based on - Cloudflare, Hive allows you to access ${ - project.type === ProjectType.Federation - ? 'the supergraph' - : project.type === ProjectType.Stitching - ? 'the list of services' - : 'the schema' - } of your API, - through a secured external service, that's always up regardless of - Hive.`; - - const generatingDescription = `Hive is now generating an authentication token and an URL you can use to fetch your ${ - project.type === ProjectType.Federation - ? 'supergraph schema' - : project.type === ProjectType.Stitching - ? 'services' - : 'schema' - }.`; - - return ( - - - - Connect to Hive - - - {description} - - {generating && ( - - - - Generating access... - - {generatingDescription} - - )} - - {!generating && mutation.data && ( - <> - You can use the following endpoint: - - To authenticate, use the following HTTP headers: - X-Hive-CDN-Key: {mutation.data.createCdnToken.token} - {project.type === ProjectType.Federation && ( - - Read the{' '} - - "Using the Registry with a Apollo Gateway" - {' '} - chapter in our documentation. - - )} - {project.type === ProjectType.Stitching && ( - - Read the{' '} - - "Using the Registry when Stitching" - {' '} - chapter in our documentation. - - )} - {project.type === ProjectType.Single && ( - - Read the{' '} - - "Using the Registry with any tool" - {' '} - chapter in our documentation. - - )} - > - )} - - - - Close - - - - - ); -}; - -const ConnectSchemaButton: React.FC<{ - target: TargetFieldsFragment; - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ target, project, organization }) => { - const { onClose, onOpen, isOpen } = useDisclosure(); - const color = useColorModeValue('#fff', '#000'); - - return ( - <> - }> - Connect - - - > - ); -}; - -const SyncSchemaButton: React.FC<{ - target: TargetFieldsFragment; - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ target, project, organization }) => { - const color = useColorModeValue('#fff', '#000'); - const [status, setStatus] = React.useState<'idle' | 'error' | 'success'>('idle'); - const [mutation, mutate] = useMutation(SchemaSyncCdnDocument); - const hasAccess = useTargetAccess({ - scope: TargetAccessScope.RegistryWrite, - member: organization.me, - redirect: false, - }); - - const sync = useCallback(() => { - mutate({ - input: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - }, - }).then(result => { - if (result.error) { - setStatus('error'); - } else { - setStatus(result.data?.schemaSyncCDN.__typename === 'SchemaSyncCDNError' ? 'error' : 'success'); - } - setTimeout(() => { - setStatus('idle'); - }, 5000); - }); - }, [mutate, setStatus]); - - if (!hasAccess || !target.hasSchema) { - return null; - } - - return ( - - } - > - {status === 'idle' ? 'Update CDN' : status === 'error' ? 'Failed to synchronize' : 'CDN is up to date'} - - - ); -}; - -function TargetSchemaInner({ - organization, - project, - target, -}: { - organization: OrganizationFieldsFragment; - project: ProjectFieldsFragment; - target: TargetFieldsFragment; -}) { - const [filterService, setFilterService] = React.useState(null); - const [term, setTerm] = React.useState(null); - const debouncedFilter = useDebouncedCallback((value: string) => { - setFilterService(value); - }, 500); - const handleChange = React.useCallback( - event => { - debouncedFilter(event.target.value); - setTerm(event.target.value); - }, - [debouncedFilter, setTerm] - ); - const reset = React.useCallback(() => { - setFilterService(''); - setTerm(''); - }, [setFilterService]); - - const isDistributed = project.type === ProjectType.Federation || project.type === ProjectType.Stitching; - - return ( - - {isDistributed && ( - { - event.preventDefault(); - }} - > - - - - } /> - - - - )} - - - > - } - > - - - ); -} - -export default function TargetSchema() { - return ( - - {({ organization, project, target }) => ( - - )} - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/lab.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/lab.tsx deleted file mode 100644 index e6a73996e..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/lab.tsx +++ /dev/null @@ -1,89 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ - -import 'graphiql/graphiql.css'; -import 'twin.macro'; - -import { Page } from '@/components/common'; -import { TargetView } from '@/components/target/View'; -import { Button, useDisclosure, useColorModeValue } from '@chakra-ui/react'; -import { VscPlug, VscSettings } from 'react-icons/vsc'; -import { ConnectLabModal } from '@/components/lab/ConnectLabScreen'; -import { CustomizeLabModal } from '@/components/lab/CustomizeLabScreen'; -import { createGraphiQLFetcher } from '@graphiql/toolkit'; -import React from 'react'; -import type { GraphiQL as GraphiQLType } from 'graphiql'; -import { Logo } from '@/components/common/Logo'; -import { NoSchemasYet } from '@/components/target/NoSchemasYet'; - -const GraphiQL: typeof GraphiQLType = process.browser - ? // eslint-disable-next-line @typescript-eslint/no-var-requires - require('graphiql').default - : null; - -export const ConnectLabTrigger: React.FC<{ endpoint: string }> = ({ endpoint }) => { - const { isOpen, onClose, onOpen: open } = useDisclosure(); - const color = useColorModeValue('#fff', '#000'); - - return ( - <> - }> - Connect - - - > - ); -}; - -// TODO: unused -export const CustomizeLabTrigger = () => { - const { isOpen, onClose, onOpen: open } = useDisclosure(); - - return ( - <> - }> - Customize - - - > - ); -}; - -const SchemaLabContent: React.FC<{ endpoint: string }> = ({ endpoint }) => { - return ( - <> - - - - - - - - > - ); -}; - -export default function SchemaLabPage() { - return ( - - {({ organization, project, target }) => { - const endpoint = `${window.location.origin}/api/lab/${organization.cleanId}/${project.cleanId}/${target.cleanId}`; - const noSchemas = target.latestSchemaVersion?.schemas.nodes?.length === 0; - - return ( - : null} - > - {GraphiQL ? noSchemas ? : : null} - - ); - }} - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/operations.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/operations.tsx deleted file mode 100644 index e7bac66eb..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/operations.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { useQuery } from 'urql'; - -import { Select, Stack } from '@chakra-ui/react'; -import { VscChevronDown } from 'react-icons/vsc'; -import { - HasCollectedOperationsDocument, - ProjectFieldsFragment, - TargetFieldsFragment, - OrganizationFieldsFragment, -} from '@/graphql'; -import { Page } from '@/components/common'; -import { DataWrapper } from '@/components/common/DataWrapper'; -import { TargetView } from '@/components/target/View'; -import { OperationsList } from '@/components/target/operations/List'; -import { OperationsStats } from '@/components/target/operations/Stats'; -import { EmptyList } from '@/components/common/EmptyList'; -import { OperationsFilterTrigger } from '@/components/target/operations/Filters'; -import { useRouteSelector } from '@/lib/hooks/use-route-selector'; -import { calculatePeriod, DATE_RANGE_OPTIONS, PeriodKey } from '@/components/common/TimeFilter'; - -const OperationsView: React.FC<{ - organization: OrganizationFieldsFragment; - project: ProjectFieldsFragment; - target: TargetFieldsFragment; -}> = ({ organization, project, target }) => { - const router = useRouteSelector(); - const selectedPeriod: PeriodKey = (router.query.period as PeriodKey) ?? '1d'; - const [selectedOperations, setSelectedOperations] = React.useState([]); - - const period = React.useMemo(() => calculatePeriod(selectedPeriod), [selectedPeriod]); - const updatePeriod = React.useCallback( - (ev: any) => { - router.update({ period: ev.target.value }); - }, - [router.update] - ); - - return ( - <> - - - - - - - } - size="sm" - > - {DATE_RANGE_OPTIONS.map(item => { - return ( - - {item.label} - - ); - })} - - - - - - - - - > - ); -}; - -const OperationsViewGate: React.FC<{ - organization: OrganizationFieldsFragment; - project: ProjectFieldsFragment; - target: TargetFieldsFragment; -}> = ({ organization, project, target }) => { - const [query] = useQuery({ - query: HasCollectedOperationsDocument, - variables: { - selector: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - }, - }, - }); - - return ( - - {result => { - if (!result.data.hasCollectedOperations) { - return ( - - ); - } - - return ; - }} - - ); -}; - -export default function TargetOperations() { - return ( - - {({ organization, project, target }) => ( - - - - )} - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/settings.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/settings.tsx deleted file mode 100644 index ce4a877c7..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/[targetId]/settings.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { useQuery } from 'urql'; -import { Settings } from '@/components/common/Settings'; -import { DataWrapper } from '@/components/common/DataWrapper'; -import { TargetView } from '@/components/target/View'; -import { NameSettings } from '@/components/target/settings/Name'; -import { DeleteSettings } from '@/components/target/settings/Delete'; -import { TokensSettings } from '@/components/target/settings/Tokens'; -import { ValidationSettings } from '@/components/target/settings/Validation'; -import { BaseSchemaSettings } from '@/components/target/settings/BaseSchema'; -import { - OrganizationFieldsFragment, - ProjectFieldsFragment, - TargetFieldsFragment, - TargetSettingsDocument, -} from '@/graphql'; -import { useTargetAccess, TargetAccessScope } from '@/lib/access/target'; - -const Inner: React.FC<{ - target: TargetFieldsFragment; - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ target, project, organization }) => { - const canAccess = useTargetAccess({ - scope: TargetAccessScope.Settings, - member: organization.me, - redirect: true, - }); - const canAccessTokens = useTargetAccess({ - scope: TargetAccessScope.TokensRead, - member: organization.me, - redirect: false, - }); - const [settings] = useQuery({ - query: TargetSettingsDocument, - variables: { - selector: { - organization: organization.cleanId, - project: project.cleanId, - target: target.cleanId, - }, - targetsSelector: { - organization: organization.cleanId, - project: project.cleanId, - }, - }, - }); - - if (!canAccess) { - return null; - } - - return ( - - {() => ( - - - {canAccessTokens && } - - - - - )} - - ); -}; - -export default function TargetSettingsPage() { - return ( - - {({ target, project, organization }) => } - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/alerts.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/alerts.tsx deleted file mode 100644 index 5d062b20d..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/alerts.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { OrganizationFieldsFragment } from '@/graphql'; -import { Page } from '@/components/common'; -import { ProjectView } from '@/components/project/View'; -import { useProjectAccess, ProjectAccessScope } from '@/lib/access/project'; -import { Alerts } from '@/components/project/alerts/Alerts'; -import { Channels } from '@/components/project/alerts/Channels'; - -const Gate: React.FC<{ - organization: OrganizationFieldsFragment; -}> = ({ organization }) => { - const canAccess = useProjectAccess({ - scope: ProjectAccessScope.Alerts, - member: organization.me, - redirect: true, - }); - - if (!canAccess) { - return null; - } - - return ( - - - - - - - ); -}; - -export default function ProjectSettingsPage() { - return {({ organization }) => }; -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/index.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/index.tsx deleted file mode 100644 index d7335725e..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/index.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import 'twin.macro'; -import { OrganizationFieldsFragment, ProjectFieldsFragment } from '@/graphql'; -import { Page } from '@/components/common'; -import { ProjectView } from '@/components/project/View'; -import { ProjectTargets } from '@/components/project/Targets'; -import { ProjectActivities } from '@/components/project/Activities'; -import { TargetCreatorTrigger } from '@/components/target/Creator'; -import { ProjectAccessScope, useProjectAccess } from '@/lib/access/project'; - -const Inner: React.FC<{ - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ project, organization }) => { - const canCreate = useProjectAccess({ - scope: ProjectAccessScope.Read, - member: organization.me, - }); - - return ( - }> - - - - - - - - - - ); -}; - -export default function ProjectPage() { - return ( - - {({ project, organization }) => } - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/operations-store.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/operations-store.tsx deleted file mode 100644 index c3eafe911..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/operations-store.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { Page } from '@/components/common'; -import { Dashboard } from '@/components/project/persisted-operations/Dashboard'; -import { ProjectView } from '@/components/project/View'; -import { ProjectFieldsFragment, OrganizationFieldsFragment } from '@/graphql'; -import { ProjectAccessScope, useProjectAccess } from '@/lib/access/project'; - -const Inner: React.FC<{ - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ project, organization }) => { - const canAccess = useProjectAccess({ - scope: ProjectAccessScope.OperationsStoreRead, - member: organization.me, - redirect: true, - }); - - if (!canAccess) { - return null; - } - - return ( - - - - ); -}; - -export default function PersistedOperationsPage() { - return ( - - {({ project, organization }) => } - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/[projectId]/settings.tsx b/packages/web/app/pages/v1/[orgId]/[projectId]/settings.tsx deleted file mode 100644 index f04d572cb..000000000 --- a/packages/web/app/pages/v1/[orgId]/[projectId]/settings.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { Settings } from '@/components/common/Settings'; -import { ProjectView } from '@/components/project/View'; -import { NameSettings } from '@/components/project/settings/Name'; -import { DeleteSettings } from '@/components/project/settings/Delete'; -import { GitRepositorySettings } from '@/components/project/settings/GitRepository'; -import { ProjectFieldsFragment, OrganizationFieldsFragment } from '@/graphql'; -import { useProjectAccess, ProjectAccessScope } from '@/lib/access/project'; - -const Inner: React.FC<{ - project: ProjectFieldsFragment; - organization: OrganizationFieldsFragment; -}> = ({ project, organization }) => { - const canAccess = useProjectAccess({ - scope: ProjectAccessScope.Settings, - member: organization.me, - redirect: true, - }); - - if (!canAccess) { - return null; - } - - return ( - - - - - - ); -}; - -export default function ProjectSettingsPage() { - return ( - - {({ project, organization }) => } - - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/index.tsx b/packages/web/app/pages/v1/[orgId]/index.tsx deleted file mode 100644 index 4b7ef5631..000000000 --- a/packages/web/app/pages/v1/[orgId]/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as React from 'react'; -import 'twin.macro'; -import { OrganizationFieldsFragment } from '@/graphql'; -import { Page } from '@/components/common'; -import { OrganizationView } from '@/components/organization/View'; -import { OrganizationProjects } from '@/components/organization/Projects'; -import { OrganizationActivities } from '@/components/organization/Activities'; -import { ProjectCreatorTrigger } from '@/components/project/Creator'; -import { OrganizationAccessScope, useOrganizationAccess } from '@/lib/access/organization'; - -const Inner: React.FC<{ organization: OrganizationFieldsFragment }> = ({ organization }) => { - const canCreate = useOrganizationAccess({ - scope: OrganizationAccessScope.Read, - member: organization?.me, - }); - - return ( - }> - - - - - - - - - - ); -}; - -export default function OrganizationPage() { - return ( - {({ organization }) => } - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/members.tsx b/packages/web/app/pages/v1/[orgId]/members.tsx deleted file mode 100644 index b40827640..000000000 --- a/packages/web/app/pages/v1/[orgId]/members.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { track } from '@/lib/mixpanel'; -import { useQuery, useMutation } from 'urql'; -import { Button, Checkbox, Table, Thead, Tbody, Tr, Th, Td, useDisclosure } from '@chakra-ui/react'; -import { FaGoogle, FaGithub, FaKey } from 'react-icons/fa'; -import { Page } from '@/components/common'; -import { CopyValue } from '@/components/common/CopyValue'; -import { OrganizationView } from '@/components/organization/View'; -import { MemberPermisssonsModal } from '@/components/organization/members/PermissionsModal'; -import { - OrganizationFieldsFragment, - OrganizationMembersDocument, - ResetInviteCodeDocument, - OrganizationMembersQuery, - DeleteOrganizationMembersDocument, - MemberFieldsFragment, - AuthProvider, -} from '@/graphql'; -import { OrganizationAccessScope, useOrganizationAccess } from '@/lib/access/organization'; -import { useNotifications } from '@/lib/hooks/use-notifications'; -import { useRouteSelector } from '@/lib/hooks/use-route-selector'; -import { DataWrapper } from '@/components/common/DataWrapper'; - -const Invitation: React.FC<{ - organization: OrganizationMembersQuery['organization']['organization']; -}> = ({ organization }) => { - const inviteUrl = `${window.location.origin}/join/${organization.inviteCode}`; - const router = useRouteSelector(); - const notify = useNotifications(); - const [mutation, mutate] = useMutation(ResetInviteCodeDocument); - - const generate = React.useCallback(() => { - track('GENERATE_NEW_INVITATION_LINK_ATTEMPT', { - organization: router.organizationId, - }); - mutate({ - selector: { - organization: router.organizationId, - }, - }).finally(() => { - notify('Generated new invitation link', 'info'); - }); - }, [mutate, notify]); - - return ( - - - - Reset - - - ); -}; - -const MemberRow: React.FC<{ - member: MemberFieldsFragment; - owner: MemberFieldsFragment; - organization: OrganizationFieldsFragment; - checked: string[]; - onCheck(id: string): void; -}> = ({ member, owner, checked, onCheck, organization }) => { - const isOwner = member.id === owner.id; - const isMe = member.id === organization.me.id; - const { isOpen, onOpen, onClose } = useDisclosure(); - - const canManage = !isOwner && !isMe; - - const provider = member.user.provider; - const providerIcon = - provider === AuthProvider.Google ? ( - - ) : provider === AuthProvider.Github ? ( - - ) : ( - - ); - - return ( - <> - - - - onCheck(member.id)} - /> - - {providerIcon} - {member.user.displayName} - {member.user.email} - - {canManage && ( - - Change permissions - - )} - - - > - ); -}; - -const MembersManager: React.FC<{ - organization: OrganizationFieldsFragment; -}> = ({ organization }) => { - const [query] = useQuery({ - query: OrganizationMembersDocument, - variables: { - selector: { - organization: organization.cleanId, - }, - }, - }); - const [checked, setChecked] = React.useState([]); - const onCheck = React.useCallback( - (id: string) => { - if (checked.includes(id)) { - setChecked(checked.filter(i => i !== id)); - } else { - setChecked(checked.concat(id)); - } - }, - [checked, setChecked] - ); - const [mutation, mutate] = useMutation(DeleteOrganizationMembersDocument); - const deleteMembers = React.useCallback(() => { - mutate({ - selector: { - organization: organization.cleanId, - users: checked, - }, - }).finally(() => { - setChecked([]); - }); - }, [mutate, checked, setChecked]); - - return ( - - {() => ( - - - - - - Delete - - - - - - - - - Name - Email - Permissions - - - - {query.data.organization.organization?.members.nodes.map(member => ( - - ))} - - - - )} - - ); -}; - -const Inner: React.FC<{ organization: OrganizationFieldsFragment }> = ({ organization }) => { - const canAccess = useOrganizationAccess({ - scope: OrganizationAccessScope.Members, - member: organization?.me, - redirect: true, - }); - - if (!canAccess) { - return null; - } - - return ( - - - - ); -}; - -export default function OrganizationSettingsPage() { - return ( - {({ organization }) => } - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/settings.tsx b/packages/web/app/pages/v1/[orgId]/settings.tsx deleted file mode 100644 index b1debcab1..000000000 --- a/packages/web/app/pages/v1/[orgId]/settings.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { OrganizationAccessScope, useOrganizationAccess } from '@/lib/access/organization'; -import { Settings } from '@/components/common/Settings'; -import { OrganizationView } from '@/components/organization/View'; -import { DeleteSettings } from '@/components/organization/settings/Delete'; -import { NameSettings } from '@/components/organization/settings/Name'; -import { IntegrationsSettings } from '@/components/organization/settings/Integrations'; -import { OrganizationFieldsFragment, OrganizationType } from '@/graphql'; - -const Inner: React.FC<{ organization: OrganizationFieldsFragment }> = ({ organization }) => { - const canAccess = useOrganizationAccess({ - scope: OrganizationAccessScope.Settings, - member: organization?.me, - redirect: true, - }); - const canAccessIntegrations = useOrganizationAccess({ - scope: OrganizationAccessScope.Integrations, - member: organization?.me, - redirect: false, - }); - - if (!canAccess) { - return null; - } - - const isRegular = organization.type === OrganizationType.Regular; - - return ( - - {isRegular && } - {canAccessIntegrations && } - {isRegular && } - - ); -}; - -export default function OrganizationSettingsPage() { - return ( - {({ organization }) => } - ); -} diff --git a/packages/web/app/pages/v1/[orgId]/subscription/index.tsx b/packages/web/app/pages/v1/[orgId]/subscription/index.tsx deleted file mode 100644 index 26c04eca5..000000000 --- a/packages/web/app/pages/v1/[orgId]/subscription/index.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import React from 'react'; -import 'twin.macro'; -import { OrganizationAccessScope, useOrganizationAccess } from '@/lib/access/organization'; -import { OrganizationView } from '@/components/organization/View'; -import { OrganizationUsageEstimationView } from '@/components/organization/Usage'; -import { OrganizationFieldsFragment, OrgBillingInfoFieldsFragment, OrgRateLimitFieldsFragment } from '@/graphql'; -import { Card, Page } from '@/components/common'; -import { BillingView } from '@/components/organization/billing/Billing'; -import { Button, Stat, StatHelpText, StatLabel, StatNumber } from '@chakra-ui/react'; -import { useRouteSelector } from '@/lib/hooks/use-route-selector'; -import { InvoicesList } from '@/components/organization/billing/InvoicesList'; -import { CurrencyFormatter } from '@/components/organization/billing/helpers'; -import { RateLimitWarn } from '@/components/organization/billing/RateLimitWarn'; - -const Inner: React.FC<{ - organization: OrganizationFieldsFragment & OrgBillingInfoFieldsFragment & OrgRateLimitFieldsFragment; -}> = ({ organization }) => { - const router = useRouteSelector(); - const canAccess = useOrganizationAccess({ - scope: OrganizationAccessScope.Settings, - member: organization?.me, - redirect: true, - }); - - if (!canAccess) { - return null; - } - - return ( - - Manage Subscription - - } - > - - - - - - Plan and Reserved Volume - - - {organization.billingConfiguration?.upcomingInvoice ? ( - - Next Invoice - - {CurrencyFormatter.format(organization.billingConfiguration.upcomingInvoice.amount)} - - {organization.billingConfiguration.upcomingInvoice.date} - - ) : null} - - - - - - - - Monthly Usage Overview - - - - - - - {organization.billingConfiguration?.invoices?.length > 0 ? ( - - Invoices - - - - - ) : null} - - ); -}; - -export default function SubscriptionPage() { - return ( - - {({ organization }) => } - - ); -}
X-Hive-CDN-Key: {mutation.data.createCdnToken.token}