Implement domains list in project settings tab (#35)

* Display pending domains card in domain layout

* Rename variables

* Refactor fields in domains json

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2023-12-28 14:14:20 +05:30 committed by GitHub
parent a6f9e18972
commit 7ba390d59b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 20 deletions

View File

@ -1,8 +1,31 @@
[ [
{ {
"domainid": 1, "id": 1,
"projectid": 1, "projectid": 1,
"domain": "randomurl.snowballtools.xyz", "name": "randomurl.snowballtools.xyz",
"status": "live" "status": "live",
"record": null
},
{
"id": 2,
"projectid": 1,
"name": "saugatt.com",
"status": "pending",
"record": {
"type": "A",
"name": "@",
"value": "56.49.19.21"
}
},
{
"id": 3,
"projectid": 1,
"name": "www.saugatt.com",
"status": "pending",
"record": {
"type": "CNAME",
"name": "www",
"value": "cname.snowballtools.xyz"
}
} }
] ]

View File

@ -1,4 +1,5 @@
import React from 'react'; import React, { useState } from 'react';
import { import {
Chip, Chip,
Typography, Typography,
@ -6,28 +7,55 @@ import {
MenuHandler, MenuHandler,
MenuList, MenuList,
MenuItem, MenuItem,
Card,
} from '@material-tailwind/react'; } from '@material-tailwind/react';
const DomainCard = (props: { domain: string; status: string }) => { import { DomainDetails, DomainStatus } from '../../../../types/project';
enum RefreshStatus {
IDLE,
CHECKING,
CHECK_SUCCESS,
CHECK_FAIL,
}
interface DomainCardProps {
domain: DomainDetails;
}
const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds
const DomainCard = ({ domain }: DomainCardProps) => {
const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE);
return ( return (
<> <>
<div className="flex justify-between py-3"> <div className="flex justify-between py-3">
<div className="flex justify-start gap-1"> <div className="flex justify-start gap-1">
<Typography variant="h6"> <Typography variant="h6">
<i>^</i> {props.domain} <i>^</i> {domain.name}
</Typography> </Typography>
<Chip <Chip
className=" w-fit" className="w-fit capitalize"
value={props.status} value={domain.status}
color="green" color={domain.status === DomainStatus.LIVE ? 'green' : 'orange'}
variant="ghost" variant="ghost"
icon={<i>^</i>} icon={<i>^</i>}
/> />
</div> </div>
<div className="flex justify-start gap-1"> <div className="flex justify-start gap-1">
<i id="refresh" className="cursor-pointer w-8 h-8"> <i
^ id="refresh"
className="cursor-pointer w-8 h-8"
onClick={() => {
SetRefreshStatus(RefreshStatus.CHECKING);
setTimeout(() => {
SetRefreshStatus(RefreshStatus.CHECK_FAIL);
}, CHECK_FAIL_TIMEOUT);
}}
>
{refreshStatus === RefreshStatus.CHECKING ? 'L' : 'R'}
</i> </i>
<Menu placement="bottom-end"> <Menu placement="bottom-end">
<MenuHandler> <MenuHandler>
@ -41,6 +69,44 @@ const DomainCard = (props: { domain: string; status: string }) => {
</div> </div>
</div> </div>
<Typography variant="small">Production</Typography> <Typography variant="small">Production</Typography>
{domain.status === DomainStatus.PENDING && (
<Card className="bg-gray-200 p-4 text-sm">
{refreshStatus === RefreshStatus.IDLE ? (
<Typography variant="small">
^ Add these records to your domain and refresh to check
</Typography>
) : refreshStatus === RefreshStatus.CHECKING ? (
<Typography variant="small" className="text-blue-500">
^ Checking records for {domain.name}
</Typography>
) : (
<div className="flex gap-2 text-red-500 mb-2">
<div>^</div>
<div className="grow">
Failed to verify records. DNS propagation can take up to 48
hours. Please ensure you added the correct records and refresh.
</div>
</div>
)}
<table>
<thead>
<tr>
<th className="text-left">Type</th>
<th className="text-left">Name</th>
<th className="text-left">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>{domain.record.type}</td>
<td>{domain.record.name}</td>
<td>{domain.record.value}</td>
</tr>
</tbody>
</table>
</Card>
)}
</> </>
); );
}; };

View File

@ -4,6 +4,7 @@ import { Button, Typography } from '@material-tailwind/react';
import DomainCard from './DomainCard'; import DomainCard from './DomainCard';
import domainsData from '../../../../assets/domains.json'; import domainsData from '../../../../assets/domains.json';
import { DomainDetails } from '../../../../types/project';
const Domains = () => { const Domains = () => {
const { id } = useParams(); const { id } = useParams();
@ -11,7 +12,7 @@ const Domains = () => {
return ( return (
<> <>
<div className="flex justify-between p-2"> <div className="flex justify-between p-2">
<Typography variant="h2">Domain</Typography> <Typography variant="h3">Domain</Typography>
<Link to="domain/add"> <Link to="domain/add">
<Button color="blue" variant="outlined" className="rounded-full"> <Button color="blue" variant="outlined" className="rounded-full">
<i>^</i> Add domain <i>^</i> Add domain
@ -19,18 +20,12 @@ const Domains = () => {
</Link> </Link>
</div> </div>
{domainsData {(domainsData as DomainDetails[])
.filter((domain) => { .filter((domain) => {
return Number(id) == domain.projectid; return Number(id) == domain.projectid;
}) })
.map((domain) => { .map((domain) => {
return ( return <DomainCard domain={domain} key={domain.id} />;
<DomainCard
status={domain.status}
domain={domain.domain}
key={domain.domainid}
/>
);
})} })}
</> </>
); );

View File

@ -61,3 +61,20 @@ export enum GitSelect {
GITEA = 'gitea', GITEA = 'gitea',
NONE = 'none', NONE = 'none',
} }
export enum DomainStatus {
LIVE = 'live',
PENDING = 'pending',
}
export interface DomainDetails {
id: number;
projectid: number;
name: string;
status: DomainStatus;
record: {
type: string;
name: string;
value: string;
};
}