Add GQL mutation for updating domain (#50)
* Pass data for all domains in edit domain dialog box * Add mutation to update domain by id * implement front end and gql client method to edit domain * Rename arguments of resolver function to update domain and project --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
a34e2286a6
commit
fdf06f9bd0
@ -365,4 +365,16 @@ export class Database {
|
|||||||
|
|
||||||
return domains;
|
return domains;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateDomainById (domainId: string, updates: DeepPartial<Domain>): Promise<boolean> {
|
||||||
|
const domainRepository = this.dataSource.getRepository(Domain);
|
||||||
|
|
||||||
|
const updateResult = await domainRepository.update({ id: Number(domainId) }, updates);
|
||||||
|
|
||||||
|
if (updateResult.affected) {
|
||||||
|
return updateResult.affected > 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,9 +153,9 @@ export const createResolvers = async (db: Database): Promise<any> => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateProject: async (_: any, { projectId, updateProject }: { projectId: string, updateProject: { name: string, description: string } }) => {
|
updateProject: async (_: any, { projectId, projectDetails }: { projectId: string, projectDetails: { name: string, description: string } }) => {
|
||||||
try {
|
try {
|
||||||
return db.updateProjectById(projectId, updateProject);
|
return db.updateProjectById(projectId, projectDetails);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
@ -198,6 +198,16 @@ export const createResolvers = async (db: Database): Promise<any> => {
|
|||||||
log(err);
|
log(err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDomain: async (_: any, { domainId, domainDetails }: { domainId: string, domainDetails: {name?: string, isRedirected?: boolean, branch?: string }}) => {
|
||||||
|
try {
|
||||||
|
await db.updateDomainById(domainId, domainDetails);
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
log(err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -129,11 +129,12 @@ type Mutation {
|
|||||||
removeMember(memberId: String!): Boolean!
|
removeMember(memberId: String!): Boolean!
|
||||||
addEnvironmentVariables(projectId: String!, environmentVariables: [AddEnvironmentVariableInput!]): Boolean!
|
addEnvironmentVariables(projectId: String!, environmentVariables: [AddEnvironmentVariableInput!]): Boolean!
|
||||||
updateDeploymentToProd(deploymentId: String!): Boolean!
|
updateDeploymentToProd(deploymentId: String!): Boolean!
|
||||||
updateProject(projectId: String!, updateProject: UpdateProjectInput): Boolean!
|
updateProject(projectId: String!, projectDetails: UpdateProjectInput): Boolean!
|
||||||
redeployToProd(deploymentId: String!): Boolean!
|
redeployToProd(deploymentId: String!): Boolean!
|
||||||
deleteProject(projectId: String!): Boolean!
|
deleteProject(projectId: 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!
|
||||||
}
|
}
|
||||||
|
|
||||||
input AddEnvironmentVariableInput {
|
input AddEnvironmentVariableInput {
|
||||||
@ -150,3 +151,9 @@ input UpdateProjectInput {
|
|||||||
input AddDomainInput {
|
input AddDomainInput {
|
||||||
name: String!
|
name: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input UpdateDomainInput {
|
||||||
|
name: String
|
||||||
|
isRedirected: Boolean
|
||||||
|
branch: String
|
||||||
|
}
|
||||||
|
@ -24,9 +24,11 @@ enum RefreshStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DomainCardProps {
|
interface DomainCardProps {
|
||||||
|
domains: Domain[];
|
||||||
domain: Domain;
|
domain: Domain;
|
||||||
repo: RepositoryDetails;
|
repo: RepositoryDetails;
|
||||||
project: ProjectDetails;
|
project: ProjectDetails;
|
||||||
|
onUpdate: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds
|
const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds
|
||||||
@ -38,7 +40,13 @@ const DOMAIN_RECORD = {
|
|||||||
value: '56.49.19.21',
|
value: '56.49.19.21',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DomainCard = ({ domain, repo, project }: DomainCardProps) => {
|
const DomainCard = ({
|
||||||
|
domains,
|
||||||
|
domain,
|
||||||
|
repo,
|
||||||
|
project,
|
||||||
|
onUpdate,
|
||||||
|
}: DomainCardProps) => {
|
||||||
const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE);
|
const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE);
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
const [editDialogOpen, setEditDialogOpen] = useState(false);
|
||||||
@ -163,10 +171,11 @@ const DomainCard = ({ domain, repo, project }: DomainCardProps) => {
|
|||||||
handleOpen={() => {
|
handleOpen={() => {
|
||||||
setEditDialogOpen((preVal) => !preVal);
|
setEditDialogOpen((preVal) => !preVal);
|
||||||
}}
|
}}
|
||||||
|
domains={domains}
|
||||||
open={editDialogOpen}
|
open={editDialogOpen}
|
||||||
domain={domain}
|
domain={domain}
|
||||||
repo={repo}
|
repo={repo}
|
||||||
project={project}
|
onUpdate={onUpdate}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -55,10 +55,12 @@ const Domains = () => {
|
|||||||
{domains.map((domain) => {
|
{domains.map((domain) => {
|
||||||
return (
|
return (
|
||||||
<DomainCard
|
<DomainCard
|
||||||
|
domains={domains}
|
||||||
domain={domain}
|
domain={domain}
|
||||||
key={domain.id}
|
key={domain.id}
|
||||||
repo={linkedRepo!}
|
repo={linkedRepo!}
|
||||||
project={currentProject!}
|
project={currentProject!}
|
||||||
|
onUpdate={fetchDomains}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { Domain } from 'gql-client';
|
import { Domain } from 'gql-client';
|
||||||
@ -15,25 +15,30 @@ import {
|
|||||||
Option,
|
Option,
|
||||||
} from '@material-tailwind/react';
|
} from '@material-tailwind/react';
|
||||||
|
|
||||||
import { ProjectDetails, RepositoryDetails } from '../../../../types/project';
|
import { RepositoryDetails } from '../../../../types/project';
|
||||||
|
import { useGQLClient } from '../../../../context/GQLClientContext';
|
||||||
|
|
||||||
const DEFAULT_REDIRECT_OPTIONS = ['none'];
|
const DEFAULT_REDIRECT_OPTIONS = ['none'];
|
||||||
|
|
||||||
interface EditDomainDialogProp {
|
interface EditDomainDialogProp {
|
||||||
|
domains: Domain[];
|
||||||
open: boolean;
|
open: boolean;
|
||||||
handleOpen: () => void;
|
handleOpen: () => void;
|
||||||
domain: Domain;
|
domain: Domain;
|
||||||
repo: RepositoryDetails;
|
repo: RepositoryDetails;
|
||||||
project: ProjectDetails;
|
onUpdate: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditDomainDialog = ({
|
const EditDomainDialog = ({
|
||||||
|
domains,
|
||||||
open,
|
open,
|
||||||
handleOpen,
|
handleOpen,
|
||||||
domain,
|
domain,
|
||||||
repo,
|
repo,
|
||||||
project,
|
onUpdate,
|
||||||
}: EditDomainDialogProp) => {
|
}: EditDomainDialogProp) => {
|
||||||
|
const client = useGQLClient();
|
||||||
|
|
||||||
const getRedirectUrl = (domain: Domain) => {
|
const getRedirectUrl = (domain: Domain) => {
|
||||||
const domainArr = domain.name.split('www.');
|
const domainArr = domain.name.split('www.');
|
||||||
let redirectUrl = '';
|
let redirectUrl = '';
|
||||||
@ -45,12 +50,6 @@ const EditDomainDialog = ({
|
|||||||
return redirectUrl;
|
return redirectUrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
const domains = project.deployments
|
|
||||||
.filter((deployment: any) => {
|
|
||||||
return deployment.domain != null;
|
|
||||||
})
|
|
||||||
.map((deployment: any) => deployment.domain);
|
|
||||||
|
|
||||||
const redirectOptions = useMemo(() => {
|
const redirectOptions = useMemo(() => {
|
||||||
const redirectUrl = getRedirectUrl(domain);
|
const redirectUrl = getRedirectUrl(domain);
|
||||||
return [...DEFAULT_REDIRECT_OPTIONS, redirectUrl];
|
return [...DEFAULT_REDIRECT_OPTIONS, redirectUrl];
|
||||||
@ -63,9 +62,31 @@ const EditDomainDialog = ({
|
|||||||
(domain) => domain.name === redirectUrl,
|
(domain) => domain.name === redirectUrl,
|
||||||
);
|
);
|
||||||
|
|
||||||
return domainRedirected?.isRedirectedto;
|
return domainRedirected?.isRedirected;
|
||||||
}, [domain]);
|
}, [domain]);
|
||||||
|
|
||||||
|
const onSubmit = useCallback(
|
||||||
|
async (data: any) => {
|
||||||
|
const updates = {
|
||||||
|
name: data.name,
|
||||||
|
branch: data.branch,
|
||||||
|
isRedirected: data.redirectedTo !== 'none',
|
||||||
|
};
|
||||||
|
|
||||||
|
const { updateDomain } = await client.updateDomain(domain.id, updates);
|
||||||
|
|
||||||
|
if (updateDomain) {
|
||||||
|
await onUpdate();
|
||||||
|
toast.success(`Domain ${domain.name} has been updated`);
|
||||||
|
} else {
|
||||||
|
toast.error(`Error updating domain ${domain.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOpen();
|
||||||
|
},
|
||||||
|
[client],
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
register,
|
register,
|
||||||
@ -94,12 +115,7 @@ const EditDomainDialog = ({
|
|||||||
X
|
X
|
||||||
</Button>
|
</Button>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<form
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
onSubmit={handleSubmit(() => {
|
|
||||||
handleOpen();
|
|
||||||
toast.success(`Domain ${domain.name} has been updated`);
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<DialogBody className="flex flex-col gap-2 p-4">
|
<DialogBody className="flex flex-col gap-2 p-4">
|
||||||
<Typography variant="small">Domain name</Typography>
|
<Typography variant="small">Domain name</Typography>
|
||||||
<Input crossOrigin={undefined} {...register('name')} />
|
<Input crossOrigin={undefined} {...register('name')} />
|
||||||
|
@ -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, RemoveMemberResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse, RollbackDeploymentResponse, AddDomainInput, AddDomainResponse, GetDomainsResponse } from './types';
|
import { AddEnvironmentVariableInput, AddEnvironmentVariablesResponse, GetDeploymentsResponse, GetEnvironmentVariablesResponse, GetOrganizationsResponse, GetProjectMembersResponse, SearchProjectsResponse, GetUserResponse, RemoveMemberResponse, UpdateDeploymentToProdResponse, GetProjectResponse, UpdateProjectResponse, UpdateProjectInput, RedeployToProdResponse, DeleteProjectResponse, GetProjectsInOrganizationResponse, RollbackDeploymentResponse, AddDomainInput, AddDomainResponse, GetDomainsResponse, UpdateDomainInput, UpdateDomainResponse } from './types';
|
||||||
import { removeMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject, addDomain, rollbackDeployment } from './mutations';
|
import { removeMember, addEnvironmentVariables, updateDeploymentToProd, updateProjectMutation, redeployToProd, deleteProject, addDomain, rollbackDeployment, updateDomainMutation } from './mutations';
|
||||||
|
|
||||||
export interface GraphQLConfig {
|
export interface GraphQLConfig {
|
||||||
gqlEndpoint: string;
|
gqlEndpoint: string;
|
||||||
@ -147,12 +147,24 @@ export class GQLClient {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateProject (projectId: string, updateProject: UpdateProjectInput): Promise<UpdateProjectResponse> {
|
async updateProject (projectId: string, projectDetails: UpdateProjectInput): Promise<UpdateProjectResponse> {
|
||||||
const { data } = await this.client.mutate({
|
const { data } = await this.client.mutate({
|
||||||
mutation: updateProjectMutation,
|
mutation: updateProjectMutation,
|
||||||
variables: {
|
variables: {
|
||||||
projectId,
|
projectId,
|
||||||
updateProject
|
projectDetails
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateDomain (domainId: string, domainDetails: UpdateDomainInput): Promise<UpdateDomainResponse> {
|
||||||
|
const { data } = await this.client.mutate({
|
||||||
|
mutation: updateDomainMutation,
|
||||||
|
variables: {
|
||||||
|
domainId,
|
||||||
|
domainDetails
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,8 +19,13 @@ mutation ($deploymentId: String!) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const updateProjectMutation = gql`
|
export const updateProjectMutation = gql`
|
||||||
mutation ($projectId: String!, $updateProject: UpdateProjectInput) {
|
mutation ($projectId: String!, $projectDetails: UpdateProjectInput) {
|
||||||
updateProject(projectId: $projectId, updateProject: $updateProject)
|
updateProject(projectId: $projectId, projectDetails: $projectDetails)
|
||||||
|
}`;
|
||||||
|
|
||||||
|
export const updateDomainMutation = gql`
|
||||||
|
mutation ($domainId: String!, $domainDetails: UpdateDomainInput!) {
|
||||||
|
updateDomain(domainId: $domainId, domainDetails: $domainDetails)
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
export const redeployToProd = gql`
|
export const redeployToProd = gql`
|
||||||
|
@ -187,6 +187,10 @@ export type UpdateProjectResponse = {
|
|||||||
updateProject: boolean;
|
updateProject: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UpdateDomainResponse = {
|
||||||
|
updateDomain: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type DeleteProjectResponse = {
|
export type DeleteProjectResponse = {
|
||||||
deleteProject: boolean;
|
deleteProject: boolean;
|
||||||
}
|
}
|
||||||
@ -196,6 +200,12 @@ export type UpdateProjectInput = {
|
|||||||
description: string
|
description: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UpdateDomainInput = {
|
||||||
|
name?: string;
|
||||||
|
isRedirected?: boolean;
|
||||||
|
branch?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type RedeployToProdResponse = {
|
export type RedeployToProdResponse = {
|
||||||
redeployToProd: boolean
|
redeployToProd: boolean
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user