Set subdomain for project and set URL for each deployment (#52)

* Display current deployment info in overview tab

* Add assign domain dialog box in deployments

* Add empty link for project settings in assign domain dialog box

* Use react router dom link

* Add sub domain to project entity

* Add deployment url with custom generated string

* Set nano id to deployment id

* Add sub domain while creating new project

* Use same id as in url

* Update readme steps for production build

* Update README

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
2024-02-05 14:56:28 +05:30
committed by GitHub
co-authored by neeraj
parent 0fdc2631ee
commit ac7064afa5
20 changed files with 460 additions and 57 deletions
@@ -1,4 +1,5 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Project } from 'gql-client';
import { Button, Typography } from '@material-tailwind/react';
@@ -16,14 +17,14 @@ const DEFAULT_FILTER_VALUE: FilterValue = {
status: StatusOptions.ALL_STATUS,
};
const DeploymentsTabPanel = ({ projectId }: { projectId: string }) => {
const DeploymentsTabPanel = ({ project }: { project: Project }) => {
const client = useGQLClient();
const [filterValue, setFilterValue] = useState(DEFAULT_FILTER_VALUE);
const [deployments, setDeployments] = useState<DeploymentDetails[]>([]);
const fetchDeployments = async () => {
const { deployments } = await client.getDeployments(projectId);
const { deployments } = await client.getDeployments(project.id);
const updatedDeployments = deployments.map((deployment) => {
return {
...deployment,
@@ -91,7 +92,7 @@ const DeploymentsTabPanel = ({ projectId }: { projectId: string }) => {
key={key}
currentDeployment={currentDeployment!}
onUpdate={onUpdateDeploymenToProd}
projectId={projectId}
project={project}
/>
);
})
@@ -23,8 +23,7 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
<div className="grow">
<Typography>{project.name}</Typography>
<Typography variant="small" color="gray">
{project.deployments[0]?.domain?.name ??
'No Production Deployment'}
{project.subDomain}
</Typography>
</div>
</div>
@@ -55,22 +54,29 @@ const OverviewTabPanel = ({ project }: OverviewProps) => {
</Button>
)}
</div>
<div className="flex justify-between p-2 text-sm">
<p>^ Source</p>
<p>{project.deployments[0]?.branch}</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>^ Deployment</p>
<p className="text-blue-600">
{project.deployments[0]?.domain?.name}
</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>^ Created</p>
<p>
{relativeTimeMs(project.createdAt)} by ^ {project.owner.name}
</p>
</div>
{project.deployments.length !== 0 ? (
<>
<div className="flex justify-between p-2 text-sm">
<p>^ Source</p>
<p>{project.deployments[0]?.branch}</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>^ Deployment</p>
<p className="text-blue-600">
{project.deployments[0]?.domain?.name}
</p>
</div>
<div className="flex justify-between p-2 text-sm">
<p>^ Created</p>
<p>
{relativeTimeMs(project.deployments[0].createdAt)} by ^{' '}
{project.deployments[0].createdBy.name}
</p>
</div>
</>
) : (
<div>No current deployment found</div>
)}
</div>
<div className="col-span-2 p-2">
<div className="flex justify-between">
@@ -47,7 +47,7 @@ const ProjectTabs = ({ project, onUpdate }: ProjectTabsProps) => {
<OverviewTabPanel project={project} />
</TabPanel>
<TabPanel>
<DeploymentsTabPanel projectId={project.id} />
<DeploymentsTabPanel project={project} />
</TabPanel>
<TabPanel>
<Database />
@@ -0,0 +1,52 @@
import React from 'react';
import { CopyBlock, atomOneLight } from 'react-code-blocks';
import { Link } from 'react-router-dom';
import {
Button,
Dialog,
DialogHeader,
DialogBody,
DialogFooter,
} from '@material-tailwind/react';
interface AssignDomainProps {
open: boolean;
handleOpen: () => void;
}
const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
return (
<Dialog open={open} handler={handleOpen}>
<DialogHeader>Assign Domain</DialogHeader>
<DialogBody>
In order to assign a domain to your production deployments, configure it
in the{' '}
{/* TODO: Navigate to settings tab panel after clicking on project settings */}
<Link to="" className="text-light-blue-800 inline">
project settings{' '}
</Link>
(recommended). If you want to assign to this specific deployment,
however, you can do so using our command-line interface:
<CopyBlock
text="snowball alias <deployment> <domain>"
language=""
showLineNumbers={false}
theme={atomOneLight}
/>
</DialogBody>
<DialogFooter className="flex justify-start">
<Button
className="rounded-3xl"
variant="gradient"
color="blue"
onClick={handleOpen}
>
<span>Okay</span>
</Button>
</DialogFooter>
</Dialog>
);
};
export default AssignDomainDialog;
@@ -10,11 +10,12 @@ import {
ChipProps,
} from '@material-tailwind/react';
import toast from 'react-hot-toast';
import { Environment } from 'gql-client';
import { Environment, Project } from 'gql-client';
import { relativeTimeMs } from '../../../../utils/time';
import ConfirmDialog from '../../../shared/ConfirmDialog';
import DeploymentDialogBodyCard from './DeploymentDialogBodyCard';
import AssignDomainDialog from './AssignDomainDialog';
import { DeploymentDetails, Status } from '../../../../types/project';
import { useGQLClient } from '../../../../context/GQLClientContext';
@@ -22,7 +23,7 @@ interface DeployDetailsCardProps {
deployment: DeploymentDetails;
currentDeployment: DeploymentDetails;
onUpdate: () => Promise<void>;
projectId: string;
project: Project;
}
const STATUS_COLORS: { [key in Status]: ChipProps['color'] } = {
@@ -35,13 +36,14 @@ const DeploymentDetailsCard = ({
deployment,
currentDeployment,
onUpdate,
projectId,
project,
}: DeployDetailsCardProps) => {
const client = useGQLClient();
const [changeToProduction, setChangeToProduction] = useState(false);
const [redeployToProduction, setRedeployToProduction] = useState(false);
const [rollbackDeployment, setRollbackDeployment] = useState(false);
const [assignDomainDialog, setAssignDomainDialog] = useState(false);
const updateDeployment = async () => {
const isUpdated = await client.updateDeploymentToProd(deployment.id);
@@ -65,7 +67,7 @@ const DeploymentDetailsCard = ({
const rollbackDeploymentHandler = async () => {
const isRollbacked = await client.rollbackDeployment(
projectId,
project.id,
deployment.id,
);
if (isRollbacked) {
@@ -80,7 +82,7 @@ const DeploymentDetailsCard = ({
<div className="grid grid-cols-4 gap-2 border-b border-gray-300 p-3 my-2">
<div className="col-span-2">
<div className="flex">
<Typography className=" basis-3/4">{deployment.title}</Typography>
<Typography className=" basis-3/4">{deployment.url}</Typography>
<Chip
value={deployment.status}
color={STATUS_COLORS[deployment.status] ?? 'gray'}
@@ -110,7 +112,11 @@ const DeploymentDetailsCard = ({
</MenuHandler>
<MenuList>
<MenuItem>^ Visit</MenuItem>
<MenuItem>^ Assign domain</MenuItem>
<MenuItem
onClick={() => setAssignDomainDialog(!assignDomainDialog)}
>
^ Assign domain
</MenuItem>
{!(deployment.environment === Environment.Production) && (
<MenuItem
onClick={() => setChangeToProduction(!changeToProduction)}
@@ -235,6 +241,10 @@ const DeploymentDetailsCard = ({
</Typography>
</div>
</ConfirmDialog>
<AssignDomainDialog
open={assignDomainDialog}
handleOpen={() => setAssignDomainDialog(!assignDomainDialog)}
/>
</div>
);
};