forked from cerc-io/snowballtools-base
		
	Implement functionality to delete domain (#59)
* Implement functionality to delete domain * Remove redirectToId from frontend --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
		
							parent
							
								
									3a7f16467e
								
							
						
					
					
						commit
						1d58beb2ec
					
				| @ -347,6 +347,28 @@ export class Database { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   async deleteDomainById (domainId: string): Promise<boolean> { | ||||||
|  |     const domainRepository = this.dataSource.getRepository(Domain); | ||||||
|  | 
 | ||||||
|  |     const domainsRedirectedFrom = await domainRepository.find({ | ||||||
|  |       where: { | ||||||
|  |         redirectToId: Number(domainId) | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     if (domainsRedirectedFrom.length > 0) { | ||||||
|  |       throw new Error('Cannot delete domain since it has redirects from other domains'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const deleteResult = await domainRepository.softDelete({ id: Number(domainId) }); | ||||||
|  | 
 | ||||||
|  |     if (deleteResult.affected) { | ||||||
|  |       return deleteResult.affected > 0; | ||||||
|  |     } else { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   async rollbackDeploymentById (projectId: string, deploymentId: string): Promise<boolean> { |   async rollbackDeploymentById (projectId: string, deploymentId: string): Promise<boolean> { | ||||||
|     const deploymentRepository = this.dataSource.getRepository(Deployment); |     const deploymentRepository = this.dataSource.getRepository(Deployment); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,7 +5,8 @@ import { | |||||||
|   CreateDateColumn, |   CreateDateColumn, | ||||||
|   UpdateDateColumn, |   UpdateDateColumn, | ||||||
|   ManyToOne, |   ManyToOne, | ||||||
|   JoinColumn |   JoinColumn, | ||||||
|  |   DeleteDateColumn | ||||||
| } from 'typeorm'; | } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| import { Project } from './Project'; | import { Project } from './Project'; | ||||||
| @ -52,4 +53,7 @@ export class Domain { | |||||||
| 
 | 
 | ||||||
|   @UpdateDateColumn() |   @UpdateDateColumn() | ||||||
|     updatedAt!: Date; |     updatedAt!: Date; | ||||||
|  | 
 | ||||||
|  |   @DeleteDateColumn() | ||||||
|  |     deletedAt?: Date; | ||||||
| } | } | ||||||
|  | |||||||
| @ -216,6 +216,16 @@ export const createResolvers = async (db: Database, app: OAuthApp): Promise<any> | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
| 
 | 
 | ||||||
|  |       deleteDomain: async (_: any, { domainId }: { domainId: string }) => { | ||||||
|  |         try { | ||||||
|  |           await db.deleteDomainById(domainId); | ||||||
|  |           return true; | ||||||
|  |         } catch (err) { | ||||||
|  |           log(err); | ||||||
|  |           return false; | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  | 
 | ||||||
|       rollbackDeployment: async (_: any, { projectId, deploymentId }: {deploymentId: string, projectId: string }) => { |       rollbackDeployment: async (_: any, { projectId, deploymentId }: {deploymentId: string, projectId: string }) => { | ||||||
|         try { |         try { | ||||||
|           return db.rollbackDeploymentById(projectId, deploymentId); |           return db.rollbackDeploymentById(projectId, deploymentId); | ||||||
|  | |||||||
| @ -141,6 +141,7 @@ type Mutation { | |||||||
|   updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean! |   updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean! | ||||||
|   redeployToProd(deploymentId: String!): Boolean! |   redeployToProd(deploymentId: String!): Boolean! | ||||||
|   deleteProject(projectId: String!): Boolean! |   deleteProject(projectId: String!): Boolean! | ||||||
|  |   deleteDomain(domainId: String!): Boolean! | ||||||
|   rollbackDeployment(projectId: String!, deploymentId: String!): Boolean! |   rollbackDeployment(projectId: String!, deploymentId: String!): Boolean! | ||||||
|   addDomain(projectId: String!, domainDetails: AddDomainInput!): Boolean! |   addDomain(projectId: String!, domainDetails: AddDomainInput!): Boolean! | ||||||
|   updateDomain(domainId: String!, domainDetails: UpdateDomainInput!): Boolean! |   updateDomain(domainId: String!, domainDetails: UpdateDomainInput!): Boolean! | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
|     "updatedAt": "2023-12-21T08:30:00", |     "updatedAt": "2023-12-21T08:30:00", | ||||||
|     "user": "bob", |     "user": "bob", | ||||||
|     "private": false, |     "private": false, | ||||||
|     "branch": ["main", "prod", "dev"] |     "branch": ["main", "prod", "test"] | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "id": 2, |     "id": 2, | ||||||
| @ -13,7 +13,7 @@ | |||||||
|     "updatedAt": "2023-12-21T08:30:00", |     "updatedAt": "2023-12-21T08:30:00", | ||||||
|     "user": "alice", |     "user": "alice", | ||||||
|     "private": true, |     "private": true, | ||||||
|     "branch": ["main", "prod", "dev"] |     "branch": ["main", "prod", "test"] | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "id": 3, |     "id": 3, | ||||||
| @ -21,7 +21,7 @@ | |||||||
|     "updatedAt": "2023-12-21T04:20:00", |     "updatedAt": "2023-12-21T04:20:00", | ||||||
|     "user": "charlie", |     "user": "charlie", | ||||||
|     "private": false, |     "private": false, | ||||||
|     "branch": ["main", "prod", "dev"] |     "branch": ["main", "prod", "test"] | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "id": 4, |     "id": 4, | ||||||
| @ -29,7 +29,7 @@ | |||||||
|     "updatedAt": "2023-12-21T04:27:00", |     "updatedAt": "2023-12-21T04:27:00", | ||||||
|     "user": "alice", |     "user": "alice", | ||||||
|     "private": false, |     "private": false, | ||||||
|     "branch": ["main", "prod", "dev"] |     "branch": ["main", "prod", "test"] | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "id": 5, |     "id": 5, | ||||||
| @ -37,6 +37,6 @@ | |||||||
|     "updatedAt": "2023-12-21T04:41:00", |     "updatedAt": "2023-12-21T04:41:00", | ||||||
|     "user": "ivan", |     "user": "ivan", | ||||||
|     "private": false, |     "private": false, | ||||||
|     "branch": ["main", "prod", "dev"] |     "branch": ["main", "prod", "test"] | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ import { | |||||||
| import { ProjectDetails, RepositoryDetails } from '../../../../types/project'; | import { ProjectDetails, RepositoryDetails } from '../../../../types/project'; | ||||||
| import ConfirmDialog from '../../../shared/ConfirmDialog'; | import ConfirmDialog from '../../../shared/ConfirmDialog'; | ||||||
| import EditDomainDialog from './EditDomainDialog'; | import EditDomainDialog from './EditDomainDialog'; | ||||||
|  | import { useGQLClient } from '../../../../context/GQLClientContext'; | ||||||
| 
 | 
 | ||||||
| enum RefreshStatus { | enum RefreshStatus { | ||||||
|   IDLE, |   IDLE, | ||||||
| @ -51,6 +52,19 @@ const DomainCard = ({ | |||||||
|   const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); |   const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); | ||||||
|   const [editDialogOpen, setEditDialogOpen] = useState(false); |   const [editDialogOpen, setEditDialogOpen] = useState(false); | ||||||
| 
 | 
 | ||||||
|  |   const client = useGQLClient(); | ||||||
|  | 
 | ||||||
|  |   const deleteDomain = async () => { | ||||||
|  |     const { deleteDomain } = await client.deleteDomain(domain.id); | ||||||
|  | 
 | ||||||
|  |     if (deleteDomain) { | ||||||
|  |       onUpdate(); | ||||||
|  |       toast.success(`Domain ${domain.name} deleted successfully`); | ||||||
|  |     } else { | ||||||
|  |       toast.error(`Error deleting domain ${domain.name}`); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <div className="flex justify-between py-3"> |       <div className="flex justify-between py-3"> | ||||||
| @ -109,8 +123,8 @@ const DomainCard = ({ | |||||||
|           open={deleteDialogOpen} |           open={deleteDialogOpen} | ||||||
|           confirmButtonTitle="Yes, Delete domain" |           confirmButtonTitle="Yes, Delete domain" | ||||||
|           handleConfirm={() => { |           handleConfirm={() => { | ||||||
|  |             deleteDomain(); | ||||||
|             setDeleteDialogOpen((preVal) => !preVal); |             setDeleteDialogOpen((preVal) => !preVal); | ||||||
|             toast.success(`Domain "${domain.name}" has been deleted`); |  | ||||||
|           }} |           }} | ||||||
|           color="red" |           color="red" | ||||||
|         > |         > | ||||||
|  | |||||||
| @ -1,12 +1,13 @@ | |||||||
| import React, { useEffect, useMemo, useState } from 'react'; | import React, { useEffect, useMemo, useState } from 'react'; | ||||||
| import { useParams, Link, useOutletContext } from 'react-router-dom'; | import { useParams, Link, useOutletContext } from 'react-router-dom'; | ||||||
|  | import { Domain } from 'gql-client'; | ||||||
| 
 | 
 | ||||||
| import { Button, Typography } from '@material-tailwind/react'; | import { Button, Typography } from '@material-tailwind/react'; | ||||||
| 
 | 
 | ||||||
| import DomainCard from './DomainCard'; | import DomainCard from './DomainCard'; | ||||||
| import { ProjectSearchOutletContext } from '../../../../types/project'; | import { ProjectSearchOutletContext } from '../../../../types/project'; | ||||||
| import { useGQLClient } from '../../../../context/GQLClientContext'; | import { useGQLClient } from '../../../../context/GQLClientContext'; | ||||||
| import { Domain } from 'gql-client'; | import repositories from '../../../../assets/repositories.json'; | ||||||
| 
 | 
 | ||||||
| const Domains = () => { | const Domains = () => { | ||||||
|   const { id } = useParams(); |   const { id } = useParams(); | ||||||
| @ -22,16 +23,6 @@ const Domains = () => { | |||||||
|     }); |     }); | ||||||
|   }, [id, projects]); |   }, [id, projects]); | ||||||
| 
 | 
 | ||||||
|   // TODO: Use github API for getting linked repository
 |  | ||||||
|   const linkedRepo = { |  | ||||||
|     id: 3, |  | ||||||
|     title: 'project-103', |  | ||||||
|     updatedAt: '2023-12-21T04:20:00', |  | ||||||
|     user: 'charlie', |  | ||||||
|     private: false, |  | ||||||
|     branch: ['main', 'prod', 'test'], |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   const fetchDomains = async () => { |   const fetchDomains = async () => { | ||||||
|     if (currentProject === undefined) { |     if (currentProject === undefined) { | ||||||
|       return; |       return; | ||||||
| @ -62,7 +53,8 @@ const Domains = () => { | |||||||
|             domains={domains} |             domains={domains} | ||||||
|             domain={domain} |             domain={domain} | ||||||
|             key={domain.id} |             key={domain.id} | ||||||
|             repo={linkedRepo!} |             // TODO: Use github API for getting linked repository
 | ||||||
|  |             repo={repositories[0]!} | ||||||
|             project={currentProject!} |             project={currentProject!} | ||||||
|             onUpdate={fetchDomains} |             onUpdate={fetchDomains} | ||||||
|           /> |           /> | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ const EditDomainDialog = ({ | |||||||
|   }, [domains, domain]); |   }, [domains, domain]); | ||||||
| 
 | 
 | ||||||
|   const isDisableDropdown = useMemo(() => { |   const isDisableDropdown = useMemo(() => { | ||||||
|     return domainRedirectedFrom?.redirectTo?.id !== undefined; |     return domainRedirectedFrom !== undefined; | ||||||
|   }, [domain, domains]); |   }, [domain, domains]); | ||||||
| 
 | 
 | ||||||
|   const { |   const { | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client'; | import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client'; | ||||||
| 
 | 
 | ||||||
| import { getUser, getOrganizations, getDeployments, getProjectMembers, searchProjects, getEnvironmentVariables, getProject, getDomains, getProjectsInOrganization } from './queries'; | import { getUser, getOrganizations, getDeployments, getProjectMembers, searchProjects, getEnvironmentVariables, getProject, getDomains, getProjectsInOrganization } from './queries'; | ||||||
| import { AddEnvironmentVariableInput, AddEnvironmentVariablesResponse, GetDeploymentsResponse, GetEnvironmentVariablesResponse, GetOrganizationsResponse, GetProjectMembersResponse, SearchProjectsResponse, GetUserResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse, RollbackDeploymentResponse, AddDomainInput, AddDomainResponse, GetDomainsResponse, UpdateDomainInput, UpdateDomainResponse, AuthenticateGitHubResponse, UnauthenticateGitHubResponse, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableInput, RemoveEnvironmentVariableResponse, UpdateProjectMemberInput, RemoveProjectMemberResponse, UpdateProjectMemberResponse } from './types'; | import { AddEnvironmentVariableInput, AddEnvironmentVariablesResponse, GetDeploymentsResponse, GetEnvironmentVariablesResponse, GetOrganizationsResponse, GetProjectMembersResponse, SearchProjectsResponse, GetUserResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse, RollbackDeploymentResponse, AddDomainInput, AddDomainResponse, GetDomainsResponse, UpdateDomainInput, UpdateDomainResponse, AuthenticateGitHubResponse, UnauthenticateGitHubResponse, UpdateEnvironmentVariableResponse, UpdateEnvironmentVariableInput, RemoveEnvironmentVariableResponse, UpdateProjectMemberInput, RemoveProjectMemberResponse, UpdateProjectMemberResponse, DeleteDomainResponse } from './types'; | ||||||
| import { removeProjectMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject, addDomain, rollbackDeployment, updateDomainMutation, authenticateGitHub, unauthenticateGitHub, updateEnvironmentVariable, removeEnvironmentVariable, updateProjectMember } from './mutations'; | import { removeProjectMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject, addDomain, rollbackDeployment, updateDomainMutation, authenticateGitHub, unauthenticateGitHub, updateEnvironmentVariable, removeEnvironmentVariable, updateProjectMember, deleteDomain } from './mutations'; | ||||||
| 
 | 
 | ||||||
| export interface GraphQLConfig { | export interface GraphQLConfig { | ||||||
|   gqlEndpoint: string; |   gqlEndpoint: string; | ||||||
| @ -228,6 +228,17 @@ export class GQLClient { | |||||||
|     return data; |     return data; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   async deleteDomain (domainId: string): Promise<DeleteDomainResponse> { | ||||||
|  |     const { data } = await this.client.mutate({ | ||||||
|  |       mutation: deleteDomain, | ||||||
|  |       variables: { | ||||||
|  |         domainId | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   async rollbackDeployment (projectId: string, deploymentId: string): Promise<RollbackDeploymentResponse> { |   async rollbackDeployment (projectId: string, deploymentId: string): Promise<RollbackDeploymentResponse> { | ||||||
|     const { data } = await this.client.mutate({ |     const { data } = await this.client.mutate({ | ||||||
|       mutation: rollbackDeployment, |       mutation: rollbackDeployment, | ||||||
|  | |||||||
| @ -58,6 +58,11 @@ mutation ($projectId: String!) { | |||||||
| } | } | ||||||
| `;
 | `;
 | ||||||
| 
 | 
 | ||||||
|  | export const deleteDomain = gql` | ||||||
|  | mutation ($domainId: String!) { | ||||||
|  |   deleteDomain(domainId: $domainId) | ||||||
|  | }`;
 | ||||||
|  | 
 | ||||||
| export const rollbackDeployment = gql` | export const rollbackDeployment = gql` | ||||||
| mutation ($projectId: String! ,$deploymentId: String!) { | mutation ($projectId: String! ,$deploymentId: String!) { | ||||||
|   rollbackDeployment(projectId: $projectId, deploymentId: $deploymentId) |   rollbackDeployment(projectId: $projectId, deploymentId: $deploymentId) | ||||||
|  | |||||||
| @ -218,6 +218,10 @@ export type DeleteProjectResponse = { | |||||||
|   deleteProject: boolean; |   deleteProject: boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export type DeleteDomainResponse = { | ||||||
|  |   deleteDomain: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export type UpdateProjectInput = { | export type UpdateProjectInput = { | ||||||
|   name: string |   name: string | ||||||
|   description: string |   description: string | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user