From 66aa8fed4fc9a4c3e43f3be44624c0dfc4932e46 Mon Sep 17 00:00:00 2001 From: Nabarun Gogoi Date: Mon, 8 Jan 2024 10:48:07 +0530 Subject: [PATCH] Add dialog for editing domains in project settings tab (#38) * Implement edit domain dialog * Pass project and repo from domain component * Fix dialog states in domain card --------- Co-authored-by: neeraj --- packages/frontend/src/assets/domains.json | 9 +- packages/frontend/src/assets/projects.json | 18 ++- .../frontend/src/assets/repositories.json | 15 +- .../projects/project/settings/DomainCard.tsx | 40 +++-- .../projects/project/settings/Domains.tsx | 31 ++-- .../project/settings/EditDomainDialog.tsx | 153 ++++++++++++++++++ packages/frontend/src/types/project.ts | 3 + 7 files changed, 236 insertions(+), 33 deletions(-) create mode 100644 packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx diff --git a/packages/frontend/src/assets/domains.json b/packages/frontend/src/assets/domains.json index 8017e914..e17d1738 100644 --- a/packages/frontend/src/assets/domains.json +++ b/packages/frontend/src/assets/domains.json @@ -4,7 +4,8 @@ "projectid": 1, "name": "randomurl.snowballtools.xyz", "status": "live", - "record": null + "record": null, + "isRedirectedto": false }, { "id": 2, @@ -15,7 +16,8 @@ "type": "A", "name": "@", "value": "56.49.19.21" - } + }, + "isRedirectedto": false }, { "id": 3, @@ -26,6 +28,7 @@ "type": "CNAME", "name": "www", "value": "cname.snowballtools.xyz" - } + }, + "isRedirectedto": true } ] diff --git a/packages/frontend/src/assets/projects.json b/packages/frontend/src/assets/projects.json index 7c917f48..f962f809 100644 --- a/packages/frontend/src/assets/projects.json +++ b/packages/frontend/src/assets/projects.json @@ -15,7 +15,8 @@ "message": "subscription added", "createdAt": "2023-12-11T04:20:00", "branch": "main" - } + }, + "repositoryId": 1 }, { "id": 2, @@ -33,7 +34,8 @@ "message": "component updates", "createdAt": "2023-12-11T04:20:00", "branch": "staging" - } + }, + "repositoryId": 1 }, { "id": 3, @@ -51,7 +53,8 @@ "message": "No repo connected", "createdAt": "2023-12-01T04:20:00", "branch": "main" - } + }, + "repositoryId": 1 }, { "id": 4, @@ -69,7 +72,8 @@ "message": "hello world", "createdAt": "2023-12-01T04:20:00", "branch": "main" - } + }, + "repositoryId": 1 }, { "id": 5, @@ -87,7 +91,8 @@ "message": "404 added", "createdAt": "2023-12-09T04:20:00", "branch": "main" - } + }, + "repositoryId": 1 }, { "id": 6, @@ -105,6 +110,7 @@ "message": "design system integrated", "createdAt": "2023-12-09T04:20:00", "branch": "prod" - } + }, + "repositoryId": 1 } ] diff --git a/packages/frontend/src/assets/repositories.json b/packages/frontend/src/assets/repositories.json index ca487012..765b5420 100644 --- a/packages/frontend/src/assets/repositories.json +++ b/packages/frontend/src/assets/repositories.json @@ -4,34 +4,39 @@ "title": "project-101", "updatedAt": "2023-12-21T08:30:00", "user": "bob", - "private": false + "private": false, + "branch": ["main", "prod", "dev"] }, { "id": 2, "title": "project-102", "updatedAt": "2023-12-21T08:30:00", "user": "alice", - "private": true + "private": true, + "branch": ["main", "prod", "dev"] }, { "id": 3, "title": "project-103", "updatedAt": "2023-12-21T04:20:00", "user": "charlie", - "private": false + "private": false, + "branch": ["main", "prod", "dev"] }, { "id": 4, "title": "project-104", "updatedAt": "2023-12-21T04:27:00", "user": "alice", - "private": false + "private": false, + "branch": ["main", "prod", "dev"] }, { "id": 5, "title": "project-105", "updatedAt": "2023-12-21T04:41:00", "user": "ivan", - "private": false + "private": false, + "branch": ["main", "prod", "dev"] } ] diff --git a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx index 021e7eec..1a68cb05 100644 --- a/packages/frontend/src/components/projects/project/settings/DomainCard.tsx +++ b/packages/frontend/src/components/projects/project/settings/DomainCard.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; - import toast from 'react-hot-toast'; + import { Chip, Typography, @@ -11,9 +11,14 @@ import { Card, } from '@material-tailwind/react'; -import { DomainDetails, DomainStatus } from '../../../../types/project'; +import { + DomainDetails, + DomainStatus, + ProjectDetails, + RepositoryDetails, +} from '../../../../types/project'; import ConfirmDialog from '../../../shared/ConfirmDialog'; -import projectData from '../../../../assets/projects.json'; +import EditDomainDialog from './EditDomainDialog'; enum RefreshStatus { IDLE, @@ -24,16 +29,16 @@ enum RefreshStatus { interface DomainCardProps { domain: DomainDetails; + repo: RepositoryDetails; + project: ProjectDetails; } const CHECK_FAIL_TIMEOUT = 5000; // In milliseconds -const DomainCard = ({ domain }: DomainCardProps) => { +const DomainCard = ({ domain, repo, project }: DomainCardProps) => { const [refreshStatus, SetRefreshStatus] = useState(RefreshStatus.IDLE); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); - const currProject = projectData.filter( - (data) => data.id === domain.projectid, - ); + const [editDialogOpen, setEditDialogOpen] = useState(false); return ( <> @@ -69,10 +74,17 @@ const DomainCard = ({ domain }: DomainCardProps) => { - ^ Edit domain + { + setEditDialogOpen((preVal) => !preVal); + }} + > + ^ Edit domain + setDeleteDialogOpen(true)} + onClick={() => setDeleteDialogOpen((preVal) => !preVal)} > ^ Delete domain @@ -94,7 +106,7 @@ const DomainCard = ({ domain }: DomainCardProps) => { Once deleted, the project{' '} - {currProject[0].title} + {project.title} {' '} will not be accessible from the domain{' '} @@ -143,6 +155,14 @@ const DomainCard = ({ domain }: DomainCardProps) => { )} + { + setEditDialogOpen((preVal) => !preVal); + }} + open={editDialogOpen} + domain={domain} + repo={repo} + /> ); }; diff --git a/packages/frontend/src/components/projects/project/settings/Domains.tsx b/packages/frontend/src/components/projects/project/settings/Domains.tsx index 9a5f4428..5676edad 100644 --- a/packages/frontend/src/components/projects/project/settings/Domains.tsx +++ b/packages/frontend/src/components/projects/project/settings/Domains.tsx @@ -1,15 +1,25 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { useParams, Link } from 'react-router-dom'; import { Button, Typography } from '@material-tailwind/react'; import DomainCard from './DomainCard'; -import domainsData from '../../../../assets/domains.json'; import { DomainDetails } from '../../../../types/project'; +import domainsData from '../../../../assets/domains.json'; +import repositories from '../../../../assets/repositories.json'; +import projectData from '../../../../assets/projects.json'; const Domains = () => { const { id } = useParams(); + const currProject = useMemo(() => { + return projectData.find((data) => data.id === Number(id)); + }, [id]); + + const linkedRepo = useMemo(() => { + return repositories.find((repo) => repo.id === currProject?.repositoryId); + }, [currProject]); + return ( <>
@@ -21,13 +31,16 @@ const Domains = () => {
- {(domainsData as DomainDetails[]) - .filter((domain) => { - return Number(id) == domain.projectid; - }) - .map((domain) => { - return ; - })} + {(domainsData as DomainDetails[]).map((domain) => { + return ( + + ); + })} ); }; diff --git a/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx new file mode 100644 index 00000000..46f820f8 --- /dev/null +++ b/packages/frontend/src/components/projects/project/settings/EditDomainDialog.tsx @@ -0,0 +1,153 @@ +import React, { useMemo } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import toast from 'react-hot-toast'; + +import { + Button, + Dialog, + DialogHeader, + DialogBody, + DialogFooter, + Input, + Typography, + Select, + Option, +} from '@material-tailwind/react'; + +import { DomainDetails, RepositoryDetails } from '../../../../types/project'; +import domains from '../../../../assets/domains.json'; + +const DEFAULT_REDIRECT_OPTIONS = ['none']; + +interface EditDomainDialogProp { + open: boolean; + handleOpen: () => void; + domain: DomainDetails; + repo: RepositoryDetails; +} + +const EditDomainDialog = ({ + open, + handleOpen, + domain, + repo, +}: EditDomainDialogProp) => { + const getRedirectUrl = (domain: DomainDetails) => { + const domainArr = domain.name.split('www.'); + let redirectUrl = ''; + if (domain.name.startsWith('www.')) { + redirectUrl = domainArr[1]; + } else { + redirectUrl = `www.${domainArr[0]}`; + } + return redirectUrl; + }; + + const redirectOptions = useMemo(() => { + const redirectUrl = getRedirectUrl(domain); + return [...DEFAULT_REDIRECT_OPTIONS, redirectUrl]; + }, [domain]); + + const isDisableDropdown = useMemo(() => { + const redirectUrl = getRedirectUrl(domain); + + const domainRedirected = domains.find( + (domain) => domain.name === redirectUrl, + ); + + return domainRedirected?.isRedirectedto; + }, [domain]); + + const { + handleSubmit, + register, + control, + watch, + formState: { isValid, isDirty }, + } = useForm({ + defaultValues: { + name: domain.name, + branch: repo.branch[0], + redirectedTo: !domain.isRedirectedto + ? redirectOptions[0] + : redirectOptions[1], + }, + }); + + return ( + + +
Edit domain
+ +
+
{ + handleOpen(); + toast.success(`Domain ${domain.name} has been updated`); + })} + > + + Domain name + + Redirect to + ( + + )} + /> + {isDisableDropdown && ( +
+
^
+ + Domain “{redirectOptions[1]}” redirects to this domain so you + can not redirect this doman further. + +
+ )} + Git branch + repo.branch.includes(value), + })} + disabled={watch('redirectedTo') !== DEFAULT_REDIRECT_OPTIONS[0]} + /> + {!isValid && ( + + We couldn't find this branch in the connected Git repository. + + )} +
+ + + + +
+
+ ); +}; + +export default EditDomainDialog; diff --git a/packages/frontend/src/types/project.ts b/packages/frontend/src/types/project.ts index a73db6d6..d784ed17 100644 --- a/packages/frontend/src/types/project.ts +++ b/packages/frontend/src/types/project.ts @@ -15,6 +15,7 @@ export interface ProjectDetails { createdAt: string; branch: string; }; + repositoryId: number; } export interface DeploymentDetails { @@ -54,6 +55,7 @@ export interface RepositoryDetails { updatedAt: string; user: string; private: boolean; + branch: string[]; } export enum GitSelect { @@ -77,4 +79,5 @@ export interface DomainDetails { name: string; value: string; }; + isRedirectedto: boolean; }