diff --git a/web/constants/project.ts b/web/constants/project.ts index 1715c0e82c..c4ef817fdb 100644 --- a/web/constants/project.ts +++ b/web/constants/project.ts @@ -115,6 +115,14 @@ export const PROJECT_SETTINGS_LINKS: { highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/labels`, Icon: SettingIcon, }, + { + key: "integrations", + label: "Integrations", + href: `/settings/integrations`, + access: EUserProjectRoles.ADMIN, + highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/integrations`, + Icon: SettingIcon, + }, { key: "estimates", label: "Estimates", diff --git a/web/constants/workspace.ts b/web/constants/workspace.ts index cbb8d23241..18cfac3a88 100644 --- a/web/constants/workspace.ts +++ b/web/constants/workspace.ts @@ -149,6 +149,22 @@ export const WORKSPACE_SETTINGS_LINKS: { highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/billing`, Icon: SettingIcon, }, + { + key: "integrations", + label: "Integrations", + href: `/settings/integrations`, + access: EUserWorkspaceRoles.ADMIN, + highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/integrations`, + Icon: SettingIcon, + }, + { + key: "import", + label: "Imports", + href: `/settings/imports`, + access: EUserWorkspaceRoles.ADMIN, + highlight: (pathname: string, baseUrl: string) => pathname === `${baseUrl}/settings/imports`, + Icon: SettingIcon, + }, { key: "export", label: "Exports", diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx new file mode 100644 index 0000000000..a4d8c4dd7b --- /dev/null +++ b/web/pages/[workspaceSlug]/projects/[projectId]/settings/integrations.tsx @@ -0,0 +1,86 @@ +import { ReactElement } from "react"; +import { observer } from "mobx-react"; +import { useRouter } from "next/router"; +import useSWR from "swr"; +import { IProject } from "@plane/types"; +// hooks +import { PageHead } from "@/components/core"; +import { EmptyState } from "@/components/empty-state"; +import { ProjectSettingHeader } from "@/components/headers"; +import { IntegrationCard } from "@/components/project"; +import { IntegrationsSettingsLoader } from "@/components/ui"; +// layouts +import { EmptyStateType } from "@/constants/empty-state"; +import { PROJECT_DETAILS, WORKSPACE_INTEGRATIONS } from "@/constants/fetch-keys"; +import { AppLayout } from "@/layouts/app-layout"; +import { ProjectSettingLayout } from "@/layouts/settings-layout"; +// services +import { NextPageWithLayout } from "@/lib/types"; +import { IntegrationService } from "@/services/integrations"; +import { ProjectService } from "@/services/project"; +// components +// ui +// types +// fetch-keys +// constants + +// services +const integrationService = new IntegrationService(); +const projectService = new ProjectService(); + +const ProjectIntegrationsPage: NextPageWithLayout = observer(() => { + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + // fetch project details + const { data: projectDetails } = useSWR( + workspaceSlug && projectId ? PROJECT_DETAILS(projectId as string) : null, + workspaceSlug && projectId ? () => projectService.getProject(workspaceSlug as string, projectId as string) : null + ); + // fetch Integrations list + const { data: workspaceIntegrations } = useSWR( + workspaceSlug ? WORKSPACE_INTEGRATIONS(workspaceSlug as string) : null, + () => (workspaceSlug ? integrationService.getWorkspaceIntegrationsList(workspaceSlug as string) : null) + ); + // derived values + const isAdmin = projectDetails?.member_role === 20; + const pageTitle = projectDetails?.name ? `${projectDetails?.name} - Integrations` : undefined; + + return ( + <> + +
+
+

Integrations

+
+ {workspaceIntegrations ? ( + workspaceIntegrations.length > 0 ? ( +
+ {workspaceIntegrations.map((integration) => ( + + ))} +
+ ) : ( +
+ +
+ ) + ) : ( + + )} +
+ + ); +}); + +ProjectIntegrationsPage.getLayout = function getLayout(page: ReactElement) { + return ( + }> + {page} + + ); +}; + +export default ProjectIntegrationsPage; diff --git a/web/pages/[workspaceSlug]/settings/imports.tsx b/web/pages/[workspaceSlug]/settings/imports.tsx new file mode 100644 index 0000000000..caf958d388 --- /dev/null +++ b/web/pages/[workspaceSlug]/settings/imports.tsx @@ -0,0 +1,58 @@ +import { observer } from "mobx-react-lite"; +// hooks +import { PageHead } from "@/components/core"; +import { WorkspaceSettingHeader } from "@/components/headers"; +import IntegrationGuide from "@/components/integration/guide"; +import { EUserWorkspaceRoles } from "@/constants/workspace"; +import { useUser, useWorkspace } from "@/hooks/store"; +// layouts +import { AppLayout } from "@/layouts/app-layout"; +import { WorkspaceSettingLayout } from "@/layouts/settings-layout"; +// components +// types +import { NextPageWithLayout } from "@/lib/types"; +// constants + +const ImportsPage: NextPageWithLayout = observer(() => { + // store hooks + const { + membership: { currentWorkspaceRole }, + } = useUser(); + const { currentWorkspace } = useWorkspace(); + + // derived values + const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN; + const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Imports` : undefined; + + if (!isAdmin) + return ( + <> + +
+

