Add confirm dialogs for deployment menu (#24)
* Add dialogs for deployment menu items * Populate deployment dialogs with dummy json * Pass production deployment as prop to deployment card --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
ef72a0351e
commit
fc2bdefe17
@ -1,8 +1,9 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"title": "nextjs-boilerplate-9t44zbky4dg-bygideon-projects",
|
||||
"status": "Building",
|
||||
"environment": "Production",
|
||||
"isProduction": true,
|
||||
"branch": "prod",
|
||||
"commit": {
|
||||
"hash": "9haif19",
|
||||
@ -12,9 +13,10 @@
|
||||
"updatedAt": "2023-12-11T04:20:00"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "nextjs-boilerplate-9232dwky4dg-bygideon-projects",
|
||||
"status": "Ready",
|
||||
"environment": "Preview",
|
||||
"isProduction": false,
|
||||
"branch": "prod",
|
||||
"commit": {
|
||||
"hash": "43de569",
|
||||
@ -24,9 +26,10 @@
|
||||
"updatedAt": "2023-12-11T04:20:00"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "nextjs-boilerplate-9saa22y4dg-bygideon-projects",
|
||||
"status": "Error",
|
||||
"environment": "Production",
|
||||
"isProduction": false,
|
||||
"branch": "main",
|
||||
"commit": {
|
||||
"hash": "4hdsf19",
|
||||
|
@ -3,13 +3,12 @@ import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { Button, Typography } from '@material-tailwind/react';
|
||||
|
||||
import deploymentData from '../../../assets/deployments.json';
|
||||
import DeployDetailsCard, {
|
||||
DeploymentDetails,
|
||||
} from './deployments/DeploymentDetailsCard';
|
||||
import DeploymentDetailsCard from './deployments/DeploymentDetailsCard';
|
||||
import FilterForm, {
|
||||
FilterValue,
|
||||
StatusOptions,
|
||||
} from './deployments/FilterForm';
|
||||
import { DeploymentDetails } from '../../../types/project';
|
||||
|
||||
const DEFAULT_FILTER_VALUE: FilterValue = {
|
||||
searchedBranch: '',
|
||||
@ -19,6 +18,12 @@ const DEFAULT_FILTER_VALUE: FilterValue = {
|
||||
const DeploymentsTabPanel = () => {
|
||||
const [filterValue, setFilterValue] = useState(DEFAULT_FILTER_VALUE);
|
||||
|
||||
const productionDeployment = useMemo(() => {
|
||||
return deploymentData.find((deployment) => {
|
||||
return deployment.isProduction === true;
|
||||
}) as DeploymentDetails;
|
||||
}, []);
|
||||
|
||||
const filteredDeployments = useMemo<DeploymentDetails[]>(() => {
|
||||
return deploymentData.filter((deployment) => {
|
||||
// Searched branch filter
|
||||
@ -55,7 +60,13 @@ const DeploymentsTabPanel = () => {
|
||||
<div className="mt-2">
|
||||
{Boolean(filteredDeployments.length) ? (
|
||||
filteredDeployments.map((deployment, key) => {
|
||||
return <DeployDetailsCard deployment={deployment} key={key} />;
|
||||
return (
|
||||
<DeploymentDetailsCard
|
||||
deployment={deployment}
|
||||
key={key}
|
||||
productionDeployment={productionDeployment}
|
||||
/>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="h-[50vh] bg-gray-100 flex rounded items-center justify-center">
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import {
|
||||
Menu,
|
||||
@ -11,28 +11,13 @@ import {
|
||||
} from '@material-tailwind/react';
|
||||
|
||||
import { relativeTime } from '../../../../utils/time';
|
||||
|
||||
export enum Status {
|
||||
BUILDING = 'Building',
|
||||
READY = 'Ready',
|
||||
ERROR = 'Error',
|
||||
}
|
||||
|
||||
export interface DeploymentDetails {
|
||||
title: string;
|
||||
status: Status;
|
||||
environment: string;
|
||||
branch: string;
|
||||
commit: {
|
||||
hash: string;
|
||||
message: string;
|
||||
};
|
||||
author: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
import ConfirmDialog from '../../../shared/ConfirmDialog';
|
||||
import DeploymentDialogBodyCard from './DeploymentDialogBodyCard';
|
||||
import { DeploymentDetails, Status } from '../../../../types/project';
|
||||
|
||||
interface DeployDetailsCardProps {
|
||||
deployment: DeploymentDetails;
|
||||
productionDeployment: DeploymentDetails;
|
||||
}
|
||||
|
||||
const STATUS_COLORS: { [key in Status]: ChipProps['color'] } = {
|
||||
@ -41,7 +26,14 @@ const STATUS_COLORS: { [key in Status]: ChipProps['color'] } = {
|
||||
[Status.ERROR]: 'red',
|
||||
};
|
||||
|
||||
const DeployDetailsCard = ({ deployment }: DeployDetailsCardProps) => {
|
||||
const DeploymentDetailsCard = ({
|
||||
deployment,
|
||||
productionDeployment,
|
||||
}: DeployDetailsCardProps) => {
|
||||
const [changeToProduction, setChangeToProduction] = useState(false);
|
||||
const [redeployToProduction, setRedeployToProduction] = useState(false);
|
||||
const [rollbackDeployment, setRollbackDeployment] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-4 gap-2 border-b border-gray-300 p-3 my-2">
|
||||
<div className="col-span-2">
|
||||
@ -54,7 +46,9 @@ const DeployDetailsCard = ({ deployment }: DeployDetailsCardProps) => {
|
||||
icon={<i>^</i>}
|
||||
/>
|
||||
</div>
|
||||
<Typography color="gray">{deployment.environment}</Typography>
|
||||
<Typography color="gray">
|
||||
{deployment.isProduction ? 'Production (Current)' : 'Preview'}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className="col-span-1">
|
||||
<Typography color="gray">^ {deployment.branch}</Typography>
|
||||
@ -73,15 +67,116 @@ const DeployDetailsCard = ({ deployment }: DeployDetailsCardProps) => {
|
||||
<MenuList>
|
||||
<MenuItem>^ Visit</MenuItem>
|
||||
<MenuItem>^ Assign domain</MenuItem>
|
||||
<MenuItem>^ Change to production</MenuItem>
|
||||
{!deployment.isProduction && (
|
||||
<MenuItem
|
||||
onClick={() => setChangeToProduction(!changeToProduction)}
|
||||
>
|
||||
^ Change to production
|
||||
</MenuItem>
|
||||
)}
|
||||
|
||||
<hr className="my-3" />
|
||||
<MenuItem>^ Redeploy</MenuItem>
|
||||
<MenuItem>^ Rollback to this version</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => setRedeployToProduction(!redeployToProduction)}
|
||||
>
|
||||
^ Redeploy to production
|
||||
</MenuItem>
|
||||
{!deployment.isProduction && (
|
||||
<MenuItem
|
||||
onClick={() => setRollbackDeployment(!rollbackDeployment)}
|
||||
>
|
||||
^ Rollback to this version
|
||||
</MenuItem>
|
||||
)}
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</div>
|
||||
<ConfirmDialog
|
||||
dialogTitle="Change to production?"
|
||||
handleOpen={() => setChangeToProduction(!changeToProduction)}
|
||||
open={changeToProduction}
|
||||
confirmButtonTitle="Change"
|
||||
color="blue"
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Typography variant="small">
|
||||
Upon confirmation, this deployment will be changed to production.
|
||||
</Typography>
|
||||
<DeploymentDialogBodyCard deployment={deployment} />
|
||||
<Typography variant="small">
|
||||
The new deployment will be associated with these domains:
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ saugatt.com
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ www.saugatt.com
|
||||
</Typography>
|
||||
</div>
|
||||
</ConfirmDialog>
|
||||
<ConfirmDialog
|
||||
dialogTitle="Redeploy to production?"
|
||||
handleOpen={() => setRedeployToProduction(!redeployToProduction)}
|
||||
open={redeployToProduction}
|
||||
confirmButtonTitle="Redeploy"
|
||||
color="blue"
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Typography variant="small">
|
||||
Upon confirmation, new deployment will be created with the same
|
||||
source code as current deployment.
|
||||
</Typography>
|
||||
<DeploymentDialogBodyCard deployment={deployment} />
|
||||
<Typography variant="small">
|
||||
These domains will point to your new deployment:
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ saugatt.com
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ www.saugatt.com
|
||||
</Typography>
|
||||
</div>
|
||||
</ConfirmDialog>
|
||||
<ConfirmDialog
|
||||
dialogTitle="Rollback to this deployment?"
|
||||
handleOpen={() => setRollbackDeployment(!rollbackDeployment)}
|
||||
open={rollbackDeployment}
|
||||
confirmButtonTitle="Rollback"
|
||||
color="blue"
|
||||
>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Typography variant="small">
|
||||
Upon confirmation, this deployment will replace your current
|
||||
deployment
|
||||
</Typography>
|
||||
<DeploymentDialogBodyCard
|
||||
deployment={productionDeployment}
|
||||
chip={{
|
||||
value: 'Live Deployment',
|
||||
color: 'green',
|
||||
}}
|
||||
/>
|
||||
<DeploymentDialogBodyCard
|
||||
deployment={deployment}
|
||||
chip={{
|
||||
value: 'New Deployment',
|
||||
color: 'orange',
|
||||
}}
|
||||
/>
|
||||
<Typography variant="small">
|
||||
These domains will point to your new deployment:
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ saugatt.com
|
||||
</Typography>
|
||||
<Typography variant="small" color="blue">
|
||||
^ www.saugatt.com
|
||||
</Typography>
|
||||
</div>
|
||||
</ConfirmDialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployDetailsCard;
|
||||
export default DeploymentDetailsCard;
|
||||
|
@ -0,0 +1,44 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Typography, Chip, Card } from '@material-tailwind/react';
|
||||
import { color } from '@material-tailwind/react/types/components/chip';
|
||||
import { DeploymentDetails } from '../../../../types/project';
|
||||
import { relativeTime } from '../../../../utils/time';
|
||||
|
||||
interface DeploymentDialogBodyCardProps {
|
||||
deployment: DeploymentDetails;
|
||||
chip?: {
|
||||
value: string;
|
||||
color?: color;
|
||||
};
|
||||
}
|
||||
|
||||
const DeploymentDialogBodyCard = ({
|
||||
chip,
|
||||
deployment,
|
||||
}: DeploymentDialogBodyCardProps) => {
|
||||
return (
|
||||
<Card className="p-2 shadow-none">
|
||||
{chip && (
|
||||
<Chip
|
||||
className={`w-fit normal-case font-normal`}
|
||||
size="sm"
|
||||
value={chip.value}
|
||||
color={chip.color}
|
||||
/>
|
||||
)}
|
||||
<Typography variant="small" className="text-black">
|
||||
deployment title
|
||||
</Typography>
|
||||
<Typography variant="small">
|
||||
^ {deployment.branch} ^ {deployment.commit.hash}{' '}
|
||||
{deployment.commit.message}
|
||||
</Typography>
|
||||
<Typography variant="small">
|
||||
^ {relativeTime(deployment.updatedAt)} ^ {deployment.author}
|
||||
</Typography>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeploymentDialogBodyCard;
|
@ -16,7 +16,7 @@ type ConfirmDialogProp = {
|
||||
open: boolean;
|
||||
handleOpen: () => void;
|
||||
confirmButtonTitle: string;
|
||||
handleConfirm: () => void;
|
||||
handleConfirm?: () => void;
|
||||
color: color;
|
||||
};
|
||||
|
||||
|
@ -16,3 +16,22 @@ export interface ProjectDetails {
|
||||
branch: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DeploymentDetails {
|
||||
title: string;
|
||||
isProduction: boolean;
|
||||
status: Status;
|
||||
branch: string;
|
||||
commit: {
|
||||
hash: string;
|
||||
message: string;
|
||||
};
|
||||
author: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export enum Status {
|
||||
BUILDING = 'Building',
|
||||
READY = 'Ready',
|
||||
ERROR = 'Error',
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user