From 303b19f95fd9d5cc28cd0caaecebd9214de3f414 Mon Sep 17 00:00:00 2001 From: yaoweiprc <6896642+yaoweiprc@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:09:48 +0800 Subject: [PATCH] tmp save --- .../components/modals/project-edit-modal.tsx | 308 ++++++++++++++++++ packages/insomnia/src/ui/routes/project.tsx | 242 ++------------ 2 files changed, 330 insertions(+), 220 deletions(-) create mode 100644 packages/insomnia/src/ui/components/modals/project-edit-modal.tsx diff --git a/packages/insomnia/src/ui/components/modals/project-edit-modal.tsx b/packages/insomnia/src/ui/components/modals/project-edit-modal.tsx new file mode 100644 index 00000000000..1822e14f181 --- /dev/null +++ b/packages/insomnia/src/ui/components/modals/project-edit-modal.tsx @@ -0,0 +1,308 @@ +import React, { + type FC, + useMemo, + useState, +} from 'react'; +import { + Button, + Dialog, + Heading, + Input, + Label, + Modal, + ModalOverlay, + Radio, + RadioGroup, + TextField, +} from 'react-aria-components'; +import { + useNavigate, +} from 'react-router-dom'; + +import { getAppWebsiteBaseURL } from '../../../common/constants'; +import * as models from '../../../models'; +import { invariant } from '../../../utils/invariant'; +import { insomniaFetch } from '../../insomniaFetch'; +import { ORG_STORAGE_RULE } from '../../routes/organization'; +import { Icon } from '../icon'; +import { showAlert, showModal } from '.'; +import { AskModal } from './ask-modal'; + +export enum PROJECT_EDIT_MODAL_TYPE { + NEW = 'new', + EDIT = 'edit', +}; + +type ProjectType = 'local' | 'remote'; + +const ProjectEditModal: FC<{ + modalType: PROJECT_EDIT_MODAL_TYPE; + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; + orgStorageRule: ORG_STORAGE_RULE; + organizationId: string; + showStorageRestrictionMessage: boolean; +}> = ({ + modalType, + isOpen, + setIsOpen, + orgStorageRule, + organizationId, + showStorageRestrictionMessage, +}) => { + const [doesShowChangeStorageTypeConfirmation, setDoesShowChangeStorageTypeConfirmation] = useState(false); + const selectedStorageTypeRef + const title = useMemo(() => { + if (modalType === PROJECT_EDIT_MODAL_TYPE.NEW) { + return 'Create a New Project'; + } else if (modalType === PROJECT_EDIT_MODAL_TYPE.EDIT) { + if (!doesShowChangeStorageTypeConfirmation) { + return 'Project Settings'; + } else { + return 'haha'; + } + } else { + throw new Error(`Invalid modal type: ${modalType}`); + } + }, [modalType, doesShowChangeStorageTypeConfirmation]); + const navigate = useNavigate(); + const defaultStorageSelection = orgStorageRule === ORG_STORAGE_RULE.LOCAL_ONLY ? 'local' : 'remote'; + return ( setIsOpen(isOpen)} + isDismissable + className="w-full h-[--visual-viewport-height] fixed z-10 top-0 left-0 flex items-center justify-center bg-black/30" + > + + + {({ close }) => ( + + + {title} + + + + + { + e.preventDefault(); + const formData = new FormData(e.currentTarget); + const type = formData.get('type'); + + if (!type) { + showAlert({ + title: 'Project type not selected', + message: 'Please select a project type before continuing', + }); + return; + } + + const name = formData.get('name'); + + createNewProject({ + organizationId, + name: (typeof name === 'string') ? name : 'My project', + projectType: type as ProjectType, + }).then( + newProjectId => { + navigate(`/organization/${organizationId}/project/${newProjectId}`); + }, + err => { + const errMsg = err.message; + if (errMsg === 'NEEDS_TO_UPGRADE') { + showModal(AskModal, { + title: 'Upgrade your plan', + message: 'You are currently on the Free plan where you can invite as many collaborators as you want as long as you don\'t have more than one project. Since you have more than one project, you need to upgrade to "Individual" or above to continue.', + yesText: 'Upgrade', + noText: 'Cancel', + onDone: async (isYes: boolean) => { + if (isYes) { + window.main.openInBrowser(`${getAppWebsiteBaseURL()}/app/subscription/update?plan=individual`); + } + }, + }); + } else if (errMsg === 'FORBIDDEN') { + showAlert({ + title: 'Could not create project.', + message: 'You do not have permission to create a project in this organization.', + }); + } else { + showAlert({ + title: 'Could not create project.', + message: errMsg, + }); + } + }, + ); + + close(); + }} + > + + + Project name + + + + + + Project type + + + + + + Cloud Sync + + + Encrypted and synced securely to the cloud, ideal for out of the box collaboration. + + + + + + Local Vault + + + Stored locally only with no cloud. Ideal when collaboration is not needed. + + + + + + Local Vault + + + Stored locally only with no cloud. Ideal when collaboration is not needed. + + + + + + + + + {showStorageRestrictionMessage && `The organization owner mandates that projects must be created and stored ${orgStorageRule.split('_').join(' ')}.`} You can optionally enable Git Sync + + + + + Cancel + + + Create + + + + + + )} + + + ); + }; + +ProjectEditModal.displayName = 'NewProjectModal'; + +async function createNewProject({ + organizationId, + name, + projectType, +}: { + organizationId: string; + name: string; + projectType: ProjectType; +}) { + invariant(organizationId, 'Organization ID is required'); + invariant(typeof name === 'string', 'Name is required'); + invariant(projectType === 'local' || projectType === 'remote', 'Project type is required'); + + const user = await models.userSession.getOrCreate(); + const sessionId = user.id; + invariant(sessionId, 'User must be logged in to create a project'); + + if (projectType === 'local') { + const project = await models.project.create({ + name, + parentId: organizationId, + }); + return project._id; + } + + try { + const newCloudProject = await insomniaFetch<{ + id: string; + name: string; + } | { + error: string; + message?: string; + }>({ + path: `/v1/organizations/${organizationId}/team-projects`, + method: 'POST', + data: { + name, + }, + sessionId, + }); + + if (!newCloudProject || 'error' in newCloudProject) { + let error = 'An unexpected error occurred while creating the project. Please try again.'; + if (newCloudProject.error === 'FORBIDDEN') { + error = newCloudProject.error; + } + + if (newCloudProject.error === 'NEEDS_TO_UPGRADE') { + error = 'Upgrade your account in order to create new Cloud Projects.'; + } + + if (newCloudProject.error === 'PROJECT_STORAGE_RESTRICTION') { + error = newCloudProject.message ?? 'The owner of the organization allows only Local Vault project creation.'; + } + + throw new Error(error); + } + + const project = await models.project.create({ + _id: newCloudProject.id, + name: newCloudProject.name, + remoteId: newCloudProject.id, + parentId: organizationId, + }); + + return project._id; + } catch (err) { + throw new Error(err instanceof Error ? err.message : `An unexpected error occurred while creating the project. Please try again. ${err}`); + } +} + +export default ProjectEditModal; diff --git a/packages/insomnia/src/ui/routes/project.tsx b/packages/insomnia/src/ui/routes/project.tsx index bf0c6dfb373..790cc2f6234 100644 --- a/packages/insomnia/src/ui/routes/project.tsx +++ b/packages/insomnia/src/ui/routes/project.tsx @@ -85,6 +85,7 @@ import { AlertModal } from '../components/modals/alert-modal'; import { GitRepositoryCloneModal } from '../components/modals/git-repository-settings-modal/git-repo-clone-modal'; import { ImportModal } from '../components/modals/import-modal'; import { MockServerSettingsModal } from '../components/modals/mock-server-settings-modal'; +import ProjectEditModal, { PROJECT_EDIT_MODAL_TYPE } from '../components/modals/project-edit-modal'; import { EmptyStatePane } from '../components/panes/project-empty-state-pane'; import { TimeFromNow } from '../components/time-from-now'; import { useInsomniaEventStreamContext } from '../context/app/insomnia-event-stream-context'; @@ -960,8 +961,7 @@ const ProjectRoute: FC = () => { run: createNewGlobalEnvironment, }, }, - ]; - const defaultStorageSelection = storage === ORG_STORAGE_RULE.LOCAL_ONLY ? 'local' : 'remote'; + ]; const isRemoteProjectInconsistent = activeProject && isRemoteProject(activeProject) && storage === ORG_STORAGE_RULE.LOCAL_ONLY; const isLocalProjectInconsistent = activeProject && !isRemoteProject(activeProject) && storage === ORG_STORAGE_RULE.CLOUD_ONLY; const isProjectInconsistent = isRemoteProjectInconsistent || isLocalProjectInconsistent; @@ -1504,151 +1504,26 @@ const ProjectRoute: FC = () => { onHide={() => setIsGitRepositoryCloneModalOpen(false)} /> )} - setIsNewProjectModalOpen(isOpen)} isDismissable className="w-full h-[--visual-viewport-height] fixed z-10 top-0 left-0 flex items-center justify-center bg-black/30"> - - - {({ close }) => ( - - - Create a new project - - - - - { - e.preventDefault(); - const formData = new FormData(e.currentTarget); - const type = formData.get('type'); - - if (!type) { - showAlert({ - title: 'Project type not selected', - message: 'Please select a project type before continuing', - }); - return; - } - - const name = formData.get('name'); - - createNewProject({ - organizationId, - name: (typeof name === 'string') ? name : 'My project', - projectType: type as ProjectType, - }).then( - newProjectId => { - navigate(`/organization/${organizationId}/project/${newProjectId}`); - }, - err => { - const errMsg = err.message; - if (errMsg === 'NEEDS_TO_UPGRADE') { - showModal(AskModal, { - title: 'Upgrade your plan', - message: 'You are currently on the Free plan where you can invite as many collaborators as you want as long as you don\'t have more than one project. Since you have more than one project, you need to upgrade to "Individual" or above to continue.', - yesText: 'Upgrade', - noText: 'Cancel', - onDone: async (isYes: boolean) => { - if (isYes) { - window.main.openInBrowser(`${getAppWebsiteBaseURL()}/app/subscription/update?plan=individual`); - } - }, - }); - } else if (errMsg === 'FORBIDDEN') { - showAlert({ - title: 'Could not create project.', - message: 'You do not have permission to create a project in this organization.', - }); - } else { - showAlert({ - title: 'Could not create project.', - message: errMsg, - }); - } - }, - ); - - close(); - }} - > - - - Project name - - - - - - Project type - - - - - - Cloud Sync - - - Encrypted and synced securely to the cloud, ideal for out of the box collaboration. - - - - - - Local Vault - - - Stored locally only with no cloud. Ideal when collaboration is not needed. - - - - - - - - - {showStorageRestrictionMessage && `The organization owner mandates that projects must be created and stored ${storage.split('_').join(' ')}.`} You can optionally enable Git Sync - - - - - Cancel - - - Create - - - - - - )} - - - + + { @@ -1853,76 +1728,3 @@ const ProjectRoute: FC = () => { ProjectRoute.displayName = 'ProjectRoute'; export default ProjectRoute; - -type ProjectType = 'local' | 'remote'; - -async function createNewProject({ - organizationId, - name, - projectType, -}: { - organizationId: string; - name: string; - projectType: ProjectType; -}) { - invariant(organizationId, 'Organization ID is required'); - invariant(typeof name === 'string', 'Name is required'); - invariant(projectType === 'local' || projectType === 'remote', 'Project type is required'); - - const user = await models.userSession.getOrCreate(); - const sessionId = user.id; - invariant(sessionId, 'User must be logged in to create a project'); - - if (projectType === 'local') { - const project = await models.project.create({ - name, - parentId: organizationId, - }); - return project._id; - } - - try { - const newCloudProject = await insomniaFetch<{ - id: string; - name: string; - } | { - error: string; - message?: string; - }>({ - path: `/v1/organizations/${organizationId}/team-projects`, - method: 'POST', - data: { - name, - }, - sessionId, - }); - - if (!newCloudProject || 'error' in newCloudProject) { - let error = 'An unexpected error occurred while creating the project. Please try again.'; - if (newCloudProject.error === 'FORBIDDEN') { - error = newCloudProject.error; - } - - if (newCloudProject.error === 'NEEDS_TO_UPGRADE') { - error = 'Upgrade your account in order to create new Cloud Projects.'; - } - - if (newCloudProject.error === 'PROJECT_STORAGE_RESTRICTION') { - error = newCloudProject.message ?? 'The owner of the organization allows only Local Vault project creation.'; - } - - throw new Error(error); - } - - const project = await models.project.create({ - _id: newCloudProject.id, - name: newCloudProject.name, - remoteId: newCloudProject.id, - parentId: organizationId, - }); - - return project._id; - } catch (err) { - throw new Error(err instanceof Error ? err.message : `An unexpected error occurred while creating the project. Please try again. ${err}`); - } -}
+ Encrypted and synced securely to the cloud, ideal for out of the box collaboration. +
+ Stored locally only with no cloud. Ideal when collaboration is not needed. +
- Encrypted and synced securely to the cloud, ideal for out of the box collaboration. -
- Stored locally only with no cloud. Ideal when collaboration is not needed. -