You are not authorized to access this page.

+
+ + ); + + return ( + <> + +
+
+

Imports

+
+ +
+ + ); +}); + +ImportsPage.getLayout = function getLayout(page: React.ReactElement) { + return ( + }> + {page} + + ); +}; + +export default ImportsPage; diff --git a/web/pages/[workspaceSlug]/settings/integrations.tsx b/web/pages/[workspaceSlug]/settings/integrations.tsx new file mode 100644 index 0000000000..9a0b6f3460 --- /dev/null +++ b/web/pages/[workspaceSlug]/settings/integrations.tsx @@ -0,0 +1,82 @@ +import { ReactElement } from "react"; +import { observer } from "mobx-react-lite"; +import { useRouter } from "next/router"; +import useSWR from "swr"; +// hooks +// services +// layouts +// components +import { PageHead } from "@/components/core"; +import { WorkspaceSettingHeader } from "@/components/headers"; +import { SingleIntegrationCard } from "@/components/integration"; +// ui +import { IntegrationAndImportExportBanner, IntegrationsSettingsLoader } from "@/components/ui"; +// types +// fetch-keys +import { APP_INTEGRATIONS } from "@/constants/fetch-keys"; +// constants +import { EUserWorkspaceRoles } from "@/constants/workspace"; +import { useUser, useWorkspace } from "@/hooks/store"; +import { AppLayout } from "@/layouts/app-layout"; +import { WorkspaceSettingLayout } from "@/layouts/settings-layout"; +import { NextPageWithLayout } from "@/lib/types"; +import { IntegrationService } from "@/services/integrations"; + +const integrationService = new IntegrationService(); + +const WorkspaceIntegrationsPage: NextPageWithLayout = observer(() => { + // router + const router = useRouter(); + const { workspaceSlug } = router.query; + // store hooks + const { + membership: { currentWorkspaceRole }, + } = useUser(); + const { currentWorkspace } = useWorkspace(); + + // derived values + const isAdmin = currentWorkspaceRole === EUserWorkspaceRoles.ADMIN; + const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Integrations` : undefined; + + const { data: appIntegrations } = useSWR(workspaceSlug && isAdmin ? APP_INTEGRATIONS : null, () => + workspaceSlug && isAdmin ? integrationService.getAppIntegrationsList() : null + ); + + if (!isAdmin) + return ( + <> + +
+

You are not authorized to access this page.

+
+ + ); + + return ( + <> + +
+ +
+ {appIntegrations ? ( + appIntegrations.map((integration) => ( + + )) + ) : ( + + )} +
+
+ + ); +}); + +WorkspaceIntegrationsPage.getLayout = function getLayout(page: ReactElement) { + return ( + }> + {page} + + ); +}; + +export default WorkspaceIntegrationsPage;