From 5bd1999799e0ff08d49f6fedafce674a1030690c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89mile=20R=C3=A9?= Date: Fri, 21 Mar 2025 17:57:47 +0400 Subject: [PATCH] Fix all lazy suspense callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Émile Ré --- .../organizations/CreateOrganizationPage.tsx | 179 +----- .../organizations/CreateOrganizationView.tsx | 170 ++++++ .../src/pages/organizations/Routes.tsx | 224 +------ .../src/pages/organizations/SettingsPage.tsx | 547 +----------------- .../src/pages/organizations/SettingsView.tsx | 542 +++++++++++++++++ ...ViewCreateOrganizationMutation.graphql.ts} | 24 +- ...ateOrganizationViewViewerQuery.graphql.ts} | 24 +- ...SettingsViewInviteUserMutation.graphql.ts} | 24 +- ...raphql.ts => SettingsViewQuery.graphql.ts} | 24 +- ...SettingsViewRemoveUserMutation.graphql.ts} | 24 +- ...ViewUpdateOrganizationMutation.graphql.ts} | 24 +- .../frameworks/CreateFrameworkPage.tsx | 229 +------- .../frameworks/CreateFrameworkView.tsx | 219 +++++++ .../frameworks/FrameworkListPage.tsx | 4 +- .../frameworks/FrameworkListView.tsx | 6 +- .../frameworks/UpdateFrameworkPage.tsx | 266 +-------- .../frameworks/UpdateFrameworkView.tsx | 258 +++++++++ ...orkViewCreateFrameworkMutation.graphql.ts} | 24 +- ...ts => UpdateFrameworkViewQuery.graphql.ts} | 24 +- ...orkViewUpdateFrameworkMutation.graphql.ts} | 24 +- .../frameworks/controls/ControlPage.tsx | 44 ++ ...ontrolOverviewPage.tsx => ControlView.tsx} | 143 ++--- .../frameworks/controls/CreateControlPage.tsx | 271 +-------- .../frameworks/controls/CreateControlView.tsx | 264 +++++++++ .../frameworks/controls/UpdateControlPage.tsx | 360 +----------- .../frameworks/controls/UpdateControlView.tsx | 355 ++++++++++++ ... ControlViewAssignTaskMutation.graphql.ts} | 24 +- ... ControlViewCreateTaskMutation.graphql.ts} | 24 +- ...trolViewDeleteEvidenceMutation.graphql.ts} | 24 +- ... ControlViewDeleteTaskMutation.graphql.ts} | 24 +- ...rolViewGetEvidenceFileUrlQuery.graphql.ts} | 24 +- ...> ControlViewOrganizationQuery.graphql.ts} | 30 +- ...graphql.ts => ControlViewQuery.graphql.ts} | 32 +- ...ontrolViewUnassignTaskMutation.graphql.ts} | 24 +- ...ViewUpdateControlStateMutation.graphql.ts} | 24 +- ...rolViewUpdateTaskStateMutation.graphql.ts} | 24 +- ...trolViewUploadEvidenceMutation.graphql.ts} | 24 +- ...ntrolViewCreateControlMutation.graphql.ts} | 24 +- ...l.ts => UpdateControlViewQuery.graphql.ts} | 24 +- ...ntrolViewUpdateControlMutation.graphql.ts} | 24 +- .../organizations/people/CreatePeoplePage.tsx | 312 +--------- .../organizations/people/CreatePeopleView.tsx | 305 ++++++++++ .../organizations/people/PeopleListPage.tsx | 331 +---------- .../organizations/people/PeopleListView.tsx | 326 +++++++++++ .../pages/organizations/people/PeoplePage.tsx | 36 ++ ...{PeopleOverviewPage.tsx => PeopleView.tsx} | 52 +- ...PeopleViewCreatePeopleMutation.graphql.ts} | 24 +- ...leListViewDeletePeopleMutation.graphql.ts} | 24 +- ... PeopleListViewPaginationQuery.graphql.ts} | 30 +- ...phql.ts => PeopleListViewQuery.graphql.ts} | 30 +- ...l.ts => PeopleListView_peoples.graphql.ts} | 22 +- ....graphql.ts => PeopleViewQuery.graphql.ts} | 24 +- ...PeopleViewUpdatePeopleMutation.graphql.ts} | 24 +- .../policies/CreatePolicyPage.tsx | 289 +-------- .../policies/CreatePolicyView.tsx | 284 +++++++++ .../organizations/policies/PolicyListPage.tsx | 374 +----------- .../organizations/policies/PolicyListView.tsx | 370 ++++++++++++ .../organizations/policies/PolicyPage.tsx | 120 ++++ ...{PolicyOverviewPage.tsx => PolicyView.tsx} | 135 +---- .../policies/UpdatePolicyPage.tsx | 281 +-------- .../policies/UpdatePolicyView.tsx | 276 +++++++++ ...ts => CreatePolicyViewMutation.graphql.ts} | 24 +- ...ql.ts => CreatePolicyViewQuery.graphql.ts} | 24 +- ...phql.ts => PolicyListViewQuery.graphql.ts} | 28 +- ...ts => PolicyViewDeleteMutation.graphql.ts} | 24 +- ....graphql.ts => PolicyViewQuery.graphql.ts} | 24 +- ...ts => UpdatePolicyViewMutation.graphql.ts} | 24 +- ...ql.ts => UpdatePolicyViewQuery.graphql.ts} | 24 +- .../organizations/vendors/VendorListPage.tsx | 4 +- .../organizations/vendors/VendorListView.tsx | 6 +- .../organizations/vendors/VendorPage.tsx | 34 ++ ...{VendorOverviewPage.tsx => VendorView.tsx} | 50 +- ....graphql.ts => VendorViewQuery.graphql.ts} | 24 +- ...VendorViewUpdateVendorMutation.graphql.ts} | 24 +- 74 files changed, 4373 insertions(+), 4257 deletions(-) create mode 100644 apps/console/src/pages/organizations/CreateOrganizationView.tsx create mode 100644 apps/console/src/pages/organizations/SettingsView.tsx rename apps/console/src/pages/organizations/__generated__/{CreateOrganizationPageCreateOrganizationMutation.graphql.ts => CreateOrganizationViewCreateOrganizationMutation.graphql.ts} (82%) rename apps/console/src/pages/organizations/__generated__/{CreateOrganizationPageViewerQuery.graphql.ts => CreateOrganizationViewViewerQuery.graphql.ts} (62%) rename apps/console/src/pages/organizations/__generated__/{SettingsPageInviteUserMutation.graphql.ts => SettingsViewInviteUserMutation.graphql.ts} (70%) rename apps/console/src/pages/organizations/__generated__/{SettingsPageQuery.graphql.ts => SettingsViewQuery.graphql.ts} (89%) rename apps/console/src/pages/organizations/__generated__/{SettingsPageRemoveUserMutation.graphql.ts => SettingsViewRemoveUserMutation.graphql.ts} (69%) rename apps/console/src/pages/organizations/__generated__/{SettingsPageUpdateOrganizationMutation.graphql.ts => SettingsViewUpdateOrganizationMutation.graphql.ts} (77%) create mode 100644 apps/console/src/pages/organizations/frameworks/CreateFrameworkView.tsx create mode 100644 apps/console/src/pages/organizations/frameworks/UpdateFrameworkView.tsx rename apps/console/src/pages/organizations/frameworks/__generated__/{CreateFrameworkPageCreateFrameworkMutation.graphql.ts => CreateFrameworkViewCreateFrameworkMutation.graphql.ts} (82%) rename apps/console/src/pages/organizations/frameworks/__generated__/{UpdateFrameworkPageQuery.graphql.ts => UpdateFrameworkViewQuery.graphql.ts} (82%) rename apps/console/src/pages/organizations/frameworks/__generated__/{UpdateFrameworkPageUpdateFrameworkMutation.graphql.ts => UpdateFrameworkViewUpdateFrameworkMutation.graphql.ts} (78%) create mode 100644 apps/console/src/pages/organizations/frameworks/controls/ControlPage.tsx rename apps/console/src/pages/organizations/frameworks/controls/{ControlOverviewPage.tsx => ControlView.tsx} (92%) create mode 100644 apps/console/src/pages/organizations/frameworks/controls/CreateControlView.tsx create mode 100644 apps/console/src/pages/organizations/frameworks/controls/UpdateControlView.tsx rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageAssignTaskMutation.graphql.ts => ControlViewAssignTaskMutation.graphql.ts} (75%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageCreateTaskMutation.graphql.ts => ControlViewCreateTaskMutation.graphql.ts} (82%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageDeleteEvidenceMutation.graphql.ts => ControlViewDeleteEvidenceMutation.graphql.ts} (73%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageDeleteTaskMutation.graphql.ts => ControlViewDeleteTaskMutation.graphql.ts} (74%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageGetEvidenceFileUrlQuery.graphql.ts => ControlViewGetEvidenceFileUrlQuery.graphql.ts} (72%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageOrganizationQuery.graphql.ts => ControlViewOrganizationQuery.graphql.ts} (79%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageQuery.graphql.ts => ControlViewQuery.graphql.ts} (86%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageUnassignTaskMutation.graphql.ts => ControlViewUnassignTaskMutation.graphql.ts} (74%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageUpdateControlStateMutation.graphql.ts => ControlViewUpdateControlStateMutation.graphql.ts} (73%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageUpdateTaskStateMutation.graphql.ts => ControlViewUpdateTaskStateMutation.graphql.ts} (72%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{ControlOverviewPageUploadEvidenceMutation.graphql.ts => ControlViewUploadEvidenceMutation.graphql.ts} (82%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{CreateControlPageCreateControlMutation.graphql.ts => CreateControlViewCreateControlMutation.graphql.ts} (85%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{UpdateControlPageQuery.graphql.ts => UpdateControlViewQuery.graphql.ts} (86%) rename apps/console/src/pages/organizations/frameworks/controls/__generated__/{UpdateControlPageUpdateControlMutation.graphql.ts => UpdateControlViewUpdateControlMutation.graphql.ts} (83%) create mode 100644 apps/console/src/pages/organizations/people/CreatePeopleView.tsx create mode 100644 apps/console/src/pages/organizations/people/PeopleListView.tsx create mode 100644 apps/console/src/pages/organizations/people/PeoplePage.tsx rename apps/console/src/pages/organizations/people/{PeopleOverviewPage.tsx => PeopleView.tsx} (86%) rename apps/console/src/pages/organizations/people/__generated__/{CreatePeoplePageCreatePeopleMutation.graphql.ts => CreatePeopleViewCreatePeopleMutation.graphql.ts} (85%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleListPageDeletePeopleMutation.graphql.ts => PeopleListViewDeletePeopleMutation.graphql.ts} (78%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleListPagePaginationQuery.graphql.ts => PeopleListViewPaginationQuery.graphql.ts} (91%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleListPageQuery.graphql.ts => PeopleListViewQuery.graphql.ts} (91%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleListPage_peoples.graphql.ts => PeopleListView_peoples.graphql.ts} (91%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleOverviewPageQuery.graphql.ts => PeopleViewQuery.graphql.ts} (81%) rename apps/console/src/pages/organizations/people/__generated__/{PeopleOverviewPageUpdatePeopleMutation.graphql.ts => PeopleViewUpdatePeopleMutation.graphql.ts} (78%) create mode 100644 apps/console/src/pages/organizations/policies/CreatePolicyView.tsx create mode 100644 apps/console/src/pages/organizations/policies/PolicyListView.tsx create mode 100644 apps/console/src/pages/organizations/policies/PolicyPage.tsx rename apps/console/src/pages/organizations/policies/{PolicyOverviewPage.tsx => PolicyView.tsx} (71%) create mode 100644 apps/console/src/pages/organizations/policies/UpdatePolicyView.tsx rename apps/console/src/pages/organizations/policies/__generated__/{CreatePolicyPageMutation.graphql.ts => CreatePolicyViewMutation.graphql.ts} (88%) rename apps/console/src/pages/organizations/policies/__generated__/{CreatePolicyPageQuery.graphql.ts => CreatePolicyViewQuery.graphql.ts} (91%) rename apps/console/src/pages/organizations/policies/__generated__/{PolicyListPageQuery.graphql.ts => PolicyListViewQuery.graphql.ts} (90%) rename apps/console/src/pages/organizations/policies/__generated__/{PolicyOverviewPageDeleteMutation.graphql.ts => PolicyViewDeleteMutation.graphql.ts} (75%) rename apps/console/src/pages/organizations/policies/__generated__/{PolicyOverviewPageQuery.graphql.ts => PolicyViewQuery.graphql.ts} (81%) rename apps/console/src/pages/organizations/policies/__generated__/{UpdatePolicyPageMutation.graphql.ts => UpdatePolicyViewMutation.graphql.ts} (86%) rename apps/console/src/pages/organizations/policies/__generated__/{UpdatePolicyPageQuery.graphql.ts => UpdatePolicyViewQuery.graphql.ts} (93%) create mode 100644 apps/console/src/pages/organizations/vendors/VendorPage.tsx rename apps/console/src/pages/organizations/vendors/{VendorOverviewPage.tsx => VendorView.tsx} (90%) rename apps/console/src/pages/organizations/vendors/__generated__/{VendorOverviewPageQuery.graphql.ts => VendorViewQuery.graphql.ts} (83%) rename apps/console/src/pages/organizations/vendors/__generated__/{VendorOverviewPageUpdateVendorMutation.graphql.ts => VendorViewUpdateVendorMutation.graphql.ts} (82%) diff --git a/apps/console/src/pages/organizations/CreateOrganizationPage.tsx b/apps/console/src/pages/organizations/CreateOrganizationPage.tsx index 8b8acefdf..e80f75974 100644 --- a/apps/console/src/pages/organizations/CreateOrganizationPage.tsx +++ b/apps/console/src/pages/organizations/CreateOrganizationPage.tsx @@ -1,87 +1,9 @@ -import { useState } from "react"; -import { useNavigate } from "react-router"; -import { - graphql, - ConnectionHandler, - useMutation, - useLazyLoadQuery, -} from "react-relay"; -import { Button } from "@/components/ui/button"; -import { - Card, - CardHeader, - CardTitle, - CardDescription, - CardContent, -} from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { useToast } from "@/hooks/use-toast"; -import { HelpCircle } from "lucide-react"; -import { CreateOrganizationPageCreateOrganizationMutation } from "./__generated__/CreateOrganizationPageCreateOrganizationMutation.graphql"; -import { CreateOrganizationPageViewerQuery } from "./__generated__/CreateOrganizationPageViewerQuery.graphql"; -import { PageTemplate, PageTemplateSkeleton } from "@/components/PageTemplate"; +import { PageTemplateSkeleton } from "@/components/PageTemplate"; +import { lazy, Suspense } from "react"; +import { useLocation } from "react-router"; +import { ErrorBoundaryWithLocation } from "./ErrorBoundary"; -const createOrganizationMutation = graphql` - mutation CreateOrganizationPageCreateOrganizationMutation( - $input: CreateOrganizationInput! - $connections: [ID!]! - ) { - createOrganization(input: $input) { - organizationEdge @appendEdge(connections: $connections) { - node { - id - name - logoUrl - } - } - } - } -`; - -const viewerQuery = graphql` - query CreateOrganizationPageViewerQuery { - viewer { - id - } - } -`; - -function EditableField({ - label, - value, - onChange, - type = "text", - helpText, - required, -}: { - label: string; - value: string; - onChange: (value: string) => void; - type?: string; - helpText?: string; - required?: boolean; -}) { - return ( -
-
- - -
-
- onChange(e.target.value)} - required={required} - /> - {helpText &&

{helpText}

} -
-
- ); -} - -export function CreateOrganizationPageSkeleton() { +export function CreateOrganizationViewSkeleton() { return ( ( - viewerQuery, - {} - ); - const [createOrganization] = - useMutation( - createOrganizationMutation - ); - const [formData, setFormData] = useState({ - name: "", - }); +const CreateOrganizationView = lazy(() => import("./CreateOrganizationView")); - const handleFieldChange = (field: keyof typeof formData, value: string) => { - setFormData((prev) => ({ - ...prev, - [field]: value, - })); - }; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - - createOrganization({ - variables: { - input: { - name: formData.name, - }, - connections: [ - ConnectionHandler.getConnectionID( - data.viewer.id, - "OrganizationSwitcher_organizations" - ), - ], - }, - onCompleted: (response) => { - const newOrg = response.createOrganization.organizationEdge.node; - toast({ - title: "Success", - description: "Organization created successfully", - variant: "default", - }); - navigate(`/organizations/${newOrg.id}`); - }, - onError: (error) => { - toast({ - title: "Error", - description: error.message || "Failed to create organization", - variant: "destructive", - }); - }, - }); - }; +export function CreateOrganizationPage() { + const location = useLocation(); return ( - } > -
- - - Organization Details - - Enter the basic information about your organization. - - - - handleFieldChange("name", value)} - helpText="The name of your organization as it will appear throughout the platform." - required - /> - - - - -
-
+ + + + ); } diff --git a/apps/console/src/pages/organizations/CreateOrganizationView.tsx b/apps/console/src/pages/organizations/CreateOrganizationView.tsx new file mode 100644 index 000000000..30dfbfc8a --- /dev/null +++ b/apps/console/src/pages/organizations/CreateOrganizationView.tsx @@ -0,0 +1,170 @@ +import { useState } from "react"; +import { useNavigate } from "react-router"; +import { + graphql, + ConnectionHandler, + useMutation, + useLazyLoadQuery, +} from "react-relay"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardHeader, + CardTitle, + CardDescription, + CardContent, +} from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { useToast } from "@/hooks/use-toast"; +import { HelpCircle } from "lucide-react"; +import { CreateOrganizationViewCreateOrganizationMutation } from "./__generated__/CreateOrganizationViewCreateOrganizationMutation.graphql"; +import { CreateOrganizationViewViewerQuery } from "./__generated__/CreateOrganizationViewViewerQuery.graphql"; +import { PageTemplate } from "@/components/PageTemplate"; + +const createOrganizationMutation = graphql` + mutation CreateOrganizationViewCreateOrganizationMutation( + $input: CreateOrganizationInput! + $connections: [ID!]! + ) { + createOrganization(input: $input) { + organizationEdge @appendEdge(connections: $connections) { + node { + id + name + logoUrl + } + } + } + } +`; + +const viewerQuery = graphql` + query CreateOrganizationViewViewerQuery { + viewer { + id + } + } +`; + +function EditableField({ + label, + value, + onChange, + type = "text", + helpText, + required, +}: { + label: string; + value: string; + onChange: (value: string) => void; + type?: string; + helpText?: string; + required?: boolean; +}) { + return ( +
+
+ + +
+
+ onChange(e.target.value)} + required={required} + /> + {helpText &&

{helpText}

} +
+
+ ); +} + +export default function CreateOrganizationView() { + const navigate = useNavigate(); + const { toast } = useToast(); + const data = useLazyLoadQuery( + viewerQuery, + {} + ); + const [createOrganization] = + useMutation( + createOrganizationMutation + ); + const [formData, setFormData] = useState({ + name: "", + }); + + const handleFieldChange = (field: keyof typeof formData, value: string) => { + setFormData((prev) => ({ + ...prev, + [field]: value, + })); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + + createOrganization({ + variables: { + input: { + name: formData.name, + }, + connections: [ + ConnectionHandler.getConnectionID( + data.viewer.id, + "OrganizationSwitcher_organizations" + ), + ], + }, + onCompleted: (response) => { + const newOrg = response.createOrganization.organizationEdge.node; + toast({ + title: "Success", + description: "Organization created successfully", + variant: "default", + }); + navigate(`/organizations/${newOrg.id}`); + }, + onError: (error) => { + toast({ + title: "Error", + description: error.message || "Failed to create organization", + variant: "destructive", + }); + }, + }); + }; + + return ( + +
+ + + Organization Details + + Enter the basic information about your organization. + + + + handleFieldChange("name", value)} + helpText="The name of your organization as it will appear throughout the platform." + required + /> + + + + +
+
+ ); +} diff --git a/apps/console/src/pages/organizations/Routes.tsx b/apps/console/src/pages/organizations/Routes.tsx index 989e18bb0..325a1e9b1 100644 --- a/apps/console/src/pages/organizations/Routes.tsx +++ b/apps/console/src/pages/organizations/Routes.tsx @@ -1,227 +1,67 @@ -import { lazy, Suspense } from "react"; import { Route, Routes } from "react-router"; -import { CreateOrganizationPageSkeleton } from "./CreateOrganizationPage"; -import { ControlOverviewPageSkeleton } from "./frameworks/controls/ControlOverviewPage"; -import { CreateControlPageSkeleton } from "./frameworks/controls/CreateControlPage"; -import { UpdateControlPageSkeleton } from "./frameworks/controls/UpdateControlPage"; -import { CreateFrameworkPageSkeleton } from "./frameworks/CreateFrameworkPage"; -import { UpdateFrameworkPageSkeleton } from "./frameworks/UpdateFrameworkPage"; -import "./HomePage"; -import { CreatePeoplePageSkeleton } from "./people/CreatePeoplePage"; -import { PeopleListPageSkeleton } from "./people/PeopleListPage"; -import { PeopleOverviewPageSkeleton } from "./people/PeopleOverviewPage"; -import { CreatePolicyPageSkeleton } from "./policies/CreatePolicyPage"; -import { PolicyListPageSkeleton } from "./policies/PolicyListPage"; -import { PolicyOverviewPageSkeleton } from "./policies/PolicyOverviewPage"; -import { UpdatePolicyPageSkeleton } from "./policies/UpdatePolicyPage"; -import { SettingsPageSkeleton } from "./SettingsPage"; import { VendorListPage } from "./vendors/VendorListPage"; -import { VendorOverviewPageSkeleton } from "./vendors/VendorOverviewPage"; -import { ErrorBoundaryWithLocation } from "./ErrorBoundary"; import OrganizationLayout from "./OrganizationLayout"; import NoOrganizationLayout from "./NoOrganizationLayout"; import { FrameworkListPage } from "./frameworks/FrameworkListPage"; import { FrameworkPage } from "./frameworks/FrameworkPage"; - -const CreateOrganizationPage = lazy(() => import("./CreateOrganizationPage")); -const ControlOverviewPage = lazy( - () => import("./frameworks/controls/ControlOverviewPage") -); -const CreateControlPage = lazy( - () => import("./frameworks/controls/CreateControlPage") -); -const UpdateControlPage = lazy( - () => import("./frameworks/controls/UpdateControlPage") -); -const CreateFrameworkPage = lazy( - () => import("./frameworks/CreateFrameworkPage") -); -const UpdateFrameworkPage = lazy( - () => import("./frameworks/UpdateFrameworkPage") -); -const HomePage = lazy(() => import("./HomePage")); -const CreatePeoplePage = lazy(() => import("./people/CreatePeoplePage")); -const PeopleListPage = lazy(() => import("./people/PeopleListPage")); -const PeopleOverviewPage = lazy(() => import("./people/PeopleOverviewPage")); -const CreatePolicyPage = lazy(() => import("./policies/CreatePolicyPage")); -const PolicyListPage = lazy(() => import("./policies/PolicyListPage")); -const PolicyOverviewPage = lazy(() => import("./policies/PolicyOverviewPage")); -const UpdatePolicyPage = lazy(() => import("./policies/UpdatePolicyPage")); -const SettingsPage = lazy(() => import("./SettingsPage")); - -const VendorOverviewPage = lazy(() => import("./vendors/VendorOverviewPage")); +import { PeopleListPage } from "./people/PeopleListPage"; +import { CreatePeoplePage } from "./people/CreatePeoplePage"; +import { PeoplePage } from "./people/PeoplePage"; +import { CreateFrameworkPage } from "./frameworks/CreateFrameworkPage"; +import { UpdateFrameworkPage } from "./frameworks/UpdateFrameworkPage"; +import { CreateControlPage } from "./frameworks/controls/CreateControlPage"; +import { ControlPage } from "./frameworks/controls/ControlPage"; +import { UpdateControlPage } from "./frameworks/controls/UpdateControlPage"; +import { VendorPage } from "./vendors/VendorPage"; +import { PolicyListPage } from "./policies/PolicyListPage"; +import { CreatePolicyPage } from "./policies/CreatePolicyPage"; +import { PolicyPage } from "./policies/PolicyPage"; +import { UpdatePolicyPage } from "./policies/UpdatePolicyPage"; +import { SettingsPage } from "./SettingsPage"; +import { CreateOrganizationPage } from "./CreateOrganizationPage"; +import HomePage from "./HomePage"; export function OrganizationsRoutes() { return ( }> - - - - - - } - /> - }> - - - - - } - /> - }> - - - - - } - /> - }> - - - - - } - /> + } /> + } /> + } /> + } /> } /> } /> - }> - - - - - } - /> + } /> } /> }> - - - - - } + element={} /> }> - - - - - } + element={} /> }> - - - - - } + element={} /> }> - - - - - } - /> - }> - - - - - } - /> - {/* Policy Routes */} - }> - - - - - } - /> - }> - - - - - } - /> - }> - - - - - } + element={} /> + } /> + } /> + } /> + } /> }> - - - - - } - /> - }> - - - - - } + element={} /> + } /> }> - }> - - - - - } - /> + } /> ); diff --git a/apps/console/src/pages/organizations/SettingsPage.tsx b/apps/console/src/pages/organizations/SettingsPage.tsx index ddbd5672f..1419348d1 100644 --- a/apps/console/src/pages/organizations/SettingsPage.tsx +++ b/apps/console/src/pages/organizations/SettingsPage.tsx @@ -1,525 +1,11 @@ -import { Building2, Upload, MoreVertical } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { - Card, - CardContent, - CardHeader, - CardTitle, - CardDescription, -} from "@/components/ui/card"; -import { Avatar, AvatarFallback } from "@/components/ui/avatar"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; -import { Suspense, useEffect, useState, useRef } from "react"; -import { - graphql, - PreloadedQuery, - usePreloadedQuery, - useQueryLoader, - useMutation, -} from "react-relay"; -import { useParams } from "react-router"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { useToast } from "@/hooks/use-toast"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/ui/dialog"; -import type { SettingsPageQuery as SettingsPageQueryType } from "./__generated__/SettingsPageQuery.graphql"; -import type { SettingsPageUpdateOrganizationMutation as SettingsPageUpdateOrganizationMutationType } from "./__generated__/SettingsPageUpdateOrganizationMutation.graphql"; -import type { SettingsPageInviteUserMutation as SettingsPageInviteUserMutationType } from "./__generated__/SettingsPageInviteUserMutation.graphql"; -import type { SettingsPageRemoveUserMutation as SettingsPageRemoveUserMutationType } from "./__generated__/SettingsPageRemoveUserMutation.graphql"; -import { PageTemplate, PageTemplateSkeleton } from "@/components/PageTemplate"; +import { PageTemplateSkeleton } from "@/components/PageTemplate"; +import { lazy, Suspense } from "react"; +import { useLocation } from "react-router"; +import { ErrorBoundaryWithLocation } from "./ErrorBoundary"; -const settingsPageQuery = graphql` - query SettingsPageQuery($organizationID: ID!) { - organization: node(id: $organizationID) { - id - ... on Organization { - name - logoUrl - users(first: 100) { - edges { - node { - id - fullName - email - createdAt - } - } - } - } - } - } -`; +const SettingsView = lazy(() => import("./SettingsView")); -const updateOrganizationMutation = graphql` - mutation SettingsPageUpdateOrganizationMutation( - $input: UpdateOrganizationInput! - ) { - updateOrganization(input: $input) { - organization { - id - name - logoUrl - } - } - } -`; - -const inviteUserMutation = graphql` - mutation SettingsPageInviteUserMutation($input: InviteUserInput!) { - inviteUser(input: $input) { - success - } - } -`; - -const removeUserMutation = graphql` - mutation SettingsPageRemoveUserMutation($input: RemoveUserInput!) { - removeUser(input: $input) { - success - } - } -`; - -function SettingsPageContent({ - queryRef, -}: { - queryRef: PreloadedQuery; -}) { - const data = usePreloadedQuery(settingsPageQuery, queryRef); - const organization = data.organization; - const users = organization.users?.edges.map((edge) => edge.node) || []; - const { toast } = useToast(); - const fileInputRef = useRef(null); - - const [isEditNameOpen, setIsEditNameOpen] = useState(false); - const [isInviteOpen, setIsInviteOpen] = useState(false); - const [inviteEmail, setInviteEmail] = useState(""); - const [inviteFullName, setInviteFullName] = useState(""); - const [isInviting, setIsInviting] = useState(false); - const [organizationName, setOrganizationName] = useState( - organization.name || "" - ); - const [isUploading, setIsUploading] = useState(false); - const [isRemoving, setIsRemoving] = useState(false); - - const [updateOrganization] = - useMutation( - updateOrganizationMutation - ); - - const [inviteUser] = - useMutation(inviteUserMutation); - - const [removeUser] = - useMutation(removeUserMutation); - - const { organizationId } = useParams(); - const [, loadQuery] = - useQueryLoader(settingsPageQuery); - - const handleUpdateName = () => { - updateOrganization({ - variables: { - input: { - organizationId: organization.id, - name: organizationName, - }, - }, - onCompleted: () => { - toast({ - title: "Organization updated", - description: "Organization name has been updated successfully.", - variant: "default", - }); - setIsEditNameOpen(false); - }, - onError: (error) => { - toast({ - title: "Error updating organization", - description: error.message, - variant: "destructive", - }); - }, - }); - }; - - const handleLogoUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - - // Create a FileReader to read the file as a data URL - const reader = new FileReader(); - reader.onloadend = () => { - setIsUploading(true); - - updateOrganization({ - variables: { - input: { - organizationId: organization.id, - logo: null, - }, - }, - uploadables: { - "input.logo": file, - }, - onCompleted: () => { - setIsUploading(false); - toast({ - title: "Logo updated", - description: "Organization logo has been updated successfully.", - variant: "default", - }); - if (fileInputRef.current) { - fileInputRef.current.value = ""; - } - }, - onError: (error) => { - setIsUploading(false); - toast({ - title: "Error updating logo", - description: error.message, - variant: "destructive", - }); - }, - }); - }; - reader.readAsDataURL(file); - }; - - const handleInviteMember = () => { - if (!inviteEmail || !inviteFullName) { - toast({ - title: "Missing information", - description: - "Please provide both email and full name for the invitation", - variant: "destructive", - }); - return; - } - - setIsInviting(true); - - inviteUser({ - variables: { - input: { - organizationId: organization.id, - email: inviteEmail, - fullName: inviteFullName, - }, - }, - onCompleted: (response) => { - setIsInviting(false); - if (response.inviteUser?.success) { - toast({ - title: "Invitation sent", - description: `An invitation has been sent to ${inviteEmail}`, - variant: "default", - }); - setIsInviteOpen(false); - setInviteEmail(""); - setInviteFullName(""); - } else { - toast({ - title: "Error sending invitation", - description: "The invitation could not be sent. Please try again.", - variant: "destructive", - }); - } - }, - onError: (error) => { - setIsInviting(false); - toast({ - title: "Error sending invitation", - description: error.message, - variant: "destructive", - }); - }, - }); - }; - - const handleRemoveUser = (userId: string) => { - setIsRemoving(true); - - removeUser({ - variables: { - input: { - organizationId: organization.id, - userId: userId, - }, - }, - onCompleted: (response) => { - setIsRemoving(false); - if (response.removeUser?.success) { - toast({ - title: "User removed", - description: "The user has been removed from the organization.", - variant: "default", - }); - // Refresh the query to update the UI - loadQuery({ organizationID: organizationId! }); - } else { - toast({ - title: "Error removing user", - description: "The user could not be removed. Please try again.", - variant: "destructive", - }); - } - }, - onError: (error) => { - setIsRemoving(false); - toast({ - title: "Error removing user", - description: error.message, - variant: "destructive", - }); - }, - }); - }; - - return ( - -
- - - Organization information - Manage your organization details - - -
- -
-
- {organization.logoUrl ? ( - Logo - ) : ( -
- -
- )} - - Upload a logo to be displayed at the top of your trust page - -
-
- - -
-
-
- -
- -
-
- - - Set the name of the organization - -
-
- {organization.name} - -
-
-
-
-
- - - -
- Workspace members - - Manage who has privileged access to your workspace and their - permissions. - -
- -
- -
- {users.length === 0 ? ( -
-
- -
-

No members found

-

- You haven't added any members to your workspace yet. -

-
- ) : ( - users.map((user) => ( -
-
- - - {user.fullName.charAt(0).toUpperCase()} - - -
- - {user.fullName} - - - {user.email} - -
-
-
- - Owner - - - - - - - handleRemoveUser(user.id)} - disabled={isRemoving} - > - {isRemoving ? "Removing..." : "Remove member"} - - - -
-
- )) - )} -
-
-
-
- - - - - Edit Organization Name - - Update the name of your organization. - - -
-
- - setOrganizationName(e.target.value)} - placeholder="Enter organization name" - /> -
-
- - - - -
-
- - - - - Invite Team Member - - Send an invitation to join your workspace. - - -
-
- - setInviteEmail(e.target.value)} - placeholder="Enter email address" - /> -
-
- - setInviteFullName(e.target.value)} - placeholder="Enter full name" - /> -
-
- - - - -
-
-
- ); -} - -export function SettingsPageSkeleton() { +export function SettingsViewSkeleton() { return ( (settingsPageQuery); - - const { organizationId } = useParams(); - - useEffect(() => { - loadQuery({ organizationID: organizationId! }); - }, [loadQuery, organizationId]); - - if (!queryRef) { - return ; - } +export function SettingsPage() { + const location = useLocation(); return ( - }> - + }> + + + ); } diff --git a/apps/console/src/pages/organizations/SettingsView.tsx b/apps/console/src/pages/organizations/SettingsView.tsx new file mode 100644 index 000000000..7473e85cd --- /dev/null +++ b/apps/console/src/pages/organizations/SettingsView.tsx @@ -0,0 +1,542 @@ +import { Building2, Upload, MoreVertical } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardHeader, + CardTitle, + CardDescription, +} from "@/components/ui/card"; +import { Avatar, AvatarFallback } from "@/components/ui/avatar"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Suspense, useEffect, useState, useRef } from "react"; +import { + graphql, + PreloadedQuery, + usePreloadedQuery, + useQueryLoader, + useMutation, +} from "react-relay"; +import { useParams } from "react-router"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { useToast } from "@/hooks/use-toast"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import type { SettingsViewQuery as SettingsViewQueryType } from "./__generated__/SettingsViewQuery.graphql"; +import type { SettingsViewUpdateOrganizationMutation as SettingsViewUpdateOrganizationMutationType } from "./__generated__/SettingsViewUpdateOrganizationMutation.graphql"; +import type { SettingsViewInviteUserMutation as SettingsViewInviteUserMutationType } from "./__generated__/SettingsViewInviteUserMutation.graphql"; +import type { SettingsViewRemoveUserMutation as SettingsViewRemoveUserMutationType } from "./__generated__/SettingsViewRemoveUserMutation.graphql"; +import { PageTemplate } from "@/components/PageTemplate"; +import { SettingsViewSkeleton } from "./SettingsPage"; + +const settingsViewQuery = graphql` + query SettingsViewQuery($organizationID: ID!) { + organization: node(id: $organizationID) { + id + ... on Organization { + name + logoUrl + users(first: 100) { + edges { + node { + id + fullName + email + createdAt + } + } + } + } + } + } +`; + +const updateOrganizationMutation = graphql` + mutation SettingsViewUpdateOrganizationMutation( + $input: UpdateOrganizationInput! + ) { + updateOrganization(input: $input) { + organization { + id + name + logoUrl + } + } + } +`; + +const inviteUserMutation = graphql` + mutation SettingsViewInviteUserMutation($input: InviteUserInput!) { + inviteUser(input: $input) { + success + } + } +`; + +const removeUserMutation = graphql` + mutation SettingsViewRemoveUserMutation($input: RemoveUserInput!) { + removeUser(input: $input) { + success + } + } +`; + +function SettingsViewContent({ + queryRef, +}: { + queryRef: PreloadedQuery; +}) { + const data = usePreloadedQuery(settingsViewQuery, queryRef); + const organization = data.organization; + const users = organization.users?.edges.map((edge) => edge.node) || []; + const { toast } = useToast(); + const fileInputRef = useRef(null); + + const [isEditNameOpen, setIsEditNameOpen] = useState(false); + const [isInviteOpen, setIsInviteOpen] = useState(false); + const [inviteEmail, setInviteEmail] = useState(""); + const [inviteFullName, setInviteFullName] = useState(""); + const [isInviting, setIsInviting] = useState(false); + const [organizationName, setOrganizationName] = useState( + organization.name || "" + ); + const [isUploading, setIsUploading] = useState(false); + const [isRemoving, setIsRemoving] = useState(false); + + const [updateOrganization] = + useMutation( + updateOrganizationMutation + ); + + const [inviteUser] = + useMutation(inviteUserMutation); + + const [removeUser] = + useMutation(removeUserMutation); + + const { organizationId } = useParams(); + const [, loadQuery] = + useQueryLoader(settingsViewQuery); + + const handleUpdateName = () => { + updateOrganization({ + variables: { + input: { + organizationId: organization.id, + name: organizationName, + }, + }, + onCompleted: () => { + toast({ + title: "Organization updated", + description: "Organization name has been updated successfully.", + variant: "default", + }); + setIsEditNameOpen(false); + }, + onError: (error) => { + toast({ + title: "Error updating organization", + description: error.message, + variant: "destructive", + }); + }, + }); + }; + + const handleLogoUpload = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + // Create a FileReader to read the file as a data URL + const reader = new FileReader(); + reader.onloadend = () => { + setIsUploading(true); + + updateOrganization({ + variables: { + input: { + organizationId: organization.id, + logo: null, + }, + }, + uploadables: { + "input.logo": file, + }, + onCompleted: () => { + setIsUploading(false); + toast({ + title: "Logo updated", + description: "Organization logo has been updated successfully.", + variant: "default", + }); + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + }, + onError: (error) => { + setIsUploading(false); + toast({ + title: "Error updating logo", + description: error.message, + variant: "destructive", + }); + }, + }); + }; + reader.readAsDataURL(file); + }; + + const handleInviteMember = () => { + if (!inviteEmail || !inviteFullName) { + toast({ + title: "Missing information", + description: + "Please provide both email and full name for the invitation", + variant: "destructive", + }); + return; + } + + setIsInviting(true); + + inviteUser({ + variables: { + input: { + organizationId: organization.id, + email: inviteEmail, + fullName: inviteFullName, + }, + }, + onCompleted: (response) => { + setIsInviting(false); + if (response.inviteUser?.success) { + toast({ + title: "Invitation sent", + description: `An invitation has been sent to ${inviteEmail}`, + variant: "default", + }); + setIsInviteOpen(false); + setInviteEmail(""); + setInviteFullName(""); + } else { + toast({ + title: "Error sending invitation", + description: "The invitation could not be sent. Please try again.", + variant: "destructive", + }); + } + }, + onError: (error) => { + setIsInviting(false); + toast({ + title: "Error sending invitation", + description: error.message, + variant: "destructive", + }); + }, + }); + }; + + const handleRemoveUser = (userId: string) => { + setIsRemoving(true); + + removeUser({ + variables: { + input: { + organizationId: organization.id, + userId: userId, + }, + }, + onCompleted: (response) => { + setIsRemoving(false); + if (response.removeUser?.success) { + toast({ + title: "User removed", + description: "The user has been removed from the organization.", + variant: "default", + }); + // Refresh the query to update the UI + loadQuery({ organizationID: organizationId! }); + } else { + toast({ + title: "Error removing user", + description: "The user could not be removed. Please try again.", + variant: "destructive", + }); + } + }, + onError: (error) => { + setIsRemoving(false); + toast({ + title: "Error removing user", + description: error.message, + variant: "destructive", + }); + }, + }); + }; + + return ( + +
+ + + Organization information + Manage your organization details + + +
+ +
+
+ {organization.logoUrl ? ( + Logo + ) : ( +
+ +
+ )} + + Upload a logo to be displayed at the top of your trust page + +
+
+ + +
+
+
+ +
+ +
+
+ + + Set the name of the organization + +
+
+ {organization.name} + +
+
+
+
+
+ + + +
+ Workspace members + + Manage who has privileged access to your workspace and their + permissions. + +
+ +
+ +
+ {users.length === 0 ? ( +
+
+ +
+

No members found

+

+ You haven't added any members to your workspace yet. +

+
+ ) : ( + users.map((user) => ( +
+
+ + + {user.fullName.charAt(0).toUpperCase()} + + +
+ + {user.fullName} + + + {user.email} + +
+
+
+ + Owner + + + + + + + handleRemoveUser(user.id)} + disabled={isRemoving} + > + {isRemoving ? "Removing..." : "Remove member"} + + + +
+
+ )) + )} +
+
+
+
+ + + + + Edit Organization Name + + Update the name of your organization. + + +
+
+ + setOrganizationName(e.target.value)} + placeholder="Enter organization name" + /> +
+
+ + + + +
+
+ + + + + Invite Team Member + + Send an invitation to join your workspace. + + +
+
+ + setInviteEmail(e.target.value)} + placeholder="Enter email address" + /> +
+
+ + setInviteFullName(e.target.value)} + placeholder="Enter full name" + /> +
+
+ + + + +
+
+
+ ); +} + +export default function SettingsView() { + const [queryRef, loadQuery] = + useQueryLoader(settingsViewQuery); + + const { organizationId } = useParams(); + + useEffect(() => { + loadQuery({ organizationID: organizationId! }); + }, [loadQuery, organizationId]); + + if (!queryRef) { + return ; + } + + return ( + }> + + + ); +} diff --git a/apps/console/src/pages/organizations/__generated__/CreateOrganizationPageCreateOrganizationMutation.graphql.ts b/apps/console/src/pages/organizations/__generated__/CreateOrganizationViewCreateOrganizationMutation.graphql.ts similarity index 82% rename from apps/console/src/pages/organizations/__generated__/CreateOrganizationPageCreateOrganizationMutation.graphql.ts rename to apps/console/src/pages/organizations/__generated__/CreateOrganizationViewCreateOrganizationMutation.graphql.ts index e684e8a29..266956136 100644 --- a/apps/console/src/pages/organizations/__generated__/CreateOrganizationPageCreateOrganizationMutation.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/CreateOrganizationViewCreateOrganizationMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -12,11 +12,11 @@ import { ConcreteRequest } from 'relay-runtime'; export type CreateOrganizationInput = { name: string; }; -export type CreateOrganizationPageCreateOrganizationMutation$variables = { +export type CreateOrganizationViewCreateOrganizationMutation$variables = { connections: ReadonlyArray; input: CreateOrganizationInput; }; -export type CreateOrganizationPageCreateOrganizationMutation$data = { +export type CreateOrganizationViewCreateOrganizationMutation$data = { readonly createOrganization: { readonly organizationEdge: { readonly node: { @@ -27,9 +27,9 @@ export type CreateOrganizationPageCreateOrganizationMutation$data = { }; }; }; -export type CreateOrganizationPageCreateOrganizationMutation = { - response: CreateOrganizationPageCreateOrganizationMutation$data; - variables: CreateOrganizationPageCreateOrganizationMutation$variables; +export type CreateOrganizationViewCreateOrganizationMutation = { + response: CreateOrganizationViewCreateOrganizationMutation$data; + variables: CreateOrganizationViewCreateOrganizationMutation$variables; }; const node: ConcreteRequest = (function(){ @@ -101,7 +101,7 @@ return { ], "kind": "Fragment", "metadata": null, - "name": "CreateOrganizationPageCreateOrganizationMutation", + "name": "CreateOrganizationViewCreateOrganizationMutation", "selections": [ { "alias": null, @@ -126,7 +126,7 @@ return { (v0/*: any*/) ], "kind": "Operation", - "name": "CreateOrganizationPageCreateOrganizationMutation", + "name": "CreateOrganizationViewCreateOrganizationMutation", "selections": [ { "alias": null, @@ -159,16 +159,16 @@ return { ] }, "params": { - "cacheID": "aa445272c59c25a9a2edc7592c1fd7cc", + "cacheID": "867788ffb7d7d5f42d86fc0b42e91d8f", "id": null, "metadata": {}, - "name": "CreateOrganizationPageCreateOrganizationMutation", + "name": "CreateOrganizationViewCreateOrganizationMutation", "operationKind": "mutation", - "text": "mutation CreateOrganizationPageCreateOrganizationMutation(\n $input: CreateOrganizationInput!\n) {\n createOrganization(input: $input) {\n organizationEdge {\n node {\n id\n name\n logoUrl\n }\n }\n }\n}\n" + "text": "mutation CreateOrganizationViewCreateOrganizationMutation(\n $input: CreateOrganizationInput!\n) {\n createOrganization(input: $input) {\n organizationEdge {\n node {\n id\n name\n logoUrl\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = "ec0da70244afe2faa02b05ee418b829e"; +(node as any).hash = "999f210db4fc65cbad47472294d9cf46"; export default node; diff --git a/apps/console/src/pages/organizations/__generated__/CreateOrganizationPageViewerQuery.graphql.ts b/apps/console/src/pages/organizations/__generated__/CreateOrganizationViewViewerQuery.graphql.ts similarity index 62% rename from apps/console/src/pages/organizations/__generated__/CreateOrganizationPageViewerQuery.graphql.ts rename to apps/console/src/pages/organizations/__generated__/CreateOrganizationViewViewerQuery.graphql.ts index 208f22160..419924e97 100644 --- a/apps/console/src/pages/organizations/__generated__/CreateOrganizationPageViewerQuery.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/CreateOrganizationViewViewerQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<371bd1a7433b281f20dd8925915a7ff2>> + * @generated SignedSource<<4f30528c9f1b2def73d7058623843697>> * @lightSyntaxTransform * @nogrep */ @@ -9,15 +9,15 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type CreateOrganizationPageViewerQuery$variables = Record; -export type CreateOrganizationPageViewerQuery$data = { +export type CreateOrganizationViewViewerQuery$variables = Record; +export type CreateOrganizationViewViewerQuery$data = { readonly viewer: { readonly id: string; }; }; -export type CreateOrganizationPageViewerQuery = { - response: CreateOrganizationPageViewerQuery$data; - variables: CreateOrganizationPageViewerQuery$variables; +export type CreateOrganizationViewViewerQuery = { + response: CreateOrganizationViewViewerQuery$data; + variables: CreateOrganizationViewViewerQuery$variables; }; const node: ConcreteRequest = (function(){ @@ -46,7 +46,7 @@ return { "argumentDefinitions": [], "kind": "Fragment", "metadata": null, - "name": "CreateOrganizationPageViewerQuery", + "name": "CreateOrganizationViewViewerQuery", "selections": (v0/*: any*/), "type": "Query", "abstractKey": null @@ -55,20 +55,20 @@ return { "operation": { "argumentDefinitions": [], "kind": "Operation", - "name": "CreateOrganizationPageViewerQuery", + "name": "CreateOrganizationViewViewerQuery", "selections": (v0/*: any*/) }, "params": { - "cacheID": "8bb495e88bada2ffda332ffbc11f3340", + "cacheID": "70c2f23f09fbeac5b8e8436e6c68b5f6", "id": null, "metadata": {}, - "name": "CreateOrganizationPageViewerQuery", + "name": "CreateOrganizationViewViewerQuery", "operationKind": "query", - "text": "query CreateOrganizationPageViewerQuery {\n viewer {\n id\n }\n}\n" + "text": "query CreateOrganizationViewViewerQuery {\n viewer {\n id\n }\n}\n" } }; })(); -(node as any).hash = "2341c7947749857243e9f492235dfd61"; +(node as any).hash = "200816c6c6173d8c7a4e5bcdab45dc45"; export default node; diff --git a/apps/console/src/pages/organizations/__generated__/SettingsPageInviteUserMutation.graphql.ts b/apps/console/src/pages/organizations/__generated__/SettingsViewInviteUserMutation.graphql.ts similarity index 70% rename from apps/console/src/pages/organizations/__generated__/SettingsPageInviteUserMutation.graphql.ts rename to apps/console/src/pages/organizations/__generated__/SettingsViewInviteUserMutation.graphql.ts index 2875d6892..8ccc8d6a4 100644 --- a/apps/console/src/pages/organizations/__generated__/SettingsPageInviteUserMutation.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/SettingsViewInviteUserMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<7eb47f6f0589a4b7c7e65fd4c313422c>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -14,17 +14,17 @@ export type InviteUserInput = { fullName: string; organizationId: string; }; -export type SettingsPageInviteUserMutation$variables = { +export type SettingsViewInviteUserMutation$variables = { input: InviteUserInput; }; -export type SettingsPageInviteUserMutation$data = { +export type SettingsViewInviteUserMutation$data = { readonly inviteUser: { readonly success: boolean; }; }; -export type SettingsPageInviteUserMutation = { - response: SettingsPageInviteUserMutation$data; - variables: SettingsPageInviteUserMutation$variables; +export type SettingsViewInviteUserMutation = { + response: SettingsViewInviteUserMutation$data; + variables: SettingsViewInviteUserMutation$variables; }; const node: ConcreteRequest = (function(){ @@ -66,7 +66,7 @@ return { "argumentDefinitions": (v0/*: any*/), "kind": "Fragment", "metadata": null, - "name": "SettingsPageInviteUserMutation", + "name": "SettingsViewInviteUserMutation", "selections": (v1/*: any*/), "type": "Mutation", "abstractKey": null @@ -75,20 +75,20 @@ return { "operation": { "argumentDefinitions": (v0/*: any*/), "kind": "Operation", - "name": "SettingsPageInviteUserMutation", + "name": "SettingsViewInviteUserMutation", "selections": (v1/*: any*/) }, "params": { - "cacheID": "732d61a66a202dc879bb81c72fb2fb24", + "cacheID": "08abe9c261dc68b1c76991ad5e6f4d95", "id": null, "metadata": {}, - "name": "SettingsPageInviteUserMutation", + "name": "SettingsViewInviteUserMutation", "operationKind": "mutation", - "text": "mutation SettingsPageInviteUserMutation(\n $input: InviteUserInput!\n) {\n inviteUser(input: $input) {\n success\n }\n}\n" + "text": "mutation SettingsViewInviteUserMutation(\n $input: InviteUserInput!\n) {\n inviteUser(input: $input) {\n success\n }\n}\n" } }; })(); -(node as any).hash = "d09b74116ff70680029667104b5b34db"; +(node as any).hash = "5e95d05ee3c0d58f9413790a4a9516bf"; export default node; diff --git a/apps/console/src/pages/organizations/__generated__/SettingsPageQuery.graphql.ts b/apps/console/src/pages/organizations/__generated__/SettingsViewQuery.graphql.ts similarity index 89% rename from apps/console/src/pages/organizations/__generated__/SettingsPageQuery.graphql.ts rename to apps/console/src/pages/organizations/__generated__/SettingsViewQuery.graphql.ts index 451ea27bf..6542a59b1 100644 --- a/apps/console/src/pages/organizations/__generated__/SettingsPageQuery.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/SettingsViewQuery.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<7fcee268b2974653bc3734b49b4082a4>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -9,10 +9,10 @@ // @ts-nocheck import { ConcreteRequest } from 'relay-runtime'; -export type SettingsPageQuery$variables = { +export type SettingsViewQuery$variables = { organizationID: string; }; -export type SettingsPageQuery$data = { +export type SettingsViewQuery$data = { readonly organization: { readonly id: string; readonly logoUrl?: string | null | undefined; @@ -29,9 +29,9 @@ export type SettingsPageQuery$data = { }; }; }; -export type SettingsPageQuery = { - response: SettingsPageQuery$data; - variables: SettingsPageQuery$variables; +export type SettingsViewQuery = { + response: SettingsViewQuery$data; + variables: SettingsViewQuery$variables; }; const node: ConcreteRequest = (function(){ @@ -143,7 +143,7 @@ return { "argumentDefinitions": (v0/*: any*/), "kind": "Fragment", "metadata": null, - "name": "SettingsPageQuery", + "name": "SettingsViewQuery", "selections": [ { "alias": "organization", @@ -166,7 +166,7 @@ return { "operation": { "argumentDefinitions": (v0/*: any*/), "kind": "Operation", - "name": "SettingsPageQuery", + "name": "SettingsViewQuery", "selections": [ { "alias": "organization", @@ -191,16 +191,16 @@ return { ] }, "params": { - "cacheID": "de417aa8583ad2d1cc7ef18223a4dc2d", + "cacheID": "1749c3e17b6efd13be678a0e968b7ac4", "id": null, "metadata": {}, - "name": "SettingsPageQuery", + "name": "SettingsViewQuery", "operationKind": "query", - "text": "query SettingsPageQuery(\n $organizationID: ID!\n) {\n organization: node(id: $organizationID) {\n __typename\n id\n ... on Organization {\n name\n logoUrl\n users(first: 100) {\n edges {\n node {\n id\n fullName\n email\n createdAt\n }\n }\n }\n }\n }\n}\n" + "text": "query SettingsViewQuery(\n $organizationID: ID!\n) {\n organization: node(id: $organizationID) {\n __typename\n id\n ... on Organization {\n name\n logoUrl\n users(first: 100) {\n edges {\n node {\n id\n fullName\n email\n createdAt\n }\n }\n }\n }\n }\n}\n" } }; })(); -(node as any).hash = "1d9482689dd9f305ca7a45fdf4ab088c"; +(node as any).hash = "147757d21500b3eb42848ebe8a43bd9f"; export default node; diff --git a/apps/console/src/pages/organizations/__generated__/SettingsPageRemoveUserMutation.graphql.ts b/apps/console/src/pages/organizations/__generated__/SettingsViewRemoveUserMutation.graphql.ts similarity index 69% rename from apps/console/src/pages/organizations/__generated__/SettingsPageRemoveUserMutation.graphql.ts rename to apps/console/src/pages/organizations/__generated__/SettingsViewRemoveUserMutation.graphql.ts index e53ee0d9e..c079cb2b2 100644 --- a/apps/console/src/pages/organizations/__generated__/SettingsPageRemoveUserMutation.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/SettingsViewRemoveUserMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<9d909d5fc7076593317b01aab165513d>> + * @generated SignedSource<<83fe53df5d49d9e2441a2e02dfaa63ee>> * @lightSyntaxTransform * @nogrep */ @@ -13,17 +13,17 @@ export type RemoveUserInput = { organizationId: string; userId: string; }; -export type SettingsPageRemoveUserMutation$variables = { +export type SettingsViewRemoveUserMutation$variables = { input: RemoveUserInput; }; -export type SettingsPageRemoveUserMutation$data = { +export type SettingsViewRemoveUserMutation$data = { readonly removeUser: { readonly success: boolean; }; }; -export type SettingsPageRemoveUserMutation = { - response: SettingsPageRemoveUserMutation$data; - variables: SettingsPageRemoveUserMutation$variables; +export type SettingsViewRemoveUserMutation = { + response: SettingsViewRemoveUserMutation$data; + variables: SettingsViewRemoveUserMutation$variables; }; const node: ConcreteRequest = (function(){ @@ -65,7 +65,7 @@ return { "argumentDefinitions": (v0/*: any*/), "kind": "Fragment", "metadata": null, - "name": "SettingsPageRemoveUserMutation", + "name": "SettingsViewRemoveUserMutation", "selections": (v1/*: any*/), "type": "Mutation", "abstractKey": null @@ -74,20 +74,20 @@ return { "operation": { "argumentDefinitions": (v0/*: any*/), "kind": "Operation", - "name": "SettingsPageRemoveUserMutation", + "name": "SettingsViewRemoveUserMutation", "selections": (v1/*: any*/) }, "params": { - "cacheID": "62588cd355b82b5a48d0b539a009b3bd", + "cacheID": "4a8d30e01815dbee5f216bbacf9f39e6", "id": null, "metadata": {}, - "name": "SettingsPageRemoveUserMutation", + "name": "SettingsViewRemoveUserMutation", "operationKind": "mutation", - "text": "mutation SettingsPageRemoveUserMutation(\n $input: RemoveUserInput!\n) {\n removeUser(input: $input) {\n success\n }\n}\n" + "text": "mutation SettingsViewRemoveUserMutation(\n $input: RemoveUserInput!\n) {\n removeUser(input: $input) {\n success\n }\n}\n" } }; })(); -(node as any).hash = "8d375bb2dfdab0f9d9520eee9f732b10"; +(node as any).hash = "a6446703d214b8c6c436aabed2d78dd7"; export default node; diff --git a/apps/console/src/pages/organizations/__generated__/SettingsPageUpdateOrganizationMutation.graphql.ts b/apps/console/src/pages/organizations/__generated__/SettingsViewUpdateOrganizationMutation.graphql.ts similarity index 77% rename from apps/console/src/pages/organizations/__generated__/SettingsPageUpdateOrganizationMutation.graphql.ts rename to apps/console/src/pages/organizations/__generated__/SettingsViewUpdateOrganizationMutation.graphql.ts index f3c60b462..3f9917940 100644 --- a/apps/console/src/pages/organizations/__generated__/SettingsPageUpdateOrganizationMutation.graphql.ts +++ b/apps/console/src/pages/organizations/__generated__/SettingsViewUpdateOrganizationMutation.graphql.ts @@ -1,5 +1,5 @@ /** - * @generated SignedSource<<76018198697d82d6f630558618c6aaff>> + * @generated SignedSource<> * @lightSyntaxTransform * @nogrep */ @@ -14,10 +14,10 @@ export type UpdateOrganizationInput = { name?: string | null | undefined; organizationId: string; }; -export type SettingsPageUpdateOrganizationMutation$variables = { +export type SettingsViewUpdateOrganizationMutation$variables = { input: UpdateOrganizationInput; }; -export type SettingsPageUpdateOrganizationMutation$data = { +export type SettingsViewUpdateOrganizationMutation$data = { readonly updateOrganization: { readonly organization: { readonly id: string; @@ -26,9 +26,9 @@ export type SettingsPageUpdateOrganizationMutation$data = { }; }; }; -export type SettingsPageUpdateOrganizationMutation = { - response: SettingsPageUpdateOrganizationMutation$data; - variables: SettingsPageUpdateOrganizationMutation$variables; +export type SettingsViewUpdateOrganizationMutation = { + response: SettingsViewUpdateOrganizationMutation$data; + variables: SettingsViewUpdateOrganizationMutation$variables; }; const node: ConcreteRequest = (function(){ @@ -95,7 +95,7 @@ return { "argumentDefinitions": (v0/*: any*/), "kind": "Fragment", "metadata": null, - "name": "SettingsPageUpdateOrganizationMutation", + "name": "SettingsViewUpdateOrganizationMutation", "selections": (v1/*: any*/), "type": "Mutation", "abstractKey": null @@ -104,20 +104,20 @@ return { "operation": { "argumentDefinitions": (v0/*: any*/), "kind": "Operation", - "name": "SettingsPageUpdateOrganizationMutation", + "name": "SettingsViewUpdateOrganizationMutation", "selections": (v1/*: any*/) }, "params": { - "cacheID": "2bf2a6e054aed9bd337372682342a30f", + "cacheID": "f2a2984a2d4e764019f4355c13dab46e", "id": null, "metadata": {}, - "name": "SettingsPageUpdateOrganizationMutation", + "name": "SettingsViewUpdateOrganizationMutation", "operationKind": "mutation", - "text": "mutation SettingsPageUpdateOrganizationMutation(\n $input: UpdateOrganizationInput!\n) {\n updateOrganization(input: $input) {\n organization {\n id\n name\n logoUrl\n }\n }\n}\n" + "text": "mutation SettingsViewUpdateOrganizationMutation(\n $input: UpdateOrganizationInput!\n) {\n updateOrganization(input: $input) {\n organization {\n id\n name\n logoUrl\n }\n }\n}\n" } }; })(); -(node as any).hash = "737ec44a08ac05e9f78827811cc0ca0e"; +(node as any).hash = "9570926c4f654570cbfe7328cd9893d6"; export default node; diff --git a/apps/console/src/pages/organizations/frameworks/CreateFrameworkPage.tsx b/apps/console/src/pages/organizations/frameworks/CreateFrameworkPage.tsx index a243c4d80..53302fbf6 100644 --- a/apps/console/src/pages/organizations/frameworks/CreateFrameworkPage.tsx +++ b/apps/console/src/pages/organizations/frameworks/CreateFrameworkPage.tsx @@ -1,215 +1,11 @@ -import { Suspense, useState } from "react"; -import { useNavigate, useParams } from "react-router"; -import { graphql, useMutation, ConnectionHandler } from "react-relay"; -import { Button } from "@/components/ui/button"; -import { Card } from "@/components/ui/card"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; -import { Textarea } from "@/components/ui/textarea"; -import { useToast } from "@/hooks/use-toast"; -import { HelpCircle } from "lucide-react"; -import { cn } from "@/lib/utils"; -import { CreateFrameworkPageCreateFrameworkMutation } from "./__generated__/CreateFrameworkPageCreateFrameworkMutation.graphql"; -import { PageTemplate, PageTemplateSkeleton } from "@/components/PageTemplate"; +import { PageTemplateSkeleton } from "@/components/PageTemplate"; +import { lazy, Suspense } from "react"; +import { useLocation } from "react-router"; +import { ErrorBoundaryWithLocation } from "../ErrorBoundary"; -const createFrameworkMutation = graphql` - mutation CreateFrameworkPageCreateFrameworkMutation( - $input: CreateFrameworkInput! - $connections: [ID!]! - ) { - createFramework(input: $input) { - frameworkEdge @prependEdge(connections: $connections) { - node { - id - name - description - } - } - } - } -`; +const CreateFrameworkView = lazy(() => import("./CreateFrameworkView")); -function EditableField({ - label, - value, - onChange, - type = "text", - helpText, - required, - multiline = false, -}: { - label: string; - value: string; - onChange: (value: string) => void; - type?: string; - helpText?: string; - required?: boolean; - multiline?: boolean; -}) { - return ( -
-
- - {helpText && ( -
- - {helpText} -
- )} -
- {multiline ? ( -